#!/bin/sh # Downloads a gopher file or directory to the current directory # Only uses port 70 for now, as I've never seen a gopher server # use anything else. # # If called on a directory, it will download all of the urls that # link to files within the directory or at deeper levels. # # So for example if a directory has a gophermap that links to stuff # on other servers or outside the directory, they will be ignored. # # Warning: this overwrites files without any prompt me=`basename "$0"` if [ "$#" -ne 1 ]; then echo "usage: $me gopher://domain.abc/path/to/file" exit fi pushd () { command pushd "$@" > /dev/null } popd () { command popd "$@" > /dev/null } selfpath="$0" url="$1" url="${url#*//}" # strip protocol domain=$(domain "gopher://$url") path="/${url#*/}" # strip domain echo $path map="$(mktemp)" echo "$path" | nc $domain 70 > "$map" cat "$map" | { # we need these brackets do to everything in the subshell and # retain the value of $quit quit=0 while read line do # this is not a gophermap, therefore use the output as a # single file download if ! [[ $line =~ ^[0135789ghiIds\;cM.].*$ ]] then filename="$(basename "$path")" cp "$map" "$filename" quit=1 break fi done if [[ $quit -eq 1 ]]; then exit fi cat "$map" | while read line do # these are all the prefixes for filetypes and directories if [[ $line =~ ^[0159ghIds\;cM].*$ ]] then split=() IFS=$'\t' read -r -a split <<< "$line" # the link name becomes the selector if the selector is # omitted selector="${split[0]}" if [[ "${split[1]}" ]]; then selector="${split[1]}" fi # no domain means current domain # ignore urls outside current domain if ! [[ "${split[2]}" ]] || \ [[ "${split[2]}" = "$domain" ]] then isdir=0 if [[ $line =~ ^[1].*$ ]] then isdir=1 fi # extract relative path by removing $path from the # selector relative="$(echo $selector | sed -e "s|$path||g")" # Recurse directory or download file if the file is # at a deeper level than the current directory case $selector/ in $path*) [[ $isdir -eq 1 ]] && \ mkdir -p "./$relative" && \ pushd "./$relative" # !!!! recursion !!!! $selfpath "$(echo "$url/$relative" | \ sed -e 's|//|/|g')" [[ $isdir -eq 1 ]] && popd ;; esac fi # end domain check fi # end type check done } # end cat "$map"