tannhauser
A PoC Gemini proxy in Gopherspace
tannhauser/tannhauser.dcgi
Download raw file: tannhauser.dcgi
#!/bin/sh
# A basic gopher-gemini gateway
# Dependencies:
# - nmap: ncat, to make a Gemini request. There should be a way to do this
# with open/libre ssl and ordinary netcat.
# - Geomyidae: A Gopher server. I don't know whether or not its CGI system
# is standard.
print_debug() {
printf "+----------------+-----------------------------------------+\n"
[ -n "$cgisearch" ] && printf "| (1) \$cgisearch : %s\n" "$cgisearch"
[ -n "$cgiargs" ] && printf "| (2) \$cgiargs : %s\n" "$cgiargs"
[ -n "$cgihost" ] && printf "| (3) \$cgihost : %s\n" "$cgihost"
[ -n "$cgiport" ] && printf "| (4) \$cgiport : %s\n" "$cgiport"
printf "+----------------+\n"
[ -n "$url" ] && printf "| \$url : %s\n" "$url"
[ -n "$host" ] && printf "| \$host : %s\n" "$host"
[ -n "$gatepath" ] && printf "| \$gatepath : %s\n" "$gatepath"
printf "+----------------+\n"
[ -n "$status" ] && printf "| \$status : %s\n" "$status"
[ -n "$code" ] && printf "| \$code : %s\n" "$code"
[ -n "$mime" ] && printf "| \$mime : %s\n" "$mime"
printf "+----------------+-----------------------------------------+\n"
}
# Geomyidae CGI command line
cgisearch="$1"
cgiargs="$2"
cgihost="$3"
cgiport="$4"
# Needed to send the request and assemble working links
if [ -n "$cgiargs" ]; then # We're following a link through the proxy
url="gemini://$cgiargs"
host="$(echo "$cgiargs" | cut -d '/' -f1)"
gatepath="$cgiargs"
elif [ -n "$cgisearch" ]; then # Process user input
if [ "$(echo "$cgisearch" | cut -d '/' -f1)" = "gemini:" ]; then
# gemini://host.tld/path
url="$cgisearch"
host="$(echo "$cgisearch" | cut -d '/' -f3)"
gatepath="${cgisearch%%gemini://}"
else
url="gemini://$cgisearch"
host="$(echo "$cgisearch" | cut -d '/' -f1)"
gatepath="$cgisearch"
fi
else
printf "CGI Error: \$cgisearch and \$cgiargs are empty\n"
print_debug
fi
# Make sure there's a trailing slash on naked domains
[ ! "$(echo "$url" | cut -d '/' -f4)" ] && url="$url/"
# ncat doesn't like host:port URIs
host="${host%%:*}"
if [ -n "$url" ] && [ -n "$host" ] ; then
printf "%s\r\n\r\n" "$url" | ncat --ssl "$host" 1965 >/tmp/astrogate || {
printf "Request Error: Failed to reach remote host\n"
print_debug
rm -f /tmp/astrogate
}
status="$(head -1 /tmp/astrogate)"
code="$(echo "$status" | cut -d ' ' -f1)"
mime="$(echo "$status" | cut -d ' ' -f2 | tr -d ';')"
[ -z "$status" ] && {
printf "CGI Error: gemini response (\$status line) is empty\n"
print_debug
rm -f /tmp/astrogate
exit 1
}
print_debug
if [ "$code" = "20" ] ; then # Everything is okay
case "$mime" in
"text/gemini")
sed "s/\t/ /g; 1 d" /tmp/astrogate \
| awk -v path="$gatepath" -v host="$host" -f ./gmi2gph.awk
;;
"text/plain")
sed "s/\t/ /g; 1 d" /tmp/astrogate
;;
*)
# TODO: differentiate between text for display and binary to dl
printf "WARNING: \$mime (%s) is something else\n" "$mime"
sed "s/\t/ /g; 1 d" /tmp/astrogate \
| awk -v path="$gatepath" -v host="$host" -f ./gmi2gph.awk
;;
esac
else
printf "Gemini Error: %s\n" "$status"
print_debug
rm -f /tmp/astrogate
exit 1
fi
rm -f /tmp/astrogate
else
printf "CGI error: \$url and/or \$host are empty\n"
print_debug
exit 1
fi
exit 0