#!/bin/sh . /etc/rc.config htdocs=${2-/var/www} port=${3-$WEBSERVER_PORT} case "$1" in start) test -z "${0##/*}" && self=$0 || self=$(pwd)/$0 cd $htdocs tcpsvd -l0 0 $port $SHELL $self show 2>&1 | logger -t tcpsvd >/dev/null 2>&1 & exit $? ;; stop) killall tcpsvd exit $? ;; show) ## run response script ;; *) echo "Use: ${0##*/} [start [HTDOCS_PATH [PORT]] | stop]" exit 1 ;; esac # parse request read request_method uri protocol test -z "${uri##*\?*}" && query=${uri#*\?} query=${query%%#*} test -z "${uri##*#*}" && search=${uri#*#} uri=${uri%%#*} uri=${uri%%\?*} uri=${uri#/} test -z "$uri" && uri="index.sh" type=${uri##*.} uri="$(echo "$uri" | sed "s/%20/ /g")" document_root=$(pwd) level=0 # parse header eval "$(echo $query | sed 's/&$\|&&//g;s/&\?\([^=]\+\)\(=\([^&]*\)\)\?/GET_\1="\3";/g' | urldecode)" while read line; do test "$line" = $'\r' && break eval "$(echo $line | sed 's/\([^:]\+\): \(.*\)./HTTP_\1="\2";/g;s/^\([^=-]*\)-/\1/g;s/^\([^=-]*\)-/\1/g')" header="$header$line" done test -z "${HTTP_Host##*:*}" && HTTP_Port=${HTTP_Host##*:} HTTP_Host=${HTTP_Host%%:*} # parse body if [ "$HTTP_ContentLength" ]; then dd bs=1 count=$HTTP_ContentLength >/tmp/webserver.$$.body 2>/dev/null if [ -z "${HTTP_ContentType##multipart/form-data*}" ]; then # multipart form data state="start" pos=0 while read -r line; do line=${line%$'\r'} if [ $state = "start" ]; then boundary="$line" state="header" elif [ $state = "header" ]; then if [ -z "$line" ]; then pos2=0 state="body" elif [ -z "${line##Content-Disposition: form-data;*}" ]; then eval ${line#*; } name="POST_$name" eval $name="" file="" elif [ -z "${line##Content-Type:*}" ]; then file="/tmp/webserver.$$.$name" echo -n > $file eval ${name}_type='${line#* }' eval ${name}_name='$filename' eval ${name}_file='$file' fi elif [ $state = "body" ]; then if [ "${line%--}" = "$boundary" ]; then if [ -z "$file" ]; then value="$(head -n $pos /tmp/webserver.$$.body | tail -n $pos2)" eval $name=${value%$'\r'} else head -n $pos /tmp/webserver.$$.body | tail -n $pos2 > $file dd if=$file bs=1 count=$(($(ls -l $file | cut -b 33-43)-2)) of=$file.tmp 2>/dev/null mv $file.tmp $file fi state="header" fi pos2=$(($pos2+1)) fi pos=$(($pos+1)) done < /tmp/webserver.$$.body elif [ -z "${HTTP_ContentType##application/x-www-form-urlencoded*}" ]; then # url encoded form data eval "$(sed 's/&$\|&&//g;s/%22/\\%22/g;s/%24/\\%24/g;s/&\?\([^=]\+\)\(=\([^&]*\)\)\?/POST_\1="\3";/g;s/+/ /g' /tmp/webserver.$$.body | urldecode)" fi fi mimetype() { mimetype=$(grep "^${1##*.}" <<- EOF txt text/plain html text/html sh text/html css text/css js text/javascript gif image/gif jpg image/jpg png image/png ico image/x-icon EOF ) echo ${mimetype#* } } header() { file=/tmp/webserver.$$.header if [ -n "$1" -a -e $file ] && grep -q "${1%% *}" $file; then sed "s|${1%% *}.*|$1|" -i $file else echo -e "$1\r" >>$file fi test -z "$1" && { cat $file; rm $file; } } session_start() { sessid="$(echo "$HTTP_Cookie" | sed 's/.*sessid=\([^;]*\).*/\1/')" if [ -e "/tmp/session_$sessid" ]; then . /tmp/session_$sessid else sessid=$(date | md5sum | cut -d " " -f 1) header "Set-Cookie: sessid=$sessid" touch /tmp/session_$sessid fi echo $sessid > /tmp/webserver.$$.session find /tmp -name session_* -amin +30 -exec rm {} \; } session_set() { name=SESSION_$1 value=$2 if [ -s /tmp/webserver.$$.session ]; then file=/tmp/session_$(cat /tmp/webserver.$$.session) if grep -qse "^$name=" $file; then sed -ie "s|^$name=.*|$name=\"$value\"|g" $file else echo "$name=\"$value\"" >> $file fi fi eval "$name=\"$value\"" } session_unset() { name=SESSION_$1 if [ -s /tmp/webserver.$$.session ]; then file=/tmp/session_$(cat /tmp/webserver.$$.session) sed -ie "/^$name=/d" $file 2>/dev/null fi unset $name } out() { awk 'NR > 1 { print h } { h = $0 } END { ORS = ""; print h }' } include() { level=$(($level+1)) { echo -n "?>"; while [ -n "$1" ]; do cat "$1"; shift; done; echo -n "/\nout << EOF\n/g;s//tmp/webserver.$$.$level . /tmp/webserver.$$.$level 2>&1 level=$(($level-1)) } # send response if [ ! -e "$uri" ]; then header "HTTP/1.0 404 File not found" header "Content-Type: text/plain" header echo "File not found: $uri" exit fi header "HTTP/1.0 200 OK" header "Content-Type: $(mimetype $uri)" case "$type" in sh) if [ "$(head -n1 "$uri")" = "#!/bin/sh" ]; then . "$uri" else include "$uri" fi ;; *) date="$(date -r "$uri" +"%Y-%m-%d %H:%M:%S")" if [ ! "$date" \> "$HTTP_IfModifiedSince" ]; then header "HTTP/1.0 304 Not Modefied" exit fi header "Last-Modified: $date" cat "$uri" ;; esac 2>&1 | { read -n1 c; header; echo -n "$c"; cat; } # | tee /tmp/webserver.$$.response rm -f /tmp/webserver.$$.*