#!/bin/bash #set -eu ################## #### GENERAL ##### ################## CAPSULE_DIR="" # PERCENT-ENCODING encode_precent_encoding(){ url=$(echo "$1"|awk '{gsub(/ /,"%20");print}') echo "$url" } decode_percent_encoding(){ echo "$1" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b" } ################# #### GEMINI ##### ################# # FILE FORMATING OPTIONS raw2gmi_print(){ printf "20 text/gemini\r\n" cat "$1" } raw2gmi_dump(){ echo '```' cat "$1" echo '```' } txt2gmi_print(){ printf "20 text/gemini\r\n" awk '{printf "%s\n\n",$0}' "$1" } txt2gmi_dump(){ awk '{printf "%s\n\n",$0}' "$1" } gmi2gmi_print(){ printf "20 text/gemini\r\n" cat "$1" } gmi2gmi_dump(){ cat "$1" } # PHARSING link2gmi(){ # Pharse a link indicated by "=>path [optional title]" # Parameter: string of the form "=>path [optional title]" line="$1" path=$(echo "${line:2}" | awk '{print $1}') path="$CAPSULE_DIR$path" # File if [[ -f "$path" ]]; then ext=$(echo "$path"|awk -F'.' '{print $NF}') case $ext in capsule) title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') title_enc=$(encode_precent_encoding "$title") echo "=>main.cgi?capsule=$path $title" ;; *) echo "=>$CAPSULE_DIR${line:2}" ;; esac fi # Directory if [[ -d "$path" ]]; then title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') title_enc=$(encode_precent_encoding "$title") echo "=>main.cgi?open=$path&title=$title_enc $title" fi # External link if [[ "${line:0:11}" == "=>gemini://" ]];then echo "$line" fi } dump2gmi(){ # Dump the content indicated by "<=path [optional title]" # Parameter: string of the form "<=path [optional title]" content=$(echo "${line:2}" | awk '{print $1}') content="$CAPSULE_DIR$content" # Directory if [[ -d "$content" ]]; then header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') if [[ "$header" != "" ]]; then echo "$header" fi while read item do ext=$(echo "${item}"|awk -F"." '{print $NF}') case $ext in txt) label=$(head -n1 "$content/$item"|awk -F':' '{print $2}') if [[ "$label" != "" ]]; then echo "=>main.cgi?print=$content/$item $label" else echo "=>main.cgi?print=$content/$item $item" fi ;; gmi) label=$(head -n1 "$content/$item" | awk '{print substr($0,2)}') echo "=>main.cgi?print=$content/$item $label" ;; text) label="$item" echo "=>main.cgi?print=$content/$item $label" ;; esac done < <(ls -1A "$content") else # File if [[ -f "$content" ]]; then header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') if [[ "$header" != "" ]]; then printf "$header\r\n" fi ext=$(echo "${content}"|awk -F"." '{print $NF}') case $ext in txt) txt2gmi_dump "$content" ;; gmi) gmi2gmi_dump "$content" ;; *) raw2gmi_dump "$content" ;; esac fi fi } # OPTIONS print_gmi(){ # Wehn QUERY_STRING="print=path" # Parameter: path path="$1" path_dec=$(decode_percent_encoding "$path") # Get file extension. ext=$(echo "$path"|awk -F"." '{print $NF}') case $ext in txt) txt2gmi_print "$path_dec" ;; gmi) gmi2gmi_print "$path_dec" ;; *) raw2gmi_print "$path_dec" ;; esac } open_gmi(){ # When QUERY_STRING="open=dir&title=title" # Parameters: dir title dir="$1" title="$2" dir_clean=$(decode_percent_encoding "$dir") title_clean=$(decode_percent_encoding "$title") printf "20 text/gemini\r\n" echo "# $title_clean" while read item do ext=$(echo "${item}"|awk -F"." '{print $NF}') case $ext in txt) label=$(head -n1 "$dir_clean/$item"|awk -F':' '{print $2}') ;; gmi) label=$(head -n1 "$dir_clean/$item") t="${label:2}" label="$t" ;; *) label="$item" ;; esac echo "=>main.cgi?print=$dir_clean/$item $label" done < <(ls -1A "$dir_clean") } # DEPLOY FUNCTIONS deploy_gmi(){ # Deploy gemini capsule # Parameter: .capsule file capsule="$1" printf "20 text/gemini\r\n" while IFS= read line do ## Link content indicated by "=>" if [[ "${line:0:2}" == "=>" ]]; then link2gmi "$line" fi # Dump the content indicated by "<=" if [[ "${line:0:2}" == "<=" ]]; then dump2gmi "$line" fi # Any other line if [[ "${line:0:2}" != "=>" ]] && [[ "${line:0:2}" != "<=" ]]; then echo -E "$line" fi done < "$capsule" } ################# #### GOPHER ##### ################# # FILE FORMATING OPTIONS raw2gopher_print(){ fmt -s -w 60 "$1" } raw2gopher_dump(){ fmt -s -w 60 "$1" } txt2gopher_print(){ awk '{printf "%s\n\n",$0}' "$1" | fmt -s -w 60 } txt2gopher_dump(){ awk '{printf "%s\n\n",$0}' "$1" | fmt -s -w 60 } gmi2gopher_print(){ fmt -s -w 60 "$1" } gmi2gopher_dump(){ fmt -s -w 60 "$1" } # PHARSING link2gopher(){ # Pharse a link indicated by "=>path [optional title]" # Parameter: string of the form "=>path [optional title]" line="$1" path=$(echo "${line:2}" | awk '{print $1}') path="$CAPSULE_DIR$path" # File if [[ -f "$path" ]]; then ext=$(echo "$path"|awk -F'.' '{print $NF}') case $ext in capsule) title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') title_enc=$(encode_precent_encoding "$title") printf "0$title\t$GOPHER_DIR/main.cgi?capsule=$path\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>main.cgi?capsule=$path $title" ;; *) title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') title_enc=$(encode_precent_encoding "$title") printf "0$title\t$GOPHER_DIR/$path\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>$CAPSULE_DIR${line:2}" ;; esac fi # Directory if [[ -d "$path" ]]; then title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') title_enc=$(encode_precent_encoding "$title") printf "0$title\t$GOPHER_DIR/main.cgi?open=$path&title=$title_enc\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>main.cgi?open=$path&title=$title_enc $title" fi # External link if [[ "${line:0:11}" == "=>gemini://" ]]; then echo "$line" fi } dump2gopher(){ # Dump the content indicated by "<=path [optional title]" # Parameter: string of the form "<=path [optional title]" content=$(echo "${line:2}" | awk '{print $1}') content="$CAPSULE_DIR$content" # Directory if [[ -d "$content" ]]; then header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') if [[ "$header" != "" ]]; then echo "$header" fi while read item do ext=$(echo "${item}"|awk -F"." '{print $NF}') case $ext in txt) label=$(head -n1 "$content/$item"|awk -F':' '{print $2}') if [[ "$label" != "" ]]; then printf "0$label\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>main.cgi?print=$content/$item $label" else printf "0$item\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>main.cgi?print=$content/$item $item" fi ;; gmi) label=$(head -n1 "$content/$item" | awk '{print substr($0,2)}') printf "0$label\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>main.cgi?print=$content/$item $label" ;; text) label="$item" printf "0$label\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>main.cgi?print=$content/$item $label" ;; esac done < <(ls -1A "$content") else # File if [[ -f "$content" ]]; then header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}') if [[ "$header" != "" ]]; then printf "$header\r\n" fi ext=$(echo "${content}"|awk -F"." '{print $NF}') case $ext in txt) txt2gopher_dump "$content" ;; gmi) gmi2gopher_dump "$content" ;; *) raw2gopher_dump "$content" ;; esac fi fi } # OPTIONS print_gopher(){ # Wehn QUERY_STRING="print=path" # Parameter: path path="$1" path_dec=$(decode_percent_encoding "$path") # Get file extension. ext=$(echo "$path"|awk -F"." '{print $NF}') case $ext in txt) txt2gopher_print "$path_dec" ;; gmi) gmi2gopher_print "$path_dec" ;; *) raw2gopher_print "$path_dec" ;; esac } open_gopher(){ # When QUERY_STRING="open=dir&title=title" # Parameters: dir title dir="$1" title="$2" dir_clean=$(decode_percent_encoding "$dir") title_clean=$(decode_percent_encoding "$title") printf "20 text/gemini\r\n" echo "# $title_clean" while read item do ext=$(echo "${item}"|awk -F"." '{print $NF}') case $ext in txt) label=$(head -n1 "$dir_clean/$item"|awk -F':' '{print $2}') ;; gmi) label=$(head -n1 "$dir_clean/$item") t="${label:2}" label="$t" ;; *) label="$item" ;; esac printf "0$label\t$GOPHER_DIR/main.cgi?print=$dir_clean/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" #echo "=>main.cgi?print=$dir_clean/$item $label" done < <(ls -1A "$dir_clean") } # DEPLOY FUNCTIONS deploy_gopher(){ # Deploy gemini capsule # Parameter: .capsule file capsule="$1" printf "20 text/gemini\r\n" while IFS= read line do ## Link content indicated by "=>" if [[ "${line:0:2}" == "=>" ]]; then link2gopher "$line" fi # Dump the content indicated by "<=" if [[ "${line:0:2}" == "<=" ]]; then dump2gopher "$line" fi # Any other line if [[ "${line:0:2}" != "=>" ]] && [[ "${line:0:2}" != "<=" ]]; then echo "$line" fi done < "$capsule" } #################### #### DEPLOYMENT #### #################### # DEPLY CAPSULE/GOPHERHOLE # Gemini if [[ "$SERVER_PROTOCOL" == "GEMINI" ]]; then # Print a file if QUERY_STRING="print=..." if [[ "${QUERY_STRING:0:5}" == "print" ]]; then path="${QUERY_STRING:6}" print_gmi "$path" else # Open a directory if QUERY_STRING="open=dir&title=title" if [[ "${QUERY_STRING:0:4}" == "open" ]]; then dir=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print $1}') title=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print substr($2,7)}') open_gmi "$dir" "$title" else # Deploy a specific capsule if QUERY_STRING="capsule=capsule" if [[ "${QUERY_STRING:0:7}" == "capsule" ]]; then capsule="${QUERY_STRING:8}" capsule_clean=$(decode_percent_encoding "${QUERY_STRING:8}") CAPSULE_DIR="$(dirname "$capsule_clean")" if [[ "$CAPSULE_DIR" != "" ]]; then CAPSULE_DIR="$CAPSULE_DIR/" fi #CAPSULE_DIR="lala" #CAPSULE_DIR="${capsule_clean%/*}" #deploy_gmi "$capsule_clean" deploy_gmi "$capsule_clean" else deploy_gmi "main.capsule" fi fi fi fi # Gopher GOPHER_DIR="/~filip/public_gemini" GOPHER_SERVER="tilde.club" GOPHER_PORT="70" if [[ "$SERVER_PROTOCOL" == "RFC1436" ]]; then echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo "You are opening a Gemini capsule via Gopher!" echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" # Print a file if QUERY_STRING="print=..." if [[ "${QUERY_STRING:0:5}" == "print" ]]; then path="${QUERY_STRING:6}" print_gopher "$path" else # Open a directory if QUERY_STRING="open=dir&title=title" if [[ "${QUERY_STRING:0:4}" == "open" ]]; then dir=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print $1}') title=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print substr($2,7)}') open_gopher "$dir" "$title" else # Deploy a specific capsule if QUERY_STRING="capsule=capsule" if [[ "${QUERY_STRING:0:7}" == "capsule" ]]; then capsule="${QUERY_STRING:8}" capsule_clean=$(decode_percent_encoding "${QUERY_STRING:8}") CAPSULE_DIR="$(dirname "$capsule_clean")" if [[ "$CAPSULE_DIR" != "" ]]; then CAPSULE_DIR="$CAPSULE_DIR/" fi #CAPSULE_DIR="lala" #CAPSULE_DIR="${capsule_clean%/*}" #deploy_gmi "$capsule_clean" deploy_gopher "$capsule_clean" else deploy_gopher "main.capsule" fi fi fi fi #if [[ "$SERVER_PROTOCOL" == "RFC1436" ]]; then #echo "You are using Gopher!" # # printf "0TITLE\t$GOPHER_DIR/file\t$GOPHER_SERVER\t$GOPHER_PORT\r\n" # printf "0gemini\t$GOPHER_DIR/gemini/gemini.gmi\ttilde.club\t70\r\n" #printf "0gemini\t/~filip/public_gemini/gemini/gemini.gmi\ttilde.club\t70\r\n" # printf "0gemini\t/~filip/cgi-bin/public_gemini/gemini/gemini.gmi\ttilde.club\t70" #fi