|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# bash-httpd, by Morty Abzug <[email protected]> |
| 4 | +# v0.02: morty: 1998/11/22: does simple file queries |
| 5 | +# v0.01: morty: 1998/11/??: proof of concept |
| 6 | + |
| 7 | +# Configurable variables |
| 8 | +PATH=/bin:/usr/bin |
| 9 | +DOC_ROOT=~morty/www/server |
| 10 | +DEF_HTML=index.html |
| 11 | +DEF_DIR=www |
| 12 | +LOG_FACILITY=local1 |
| 13 | + |
| 14 | +# End of configurables |
| 15 | +HTTP_VERSION="HTTP/1.0" |
| 16 | +SERVER="bash-httpd/0.02" |
| 17 | + |
| 18 | +CR=`printf "\015"` |
| 19 | +program="${0##/*/}" |
| 20 | + |
| 21 | +response_code(){ |
| 22 | + num="$1" |
| 23 | + case "$num" in |
| 24 | + 200) err="OK";; |
| 25 | + 403) err="Forbidden";; |
| 26 | + 404) err="Not Found";; |
| 27 | + 500) err="Internal Server Error";; |
| 28 | + 501) err="Not Implemented";; |
| 29 | + *) err="Internal Server Error" |
| 30 | + log err "Unknown response: $num" |
| 31 | + num=500 |
| 32 | + ;; |
| 33 | + esac |
| 34 | + log notice "response: $num" |
| 35 | + echo "$HTTP_VERSION $num $err" |
| 36 | +} |
| 37 | + |
| 38 | +error(){ |
| 39 | + response_code $1 |
| 40 | + if [ "$2" ]; then problem="$2"; else problem="$err"; fi |
| 41 | +cat <<EOF |
| 42 | +Content-Type: text/html |
| 43 | +
|
| 44 | +<html> <head> <title> $problem </title> |
| 45 | +<body> <h1> $num $problem </h1> $problem </body> </html> |
| 46 | +EOF |
| 47 | + log err "$problem" |
| 48 | + exit 1 |
| 49 | +} |
| 50 | + |
| 51 | +log(){ |
| 52 | + level="$1"; message="$2" |
| 53 | + logger -p $LOG_FACILITY."$level" "$program[$$]: $method $url $version: $message" |
| 54 | +} |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +read method url version |
| 59 | + |
| 60 | +method="${method%$CR}"; |
| 61 | +url="${url%$CR}"; |
| 62 | +version="${version%$CR}"; |
| 63 | + |
| 64 | +case "$version" in |
| 65 | + ""|http/0.9|HTTP/0.9) |
| 66 | + readmore=0;; |
| 67 | + http/1.0|HTTP/1.0|http/1.1|HTTP/1.1) |
| 68 | + readmore=1;; |
| 69 | + *) |
| 70 | + log notice "$method $url $version" |
| 71 | + error 501 "Unknown version";; |
| 72 | +esac |
| 73 | + |
| 74 | +if [ "$readmore" != 0 ]; then |
| 75 | + read foo; while [ "$foo" != "$CR" -a "$foo" != "" ]; do read foo; done |
| 76 | +fi |
| 77 | + |
| 78 | +case "$method" in |
| 79 | + GET|get) |
| 80 | + what=get;; |
| 81 | + HEAD|head) |
| 82 | + what=head;; |
| 83 | + *) |
| 84 | + error 501 "Unimplemented method";; |
| 85 | +esac |
| 86 | + |
| 87 | +case "$url" in |
| 88 | + */../*|*[^/A-Za-z0-9~.-]*) |
| 89 | + error 403 "Illegal attempt to access resource" |
| 90 | + ;; |
| 91 | + /~*) |
| 92 | + user="${url#/~}"; |
| 93 | + user="${user%%/*}"; |
| 94 | + user=`eval echo ~$user`; # we had *better* have cleaned up $url |
| 95 | + rest="${url#/~*/}"; rest="${rest##/~*}"; |
| 96 | + type=file; file="$user/$DEF_DIR/$rest" |
| 97 | + ;; |
| 98 | + ""|/*) |
| 99 | + type=file; file="$DOC_ROOT/$url" |
| 100 | + ;; |
| 101 | + *) |
| 102 | + error 501 "Unknown request type" |
| 103 | + ;; |
| 104 | +esac |
| 105 | + |
| 106 | +case $type in |
| 107 | + file) |
| 108 | + if [ -d "$file" ]; then file="$file/$DEF_HTML"; fi |
| 109 | + if [ ! -e "$file" ]; then error 404; fi |
| 110 | + if [ ! -r "$file" ]; then error 403; fi |
| 111 | + response_code 200 |
| 112 | + if [ "$what" = "head" ]; then echo; exit 0; fi |
| 113 | + case "$file" in |
| 114 | + *.html | *.htm) mime=text/html;; |
| 115 | + *.jpg|*.jpeg) mime=image/jpeg;; |
| 116 | + *.gif) mime=image/gif;; |
| 117 | + *.gz|*.tgz) mime=application/binary;; |
| 118 | + *.txt|*.text) mime=text/plain;; |
| 119 | + *) mime=application/binary;; |
| 120 | + esac |
| 121 | + echo Content-Type: $mime; echo; cat $file |
| 122 | + ;; |
| 123 | + *) |
| 124 | + error 501 "Messed up internal type" |
| 125 | + ;; |
| 126 | +esac |
| 127 | + |
0 commit comments