diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-04-16 11:37:02 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-04-16 11:37:02 +0200 |
commit | fba665a8889ad7ec20f926bf2719be5c688ed829 (patch) | |
tree | 531b305e8b570f42fb0c4f7a1d3844f165b51669 | |
parent | d0ae4103ddca21b7b765347611a9cf33f0cccd74 (diff) | |
download | busybox-w32-fba665a8889ad7ec20f926bf2719be5c688ed829.tar.gz busybox-w32-fba665a8889ad7ec20f926bf2719be5c688ed829.tar.bz2 busybox-w32-fba665a8889ad7ec20f926bf2719be5c688ed829.zip |
httpd: put all headers into environment as HTTP_UPPERCASED_HEADER=val
Set up environment variables before running the CGI script.
The variables will be named HTTP_<filtered_name> where the <filtered_name>
is the header name capitalized and all characters not matching
[a-z] | [A-Z] | [0-9] replaced with '_'.
function old new delta
http_response 80 88 +8
http_response_type 20 22 +2
send_headers 718 715 -3
parse_conf 1481 1478 -3
get_line 128 110 -18
cgi_io_loop_and_exit 599 569 -30
send_cgi_and_exit 882 738 -144
handle_incoming_and_exit 2793 2592 -201
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/6 up/down: 10/-399) Total: -389 bytes
text data bss dec hex filename
982178 485 7296 989959 f1b07 busybox_old
981675 485 7296 989456 f1910 busybox_unstripped
Signed-off-by: Alexander Vickberg <wickbergster@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/httpd.c | 225 |
1 files changed, 120 insertions, 105 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 53be500d3..11c26a891 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -267,6 +267,7 @@ | |||
267 | #define DEBUG 0 | 267 | #define DEBUG 0 |
268 | 268 | ||
269 | #define IOBUF_SIZE 8192 | 269 | #define IOBUF_SIZE 8192 |
270 | #define MAX_HTTP_HEADERS_SIZE ((8*1024) - 16) | ||
270 | #if PIPE_BUF >= IOBUF_SIZE | 271 | #if PIPE_BUF >= IOBUF_SIZE |
271 | # error "PIPE_BUF >= IOBUF_SIZE" | 272 | # error "PIPE_BUF >= IOBUF_SIZE" |
272 | #endif | 273 | #endif |
@@ -305,6 +306,13 @@ typedef struct Htaccess_Proxy { | |||
305 | char *url_to; | 306 | char *url_to; |
306 | } Htaccess_Proxy; | 307 | } Htaccess_Proxy; |
307 | 308 | ||
309 | typedef enum CGI_type { | ||
310 | CGI_NONE = 0, | ||
311 | CGI_NORMAL, | ||
312 | CGI_INDEX, | ||
313 | CGI_INTERPRETER, | ||
314 | } CGI_type; | ||
315 | |||
308 | enum { | 316 | enum { |
309 | HTTP_OK = 200, | 317 | HTTP_OK = 200, |
310 | HTTP_PARTIAL_CONTENT = 206, | 318 | HTTP_PARTIAL_CONTENT = 206, |
@@ -316,6 +324,7 @@ enum { | |||
316 | HTTP_REQUEST_TIMEOUT = 408, | 324 | HTTP_REQUEST_TIMEOUT = 408, |
317 | HTTP_NOT_IMPLEMENTED = 501, /* used for unrecognized requests */ | 325 | HTTP_NOT_IMPLEMENTED = 501, /* used for unrecognized requests */ |
318 | HTTP_INTERNAL_SERVER_ERROR = 500, | 326 | HTTP_INTERNAL_SERVER_ERROR = 500, |
327 | HTTP_ENTITY_TOO_LARGE = 413, | ||
319 | HTTP_CONTINUE = 100, | 328 | HTTP_CONTINUE = 100, |
320 | #if 0 /* future use */ | 329 | #if 0 /* future use */ |
321 | HTTP_SWITCHING_PROTOCOLS = 101, | 330 | HTTP_SWITCHING_PROTOCOLS = 101, |
@@ -347,6 +356,7 @@ static const uint16_t http_response_type[] ALIGN2 = { | |||
347 | HTTP_BAD_REQUEST, | 356 | HTTP_BAD_REQUEST, |
348 | HTTP_FORBIDDEN, | 357 | HTTP_FORBIDDEN, |
349 | HTTP_INTERNAL_SERVER_ERROR, | 358 | HTTP_INTERNAL_SERVER_ERROR, |
359 | HTTP_ENTITY_TOO_LARGE, | ||
350 | #if 0 /* not implemented */ | 360 | #if 0 /* not implemented */ |
351 | HTTP_CREATED, | 361 | HTTP_CREATED, |
352 | HTTP_ACCEPTED, | 362 | HTTP_ACCEPTED, |
@@ -377,6 +387,7 @@ static const struct { | |||
377 | { "Bad Request", "Unsupported method" }, | 387 | { "Bad Request", "Unsupported method" }, |
378 | { "Forbidden", "" }, | 388 | { "Forbidden", "" }, |
379 | { "Internal Server Error", "Internal Server Error" }, | 389 | { "Internal Server Error", "Internal Server Error" }, |
390 | { "Entity Too Large", "Entity Too Large" }, | ||
380 | #if 0 /* not implemented */ | 391 | #if 0 /* not implemented */ |
381 | { "Created" }, | 392 | { "Created" }, |
382 | { "Accepted" }, | 393 | { "Accepted" }, |
@@ -412,11 +423,6 @@ struct globals { | |||
412 | 423 | ||
413 | IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) | 424 | IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) |
414 | IF_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) | 425 | IF_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) |
415 | IF_FEATURE_HTTPD_CGI(char *referer;) | ||
416 | IF_FEATURE_HTTPD_CGI(char *user_agent;) | ||
417 | IF_FEATURE_HTTPD_CGI(char *host;) | ||
418 | IF_FEATURE_HTTPD_CGI(char *http_accept;) | ||
419 | IF_FEATURE_HTTPD_CGI(char *http_accept_language;) | ||
420 | 426 | ||
421 | off_t file_size; /* -1 - unknown */ | 427 | off_t file_size; /* -1 - unknown */ |
422 | #if ENABLE_FEATURE_HTTPD_RANGES | 428 | #if ENABLE_FEATURE_HTTPD_RANGES |
@@ -1439,23 +1445,17 @@ static void setenv1(const char *name, const char *value) | |||
1439 | * const char *url The requested URL (with leading /). | 1445 | * const char *url The requested URL (with leading /). |
1440 | * const char *orig_uri The original URI before rewriting (if any) | 1446 | * const char *orig_uri The original URI before rewriting (if any) |
1441 | * int post_len Length of the POST body. | 1447 | * int post_len Length of the POST body. |
1442 | * const char *cookie For set HTTP_COOKIE. | ||
1443 | * const char *content_type For set CONTENT_TYPE. | ||
1444 | */ | 1448 | */ |
1445 | static void send_cgi_and_exit( | 1449 | static void send_cgi_and_exit( |
1446 | const char *url, | 1450 | const char *url, |
1447 | const char *orig_uri, | 1451 | const char *orig_uri, |
1448 | const char *request, | 1452 | const char *request, |
1449 | int post_len, | 1453 | int post_len) NORETURN; |
1450 | const char *cookie, | ||
1451 | const char *content_type) NORETURN; | ||
1452 | static void send_cgi_and_exit( | 1454 | static void send_cgi_and_exit( |
1453 | const char *url, | 1455 | const char *url, |
1454 | const char *orig_uri, | 1456 | const char *orig_uri, |
1455 | const char *request, | 1457 | const char *request, |
1456 | int post_len, | 1458 | int post_len) |
1457 | const char *cookie, | ||
1458 | const char *content_type) | ||
1459 | { | 1459 | { |
1460 | struct fd_pair fromCgi; /* CGI -> httpd pipe */ | 1460 | struct fd_pair fromCgi; /* CGI -> httpd pipe */ |
1461 | struct fd_pair toCgi; /* httpd -> CGI pipe */ | 1461 | struct fd_pair toCgi; /* httpd -> CGI pipe */ |
@@ -1533,26 +1533,14 @@ static void send_cgi_and_exit( | |||
1533 | #endif | 1533 | #endif |
1534 | } | 1534 | } |
1535 | } | 1535 | } |
1536 | setenv1("HTTP_USER_AGENT", G.user_agent); | ||
1537 | if (G.http_accept) | ||
1538 | setenv1("HTTP_ACCEPT", G.http_accept); | ||
1539 | if (G.http_accept_language) | ||
1540 | setenv1("HTTP_ACCEPT_LANGUAGE", G.http_accept_language); | ||
1541 | if (post_len) | 1536 | if (post_len) |
1542 | putenv(xasprintf("CONTENT_LENGTH=%u", post_len)); | 1537 | putenv(xasprintf("CONTENT_LENGTH=%u", post_len)); |
1543 | if (cookie) | ||
1544 | setenv1("HTTP_COOKIE", cookie); | ||
1545 | if (content_type) | ||
1546 | setenv1("CONTENT_TYPE", content_type); | ||
1547 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1538 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
1548 | if (remoteuser) { | 1539 | if (remoteuser) { |
1549 | setenv1("REMOTE_USER", remoteuser); | 1540 | setenv1("REMOTE_USER", remoteuser); |
1550 | putenv((char*)"AUTH_TYPE=Basic"); | 1541 | putenv((char*)"AUTH_TYPE=Basic"); |
1551 | } | 1542 | } |
1552 | #endif | 1543 | #endif |
1553 | if (G.referer) | ||
1554 | setenv1("HTTP_REFERER", G.referer); | ||
1555 | setenv1("HTTP_HOST", G.host); /* set to "" if NULL */ | ||
1556 | /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this, | 1544 | /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this, |
1557 | * just run "env SERVER_NAME=xyz httpd ..." instead */ | 1545 | * just run "env SERVER_NAME=xyz httpd ..." instead */ |
1558 | 1546 | ||
@@ -2083,12 +2071,12 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2083 | char *urlcopy; | 2071 | char *urlcopy; |
2084 | char *urlp; | 2072 | char *urlp; |
2085 | char *tptr; | 2073 | char *tptr; |
2074 | unsigned header_len; | ||
2086 | #if ENABLE_FEATURE_HTTPD_CGI | 2075 | #if ENABLE_FEATURE_HTTPD_CGI |
2087 | static const char request_HEAD[] ALIGN1 = "HEAD"; | 2076 | static const char request_HEAD[] ALIGN1 = "HEAD"; |
2088 | const char *prequest; | 2077 | const char *prequest; |
2089 | char *cookie = NULL; | ||
2090 | char *content_type = NULL; | ||
2091 | unsigned long length = 0; | 2078 | unsigned long length = 0; |
2079 | enum CGI_type cgi_type = CGI_NONE; | ||
2092 | #elif ENABLE_FEATURE_HTTPD_PROXY | 2080 | #elif ENABLE_FEATURE_HTTPD_PROXY |
2093 | #define prequest request_GET | 2081 | #define prequest request_GET |
2094 | unsigned long length = 0; | 2082 | unsigned long length = 0; |
@@ -2201,7 +2189,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2201 | #if ENABLE_FEATURE_HTTPD_PROXY | 2189 | #if ENABLE_FEATURE_HTTPD_PROXY |
2202 | proxy_entry = find_proxy_entry(urlcopy); | 2190 | proxy_entry = find_proxy_entry(urlcopy); |
2203 | if (proxy_entry) | 2191 | if (proxy_entry) |
2204 | header_buf = header_ptr = xmalloc(IOBUF_SIZE); | 2192 | header_buf = header_ptr = xmalloc(MAX_HTTP_HEADERS_SIZE + 2); |
2193 | //TODO: why we don't just start pumping data to proxy here, | ||
2194 | //without decoding URL, saving headers and such??? | ||
2205 | else | 2195 | else |
2206 | #endif | 2196 | #endif |
2207 | { | 2197 | { |
@@ -2275,31 +2265,79 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2275 | *tptr = '/'; | 2265 | *tptr = '/'; |
2276 | } | 2266 | } |
2277 | 2267 | ||
2268 | tptr = urlcopy + 1; /* skip first '/' */ | ||
2269 | |||
2270 | #if ENABLE_FEATURE_HTTPD_CGI | ||
2271 | if (is_prefixed_with(tptr, "cgi-bin/")) { | ||
2272 | if (tptr[8] == '\0') { | ||
2273 | /* protect listing "cgi-bin/" */ | ||
2274 | send_headers_and_exit(HTTP_FORBIDDEN); | ||
2275 | } | ||
2276 | cgi_type = CGI_NORMAL; | ||
2277 | } | ||
2278 | #endif | ||
2279 | |||
2280 | if (urlp[-1] == '/') { | ||
2281 | /* When index_page string is appended to <dir>/ URL, it overwrites | ||
2282 | * the query string. If we fall back to call /cgi-bin/index.cgi, | ||
2283 | * query string would be lost and not available to the CGI. | ||
2284 | * Work around it by making a deep copy. | ||
2285 | */ | ||
2286 | if (ENABLE_FEATURE_HTTPD_CGI) | ||
2287 | g_query = xstrdup(g_query); /* ok for NULL too */ | ||
2288 | strcpy(urlp, index_page); | ||
2289 | } | ||
2290 | if (stat(tptr, &sb) == 0) { | ||
2291 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | ||
2292 | char *suffix = strrchr(tptr, '.'); | ||
2293 | if (suffix) { | ||
2294 | Htaccess *cur; | ||
2295 | for (cur = script_i; cur; cur = cur->next) { | ||
2296 | if (strcmp(cur->before_colon + 1, suffix) == 0) { | ||
2297 | cgi_type = CGI_INTERPRETER; | ||
2298 | break; | ||
2299 | } | ||
2300 | } | ||
2301 | } | ||
2302 | #endif | ||
2303 | if (!found_moved_temporarily) { | ||
2304 | file_size = sb.st_size; | ||
2305 | last_mod = sb.st_mtime; | ||
2306 | } | ||
2307 | } | ||
2308 | #if ENABLE_FEATURE_HTTPD_CGI | ||
2309 | else if (urlp[-1] == '/') { | ||
2310 | /* It's a dir URL and there is no index.html | ||
2311 | * Try cgi-bin/index.cgi */ | ||
2312 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { | ||
2313 | cgi_type = CGI_INDEX; | ||
2314 | } | ||
2315 | } | ||
2316 | #endif | ||
2317 | urlp[0] = '\0'; | ||
2318 | |||
2319 | header_len = 0; | ||
2278 | if (http_major_version >= '0') { | 2320 | if (http_major_version >= '0') { |
2279 | /* Request was with "... HTTP/nXXX", and n >= 0 */ | 2321 | /* Request was with "... HTTP/nXXX", and n >= 0 */ |
2280 | 2322 | ||
2281 | /* Read until blank line */ | 2323 | /* Read until blank line */ |
2282 | while (1) { | 2324 | while (1) { |
2283 | if (!get_line()) | 2325 | int iobuf_len = get_line(); |
2326 | if (!iobuf_len) | ||
2284 | break; /* EOF or error or empty line */ | 2327 | break; /* EOF or error or empty line */ |
2328 | header_len += iobuf_len + 2; | ||
2329 | if (header_len >= MAX_HTTP_HEADERS_SIZE) | ||
2330 | send_headers_and_exit(HTTP_ENTITY_TOO_LARGE); | ||
2285 | if (DEBUG) | 2331 | if (DEBUG) |
2286 | bb_error_msg("header: '%s'", iobuf); | 2332 | bb_error_msg("header: '%s'", iobuf); |
2287 | |||
2288 | #if ENABLE_FEATURE_HTTPD_PROXY | 2333 | #if ENABLE_FEATURE_HTTPD_PROXY |
2289 | if (proxy_entry) { | 2334 | if (proxy_entry) { |
2290 | /* Why 4, not 2? | 2335 | /* protected from overflow by header_len check above */ |
2291 | * We need 2 more bytes for yet another "\r\n" - | 2336 | memcpy(header_ptr, iobuf, iobuf_len); |
2292 | * see near fdprintf(proxy_fd...) further below. | 2337 | header_ptr += iobuf_len; |
2293 | */ | 2338 | header_ptr[0] = '\r'; |
2294 | int maxlen = (IOBUF_SIZE-4) - (int)(header_ptr - header_buf); | 2339 | header_ptr[1] = '\n'; |
2295 | if (maxlen > 0) { | 2340 | header_ptr += 2; |
2296 | int len = strnlen(iobuf, maxlen); | ||
2297 | memcpy(header_ptr, iobuf, len); | ||
2298 | header_ptr += len; | ||
2299 | header_ptr[0] = '\r'; | ||
2300 | header_ptr[1] = '\n'; | ||
2301 | header_ptr += 2; | ||
2302 | } | ||
2303 | } | 2341 | } |
2304 | #endif | 2342 | #endif |
2305 | 2343 | ||
@@ -2321,30 +2359,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2321 | if (errno || length > INT_MAX) | 2359 | if (errno || length > INT_MAX) |
2322 | send_headers_and_exit(HTTP_BAD_REQUEST); | 2360 | send_headers_and_exit(HTTP_BAD_REQUEST); |
2323 | } | 2361 | } |
2324 | } | 2362 | continue; |
2325 | #endif | ||
2326 | #if ENABLE_FEATURE_HTTPD_CGI | ||
2327 | else if (STRNCASECMP(iobuf, "Cookie:") == 0) { | ||
2328 | if (!cookie) /* in case they send millions of these, do not OOM */ | ||
2329 | cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); | ||
2330 | } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { | ||
2331 | if (!content_type) | ||
2332 | content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); | ||
2333 | } else if (STRNCASECMP(iobuf, "Referer:") == 0) { | ||
2334 | if (!G.referer) | ||
2335 | G.referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); | ||
2336 | } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) { | ||
2337 | if (!G.user_agent) | ||
2338 | G.user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); | ||
2339 | } else if (STRNCASECMP(iobuf, "Host:") == 0) { | ||
2340 | if (!G.host) | ||
2341 | G.host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1)); | ||
2342 | } else if (STRNCASECMP(iobuf, "Accept:") == 0) { | ||
2343 | if (!G.http_accept) | ||
2344 | G.http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1)); | ||
2345 | } else if (STRNCASECMP(iobuf, "Accept-Language:") == 0) { | ||
2346 | if (!G.http_accept_language) | ||
2347 | G.http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1)); | ||
2348 | } | 2363 | } |
2349 | #endif | 2364 | #endif |
2350 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 2365 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
@@ -2360,6 +2375,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2360 | /* decodeBase64() skips whitespace itself */ | 2375 | /* decodeBase64() skips whitespace itself */ |
2361 | decodeBase64(tptr); | 2376 | decodeBase64(tptr); |
2362 | authorized = check_user_passwd(urlcopy, tptr); | 2377 | authorized = check_user_passwd(urlcopy, tptr); |
2378 | continue; | ||
2363 | } | 2379 | } |
2364 | #endif | 2380 | #endif |
2365 | #if ENABLE_FEATURE_HTTPD_RANGES | 2381 | #if ENABLE_FEATURE_HTTPD_RANGES |
@@ -2377,6 +2393,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2377 | range_start = -1; | 2393 | range_start = -1; |
2378 | } | 2394 | } |
2379 | } | 2395 | } |
2396 | continue; | ||
2380 | } | 2397 | } |
2381 | #endif | 2398 | #endif |
2382 | #if ENABLE_FEATURE_HTTPD_GZIP | 2399 | #if ENABLE_FEATURE_HTTPD_GZIP |
@@ -2394,6 +2411,35 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2394 | content_gzip = 1; | 2411 | content_gzip = 1; |
2395 | //} | 2412 | //} |
2396 | } | 2413 | } |
2414 | continue; | ||
2415 | } | ||
2416 | #endif | ||
2417 | #if ENABLE_FEATURE_HTTPD_CGI | ||
2418 | if (cgi_type != CGI_NONE) { | ||
2419 | bool ct = (STRNCASECMP(iobuf, "Content-Type:") == 0); | ||
2420 | char *cp; | ||
2421 | char *colon = strchr(iobuf, ':'); | ||
2422 | |||
2423 | if (!colon) | ||
2424 | continue; | ||
2425 | cp = iobuf; | ||
2426 | while (cp < colon) { | ||
2427 | /* a-z => A-Z, not-alnum => _ */ | ||
2428 | char c = (*cp & ~0x20); /* toupper for A-Za-z, undef for others */ | ||
2429 | if ((unsigned)(c - 'A') <= ('Z' - 'A')) { | ||
2430 | *cp++ = c; | ||
2431 | continue; | ||
2432 | } | ||
2433 | if (!isdigit(*cp)) | ||
2434 | *cp = '_'; | ||
2435 | cp++; | ||
2436 | } | ||
2437 | /* "Content-Type:" gets no HTTP_ prefix, all others do */ | ||
2438 | cp = xasprintf(ct ? "HTTP_%.*s=%s" + 5 : "HTTP_%.*s=%s", | ||
2439 | (int)(colon - iobuf), iobuf, | ||
2440 | skip_whitespace(colon + 1) | ||
2441 | ); | ||
2442 | putenv(cp); | ||
2397 | } | 2443 | } |
2398 | #endif | 2444 | #endif |
2399 | } /* while extra header reading */ | 2445 | } /* while extra header reading */ |
@@ -2452,51 +2498,20 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2452 | tptr = urlcopy + 1; /* skip first '/' */ | 2498 | tptr = urlcopy + 1; /* skip first '/' */ |
2453 | 2499 | ||
2454 | #if ENABLE_FEATURE_HTTPD_CGI | 2500 | #if ENABLE_FEATURE_HTTPD_CGI |
2455 | if (is_prefixed_with(tptr, "cgi-bin/")) { | 2501 | if (cgi_type != CGI_NONE) { |
2456 | if (tptr[8] == '\0') { | 2502 | send_cgi_and_exit( |
2457 | /* protect listing "cgi-bin/" */ | 2503 | (cgi_type == CGI_INDEX) ? "/cgi-bin/index.cgi" |
2458 | send_headers_and_exit(HTTP_FORBIDDEN); | 2504 | /*CGI_NORMAL or CGI_INTERPRETER*/ : urlcopy, |
2459 | } | 2505 | urlcopy, prequest, length |
2460 | send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type); | 2506 | ); |
2461 | } | 2507 | } |
2462 | #endif | 2508 | #endif |
2463 | 2509 | ||
2464 | if (urlp[-1] == '/') { | 2510 | if (urlp[-1] == '/') { |
2465 | /* When index_page string is appended to <dir>/ URL, it overwrites | ||
2466 | * the query string. If we fall back to call /cgi-bin/index.cgi, | ||
2467 | * query string would be lost and not available to the CGI. | ||
2468 | * Work around it by making a deep copy. | ||
2469 | */ | ||
2470 | if (ENABLE_FEATURE_HTTPD_CGI) | ||
2471 | g_query = xstrdup(g_query); /* ok for NULL too */ | ||
2472 | strcpy(urlp, index_page); | 2511 | strcpy(urlp, index_page); |
2473 | } | 2512 | } |
2474 | if (stat(tptr, &sb) == 0) { | ||
2475 | #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR | ||
2476 | char *suffix = strrchr(tptr, '.'); | ||
2477 | if (suffix) { | ||
2478 | Htaccess *cur; | ||
2479 | for (cur = script_i; cur; cur = cur->next) { | ||
2480 | if (strcmp(cur->before_colon + 1, suffix) == 0) { | ||
2481 | send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type); | ||
2482 | } | ||
2483 | } | ||
2484 | } | ||
2485 | #endif | ||
2486 | file_size = sb.st_size; | ||
2487 | last_mod = sb.st_mtime; | ||
2488 | } | ||
2489 | #if ENABLE_FEATURE_HTTPD_CGI | ||
2490 | else if (urlp[-1] == '/') { | ||
2491 | /* It's a dir URL and there is no index.html | ||
2492 | * Try cgi-bin/index.cgi */ | ||
2493 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { | ||
2494 | urlp[0] = '\0'; /* remove index_page */ | ||
2495 | send_cgi_and_exit("/cgi-bin/index.cgi", urlcopy, prequest, length, cookie, content_type); | ||
2496 | } | ||
2497 | } | ||
2498 | /* else fall through to send_file, it errors out if open fails: */ | ||
2499 | 2513 | ||
2514 | #if ENABLE_FEATURE_HTTPD_CGI | ||
2500 | if (prequest != request_GET && prequest != request_HEAD) { | 2515 | if (prequest != request_GET && prequest != request_HEAD) { |
2501 | /* POST for files does not make sense */ | 2516 | /* POST for files does not make sense */ |
2502 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | 2517 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); |