diff options
author | stanley lieber <stanley.lieber@gmail.com> | 2013-02-04 16:40:05 -0600 |
---|---|---|
committer | stanley lieber <stanley.lieber@gmail.com> | 2013-02-04 16:40:05 -0600 |
commit | c877493fb00717de1a22860d88efb75ebf14ebec (patch) | |
tree | cb3cb0e47598e2880cdd20367925102856d41a5d /rc/bin/rc-httpd | |
parent | 0b212ed5054cd08bbc14a12936c07bc1ff5890a2 (diff) | |
download | plan9front-c877493fb00717de1a22860d88efb75ebf14ebec.tar.xz |
add rc-httpd
Diffstat (limited to 'rc/bin/rc-httpd')
-rwxr-xr-x | rc/bin/rc-httpd/handlers/cgi | 54 | ||||
-rwxr-xr-x | rc/bin/rc-httpd/handlers/dir-index | 111 | ||||
-rwxr-xr-x | rc/bin/rc-httpd/handlers/error | 38 | ||||
-rwxr-xr-x | rc/bin/rc-httpd/handlers/redirect | 30 | ||||
-rwxr-xr-x | rc/bin/rc-httpd/handlers/serve-static | 30 | ||||
-rwxr-xr-x | rc/bin/rc-httpd/handlers/static-or-cgi | 14 | ||||
-rwxr-xr-x | rc/bin/rc-httpd/handlers/static-or-index | 5 | ||||
-rwxr-xr-x | rc/bin/rc-httpd/rc-httpd | 86 |
8 files changed, 368 insertions, 0 deletions
diff --git a/rc/bin/rc-httpd/handlers/cgi b/rc/bin/rc-httpd/handlers/cgi new file mode 100755 index 000000000..96707630c --- /dev/null +++ b/rc/bin/rc-httpd/handlers/cgi @@ -0,0 +1,54 @@ +#!/bin/rc +fn filter_headers{ + response='HTTP/1.1 200 OK'^$cr + lines='' + done=false + while(~ $done false){ + line=`{read} + head=`{echo $line | awk '{print tolower($1)}'} + if(~ $head status:*){ + tmp=`{echo $line | awk '{$1="" ; print}'} + response='HTTP/1.1 '^$"tmp^$cr + } + if not if(~ $line '') + done=true + if not + lines=$"lines^$"line^$cr^' +' + } + echo $response + echo -n $"lines +} + +fn run_cgi { + path=$cgi_path exec $"cgi_bin $params +} + +cgi_bin=$1 +if(! ~ $cgi_bin /*){ + pwd=`{pwd} + cgi_bin=$"pwd ^ / ^ $cgi_bin +} + +cgi_dir=$*($#*) +if(! test -d $cgi_dir){ + cgi_dir=`{basename -d $cgi_dir} + cgi_dir=$"cgi_dir +} + +if(! test -d $"cgi_dir){ + error 500 + exit +} +if(! test -f $cgi_bin -x $cgi_bin){ + error 500 + exit +} +do_log 200 +builtin cd $"cgi_dir +run_cgi | { + filter_headers + emit_extra_headers + echo $cr + exec cat +} diff --git a/rc/bin/rc-httpd/handlers/dir-index b/rc/bin/rc-httpd/handlers/dir-index new file mode 100755 index 000000000..39452bfd7 --- /dev/null +++ b/rc/bin/rc-httpd/handlers/dir-index @@ -0,0 +1,111 @@ +#!/bin/rc +PATH_INFO=`{echo $PATH_INFO | urlencode -d} +full_path=$"FS_ROOT^$"PATH_INFO +full_path=$"full_path +if(! test -d $full_path){ + error 404 + exit +} +if(! test -r $full_path -x $full_path){ + error 503 + exit +} +do_log 200 +builtin cd $full_path +if(~ $"NOINDEXFILE ^ $"NOINDEX ''){ + ifile=index.htm* + if(! ~ $ifile(1) *'*'){ + PATH_INFO=$ifile(1) + FS_ROOT='' + exec serve-static + } +} +title=`{echo $SITE_TITLE | sed s,%s,^$"PATH_INFO^,} +title=$"title +lso=() +switch($2){ +case size + # ls has no option to sort by size + # could pipe it through sort, I suppose +case date + lso=-t +} +echo 'HTTP/1.1 200 OK'^$cr +emit_extra_headers +echo 'Content-type: text/html'^$cr +echo $cr +echo '<html> +<head> +<title>'^$title^'</title> +<style type="text/css"> + .size { + text-align: right; + padding-right: 4pt; + } + .day { + text-align: right; + padding-right: 3pt; + } + .datetime { + text-align: right; + } + .name { + text-align: right; + padding-left: 3pt; + } +</style> +</head> +<body>' +echo '<h1>'^$title^'</h1>' +if(! ~ $PATH_INFO /) + echo '<a href="../">Parent directory</a>' +echo '<table>' +ls -lQ $lso | awk ' +function urlencode(loc){ + # very minimal encoding, just enough for our static-file purposes + url=loc + gsub("%", "%25", url) # this one first! + gsub("\\$", "%24", url) + gsub("&", "%26", url) + gsub("\\+", "%2B", url) + gsub("\\?", "%3F", url) + gsub(" ", "%20", url) + gsub("\"", "%22", url) + gsub("#", "%23", url) + return url +} +function hrsize(size){ + if(size > 1073741824) return sprintf("%.1fGB", size/1073741824) + if(size > 10485760) return sprintf("%iMB", size/1048576) + if(size > 1048576) return sprintf("%.1fMB", size/1048576) + if(size > 10240) return sprintf("%iKB", size/1024) + if(size > 1024) return sprintf("%.1fKB", size/1024) + return sprintf("%iB", size) +} +/^-/ { + print "<tr>" + print "<td class=\"size\">"hrsize($6)"</td>" + print "<td class=\"month\">"$7"</td>" + print "<td class=\"day\">"$8"</td>" + print "<td class=\"datetime\">"$9"</td>" + $1="" ; $2="" ; $3="" ; $4="" ; $5="" ; $6="" ; $7="" ; $8="" ; $9="" + sub("^ *?", "") + print "<td><a class=\"file name\" href=\""urlencode($0)"\">"$0"</a></td>" + print "</tr>" + $0="" +} +/^d/ { + print "<tr>" + print "<td class=\"size\"> </td>" + print "<td class=\"month\">"$7"</td>" + print "<td class=\"day\">"$8"</td>" + print "<td class=\"datetime\">"$9"</td>" + $1="" ; $2="" ; $3="" ; $4="" ; $5="" ; $6="" ; $7="" ; $8="" ; $9="" + sub("^ *?", "") + print "<td><a class=\"dir name\" href=\""urlencode($0)"/\">"$0"/</a></td>" + print "</tr>" +}' +echo '</table> + +</body> +</html>' diff --git a/rc/bin/rc-httpd/handlers/error b/rc/bin/rc-httpd/handlers/error new file mode 100755 index 000000000..e38d41f01 --- /dev/null +++ b/rc/bin/rc-httpd/handlers/error @@ -0,0 +1,38 @@ +#!/bin/rc +# DO NOT make this script callable directly from the web! +fn do_error{ + echo 'HTTP/1.1 '^$1^$cr + emit_extra_headers + echo 'Content-type: text/html'^$cr + echo $cr + echo '<html> +<head> +<title>'^$1^'</title> +</head> +<body> +<h1>'^$1^'</h1>' + echo $2 + echo '<p><i>rc-httpd at' $SERVER_NAME '</i>' + echo ' + </body> + </html> + ' +} + +fn 404{ + do_error '404 Not Found' \ + 'The requested path '^$"location^' was not found on this server.' +} + +fn 500{ + do_error '500 Internal Server Error' \ + 'The server has encountered an internal misconfiguration and is unable to satisfy your request.' +} + +fn 503{ + do_error '503 Forbidden' \ + 'You do not have permission to access '^$"location^' on this server.' +} + +do_log $1 +$1 diff --git a/rc/bin/rc-httpd/handlers/redirect b/rc/bin/rc-httpd/handlers/redirect new file mode 100755 index 000000000..e223091eb --- /dev/null +++ b/rc/bin/rc-httpd/handlers/redirect @@ -0,0 +1,30 @@ +#!/bin/rc +if(~ $#2 0){ + error 500 + exit +} +switch($1){ +case perm* + do_log 301 + echo 'HTTP/1.1 301 Moved Permanently'^$cr +case temp* + do_log 302 + echo 'HTTP/1.1 302 Moved Temporarily'^$cr +case seeother + do_log 303 + echo 'HTTP/1.1 303 See Other'^$cr +case * + error 500 + exit +} +echo 'Location: ' ^ $2 ^ $cr +emit_extra_headers +echo 'Content-type: text/html'^$cr +echo $cr +echo '<html><body>' +if(~ $#3 0) + echo 'Browser did not accept redirect.' +if not + echo $3 +echo '<a href="'^$"location^'/">Click here</a>' +echo '</body></html>' diff --git a/rc/bin/rc-httpd/handlers/serve-static b/rc/bin/rc-httpd/handlers/serve-static new file mode 100755 index 000000000..3f7544286 --- /dev/null +++ b/rc/bin/rc-httpd/handlers/serve-static @@ -0,0 +1,30 @@ +#!/bin/rc +full_path=`{echo $"FS_ROOT^$"PATH_INFO | urlencode -d} +full_path=$"full_path +if(~ $full_path */) + error 503 +if(test -d $full_path){ + redirect perm $"location^'/' \ + 'URL not quite right, and browser did not accept redirect.' + exit +} +if(! test -e $full_path){ + error 404 + exit +} +if(! test -r $full_path){ + error 503 + exit +} +do_log 200 +type=`{file -m $full_path} +if(~ $type text/*) + max_age=3600 # 1 hour +if not + max_age=604800 # 1 week +echo 'HTTP/1.1 200 OK'^$cr +emit_extra_headers +echo 'Content-type: '^$type^$cr +echo 'Cache-control: max-age='^$max_age^$cr +echo $cr +exec cat $full_path diff --git a/rc/bin/rc-httpd/handlers/static-or-cgi b/rc/bin/rc-httpd/handlers/static-or-cgi new file mode 100755 index 000000000..4d8a2d44a --- /dev/null +++ b/rc/bin/rc-httpd/handlers/static-or-cgi @@ -0,0 +1,14 @@ +#!/bin/rc +cgiargs=$* + +fn error{ + if(~ $1 404) + exec cgi $cgiargs + if not + $rc_httpd_dir/handlers/error $1 +} + +if(~ $location */) + exec cgi $cgiargs +if not + exec serve-static diff --git a/rc/bin/rc-httpd/handlers/static-or-index b/rc/bin/rc-httpd/handlers/static-or-index new file mode 100755 index 000000000..f0904f8a9 --- /dev/null +++ b/rc/bin/rc-httpd/handlers/static-or-index @@ -0,0 +1,5 @@ +#!/bin/rc +if(~ $PATH_INFO */) + exec dir-index $params +if not + exec serve-static diff --git a/rc/bin/rc-httpd/rc-httpd b/rc/bin/rc-httpd/rc-httpd new file mode 100755 index 000000000..e2a64948c --- /dev/null +++ b/rc/bin/rc-httpd/rc-httpd @@ -0,0 +1,86 @@ +#!/bin/rc +rc_httpd_dir=/rc/bin/rc-httpd +path=(/bin $rc_httpd_dir/handlers) +cgi_path=/bin +SERVER_PORT=80 # default for CGI scripts, may be overridden by the Host header +extra_headers='Server: rc-httpd' +cr=
+ +fn do_log{ + echo `{date} :: $SERVER_NAME :: $request :: \ + $HTTP_USER_AGENT :: $1 :: $HTTP_REFERER >[1=2] +} + +fn emit_extra_headers{ + for(header in $extra_headers) + echo $"header^$cr +} + +fn getline{ read | sed 's/'^$"cr^'$//g' } + +fn terminate{ + echo `{date} connection terminated >[1=2] + exit terminate +} + +fn trim_input{ read -c $CONTENT_LENGTH } + +request=`{getline} +if(~ $#request 0) + terminate +REQUEST_METHOD=$request(1) +REQUEST_URI=$request(2) +reqlines='' +HTTP_COOKIE='' +done=false +while(~ $"done false){ + line=`{getline} + if(~ $#line 0) + done=true + reqlines=$"reqlines$"line' +' + h=`{echo $line | awk '{print tolower($1)}'} + switch($h){ + case '' + done=true + case host: + tmp=`{echo $line(2) | sed 's/:/ /'} + SERVER_NAME=$tmp(1) + if(! ~ $#tmp 1) + SERVER_PORT=$tmp(2) + case referer: + HTTP_REFERER=$line(2) + case user-agent: + HTTP_USER_AGENT=`{echo $line | sed 's;[^:]+:[ ]+;;'} + case content-length: + CONTENT_LENGTH=$line(2) + case cookie: + cookie=`{echo $line | sed 's;^[^:]+:[ ]*;;'} + HTTP_COOKIE=$"HTTP_COOKIE^$"cookie^'; ' + } +} +if(~ $REQUEST_URI http://*){ + SERVER_NAME=`{echo $REQUEST_URI | sed ' + s;^http://;; + s;/.*;; + '} + REQUEST_URI=`{echo $REQUEST_URI | sed 's;^http://[^/]+/?;/;'} +} +QUERY_STRING=`{echo $REQUEST_URI | sed 's;[^?]*\??;;'} +params=`{echo $QUERY_STRING | sed 's;\+; ;g'} +location=`{echo $REQUEST_URI | sed 's;\?.*;;'} +location=`{echo $location | sed ' + s;[^/]+/\.\./;/;g + s;/\./;/;g + s;//+;/;g +'} +if(~ $REQUEST_METHOD POST){ + if(! ~ $"CONTENT_LENGTH '') + trim_input | exec $rc_httpd_dir/select-handler + if not{ + echo 'POST without content-length, assuming no keep-alive.' >[1=2] + exec $rc_httpd_dir/select-handler + } +} +if not + . $rc_httpd_dir/select-handler |