httpd: cgi-bin support for DELETE, PUT, OPTIONS etc methods

function                                             old     new   delta
handle_incoming_and_exit                            2217    2240     +23
static.request_POST                                    -       5      +5
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 28/0)               Total: 28 bytes

Signed-off-by: Alexander Sack <asac@pantacor.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
pull/18/merge
Alexander Sack 2021-05-04 07:41:50 +00:00 committed by Denys Vlasenko
parent 8e71f2aab8
commit 36e932abdf
1 changed files with 40 additions and 45 deletions

View File

@ -344,13 +344,6 @@ typedef struct Htaccess_Proxy {
char *url_to; char *url_to;
} Htaccess_Proxy; } Htaccess_Proxy;
typedef enum CGI_type {
CGI_NONE = 0,
CGI_NORMAL,
CGI_INDEX,
CGI_INTERPRETER,
} CGI_type;
enum { enum {
HTTP_OK = 200, HTTP_OK = 200,
HTTP_PARTIAL_CONTENT = 206, HTTP_PARTIAL_CONTENT = 206,
@ -2174,7 +2167,6 @@ static void send_REQUEST_TIMEOUT_and_exit(int sig UNUSED_PARAM)
static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) NORETURN; static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) NORETURN;
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";
struct stat sb; struct stat sb;
char *urlcopy; char *urlcopy;
char *urlp; char *urlp;
@ -2186,13 +2178,17 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
unsigned total_headers_len; unsigned total_headers_len;
#endif #endif
#if ENABLE_FEATURE_HTTPD_CGI #if ENABLE_FEATURE_HTTPD_CGI
static const char request_GET[] ALIGN1 = "GET";
static const char request_HEAD[] ALIGN1 = "HEAD"; static const char request_HEAD[] ALIGN1 = "HEAD";
static const char request_POST[] ALIGN1 = "POST";
const char *prequest; const char *prequest;
unsigned long length = 0; unsigned long POST_length;
enum CGI_type cgi_type = CGI_NONE; enum CGI_type {
#elif ENABLE_FEATURE_HTTPD_PROXY CGI_NONE = 0,
#define prequest request_GET CGI_NORMAL,
unsigned long length = 0; CGI_INDEX,
CGI_INTERPRETER,
} cgi_type = CGI_NONE;
#endif #endif
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
smallint authorized = -1; smallint authorized = -1;
@ -2235,7 +2231,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
if (!get_line()) /* EOF or error or empty line */ if (!get_line()) /* EOF or error or empty line */
send_headers_and_exit(HTTP_BAD_REQUEST); send_headers_and_exit(HTTP_BAD_REQUEST);
/* Determine type of request (GET/POST) */ /* Determine type of request (GET/POST/...) */
// rfc2616: method and URI is separated by exactly one space // rfc2616: method and URI is separated by exactly one space
//urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed
urlp = strchr(iobuf, ' '); urlp = strchr(iobuf, ' ');
@ -2244,16 +2240,20 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
*urlp++ = '\0'; *urlp++ = '\0';
#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)
goto found;
prequest = request_HEAD; prequest = request_HEAD;
if (strcasecmp(iobuf, prequest) != 0) { if (strcasecmp(iobuf, prequest) == 0)
prequest = "POST"; goto found;
if (strcasecmp(iobuf, prequest) != 0) prequest = request_POST;
send_headers_and_exit(HTTP_NOT_IMPLEMENTED); if (strcasecmp(iobuf, prequest) == 0)
} goto found;
} /* For CGI, allow other requests too (DELETE, PUT, OPTIONS, etc) */
prequest = alloca(16);
safe_strncpy((char*)prequest, iobuf, 16);
found:
#else #else
if (strcasecmp(iobuf, request_GET) != 0) if (strcasecmp(iobuf, "GET") != 0)
send_headers_and_exit(HTTP_NOT_IMPLEMENTED); send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
#endif #endif
// rfc2616: method and URI is separated by exactly one space // rfc2616: method and URI is separated by exactly one space
@ -2300,7 +2300,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
* to http://hostname[:port]/new/pathSFX * to http://hostname[:port]/new/pathSFX
*/ */
fdprintf(proxy_fd, "%s %s%s %s\r\n", fdprintf(proxy_fd, "%s %s%s %s\r\n",
prequest, /* "GET" or "POST" */ iobuf, /* "GET" / "POST" / etc */
proxy_entry->url_to, /* "/new/path" */ proxy_entry->url_to, /* "/new/path" */
urlcopy + strlen(proxy_entry->url_from), /* "SFX" */ urlcopy + strlen(proxy_entry->url_from), /* "SFX" */
HTTP_slash /* "HTTP/xyz" */ HTTP_slash /* "HTTP/xyz" */
@ -2328,7 +2328,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
/* Algorithm stolen from libbb bb_simplify_path(), /* Algorithm stolen from libbb bb_simplify_path(),
* but don't strdup, retain trailing slash, protect root */ * but don't strdup, retain trailing slash, protect root */
urlp = tptr = urlcopy; urlp = tptr = urlcopy;
for (;;) { while (1) {
if (*urlp == '/') { if (*urlp == '/') {
/* skip duplicate (or initial) slash */ /* skip duplicate (or initial) slash */
if (*tptr == '/') { if (*tptr == '/') {
@ -2435,6 +2435,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
#if ENABLE_FEATURE_HTTPD_CGI #if ENABLE_FEATURE_HTTPD_CGI
total_headers_len = 0; total_headers_len = 0;
POST_length = 0;
#endif #endif
/* Read until blank line */ /* Read until blank line */
@ -2450,24 +2451,17 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
#endif #endif
if (DEBUG) if (DEBUG)
bb_error_msg("header: '%s'", iobuf); bb_error_msg("header: '%s'", iobuf);
#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY
/* Try and do our best to parse more lines */
if (STRNCASECMP(iobuf, "Content-Length:") == 0) {
/* extra read only for POST */
if (prequest != request_GET
#if ENABLE_FEATURE_HTTPD_CGI #if ENABLE_FEATURE_HTTPD_CGI
&& prequest != request_HEAD /* Only POST needs to know POST_length */
# endif if (prequest == request_POST && STRNCASECMP(iobuf, "Content-Length:") == 0) {
) {
tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1); tptr = skip_whitespace(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);
/* not using strtoul: it ignores leading minus! */ /* not using strtoul: it ignores leading minus! */
length = bb_strtou(tptr, NULL, 10); POST_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 */
if (errno || length > INT_MAX) if (errno || POST_length > INT_MAX)
send_headers_and_exit(HTTP_BAD_REQUEST); send_headers_and_exit(HTTP_BAD_REQUEST);
}
continue; continue;
} }
#endif #endif
@ -2588,7 +2582,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
send_cgi_and_exit( send_cgi_and_exit(
(cgi_type == CGI_INDEX) ? "/cgi-bin/index.cgi" (cgi_type == CGI_INDEX) ? "/cgi-bin/index.cgi"
/*CGI_NORMAL or CGI_INTERPRETER*/ : urlcopy, /*CGI_NORMAL or CGI_INTERPRETER*/ : urlcopy,
urlcopy, prequest, length urlcopy, prequest, POST_length
); );
} }
#endif #endif
@ -2599,13 +2593,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
#if ENABLE_FEATURE_HTTPD_CGI #if ENABLE_FEATURE_HTTPD_CGI
if (prequest != request_GET && prequest != request_HEAD) { if (prequest != request_GET && prequest != request_HEAD) {
/* POST for files does not make sense */ /* POST / DELETE / PUT / OPTIONS for files do not make sense */
send_headers_and_exit(HTTP_NOT_IMPLEMENTED); send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
} }
send_file_and_exit(tptr, send_file_and_exit(tptr,
(prequest != request_HEAD ? SEND_HEADERS_AND_BODY : SEND_HEADERS) (prequest != request_HEAD ? SEND_HEADERS_AND_BODY : SEND_HEADERS)
); );
#else #else
/* It was verified earlier that it is a "GET" */
send_file_and_exit(tptr, SEND_HEADERS_AND_BODY); send_file_and_exit(tptr, SEND_HEADERS_AND_BODY);
#endif #endif
} }