X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fhttpd.c;h=6dbc219e746e6ec5545a1d787d7c4964729dca4e;hb=765b0eed3ef29a80115708c3249d3a541509cd24;hp=5cd98a5738031e31d38ab009e754fc25e1bab3f5;hpb=62851171db373fc24784357dc986c28058b68edf;p=oweals%2Fbusybox.git diff --git a/networking/httpd.c b/networking/httpd.c index 5cd98a573..6dbc219e7 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -20,14 +20,14 @@ * httpd -p 80 -u 80 -h /www -c /etc/httpd.conf -r "Web Server Authentication" * * - * When a url starts by "/cgi-bin/" it is assumed to be a cgi script. The + * When an url starts by "/cgi-bin/" it is assumed to be a cgi script. The * server changes directory to the location of the script and executes it * after setting QUERY_STRING and other environment variables. * * Doc: * "CGI Environment Variables": http://hoohoo.ncsa.uiuc.edu/cgi/env.html * - * The applet can also be invoked as a url arg decoder and html text encoder + * The applet can also be invoked as an url arg decoder and html text encoder * as follows: * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World" * bar=`httpd -e ""` # encode as "<Hello World>" @@ -231,6 +231,8 @@ static const struct { #endif }; +static const char index_html[] ALIGN1 = "index.html"; + struct globals { int verbose; /* must be int (used by getopt32) */ @@ -328,7 +330,7 @@ enum { SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \ bind_addr_or_port = "80"; \ - index_page = "index.html"; \ + index_page = index_html; \ file_size = -1; \ } while (0) @@ -569,6 +571,8 @@ static void parse_conf(const char *path, int flag) ch = (buf[0] & ~0x20); /* toupper if it's a letter */ if (ch == 'I') { + if (index_page != index_html) + free((char*)index_page); index_page = xstrdup(after_colon); continue; } @@ -718,7 +722,7 @@ static void parse_conf(const char *path, int flag) /* form "/path/file" */ sprintf(cur->before_colon, "/%s%.*s", path, - after_colon - buf - 1, /* includes "/", but not ":" */ + (int) (after_colon - buf - 1), /* includes "/", but not ":" */ buf); /* canonicalize it */ p = bb_simplify_abs_path_inplace(cur->before_colon); @@ -1017,7 +1021,7 @@ static void send_headers(int responseNum) strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod)); #if ENABLE_FEATURE_HTTPD_RANGES if (responseNum == HTTP_PARTIAL_CONTENT) { - len += sprintf(iobuf + len, "Content-Range: bytes %"OFF_FMT"d-%"OFF_FMT"d/%"OFF_FMT"d\r\n", + len += sprintf(iobuf + len, "Content-Range: bytes %"OFF_FMT"u-%"OFF_FMT"u/%"OFF_FMT"u\r\n", range_start, range_end, file_size); @@ -1028,7 +1032,7 @@ static void send_headers(int responseNum) #if ENABLE_FEATURE_HTTPD_RANGES "Accept-Ranges: bytes\r\n" #endif - "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n", + "Last-Modified: %s\r\n%s %"OFF_FMT"u\r\n", tmp_str, "Content-length:", file_size @@ -1141,13 +1145,14 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post /* post_len <= 0 && hdr_cnt <= 0: * no more POST data to CGI, * let CGI see EOF on CGI's stdin */ - close(toCgi_wr); + if (toCgi_wr != fromCgi_rd) + close(toCgi_wr); toCgi_wr = 0; } } /* Now wait on the set of sockets */ - count = safe_poll(pfd, 3, -1); + count = safe_poll(pfd, toCgi_wr ? TO_CGI+1 : FROM_CGI+1, -1); if (count <= 0) { #if 0 if (safe_waitpid(pid, &status, WNOHANG) <= 0) { @@ -1321,10 +1326,8 @@ static void send_cgi_and_exit( /* Check for [dirs/]script.cgi/PATH_INFO */ script = (char*)url; while ((script = strchr(script + 1, '/')) != NULL) { - struct stat sb; - *script = '\0'; - if (!is_directory(url + 1, 1, &sb)) { + if (!is_directory(url + 1, 1, NULL)) { /* not directory, found script.cgi/PATH_INFO */ *script = '/'; break; @@ -1430,7 +1433,7 @@ static void send_cgi_and_exit( if (script != url) { /* paranoia */ *script = '\0'; if (chdir(url + 1) != 0) { - bb_perror_msg("chdir %s", url + 1); + bb_perror_msg("chdir(%s)", url + 1); goto error_execing_cgi; } // not needed: *script = '/'; @@ -1500,32 +1503,8 @@ static void send_cgi_and_exit( */ static NOINLINE void send_file_and_exit(const char *url, int what) { - static const char *const suffixTable[] = { - /* Warning: shorter equivalent suffix in one line must be first */ - ".htm.html", "text/html", - ".jpg.jpeg", "image/jpeg", - ".gif", "image/gif", - ".png", "image/png", - ".txt.h.c.cc.cpp", "text/plain", - ".css", "text/css", - ".wav", "audio/wav", - ".avi", "video/x-msvideo", - ".qt.mov", "video/quicktime", - ".mpe.mpeg", "video/mpeg", - ".mid.midi", "audio/midi", - ".mp3", "audio/mpeg", -#if 0 /* unpopular */ - ".au", "audio/basic", - ".pac", "application/x-ns-proxy-autoconfig", - ".vrml.wrl", "model/vrml", -#endif - NULL - }; - char *suffix; int fd; - const char *const *table; - const char *try_suffix; ssize_t count; fd = open(url, O_RDONLY); @@ -1543,22 +1522,61 @@ static NOINLINE void send_file_and_exit(const char *url, int what) * (happens if you abort downloads from local httpd): */ signal(SIGPIPE, SIG_IGN); - suffix = strrchr(url, '.'); - - /* If not found, set default as "application/octet-stream"; */ + /* If not found, default is "application/octet-stream" */ found_mime_type = "application/octet-stream"; + suffix = strrchr(url, '.'); if (suffix) { + static const char suffixTable[] ALIGN1 = + /* Shorter suffix must be first: + * ".html.htm" will fail for ".htm" + */ + ".txt.h.c.cc.cpp\0" "text/plain\0" + /* .htm line must be after .h line */ + ".htm.html\0" "text/html\0" + ".jpg.jpeg\0" "image/jpeg\0" + ".gif\0" "image/gif\0" + ".png\0" "image/png\0" + /* .css line must be after .c line */ + ".css\0" "text/css\0" + ".wav\0" "audio/wav\0" + ".avi\0" "video/x-msvideo\0" + ".qt.mov\0" "video/quicktime\0" + ".mpe.mpeg\0" "video/mpeg\0" + ".mid.midi\0" "audio/midi\0" + ".mp3\0" "audio/mpeg\0" +#if 0 /* unpopular */ + ".au\0" "audio/basic\0" + ".pac\0" "application/x-ns-proxy-autoconfig\0" + ".vrml.wrl\0" "model/vrml\0" +#endif + /* compiler adds another "\0" here */ + ; Htaccess *cur; - for (table = suffixTable; *table; table += 2) { - try_suffix = strstr(table[0], suffix); - if (try_suffix) { - try_suffix += strlen(suffix); - if (*try_suffix == '\0' || *try_suffix == '.') { - found_mime_type = table[1]; - break; - } + + /* Examine built-in table */ + const char *table = suffixTable; + const char *table_next; + for (; *table; table = table_next) { + const char *try_suffix; + const char *mime_type; + mime_type = table + strlen(table) + 1; + table_next = mime_type + strlen(mime_type) + 1; + try_suffix = strstr(table, suffix); + if (!try_suffix) + continue; + try_suffix += strlen(suffix); + if (*try_suffix == '\0' || *try_suffix == '.') { + found_mime_type = mime_type; + break; } + /* Example: strstr(table, ".av") != NULL, but it + * does not match ".avi" after all and we end up here. + * The table is arranged so that in this case we know + * that it can't match anything in the following lines, + * and we stop the search: */ + break; } + /* ...then user's table */ for (cur = mime_a; cur; cur = cur->next) { if (strcmp(cur->before_colon, suffix) == 0) { found_mime_type = cur->after_colon; @@ -1915,7 +1933,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) /* If URL is a directory, add '/' */ if (urlp[-1] != '/') { - if (is_directory(urlcopy + 1, 1, &sb)) { + if (is_directory(urlcopy + 1, 1, NULL)) { found_moved_temporarily = urlcopy; } } @@ -1929,7 +1947,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) while (ip_allowed && (tptr = strchr(tptr + 1, '/')) != NULL) { /* have path1/path2 */ *tptr = '\0'; - if (is_directory(urlcopy + 1, 1, &sb)) { + if (is_directory(urlcopy + 1, 1, NULL)) { /* may have subdir config */ parse_conf(urlcopy + 1, SUBDIR_PARSE); ip_allowed = checkPermIP(); @@ -2086,8 +2104,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) header_ptr += 2; write(proxy_fd, header_buf, header_ptr - header_buf); free(header_buf); /* on the order of 8k, free it */ - /* cgi_io_loop_and_exit needs to have two distinct fds */ - cgi_io_loop_and_exit(proxy_fd, dup(proxy_fd), length); + cgi_io_loop_and_exit(proxy_fd, proxy_fd, length); } #endif @@ -2101,8 +2118,12 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) } send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type); } +#endif + + if (urlp[-1] == '/') + strcpy(urlp, index_page); + if (stat(tptr, &sb) == 0) { #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR - { char *suffix = strrchr(tptr, '.'); if (suffix) { Htaccess *cur; @@ -2112,16 +2133,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) } } } - } #endif - if (prequest != request_GET && prequest != request_HEAD) { - send_headers_and_exit(HTTP_NOT_IMPLEMENTED); - } -#endif /* FEATURE_HTTPD_CGI */ - - if (urlp[-1] == '/') - strcpy(urlp, index_page); - if (stat(tptr, &sb) == 0) { file_size = sb.st_size; last_mod = sb.st_mtime; } @@ -2135,19 +2147,18 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type); } } -#endif - /* else { - * fall through to send_file, it errors out if open fails - * } - */ + /* else fall through to send_file, it errors out if open fails: */ + if (prequest != request_GET && prequest != request_HEAD) { + /* POST for files does not make sense */ + send_headers_and_exit(HTTP_NOT_IMPLEMENTED); + } send_file_and_exit(tptr, -#if ENABLE_FEATURE_HTTPD_CGI (prequest != request_HEAD ? SEND_HEADERS_AND_BODY : SEND_HEADERS) + ); #else - SEND_HEADERS_AND_BODY + send_file_and_exit(tptr, SEND_HEADERS_AND_BODY); #endif - ); } /* @@ -2336,7 +2347,12 @@ int httpd_main(int argc UNUSED_PARAM, char **argv) #endif #if ENABLE_FEATURE_HTTPD_AUTH_MD5 if (opt & OPT_MD5) { - puts(pw_encrypt(pass, "$1$", 1)); + char salt[sizeof("$1$XXXXXXXX")]; + salt[0] = '$'; + salt[1] = '1'; + salt[2] = '$'; + crypt_make_salt(salt + 3, 4, 0); + puts(pw_encrypt(pass, salt, 1)); return 0; } #endif