summaryrefslogtreecommitdiffhomepage
path: root/networking
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-11-21 00:12:09 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-11-21 00:12:09 +0000
commit5d148e2646874a6f460402f2dd70ea2fb6be08dd (patch)
treefae60c2d7ca0d917f73f6a87554657c09a0ddb7b /networking
parentfcdb00f7359488d197ac3361dfbc49ccdead8b87 (diff)
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.c27
-rw-r--r--networking/httpd_index_cgi_example55
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,
post_readed_size = 0;
post_readed_idx = 0;
- inFd = fromCgi[0];
+ inFd = fromCgi[0];
outFd = toCgi[1];
close(fromCgi[1]);
close(toCgi[0]);
@@ -1190,6 +1190,10 @@ static int sendCgi(const char *url,
if (strncmp(rbuf, "HTTP/1.0 200 OK\r\n", 4) != 0) {
full_write(s, "HTTP/1.0 200 OK\r\n", 17);
}
+ /* Sometimes CGI is writing to pipe in small chunks
+ * and we don't see Content-type (because the read
+ * is too short) and we emit bogus "text/plain"!
+ * Is it a bug or CGI *has to* write it in one piece? */
if (strstr(rbuf, "ontent-") == 0) {
full_write(s, "Content-type: text/plain\r\n\r\n", 28);
}
@@ -1480,6 +1484,7 @@ static void handleIncoming(void)
strcpy(url, buf);
/* extract url args if present */
test = strchr(url, '?');
+ config->query = NULL;
if (test) {
*test++ = '\0';
config->query = test;
@@ -1640,20 +1645,26 @@ static void handleIncoming(void)
sendHeaders(HTTP_NOT_IMPLEMENTED);
break;
}
- if (purl[-1] == '/') {
- if (access("cgi-bin/index.cgi", X_OK) == 0) {
- config->query = url;
- sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
- break;
- }
- }
#endif /* FEATURE_HTTPD_CGI */
if (purl[-1] == '/')
strcpy(purl, "index.html");
if (stat(test, &sb) == 0) {
+ /* It's a dir URL and there is index.html */
config->ContentLength = sb.st_size;
config->last_mod = sb.st_mtime;
}
+#if ENABLE_FEATURE_HTTPD_CGI
+ else if (purl[-1] == '/') {
+ /* It's a dir URL and there is no index.html
+ * Try cgi-bin/index.cgi */
+ if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
+ purl[0] = '\0';
+ config->query = url;
+ sendCgi("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
+ break;
+ }
+ }
+#endif /* FEATURE_HTTPD_CGI */
sendFile(test);
config->ContentLength = -1;
} 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 @@
+#!/bin/sh
+# This CGI creates directory index.
+# Put it into cgi-bin/index.cgi and chmod 0755.
+#
+# Problems:
+# * Unsafe wrt weird filenames with <>"'& etc...
+# * Not efficient: calls stat (program, not syscall) for each file
+# * Probably requires bash
+#
+# If you want speed and safety, you need to code it in C
+
+# Must start with '/'
+test "${QUERY_STRING:0:1}" = "/" || exit 1
+# /../ is not allowed
+test "${QUERY_STRING%/../*}" = "$QUERY_STRING" || exit 1
+test "${QUERY_STRING%/..}" = "$QUERY_STRING" || exit 1
+
+# Outta cgi-bin...
+cd .. 2>/dev/null || exit 1
+# Strip leading '/', go to target dir
+cd "${QUERY_STRING:1}" 2>/dev/null || exit 1
+
+f=`dirname "$QUERY_STRING"`
+test "$f" = "/" && f=""
+
+# Pipe thru dd (need to write header as single write(),
+# or else httpd doesn't see "Content-type: text/html"
+# in first read() and decides that it is not html)
+{
+printf "%s" \
+$'HTTP/1.0 200 OK\r\n'\
+$'Content-type: text/html\r\n\r\n'\
+"<html><head><title>Index of $QUERY_STRING</title></head>"$'\r\n'\
+"<body><h1>Index of $QUERY_STRING</h1><pre>"$'\r\n'\
+$'<table width=100%>\r\n'\
+$'<col><col><col width=0*>\r\n'\
+$'<tr><th>Name<th align=right>Last modified<th align=right>Size\r\n'\
+\
+"<tr><td><a href='$f/'>..</a><td><td>"$'\r\n'
+
+IFS='#'
+for f in *; do
+ # Guard against empty dirs...
+ test -e "$f" && \
+ stat -c "%F#%s#%z" "$f" | {
+ read type size cdt junk
+ dir=''
+ test "$type" = "directory" && dir='/'
+ cdt="${cdt//.*}" # no fractional seconds
+ cdt="${cdt// /&nbsp;}" # prevent wrapping around space
+ printf "%s" "<tr><td><a href='$f$dir'>$f</a><td align=right>$cdt<td align=right>$size"$'\r\n'
+ }
+done
+printf "</table></pre><hr></body></html>"$'\r\n'
+} | dd bs=4k