diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-21 00:12:09 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-21 00:12:09 +0000 |
commit | 5d148e2646874a6f460402f2dd70ea2fb6be08dd (patch) | |
tree | fae60c2d7ca0d917f73f6a87554657c09a0ddb7b /networking | |
parent | fcdb00f7359488d197ac3361dfbc49ccdead8b87 (diff) | |
download | busybox-w32-5d148e2646874a6f460402f2dd70ea2fb6be08dd.tar.gz busybox-w32-5d148e2646874a6f460402f2dd70ea2fb6be08dd.tar.bz2 busybox-w32-5d148e2646874a6f460402f2dd70ea2fb6be08dd.zip |
httpd: fix cgi-bin/index.cgi support, add example of it,
stat: fix end-of-line if format is specified (wasn't printing it),
fix %z (time) format to match coreutils 6.3
Diffstat (limited to 'networking')
-rw-r--r-- | networking/httpd.c | 27 | ||||
-rw-r--r-- | networking/httpd_index_cgi_example | 55 |
2 files changed, 74 insertions, 8 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 47d41a1e2..08b40e014 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -1103,7 +1103,7 @@ static int sendCgi(const char *url, | |||
1103 | 1103 | ||
1104 | post_readed_size = 0; | 1104 | post_readed_size = 0; |
1105 | post_readed_idx = 0; | 1105 | post_readed_idx = 0; |
1106 | inFd = fromCgi[0]; | 1106 | inFd = fromCgi[0]; |
1107 | outFd = toCgi[1]; | 1107 | outFd = toCgi[1]; |
1108 | close(fromCgi[1]); | 1108 | close(fromCgi[1]); |
1109 | close(toCgi[0]); | 1109 | close(toCgi[0]); |
@@ -1190,6 +1190,10 @@ static int sendCgi(const char *url, | |||
1190 | if (strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) { | 1190 | if (strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) { |
1191 | full_write(s, "HTTP/1.0 200 OK\r\n", 17); | 1191 | full_write(s, "HTTP/1.0 200 OK\r\n", 17); |
1192 | } | 1192 | } |
1193 | /* Sometimes CGI is writing to pipe in small chunks | ||
1194 | * and we don't see Content-type (because the read | ||
1195 | * is too short) and we emit bogus "text/plain"! | ||
1196 | * Is it a bug or CGI *has to* write it in one piece? */ | ||
1193 | if (strstr(rbuf, "ontent-") == 0) { | 1197 | if (strstr(rbuf, "ontent-") == 0) { |
1194 | full_write(s, "Content-type: text/plain\r\n\r\n", 28); | 1198 | full_write(s, "Content-type: text/plain\r\n\r\n", 28); |
1195 | } | 1199 | } |
@@ -1480,6 +1484,7 @@ static void handleIncoming(void) | |||
1480 | strcpy(url, buf); | 1484 | strcpy(url, buf); |
1481 | /* extract url args if present */ | 1485 | /* extract url args if present */ |
1482 | test = strchr(url, '?'); | 1486 | test = strchr(url, '?'); |
1487 | config->query = NULL; | ||
1483 | if (test) { | 1488 | if (test) { |
1484 | *test++ = '\0'; | 1489 | *test++ = '\0'; |
1485 | config->query = test; | 1490 | config->query = test; |
@@ -1640,20 +1645,26 @@ static void handleIncoming(void) | |||
1640 | sendHeaders(HTTP_NOT_IMPLEMENTED); | 1645 | sendHeaders(HTTP_NOT_IMPLEMENTED); |
1641 | break; | 1646 | break; |
1642 | } | 1647 | } |
1643 | if (purl[-1] == '/') { | ||
1644 | if (access("cgi-bin/index.cgi", X_OK) == 0) { | ||
1645 | config->query = url; | ||
1646 | sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type); | ||
1647 | break; | ||
1648 | } | ||
1649 | } | ||
1650 | #endif /* FEATURE_HTTPD_CGI */ | 1648 | #endif /* FEATURE_HTTPD_CGI */ |
1651 | if (purl[-1] == '/') | 1649 | if (purl[-1] == '/') |
1652 | strcpy(purl, "index.html"); | 1650 | strcpy(purl, "index.html"); |
1653 | if (stat(test, &sb) == 0) { | 1651 | if (stat(test, &sb) == 0) { |
1652 | /* It's a dir URL and there is index.html */ | ||
1654 | config->ContentLength = sb.st_size; | 1653 | config->ContentLength = sb.st_size; |
1655 | config->last_mod = sb.st_mtime; | 1654 | config->last_mod = sb.st_mtime; |
1656 | } | 1655 | } |
1656 | #if ENABLE_FEATURE_HTTPD_CGI | ||
1657 | else if (purl[-1] == '/') { | ||
1658 | /* It's a dir URL and there is no index.html | ||
1659 | * Try cgi-bin/index.cgi */ | ||
1660 | if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { | ||
1661 | purl[0] = '\0'; | ||
1662 | config->query = url; | ||
1663 | sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type); | ||
1664 | break; | ||
1665 | } | ||
1666 | } | ||
1667 | #endif /* FEATURE_HTTPD_CGI */ | ||
1657 | sendFile(test); | 1668 | sendFile(test); |
1658 | config->ContentLength = -1; | 1669 | config->ContentLength = -1; |
1659 | } while (0); | 1670 | } while (0); |
diff --git a/networking/httpd_index_cgi_example b/networking/httpd_index_cgi_example new file mode 100644 index 000000000..31e768c70 --- /dev/null +++ b/networking/httpd_index_cgi_example | |||
@@ -0,0 +1,55 @@ | |||
1 | #!/bin/sh | ||
2 | # This CGI creates directory index. | ||
3 | # Put it into cgi-bin/index.cgi and chmod 0755. | ||
4 | # | ||
5 | # Problems: | ||
6 | # * Unsafe wrt weird filenames with <>"'& etc... | ||
7 | # * Not efficient: calls stat (program, not syscall) for each file | ||
8 | # * Probably requires bash | ||
9 | # | ||
10 | # If you want speed and safety, you need to code it in C | ||
11 | |||
12 | # Must start with '/' | ||
13 | test "${QUERY_STRING:0:1}" = "/" || exit 1 | ||
14 | # /../ is not allowed | ||
15 | test "${QUERY_STRING%/../*}" = "$QUERY_STRING" || exit 1 | ||
16 | test "${QUERY_STRING%/..}" = "$QUERY_STRING" || exit 1 | ||
17 | |||
18 | # Outta cgi-bin... | ||
19 | cd .. 2>/dev/null || exit 1 | ||
20 | # Strip leading '/', go to target dir | ||
21 | cd "${QUERY_STRING:1}" 2>/dev/null || exit 1 | ||
22 | |||
23 | f=`dirname "$QUERY_STRING"` | ||
24 | test "$f" = "/" && f="" | ||
25 | |||
26 | # Pipe thru dd (need to write header as single write(), | ||
27 | # or else httpd doesn't see "Content-type: text/html" | ||
28 | # in first read() and decides that it is not html) | ||
29 | { | ||
30 | printf "%s" \ | ||
31 | $'HTTP/1.0 200 OK\r\n'\ | ||
32 | $'Content-type: text/html\r\n\r\n'\ | ||
33 | "<html><head><title>Index of $QUERY_STRING</title></head>"$'\r\n'\ | ||
34 | "<body><h1>Index of $QUERY_STRING</h1><pre>"$'\r\n'\ | ||
35 | $'<table width=100%>\r\n'\ | ||
36 | $'<col><col><col width=0*>\r\n'\ | ||
37 | $'<tr><th>Name<th align=right>Last modified<th align=right>Size\r\n'\ | ||
38 | \ | ||
39 | "<tr><td><a href='$f/'>..</a><td><td>"$'\r\n' | ||
40 | |||
41 | IFS='#' | ||
42 | for f in *; do | ||
43 | # Guard against empty dirs... | ||
44 | test -e "$f" && \ | ||
45 | stat -c "%F#%s#%z" "$f" | { | ||
46 | read type size cdt junk | ||
47 | dir='' | ||
48 | test "$type" = "directory" && dir='/' | ||
49 | cdt="${cdt//.*}" # no fractional seconds | ||
50 | cdt="${cdt// / }" # prevent wrapping around space | ||
51 | printf "%s" "<tr><td><a href='$f$dir'>$f</a><td align=right>$cdt<td align=right>$size"$'\r\n' | ||
52 | } | ||
53 | done | ||
54 | printf "</table></pre><hr></body></html>"$'\r\n' | ||
55 | } | dd bs=4k | ||