aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--src/include/microhttpd.h2
-rw-r--r--src/microhttpd/connection.c140
-rw-r--r--src/microhttpd/daemon.c8
-rw-r--r--src/microhttpd/digestauth.c118
-rw-r--r--src/microhttpd/internal.c112
-rw-r--r--src/microhttpd/internal.h40
7 files changed, 212 insertions, 213 deletions
diff --git a/ChangeLog b/ChangeLog
index 5a11c952..e6f17285 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
1Mon 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
1Thu Oct 1 21:22:05 CEST 2015 6Thu 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 */
1177static int 1177static int
1178connection_add_header (struct MHD_Connection *connection, 1178connection_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 */
1206static int
1207parse_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 */
1292static int 1208static 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
1392parse_initial_message_line (struct MHD_Connection *connection, 1311parse_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 */
449static int 450static int
450test_header (struct MHD_Connection *connection, 451test_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 */
188int
189MHD_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
1447MHD_unescape_plus (char *arg); 1447MHD_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 */
1461typedef 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 */
1482int
1483MHD_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