diff options
Diffstat (limited to 'http_parser.c')
| -rw-r--r-- | http_parser.c | 109 |
1 files changed, 55 insertions, 54 deletions
diff --git a/http_parser.c b/http_parser.c index 30e74c8..03d8d91 100644 --- a/http_parser.c +++ b/http_parser.c | |||
| @@ -54,7 +54,7 @@ static inline char * handle_colon(char ** start, char ** end, char ** search) { | |||
| 54 | return *start; // remember, where name starts, will be important in the newline case | 54 | return *start; // remember, where name starts, will be important in the newline case |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static inline void handle_semicolon(char ** start, char ** end, char ** search) { | 57 | static inline char * handle_semicolon(char ** start, char ** end, char ** search) { |
| 58 | // find the form-data boundary in the main header | 58 | // find the form-data boundary in the main header |
| 59 | *start += strspn(*start, "; "); // remove spaces and semicolons (boundary check implicit; also stops at '\0') | 59 | *start += strspn(*start, "; "); // remove spaces and semicolons (boundary check implicit; also stops at '\0') |
| 60 | 60 | ||
| @@ -63,10 +63,15 @@ static inline void handle_semicolon(char ** start, char ** end, char ** search) | |||
| 63 | { | 63 | { |
| 64 | *end = *end + sizeof(s_multipart_form_data) + 1; | 64 | *end = *end + sizeof(s_multipart_form_data) + 1; |
| 65 | *end += strspn(*end, "-"); | 65 | *end += strspn(*end, "-"); |
| 66 | *start = *end; | ||
| 66 | DEBUG("> Boundary found, now looking where it ends...\n"); | 67 | DEBUG("> Boundary found, now looking where it ends...\n"); |
| 68 | |||
| 69 | *end += strcspn(*end, "\r\n "); | ||
| 70 | *end[0] = '\0'; | ||
| 67 | } | 71 | } |
| 68 | 72 | ||
| 69 | *search = "\r\n"; // do not search further semicolons | 73 | *search = "\r\n"; // do not search further semicolons |
| 74 | return *start; | ||
| 70 | } | 75 | } |
| 71 | 76 | ||
| 72 | void parse_http(size_t new_socket, char * request, size_t request_length) { | 77 | void parse_http(size_t new_socket, char * request, size_t request_length) { |
| @@ -90,12 +95,11 @@ void parse_http(size_t new_socket, char * request, size_t request_length) { | |||
| 90 | size_t matchlen = strspn(end, search); | 95 | size_t matchlen = strspn(end, search); |
| 91 | switch(end[0]) { | 96 | switch(end[0]) { |
| 92 | case ':': | 97 | case ':': |
| 93 | handle_colon(&start, &end, &search); | 98 | name = handle_colon(&start, &end, &search); |
| 94 | name = start; | ||
| 95 | break; | 99 | break; |
| 96 | case ';': | 100 | case ';': |
| 97 | handle_semicolon(&start, &end, &search); | 101 | http_header.boundary = handle_semicolon(&start, &end, &search); |
| 98 | http_header.boundary = end; | 102 | http_header.boundary_size = end - start; |
| 99 | break; | 103 | break; |
| 100 | case '\r': // fallthrough | 104 | case '\r': // fallthrough |
| 101 | case '\n': | 105 | case '\n': |
| @@ -123,62 +127,59 @@ void parse_http(size_t new_socket, char * request, size_t request_length) { | |||
| 123 | if (0 == strcasecmp("Content-Disposition", name)) | 127 | if (0 == strcasecmp("Content-Disposition", name)) |
| 124 | { http_header.content_disposition = start; } | 128 | { http_header.content_disposition = start; } |
| 125 | } // }}} | 129 | } // }}} |
| 126 | DEBUG("\033[32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start); | ||
| 127 | // {{{ check if a http header ended (e.g. two newlines) | ||
| 128 | if(matchlen > http_header.newline_length) { | ||
| 129 | DEBUG("> END HEADERS, because there were %d newlines; boundary='%s'[%ld]\n", matchlen / http_header.newline_length, http_header.boundary, http_header.boundary_size); | ||
| 130 | end += matchlen; | ||
| 131 | |||
| 132 | // if it was the first header, we calculate the boundary size and expect more headers to come after a boundary | ||
| 133 | if(http_header.boundary && http_header.boundary_size == 0) { | ||
| 134 | DEBUG("================================================================================\n"); | ||
| 135 | http_header.boundary_size = strlen(http_header.boundary); | ||
| 136 | // skip the first header and boundary... | ||
| 137 | start = end; | ||
| 138 | start += strspn(start, "-"); | ||
| 139 | start += http_header.boundary_size; | ||
| 140 | start += http_header.newline_length; | ||
| 141 | continue; | ||
| 142 | } else { | ||
| 143 | char * content_start = end; | ||
| 144 | while(1) | ||
| 145 | { | ||
| 146 | size_t size_remaining = (size_t) request_length - (end - request) - 1; | ||
| 147 | DEBUG("%ld remaining.\n", size_remaining); | ||
| 148 | |||
| 149 | if(size_remaining <= 0) { | ||
| 150 | DEBUG("> not even the boundary would fit in that what is left.\n"); | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | |||
| 154 | if(NULL == (end = memchr((void*) end, '-', size_remaining))) { | ||
| 155 | DEBUG("no further '-' found\n"); | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | |||
| 159 | char * content_end = end - http_header.newline_length; | ||
| 160 | |||
| 161 | end += strspn(end, "-"); | ||
| 162 | if(0 == strncmp(end, http_header.boundary, http_header.boundary_size)) { | ||
| 163 | size_t file_size = content_end - content_start; | ||
| 164 | DEBUG("> Content ends here, size of the last file is %ld\n", file_size); | ||
| 165 | 130 | ||
| 166 | content_start[file_size + 1] = '\0'; | 131 | // {{{ DEBUG |
| 167 | next_part(&http_header, content_start, file_size); | 132 | DEBUG("\033[32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start); |
| 168 | 133 | // }}} | |
| 169 | end += http_header.boundary_size; | ||
| 170 | matchlen = strspn(end, "\r\n"); | ||
| 171 | DEBUG("> end is at %p, matchlen is %ld\n", end, matchlen); | ||
| 172 | 134 | ||
| 173 | search = ":"; | 135 | // check if a http header ended (e.g. two newlines) |
| 136 | if(matchlen > http_header.newline_length) { | ||
| 137 | end += matchlen; // go behind the double line break... | ||
| 138 | |||
| 139 | //{{{ DEBUG | ||
| 140 | DEBUG("> END HEADERS, because there were %d newlines; boundary='%s'[%ld]\n", | ||
| 141 | matchlen / http_header.newline_length, | ||
| 142 | http_header.boundary, | ||
| 143 | http_header.boundary_size | ||
| 144 | ); // }}} | ||
| 145 | |||
| 146 | start = end; | ||
| 147 | for(; ; ) | ||
| 148 | { | ||
| 149 | size_t size_remaining = (size_t) request_length - (end - request) - 1; | ||
| 150 | |||
| 151 | // {{{ DEBUG | ||
| 152 | DEBUG("%ld remaining.\n", size_remaining); | ||
| 153 | // }}} | ||
| 154 | |||
| 155 | matchlen = strspn(end, "-"); | ||
| 156 | if(0 == strncmp(end + matchlen, http_header.boundary, http_header.boundary_size)) { | ||
| 157 | size_t file_size = end - http_header.newline_length - start; | ||
| 158 | DEBUG("> Content ends here, size of the last file is %ld\n", file_size); | ||
| 159 | start[file_size + 1] = '\0'; | ||
| 160 | |||
| 161 | next_part(&http_header, start, file_size); | ||
| 162 | |||
| 163 | end += http_header.boundary_size + matchlen; | ||
| 164 | matchlen = http_header.newline_length; | ||
| 165 | DEBUG("> end is at %p, matchlen is %ld\n", end, matchlen); | ||
| 166 | search = ":"; | ||
| 167 | break; | ||
| 168 | } else { | ||
| 169 | |||
| 170 | if(!http_header.boundary | ||
| 171 | || size_remaining <= 0 | ||
| 172 | || NULL == (end = memchr((void*) end, '-', size_remaining))) { | ||
| 173 | // {{{ DEBUG | ||
| 174 | DEBUG("EOF reached or no further '-' found\n"); | ||
| 175 | // }}} | ||
| 174 | break; | 176 | break; |
| 175 | } else { | ||
| 176 | end = end + 1; | ||
| 177 | } | 177 | } |
| 178 | // end++; | ||
| 178 | } | 179 | } |
| 179 | } | 180 | } |
| 180 | break; | 181 | break; |
| 181 | } // }}} if condition after a header | 182 | } // if condition after a header |
| 182 | } // switch | 183 | } // switch |
| 183 | 184 | ||
| 184 | if(NULL == end) | 185 | if(NULL == end) |
