diff options
Diffstat (limited to 'src/examples/demo_https.c')
-rw-r--r-- | src/examples/demo_https.c | 846 |
1 files changed, 430 insertions, 416 deletions
diff --git a/src/examples/demo_https.c b/src/examples/demo_https.c index f2230b16..7f7eb3a5 100644 --- a/src/examples/demo_https.c +++ b/src/examples/demo_https.c | |||
@@ -44,10 +44,10 @@ | |||
44 | #include <limits.h> | 44 | #include <limits.h> |
45 | #include <ctype.h> | 45 | #include <ctype.h> |
46 | 46 | ||
47 | #if defined(CPU_COUNT) && (CPU_COUNT+0) < 2 | 47 | #if defined(CPU_COUNT) && (CPU_COUNT + 0) < 2 |
48 | #undef CPU_COUNT | 48 | #undef CPU_COUNT |
49 | #endif | 49 | #endif |
50 | #if !defined(CPU_COUNT) | 50 | #if ! defined(CPU_COUNT) |
51 | #define CPU_COUNT 2 | 51 | #define CPU_COUNT 2 |
52 | #endif | 52 | #endif |
53 | 53 | ||
@@ -76,46 +76,50 @@ | |||
76 | /** | 76 | /** |
77 | * Page returned for file-not-found. | 77 | * Page returned for file-not-found. |
78 | */ | 78 | */ |
79 | #define FILE_NOT_FOUND_PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>" | 79 | #define FILE_NOT_FOUND_PAGE \ |
80 | "<html><head><title>File not found</title></head><body>File not found</body></html>" | ||
80 | 81 | ||
81 | 82 | ||
82 | /** | 83 | /** |
83 | * Page returned for internal errors. | 84 | * Page returned for internal errors. |
84 | */ | 85 | */ |
85 | #define INTERNAL_ERROR_PAGE "<html><head><title>Internal error</title></head><body>Internal error</body></html>" | 86 | #define INTERNAL_ERROR_PAGE \ |
87 | "<html><head><title>Internal error</title></head><body>Internal error</body></html>" | ||
86 | 88 | ||
87 | 89 | ||
88 | /** | 90 | /** |
89 | * Page returned for refused requests. | 91 | * Page returned for refused requests. |
90 | */ | 92 | */ |
91 | #define REQUEST_REFUSED_PAGE "<html><head><title>Request refused</title></head><body>Request refused (file exists?)</body></html>" | 93 | #define REQUEST_REFUSED_PAGE \ |
94 | "<html><head><title>Request refused</title></head><body>Request refused (file exists?)</body></html>" | ||
92 | 95 | ||
93 | 96 | ||
94 | /** | 97 | /** |
95 | * Head of index page. | 98 | * Head of index page. |
96 | */ | 99 | */ |
97 | #define INDEX_PAGE_HEADER "<html>\n<head><title>Welcome</title></head>\n<body>\n"\ | 100 | #define INDEX_PAGE_HEADER \ |
98 | "<h1>Upload</h1>\n"\ | 101 | "<html>\n<head><title>Welcome</title></head>\n<body>\n" \ |
99 | "<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/\">\n"\ | 102 | "<h1>Upload</h1>\n" \ |
100 | "<dl><dt>Content type:</dt><dd>"\ | 103 | "<form method=\"POST\" enctype=\"multipart/form-data\" action=\"/\">\n" \ |
101 | "<input type=\"radio\" name=\"category\" value=\"books\">Book</input>"\ | 104 | "<dl><dt>Content type:</dt><dd>" \ |
102 | "<input type=\"radio\" name=\"category\" value=\"images\">Image</input>"\ | 105 | "<input type=\"radio\" name=\"category\" value=\"books\">Book</input>" \ |
103 | "<input type=\"radio\" name=\"category\" value=\"music\">Music</input>"\ | 106 | "<input type=\"radio\" name=\"category\" value=\"images\">Image</input>" \ |
104 | "<input type=\"radio\" name=\"category\" value=\"software\">Software</input>"\ | 107 | "<input type=\"radio\" name=\"category\" value=\"music\">Music</input>" \ |
105 | "<input type=\"radio\" name=\"category\" value=\"videos\">Videos</input>\n"\ | 108 | "<input type=\"radio\" name=\"category\" value=\"software\">Software</input>" \ |
106 | "<input type=\"radio\" name=\"category\" value=\"other\" checked>Other</input></dd>"\ | 109 | "<input type=\"radio\" name=\"category\" value=\"videos\">Videos</input>\n" \ |
107 | "<dt>Language:</dt><dd>"\ | 110 | "<input type=\"radio\" name=\"category\" value=\"other\" checked>Other</input></dd>" \ |
108 | "<input type=\"radio\" name=\"language\" value=\"no-lang\" checked>none</input>"\ | 111 | "<dt>Language:</dt><dd>" \ |
109 | "<input type=\"radio\" name=\"language\" value=\"en\">English</input>"\ | 112 | "<input type=\"radio\" name=\"language\" value=\"no-lang\" checked>none</input>" \ |
110 | "<input type=\"radio\" name=\"language\" value=\"de\">German</input>"\ | 113 | "<input type=\"radio\" name=\"language\" value=\"en\">English</input>" \ |
111 | "<input type=\"radio\" name=\"language\" value=\"fr\">French</input>"\ | 114 | "<input type=\"radio\" name=\"language\" value=\"de\">German</input>" \ |
112 | "<input type=\"radio\" name=\"language\" value=\"es\">Spanish</input></dd>\n"\ | 115 | "<input type=\"radio\" name=\"language\" value=\"fr\">French</input>" \ |
113 | "<dt>File:</dt><dd>"\ | 116 | "<input type=\"radio\" name=\"language\" value=\"es\">Spanish</input></dd>\n" \ |
114 | "<input type=\"file\" name=\"upload\"/></dd></dl>"\ | 117 | "<dt>File:</dt><dd>" \ |
115 | "<input type=\"submit\" value=\"Send!\"/>\n"\ | 118 | "<input type=\"file\" name=\"upload\"/></dd></dl>" \ |
116 | "</form>\n"\ | 119 | "<input type=\"submit\" value=\"Send!\"/>\n" \ |
117 | "<h1>Download</h1>\n"\ | 120 | "</form>\n" \ |
118 | "<ol>\n" | 121 | "<h1>Download</h1>\n" \ |
122 | "<ol>\n" | ||
119 | 123 | ||
120 | /** | 124 | /** |
121 | * Footer of index page. | 125 | * Footer of index page. |
@@ -127,16 +131,15 @@ | |||
127 | * NULL-terminated array of supported upload categories. Should match HTML | 131 | * NULL-terminated array of supported upload categories. Should match HTML |
128 | * in the form. | 132 | * in the form. |
129 | */ | 133 | */ |
130 | static const char * const categories[] = | 134 | static const char *const categories[] = { |
131 | { | 135 | "books", |
132 | "books", | 136 | "images", |
133 | "images", | 137 | "music", |
134 | "music", | 138 | "software", |
135 | "software", | 139 | "videos", |
136 | "videos", | 140 | "other", |
137 | "other", | 141 | NULL, |
138 | NULL, | 142 | }; |
139 | }; | ||
140 | 143 | ||
141 | 144 | ||
142 | /** | 145 | /** |
@@ -160,15 +163,14 @@ struct Language | |||
160 | * NULL-terminated array of supported upload categories. Should match HTML | 163 | * NULL-terminated array of supported upload categories. Should match HTML |
161 | * in the form. | 164 | * in the form. |
162 | */ | 165 | */ |
163 | static const struct Language languages[] = | 166 | static const struct Language languages[] = { |
164 | { | 167 | { "no-lang", "No language specified" }, |
165 | { "no-lang", "No language specified" }, | 168 | { "en", "English" }, |
166 | { "en", "English" }, | 169 | { "de", "German" }, |
167 | { "de", "German" }, | 170 | { "fr", "French" }, |
168 | { "fr", "French" }, | 171 | { "es", "Spanish" }, |
169 | { "es", "Spanish" }, | 172 | { NULL, NULL }, |
170 | { NULL, NULL }, | 173 | }; |
171 | }; | ||
172 | 174 | ||
173 | 175 | ||
174 | /** | 176 | /** |
@@ -213,8 +215,8 @@ static void | |||
213 | mark_as_html (struct MHD_Response *response) | 215 | mark_as_html (struct MHD_Response *response) |
214 | { | 216 | { |
215 | (void) MHD_add_response_header (response, | 217 | (void) MHD_add_response_header (response, |
216 | MHD_HTTP_HEADER_CONTENT_TYPE, | 218 | MHD_HTTP_HEADER_CONTENT_TYPE, |
217 | "text/html"); | 219 | "text/html"); |
218 | } | 220 | } |
219 | 221 | ||
220 | 222 | ||
@@ -267,7 +269,7 @@ struct ResponseDataContext | |||
267 | */ | 269 | */ |
268 | static int | 270 | static int |
269 | list_directory (struct ResponseDataContext *rdc, | 271 | list_directory (struct ResponseDataContext *rdc, |
270 | const char *dirname) | 272 | const char *dirname) |
271 | { | 273 | { |
272 | char fullname[PATH_MAX]; | 274 | char fullname[PATH_MAX]; |
273 | struct stat sbuf; | 275 | struct stat sbuf; |
@@ -277,35 +279,35 @@ list_directory (struct ResponseDataContext *rdc, | |||
277 | if (NULL == (dir = opendir (dirname))) | 279 | if (NULL == (dir = opendir (dirname))) |
278 | return MHD_NO; | 280 | return MHD_NO; |
279 | while (NULL != (de = readdir (dir))) | 281 | while (NULL != (de = readdir (dir))) |
282 | { | ||
283 | if ('.' == de->d_name[0]) | ||
284 | continue; | ||
285 | if (sizeof (fullname) <= (size_t) | ||
286 | snprintf (fullname, sizeof (fullname), | ||
287 | "%s/%s", | ||
288 | dirname, de->d_name)) | ||
289 | continue; /* ugh, file too long? how can this be!? */ | ||
290 | if (0 != stat (fullname, &sbuf)) | ||
291 | continue; /* ugh, failed to 'stat' */ | ||
292 | if (! S_ISREG (sbuf.st_mode)) | ||
293 | continue; /* not a regular file, skip */ | ||
294 | if (rdc->off + 1024 > rdc->buf_len) | ||
280 | { | 295 | { |
281 | if ('.' == de->d_name[0]) | 296 | void *r; |
282 | continue; | 297 | |
283 | if (sizeof (fullname) <= (size_t) | 298 | if ( (2 * rdc->buf_len + 1024) < rdc->buf_len) |
284 | snprintf (fullname, sizeof (fullname), | 299 | break; /* more than SIZE_T _index_ size? Too big for us */ |
285 | "%s/%s", | 300 | rdc->buf_len = 2 * rdc->buf_len + 1024; |
286 | dirname, de->d_name)) | 301 | if (NULL == (r = realloc (rdc->buf, rdc->buf_len))) |
287 | continue; /* ugh, file too long? how can this be!? */ | 302 | break; /* out of memory */ |
288 | if (0 != stat (fullname, &sbuf)) | 303 | rdc->buf = r; |
289 | continue; /* ugh, failed to 'stat' */ | ||
290 | if (! S_ISREG (sbuf.st_mode)) | ||
291 | continue; /* not a regular file, skip */ | ||
292 | if (rdc->off + 1024 > rdc->buf_len) | ||
293 | { | ||
294 | void *r; | ||
295 | |||
296 | if ( (2 * rdc->buf_len + 1024) < rdc->buf_len) | ||
297 | break; /* more than SIZE_T _index_ size? Too big for us */ | ||
298 | rdc->buf_len = 2 * rdc->buf_len + 1024; | ||
299 | if (NULL == (r = realloc (rdc->buf, rdc->buf_len))) | ||
300 | break; /* out of memory */ | ||
301 | rdc->buf = r; | ||
302 | } | ||
303 | rdc->off += snprintf (&rdc->buf[rdc->off], | ||
304 | rdc->buf_len - rdc->off, | ||
305 | "<li><a href=\"/%s\">%s</a></li>\n", | ||
306 | fullname, | ||
307 | de->d_name); | ||
308 | } | 304 | } |
305 | rdc->off += snprintf (&rdc->buf[rdc->off], | ||
306 | rdc->buf_len - rdc->off, | ||
307 | "<li><a href=\"/%s\">%s</a></li>\n", | ||
308 | fullname, | ||
309 | de->d_name); | ||
310 | } | ||
309 | (void) closedir (dir); | 311 | (void) closedir (dir); |
310 | return MHD_YES; | 312 | return MHD_YES; |
311 | } | 313 | } |
@@ -329,65 +331,66 @@ update_directory () | |||
329 | 331 | ||
330 | rdc.buf_len = initial_allocation; | 332 | rdc.buf_len = initial_allocation; |
331 | if (NULL == (rdc.buf = malloc (rdc.buf_len))) | 333 | if (NULL == (rdc.buf = malloc (rdc.buf_len))) |
332 | { | 334 | { |
333 | update_cached_response (NULL); | 335 | update_cached_response (NULL); |
334 | return; | 336 | return; |
335 | } | 337 | } |
336 | rdc.off = snprintf (rdc.buf, rdc.buf_len, | 338 | rdc.off = snprintf (rdc.buf, rdc.buf_len, |
337 | "%s", | 339 | "%s", |
338 | INDEX_PAGE_HEADER); | 340 | INDEX_PAGE_HEADER); |
339 | for (language_idx = 0; NULL != languages[language_idx].dirname; language_idx++) | 341 | for (language_idx = 0; NULL != languages[language_idx].dirname; |
342 | language_idx++) | ||
343 | { | ||
344 | language = &languages[language_idx]; | ||
345 | |||
346 | if (0 != stat (language->dirname, &sbuf)) | ||
347 | continue; /* empty */ | ||
348 | /* we ensured always +1k room, filenames are ~256 bytes, | ||
349 | so there is always still enough space for the header | ||
350 | without need for an additional reallocation check. */ | ||
351 | rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off, | ||
352 | "<h2>%s</h2>\n", | ||
353 | language->longname); | ||
354 | for (category_idx = 0; NULL != categories[category_idx]; category_idx++) | ||
340 | { | 355 | { |
341 | language = &languages[language_idx]; | 356 | category = categories[category_idx]; |
357 | snprintf (dir_name, sizeof (dir_name), | ||
358 | "%s/%s", | ||
359 | language->dirname, | ||
360 | category); | ||
361 | if (0 != stat (dir_name, &sbuf)) | ||
362 | continue; /* empty */ | ||
342 | 363 | ||
343 | if (0 != stat (language->dirname, &sbuf)) | ||
344 | continue; /* empty */ | ||
345 | /* we ensured always +1k room, filenames are ~256 bytes, | 364 | /* we ensured always +1k room, filenames are ~256 bytes, |
346 | so there is always still enough space for the header | 365 | so there is always still enough space for the header |
347 | without need for an additional reallocation check. */ | 366 | without need for an additional reallocation check. */ |
348 | rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off, | 367 | rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off, |
349 | "<h2>%s</h2>\n", | 368 | "<h3>%s</h3>\n", |
350 | language->longname); | 369 | category); |
351 | for (category_idx = 0; NULL != categories[category_idx]; category_idx++) | 370 | |
352 | { | 371 | if (MHD_NO == list_directory (&rdc, dir_name)) |
353 | category = categories[category_idx]; | 372 | { |
354 | snprintf (dir_name, sizeof (dir_name), | 373 | free (rdc.buf); |
355 | "%s/%s", | 374 | update_cached_response (NULL); |
356 | language->dirname, | 375 | return; |
357 | category); | 376 | } |
358 | if (0 != stat (dir_name, &sbuf)) | ||
359 | continue; /* empty */ | ||
360 | |||
361 | /* we ensured always +1k room, filenames are ~256 bytes, | ||
362 | so there is always still enough space for the header | ||
363 | without need for an additional reallocation check. */ | ||
364 | rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off, | ||
365 | "<h3>%s</h3>\n", | ||
366 | category); | ||
367 | |||
368 | if (MHD_NO == list_directory (&rdc, dir_name)) | ||
369 | { | ||
370 | free (rdc.buf); | ||
371 | update_cached_response (NULL); | ||
372 | return; | ||
373 | } | ||
374 | } | ||
375 | } | 377 | } |
378 | } | ||
376 | /* we ensured always +1k room, filenames are ~256 bytes, | 379 | /* we ensured always +1k room, filenames are ~256 bytes, |
377 | so there is always still enough space for the footer | 380 | so there is always still enough space for the footer |
378 | without need for a final reallocation check. */ | 381 | without need for a final reallocation check. */ |
379 | rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off, | 382 | rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off, |
380 | "%s", | 383 | "%s", |
381 | INDEX_PAGE_FOOTER); | 384 | INDEX_PAGE_FOOTER); |
382 | initial_allocation = rdc.buf_len; /* remember for next time */ | 385 | initial_allocation = rdc.buf_len; /* remember for next time */ |
383 | response = MHD_create_response_from_buffer (rdc.off, | 386 | response = MHD_create_response_from_buffer (rdc.off, |
384 | rdc.buf, | 387 | rdc.buf, |
385 | MHD_RESPMEM_MUST_FREE); | 388 | MHD_RESPMEM_MUST_FREE); |
386 | mark_as_html (response); | 389 | mark_as_html (response); |
387 | #if FORCE_CLOSE | 390 | #if FORCE_CLOSE |
388 | (void) MHD_add_response_header (response, | 391 | (void) MHD_add_response_header (response, |
389 | MHD_HTTP_HEADER_CONNECTION, | 392 | MHD_HTTP_HEADER_CONNECTION, |
390 | "close"); | 393 | "close"); |
391 | #endif | 394 | #endif |
392 | update_cached_response (response); | 395 | update_cached_response (response); |
393 | } | 396 | } |
@@ -446,8 +449,8 @@ struct UploadContext | |||
446 | */ | 449 | */ |
447 | static int | 450 | static int |
448 | do_append (char **ret, | 451 | do_append (char **ret, |
449 | const char *data, | 452 | const char *data, |
450 | size_t size) | 453 | size_t size) |
451 | { | 454 | { |
452 | char *buf; | 455 | char *buf; |
453 | size_t old_len; | 456 | size_t old_len; |
@@ -459,15 +462,15 @@ do_append (char **ret, | |||
459 | if (NULL == (buf = malloc (old_len + size + 1))) | 462 | if (NULL == (buf = malloc (old_len + size + 1))) |
460 | return MHD_NO; | 463 | return MHD_NO; |
461 | if (NULL != *ret) | 464 | if (NULL != *ret) |
462 | { | 465 | { |
463 | memcpy (buf, | 466 | memcpy (buf, |
464 | *ret, | 467 | *ret, |
465 | old_len); | 468 | old_len); |
466 | free (*ret); | 469 | free (*ret); |
467 | } | 470 | } |
468 | memcpy (&buf[old_len], | 471 | memcpy (&buf[old_len], |
469 | data, | 472 | data, |
470 | size); | 473 | size); |
471 | buf[old_len + size] = '\0'; | 474 | buf[old_len + size] = '\0'; |
472 | *ret = buf; | 475 | *ret = buf; |
473 | return MHD_YES; | 476 | return MHD_YES; |
@@ -495,119 +498,119 @@ do_append (char **ret, | |||
495 | */ | 498 | */ |
496 | static int | 499 | static int |
497 | process_upload_data (void *cls, | 500 | process_upload_data (void *cls, |
498 | enum MHD_ValueKind kind, | 501 | enum MHD_ValueKind kind, |
499 | const char *key, | 502 | const char *key, |
500 | const char *filename, | 503 | const char *filename, |
501 | const char *content_type, | 504 | const char *content_type, |
502 | const char *transfer_encoding, | 505 | const char *transfer_encoding, |
503 | const char *data, | 506 | const char *data, |
504 | uint64_t off, | 507 | uint64_t off, |
505 | size_t size) | 508 | size_t size) |
506 | { | 509 | { |
507 | struct UploadContext *uc = cls; | 510 | struct UploadContext *uc = cls; |
508 | int i; | 511 | int i; |
509 | (void)kind; /* Unused. Silent compiler warning. */ | 512 | (void) kind; /* Unused. Silent compiler warning. */ |
510 | (void)content_type; /* Unused. Silent compiler warning. */ | 513 | (void) content_type; /* Unused. Silent compiler warning. */ |
511 | (void)transfer_encoding; /* Unused. Silent compiler warning. */ | 514 | (void) transfer_encoding; /* Unused. Silent compiler warning. */ |
512 | (void)off; /* Unused. Silent compiler warning. */ | 515 | (void) off; /* Unused. Silent compiler warning. */ |
513 | 516 | ||
514 | if (0 == strcmp (key, "category")) | 517 | if (0 == strcmp (key, "category")) |
515 | return do_append (&uc->category, data, size); | 518 | return do_append (&uc->category, data, size); |
516 | if (0 == strcmp (key, "language")) | 519 | if (0 == strcmp (key, "language")) |
517 | return do_append (&uc->language, data, size); | 520 | return do_append (&uc->language, data, size); |
518 | if (0 != strcmp (key, "upload")) | 521 | if (0 != strcmp (key, "upload")) |
519 | { | 522 | { |
520 | fprintf (stderr, | 523 | fprintf (stderr, |
521 | "Ignoring unexpected form value `%s'\n", | 524 | "Ignoring unexpected form value `%s'\n", |
522 | key); | 525 | key); |
523 | return MHD_YES; /* ignore */ | 526 | return MHD_YES; /* ignore */ |
524 | } | 527 | } |
525 | if (NULL == filename) | 528 | if (NULL == filename) |
526 | { | 529 | { |
527 | fprintf (stderr, "No filename, aborting upload\n"); | 530 | fprintf (stderr, "No filename, aborting upload\n"); |
528 | return MHD_NO; /* no filename, error */ | 531 | return MHD_NO; /* no filename, error */ |
529 | } | 532 | } |
530 | if ( (NULL == uc->category) || | 533 | if ( (NULL == uc->category) || |
531 | (NULL == uc->language) ) | 534 | (NULL == uc->language) ) |
535 | { | ||
536 | fprintf (stderr, | ||
537 | "Missing form data for upload `%s'\n", | ||
538 | filename); | ||
539 | uc->response = request_refused_response; | ||
540 | return MHD_NO; | ||
541 | } | ||
542 | if (-1 == uc->fd) | ||
543 | { | ||
544 | char fn[PATH_MAX]; | ||
545 | |||
546 | if ( (NULL != strstr (filename, "..")) || | ||
547 | (NULL != strchr (filename, '/')) || | ||
548 | (NULL != strchr (filename, '\\')) ) | ||
532 | { | 549 | { |
533 | fprintf (stderr, | ||
534 | "Missing form data for upload `%s'\n", | ||
535 | filename); | ||
536 | uc->response = request_refused_response; | 550 | uc->response = request_refused_response; |
537 | return MHD_NO; | 551 | return MHD_NO; |
538 | } | 552 | } |
539 | if (-1 == uc->fd) | 553 | /* create directories -- if they don't exist already */ |
540 | { | ||
541 | char fn[PATH_MAX]; | ||
542 | |||
543 | if ( (NULL != strstr (filename, "..")) || | ||
544 | (NULL != strchr (filename, '/')) || | ||
545 | (NULL != strchr (filename, '\\')) ) | ||
546 | { | ||
547 | uc->response = request_refused_response; | ||
548 | return MHD_NO; | ||
549 | } | ||
550 | /* create directories -- if they don't exist already */ | ||
551 | #ifdef WINDOWS | 554 | #ifdef WINDOWS |
552 | (void) mkdir (uc->language); | 555 | (void) mkdir (uc->language); |
553 | #else | 556 | #else |
554 | (void) mkdir (uc->language, S_IRWXU); | 557 | (void) mkdir (uc->language, S_IRWXU); |
555 | #endif | 558 | #endif |
556 | snprintf (fn, sizeof (fn), | 559 | snprintf (fn, sizeof (fn), |
557 | "%s/%s", | 560 | "%s/%s", |
558 | uc->language, | 561 | uc->language, |
559 | uc->category); | 562 | uc->category); |
560 | #ifdef WINDOWS | 563 | #ifdef WINDOWS |
561 | (void) mkdir (fn); | 564 | (void) mkdir (fn); |
562 | #else | 565 | #else |
563 | (void) mkdir (fn, S_IRWXU); | 566 | (void) mkdir (fn, S_IRWXU); |
564 | #endif | 567 | #endif |
565 | /* open file */ | 568 | /* open file */ |
566 | snprintf (fn, sizeof (fn), | 569 | snprintf (fn, sizeof (fn), |
567 | "%s/%s/%s", | 570 | "%s/%s/%s", |
568 | uc->language, | 571 | uc->language, |
569 | uc->category, | 572 | uc->category, |
570 | filename); | 573 | filename); |
571 | for (i=strlen (fn)-1;i>=0;i--) | 574 | for (i = strlen (fn) - 1; i>=0; i--) |
572 | if (! isprint ((unsigned char) fn[i])) | 575 | if (! isprint ((unsigned char) fn[i])) |
573 | fn[i] = '_'; | 576 | fn[i] = '_'; |
574 | uc->fd = open (fn, | 577 | uc->fd = open (fn, |
575 | O_CREAT | O_EXCL | 578 | O_CREAT | O_EXCL |
576 | #if O_LARGEFILE | 579 | #if O_LARGEFILE |
577 | | O_LARGEFILE | 580 | | O_LARGEFILE |
578 | #endif | 581 | #endif |
579 | | O_WRONLY, | 582 | | O_WRONLY, |
580 | S_IRUSR | S_IWUSR); | 583 | S_IRUSR | S_IWUSR); |
581 | if (-1 == uc->fd) | 584 | if (-1 == uc->fd) |
582 | { | 585 | { |
583 | fprintf (stderr, | 586 | fprintf (stderr, |
584 | "Error opening file `%s' for upload: %s\n", | 587 | "Error opening file `%s' for upload: %s\n", |
585 | fn, | 588 | fn, |
586 | strerror (errno)); | 589 | strerror (errno)); |
587 | uc->response = request_refused_response; | 590 | uc->response = request_refused_response; |
588 | return MHD_NO; | 591 | return MHD_NO; |
589 | } | ||
590 | uc->filename = strdup (fn); | ||
591 | } | 592 | } |
593 | uc->filename = strdup (fn); | ||
594 | } | ||
592 | if ( (0 != size) && | 595 | if ( (0 != size) && |
593 | (size != (size_t) write (uc->fd, data, size)) ) | 596 | (size != (size_t) write (uc->fd, data, size)) ) |
597 | { | ||
598 | /* write failed; likely: disk full */ | ||
599 | fprintf (stderr, | ||
600 | "Error writing to file `%s': %s\n", | ||
601 | uc->filename, | ||
602 | strerror (errno)); | ||
603 | uc->response = internal_error_response; | ||
604 | close (uc->fd); | ||
605 | uc->fd = -1; | ||
606 | if (NULL != uc->filename) | ||
594 | { | 607 | { |
595 | /* write failed; likely: disk full */ | 608 | unlink (uc->filename); |
596 | fprintf (stderr, | 609 | free (uc->filename); |
597 | "Error writing to file `%s': %s\n", | 610 | uc->filename = NULL; |
598 | uc->filename, | ||
599 | strerror (errno)); | ||
600 | uc->response = internal_error_response; | ||
601 | close (uc->fd); | ||
602 | uc->fd = -1; | ||
603 | if (NULL != uc->filename) | ||
604 | { | ||
605 | unlink (uc->filename); | ||
606 | free (uc->filename); | ||
607 | uc->filename = NULL; | ||
608 | } | ||
609 | return MHD_NO; | ||
610 | } | 611 | } |
612 | return MHD_NO; | ||
613 | } | ||
611 | return MHD_YES; | 614 | return MHD_YES; |
612 | } | 615 | } |
613 | 616 | ||
@@ -625,32 +628,32 @@ process_upload_data (void *cls, | |||
625 | */ | 628 | */ |
626 | static void | 629 | static void |
627 | response_completed_callback (void *cls, | 630 | response_completed_callback (void *cls, |
628 | struct MHD_Connection *connection, | 631 | struct MHD_Connection *connection, |
629 | void **con_cls, | 632 | void **con_cls, |
630 | enum MHD_RequestTerminationCode toe) | 633 | enum MHD_RequestTerminationCode toe) |
631 | { | 634 | { |
632 | struct UploadContext *uc = *con_cls; | 635 | struct UploadContext *uc = *con_cls; |
633 | (void)cls; /* Unused. Silent compiler warning. */ | 636 | (void) cls; /* Unused. Silent compiler warning. */ |
634 | (void)connection; /* Unused. Silent compiler warning. */ | 637 | (void) connection; /* Unused. Silent compiler warning. */ |
635 | (void)toe; /* Unused. Silent compiler warning. */ | 638 | (void) toe; /* Unused. Silent compiler warning. */ |
636 | 639 | ||
637 | if (NULL == uc) | 640 | if (NULL == uc) |
638 | return; /* this request wasn't an upload request */ | 641 | return; /* this request wasn't an upload request */ |
639 | if (NULL != uc->pp) | 642 | if (NULL != uc->pp) |
640 | { | 643 | { |
641 | MHD_destroy_post_processor (uc->pp); | 644 | MHD_destroy_post_processor (uc->pp); |
642 | uc->pp = NULL; | 645 | uc->pp = NULL; |
643 | } | 646 | } |
644 | if (-1 != uc->fd) | 647 | if (-1 != uc->fd) |
645 | { | 648 | { |
646 | (void) close (uc->fd); | 649 | (void) close (uc->fd); |
647 | if (NULL != uc->filename) | 650 | if (NULL != uc->filename) |
648 | { | 651 | { |
649 | fprintf (stderr, | 652 | fprintf (stderr, |
650 | "Upload of file `%s' failed (incomplete or aborted), removing file.\n", | 653 | "Upload of file `%s' failed (incomplete or aborted), removing file.\n", |
651 | uc->filename); | 654 | uc->filename); |
652 | (void) unlink (uc->filename); | 655 | (void) unlink (uc->filename); |
653 | } | 656 | } |
654 | } | 657 | } |
655 | if (NULL != uc->filename) | 658 | if (NULL != uc->filename) |
656 | free (uc->filename); | 659 | free (uc->filename); |
@@ -672,12 +675,12 @@ return_directory_response (struct MHD_Connection *connection) | |||
672 | (void) pthread_mutex_lock (&mutex); | 675 | (void) pthread_mutex_lock (&mutex); |
673 | if (NULL == cached_directory_response) | 676 | if (NULL == cached_directory_response) |
674 | ret = MHD_queue_response (connection, | 677 | ret = MHD_queue_response (connection, |
675 | MHD_HTTP_INTERNAL_SERVER_ERROR, | 678 | MHD_HTTP_INTERNAL_SERVER_ERROR, |
676 | internal_error_response); | 679 | internal_error_response); |
677 | else | 680 | else |
678 | ret = MHD_queue_response (connection, | 681 | ret = MHD_queue_response (connection, |
679 | MHD_HTTP_OK, | 682 | MHD_HTTP_OK, |
680 | cached_directory_response); | 683 | cached_directory_response); |
681 | (void) pthread_mutex_unlock (&mutex); | 684 | (void) pthread_mutex_unlock (&mutex); |
682 | return ret; | 685 | return ret; |
683 | } | 686 | } |
@@ -698,131 +701,131 @@ return_directory_response (struct MHD_Connection *connection) | |||
698 | */ | 701 | */ |
699 | static int | 702 | static int |
700 | generate_page (void *cls, | 703 | generate_page (void *cls, |
701 | struct MHD_Connection *connection, | 704 | struct MHD_Connection *connection, |
702 | const char *url, | 705 | const char *url, |
703 | const char *method, | 706 | const char *method, |
704 | const char *version, | 707 | const char *version, |
705 | const char *upload_data, | 708 | const char *upload_data, |
706 | size_t *upload_data_size, void **ptr) | 709 | size_t *upload_data_size, void **ptr) |
707 | { | 710 | { |
708 | struct MHD_Response *response; | 711 | struct MHD_Response *response; |
709 | int ret; | 712 | int ret; |
710 | int fd; | 713 | int fd; |
711 | struct stat buf; | 714 | struct stat buf; |
712 | (void)cls; /* Unused. Silent compiler warning. */ | 715 | (void) cls; /* Unused. Silent compiler warning. */ |
713 | (void)version; /* Unused. Silent compiler warning. */ | 716 | (void) version; /* Unused. Silent compiler warning. */ |
714 | 717 | ||
715 | if (0 != strcmp (url, "/")) | 718 | if (0 != strcmp (url, "/")) |
716 | { | 719 | { |
717 | /* should be file download */ | 720 | /* should be file download */ |
718 | #ifdef MHD_HAVE_LIBMAGIC | 721 | #ifdef MHD_HAVE_LIBMAGIC |
719 | char file_data[MAGIC_HEADER_SIZE]; | 722 | char file_data[MAGIC_HEADER_SIZE]; |
720 | ssize_t got; | 723 | ssize_t got; |
721 | #endif /* MHD_HAVE_LIBMAGIC */ | 724 | #endif /* MHD_HAVE_LIBMAGIC */ |
722 | const char *mime; | 725 | const char *mime; |
723 | 726 | ||
724 | if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) | 727 | if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) |
725 | return MHD_NO; /* unexpected method (we're not polite...) */ | 728 | return MHD_NO; /* unexpected method (we're not polite...) */ |
726 | fd = -1; | 729 | fd = -1; |
727 | if ( (NULL == strstr (&url[1], "..")) && | 730 | if ( (NULL == strstr (&url[1], "..")) && |
728 | ('/' != url[1]) ) | 731 | ('/' != url[1]) ) |
729 | { | 732 | { |
730 | fd = open (&url[1], O_RDONLY); | 733 | fd = open (&url[1], O_RDONLY); |
731 | if ( (-1 != fd) && | 734 | if ( (-1 != fd) && |
732 | ( (0 != fstat (fd, &buf)) || | 735 | ( (0 != fstat (fd, &buf)) || |
733 | (! S_ISREG (buf.st_mode)) ) ) | 736 | (! S_ISREG (buf.st_mode)) ) ) |
734 | { | 737 | { |
735 | (void) close (fd); | 738 | (void) close (fd); |
736 | fd = -1; | 739 | fd = -1; |
737 | } | 740 | } |
738 | } | 741 | } |
739 | if (-1 == fd) | 742 | if (-1 == fd) |
740 | return MHD_queue_response (connection, | 743 | return MHD_queue_response (connection, |
741 | MHD_HTTP_NOT_FOUND, | 744 | MHD_HTTP_NOT_FOUND, |
742 | file_not_found_response); | 745 | file_not_found_response); |
743 | #ifdef MHD_HAVE_LIBMAGIC | 746 | #ifdef MHD_HAVE_LIBMAGIC |
744 | /* read beginning of the file to determine mime type */ | 747 | /* read beginning of the file to determine mime type */ |
745 | got = read (fd, file_data, sizeof (file_data)); | 748 | got = read (fd, file_data, sizeof (file_data)); |
746 | (void) lseek (fd, 0, SEEK_SET); | 749 | (void) lseek (fd, 0, SEEK_SET); |
747 | if (-1 != got) | 750 | if (-1 != got) |
748 | mime = magic_buffer (magic, file_data, got); | 751 | mime = magic_buffer (magic, file_data, got); |
749 | else | 752 | else |
750 | #endif /* MHD_HAVE_LIBMAGIC */ | 753 | #endif /* MHD_HAVE_LIBMAGIC */ |
751 | mime = NULL; | 754 | mime = NULL; |
752 | 755 | ||
753 | if (NULL == (response = MHD_create_response_from_fd (buf.st_size, | 756 | if (NULL == (response = MHD_create_response_from_fd (buf.st_size, |
754 | fd))) | 757 | fd))) |
755 | { | 758 | { |
756 | /* internal error (i.e. out of memory) */ | 759 | /* internal error (i.e. out of memory) */ |
757 | (void) close (fd); | 760 | (void) close (fd); |
758 | return MHD_NO; | 761 | return MHD_NO; |
759 | } | ||
760 | |||
761 | /* add mime type if we had one */ | ||
762 | if (NULL != mime) | ||
763 | (void) MHD_add_response_header (response, | ||
764 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
765 | mime); | ||
766 | ret = MHD_queue_response (connection, | ||
767 | MHD_HTTP_OK, | ||
768 | response); | ||
769 | MHD_destroy_response (response); | ||
770 | return ret; | ||
771 | } | 762 | } |
772 | 763 | ||
764 | /* add mime type if we had one */ | ||
765 | if (NULL != mime) | ||
766 | (void) MHD_add_response_header (response, | ||
767 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
768 | mime); | ||
769 | ret = MHD_queue_response (connection, | ||
770 | MHD_HTTP_OK, | ||
771 | response); | ||
772 | MHD_destroy_response (response); | ||
773 | return ret; | ||
774 | } | ||
775 | |||
773 | if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) | 776 | if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) |
777 | { | ||
778 | /* upload! */ | ||
779 | struct UploadContext *uc = *ptr; | ||
780 | |||
781 | if (NULL == uc) | ||
782 | { | ||
783 | if (NULL == (uc = malloc (sizeof (struct UploadContext)))) | ||
784 | return MHD_NO; /* out of memory, close connection */ | ||
785 | memset (uc, 0, sizeof (struct UploadContext)); | ||
786 | uc->fd = -1; | ||
787 | uc->connection = connection; | ||
788 | uc->pp = MHD_create_post_processor (connection, | ||
789 | 64 * 1024 /* buffer size */, | ||
790 | &process_upload_data, uc); | ||
791 | if (NULL == uc->pp) | ||
792 | { | ||
793 | /* out of memory, close connection */ | ||
794 | free (uc); | ||
795 | return MHD_NO; | ||
796 | } | ||
797 | *ptr = uc; | ||
798 | return MHD_YES; | ||
799 | } | ||
800 | if (0 != *upload_data_size) | ||
801 | { | ||
802 | if (NULL == uc->response) | ||
803 | (void) MHD_post_process (uc->pp, | ||
804 | upload_data, | ||
805 | *upload_data_size); | ||
806 | *upload_data_size = 0; | ||
807 | return MHD_YES; | ||
808 | } | ||
809 | /* end of upload, finish it! */ | ||
810 | MHD_destroy_post_processor (uc->pp); | ||
811 | uc->pp = NULL; | ||
812 | if (-1 != uc->fd) | ||
813 | { | ||
814 | close (uc->fd); | ||
815 | uc->fd = -1; | ||
816 | } | ||
817 | if (NULL != uc->response) | ||
818 | { | ||
819 | return MHD_queue_response (connection, | ||
820 | MHD_HTTP_FORBIDDEN, | ||
821 | uc->response); | ||
822 | } | ||
823 | else | ||
774 | { | 824 | { |
775 | /* upload! */ | 825 | update_directory (); |
776 | struct UploadContext *uc = *ptr; | 826 | return return_directory_response (connection); |
777 | |||
778 | if (NULL == uc) | ||
779 | { | ||
780 | if (NULL == (uc = malloc (sizeof (struct UploadContext)))) | ||
781 | return MHD_NO; /* out of memory, close connection */ | ||
782 | memset (uc, 0, sizeof (struct UploadContext)); | ||
783 | uc->fd = -1; | ||
784 | uc->connection = connection; | ||
785 | uc->pp = MHD_create_post_processor (connection, | ||
786 | 64 * 1024 /* buffer size */, | ||
787 | &process_upload_data, uc); | ||
788 | if (NULL == uc->pp) | ||
789 | { | ||
790 | /* out of memory, close connection */ | ||
791 | free (uc); | ||
792 | return MHD_NO; | ||
793 | } | ||
794 | *ptr = uc; | ||
795 | return MHD_YES; | ||
796 | } | ||
797 | if (0 != *upload_data_size) | ||
798 | { | ||
799 | if (NULL == uc->response) | ||
800 | (void) MHD_post_process (uc->pp, | ||
801 | upload_data, | ||
802 | *upload_data_size); | ||
803 | *upload_data_size = 0; | ||
804 | return MHD_YES; | ||
805 | } | ||
806 | /* end of upload, finish it! */ | ||
807 | MHD_destroy_post_processor (uc->pp); | ||
808 | uc->pp = NULL; | ||
809 | if (-1 != uc->fd) | ||
810 | { | ||
811 | close (uc->fd); | ||
812 | uc->fd = -1; | ||
813 | } | ||
814 | if (NULL != uc->response) | ||
815 | { | ||
816 | return MHD_queue_response (connection, | ||
817 | MHD_HTTP_FORBIDDEN, | ||
818 | uc->response); | ||
819 | } | ||
820 | else | ||
821 | { | ||
822 | update_directory (); | ||
823 | return return_directory_response (connection); | ||
824 | } | ||
825 | } | 827 | } |
828 | } | ||
826 | if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) | 829 | if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) |
827 | { | 830 | { |
828 | return return_directory_response (connection); | 831 | return return_directory_response (connection); |
@@ -830,8 +833,8 @@ generate_page (void *cls, | |||
830 | 833 | ||
831 | /* unexpected request, refuse */ | 834 | /* unexpected request, refuse */ |
832 | return MHD_queue_response (connection, | 835 | return MHD_queue_response (connection, |
833 | MHD_HTTP_FORBIDDEN, | 836 | MHD_HTTP_FORBIDDEN, |
834 | request_refused_response); | 837 | request_refused_response); |
835 | } | 838 | } |
836 | 839 | ||
837 | 840 | ||
@@ -844,7 +847,7 @@ generate_page (void *cls, | |||
844 | static void | 847 | static void |
845 | catcher (int sig) | 848 | catcher (int sig) |
846 | { | 849 | { |
847 | (void)sig; /* Unused. Silent compiler warning. */ | 850 | (void) sig; /* Unused. Silent compiler warning. */ |
848 | /* do nothing */ | 851 | /* do nothing */ |
849 | } | 852 | } |
850 | 853 | ||
@@ -873,53 +876,53 @@ ignore_sigpipe (void) | |||
873 | 876 | ||
874 | /* test server key */ | 877 | /* test server key */ |
875 | const char srv_signed_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n" | 878 | const char srv_signed_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n" |
876 | "MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n" | 879 | "MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n" |
877 | "+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n" | 880 | "+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n" |
878 | "q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n" | 881 | "q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n" |
879 | "20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n" | 882 | "20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n" |
880 | "QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n" | 883 | "QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n" |
881 | "yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n" | 884 | "yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n" |
882 | "+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n" | 885 | "+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n" |
883 | "lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n" | 886 | "lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n" |
884 | "DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n" | 887 | "DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n" |
885 | "bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n" | 888 | "bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n" |
886 | "sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n" | 889 | "sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n" |
887 | "Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n" | 890 | "Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n" |
888 | "d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n" | 891 | "d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n" |
889 | "pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n" | 892 | "pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n" |
890 | "b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n" | 893 | "b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n" |
891 | "cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n" | 894 | "cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n" |
892 | "LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n" | 895 | "LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n" |
893 | "2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n" | 896 | "2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n" |
894 | "SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n" | 897 | "SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n" |
895 | "Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n" | 898 | "Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n" |
896 | "4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n" | 899 | "4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n" |
897 | "IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n" | 900 | "IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n" |
898 | "C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n" | 901 | "C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n" |
899 | "GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n" | 902 | "GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n" |
900 | "tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n" | 903 | "tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n" |
901 | "-----END RSA PRIVATE KEY-----\n"; | 904 | "-----END RSA PRIVATE KEY-----\n"; |
902 | 905 | ||
903 | /* test server CA signed certificates */ | 906 | /* test server CA signed certificates */ |
904 | const char srv_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n" | 907 | const char srv_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n" |
905 | "MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n" | 908 | "MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n" |
906 | "dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n" | 909 | "dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n" |
907 | "A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n" | 910 | "A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n" |
908 | "vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n" | 911 | "vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n" |
909 | "dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n" | 912 | "dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n" |
910 | "F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n" | 913 | "F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n" |
911 | "IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n" | 914 | "IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n" |
912 | "II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n" | 915 | "II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n" |
913 | "RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n" | 916 | "RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n" |
914 | "MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n" | 917 | "MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n" |
915 | "XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n" | 918 | "XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n" |
916 | "CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n" | 919 | "CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n" |
917 | "GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n" | 920 | "GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n" |
918 | "A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n" | 921 | "A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n" |
919 | "YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n" | 922 | "YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n" |
920 | "Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n" | 923 | "Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n" |
921 | "4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n" | 924 | "4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n" |
922 | "-----END CERTIFICATE-----\n"; | 925 | "-----END CERTIFICATE-----\n"; |
923 | 926 | ||
924 | 927 | ||
925 | /** | 928 | /** |
@@ -940,11 +943,11 @@ main (int argc, char *const *argv) | |||
940 | if ( (argc != 2) || | 943 | if ( (argc != 2) || |
941 | (1 != sscanf (argv[1], "%u", &port)) || | 944 | (1 != sscanf (argv[1], "%u", &port)) || |
942 | (UINT16_MAX < port) ) | 945 | (UINT16_MAX < port) ) |
943 | { | 946 | { |
944 | fprintf (stderr, | 947 | fprintf (stderr, |
945 | "%s PORT\n", argv[0]); | 948 | "%s PORT\n", argv[0]); |
946 | return 1; | 949 | return 1; |
947 | } | 950 | } |
948 | #ifndef MINGW | 951 | #ifndef MINGW |
949 | ignore_sigpipe (); | 952 | ignore_sigpipe (); |
950 | #endif | 953 | #endif |
@@ -954,35 +957,46 @@ main (int argc, char *const *argv) | |||
954 | #endif /* MHD_HAVE_LIBMAGIC */ | 957 | #endif /* MHD_HAVE_LIBMAGIC */ |
955 | 958 | ||
956 | (void) pthread_mutex_init (&mutex, NULL); | 959 | (void) pthread_mutex_init (&mutex, NULL); |
957 | file_not_found_response = MHD_create_response_from_buffer (strlen (FILE_NOT_FOUND_PAGE), | 960 | file_not_found_response = MHD_create_response_from_buffer (strlen ( |
958 | (void *) FILE_NOT_FOUND_PAGE, | 961 | FILE_NOT_FOUND_PAGE), |
959 | MHD_RESPMEM_PERSISTENT); | 962 | (void *) |
963 | FILE_NOT_FOUND_PAGE, | ||
964 | MHD_RESPMEM_PERSISTENT); | ||
960 | mark_as_html (file_not_found_response); | 965 | mark_as_html (file_not_found_response); |
961 | request_refused_response = MHD_create_response_from_buffer (strlen (REQUEST_REFUSED_PAGE), | 966 | request_refused_response = MHD_create_response_from_buffer (strlen ( |
962 | (void *) REQUEST_REFUSED_PAGE, | 967 | REQUEST_REFUSED_PAGE), |
963 | MHD_RESPMEM_PERSISTENT); | 968 | (void *) |
969 | REQUEST_REFUSED_PAGE, | ||
970 | MHD_RESPMEM_PERSISTENT); | ||
964 | mark_as_html (request_refused_response); | 971 | mark_as_html (request_refused_response); |
965 | internal_error_response = MHD_create_response_from_buffer (strlen (INTERNAL_ERROR_PAGE), | 972 | internal_error_response = MHD_create_response_from_buffer (strlen ( |
966 | (void *) INTERNAL_ERROR_PAGE, | 973 | INTERNAL_ERROR_PAGE), |
967 | MHD_RESPMEM_PERSISTENT); | 974 | (void *) |
975 | INTERNAL_ERROR_PAGE, | ||
976 | MHD_RESPMEM_PERSISTENT); | ||
968 | mark_as_html (internal_error_response); | 977 | mark_as_html (internal_error_response); |
969 | update_directory (); | 978 | update_directory (); |
970 | d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_TLS, | 979 | d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD |
980 | | MHD_USE_ERROR_LOG | MHD_USE_TLS, | ||
971 | port, | 981 | port, |
972 | NULL, NULL, | 982 | NULL, NULL, |
973 | &generate_page, NULL, | 983 | &generate_page, NULL, |
974 | MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (256 * 1024), | 984 | MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (256 |
985 | * 1024), | ||
975 | #if PRODUCTION | 986 | #if PRODUCTION |
976 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) (64), | 987 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) (64), |
977 | #endif | 988 | #endif |
978 | MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) (120 /* seconds */), | 989 | MHD_OPTION_CONNECTION_TIMEOUT, (unsigned |
979 | MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS, | 990 | int) (120 /* seconds */), |
980 | MHD_OPTION_NOTIFY_COMPLETED, &response_completed_callback, NULL, | 991 | MHD_OPTION_THREAD_POOL_SIZE, (unsigned |
981 | /* Optionally, the gnutls_load_file() can be used to | 992 | int) NUMBER_OF_THREADS, |
982 | load the key and the certificate from file. */ | 993 | MHD_OPTION_NOTIFY_COMPLETED, |
983 | MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, | 994 | &response_completed_callback, NULL, |
984 | MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, | 995 | /* Optionally, the gnutls_load_file() can be used to |
985 | MHD_OPTION_END); | 996 | load the key and the certificate from file. */ |
997 | MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, | ||
998 | MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, | ||
999 | MHD_OPTION_END); | ||
986 | if (NULL == d) | 1000 | if (NULL == d) |
987 | return 1; | 1001 | return 1; |
988 | fprintf (stderr, "HTTP server running. Press ENTER to stop the server\n"); | 1002 | fprintf (stderr, "HTTP server running. Press ENTER to stop the server\n"); |