#!/bin/sh

# ATTENTION: Saunalahti/Elisa has disabled their old webpage authentication method
# which this script relied on. This does not actually work at the moment.
# Feel free to send patches.


#	smsl v.1.8 - send SMS via Saunalahti (for customers only)
#
#	Copyright Mikko Rauhala <mjr@iki.fi>, 2008-2010
#
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar at
# http://sam.zoy.org/wtfpl/COPYING and reproduced here:
#
#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
#                    Version 2, December 2004
#
# Copyright (C) 2004 Sam Hocevar
#  14 rue de Plaisance, 75014 Paris, France
# Everyone is permitted to copy and distribute verbatim or modified
# copies of this license document, and changing it is allowed as long
# as the name is changed.
#
#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
#   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
#  0. You just DO WHAT THE FUCK YOU WANT TO.

#        README:

# This program doesn't give you free SMS. It merely interfaces with the
# Saunalahti web UI at https://oma.saunalahti.fi/settings/smsSend for
# sending SMS you've either got coming to you with your service package,
# or for which you've paid separately. It's mostly a handy way for
# sending SMS from a proper keyboard when you've got one available.

# ~/.smsl/config defines the variables LOGIN, PASSWORD and optionally
# NUMBER for the source number (if NUMBER is not set, it will default to
# LOGIN - the Saunalahti web UI will present you with the possible other
# valid options). The variables must be on their own lines as "KEY=value",
# without the quotes. Empty lines and #-comments are allowed. 

# For logging, you may spesify also LOGFILE (defaults to ~/.smsl/log)
# or NOLOG=1 to disable logging. DATEFORMAT may also be set if desired.

# Example (though remove the comment markers for the actual file):

# LOGIN=0505555555
# PASSWORD=seecreet

# And you're set to send SMSes from your login number.

# You may also create ~/.smsl/phonebook for some simple phonebook
# functionality. The file should contain sed commands to be run
# on the recipient list. For instance: s/myself/0505555555/g

# Caveat: Saunalahti doesn't do international recipients. +358 numbers
# are converted into Finnish local numbers before sending, though.
# Also the error reporting is not as robust as it could be, but at least
# it 1) exists now and 2) seems to work with the current web service.

# Addendum: It seems that the Saunalahti web service just hangs 
# sometimes (with a regular browser too), resulting in the script 
# hanging as well. I might try and hack together timeout detection
# and/or retry looping at some point but for now just be aware of it
# (or submit a patch ;). If the script _does_ get around to exiting
# without errors there should (hopefully) be no trouble.
#
# Addendum 2: things seem to be better these days, hope it stays that way.

# ChangeLog:

# 1.8 * Fixed error message for overlong messages.

# 1.7 * Tweaked to recognize the new login welcome message.

# 1.6 * Configuration now at ~/.smsl/config, old location used as fallback
#     * Phonebook now at ~/.smsl/phonebook, old location used as fallback
#     * Will now log to ~/.smsl/log (or LOGFILE as given in config)
#     * Fixed bug with password that include "="

# 1.5 * Added .smslphonebook sed translations
#     * Added -n for no-act and -v for verbose
#     * Giving the message in multiple parameters now works akin to echo
#     * Removed sleeps
#     * Changed fallback temporary files to .smsl.*

# 1.4 * Fixed a couple of nbsps that should've been spaces. Apparently
#       there was no effect unless mktemp both exists and fails.

# 1.3 * Do a couple of sleeps between the HTTP requests to see if 
#       the spurious problems are race conditions in the Saunalahti 
#       service

# 1.2 * Hiding the Saunalahti password from curl command line.
#     * If mktemp not available, falling back to temp files named ~/.smslrc.*

# 1.1 * We now use curl instead of wget, since we can then ditch the horrible
#       URL-encoding code (which also had a byte order bug)
#     * Due to this, also login and password are urlencoded now properly...
#     * Checks for some programs not always installed on legacy systems
#     * Support for a defined cookie jar file in lieu of mktemp

# 1.0 * (Simplistic) error checks for server communication
#     * Use the C locale for consistent grepping

# 0.9 * Initial release

LC_ALL=C
export LC_ALL

RETVAL=0

ohnoes()
{
	echo "$1" 1>&2
	if [ "a$COOKIEJAR" != a ]
	then
		rm -f "$COOKIEJAR"
	fi
	if [ "a$PWFILE" != a ]
	then
		rm -f "$PWFILE"
	fi
	exit 1
}

# Ugly parsing, but can't be arsed.
NOACT=0
VERBOSE=0
OPTION_ERROR=0
while echo "a$1" | grep -q "^a-"
do
	case "$1" in
		"-n")	NOACT=1
		;;
		"-v")	VERBOSE=1
		;;
		"-nv"|"-vn")
			NOACT=1
			VERBOSE=1
		;;
		*)	OPTION_ERROR=1
		;;
	esac
	shift
done

if [ "a$2" = "a" -o "a$OPTION_ERROR" = "a1" ]
then
	echo "Usage: smsl [-nv] number(s) message" 1>&2
	echo 1>&2
	echo "You may enter multiple numbers separated by commas." 1>&2
	echo "The number list will be run through sed commands" 1>&2
	echo "in ~/.smslphonebook if it exists." 1>&2
	echo 1>&2
	echo "The SMS server wants ISO-8859-1 encoded messages." 1>&2
	echo "Valid UTF-8 messages will be converted if possible," 1>&2
	echo "otherwise the message will be passed as is." 1>&2
	echo 1>&2
	echo "-n will do preliminary processing but skip sending." 1>&2
	echo "-v will display the numbers and the message." 1>&2
	echo 1>&2
	exit 0
fi

if ! which curl > /dev/null
then
	ohnoes "curl is required for this version of smsl, aborting"
fi

if which iconv > /dev/null && iconv -l | grep -qi "UTF-8" && iconv -l | grep -qi "ISO-8859-1"
then
	if iconv --version 2> /dev/null | grep -q "GNU"
	then
		ICONV_TARGET="ISO-8859-1//TRANSLIT"
	else
		ICONV_TARGET="ISO-8859-1"
	fi
fi

GIVEN_RECIPIENTS="$1"
RECIPIENTS="$GIVEN_RECIPIENTS"
shift
MESSAGE="$@"

if [ -e "$HOME/.smsl/phonebook" ]
then
	PHONEBOOK="$HOME/.smsl/phonebook"
else
	PHONEBOOK="$HOME/.smslphonebook"
fi

if [ -e "$PHONEBOOK" ]
then
	RECIPIENTS="`echo -n "$RECIPIENTS" | sed -f "$PHONEBOOK"`" || ohnoes "Error processing $PHONEBOOK" ]
fi

RECIPIENTS="`echo -n "$RECIPIENTS" | sed 's/+358/0/g'`"

if echo -n "$RECIPIENTS" | grep -q '[^0-9,]'
then
	echo "Invalid recipients: $RECIPIENTS" 1>&2
	ohnoes 'Only digits, "," and "+358" are accepted after phonebook translation.'
fi

if [ "a$ICONV_TARGET" != a ] && echo -n "$MESSAGE" | iconv -f UTF-8 -t "$ICONV_TARGET" > /dev/null 2>&1
then
		MESSAGE="`echo -n "$MESSAGE" | iconv -f UTF-8 -t "$ICONV_TARGET"`"
fi

MESSAGELEN="`echo -n "$MESSAGE" | wc -c`"
if [ "$MESSAGELEN" -gt 160 ]
then
	ohnoes "Message length is $MESSAGELEN. Only 160 characters are allowed, aborting."
fi

NOLOG=0
LOGFILE="$HOME/.smsl/log"
DATEFORMAT="%F-%T"

if ! [ -e "$HOME/.smsl" ]
then
	mkdir -p "$HOME/.smsl" || ohnoes "failed to create $HOME/.smsl, aborting"
fi

if [ -e "$HOME/.smsl/config" ]
then
	CONFIG="$HOME/.smsl/config"
else
	CONFIG="$HOME/.smslrc"
fi

if [ -e "$CONFIG" ]
then
	. "$CONFIG" || ohnoes "failed to parse $CONFIG, aborting"
else
	ohnoes "$HOME/.smsl/config does not exist, aborting"
fi

if [ "a$LOGIN" = a ]
then
	ohnoes "User account not defined, aborting"
fi

if ! grep -q "^PASSWORD=" "$CONFIG"
then
	ohnoes "User password not defined, aborting"
fi

if [ "a$NUMBER" = a ]
then
	NUMBER="$LOGIN"
fi

if [ "a$VERBOSE" = a1 ]
then
	echo "From $NUMBER to $RECIPIENTS:"
	echo "$MESSAGE"
fi

if [ "a$NOACT" = a1 ]
then
	exit 0
fi

umask 077
if which mktemp > /dev/null
then
	COOKIEJAR="`mktemp -t smsl.cookiejar.XXXXXXXXXX`" || ohnoes "mktemp failed, aborting"
	PWFILE="`mktemp -t smsl.pass.XXXXXXXXXX`" || ohnoes "mktemp failed, aborting"
else
	COOKIEJAR="$HOME/.smsl/.cookiejar.$$"
	PWFILE="$HOME/.smsl/.pass.$$"
fi

grep "^PASSWORD=" "$CONFIG" | tail -n 1 | sed "s/^PASSWORD=//" | tr -d "\n" > "$PWFILE"

if ! curl -c "$COOKIEJAR" --data-urlencode "username=$LOGIN" --data-urlencode "password@$PWFILE" https://oma.saunalahti.fi/settings/ 2> /dev/null | grep -qi "Tervetuloa Oma.*Saunalahteen"
then
	ohnoes "Login to Saunalahti (probably) failed; check your password."
fi

if curl -b "$COOKIEJAR" https://oma.saunalahti.fi/settings/smsSend 2> /dev/null | grep -qi "Sinulla ei ole viestej.* varastossa"
then
	echo "You have no messages left on your account. Message not sent." 2>&1 
	if [ "a$NOLOG" = "a0" ]
	then
		echo "$(date +"$DATEFORMAT"): Insufficient message quota for sending to $GIVEN_RECIPIENTS ($RECIPIENTS): $MESSAGE" >> "$LOGFILE"
	fi
	RETVAL=3
else
	if ! curl -b "$COOKIEJAR" --data-urlencode "sender=$NUMBER" --data-urlencode "recipients=$RECIPIENTS" --data-urlencode "text=$MESSAGE" --data "send=L%e4het%e4" https://oma.saunalahti.fi/settings/smsSend 2> /dev/null | grep -qi "Viesti l.*hetetty"
	then
		echo "Message probably not sent successfully." 2>&1
		if [ "a$NOLOG" = "a0" ]
		then
			echo "$(date +"$DATEFORMAT"): Failed sending to $GIVEN_RECIPIENTS ($RECIPIENTS): $MESSAGE" >> "$LOGFILE"
		fi
		RETVAL=2
	else
		if [ "a$NOLOG" = "a0" ]
		then
			echo "$(date +"$DATEFORMAT"): Sent to $GIVEN_RECIPIENTS ($RECIPIENTS): $MESSAGE" >> "$LOGFILE"
		fi
	fi
fi

if ! curl -b "$COOKIEJAR" https://oma.saunalahti.fi/settings/Logout 2> /dev/null | grep -qi "Olet kirjautunut ulos"
then
	echo "Error logging out of Saunalahti web services. Quitting anyway." 2>&1
fi

rm -f "$COOKIEJAR"
rm -f "$PWFILE"

exit $RETVAL
