root/freepbx/branches/bootstrap/amp_conf/htdocs/admin/functions.inc.php

Revision 10812, 39.5 kB (checked in by p_lindheimer, 2 years ago)

undefined variables

  • Property svn:mime-type set to text/html
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php /* $id$ */
2 //Copyright (C) 2004 Coalescent Systems Inc. (info@coalescentsystems.ca)
3 //
4 //This program is free software; you can redistribute it and/or
5 //modify it under the terms of the GNU General Public License
6 //as published by the Free Software Foundation; either version 2
7 //of the License, or (at your option) any later version.
8 //
9 //This program is distributed in the hope that it will be useful,
10 //but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //GNU General Public License for more details.
13
14 //include all necessary classes TODO: include them dynamically as needed
15 $dirname = dirname(__FILE__);
16
17 require_once($dirname . '/libraries/components.class.php');
18 require_once($dirname . '/libraries/xml2Array.class.php');
19 require_once($dirname . '/libraries/cronmanager.class.php');
20 require_once($dirname . '/libraries/moduleHook.class.php');
21 require_once($dirname . '/libraries/notifications.class.php');
22 require_once($dirname . '/libraries/ampuser.class.php');
23 require_once($dirname . '/libraries/components.class.php');
24 require_once($dirname . '/libraries/modulelist.class.php');
25 require_once($dirname . '/libraries/config.functions.php');
26 require_once($dirname . '/libraries/featurecodes.class.php');
27
28 //include other files
29 require_once($dirname . '/libraries/module.functions.php');
30 require_once($dirname . '/libraries/usage_registry.functions.php');
31 require_once($dirname . '/libraries/php-upgrade.functions.php');
32 require_once($dirname . '/libraries/sql.functions.php');
33
34 // returns true if extension is within allowed range
35 function checkRange($extension){
36   $low = isset($_SESSION["AMP_user"]->_extension_low)?$_SESSION["AMP_user"]->_extension_low:'';
37   $high = isset($_SESSION["AMP_user"]->_extension_high)?$_SESSION["AMP_user"]->_extension_high:'';
38  
39   if ((($extension >= $low) && ($extension <= $high)) || ($low == '' && $high == ''))
40     return true;
41   else
42     return false;
43 }
44
45 function getAmpAdminUsers() {
46   global $db;
47
48   $sql = "SELECT username FROM ampusers WHERE sections='*'";
49   $results = $db->getAll($sql);
50   if(DB::IsError($results)) {
51      die_freepbx($sql."<br>\n".$results->getMessage());
52   }
53   return $results;
54 }
55
56 function getAmpUser($username) {
57   global $db;
58  
59   $sql = "SELECT username, password_sha1, extension_low, extension_high, deptname, sections FROM ampusers WHERE username = '".$db->escapeSimple($username)."'";
60   $results = $db->getAll($sql);
61   if(DB::IsError($results)) {
62      die_freepbx($sql."<br>\n".$results->getMessage());
63   }
64  
65   if (count($results) > 0) {
66     $user = array();
67     $user["username"] = $results[0][0];
68     $user["password_sha1"] = $results[0][1];
69     $user["extension_low"] = $results[0][2];
70     $user["extension_high"] = $results[0][3];
71     $user["deptname"] = $results[0][4];
72     $user["sections"] = explode(";",$results[0][5]);
73     return $user;
74   } else {
75     return false;
76   }
77 }
78
79 // returns true if department string matches dept for this user
80 function checkDept($dept){
81   $deptname = isset($_SESSION["AMP_user"])?$_SESSION["AMP_user"]->_deptname:null;
82  
83   if ( ($dept == null) || ($dept == $deptname) )
84     return true;
85   else
86     return false;
87 }
88
89 /**
90  * returns true if asterisk is running with chan_dahdi
91  *
92  * @return bool
93  */
94 function ast_with_dahdi() {
95   global $version;
96   global $astman;
97   global $amp_conf;
98   global $chan_dahdi_loaded;
99
100   // determine once, subsequent calls will use this
101   global $ast_with_dahdi;
102
103   if (isset($ast_with_dahdi)) {
104     return $ast_with_dahdi;
105   }
106  
107   if (empty($version)) {
108     $engine_info = engine_getinfo();
109     $version = $engine_info['version'];
110   }
111     
112   if (version_compare($version, '1.4', 'ge') && $amp_conf['AMPENGINE'] == 'asterisk') {   
113     if ($amp_conf['ZAP2DAHDICOMPAT']) {
114       $ast_with_dahdi = true;
115       $chan_dahdi_loaded = true;
116       return true;
117     } else if (isset($astman) && $astman->connected()) {
118       // earlier revisions of 1.4 and dahdi loaded but still running as zap, so if ZapScan is present, we assume
119       // that is the mode it is running in.
120       $response = $astman->send_request('Command', array('Command' => 'show applications like ZapScan'));
121       if (!preg_match('/1 Applications Matching/', $response['data'])) {
122         $ast_with_dahdi = true;
123         $chan_dahdi_loaded = true;
124         return $ast_with_dahdi;
125       } else {
126         $chan_dahdi_loaded = false;
127       }
128     }
129   }
130   $ast_with_dahdi = false;
131   return $ast_with_dahdi;
132 }
133
134 function engine_getinfo() {
135   global $amp_conf;
136   global $astman;
137
138   switch ($amp_conf['AMPENGINE']) {
139     case 'asterisk':
140       if (isset($astman) && $astman->connected()) {
141         //get version (1.4)
142         $response = $astman->send_request('Command', array('Command'=>'core show version'));
143         if (preg_match('/No such command/',$response['data'])) {
144           // get version (1.2)
145           $response = $astman->send_request('Command', array('Command'=>'show version'));
146         }
147         $verinfo = $response['data'];
148       } else {
149         // could not connect to asterisk manager, try console
150         $verinfo = exec('asterisk -V');
151       }
152       
153       if (preg_match('/Asterisk (\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
154         return array('engine'=>'asterisk', 'version' => $matches[1], 'additional' => $matches[4], 'raw' => $verinfo);
155       } elseif (preg_match('/Asterisk SVN-(\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
156         return array('engine'=>'asterisk', 'version' => $matches[1], 'additional' => $matches[4], 'raw' => $verinfo);
157       } elseif (preg_match('/Asterisk SVN-branch-(\d+(\.\d+)*)-r(-?(\S*))/', $verinfo, $matches)) {
158         return array('engine'=>'asterisk', 'version' => $matches[1].'.'.$matches[4], 'additional' => $matches[4], 'raw' => $verinfo);
159       } elseif (preg_match('/Asterisk SVN-trunk-r(-?(\S*))/', $verinfo, $matches)) {
160         return array('engine'=>'asterisk', 'version' => '1.8', 'additional' => $matches[1], 'raw' => $verinfo);
161       } elseif (preg_match('/Asterisk SVN-.+-(\d+(\.\d+)*)-r(-?(\S*))-(.+)/', $verinfo, $matches)) {
162         return array('engine'=>'asterisk', 'version' => $matches[1], 'additional' => $matches[3], 'raw' => $verinfo);
163       } elseif (preg_match('/Asterisk [B].(\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
164         return array('engine'=>'asterisk', 'version' => '1.2', 'additional' => $matches[3], 'raw' => $verinfo);
165       } elseif (preg_match('/Asterisk [C].(\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
166         return array('engine'=>'asterisk', 'version' => '1.4', 'additional' => $matches[3], 'raw' => $verinfo);
167       }
168
169       return array('engine'=>'ERROR-UNABLE-TO-PARSE', 'version'=>'0', 'additional' => '0', 'raw' => $verinfo);
170     break;
171   }
172   return array('engine'=>'ERROR-UNSUPPORTED-ENGINE-'.$amp_conf['AMPENGINE'], 'version'=>'0', 'additional' => '0', 'raw' => $verinfo);
173 }
174
175 if (!function_exists('version_compare_freepbx')) {
176   /* version_compare that works with FreePBX version numbers
177   */
178   function version_compare_freepbx($version1, $version2, $op = null) {
179           $version1 = str_replace("rc","RC", strtolower($version1));
180           $version2 = str_replace("rc","RC", strtolower($version2));
181       if (!is_null($op)) {
182         return version_compare($version1, $version2, $op);
183       } else {
184         return version_compare($version1, $version2);
185       }
186   }
187 }
188
189 function die_freepbx($text, $extended_text="", $type="FATAL") {
190   $trace = print_r(debug_backtrace(),true);
191   if (function_exists('fatal')) {
192     // "custom" error handler
193     // fatal may only take one param, so we suppress error messages because it doesn't really matter
194     @fatal($text."\n".$trace, $extended_text, $type);
195   } else if (isset($_SERVER['REQUEST_METHOD'])) {
196     // running in webserver
197     echo "<h1>".$type." ERROR</h1>\n";
198     echo "<h3>".$text."</h3>\n";
199     if (!empty($extended_text)) {
200       echo "<p>".$extended_text."</p>\n";
201     }
202     echo "<h4>"._("Trace Back")."</h4>";
203     echo "<pre>$trace</pre>";
204   } else {
205     // CLI
206     echo "[$type] ".$text." ".$extended_text."\n";
207     echo "Trace Back:\n";
208     echo $trace;
209   }
210
211   // always ensure we exit at this point
212   exit(1);
213 }
214
215 //tell application we need to reload asterisk
216 function needreload() {
217   global $db;
218   $sql = "UPDATE admin SET value = 'true' WHERE variable = 'need_reload'";
219   $result = $db->query($sql);
220   if(DB::IsError($result)) {     
221     die_freepbx($sql."<br>\n".$result->getMessage());
222   }
223 }
224
225 function check_reload_needed() {
226   global $db;
227   global $amp_conf;
228   $sql = "SELECT value FROM admin WHERE variable = 'need_reload'";
229   $row = $db->getRow($sql);
230   if(DB::IsError($row)) {
231     die_freepbx($sql."<br>\n".$row->getMessage());
232   }
233   return ($row[0] == 'true' || $amp_conf['DEVELRELOAD']);
234 }
235
236 function do_reload() {
237   global $amp_conf, $asterisk_conf, $db, $astman, $version;
238
239   if (empty($version)) {
240     $engine_info = engine_getinfo();
241     $version = $engine_info['version'];
242   }
243  
244   $notify =& notifications::create($db);
245  
246   $return = array('num_errors'=>0,'test'=>'abc');
247   $exit_val = null;
248  
249   if (isset($amp_conf["PRE_RELOAD"]) && !empty($amp_conf['PRE_RELOAD']))  {
250     exec( $amp_conf["PRE_RELOAD"], $output, $exit_val );
251     
252     if ($exit_val != 0) {
253       $desc = sprintf(_("Exit code was %s and output was: %s"), $exit_val, "\n\n".implode("\n",$output));
254       $notify->add_error('freepbx','reload_pre_script', sprintf(_('Could not run %s script.'), $amp_conf['PRE_RELOAD']), $desc);
255       
256       $return['num_errors']++;
257     } else {
258       $notify->delete('freepbx', 'reload_pre_script');
259     }
260   }
261  
262   $retrieve = $amp_conf['AMPBIN'].'/retrieve_conf 2>&1';
263   //exec($retrieve.'&>'.$asterisk_conf['astlogdir'].'/freepbx-retrieve.log', $output, $exit_val);
264   exec($retrieve, $output, $exit_val);
265  
266   // retrieve_conf html output
267   $return['retrieve_conf'] = 'exit: '.$exit_val.'<br/>'.implode('<br/>',$output);
268  
269   if ($exit_val != 0) {
270     $return['status'] = false;
271     $return['message'] = sprintf(_('Reload failed because retrieve_conf encountered an error: %s'),$exit_val);
272     $return['num_errors']++;
273     $notify->add_critical('freepbx','RCONFFAIL', _("retrieve_conf failed, config not applied"), $return['message']);
274     return $return;
275   }
276  
277   if (!isset($astman) || !$astman) {
278     $return['status'] = false;
279     $return['message'] = _('Reload failed because FreePBX could not connect to the asterisk manager interface.');
280     $return['num_errors']++;
281     $notify->add_critical('freepbx','RCONFFAIL', _("retrieve_conf failed, config not applied"), $return['message']);
282     return $return;
283   }
284   $notify->delete('freepbx', 'RCONFFAIL');
285  
286   //reload MOH to get around 'reload' not actually doing that.
287   $astman->send_request('Command', array('Command'=>'moh reload'));
288  
289   //reload asterisk
290   if (version_compare($version,'1.4','lt')) {
291     $astman->send_request('Command', array('Command'=>'reload'));
292   } else {
293     $astman->send_request('Command', array('Command'=>'module reload')); 
294   }
295  
296   $return['status'] = true;
297   $return['message'] = _('Successfully reloaded');
298  
299  
300   if ($amp_conf['FOPRUN'] && !$amp_conf['FOPDISABLE']) {
301     //bounce op_server.pl
302     $wOpBounce = $amp_conf['AMPBIN'].'/bounce_op.sh';
303     exec($wOpBounce.' &>'.$asterisk_conf['astlogdir'].'/freepbx-bounce_op.log', $output, $exit_val);
304     
305     if ($exit_val != 0) {
306       $desc = _('Could not reload the FOP operator panel server using the bounce_op.sh script. Configuration changes may not be reflected in the panel display.');
307       $notify->add_error('freepbx','reload_fop', _('Could not reload FOP server'), $desc);
308       
309       $return['num_errors']++;
310     } else {
311       $notify->delete('freepbx','reload_fop');
312     }
313   }
314  
315   //store asterisk reloaded status
316   $sql = "UPDATE admin SET value = 'false' WHERE variable = 'need_reload'";
317   $result = $db->query($sql);
318   if(DB::IsError($result)) {
319     $return['message'] = _('Successful reload, but could not clear reload flag due to a database error: ').$db->getMessage();
320     $return['num_errors']++;
321   }
322  
323   if (isset($amp_conf["POST_RELOAD"]) && !empty($amp_conf['POST_RELOAD']))  {
324     exec( $amp_conf["POST_RELOAD"], $output, $exit_val );
325     
326     if ($exit_val != 0) {
327       $desc = sprintf(_("Exit code was %s and output was: %s"), $exit_val, "\n\n".implode("\n",$output));
328       $notify->add_error('freepbx','reload_post_script', sprintf(_('Could not run %s script.'), 'POST_RELOAD'), $desc);
329       
330       $return['num_errors']++;
331     } else {
332       $notify->delete('freepbx', 'reload_post_script');
333     }
334   }
335  
336   return $return;
337 }
338
339 //get the version number
340 function getversion() {
341   global $db;
342   $sql = "SELECT value FROM admin WHERE variable = 'version'";
343   $results = $db->getRow($sql);
344   if(DB::IsError($results)) {
345     die_freepbx($sql."<br>\n".$results->getMessage());
346   }
347   return $results[0];
348 }
349
350 //get the version number
351 function get_framework_version() {
352   global $db;
353   $sql = "SELECT version FROM modules WHERE modulename = 'framework' AND enabled = 1";
354   $version = $db->getOne($sql);
355   if(DB::IsError($version)) {
356     die_freepbx($sql."<br>\n".$version->getMessage());
357   }
358   return $version;
359 }
360
361 // draw list for users and devices with paging
362 // $skip has been deprecated, used to be used to page-enate
363 function drawListMenu($results, $skip, $type, $dispnum, $extdisplay, $description=false) {
364  
365   $index = 0;
366   echo "<ul>\n";
367   if ($description !== false) {
368     echo "\t<li><a ".($extdisplay=='' ? 'class="current"':'')." href=\"config.php?type=".$type."&display=".$dispnum."\">"._("Add")." ".$description."</a></li>\n";
369   }
370   if (isset($results)) {
371     foreach ($results as $key=>$result) {
372       $index= $index + 1;
373       echo "\t<li><a".($extdisplay==$result[0] ? ' class="current"':''). " href=\"config.php?type=".$type."&display=".$dispnum."&extdisplay={$result[0]}\">{$result[1]} &lt;{$result[0]}&gt;</a></li>\n";
374     }
375   }
376   echo "</ul>\n";
377 }
378
379 // this function returns true if $astman is defined and set to something (implying a current connection, false otherwise.
380 // this function no longer puts out an error message, it is up to the caller to handle the situation.
381 // Should probably be changed (at least name) to check if a connection is available to the current engine)
382 //
383 function checkAstMan() {
384   global $astman;
385
386   return ($astman)?true:false;
387 }
388
389 /* merge_ext_followme($dest) {
390  *
391  * The purpose of this function is to take a destination
392  * that was either a core extension OR a findmefollow-destination
393  * and convert it so that they are merged and handled just like
394  * direct-did routing
395  *
396  * Assuming an extension number of 222:
397  *
398  * The two formats that existed for findmefollow were:
399  *
400  * ext-findmefollow,222,1
401  * ext-findmefollow,FM222,1
402  *
403  * The one format that existed for core was:
404  *
405  * ext-local,222,1
406  *
407  * In all those cases they should be converted to:
408  *
409  * from-did-direct,222,1
410  *
411  */
412 function merge_ext_followme($dest) {
413
414   if (preg_match("/^\s*ext-findmefollow,(FM)?(\d+),(\d+)/",$dest,$matches) ||
415       preg_match("/^\s*ext-local,(FM)?(\d+),(\d+)/",$dest,$matches) ) {
416         // matches[2] => extn
417         // matches[3] => priority
418     return "from-did-direct,".$matches[2].",".$matches[3];
419   } else {
420     return $dest;
421   }
422 }
423
424 /** Recursively read voicemail.conf (and any included files)
425  * This function is called by getVoicemailConf()
426  */
427 function parse_voicemailconf($filename, &$vmconf, &$section) {
428   if (is_null($vmconf)) {
429     $vmconf = array();
430   }
431   if (is_null($section)) {
432     $section = "general";
433   }
434  
435   if (file_exists($filename)) {
436     $fd = fopen($filename, "r");
437     while ($line = fgets($fd, 1024)) {
438       if (preg_match("/^\s*(\d+)\s*=>\s*(\d*),(.*),(.*),(.*),(.*)\s*([;#].*)?/",$line,$matches)) {
439         // "mailbox=>password,name,email,pager,options"
440         // this is a voicemail line
441         $vmconf[$section][ $matches[1] ] = array("mailbox"=>$matches[1],
442                   "pwd"=>$matches[2],
443                   "name"=>$matches[3],
444                   "email"=>$matches[4],
445                   "pager"=>$matches[5],
446                   "options"=>array(),
447                   );
448                 
449         // parse options
450         //output($matches);
451         foreach (explode("|",$matches[6]) as $opt) {
452           $temp = explode("=",$opt);
453           //output($temp);
454           if (isset($temp[1])) {
455             list($key,$value) = $temp;
456             $vmconf[$section][ $matches[1] ]["options"][$key] = $value;
457           }
458         }
459       } else if (preg_match('/^(?:\s*)#include(?:\s+)["\']{0,1}([^"\']*)["\']{0,1}(\s*[;#].*)?$/',$line,$matches)) {
460         // include another file
461         
462         if ($matches[1][0] == "/") {
463           // absolute path
464           $filename = trim($matches[1]);
465         } else {
466           // relative path
467           $filename =  dirname($filename)."/".trim($matches[1]);
468         }
469         
470         parse_voicemailconf($filename, $vmconf, $section);
471         
472       } else if (preg_match("/^\s*\[(.+)\]/",$line,$matches)) {
473         // section name
474         $section = strtolower($matches[1]);
475       } else if (preg_match("/^\s*([a-zA-Z0-9-_]+)\s*=\s*(.*?)\s*([;#].*)?$/",$line,$matches)) {
476         // name = value
477         // option line
478         $vmconf[$section][ $matches[1] ] = $matches[2];
479       }
480     }
481     fclose($fd);
482   }
483 }
484
485 /** Write the voicemail.conf file
486  * This is called by saveVoicemail()
487  * It's important to make a copy of $vmconf before passing it. Since this is a recursive function, has to
488  * pass by reference. At the same time, it removes entries as it writes them to the file, so if you don't have
489  * a copy, by the time it's done $vmconf will be empty.
490 */
491 function write_voicemailconf($filename, &$vmconf, &$section, $iteration = 0) {
492   global $amp_conf;
493   if ($iteration == 0) {
494     $section = null;
495   }
496  
497   $output = array();
498     
499   // if the file does not, copy if from the template.
500   // TODO: is this logical?
501   if (!file_exists($filename)) {
502     if (!copy( rtrim($amp_conf["ASTETCDIR"],"/")."/voicemail.conf.template", $filename )){
503       return;
504     }
505   }
506  
507     $fd = fopen($filename, "r");
508     while ($line = fgets($fd, 1024)) {
509       if (preg_match("/^(\s*)(\d+)(\s*)=>(\s*)(\d*),(.*),(.*),(.*),(.*)(\s*[;#].*)?$/",$line,$matches)) {
510         // "mailbox=>password,name,email,pager,options"
511         // this is a voicemail line
512         //DEBUG echo "\nmailbox";
513         
514         // make sure we have something as a comment
515         if (!isset($matches[10])) {
516           $matches[10] = "";
517         }
518         
519         // $matches[1] [3] and [4] are to preserve indents/whitespace, we add these back in
520         
521         if (isset($vmconf[$section][ $matches[2] ])) { 
522           // we have this one loaded
523           // repopulate from our version
524           $temp = & $vmconf[$section][ $matches[2] ];
525           
526           $options = array();
527           foreach ($temp["options"] as $key=>$value) {
528             $options[] = $key."=".$value;
529           }
530           
531           $output[] = $matches[1].$temp["mailbox"].$matches[3]."=>".$matches[4].$temp["pwd"].",".$temp["name"].",".$temp["email"].",".$temp["pager"].",". implode("|",$options).$matches[10];
532           
533           // remove this one from $vmconf
534           unset($vmconf[$section][ $matches[2] ]);
535         } else {
536           // we don't know about this mailbox, so it must be deleted
537           // (and hopefully not JUST added since we did read_voiceamilconf)
538           
539           // do nothing
540         }
541         
542       } else if (preg_match('/^(\s*)#include(\s+)["\']{0,1}([^"\']*)["\']{0,1}(\s*[;#].*)?$/',$line,$matches)) {
543         // include another file
544         //DEBUG echo "\ninclude ".$matches[3]."<blockquote>";
545         
546         // make sure we have something as a comment
547         if (!isset($matches[4])) {
548           $matches[4] = "";
549         }
550         
551         if ($matches[3][0] == "/") {
552           // absolute path
553           $include_filename = trim($matches[3]);
554         } else {
555           // relative path
556           $include_filename =  dirname($filename)."/".trim($matches[3]);
557         }
558         
559         $output[] = trim($matches[0]);
560         write_voicemailconf($include_filename, $vmconf, $section, $iteration+1);
561         
562         //DEBUG echo "</blockquote>";
563         
564       } else if (preg_match("/^(\s*)\[(.+)\](\s*[;#].*)?$/",$line,$matches)) {
565         // section name
566         //DEBUG echo "\nsection";
567         
568         // make sure we have something as a comment
569         if (!isset($matches[3])) {
570           $matches[3] = "";
571         }
572         
573         // check if this is the first run (section is null)
574         if ($section !== null) {
575           // we need to add any new entries here, before the section changes
576           //DEBUG echo "<blockquote><i>";
577           //DEBUG var_dump($vmconf[$section]);
578           if (isset($vmconf[$section])){  //need this, or we get an error if we unset the last items in this section - should probably automatically remove the section/context from voicemail.conf
579             foreach ($vmconf[$section] as $key=>$value) {
580               if (is_array($value)) {
581                 // mailbox line
582                 
583                 $temp = & $vmconf[$section][ $key ];
584                 
585                 $options = array();
586                 foreach ($temp["options"] as $key1=>$value) {
587                   $options[] = $key1."=".$value;
588                 }
589                 
590                 $output[] = $temp["mailbox"]." => ".$temp["pwd"].",".$temp["name"].",".$temp["email"].",".$temp["pager"].",". implode("|",$options);
591                 
592                 // remove this one from $vmconf
593                 unset($vmconf[$section][ $key ]);
594                 
595               } else {
596                 // option line
597                 
598                 $output[] = $key."=".$vmconf[$section][ $key ];
599                 
600                 // remove this one from $vmconf
601                 unset($vmconf[$section][ $key ]);
602               }
603             }
604           }
605           //DEBUG echo "</i></blockquote>";
606         }
607         
608         $section = strtolower($matches[2]);
609         $output[] = $matches[1]."[".$section."]".$matches[3];
610         $existing_sections[] = $section; //remember that this section exists
611
612       } else if (preg_match("/^(\s*)([a-zA-Z0-9-_]+)(\s*)=(\s*)(.*?)(\s*[;#].*)?$/",$line,$matches)) {
613         // name = value
614         // option line
615         //DEBUG echo "\noption line";
616         
617         
618         // make sure we have something as a comment
619         if (!isset($matches[6])) {
620           $matches[6] = "";
621         }
622         
623         if (isset($vmconf[$section][ $matches[2] ])) {
624           $output[] = $matches[1].$matches[2].$matches[3]."=".$matches[4].$vmconf[$section][ $matches[2] ].$matches[6];
625           
626           // remove this one from $vmconf
627           unset($vmconf[$section][ $matches[2] ]);
628         }
629         // else it's been deleted, so we don't write it in
630         
631       } else {
632         // unknown other line -- probably a comment or whitespace
633         //DEBUG echo "\nother: ".$line;
634         
635         $output[] = str_replace(array("\n","\r"),"",$line); // str_replace so we don't double-space
636       }
637     }
638     
639     if (($iteration == 0) && (is_array($vmconf))) {
640       // we need to add any new entries here, since it's the end of the file
641       //DEBUG echo "END OF FILE!! <blockquote><i>";
642       //DEBUG var_dump($vmconf);
643       foreach (array_keys($vmconf) as $section) {
644         if (!in_array($section,$existing_sections))  // If this is a new section, write the context label
645           $output[] = "[".$section."]";
646         foreach ($vmconf[$section] as $key=>$value) {
647           if (is_array($value)) {
648             // mailbox line
649             
650             $temp = & $vmconf[$section][ $key ];
651             
652             $options = array();
653             foreach ($temp["options"] as $key=>$value) {
654               $options[] = $key."=".$value;
655             }
656             
657             $output[] = $temp["mailbox"]." => ".$temp["pwd"].",".$temp["name"].",".$temp["email"].",".$temp["pager"].",". implode("|",$options);
658             
659             // remove this one from $vmconf
660             unset($vmconf[$section][ $key ]);
661             
662           } else {
663             // option line
664             
665             $output[] = $key."=".$vmconf[$section][ $key ];
666             
667             // remove this one from $vmconf
668             unset($vmconf[$section][$key ]);
669           }
670         }
671       }
672       //DEBUG echo "</i></blockquote>";
673     }
674     
675     fclose($fd);
676     
677     //DEBUG echo "\n\nwriting ".$filename;
678     //DEBUG echo "\n-----------\n";
679     //DEBUG echo implode("\n",$output);
680     //DEBUG echo "\n-----------\n";
681     
682     // write this file back out
683     
684     if ($fd = fopen($filename, "w")) {
685       fwrite($fd, implode("\n",$output)."\n");
686       fclose($fd);
687     }
688 }
689
690 /*
691  * $goto is the current goto destination setting
692  * $i is the destination set number (used when drawing multiple destination sets in a single form ie: digital receptionist)
693  * ensure that any form that includes this calls the setDestinations() javascript function on submit.
694  * ie: if the form name is "edit", and drawselects has been called with $i=2 then use onsubmit="setDestinations(edit,2)"
695  * $table specifies if the destinations will be drawn in a new <tr> and <td>
696  *
697  */   
698 function drawselects($goto,$i,$show_custom=false, $table=true, $nodest_msg='') {
699   global $tabindex, $active_modules, $drawselect_destinations, $drawselects_module_hash;
700   $html=$destmod=$errorclass=$errorstyle='';
701   if ($nodest_msg == '') {
702     $nodest_msg = '== '._('choose one').' ==';
703   }
704
705   if($table){$html.='<tr><td colspan=2>';}//wrap in table tags if requested
706
707   if(!isset($drawselect_destinations)){
708     //check for module-specific destination functions
709     foreach($active_modules as $rawmod => $module){
710       $funct = strtolower($rawmod.'_destinations');
711     
712       //if the modulename_destinations() function exits, run it and display selections for it
713       if (function_exists($funct)) {
714         $destArray = $funct(); //returns an array with 'destination' and 'description', and optionally 'category'
715         if(is_Array($destArray)) {
716           foreach($destArray as $dest){
717             $cat=(isset($dest['category'])?$dest['category']:$module['displayname']);
718             $drawselect_destinations[$cat][] = $dest;
719             $drawselects_module_hash[$cat] = $rawmod;
720           }
721         }
722       }
723     }
724     //sort destination alphabetically   
725     ksort($drawselect_destinations);
726     ksort($drawselects_module_hash);
727   }
728   //set variables as arrays for the rare (impossible?) case where there are none
729   if(!isset($drawselect_destinations)){$drawselect_destinations=array();}
730   if(!isset($drawselects_module_hash)){$drawselects_module_hash = array();}
731
732   $foundone=false;
733   $tabindex_needed=true;
734   //get the destination module name if we have a $goto, add custom if there is an issue
735   if($goto){
736     foreach($drawselects_module_hash as $mod => $description){
737       foreach($drawselect_destinations[$mod] as $destination){
738         if($goto==$destination['destination']){
739           $destmod=$mod;
740         }
741       }
742     }
743     if($destmod==''){//if we haven't found a match, display error dest
744       $destmod='Error';
745       $drawselect_destinations['Error'][]=array('destination'=>$goto, 'description'=>'Bad Dest: '.$goto, 'class'=>'drawselect_error');
746       $drawselects_module_hash['Error']='error';
747     }
748   }
749
750   //draw "parent" select box
751   $style=' style="'.(($destmod=='Error')?'background-color:red;':'background-color:white;').'"';
752   $html.='<select name="goto'.$i.'" class="destdropdown" '.$style.' tabindex="'.++$tabindex.'">';
753   $html.='<option value="" style="background-color:white;">'.$nodest_msg.'</option>';
754   foreach($drawselects_module_hash as $mod => $disc){
755     /* We bind to the hosting module's domain. If we find the translation there we use it, if not
756      * we try the default 'amp' domain. If still no luck, we will try the _() which is the current
757      * module's display since some old translation code may have stored it locally but should migrate */
758     bindtextdomain($drawselects_module_hash[$mod],"modules/".$drawselects_module_hash[$mod]."/i18n");
759     bind_textdomain_codeset($drawselects_module_hash[$mod], 'utf8');
760     $label_text=dgettext($drawselects_module_hash[$mod],$mod);
761     if($label_text==$mod){$label_text=dgettext('amp',$label_text);}
762     if($label_text==$mod){$label_text=_($label_text);}
763     /* end i18n */
764     $selected=($mod==$destmod)?' SELECTED ':' ';
765     $style=' style="'.(($mod=='Error')?'background-color:red;':'background-color:white;').'"';
766     $html.='<option value="'.str_replace(' ','_',$mod).'"'.$selected.$style.'>'.$label_text.'</option>';
767   }
768   $html.='</select> ';
769  
770   //draw "children" select boxes
771   $tabindexhtml=' tabindex="'.++$tabindex.'"';//keep out of the foreach so that we don't increment it
772   foreach($drawselect_destinations as $cat=>$destination){
773     $style=(($cat==$destmod)?'':'display:none;');
774     if($cat=='Error'){$style.=' '.$errorstyle;}//add error style
775     $style=' style="'.(($cat=='Error')?'background-color:red;':$style).'"';
776     $html.='<select name="'.str_replace(' ','_',$cat).$i.'" '.$tabindexhtml.$style.' class="destdropdown2">';
777     foreach($destination as $dest){
778       $selected=($goto==$dest['destination'])?'SELECTED ':' ';
779     // This is ugly, but I can't think of another way to do localization for this child object
780         if(isset( $dest['category']) && dgettext('amp',"Terminate Call") == $dest['category']) {
781           $child_label_text = dgettext('amp',$dest['description']);
782       }
783         else {
784       $child_label_text=$dest['description'];
785       }
786       $style=' style="'.(($cat=='Error')?'background-color:red;':'background-color:white;').'"';
787       $html.='<option value="'.$dest['destination'].'" '.$selected.$style.'>'.$child_label_text.'</option>';
788     }
789     $html.='</select>';
790   }
791   if(isset($drawselect_destinations['Error'])){unset($drawselect_destinations['Error']);}
792   if(isset($drawselects_module_hash['Error'])){unset($drawselects_module_hash['Error']);}
793   if($table){$html.='</td></tr>';}//wrap in table tags if requested
794  
795   return $html;
796 }
797
798 /* below are legacy functions required to allow pre 2.0 modules to function (ie: interact with 'extensions' table) */
799
800   //add to extensions table - used in callgroups.php
801   function legacy_extensions_add($addarray) {
802     global $db;
803     $sql = "INSERT INTO extensions (context, extension, priority, application, args, descr, flags) VALUES ('".$addarray[0]."', '".$addarray[1]."', '".$addarray[2]."', '".$addarray[3]."', '".$addarray[4]."', '".$addarray[5]."' , '".$addarray[6]."')";
804     $result = $db->query($sql);
805     if(DB::IsError($result)) {
806       die_freepbx($sql."<br>\n".$result->getMessage());
807     }
808     return $result;
809   }
810  
811   //delete extension from extensions table
812   function legacy_extensions_del($context,$exten) {
813     global $db;
814     $sql = "DELETE FROM extensions WHERE context = '".$db->escapeSimple($context)."' AND `extension` = '".$db->escapeSimple($exten)."'";
815     $result = $db->query($sql);
816     if(DB::IsError($result)) {
817       die_freepbx($sql."<br>\n".$result->getMessage());
818     }
819     return $result;
820   }
821  
822   //get args for specified exten and priority - primarily used to grab goto destination
823   function legacy_args_get($exten,$priority,$context) {
824     global $db;
825     $sql = "SELECT args FROM extensions WHERE extension = '".$db->escapeSimple($exten)."' AND priority = '".$db->escapeSimple($priority)."' AND context = '".$db->escapeSimple($context)."'";
826     list($args) = $db->getRow($sql);
827     return $args;
828   }
829
830 /* end legacy functions */
831
832
833 function get_headers_assoc($url ) {
834   $url_info=parse_url($url);
835   if (isset($url_info['scheme']) && $url_info['scheme'] == 'https') {
836     $port = isset($url_info['port']) ? $url_info['port'] : 443;
837     @$fp=fsockopen('ssl://'.$url_info['host'], $port, $errno, $errstr, 10);
838   } else {
839     $port = isset($url_info['port']) ? $url_info['port'] : 80;
840     @$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 10);
841   }
842   if ($fp) {
843     stream_set_timeout($fp, 10);
844     $head = "HEAD ".@$url_info['path']."?".@$url_info['query'];
845     $head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
846     fputs($fp, $head);
847     while(!feof($fp)) {
848       if($header=trim(fgets($fp, 1024))) {
849         $sc_pos = strpos($header, ':');
850         if ($sc_pos === false) {
851           $headers['status'] = $header;
852         } else {
853           $label = substr( $header, 0, $sc_pos );
854           $value = substr( $header, $sc_pos+1 );
855           $headers[strtolower($label)] = trim($value);
856         }
857       }
858     }
859     return $headers;
860   } else {
861     return false;
862   }
863 }
864
865
866 // Dragged this in from page.modules.php, so it can be used by install_amp.
867 function runModuleSQL($moddir,$type){
868   trigger_error("runModuleSQL() is depreciated - please use _module_runscripts(), or preferably module_install() or module_enable() instead", E_USER_WARNING);
869   _module_runscripts($moddir, $type);
870 }
871
872 /** Log a debug message to a debug file
873  * @param  string   debug message to be printed
874  * @param  string   depreciated
875  * @param  string   depreciated
876  */
877 function freepbx_debug($string, $option='', $filename='') {
878   dbug($string);
879 }
880  /*
881   * FreePBX Debugging function
882   * This function can be called as follows:
883   * dbug() - will just print a time stamp to the debug log file ($amp_conf['FPBXDBUGFILE'])
884   * dbug('string') - same as above + will print the string
885   * dbug('string',$array) - same as above + will print_r the array after the message
886   * dbug($array) - will print_r the array with no message (just a time stamp) 
887   * dbug('string',$array,1) - same as above + will var_dump the array
888   * dbug($array,1) - will var_dump the array with no message  (just a time stamp)
889   *   
890   */ 
891 function dbug(){
892   $opts = func_get_args();
893   $disc = $msg = $dump = null;
894
895   $dump = 0;
896   //sort arguments
897   switch (count($opts)) {
898     case 1:
899       $msg    = $opts[0];
900       break;
901     case 2:
902       if ( is_array($opts[0]) || is_object($opts[0]) ) {
903         $msg  = $opts[0];
904         $dump = $opts[1];
905       } else {
906         $disc = $opts[0];
907         $msg  = $opts[1];
908       }
909       break;
910     case 3:
911       $disc   = $opts[0];
912       $msg    = $opts[1];
913       $dump   = $opts[2];
914       break; 
915   }
916  
917   if ($disc) {
918     $disc = ' \'' . $disc . '\':';
919   }
920  
921   $bt = debug_backtrace();
922   $txt = date("Y-M-d H:i:s")
923     . "\t" . $bt[0]['file'] . ':' . $bt[0]['line']
924     . "\n\n"
925     . $disc
926     . "\n"; //add timestamp + file info
927   dbug_write($txt);
928   if ($dump==1) {//force output via var_dump
929     ob_start();
930     var_dump($msg);
931     $msg=ob_get_contents();
932     ob_end_clean();
933     dbug_write($msg."\n\n\n");
934   } elseif(is_array($msg)||is_object($msg)) {
935     dbug_write(print_r($msg,true)."\n\n\n");
936   } else {
937     dbug_write($msg."\n\n\n");
938   }
939 }
940
941 function dbug_write($txt,$check=''){
942   global $amp_conf;
943   $append=false;
944   //optionaly ensure that dbug file is smaller than $max_size
945   if($check){
946     $max_size = 52428800;//hardcoded to 50MB. is that bad? not enough?
947     $size = filesize($amp_conf['FPBXDBUGFILE']);
948     $append = (($size > $max_size) ? false : true );
949   }
950   if ($append) {
951     file_put_contents($amp_conf['FPBXDBUGFILE'],$txt);
952   } else {
953     file_put_contents($amp_conf['FPBXDBUGFILE'],$txt, FILE_APPEND);
954   }
955  
956 }
957
958 //http://php.net/manual/en/function.set-error-handler.php
959 function freepbx_error_handler($errno, $errstr, $errfile, $errline,  $errcontext) {
960   $txt = date("Y-M-d H:i:s")
961     . "\t" . $errfile . ':' . $errline
962     . "\n\n"
963     . 'ERROR[' . $errno . ']: '
964     . $errstr
965     . "\n\n\n";
966   dbug_write($txt,$check='');
967 }
968
969 /** Log an error to the (database-based) log
970  * @param  string   The section or script where the error occurred
971  * @param  string   The level/severity of the error. Valid levels: 'error', 'warning', 'debug', 'devel-debug'
972  * @param  string   The error message
973  */
974 function freepbx_log($section, $level, $message) {
975   global $db;
976   global $debug; // This is used by retrieve_conf
977   global $amp_conf;
978
979   if (isset($debug) && ($debug != false)) {
980     print "[DEBUG-$section] ($level) $message\n";
981   }
982   if (!$amp_conf['AMPENABLEDEVELDEBUG'] && strtolower(trim($level)) == 'devel-debug') {
983     return true;
984   }
985         
986   if (!$amp_conf['AMPDISABLELOG']) {
987     switch (strtoupper($amp_conf['AMPSYSLOGLEVEL'])) {
988       case 'LOG_EMERG':
989         syslog(LOG_EMERG,"FreePBX-[$level][$section] $message");
990         break;
991       case 'LOG_ALERT':
992         syslog(LOG_ALERT,"FreePBX-[$level][$section] $message");
993         break;
994       case 'LOG_CRIT':
995         syslog(LOG_CRIT,"FreePBX-[$level][$section] $message");
996         break;
997       case 'LOG_ERR':
998         syslog(LOG_ERR,"FreePBX-[$level][$section] $message");
999         break;
1000       case 'LOG_WARNING':
1001         syslog(LOG_WARNING,"FreePBX-[$level][$section] $message");
1002         break;
1003       case 'LOG_NOTICE':
1004         syslog(LOG_NOTICE,"FreePBX-[$level][$section] $message");
1005         break;
1006       case 'LOG_INFO':
1007         syslog(LOG_INFO,"FreePBX-[$level][$section] $message");
1008         break;
1009       case 'LOG_DEBUG':
1010         syslog(LOG_DEBUG,"FreePBX-[$level][$section] $message");
1011         break;
1012       case 'SQL':
1013       case 'LOG_SQL':
1014       default:
1015         $sth = $db->prepare("INSERT INTO freepbx_log (time, section, level, message) VALUES (NOW(),?,?,?)");
1016         $db->execute($sth, array($section, $level, $message));
1017         break;
1018     }
1019
1020   }
1021 }
1022
1023 /** Abort all output, and redirect the browser's location.
1024  *
1025  * Useful for returning to the user to a GET location immediately after doing
1026  * a successful POST operation. This avoids the "this page was sent via POST, resubmit?"
1027  * message in the users browser, and also overwrites the POST page as a location in
1028  * the browser's URL history (eg, they can't press the back button and end up re-submitting
1029  * the page).
1030  *
1031  * @param string   The url to go to
1032  * @param bool     If execution should stop after the function. Defaults to true
1033  */
1034 function redirect($url, $stop_processing = true) {
1035   // TODO: If I don't call ob_end_clean() then is output buffering still on? Do I need to run it off still?
1036   //       (note ob_end_flush() results in the same php NOTICE so not sure how to turn it off. (?ob_implicit_flush(true)?)
1037   //
1038   @ob_end_clean();
1039   @header('Location: '.$url);
1040   if ($stop_processing) exit;
1041 }
1042
1043 /** Abort all output, and redirect the browser's location using standard
1044  * FreePBX user interface variables. By default, will take POST/GET variables
1045  * 'type' and 'display' and pass them along in the URL.
1046  * Also accepts a variable number of parameters, each being the name of a variable
1047  * to pass on.
1048  *
1049  * For example, calling redirect_standard('extdisplay','test'); will take $_REQUEST['type'],
1050  * $_REQUEST['display'], $_REQUEST['extdisplay'], and $_REQUEST['test'],
1051  * and if any are present, use them to build a GET string (eg, "config.php?type=setup&
1052  * display=somemodule&extdisplay=53&test=yes", which is then passed to redirect() to send the browser
1053  * there.
1054  *
1055  * redirect_standard_continue does exactly the same thing but does NOT abort processing. This
1056  * is used when you wish to do a redirect but there is a possibility of other hooks still needing
1057  * to continue processing. Note that this is used in core when in 'extensions' mode, as both the
1058  * users and devices modules need to hook into it together.
1059  *
1060  * @param string  (optional, variable number) The name of a variable from $_REQUEST to
1061  *                pass on to a GET URL.
1062  *
1063  */
1064 function redirect_standard( /* Note. Read the next line. Variable No of Params */ ) {
1065   $args = func_get_Args();
1066
1067         foreach (array_merge(array('type','display'),$args) as $arg) {
1068                 if (isset($_REQUEST[$arg])) {
1069                         $urlopts[] = $arg.'='.urlencode($_REQUEST[$arg]);
1070                 }
1071         }
1072         $url = $_SERVER['PHP_SELF'].'?'.implode('&',$urlopts);
1073         redirect($url);
1074 }
1075
1076 function redirect_standard_continue( /* Note. Read the next line. Varaible No of Params */ ) {
1077   $args = func_get_Args();
1078
1079         foreach (array_merge(array('type','display'),$args) as $arg) {
1080                 if (isset($_REQUEST[$arg])) {
1081                         $urlopts[] = $arg.'='.urlencode($_REQUEST[$arg]);
1082                 }
1083         }
1084         $url = $_SERVER['PHP_SELF'].'?'.implode('&',$urlopts);
1085         redirect($url, false);
1086 }
1087
1088 //This function calls modulename_contexts()
1089 //expects a returned array which minimally includes 'context' => the actual context to include
1090 //can also define 'description' => the display for this context - if undefined will be set to 'context'
1091 //'module' => the display for the section this should be listed under defaults to module display (can be used to group subsets within one module)
1092 //'parent' => if including another context automatically includes this one, list the parent context
1093 //'priority' => default sort order for includes range -50 to +50, 0 is default
1094 //'enabled' => can be used to flag a context as disabled and it won't be included, but will not have its settings removed.
1095 //'extension' => can be used to tag with an extension for checkRange($extension)
1096 //'dept' => can be used to tag with a department for checkDept($dept)
1097 //  this defaults to false for disabled modules.
1098 function freepbx_get_contexts() {
1099   $modules = module_getinfo(false, array(MODULE_STATUS_ENABLED, MODULE_STATUS_DISABLED, MODULE_STATUS_NEEDUPGRADE));
1100  
1101   $contexts = array();
1102  
1103   foreach ($modules as $modname => $mod) {
1104                 $funct = strtolower($modname.'_contexts');
1105     if (function_exists($funct)) {
1106       // call the  modulename_contexts() function
1107       $contextArray = $funct();
1108       if (is_array($contextArray)) {
1109         foreach ($contextArray as $con) {
1110           if (isset($con['context'])) {
1111             if (!isset($con['description'])) {
1112               $con['description'] = $con['context'];
1113             }
1114             if (!isset($con['module'])) {
1115               $con['module'] = $mod['displayName'];
1116             }
1117             if (!isset($con['priority'])) {
1118               $con['priority'] = 0;
1119             }
1120             if (!isset($con['parent'])) {
1121               $con['parent'] = '';
1122             }
1123             if (!isset($con['extension'])) {
1124               $con['extension'] = null;
1125             }
1126             if (!isset($con['dept'])) {
1127               $con['dept'] = null;
1128             }
1129             if ($mod['status'] == MODULE_STATUS_ENABLED) {
1130               if (!isset($con['enabled'])) {
1131                 $con['enabled'] = true;
1132               }
1133             } else {
1134               $con['enabled'] = false;
1135             }
1136             $contexts[ $con['context'] ] = $con;
1137           }
1138         }
1139       }
1140     }
1141   }
1142   return $contexts;
1143 }
1144
1145 ?>
Note: See TracBrowser for help on using the browser.