#! /bin/ksh
#Set your hostname after this variable
fqdn=gopher.zcrayfish.soy
cr=$(printf '\r')
crlf=$(printf '\r\n')
null=$(printf '')
error400 () {
printf "%s\15\12" "HTTP/1.0 400 Bad Request" \
"Content-Type: text/plain; charset=us-ascii" \
"Allow: GET" \
"Date: $date" \
"Server: gopher to http gateway at $fqdn" \
"Connection: close" \
"" \
"HTTP/1.0 400 Bad Request" \
"Request could not be understood - bad syntax" \
"" \
"gopher to http gateway at $fqdn"
exit
}
error404 () {
printf "%s\15\12" "HTTP/1.0 404 Not Found" \
"Content-Type: text/plain; charset=us-ascii" \
"Date: $date" \
"Server: gopher to http gateway at $fqdn" \
"Connection: close" \
"" \
"HTTP/1.0 404 Not Found" \
"'$obj' doesn't exist!" \
"This resource cannot be located." \
"" \
"gopher to http gateway at $fqdn"
}
error501 () {
printf "%s\15\12" "HTTP/1.0 501 Not Implemented" \
"Content-Type: text/plain; charset=us-ascii" \
"Allow: GET" \
"Date: $date" \
"Server: gopher to http gateway at $fqdn" \
"Connection: close" \
"" \
"HTTP/1.0 501 Not Implemented" \
"This error has accoured for one of the following reasons:" \
" *This server only implements the GET method (e.g. your browser sent a HEAD or PUT)" \
" *This server, while acting as a gateway or proxy, does not support CSO queries." \
"" \
"gopher to http gateway at $fqdn"
exit
}
# Gather request
read -t 30 -r cmd obj proto badclient
#Did we time out... If so just exit, HTTP 1.0 does not have a timeout code
test "$?" != "0" && exit
# See if request is a GET, if not, throw it away
test "$cmd" != 'GET' && error501 && exit
# Likewise ignore invalid gets too.
test ! -z "$badclient" && error400 && exit
# If it all looks good, find out what they want
filename="$(printf "%s" "$obj" | sed -e 's/%2c/,/' -e 's/%20/ /')"
# Gather headers, assume headers are done when we see CRLF or weird crap
while /bin/true; do
read -t 300 -r header headervalue
test "$header" = "$cr" && break
test "$header" = "$crlf" && break
test "$header" = "$null" && break
header="$(printf "$header" | sed -e 's/://')"
eval $header=$headervalue
#[ "$header" == $'\r ] && break;
done
#log me up?
echo $cmd $obj $proto $badclient >> /tmp/www3.log
echo $header $headervalue >> /tmp/www3.log
#Get the HTTP command, filename, protocol version . . .
while read -r cmd obj proto badclient
do
# We put the date in the loop in case the client waits before sending another request
date="$(date -u +'%a, %d %b %Y %H:%M:%S GMT')"
case "$cmd" in
GET)
# See if request is a GET, if not, throw it away
test "$cmd" != 'GET' && error501 && exit
# Likewise ignore invalid gets too.
test ! -z "$badclient" && error400 && exit
# If it all looks good, find out what they want
filename="$(printf "%s" "$obj" | sed -e 's/%2c/,/' -e 's/%20/ /')"
#Step4
case "$filename" in
/favicon.ico)
error404
;;
/sitemap*|/robots.txt)
printf "%s\15\12" "HTTP/1.0 200 OK" \
"Date: $date" \
"Server: gopher to http gateway at $fqdn" \
"Connection: close" \
""
lynx -anonymous -source "gopher://$fqdn/0/$filename";
;;
/2*)
error501
;;
/7*httpsearch*)
printf "%s\15\12" "HTTP/1.0 200 OK" \
"Content-Type: text/html; level=1" \
"Date: $date" \
"Server: gopher to http gateway at $fqdn" \
"Connection: close" \
"" \
'<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 1//EN">'
searchytwothousand="$(printf "%s" "$filename" | sed 's/httpsearch=//g')"
lynx -anonymous -dump -source "gopher://$fqdn:70$searchytwothousand" | sed 's/<A HREF="\/\/$fqdn:70/<A HREF="http:\/\/$fqdn:80/g' | sed 's/<A HREF="\/\//<A HREF="gopher:\/\//g'
exit
;;
/7*)
printf "%s\15\12" "HTTP/1.0 200 OK" \
"Content-Type: text/html; charset=us-ascii" \
"Date: $date" \
"Server: gopher to http gateway at $fqdn" \
"Connection: close" \
"" \
'<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">' \
'<title></title>' \
"<form action='$fqdn$filename' method='get'>" \
'<p>This is a searchable gopher index. Enter search keywords:<input type="text" name="httpsearch"></p></form>'
;;
/debug*)
printf "%s\15\12" "HTTP/1.0 200 OK" \
"Content-Type: text/plain" \
""
set
;;
###START OF DUMB / NON-INTELLIGENT GOPHER TYPES###
/[04569IMPdghps]*)
printf "%s\15\12" "HTTP/1.0 200 OK"
case "$filename" in
/0*)
printf "%s\15\12" "Content-Type: text/plain"
;;
/4*)
printf "%s\15\12" "Content-Type: application/mac-binhex40"
;;
/5*)
printf "%s\15\12" "Content-Type: application/octet-stream"
;;
/6*)
printf "%s\15\12" "Content-Type: message/rfc822"
;;
/9*)
printf "%s\15\12" "Content-Type: application/octet-stream"
;;
/I*)
printf "%s\15\12" "Content-Type: image/jpeg"
;;
/M*)
printf "%s\15\12" "Content-Type: message/rfc822"
;;
/P*)
printf "%s\15\12" "Content-Type: application/pdf"
;;
/d*)
printf "%s\15\12" "Content-Type: application/pdf"
;;
/g*)
printf "%s\15\12" "Content-Type: image/gif"
;;
/h*)
printf "%s\15\12" "Content-Type: text/html"
;;
/p*)
printf "%s\15\12" "Content-Type: image/png"
;;
/s*)
printf "%s\15\12" "Content-Type: application/octet-stream"
;;
esac
printf "%s\15\12" "Date: $date" \
"Server: gopher to http gateway at $fqdn" \
"Connection: close" \
""
lynx -anonymous -dump -source "gopher://$fqdn:70$filename"
;;
###END OF DUMB / NON-INTELLIGENT GOPHER TYPES###
*)
printf "%s\15\12" 'HTTP/1.0 200 OK' \
'Content-Type: text/html; level=1' \
"Date: $date" \
"Server: gopher to http gateway at $fqdn" \
'Connection: close' \
'' \
'<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 1//EN">'
lynx -anonymous -dump -source "gopher://$fqdn:70$filename" | \
tidy -in -w 0 -cn --doctype omit --show-errors 0 --show-warnings 0 --tidy-mark 0 --quiet 1 --uppercase-tags 1 --uppercase-attributes 1| \
sed -e 's/<A HREF="\/\/'$fqdn':70/<A HREF="http:\/\/'$fqdn'/g' -e 's/<A HREF="\/\//<A HREF="gopher:\/\//g'
;;
esac
;;
HEAD|POST|PUT|DELETE|TRACE|CONNECT|PATCH)
error501
;;
"$cr" | "$crlf" | "$null" )
exit;
;;
esac
done
exit
Response:
text/plain