root/freepbx/trunk/amp_conf/htdocs/admin/functions.inc.php

Revision 12522, 20.1 kB (checked in by p_lindheimer, 5 months ago)

fixes failed autoload scenarios when Zend obfuscated modules are sometimes present

  • 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 $dirname = dirname(__FILE__);
15 define('MODULE_STATUS_NOTINSTALLED', 0);
16 define('MODULE_STATUS_DISABLED', 1);
17 define('MODULE_STATUS_ENABLED', 2);
18 define('MODULE_STATUS_NEEDUPGRADE', 3);
19 define('MODULE_STATUS_BROKEN', -1);
20
21 //http://php.net/manual/en/function.phpversion.php
22 if (!defined('PHP_VERSION_ID')) {
23     $version = explode('.', PHP_VERSION);
24     define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
25 }
26
27 spl_autoload_register('fpbx_framework_autoloader');
28
29 //class that handels freepbx global setting. Dont autoload - we ALWAYS need this anyway
30 require_once($dirname . '/libraries/freepbx_conf.class.php');
31
32 //----------include function files----------
33
34 //freepbx helpers for debuggin/logging/comparing
35 require_once($dirname . '/libraries/utility.functions.php');
36
37 //module state manipulation functions
38 require_once($dirname . '/libraries/module.functions.php');
39
40 //dynamic registry of which exten's are in use and by whom
41 require_once($dirname . '/libraries/usage_registry.functions.php');
42
43 //emulated compatability for older versions of freepbx
44 require_once($dirname . '/libraries/php-upgrade.functions.php');
45
46 //lightweight query functions
47 require_once($dirname . '/libraries/sql.functions.php');
48
49 //functions for view related activities
50 require_once($dirname . '/libraries/view.functions.php');
51
52 //functions for reding writing voicemail files
53 require_once($dirname . '/libraries/voicemail.function.php');
54
55 //legacy functions
56 require_once($dirname . '/libraries/legacy.functions.php');
57
58 //feature code related functions - not sure why these arent part of the class
59 require_once($dirname . '/libraries/featurecodes.functions.php');
60
61 //----------include helpers----------
62
63 //freepbx specific gui helpers
64 require_once($dirname . '/helpers/freepbx_helpers.php');
65
66 //general html helpers
67 require_once($dirname . '/helpers/html_helper.php');
68
69 //form generation
70 if (!defined('BASEPATH')){define('BASEPATH', '');}
71 if (!function_exists('get_instance')) {
72   function get_instance(){return new ci_def();}
73 }
74 if (!class_exists('ci_def')) {
75   class ci_def {function __construct(){$this->lang = new ci_lan_def(); $this->config = new ci_config(); $this->uri = new ci_uri_string();}}
76 }
77 if (!class_exists('ci_lan_def')) {
78   class ci_lan_def {function load(){return false;} function line(){return false;}}
79 }
80 if (!class_exists('ci_config')) {
81   class ci_config {function __construct(){return false;} function site_url($v){return $v;} function item(){return false;}}
82 }
83 if (!class_exists('ci_uri_string')) {
84   class ci_uri_string {function  uri_string(){return false;}}
85 }
86 if (!function_exists('config_item')) {
87   function config_item(){}
88 }
89 require_once($dirname . '/helpers/form_helper.php');
90
91 //freepbx autoloader
92 function fpbx_framework_autoloader($class) {
93   $dirname = dirname(__FILE__);
94   if (substr($class, 0, 3) == 'gui') {
95     $class = 'component';
96   }
97
98   /* Special case of TRUE forces all classes to be loaded. Make sure to add new classes to this array
99    * as they are added to the autoloader. This was added because the presence of Zend enabled modules
100    * can result in the autoloader function failing.
101    *
102    * Basically, every 'case' below should have a corresponding entry in the $class array below.
103    */
104   if ($class === true) {
105     $class = array('ampuser','CI_Email','CI_Table','CssMin','component','featurecode','cronmanager','moduleHook','modulelist','notifications','xml2Array');
106   } else {
107     $class = array($class);
108   }
109
110   foreach ($class as $this_class) switch($this_class){
111     case 'ampuser':
112       require_once($dirname . '/libraries/ampuser.class.php');
113       break;
114     case 'CI_Email':
115       //make upstream scripts happy - for $CI_Email->_set_error_message()
116       if (!function_exists('log_message')) {
117         function log_message(){};
118       }
119       if (!function_exists('get_instance')) {
120         function get_instance(){return new ci_def();}
121       }
122       if (!class_exists('ci_def')) {
123         class ci_def {function __construct(){$this->lang = new ci_lan_def();}}
124       }
125       if (!class_exists('ci_lan_def')) {
126         class ci_lan_def {function load(){return false;} function line(){return false;}}
127       }
128       if (!defined('BASEPATH')){
129         define('BASEPATH', '');
130       }
131       if (!defined('FOPEN_READ')) {
132         define('FOPEN_READ', 'rb');
133       }
134       require_once($dirname . '/helpers/Email.php');
135       break;
136     case 'CI_Table':
137       //make upstream scripts happy
138       if (!function_exists('log_message')) {
139         function log_message(){};
140       }
141       if (!defined('BASEPATH')){define('BASEPATH', '');}
142       require_once($dirname . '/helpers/Table.php');
143       break;
144     case 'CssMin':
145       require_once($dirname . '/libraries/cssmin.class.php');
146       break;
147     case 'component':
148         require_once($dirname . '/libraries/components.class.php');
149         break;
150     case 'featurecode':
151       require_once($dirname . '/libraries/featurecodes.class.php');
152       break;
153     case 'cronmanager':
154       require($dirname . '/libraries/cronmanager.class.php');
155       break;
156     case 'moduleHook':
157       require_once($dirname . '/libraries/moduleHook.class.php');
158       break;
159     case 'modulelist':
160       require_once($dirname . '/libraries/modulelist.class.php');
161       break;
162     case 'notifications':
163       require_once($dirname . '/libraries/notifications.class.php');
164       break;
165       case 'xml2Array':
166         require_once($dirname . '/libraries/xml2Array.class.php');
167         break;
168     default:
169       //TODO: enable some logging here
170       break;
171     }
172 }
173 /**
174  * returns true if asterisk is running with chan_dahdi
175  *
176  * @return bool
177  */
178 function ast_with_dahdi() {
179   global $version;
180   global $astman;
181   global $amp_conf;
182   global $chan_dahdi_loaded;
183
184   // determine once, subsequent calls will use this
185   global $ast_with_dahdi;
186
187   if (isset($ast_with_dahdi)) {
188     return $ast_with_dahdi;
189   }
190   if (!isset($version) || !$version || !is_string($version)) {
191     $engine_info = engine_getinfo();
192     $version = $engine_info['version'];
193   }
194     
195   if (version_compare($version, '1.4', 'ge') && $amp_conf['AMPENGINE'] == 'asterisk') {   
196     if ($amp_conf['ZAP2DAHDICOMPAT']) {
197       $ast_with_dahdi = true;
198       $chan_dahdi_loaded = true;
199       return true;
200     } else if (isset($astman) && $astman->connected()) {
201       // earlier revisions of 1.4 and dahdi loaded but still running as zap, so if ZapScan is present, we assume
202       // that is the mode it is running in.
203       $response = $astman->send_request('Command', array('Command' => 'show applications like ZapScan'));
204       if (!preg_match('/1 Applications Matching/', $response['data'])) {
205         $ast_with_dahdi = true;
206         $chan_dahdi_loaded = true;
207         return $ast_with_dahdi;
208       } else {
209         $chan_dahdi_loaded = false;
210       }
211     }
212   }
213   $ast_with_dahdi = false;
214   return $ast_with_dahdi;
215 }
216
217 function engine_getinfo($force_read=false) {
218   global $amp_conf;
219   global $astman;
220   static $engine_info;
221
222   $gotinfo = false;
223
224   if (!$force_read && isset($engine_info) && $engine_info != '') {
225     return $engine_info;
226   }
227
228   switch ($amp_conf['AMPENGINE']) {
229     case 'asterisk':
230       if (isset($astman) && $astman->connected()) {
231         //get version (1.4)
232         $response = $astman->send_request('Command', array('Command'=>'core show version'));
233         if (preg_match('/No such command/',$response['data'])) {
234           // get version (1.2)
235           $response = $astman->send_request('Command', array('Command'=>'show version'));
236         }
237         $verinfo = $response['data'];
238       } else {
239         // could not connect to asterisk manager, try console
240         $verinfo = exec('asterisk -V');
241       }
242       
243       if (preg_match('/Asterisk (\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
244         $engine_info = array('engine'=>'asterisk', 'version' => $matches[1], 'additional' => $matches[4], 'raw' => $verinfo);
245         $gotinfo = true;
246       } elseif (preg_match('/Asterisk SVN-(\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
247         $engine_info = array('engine'=>'asterisk', 'version' => $matches[1], 'additional' => $matches[4], 'raw' => $verinfo);
248         $gotinfo = true;
249       } elseif (preg_match('/Asterisk SVN-branch-(\d+(\.\d+)*)-r(-?(\S*))/', $verinfo, $matches)) {
250         $engine_info = array('engine'=>'asterisk', 'version' => $matches[1].'.'.$matches[4], 'additional' => $matches[4], 'raw' => $verinfo);
251         $gotinfo = true;
252       } elseif (preg_match('/Asterisk SVN-trunk-r(-?(\S*))/', $verinfo, $matches)) {
253         $engine_info = array('engine'=>'asterisk', 'version' => '1.8', 'additional' => $matches[1], 'raw' => $verinfo);
254         $gotinfo = true;
255       } elseif (preg_match('/Asterisk SVN-.+-(\d+(\.\d+)*)-r(-?(\S*))-(.+)/', $verinfo, $matches)) {
256         $engine_info = array('engine'=>'asterisk', 'version' => $matches[1], 'additional' => $matches[3], 'raw' => $verinfo);
257         $gotinfo = true;
258       } elseif (preg_match('/Asterisk [B].(\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
259         $engine_info = array('engine'=>'asterisk', 'version' => '1.2', 'additional' => $matches[3], 'raw' => $verinfo);
260         $gotinfo = true;
261       } elseif (preg_match('/Asterisk [C].(\d+(\.\d+)*)(-?(\S*))/', $verinfo, $matches)) {
262         $engine_info = array('engine'=>'asterisk', 'version' => '1.4', 'additional' => $matches[3], 'raw' => $verinfo);
263         $gotinfo = true;
264       }
265
266       if (!$gotinfo) {
267         $engine_info = array('engine'=>'ERROR-UNABLE-TO-PARSE', 'version'=>'0', 'additional' => '0', 'raw' => $verinfo);
268       }
269       if ($amp_conf['FORCED_ASTVERSION']) {
270         $engine_info['engine'] = $amp_conf['AMPENGINE'];
271         $engine_info['version'] = $amp_conf['FORCED_ASTVERSION'];
272       }
273
274       // Now we make sure the ASTVERSION freepbx_setting/amp_conf value is defined and set
275
276       // this is not initialized in the installer because I think there are scenarios where
277       // Asterisk may not be running and we may some day not need it to be so just deal
278       // with it here.
279       //
280       $freepbx_conf =& freepbx_conf::create();
281       if (!$freepbx_conf->conf_setting_exists('ASTVERSION')) {
282         // ASTVERSION
283         //
284         $set['value'] = $engine_info['version'];
285         $set['defaultval'] = '';
286         $set['options'] = '';
287         $set['readonly'] = 1;
288         $set['hidden'] = 1;
289         $set['level'] = 10;
290         $set['module'] = '';
291         $set['category'] = 'Internal Use';
292         $set['emptyok'] = 1;
293         $set['name'] = 'Asterisk Version';
294         $set['description'] = "Last Asterisk Version detected (or forced)";
295         $set['type'] = CONF_TYPE_TEXT;
296         $freepbx_conf->define_conf_setting('ASTVERSION',$set,true);
297         unset($set);
298         $amp_conf['ASTVERSION'] = $engine_info['version'];
299       }
300
301       if ($engine_info['version'] != $amp_conf['ASTVERSION']) {
302         $freepbx_conf->set_conf_values(array('ASTVERSION' => $engine_info['version']), true, true);
303       }
304
305       return $engine_info;
306     break;
307   }
308   $engine_info = array('engine'=>'ERROR-UNSUPPORTED-ENGINE-'.$amp_conf['AMPENGINE'], 'version'=>'0', 'additional' => '0', 'raw' => $verinfo);
309   return $engine_info;
310 }
311
312 function do_reload() {
313   global $amp_conf, $asterisk_conf, $db, $astman, $version;
314
315   if (empty($version)) {
316     $engine_info = engine_getinfo();
317     $version = $engine_info['version'];
318   }
319  
320   $notify =& notifications::create($db);
321  
322   $return = array('num_errors'=>0,'test'=>'abc');
323   $exit_val = null;
324  
325   if (isset($amp_conf["PRE_RELOAD"]) && !empty($amp_conf['PRE_RELOAD']))  {
326     exec( $amp_conf["PRE_RELOAD"], $output, $exit_val );
327     
328     if ($exit_val != 0) {
329       $desc = sprintf(_("Exit code was %s and output was: %s"), $exit_val, "\n\n".implode("\n",$output));
330       $notify->add_error('freepbx','reload_pre_script', sprintf(_('Could not run %s script.'), $amp_conf['PRE_RELOAD']), $desc);
331       
332       $return['num_errors']++;
333     } else {
334       $notify->delete('freepbx', 'reload_pre_script');
335     }
336   }
337  
338   $retrieve = $amp_conf['AMPBIN'].'/retrieve_conf 2>&1';
339   //exec($retrieve.'&>'.$asterisk_conf['astlogdir'].'/freepbx-retrieve.log', $output, $exit_val);
340   exec($retrieve, $output, $exit_val);
341  
342   // retrieve_conf html output
343   $return['retrieve_conf'] = 'exit: '.$exit_val.'<br/>'.implode('<br/>',$output);
344  
345   if ($exit_val != 0) {
346     $return['status'] = false;
347     $return['message'] = sprintf(_('Reload failed because retrieve_conf encountered an error: %s'),$exit_val);
348     $return['num_errors']++;
349     $notify->add_critical('freepbx','RCONFFAIL', _("retrieve_conf failed, config not applied"), $return['message']);
350     return $return;
351   }
352
353   if (!isset($astman) || !$astman) {
354     $return['status'] = false;
355     $return['message'] = _('Reload failed because FreePBX could not connect to the asterisk manager interface.');
356     $return['num_errors']++;
357     $notify->add_critical('freepbx','RCONFFAIL', _("retrieve_conf failed, config not applied"), $return['message']);
358     return $return;
359   }
360   $notify->delete('freepbx', 'RCONFFAIL');
361  
362   //reload MOH to get around 'reload' not actually doing that.
363   $astman->send_request('Command', array('Command'=>'moh reload'));
364  
365   //reload asterisk
366   if (version_compare($version,'1.4','lt')) {
367     $astman->send_request('Command', array('Command'=>'reload'));
368   } else {
369     $astman->send_request('Command', array('Command'=>'module reload')); 
370   }
371  
372   $return['status'] = true;
373   $return['message'] = _('Successfully reloaded');
374  
375   if ($amp_conf['FOPRUN'] && !$amp_conf['FOPDISABLE']) {
376     unset($output);
377     exec('killall -HUP op_server.pl 2>&1', $output, $exit_val);
378     if ($exit_val != 0) {
379       $desc = _('Could not reload the FOP operator panel server using killall -HUP op_server.pl. Configuration changes may not be reflected in the panel display.');
380       $notify->add_error('freepbx','reload_fop', _('Could not reload FOP server'), $desc);
381       // send the error output to dbug log if enabled.
382       dbug($output);
383       
384       $return['num_errors']++;
385     } else {
386       $notify->delete('freepbx','reload_fop');
387     }
388   }
389  
390   //store asterisk reloaded status
391   $sql = "UPDATE admin SET value = 'false' WHERE variable = 'need_reload'";
392   $result = $db->query($sql);
393   if(DB::IsError($result)) {
394     $return['message'] = _('Successful reload, but could not clear reload flag due to a database error: ').$db->getMessage();
395     $return['num_errors']++;
396   }
397  
398   if (isset($amp_conf["POST_RELOAD"]) && !empty($amp_conf['POST_RELOAD']))  {
399     exec( $amp_conf["POST_RELOAD"], $output, $exit_val );
400     
401     if ($exit_val != 0) {
402       $desc = sprintf(_("Exit code was %s and output was: %s"), $exit_val, "\n\n".implode("\n",$output));
403       $notify->add_error('freepbx','reload_post_script', sprintf(_('Could not run %s script.'), 'POST_RELOAD'), $desc);
404       
405       $return['num_errors']++;
406     } else {
407       $notify->delete('freepbx', 'reload_post_script');
408     }
409   }
410  
411   return $return;
412 }
413
414
415 // draw list for users and devices with paging
416 // $skip has been deprecated, used to be used to page-enate
417 function drawListMenu($results, $skip, $type, $dispnum, $extdisplay, $description=false) {
418  
419   $index = 0;
420   echo "<ul>\n";
421   if ($description !== false) {
422     echo "\t<li><a ".($extdisplay=='' ? 'class="current"':'')." href=\"config.php?type=".$type."&display=".$dispnum."\">"._("Add")." ".$description."</a></li>\n";
423   }
424   if (isset($results)) {
425     foreach ($results as $key=>$result) {
426       $index= $index + 1;
427       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";
428     }
429   }
430   echo "</ul>\n";
431 }
432
433 // this function returns true if $astman is defined and set to something (implying a current connection, false otherwise.
434 // this function no longer puts out an error message, it is up to the caller to handle the situation.
435 // Should probably be changed (at least name) to check if a connection is available to the current engine)
436 //
437 function checkAstMan() {
438   global $astman;
439
440   return ($astman)?true:false;
441 }
442
443 /* merge_ext_followme($dest) {
444  *
445  * The purpose of this function is to take a destination
446  * that was either a core extension OR a findmefollow-destination
447  * and convert it so that they are merged and handled just like
448  * direct-did routing
449  *
450  * Assuming an extension number of 222:
451  *
452  * The two formats that existed for findmefollow were:
453  *
454  * ext-findmefollow,222,1
455  * ext-findmefollow,FM222,1
456  *
457  * The one format that existed for core was:
458  *
459  * ext-local,222,1
460  *
461  * In all those cases they should be converted to:
462  *
463  * from-did-direct,222,1
464  *
465  */
466 function merge_ext_followme($dest) {
467
468   if (preg_match("/^\s*ext-findmefollow,(FM)?(\d+),(\d+)/",$dest,$matches) ||
469       preg_match("/^\s*ext-local,(FM)?(\d+),(\d+)/",$dest,$matches) ) {
470         // matches[2] => extn
471         // matches[3] => priority
472     return "from-did-direct,".$matches[2].",".$matches[3];
473   } else {
474     return $dest;
475   }
476 }
477
478 function get_headers_assoc($url) {
479   $url_info=parse_url($url);
480   $host = isset($url_info['host']) ? $url_info['host'] : '';
481   if (isset($url_info['scheme']) && $url_info['scheme'] == 'https') {
482     $port = isset($url_info['port']) ? $url_info['port'] : 443;
483     @$fp=fsockopen('ssl://'.$host, $port, $errno, $errstr, 10);
484   } else {
485     $port = isset($url_info['port']) ? $url_info['port'] : 80;
486     @$fp=fsockopen($host, $port, $errno, $errstr, 10);
487   }
488   if ($fp) {
489     stream_set_timeout($fp, 10);
490     $query = isset($url_info['query']) ? $url_info['query'] : '';
491     $head = "HEAD ".@$url_info['path']."?".$query;
492     $head .= " HTTP/1.0\r\nHost: ".$host."\r\n\r\n";
493     fputs($fp, $head);
494     while(!feof($fp)) {
495       if($header=trim(fgets($fp, 1024))) {
496         $sc_pos = strpos($header, ':');
497         if ($sc_pos === false) {
498           $headers['status'] = $header;
499         } else {
500           $label = substr( $header, 0, $sc_pos );
501           $value = substr( $header, $sc_pos+1 );
502           $headers[strtolower($label)] = trim($value);
503         }
504       }
505     }
506     return $headers;
507   } else {
508     return false;
509   }
510 }
511
512
513 // Dragged this in from page.modules.php, so it can be used by install_amp.
514 function runModuleSQL($moddir,$type){
515   trigger_error("runModuleSQL() is depreciated - please use _module_runscripts(), or preferably module_install() or module_enable() instead", E_USER_WARNING);
516   _module_runscripts($moddir, $type);
517 }
518
519 //This function calls modulename_contexts()
520 //expects a returned array which minimally includes 'context' => the actual context to include
521 //can also define 'description' => the display for this context - if undefined will be set to 'context'
522 //'module' => the display for the section this should be listed under defaults to module display (can be used to group subsets within one module)
523 //'parent' => if including another context automatically includes this one, list the parent context
524 //'priority' => default sort order for includes range -50 to +50, 0 is default
525 //'enabled' => can be used to flag a context as disabled and it won't be included, but will not have its settings removed.
526 //'extension' => can be used to tag with an extension for checkRange($extension)
527 //'dept' => can be used to tag with a department for checkDept($dept)
528 //  this defaults to false for disabled modules.
529 function freepbx_get_contexts() {
530   $modules = module_getinfo(false, array(MODULE_STATUS_ENABLED, MODULE_STATUS_DISABLED, MODULE_STATUS_NEEDUPGRADE));
531  
532   $contexts = array();
533  
534   foreach ($modules as $modname => $mod) {
535                 $funct = strtolower($modname.'_contexts');
536     if (function_exists($funct)) {
537       // call the  modulename_contexts() function
538       $contextArray = $funct();
539       if (is_array($contextArray)) {
540         foreach ($contextArray as $con) {
541           if (isset($con['context'])) {
542             if (!isset($con['description'])) {
543               $con['description'] = $con['context'];
544             }
545             if (!isset($con['module'])) {
546               $con['module'] = $mod['displayName'];
547             }
548             if (!isset($con['priority'])) {
549               $con['priority'] = 0;
550             }
551             if (!isset($con['parent'])) {
552               $con['parent'] = '';
553             }
554             if (!isset($con['extension'])) {
555               $con['extension'] = null;
556             }
557             if (!isset($con['dept'])) {
558               $con['dept'] = null;
559             }
560             if ($mod['status'] == MODULE_STATUS_ENABLED) {
561               if (!isset($con['enabled'])) {
562                 $con['enabled'] = true;
563               }
564             } else {
565               $con['enabled'] = false;
566             }
567             $contexts[ $con['context'] ] = $con;
568           }
569         }
570       }
571     }
572   }
573   return $contexts;
574 }
575
576 ?>
Note: See TracBrowser for help on using the browser.