#!/bin/sh
# CGItest v1.4.1  (c) 15.2.99 by Andreas Ley  (u) 9.12.2023
# Test CGIs offline

usage()
{
	echo "Usage: $(basename $0) [-V fqdn] [-p pathinfo] [-q querystring] [-P file] [-s] [-a user:pass|-r user] cgi-script" >&2
	echo "-V  Use the given VHost" >&2
	echo "-p  call the cgi-script with the given pathinfo" >&2
	echo "-q  call the cgi-script with the given querystring" >&2
	echo "-P  post the given file to the cgi-script" >&2
	echo "-s  call the cgi-script with SSL environment" >&2
	echo "-a  call the cgi-script with the given basic authorization" >&2
	echo "-r  call the cgi-script with given authenticated remote user" >&2
	exit 1
}

#
# Option parsing
#

set -- $(getopt V:p:q:P:sa:r:hx $*) || usage

remote_user=
while :; do
	case $1 in
		-h)     sed '1d;s/^# *//;/^$/q' $0; usage;;
		-x)	set -x; shift;;
		-V)     vhost="$2"; shift 2;;
		-p)     pathinfo="$2"; shift 2;;
		-q)     querystring="$2"; shift 2;;
		-P)     post="$2"; shift 2;;
		-s)     ssl=true; shift;;
		-a)     auth="$2"; shift 2;;
		-r)     remote_user="$2"; shift 2;;
		--)     shift; break;;
	esac
done

test $# -lt 1 && usage

if test ! -x "$1"; then
	echo "$1: cannot execute" >&2
	exit 1
fi

if test -n "${post}"; then
	if test ! -r "${post}"; then
		echo "${post}: cannot read" >&2
		exit 1
	fi
	case "${post}" in
		/*)	:;;
		*)	post="$(pwd)/${post}";;
	esac
fi

PATH=/bin:/usr/bin
export PATH

unset CDPATH

path='/usr/bin:/bin'
host="$(hostname --fqdn)"
addr="$(hostname --ip-address | awk '{print$1}')"
root=/usr/local/etc/httpd
cgibin=true
test -d /var/www && root=/var/www && cgibin=false
server="$(sed -n '2s/# \([^ ]*\) \([^ ]*\) .*/\1\/\2/p' $0)"
config="${root}/conf/httpd.conf"
if test -n "${vhost}"; then
	root="${root}/${vhost}"
	config="${root}/conf/identity.conf"
fi
serveradmin="$(awk '$1=="ServerAdmin"{print$2}' ${config})"
serveradmin="${serveradmin:-webmaster@kit.edu}"
servername="$(awk '$1=="ServerName"{print$2}' ${config})"
servername="${servername:-${vhost:-${host}}}"
case "${pathinfo}" in
	/*)	:;;
	*)	pathinfo="/${pathinfo}";;
esac
pathtranslated="${root}/htdocs${pathinfo}"

if test -n "${auth}"; then
	auth="HTTP_AUTHORIZATION=Basic $(basic-encode ${auth})"
fi

home=$(cd ${HOME} && /bin/pwd)
dir=$(dirname $1)
file=$(cd ${dir} && /bin/pwd)/$(basename $1)
shift

case ${file} in
	${home}/public_html/*.cgi)
		case $(stat -c %a ${dir}) in
			*[2367]|*[2367]?)
				echo "ERROR: Script must lie in directory writable only for owner!" >&2;;
		esac
		case $(stat -c %a ${file}) in
			*[2367]|*[2367]?)
				echo "ERROR: Script must be writable only for owner!" >&2;;
		esac
		uid=$(id -u)
		gid=$(id -g)
		test $(stat -c %u ${file}) = ${uid} || \
			echo "ERROR: You're not the owner of the script!" >&2
		test $(stat -c %g ${file}) = ${gid} || \
			echo "ERROR: The script's group is not your group!" >&2
		test $(stat -c %u ${dir}) = ${uid} || \
			echo "ERROR: You're not the owner of the script's directory!" >&2
		test $(stat -c %g ${dir}) = ${gid} || \
			echo "ERROR: The script's directory's group is not your group!" >&2
		test ${uid} -lt 100 && \
			echo "ERROR: Your user id is below 100!" >&2
		test ${gid} -lt 100 && \
			echo "ERROR: Your group id is below 100!" >&2
		cd ${dir}
		script=$(echo ${file} | sed "s%\$(dirname ${HOME}\)/\([^/]*\)/public_html%/~\1%");;
	${home}/public_html/*)
		echo "ERROR: Script must have .cgi extension" >&2
		script=$(echo ${file} | sed "s%\$(dirname ${HOME}\)/\([^/]*\)/public_html%/~\1%");;
	*)
		script=${file}
		echo "ERROR: Script must have .cgi extension and lie in ~/public_html" >&2
		echo "WARNING: Unable to set Script-Path-related environment correctly" >&2;;
esac

#
# Set environment, call cgi-script
#

if test -z "${ssl}"; then
	if test -z "${post}"; then
		exec env -i \
		AUTH_TYPE= \
		CONTENT_LENGTH= \
		CONTENT_TYPE= \
		DOCUMENT_ROOT="${root}/htdocs" \
		GATEWAY_INTERFACE="CGI/1.1" \
		HTTP_ACCEPT="*/*" ${auth+"${auth}"} \
		PATH="${path}" \
		PATH_INFO="${pathinfo}" \
		PATH_TRANSLATED="${pathtranslated}" \
		QUERY_STRING="${querystring}" \
		REMOTE_ADDR="${addr}" \
		REMOTE_HOST="${host}" \
		REMOTE_PORT="7168" \
		REMOTE_USER="${remote_user}" \
		REQUEST_METHOD="GET" \
		REQUEST_SCHEME="http" \
		REQUEST_URI="${script}${pathinfo}" \
		SCRIPT_FILENAME="${file}" \
		SCRIPT_NAME="${script}" \
		SCRIPT_URL="${script}${pathinfo}" \
		SCRIPT_URI="http://${servername}${script}${pathinfo}" \
		SERVER_ADMIN="${serveradmin}" \
		SERVER_NAME="${servername}" \
		SERVER_PORT="80" \
		SERVER_PROTOCOL="HTTP/1.0" \
		SERVER_SIGNATURE= \
		SERVER_SOFTWARE="${server}" \
		"${file}" ${1+"$@"}
	else
		exec env - \
		AUTH_TYPE= \
		CONTENT_LENGTH="$(stat -s ${post})" \
		CONTENT_TYPE="application/x-www-form-urlencoded" \
		DOCUMENT_ROOT="${root}/htdocs" \
		GATEWAY_INTERFACE="CGI/1.1" \
		HTTP_ACCEPT="*/*" ${auth+"${auth}"} \
		PATH="${path}" \
		PATH_INFO="${pathinfo}" \
		PATH_TRANSLATED="${pathtranslated}" \
		QUERY_STRING="${querystring}" \
		REMOTE_ADDR="${addr}" \
		REMOTE_HOST="${host}" \
		REMOTE_PORT="7168" \
		REMOTE_USER="${remote_user}" \
		REQUEST_METHOD="POST" \
		REQUEST_SCHEME="http" \
		REQUEST_URI="${script}${pathinfo}" \
		SCRIPT_FILENAME="${file}" \
		SCRIPT_NAME="${script}" \
		SCRIPT_URL="${script}${pathinfo}" \
		SCRIPT_URI="http://${servername}${script}${pathinfo}" \
		SERVER_ADMIN="${serveradmin}" \
		SERVER_NAME="${servername}" \
		SERVER_PORT="80" \
		SERVER_PROTOCOL="HTTP/1.0" \
		SERVER_SIGNATURE= \
		SERVER_SOFTWARE="${server}" \
		"${file}" ${1+"$@"} <${post}
	fi
else
	if test -z "${post}"; then
		exec env - \
		AUTH_TYPE= \
		CONTENT_LENGTH= \
		CONTENT_TYPE= \
		DOCUMENT_ROOT="${root}/htdocs" \
		GATEWAY_INTERFACE="CGI/1.1" \
		HTTPS="on" \
		HTTP_ACCEPT="*/*" ${auth+"${auth}"} \
		PATH="${path}" \
		PATH_INFO="${pathinfo}" \
		PATH_TRANSLATED="${pathtranslated}" \
		QUERY_STRING="${querystring}" \
		REMOTE_ADDR="${addr}" \
		REMOTE_HOST="${host}" \
		REMOTE_PORT="7168" \
		REMOTE_USER="${remote_user}" \
		REQUEST_METHOD="GET" \
		REQUEST_SCHEME="https" \
		REQUEST_URI="${script}${pathinfo}" \
		SCRIPT_FILENAME="${file}" \
		SCRIPT_NAME="${script}" \
		SCRIPT_URL="${script}${pathinfo}" \
		SCRIPT_URI="https://${servername}${script}${pathinfo}" \
		SERVER_ADMIN="${serveradmin}" \
		SERVER_NAME="${servername}" \
		SERVER_PORT="443" \
		SERVER_PROTOCOL="HTTP/1.0" \
		SERVER_SIGNATURE= \
		SERVER_SOFTWARE="${server}" \
		SSL_TLS_SNI="${servername}" \
		"${file}" ${1+"$@"}
	else
		exec env - \
		AUTH_TYPE= \
		CONTENT_LENGTH="$(stat -s ${post})" \
		CONTENT_TYPE="application/x-www-form-urlencoded" \
		DOCUMENT_ROOT="${root}/htdocs" \
		GATEWAY_INTERFACE="CGI/1.1" \
		HTTPS="on" \
		HTTP_ACCEPT="*/*" ${auth+"${auth}"} \
		PATH="${path}" \
		PATH_INFO="${pathinfo}" \
		PATH_TRANSLATED="${pathtranslated}" \
		QUERY_STRING="${querystring}" \
		REMOTE_ADDR="${addr}" \
		REMOTE_HOST="${host}" \
		REMOTE_PORT="7168" \
		REMOTE_USER="${remote_user}" \
		REQUEST_METHOD="POST" \
		REQUEST_SCHEME="https" \
		REQUEST_URI="${script}${pathinfo}" \
		SCRIPT_FILENAME="${file}" \
		SCRIPT_NAME="${script}" \
		SCRIPT_URL="${script}${pathinfo}" \
		SCRIPT_URI="https://${servername}${script}${pathinfo}" \
		SERVER_ADMIN="${serveradmin}" \
		SERVER_NAME="${servername}" \
		SERVER_PORT="443" \
		SERVER_PROTOCOL="HTTP/1.0" \
		SERVER_SIGNATURE= \
		SERVER_SOFTWARE="${server}" \
		SSL_TLS_SNI="${servername}" \
		"${file}" ${1+"$@"} <${post}
	fi
fi
