]> git.xonotic.org Git - xonotic/gmqcc.git/blob - doc/html/download.c
Fix that
[xonotic/gmqcc.git] / doc / html / download.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5
6 /*
7  * protect some information, not that I care, but this is just to stay
8  * safer.
9  */
10 #define SECURITY_BASE  "\
11 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
12 #define SECURITY_TOKEN "\
13 P29hdXRoX2NvbnN1bWVyX2tleT03NnZoM3E0Mmhudm16bTMmb2F1dGhfdG9rZW49\
14 dzBieHpmMGRmdDhlZGZxJm9hdXRoX3NpZ25hdHVyZV9tZXRob2Q9UExBSU5URVhU\
15 Jm9hdXRoX3NpZ25hdHVyZT10bWVlY2h0MmNtaDcyeGElMjY5dm9zeDd4OGd5NGtn\
16 amsmb2F1dGhfdGltZXN0YW1wPSZvYXV0aF9ub25jZT0xMjE2NQo="
17
18 int isbase64(char c) {
19    return !!(c && strchr(SECURITY_BASE, c) != NULL);
20 }
21 char value(char c) {
22     const char *load = SECURITY_BASE;
23     const char *find = strchr(load, c);
24
25     return (find) ? find - load : 0;
26 }
27
28 int security_decode(unsigned char *dest, const unsigned char *src, int srclen) {
29     unsigned char *p;
30
31     if(!*src)
32         return 0;
33
34     *dest = 0;
35     p = dest;
36
37     do {
38         *p++ = (value(src[0]) << 2) | (value(src[1]) >> 4);
39         *p++ = (value(src[1]) << 4) | (value(src[2]) >> 2);
40         *p++ = (value(src[2]) << 6) | (value(src[3]) >> 0);
41
42         if(!isbase64(src[1])) {
43             p -= 2;
44             break;
45         }
46         else if(!isbase64(src[2])) {
47             p -= 2;
48             break;
49         }
50         else if(!isbase64(src[3])) {
51             p--;
52             break;
53         }
54         src += 4;
55
56         while(*src && (*src == 13 || *src == 10))
57         src++;
58     } while(srclen-= 4);
59
60     *p = 0;
61     return p-dest;
62 }
63
64 #define BASEURL          " https://api-content.dropbox.com/1/files/sandbox/"
65
66 /*
67  * If more platforms are supported add the entries between the start
68  * tag here, and the end tag below. Nothing else needs to be done
69  * <tag> (the table needs to match the HTML too)
70  */
71 #define ARCHLINUX_32_REF "%sgmqcc-%c.%c.%c-1-i686.pkg.tar.xz%s"
72 #define ARCHLINUX_64_REF "%sgmqcc-%c.%c.%c-1-x86_64.pkg.tar.xz%s"
73 #define DEBIAN_32_REF    "%sgmqcc-%c.%c.%c-i686.deb%s"
74 #define DEBIAN_64_REF    "%sgmqcc-%c.%c.%c-x86_64.deb%s"
75 #define WINDOWS_32_REF   "%sgmqcc-%c.%c.%c-win32.zip%s"
76 #define WINDOWS_64_REF   "%sgmqcc-%c.%c.%c-win64.zip%s"
77 #define SLACKWARE_32_REF "%sgmqcc-%c.%c.%c-i686.txz%s"
78 #define SLACKWARE_64_REF "%sgmqcc-%c.%c.%c-x86_64.txz%s"
79
80
81 #define HTML "\
82 <!doctype html>\
83 <html>\
84 <head>\
85  <meta charset=\"utf-8\">\
86  <meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\">\
87  <title>GMQCC</title>\
88  <link rel=\"stylesheet\" href=\"stylesheets/styles.css\">\
89  <link rel=\"stylesheet\" href=\"stylesheets/pygment_trac.css\">\
90  <script src=\"javascripts/scale.fix.js\"></script>\
91  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\">\
92  <!--[if lt IE 9]>\
93  <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\
94  <![endif]-->\
95 </head>\
96 <body>\
97  <a href=\"https://github.com/graphitemaster/gmqcc\"><div class=\"fork\"></div></a>\
98  <div class=\"wrapper\">\
99   <header>\
100    <h1 class=\"header\">GMQCC</h1>\
101    <p class=\"header\">An Improved Quake C Compiler</p>\
102    <ul>\
103     <li class=\"buttons\"><a href=index.html>Index</a></li>\
104     <li class=\"download\"><a href=\"download.html\">Download</a></li>\
105     <li class=\"buttons\"><a href=\"https://github.com/graphitemaster/gmqcc/issues\">Issues</a></li>\
106     <li class=\"buttons\"><a href=\"doc.html\">Documentation</a></li>\
107     <li class=\"buttons\"><a href=\"https://github.com/graphitemaster/gmqcc\">View On GitHub</a></li>\
108    </ul>\
109   </header>\
110   <section>\
111     <table>\
112      <tr>\
113       <th>Operating System / Distribution</th>\
114       <th>x86 Architecture</th>\
115       <th>x86_64 Architecture</th>\
116      </tr>\
117      <tr>\
118       <td>Archlinux</td>\
119       <td><a href=\"%s\">Download</a></td>\
120       <td><a href=\"%s\">Download</a></td>\
121      </tr>\
122      <tr>\
123       <td>Debian</td>\
124       <td><a href=\"%s\">Download</a></td>\
125       <td><a href=\"%s\">Download</a></td>\
126      </tr>\
127      <tr>\
128       <td>Slackware</td>\
129       <td><a href=\"%s\">Download</a></td>\
130       <td><a href=\"%s\">Download</a></td>\
131      <tr>\
132       <td>Windows</td>\
133       <td><a href=\"%s\">Download</a></td>\
134       <td><a href=\"%s\">Download</a></td>\
135     </tr>\
136     </table>\
137   </section>\
138   <footer>\
139    <script type=\"text/javascript\" src=\"http://www.ohloh.net/p/602517/widgets/project_partner_badge.js\"></script>\
140   </footer>\
141  </div>\
142  <!--[if !IE]><script>fixScale(document);</script><![endif]-->\
143 </body>\
144 </html>\
145 "
146
147 static char build_table[][4096] = {
148     ARCHLINUX_32_REF, ARCHLINUX_64_REF,
149     DEBIAN_32_REF,    DEBIAN_64_REF,
150     SLACKWARE_32_REF, SLACKWARE_64_REF,
151     WINDOWS_32_REF,   WINDOWS_64_REF
152 };
153 /* </tag> */
154
155 #define ISXDIGIT(c) ((c >= 48 && c <= 57) || ((c & ~0x20) >= 65 && (c & ~0x20) <= 70))
156 typedef struct {
157     char        *data;
158     unsigned int len;
159     unsigned int size;
160 } url_t;
161 void escape(url_t *str) {
162     char *p, *ptr;
163     char hexstr[3];
164     unsigned int  i=0;
165     unsigned long l=0;
166
167     p = str->data;
168     for(i=0; i < str->len; i++) {
169         if((p - str->data) >= str->len)
170             break;
171         if(*p == '%' &&
172             ((p - str->data)+2) < str->len &&
173             ISXDIGIT(*(p+1)) &&
174             ISXDIGIT(*(p+2))
175         ) {
176             p++;
177             hexstr[0] = *p++;
178             hexstr[1] = *p++;
179             hexstr[2] = 0;
180             l = strtoul(hexstr, &ptr, 16);
181             str->data[i] = (char)(l & 0x7f);
182             continue;
183         }
184         if(*p == '+') {
185             *p = ' ';
186         }
187         str->data[i] = *p++;
188     }
189     str->data[i] = 0;
190     str->len     = i;
191 }
192
193 void version(const char *directory, char *major, char *minor, char *patch) {
194     FILE    *handle;
195     char     file[4096];
196     size_t   size = 0;
197     char    *data = NULL;
198     snprintf(file, sizeof(file), "%s/gmqcc.h", directory);
199
200     handle = fopen(file, "r");
201     if (!handle) {
202         fprintf(stderr, "failed to open %s for reading version (%s)\n",
203             file, strerror(errno)
204         );
205         abort();
206     }
207
208     while (getline(&data, &size, handle) != EOF) {
209
210         #define TEST(TYPE, STORE)                               \
211             if (strstr(data, "#define GMQCC_VERSION_" TYPE )) { \
212                 char *get = data;                               \
213                 while (!isdigit(*get))                          \
214                     get++;                                      \
215                 *STORE = *get;                                  \
216             }
217
218         TEST("MAJOR", major)
219         TEST("MINOR", minor)
220         TEST("PATCH", patch)
221
222         #undef TEST
223     }
224
225     free(data);
226 }
227
228 void genhtml() {
229     FILE *fp = fopen("download.html", "w");
230     if (!fp) {
231         fprintf(stderr, "failed to generate HTML: %s\n", strerror(errno));
232         abort();
233     }
234
235     fprintf(fp, HTML,
236         build_table[0], build_table[1],
237         build_table[2], build_table[3],
238         build_table[4], build_table[5],
239         build_table[6], build_table[7]
240     );
241     fclose (fp);
242 }
243
244 /*
245  * Builds a list of download links with the right version and handles the
246  * rest of the magic.
247  */
248 void build(const char *directory) {
249     /* Figure out version number */
250     char   find[3];
251     char   decode[4096];
252     size_t size;
253     version(directory, &find[0], &find[1], &find[2]);
254
255     /*
256      * decode the secuity stuff for preparing the URLs which will be used
257      * as links.
258      */
259     memset(decode, 0, sizeof(decode));
260     security_decode(decode, SECURITY_TOKEN, strlen(SECURITY_TOKEN));
261
262     for (size = 0; size < sizeof(build_table) / sizeof(*build_table); size++) {
263         char *load = strdup(build_table[size]);
264         url_t esc  = { NULL, 0 };
265
266         snprintf(build_table[size], 4096, load, BASEURL, find[0], find[1], find[2], decode);
267         esc.data = strdup(build_table[size]);
268         esc.size = strlen(build_table[size]);
269         esc.len  = esc.size;
270
271         /* Yes we also need to escape URLs just incase */
272         escape(&esc);
273         free(load);
274     }
275
276     /*
277      * Now generate the HTML file for those download links by asking tinyurl to
278      */
279     genhtml();
280 }
281
282 int main(int argc, char **argv) {
283     size_t itr;
284
285     argc--;
286     argv++;
287     if (!argc) {
288         printf("usage: %s [gmqcc.h location]\n", argv[-1]);
289         return 0;
290     }
291
292     build(*argv);
293 }