💾 Archived View for celehner.com › add-backlink captured on 2021-12-17 at 13:26:06.

View Raw

More Information

⬅️ Previous capture (2021-11-30)

-=-=-=-=-=-=-

#!/bin/sh

if [ -n "$GEMINI_URL" ]; then
	# serve own source
	printf '20 text/plain\r\n'
	exec cat "$0"
fi

target_url=${1?url}
path=${2?path}
query=${3?query}
file=${4?file}

if [ -z "$query" ]; then
	exec printf '10 Gemini URL that links to "%s"\r\n' "$target_url"
fi

urldecode() {
	# Whinger https://stackoverflow.com/questions/3728049/using-awk-printf-to-urldecode-text/46830163#46830163
	awk 'BEGIN {for (y=0;y<127;y++) if (y!=37) gsub(sprintf("%%%02x|%%%02X",y,y), y==38 ? "\\&" : sprintf("%c", y), ARGV[1]);gsub(/%25/, "%", ARGV[1]);print ARGV[1]}' "$1"
}

url=$(urldecode "$query")

case "$url" in
	gemini://*);;
	*) exec printf '40 URL must be gemini://\r\n';;
esac

has_link() {
	local file=${1?file}
	local target=${2?target}
	# TODO check link more
	target_scheme_relative=${target#gemini:}
	#grep -qF "=> $target" "$file" || grep -qF "=> $target_scheme_relative" "$tmp"
	#awk -v url1="$target" -v url2="$target_scheme_relative" '$1 == "=>" && ($2 == url1 || $2 == url2) {exit 0} END {exit 1}' "$file"
	awk -v url1="$target" -v url2="$target_scheme_relative" 'BEGIN { rc=1; } $1 == "=>" && ($2 == url1 || $2 == url2) {rc=0; exit} END {exit rc}' "$file"
}

if has_link "$file" "$url"; then
	exec printf '40 URL is already listed\r\n'
fi

fetch() {
	local url=$1
	local url1=${url#gemini://}
	local hostname=${url1%%/*}
	local host=${hostname%%:*}
	local port=${hostname##*:}
	if [ "$host" = "$port" ]; then port=1965; fi
	printf '%s\r\n' "$url" | ncat --no-shutdown --ssl "$host" "$port"
}

tmp=$(mktemp) || exec printf '50 Unable to create temp file\r\n'
cleanup() {
	rm -f "$tmp"
}
clean_exec() {
	cleanup
	exec "$@"
}
trap cleanup 1 2 13 15
fetch "$url" >"$tmp" || clean_exec printf '50 Unable to fetch resource\r\n'
status=$(head -1 "$tmp")
if ! printf %s "$status" | grep -q "20 text/gemini\\(;\\|\s*$\\)"; then
	clean_exec printf '50 Status must be 20 text/gemini; got %s\r\n' "$status"
fi

if ! has_link "$tmp" "$target_url"; then
	clean_exec printf '40 Link not found in resource\r\n'
fi

# link was found
title=$(sed '1d; s/^#\+\s\+//; 2q' "$tmp")
rm -f "$tmp"

if ! test -e "$file"; then
	exec printf '40 Destination page does not exist\r\n'
fi

if ! printf "=> %s %s\n" "$url" "$title" >>$file; then
	exec printf '50 Error adding link :(\r\n'
fi

printf '20 text/gemini\r\n'
printf 'Link added!\n\n'

umask 0002
if ! (git add "$file" && git commit -m "Add backlink" "$file"); then
	printf 'But unable to commit.\n\n'
fi

printf '=> %s Back\n' "$target_url"

mail -s 'Gemini backlink added' cel <<EOF
Page: $target_url
Link: $url ($title)
EOF