diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-03-31 20:22:02 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-03-31 20:22:02 +0000 |
commit | 4b0588d78b33db21c483d52ade209bb0bf27a6dc (patch) | |
tree | 01658741162a9d8112dadc14782bd66634e097d5 | |
parent | 7b8fb41d1e766ed2285f3ad57f9d21f174471a53 (diff) | |
download | libmicrohttpd-4b0588d78b33db21c483d52ade209bb0bf27a6dc.tar.gz libmicrohttpd-4b0588d78b33db21c483d52ade209bb0bf27a6dc.zip |
add mime types to demo
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | src/examples/Makefile.am | 8 | ||||
-rw-r--r-- | src/examples/demo.c | 301 |
3 files changed, 246 insertions, 71 deletions
diff --git a/configure.ac b/configure.ac index 1a1e312a..ad3b1029 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -255,6 +255,14 @@ then | |||
255 | AC_DEFINE_UNQUOTED([MHD_REQ_CURL_GNUTLS_VERSION], "$MHD_REQ_CURL_GNUTLS_VERSION", [gnuTLS lib version - used in conjunction with cURL]) | 255 | AC_DEFINE_UNQUOTED([MHD_REQ_CURL_GNUTLS_VERSION], "$MHD_REQ_CURL_GNUTLS_VERSION", [gnuTLS lib version - used in conjunction with cURL]) |
256 | AC_DEFINE_UNQUOTED([MHD_REQ_CURL_NSS_VERSION], "$MHD_REQ_CURL_NSS_VERSION", [NSS lib version - used in conjunction with cURL]) | 256 | AC_DEFINE_UNQUOTED([MHD_REQ_CURL_NSS_VERSION], "$MHD_REQ_CURL_NSS_VERSION", [NSS lib version - used in conjunction with cURL]) |
257 | fi | 257 | fi |
258 | |||
259 | AC_MSG_CHECKING(for magic_open -lmagic) | ||
260 | AC_CHECK_LIB(magic, magic_open, | ||
261 | [AC_CHECK_HEADERS([magic.h], | ||
262 | AM_CONDITIONAL(HAVE_MAGIC, true), | ||
263 | AM_CONDITIONAL(HAVE_MAGIC, false))], | ||
264 | AM_CONDITIONAL(HAVE_MAGIC, false)) | ||
265 | |||
258 | LIBS=$SAVE_LIBS | 266 | LIBS=$SAVE_LIBS |
259 | AM_CONDITIONAL(HAVE_CURL, test x$curl = x1) | 267 | AM_CONDITIONAL(HAVE_CURL, test x$curl = x1) |
260 | 268 | ||
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index a27e5268..ef4de773 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am | |||
@@ -29,8 +29,11 @@ noinst_PROGRAMS += https_fileserver_example | |||
29 | endif | 29 | endif |
30 | if HAVE_POSTPROCESSOR | 30 | if HAVE_POSTPROCESSOR |
31 | noinst_PROGRAMS += \ | 31 | noinst_PROGRAMS += \ |
32 | demo \ | ||
33 | post_example | 32 | post_example |
33 | if HAVE_MAGIC | ||
34 | noinst_PROGRAMS += \ | ||
35 | demo | ||
36 | endif | ||
34 | endif | 37 | endif |
35 | 38 | ||
36 | if ENABLE_DAUTH | 39 | if ENABLE_DAUTH |
@@ -55,7 +58,8 @@ minimal_example_LDADD = \ | |||
55 | demo_SOURCES = \ | 58 | demo_SOURCES = \ |
56 | demo.c | 59 | demo.c |
57 | demo_LDADD = \ | 60 | demo_LDADD = \ |
58 | $(top_builddir)/src/daemon/libmicrohttpd.la | 61 | $(top_builddir)/src/daemon/libmicrohttpd.la \ |
62 | -lmagic | ||
59 | 63 | ||
60 | dual_stack_example_SOURCES = \ | 64 | dual_stack_example_SOURCES = \ |
61 | dual_stack_example.c | 65 | dual_stack_example.c |
diff --git a/src/examples/demo.c b/src/examples/demo.c index 0a600519..600b0f11 100644 --- a/src/examples/demo.c +++ b/src/examples/demo.c | |||
@@ -23,17 +23,23 @@ | |||
23 | * @author Christian Grothoff | 23 | * @author Christian Grothoff |
24 | * | 24 | * |
25 | * TODO: | 25 | * TODO: |
26 | * - even with LARGE memory pool & buffers, uploads proceed at 5000 bytes/call (ugh) | ||
27 | * - should have a slightly more ambitious upload form & file listing (structure!) | 26 | * - should have a slightly more ambitious upload form & file listing (structure!) |
28 | * - may want to add MIME-types to replies | ||
29 | */ | 27 | */ |
30 | #include "platform.h" | 28 | #include "platform.h" |
31 | #include <microhttpd.h> | 29 | #include <microhttpd.h> |
32 | #include <unistd.h> | 30 | #include <unistd.h> |
33 | #include <pthread.h> | 31 | #include <pthread.h> |
34 | #include <sys/types.h> | 32 | #include <sys/types.h> |
33 | #include <sys/stat.h> | ||
35 | #include <dirent.h> | 34 | #include <dirent.h> |
35 | #include <magic.h> | ||
36 | 36 | ||
37 | /** | ||
38 | * How many bytes of a file do we give to libmagic to determine the mime type? | ||
39 | * 16k might be a bit excessive, but ought not hurt performance much anyway, | ||
40 | * and should definitively be on the safe side. | ||
41 | */ | ||
42 | #define MAGIC_HEADER_SIZE (16 * 1024) | ||
37 | 43 | ||
38 | /** | 44 | /** |
39 | * Page returned for file-not-found. | 45 | * Page returned for file-not-found. |
@@ -48,6 +54,12 @@ | |||
48 | 54 | ||
49 | 55 | ||
50 | /** | 56 | /** |
57 | * Page returned for refused requests. | ||
58 | */ | ||
59 | #define REQUEST_REFUSED_PAGE "<html><head><title>Request refused</title></head><body>Request refused (file exists?)</body></html>" | ||
60 | |||
61 | |||
62 | /** | ||
51 | * Head of index page. | 63 | * Head of index page. |
52 | */ | 64 | */ |
53 | #define INDEX_PAGE_HEADER "<html>\n<head><title>Welcome</title></head>\n<body>\n"\ | 65 | #define INDEX_PAGE_HEADER "<html>\n<head><title>Welcome</title></head>\n<body>\n"\ |
@@ -63,6 +75,7 @@ | |||
63 | #define INDEX_PAGE_FOOTER "</ol>\n</body>\n</html>" | 75 | #define INDEX_PAGE_FOOTER "</ol>\n</body>\n</html>" |
64 | 76 | ||
65 | 77 | ||
78 | |||
66 | /** | 79 | /** |
67 | * Response returned if the requested file does not exist (or is not accessible). | 80 | * Response returned if the requested file does not exist (or is not accessible). |
68 | */ | 81 | */ |
@@ -79,10 +92,34 @@ static struct MHD_Response *internal_error_response; | |||
79 | static struct MHD_Response *cached_directory_response; | 92 | static struct MHD_Response *cached_directory_response; |
80 | 93 | ||
81 | /** | 94 | /** |
95 | * Response returned for refused uploads. | ||
96 | */ | ||
97 | static struct MHD_Response *request_refused_response; | ||
98 | |||
99 | /** | ||
82 | * Mutex used when we update the cached directory response object. | 100 | * Mutex used when we update the cached directory response object. |
83 | */ | 101 | */ |
84 | static pthread_mutex_t mutex; | 102 | static pthread_mutex_t mutex; |
85 | 103 | ||
104 | /** | ||
105 | * Global handle to MAGIC data. | ||
106 | */ | ||
107 | static magic_t magic; | ||
108 | |||
109 | |||
110 | /** | ||
111 | * Mark the given response as HTML for the brower. | ||
112 | * | ||
113 | * @param response response to mark | ||
114 | */ | ||
115 | static void | ||
116 | mark_as_html (struct MHD_Response *response) | ||
117 | { | ||
118 | (void) MHD_add_response_header (response, | ||
119 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
120 | "text/html"); | ||
121 | } | ||
122 | |||
86 | 123 | ||
87 | /** | 124 | /** |
88 | * Replace the existing 'cached_directory_response' with the | 125 | * Replace the existing 'cached_directory_response' with the |
@@ -102,68 +139,119 @@ update_cached_response (struct MHD_Response *response) | |||
102 | 139 | ||
103 | 140 | ||
104 | /** | 141 | /** |
105 | * Re-scan our local directory and re-build the index. | 142 | * Context keeping the data for the response we're building. |
106 | */ | 143 | */ |
107 | static void | 144 | struct ResponseDataContext |
108 | update_directory () | ||
109 | { | 145 | { |
110 | static size_t initial_allocation = 32 * 1024; /* initial size for response buffer */ | 146 | /** |
111 | DIR *dir; | 147 | * Response data string. |
112 | struct dirent *de; | 148 | */ |
113 | struct MHD_Response *response; | ||
114 | char *buf; | 149 | char *buf; |
150 | |||
151 | /** | ||
152 | * Number of bytes allocated for 'buf'. | ||
153 | */ | ||
115 | size_t buf_len; | 154 | size_t buf_len; |
155 | |||
156 | /** | ||
157 | * Current position where we append to 'buf'. Must be smaller or equal to 'buf_len'. | ||
158 | */ | ||
116 | size_t off; | 159 | size_t off; |
117 | 160 | ||
118 | dir = opendir ("."); | 161 | }; |
119 | if (NULL == dir) | 162 | |
120 | goto err; | 163 | |
121 | buf_len = initial_allocation; | 164 | /** |
122 | buf = malloc (buf_len); | 165 | * Create a listing of the files in 'dirname' in HTML. |
123 | if (NULL == buf) | 166 | * |
124 | { | 167 | * @param rdc where to store the list of files |
125 | closedir (dir); | 168 | * @param dirname name of the directory to list |
126 | goto err; | 169 | * @return MHD_YES on success, MHD_NO on error |
127 | } | 170 | */ |
128 | off = snprintf (buf, buf_len, | 171 | static int |
129 | "%s", | 172 | list_directory (struct ResponseDataContext *rdc, |
130 | INDEX_PAGE_HEADER); | 173 | const char *dirname) |
174 | { | ||
175 | char fullname[PATH_MAX]; | ||
176 | struct stat sbuf; | ||
177 | DIR *dir; | ||
178 | struct dirent *de; | ||
179 | |||
180 | if (NULL == (dir = opendir (dirname))) | ||
181 | return MHD_NO; | ||
131 | while (NULL != (de = readdir (dir))) | 182 | while (NULL != (de = readdir (dir))) |
132 | { | 183 | { |
133 | if ('.' == de->d_name[0]) | 184 | if ('.' == de->d_name[0]) |
134 | continue; | 185 | continue; |
135 | if (off + 1024 > buf_len) | 186 | if (sizeof (fullname) <= |
187 | snprintf (fullname, sizeof (fullname), | ||
188 | "%s/%s", | ||
189 | dirname, de->d_name)) | ||
190 | continue; /* ugh, file too long? how can this be!? */ | ||
191 | if (0 != stat (fullname, &sbuf)) | ||
192 | continue; /* ugh, failed to 'stat' */ | ||
193 | if (! S_ISREG (sbuf.st_mode)) | ||
194 | continue; /* not a regular file, skip */ | ||
195 | if (rdc->off + 1024 > rdc->buf_len) | ||
136 | { | 196 | { |
137 | void *r; | 197 | void *r; |
138 | 198 | ||
139 | if ( (2 * buf_len + 1024) < buf_len) | 199 | if ( (2 * rdc->buf_len + 1024) < rdc->buf_len) |
140 | break; /* more than SIZE_T _index_ size? Too big for us */ | 200 | break; /* more than SIZE_T _index_ size? Too big for us */ |
141 | buf_len = 2 * buf_len + 1024; | 201 | rdc->buf_len = 2 * rdc->buf_len + 1024; |
142 | if (NULL == (r = realloc (buf, buf_len))) | 202 | if (NULL == (r = realloc (rdc->buf, rdc->buf_len))) |
143 | break; /* out of memory */ | 203 | break; /* out of memory */ |
144 | buf = r; | 204 | rdc->buf = r; |
145 | } | 205 | } |
146 | off += snprintf (&buf[off], buf_len - off, | 206 | rdc->off += snprintf (&rdc->buf[rdc->off], |
147 | "<li><a href=\"/%s\">%s</a></li>\n", | 207 | rdc->buf_len - rdc->off, |
148 | de->d_name, | 208 | "<li><a href=\"/%s\">%s</a></li>\n", |
149 | de->d_name); | 209 | de->d_name, |
210 | de->d_name); | ||
211 | } | ||
212 | (void) closedir (dir); | ||
213 | return MHD_YES; | ||
214 | } | ||
215 | |||
216 | |||
217 | /** | ||
218 | * Re-scan our local directory and re-build the index. | ||
219 | */ | ||
220 | static void | ||
221 | update_directory () | ||
222 | { | ||
223 | static size_t initial_allocation = 32 * 1024; /* initial size for response buffer */ | ||
224 | struct MHD_Response *response; | ||
225 | struct ResponseDataContext rdc; | ||
226 | |||
227 | rdc.buf_len = initial_allocation; | ||
228 | if (NULL == (rdc.buf = malloc (rdc.buf_len))) | ||
229 | { | ||
230 | update_cached_response (NULL); | ||
231 | return; | ||
232 | } | ||
233 | rdc.off = snprintf (rdc.buf, rdc.buf_len, | ||
234 | "%s", | ||
235 | INDEX_PAGE_HEADER); | ||
236 | |||
237 | if (MHD_NO == list_directory (&rdc, ".")) | ||
238 | { | ||
239 | free (rdc.buf); | ||
240 | update_cached_response (NULL); | ||
241 | return; | ||
150 | } | 242 | } |
151 | /* we ensured always +1k room, filenames are ~256 bytes, | 243 | /* we ensured always +1k room, filenames are ~256 bytes, |
152 | so there is always still enough space for the footer | 244 | so there is always still enough space for the footer |
153 | without need for a final reallocation check. */ | 245 | without need for a final reallocation check. */ |
154 | off += snprintf (&buf[off], buf_len - off, | 246 | rdc.off += snprintf (&rdc.buf[rdc.off], rdc.buf_len - rdc.off, |
155 | "%s", | 247 | "%s", |
156 | INDEX_PAGE_FOOTER); | 248 | INDEX_PAGE_FOOTER); |
157 | closedir (dir); | 249 | initial_allocation = rdc.buf_len; /* remember for next time */ |
158 | initial_allocation = buf_len; /* remember for next time */ | 250 | response = MHD_create_response_from_buffer (rdc.off, |
159 | response = MHD_create_response_from_buffer (off, | 251 | rdc.buf, |
160 | buf, | ||
161 | MHD_RESPMEM_MUST_FREE); | 252 | MHD_RESPMEM_MUST_FREE); |
253 | mark_as_html (response); | ||
162 | update_cached_response (response); | 254 | update_cached_response (response); |
163 | return; | ||
164 | err: | ||
165 | /* failed to list directory, use error page */ | ||
166 | update_cached_response (NULL); | ||
167 | } | 255 | } |
168 | 256 | ||
169 | 257 | ||
@@ -178,6 +266,11 @@ struct UploadContext | |||
178 | int fd; | 266 | int fd; |
179 | 267 | ||
180 | /** | 268 | /** |
269 | * Name of the file on disk (used to remove on errors). | ||
270 | */ | ||
271 | char *filename; | ||
272 | |||
273 | /** | ||
181 | * Post processor we're using to process the upload. | 274 | * Post processor we're using to process the upload. |
182 | */ | 275 | */ |
183 | struct MHD_PostProcessor *pp; | 276 | struct MHD_PostProcessor *pp; |
@@ -186,6 +279,11 @@ struct UploadContext | |||
186 | * Handle to connection that we're processing the upload for. | 279 | * Handle to connection that we're processing the upload for. |
187 | */ | 280 | */ |
188 | struct MHD_Connection *connection; | 281 | struct MHD_Connection *connection; |
282 | |||
283 | /** | ||
284 | * Response to generate, NULL to use directory. | ||
285 | */ | ||
286 | struct MHD_Response *response; | ||
189 | }; | 287 | }; |
190 | 288 | ||
191 | 289 | ||
@@ -228,32 +326,48 @@ process_upload_data (void *cls, | |||
228 | } | 326 | } |
229 | if (-1 == uc->fd) | 327 | if (-1 == uc->fd) |
230 | { | 328 | { |
329 | if ( (NULL != strstr (filename, "..")) || | ||
330 | (NULL != strchr (filename, '/')) || | ||
331 | (NULL != strchr (filename, '\\')) ) | ||
332 | { | ||
333 | uc->response = request_refused_response; | ||
334 | return MHD_NO; | ||
335 | } | ||
231 | uc->fd = open (filename, | 336 | uc->fd = open (filename, |
232 | O_CREAT | O_EXCL | 337 | O_CREAT | O_EXCL |
233 | #if O_LARGEFILE | 338 | #if O_LARGEFILE |
234 | | O_LARGEFILE | 339 | | O_LARGEFILE |
235 | #endif | 340 | #endif |
236 | #if O_NONBLOCK | ||
237 | | O_NONBLOCK | ||
238 | #endif | ||
239 | | O_WRONLY, | 341 | | O_WRONLY, |
240 | S_IRUSR | S_IWUSR); | 342 | S_IRUSR | S_IWUSR); |
241 | if (-1 == uc->fd) | 343 | if (-1 == uc->fd) |
242 | { | 344 | { |
243 | // FIXME: generate error page NICELY | 345 | fprintf (stderr, |
244 | fprintf (stderr, "Error opening file to write!\n"); | 346 | "Error opening file `%s' for upload: %s\n", |
347 | filename, | ||
348 | strerror (errno)); | ||
349 | uc->response = request_refused_response; | ||
245 | return MHD_NO; | 350 | return MHD_NO; |
246 | } | 351 | } |
247 | } | 352 | } |
248 | else if (0 == size) | 353 | uc->filename = strdup (filename); |
249 | sleep (1); | ||
250 | |||
251 | |||
252 | if ( (0 != size) && | 354 | if ( (0 != size) && |
253 | (size != write (uc->fd, data, size)) ) | 355 | (size != write (uc->fd, data, size)) ) |
254 | { | 356 | { |
255 | // FIXME: generate error page NICELY | 357 | /* write failed; likely: disk full */ |
256 | fprintf (stderr, "Error writing to disk!\n"); | 358 | fprintf (stderr, |
359 | "Error writing to file `%s': %s\n", | ||
360 | filename, | ||
361 | strerror (errno)); | ||
362 | uc->response = internal_error_response; | ||
363 | close (uc->fd); | ||
364 | uc->fd = -1; | ||
365 | if (NULL != uc->filename) | ||
366 | { | ||
367 | unlink (uc->filename); | ||
368 | free (uc->filename); | ||
369 | uc->filename = NULL; | ||
370 | } | ||
257 | return MHD_NO; | 371 | return MHD_NO; |
258 | } | 372 | } |
259 | return MHD_YES; | 373 | return MHD_YES; |
@@ -288,10 +402,17 @@ response_completed_callback (void *cls, | |||
288 | } | 402 | } |
289 | if (-1 != uc->fd) | 403 | if (-1 != uc->fd) |
290 | { | 404 | { |
291 | close (uc->fd); | 405 | (void) close (uc->fd); |
292 | fprintf (stderr, "Possible upload failure, need to remove file?!\n"); | 406 | if (NULL != uc->filename) |
293 | /* FIXME: unlink here on error!? */ | 407 | { |
408 | fprintf (stderr, | ||
409 | "Upload of file `%s' failed (incomplete or aborted), removing file.\n", | ||
410 | uc->filename); | ||
411 | (void) unlink (uc->filename); | ||
412 | } | ||
294 | } | 413 | } |
414 | if (NULL != uc->filename) | ||
415 | free (uc->filename); | ||
295 | free (uc); | 416 | free (uc); |
296 | } | 417 | } |
297 | 418 | ||
@@ -303,7 +424,7 @@ response_completed_callback (void *cls, | |||
303 | * @return MHD_YES on success, MHD_NO on error | 424 | * @return MHD_YES on success, MHD_NO on error |
304 | */ | 425 | */ |
305 | static int | 426 | static int |
306 | list_directory (struct MHD_Connection *connection) | 427 | return_directory_response (struct MHD_Connection *connection) |
307 | { | 428 | { |
308 | int ret; | 429 | int ret; |
309 | 430 | ||
@@ -321,7 +442,6 @@ list_directory (struct MHD_Connection *connection) | |||
321 | } | 442 | } |
322 | 443 | ||
323 | 444 | ||
324 | |||
325 | /** | 445 | /** |
326 | * Main callback from MHD, used to generate the page. | 446 | * Main callback from MHD, used to generate the page. |
327 | * | 447 | * |
@@ -352,6 +472,10 @@ generate_page (void *cls, | |||
352 | if (0 != strcmp (url, "/")) | 472 | if (0 != strcmp (url, "/")) |
353 | { | 473 | { |
354 | /* should be file download */ | 474 | /* should be file download */ |
475 | char file_data[MAGIC_HEADER_SIZE]; | ||
476 | ssize_t got; | ||
477 | const char *mime; | ||
478 | |||
355 | if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) | 479 | if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) |
356 | return MHD_NO; /* unexpected method (we're not polite...) */ | 480 | return MHD_NO; /* unexpected method (we're not polite...) */ |
357 | if ( (0 == stat (&url[1], &buf)) && | 481 | if ( (0 == stat (&url[1], &buf)) && |
@@ -364,6 +488,14 @@ generate_page (void *cls, | |||
364 | return MHD_queue_response (connection, | 488 | return MHD_queue_response (connection, |
365 | MHD_HTTP_NOT_FOUND, | 489 | MHD_HTTP_NOT_FOUND, |
366 | file_not_found_response); | 490 | file_not_found_response); |
491 | /* read beginning of the file to determine mime type */ | ||
492 | got = read (fd, file_data, sizeof (file_data)); | ||
493 | if (-1 != got) | ||
494 | mime = magic_buffer (magic, file_data, got); | ||
495 | else | ||
496 | mime = NULL; | ||
497 | (void) lseek (fd, 0, SEEK_SET); | ||
498 | |||
367 | if (NULL == (response = MHD_create_response_from_fd (buf.st_size, | 499 | if (NULL == (response = MHD_create_response_from_fd (buf.st_size, |
368 | fd))) | 500 | fd))) |
369 | { | 501 | { |
@@ -371,6 +503,12 @@ generate_page (void *cls, | |||
371 | (void) close (fd); | 503 | (void) close (fd); |
372 | return MHD_NO; | 504 | return MHD_NO; |
373 | } | 505 | } |
506 | |||
507 | /* add mime type if we had one */ | ||
508 | if (NULL != mime) | ||
509 | (void) MHD_add_response_header (response, | ||
510 | MHD_HTTP_HEADER_CONTENT_TYPE, | ||
511 | mime); | ||
374 | ret = MHD_queue_response (connection, | 512 | ret = MHD_queue_response (connection, |
375 | MHD_HTTP_OK, | 513 | MHD_HTTP_OK, |
376 | response); | 514 | response); |
@@ -387,6 +525,8 @@ generate_page (void *cls, | |||
387 | { | 525 | { |
388 | if (NULL == (uc = malloc (sizeof (struct UploadContext)))) | 526 | if (NULL == (uc = malloc (sizeof (struct UploadContext)))) |
389 | return MHD_NO; /* out of memory, close connection */ | 527 | return MHD_NO; /* out of memory, close connection */ |
528 | uc->response = NULL; | ||
529 | uc->filename = NULL; | ||
390 | uc->fd = -1; | 530 | uc->fd = -1; |
391 | uc->connection = connection; | 531 | uc->connection = connection; |
392 | uc->pp = MHD_create_post_processor (connection, | 532 | uc->pp = MHD_create_post_processor (connection, |
@@ -400,14 +540,15 @@ generate_page (void *cls, | |||
400 | } | 540 | } |
401 | *ptr = uc; | 541 | *ptr = uc; |
402 | return MHD_YES; | 542 | return MHD_YES; |
403 | } | 543 | } |
404 | if (0 != *upload_data_size) | 544 | if (0 != *upload_data_size) |
405 | { | 545 | { |
406 | ret = MHD_post_process (uc->pp, | 546 | if (NULL != uc->response) |
407 | upload_data, | 547 | (void) MHD_post_process (uc->pp, |
408 | *upload_data_size); | 548 | upload_data, |
549 | *upload_data_size); | ||
409 | *upload_data_size = 0; | 550 | *upload_data_size = 0; |
410 | return ret; | 551 | return MHD_YES; |
411 | } | 552 | } |
412 | /* end of upload, finish it! */ | 553 | /* end of upload, finish it! */ |
413 | MHD_destroy_post_processor (uc->pp); | 554 | MHD_destroy_post_processor (uc->pp); |
@@ -417,22 +558,32 @@ generate_page (void *cls, | |||
417 | close (uc->fd); | 558 | close (uc->fd); |
418 | uc->fd = -1; | 559 | uc->fd = -1; |
419 | } | 560 | } |
420 | update_directory (); | 561 | if (NULL != uc->response) |
421 | return list_directory (connection); | 562 | { |
563 | return MHD_queue_response (connection, | ||
564 | MHD_HTTP_FORBIDDEN, | ||
565 | uc->response); | ||
566 | } | ||
567 | else | ||
568 | { | ||
569 | update_directory (); | ||
570 | return return_directory_response (connection); | ||
571 | } | ||
422 | } | 572 | } |
423 | if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) | 573 | if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) |
424 | return list_directory (connection); | 574 | return return_directory_response (connection); |
425 | 575 | ||
426 | /* unexpected request, refuse */ | 576 | /* unexpected request, refuse */ |
427 | fprintf (stderr, "Unexpected request, refusing\n"); | 577 | return MHD_queue_response (connection, |
428 | return MHD_NO; | 578 | MHD_HTTP_FORBIDDEN, |
579 | request_refused_response); | ||
429 | } | 580 | } |
430 | 581 | ||
431 | 582 | ||
432 | /** | 583 | /** |
433 | * Entry point to demo. Note: this HTTP server will make all | 584 | * Entry point to demo. Note: this HTTP server will make all |
434 | * files in the current directory and its subdirectories available | 585 | * files in the current directory and its subdirectories available |
435 | * to anyone. | 586 | * to anyone. Press ENTER to stop the server once it has started. |
436 | * | 587 | * |
437 | * @param argc number of arguments in argv | 588 | * @param argc number of arguments in argv |
438 | * @param argv first and only argument should be the port number | 589 | * @param argv first and only argument should be the port number |
@@ -452,13 +603,22 @@ main (int argc, char *const *argv) | |||
452 | "%s PORT\n", argv[0]); | 603 | "%s PORT\n", argv[0]); |
453 | return 1; | 604 | return 1; |
454 | } | 605 | } |
606 | magic = magic_open (MAGIC_MIME_TYPE); | ||
607 | (void) magic_load (magic, NULL); | ||
608 | |||
455 | (void) pthread_mutex_init (&mutex, NULL); | 609 | (void) pthread_mutex_init (&mutex, NULL); |
456 | file_not_found_response = MHD_create_response_from_buffer (strlen (FILE_NOT_FOUND_PAGE), | 610 | file_not_found_response = MHD_create_response_from_buffer (strlen (FILE_NOT_FOUND_PAGE), |
457 | (void *) FILE_NOT_FOUND_PAGE, | 611 | (void *) FILE_NOT_FOUND_PAGE, |
458 | MHD_RESPMEM_PERSISTENT); | 612 | MHD_RESPMEM_PERSISTENT); |
613 | mark_as_html (file_not_found_response); | ||
614 | request_refused_response = MHD_create_response_from_buffer (strlen (REQUEST_REFUSED_PAGE), | ||
615 | (void *) REQUEST_REFUSED_PAGE, | ||
616 | MHD_RESPMEM_PERSISTENT); | ||
617 | mark_as_html (request_refused_response); | ||
459 | internal_error_response = MHD_create_response_from_buffer (strlen (INTERNAL_ERROR_PAGE), | 618 | internal_error_response = MHD_create_response_from_buffer (strlen (INTERNAL_ERROR_PAGE), |
460 | (void *) INTERNAL_ERROR_PAGE, | 619 | (void *) INTERNAL_ERROR_PAGE, |
461 | MHD_RESPMEM_PERSISTENT); | 620 | MHD_RESPMEM_PERSISTENT); |
621 | mark_as_html (internal_error_response); | ||
462 | update_directory (); | 622 | update_directory (); |
463 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | 623 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, |
464 | port, | 624 | port, |
@@ -470,12 +630,15 @@ main (int argc, char *const *argv) | |||
470 | MHD_OPTION_END); | 630 | MHD_OPTION_END); |
471 | if (NULL == d) | 631 | if (NULL == d) |
472 | return 1; | 632 | return 1; |
633 | fprintf (stderr, "HTTP server running. Press ENTER to stop the server\n"); | ||
473 | (void) getc (stdin); | 634 | (void) getc (stdin); |
474 | MHD_stop_daemon (d); | 635 | MHD_stop_daemon (d); |
475 | MHD_destroy_response (file_not_found_response); | 636 | MHD_destroy_response (file_not_found_response); |
637 | MHD_destroy_response (request_refused_response); | ||
476 | MHD_destroy_response (internal_error_response); | 638 | MHD_destroy_response (internal_error_response); |
477 | update_cached_response (NULL); | 639 | update_cached_response (NULL); |
478 | (void) pthread_mutex_destroy (&mutex); | 640 | (void) pthread_mutex_destroy (&mutex); |
641 | magic_close (magic); | ||
479 | return 0; | 642 | return 0; |
480 | } | 643 | } |
481 | 644 | ||