#!/bin/sh
#
########################################################
#
# Filename: /usr/lib/cups/backend/faxgate
#
# Function: CUPS-Backend for faxsending via CapiSuite
# Author: Ingo Goeppert <ingo.goeppert@gmx.de>
# Version: 0.14 from Mo Mai 28 09:35:56 2007
#
# Charset: UTF-8
#
########################################################
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#

###############################
# Do checks and assign values #
###############################

# create file only readable by the user who executes the script
umask 166

# Configuration for this script
CONFIG=/etc/faxgate/faxgate.conf

# check if config-file exists
if [ -f $CONFIG ]; then
   . $CONFIG
   # check if faxgate.py is missing
   faxgate.py &>/dev/null
   if [ "$?" != "2" ]; then
      # tell it cups, exit and stop the printer
      echo "ERROR: faxgate.py not found or not executeable, exiting!" 1>&2
      exit 1
   # faxgate.py is ok then
   else
      # check if getjobopt is missing
      getjobopt &>/dev/null
      if [ "$?" != "1" ]; then
         # tell it cups, exit and stop the printer
         echo "ERROR: getjobopt not found or not executeable, exiting!" 1>&2
         exit 1
      # faxgate.py and getjobopt are ok then
      else
         # check if file with messages is missing
         if [ ! -f $MESSAGES ]; then
            # tell it cups, exit and stop printer
            echo "ERROR: $MESSAGES not found, exiting!" 1>&2
            exit 1
         fi
      fi
   fi
# if config is missing
else
   # tell it cups, exit and stop printer
   echo "ERROR: $CONFIG not found, exiting!" 1>&2
   exit 1
fi

# if no arguments given, print the uri scheme
if [ $# -eq 0 ]; then
   echo "file faxgate://capisuite \"Unknown\" \"Faxgate via Software-Faxmachine\""
   exit 0
fi

# if to less or to much arguments given, print usage help, and stop printer
if [ $# -ne 5 -a $# -ne 6 ]; then
   echo "Usage: faxgate job-id user title copies options [file]"
   echo "example for device-URI: 'faxgate:/local'"
   echo "Install a printqueue with 'lpadmin -p <faxgate-printer-name> -v faxgate -m Faxgate.ppd.gz -E'"
   echo "Currently only capisuite is supported!"
   exit 1;
fi

# Names of the arguments
     all="$@"
 printer="$0"
     job="$1"
    user="$2"
   title="$3"
  copies="$4"
 options="$5"
filename="$6"

# workaround for people who run cupsd not as root
if [ "$(id -u)" = "0" ]; then
   # if we are root we don't need sudo
   sudo=""
else
   # if cupsd runs not as root please configure sudo to allow the user
   # who runs cupsd to run capisuitefax as root
   sudo="sudo"
fi

#############
# functions #
#############

# function to save log and cleanup tempfiles
# 
function log_and_clean() {

	if [ "$DEBUG" -gt "0" ]; then
		# debug output
		# copy the printfile into tmpdir
		if [ "$filename" != "" -a "$filename" != "$TMPPRINTFILE" -a -e "$filename" ]; then
		    cp "$filename" "$TMPPRINTFILE" &>/dev/null
		fi
		echo -e "\n\n*****************************************************************************\n\n" >> "$TMPDIR"/faxgate.log
		echo -e "Temporary logfile from CUPS-Faxgate Backend\n" >> "$TMPDIR"/faxgate.log
		echo -e "Date and time: $(date)\n\nParameter:\nAll: $all" >> "$TMPDIR"/faxgate.log
		echo "0 - scriptname:     $printer" >> "$TMPDIR"/faxgate.log
		echo "1 - job-id:         $job" >> "$TMPDIR"/faxgate.log
		echo "2 - user:           $user" >> "$TMPDIR"/faxgate.log
		echo "3 - title/filename: $title" >> "$TMPDIR"/faxgate.log
		echo "4 - copies:         $copies" >> "$TMPDIR"/faxgate.log
		echo "5 - options:        $options" >> "$TMPDIR"/faxgate.log
		echo "6 - printfilename:  $filename" >> "$TMPDIR"/faxgate.log
		echo -e "\nThe environment:" >> "$TMPDIR"/faxgate.log
		echo "CHARSET:         $CHARSET" >> "$TMPDIR"/faxgate.log
		echo "CONTENT_TYPE:    $CONTENT_TYPE" >> "$TMPDIR"/faxgate.log
		echo "CUPS_DATADIR:    $CUPS_DATADIR" >> "$TMPDIR"/faxgate.log
		echo "CUPS_SERVERROOT: $CUPS_SERVERROOT" >> "$TMPDIR"/faxgate.log
		echo "DEVICE_URI:      $DEVICE_URI" >> "$TMPDIR"/faxgate.log
		echo "LANG:            $LANG" >> "$TMPDIR"/faxgate.log
		echo "PATH:            $PATH" >> "$TMPDIR"/faxgate.log
		echo "PPD:             $PPD" >> "$TMPDIR"/faxgate.log
		echo "PRINTER:         $PRINTER" >> "$TMPDIR"/faxgate.log
		echo "RIP_CACHE:       $RIP_CACHE" >> "$TMPDIR"/faxgate.log
		echo "SOFTWARE:        $SOFTWARE" >> "$TMPDIR"/faxgate.log
		echo "TZ:              $TZ" >> "$TMPDIR"/faxgate.log
		echo "USER:            $USER" >> "$TMPDIR"/faxgate.log
		echo "ID:              $(id -u)" >> "$TMPDIR"/faxgate.log
		echo "TMPDIR:          $TMPDIR" >> "$TMPDIR"/faxgate.log
		echo -e "\nVariables generated by $0" >> "$TMPDIR"/faxgate.log
		echo "Mailaddress:   $mailto" >> "$TMPDIR"/faxgate.log
		echo "Faxnumber:     $faxnumber" >> "$TMPDIR"/faxgate.log
		echo "Tempfile:      $TMPPRINTFILE" >> "$TMPDIR"/faxgate.log
		echo "Hostip:        $hostip" >> "$TMPDIR"/faxgate.log
		echo "Sudo:          $sudo" >> "$TMPDIR"/faxgate.log
		echo -e "\n\n*****************************************************************************" >> "$TMPDIR"/faxgate.log
	else
		# if tempfile created, delete it
		if [ "$TMPPRINTFILE" = "$printfile" ]; then
			if [ -e "$TMPPRINTFILE" ]; then
				rm "$TMPPRINTFILE"
			fi
		fi
		if [ -e "$TMPPRINTFILE.pdf" ]; then
			rm "$TMPPRINTFILE.pdf"
		fi
	fi

}

# check if user should be mapped to the default user
if [ "$DEF_USER" != "" ]; then
	IFS=","
	for name in $USERS; do
		if [ "$user" = "$name" ]; then
			user="$DEF_USER"
			break
		fi
	done
	unset IFS
fi

# check if the user is allowed to send faxes and set the mailaddress
# is user option nobody or empty
if [ "$user" = "nobody" -o "$user" = "" ]; then
	. $MESSAGES
	# tell it cups
	echo "$WRONGERR" 1>&2
	# tell it the faxmaster and exit
	if [ "$FAXMASTER" != "" ]; then
		faxgate.py --from="Faxgate Backend <$FAXMASTER>" --to="Faxmaster <$FAXMASTER>" \
		--subject="$WRONGSUB" --body="$WRONGBODY" -m 1>&2
	fi
	if [ "$FAXMASTERIP" != "" ]; then
		$sudo faxgate.py --user="Faxmaster" --ip="$FAXMASTERIP" --port="$PORT" --command="Warn_err: $WRONGERR" 1>&2
		if [ "$?" = "1" ]; then
			. $MESSAGES
			# tell it cups
			echo "$SUDOFERRERR" 1>&2
			# tell it the faxmaster and exit
			if [ "$FAXMASTER" != "" ]; then
				faxgate.py --from="Faxgate Backend <$FAXMASTER>" --to="Faxmaster <$FAXMASTER>" \
				--subject="$SUDOFERRORSUB" --body="$SUDOFERRORBODY" -m 1>&2
			fi
			log_and_clean
			exit 1
		fi
	fi
	log_and_clean
	exit 0
else
	# faxgate.py gives maildress back if user valid for faxsending, if invalid empty string
	mailto="$($sudo faxgate.py -u $user)"
	result="$?"
	# if capisuite reports a error
	if [ "$mailto" = "" ]; then
		. $MESSAGES
		if [ "$result" = "1" ]; then
			# tell it cups
			echo "$SUDOFERRERR" 1>&2
			# tell it the faxmaster and exit
			if [ "$FAXMASTER" != "" ]; then
				faxgate.py --from="Faxgate Backend <$FAXMASTER>" --to="Faxmaster <$FAXMASTER>" \
				--subject="$SUDOFERRORSUB" --body="$SUDOFERRORBODY" -m 1>&2
			fi
			log_and_clean
			exit 1
		fi
		# tell it cups
		echo "$CAPIERRERR" 1>&2
		# tell it the faxmaster and exit
		if [ "$FAXMASTER" != "" ]; then
			faxgate.py --from="Faxgate Backend <$FAXMASTER>" --to="Faxmaster <$FAXMASTER>" \
			--subject="$CAPIERRORSUB" --body="$CAPIERRORBODY" -m 1>&2
		fi
		if [ "$FAXMASTERIP" != "" ]; then
			$sudo faxgate.py --user="Faxmaster" --ip="$FAXMASTERIP" --port="$PORT" --command="Warn_err: $CAPIERRERR" 1>&2
		fi
		log_and_clean
		exit 0
	# first checks passed
	else
		. $MESSAGES
		# tell cups what is the next
		echo "$INFOGOOD" 1>&2
	fi
fi

# if 6 arguments given
if [ $# -eq 6 ]; then
	# the 6th is the printfile
	printfile="$filename"
else
	# if not the printfile comes via standard input
	cat > "$TMPPRINTFILE"
	printfile="$TMPPRINTFILE"
fi

###########################################################
# All argument-checks done,                               #
# since here the script should be called in a correct way #
###########################################################

###############################
# Start to find the faxnumber #
# and IP/hostname of host     #
###############################

# Set defaults
faxnumber=""
hostip=""
canceled="0"

# check first the options if a option faxnumber and/or ip is given
for option in $options; do
	case "$option" in
	# case pattern matches assign the number
	faxnumber=*)
		if [ "$USEOPTION" = "yes" ]; then
			# strip the unnecessary parts from the option, the faxnumber should be left over
			faxnumber=`echo "$option" | tr "++" "00" | tr -d [:alpha:] | tr -d [:punct:] | tr -d [:blank:]`
		fi
	;;
	# case option ip (from samba) given
	ip=*)
		if [ "$USECLIENT" = "yes" ]; then
			# assign it
			hostip="${option#ip=}"
		fi
	;;
	# else do nothing
	*) : ;;
	esac
done

# if there is no ip found before search it for later actions
if [ "$hostip" = "" -a "$USECLIENT" = "yes" ]; then
	# check the job-option via ipp-request
	ippjobopts="$(getjobopt ipp://localhost/jobs/"$job" | grep -ie job-originating-host-name)"
	# is the hostip/name in reply
	case "$ippjobopts" in
	# assign it
	job-originating-host-name=*)
		hostip="${ippjobopts#job-originating-host-name=}"
	;;
	# else do nothing
	*) : ;;
	esac
fi

# if there is still no faxnumber
if [ "$faxnumber" = "" -a "$USETITLE" = "yes" ]; then
	# check if the title (= normaly the filename) contains the keyword "faxto" in any case
	# since samba 3.x titel can contain more than one item
	for item in $title; do
		# if keyword previously matched
		if [ "$faxnumber" != "" ]; then
			# add all following items
			faxnumber=${faxnumber}${item}
 		fi
		# if keyword matches
		case "$item" in
		faxto*)
			faxnumber=${faxnumber}${item}
		;;
		FAXTO*)
			faxnumber=${faxnumber}${item}
		;;
		# else do nothing
		*) : ;;
		esac
	done
	# strip the unnecessary parts from the title, the faxnumber should be left over
	faxnumber=`echo $faxnumber | tr "++" "00" | tr -d [:alpha:] | tr -d [:punct:] | tr -d [:blank:]`
fi

# if there is still no faxnumber
if [ "$faxnumber" = "" -a "$USETEXT" = "yes" ]; then
	case "$SCANOPTION" in
	normal)
		psselect -p1 "$printfile" | ps2pdf -r9x9  -dDownsampleColorImages=true -dColorImageResolution=9  -dDownsampleGrayImages=true -dGrayImageResolution=9 - "$TMPPRINTFILE.pdf"
		command="ps2ascii $TMPPRINTFILE.pdf"
	;;
	all)
		ps2pdf -r9x9  -dDownsampleColorImages=true -dColorImageResolution=9  -dDownsampleGrayImages=true -dGrayImageResolution=9 "$printfile" "$TMPPRINTFILE.pdf"
		command="ps2ascii $TMPPRINTFILE.pdf"
	;;
	nopdf)
		command="psselect -p1 "$printfile" | ps2ascii"
	;;
	nopdfall)
		command="ps2ascii $printfile"
	;;
	# else do same as "normal"
	*)
		psselect -p1 "$printfile" | ps2pdf -r9x9  -dDownsampleColorImages=true -dColorImageResolution=9  -dDownsampleGrayImages=true -dGrayImageResolution=9 - "$TMPPRINTFILE.pdf"
		command="ps2ascii $TMPPRINTFILE.pdf"
	;;
	esac
	# check the postscriptfile for a faxnumber and assign it
	# the $0=$0 "xxx" is needed because a endline after the number causes problems with awk
	faxnumber="$($command | tr -d "[:blank:]" | awk '{ IGNORECASE=1 } /FAX-Nr ?.: ?[0-9-]*/ \
		{  $0=$0 "xxx"; \
			gsub(/-/,""); \
			anfang=match($0,/ ?: ?/); \
			anfang=anfang+match(substr($0,anfang),/[0-9]/)-1; \
			ende=match(substr($0,anfang),/[^0-9]/)-1; \
			printf ("%s",substr($0,anfang,ende)) \
		}')"
fi

# if there is still no faxnumber
if [ "$faxnumber" = ""  -a "$USECLIENT" = "yes" ]; then
	# use ip/hostname to connect to and ask for the number
	if [ "$hostip" != "" ]; then
		# try to connect to host an save the answer
		answer="$($sudo faxgate.py --user="$user" --ip="$hostip" --port="$PORT" --command="Question: faxnumber")"
		# connection was successfully
		if [ "$?" = "0" ]; then
			# the answer is the faxnumber
			faxnumber="$answer"
			# if now there is no number the user canceled
			if [ "$faxnumber" = "" ]; then
				canceled="1"
			fi
		else
			# print debugmessage
			echo "$answer" 1>&2
		fi
	fi
fi

##################################
# end of searching the faxnumber #
##################################

#####################################
# try to send the fax via capisuite #
#####################################

# if there is still no faxnumber
if [ "$faxnumber" = "" ]; then
	if [ "$canceled" -gt "0" ]; then
		# tell it cups
		echo "INFO: $USERCANCELED" 1>&2
		# tell it them self via network
		echo "DEBUG: $($sudo faxgate.py --user="$user" --ip="$hostip" --port="$PORT" --command="Info_snd: $USERCANCELED")" 1>&2
	else
		# tell it cups
		echo "$NONUMERR" 1>&2
		if [ "$WITH_MAIL" = "yes" ]; then
			# tell it the user
			faxgate.py --from="Faxgate Backend <$FAXMASTER>" --to="$mailto" \
			--subject="$NONUMSUB" --body="$NONUMBODY" -m 1>&2
			# tell it the user via network
			echo "DEBUG: $($sudo faxgate.py --user="$user" --ip="$hostip" --port="$PORT" --command="Warn_snd: $NONUMSUB")" 1>&2
		fi
	fi
# try to send fax
else
	# check the debug-level
	if [ "$DEBUG" -lt "2" ]; then
		# send the fax via capisuitefax and check if it was successfully
		sendingmessage="$($sudo capisuitefax -u "$user" -d "$faxnumber" -i "$hostip" -p "$PORT" "$printfile")"
		result="$?"
		if [ "$result" = "0" ]; then
			# tell it cups
			echo "INFO: $sendingmessage" 1>&2
			# page counting, only one for each job
			echo "PAGE: 1 $copies" 1>&2
		else
			if [ "$result" = "1" ]; then
				# tell it cups
				echo "$SUDOCERRERR" 1>&2
				# tell it the faxmaster and exit
				if [ "$FAXMASTER" != "" ]; then
					faxgate.py --from="Faxgate Backend <$FAXMASTER>" --to="Faxmaster <$FAXMASTER>" \
					--subject="$SUDOCERRORSUB" --body="$SUDOCERRORBODY" -m 1>&2
				fi
				log_and_clean
				exit 1
			else
				# print debugmessage to cups logfile
				echo "DEBUG: $sendingmessage" 1>&2
			fi
		fi
		# tell it the user via network
		echo "DEBUG: $($sudo faxgate.py --user="$user" --ip="$hostip" --port="$PORT" --command="Good_snd: $sendingmessage")" 1>&2
	fi
	# check log-level
	if [ "$LOG" = "yes" ]; then
		echo "User: ${user:-unknown} | Title: ${title:-unnamed} | Faxnumber: ${faxnumber:-empty} | Date: $(date)" >>"$LOGFILE"
	fi
fi

######################
# end of sending fax #
######################

log_and_clean

exit 0
