cfcf6367e8a8d200e1e0957c188b482813d18cb0
[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
78 #define HTML "\
79 <!doctype html>\
80 <html>\
81 <head>\
82  <meta charset=\"utf-8\">\
83  <meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\">\
84  <title>GMQCC</title>\
85  <link rel=\"stylesheet\" href=\"stylesheets/styles.css\">\
86  <link rel=\"stylesheet\" href=\"stylesheets/pygment_trac.css\">\
87  <script src=\"javascripts/scale.fix.js\"></script>\
88  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\">\
89  <!--[if lt IE 9]>\
90  <script src=\"//html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\
91  <![endif]-->\
92 </head>\
93 <body>\
94  <a href=\"https://github.com/graphitemaster/gmqcc\"><div class=\"fork\"></div></a>\
95  <div class=\"wrapper\">\
96   <header>\
97    <h1 class=\"header\">GMQCC</h1>\
98    <p class=\"header\">An Improved Quake C Compiler</p>\
99    <ul>\
100     <li class=\"buttons\"><a href=index.html>Index</a></li>\
101     <li class=\"download\"><a href=\"download.html\">Download</a></li>\
102     <li class=\"buttons\"><a href=\"https://github.com/graphitemaster/gmqcc/issues\">Issues</a></li>\
103     <li class=\"buttons\"><a href=\"doc.html\">Documentation</a></li>\
104     <li class=\"buttons\"><a href=\"https://github.com/graphitemaster/gmqcc\">View On GitHub</a></li>\
105    </ul>\
106   </header>\
107   <section>\
108     <table>\
109      <tr>\
110       <th>Operating System / Distribution</th>\
111       <th>x86 Architecture</th>\
112       <th>x86_64 Architecture</th>\
113      </tr>\
114      <tr>\
115       <td>Archlinux</td>\
116       <td><a href=\"%s\">Download</a></td>\
117       <td><a href=\"%s\">Download</a></td>\
118      </tr>\
119      <tr>\
120       <td>Debian</td>\
121       <td><a href=\"%s\">Download</a></td>\
122       <td><a href=\"%s\">Download</a></td>\
123      </tr>\
124      <tr>\
125       <td>Windows</td>\
126       <td><a href=\"%s\">Download</a></td>\
127       <td><a href=\"%s\">Download</a></td>\
128     </tr>\
129     </table>\
130   </section>\
131   <footer>\
132    <script type=\"text/javascript\" src=\"http://www.ohloh.net/p/602517/widgets/project_partner_badge.js\"></script>\
133   </footer>\
134  </div>\
135  <!--[if !IE]><script>fixScale(document);</script><![endif]-->\
136 </body>\
137 </html>\
138 "
139
140 static char build_table[][4096] = {
141     ARCHLINUX_32_REF, ARCHLINUX_64_REF,
142     DEBIAN_32_REF,    DEBIAN_64_REF,
143     WINDOWS_32_REF,   WINDOWS_64_REF
144 };
145 /* </tag> */
146
147 #define ISXDIGIT(c) ((c >= 48 && c <= 57) || ((c & ~0x20) >= 65 && (c & ~0x20) <= 70))
148 typedef struct {
149     char        *data;
150     unsigned int len;
151     unsigned int size;
152 } url_t;
153 void escape(url_t *str) {
154     char *p, *ptr;
155     char hexstr[3];
156     unsigned int  i=0;
157     unsigned long l=0;
158
159     p = str->data;
160     for(i=0; i < str->len; i++) {
161         if((p - str->data) >= str->len)
162             break;
163         if(*p == '%' &&
164             ((p - str->data)+2) < str->len &&
165             ISXDIGIT(*(p+1)) &&
166             ISXDIGIT(*(p+2))
167         ) {
168             p++;
169             hexstr[0] = *p++;
170             hexstr[1] = *p++;
171             hexstr[2] = 0;
172             l = strtoul(hexstr, &ptr, 16);
173             str->data[i] = (char)(l & 0x7f);
174             continue;
175         }
176         if(*p == '+') {
177             *p = ' ';
178         }
179         str->data[i] = *p++;
180     }
181     str->data[i] = 0;
182     str->len     = i;
183 }
184
185 void version(const char *directory, char *major, char *minor, char *patch) {
186     FILE    *handle;
187     char     file[4096];
188     size_t   size = 0;
189     char    *data = NULL;
190     snprintf(file, sizeof(file), "%s/gmqcc.h", directory);
191
192     handle = fopen(file, "r");
193     if (!handle) {
194         fprintf(stderr, "failed to open %s for reading version (%s)\n",
195             file, strerror(errno)
196         );
197         abort();
198     }
199
200     while (getline(&data, &size, handle) != EOF) {
201
202         #define TEST(TYPE, STORE)                               \
203             if (strstr(data, "#define GMQCC_VERSION_" TYPE )) { \
204                 char *get = data;                               \
205                 while (!isdigit(*get))                          \
206                     get++;                                      \
207                 *STORE = *get;                                  \
208             }
209
210         TEST("MAJOR", major)
211         TEST("MINOR", minor)
212         TEST("PATCH", patch)
213
214         #undef TEST
215     }
216
217     free(data);
218 }
219
220 void genhtml() {
221     FILE *fp = fopen("download.html", "w");
222     if (!fp) {
223         fprintf(stderr, "failed to generate HTML: %s\n", strerror(errno));
224         abort();
225     }
226
227     fprintf(fp, HTML,
228         build_table[0], build_table[1],
229         build_table[2], build_table[3],
230         build_table[4], build_table[5]
231     );
232     fclose (fp);
233 }
234
235 /*
236  * Builds a list of download links with the right version and handles the
237  * rest of the magic.
238  */
239 void build(const char *directory) {
240     /* Figure out version number */
241     char   find[3];
242     char   decode[4096];
243     size_t size;
244     version(directory, &find[0], &find[1], &find[2]);
245
246     /*
247      * decode the secuity stuff for preparing the URLs which will be used
248      * as links.
249      */
250     memset(decode, 0, sizeof(decode));
251     security_decode(decode, SECURITY_TOKEN, strlen(SECURITY_TOKEN));
252
253     for (size = 0; size < sizeof(build_table) / sizeof(*build_table); size++) {
254         char *load = strdup(build_table[size]);
255         url_t esc  = { NULL, 0 };
256
257         snprintf(build_table[size], 4096, load, BASEURL, find[0], find[1], find[2], decode);
258         esc.data = strdup(build_table[size]);
259         esc.size = strlen(build_table[size]);
260         esc.len  = esc.size;
261
262         /* Yes we also need to escape URLs just incase */
263         escape(&esc);
264         free(load);
265     }
266
267     /*
268      * Now generate the HTML file for those download links by asking tinyurl to
269      */
270     genhtml();
271 }
272
273 int main(int argc, char **argv) {
274     size_t itr;
275
276     argc--;
277     argv++;
278     if (!argc) {
279         printf("usage: %s [gmqcc.h location]\n", argv[-1]);
280         return 0;
281     }
282
283     build(*argv);
284 }