From c8b8e9f74d207b38f0d76443d64cba6763167104 Mon Sep 17 00:00:00 2001 From: bel Date: Sat, 20 Aug 2016 01:43:14 +0200 Subject: [PATCH] Add example for parsing uploaded files on the fly --- examples/embedded_c/embedded_c.c | 182 +++++++++++++++++++++++++++++-- 1 file changed, 172 insertions(+), 10 deletions(-) diff --git a/examples/embedded_c/embedded_c.c b/examples/embedded_c/embedded_c.c index 33511ce8..9def923b 100644 --- a/examples/embedded_c/embedded_c.c +++ b/examples/embedded_c/embedded_c.c @@ -40,7 +40,9 @@ int exitNow = 0; int ExampleHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This is an example text from a C handler

"); mg_printf( @@ -74,6 +76,10 @@ ExampleHandler(struct mg_connection *conn, void *cbdata) mg_printf(conn, "

To see a page from the CookieHandler handler click cookie

"); + mg_printf(conn, + "

To see an example for parsing files on the fly click form (form for " + "uploading files)

"); #ifdef USE_WEBSOCKET mg_printf(conn, @@ -89,7 +95,9 @@ ExampleHandler(struct mg_connection *conn, void *cbdata) int ExitHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); mg_printf(conn, "Server will shut down.\n"); mg_printf(conn, "Bye!\n"); exitNow = 1; @@ -100,7 +108,9 @@ ExitHandler(struct mg_connection *conn, void *cbdata) int AHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This is the A handler!!!

"); mg_printf(conn, "\n"); @@ -111,7 +121,9 @@ AHandler(struct mg_connection *conn, void *cbdata) int ABHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This is the AB handler!!!

"); mg_printf(conn, "\n"); @@ -125,7 +137,9 @@ BXHandler(struct mg_connection *conn, void *cbdata) /* Handler may access the request info using mg_get_request_info */ const struct mg_request_info *req_info = mg_get_request_info(conn); - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This is the BX handler %p!!!

", cbdata); mg_printf(conn, "

The actual uri is %s

", req_info->uri); @@ -140,7 +154,9 @@ FooHandler(struct mg_connection *conn, void *cbdata) /* Handler may access the request info using mg_get_request_info */ const struct mg_request_info *req_info = mg_get_request_info(conn); - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This is the Foo handler!!!

"); mg_printf(conn, @@ -159,7 +175,9 @@ CloseHandler(struct mg_connection *conn, void *cbdata) /* Handler may access the request info using mg_get_request_info */ const struct mg_request_info *req_info = mg_get_request_info(conn); - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This handler will close the connection in a second

"); @@ -256,7 +274,9 @@ FormHandler(struct mg_connection *conn, void *cbdata) * mg_handle_form_request. */ (void)req_info; - mg_printf(conn, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); fdh.user_data = (void *)conn; /* Call the form handler */ @@ -268,6 +288,136 @@ FormHandler(struct mg_connection *conn, void *cbdata) } +int +FileUploadForm(struct mg_connection *conn, void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + + mg_printf(conn, "\n"); + mg_printf(conn, "\n\n"); + mg_printf(conn, "\n"); + mg_printf(conn, "File upload\n"); + mg_printf(conn, "\n\n"); + mg_printf(conn, + "
\n", + (const char *)cbdata); + mg_printf(conn, "\n"); + mg_printf(conn, "\n"); + mg_printf(conn, "
\n\n\n"); + return 1; +} + +#define MD5_STATIC static +#include "../src/md5.inl" + +struct tfile_checksum { + char name[128]; + unsigned long long length; + md5_state_t chksum; +}; + +#define MAX_FILES (10) + +struct tfiles_checksums { + int index; + struct tfile_checksum file[MAX_FILES]; +}; + + +int +field_disp_read_on_the_fly(const char *key, + const char *filename, + char *path, + size_t pathlen, + void *user_data) +{ + struct tfiles_checksums *context = (struct tfiles_checksums *)user_data; + + (void)key; + (void)path; + (void)pathlen; + + if (context->index < MAX_FILES) { + context->index++; + strncpy(context->file[context->index - 1].name, filename, 128); + context->file[context->index - 1].name[127] = 0; + context->file[context->index - 1].length = 0; + md5_init(&(context->file[context->index - 1].chksum)); + return FORM_FIELD_STORAGE_GET; + } + return FORM_FIELD_STORAGE_ABORT; +} + + +int +field_get_checksum(const char *key, + const char *value, + size_t valuelen, + void *user_data) +{ + struct tfiles_checksums *context = (struct tfiles_checksums *)user_data; + + char path[1026]; + FILE *f; + + (void)key; + + context->file[context->index - 1].length += valuelen; + md5_append(&(context->file[context->index - 1].chksum), + (const md5_byte_t *)value, + valuelen); + + return 0; +} + + +int +CheckSumHandler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + int i, j, ret; + struct tfiles_checksums chksums; + md5_byte_t digest[16]; + struct mg_form_data_handler fdh = {field_disp_read_on_the_fly, + field_get_checksum, + 0, + (void *)&chksums}; + + /* It would be possible to check the request info here before calling + * mg_handle_form_request. */ + (void)req_info; + + memset(&chksums, 0, sizeof(chksums)); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n"); + + /* Call the form handler */ + mg_printf(conn, "File checksums:"); + ret = mg_handle_form_request(conn, &fdh); + for (i = 0; i < chksums.index; i++) { + md5_finish(&(chksums.file[i].chksum), digest); + /* Visual Studio 2010+ support llu */ + mg_printf(conn, + "\r\n%s %llu ", + chksums.file[i].name, + chksums.file[i].length); + for (j = 0; j < 16; j++) { + mg_printf(conn, "%02x", (unsigned int)digest[j]); + } + } + mg_printf(conn, "\r\n%i files\r\n", ret); + + return 1; +} + + int CookieHandler(struct mg_connection *conn, void *cbdata) { @@ -280,7 +430,7 @@ CookieHandler(struct mg_connection *conn, void *cbdata) (void)mg_get_cookie(cookie, "first", first_str, sizeof(first_str)); (void)mg_get_cookie(cookie, "count", count_str, sizeof(count_str)); - mg_printf(conn, "HTTP/1.1 200 OK\r\n"); + mg_printf(conn, "HTTP/1.1 200 OK\r\nConnection: close\r\n"); if (first_str[0] == 0) { time_t t = time(0); struct tm *ptm = localtime(&t); @@ -316,7 +466,9 @@ CookieHandler(struct mg_connection *conn, void *cbdata) int WebSocketStartHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); mg_printf(conn, "\n"); mg_printf(conn, "\n\n"); @@ -577,6 +729,16 @@ main(int argc, char *argv[]) FormHandler, (void *)0); + /* Add a file upload handler for parsing files on the fly */ + mg_set_request_handler(ctx, + "/on_the_fly_form", + FileUploadForm, + (void *)"/on_the_fly_form.md5.callback"); + mg_set_request_handler(ctx, + "/on_the_fly_form.md5.callback", + CheckSumHandler, + (void *)0); + /* Add handler for /cookie example */ mg_set_request_handler(ctx, "/cookie", CookieHandler, 0);