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) |