aboutsummaryrefslogtreecommitdiff
path: root/src/examples/demo_https.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/examples/demo_https.c')
-rw-r--r--src/examples/demo_https.c846
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 */
130static const char * const categories[] = 134static 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 */
163static const struct Language languages[] = 166static 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
213mark_as_html (struct MHD_Response *response) 215mark_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 */
268static int 270static int
269list_directory (struct ResponseDataContext *rdc, 271list_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 */
447static int 450static int
448do_append (char **ret, 451do_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 */
496static int 499static int
497process_upload_data (void *cls, 500process_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 */
626static void 629static void
627response_completed_callback (void *cls, 630response_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 */
699static int 702static int
700generate_page (void *cls, 703generate_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,
844static void 847static void
845catcher (int sig) 848catcher (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 */
875const char srv_signed_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n" 878const 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 */
904const char srv_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n" 907const 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");