#!/usr/bin/python
#
#             capisuitefax - capisuite tool for enqueuing faxes
#            ---------------------------------------------------
#    copyright            : (C) 2002 by Gernot Hillier
#    email                : gernot@hillier.de
#    version              : $Revision: 1.7 $
#
#  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.

import getopt,os,sys,re,time,pwd,errno,fcntl,string
# capisuite stuff
import cs_helpers

dialstring=""
addressee=""
subject=""
abort=""
user=""
quiet=0
listqueue=0
useprefix=1

def usage(error=""):
	print """capisuitefax - capisuite tool for enqueueing faxes

usage:
capisuitefax [<send options>] -d <number> file1 [file2...] or
capisuitefax [-q] -a <id>
capisuitefax -l
capisuitefax -h

possible send options are:

-d <dial>, --dialstring=<dial>	send fax to this number (mandatory)
-n, --noprefix			ignore configured dial prefix for this call
				(for internal calls)
-u <user>, --user=<user>	send fax as <user> (only when called as root!)
-A <addr>, --addressee=<addr>	addressee (for informational purposes)
-S <subj>, --subject=<subj>	some subject (for informational purposes)

other options:

-q, --quiet			be quiet, don't output informational messages
-a <id>, --abort=<id>		abort fax job with id (id is a number)
-h, --help			print this usage information
-l, --list			print jobs in the send queue

The given files must be in Adobe PostScript or PDF format"""
	if (error!=""):
		print
		print "ERROR:",error
	sys.exit(1)

def showlist(config,user):
	sendq=cs_helpers.getOption(config,"","fax_user_dir")
	if (sendq==None):
		print "ERROR: option fax_user_dir not set in fax configuration"
		sys.exit(1)
	sendq=os.path.join(sendq,user,"sendq")+"/"

	print "ID	Nr./Addressee	Tries	Next try			Subject"

	files=os.listdir(sendq)
	files=filter (lambda s: re.match("fax-.*\.txt",s),files)
	if (not len(files)):
		print "--- queue empty ---"

	for job in files:
		control=cs_helpers.readConfig(sendq+job)
		sys.stdout.write(re.match("fax-([0-9]+)\.txt",job).group(1))
		sys.stdout.write("\t")
		dest=cs_helpers.getOption(control,"GLOBAL","addressee","")
		if (dest==""):
			dest=control.get("GLOBAL","dialstring")
		sys.stdout.write(dest+"\t")
		if (len(dest)<8):
			sys.stdout.write("\t")
		sys.stdout.write(control.get("GLOBAL","tries")+"\t")
		sys.stdout.write(control.get("GLOBAL","starttime")+"\t")
		sys.stdout.write(cs_helpers.getOption(control,"GLOBAL","subject","")+"\n")

	sys.exit(0)

def abortjob(config,user,job):
	sendq=cs_helpers.getOption(config,"","fax_user_dir")
	if (sendq==None):
		print "ERROR: option fax_user_dir not set in fax configuration"
		sys.exit(1)
	sendq=os.path.join(sendq,user,"sendq")+"/"
	job="fax-"+job+".txt"

	if (not os.access(sendq+job,os.W_OK)):
		print "job to abort not valid"
		sys.exit(1)

	try:
		lockfile=open(sendq+job[:-3]+"lock","w")
		# lock so that it isn't deleted while sending
		fcntl.lockf(lockfile,fcntl.LOCK_EX | fcntl.LOCK_NB)
		os.unlink(sendq+job)
		os.unlink(sendq+job[:-3]+"sff")
		fcntl.lockf(lockfile,fcntl.LOCK_UN)
		os.unlink(sendq+job[:-3]+"lock")
	except IOError,err:
		if (err.errno in (errno.EACCES,errno.EAGAIN)):
			print "Job is currently in transmission. Can't abort."

try:
	optlist,args = getopt.getopt(sys.argv[1:], "d:a:u:lhqnA:S:"
	  ,['dialstring=','noprefix','help',"abort=","list","quiet","user=",
	    'addressee=','subject='])

except getopt.GetoptError, e:
	usage(e.msg)

# read options
for option,param in optlist:
	if option in ('-d','--dialstring'): dialstring=param
	if option in ('-A','--addressee'): addressee=param
	if option in ('-S','--subject'): subject=param
	if option in ('-n','--noprefix'): useprefix=0
	if option in ('-h','--help'): usage()
	if option in ('-l','--list'): listqueue=1
	if option in ('-a','--abort'): abort=param
	if option in ('-q','--quiet'): quiet=1
	if option in ('-u','--user'):
		if (os.getuid()==0):
			user=param
		else:
			usage("--user may only used as root!")

if (not abort and not listqueue and not dialstring):
	usage("No usable command given.")

# filter out common separators from dialstring, check it
dialstring=dialstring.translate(string.maketrans("",""),"-/ ()")
for i in dialstring:
	if ((i>'9' or i<'0') and i not in ('+*#')):
		usage("Invalid dialstring given.")

if (dialstring and len(args)==0):
	usage("No fax files given")

# test if this user is allowed to send faxes
config=cs_helpers.readConfig()
if (user==""):
	user=pwd.getpwuid(os.getuid())[0]
if (not config.has_section(user)):
	print "Sorry, you're no valid user for CapiSuite"
	sys.exit(1)

if ((cs_helpers.getOption(config,user,"outgoing_MSN","")=="") and (config.get(user,"fax_numbers","")=="")):
	print "Sorry, you're not allowed to use fax services"
	sys.exit(1)

# test environment
sendq=cs_helpers.getOption(config,"","fax_user_dir")
if (sendq==None):
	print "ERROR: option fax_user_dir not set in fax configuration"
	sys.exit(1)
sendq=os.path.join(sendq,user,"sendq")+"/"
if (not os.access(sendq,os.W_OK)):
	print "can't write to queue dir"
	sys.exit(1)

if (listqueue):
	showlist(config,user)

if (abort):
	abortjob(config,user,abort)

prefix=cs_helpers.getOption(config,user,"dial_prefix","")
if (useprefix):
	dialstring=prefix+dialstring

# convert and enqueue files
for i in args:
	if (not os.access(i,os.R_OK)):
		sys.stderr.write("can't open "+i+'\n')
		continue
	t=os.popen("file -b -i "+cs_helpers.escape(i)+" 2>/dev/null")
	filetype=t.read()
	if (t.close()):
		usage("can't execute \"file\"")
	if (not re.search("application/postscript",filetype) \
	  and not re.search("application/pdf",filetype)):
		sys.stderr.write(i+" is not a PostScript/PDF file\n")
		continue

	newname=cs_helpers.uniqueName(sendq,"fax","sff")

	command="gs -dNOPAUSE -dQUIET -dBATCH -sPAPERSIZE=a4 -sDEVICE=cfax -sOutputFile=" \
	  + newname+" "+cs_helpers.escape(i)
	ret=(os.system(command))>>8
	if (ret):
		sys.stderr.write("error during SFF-conversion at file "+i+'. \
		Ghostscript not installed?\n')
		sys.exit()

	cs_helpers.writeDescription(newname,"dialstring=\""+dialstring+"\"\n"
	  +"starttime=\""+time.ctime()+"\"\ntries=\"0\"\n"
	  +"user=\""+user+"\"\naddressee=\""+addressee+"\"\nsubject=\""
	  +subject+"\"\n")
	os.chmod(newname,0600)
	os.chmod(newname[:-3]+"txt",0600)
	if (os.getuid()==0):
		user_entry=pwd.getpwnam(user)
		os.chown(newname,user_entry[2],user_entry[3])
		os.chown(newname[:-3]+"txt",user_entry[2],user_entry[3])
	print i,"successful enqueued as",newname,"for",dialstring
