#!/bin/sh

# html2pager - version 0.1
#
# Copyright (C) 2006, Jeremy Laidman
# under the GNU General Public License.
# For details: http://www.gnu.org/licenses/gpl.txt
#
# a web interface to gnokii, written in bourne shell, cos we know it's there
# assumes we're being run from (x)inetd, doesn't work as CGI (yet)

# Todo:
# - ensure we can't be compromised by dodgy characters
# - some degree of logging
# - authentication

# Bugs, problems, caveats:
# - there are probably some bash-ism

#------------------------------------------------------------#

FORMFILE=`dirname $0`/"pager.html"
GNOKII=/usr/local/gnokii/bin/gnokii

#------------------------------------------------------------#

# default form if FORMFILE doesn't exist
FORM='<HEAD>
<TITLE>Pager Form</TITLE>
</HEAD>
<BODY>
<H2>Pager Form</H2>
<FORM>
Number:
<INPUT type="text" name="number"/>
<BR>
Message:<BR>
<TEXTAREA name="message" cols=80 rows=4/></TEXTAREA>
<BR>
<INPUT type="submit" value="Page">
</FORM>
</BODY>
'
#------------------------------------------------------------#

die() {
	while [ $# -gt 0 ]; do
		echo "$1"
		shift
	done
	exit 0
}

cleanread() {
	read -t30 L
	( IFS=""; set - $L; echo $1 )
	unset L
}

split() {
	# give me names of var and val global variables
	# and a separator string
	# and a string of the form "bla=moo"
	# and I'll set VAR=bla and VAL=moo
	L_VAR1=$1
	L_VAR2=$2
	L_SEP=$3
	L_STRING=$4

	#echo "STR=$L_STRING"
	#echo "LHS="${L_STRING%%=*}
	#echo "RHS="${L_STRING#?*=}

	# these barf on some chars (eg single quotes) so we just ignore
	eval $L_VAR1=${L_STRING%%=*} 2>/dev/null
	eval $L_VAR2=${L_STRING#?*=} 2>/dev/null

	#echo "VAL is $VAL"
}

send_message() {
	# run gnokii and send the message
	# return error message, or blank if OK
	NUM=$1
	MSG=$2
	echo "$MSG" | $GNOKII --sendsms "$NUM" 2>&1
	RC=$?
	case $RC in
		0)	:;;	# all OK, no return
		1)	echo "Run failed ";;	# gnokii failed, will have error already
		127)	echo "Exec failed";;
		*)	echo "Unexpected error: $RC";;
	esac
	# returns empty on failure
}

#------------------------------------------------------------#

REQUEST=`cleanread`
set - $REQUEST
if [ $# -lt 2 -o $# -gt 3 ]; then
	die "HTTP/1.0 501 badly formatted request [$REQUEST]"
fi

if [ $# -eq 2 ]; then
	die "HTTP/1.0 505 HTTP version 0.9 unsupported"
fi

TYPE="$1"
URI="$2"
VER="$3"

if [ "$VER" != "HTTP/1.0" -a "$VER" != "HTTP/1.1" ]; then
	die "HTTP/1.0 505 HTTP Version $VER unsupported"
fi

case $TYPE in
	[Gg][Ee][Tt])		TYPE="GET";;
	[Pp][Uu][Tt])		TYPE="PUT";;
	[Pp][Oo][Ss][Tt])	TYPE="POST";;
	[Hh][Ee][Aa][Dd])	TYPE="HEAD";;
	*)			die "HTTP/1.0 500 Method $TYPE not supported"
esac

if [ "$TYPE" != "GET" -a "$TYPE" != "HEAD" ]; then
	die "HTTP/1.0 501 Method $TYPE not supported"
fi

# need to get rest of the lines until newline
LINE=`cleanread`
LINE=`echo $LINE`
while [ "$LINE" ]; do
	# we have a header
	LINE=`cleanread`
done

# extract info from URI, note that this breaks with an empty var=val section
IFSSAVE="$IFS"
IFS='?&'
set - $URI
IFS="$IFSSAVE"
shift	# get past the "?"
LINE="$1"
while [ "$LINE" ]; do
	# some escaping to protect us
	LINE=${LINE//\"/%22}
	LINE=${LINE//\&/%26}
	LINE=${LINE//\'/%27}
	LINE=${LINE//\(/%28}
	LINE=${LINE//\)/%29}
	LINE=${LINE//\;/%3b}
	LINE=${LINE//\\/%5c}	# unlikely to ever get this
	split "VAR" "VAL" "=" $LINE
	case $VAR in
		number)  NUMBER=$VAL;;
		message) MESSAGE=$VAL;;
		debug)   DEBUG=$VAL;;
	esac
	shift
	LINE=$1
done

# + and , don't need escaping for later on, so we turn them back
# now to let the cleanup work
NUMBER=${NUMBER//\%2[bB]/+}
NUMBER=${NUMBER//\%2[cC]/,}
NUMBER=${NUMBER//[^,+0-9]/}	# strip non-numerics but not + or ,

if [ ! "$NUMBER" -o ! "$MESSAGE" ]; then
	if [ -f $FORMFILE ]; then
		cat $FORMFILE
		exit
	else
		if [ "$FORM" ]; then
			echo "$FORM"
		else
			die "HTTP/1.0 501 Number or message not specified" \
				"" \
				"Please specify number=nnn and message=text"
		fi
	fi
	exit
fi

# present results
echo "HTTP/1.0 200 OK"
echo "Content-type: text/plain"
echo ""
[ "$TYPE" = "HEAD" ] && exit

if [ "$DEBUG" ]; then
	echo "Debug mode on"
	echo "Requested $TYPE on $URI"
	echo "Number: $NUMBER"
	echo "Message: $MESSAGE"
fi

# clean up message containing escapes
NL="
"
MESSAGE=${MESSAGE//\%0[dD]%0[aA]/$NL}
MESSAGE=${MESSAGE//\%0[dDaA]/$NL}
MESSAGE=${MESSAGE//\%20/\ }
MESSAGE=${MESSAGE//\%21/\!}
MESSAGE=${MESSAGE//\%22/\"}	# may need to escape the quote
MESSAGE=${MESSAGE//\%23/\#}
MESSAGE=${MESSAGE//\%24/\$}
MESSAGE=${MESSAGE//\%25/\%}
MESSAGE=${MESSAGE//\%26/\&}
MESSAGE=${MESSAGE//\%27/\'}
MESSAGE=${MESSAGE//\%28/\(}
MESSAGE=${MESSAGE//\%29/\)}
MESSAGE=${MESSAGE//\%2[aA]/*}
MESSAGE=${MESSAGE//\%2[bB]/+}
MESSAGE=${MESSAGE//\%2[cC]/,}
MESSAGE=${MESSAGE//\%2[dD]/-}
MESSAGE=${MESSAGE//\%2[eE]/\.}
MESSAGE=${MESSAGE//\%2[fF]/\/}
MESSAGE=${MESSAGE//\%30/0}
MESSAGE=${MESSAGE//\%31/1}
MESSAGE=${MESSAGE//\%32/2}
MESSAGE=${MESSAGE//\%33/3}
MESSAGE=${MESSAGE//\%34/4}
MESSAGE=${MESSAGE//\%35/5}
MESSAGE=${MESSAGE//\%36/6}
MESSAGE=${MESSAGE//\%37/7}
MESSAGE=${MESSAGE//\%38/8}
MESSAGE=${MESSAGE//\%39/9}
MESSAGE=${MESSAGE//\%3[aA]/:}
MESSAGE=${MESSAGE//\%3[bB]/;}
MESSAGE=${MESSAGE//\%3[cC]/<}
MESSAGE=${MESSAGE//\%3[dD]/=}
MESSAGE=${MESSAGE//\%3[eE]/>}
MESSAGE=${MESSAGE//\%3[fF]/?}
MESSAGE=${MESSAGE//\%40/@}
MESSAGE=${MESSAGE//\%5[bB]/\[}
MESSAGE=${MESSAGE//\%5[cC]/\\}	# perhaps this is a bad idea
MESSAGE=${MESSAGE//\%5[dD]/\]}
MESSAGE=${MESSAGE//\%5[eE]/\^}
MESSAGE=${MESSAGE//\%5[fF]/\_}
MESSAGE=${MESSAGE//\%60/\`}
MESSAGE=${MESSAGE//\%7[bB]/\{}
MESSAGE=${MESSAGE//\%7[cC]/\|}
MESSAGE=${MESSAGE//\%7[dD]/\}}
MESSAGE=${MESSAGE//\%7[eE]/\~}

echo "$MESSAGE" >/tmp/bla
RESULT=`send_message $NUMBER $MESSAGE`
if [ "$RESULT" ]; then
	echo "FAILED"
	echo "$RESULT"
	echo "NUMBER=[$NUMBER]"
	echo "MESSAGE=[$MESSAGE]"
else
	echo "OK"
fi
