diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-21 00:12:07 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-21 00:12:07 +0000 |
commit | 2f518b078b4d657b618589cce9a3d66edb5f31da (patch) | |
tree | 4a269736951c517cbd9baa17b2e449719833222b | |
parent | 081efd12325ed0b768d404e10f1ac749a90f8225 (diff) | |
download | busybox-w32-2f518b078b4d657b618589cce9a3d66edb5f31da.tar.gz busybox-w32-2f518b078b4d657b618589cce9a3d66edb5f31da.tar.bz2 busybox-w32-2f518b078b4d657b618589cce9a3d66edb5f31da.zip |
httpd: "HEAD" support. Closes bug 1530.
send_file_and_exit 629 645 +16
static.request_HEAD - 5 +5
handle_incoming_and_exit 2732 2737 +5
send_headers 594 597 +3
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/0 up/down: 29/0) Total: 29 bytes
text data bss dec hex filename
796283 740 7484 804507 c469b busybox_old
796312 740 7484 804536 c46b8 busybox_unstripped
-rw-r--r-- | networking/httpd.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index bcd1126a6..5be53179f 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -340,7 +340,12 @@ enum { | |||
340 | #define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1) | 340 | #define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1) |
341 | 341 | ||
342 | /* Prototypes */ | 342 | /* Prototypes */ |
343 | static void send_file_and_exit(const char *url, int headers) ATTRIBUTE_NORETURN; | 343 | enum { |
344 | SEND_HEADERS = (1 << 0), | ||
345 | SEND_BODY = (1 << 1), | ||
346 | SEND_HEADERS_AND_BODY = SEND_HEADERS + SEND_BODY, | ||
347 | }; | ||
348 | static void send_file_and_exit(const char *url, int what) ATTRIBUTE_NORETURN; | ||
344 | 349 | ||
345 | static void free_llist(has_next_ptr **pptr) | 350 | static void free_llist(has_next_ptr **pptr) |
346 | { | 351 | { |
@@ -957,7 +962,7 @@ static void send_headers(int responseNum) | |||
957 | const char *infoString = NULL; | 962 | const char *infoString = NULL; |
958 | const char *mime_type; | 963 | const char *mime_type; |
959 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES | 964 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES |
960 | const char *error_page = 0; | 965 | const char *error_page = NULL; |
961 | #endif | 966 | #endif |
962 | unsigned i; | 967 | unsigned i; |
963 | time_t timer = time(0); | 968 | time_t timer = time(0); |
@@ -1012,7 +1017,7 @@ static void send_headers(int responseNum) | |||
1012 | full_write(1, iobuf, len); | 1017 | full_write(1, iobuf, len); |
1013 | if (DEBUG) | 1018 | if (DEBUG) |
1014 | fprintf(stderr, "writing error page: '%s'\n", error_page); | 1019 | fprintf(stderr, "writing error page: '%s'\n", error_page); |
1015 | return send_file_and_exit(error_page, FALSE); | 1020 | return send_file_and_exit(error_page, SEND_BODY); |
1016 | } | 1021 | } |
1017 | #endif | 1022 | #endif |
1018 | 1023 | ||
@@ -1480,10 +1485,10 @@ static void send_cgi_and_exit( | |||
1480 | * Send a file response to a HTTP request, and exit | 1485 | * Send a file response to a HTTP request, and exit |
1481 | * | 1486 | * |
1482 | * Parameters: | 1487 | * Parameters: |
1483 | * const char *url The requested URL (with leading /). | 1488 | * const char *url The requested URL (with leading /). |
1484 | * headers Don't send headers before if FALSE. | 1489 | * what What to send (headers/body/both). |
1485 | */ | 1490 | */ |
1486 | static void send_file_and_exit(const char *url, int headers) | 1491 | static void send_file_and_exit(const char *url, int what) |
1487 | { | 1492 | { |
1488 | static const char *const suffixTable[] = { | 1493 | static const char *const suffixTable[] = { |
1489 | /* Warning: shorter equivalent suffix in one line must be first */ | 1494 | /* Warning: shorter equivalent suffix in one line must be first */ |
@@ -1516,6 +1521,10 @@ static void send_file_and_exit(const char *url, int headers) | |||
1516 | off_t offset; | 1521 | off_t offset; |
1517 | #endif | 1522 | #endif |
1518 | 1523 | ||
1524 | /* If you want to know about EPIPE below | ||
1525 | * (happens if you abort downloads from local httpd): */ | ||
1526 | signal(SIGPIPE, SIG_IGN); | ||
1527 | |||
1519 | suffix = strrchr(url, '.'); | 1528 | suffix = strrchr(url, '.'); |
1520 | 1529 | ||
1521 | /* If not found, set default as "application/octet-stream"; */ | 1530 | /* If not found, set default as "application/octet-stream"; */ |
@@ -1552,11 +1561,15 @@ static void send_file_and_exit(const char *url, int headers) | |||
1552 | if (f < 0) { | 1561 | if (f < 0) { |
1553 | if (DEBUG) | 1562 | if (DEBUG) |
1554 | bb_perror_msg("cannot open '%s'", url); | 1563 | bb_perror_msg("cannot open '%s'", url); |
1555 | if (headers) | 1564 | /* Error pages are sent by using send_file_and_exit(SEND_BODY). |
1565 | * IOW: it is unsafe to call send_headers_and_exit | ||
1566 | * if what is SEND_BODY! Can recurse! */ | ||
1567 | if (what != SEND_BODY) | ||
1556 | send_headers_and_exit(HTTP_NOT_FOUND); | 1568 | send_headers_and_exit(HTTP_NOT_FOUND); |
1569 | log_and_exit(); | ||
1557 | } | 1570 | } |
1558 | #if ENABLE_FEATURE_HTTPD_RANGES | 1571 | #if ENABLE_FEATURE_HTTPD_RANGES |
1559 | if (!headers) | 1572 | if (what == SEND_BODY) |
1560 | range_start = 0; /* err pages and ranges don't mix */ | 1573 | range_start = 0; /* err pages and ranges don't mix */ |
1561 | range_len = MAXINT(off_t); | 1574 | range_len = MAXINT(off_t); |
1562 | if (range_start) { | 1575 | if (range_start) { |
@@ -1571,18 +1584,14 @@ static void send_file_and_exit(const char *url, int headers) | |||
1571 | } else { | 1584 | } else { |
1572 | range_len = range_end - range_start + 1; | 1585 | range_len = range_end - range_start + 1; |
1573 | send_headers(HTTP_PARTIAL_CONTENT); | 1586 | send_headers(HTTP_PARTIAL_CONTENT); |
1574 | headers = 0; | 1587 | what = SEND_BODY; |
1575 | } | 1588 | } |
1576 | } | 1589 | } |
1577 | #endif | 1590 | #endif |
1578 | 1591 | ||
1579 | if (headers) | 1592 | if (what & SEND_HEADERS) |
1580 | send_headers(HTTP_OK); | 1593 | send_headers(HTTP_OK); |
1581 | 1594 | ||
1582 | /* If you want to know about EPIPE below | ||
1583 | * (happens if you abort downloads from local httpd): */ | ||
1584 | signal(SIGPIPE, SIG_IGN); | ||
1585 | |||
1586 | #if ENABLE_FEATURE_HTTPD_USE_SENDFILE | 1595 | #if ENABLE_FEATURE_HTTPD_USE_SENDFILE |
1587 | offset = range_start; | 1596 | offset = range_start; |
1588 | do { | 1597 | do { |
@@ -1756,13 +1765,13 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) ATTRIBUTE | |||
1756 | static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | 1765 | static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) |
1757 | { | 1766 | { |
1758 | static const char request_GET[] ALIGN1 = "GET"; | 1767 | static const char request_GET[] ALIGN1 = "GET"; |
1759 | |||
1760 | struct stat sb; | 1768 | struct stat sb; |
1761 | char *urlcopy; | 1769 | char *urlcopy; |
1762 | char *urlp; | 1770 | char *urlp; |
1763 | char *tptr; | 1771 | char *tptr; |
1764 | int ip_allowed; | 1772 | int ip_allowed; |
1765 | #if ENABLE_FEATURE_HTTPD_CGI | 1773 | #if ENABLE_FEATURE_HTTPD_CGI |
1774 | static const char request_HEAD[] ALIGN1 = "HEAD"; | ||
1766 | const char *prequest; | 1775 | const char *prequest; |
1767 | char *cookie = NULL; | 1776 | char *cookie = NULL; |
1768 | char *content_type = NULL; | 1777 | char *content_type = NULL; |
@@ -1827,9 +1836,12 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1827 | #if ENABLE_FEATURE_HTTPD_CGI | 1836 | #if ENABLE_FEATURE_HTTPD_CGI |
1828 | prequest = request_GET; | 1837 | prequest = request_GET; |
1829 | if (strcasecmp(iobuf, prequest) != 0) { | 1838 | if (strcasecmp(iobuf, prequest) != 0) { |
1830 | prequest = "POST"; | 1839 | prequest = request_HEAD; |
1831 | if (strcasecmp(iobuf, prequest) != 0) | 1840 | if (strcasecmp(iobuf, prequest) != 0) { |
1832 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | 1841 | prequest = "POST"; |
1842 | if (strcasecmp(iobuf, prequest) != 0) | ||
1843 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | ||
1844 | } | ||
1833 | } | 1845 | } |
1834 | #else | 1846 | #else |
1835 | if (strcasecmp(iobuf, request_GET) != 0) | 1847 | if (strcasecmp(iobuf, request_GET) != 0) |
@@ -1964,17 +1976,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
1964 | /* Try and do our best to parse more lines */ | 1976 | /* Try and do our best to parse more lines */ |
1965 | if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { | 1977 | if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { |
1966 | /* extra read only for POST */ | 1978 | /* extra read only for POST */ |
1967 | if (prequest != request_GET) { | 1979 | if (prequest != request_GET && prequest != request_HEAD) { |
1968 | tptr = iobuf + sizeof("Content-length:") - 1; | 1980 | tptr = iobuf + sizeof("Content-length:") - 1; |
1969 | if (!tptr[0]) | 1981 | if (!tptr[0]) |
1970 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1982 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1971 | errno = 0; | ||
1972 | /* not using strtoul: it ignores leading minus! */ | 1983 | /* not using strtoul: it ignores leading minus! */ |
1973 | length = strtol(tptr, &tptr, 10); | 1984 | length = bb_strtou(tptr, NULL, 10); |
1974 | /* length is "ulong", but we need to pass it to int later */ | 1985 | /* length is "ulong", but we need to pass it to int later */ |
1975 | /* so we check for negative or too large values in one go: */ | 1986 | if (errno || length > INT_MAX) |
1976 | /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */ | ||
1977 | if (tptr[0] || errno || length > INT_MAX) | ||
1978 | send_headers_and_exit(HTTP_BAD_REQUEST); | 1987 | send_headers_and_exit(HTTP_BAD_REQUEST); |
1979 | } | 1988 | } |
1980 | } | 1989 | } |
@@ -2096,7 +2105,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2096 | } | 2105 | } |
2097 | } | 2106 | } |
2098 | #endif | 2107 | #endif |
2099 | if (prequest != request_GET) { | 2108 | if (prequest != request_GET && prequest != request_HEAD) { |
2100 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | 2109 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); |
2101 | } | 2110 | } |
2102 | #endif /* FEATURE_HTTPD_CGI */ | 2111 | #endif /* FEATURE_HTTPD_CGI */ |
@@ -2123,7 +2132,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2123 | * } | 2132 | * } |
2124 | */ | 2133 | */ |
2125 | 2134 | ||
2126 | send_file_and_exit(tptr, TRUE); | 2135 | send_file_and_exit(tptr, |
2136 | (prequest != request_HEAD ? SEND_HEADERS_AND_BODY : SEND_HEADERS)); | ||
2127 | } | 2137 | } |
2128 | 2138 | ||
2129 | /* | 2139 | /* |