def callIncoming(call,service,call_from,call_to): # read config file and search for call_to in the user sections try: config=cs_helpers.readConfig() userlist=config.sections() userlist.remove('GLOBAL') curr_user="" for u in userlist: if config.has_option(u,'voice_numbers'): numbers=config.get(u,'voice_numbers') if (call_to in numbers.split(',') or numbers=="*"): if (service==capisuite.SERVICE_VOICE): curr_user=u curr_service=capisuite.SERVICE_VOICE break if (service==capisuite.SERVICE_FAXG3): curr_user=u curr_service=capisuite.SERVICE_FAXG3 break if config.has_option(u,'fax_numbers'): numbers=config.get(u,'fax_numbers') if (call_to in numbers.split(',') or numbers=="*"): if (service in (capisuite.SERVICE_FAXG3,capisuite.SERVICE_VOICE)): curr_user=u curr_service=capisuite.SERVICE_FAXG3 break except IOError,e: capisuite.error("Error occured during config file reading: "+e+" Disconnecting...") capisuite.reject(call,0x34A9) return
def sendfax(capi,job,outgoing_nr,dialstring,user,config): try: controller=int(cs_helpers.getOption(config,"","send_controller","1")) timeout=int(cs_helpers.getOption(config,user,"outgoing_timeout","60")) stationID=cs_helpers.getOption(config,user,"fax_stationID") if (stationID==None): capisuite.error("Warning: fax_stationID for user %s not set" % user) stationID="" headline=cs_helpers.getOption(config,user,"fax_headline","") (call,result)=capisuite.call_faxG3(capi,controller,outgoing_nr,dialstring,timeout,stationID,headline) if (result!=0): return(result,0) capisuite.fax_send(call,job) return(capisuite.disconnect(call)) except capisuite.CallGoneError: return(capisuite.disconnect(call))
def callIncoming(call, service, fax_caller, fax_callee): timenow = time.localtime() fax_stationid = '' fax_bitrate = '' fax_resolution = '' fax_color = '' fax_error = (-1, -1) fax_pdffile = '' error = 0 # open config try: cfg = mfconfig.config(os.path.join(homepath, 'mrfaxe.conf')) except mfconfig.Error, e: capisuite.error('Failed to read config file: ' + str(e)) capisuite.reject(call, 0x34A9) return
def idle(capi): config=cs_helpers.readConfig() spool=cs_helpers.getOption(config,"","spool_dir") if (spool==None): capisuite.error("global option spool_dir not found.") return done=os.path.join(spool,"done") failed=os.path.join(spool,"failed") if (not os.access(done,os.W_OK) or not os.access(failed,os.W_OK)): capisuite.error("Can't read/write to the necessary spool dirs") return userlist=config.sections() userlist.remove('GLOBAL') for user in userlist: # search in all user-specified sendq's userdata=pwd.getpwnam(user) outgoing_nr=cs_helpers.getOption(config,user,"outgoing_MSN","") if (outgoing_nr==""): incoming_nrs=cs_helpers.getOption(config,user,"fax_numbers","") if (incoming_nrs==""): continue else: outgoing_nr=(incoming_nrs.split(','))[0] udir=cs_helpers.getOption(config,"","fax_user_dir") if (udir==None): capisuite.error("global option fax_user_dir not found.") return udir=os.path.join(udir,user) sendq=os.path.join(udir,"sendq") if (not os.access(udir,os.F_OK)): os.mkdir(udir,0700) os.chown(udir,userdata[2],userdata[3]) if (not os.access(sendq,os.F_OK)): os.mkdir(sendq,0700) os.chown(sendq,userdata[2],userdata[3]) files=os.listdir(sendq) files=filter (lambda s: re.match("fax-.*\.txt",s),files) for job in files: job_fax="%ssff" % job[:-3] real_user_c=os.stat(os.path.join(sendq,job)).st_uid real_user_j=os.stat(os.path.join(sendq,job_fax)).st_uid if (real_user_j!=pwd.getpwnam(user)[2] or real_user_c!=pwd.getpwnam(user)[2]): capisuite.error("job %s seems to be manipulated (wrong uid)! Ignoring..." % os.path.join(sendq,job_fax)) continue lockfile=open(os.path.join(sendq,"%slock" % job[:-3]),"w") # read directory contents fcntl.lockf(lockfile,fcntl.LOCK_EX) # lock so that it isn't deleted while sending if (not os.access(os.path.join(sendq,job),os.W_OK)): # perhaps it was cancelled? fcntl.lockf(lockfile,fcntl.LOCK_UN) lockfile.close() os.unlink(os.path.join(sendq,"%slock" % job[:-3])) continue control=cs_helpers.readConfig(os.path.join(sendq,job)) # set DST value to -1 (unknown), as strptime sets it wrong for some reason starttime=(time.strptime(control.get("GLOBAL","starttime")))[0:8]+(-1,) starttime=time.mktime(starttime) if (starttime>time.time()): fcntl.lockf(lockfile,fcntl.LOCK_UN) lockfile.close() os.unlink(os.path.join(sendq,"%slock" % job[:-3])) continue tries=control.getint("GLOBAL","tries") dialstring=control.get("GLOBAL","dialstring") addressee=cs_helpers.getOption(control,"GLOBAL","addressee","") subject=cs_helpers.getOption(control,"GLOBAL","subject","") mailaddress=cs_helpers.getOption(config,user,"fax_email","") if (mailaddress==""): mailaddress=user fromaddress=cs_helpers.getOption(config,user,"fax_email_from","") if (fromaddress==""): fromaddress=user capisuite.log("job %s from %s to %s initiated" % (job_fax,user,dialstring),1) result,resultB3 = sendfax(capi,os.path.join(sendq,job_fax),outgoing_nr,dialstring,user,config) tries+=1 capisuite.log("job %s: result was %x,%x" % (job_fax,result,resultB3),1) if (result in (0,0x3400,0x3480,0x3490,0x349f) and resultB3==0): movejob(job_fax,sendq,done,user) capisuite.log("job %s: finished successfully" % job_fax,1) mailtext="Your fax job to %s (%s) was sent successfully.\n\n" \ "Subject: %s\nFilename: %s\nNeeded tries: %i\n" \ "Last result: 0x%x/0x%x\n\nIt was moved to " \ "file://%s on host \"%s\"" % (addressee,dialstring, \ subject,job_fax,tries,result,resultB3, \ os.path.join(done,"%s-%s" % (user,job_fax)), \ os.uname()[1]) cs_helpers.sendSimpleMail(fromaddress,mailaddress, "Fax to %s (%s) sent successfully." % (addressee,dialstring), mailtext) else: max_tries=int(cs_helpers.getOption(config,"","send_tries","10")) delays=cs_helpers.getOption(config,"","send_delays","60,60,60,300,300,3600,3600,18000,36000").split(",") delays=map(int,delays) if ((tries-1)<len(delays)): next_delay=delays[tries-1] else: next_delay=delays[-1] starttime=time.time()+next_delay capisuite.log("job %s: delayed for %i seconds" % (job_fax,next_delay),2) cs_helpers.writeDescription(os.path.join(sendq,job_fax), \ "dialstring=\"%s\"\nstarttime=\"%s\"\ntries=\"%i\"\n" \ "user=\"%s\"\naddressee=\"%s\"\nsubject=\"%s\"\n" \ % (dialstring,time.ctime(starttime),tries,user, \ addressee,subject)) if (tries>=max_tries): movejob(job_fax,sendq,failed,user) capisuite.log("job %s: failed finally" % job_fax,1) mailtext="I'm sorry, but your fax job to %s (%s) " \ "failed finally.\n\nSubject: %s\n" \ "Filename: %s\nTries: %i\n" \ "Last result: 0x%x/0x%x\n\n" \ "It was moved to file://%s-%s on host %s.\n\n" \ % (addressee,dialstring,subject,job_fax,tries,result, \ resultB3,os.path.join(failed,user),job_fax,os.uname()[1]) cs_helpers.sendSimpleMail(fromaddress,mailaddress, "Fax to %s (%s) FAILED." % (addressee,dialstring), mailtext) fcntl.lockf(lockfile,fcntl.LOCK_UN) lockfile.close() os.unlink("%slock" % os.path.join(sendq,job[:-3]))
# open config try: cfg = mfconfig.config(os.path.join(homepath, 'mrfaxe.conf')) except mfconfig.Error, e: capisuite.error('Failed to read config file: ' + str(e)) capisuite.reject(call, 0x34A9) return # chek if all needed config settings are set miss = cfg.exists(('stationid', 'headline', 'delay', 'tempdir', 'temppref', 'savedir', 'savepref', 'dbfile', 'printing', 'printer', 'printsrv', 'papersize', 'sfftobmp', 'tiff2pdf', 'lp')) if not miss is None: capisuite.error('Missing settings in config' + str(miss)) capisuite.reject(call, 0x34A9) return del(miss) # ceck if if the external tools exists try: if not os.path.exists(cfg.get('sfftobmp')): raise Exception(cfg.get('sfftobmp')) if not os.path.exists(cfg.get('tiff2pdf')): raise Exception(cfg.get('tiff2pdf')) if not os.path.exists(cfg.get('lp')) and cfg.getbool('printing'): raise Exception(cfg.get('lp')) except Exception, e: capisuite.error(str(e) + ' missing but needed') capisuite.reject(call, 0x34A9)
def faxIncoming(call,call_from,call_to,curr_user,config,already_connected): try: udir=cs_helpers.getOption(config,"","fax_user_dir") if (udir==None): capisuite.error("global option fax_user_dir not found! -> rejecting call") capisuite.reject(call,0x34A9) return udir=os.path.join(udir,curr_user)+"/" if (not os.access(udir,os.F_OK)): userdata=pwd.getpwnam(curr_user) os.mkdir(udir,0700) os.chown(udir,userdata[2],userdata[3]) if (not os.access(udir+"received/",os.F_OK)): userdata=pwd.getpwnam(curr_user) os.mkdir(udir+"received/",0700) os.chown(udir+"received/",userdata[2],userdata[3]) except KeyError: capisuite.error("user "+curr_user+" is not a valid system user. Disconnecting",call) capisuite.reject(call,0x34A9) return filename="" # assure the variable is defined... try: stationID=cs_helpers.getOption(config,curr_user,"fax_stationID") if (stationID==None): capisuite.error("Warning: fax_stationID not found for user "+curr_user+" -> using empty string") stationID="" headline=cs_helpers.getOption(config,curr_user,"fax_headline","") # empty string is no problem here capisuite.log("call from "+call_from+" to "+call_to+" for "+curr_user+" connecting with fax",1,call) if (already_connected): faxInfo=capisuite.switch_to_faxG3(call,stationID,headline) else: faxInfo=capisuite.connect_faxG3(call,stationID,headline,0) if (faxInfo!=None and faxInfo[3]==1): faxFormat="cff" # color fax else: faxFormat="sff" # normal b&w fax filename=cs_helpers.uniqueName(udir+"received/","fax",faxFormat) capisuite.fax_receive(call,filename) (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call) except capisuite.CallGoneError: # catch this here to get the cause info in the mail (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call) if (os.access(filename,os.R_OK)): cs_helpers.writeDescription(filename, "call_from=\""+call_from+"\"\ncall_to=\""+call_to+"\"\ntime=\"" +time.ctime()+"\"\ncause=\"0x%x/0x%x\"\n" % (cause,causeB3)) userdata=pwd.getpwnam(curr_user) os.chmod(filename,0600) os.chown(filename,userdata[2],userdata[3]) os.chmod(filename[:-3]+"txt",0600) os.chown(filename[:-3]+"txt",userdata[2],userdata[3]) fromaddress=cs_helpers.getOption(config,curr_user,"fax_email_from","") if (fromaddress==""): fromaddress=curr_user mailaddress=cs_helpers.getOption(config,curr_user,"fax_email","") if (mailaddress==""): mailaddress=curr_user action=cs_helpers.getOption(config,curr_user,"fax_action","").lower() if (action not in ("mailandsave","saveonly")): capisuite.error("Warning: No valid fax_action definition found for user "+curr_user+" -> assuming SaveOnly") action="saveonly" if (action=="mailandsave"): cs_helpers.sendMIMEMail(fromaddress, mailaddress, "Fax received from "+call_from+" to "+call_to, faxFormat, "You got a fax from "+call_from+" to "+call_to+"\nDate: "+time.ctime()+"\n\n" +"See attached file.\nThe original file was saved to file://"+filename+"\n\n", filename)
def voiceIncoming(call,call_from,call_to,curr_user,config): try: udir=cs_helpers.getOption(config,"","voice_user_dir") if (udir==None): capisuite.error("global option voice_user_dir not found! -> rejecting call") capisuite.reject(call,0x34A9) return udir=os.path.join(udir,curr_user)+"/" if (not os.access(udir,os.F_OK)): userdata=pwd.getpwnam(curr_user) os.mkdir(udir,0700) os.chown(udir,userdata[2],userdata[3]) if (not os.access(udir+"received/",os.F_OK)): userdata=pwd.getpwnam(curr_user) os.mkdir(udir+"received/",0700) os.chown(udir+"received/",userdata[2],userdata[3]) except KeyError: capisuite.error("user "+curr_user+" is not a valid system user. Disconnecting",call) capisuite.reject(call,0x34A9) return filename=cs_helpers.uniqueName(udir+"received/","voice","la") action=cs_helpers.getOption(config,curr_user,"voice_action","").lower() if (action not in ("mailandsave","saveonly","none")): capisuite.error("Warning: No valid voice_action definition found for user "+curr_user+" -> assuming SaveOnly") action="saveonly" try: capisuite.enable_DTMF(call) userannouncement=udir+cs_helpers.getOption(config,curr_user,"announcement","announcement.la") pin=cs_helpers.getOption(config,curr_user,"pin","") if (os.access(userannouncement,os.R_OK)): capisuite.audio_send(call,userannouncement,1) else: if (call_to!="-"): capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"anrufbeantworter-von.la"),1) cs_helpers.sayNumber(call,call_to,curr_user,config) capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"bitte-nachricht.la"),1) if (action!="none"): capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la"),1) length=cs_helpers.getOption(config,curr_user,"record_length","60") silence_timeout=cs_helpers.getOption(config,curr_user,"record_silence_timeout","5") capisuite.audio_receive(call,filename,int(length), int(silence_timeout),1) dtmf_list=capisuite.read_DTMF(call,0) if (dtmf_list=="X"): if (os.access(filename,os.R_OK)): os.unlink(filename) faxIncoming(call,call_from,call_to,curr_user,config,1) elif (dtmf_list!="" and pin!=""): dtmf_list+=capisuite.read_DTMF(call,3) # wait 5 seconds for input count=1 while (count<3 and pin!=dtmf_list): # try again if input was wrong capisuite.log("wrong PIN entered...",1,call) capisuite.audio_send(call,cs_helpers.getAudio(config,curr_user,"beep.la")) dtmf_list=capisuite.read_DTMF(call,3) count+=1 if (pin==dtmf_list): if (os.access(filename,os.R_OK)): os.unlink(filename) capisuite.log("Starting remote inquiry...",1,call) remoteInquiry(call,udir,curr_user,config) (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call) except capisuite.CallGoneError: # catch this here to get the cause info in the mail (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call) if (os.access(filename,os.R_OK)): cs_helpers.writeDescription(filename, "call_from=\""+call_from+"\"\ncall_to=\""+call_to+"\"\ntime=\"" +time.ctime()+"\"\ncause=\"0x%x/0x%x\"\n" % (cause,causeB3)) userdata=pwd.getpwnam(curr_user) os.chmod(filename,0600) os.chown(filename,userdata[2],userdata[3]) os.chmod(filename[:-2]+"txt",0600) os.chown(filename[:-2]+"txt",userdata[2],userdata[3]) fromaddress=cs_helpers.getOption(config,curr_user,"voice_email_from","") if (fromaddress==""): fromaddress=curr_user mailaddress=cs_helpers.getOption(config,curr_user,"voice_email","") if (mailaddress==""): mailaddress=curr_user if (action=="mailandsave"): cs_helpers.sendMIMEMail(fromaddress, mailaddress, "Voice call received from "+call_from+" to "+call_to, "la", "You got a voice call from "+call_from+" to "+call_to+"\nDate: "+time.ctime()+"\n\n" +"See attached file.\nThe original file was saved to file://"+filename+"\n\n", filename)
break except IOError,e: capisuite.error("Error occured during config file reading: "+e+" Disconnecting...") capisuite.reject(call,0x34A9) return # answer the call with the right service if (curr_user==""): capisuite.log("call from "+call_from+" to "+call_to+" ignoring",1,call) capisuite.reject(call,1) return try: if (curr_service==capisuite.SERVICE_VOICE): delay=cs_helpers.getOption(config,curr_user,"voice_delay") if (delay==None): capisuite.error("voice_delay not found for user "+curr_user+"! -> rejecting call") capisuite.reject(call,0x34A9) return capisuite.log("call from "+call_from+" to "+call_to+" for "+curr_user+" connecting with voice",1,call) capisuite.connect_voice(call,int(delay)) voiceIncoming(call,call_from,call_to,curr_user,config) elif (curr_service==capisuite.SERVICE_FAXG3): faxIncoming(call,call_from,call_to,curr_user,config,0) except capisuite.CallGoneError: # catch exceptions from connect_* (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call) # @brief called by callIncoming when an incoming fax call is received # # @param call reference to the call. Needed by all capisuite functions # @param call_from string containing the number of the calling party
def faxIncoming(call,call_from,call_to,curr_user,config,already_connected): try: udir=cs_helpers.getOption(config,"","fax_user_dir") if (udir==None): capisuite.error("global option fax_user_dir not found! -> rejecting call") capisuite.reject(call,0x34A9) return udir=os.path.join(udir,curr_user) if (not os.path.exists(udir)): userdata=pwd.getpwnam(curr_user) os.mkdir(udir,0700) os.chown(udir,userdata[2],userdata[3]) if (not os.path.exists(os.path.join(udir,"received"))): userdata=pwd.getpwnam(curr_user) os.mkdir(os.path.join(udir,"received"),0700) os.chown(os.path.join(udir,"received"),userdata[2],userdata[3]) except KeyError: capisuite.error("user %s is not a valid system user. Disconnecting" % curr_user,call) capisuite.reject(call,0x34A9) return filename="" # assure the variable is defined... faxInfo=None try: stationID=cs_helpers.getOption(config,curr_user,"fax_stationID") if (stationID==None): capisuite.error("Warning: fax_stationID not found for user %s -> using empty string" % curr_user) stationID="" headline=cs_helpers.getOption(config,curr_user,"fax_headline","") # empty string is no problem here capisuite.log("call from %s to %s for %s connecting with fax" % (call_from,call_to,curr_user),1,call) if (already_connected): faxInfo=capisuite.switch_to_faxG3(call,stationID,headline) else: faxInfo=capisuite.connect_faxG3(call,stationID,headline,0) if (faxInfo!=None and faxInfo[3]==1): faxFormat="cff" # color fax else: faxFormat="sff" # normal b&w fax filename=cs_helpers.uniqueName(os.path.join(udir,"received"),"fax",faxFormat) faxInfo=capisuite.fax_receive(call,filename) (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection finished with cause 0x%x,0x%x" % (cause,causeB3),1,call) except capisuite.CallGoneError: # catch this here to get the cause info in the mail (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call) if (os.access(filename,os.R_OK)): cs_helpers.writeDescription(filename, "call_from=\"%s\"\ncall_to=\"%s\"\ntime=\"%s\"\n" \ "cause=\"0x%x/0x%x\"\n" % (call_from,call_to,time.ctime(),cause,causeB3)) userdata=pwd.getpwnam(curr_user) os.chmod(filename,0600) os.chown(filename,userdata[2],userdata[3]) os.chmod("%stxt" % filename[:-3],0600) os.chown("%stxt" % filename[:-3],userdata[2],userdata[3]) fromaddress=cs_helpers.getOption(config,curr_user,"fax_email_from","") if (fromaddress==""): fromaddress=curr_user mailaddress=cs_helpers.getOption(config,curr_user,"fax_email","") if (mailaddress==""): mailaddress=curr_user action=cs_helpers.getOption(config,curr_user,"fax_action","").lower() if (action not in ("mailandsave","saveonly")): capisuite.error("Warning: No valid fax_action definition found for user %s -> assuming SaveOnly" % curr_user) action="saveonly" if (action=="mailandsave"): mailText="You got a fax from %s to %s\nDate: %s" % (call_from,call_to,time.ctime()) if (faxInfo!=None and len(faxInfo)>=5): mailText="%sStation ID: %s\nTransmission Details: bit rate %i " \ "%s %s\nPages: %i\n\nSee attached file.\n" \ "The original file was saved to file://%s " \ "on host \"%s\"." % (mailText,faxInfo[0], \ faxInfo[1],(faxInfo[2] and "hiRes" or "loRes"), \ (faxInfo[3] and "color" or ""),faxInfo[4], \ fileName,os.uname()[1]) cs_helpers.sendMIMEMail(fromaddress, mailaddress, "Fax received from %s to %s" % (call_from,call_to), faxFormat, mailText, filename)
break except IOError,e: capisuite.error("Error occured during config file reading: %s Disconnecting..." % e) capisuite.reject(call,0x34A9) return # answer the call with the right service if (curr_user==""): capisuite.log("call from %s to %s ignoring" % (call_from,call_to),1,call) capisuite.reject(call,1) return try: if (curr_service==capisuite.SERVICE_VOICE): delay=cs_helpers.getOption(config,curr_user,"voice_delay") if (delay==None): capisuite.error("voice_delay not found for user %s! -> rejecting call" % curr_user) capisuite.reject(call,0x34A9) return capisuite.log("call from %s to %s for %s connecting with voice" % (call_from,call_to,curr_user),1,call) capisuite.connect_voice(call,int(delay)) voiceIncoming(call,call_from,call_to,curr_user,config) elif (curr_service==capisuite.SERVICE_FAXG3): faxIncoming(call,call_from,call_to,curr_user,config,0) except capisuite.CallGoneError: # catch exceptions from connect_* (cause,causeB3)=capisuite.disconnect(call) capisuite.log("connection lost with cause 0x%x,0x%x" % (cause,causeB3),1,call) # @brief called by callIncoming when an incoming fax call is received # # @param call reference to the call. Needed by all capisuite functions # @param call_from string containing the number of the calling party