root/modules/branches/2.10/fax/functions.inc.php

Revision 14227, 35.7 kB (checked in by mbrevda, 11 months ago)

re #5906 - php < 5.2 doesnt set filename

Line 
1 <?php
2 /* $Id */
3 if (!defined('FREEPBX_IS_AUTH')) { die('No direct script access allowed'); }
4
5 function fax_getdest($exten) {
6     return array("ext-fax,$exten,1");
7 }
8
9 function fax_getdestinfo($dest) {
10   global $amp_conf;
11     if (substr(trim($dest),0,8) == 'ext-fax,') {
12         $usr = explode(',',$dest);
13         $usr = $usr[1];
14         $thisusr = fax_get_user($usr);
15         if (empty($thisusr)) {
16             return array();
17         } else {
18             $display = ($amp_conf['AMPEXTENSIONS'] == "deviceanduser")?'users':'extensions';
19             return array('description' => sprintf(_("Fax user %s"),$usr),
20                          'edit_url' => 'config.php?display='.$display.'&extdisplay='.urlencode($usr),
21                                   );
22         }
23     } else {
24         return false;
25     }
26 }
27
28 function fax_check_destinations($dest=true) {
29     global $active_modules;
30
31     $destlist = array();
32     if (is_array($dest) && empty($dest)) {
33         return $destlist;
34     }
35     $sql = "SELECT a.extension, a.cidnum, b.description, a.destination FROM fax_incoming a JOIN incoming b ";
36   $sql .= "WHERE a.extension = b.extension AND a.cidnum = b.cidnum AND a.legacy_email IS NULL ";
37     if ($dest !== true) {
38         $sql .= "AND a.destination in ('".implode("','",$dest)."') ";
39     }
40     $sql .= "ORDER BY extension, cidnum";
41     $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
42
43     //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
44
45     foreach ($results as $result) {
46         $thisdest = $result['destination'];
47         $thisid   = $result['extension'].'/'.$result['cidnum'];
48         $destlist[] = array(
49             'dest' => $thisdest,
50             'description' => sprintf(_("Inbound Fax Detection: %s (%s)"),$result['description'],$thisid),
51             'edit_url' => 'config.php?display=did&extdisplay='.urlencode($thisid),
52         );
53     }
54     return $destlist;
55 }
56
57 function fax_change_destination($old_dest, $new_dest) {
58     $sql = 'UPDATE fax_incoming SET destination = "' . $new_dest . '" WHERE destination = "' . $old_dest . '"';
59     sql($sql, "query");
60 }
61
62 function fax_applyhooks() {
63     global $currentcomponent;
64     // Add the 'process' function - this gets called when the page is loaded, to hook into
65     // displaying stuff on the page.
66     $currentcomponent->addguifunc('fax_configpageload');
67 }
68
69 // This is called before the page is actually displayed, so we can use addguielem(). draws hook on the extensions/users page
70 function fax_configpageload() {
71     global $currentcomponent;
72     global $display;
73     $extdisplay=isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:'';
74     $extensions=isset($_REQUEST['extensions'])?$_REQUEST['extensions']:'';
75     $users=isset($_REQUEST['users'])?$_REQUEST['users']:'';
76     
77     if ($display == 'extensions' || $display == 'users') {
78         if($extdisplay!=''){
79             $fax=fax_get_user($extdisplay);
80             $faxenabled=$fax['faxenabled'];
81             $faxemail=$fax['faxemail'];
82         }//get settings in to variables
83         $section = _('Fax');
84         $toggleemail='if($(this).attr(\'checked\')){$(\'[id^=fax]\').removeAttr(\'disabled\');}else{$(\'[id^=fax]\').attr(\'disabled\',\'true\');$(this).removeAttr(\'disabled\');}';
85         //check for fax prequsits, and alert the user if something is amiss
86         $fax=fax_detect();
87         if(!$fax['module']){//missing modules
88             $currentcomponent->addguielem($section, new gui_label('error','<font color="red">'._('ERROR: No FAX modules detected!<br>Fax-related dialplan will <b>NOT</b> be generated.<br>This module requires Fax for Asterisk or spandsp based app_fax or app_rxfax to function.').'</font>'));
89         }elseif($fax['ffa'] && $fax['license'] < 1){//missing license
90             $currentcomponent->addguielem($section, new gui_label('error','<font color="red">'._('ERROR: No Fax license detected.<br>Fax-related dialplan will <b>NOT</b> be generated!<br>This module has detected that Fax for Asterisk is installed without a license.<br>At least one license is required (it is available for free) and must be installed.').'</font>'));
91         }
92         $usage_list = framework_display_destination_usage(fax_getdest($extdisplay));
93         if (!empty($usage_list)) {
94             $currentcomponent->addguielem('_top', new gui_link_label('faxdests', "&nbsp;Fax".$usage_list['text'], $usage_list['tooltip'], true), 5);
95         }
96         
97         $currentcomponent->addguielem($section, new gui_checkbox('faxenabled',$faxenabled,_('Enabled'), _('Enable this user to receive faxes'),'true','',$toggleemail));
98         $currentcomponent->addguielem($section, new gui_textbox('faxemail', $faxemail, _('Fax Email'), _('Enter an email address where faxes sent to this extension will be delivered.'), '!isEmail()', _('Please Enter a valid email address for fax delivery.'), TRUE, '', ($faxenabled == 'true')?'':'true'));
99     }
100 }
101
102 function fax_configpageinit($pagename) {
103     global $currentcomponent;
104     // On a 'new' user, 'tech_hardware' is set, and there's no extension.
105     if (
106         isset($_REQUEST['display'])
107         && ($_REQUEST['display'] == 'users' || $_REQUEST['display'] == 'extensions')
108         && isset($_REQUEST['extdisplay'])
109         && $_REQUEST['extdisplay'] != ''
110     ) {
111         $currentcomponent->addprocessfunc('fax_configpageload', 1);
112         $currentcomponent->addprocessfunc('fax_configprocess', 1);
113     }
114 }
115
116 //prosses received arguments
117 function fax_configprocess() {
118     $action        = isset($_REQUEST['action']) ?$_REQUEST['action']:null;
119     $ext        = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:$_REQUEST['extension'];
120     $faxenabled    = isset($_REQUEST['faxenabled'])?$_REQUEST['faxenabled']:null;
121     $faxemail    = isset($_REQUEST['faxemail'])?$_REQUEST['faxemail']:null;
122     switch ($action) {
123         case 'edit':
124             fax_save_user($ext,$faxenabled,$faxemail);
125              break;
126         case 'del':
127             fax_delete_user($ext);
128             break;
129         }
130 }
131
132 function fax_dahdi_faxdetect(){
133     /*
134      * kepping this always set to true for freepbx 2.7 as we cant currently properly detect this - MB
135      *
136      */
137   return true;
138 }
139
140 function fax_delete_incoming($extdisplay){
141     global $db;
142     $opts        = explode('/', $extdisplay);
143     $extension    = $opts['0'];
144     $cidnum        = $opts['1']; //set vars
145     sql("DELETE FROM fax_incoming WHERE cidnum = '"
146         . $db->escapeSimple($cidnum)
147         . "' and extension = '"
148         . $db->escapeSimple($extension)
149         . "'");
150 }
151
152 function fax_delete_user($faxext) {
153        global $db;
154        $faxext = $db->escapeSimple($faxext);
155        sql('DELETE FROM fax_users where user = "' . $faxext . '"');
156 }
157
158 function fax_destinations(){
159     global $module_page;
160
161     foreach (fax_get_destinations() as $row) {
162         $extens[] = array('destination' => 'ext-fax,' . $row['user'] . ',1', 'description' => $row['name'].' ('.$row['user'].')', 'category' => _('Fax Recipient'));
163     }
164     return isset($extens)?$extens:null;
165 }
166
167 //check to see if any fax modules and licenses are loaded in to asterisk
168 function fax_detect($astver=null){
169     global $amp_conf;
170     global $astman;
171
172   if ($astver === null) {
173     $engineinfo = engine_getinfo();
174     $astver $engineinfo['version'];
175   }
176   $ast_ge_14 = version_compare($astver, '1.4', 'ge');
177   $ast_ge_18 = version_compare($astver, '1.8', 'ge');
178
179     $fax=null;
180     $appfax = $receivefax = false;//return false by default in case asterisk isnt reachable
181     if ($amp_conf['AMPENGINE'] == 'asterisk' && isset($astman) && $astman->connected()) {
182         //check for fax modules
183     $module_show_command = $ast_ge_14 ? 'module show like ' : 'show modules like ';
184         $app = $astman->send_request('Command', array('Command' => $module_show_command.'res_fax'));
185         if (preg_match('/[1-9] modules loaded/', $app['data'])){
186       $fax['module']='res_fax';
187     } else {
188           $receive = $astman->send_request('Command', array('Command' => $module_show_command.'app_fax'));
189           if (preg_match('/[1-9] modules loaded/', $receive['data'])){$fax['module']='app_fax';}
190     }
191     if (!isset($fax['module'])) {
192           $app = $astman->send_request('Command', array('Command' => $module_show_command.'app_rxfax'));
193       $fax['module'] = preg_match('/[1-9] modules loaded/', $app['data']) ? 'app_rxfax': null;
194     }
195         $response = $astman->send_request('Command', array('Command' => $module_show_command.'app_nv_faxdetect'));
196     $fax['nvfax']= preg_match('/[1-9] modules loaded/', $response['data']) ? true : false;
197
198         $response = $astman->send_request('Command', array('Command' => $module_show_command.'res_fax_digium'));
199     $fax['ffa']= preg_match('/[1-9] modules loaded/', $response['data']) ? true : false;
200
201     if ($ast_ge_18) {
202       if ($fax['ffa']) {
203         $fax['spandsp'] = false;
204       } else {
205             $response = $astman->send_request('Command', array('Command' => $module_show_command.'res_fax_spandsp'));
206         $fax['spandsp'] = preg_match('/[1-9] modules loaded/', $response['data']) ? true : false;
207       }
208     }
209
210     switch($fax['module']) {
211     case 'res_fax':
212       $fax['receivefax'] = 'receivefax';
213       break;
214     case 'app_rxfax':
215       $fax['receivefax'] = 'rxfax';
216       break;
217     case 'app_fax':
218       $application_show_command = $ast_ge_14 ? 'core show applications like ' : 'show applications like ';
219           $response = $astman->send_request('Command', array('Command' => $application_show_command.'receivefax'));
220       if (preg_match('/1 Applications Matching/', $response['data'])) {
221         $fax['receivefax'] = 'receivefax';
222       } else {
223             $response = $astman->send_request('Command', array('Command' => $application_show_command.'rxfax'));
224         if (preg_match('/1 Applications Matching/', $response['data'])) {
225           $fax['receivefax'] = 'rxfax';
226         } else {
227           $fax['receivefax'] = 'none';
228         }
229       }
230       break;
231     }
232
233         //get license count
234         $lic = $astman->send_request('Command', array('Command' => 'fax show stats'));
235         foreach(explode("\n",$lic['data']) as $licdata){
236         $d=explode(':',$licdata);
237         $data[trim($d['0'])]=isset($d['1'])?trim($d['1']):null;
238         }
239         $fax['license']=isset($data['Licensed Channels']) ? $data['Licensed Channels'] : '';
240     }
241     return $fax;
242 }
243
244 function fax_get_config($engine){
245   global $version;
246   global $ext;
247   global $amp_conf;
248   global $core_conf;
249
250   $ast_lt_18 = version_compare($version, '1.8', 'lt');
251   $ast_ge_16 = version_compare($version, '1.6', 'ge');
252     $fax=fax_detect($version);
253     if($fax['module'] && ($ast_lt_18 || $fax['ffa'] || $fax['spandsp'])){ //dont continue unless we have a fax module in asterisk
254
255     $t38_fb = $ast_ge_16 ? ',f' : '';
256         $context='ext-fax';
257         $dests=fax_get_destinations();
258         if($dests){
259             foreach ($dests as $row) {
260                 $exten=$row['user'];
261                 $ext->add($context, $exten, '', new ext_set('FAX_FOR',$row['name'].' ('.$row['user'].')'));
262                 $ext->add($context, $exten, '', new ext_noop('Receiving Fax for: ${FAX_FOR}, From: ${CALLERID(all)}'));
263                 $ext->add($context, $exten, '', new ext_set('FAX_RX_EMAIL', $row['faxemail']));           
264                 $ext->add($context, $exten, 'receivefax', new ext_goto('receivefax','s'));
265             }
266         }
267     /*
268       FAX Failures are not handled well as of this coding in by ReceiveFAX. If there is a license available then it provides
269       information. If not, nothing is provided. FAXSTATUS is supported in 1.4 to handle legacy with RxFax(). In order to create
270       dialplan to try and handle all cases, we use FAXSTATUS and set it ourselves as needed. It appears that if a fax fails with
271       ReceiveFAX we can always continue execution and if it succeeds, then execution goes to hangup. So using that information
272       we try to trap and report on all cases.
273     */
274     $exten = 's';
275       $ext->add($context, $exten, '', new ext_macro('user-callerid')); // $cmd,n,Macro(user-callerid)
276     $ext->add($context, $exten, '', new ext_noop('Receiving Fax for: ${FAX_RX_EMAIL} , From: ${CALLERID(all)}'));
277     $ext->add($context, $exten, 'receivefax', new ext_stopplaytones(''));
278     switch ($fax['module']) {
279     case 'app_rxfax':
280       $ext->add($context, $exten, '', new ext_rxfax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif')); //receive fax, then email it on
281     break;
282     case 'app_fax':
283       // $fax['receivefax'] should be rxfax or receivefax, it could be none in which case we don't know. We'll just make it
284       // ReceiveFAX in that case since it will fail anyhow.
285       if ($fax['receivefax'] == 'rxfax') {
286         $ext->add($context, $exten, '', new ext_rxfax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif')); //receive fax, then email it on
287       } elseif ($fax['receivefax'] == 'receivefax') {
288         $ext->add($context, $exten, '', new ext_receivefax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif'.$t38_fb)); //receive fax, then email it on
289       } else {
290         $ext->add($context, $exten, '', new ext_noop('ERROR: NO Receive FAX application detected, putting in dialplan for ReceiveFAX as default'));
291         $ext->add($context, $exten, '', new ext_receivefax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif'.$t38_fb)); //receive fax, then email it on
292               $ext->add($context, $exten, '', new ext_execif('$["${FAXSTATUS}" = ""]','Set','FAXSTATUS=${IF($["${FAXOPT(error)}" = ""]?"FAILED LICENSE EXCEEDED":"FAILED FAXOPT: error: ${FAXOPT(error)} status: ${FAXOPT(status)} statusstr: ${FAXOPT(statusstr)}")}'));
293       }
294     break;
295     case 'res_fax':
296       $ext->add($context, $exten, '', new ext_receivefax('${ASTSPOOLDIR}/fax/${UNIQUEID}.tif'.$t38_fb)); //receive fax, then email it on
297       if ($ast_ge_16) {
298         if ($fax['ffa']) {
299           $ext->add($context, $exten, '', new ext_execif('$["${FAXSTATUS}"="" | "${FAXSTATUS}" = "FAILED" & "${FAXERROR}" = "INIT_ERROR"]','Set','FAXSTATUS=FAILED LICENSE MAY BE EXCEEDED check log errors'));
300         }
301         $ext->add($context, $exten, '', new ext_execif('$["${FAXSTATUS:0:6}"="FAILED" && "${FAXERROR}"!="INIT_ERROR"]','Set','FAXSTATUS="FAILED: error: ${FAXERROR} statusstr: ${FAXOPT(statusstr)}"'));
302       } else {
303         // Some versions or settings appear to have successful completions continue, so check status and goto hangup code
304         if ($fax['ffa']) {
305           $ext->add($context, $exten, '', new ext_execif('$["${FAXOPT(error)}"=""]','Set','FAXSTATUS=FAILED LICENSE MAY BE EXCEEDED'));
306         }
307         $ext->add($context, $exten, '', new ext_execif('$["${FAXOPT(error)}"!="" && "${FAXOPT(error)}"!="NO_ERROR"]','Set','FAXSTATUS="FAILED FAXOPT: error: ${FAXOPT(error)} status: ${FAXOPT(status)} statusstr: ${FAXOPT(statusstr)}"'));
308       }
309           $ext->add($context, $exten, '', new ext_hangup());
310
311     break;
312     default: // unknown
313       $ext->add($context, $exten, '', new ext_noop('No Known FAX Technology installed to receive a fax, aborting'));
314             $ext->add($context, $exten, '', new ext_set('FAXSTATUS','FAILED No Known Fax Reception Apps available to process'));
315             $ext->add($context, $exten, '', new ext_hangup());
316     }
317     $exten = 'h';
318
319     // if there is a file there, mail it even if we failed:
320     $ext->add($context, $exten, '', new ext_gotoif('$[${STAT(e,${ASTSPOOLDIR}/fax/${UNIQUEID}.tif)} = 0]','failed'));
321     $ext->add($context, $exten, '', new ext_noop_trace('PROCESSING FAX with status: [${FAXSTATUS}] for: [${FAX_RX_EMAIL}], From: [${CALLERID(all)}]'));
322     $ext->add($context, $exten, 'process', new ext_gotoif('$[${LEN(${FAX_RX_EMAIL})} = 0]','noemail'));
323     //delete is a variable so that other modules can prevent it should then need to prosses the file further
324     $ext->add($context, $exten, 'delete_opt', new ext_set('DELETE_AFTER_SEND', 'true'));
325     $ext->add($context, $exten, '', new ext_system('${ASTVARLIBDIR}/bin/fax2mail.php --to "${FAX_RX_EMAIL}" --dest "${FROM_DID}" --callerid \'${CALLERID(all)}\' --file ${ASTSPOOLDIR}/fax/${UNIQUEID}.tif --exten "${FAX_FOR}" --delete "${DELETE_AFTER_SEND}"'));
326
327       $ext->add($context, $exten, 'end', new ext_macro('hangupcall'));
328
329     $ext->add($context, $exten, 'noemail', new ext_noop('ERROR: No Email Address to send FAX: status: [${FAXSTATUS}],  From: [${CALLERID(all)}]'));
330       $ext->add($context, $exten, '', new ext_macro('hangupcall'));
331
332     $ext->add($context, $exten, 'failed', new ext_noop('FAX ${FAXSTATUS} for: ${FAX_RX_EMAIL} , From: ${CALLERID(all)}'),'process',101);
333       $ext->add($context, $exten, '', new ext_macro('hangupcall'));
334
335
336         //write out res_fax.conf and res_fax_digium.conf
337         fax_write_conf();
338  
339     $modulename = 'fax';
340     $fcc = new featurecode($modulename, 'simu_fax');
341     $fc_simu_fax = $fcc->getCodeActive();
342     unset($fcc);
343  
344     if ($fc_simu_fax != '') {
345       $default_address = sql('SELECT value FROM fax_details WHERE `key` = \'FAX_RX_EMAIL\'','getRow');
346       $ext->addInclude('from-internal-additional', 'app-fax'); // Add the include from from-internal
347       $ext->add('app-fax', $fc_simu_fax, '', new ext_setvar('FAX_RX_EMAIL', $default_address[0]));
348       $ext->add('app-fax', $fc_simu_fax, '', new ext_goto('1', 's', 'ext-fax'));
349       $ext->add('app-fax', 'h', '', new ext_macro('hangupcall'));
350     }
351     // This is not really needed but is put here in case some ever accidently switches the order below when
352     // checking for this setting since $fax['module'] will be set there and the 2nd part never checked
353     $fax_settings['force_detection'] = 'yes';
354     } else {
355     $fax_settings=fax_get_settings();
356   }
357     if (($fax['module'] && ($ast_lt_18 || $fax['ffa'] || $fax['spandsp'])) || $fax_settings['force_detection'] == 'yes') {
358       if ($ast_ge_16 && isset($core_conf) && is_a($core_conf, "core_conf")) {
359           $core_conf->addSipGeneral('faxdetect','yes');
360       }
361
362         $ext->add('ext-did-0001', 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
363         $ext->add('ext-did-0002', 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
364
365     // Add fax extension to ivr and announcement as inbound controle may be passed quickly to them and still detection is desired
366     if (function_exists('ivr_list')) {
367             $ivrlist = ivr_list();
368             if(is_array($ivrlist)) foreach($ivrlist as $item) {
369             $ext->add("ivr-".$item['ivr_id'], 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
370       }
371     }
372     if (function_exists('announcement_list')) foreach (announcement_list() as $row) {
373       $ext->add('app-announcement-'.$row['announcement_id'], 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));
374     }
375     }
376 }
377
378 function fax_get_destinations(){
379     global $db;
380     $sql = "SELECT fax_users.user,fax_users.faxemail,users.name FROM fax_users, users where fax_users.faxenabled = 'true' and users.extension = fax_users.user ORDER BY fax_users.user";
381     $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
382     if(DB::IsError($results)) {
383         die_freepbx($results->getMessage()."<br><br>Error selecting from fax");   
384     }
385     return $results;
386 }
387
388 function fax_get_incoming($extension=null,$cidnum=null){
389     global $db;
390     if($extension !== null || $cidnum !== null){
391         $sql="SELECT * FROM fax_incoming WHERE extension = ? AND cidnum = ?";
392         $settings = $db->getRow($sql, array($extension, $cidnum), DB_FETCHMODE_ASSOC);
393         if(isset($settings['legacy_email'])&&$settings['legacy_email']=='NULL'){$settings['legacy_email']=null;}//convert string to real value
394     }else{
395         $sql="SELECT fax_incoming.*, incoming.pricid FROM fax_incoming, incoming where fax_incoming.cidnum=incoming.cidnum and fax_incoming.extension=incoming.extension;";
396         $settings=$db->getAll($sql, DB_FETCHMODE_ASSOC);
397     }
398     return $settings;
399 }
400
401 function fax_get_user($faxext = ''){
402     global $db;
403     if ($faxext) {
404         $sql        = "SELECT * FROM fax_users WHERE user = ?";
405         $settings    = $db->getRow($sql, array($faxext), DB_FETCHMODE_ASSOC);
406     } else {
407         $sql        = "SELECT * FROM fax_users";
408         $settings    = $db->getAll($sql, DB_FETCHMODE_ASSOC);
409     }
410     db_e($settings);
411     
412     //make sure were retuning an array (even if its blank)
413     if (!is_array($settings)) {
414         $settings = array();
415     }
416     
417     return $settings;
418 }
419
420 function fax_get_settings(){
421     $settings = sql('SELECT * FROM fax_details', 'getAssoc', 'DB_FETCHMODE_ASSOC');
422     foreach($settings as $setting => $value){
423         $set[$setting]=$value['0'];
424     }
425     if(!is_array($set)){$set=array();}//never return a null value
426     return $set;
427 }
428
429
430 function fax_hook_core($viewing_itemid, $target_menuid){
431     //hmm, not sure why engine_getinfo() isnt being called here?! should probobly read: $info=engine_getinfo();
432     //this is what serves fax code to inbound routing
433     $tabindex=null;
434     $type=isset($_REQUEST['type'])?$_REQUEST['type']:'';
435     $extension=isset($_REQUEST['extension'])?$_REQUEST['extension']:'';
436     $cidnum=isset($_REQUEST['cidnum'])?$_REQUEST['cidnum']:'';
437     $extdisplay=isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:'';
438     
439     //if were editing, get save parms. Get parms
440
441     if(!$extension && !$cidnum){//set $extension,$cidnum if we dont already have them
442         if ($extdisplay) {
443             $opts        = explode('/', $extdisplay);
444             $extension    = $opts['0'];
445             $cidnum        = isset($opts['1']) ? $opts['1'] : '';
446         } else {
447             $extension = $cidnum = '';
448         }
449         
450     }
451
452     $fax=fax_get_incoming($extension,$cidnum);
453     $html='';
454     if($target_menuid == 'did'){
455     $fax_dahdi_faxdetect=fax_dahdi_faxdetect();
456     $fax_sip_faxdetect=fax_sip_faxdetect();
457     $dahdi=ast_with_dahdi()?_('Dahdi'):_('Zaptel');
458     $fax_detect=fax_detect();
459     $fax_settings=fax_get_settings();
460     //ensure that we are using destination for both fax detect and the regular calls
461         $html='<script type="text/javascript">$(document).ready(function(){
462         $("input[name=Submit]").click(function(){
463             if($("input[name=faxenabled]:checked").val()=="true" && !$("[name=gotoFAX]").val()){//ensure the user selected a fax destination
464             alert('._('"You have selected Fax Detection on this route. Please select a valid destination to route calls detected as faxes to."').');return false; }    }) });</script>';
465         $html .= '<tr><td colspan="2"><h5>';
466         $html.=_('Fax Detect');
467         $html.='<hr></h5></td></tr>';
468         $html.='<tr>';
469         $html.='<td><a href="#" class="info">';
470         $html.=_("Detect Faxes").'<span>'._("Attempt to detect faxes on this DID.")."<ul><li>"._("No: No attempts are made to auto-determine the call type; all calls sent to destination below. Use this option if this DID is used exclusively for voice OR fax.")."</li><li>"._("Yes: try to auto determine the type of call; route to the fax destination if call is a fax, otherwise send to regular destination. Use this option if you receive both voice and fax calls on this line")."</li>";
471         if($fax_settings['legacy_mode'] == 'yes' || $fax['legacy_email']!==null){
472         $html.='<li>'._('Legacy: Same as YES, only you can enter an email address as the destination. This option is ONLY for supporting migrated legacy fax routes. You should upgrade this route by choosing YES, and selecting a valid destination!').'</li>';
473         }       
474         $html.='</ul></span></a>:</td>';
475         
476         //dont allow detection to be set if we have no valid detection types
477         if(!$fax_dahdi_faxdetect && !$fax_sip_faxdetect && !$fax_detect['nvfax']){
478             $js="if ($(this).val() == 'true'){alert('"._('No fax detection methods found or no valid license. Faxing cannot be enabled.')."');return false;}";
479             $html.='<td><span class="radioset"><input type="radio" id="faxenabled_yes" name="faxenabled" value="false" CHECKED /><label for="faxenabled_no">No</label>';
480             $html.='<input type="radio" name="faxenabled" id="faxenabled_no" value="true"  onclick="'.$js.'"/><label for="faxenabled_yes">Yes</label></span></td></tr>';
481             $html.='</table><table>';
482         }else{
483             /*
484              * show detection options
485              *
486              * js to show/hide the detection settings. Second slide is always in a
487              * callback so that we ait for the fits animation to complete before
488              * playing the second
489              */
490             if($fax['legacy_email']===null && $fax_settings['legacy_mode'] == 'no'){
491                 $jsno="$('.faxdetect').slideUp();";
492                 $jsyes="$('.faxdetect').slideDown();";
493             }else{
494                 $jsno="$('.faxdetect').slideUp();$('.legacyemail').slideUp();";
495                 $jsyes="$('.legacyemail').slideUp('400',function(){
496                             $('.faxdetect').slideDown()
497                         });";
498                 $jslegacy="$('.faxdest27').slideUp('400',function(){
499                                 $('.faxdetect, .legacyemail').not($('.faxdest27')).slideDown();
500                         });";
501             }
502             $html.='<td><span class="radioset"><input type="radio" name="faxenabled" id="faxenabled_no" value="false" CHECKED onclick="'.$jsno.'"/><label for="faxenabled_no">' . _('No') . '</label>';
503             $html.='<input type="radio" name="faxenabled" id="faxenabled_yes" value="true" '.($fax?'CHECKED':'').' onclick="'.$jsyes.'"/><label for="faxenabled_yes">' . _('Yes') . '</label>';
504             if($fax['legacy_email']!==null || $fax_settings['legacy_mode'] == 'yes'){
505                 $html.='<input type="radio" name="faxenabled" id="faxenabled_legacy" value="legacy"'.($fax['legacy_email'] !== null ? ' CHECKED ':'').'onclick="'.$jslegacy.'"/><label for="faxenabled_legacy">' . _('Legacy');
506             }
507       $html.='</td></tr>';
508             $html.='</table>';
509         }   
510         //fax detection+destinations, hidden if there is fax is disabled
511         $html.='<table class=faxdetect '.($fax?'':'style="display: none;"').'>';   
512         $info=engine_getinfo();
513         $html.='<tr><td width="156px"><a href="#" class="info">'._('Fax Detection type').'<span>'._("Type of fax detection to use.")."<ul><li>".$dahdi.": "._("use ").$dahdi._(" fax detection; requires 'faxdetect=' to be set to 'incoming' or 'both' in ").$dahdi.".conf</li><li>"._("Sip: use sip fax detection (t38). Requires asterisk 1.6.2 or greater and 'faxdetect=yes' in the sip config files")."</li><li>"._("NV Fax Detect: Use NV Fax Detection; Requires NV Fax Detect to be installed and recognized by asterisk")."</li></ul>".'.</span></a>:</td>';
514         $html.='<td><select name="faxdetection" tabindex="'.++$tabindex.'">';
515         //$html.='<option value="Auto"'.($faxdetection == 'auto' ? 'SELECTED' : '').'>'. _("Auto").'</option>';<li>Auto: allow the system to chose the best fax detection method</li>       
516         $html.='<option value="dahdi" '.($fax['detection'] == 'dahdi' ? 'SELECTED' : '').' '.($fax_dahdi_faxdetect?'':'disabled').'>'.$dahdi.'</option>';
517         $html.='<option value="nvfax"'.($fax['detection'] == 'nvfax' ? 'SELECTED' : '').($fax_detect['nvfax']?'':'disabled').'>'. _("NVFax").'</option>';
518         $html.='<option value="sip" '.($fax['detection'] == 'sip' ? 'SELECTED' : '').' '.((($info['version'] >= "1.6.2") && $fax_sip_faxdetect)?'':'disabled').'>'. _("Sip").'</option>';
519         $html.='</select></td></tr>';
520         
521         $html.='<tr><td><a href="#" class="info">'._("Fax Detection Time").'<span>'._('How long to wait and try to detect fax. Please note that callers to a '.$dahdi.' channel will hear ringing for this amount of time (i.e. the system wont "answer" the call, it will just play ringing)').'.</span></a>:</td>';
522         $html.='<td><select name="faxdetectionwait" tabindex="'.++$tabindex.'">';
523         if(!$fax['detectionwait']){$fax['detectionwait']=4;}//default wait time is 4 second
524         for($i=2;$i < 11; $i++){
525             $html.='<option value="'.$i.'" '.($fax['detectionwait']==$i?'SELECTED':'').'>'.$i.'</option>';   
526         }
527         $html.='</select></td></tr>';
528         if($fax['legacy_email']!==null || $fax_settings['legacy_mode'] == 'yes'){   
529             $html.='</table>';
530             $html.='<table class="legacyemail"'.($fax['legacy_email'] === null ? ' style="display: none;"':'').'>';
531             $html.='<tr ><td><a href="#" class="info">'._("Fax Email Destination").'<span>'._('Address to email faxes to on fax detection.<br />PLEASE NOTE: In this version of FreePBX, you can now set the fax destination from a list of destinations. Extensions/Users can be fax enabled in the user/extension screen and set an email address there. This will create a new destination type that can be selected. To upgrade this option to the full destination list, select YES to Detect Faxes and select a destination. After clicking submit, this route will be upgraded. This Legacy option will no longer be available after the change, it is provided to handle legacy migrations from previous versions of FreePBX only.').'.</span></a>:</td>';
532             $html.='<td><input name="legacy_email" value="'.$fax['legacy_email'].'"></td></tr>';
533             $html.='</table>';
534             $html.='<table class="faxdest27 faxdetect" style="display: none" >';
535     }       
536         $html.='<tr class="faxdest"><td><a href="#" class="info">'._("Fax Destination").'<span>'._('Where to send the call if we detect that its a fax').'.</span></a>:</td>';
537         $html.='<td>';
538         $html.=$fax_detect?drawselects(isset($fax['destination'])?$fax['destination']:null,'FAX',false,false):'';
539         $html.='</td></tr></table>';
540         $html.='<table>';
541     }
542     return $html;
543
544 }
545
546 function fax_hookGet_config($engine){
547   global $version;
548     $fax=fax_detect($version);
549   if ($fax['module']) {
550       $fax_settings['force_detection'] = 'yes';
551   } else {
552     $fax_settings=fax_get_settings();
553   }
554     if($fax_settings['force_detection'] == 'yes'){ //dont continue unless we have a fax module in asterisk
555         global $ext;
556         global $engine;
557         $routes=fax_get_incoming();
558         foreach($routes as $current => $route){
559       if ($route['detection'] == 'nvfax' && !$fax['nvfax']) {
560         //TODO: add notificatoin to notification panel that this was skipped because NVFaxdetec not present
561         continue; // skip this one if there is no NVFaxdetect installed on this system
562       }
563             if($route['extension']=='' && $route['cidnum']){//callerID only
564                 $extension='s/'.$route['cidnum'];
565                 $context=($route['pricid']=='CHECKED')?'ext-did-0001':'ext-did-0002';
566             }else{
567                 if(($route['extension'] && $route['cidnum'])||($route['extension']=='' && $route['cidnum']=='')){//callerid+did / any/any
568                     $context='ext-did-0001';
569                 }else{//did only
570                     $context='ext-did-0002';
571                 }
572                 $extension=($route['extension']!=''?$route['extension']:'s').($route['cidnum']==''?'':'/'.$route['cidnum']);
573             }
574       if ($route['legacy_email'] === null) {
575               $ext->splice($context, $extension, 'dest-ext', new ext_setvar('FAX_DEST',str_replace(',','^',$route['destination'])));
576       } else {
577               $ext->splice($context, $extension, 'dest-ext', new ext_setvar('FAX_DEST','ext-fax^s^1'));
578         if ($route['legacy_email']) {
579                 $fax_rx_email = $route['legacy_email'];
580         } else {
581           if (!isset($default_fax_rx_email)) {
582                   $default_address = sql('SELECT value FROM fax_details WHERE `key` = \'fax_rx_email\'','getRow');
583             $default_fax_rx_email = $default_address[0];
584           }
585           $fax_rx_email = $default_fax_rx_email;
586         }
587               $ext->splice($context, $extension, 'dest-ext', new ext_setvar('FAX_RX_EMAIL',$fax_rx_email));
588       }
589           $ext->splice($context, $extension, 'dest-ext', new ext_answer(''));
590       if ($route['detection'] == 'nvfax') {
591             $ext->splice($context, $extension, 'dest-ext', new ext_playtones('ring'));
592             $ext->splice($context, $extension, 'dest-ext', new ext_nvfaxdetect($route['detectionwait'].",t"));
593       } else {
594             $ext->splice($context, $extension, 'dest-ext', new ext_wait($route['detectionwait']));
595       }
596         }
597     }
598 }
599
600 function fax_hookProcess_core(){
601     $display=isset($_REQUEST['display'])?$_REQUEST['display']:'';
602     $action=isset($_REQUEST['action'])?$_REQUEST['action']:'';
603     if ($display == 'did' && $action!=''){
604
605       $cidnum=isset($_REQUEST['cidnum'])?$_REQUEST['cidnum']:'';
606       $extension=isset($_REQUEST['extension'])?$_REQUEST['extension']:'';
607       $extdisplay=isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:'';
608       $enabled=isset($_REQUEST['faxenabled'])?$_REQUEST['faxenabled']:'false';
609       $detection=isset($_REQUEST['faxdetection'])?$_REQUEST['faxdetection']:'';
610       $detectionwait=isset($_REQUEST['faxdetectionwait'])?$_REQUEST['faxdetectionwait']:'';
611       $dest=(isset($_REQUEST['gotoFAX'])?$_REQUEST['gotoFAX'].'FAX':null);
612       $dest=isset($_REQUEST[$dest])?$_REQUEST[$dest]:'';
613     if ($enabled != 'legacy') {
614       $legacy_email = null;
615     } else {
616         $legacy_email=isset($_REQUEST['legacy_email'])?$_REQUEST['legacy_email']:'';
617     }
618         fax_delete_incoming($extdisplay);    //remove mature entry on edit or delete
619         if (($action == 'edtIncoming' || $action == 'addIncoming') && $enabled != 'false'){
620             fax_save_incoming($cidnum,$extension,$enabled,$detection,$detectionwait,$dest,$legacy_email);
621         }
622     }
623 }
624
625
626 function fax_save_incoming($cidnum,$extension,$enabled,$detection,$detectionwait,$dest,$legacy_email){
627     global $db;
628   $legacy_email $legacy_email === null ? 'NULL' : "'".$db->escapeSimple("$legacy_email")."'";
629     sql("INSERT INTO fax_incoming (cidnum, extension, detection, detectionwait, destination, legacy_email) VALUES ('".$db->escapeSimple($cidnum)."', '".$db->escapeSimple($extension)."', '".$db->escapeSimple($detection)."', '".$db->escapeSimple($detectionwait)."', '".$db->escapeSimple($dest)."',".$legacy_email.")");
630 }
631
632 function fax_save_settings($settings){
633     global $db;
634     if (is_array($settings)) foreach($settings as $key => $value){
635         sql("REPLACE INTO fax_details (`key`, `value`) VALUES ('".$key."','".$db->escapeSimple($value)."')");
636     }
637     
638     needreload();
639 }
640
641 function fax_save_user($faxext,$faxenabled,$faxemail = '') {
642     global $db;
643     $sql = 'REPLACE INTO fax_users (user, faxenabled, faxemail) VALUES (?, ?, ?)';
644     $ret = $db->query($sql, array($faxext, $faxenabled, $faxemail));
645     db_e($ret);
646
647     return true;
648 }
649
650 function fax_sip_faxdetect(){
651     global $asterisk_conf;
652      return true;
653 }
654
655 //write out res_fax.conf and res_fax_digium.conf
656 function fax_write_conf(){
657     global $amp_conf, $WARNING_BANNER;
658     $set=fax_get_settings();
659     //res_fax.conf
660     $data=$WARNING_BANNER;
661     $data.="[general]\n";
662     $data.="#include res_fax_custom.conf\n";
663     $data.='minrate='.$set['minrate']."\n";
664     $data.='maxrate='.$set['maxrate']."\n";
665     $file=fopen($amp_conf['ASTETCDIR'].'/res_fax.conf','w');
666     fwrite($file, $data);
667     fclose($file);
668     
669     //res_fax_digium.conf
670     $data=$WARNING_BANNER;
671     $data.="[general]\n";
672     $data.="#include res_fax_digium_custom.conf\n";
673     $data.='ecm='.$set['ecm']."\n";
674     $file=fopen($amp_conf['ASTETCDIR'].'/res_fax_digium.conf','w');
675     fwrite($file, $data);
676     fclose($file);
677 }
678
679 /**
680  * Converts a file to different format
681  * @param string - conversion type in the format of 'from2to'
682  * @param string - path to origional file
683  * @param string - path to save new file
684  * @param bool - wether to keep or delete the orgional file
685  *
686  * @return string - path to fresh pdf
687  *
688  * Supported conversions:
689  *    - pdf2tiff
690  *    - tif2pdf
691  *    - ps2tif
692  */
693 function fax_file_convert($type, $in, $out = '', $keep_orig = false, $opts = array()) {
694     global $amp_conf;
695     //ensure file exists
696     if (!is_file($in)) {
697         return false;
698     }
699     
700     //set out filename if not specified
701     if (!$out) {
702         switch ($type) {
703             case 'pdf2tif':
704             case 'ps2tif':
705                 $ext = '.tif';
706                 break;
707             case 'tif2pdf':
708                 $ext = '.pdf';
709                 break;
710         }
711         $pathinfo = pathinfo($in);
712
713         //php < 5.2 doesnt provide filename
714         if (!isset($pathinfo['filename'])) {
715             $pathinfo['filename']
716                 = substr($pathinfo['basename'], 0,
717                         strrpos($pathinfo['basename'],
718                             '.' . $pathinfo['extension']
719                         )
720                 );
721         }
722         
723         $out = $pathinfo['dirname']
724                     . '/'
725                     . $pathinfo['filename']
726                     . $ext;
727     }
728     
729     //if file exists, assume its been converted already
730     if (file_exists($out)) {
731         return $out;
732     }
733     
734     //ensure cli command exists
735     switch ($type) {
736         case 'pdf2tif':
737         case 'ps2tif':
738             $gs = fpbx_which('gs');
739             if (!$gs) {
740                 dbug('gs not found, not converting ' . $in);
741                 return $in;
742             }
743             $gs = $gs . ' -q -dNOPAUSE -dBATCH -sPAPERSIZE=letter ';
744             break;
745         case 'tif2pdf':
746             $tiff2pdf = fpbx_which('tiff2pdf');
747             if (!$tiff2pdf) {
748                 dbug('tiff2pdf not found, not converting ' . $in);
749                 return $in;
750             }
751             break;
752     }
753
754     //convert!
755     switch ($type) {
756         case 'pdf2tif':
757         case 'ps2tif':
758             $cmd = $gs
759                 . '-sDEVICE=tiffg4 '
760                 . '-sOutputFile=' . $out . ' ' . $in;
761             break;
762         case 'tif2pdf':
763             $cmd = $tiff2pdf
764                     . ' -z '
765                     . '-c "PBXact by Schmooze Communications" '
766                     . '-a "' . $amp_conf['PDFAUTHOR'] . '" '
767                     . (isset($opts['title']) ? '-t "' . $opts['title'] . '" ' : '')
768                     . '-o ' . $out . ' ' . $in;
769             break;
770         default:
771             break;
772     }
773
774     exec($cmd, $ret, $status);
775     
776     //remove original
777     if ($status === 0 && !$keep_orig) {
778         unlink($in);
779     }
780     
781     return $status === 0 ? $out : $in;
782 }
783
784 /**
785  * Get info on a tiff file. Require tiffinfo
786  * @param string - absolute path to file
787  * @param string - specifc option to receive
788  *
789  * @return mixed - if $opt & exists returns a string, else bool false,
790  * otherwise an array of details
791  */
792 function fax_tiffinfo($file, $opt = '') {
793     //ensure file exists
794     if (!is_file($file)) {
795         return false;
796     }
797     
798     $tiffinfo    = fpbx_which('tiffinfo');
799     $info        = array();
800     
801     if (!$tiffinfo) {
802         return false;
803     }
804     exec($tiffinfo . ' ' . $file, $output);
805     
806     if ($output && strpos($output[0], 'Not a TIFF or MDI file') === 0) {
807         return false;
808     }
809     
810     foreach ($output as $out) {
811         $o = explode(':', $out, 2);
812         $info[trim($o[0])] = isset($o[1]) ? trim($o[1]) : '';
813     }
814     
815     if (!$info) {
816         return false;
817     }
818     
819     //special case prossesing
820     //Page Number: defualt format = 0-0. Use only first set of digits, increment by 1
821     $info['Page Number'] = explode('-', $info['Page Number']);
822     $info['Page Number'] = $info['Page Number'][0] + 1;
823     
824     if ($opt) {
825         return isset($info[$opt]) ? $info[$opt] : false;
826     }
827     
828     return $info;
829 }
830 ?>
831
Note: See TracBrowser for help on using the browser.