X-Git-Url: http://git.nikiroo.be/?p=gofetch.git;a=blobdiff_plain;f=gopher.sh;h=5d7439f82955a160c904379315aebfc34884bed1;hp=d0c9ea5eae3e0d7802d47f6089609f0a67146224;hb=HEAD;hpb=c8b05198d89f026d13a577f57d2dda8cb608a3be diff --git a/gopher.sh b/gopher.sh old mode 100644 new mode 100755 index d0c9ea5..5d7439f --- a/gopher.sh +++ b/gopher.sh @@ -1,47 +1,237 @@ #!/bin/sh -# $0 [prog ($1 will be the query)] ([port]) - -[ "$ADDR" = "" ] && ADDR=127.0.0.1 -[ "$LOG" = "" ] && LOG=/tmp/log.err -[ "$PIDF" = "" ] && PIDF="`mktemp`" -[ "$TIMEOUT" = "" ] && TIMEOUT=10 -[ "$MAXCON" = "" ] && MAXCON=1024 -prog="$1" -port="$2" -[ "$port" = "" ] && port=70 - -if [ "$prog" = "" ]; then - rm "$PIDF" - echo "Syntax: $0 [prog (\$1 will be the query)] ([port])" >&2 +# $0 [gopher uri] ([mode]) +# uri: the gopher URI to dig to, e.g.: +# - gopher://sdf.org:70/1/faq +# - sdf.org/faq +# - sdf.org/1/faq +# - http://gopher.nikiroo.be:80/news +# - ... +# default port is 70 for gopher, 80 for http, 443 for https +# default filetype depends upon selector: +# - 0: plain text +# - 1: menu (dir-like) +# - ... +# - download: fake mode to download the result without changes + +# Manual: +# When asked for a number, you can also enter 'n' or 'p' to get the +# next or previous item (+1 or -1) + +# ENV variables: +# LINK_COLOR: escape sequences colour (def: 2) +# - : means no escape sequence +# 1 : means colour 1 +# 2 : means colour 2 +# [...] +# INVERT : invert the output for image viewing (for white backgrounds) +# 0 : do not invert (default) +# 1 : invert + +# EXIT Codes: +# 0: ok +# 1: syntax error +# 2: cannot contact server +# 3: unknown selector mode +# 255: special exit more 'q' + +URI="$1" + +PREFIX="[0-9hIg+]" + +PROTOCOL="`echo $URI | sed 's|^\([^:]*://\)\?\([^:/]*\)\(:[^/]*\)\?/\?\(.*\)\?|\1|g'`" +SERVER="`echo $URI | sed 's|^\([^:]*://\)\?\([^:/]*\)\(:[^/]*\)\?/\?\(.*\)\?|\2|g'`" +PORT="`echo $URI | sed 's|^\([^:]*://\)\?\([^:/]*\)\(:[^/]*\)\?/\?\(.*\)\?|\3|g'`" +SELECTOR="`echo $URI | sed 's|^\([^:]*://\)\?\([^:/]*\)\(:[^/]*\)\?/\?\(.*\)\?|\4|g'`" +MODE= + +PORT="`echo "$PORT" | sed 's/^://'`" + +# Defaults: +if [ "$PORT" = "" ];then + case "$PROTOCOL" in + http://) PORT=80 ;; + https://) PORT=443;; + *) PORT=70 ;; + esac +fi + +if [ "$MODE" = "" ]; then + # "" or dir-like selector? -> 1 ; if not -> 0 + echo "$SELECTOR" | grep "/$" >/dev/null && MODE=1 || MODE=0 + [ "$SELECTOR" = "" ] && MODE=1 + + # check explicit modes: + if echo "$SELECTOR" | grep "^/\?\($PREFIX\|download\)/" >/dev/null; then + MODE="`echo "$SELECTOR" | sed 's:^/\?\([^/]*\)/\(.*\):\1:'`" + SELECTOR="`echo "$SELECTOR" | sed 's:^/\?\([^/]*\)/\(.*\):\2:'`" + fi +fi + +if [ "$SERVER" = "" ]; then + echo "Syntax error: $0 [gopher uri]" >&2 exit 1 fi -tmpd=`mktemp -t -d .gopher-service.XXXXXX` -if [ ! -d "$tmpd" ]; then - rm "$PIDF" - echo "Cannot create temporary directory, aborting..." >&2 +# can be "-" for no escape sequences +[ "$LINK_COLOR" = "" ] && LINK_COLOR=2 + +# Start and end link tags +SL= +EL= +if [ "$LINK_COLOR" != "-" ]; then + SL="`tput setf $LINK_COLOR``tput setaf $LINK_COLOR`" + EL="`tput init`" + export LESS="${LESS} -R" +fi + +# Invert image viewer +if [ "$INVERT" = 1 ]; then + INVERT="--invert" +else + INVERT= +fi + +# $0 [FILE] +# Display a gopher menu for the given resource +cat_menu() { + i=0 + cat "$1" | grep "^i\|^$PREFIX" | sed 's:\\:\\\\\\\\:g' | while read ln; do + if echo "$ln" | grep "^i" >/dev/null 2>&1; then + echo "$ln" | sed "s:^.\([^\t]*\).*$: \1:g" + elif echo "$ln" | grep "^$PREFIX" >/dev/null 2>&1; then + i=`expr $i + 1` + [ $i -le 9 ] && i=0$i + field="`echo "$ln" | cut -c1`" + case "$field" in + 0) typ='TXT';; + 1) typ='DIR';; # menu, actually + 7) typ='(?)';; # query + 8) typ='TEL';; # TELnet (not TELephone) + h) typ='WEB';; # HTML + I) typ='IMG';; + g) typ='GIF';; + +) typ='SVR';; # redundant server + *) typ='!!!';; + esac + echo "$ln" | sed "s:^.\\([^\t]*\\).*:$typ $i $SL\\1$EL:g" + fi + done +} + +# $0 [FILE] [INDEX] [FIELD] +# Get a field from the given-by-index link in FILE +# +# Fields: +# 1 = type/name +# 2 = selector +# 3 = server +# 4 = port +getsel() { + cat "$1" | grep "^$PREFIX" | tail -n+"$2" | head -n 1 | cut -f"$3" +} + +# Save page content to 'tmp' file +tmp="`mktemp -t gofetch.current_page.XXXXXX`" +finish() { + rm -rf "$tmp" "$tmp.jpg" "$tmp.menu" "$tmp.choice" +} +trap finish EXIT + +ok=true +if [ "$PROTOCOL" = gopher:// -o "$PROTOCOL" = "" ]; then + echo "$SELECTOR" | nc "$SERVER" "$PORT" > "$tmp" || ok=false +else + if wget -h >/dev/null 2>&1; then + wget "${PROTOCOL}$SERVER:$PORT/$SELECTOR" -O "$tmp" >/dev/null 2>&1 + else + curl "${PROTOCOL}$SERVER:$PORT/$SELECTOR" > "$tmp" 2>/dev/null + fi +fi + +if [ $ok = false ]; then + echo Cannot contact gopher uri "[$URI]" >&2 exit 2 fi -touch "$PIDF" -echo "$PIDF" - -i=0 -while [ -e "$PIDF" ]; do - i=`expr $i + 1` - [ $i -gt "$MAXCON" ] && i=1 - fifo="$tmpd/fifo.$i" - rm -f "$fifo" - mkfifo "$fifo" - < "$fifo" nc -l -q0 -w"$TIMEOUT" "$ADDR" -p "$port" | ( - read -r query - query="`echo "$query" | cut -f2 -d' '`" - ( - "$prog" "$query" 2>> "$LOG" - rm "$fifo" - )& - ) > "$fifo" -done -rm -rf "$tmpd" +if [ $MODE = 1 ]; then + sed --in-place 's:\r\n:\n:g;s:\r::g' "$tmp" +fi + +# Process page content +case "$MODE" in +download) + # Special, fake mode, only from top-level + cat "$tmp" +;; +0) + cat "$tmp" | less +;; +1|+) + CHOICE=0 + while [ "$CHOICE" != "" ]; do + cat_menu "$tmp" | less + read -p "[$SELECTOR]: " NEW_CHOICE + if [ "$NEW_CHOICE" = p ]; then + CHOICE=`expr "$CHOICE" - 1 2>/dev/null` + if [ "$CHOICE" -lt 0 ]; then + CHOICE=`cat "$tmp" | grep "^$PREFIX" | wc --lines` + fi + elif [ "$NEW_CHOICE" = n ]; then + CHOICE=`expr "$CHOICE" + 1 2>/dev/null` + else + CHOICE="$NEW_CHOICE" + fi + + [ "$CHOICE" = q ] && exit 255 # force-quit + index="`expr 1 \* "$CHOICE" 2>/dev/null`" + if [ "$index" != "" ]; then + goto_server="`getsel "$tmp" $index 3`" + goto_sel="`getsel "$tmp" $index 2`" + goto_port="`getsel "$tmp" $index 4`" + goto_mode="`getsel "$tmp" $index 1 | cut -c1`" + echo "Digging to [$goto_server:$goto_port] $index [$goto_sel]..." + sh "$0" "$goto_server:$goto_port/$goto_mode/$goto_sel" + [ $? = 255 ] && exit 255 # force-quit + fi + done +;; +7) + read -p "Query: " SEARCH + selQuery="$SELECTOR $SEARCH" + + exec sh "$0" "$SERVER" "$selQuery" "$PORT" 1 +;; +8) + telnet -l "$SELECTOR" "$SERVER" "$PORT" + read DUMMY +;; +9) + echo "" | less +;; +g|I) + if img2aa --help >/dev/null 2>&1; then + img2aa --mode=DITHERING \ + $INVERT \ + --width=74 "$tmp" | less + elif jp2a -h >/dev/null 2>&1; then + if convert -h >/dev/null 2>&1; then + convert "$tmp" "$tmp.jpg" + jp2a --border --chars=" .-+=o8#"\ + $INVERT \ + --width=74 "$tmp.jpg" | less + else + echo "required program not found to view images: convert" \ + | less + fi + else + echo "required program not found to view images:" \ + jp2a or img2aa | less + fi +;; +*) + echo "unknwon selector mode: <$MODE>" | less + exit 3 +;; +esac