diff options
Diffstat (limited to 'src/daemon/connection.c')
-rw-r--r-- | src/daemon/connection.c | 1541 |
1 files changed, 777 insertions, 764 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c index b5d0b3dd..fdbc975c 100644 --- a/src/daemon/connection.c +++ b/src/daemon/connection.c | |||
@@ -50,29 +50,29 @@ | |||
50 | * @return number of entries iterated over | 50 | * @return number of entries iterated over |
51 | */ | 51 | */ |
52 | int | 52 | int |
53 | MHD_get_connection_values(struct MHD_Connection * connection, | 53 | MHD_get_connection_values (struct MHD_Connection *connection, |
54 | enum MHD_ValueKind kind, | 54 | enum MHD_ValueKind kind, |
55 | MHD_KeyValueIterator iterator, | 55 | MHD_KeyValueIterator iterator, void *iterator_cls) |
56 | void * iterator_cls) { | 56 | { |
57 | int ret; | 57 | int ret; |
58 | struct MHD_HTTP_Header * pos; | 58 | struct MHD_HTTP_Header *pos; |
59 | 59 | ||
60 | if (connection == NULL) | 60 | if (connection == NULL) |
61 | return -1; | 61 | return -1; |
62 | ret = 0; | 62 | ret = 0; |
63 | pos = connection->headers_received; | 63 | pos = connection->headers_received; |
64 | while (pos != NULL) { | 64 | while (pos != NULL) |
65 | if (0 != (pos->kind & kind)) { | 65 | { |
66 | ret++; | 66 | if (0 != (pos->kind & kind)) |
67 | if ( (iterator != NULL) && | 67 | { |
68 | (MHD_YES != iterator(iterator_cls, | 68 | ret++; |
69 | kind, | 69 | if ((iterator != NULL) && |
70 | pos->header, | 70 | (MHD_YES != iterator (iterator_cls, |
71 | pos->value)) ) | 71 | kind, pos->header, pos->value))) |
72 | return ret; | 72 | return ret; |
73 | } | ||
74 | pos = pos->next; | ||
73 | } | 75 | } |
74 | pos = pos->next; | ||
75 | } | ||
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
78 | 78 | ||
@@ -85,21 +85,20 @@ MHD_get_connection_values(struct MHD_Connection * connection, | |||
85 | * @return NULL if no such item was found | 85 | * @return NULL if no such item was found |
86 | */ | 86 | */ |
87 | const char * | 87 | const char * |
88 | MHD_lookup_connection_value(struct MHD_Connection * connection, | 88 | MHD_lookup_connection_value (struct MHD_Connection *connection, |
89 | enum MHD_ValueKind kind, | 89 | enum MHD_ValueKind kind, const char *key) |
90 | const char * key) { | 90 | { |
91 | struct MHD_HTTP_Header * pos; | 91 | struct MHD_HTTP_Header *pos; |
92 | 92 | ||
93 | if (connection == NULL) | 93 | if (connection == NULL) |
94 | return NULL; | 94 | return NULL; |
95 | pos = connection->headers_received; | 95 | pos = connection->headers_received; |
96 | while (pos != NULL) { | 96 | while (pos != NULL) |
97 | if ( (0 != (pos->kind & kind)) && | 97 | { |
98 | (0 == strcasecmp(key, | 98 | if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header))) |
99 | pos->header)) ) | 99 | return pos->value; |
100 | return pos->value; | 100 | pos = pos->next; |
101 | pos = pos->next; | 101 | } |
102 | } | ||
103 | return NULL; | 102 | return NULL; |
104 | } | 103 | } |
105 | 104 | ||
@@ -114,25 +113,24 @@ MHD_lookup_connection_value(struct MHD_Connection * connection, | |||
114 | * MHD_YES on success or if message has been queued | 113 | * MHD_YES on success or if message has been queued |
115 | */ | 114 | */ |
116 | int | 115 | int |
117 | MHD_queue_response(struct MHD_Connection * connection, | 116 | MHD_queue_response (struct MHD_Connection *connection, |
118 | unsigned int status_code, | 117 | unsigned int status_code, struct MHD_Response *response) |
119 | struct MHD_Response * response) { | 118 | { |
120 | if ( (connection == NULL) || | 119 | if ((connection == NULL) || |
121 | (response == NULL) || | 120 | (response == NULL) || |
122 | (connection->response != NULL) || | 121 | (connection->response != NULL) || |
123 | (connection->bodyReceived == 0) || | 122 | (connection->bodyReceived == 0) || (connection->headersReceived == 0)) |
124 | (connection->headersReceived == 0) ) | 123 | return MHD_NO; |
125 | return MHD_NO; | 124 | MHD_increment_response_rc (response); |
126 | MHD_increment_response_rc(response); | ||
127 | connection->response = response; | 125 | connection->response = response; |
128 | connection->responseCode = status_code; | 126 | connection->responseCode = status_code; |
129 | if ( (connection->method != NULL) && | 127 | if ((connection->method != NULL) && |
130 | (0 == strcasecmp(connection->method, | 128 | (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD))) |
131 | MHD_HTTP_METHOD_HEAD)) ) { | 129 | { |
132 | /* if this is a "HEAD" request, pretend that we | 130 | /* if this is a "HEAD" request, pretend that we |
133 | have already sent the full message body */ | 131 | have already sent the full message body */ |
134 | connection->messagePos = response->total_size; | 132 | connection->messagePos = response->total_size; |
135 | } | 133 | } |
136 | return MHD_YES; | 134 | return MHD_YES; |
137 | } | 135 | } |
138 | 136 | ||
@@ -140,20 +138,20 @@ MHD_queue_response(struct MHD_Connection * connection, | |||
140 | * Do we (still) need to send a 100 continue | 138 | * Do we (still) need to send a 100 continue |
141 | * message for this connection? | 139 | * message for this connection? |
142 | */ | 140 | */ |
143 | static int | 141 | static int |
144 | MHD_need_100_continue(struct MHD_Connection * connection) { | 142 | MHD_need_100_continue (struct MHD_Connection *connection) |
145 | const char * expect; | 143 | { |
144 | const char *expect; | ||
146 | 145 | ||
147 | return ( (connection->version != NULL) && | 146 | return ((connection->version != NULL) && |
148 | (0 == strcasecmp(connection->version, | 147 | (0 == strcasecmp (connection->version, |
149 | MHD_HTTP_VERSION_1_1)) && | 148 | MHD_HTTP_VERSION_1_1)) && |
150 | (connection->headersReceived == 1) && | 149 | (connection->headersReceived == 1) && |
151 | (NULL != (expect = MHD_lookup_connection_value(connection, | 150 | (NULL != (expect = MHD_lookup_connection_value (connection, |
152 | MHD_HEADER_KIND, | 151 | MHD_HEADER_KIND, |
153 | MHD_HTTP_HEADER_EXPECT))) && | 152 | MHD_HTTP_HEADER_EXPECT))) |
154 | (0 == strcasecmp(expect, | 153 | && (0 == strcasecmp (expect, "100-continue")) |
155 | "100-continue")) && | 154 | && (connection->continuePos < strlen (HTTP_100_CONTINUE))); |
156 | (connection->continuePos < strlen(HTTP_100_CONTINUE)) ); | ||
157 | } | 155 | } |
158 | 156 | ||
159 | /** | 157 | /** |
@@ -162,49 +160,56 @@ MHD_need_100_continue(struct MHD_Connection * connection) { | |||
162 | * @return MHD_YES on success | 160 | * @return MHD_YES on success |
163 | */ | 161 | */ |
164 | int | 162 | int |
165 | MHD_connection_get_fdset(struct MHD_Connection * connection, | 163 | MHD_connection_get_fdset (struct MHD_Connection *connection, |
166 | fd_set * read_fd_set, | 164 | fd_set * read_fd_set, |
167 | fd_set * write_fd_set, | 165 | fd_set * write_fd_set, |
168 | fd_set * except_fd_set, | 166 | fd_set * except_fd_set, int *max_fd) |
169 | int * max_fd) { | 167 | { |
170 | int fd; | 168 | int fd; |
171 | void * buf; | 169 | void *buf; |
172 | 170 | ||
173 | fd = connection->socket_fd; | 171 | fd = connection->socket_fd; |
174 | if (fd == -1) | 172 | if (fd == -1) |
175 | return MHD_YES; | 173 | return MHD_YES; |
176 | if ( (connection->read_close == MHD_NO) && | 174 | if ((connection->read_close == MHD_NO) && |
177 | ( (connection->headersReceived == 0) || | 175 | ((connection->headersReceived == 0) || |
178 | (connection->readLoc < connection->read_buffer_size) ) ) { | 176 | (connection->readLoc < connection->read_buffer_size))) |
179 | FD_SET(fd, read_fd_set); | 177 | { |
180 | if (fd > *max_fd) | 178 | FD_SET (fd, read_fd_set); |
181 | *max_fd = fd; | 179 | if (fd > *max_fd) |
182 | } else { | 180 | *max_fd = fd; |
183 | if ( (connection->read_close == MHD_NO) && | 181 | } |
184 | ( (connection->headersReceived == 1) && | 182 | else |
185 | (connection->post_processed == MHD_NO) && | 183 | { |
186 | (connection->readLoc == connection->read_buffer_size) ) ) { | 184 | if ((connection->read_close == MHD_NO) && |
187 | /* try growing the read buffer, just in case */ | 185 | ((connection->headersReceived == 1) && |
188 | buf = MHD_pool_reallocate(connection->pool, | 186 | (connection->post_processed == MHD_NO) && |
189 | connection->read_buffer, | 187 | (connection->readLoc == connection->read_buffer_size))) |
190 | connection->read_buffer_size, | 188 | { |
191 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); | 189 | /* try growing the read buffer, just in case */ |
192 | if (buf != NULL) { | 190 | buf = MHD_pool_reallocate (connection->pool, |
193 | /* we can actually grow the buffer, do it! */ | 191 | connection->read_buffer, |
194 | connection->read_buffer = buf; | 192 | connection->read_buffer_size, |
195 | connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; | 193 | connection->read_buffer_size * 2 + |
196 | FD_SET(fd, read_fd_set); | 194 | MHD_BUF_INC_SIZE); |
197 | if (fd > *max_fd) | 195 | if (buf != NULL) |
198 | *max_fd = fd; | 196 | { |
199 | } | 197 | /* we can actually grow the buffer, do it! */ |
198 | connection->read_buffer = buf; | ||
199 | connection->read_buffer_size = | ||
200 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; | ||
201 | FD_SET (fd, read_fd_set); | ||
202 | if (fd > *max_fd) | ||
203 | *max_fd = fd; | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | if ((connection->response != NULL) || MHD_need_100_continue (connection)) | ||
208 | { | ||
209 | FD_SET (fd, write_fd_set); | ||
210 | if (fd > *max_fd) | ||
211 | *max_fd = fd; | ||
200 | } | 212 | } |
201 | } | ||
202 | if ( (connection->response != NULL) || | ||
203 | MHD_need_100_continue(connection) ) { | ||
204 | FD_SET(fd, write_fd_set); | ||
205 | if (fd > *max_fd) | ||
206 | *max_fd = fd; | ||
207 | } | ||
208 | return MHD_YES; | 213 | return MHD_YES; |
209 | } | 214 | } |
210 | 215 | ||
@@ -216,9 +221,10 @@ MHD_connection_get_fdset(struct MHD_Connection * connection, | |||
216 | * @param status_code the response code to send (413 or 414) | 221 | * @param status_code the response code to send (413 or 414) |
217 | */ | 222 | */ |
218 | static void | 223 | static void |
219 | MHD_excessive_data_handler(struct MHD_Connection * connection, | 224 | MHD_excessive_data_handler (struct MHD_Connection *connection, |
220 | unsigned int status_code) { | 225 | unsigned int status_code) |
221 | struct MHD_Response * response; | 226 | { |
227 | struct MHD_Response *response; | ||
222 | 228 | ||
223 | /* die, header far too long to be reasonable; | 229 | /* die, header far too long to be reasonable; |
224 | FIXME: send proper response to client | 230 | FIXME: send proper response to client |
@@ -226,16 +232,12 @@ MHD_excessive_data_handler(struct MHD_Connection * connection, | |||
226 | connection->read_close = MHD_YES; | 232 | connection->read_close = MHD_YES; |
227 | connection->headersReceived = MHD_YES; | 233 | connection->headersReceived = MHD_YES; |
228 | connection->bodyReceived = MHD_YES; | 234 | connection->bodyReceived = MHD_YES; |
229 | MHD_DLOG(connection->daemon, | 235 | MHD_DLOG (connection->daemon, |
230 | "Received excessively long header, closing connection.\n"); | 236 | "Received excessively long header, closing connection.\n"); |
231 | response = MHD_create_response_from_data(strlen(REQUEST_TOO_BIG), | 237 | response = MHD_create_response_from_data (strlen (REQUEST_TOO_BIG), |
232 | REQUEST_TOO_BIG, | 238 | REQUEST_TOO_BIG, MHD_NO, MHD_NO); |
233 | MHD_NO, | 239 | MHD_queue_response (connection, status_code, response); |
234 | MHD_NO); | 240 | MHD_destroy_response (response); |
235 | MHD_queue_response(connection, | ||
236 | status_code, | ||
237 | response); | ||
238 | MHD_destroy_response(response); | ||
239 | } | 241 | } |
240 | 242 | ||
241 | /** | 243 | /** |
@@ -247,41 +249,47 @@ MHD_excessive_data_handler(struct MHD_Connection * connection, | |||
247 | * return NULL. Otherwise return a pointer to the line. | 249 | * return NULL. Otherwise return a pointer to the line. |
248 | */ | 250 | */ |
249 | static char * | 251 | static char * |
250 | MHD_get_next_header_line(struct MHD_Connection * connection) { | 252 | MHD_get_next_header_line (struct MHD_Connection *connection) |
251 | char * rbuf; | 253 | { |
254 | char *rbuf; | ||
252 | size_t pos; | 255 | size_t pos; |
253 | 256 | ||
254 | if (connection->readLoc == 0) | 257 | if (connection->readLoc == 0) |
255 | return NULL; | 258 | return NULL; |
256 | pos = 0; | 259 | pos = 0; |
257 | rbuf = connection->read_buffer; | 260 | rbuf = connection->read_buffer; |
258 | while ( (pos < connection->readLoc - 1) && | 261 | while ((pos < connection->readLoc - 1) && |
259 | (rbuf[pos] != '\r') && | 262 | (rbuf[pos] != '\r') && (rbuf[pos] != '\n')) |
260 | (rbuf[pos] != '\n') ) | ||
261 | pos++; | 263 | pos++; |
262 | if (pos == connection->readLoc - 1) { | 264 | if (pos == connection->readLoc - 1) |
263 | /* not found, consider growing... */ | 265 | { |
264 | if (connection->readLoc == connection->read_buffer_size) { | 266 | /* not found, consider growing... */ |
265 | rbuf = MHD_pool_reallocate(connection->pool, | 267 | if (connection->readLoc == connection->read_buffer_size) |
266 | connection->read_buffer, | 268 | { |
267 | connection->read_buffer_size, | 269 | rbuf = MHD_pool_reallocate (connection->pool, |
268 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); | 270 | connection->read_buffer, |
269 | if (rbuf == NULL) { | 271 | connection->read_buffer_size, |
270 | MHD_excessive_data_handler(connection, | 272 | connection->read_buffer_size * 2 + |
271 | (connection->url != NULL) | 273 | MHD_BUF_INC_SIZE); |
272 | ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE | 274 | if (rbuf == NULL) |
273 | : MHD_HTTP_REQUEST_URI_TOO_LONG); | 275 | { |
274 | } else { | 276 | MHD_excessive_data_handler (connection, |
275 | connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; | 277 | (connection->url != NULL) |
276 | connection->read_buffer = rbuf; | 278 | ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE |
277 | } | 279 | : MHD_HTTP_REQUEST_URI_TOO_LONG); |
280 | } | ||
281 | else | ||
282 | { | ||
283 | connection->read_buffer_size = | ||
284 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; | ||
285 | connection->read_buffer = rbuf; | ||
286 | } | ||
287 | } | ||
288 | return NULL; | ||
278 | } | 289 | } |
279 | return NULL; | ||
280 | } | ||
281 | /* found, check if we have proper CRLF */ | 290 | /* found, check if we have proper CRLF */ |
282 | if ( (rbuf[pos] == '\r') && | 291 | if ((rbuf[pos] == '\r') && (rbuf[pos + 1] == '\n')) |
283 | (rbuf[pos+1] == '\n') ) | 292 | rbuf[pos++] = '\0'; /* skip both r and n */ |
284 | rbuf[pos++] = '\0'; /* skip both r and n */ | ||
285 | rbuf[pos++] = '\0'; | 293 | rbuf[pos++] = '\0'; |
286 | connection->read_buffer += pos; | 294 | connection->read_buffer += pos; |
287 | connection->read_buffer_size -= pos; | 295 | connection->read_buffer_size -= pos; |
@@ -293,22 +301,21 @@ MHD_get_next_header_line(struct MHD_Connection * connection) { | |||
293 | * @return MHD_NO on failure (out of memory), MHD_YES for success | 301 | * @return MHD_NO on failure (out of memory), MHD_YES for success |
294 | */ | 302 | */ |
295 | static int | 303 | static int |
296 | MHD_connection_add_header(struct MHD_Connection * connection, | 304 | MHD_connection_add_header (struct MHD_Connection *connection, |
297 | char * key, | 305 | char *key, char *value, enum MHD_ValueKind kind) |
298 | char * value, | 306 | { |
299 | enum MHD_ValueKind kind) { | 307 | struct MHD_HTTP_Header *hdr; |
300 | struct MHD_HTTP_Header * hdr; | ||
301 | 308 | ||
302 | hdr = MHD_pool_allocate(connection->pool, | 309 | hdr = MHD_pool_allocate (connection->pool, |
303 | sizeof(struct MHD_HTTP_Header), | 310 | sizeof (struct MHD_HTTP_Header), MHD_YES); |
304 | MHD_YES); | 311 | if (hdr == NULL) |
305 | if (hdr == NULL) { | 312 | { |
306 | MHD_DLOG(connection->daemon, | 313 | MHD_DLOG (connection->daemon, |
307 | "Not enough memory to allocate header record!\n"); | 314 | "Not enough memory to allocate header record!\n"); |
308 | MHD_excessive_data_handler(connection, | 315 | MHD_excessive_data_handler (connection, |
309 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | 316 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); |
310 | return MHD_NO; | 317 | return MHD_NO; |
311 | } | 318 | } |
312 | hdr->next = connection->headers_received; | 319 | hdr->next = connection->headers_received; |
313 | hdr->header = key; | 320 | hdr->header = key; |
314 | hdr->value = value; | 321 | hdr->value = value; |
@@ -319,60 +326,57 @@ MHD_connection_add_header(struct MHD_Connection * connection, | |||
319 | 326 | ||
320 | /** | 327 | /** |
321 | * Process escape sequences ('+'=space, %HH) | 328 | * Process escape sequences ('+'=space, %HH) |
322 | */ | 329 | */ |
323 | static void | 330 | static void |
324 | MHD_http_unescape(char * val) { | 331 | MHD_http_unescape (char *val) |
325 | char * esc; | 332 | { |
333 | char *esc; | ||
326 | unsigned int num; | 334 | unsigned int num; |
327 | 335 | ||
328 | while (NULL != (esc = strstr(val, "+"))) | 336 | while (NULL != (esc = strstr (val, "+"))) |
329 | *esc = ' '; | 337 | *esc = ' '; |
330 | while (NULL != (esc = strstr(val, "%"))) { | 338 | while (NULL != (esc = strstr (val, "%"))) |
331 | if ( (1 == sscanf(&esc[1], | 339 | { |
332 | "%2x", | 340 | if ((1 == sscanf (&esc[1], |
333 | &num)) || | 341 | "%2x", &num)) || (1 == sscanf (&esc[1], "%2X", &num))) |
334 | (1 == sscanf(&esc[1], | 342 | { |
335 | "%2X", | 343 | esc[0] = (unsigned char) num; |
336 | &num)) ) { | 344 | memmove (&esc[1], &esc[3], strlen (&esc[3])); |
337 | esc[0] = (unsigned char) num; | 345 | } |
338 | memmove(&esc[1], | 346 | val = esc + 1; |
339 | &esc[3], | ||
340 | strlen(&esc[3])); | ||
341 | } | 347 | } |
342 | val = esc+1; | ||
343 | } | ||
344 | } | 348 | } |
345 | 349 | ||
346 | /** | 350 | /** |
347 | * @return MHD_NO on failure (out of memory), MHD_YES for success | 351 | * @return MHD_NO on failure (out of memory), MHD_YES for success |
348 | */ | 352 | */ |
349 | static int | 353 | static int |
350 | parse_arguments(enum MHD_ValueKind kind, | 354 | parse_arguments (enum MHD_ValueKind kind, |
351 | struct MHD_Connection * connection, | 355 | struct MHD_Connection *connection, char *args) |
352 | char * args) { | 356 | { |
353 | char * equals; | 357 | char *equals; |
354 | char * amper; | 358 | char *amper; |
355 | 359 | ||
356 | while (args != NULL) { | 360 | while (args != NULL) |
357 | equals = strstr(args, "="); | 361 | { |
358 | if (equals == NULL) | 362 | equals = strstr (args, "="); |
359 | return MHD_NO; /* invalid, ignore */ | 363 | if (equals == NULL) |
360 | equals[0] = '\0'; | 364 | return MHD_NO; /* invalid, ignore */ |
361 | equals++; | 365 | equals[0] = '\0'; |
362 | amper = strstr(equals, "&"); | 366 | equals++; |
363 | if (amper != NULL) { | 367 | amper = strstr (equals, "&"); |
364 | amper[0] = '\0'; | 368 | if (amper != NULL) |
365 | amper++; | 369 | { |
370 | amper[0] = '\0'; | ||
371 | amper++; | ||
372 | } | ||
373 | MHD_http_unescape (args); | ||
374 | MHD_http_unescape (equals); | ||
375 | if (MHD_NO == MHD_connection_add_header (connection, | ||
376 | args, equals, kind)) | ||
377 | return MHD_NO; | ||
378 | args = amper; | ||
366 | } | 379 | } |
367 | MHD_http_unescape(args); | ||
368 | MHD_http_unescape(equals); | ||
369 | if (MHD_NO == MHD_connection_add_header(connection, | ||
370 | args, | ||
371 | equals, | ||
372 | kind)) | ||
373 | return MHD_NO; | ||
374 | args = amper; | ||
375 | } | ||
376 | return MHD_YES; | 380 | return MHD_YES; |
377 | } | 381 | } |
378 | 382 | ||
@@ -382,68 +386,63 @@ parse_arguments(enum MHD_ValueKind kind, | |||
382 | * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory) | 386 | * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory) |
383 | */ | 387 | */ |
384 | static int | 388 | static int |
385 | MHD_parse_cookie_header(struct MHD_Connection * connection) { | 389 | MHD_parse_cookie_header (struct MHD_Connection *connection) |
386 | const char * hdr; | 390 | { |
387 | char * cpy; | 391 | const char *hdr; |
388 | char * pos; | 392 | char *cpy; |
389 | char * semicolon; | 393 | char *pos; |
390 | char * equals; | 394 | char *semicolon; |
395 | char *equals; | ||
391 | int quotes; | 396 | int quotes; |
392 | 397 | ||
393 | hdr = MHD_lookup_connection_value(connection, | 398 | hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Cookie"); |
394 | MHD_HEADER_KIND, | ||
395 | "Cookie"); | ||
396 | if (hdr == NULL) | 399 | if (hdr == NULL) |
397 | return MHD_YES; | 400 | return MHD_YES; |
398 | cpy = MHD_pool_allocate(connection->pool, | 401 | cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES); |
399 | strlen(hdr)+1, | 402 | if (cpy == NULL) |
400 | MHD_YES); | 403 | { |
401 | if (cpy == NULL) { | 404 | MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n"); |
402 | MHD_DLOG(connection->daemon, | 405 | MHD_excessive_data_handler (connection, |
403 | "Not enough memory to parse cookies!\n"); | 406 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); |
404 | MHD_excessive_data_handler(connection, | 407 | return MHD_NO; |
405 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | ||
406 | return MHD_NO; | ||
407 | } | ||
408 | memcpy(cpy, | ||
409 | hdr, | ||
410 | strlen(hdr)+1); | ||
411 | pos = cpy; | ||
412 | while (pos != NULL) { | ||
413 | equals = strstr(pos, "="); | ||
414 | if (equals == NULL) | ||
415 | break; | ||
416 | equals[0] = '\0'; | ||
417 | equals++; | ||
418 | quotes = 0; | ||
419 | semicolon = equals; | ||
420 | while ( (semicolon[0] != '\0') && | ||
421 | ( (quotes != 0) || | ||
422 | ( (semicolon[0] != ';') && | ||
423 | (semicolon[0] != ',') ) ) ) { | ||
424 | if (semicolon[0] == '"') | ||
425 | quotes = (quotes + 1) & 1; | ||
426 | semicolon++; | ||
427 | } | ||
428 | if (semicolon[0] == '\0') | ||
429 | semicolon = NULL; | ||
430 | if (semicolon != NULL) { | ||
431 | semicolon[0] = '\0'; | ||
432 | semicolon++; | ||
433 | } | 408 | } |
434 | /* remove quotes */ | 409 | memcpy (cpy, hdr, strlen (hdr) + 1); |
435 | if ( (equals[0] == '"') && | 410 | pos = cpy; |
436 | (equals[strlen(equals)-1] == '"') ) { | 411 | while (pos != NULL) |
437 | equals[strlen(equals)-1] = '\0'; | 412 | { |
413 | equals = strstr (pos, "="); | ||
414 | if (equals == NULL) | ||
415 | break; | ||
416 | equals[0] = '\0'; | ||
438 | equals++; | 417 | equals++; |
418 | quotes = 0; | ||
419 | semicolon = equals; | ||
420 | while ((semicolon[0] != '\0') && | ||
421 | ((quotes != 0) || | ||
422 | ((semicolon[0] != ';') && (semicolon[0] != ',')))) | ||
423 | { | ||
424 | if (semicolon[0] == '"') | ||
425 | quotes = (quotes + 1) & 1; | ||
426 | semicolon++; | ||
427 | } | ||
428 | if (semicolon[0] == '\0') | ||
429 | semicolon = NULL; | ||
430 | if (semicolon != NULL) | ||
431 | { | ||
432 | semicolon[0] = '\0'; | ||
433 | semicolon++; | ||
434 | } | ||
435 | /* remove quotes */ | ||
436 | if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"')) | ||
437 | { | ||
438 | equals[strlen (equals) - 1] = '\0'; | ||
439 | equals++; | ||
440 | } | ||
441 | if (MHD_NO == MHD_connection_add_header (connection, | ||
442 | pos, equals, MHD_COOKIE_KIND)) | ||
443 | return MHD_NO; | ||
444 | pos = semicolon; | ||
439 | } | 445 | } |
440 | if (MHD_NO == MHD_connection_add_header(connection, | ||
441 | pos, | ||
442 | equals, | ||
443 | MHD_COOKIE_KIND)) | ||
444 | return MHD_NO; | ||
445 | pos = semicolon; | ||
446 | } | ||
447 | return MHD_YES; | 446 | return MHD_YES; |
448 | } | 447 | } |
449 | 448 | ||
@@ -455,33 +454,33 @@ MHD_parse_cookie_header(struct MHD_Connection * connection) { | |||
455 | * @return MHD_YES if the line is ok, MHD_NO if it is malformed | 454 | * @return MHD_YES if the line is ok, MHD_NO if it is malformed |
456 | */ | 455 | */ |
457 | static int | 456 | static int |
458 | parse_initial_message_line(struct MHD_Connection * connection, | 457 | parse_initial_message_line (struct MHD_Connection *connection, char *line) |
459 | char * line) { | 458 | { |
460 | char * uri; | 459 | char *uri; |
461 | char * httpVersion; | 460 | char *httpVersion; |
462 | char * args; | 461 | char *args; |
463 | 462 | ||
464 | uri = strstr(line, " "); | 463 | uri = strstr (line, " "); |
465 | if (uri == NULL) | 464 | if (uri == NULL) |
466 | return MHD_NO; /* serious error */ | 465 | return MHD_NO; /* serious error */ |
467 | uri[0] = '\0'; | 466 | uri[0] = '\0'; |
468 | connection->method = line; | 467 | connection->method = line; |
469 | uri++; | 468 | uri++; |
470 | while (uri[0] == ' ') | 469 | while (uri[0] == ' ') |
471 | uri++; | 470 | uri++; |
472 | httpVersion = strstr(uri, " "); | 471 | httpVersion = strstr (uri, " "); |
473 | if (httpVersion != NULL) { | 472 | if (httpVersion != NULL) |
474 | httpVersion[0] = '\0'; | 473 | { |
475 | httpVersion++; | 474 | httpVersion[0] = '\0'; |
476 | } | 475 | httpVersion++; |
477 | args = strstr(uri, "?"); | 476 | } |
478 | if (args != NULL) { | 477 | args = strstr (uri, "?"); |
479 | args[0] = '\0'; | 478 | if (args != NULL) |
480 | args++; | 479 | { |
481 | parse_arguments(MHD_GET_ARGUMENT_KIND, | 480 | args[0] = '\0'; |
482 | connection, | 481 | args++; |
483 | args); | 482 | parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args); |
484 | } | 483 | } |
485 | connection->url = uri; | 484 | connection->url = uri; |
486 | if (httpVersion == NULL) | 485 | if (httpVersion == NULL) |
487 | connection->version = ""; | 486 | connection->version = ""; |
@@ -502,131 +501,137 @@ parse_initial_message_line(struct MHD_Connection * connection, | |||
502 | * size of the body is unknown, it should be set to -1. | 501 | * size of the body is unknown, it should be set to -1. |
503 | */ | 502 | */ |
504 | static void | 503 | static void |
505 | MHD_parse_connection_headers(struct MHD_Connection * connection) { | 504 | MHD_parse_connection_headers (struct MHD_Connection *connection) |
506 | char * last; | 505 | { |
507 | char * line; | 506 | char *last; |
508 | char * colon; | 507 | char *line; |
509 | char * tmp; | 508 | char *colon; |
510 | const char * clen; | 509 | char *tmp; |
511 | const char * end; | 510 | const char *clen; |
511 | const char *end; | ||
512 | unsigned long long cval; | 512 | unsigned long long cval; |
513 | 513 | ||
514 | if (connection->bodyReceived == 1) | 514 | if (connection->bodyReceived == 1) |
515 | abort(); | 515 | abort (); |
516 | last = NULL; | 516 | last = NULL; |
517 | while (NULL != (line = MHD_get_next_header_line(connection))) { | 517 | while (NULL != (line = MHD_get_next_header_line (connection))) |
518 | if (last != NULL) { | 518 | { |
519 | if ( (line[0] == ' ') || | 519 | if (last != NULL) |
520 | (line[0] == '\t') ) { | 520 | { |
521 | /* value was continued on the next line, see | 521 | if ((line[0] == ' ') || (line[0] == '\t')) |
522 | http://www.jmarshall.com/easy/http/ */ | 522 | { |
523 | last = MHD_pool_reallocate(connection->pool, | 523 | /* value was continued on the next line, see |
524 | last, | 524 | http://www.jmarshall.com/easy/http/ */ |
525 | strlen(last)+1, | 525 | last = MHD_pool_reallocate (connection->pool, |
526 | strlen(line) + strlen(last) + 1); | 526 | last, |
527 | if (last == NULL) { | 527 | strlen (last) + 1, |
528 | MHD_excessive_data_handler(connection, | 528 | strlen (line) + strlen (last) + 1); |
529 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | 529 | if (last == NULL) |
530 | break; | 530 | { |
531 | } | 531 | MHD_excessive_data_handler (connection, |
532 | tmp = line; | 532 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); |
533 | while ( (tmp[0] == ' ') || | 533 | break; |
534 | (tmp[0] == '\t') ) | 534 | } |
535 | tmp++; /* skip whitespace at start of 2nd line */ | 535 | tmp = line; |
536 | strcat(last, tmp); | 536 | while ((tmp[0] == ' ') || (tmp[0] == '\t')) |
537 | continue; /* possibly more than 2 lines... */ | 537 | tmp++; /* skip whitespace at start of 2nd line */ |
538 | } else { | 538 | strcat (last, tmp); |
539 | if (MHD_NO == MHD_connection_add_header(connection, | 539 | continue; /* possibly more than 2 lines... */ |
540 | last, | 540 | } |
541 | colon, | 541 | else |
542 | MHD_HEADER_KIND)) | 542 | { |
543 | return; | 543 | if (MHD_NO == MHD_connection_add_header (connection, |
544 | last = NULL; | 544 | last, |
545 | } | 545 | colon, |
546 | MHD_HEADER_KIND)) | ||
547 | return; | ||
548 | last = NULL; | ||
549 | } | ||
550 | } | ||
551 | if (connection->url == NULL) | ||
552 | { | ||
553 | /* line must be request line (first line of header) */ | ||
554 | if (MHD_NO == parse_initial_message_line (connection, line)) | ||
555 | goto DIE; | ||
556 | continue; | ||
557 | } | ||
558 | /* check if this is the end of the header */ | ||
559 | if (strlen (line) == 0) | ||
560 | { | ||
561 | /* end of header */ | ||
562 | connection->headersReceived = 1; | ||
563 | clen = MHD_lookup_connection_value (connection, | ||
564 | MHD_HEADER_KIND, | ||
565 | MHD_HTTP_HEADER_CONTENT_LENGTH); | ||
566 | if (clen != NULL) | ||
567 | { | ||
568 | if (1 != sscanf (clen, "%llu", &cval)) | ||
569 | { | ||
570 | MHD_DLOG (connection->daemon, | ||
571 | "Failed to parse `%s' header `%s', closing connection.\n", | ||
572 | MHD_HTTP_HEADER_CONTENT_LENGTH, clen); | ||
573 | goto DIE; | ||
574 | } | ||
575 | connection->uploadSize = cval; | ||
576 | connection->bodyReceived = cval == 0 ? 1 : 0; | ||
577 | } | ||
578 | else | ||
579 | { | ||
580 | if (NULL == MHD_lookup_connection_value (connection, | ||
581 | MHD_HEADER_KIND, | ||
582 | MHD_HTTP_HEADER_TRANSFER_ENCODING)) | ||
583 | { | ||
584 | /* this request does not have a body */ | ||
585 | connection->uploadSize = 0; | ||
586 | connection->bodyReceived = 1; | ||
587 | } | ||
588 | else | ||
589 | { | ||
590 | connection->uploadSize = -1; /* unknown size */ | ||
591 | connection->bodyReceived = 0; | ||
592 | } | ||
593 | } | ||
594 | end = MHD_lookup_connection_value (connection, | ||
595 | MHD_HEADER_KIND, | ||
596 | MHD_HTTP_HEADER_CONNECTION); | ||
597 | if ((end != NULL) && (0 == strcasecmp (end, "close"))) | ||
598 | { | ||
599 | /* other side explicitly requested | ||
600 | that we close the connection after | ||
601 | this request */ | ||
602 | connection->read_close = MHD_YES; | ||
603 | } | ||
604 | break; | ||
605 | } | ||
606 | /* line should be normal header line, find colon */ | ||
607 | colon = strstr (line, ":"); | ||
608 | if (colon == NULL) | ||
609 | { | ||
610 | /* error in header line, die hard */ | ||
611 | MHD_DLOG (connection->daemon, | ||
612 | "Received malformed line (no colon), closing connection.\n"); | ||
613 | goto DIE; | ||
614 | } | ||
615 | /* zero-terminate header */ | ||
616 | colon[0] = '\0'; | ||
617 | colon++; /* advance to value */ | ||
618 | while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t'))) | ||
619 | colon++; | ||
620 | /* we do the actual adding of the connection | ||
621 | header at the beginning of the while | ||
622 | loop since we need to be able to inspect | ||
623 | the *next* header line (in case it starts | ||
624 | with a space...) */ | ||
625 | last = line; | ||
546 | } | 626 | } |
547 | if (connection->url == NULL) { | 627 | if ((last != NULL) && |
548 | /* line must be request line (first line of header) */ | 628 | (MHD_NO == MHD_connection_add_header (connection, |
549 | if (MHD_NO == parse_initial_message_line(connection, | 629 | last, colon, MHD_HEADER_KIND))) |
550 | line)) | 630 | return; /* error */ |
551 | goto DIE; | 631 | MHD_parse_cookie_header (connection); |
552 | continue; | ||
553 | } | ||
554 | /* check if this is the end of the header */ | ||
555 | if (strlen(line) == 0) { | ||
556 | /* end of header */ | ||
557 | connection->headersReceived = 1; | ||
558 | clen = MHD_lookup_connection_value(connection, | ||
559 | MHD_HEADER_KIND, | ||
560 | MHD_HTTP_HEADER_CONTENT_LENGTH); | ||
561 | if (clen != NULL) { | ||
562 | if (1 != sscanf(clen, | ||
563 | "%llu", | ||
564 | &cval)) { | ||
565 | MHD_DLOG(connection->daemon, | ||
566 | "Failed to parse `%s' header `%s', closing connection.\n", | ||
567 | MHD_HTTP_HEADER_CONTENT_LENGTH, | ||
568 | clen); | ||
569 | goto DIE; | ||
570 | } | ||
571 | connection->uploadSize = cval; | ||
572 | connection->bodyReceived = cval == 0 ? 1 : 0; | ||
573 | } else { | ||
574 | if (NULL == MHD_lookup_connection_value(connection, | ||
575 | MHD_HEADER_KIND, | ||
576 | MHD_HTTP_HEADER_TRANSFER_ENCODING)) { | ||
577 | /* this request does not have a body */ | ||
578 | connection->uploadSize = 0; | ||
579 | connection->bodyReceived = 1; | ||
580 | } else { | ||
581 | connection->uploadSize = -1; /* unknown size */ | ||
582 | connection->bodyReceived = 0; | ||
583 | } | ||
584 | } | ||
585 | end = MHD_lookup_connection_value(connection, | ||
586 | MHD_HEADER_KIND, | ||
587 | MHD_HTTP_HEADER_CONNECTION); | ||
588 | if ( (end != NULL) && | ||
589 | (0 == strcasecmp(end, | ||
590 | "close")) ) { | ||
591 | /* other side explicitly requested | ||
592 | that we close the connection after | ||
593 | this request */ | ||
594 | connection->read_close = MHD_YES; | ||
595 | } | ||
596 | break; | ||
597 | } | ||
598 | /* line should be normal header line, find colon */ | ||
599 | colon = strstr(line, ":"); | ||
600 | if (colon == NULL) { | ||
601 | /* error in header line, die hard */ | ||
602 | MHD_DLOG(connection->daemon, | ||
603 | "Received malformed line (no colon), closing connection.\n"); | ||
604 | goto DIE; | ||
605 | } | ||
606 | /* zero-terminate header */ | ||
607 | colon[0] = '\0'; | ||
608 | colon++; /* advance to value */ | ||
609 | while ( (colon[0] != '\0') && | ||
610 | ( (colon[0] == ' ') || | ||
611 | (colon[0] == '\t') ) ) | ||
612 | colon++; | ||
613 | /* we do the actual adding of the connection | ||
614 | header at the beginning of the while | ||
615 | loop since we need to be able to inspect | ||
616 | the *next* header line (in case it starts | ||
617 | with a space...) */ | ||
618 | last = line; | ||
619 | } | ||
620 | if ( (last != NULL) && | ||
621 | (MHD_NO == MHD_connection_add_header(connection, | ||
622 | last, | ||
623 | colon, | ||
624 | MHD_HEADER_KIND)) ) | ||
625 | return; /* error */ | ||
626 | MHD_parse_cookie_header(connection); | ||
627 | return; | 632 | return; |
628 | DIE: | 633 | DIE: |
629 | CLOSE(connection->socket_fd); | 634 | CLOSE (connection->socket_fd); |
630 | connection->socket_fd = -1; | 635 | connection->socket_fd = -1; |
631 | } | 636 | } |
632 | 637 | ||
@@ -635,16 +640,17 @@ MHD_parse_connection_headers(struct MHD_Connection * connection) { | |||
635 | * Find the handler responsible for this request. | 640 | * Find the handler responsible for this request. |
636 | */ | 641 | */ |
637 | static struct MHD_Access_Handler * | 642 | static struct MHD_Access_Handler * |
638 | MHD_find_access_handler(struct MHD_Connection * connection) { | 643 | MHD_find_access_handler (struct MHD_Connection *connection) |
639 | struct MHD_Access_Handler * pos; | 644 | { |
645 | struct MHD_Access_Handler *pos; | ||
640 | 646 | ||
641 | pos = connection->daemon->handlers; | 647 | pos = connection->daemon->handlers; |
642 | while (pos != NULL) { | 648 | while (pos != NULL) |
643 | if (0 == strcmp(connection->url, | 649 | { |
644 | pos->uri_prefix)) | 650 | if (0 == strcmp (connection->url, pos->uri_prefix)) |
645 | return pos; | 651 | return pos; |
646 | pos = pos->next; | 652 | pos = pos->next; |
647 | } | 653 | } |
648 | return &connection->daemon->default_handler; | 654 | return &connection->daemon->default_handler; |
649 | } | 655 | } |
650 | 656 | ||
@@ -659,33 +665,33 @@ MHD_find_access_handler(struct MHD_Connection * connection) { | |||
659 | * @return MHD_YES if so | 665 | * @return MHD_YES if so |
660 | */ | 666 | */ |
661 | static int | 667 | static int |
662 | MHD_test_post_data(struct MHD_Connection * connection) { | 668 | MHD_test_post_data (struct MHD_Connection *connection) |
663 | const char * encoding; | 669 | { |
664 | void * buf; | 670 | const char *encoding; |
671 | void *buf; | ||
665 | 672 | ||
666 | if ( (connection->method == NULL) || | 673 | if ((connection->method == NULL) || |
667 | (connection->response != NULL) || | 674 | (connection->response != NULL) || |
668 | (0 != strcasecmp(connection->method, | 675 | (0 != strcasecmp (connection->method, MHD_HTTP_METHOD_POST))) |
669 | MHD_HTTP_METHOD_POST)) ) | ||
670 | return MHD_NO; | 676 | return MHD_NO; |
671 | encoding = MHD_lookup_connection_value(connection, | 677 | encoding = MHD_lookup_connection_value (connection, |
672 | MHD_HEADER_KIND, | 678 | MHD_HEADER_KIND, |
673 | MHD_HTTP_HEADER_CONTENT_TYPE); | 679 | MHD_HTTP_HEADER_CONTENT_TYPE); |
674 | if (encoding == NULL) | 680 | if (encoding == NULL) |
675 | return MHD_NO; | 681 | return MHD_NO; |
676 | if ( (0 == strcasecmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED, | 682 | if ((0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, |
677 | encoding)) && | 683 | encoding)) && (connection->uploadSize != -1)) |
678 | (connection->uploadSize != -1) ) { | 684 | { |
679 | buf = MHD_pool_reallocate(connection->pool, | 685 | buf = MHD_pool_reallocate (connection->pool, |
680 | connection->read_buffer, | 686 | connection->read_buffer, |
681 | connection->read_buffer_size, | 687 | connection->read_buffer_size, |
682 | connection->uploadSize + 1); | 688 | connection->uploadSize + 1); |
683 | if (buf == NULL) | 689 | if (buf == NULL) |
684 | return MHD_NO; | 690 | return MHD_NO; |
685 | connection->read_buffer_size = connection->uploadSize + 1; | 691 | connection->read_buffer_size = connection->uploadSize + 1; |
686 | connection->read_buffer = buf; | 692 | connection->read_buffer = buf; |
687 | return MHD_YES; | 693 | return MHD_YES; |
688 | } | 694 | } |
689 | return MHD_NO; | 695 | return MHD_NO; |
690 | } | 696 | } |
691 | 697 | ||
@@ -704,47 +710,47 @@ MHD_test_post_data(struct MHD_Connection * connection) { | |||
704 | * memory). | 710 | * memory). |
705 | */ | 711 | */ |
706 | static int | 712 | static int |
707 | MHD_parse_post_data(struct MHD_Connection * connection) { | 713 | MHD_parse_post_data (struct MHD_Connection *connection) |
708 | const char * encoding; | 714 | { |
715 | const char *encoding; | ||
709 | int ret; | 716 | int ret; |
710 | 717 | ||
711 | encoding = MHD_lookup_connection_value(connection, | 718 | encoding = MHD_lookup_connection_value (connection, |
712 | MHD_HEADER_KIND, | 719 | MHD_HEADER_KIND, |
713 | MHD_HTTP_HEADER_CONTENT_TYPE); | 720 | MHD_HTTP_HEADER_CONTENT_TYPE); |
714 | if (encoding == NULL) | 721 | if (encoding == NULL) |
715 | return MHD_NO; | ||
716 | if (0 == strcasecmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED, | ||
717 | encoding)) { | ||
718 | ret = parse_arguments(MHD_POSTDATA_KIND, | ||
719 | connection, | ||
720 | connection->read_buffer); | ||
721 | /* invalidate read buffer for other uses -- | ||
722 | in particular, do not give it to the | ||
723 | client; if this were to be needed, we would | ||
724 | have to make a copy, which would double memory | ||
725 | requirements */ | ||
726 | connection->read_buffer_size = 0; | ||
727 | connection->readLoc = 0; | ||
728 | connection->uploadSize = 0; | ||
729 | connection->read_buffer = NULL; | ||
730 | return ret; | ||
731 | } | ||
732 | if (0 == strcasecmp(MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, | ||
733 | encoding)) { | ||
734 | /* this code should never been reached right now, | ||
735 | since the test_post_data function would already | ||
736 | return MHD_NO; code is here only for future | ||
737 | extensions... */ | ||
738 | /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */ | ||
739 | MHD_DLOG(connection->daemon, | ||
740 | "Unsupported multipart encoding of POST data specified, not processing POST data.\n"); | ||
741 | return MHD_NO; | 722 | return MHD_NO; |
742 | } | 723 | if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding)) |
724 | { | ||
725 | ret = parse_arguments (MHD_POSTDATA_KIND, | ||
726 | connection, connection->read_buffer); | ||
727 | /* invalidate read buffer for other uses -- | ||
728 | in particular, do not give it to the | ||
729 | client; if this were to be needed, we would | ||
730 | have to make a copy, which would double memory | ||
731 | requirements */ | ||
732 | connection->read_buffer_size = 0; | ||
733 | connection->readLoc = 0; | ||
734 | connection->uploadSize = 0; | ||
735 | connection->read_buffer = NULL; | ||
736 | return ret; | ||
737 | } | ||
738 | if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding)) | ||
739 | { | ||
740 | /* this code should never been reached right now, | ||
741 | since the test_post_data function would already | ||
742 | return MHD_NO; code is here only for future | ||
743 | extensions... */ | ||
744 | /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */ | ||
745 | MHD_DLOG (connection->daemon, | ||
746 | "Unsupported multipart encoding of POST data specified, not processing POST data.\n"); | ||
747 | return MHD_NO; | ||
748 | } | ||
743 | /* this should never be reached, just here for | 749 | /* this should never be reached, just here for |
744 | error checking */ | 750 | error checking */ |
745 | MHD_DLOG(connection->daemon, | 751 | MHD_DLOG (connection->daemon, |
746 | "Unknown encoding of POST data specified, not processing POST data.\n"); | 752 | "Unknown encoding of POST data specified, not processing POST data.\n"); |
747 | return MHD_NO; | 753 | return MHD_NO; |
748 | } | 754 | } |
749 | 755 | ||
750 | /** | 756 | /** |
@@ -752,46 +758,47 @@ MHD_parse_post_data(struct MHD_Connection * connection) { | |||
752 | * connection. | 758 | * connection. |
753 | */ | 759 | */ |
754 | void | 760 | void |
755 | MHD_call_connection_handler(struct MHD_Connection * connection) { | 761 | MHD_call_connection_handler (struct MHD_Connection *connection) |
756 | struct MHD_Access_Handler * ah; | 762 | { |
763 | struct MHD_Access_Handler *ah; | ||
757 | unsigned int processed; | 764 | unsigned int processed; |
758 | 765 | ||
759 | if (connection->response != NULL) | 766 | if (connection->response != NULL) |
760 | return; /* already queued a response */ | 767 | return; /* already queued a response */ |
761 | if (connection->headersReceived == 0) | 768 | if (connection->headersReceived == 0) |
762 | abort(); /* bad timing... */ | 769 | abort (); /* bad timing... */ |
763 | ah = MHD_find_access_handler(connection); | 770 | ah = MHD_find_access_handler (connection); |
764 | processed = connection->readLoc; | 771 | processed = connection->readLoc; |
765 | if (MHD_NO == ah->dh(ah->dh_cls, | 772 | if (MHD_NO == ah->dh (ah->dh_cls, |
766 | connection, | 773 | connection, |
767 | connection->url, | 774 | connection->url, |
768 | connection->method, | 775 | connection->method, |
769 | connection->version, | 776 | connection->version, |
770 | connection->read_buffer, | 777 | connection->read_buffer, &processed)) |
771 | &processed)) { | 778 | { |
772 | /* serios internal error, close connection */ | 779 | /* serios internal error, close connection */ |
773 | MHD_DLOG(connection->daemon, | 780 | MHD_DLOG (connection->daemon, |
774 | "Internal application error, closing connection.\n"); | 781 | "Internal application error, closing connection.\n"); |
775 | CLOSE(connection->socket_fd); | 782 | CLOSE (connection->socket_fd); |
776 | connection->socket_fd = -1; | 783 | connection->socket_fd = -1; |
777 | return; | 784 | return; |
778 | } | 785 | } |
779 | /* dh left "processed" bytes in buffer for next time... */ | 786 | /* dh left "processed" bytes in buffer for next time... */ |
780 | memmove(connection->read_buffer, | 787 | memmove (connection->read_buffer, |
781 | &connection->read_buffer[connection->readLoc - processed], | 788 | &connection->read_buffer[connection->readLoc - processed], |
782 | processed); | 789 | processed); |
783 | if (connection->uploadSize != -1) | 790 | if (connection->uploadSize != -1) |
784 | connection->uploadSize -= (connection->readLoc - processed); | 791 | connection->uploadSize -= (connection->readLoc - processed); |
785 | connection->readLoc = processed; | 792 | connection->readLoc = processed; |
786 | if ( (connection->uploadSize == 0) || | 793 | if ((connection->uploadSize == 0) || |
787 | ( (connection->readLoc == 0) && | 794 | ((connection->readLoc == 0) && |
788 | (connection->uploadSize == -1) && | 795 | (connection->uploadSize == -1) && (connection->socket_fd == -1))) |
789 | (connection->socket_fd == -1) ) ) { | 796 | { |
790 | connection->bodyReceived = 1; | 797 | connection->bodyReceived = 1; |
791 | connection->readLoc = 0; | 798 | connection->readLoc = 0; |
792 | connection->read_buffer_size = 0; | 799 | connection->read_buffer_size = 0; |
793 | connection->read_buffer = NULL; | 800 | connection->read_buffer = NULL; |
794 | } | 801 | } |
795 | } | 802 | } |
796 | 803 | ||
797 | 804 | ||
@@ -802,81 +809,88 @@ MHD_call_connection_handler(struct MHD_Connection * connection) { | |||
802 | * to handle reads. | 809 | * to handle reads. |
803 | */ | 810 | */ |
804 | int | 811 | int |
805 | MHD_connection_handle_read(struct MHD_Connection * connection) { | 812 | MHD_connection_handle_read (struct MHD_Connection *connection) |
813 | { | ||
806 | int bytes_read; | 814 | int bytes_read; |
807 | void * tmp; | 815 | void *tmp; |
808 | 816 | ||
809 | if (connection->pool == NULL) | 817 | if (connection->pool == NULL) |
810 | connection->pool = MHD_pool_create(connection->daemon->pool_size); | 818 | connection->pool = MHD_pool_create (connection->daemon->pool_size); |
811 | if (connection->pool == NULL) { | 819 | if (connection->pool == NULL) |
812 | MHD_DLOG(connection->daemon, | 820 | { |
813 | "Failed to create memory pool!\n"); | 821 | MHD_DLOG (connection->daemon, "Failed to create memory pool!\n"); |
814 | CLOSE(connection->socket_fd); | 822 | CLOSE (connection->socket_fd); |
815 | connection->socket_fd = -1; | 823 | connection->socket_fd = -1; |
816 | return MHD_NO; | ||
817 | } | ||
818 | if ( (connection->readLoc >= connection->read_buffer_size) && | ||
819 | (connection->headersReceived == 0) ) { | ||
820 | /* need to grow read buffer */ | ||
821 | tmp = MHD_pool_reallocate(connection->pool, | ||
822 | connection->read_buffer, | ||
823 | connection->read_buffer_size, | ||
824 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); | ||
825 | if (tmp == NULL) { | ||
826 | MHD_DLOG(connection->daemon, | ||
827 | "Not enough memory for reading headers!\n"); | ||
828 | MHD_excessive_data_handler(connection, | ||
829 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); | ||
830 | return MHD_NO; | 824 | return MHD_NO; |
831 | } | 825 | } |
832 | connection->read_buffer = tmp; | 826 | if ((connection->readLoc >= connection->read_buffer_size) && |
833 | connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; | 827 | (connection->headersReceived == 0)) |
834 | } | 828 | { |
835 | if (connection->readLoc >= connection->read_buffer_size) { | 829 | /* need to grow read buffer */ |
836 | MHD_DLOG(connection->daemon, | 830 | tmp = MHD_pool_reallocate (connection->pool, |
837 | "Unexpected call to %s.\n", | 831 | connection->read_buffer, |
838 | __FUNCTION__); | 832 | connection->read_buffer_size, |
839 | return MHD_NO; | 833 | connection->read_buffer_size * 2 + |
840 | } | 834 | MHD_BUF_INC_SIZE); |
841 | bytes_read = RECV(connection->socket_fd, | 835 | if (tmp == NULL) |
842 | &connection->read_buffer[connection->readLoc], | 836 | { |
843 | connection->read_buffer_size - connection->readLoc, | 837 | MHD_DLOG (connection->daemon, |
844 | 0); | 838 | "Not enough memory for reading headers!\n"); |
845 | if (bytes_read < 0) { | 839 | MHD_excessive_data_handler (connection, |
846 | if (errno == EINTR) | 840 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); |
841 | return MHD_NO; | ||
842 | } | ||
843 | connection->read_buffer = tmp; | ||
844 | connection->read_buffer_size = | ||
845 | connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; | ||
846 | } | ||
847 | if (connection->readLoc >= connection->read_buffer_size) | ||
848 | { | ||
849 | MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__); | ||
847 | return MHD_NO; | 850 | return MHD_NO; |
848 | MHD_DLOG(connection->daemon, | 851 | } |
849 | "Failed to receive data: %s\n", | 852 | bytes_read = RECV (connection->socket_fd, |
850 | STRERROR(errno)); | 853 | &connection->read_buffer[connection->readLoc], |
851 | CLOSE(connection->socket_fd); | 854 | connection->read_buffer_size - connection->readLoc, 0); |
852 | connection->socket_fd = -1; | 855 | if (bytes_read < 0) |
853 | return MHD_YES; | 856 | { |
854 | } | 857 | if (errno == EINTR) |
855 | if (bytes_read == 0) { | 858 | return MHD_NO; |
856 | /* other side closed connection */ | 859 | MHD_DLOG (connection->daemon, |
857 | connection->read_close = MHD_YES; | 860 | "Failed to receive data: %s\n", STRERROR (errno)); |
858 | if (connection->readLoc > 0) | 861 | CLOSE (connection->socket_fd); |
859 | MHD_call_connection_handler(connection); | 862 | connection->socket_fd = -1; |
860 | shutdown(connection->socket_fd, SHUT_RD); | 863 | return MHD_YES; |
861 | return MHD_YES; | 864 | } |
862 | } | 865 | if (bytes_read == 0) |
866 | { | ||
867 | /* other side closed connection */ | ||
868 | connection->read_close = MHD_YES; | ||
869 | if (connection->readLoc > 0) | ||
870 | MHD_call_connection_handler (connection); | ||
871 | shutdown (connection->socket_fd, SHUT_RD); | ||
872 | return MHD_YES; | ||
873 | } | ||
863 | connection->readLoc += bytes_read; | 874 | connection->readLoc += bytes_read; |
864 | if (connection->headersReceived == 0) { | 875 | if (connection->headersReceived == 0) |
865 | MHD_parse_connection_headers(connection); | 876 | { |
866 | if (connection->headersReceived == 1) { | 877 | MHD_parse_connection_headers (connection); |
867 | connection->post_processed = MHD_test_post_data(connection); | 878 | if (connection->headersReceived == 1) |
879 | { | ||
880 | connection->post_processed = MHD_test_post_data (connection); | ||
881 | } | ||
882 | } | ||
883 | if (connection->headersReceived == 1) | ||
884 | { | ||
885 | if ((connection->post_processed == MHD_YES) && | ||
886 | (connection->uploadSize == connection->readLoc)) | ||
887 | if (MHD_NO == MHD_parse_post_data (connection)) | ||
888 | connection->post_processed = MHD_NO; | ||
889 | if (((connection->post_processed == MHD_NO) || | ||
890 | (connection->read_buffer_size == connection->readLoc)) && | ||
891 | (connection->method != NULL)) | ||
892 | MHD_call_connection_handler (connection); | ||
868 | } | 893 | } |
869 | } | ||
870 | if (connection->headersReceived == 1) { | ||
871 | if ( (connection->post_processed == MHD_YES) && | ||
872 | (connection->uploadSize == connection->readLoc) ) | ||
873 | if (MHD_NO == MHD_parse_post_data(connection)) | ||
874 | connection->post_processed = MHD_NO; | ||
875 | if ( ( (connection->post_processed == MHD_NO) || | ||
876 | (connection->read_buffer_size == connection->readLoc) ) && | ||
877 | (connection->method != NULL) ) | ||
878 | MHD_call_connection_handler(connection); | ||
879 | } | ||
880 | return MHD_YES; | 894 | return MHD_YES; |
881 | } | 895 | } |
882 | 896 | ||
@@ -885,48 +899,51 @@ MHD_connection_handle_read(struct MHD_Connection * connection) { | |||
885 | * for http-compiliance. | 899 | * for http-compiliance. |
886 | */ | 900 | */ |
887 | static void | 901 | static void |
888 | MHD_add_extra_headers(struct MHD_Connection * connection) { | 902 | MHD_add_extra_headers (struct MHD_Connection *connection) |
889 | const char * have; | 903 | { |
904 | const char *have; | ||
890 | char buf[128]; | 905 | char buf[128]; |
891 | 906 | ||
892 | if (connection->response->total_size == -1) { | 907 | if (connection->response->total_size == -1) |
893 | have = MHD_get_response_header(connection->response, | 908 | { |
894 | MHD_HTTP_HEADER_CONNECTION); | 909 | have = MHD_get_response_header (connection->response, |
895 | if (have == NULL) | 910 | MHD_HTTP_HEADER_CONNECTION); |
896 | MHD_add_response_header(connection->response, | 911 | if (have == NULL) |
897 | MHD_HTTP_HEADER_CONNECTION, | 912 | MHD_add_response_header (connection->response, |
898 | "close"); | 913 | MHD_HTTP_HEADER_CONNECTION, "close"); |
899 | } else if (NULL == MHD_get_response_header(connection->response, | 914 | } |
900 | MHD_HTTP_HEADER_CONTENT_LENGTH)) { | 915 | else if (NULL == MHD_get_response_header (connection->response, |
901 | _REAL_SNPRINTF(buf, | 916 | MHD_HTTP_HEADER_CONTENT_LENGTH)) |
902 | 128, | 917 | { |
903 | "%llu", | 918 | _REAL_SNPRINTF (buf, |
904 | (unsigned long long) connection->response->total_size); | 919 | 128, |
905 | MHD_add_response_header(connection->response, | 920 | "%llu", |
906 | MHD_HTTP_HEADER_CONTENT_LENGTH, | 921 | (unsigned long long) connection->response->total_size); |
907 | buf); | 922 | MHD_add_response_header (connection->response, |
908 | } | 923 | MHD_HTTP_HEADER_CONTENT_LENGTH, buf); |
924 | } | ||
909 | } | 925 | } |
910 | 926 | ||
911 | static void get_date_string(char * date, | 927 | static void |
912 | unsigned int max) { | 928 | get_date_string (char *date, unsigned int max) |
913 | static const char * days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; | 929 | { |
914 | static const char * mons[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; | 930 | static const char *days[] = |
931 | { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; | ||
932 | static const char *mons[] = | ||
933 | { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", | ||
934 | "Nov", "Dec" }; | ||
915 | struct tm now; | 935 | struct tm now; |
916 | time_t t; | 936 | time_t t; |
917 | 937 | ||
918 | time(&t); | 938 | time (&t); |
919 | gmtime_r(&t, &now); | 939 | gmtime_r (&t, &now); |
920 | snprintf(date, | 940 | snprintf (date, |
921 | max-1, | 941 | max - 1, |
922 | "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", | 942 | "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", |
923 | days[now.tm_wday % 7], | 943 | days[now.tm_wday % 7], |
924 | now.tm_mday, | 944 | now.tm_mday, |
925 | mons[now.tm_mon % 12], | 945 | mons[now.tm_mon % 12], |
926 | now.tm_year, | 946 | now.tm_year, now.tm_hour, now.tm_min, now.tm_sec); |
927 | now.tm_hour, | ||
928 | now.tm_min, | ||
929 | now.tm_sec); | ||
930 | } | 947 | } |
931 | 948 | ||
932 | /** | 949 | /** |
@@ -935,62 +952,53 @@ static void get_date_string(char * date, | |||
935 | * HTTPd's response. | 952 | * HTTPd's response. |
936 | */ | 953 | */ |
937 | static int | 954 | static int |
938 | MHD_build_header_response(struct MHD_Connection * connection) { | 955 | MHD_build_header_response (struct MHD_Connection *connection) |
956 | { | ||
939 | size_t size; | 957 | size_t size; |
940 | size_t off; | 958 | size_t off; |
941 | struct MHD_HTTP_Header * pos; | 959 | struct MHD_HTTP_Header *pos; |
942 | char code[32]; | 960 | char code[32]; |
943 | char date[128]; | 961 | char date[128]; |
944 | char * data; | 962 | char *data; |
945 | 963 | ||
946 | MHD_add_extra_headers(connection); | 964 | MHD_add_extra_headers (connection); |
947 | SPRINTF(code, | 965 | SPRINTF (code, "%s %u\r\n", MHD_HTTP_VERSION_1_1, connection->responseCode); |
948 | "%s %u\r\n", | 966 | off = strlen (code); |
949 | MHD_HTTP_VERSION_1_1, | ||
950 | connection->responseCode); | ||
951 | off = strlen(code); | ||
952 | /* estimate size */ | 967 | /* estimate size */ |
953 | size = off + 2; /* extra \r\n at the end */ | 968 | size = off + 2; /* extra \r\n at the end */ |
954 | pos = connection->response->first_header; | 969 | pos = connection->response->first_header; |
955 | while (pos != NULL) { | 970 | while (pos != NULL) |
956 | size += strlen(pos->header) + strlen(pos->value) + 4; /* colon, space, linefeeds */ | 971 | { |
957 | pos = pos->next; | 972 | size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */ |
958 | } | 973 | pos = pos->next; |
959 | if (NULL == MHD_get_response_header(connection->response, | 974 | } |
960 | MHD_HTTP_HEADER_DATE)) | 975 | if (NULL == MHD_get_response_header (connection->response, |
961 | get_date_string(date, sizeof(date)); | 976 | MHD_HTTP_HEADER_DATE)) |
977 | get_date_string (date, sizeof (date)); | ||
962 | else | 978 | else |
963 | date[0] = '\0'; | 979 | date[0] = '\0'; |
964 | size += strlen(date); | 980 | size += strlen (date); |
965 | /* produce data */ | 981 | /* produce data */ |
966 | data = MHD_pool_allocate(connection->pool, | 982 | data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES); |
967 | size + 1, | 983 | if (data == NULL) |
968 | MHD_YES); | 984 | { |
969 | if (data == NULL) { | 985 | MHD_DLOG (connection->daemon, "Not enough memory for write!\n"); |
970 | MHD_DLOG(connection->daemon, | 986 | return MHD_NO; |
971 | "Not enough memory for write!\n"); | 987 | } |
972 | return MHD_NO; | 988 | memcpy (data, code, off); |
973 | } | ||
974 | memcpy(data, | ||
975 | code, | ||
976 | off); | ||
977 | pos = connection->response->first_header; | 989 | pos = connection->response->first_header; |
978 | while (pos != NULL) { | 990 | while (pos != NULL) |
979 | SPRINTF(&data[off], | 991 | { |
980 | "%s: %s\r\n", | 992 | SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value); |
981 | pos->header, | 993 | off += strlen (pos->header) + strlen (pos->value) + 4; |
982 | pos->value); | 994 | pos = pos->next; |
983 | off += strlen(pos->header) + strlen(pos->value) + 4; | 995 | } |
984 | pos = pos->next; | 996 | strcpy (&data[off], date); |
985 | } | 997 | off += strlen (date); |
986 | strcpy(&data[off], | 998 | sprintf (&data[off], "\r\n"); |
987 | date); | ||
988 | off += strlen(date); | ||
989 | sprintf(&data[off], | ||
990 | "\r\n"); | ||
991 | off += 2; | 999 | off += 2; |
992 | if (off != size) | 1000 | if (off != size) |
993 | abort(); | 1001 | abort (); |
994 | connection->write_buffer = data; | 1002 | connection->write_buffer = data; |
995 | connection->writeLoc = size; | 1003 | connection->writeLoc = size; |
996 | connection->writePos = 0; | 1004 | connection->writePos = 0; |
@@ -1005,159 +1013,164 @@ MHD_build_header_response(struct MHD_Connection * connection) { | |||
1005 | * call this function | 1013 | * call this function |
1006 | */ | 1014 | */ |
1007 | int | 1015 | int |
1008 | MHD_connection_handle_write(struct MHD_Connection * connection) { | 1016 | MHD_connection_handle_write (struct MHD_Connection *connection) |
1009 | struct MHD_Response * response; | 1017 | { |
1018 | struct MHD_Response *response; | ||
1010 | int ret; | 1019 | int ret; |
1011 | 1020 | ||
1012 | if (MHD_need_100_continue(connection)) { | 1021 | if (MHD_need_100_continue (connection)) |
1013 | ret = SEND(connection->socket_fd, | 1022 | { |
1014 | &HTTP_100_CONTINUE[connection->continuePos], | 1023 | ret = SEND (connection->socket_fd, |
1015 | strlen(HTTP_100_CONTINUE) - connection->continuePos, | 1024 | &HTTP_100_CONTINUE[connection->continuePos], |
1016 | 0); | 1025 | strlen (HTTP_100_CONTINUE) - connection->continuePos, 0); |
1017 | if (ret < 0) { | 1026 | if (ret < 0) |
1018 | if (errno == EINTR) | 1027 | { |
1019 | return MHD_YES; | 1028 | if (errno == EINTR) |
1020 | MHD_DLOG(connection->daemon, | 1029 | return MHD_YES; |
1021 | "Failed to send data: %s\n", | 1030 | MHD_DLOG (connection->daemon, |
1022 | STRERROR(errno)); | 1031 | "Failed to send data: %s\n", STRERROR (errno)); |
1023 | CLOSE(connection->socket_fd); | 1032 | CLOSE (connection->socket_fd); |
1024 | connection->socket_fd = -1; | 1033 | connection->socket_fd = -1; |
1034 | return MHD_YES; | ||
1035 | } | ||
1036 | connection->continuePos += ret; | ||
1025 | return MHD_YES; | 1037 | return MHD_YES; |
1026 | } | 1038 | } |
1027 | connection->continuePos += ret; | ||
1028 | return MHD_YES; | ||
1029 | } | ||
1030 | response = connection->response; | 1039 | response = connection->response; |
1031 | if(response == NULL) { | 1040 | if (response == NULL) |
1032 | MHD_DLOG(connection->daemon, | 1041 | { |
1033 | "Unexpected call to %s.\n", | 1042 | MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__); |
1034 | __FUNCTION__); | 1043 | return MHD_NO; |
1035 | return MHD_NO; | ||
1036 | } | ||
1037 | if (! connection->headersSent) { | ||
1038 | if ( (connection->write_buffer == NULL) && | ||
1039 | (MHD_NO == MHD_build_header_response(connection)) ) { | ||
1040 | /* oops - close! */ | ||
1041 | CLOSE(connection->socket_fd); | ||
1042 | connection->socket_fd = -1; | ||
1043 | return MHD_NO; | ||
1044 | } | 1044 | } |
1045 | ret = SEND(connection->socket_fd, | 1045 | if (!connection->headersSent) |
1046 | &connection->write_buffer[connection->writePos], | 1046 | { |
1047 | connection->writeLoc - connection->writePos, | 1047 | if ((connection->write_buffer == NULL) && |
1048 | 0); | 1048 | (MHD_NO == MHD_build_header_response (connection))) |
1049 | if (ret < 0) { | 1049 | { |
1050 | if (errno == EINTR) | 1050 | /* oops - close! */ |
1051 | return MHD_YES; | 1051 | CLOSE (connection->socket_fd); |
1052 | MHD_DLOG(connection->daemon, | 1052 | connection->socket_fd = -1; |
1053 | "Failed to send data: %s\n", | 1053 | return MHD_NO; |
1054 | STRERROR(errno)); | 1054 | } |
1055 | CLOSE(connection->socket_fd); | 1055 | ret = SEND (connection->socket_fd, |
1056 | connection->socket_fd = -1; | 1056 | &connection->write_buffer[connection->writePos], |
1057 | connection->writeLoc - connection->writePos, 0); | ||
1058 | if (ret < 0) | ||
1059 | { | ||
1060 | if (errno == EINTR) | ||
1061 | return MHD_YES; | ||
1062 | MHD_DLOG (connection->daemon, | ||
1063 | "Failed to send data: %s\n", STRERROR (errno)); | ||
1064 | CLOSE (connection->socket_fd); | ||
1065 | connection->socket_fd = -1; | ||
1066 | return MHD_YES; | ||
1067 | } | ||
1068 | connection->writePos += ret; | ||
1069 | if (connection->writeLoc == connection->writePos) | ||
1070 | { | ||
1071 | connection->writeLoc = 0; | ||
1072 | connection->writePos = 0; | ||
1073 | connection->headersSent = 1; | ||
1074 | MHD_pool_reallocate (connection->pool, | ||
1075 | connection->write_buffer, | ||
1076 | connection->write_buffer_size, 0); | ||
1077 | connection->write_buffer = NULL; | ||
1078 | connection->write_buffer_size = 0; | ||
1079 | } | ||
1057 | return MHD_YES; | 1080 | return MHD_YES; |
1058 | } | 1081 | } |
1059 | connection->writePos += ret; | ||
1060 | if (connection->writeLoc == connection->writePos) { | ||
1061 | connection->writeLoc = 0; | ||
1062 | connection->writePos = 0; | ||
1063 | connection->headersSent = 1; | ||
1064 | MHD_pool_reallocate(connection->pool, | ||
1065 | connection->write_buffer, | ||
1066 | connection->write_buffer_size, | ||
1067 | 0); | ||
1068 | connection->write_buffer = NULL; | ||
1069 | connection->write_buffer_size = 0; | ||
1070 | } | ||
1071 | return MHD_YES; | ||
1072 | } | ||
1073 | if (response->total_size < connection->messagePos) | 1082 | if (response->total_size < connection->messagePos) |
1074 | abort(); /* internal error */ | 1083 | abort (); /* internal error */ |
1075 | if (response->crc != NULL) | 1084 | if (response->crc != NULL) |
1076 | pthread_mutex_lock(&response->mutex); | 1085 | pthread_mutex_lock (&response->mutex); |
1077 | 1086 | ||
1078 | /* prepare send buffer */ | 1087 | /* prepare send buffer */ |
1079 | if ( (response->crc != NULL) && | 1088 | if ((response->crc != NULL) && |
1080 | ( (response->data_start > connection->messagePos) || | 1089 | ((response->data_start > connection->messagePos) || |
1081 | (response->data_start + response->data_size <= connection->messagePos) ) ) { | 1090 | (response->data_start + response->data_size <= |
1082 | ret = response->crc(response->crc_cls, | 1091 | connection->messagePos))) |
1083 | connection->messagePos, | 1092 | { |
1084 | response->data, | 1093 | ret = response->crc (response->crc_cls, |
1085 | MIN(response->data_buffer_size, | 1094 | connection->messagePos, |
1086 | response->total_size - connection->messagePos)); | 1095 | response->data, |
1087 | if (ret == -1) { | 1096 | MIN (response->data_buffer_size, |
1088 | /* end of message, signal other side by closing! */ | 1097 | response->total_size - |
1089 | response->total_size = connection->messagePos; | 1098 | connection->messagePos)); |
1090 | CLOSE(connection->socket_fd); | 1099 | if (ret == -1) |
1091 | connection->socket_fd = -1; | 1100 | { |
1092 | if (response->crc != NULL) | 1101 | /* end of message, signal other side by closing! */ |
1093 | pthread_mutex_unlock(&response->mutex); | 1102 | response->total_size = connection->messagePos; |
1094 | return MHD_YES; | 1103 | CLOSE (connection->socket_fd); |
1095 | } | 1104 | connection->socket_fd = -1; |
1096 | response->data_start = connection->messagePos; | 1105 | if (response->crc != NULL) |
1097 | response->data_size = ret; | 1106 | pthread_mutex_unlock (&response->mutex); |
1098 | if (ret == 0) { | 1107 | return MHD_YES; |
1099 | if (response->crc != NULL) | 1108 | } |
1100 | pthread_mutex_unlock(&response->mutex); | 1109 | response->data_start = connection->messagePos; |
1101 | return MHD_YES; | 1110 | response->data_size = ret; |
1111 | if (ret == 0) | ||
1112 | { | ||
1113 | if (response->crc != NULL) | ||
1114 | pthread_mutex_unlock (&response->mutex); | ||
1115 | return MHD_YES; | ||
1116 | } | ||
1102 | } | 1117 | } |
1103 | } | ||
1104 | /* transmit */ | 1118 | /* transmit */ |
1105 | ret = SEND(connection->socket_fd, | 1119 | ret = SEND (connection->socket_fd, |
1106 | &response->data[connection->messagePos - response->data_start], | 1120 | &response->data[connection->messagePos - response->data_start], |
1107 | response->data_size - (connection->messagePos - response->data_start), | 1121 | response->data_size - (connection->messagePos - |
1108 | 0); | 1122 | response->data_start), 0); |
1109 | if (response->crc != NULL) | 1123 | if (response->crc != NULL) |
1110 | pthread_mutex_unlock(&response->mutex); | 1124 | pthread_mutex_unlock (&response->mutex); |
1111 | if (ret < 0) { | 1125 | if (ret < 0) |
1112 | if (errno == EINTR) | 1126 | { |
1127 | if (errno == EINTR) | ||
1128 | return MHD_YES; | ||
1129 | MHD_DLOG (connection->daemon, | ||
1130 | "Failed to send data: %s\n", STRERROR (errno)); | ||
1131 | CLOSE (connection->socket_fd); | ||
1132 | connection->socket_fd = -1; | ||
1113 | return MHD_YES; | 1133 | return MHD_YES; |
1114 | MHD_DLOG(connection->daemon, | 1134 | } |
1115 | "Failed to send data: %s\n", | ||
1116 | STRERROR(errno)); | ||
1117 | CLOSE(connection->socket_fd); | ||
1118 | connection->socket_fd = -1; | ||
1119 | return MHD_YES; | ||
1120 | } | ||
1121 | connection->messagePos += ret; | 1135 | connection->messagePos += ret; |
1122 | if (connection->messagePos > response->total_size) | 1136 | if (connection->messagePos > response->total_size) |
1123 | abort(); /* internal error */ | 1137 | abort (); /* internal error */ |
1124 | if (connection->messagePos == response->total_size) { | 1138 | if (connection->messagePos == response->total_size) |
1125 | if ( (connection->bodyReceived == 0) || | 1139 | { |
1126 | (connection->headersReceived == 0) ) | 1140 | if ((connection->bodyReceived == 0) || |
1127 | abort(); /* internal error */ | 1141 | (connection->headersReceived == 0)) |
1128 | MHD_destroy_response(response); | 1142 | abort (); /* internal error */ |
1129 | connection->continuePos = 0; | 1143 | MHD_destroy_response (response); |
1130 | connection->responseCode = 0; | 1144 | connection->continuePos = 0; |
1131 | connection->response = NULL; | 1145 | connection->responseCode = 0; |
1132 | connection->headers_received = NULL; | 1146 | connection->response = NULL; |
1133 | connection->headersReceived = 0; | 1147 | connection->headers_received = NULL; |
1134 | connection->headersSent = 0; | 1148 | connection->headersReceived = 0; |
1135 | connection->bodyReceived = 0; | 1149 | connection->headersSent = 0; |
1136 | connection->messagePos = 0; | 1150 | connection->bodyReceived = 0; |
1137 | connection->method = NULL; | 1151 | connection->messagePos = 0; |
1138 | connection->url = NULL; | 1152 | connection->method = NULL; |
1139 | if ( (connection->read_close == MHD_YES) || | 1153 | connection->url = NULL; |
1140 | (0 != strcasecmp(MHD_HTTP_VERSION_1_1, | 1154 | if ((connection->read_close == MHD_YES) || |
1141 | connection->version)) ) { | 1155 | (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))) |
1142 | /* closed for reading => close for good! */ | 1156 | { |
1143 | if (connection->socket_fd != -1) | 1157 | /* closed for reading => close for good! */ |
1144 | CLOSE(connection->socket_fd); | 1158 | if (connection->socket_fd != -1) |
1145 | connection->socket_fd = -1; | 1159 | CLOSE (connection->socket_fd); |
1160 | connection->socket_fd = -1; | ||
1161 | } | ||
1162 | connection->version = NULL; | ||
1163 | connection->read_buffer = NULL; | ||
1164 | connection->write_buffer = NULL; | ||
1165 | connection->read_buffer_size = 0; | ||
1166 | connection->readLoc = 0; | ||
1167 | connection->write_buffer_size = 0; | ||
1168 | connection->writePos = 0; | ||
1169 | connection->writeLoc = 0; | ||
1170 | MHD_pool_destroy (connection->pool); | ||
1171 | connection->pool = NULL; | ||
1146 | } | 1172 | } |
1147 | connection->version = NULL; | ||
1148 | connection->read_buffer = NULL; | ||
1149 | connection->write_buffer = NULL; | ||
1150 | connection->read_buffer_size = 0; | ||
1151 | connection->readLoc = 0; | ||
1152 | connection->write_buffer_size = 0; | ||
1153 | connection->writePos = 0; | ||
1154 | connection->writeLoc = 0; | ||
1155 | MHD_pool_destroy(connection->pool); | ||
1156 | connection->pool = NULL; | ||
1157 | } | ||
1158 | return MHD_YES; | 1173 | return MHD_YES; |
1159 | } | 1174 | } |
1160 | 1175 | ||
1161 | /* end of connection.c */ | 1176 | /* end of connection.c */ |
1162 | |||
1163 | |||