From 316d434ea8c0e7de1359dd04644cdc9dc955c839 Mon Sep 17 00:00:00 2001 From: Max Christian Pohle Date: Wed, 17 Nov 2021 21:54:56 +0100 Subject: That is much better now --- main.c | 178 +++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 95 insertions(+), 83 deletions(-) diff --git a/main.c b/main.c index 2bf2e14..7fef5f3 100644 --- a/main.c +++ b/main.c @@ -54,12 +54,16 @@ void read_everything(FILE * f_r, FILE * output) { if(-2 == size || (-1 == size && EWOULDBLOCK == errno)) { usleep(EWOULDBLOCK_DELAY); // try again a little later continue; - } else if (1 != size) { // I expect one nmemb of data - break; } fwrite(read_buffer, read_buffer_length, 1, output); + fwrite(read_buffer, read_buffer_length, 1, stdout); + + if (1 != size) { // I expect one nmemb of data + break; + } } + fflush(stdout); fflush(output); } @@ -83,6 +87,14 @@ void header_next(const char * key, const char * value) { } } +typedef struct { + int newline_length; // lenght of one newline in bytes (\n has 1, CR/LF has 2) + char * method; + char * boundary; + char * content_type; + char * content_disposition; +} Http_Header; + void * next_customer(size_t new_socket) { FILE * f_r = fdopen((size_t) new_socket, "r"); FILE * f_w = fdopen((size_t) new_socket, "w"); @@ -93,111 +105,111 @@ void * next_customer(size_t new_socket) { verbose("\n\n########################################## Content Reader [%d]\n", f_r); read_everything(f_r, output); - verbose("\n\n########################################## Content Parser"); + verbose("\n\n########################################## Content Parser\n"); // token parser... - const char * boundary = NULL; - size_t boundary_length = 0; - char * search = NULL; char * key = output_buffer; char * saveptr = NULL; char * content_start = NULL; char * content_end = NULL; - while(key ? key[0] != '\0' : 1) { - verbose("> [!] Next iteration with search '%s'\n", search); - for(char * - token = strtok_r(NULL == saveptr ? output_buffer : saveptr, NULL == search ? "\n\r" : search, &saveptr); - token != NULL; - token = strtok_r(NULL, search, &saveptr)) - { - - if(!search) { // first round: HTTP status code - verbose("> First Iteration: HTTP sanity check of: %s\n", token); - search = ":"; - continue; - } + char * start = output_buffer; + char * end; + char * search = "\r\n"; + + Http_Header http_header; + http_header.newline_length = 1; + http_header.method = NULL; + http_header.boundary = NULL; + http_header.content_disposition = NULL; + http_header.content_type = NULL; + + char * name = NULL; + while(NULL != (end = strpbrk(start, search))) { - if(!key) { - search = "\r\n"; // we found a key and expect the value to be between here and EOL - key = &token[strspn(token, search)]; // also remove leading spaces + size_t matchlen = strspn(end, search); + switch(end[0]) { + case ':': + end[0] = '\0'; + end++; - if(0 == strncmp(token, "\n\r\n", 3) - || 0 == strncmp(token, "\n\n", 2)) { + name = start; + + if (0 == strcasecmp("Content-Type", start)) { + search = "\r\n;"; + } else { search = "\r\n"; + } + break; + case ';': + { + start += strspn(start, "; "); + + const char s_multipart_form_data[] = "boundary="; + if(NULL == http_header.boundary && 0 < strcasecmp(start, s_multipart_form_data)) + { + http_header.boundary = end + sizeof(s_multipart_form_data) + 1; + http_header.boundary += strspn(http_header.boundary, "-"); + // verbose("GESCHAFFT %s QQQQ %s\n", http_header.boundary, end); + search = "\r\n"; + continue; + } break; } - } else { // value - - token += strspn(token, ": "); - const char * value = token; - - const char pattern[] = "multipart/form-data; boundary="; - if(!boundary && strstr(key, "Content-Type") && strncmp(value, pattern, sizeof(pattern))) { - boundary = &value[sizeof(pattern) + strspn(&value[sizeof(pattern)], "-")]; - boundary_length = strlen(boundary); - verbose("> [!] boundary detected '%s' ", boundary); + case '\r': // fallthrough + case '\n': + end[0] = '\0'; + search = ":"; // we will continue to search for headers + + + if(NULL == name) { + if(NULL == http_header.method) { + verbose("[%ld]> HTTP REQUEST LINE :: %s \n", matchlen, start); + http_header.method = start; + http_header.newline_length = matchlen; + } else { + verbose("[...]\n"); // if we want to intentially skip something, we land here by setting name = NUL; + break; + } + } else { // we know that name is not NULL and can work with it + if (0 == strcasecmp("Content-Disposition", name)) + { http_header.content_disposition = start; } } - header_next(key, value); - - verbose("> [%ld] \"%s\" :: \"%s\"\n", key - output_buffer, key, value); fflush(stdout); + verbose("\033[0;32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start); - search = ":"; - key = NULL; - } - } - - if(!key) - break; - // printf("We are now here: %ld\n", key - output_buffer); - verbose("We are now here: %s\n", key); - - // jump over the content... - content_start = key; - while((key = memchr(key, '\n', output_buffer_length - (key - output_buffer)))) { - if(!key) { - verbose("out at %p\n", key); + if(matchlen > http_header.newline_length) { + verbose("END HEADERS, boundary='%s'\n", http_header.boundary); + // start = strstr(end, http_header.boundary); + search = "-"; + } break; - } else { - key++; - } - - if(key[0] == '-') { - if(0 == strncmp(&key[strspn(key, "-")], boundary, boundary_length)) { - verbose("> boundary found."); - - if(key[-1] == '\n') key--; - if(key[-1] == '\r') key--; - - content_end = key; - key += strspn(key, "\r\n-"); - key += boundary_length; - key += strspn(key, "\r\n"); - saveptr = key; - key = NULL; - search = ":"; + case '-': + { + char * content_start = end; + content_start += strspn(content_start, "-"); + // verbose("CONTENT: %s\n", content_start); + if(0 <= strcmp(content_start, http_header.boundary)) { + verbose("MATCH\n"); + search = "\r\n"; + start = content_start + strlen(http_header.boundary); + name = NULL; + continue; + } else { + verbose("NO MATCH\n"); + } break; } - } } - verbose("content is %p - %p = %ld in size\n", content_end, content_start, content_end - content_start); - if(content_end - content_start > 1000) { - FILE * f_w = fopen("/tmp/test.gif", "w"); - fwrite(content_start, content_end - content_start, 1, f_w); - fclose(f_w); - puts("FILE WRITTEN"); - } + start = end + matchlen; + } - // printf("We have gone to %ld\n", key - output_buffer); fflush(stdout); - if(key && key[0] == '\0') // final boundary reached? - break; + if(http_header.boundary) + verbose("http-boundary: %s", http_header.boundary); - // usleep(100000); - } verbose("> sending answer..."); send_answer(f_w); -- cgit v1.2.3