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
This commit is contained in:
@ -340,7 +340,12 @@ enum {
|
|||||||
#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
|
#define STRNCASECMP(a, str) strncasecmp((a), (str), sizeof(str)-1)
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
static void send_file_and_exit(const char *url, int headers) ATTRIBUTE_NORETURN;
|
enum {
|
||||||
|
SEND_HEADERS = (1 << 0),
|
||||||
|
SEND_BODY = (1 << 1),
|
||||||
|
SEND_HEADERS_AND_BODY = SEND_HEADERS + SEND_BODY,
|
||||||
|
};
|
||||||
|
static void send_file_and_exit(const char *url, int what) ATTRIBUTE_NORETURN;
|
||||||
|
|
||||||
static void free_llist(has_next_ptr **pptr)
|
static void free_llist(has_next_ptr **pptr)
|
||||||
{
|
{
|
||||||
@ -957,7 +962,7 @@ static void send_headers(int responseNum)
|
|||||||
const char *infoString = NULL;
|
const char *infoString = NULL;
|
||||||
const char *mime_type;
|
const char *mime_type;
|
||||||
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
||||||
const char *error_page = 0;
|
const char *error_page = NULL;
|
||||||
#endif
|
#endif
|
||||||
unsigned i;
|
unsigned i;
|
||||||
time_t timer = time(0);
|
time_t timer = time(0);
|
||||||
@ -1012,7 +1017,7 @@ static void send_headers(int responseNum)
|
|||||||
full_write(1, iobuf, len);
|
full_write(1, iobuf, len);
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
fprintf(stderr, "writing error page: '%s'\n", error_page);
|
fprintf(stderr, "writing error page: '%s'\n", error_page);
|
||||||
return send_file_and_exit(error_page, FALSE);
|
return send_file_and_exit(error_page, SEND_BODY);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1480,10 +1485,10 @@ static void send_cgi_and_exit(
|
|||||||
* Send a file response to a HTTP request, and exit
|
* Send a file response to a HTTP request, and exit
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* const char *url The requested URL (with leading /).
|
* const char *url The requested URL (with leading /).
|
||||||
* headers Don't send headers before if FALSE.
|
* what What to send (headers/body/both).
|
||||||
*/
|
*/
|
||||||
static void send_file_and_exit(const char *url, int headers)
|
static void send_file_and_exit(const char *url, int what)
|
||||||
{
|
{
|
||||||
static const char *const suffixTable[] = {
|
static const char *const suffixTable[] = {
|
||||||
/* Warning: shorter equivalent suffix in one line must be first */
|
/* 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)
|
|||||||
off_t offset;
|
off_t offset;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If you want to know about EPIPE below
|
||||||
|
* (happens if you abort downloads from local httpd): */
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
suffix = strrchr(url, '.');
|
suffix = strrchr(url, '.');
|
||||||
|
|
||||||
/* If not found, set default as "application/octet-stream"; */
|
/* If not found, set default as "application/octet-stream"; */
|
||||||
@ -1552,11 +1561,15 @@ static void send_file_and_exit(const char *url, int headers)
|
|||||||
if (f < 0) {
|
if (f < 0) {
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
bb_perror_msg("cannot open '%s'", url);
|
bb_perror_msg("cannot open '%s'", url);
|
||||||
if (headers)
|
/* Error pages are sent by using send_file_and_exit(SEND_BODY).
|
||||||
|
* IOW: it is unsafe to call send_headers_and_exit
|
||||||
|
* if what is SEND_BODY! Can recurse! */
|
||||||
|
if (what != SEND_BODY)
|
||||||
send_headers_and_exit(HTTP_NOT_FOUND);
|
send_headers_and_exit(HTTP_NOT_FOUND);
|
||||||
|
log_and_exit();
|
||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_HTTPD_RANGES
|
#if ENABLE_FEATURE_HTTPD_RANGES
|
||||||
if (!headers)
|
if (what == SEND_BODY)
|
||||||
range_start = 0; /* err pages and ranges don't mix */
|
range_start = 0; /* err pages and ranges don't mix */
|
||||||
range_len = MAXINT(off_t);
|
range_len = MAXINT(off_t);
|
||||||
if (range_start) {
|
if (range_start) {
|
||||||
@ -1571,18 +1584,14 @@ static void send_file_and_exit(const char *url, int headers)
|
|||||||
} else {
|
} else {
|
||||||
range_len = range_end - range_start + 1;
|
range_len = range_end - range_start + 1;
|
||||||
send_headers(HTTP_PARTIAL_CONTENT);
|
send_headers(HTTP_PARTIAL_CONTENT);
|
||||||
headers = 0;
|
what = SEND_BODY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (headers)
|
if (what & SEND_HEADERS)
|
||||||
send_headers(HTTP_OK);
|
send_headers(HTTP_OK);
|
||||||
|
|
||||||
/* If you want to know about EPIPE below
|
|
||||||
* (happens if you abort downloads from local httpd): */
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
|
#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
|
||||||
offset = range_start;
|
offset = range_start;
|
||||||
do {
|
do {
|
||||||
@ -1756,13 +1765,13 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) ATTRIBUTE
|
|||||||
static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
||||||
{
|
{
|
||||||
static const char request_GET[] ALIGN1 = "GET";
|
static const char request_GET[] ALIGN1 = "GET";
|
||||||
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char *urlcopy;
|
char *urlcopy;
|
||||||
char *urlp;
|
char *urlp;
|
||||||
char *tptr;
|
char *tptr;
|
||||||
int ip_allowed;
|
int ip_allowed;
|
||||||
#if ENABLE_FEATURE_HTTPD_CGI
|
#if ENABLE_FEATURE_HTTPD_CGI
|
||||||
|
static const char request_HEAD[] ALIGN1 = "HEAD";
|
||||||
const char *prequest;
|
const char *prequest;
|
||||||
char *cookie = NULL;
|
char *cookie = NULL;
|
||||||
char *content_type = NULL;
|
char *content_type = NULL;
|
||||||
@ -1827,9 +1836,12 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
|||||||
#if ENABLE_FEATURE_HTTPD_CGI
|
#if ENABLE_FEATURE_HTTPD_CGI
|
||||||
prequest = request_GET;
|
prequest = request_GET;
|
||||||
if (strcasecmp(iobuf, prequest) != 0) {
|
if (strcasecmp(iobuf, prequest) != 0) {
|
||||||
prequest = "POST";
|
prequest = request_HEAD;
|
||||||
if (strcasecmp(iobuf, prequest) != 0)
|
if (strcasecmp(iobuf, prequest) != 0) {
|
||||||
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
prequest = "POST";
|
||||||
|
if (strcasecmp(iobuf, prequest) != 0)
|
||||||
|
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (strcasecmp(iobuf, request_GET) != 0)
|
if (strcasecmp(iobuf, request_GET) != 0)
|
||||||
@ -1964,17 +1976,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
|||||||
/* Try and do our best to parse more lines */
|
/* Try and do our best to parse more lines */
|
||||||
if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
|
if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
|
||||||
/* extra read only for POST */
|
/* extra read only for POST */
|
||||||
if (prequest != request_GET) {
|
if (prequest != request_GET && prequest != request_HEAD) {
|
||||||
tptr = iobuf + sizeof("Content-length:") - 1;
|
tptr = iobuf + sizeof("Content-length:") - 1;
|
||||||
if (!tptr[0])
|
if (!tptr[0])
|
||||||
send_headers_and_exit(HTTP_BAD_REQUEST);
|
send_headers_and_exit(HTTP_BAD_REQUEST);
|
||||||
errno = 0;
|
|
||||||
/* not using strtoul: it ignores leading minus! */
|
/* not using strtoul: it ignores leading minus! */
|
||||||
length = strtol(tptr, &tptr, 10);
|
length = bb_strtou(tptr, NULL, 10);
|
||||||
/* length is "ulong", but we need to pass it to int later */
|
/* length is "ulong", but we need to pass it to int later */
|
||||||
/* so we check for negative or too large values in one go: */
|
if (errno || length > INT_MAX)
|
||||||
/* (long -> ulong conv caused negatives to be seen as > INT_MAX) */
|
|
||||||
if (tptr[0] || errno || length > INT_MAX)
|
|
||||||
send_headers_and_exit(HTTP_BAD_REQUEST);
|
send_headers_and_exit(HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2096,7 +2105,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (prequest != request_GET) {
|
if (prequest != request_GET && prequest != request_HEAD) {
|
||||||
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
||||||
}
|
}
|
||||||
#endif /* FEATURE_HTTPD_CGI */
|
#endif /* FEATURE_HTTPD_CGI */
|
||||||
@ -2123,7 +2132,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
send_file_and_exit(tptr, TRUE);
|
send_file_and_exit(tptr,
|
||||||
|
(prequest != request_HEAD ? SEND_HEADERS_AND_BODY : SEND_HEADERS));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user