diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | src/include/microhttpd.h | 2 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 140 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 8 | ||||
-rw-r--r-- | src/microhttpd/digestauth.c | 118 | ||||
-rw-r--r-- | src/microhttpd/internal.c | 112 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 40 |
7 files changed, 212 insertions, 213 deletions
@@ -1,3 +1,8 @@ | |||
1 | Mon Oct 5 11:53:52 CEST 2015 | ||
2 | Deduplicate code between digestauth and connection | ||
3 | parsing logic for URI arguments, shared code moved | ||
4 | to new MHD_parse_arguments_ function in internal.c. -CG | ||
5 | |||
1 | Thu Oct 1 21:22:05 CEST 2015 | 6 | Thu Oct 1 21:22:05 CEST 2015 |
2 | Releasing libmicrohttpd 0.9.44. -CG | 7 | Releasing libmicrohttpd 0.9.44. -CG |
3 | 8 | ||
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index ef8802c4..d066cecc 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -130,7 +130,7 @@ typedef intptr_t ssize_t; | |||
130 | * Current version of the library. | 130 | * Current version of the library. |
131 | * 0x01093001 = 1.9.30-1. | 131 | * 0x01093001 = 1.9.30-1. |
132 | */ | 132 | */ |
133 | #define MHD_VERSION 0x00094400 | 133 | #define MHD_VERSION 0x00094401 |
134 | 134 | ||
135 | /** | 135 | /** |
136 | * MHD-internal return code for "YES". | 136 | * MHD-internal return code for "YES". |
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 626cba26..8d05c75f 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -1176,17 +1176,22 @@ get_next_header_line (struct MHD_Connection *connection) | |||
1176 | */ | 1176 | */ |
1177 | static int | 1177 | static int |
1178 | connection_add_header (struct MHD_Connection *connection, | 1178 | connection_add_header (struct MHD_Connection *connection, |
1179 | char *key, char *value, enum MHD_ValueKind kind) | 1179 | const char *key, |
1180 | const char *value, | ||
1181 | enum MHD_ValueKind kind) | ||
1180 | { | 1182 | { |
1181 | if (MHD_NO == MHD_set_connection_value (connection, | 1183 | if (MHD_NO == |
1182 | kind, | 1184 | MHD_set_connection_value (connection, |
1183 | key, value)) | 1185 | kind, |
1186 | key, | ||
1187 | value)) | ||
1184 | { | 1188 | { |
1185 | #if HAVE_MESSAGES | 1189 | #if HAVE_MESSAGES |
1186 | MHD_DLOG (connection->daemon, | 1190 | MHD_DLOG (connection->daemon, |
1187 | "Not enough memory to allocate header record!\n"); | 1191 | "Not enough memory to allocate header record!\n"); |
1188 | #endif | 1192 | #endif |
1189 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, | 1193 | transmit_error_response (connection, |
1194 | MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, | ||
1190 | REQUEST_TOO_BIG); | 1195 | REQUEST_TOO_BIG); |
1191 | return MHD_NO; | 1196 | return MHD_NO; |
1192 | } | 1197 | } |
@@ -1195,98 +1200,9 @@ connection_add_header (struct MHD_Connection *connection, | |||
1195 | 1200 | ||
1196 | 1201 | ||
1197 | /** | 1202 | /** |
1198 | * Parse and unescape the arguments given by the client as part | ||
1199 | * of the HTTP request URI. | ||
1200 | * | ||
1201 | * @param kind header kind to use for adding to the connection | ||
1202 | * @param connection connection to add headers to | ||
1203 | * @param args argument URI string (after "?" in URI) | ||
1204 | * @return #MHD_NO on failure (out of memory), #MHD_YES for success | ||
1205 | */ | ||
1206 | static int | ||
1207 | parse_arguments (enum MHD_ValueKind kind, | ||
1208 | struct MHD_Connection *connection, | ||
1209 | char *args) | ||
1210 | { | ||
1211 | char *equals; | ||
1212 | char *amper; | ||
1213 | |||
1214 | while (NULL != args) | ||
1215 | { | ||
1216 | equals = strchr (args, '='); | ||
1217 | amper = strchr (args, '&'); | ||
1218 | if (NULL == amper) | ||
1219 | { | ||
1220 | /* last argument */ | ||
1221 | if (NULL == equals) | ||
1222 | { | ||
1223 | /* got 'foo', add key 'foo' with NULL for value */ | ||
1224 | MHD_unescape_plus (args); | ||
1225 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
1226 | connection, | ||
1227 | args); | ||
1228 | return connection_add_header (connection, | ||
1229 | args, | ||
1230 | NULL, | ||
1231 | kind); | ||
1232 | } | ||
1233 | /* got 'foo=bar' */ | ||
1234 | equals[0] = '\0'; | ||
1235 | equals++; | ||
1236 | MHD_unescape_plus (args); | ||
1237 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
1238 | connection, | ||
1239 | args); | ||
1240 | MHD_unescape_plus (equals); | ||
1241 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
1242 | connection, | ||
1243 | equals); | ||
1244 | return connection_add_header (connection, args, equals, kind); | ||
1245 | } | ||
1246 | /* amper is non-NULL here */ | ||
1247 | amper[0] = '\0'; | ||
1248 | amper++; | ||
1249 | if ( (NULL == equals) || | ||
1250 | (equals >= amper) ) | ||
1251 | { | ||
1252 | /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */ | ||
1253 | MHD_unescape_plus (args); | ||
1254 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
1255 | connection, | ||
1256 | args); | ||
1257 | if (MHD_NO == | ||
1258 | connection_add_header (connection, | ||
1259 | args, | ||
1260 | NULL, | ||
1261 | kind)) | ||
1262 | return MHD_NO; | ||
1263 | /* continue with 'bar' */ | ||
1264 | args = amper; | ||
1265 | continue; | ||
1266 | } | ||
1267 | /* equals and amper are non-NULL here, and equals < amper, | ||
1268 | so we got regular 'foo=value&bar...'-kind of argument */ | ||
1269 | equals[0] = '\0'; | ||
1270 | equals++; | ||
1271 | MHD_unescape_plus (args); | ||
1272 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
1273 | connection, | ||
1274 | args); | ||
1275 | MHD_unescape_plus (equals); | ||
1276 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
1277 | connection, | ||
1278 | equals); | ||
1279 | if (MHD_NO == connection_add_header (connection, args, equals, kind)) | ||
1280 | return MHD_NO; | ||
1281 | args = amper; | ||
1282 | } | ||
1283 | return MHD_YES; | ||
1284 | } | ||
1285 | |||
1286 | |||
1287 | /** | ||
1288 | * Parse the cookie header (see RFC 2109). | 1203 | * Parse the cookie header (see RFC 2109). |
1289 | * | 1204 | * |
1205 | * @param connection connection to parse header of | ||
1290 | * @return #MHD_YES for success, #MHD_NO for failure (malformed, out of memory) | 1206 | * @return #MHD_YES for success, #MHD_NO for failure (malformed, out of memory) |
1291 | */ | 1207 | */ |
1292 | static int | 1208 | static int |
@@ -1372,8 +1288,11 @@ parse_cookie_header (struct MHD_Connection *connection) | |||
1372 | equals[strlen (equals) - 1] = '\0'; | 1288 | equals[strlen (equals) - 1] = '\0'; |
1373 | equals++; | 1289 | equals++; |
1374 | } | 1290 | } |
1375 | if (MHD_NO == connection_add_header (connection, | 1291 | if (MHD_NO == |
1376 | pos, equals, MHD_COOKIE_KIND)) | 1292 | connection_add_header (connection, |
1293 | pos, | ||
1294 | equals, | ||
1295 | MHD_COOKIE_KIND)) | ||
1377 | return MHD_NO; | 1296 | return MHD_NO; |
1378 | pos = semicolon; | 1297 | pos = semicolon; |
1379 | } | 1298 | } |
@@ -1392,9 +1311,11 @@ static int | |||
1392 | parse_initial_message_line (struct MHD_Connection *connection, | 1311 | parse_initial_message_line (struct MHD_Connection *connection, |
1393 | char *line) | 1312 | char *line) |
1394 | { | 1313 | { |
1314 | struct MHD_Daemon *daemon = connection->daemon; | ||
1395 | char *uri; | 1315 | char *uri; |
1396 | char *http_version; | 1316 | char *http_version; |
1397 | char *args; | 1317 | char *args; |
1318 | unsigned int unused_num_headers; | ||
1398 | 1319 | ||
1399 | if (NULL == (uri = strchr (line, ' '))) | 1320 | if (NULL == (uri = strchr (line, ' '))) |
1400 | return MHD_NO; /* serious error */ | 1321 | return MHD_NO; /* serious error */ |
@@ -1409,21 +1330,26 @@ parse_initial_message_line (struct MHD_Connection *connection, | |||
1409 | http_version[0] = '\0'; | 1330 | http_version[0] = '\0'; |
1410 | http_version++; | 1331 | http_version++; |
1411 | } | 1332 | } |
1412 | if (NULL != connection->daemon->uri_log_callback) | 1333 | if (NULL != daemon->uri_log_callback) |
1413 | connection->client_context | 1334 | connection->client_context |
1414 | = connection->daemon->uri_log_callback (connection->daemon->uri_log_callback_cls, | 1335 | = daemon->uri_log_callback (daemon->uri_log_callback_cls, |
1415 | uri, | 1336 | uri, |
1416 | connection); | 1337 | connection); |
1417 | args = strchr (uri, '?'); | 1338 | args = strchr (uri, '?'); |
1418 | if (NULL != args) | 1339 | if (NULL != args) |
1419 | { | 1340 | { |
1420 | args[0] = '\0'; | 1341 | args[0] = '\0'; |
1421 | args++; | 1342 | args++; |
1422 | parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args); | 1343 | /* note that this call clobbers 'args' */ |
1344 | MHD_parse_arguments_ (connection, | ||
1345 | MHD_GET_ARGUMENT_KIND, | ||
1346 | args, | ||
1347 | &connection_add_header, | ||
1348 | &unused_num_headers); | ||
1423 | } | 1349 | } |
1424 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | 1350 | daemon->unescape_callback (daemon->unescape_callback_cls, |
1425 | connection, | 1351 | connection, |
1426 | uri); | 1352 | uri); |
1427 | connection->url = uri; | 1353 | connection->url = uri; |
1428 | if (NULL == http_version) | 1354 | if (NULL == http_version) |
1429 | connection->version = ""; | 1355 | connection->version = ""; |
@@ -1858,7 +1784,9 @@ process_broken_line (struct MHD_Connection *connection, | |||
1858 | } | 1784 | } |
1859 | EXTRA_CHECK ((NULL != last) && (NULL != connection->colon)); | 1785 | EXTRA_CHECK ((NULL != last) && (NULL != connection->colon)); |
1860 | if ((MHD_NO == connection_add_header (connection, | 1786 | if ((MHD_NO == connection_add_header (connection, |
1861 | last, connection->colon, kind))) | 1787 | last, |
1788 | connection->colon, | ||
1789 | kind))) | ||
1862 | { | 1790 | { |
1863 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, | 1791 | transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, |
1864 | REQUEST_TOO_BIG); | 1792 | REQUEST_TOO_BIG); |
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index cfc35955..9edf5fb8 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -1130,12 +1130,12 @@ send_param_adapter (struct MHD_Connection *connection, | |||
1130 | left = connection->response->total_size - connection->response_write_position; | 1130 | left = connection->response->total_size - connection->response_write_position; |
1131 | #ifndef HAVE_SENDFILE64 | 1131 | #ifndef HAVE_SENDFILE64 |
1132 | offset = (off_t) offsetu64; | 1132 | offset = (off_t) offsetu64; |
1133 | if ( (offsetu64 <= (uint64_t)OFF_T_MAX) && | 1133 | if ( (offsetu64 <= (uint64_t) OFF_T_MAX) && |
1134 | 0 < (ret = sendfile (connection->socket_fd, fd, &offset, left))) | 1134 | (0 < (ret = sendfile (connection->socket_fd, fd, &offset, left))) ) |
1135 | #else /* HAVE_SENDFILE64 */ | 1135 | #else /* HAVE_SENDFILE64 */ |
1136 | offset = (off64_t) offsetu64; | 1136 | offset = (off64_t) offsetu64; |
1137 | if ( (offsetu64 <= (uint64_t)OFF64_T_MAX) && | 1137 | if ( (offsetu64 <= (uint64_t) OFF64_T_MAX) && |
1138 | 0 < (ret = sendfile64 (connection->socket_fd, fd, &offset, left))) | 1138 | (0 < (ret = sendfile64 (connection->socket_fd, fd, &offset, left))) ) |
1139 | #endif /* HAVE_SENDFILE64 */ | 1139 | #endif /* HAVE_SENDFILE64 */ |
1140 | { | 1140 | { |
1141 | #if EPOLL_SUPPORT | 1141 | #if EPOLL_SUPPORT |
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c index f0d0a806..3ed76a35 100644 --- a/src/microhttpd/digestauth.c +++ b/src/microhttpd/digestauth.c | |||
@@ -443,19 +443,21 @@ calculate_nonce (uint32_t nonce_time, | |||
443 | * @param connection the connection | 443 | * @param connection the connection |
444 | * @param key the key | 444 | * @param key the key |
445 | * @param value the value, can be NULL | 445 | * @param value the value, can be NULL |
446 | * @param kind type of the header | ||
446 | * @return #MHD_YES if the key-value pair is in the headers, | 447 | * @return #MHD_YES if the key-value pair is in the headers, |
447 | * #MHD_NO if not | 448 | * #MHD_NO if not |
448 | */ | 449 | */ |
449 | static int | 450 | static int |
450 | test_header (struct MHD_Connection *connection, | 451 | test_header (struct MHD_Connection *connection, |
451 | const char *key, | 452 | const char *key, |
452 | const char *value) | 453 | const char *value, |
454 | enum MHD_ValueKind kind) | ||
453 | { | 455 | { |
454 | struct MHD_HTTP_Header *pos; | 456 | struct MHD_HTTP_Header *pos; |
455 | 457 | ||
456 | for (pos = connection->headers_received; NULL != pos; pos = pos->next) | 458 | for (pos = connection->headers_received; NULL != pos; pos = pos->next) |
457 | { | 459 | { |
458 | if (MHD_GET_ARGUMENT_KIND != pos->kind) | 460 | if (kind != pos->kind) |
459 | continue; | 461 | continue; |
460 | if (0 != strcmp (key, pos->header)) | 462 | if (0 != strcmp (key, pos->header)) |
461 | continue; | 463 | continue; |
@@ -488,114 +490,26 @@ check_argument_match (struct MHD_Connection *connection, | |||
488 | { | 490 | { |
489 | struct MHD_HTTP_Header *pos; | 491 | struct MHD_HTTP_Header *pos; |
490 | char *argb; | 492 | char *argb; |
491 | char *argp; | ||
492 | char *equals; | ||
493 | char *amper; | ||
494 | unsigned int num_headers; | 493 | unsigned int num_headers; |
494 | int ret; | ||
495 | 495 | ||
496 | argb = strdup (args); | 496 | argb = strdup (args); |
497 | if (NULL == argb) | 497 | if (NULL == argb) |
498 | { | 498 | { |
499 | #if HAVE_MESSAGES | 499 | #if HAVE_MESSAGES |
500 | MHD_DLOG (connection->daemon, | 500 | MHD_DLOG (connection->daemon, |
501 | "Failed to allocate memory for copy of URI arguments\n"); | 501 | "Failed to allocate memory for copy of URI arguments\n"); |
502 | #endif /* HAVE_MESSAGES */ | 502 | #endif /* HAVE_MESSAGES */ |
503 | return MHD_NO; | 503 | return MHD_NO; |
504 | } | ||
505 | num_headers = 0; | ||
506 | argp = argb; | ||
507 | while ( (NULL != argp) && | ||
508 | ('\0' != argp[0]) ) | ||
509 | { | ||
510 | equals = strchr (argp, '='); | ||
511 | amper = strchr (argp, '&'); | ||
512 | if (NULL == amper) | ||
513 | { | ||
514 | /* last argument */ | ||
515 | if (NULL == equals) | ||
516 | { | ||
517 | /* last argument, without '=' */ | ||
518 | MHD_unescape_plus (argp); | ||
519 | if (MHD_YES != test_header (connection, | ||
520 | argp, | ||
521 | NULL)) | ||
522 | { | ||
523 | free (argb); | ||
524 | return MHD_NO; | ||
525 | } | ||
526 | num_headers++; | ||
527 | break; | ||
528 | } | ||
529 | /* got 'foo=bar' */ | ||
530 | equals[0] = '\0'; | ||
531 | equals++; | ||
532 | MHD_unescape_plus (argp); | ||
533 | /* add with 'value' NULL */ | ||
534 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
535 | connection, | ||
536 | argp); | ||
537 | MHD_unescape_plus (equals); | ||
538 | /* add with 'value' NULL */ | ||
539 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
540 | connection, | ||
541 | equals); | ||
542 | if (MHD_YES != test_header (connection, | ||
543 | argp, | ||
544 | equals)) | ||
545 | { | ||
546 | free (argb); | ||
547 | return MHD_NO; | ||
548 | } | ||
549 | num_headers++; | ||
550 | break; | ||
551 | } | ||
552 | /* amper is non-NULL here */ | ||
553 | amper[0] = '\0'; | ||
554 | amper++; | ||
555 | if ( (NULL == equals) || | ||
556 | (equals >= amper) ) | ||
557 | { | ||
558 | /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */ | ||
559 | MHD_unescape_plus (argp); | ||
560 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
561 | connection, | ||
562 | argp); | ||
563 | if (MHD_YES != | ||
564 | test_header (connection, | ||
565 | argp, | ||
566 | NULL)) | ||
567 | { | ||
568 | free (argb); | ||
569 | return MHD_NO; | ||
570 | } | ||
571 | /* continue with 'bar' */ | ||
572 | num_headers++; | ||
573 | args = amper; | ||
574 | continue; | ||
575 | } | ||
576 | equals[0] = '\0'; | ||
577 | equals++; | ||
578 | MHD_unescape_plus (argp); | ||
579 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
580 | connection, | ||
581 | argp); | ||
582 | MHD_unescape_plus (equals); | ||
583 | connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls, | ||
584 | connection, | ||
585 | equals); | ||
586 | if (MHD_YES != | ||
587 | test_header (connection, | ||
588 | argp, | ||
589 | equals)) | ||
590 | { | ||
591 | free (argb); | ||
592 | return MHD_NO; | ||
593 | } | ||
594 | num_headers++; | ||
595 | argp = amper; | ||
596 | } | 504 | } |
505 | ret = MHD_parse_arguments_ (connection, | ||
506 | MHD_GET_ARGUMENT_KIND, | ||
507 | argb, | ||
508 | &test_header, | ||
509 | &num_headers); | ||
597 | free (argb); | 510 | free (argb); |
598 | 511 | if (MHD_YES != ret) | |
512 | return MHD_NO; | ||
599 | /* also check that the number of headers matches */ | 513 | /* also check that the number of headers matches */ |
600 | for (pos = connection->headers_received; NULL != pos; pos = pos->next) | 514 | for (pos = connection->headers_received; NULL != pos; pos = pos->next) |
601 | { | 515 | { |
diff --git a/src/microhttpd/internal.c b/src/microhttpd/internal.c index b4f12521..515eeabf 100644 --- a/src/microhttpd/internal.c +++ b/src/microhttpd/internal.c | |||
@@ -171,4 +171,116 @@ MHD_http_unescape (char *val) | |||
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | /** | ||
175 | * Parse and unescape the arguments given by the client | ||
176 | * as part of the HTTP request URI. | ||
177 | * | ||
178 | * @param kind header kind to pass to @a cb | ||
179 | * @param connection connection to add headers to | ||
180 | * @param[in|out] args argument URI string (after "?" in URI), | ||
181 | * clobbered in the process! | ||
182 | * @param cb function to call on each key-value pair found | ||
183 | * @param[out] num_headers set to the number of headers found | ||
184 | * @return #MHD_NO on failure (@a cb returned #MHD_NO), | ||
185 | * #MHD_YES for success (parsing succeeded, @a cb always | ||
186 | * returned #MHD_YES) | ||
187 | */ | ||
188 | int | ||
189 | MHD_parse_arguments_ (struct MHD_Connection *connection, | ||
190 | enum MHD_ValueKind kind, | ||
191 | char *args, | ||
192 | MHD_ArgumentIterator_ cb, | ||
193 | unsigned int *num_headers) | ||
194 | { | ||
195 | struct MHD_Daemon *daemon = connection->daemon; | ||
196 | char *equals; | ||
197 | char *amper; | ||
198 | |||
199 | *num_headers = 0; | ||
200 | while ( (NULL != args) && | ||
201 | ('\0' != args[0]) ) | ||
202 | { | ||
203 | equals = strchr (args, '='); | ||
204 | amper = strchr (args, '&'); | ||
205 | if (NULL == amper) | ||
206 | { | ||
207 | /* last argument */ | ||
208 | if (NULL == equals) | ||
209 | { | ||
210 | /* last argument, without '=' */ | ||
211 | MHD_unescape_plus (args); | ||
212 | daemon->unescape_callback (daemon->unescape_callback_cls, | ||
213 | connection, | ||
214 | args); | ||
215 | if (MHD_YES != cb (connection, | ||
216 | args, | ||
217 | NULL, | ||
218 | kind)) | ||
219 | return MHD_NO; | ||
220 | (*num_headers)++; | ||
221 | break; | ||
222 | } | ||
223 | /* got 'foo=bar' */ | ||
224 | equals[0] = '\0'; | ||
225 | equals++; | ||
226 | MHD_unescape_plus (args); | ||
227 | daemon->unescape_callback (daemon->unescape_callback_cls, | ||
228 | connection, | ||
229 | args); | ||
230 | MHD_unescape_plus (equals); | ||
231 | daemon->unescape_callback (daemon->unescape_callback_cls, | ||
232 | connection, | ||
233 | equals); | ||
234 | if (MHD_YES != cb (connection, | ||
235 | args, | ||
236 | equals, | ||
237 | kind)) | ||
238 | return MHD_NO; | ||
239 | (*num_headers)++; | ||
240 | break; | ||
241 | } | ||
242 | /* amper is non-NULL here */ | ||
243 | amper[0] = '\0'; | ||
244 | amper++; | ||
245 | if ( (NULL == equals) || | ||
246 | (equals >= amper) ) | ||
247 | { | ||
248 | /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */ | ||
249 | MHD_unescape_plus (args); | ||
250 | daemon->unescape_callback (daemon->unescape_callback_cls, | ||
251 | connection, | ||
252 | args); | ||
253 | if (MHD_YES != cb (connection, | ||
254 | args, | ||
255 | NULL, | ||
256 | kind)) | ||
257 | return MHD_NO; | ||
258 | /* continue with 'bar' */ | ||
259 | (*num_headers)++; | ||
260 | args = amper; | ||
261 | continue; | ||
262 | } | ||
263 | /* equals and amper are non-NULL here, and equals < amper, | ||
264 | so we got regular 'foo=value&bar...'-kind of argument */ | ||
265 | equals[0] = '\0'; | ||
266 | equals++; | ||
267 | MHD_unescape_plus (args); | ||
268 | daemon->unescape_callback (daemon->unescape_callback_cls, | ||
269 | connection, | ||
270 | args); | ||
271 | MHD_unescape_plus (equals); | ||
272 | daemon->unescape_callback (daemon->unescape_callback_cls, | ||
273 | connection, | ||
274 | equals); | ||
275 | if (MHD_YES != cb (connection, | ||
276 | args, | ||
277 | equals, | ||
278 | kind)) | ||
279 | return MHD_NO; | ||
280 | (*num_headers)++; | ||
281 | args = amper; | ||
282 | } | ||
283 | return MHD_YES; | ||
284 | } | ||
285 | |||
174 | /* end of internal.c */ | 286 | /* end of internal.c */ |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index d2fdd925..7d43252a 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -1447,4 +1447,44 @@ void | |||
1447 | MHD_unescape_plus (char *arg); | 1447 | MHD_unescape_plus (char *arg); |
1448 | 1448 | ||
1449 | 1449 | ||
1450 | /** | ||
1451 | * Callback invoked when iterating over @a key / @a value | ||
1452 | * argument pairs during parsing. | ||
1453 | * | ||
1454 | * @param connection context of the iteration | ||
1455 | * @param key 0-terminated key string, never NULL | ||
1456 | * @param value 0-terminated value string, may be NULL | ||
1457 | * @param kind origin of the key-value pair | ||
1458 | * @return #MHD_YES on success (continue to iterate) | ||
1459 | * #MHD_NO to signal failure (and abort iteration) | ||
1460 | */ | ||
1461 | typedef int | ||
1462 | (*MHD_ArgumentIterator_)(struct MHD_Connection *connection, | ||
1463 | const char *key, | ||
1464 | const char *value, | ||
1465 | enum MHD_ValueKind kind); | ||
1466 | |||
1467 | |||
1468 | /** | ||
1469 | * Parse and unescape the arguments given by the client | ||
1470 | * as part of the HTTP request URI. | ||
1471 | * | ||
1472 | * @param kind header kind to pass to @a cb | ||
1473 | * @param connection connection to add headers to | ||
1474 | * @param[in|out] args argument URI string (after "?" in URI), | ||
1475 | * clobbered in the process! | ||
1476 | * @param cb function to call on each key-value pair found | ||
1477 | * @param[out] num_headers set to the number of headers found | ||
1478 | * @return #MHD_NO on failure (@a cb returned #MHD_NO), | ||
1479 | * #MHD_YES for success (parsing succeeded, @a cb always | ||
1480 | * returned #MHD_YES) | ||
1481 | */ | ||
1482 | int | ||
1483 | MHD_parse_arguments_ (struct MHD_Connection *connection, | ||
1484 | enum MHD_ValueKind kind, | ||
1485 | char *args, | ||
1486 | MHD_ArgumentIterator_ cb, | ||
1487 | unsigned int *num_headers); | ||
1488 | |||
1489 | |||
1450 | #endif | 1490 | #endif |