root/contributed_modules/modules/smartroutes/functions.inc.php

Revision 11431, 49.9 kB (checked in by escape2mtns, 2 years ago)

allow '0' seconds for fax delay

  • Property svn:executable set to *
Line 
1 <?php   
2 /**
3  * FreePBX SmartRoutes Module
4  *
5  * Copyright (c) 2011, VoiceNation, LLC.
6  *
7  * This program is free software, distributed under the terms of
8  * the GNU General Public License Version 2.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18 */
19
20 include '../fax/functions.inc.php'// so we can include the same fax hook code that the standard inbound route includes (if available)
21
22
23 function smartroutes_list() {
24     global $db;
25
26     $sql = "SELECT * FROM smartroute ORDER BY name";
27     $list = $db->getAll($sql, DB_FETCHMODE_ASSOC);
28     if(DB::IsError($list)) return null;
29
30     return $list;   
31 }
32
33
34 function smartroutes_getdest($id) {
35     return array('smartroute-'.$id.',s,1');
36     }
37
38     
39 function smartroutes_get_route($id) {
40     global $db;
41     
42     $route = $db->getAll("SELECT * FROM smartroute where id='$id'", DB_FETCHMODE_ASSOC);
43     
44     if(DB::IsError($route)) {
45         return null;
46         }
47         
48     return $route[0];
49     }
50
51 function smartroutes_get_queries($id) {
52     global $db;
53
54     $sql = "SELECT * FROM smartroute_query where id='$id'";
55     $queries = $db->getAll($sql, DB_FETCHMODE_ASSOC);   
56         
57     return $queries;
58     }
59
60 function smartroutes_get_dests($id) {
61     global $db;
62
63     $sql = "SELECT * FROM smartroute_dest where id='$id'";
64     $dests = $db->getAll($sql, DB_FETCHMODE_ASSOC);   
65         
66     return $dests;
67     }
68     
69     
70 function smartroutes_add_route($name) {
71     global $db;
72     
73     // see if that route already exists
74     $route = $db->getRow("SELECT id FROM smartroute WHERE name='$name'");
75     
76     // route doesn't exist so create
77     if(DB::IsError($route) || count($route)==0) {
78         sql("INSERT INTO smartroute (name) VALUES ('$name')");
79         $route = $db->getRow("SELECT id FROM smartroute WHERE name='$name'");
80         sql("INSERT INTO smartroute_query (id,mainquery,use_wizard) VALUES ('$route[0]','1','1')");
81         }   
82         
83     if(!empty($route[0]) && !DB::IsError($route)) return $route[0];
84     
85     return null;
86     }
87
88 function smartroutes_del($id) {
89     global $db;
90
91     sql("DELETE FROM smartroute WHERE id='$id'");
92     sql("DELETE FROM smartroute_query WHERE id='$id'");   
93     sql("DELETE FROM smartroute_dest WHERE id='$id'");
94
95     return null;
96 }
97
98 function smartroutes_save($id) {
99     global $db;   
100
101     $id = $db->escapeSimple(isset($_POST['id']) ? $_POST['id'] : '');
102     if(empty($id)) return false
103
104     // set default destination
105     $destination = $_POST[$_POST["goto".$_POST[smartroute_default_destination]].$_POST[smartroute_default_destination]];
106     $sql = " `destination` = '".$db->escapeSimple($destination)."',";
107     
108     // set fax destination   
109     if(isset($_POST["gotoFAX"])) {
110         $faxdestination = $_POST[$_POST["gotoFAX"]."FAX"];
111         $sql .= " `faxdestination` = '".$db->escapeSimple($faxdestination)."',";
112         }
113     
114     foreach ($_POST as $key => $value) {
115         switch ($key) {
116             case 'faxenabled':
117                 // FIX true/false
118                 if($value == 'true') {
119                     $value = '1';
120                 }
121                 else {
122                     $value = '0';
123                 }
124                 
125             case 'name':
126             case 'search-type':
127             case 'limitciddigits':
128             case 'limitdiddigits':
129             case 'dbengine':
130             case 'odbc-dsn':
131             case 'mysql-host':
132             case 'mysql-database':
133             case 'mysql-username':
134             case 'mysql-password':           
135             case 'privacyman':
136             case 'pmmaxretries':
137             case 'pmminlength':
138             case 'alertinfo':
139             case 'ringing':
140             case 'mohclass':
141             case 'description':
142             case 'grppre':
143             case 'delay_answer':
144             case 'pricid':
145             case 'destination':
146             case 'faxdetection':
147             case 'legacy_email':
148             case 'faxdetectionwait':
149                 $sql_value = $db->escapeSimple($value);
150                 $sql .= " `$key` = '$sql_value',";
151                 break;
152             default:
153             }
154         }
155         
156     if ($sql == '') {
157         return false;
158         }
159         
160     $sql = substr($sql,0,(strlen($sql)-1)); //strip off tailing ','
161     $sql_update = "UPDATE `smartroute` SET"."$sql WHERE `id` = '$id'";
162     
163     // UPDATE THE ACTUAL SMARTROUTE
164     sql($sql_update);
165     
166     // ****** now update the main query - DON'T DELETE BECAUSE WE MAY BE *LIVE* SO ONLY UPDATE MAIN QUERY
167     $sql = "UPDATE `smartroute_query` SET ";
168     
169     if(isset($_POST['smartroute_mainquery_wizard'])) {
170         if($_POST['smartroute_mainquery_wizard'] == 'yes') {
171             $sql .= " use_wizard='1', ";
172             }
173         else {
174             $sql .= " use_wizard='0', ";
175             }
176         }
177     
178     if(isset($_POST['smartroute_query_wiz_table'])) {
179         $wiz_table = $db->escapeSimple(isset($_POST['smartroute_query_wiz_table'])?$_POST['smartroute_query_wiz_table'] :'');
180         $wiz_findcolumn = $db->escapeSimple(isset($_POST['smartroute_query_wiz_scol'])?$_POST['smartroute_query_wiz_scol'] :'');
181         $wiz_matchvar = $db->escapeSimple(isset($_POST['smartroute_query_wiz_mvar'])?$_POST['smartroute_query_wiz_mvar'] :'');
182         $wiz_retcolumn = $db->escapeSimple(isset($_POST['smartroute_query_wiz_rcol'])?$_POST['smartroute_query_wiz_rcol'] :'');
183         
184         $sql .= "
185             wiz_table='$wiz_table',
186             wiz_findcolumn='$wiz_findcolumn',
187             wiz_retcolumn='$wiz_retcolumn',
188             wiz_matchvar='$wiz_matchvar',
189             ";
190         }
191         
192     if(isset($_POST['smartroute_query_adv_sql'])) {
193         $adv_query = $db->escapeSimple(isset($_POST['smartroute_query_adv_sql'][0])?$_POST['smartroute_query_adv_sql'][0] : '');
194         $adv_varname1 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var1'][0])?$_POST['smartroute_query_adv_var1'][0]: '');
195         $adv_varname2 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var2'][0])?$_POST['smartroute_query_adv_var2'][0]: '');
196         $adv_varname3 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var3'][0])?$_POST['smartroute_query_adv_var3'][0]: '');
197         $adv_varname4 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var4'][0])?$_POST['smartroute_query_adv_var4'][0]: '');
198         $adv_varname5 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var5'][0])?$_POST['smartroute_query_adv_var5'][0]: '');
199         
200         $sql .= "
201             adv_query='$adv_query',
202             adv_varname1='$adv_varname1',
203             adv_varname2='$adv_varname2',
204             adv_varname3='$adv_varname3',
205             adv_varname4='$adv_varname4',
206             adv_varname5='$adv_varname5',
207             ";
208         }   
209     $sql = trim($sql); // strip trailing whitespace so we can drop the last ','   
210     $sql = substr($sql,0,(strlen($sql)-1)); //strip off tailing ','       
211     $sql .= " WHERE (id='$id' AND mainquery='1')";
212         
213     // UPDATE THE ACTUAL SMARTROUTE MAIN QUERY
214     sql($sql);
215     
216     // DELETE THE SECONDARY QUERIES USED TO PULL VARS/VALUES (less critical)
217     sql("DELETE FROM smartroute_query WHERE id='$id' AND mainquery='0'");
218
219     // RE-ADD THE SECONDARY QUERIES
220     if(isset($_POST['smartroute_query_adv_sql'])) {
221         $total = count($_POST['smartroute_query_adv_sql']);
222                 
223         foreach($_POST['smartroute_query_adv_sql'] as $curr_row => $query_adv_sql_row) {
224             if($curr_row == 0) {
225                 continue; // skip main query already handled
226                 }
227             $adv_query = $db->escapeSimple(isset($_POST['smartroute_query_adv_sql'][$curr_row])?$_POST['smartroute_query_adv_sql'][$curr_row] : '');
228             $adv_varname1 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var1'][$curr_row])?$_POST['smartroute_query_adv_var1'][$curr_row]: '');
229             $adv_varname2 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var2'][$curr_row])?$_POST['smartroute_query_adv_var2'][$curr_row]: '');
230             $adv_varname3 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var3'][$curr_row])?$_POST['smartroute_query_adv_var3'][$curr_row]: '');
231             $adv_varname4 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var4'][$curr_row])?$_POST['smartroute_query_adv_var4'][$curr_row]: '');
232             $adv_varname5 = $db->escapeSimple(isset($_POST['smartroute_query_adv_var5'][$curr_row])?$_POST['smartroute_query_adv_var5'][$curr_row]: '');
233             
234             $sql = "INSERT INTO smartroute_query
235             (id,mainquery,use_wizard,adv_query,adv_varname1,adv_varname2,adv_varname3,adv_varname4,adv_varname5)
236             VALUES
237             ('$id','0','0','$adv_query','$adv_varname1','$adv_varname2','$adv_varname3','$adv_varname4','$adv_varname5')";
238         
239             // UPDATE THE ACTUAL SMARTROUTE QUERY
240             sql($sql);
241             }
242         }   
243         
244     // SAVE THE DESTINATIONS
245     if(isset($_POST['smartroute_dest_match'])) {
246         $total = count($_POST['smartroute_dest_match']);
247         $used_matchkeys = array();
248         
249         foreach($_POST['smartroute_dest_match'] as $curr_row => $dest_match_row) {
250             $matchkey = $db->escapeSimple(isset($_POST['smartroute_dest_match'][$curr_row])?$_POST['smartroute_dest_match'][$curr_row] : '');
251             $extvar = $db->escapeSimple(isset($_POST['smartroute_dest_extvar'][$curr_row])?$_POST['smartroute_dest_extvar'][$curr_row] : '');
252             $destination_set = $db->escapeSimple(isset($_POST['smartroute_dest'][$curr_row])?$_POST['smartroute_dest'][$curr_row] : '');
253             $failover_set = $db->escapeSimple(isset($_POST['smartroute_faildest'][$curr_row])?$_POST['smartroute_faildest'][$curr_row] : '');
254             
255             $destination = $_POST[$_POST["goto".$destination_set].$destination_set];
256             $failover = $_POST[$_POST["goto".$failover_set].$failover_set];
257             
258             $matchkey = trim($matchkey);
259             if(empty($matchkey)) {
260                 // skip empty values
261                 continue;
262                 }
263         
264             // UPDATE THE ACTUAL SMARTROUTE DESTINATION
265             $row = $db->getRow("SELECT * FROM smartroute_dest WHERE id='$id' and matchkey='$matchkey'");
266             
267             if(count($row) == 0) {
268                 sql("INSERT INTO smartroute_dest (id, matchkey, extvar, destination, failover_dest) VALUES ('$id', '$matchkey', '$extvar', '$destination', '$failover')");
269                 }
270             else {
271                 sql("UPDATE smartroute_dest SET extvar='$extvar', destination='$destination', failover_dest='$failover' WHERE id='$id' and matchkey='$matchkey'");
272                 }
273             
274             $used_matchkeys[] = $matchkey;
275             }
276             
277         // delete any destinations no longer in use
278         $sql = "SELECT * FROM smartroute_dest WHERE id='$id'";
279         $rows = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
280         
281         foreach($rows as $row) {
282             if(!in_array($row['matchkey'], $used_matchkeys)) {
283                 $delkey = $row['matchkey'];
284                 sql("DELETE FROM smartroute_dest WHERE (id='$id' AND matchkey='$delkey')");
285                 }           
286             }           
287         }
288     else {
289         // no destination matches left
290         sql("DELETE FROM smartroute_dest WHERE id='$id'");
291         }
292     }
293
294     
295 function smartroutes_destinations() {
296     $destinations = array();
297     $smartroutes = smartroutes_list();
298
299     if(isset($smartroutes)) {
300         foreach($smartroutes as $route){
301             $destinations[] = array('destination' => 'smartroute-'.$route['id'].',${EXTEN},1','description' => $route['name']);
302             }
303         }
304         
305     if(count($destinations)) return $destinations;   
306     return null;   
307 }
308
309
310 // for debugging get_config
311 function ob_file_callback($buffer)
312 {
313   global $ob_file;
314   fwrite($ob_file,$buffer);
315 }
316
317 function smartroutes_get_config($engine) {
318     global $ext;
319     global $version;   
320     $replacements = array ('\\' => '\\\\','"' => '\\"','\'' => '\\\'',' ' => '\\ ',',' => '\\,','(' => '\\(',')' => '\\)','.' => '\\.','|' => '\\|' );   
321     
322     if($engine != 'asterisk') {
323         return;       
324         }
325         
326     // for debugging get_config
327 //    global $ob_file;
328 //    $ob_file = fopen('/tmp/smartroute.log','w');
329 //    ob_start('ob_file_callback');
330
331     // *** FIRST FIX CATCHALL TO SET FROM_DID  (we need this when the catch-all is routed to smartroutes for processing - that way we can search on FROM_DID)
332     // NEED THE INVALID EXTENSION MATCH FOR DID'S WITH + IN FRONT (like Level3)
333     $ext->add('ext-did-catchall', 'i', '', new ext_noop('Catch-All DID Match - Found ${INVALID_EXTEN} - You probably want a DID for this.'));
334        $ext->add('ext-did-catchall', 'i', '', new ext_setvar('__CATCHALL_DID','${INVALID_EXTEN}'));
335     $ext->add('ext-did-catchall', 'i', '', new ext_goto('ext-did,s,1'));       
336         
337     // on FreePBX 2.8 ours is the first line for this context
338        $ext->add('ext-did-catchall', '_.', '', new ext_setvar('__FROM_DID','${EXTEN}'));
339        // actually, FreePBX is setting FROM_DID in ext-did-001 as 's' so let's keep our own var too *** MAKE SURE TO USE _. so we can get non-numeric DID's too
340        $ext->add('ext-did-catchall', '_.', '', new ext_setvar('__CATCHALL_DID','${EXTEN}'));
341     
342     // get list of routes
343     $smartroutes = smartroutes_list();
344     $odbc_queries = array();
345     
346     if(is_array($smartroutes)) {
347         foreach($smartroutes as $smartroute) {
348             $id = $smartroute['id'];
349             $context = "smartroute-".$smartroute['id'];
350             $extension = '_X.';
351             $smartroute_queries = smartroutes_get_queries($id);
352             $smartroute_dests = smartroutes_get_dests($id);
353
354             // PREP QUERIES FIRST
355             if(version_compare($version, "1.6", "lt")) {
356                 $escapeMySQL = true;
357                 }
358             else {
359                 $escapeMySQL = false;
360                 }
361             
362             // find main query AND prepare query AND escape mysql if necessary
363             $main_query = 0;
364             foreach ($smartroute_queries as $index => &$query) {
365                 
366                 if($smartroute_queries[$index]['mainquery'] == 1 && $smartroute_queries[$index]['use_wizard'] == 1) {
367                     if(!empty($query['wiz_table'])) {
368                         // we build the query from the wizard fields
369                         $smartroute_queries[$index]['adv_query'] = "SELECT ".$query['wiz_retcolumn']." FROM ".$query['wiz_table']." WHERE ".$query['wiz_findcolumn']." = '\${".$query['wiz_matchvar']."}'";
370                         }
371                     else {
372                         $smartroute_queries[$index]['adv_query'] = ""; // blank if no query
373                         }
374                     }
375                 
376                 if($smartroute['dbengine'] == 'mysql' && $escapeMySQL) {
377                     // version 1.2/1.4 asterisk requires escaping inline mysql searches
378                     $smartroute_queries[$index]['query'] = str_replace(array_keys($replacements), array_values($replacements), $smartroute_queries[$index]['adv_query']);
379                     }
380                 else {
381                     $smartroute_queries[$index]['query'] = $smartroute_queries[$index]['adv_query'];
382                     }
383
384                 // record index of main query
385                 if($query['mainquery'] == '1') {
386                     $main_query = $index;
387                     }
388
389                 // save query index (how we build unique query names)
390                 $smartroute_queries[$index]['index'] = $index;                   
391                 // BUILD ODBC QUERIES (and assign query names)
392                 // /etc/asterisk/func_odbc.conf
393                 if($smartroute['dbengine'] == 'odbc') {
394                     // create odbc query
395                     $odbc_query = smartroutes_create_odbc_query($smartroute, $smartroute_queries[$index]);
396                     // note odbc query name for this query
397                     $smartroute_queries[$index]['odbc_query'] = $odbc_query;
398
399                     // store to write to file when done
400                     $odbc_queries[] = $odbc_query;
401                     }
402                     
403                 if($smartroute_queries[$index]['use_wizard'] == 1) {
404                     $smartroute_queries[$index]['return_count'] = 1;
405                     $smartroute_queries[$index]['adv_varname1'] = "DBRESULT";
406                     }
407                 else {
408                     // count the numbers of returns needed (by counting commas before FROM
409                     // ------------------------------------------------------------------------------------------------------------
410                     // NOTE!!!: not precise because complex queries with sub-function returns will increase value (but we cap at 5)
411                     // ------------------------------------------------------------------------------------------------------------
412                     $sqlparts = explode(" FROM ", strtoupper($smartroute_queries[$index]['query']));
413                     $smartroute_queries[$index]['return_count'] = substr_count($sqlparts[0], ",")+1;           
414                     // we cap at 5 returns tracked
415                     if($smartroute_queries[$index]['return_count'] > 5)
416                         $smartroute_queries[$index]['return_count'] = 5;
417                         
418                     // make sure we have varnames for the necessary returns AND BUILD ARRAY var
419                     $smartroute_queries[$index]['array_var'] = "ARRAY(";
420                     $smartroute_queries[$index]['mysql_array_var'] = "";
421                     
422                     for($currVar = 1; $currVar <= $smartroute_queries[$index]['return_count']; $currVar++) {
423                         if(empty($smartroute_queries[$index]['adv_varname'.$currVar])) {
424                             $smartroute_queries[$index]['adv_varname'.$currVar] = "DBQUERY_RET_".$index."_".$currVar;
425                             }
426                             
427                         // assemble array var for assigning result of db query
428                         if($currVar > 1) {
429                             $smartroute_queries[$index]['array_var'] .= ",";
430                             $smartroute_queries[$index]['mysql_array_var'] .= " ";
431                             }                       
432                         $smartroute_queries[$index]['array_var'] .= $smartroute_queries[$index]['adv_varname'.$currVar];
433                         $smartroute_queries[$index]['mysql_array_var'] .= $smartroute_queries[$index]['adv_varname'.$currVar];
434                         }
435                     $smartroute_queries[$index]['array_var'] .= ")";
436
437                     if($smartroute['dbengine'] == 'mysql' && $escapeMySQL) {
438                         // version 1.2/1.4 asterisk requires escaping inline mysql searches
439                         $smartroute_queries[$index]['mysql_array_var'] = str_replace(array_keys($replacements), array_values($replacements), $smartroute_queries[$index]['mysql_array_var']);
440                         }                   
441                     }                                       
442                 }
443
444             // **** START WRITING DIALPLAN FOR THIS ROUTE
445             // **** first start with the invalid handler (when the sip provider sends non-numeric characters in DID (like '+')
446             $ext->add($context, 'i', '', new ext_noop('Smartroute invalid DID handler - FIX EXTENSION VAR'));
447             // fix EXTEN and send back through the smartroute
448             if($smartroute['limitdiddigits'] != "" && $smartroute['limitdiddigits'] > '0') {
449                 // only use the last xx digits from did (effectively stripping unnecessary prefixes)
450                 $ext->add($context, 'i', '', new ext_setvar('FIX_EXTEN','${INVALID_EXTEN:-'.$smartroute['limitdiddigits'].'}'));
451                 }       
452             else {
453                 $ext->add($context, 'i', '', new ext_setvar('FIX_EXTEN','${INVALID_EXTEN}'));
454                 }
455
456             $ext->add($context, 'i', '', new ext_setvar('TMP','0'));
457             $ext->add($context, 'i', '', new ext_setvar('ANS',''));
458             $ext->add($context, 'i', '', new ext_setvar('END','${LEN(${FIX_EXTEN})}'));
459             $ext->add($context, 'i', 'clean_ext_loop_top', new ext_gotoif('$["${TMP}" = "${END}"]','clean_ext_done'));
460             $ext->add($context, 'i', '', new ext_setvar('TCH','${FIX_EXTEN:${TMP}:1}'));
461             $ext->add($context, 'i', '', new ext_gotoif('$["${TCH}" < "0"]','clean_ext_ignore_char'));
462             $ext->add($context, 'i', '', new ext_gotoif('$["${TCH}" > "9"]','clean_ext_ignore_char'));
463             $ext->add($context, 'i', '', new ext_setvar('ANS','${ANS}${TCH}'));
464             $ext->add($context, 'i', 'clean_ext_ignore_char', new ext_setvar('TMP','$[${TMP}+1]'));
465             $ext->add($context, 'i', '', new ext_goto('clean_ext_loop_top'));           
466             $ext->add($context, 'i', 'clean_ext_done', new ext_setvar('FIX_EXTEN','${ANS}'));       
467             $ext->add($context, 'i', '', new ext_goto('smartroute-'.$id.',${FIX_EXTEN},1'));       
468
469             // *** now include handler in case passed extension is 's' - pull EXTEN from CATCHALL_DID
470             $ext->add($context, 's', '', new ext_noop('Smartroute passed generic extension s handler - FIX EXTENSION VAR'));
471             $ext->add($context, 's', '', new ext_gotoif('$["${CATCHALL_DID}" != "s" & "${CATCHALL_DID}empty" != "empty"]','smartroute-'.$id.',${CATCHALL_DID},1'));
472             $ext->add($context, 's', '', new ext_gotoif('$["${FROM_DID}" != "s" & "${FROM_DID}empty" != "empty"]','smartroute-'.$id.',${FROM_DID},1'));
473             $ext->add($context, 's', '', new ext_goto('smartroute-'.$id.',${CALLERID(dnid)},1'));           
474             
475             // proceed with standard dialplan
476             $ext->add($context, $extension, '', new ext_noop('Smartroute: Start Standard Processing - DB Routing'));
477             
478             // if FROM_DID isn't set (OR IS SET AS 's') then set it as the EXTEN passed into this context, or the CATCHALL_DID, or the CALLERID(dnid)
479             $ext->add($context, $extension, '', new ext_execif('$[ "${FROM_DID}" = "" | "${FROM_DID}" = "s"] ','Set','__FROM_DID=${EXTEN}'));
480             $ext->add($context, $extension, '', new ext_execif('$[ "${FROM_DID}" = "" | "${FROM_DID}" = "s"] ','Set','__FROM_DID=${CATCHALL_DID}'));
481             $ext->add($context, $extension, '', new ext_execif('$[ "${FROM_DID}" = "" | "${FROM_DID}" = "s"] ','Set','__FROM_DID=${CALLERID(dnid)}'));
482             
483             if($smartroute['limitdiddigits'] != "" && $smartroute['limitdiddigits'] > '0') {
484                 // only use the last xx digits from did (effectively stripping unnecessary prefixes)
485                 $ext->add($context, $extension, '', new ext_execif('$[ "${FROM_DID}" = "" ] ','Set','__FROM_DID=${EXTEN}'));
486                 $ext->add($context, $extension, '', new ext_setvar('__FROM_DID','${FROM_DID:-'.$smartroute['limitdiddigits'].'}'));
487                 }       
488             else {
489                 // no from_did set so use EXTEN as from_did
490                 $ext->add($context, $extension, '', new ext_execif('$[ "${FROM_DID}" = "" ] ','Set','__FROM_DID=${EXTEN}'));
491                 }           
492
493             // *** write standard inbound route stuff
494             // always set callerID name
495             $ext->add($context, $extension, '', new ext_execif('$[ "${CALLERID(name)}" = "" ] ','Set','CALLERID(name)=${CALLERID(num)}'));
496             
497             // after setting callerID name, strip unnecessary callerID prefix (for routing and accounting purposes)
498             if($smartroute['limitciddigits'] != "" && $smartroute['limitciddigits'] > '0') {
499                 // only use the last xx digits from caller-id (effectively stripping unnecessary prefixes)
500                 $ext->add($context, $extension, '', new ext_setvar('CALLERID(num)','${CALLERID(num):-'.$smartroute['limitciddigits'].'}'));
501                 }                   
502             
503             if (!empty($item['mohclass']) && trim($smartroute['mohclass']) != 'default') {
504                 $ext->add($context, $extension, '', new ext_setmusiconhold($smartroute['mohclass']));
505                 $ext->add($context, $extension, '', new ext_setvar('__MOHCLASS',$smartroute['mohclass']));
506                 }
507
508             // If we require RINGING, signal it as soon as we enter.
509             if ($smartroute['ringing'] === "CHECKED") {
510                 $ext->add($context, $extension, '', new ext_ringing(''));
511                 }
512             if ($smartroute['delay_answer']) {
513                 $ext->add($context, $extension, '', new ext_wait($smartroute['delay_answer']));
514                 }
515                 
516             if ($item['privacyman'] == "1") {
517                 $ext->add($context, $extension, '', new ext_macro('privacy-mgr',$smartroute['pmmaxretries'].','.$smartroute['pmminlength']));
518                 }
519             else {
520                 // if privacymanager is used, this is not necessary as it will not let blocked/anonymous calls through
521                 // otherwise, we need to save the caller presence to set it properly if we forward the call back out the pbx
522                 // note - the indirect table could go away as of 1.4.20 where it is fixed so that SetCallerPres can take
523                 // the raw format.
524                 //
525                 if(version_compare($version, "1.6", "lt")) {
526                     $ext->add($context, $extension, '', new ext_setvar('__CALLINGPRES_SV','${CALLINGPRES_${CALLINGPRES}}'));
527                     }
528                 else {
529                     $ext->add($context, $extension, '', new ext_setvar('__CALLINGPRES_SV','${CALLERPRES()}'));
530                     }
531                 $ext->add($context, $extension, '', new ext_setcallerpres('allowed_not_screened'));
532                 }
533             
534             if (!empty($smartroute['alertinfo'])) {
535                 $ext->add($context, $extension, '', new ext_setvar("__ALERT_INFO", str_replace(';', '\;', $smartroute['alertinfo'])));
536                 }               
537                 
538             if (!empty($smartroute['grppre'])) {
539                 $ext->add($context, $extension, '', new ext_setvar('_RGPREFIX', $smartroute['grppre']));
540                 $ext->add($context, $extension, '', new ext_setvar('CALLERID(name)','${RGPREFIX}${CALLERID(name)}'));
541                 }
542                 
543             // *** FAX DIALPLAN COMPONENTS
544             if (function_exists('fax_get_config') && $smartroute['faxenabled'] == 1) {
545                 $ext->add($context, 'fax', '', new ext_goto('${CUT(FAX_DEST,^,1)},${CUT(FAX_DEST,^,2)},${CUT(FAX_DEST,^,3)}'));               
546                 
547                 $fax=fax_detect($version);
548                 if ($fax['module']) {
549                     $fax_settings['force_detection'] = 'yes';
550                     }
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                     if ($smartroute['faxdetection'] == 'nvfax' && !$fax['nvfax']) {
556                         //TODO: add notificatoin to notification panel that this was skipped because NVFaxdetec not present
557                         // skip this one if there is no NVFaxdetect installed on this system
558                           }
559                       else {
560                         // proceed with forced fax detection
561                         if(!isset($smartroute['legacy_email'])) $smartroute['legacy_email'] = null;
562                         if ($smartroute['legacy_email'] === null) {
563                             $ext->splice($context, $extension, 'dest-ext', new ext_setvar('FAX_DEST',str_replace(',','^',$smartroute['faxdestination'])));
564                             }
565                         else {
566                             $ext->splice($context, $extension, 'dest-ext', new ext_setvar('FAX_DEST','ext-fax^s^1'));
567                             if (!empty($smartroute['legacy_email'])) {
568                                 $fax_rx_email = $smartroute['legacy_email'];
569                                 }
570                             else {
571                                 if (!isset($default_fax_rx_email)) {
572                                     $default_address = sql('SELECT value FROM fax_details WHERE `key` = \'fax_rx_email\'','getRow');
573                                     $default_fax_rx_email = $default_address[0];
574                                     }
575                                 $fax_rx_email = $default_fax_rx_email;
576                                 }
577                             $ext->splice($context, $extension, 'dest-ext', new ext_setvar('FAX_RX_EMAIL',$fax_rx_email));
578                             }
579                         $ext->splice($context, $extension, 'dest-ext', new ext_answer(''));
580                         if ($smartroute['faxdetection'] == 'nvfax') {
581                             $ext->splice($context, $extension, 'dest-ext', new ext_playtones('ring'));
582                             $ext->splice($context, $extension, 'dest-ext', new ext_nvfaxdetect($smartrouteroute['faxdetectionwait'].",t"));
583                             }
584                         else {
585                             $ext->splice($context, $extension, 'dest-ext', new ext_wait($smartroute['faxdetectionwait']));
586                             }                         
587                           }
588                     }               
589                 }
590             else {
591                 // blank the fax destination if fax disabled on this route
592                 $ext->splice($context, $extension, 'dest-ext', new ext_setvar('FAX_DEST',''));
593                 }
594                 
595                 
596             // **** DONE WITH STANDARD INBOUND ROUTE DIALPLAN
597             // write the main query in dialplan   
598             $ext->add($context, $extension, '', new ext_noop('Smartroute: '.$smartroute['name']));
599             
600             $mainQueryPresent = false;
601                 
602             if($smartroute['dbengine'] == 'mysql' && !empty($smartroute_queries[$main_query]['query'])) {
603                 $mainQueryPresent = true;
604                 
605                 // write mysql version of query
606                 $ext->add($context, $extension, '', new ext_mysql_connect('connid', $smartroute['mysql-host'],  $smartroute['mysql-username'],  $smartroute['mysql-password'],  $smartroute['mysql-database']));
607                 $ext->add($context, $extension, '', new ext_mysql_query('resultid', 'connid', $smartroute_queries[$main_query]['query']));
608                 if($smartroute_queries[$main_query]['return_count'] == 1) {
609                     // assign result of query to single var
610                     $ext->add($context, $extension, '', new ext_mysql_fetch('fetchid', 'resultid', $smartroute_queries[$main_query]['adv_varname1']));
611                     }
612                 else {
613                     // assign result of query to array var (multiple results)
614                     $ext->add($context, $extension, '', new ext_mysql_fetch('fetchid', 'resultid', $smartroute_queries[$main_query]['mysql_array_var']));                   
615                     }
616                 $ext->add($context, $extension, '', new ext_mysql_clear('resultid'));                           
617                 $ext->add($context, $extension, '', new ext_mysql_disconnect('connid'));
618                 $ext->add($context, $extension, '', new ext_execif('$[${fetchid} = 0]', 'Set', $smartroute_queries[$main_query]['adv_varname1'].'=""'));
619                 $ext->add($context, $extension, '', new ext_gotoif('$[${fetchid} = 0]','no_match_found'));
620                 }
621             else if(!empty($smartroute_queries[$main_query]['odbc_query'])) {
622                 $mainQueryPresent = true;
623                 
624                 // write odbc version of query
625                 if($smartroute_queries[$main_query]['return_count'] == 1) {
626                     // assign result of query to single var
627                     $ext->add($context, $extension, '', new ext_setvar($smartroute_queries[$main_query]['adv_varname1'], $smartroute_queries[$main_query]['odbc_query']['odbc_command']));
628                     }
629                 else {
630                     // assign result of query to array var (multiple results)
631                     $ext->add($context, $extension, '', new ext_setvar($smartroute_queries[$main_query]['array_var'], $smartroute_queries[$main_query]['odbc_query']['odbc_command']));
632                     }
633                 }
634                 
635             if($mainQueryPresent) {               
636                 // write destination gotos
637                 if(!empty($smartroute_dests)) {
638                     // set match-type
639                     switch($smartroute['search-type']) {
640                         case 'LESSER':
641                             $matchtype = "<";
642                             break;
643                             
644                         case 'GREATER':
645                             $matchtype = ">";
646                             break;
647                             
648                         case 'EXACT':
649                         default:
650                             $matchtype = "=";
651                             break;
652                         }
653                         
654                     // if main query first var was setting a global var, strip the __ prefix
655                     $smartroute_queries[$main_query]['adv_varname1'] = trim($smartroute_queries[$main_query]['adv_varname1']);
656                     if($smartroute_queries[$main_query]['adv_varname1'][0] == '_' && $smartroute_queries[$main_query]['adv_varname1'][0] == '_') {
657                         $smartroute_queries[$main_query]['adv_varname1'] = substr($smartroute_queries[$main_query]['adv_varname1'], 2);
658                         }                       
659                 
660                     // first write the goto statements (redirect to another part of this section - multiline)                           
661                     foreach($smartroute_dests as $index => $dest) {
662                         $smartroute_dests[$index]['index'] = $index;
663                             
664                         $ext->add($context, $extension, '', new ext_gotoif('$["${'.$smartroute_queries[$main_query]['adv_varname1'].'}" '.$matchtype.' "'.$dest['matchkey'].'"]',"destination".$index));
665                         }
666                     }           
667                 }
668                 
669             // write the default destination goto
670             $ext->add($context, $extension, 'no_match_found', new ext_noop('No Smartroute Match: Goto Default Destination'));
671             
672             if(!empty($smartroute['destination'])) {
673                 $ext->add($context, $extension, '', new ext_goto($smartroute['destination']));
674                 }
675             $ext->add($context, $extension, '', new ext_hangup(''));
676             
677             // write the destination sections
678             if(!empty($smartroute_dests)) {
679                 // first write the goto statements (redirect to another part of this section - multiline)
680                 foreach($smartroute_dests as $dest) {
681                     $macrodestination = false;                   
682                     
683                     // change destination trunks from ext-trunk to dialout-trunk
684                     // NOTE: will require dialout rules to be set appropriately (ex: allow international if attempting international) or call will fail
685                     if(strstr($dest['destination'], "ext-trunk")) {
686                         // fix trunk destinations to use override extension and the dialout macro
687                         $destparts = explode(",", $dest['destination']);
688                         $dest['destination'] = "Macro(dialout-trunk,".$destparts[1].",".(empty($dest['extvar'])?"${FROM_DID}":$dest['extvar']).",)";
689                         $macrodestination = true;
690                         }
691                     
692                     // set processing vars
693                     $ext->add($context, $extension, 'destination'.$dest['index'], new ext_setvar('SR_PRIMARY_DEST', str_replace(',','^',$dest['destination'])));
694                     $ext->add($context, $extension, '', new ext_setvar('SR_FAILOVER_DEST', str_replace(',','^',$dest['failover_dest'])));
695                     $ext->add($context, $extension, '', new ext_setvar('SR_OR_EXTVAR', '"'.$dest['extvar'].'"'));
696                     if($macrodestination) {
697                         // this tells processing section to use a macro and not goto for primary destination (allows failover)
698                         $ext->add($context, $extension, '', new ext_setvar('SR_MACRO', "YES"));
699                         $ext->add($context, $extension, '', new ext_setvar('SR_MACRO_TRUNK', $destparts[1]));
700                         }                   
701                     else {
702                         // clear these
703                         $ext->add($context, $extension, '', new ext_setvar('SR_MACRO', ""));
704                         $ext->add($context, $extension, '', new ext_setvar('SR_MACRO_TRUNK', ""));
705                         }
706                     $ext->add($context, $extension, '', new ext_goto("process_match_found"));
707                     }
708                 }           
709
710             // CLEANUP *** SHOULD NOT REACH THIS LINE OF DIALPLAN CODE ***
711             $ext->add($context, $extension, '', new ext_noop('Smartroute Error - should never get here.'));
712             $ext->add($context, $extension, '', new ext_hangup(''));
713                             
714             // write the section to process found match"
715             // first write the secondary queries to pull data
716             // then see if we need to use the extvar
717             // finally attempt transfer to primary and if fails then attempt transfer to failover_dest
718             $ext->add($context, $extension, 'process_match_found', new ext_noop('Process Match Found'));
719             
720             if(count($smartroute_queries) > 1) {
721
722                 // connect 1 time, run queries and then close connection afterward
723                 if($smartroute['dbengine'] == 'mysql') {
724                     $ext->add($context, $extension, '', new ext_mysql_connect('connid', $smartroute['mysql-host'],  $smartroute['mysql-username'],  $smartroute['mysql-password'],  $smartroute['mysql-database']));
725                     }           
726                 
727                 // start by writing secondary queries
728                 foreach ($smartroute_queries as $index => $query) {
729                     if($smartroute_queries[$index]['mainquery'] == 1) {
730                         // skip main query (processed above)
731                         continue;
732                         }               
733                     
734                     if($smartroute['dbengine'] == 'mysql') {
735                         // write mysql version of query
736                         $ext->add($context, $extension, '', new ext_mysql_query('resultid', 'connid', $query['query']));
737                         if($query['return_count'] == 1) {
738                             // assign result of query to single var
739                             $ext->add($context, $extension, '', new ext_mysql_fetch('fetchid', 'resultid', $query['adv_varname1']));
740                             }
741                         else {
742                             // assign result of query to array var (multiple results)
743                             $ext->add($context, $extension, '', new ext_mysql_fetch('fetchid', 'resultid', $query['mysql_array_var']));                   
744                             }
745                         $ext->add($context, $extension, '', new ext_mysql_clear('resultid'));                           
746                         }
747                     else {
748                         // write odbc version of query
749                         if($query['return_count'] == 1) {
750                             // assign result of query to single var
751                             $ext->add($context, $extension, '', new ext_setvar($query['adv_varname1'], $query['odbc_query']['odbc_command']));
752                             }
753                         else {
754                             // assign result of query to array var (multiple results)
755                             $ext->add($context, $extension, '', new ext_setvar($query['array_var'], $query['odbc_query']['odbc_command']));
756                             }
757                         }
758                     }
759     
760                 // connect 1 time, run queries and then close connection afterward
761                 if($smartroute['dbengine'] == 'mysql') {
762                     $ext->add($context, $extension, '', new ext_mysql_disconnect('connid'));
763                     }
764                 }           
765                 
766             // if extvar not blank, set FROM_DID=extvar (ext-trunk will dial whatever is in FROM_DID)
767             // not needed for dialout-trunk: $ext->add($context, $extension, '', new ext_execif('$["${SR_OR_EXTVAR}empty" != "empty"]', new ext_setvar('FROM_DID', '${SR_OR_EXTVAR}'));
768
769             // when doing the actual dialing, we use the dial-out macros dialout-trunk instead of the normal ext-trunk (that doesn't allow failover)
770             // if we used the normal ext-trunk, we could set FROM_DID=SR_OR_EXTVAR in order to translate to a new extension on a destination trunk
771             $ext->add($context, $extension, '', new ext_gotoif('$["${SR_MACRO}empty" != "empty"]',"process_macrotrunk"));
772             
773             // standard goto on primary (won't allow failover
774             $ext->add($context, $extension, '', new ext_goto('${CUT(SR_PRIMARY_DEST,^,1)},${CUT(SR_PRIMARY_DEST,^,2)},${CUT(SR_PRIMARY_DEST,^,3)}'));
775             $ext->add($context, $extension, '', new ext_goto('${CUT(SR_FAILOVER_DEST,^,1)},${CUT(SR_FAILOVER_DEST,^,2)},${CUT(SR_FAILOVER_DEST,^,3)}'));
776             $ext->add($context, $extension, '', new ext_hangup(''));           
777             
778             // primary trunk goto allows macro and failover
779             $ext->add($context, $extension, 'process_macrotrunk', new ext_noop('Process Trunk Destination with Failover'));
780             $ext->add($context, $extension, '', new ext_setvar('INTRACOMPANYROUTE', 'YES')); // necessary so macro-dialout-trunk won't set callerid to trunk default - this one is overkill but what the heck
781             $ext->add($context, $extension, '', new ext_setvar('KEEPCID', 'TRUE')); // necessary so macro-dialout-trunk won't set callerid to trunk default
782             $ext->add($context, $extension, '', new ext_setvar('OUTDISABLE_${SR_MACRO_TRUNK}', 'off')); // necessary so we can override disabled outbound dialing for trunk
783             
784             // if we failover, macro-dialout-trunk resets the callerid so we have to save it here
785             $ext->add($context, $extension, '', new ext_setvar('SAVECID', '${CALLERID(number)}')); // necessary so macro-dialout-trunk won't set callerid to trunk default           
786                 
787             $ext->add($context, $extension, '', new ext_execif('$["${SR_OR_EXTVAR}empty" = "empty"]', 'Set', 'SR_OR_EXTVAR=${FROM_DID}'));
788             $ext->add($context, $extension, '', new ext_macro('dialout-trunk','${SR_MACRO_TRUNK},${SR_OR_EXTVAR},'));
789             // if primary fails then go to failover destination
790             // if we failover, macro-dialout-trunk resets the callerid so we have to RESTORE it here
791             $ext->add($context, $extension, '', new ext_setvar('CALLERID(number)', '${SAVECID}')); // necessary so macro-dialout-trunk won't set callerid to trunk default
792             
793             $ext->add($context, $extension, '', new ext_goto('${CUT(SR_FAILOVER_DEST,^,1)},${CUT(SR_FAILOVER_DEST,^,2)},${CUT(SR_FAILOVER_DEST,^,3)}'));       
794               $ext->add($context, $extension, '', new ext_hangup(''));           
795               
796               // add hangup extension/state
797             $ext->add($context, 'h', '', new ext_macro('hangupcall',''));                 
798             }
799         }
800         
801     // NOW WRITE ODBC QUERY FILE
802     if(count($odbc_queries) > 0) {
803         smartroutes_save_odbc_funcs($odbc_queries);
804         }
805
806     // for debugging get_config
807 //    ob_end_flush();
808 //    fclose($ob_file);       
809     }
810     
811
812         
813 function smartroutes_create_odbc_query($smartroute, $query) {
814     $odbc_query = array();
815     $clean_name = preg_replace("/[^a-zA-Z0-9\s]/", "_", $smartroute['name']);
816     
817     // build odbc query vals
818     $odbc_query['prefix'] = "SMARTRDB";
819     $odbc_query['dsn'] = $smartroute['odbc-dsn'];
820     $odbc_query['label'] = strtoupper($clean_name.$query['index']);
821     $odbc_query['orig_query'] = $query['query'];
822     $odbc_query['query'] = $query['query'];   
823     $odbc_query['args'] = array();
824     // build the odbc command
825     $odbc_query['odbc_command'] = '${'.$odbc_query['prefix']."_".$odbc_query['label']."(";
826     
827     // get query args and convert query to arg-based
828     preg_match_all("/\{[\s]*([^:}]*)[:\}]/", $odbc_query['query'], $ast_vars);
829
830     // preg_match returns the entire match (with brackets) in array[0] and just the matched parts in array[1]
831     $ast_vars = $ast_vars[1];
832     
833     if(is_array($ast_vars) && count($ast_vars)) {
834         // get just unique values
835         $ast_vars = array_unique($ast_vars);
836         $currArg = 1;
837         // replace with args
838         foreach($ast_vars as $index => $ast_var) {
839             $arg = array();           
840             $arg['arg'] = 'ARG'.$currArg;
841             $arg['var'] = $ast_var;
842             $arg['varnum'] = $currArg;           
843             $odbc_query['args'][] = $arg;
844                         
845             // first replace with arg (with or without ':') AND SQL_ESC
846             // replace where we don't have the ':' (asterisk var substring notation)
847             $odbc_query['query'] = preg_replace("/\{[\s]*".$arg['var']."[\}]/", '{SQL_ESC(\${'.$arg['arg'].'})}', $odbc_query['query']);
848             // replace where we DO have the ':' (asterisk var substring notation)
849             $odbc_query['query'] = preg_replace("/\{[\s]*".$arg['var']."[:]([^\}]*)[\}]/", '{SQL_ESC(\${'.$arg['arg'].':$1})}', $odbc_query['query']);
850             // continue building odbc command
851             if($currArg > 1) $odbc_query['odbc_command'] .= ",";
852             $odbc_query['odbc_command'] .= '${'.$ast_var.'}';
853             
854             ++$currArg;           
855             }       
856         }   
857
858     // finish/close odbc command
859     $odbc_query['odbc_command'] .= ")}";
860     return $odbc_query;
861     }     
862     
863
864     
865 function smartroutes_save_odbc_funcs($odbc_queries) {
866     global $version;
867
868     // note that readsql and writesql are required for asterisk 1.6.x and higher.  In earlier versions, read and write might be required.
869     // don't forget to SQL_ESC the args in the query sql
870     $odbc_config = array();
871     
872     // open config file for reading
873     $fh = fopen('/etc/asterisk/func_odbc.conf', 'r');
874     
875     // read current functions
876     $func_name = "";
877     while($line=fgets($fh))    {
878         $line = trim($line);
879         if(empty($line)) continue;
880         
881         if($line[0] == '[') {
882             // this is a new odbc function
883             $func_name = substr($line, 1, -1);
884             
885             // just in case there was a comment or something on the end and we didn't strip the end bracket
886             $end_bracket = strpos($func_name, ']');
887             if($end_bracket !== false) {
888                 $func_name = substr($func_name,0,$end_bracket);
889                 }
890             $func_name = trim($func_name);
891             $odbc_config[$func_name] = array();
892             }
893         else {
894             $func_setting = explode("=",$line);
895             }
896         
897         if(empty($func_name)) continue;
898         if(empty($func_setting) || empty($func_setting[0]) || empty($func_setting[1])) continue;
899         
900         $func_setting[0] = strtolower(trim($func_setting[0]));       
901         $odbc_config[$func_name][$func_setting[0]] = trim($func_setting[1]);
902         }
903         
904     // close config file
905     fclose($fh);
906     
907     // remove any of our previous smartroute functions
908     foreach($odbc_config as $funcname => $funcdef) {
909         $funcname = trim($funcname);
910         if(strpos($funcname, "SMARTRDB") !== false) {
911             // remove this previous smartroute func
912             unset($odbc_config[$funcname]);
913             }
914         if(isset($funcdef['prefix'])) {
915             $funcdef['prefix'] = trim($funcdef['prefix']);
916             if(strpos($funcdef['prefix'],"SMARTRDB") !== false) {
917                 // remove this previous smartroute func
918                 unset($odbc_config[$funcname]);               
919                 }
920             }
921         }   
922     
923     // prepare new functions  (overlap our functions on top of existing ones so that we don't remove anything created outside this module)
924     foreach($odbc_queries as $label => $query) {       
925         $odbc_config[$query['label']]['prefix'] = $query['prefix'];
926         $odbc_config[$query['label']]['dsn'] = $query['dsn'];
927         
928         if(version_compare($version, "1.6", "lt")) {
929             $odbc_config[$query['label']]['read'] = $query['query'];
930             }
931         else {
932             $odbc_config[$query['label']]['readsql'] = $query['query'];
933             }       
934         } 
935     
936     // write the odbc config
937     $output = array();
938     foreach($odbc_config as $label => $settings) {
939         $output[] = "[$label]";
940         foreach($settings as $key => $value) {
941             $output[] = "$key = $value";
942             }
943         $output[] = "";       
944         }
945     // add newline at end
946     $output[] = "";
947         
948     // open config file for writing and truncate to zero length
949     $fh = fopen('/etc/asterisk/func_odbc.conf', 'w+');       
950     $output = implode("\n", $output);
951     fwrite($fh, $output);
952     
953     // close config file
954     fclose($fh);
955     
956 }
957     
958     
959     
960 function smartroutes_fax_hook_core($viewing_itemid, $target_menuid, $smartroute){  // ejr 2-31-11 modified to pass smartroute array
961   //hmm, not sure why engine_getinfo() isnt being called here?! should probobly read: $info=engine_getinfo();
962   //this is what serves fax code to inbound routing
963   $tabindex=null;
964   $type=isset($_REQUEST['type'])?$_REQUEST['type']:'';
965   $extension=isset($_REQUEST['extension'])?$_REQUEST['extension']:'';
966   $cidnum=isset($_REQUEST['cidnum'])?$_REQUEST['cidnum']:'';
967   $extdisplay=isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:'';
968
969   //if were editing, get save parms. Get parms
970   if ($type != 'setup'){
971     if(!$extension && !$cidnum){//set $extension,$cidnum if we dont already have them
972       $opts=explode('/', $extdisplay);$extension=$opts['0'];$cidnum=$opts['1'];
973     }
974     
975     // ejr 2-31-11 modified for smartroute data
976     //$fax=fax_get_incoming($extension,$cidnum);
977     if($smartroute['faxenabled'] == '1')
978         $fax = array('detection'=>$smartroute['faxdetection'], 'detectionwait'=>$smartroute['faxdetectionwait'], 'destination'=>$smartroute['faxdestination'], 'legacy_email'=>null);
979     else
980         $fax = null;
981   }else{
982     $fax=null;
983   }
984   $html='';
985   if($target_menuid == 'did'){
986     $fax_dahdi_faxdetect=fax_dahdi_faxdetect();
987     $fax_sip_faxdetect=fax_sip_faxdetect();
988     $dahdi=ast_with_dahdi()?_('Dahdi'):_('Zaptel');
989     $fax_detect=fax_detect();
990     $fax_settings=fax_get_settings();
991     //ensure that we are using destination for both fax detect and the regular calls
992     $html='<script type="text/javascript">$(document).ready(function(){
993     $("input[name=Submit]").click(function(){
994       if($("input[name=faxenabled]:checked").val()=="true" && !$("[name=gotoFAX]").val()){//ensure the user selected a fax destination
995       alert('._('"You have selected Fax Detection on this route. Please select a valid destination to route calls detected as faxes to."').');return false; } }) });</script>';
996     $html .= '<tr><td colspan="2"><h5>';
997     $html.=_('Fax Detect');
998     $html.='<hr></h5></td></tr>';
999     $html.='<tr>';
1000     $html.='<td><a href="#" class="info">';
1001     $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>";
1002     if($fax_settings['legacy_mode'] == 'yes' || $fax['legacy_email']!==null){
1003       $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>';
1004     }
1005     $html.='</ul></span></a>:</td>';
1006     //dont allow detection to be set if we have no valid detection types
1007     if(!$fax_dahdi_faxdetect && !$fax_sip_faxdetect && !$fax_detect['nvfax']){
1008       $js="if ($(this).val() == 'true'){alert('"._('No fax detection methods found or no valid license. Faxing cannot be enabled.')."');return false;}";
1009       $html.='<td><input type="radio" name="faxenabled" value="false" CHECKED />No';
1010       $html.='<input type="radio" name="faxenabled" value="true"  onclick="'.$js.'"/>Yes</td></tr>';
1011       $html.='</table><table>';
1012     }else{
1013       /*
1014        * show detection options
1015        *
1016        * js to show/hide the detection settings. Second slide is always in a
1017        * callback so that we ait for the fits animation to complete before
1018        * playing the second
1019        */
1020       if($fax['legacy_email']===null && $fax_settings['legacy_mode'] == 'no'){
1021         $jsno="$('.faxdetect').slideUp();";
1022         $jsyes="$('.faxdetect').slideDown();";
1023       }else{
1024         $jsno="$('.faxdetect').slideUp();$('.legacyemail').slideUp();";
1025         $jsyes="$('.legacyemail').slideUp('400',function(){
1026               $('.faxdetect').slideDown()
1027             });";
1028         $jslegacy="$('.faxdest27').slideUp('400',function(){
1029                 $('.faxdetect, .legacyemail').not($('.faxdest27')).slideDown();
1030             });";
1031       }
1032       $html.='<td><input type="radio" name="faxenabled" value="false" CHECKED onclick="'.$jsno.'"/>No';
1033       $html.='<input type="radio" name="faxenabled" value="true" '.($fax?'CHECKED':'').' onclick="'.$jsyes.'"/>Yes';
1034       if($fax['legacy_email']!==null || $fax_settings['legacy_mode'] == 'yes'){
1035         $html.='<input type="radio" name="faxenabled" value="legacy"'.($fax['legacy_email'] !== null ? ' CHECKED ':'').'onclick="'.$jslegacy.'"/>Legacy';
1036       }
1037       $html.='</td></tr>';
1038       $html.='</table>';
1039     }
1040     //fax detection+destinations, hidden if there is fax is disabled
1041     $html.='<table class=faxdetect '.($fax?'':'style="display: none;"').'>';
1042     $info=engine_getinfo();
1043     $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>';
1044     $html.='<td><select name="faxdetection" tabindex="'.++$tabindex.'">';
1045     //$html.='<option value="Auto"'.($faxdetection == 'auto' ? 'SELECTED' : '').'>'. _("Auto").'</option>';<li>Auto: allow the system to chose the best fax detection method</li>
1046     $html.='<option value="dahdi" '.($fax['detection'] == 'dahdi' ? 'SELECTED' : '').' '.($fax_dahdi_faxdetect?'':'disabled').'>'.$dahdi.'</option>';
1047     $html.='<option value="nvfax"'.($fax['detection'] == 'nvfax' ? 'SELECTED' : '').($fax_detect['nvfax']?'':'disabled').'>'. _("NVFax").'</option>';
1048     $html.='<option value="sip" '.($fax['detection'] == 'sip' ? 'SELECTED' : '').' '.((($info['version'] >= "1.6.2") && $fax_sip_faxdetect)?'':'disabled').'>'. _("Sip").'</option>';
1049     $html.='</select></td></tr>';
1050     
1051     $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>';
1052     $html.='<td><select name="faxdetectionwait" tabindex="'.++$tabindex.'">';
1053     // ejr 2-17-11 allow zero seconds 
1054     if($fax['detectionwait'] == ''){$fax['detectionwait']=4;}//default wait time is 4 second
1055     
1056     // ejr 2-15-11 allow zero seconds so fax context is created but we don't wait
1057     // important for trunks that dialout and connect - fax detected by dahdi after we go out over trunk - no need to wait here
1058     for($i=0;$i < 11; $i++){
1059       $html.='<option value="'.$i.'" '.($fax['detectionwait']==$i?'SELECTED':'').'>'.$i.'</option>';
1060     }
1061     $html.='</select></td></tr>';
1062     if($fax['legacy_email']!==null || $fax_settings['legacy_mode'] == 'yes'){
1063       $html.='</table>';
1064       $html.='<table class="legacyemail"'.($fax['legacy_email'] === null ? ' style="display: none;"':'').'>';
1065       $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>';
1066       $html.='<td><input name="legacy_email" value="'.$fax['legacy_email'].'"></td></tr>';
1067       $html.='</table>';
1068       $html.='<table class="faxdest27 faxdetect" style="display: none" >';
1069   }
1070     $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>';
1071     $html.='<td>';
1072     $html.=$fax_detect?drawselects(isset($fax['destination'])?$fax['destination']:null,'FAX',false,false):'';
1073     $html.='</td></tr></table>';
1074     $html.='<table>';
1075   }
1076   return $html;
1077
1078 }
1079     
1080     
1081     
1082
1083 ?>
Note: See TracBrowser for help on using the browser.