root/freepbx/trunk/amp_conf/htdocs/admin/libraries/utility.functions.php

Revision 14253, 38.8 kB (checked in by p_lindheimer, 10 months ago)

Merged revisions 13971-13972,13979,14026,14031,14048-14049,14052,14054,14060,14082,14119,14128,14133-14135,14148-14149,14151-14153,14159,14205,14218 via svnmerge from
http://www.freepbx.org/v2/svn/freepbx/branches/2.10

........

r13971 | p_lindheimer | 2012-04-14 10:56:49 -0700 (Sat, 14 Apr 2012) | 1 line


don't make manager creds readonly now that they are auto updated when changed

........

r13972 | p_lindheimer | 2012-04-14 11:43:05 -0700 (Sat, 14 Apr 2012) | 1 line


fixes #5716 and fixes #5763 set reasonable timeouts with wget, port 5060 is still an issue and the server needs to be checked as something has changed there

........

r13979 | p_lindheimer | 2012-04-17 17:12:25 -0700 (Tue, 17 Apr 2012) | 1 line


this is supplied by core now

........

r14026 | p_lindheimer | 2012-04-27 13:18:08 -0700 (Fri, 27 Apr 2012) | 1 line


fixes #5742 conflict with html ID on Advanced Settings page breaks abiliity to change this one setting, will go live with next framework module update

........

r14031 | mbrevda | 2012-04-30 07:58:12 -0700 (Mon, 30 Apr 2012) | 1 line


fixes #5743 by namsepacing ari css stuff

........

r14048 | p_lindheimer | 2012-05-03 07:19:25 -0700 (Thu, 03 May 2012) | 1 line


fixes #5533 harmless warning message by not checking the filesize of the log file the first time if it does not exists yet

........

r14049 | p_lindheimer | 2012-05-03 08:54:56 -0700 (Thu, 03 May 2012) | 1 line


check if dbug file exists before calculatin size to remove otherwise harmless warning message re #5533

........

r14052 | p_lindheimer | 2012-05-04 08:26:35 -0700 (Fri, 04 May 2012) | 1 line


revert r12549 merged in error as well as remove undefined index all re #5692 which may fix issues but needs testing

........

r14054 | p_lindheimer | 2012-05-04 09:12:50 -0700 (Fri, 04 May 2012) | 1 line


don't duplicate this first setting re #5692

........

r14060 | p_lindheimer | 2012-05-07 15:03:50 -0700 (Mon, 07 May 2012) | 1 line


revert accidental checkin of part of r13972 re #5812

........

r14082 | p_lindheimer | 2012-05-18 15:16:54 -0700 (Fri, 18 May 2012) | 1 line


incorrect parsing of REQUEST variable results in streamlined ajax path's not being honored

........

r14119 | mbrevda | 2012-05-30 00:10:38 -0700 (Wed, 30 May 2012) | 1 line


function to recursivly remove a directory

........

r14128 | p_lindheimer | 2012-06-11 08:21:11 -0700 (Mon, 11 Jun 2012) | 1 line


fixes #5874 variable name typo

........

r14133 | p_lindheimer | 2012-06-14 11:22:37 -0700 (Thu, 14 Jun 2012) | 1 line


remove some advanced settings no longer valid

........

r14134 | p_lindheimer | 2012-06-14 12:37:43 -0700 (Thu, 14 Jun 2012) | 1 line


makes spnosor image and associated link configurable as is freepbx image

........

r14135 | p_lindheimer | 2012-06-14 12:39:02 -0700 (Thu, 14 Jun 2012) | 1 line


closes #5833 USEDEVSTATE defaults to true

........

r14148 | p_lindheimer | 2012-06-15 13:19:15 -0700 (Fri, 15 Jun 2012) | 1 line


fixes #5646 reload Asterisk after initial start if using Dynamic Hints to get over Asterisk bug where #exec fails on first startup

........

r14149 | mbrevda | 2012-06-18 08:48:21 -0700 (Mon, 18 Jun 2012) | 1 line


re #5879, #5839 - add bootstrap hook; write writetimeout to mamanger.conf; cosmetics

........

r14151 | mbrevda | 2012-06-19 05:36:10 -0700 (Tue, 19 Jun 2012) | 1 line


syntaxt error

........

r14152 | p_lindheimer | 2012-06-19 08:23:43 -0700 (Tue, 19 Jun 2012) | 1 line


add 2.10.1 upgrade dir, migration for writetimeout re #5839, and remove some advanced settings that are no longer used

........

r14153 | GameGamer?43 | 2012-06-19 15:10:37 -0700 (Tue, 19 Jun 2012) | 1 line


closes #5885 - check recordings in cdr prior to enabling or disabling the delete button

........

r14159 | p_lindheimer | 2012-06-27 16:51:15 -0700 (Wed, 27 Jun 2012) | 1 line


don't take out the description or it doesn't show up in module admin when not online

........

r14205 | p_lindheimer | 2012-06-30 13:11:53 -0700 (Sat, 30 Jun 2012) | 1 line


Creating release 2.10.1

........

r14218 | p_lindheimer | 2012-06-30 13:30:57 -0700 (Sat, 30 Jun 2012) | 1 line


remove some of the security auditing code that got checked in error and not used or ready

........

  • 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
2
3 define('EOL', isset($_SERVER['REQUEST_METHOD']) ? "<br />" :  PHP_EOL);
4
5 define("FPBX_LOG_FATAL",    "FATAL");
6 define("FPBX_LOG_CRITICAL", "CRITICAL");
7 define("FPBX_LOG_SECURITY", "SECURITY");
8 define("FPBX_LOG_UPDATE",   "UPDATE");
9 define("FPBX_LOG_ERROR",    "ERROR");
10 define("FPBX_LOG_WARNING",  "WARNING");
11 define("FPBX_LOG_NOTICE",   "NOTICE");
12 define("FPBX_LOG_INFO",     "INFO");
13 define("FPBX_LOG_PHP",      "PHP");
14
15 /** FreePBX Logging facility to FILE or syslog
16  * @param  string   The level/severity of the error. Valid levels use constants:
17  *                  FPBX_LOG_FATAL, FPBX_LOG_CRITICAL, FPBX_LOG_SECURITY, FPBX_LOG_UPDATE,
18  *                  FPBX_LOG_ERROR, FPBX_LOG_WARNING, FPBX_LOG_NOTICE, FPBX_LOG_INFO.
19  * @param  string   The error message
20  */
21 function freepbx_log($level, $message) {
22   global $amp_conf;
23
24   $php_error_handler = false;
25   $bt = debug_backtrace();
26
27   if (isset($bt[1]) && $bt[1]['function'] == 'freepbx_error_handler') {
28     $php_error_handler = true;
29   } elseif (isset($bt[1]) && $bt[1]['function'] == 'out' || $bt[1]['function'] == 'die_freepbx') {
30     $file_full = $bt[1]['file'];
31     $line = $bt[1]['line'];
32   } elseif (basename($bt[0]['file']) == 'notifications.class.php') {
33     $file_full = $bt[2]['file'];
34     $line = $bt[2]['line'];
35   } else {
36     $file_full = $bt[0]['file'];
37     $line = $bt[0]['line'];
38   }
39
40   if (!$php_error_handler) {
41     $file_base = basename($file_full);
42     $file_dir  = basename(dirname($file_full));
43     $txt = sprintf("[%s] (%s/%s:%s) - %s\n", $level, $file_dir, $file_base, $line, $message);
44   } else {
45     // PHP Error Handler provides it's own formatting
46     $txt = sprintf("[%s-%s\n", $level, $message);
47   }
48
49   // if it is not set, it's probably an initial installation so we want to log something
50   if (!isset($amp_conf['AMPDISABLELOG']) || !$amp_conf['AMPDISABLELOG']) {
51     $log_type = isset($amp_conf['AMPSYSLOGLEVEL']) ? $amp_conf['AMPSYSLOGLEVEL'] : 'FILE';
52     switch ($log_type) {
53       case 'LOG_EMERG':
54       case 'LOG_ALERT':
55       case 'LOG_CRIT':
56       case 'LOG_ERR':
57       case 'LOG_WARNING':
58       case 'LOG_NOTICE':
59       case 'LOG_INFO':
60       case 'LOG_DEBUG':
61         syslog(constant($log_type),"FreePBX - $txt");
62         break;
63       case 'SQL':     // Core will remove these settings once migrated,
64       case 'LOG_SQL': // default to FILE during any interim steps.
65       case 'FILE':
66       default:
67         // during initial install, there may be no log file provided because the script has not fully bootstrapped
68         // so we will default to a pre-install log file name. We will make a file name mandatory with a proper
69         // default in FPBX_LOG_FILE
70         $log_file = isset($amp_conf['FPBX_LOG_FILE']) ? $amp_conf['FPBX_LOG_FILE'] : '/tmp/freepbx_pre_install.log';
71         $tstamp   = date("Y-M-d H:i:s");
72
73         // Don't append if the file is greater than ~2G since some systems fail
74         //
75         $size = file_exists($log_file) ? sprintf("%u", filesize($log_file)) + strlen($txt) : 0;
76         if ($size < 2000000000) {
77           file_put_contents($log_file, "[$tstamp] $txt", FILE_APPEND);
78         }
79         break;
80     }
81   }
82 }
83
84 /* version_compare that works with FreePBX version numbers
85 */
86 function version_compare_freepbx($version1, $version2, $op = null) {
87   $version1 = str_replace("rc","RC", strtolower($version1));
88   $version2 = str_replace("rc","RC", strtolower($version2));
89   if (!is_null($op)) {
90     return version_compare($version1, $version2, $op);
91   } else {
92     return version_compare($version1, $version2);
93   }
94 }
95
96 function compress_framework_css() {
97   global $amp_conf;
98   $mainstyle_css      = $amp_conf['BRAND_CSS_ALT_MAINSTYLE']
99             ? $amp_conf['BRAND_CSS_ALT_MAINSTYLE']
100             : 'assets/css/mainstyle.css';
101   $wwwroot      = $amp_conf['AMPWEBROOT'] . "/admin";
102   $mainstyle_css_gen  = $wwwroot . '/' . $amp_conf['mainstyle_css_generated'];
103   $mainstyle_css    = $wwwroot . '/' . $mainstyle_css;
104   $new_css      = file_get_contents($mainstyle_css)
105             . file_get_contents($wwwroot . '/' . $amp_conf['JQUERY_CSS']);
106   $new_css      = CssMin::minify($new_css);
107   $new_md5      = md5($new_css);
108   $gen_md5      = file_exists($mainstyle_css_gen) ? md5(file_get_contents($mainstyle_css_gen)) : '';
109
110  
111   //regenerate if hashes dont match
112   if ($new_md5 != $gen_md5) {
113     $ms_path = dirname($mainstyle_css);
114
115     // it's important for filename tp unique
116     //because that will force browsers to reload vs. caching it
117     $mainstyle_css_generated = $ms_path.'/mstyle_autogen_' . time() . '.css';
118     //remove any stale generated css files
119     exec(fpbx_which('rm') . ' -f ' . $ms_path . '/mstyle_autogen_*');
120    
121     $ret = file_put_contents($mainstyle_css_generated, $new_css);
122
123     // Now assuming we write something reasonable, we need to save the generated file name and mtimes so
124     // next time through this ordeal, we see everything is setup and skip all of this.
125     //
126     // we skip this all this if we get back false or 0 (nothing written) in which case we will use the original
127     // We need to set the value in addition to defining the setting
128     //since if already defined the value won't be reset.
129     if ($ret) {
130       $freepbx_conf =& freepbx_conf::create();
131       $val_update['mainstyle_css_generated'] = str_replace($wwwroot . '/', '', $mainstyle_css_generated);
132      
133       // Update the values (in case these are new) and commit
134       $freepbx_conf->set_conf_values($val_update, true, true);
135
136
137       // If it is a regular file (could have been first time and previous was blank then delete old
138       if (is_file($mainstyle_css_gen) && !unlink($mainstyle_css_gen)) {
139         freepbx_log(FPBX_LOG_WARNING,
140               sprintf(_('failed to delete %s from assets/css directory after '
141                   . 'creating updated CSS file.'),
142                   $mainstyle_css_generated_full_path));
143       }
144     }
145   }
146  
147 }
148
149 function die_freepbx($text, $extended_text="", $type="FATAL") {
150   global $amp_conf;
151
152   $bt = debug_backtrace();
153   freepbx_log(FPBX_LOG_FATAL, "die_freepbx(): ".$text);
154
155   if (isset($_SERVER['REQUEST_METHOD'])) {
156     // running in webserver
157     $trace =  "<h1>".$type." ERROR</h1>\n";
158     $trace .= "<h3>".$text."</h3>\n";
159     if (!empty($extended_text)) {
160       $trace .= "<p>".$extended_text."</p>\n";
161     }
162     $trace .= "<h4>"._("Trace Back")."</h4>";
163
164     $main_fmt = "%s:%s %s()<br />\n";
165     $arg_fmt = "&nbsp;&nbsp;[%s]: %s<br />\n";
166     $separator = "<br />\n";
167     $tail = "<br />\n";
168     $f = 'htmlspecialchars';
169   } else {
170     // CLI
171     $trace =  "[$type] ".$text." ".$extended_text."\n\n";
172     $trace .= "Trace Back:\n\n";
173
174     $main_fmt = "%s:%s %s()\n";
175     $arg_fmt = " [%s]: %s\n";
176     $separator = "\n";
177     $tail = "";
178     $f = 'trim';
179   }
180
181   foreach ($bt as $l) {
182     $cl = isset($l['class']) ? $f($l['class']) : '';
183     $ty = isset($l['type']) ? $f($l['type']) : '';
184     $func = $f($cl . $ty . $l['function']);
185     $trace .= sprintf($main_fmt, $l['file'], $l['line'], $func);
186     if (isset($l['args'])) foreach ($l['args'] as $i => $a) {
187       $trace .= sprintf($arg_fmt, $i, $f($a));
188     }
189     $trace .= $separator;
190   }
191   echo $trace . $tail;
192
193   if ($amp_conf['DIE_FREEPBX_VERBOSE']) {
194     $trace = print_r($bt,true);
195     if (isset($_SERVER['REQUEST_METHOD'])) {
196       echo '<pre>' .$trace. '</pre>';
197     } else {
198       echo $trace;
199     }
200   }
201
202   // Now die!
203   exit(1);
204 }
205
206 //get the version number
207 function getversion($cached=true) {
208   global $db;
209   static $version;
210   if (isset($version) && $version && $cached) {
211     return $version;
212   }
213   $sql    = "SELECT value FROM admin WHERE variable = 'version'";
214   $results  = $db->getRow($sql);
215   if($db->IsError($results)) {
216     die_freepbx($sql."<br>\n".$results->getMessage());
217   }
218   return $results[0];
219 }
220
221 //get the version number
222 function get_framework_version($cached=true) {
223   global $db;
224   static $version;
225   if (isset($version) && $version && $cached) {
226     return $version;
227   }
228   $sql    = "SELECT version FROM modules WHERE modulename = 'framework' AND enabled = 1";
229   $version  = $db->getOne($sql);
230   if($db->IsError($version)) {
231     die_freepbx($sql."<br>\n".$version->getMessage());
232   }
233   return $version;
234 }
235
236 //tell application we need to reload asterisk
237 function needreload() {
238   global $db;
239   $sql  = "UPDATE admin SET value = 'true' WHERE variable = 'need_reload'";
240   $result = $db->query($sql);
241   if($db->IsError($result)) {     
242     die_freepbx($sql.$result->getMessage());
243   }
244 }
245
246 function check_reload_needed() {
247   global $db;
248   global $amp_conf;
249   $sql = "SELECT value FROM admin WHERE variable = 'need_reload'";
250   $row = $db->getRow($sql);
251   if($db->IsError($row)) {
252     die_freepbx($sql.$row->getMessage());
253   }
254   return ($row[0] == 'true' || $amp_conf['DEVELRELOAD']);
255 }
256
257 /** Log a debug message to a debug file
258  * @param  string   debug message to be printed
259  * @param  string   depreciated
260  * @param  string   depreciated
261  */
262 function freepbx_debug($string, $option='', $filename='') {
263   dbug($string);
264 }
265
266 /**
267  * FreePBX Debugging function
268  * This function can be called as follows:
269  * dbug() - will just print a time stamp to the debug log file ($amp_conf['FPBXDBUGFILE'])
270  * dbug('string') - same as above + will print the string
271  * dbug('string',$array) - same as above + will print_r the array after the message
272  * dbug($array) - will print_r the array with no message (just a time stamp) 
273  * dbug('string',$array,1) - same as above + will var_dump the array
274  * dbug($array,1) - will var_dump the array with no message  (just a time stamp)
275  *   
276  * @author Moshe Brevda mbrevda => gmail ~ com
277  */ 
278 function dbug(){
279   global $amp_conf;
280
281   $opts = func_get_args();
282   $disc = $msg = $dump = null;
283
284   // Check if it is set to avoid un-defined errors if using in code portions that are
285   // not yet bootstrapped. Default to enabling it.
286   //
287   if (isset($amp_conf['FPBXDBUGDISABLE']) && $amp_conf['FPBXDBUGDISABLE']) {
288     return;
289   }
290
291   $dump = 0;
292   //sort arguments
293   switch (count($opts)) {
294     case 1:
295       $msg    = $opts[0];
296       break;
297     case 2:
298       if ( is_array($opts[0]) || is_object($opts[0]) ) {
299         $msg  = $opts[0];
300         $dump = $opts[1];
301       } else {
302         $disc = $opts[0];
303         $msg  = $opts[1];
304       }
305       break;
306     case 3:
307       $disc   = $opts[0];
308       $msg    = $opts[1];
309       $dump   = $opts[2];
310       break; 
311   }
312  
313   if (isset($disc) && $disc) {
314     $disc = ' \'' . $disc . '\':';
315   } else {
316     $disc = '';
317   }
318  
319   $bt = debug_backtrace();
320   $txt = date("Y-M-d H:i:s")
321     . "\t" . $bt[0]['file'] . ':' . $bt[0]['line']
322     . "\n\n"
323     . $disc
324     . "\n"; //add timestamp + file info
325   dbug_write($txt, true);
326   if ($dump==1) {//force output via var_dump
327     ob_start();
328     var_dump($msg);
329     $msg=ob_get_contents();
330     ob_end_clean();
331     dbug_write($msg."\n\n\n");
332   } elseif(is_array($msg) || is_object($msg)) {
333     dbug_write(print_r($msg,true)."\n\n\n");
334   } else {
335     dbug_write($msg."\n\n\n");
336   }
337 }
338
339 //http://php.net/manual/en/function.set-error-handler.php
340 function freepbx_error_handler($errno, $errstr, $errfile, $errline,  $errcontext) {
341         global $amp_conf;
342
343         //for pre 5.2
344         if (!defined('E_RECOVERABLE_ERROR')) {
345                 define('E_RECOVERABLE_ERROR', '');
346         }
347         $errortype = array (
348                 E_ERROR                                 => 'ERROR',
349                 E_WARNING                               => 'WARNING',
350                 E_PARSE                                 => 'PARSE_ERROR',
351                 E_NOTICE                                => 'NOTICE',
352                 E_CORE_ERROR                    => 'CORE_ERROR',
353                 E_CORE_WARNING                  => 'CORE_WARNING',
354                 E_COMPILE_ERROR                 => 'COMPILE_ERROR',
355                 E_COMPILE_WARNING               => 'COMPILE_WARNING',
356                 E_USER_ERROR                    => 'USER_ERROR',
357                 E_USER_WARNING                  => 'USER_WARNING',
358                 E_USER_NOTICE                   => 'USER_NOTICE',
359                 E_STRICT                                => 'RUNTIM_NOTICE',
360                 E_RECOVERABLE_ERROR     => 'CATCHABLE_FATAL_ERROR',
361                 );
362
363         if (!isset($amp_conf['PHP_ERROR_HANDLER_OUTPUT'])) {
364                 $amp_conf['PHP_ERROR_HANDLER_OUTPUT'] = 'dbug';
365         }
366
367         switch($amp_conf['PHP_ERROR_HANDLER_OUTPUT']) {
368                 case 'freepbxlog':
369                         $txt = sprintf("%s] (%s:%s) - %s", $errortype[$errno], $errfile, $errline, $errstr);
370                         freepbx_log(FPBX_LOG_PHP,$txt);
371                         break;
372                 case 'off':
373                         break;
374                 case 'dbug':
375                         default:
376             $errormsg = isset($errortype[$errno])
377                   ? $errortype[$errno]
378                   : 'Undefined Error';
379                         $txt = date("Y-M-d H:i:s")
380                                 . "\t" . $errfile . ':' . $errline
381                                 . "\n"
382                                 . '[' . $errormsg . ']: '
383                                 . $errstr
384                                 . "\n\n";
385                                 dbug_write($txt, $check='');
386                                 break;
387                         }
388 }
389
390
391 global $outn_function_buffer;
392 $outn_function_buffer='';
393 function out($text,$log=true) {
394   global $outn_function_buffer;
395   global $amp_conf;
396   echo $text.EOL;
397   // if not set, could be bootstrapping so default to true
398   if ($log && (!isset($amp_conf['LOG_OUT_MESSAGES']) || $amp_conf['LOG_OUT_MESSAGES'])) {
399     $outn_function_buffer .= $text;
400     freepbx_log(FPBX_LOG_INFO,$outn_function_buffer);
401     $outn_function_buffer = '';
402   }
403 }
404
405 function outn($text,$log=true) {
406   global $outn_function_buffer;
407   global $amp_conf;
408   echo $text;
409   // if not set, could be bootstrapping so default to true
410   if ($log && (!isset($amp_conf['LOG_OUT_MESSAGES']) || $amp_conf['LOG_OUT_MESSAGES'])) {
411     // Don't log, just accumualte until matching out() dumps the accumulated text
412     $outn_function_buffer .= $text;
413   }
414 }
415
416 function error($text,$log=true) {
417   echo "[ERROR] ".$text.EOL;
418   if ($log) {
419     freepbx_log(FPBX_LOG_ERROR,$text);
420   }
421 }
422
423 // TODO: used in retrieve_conf, scan code base and remove if appropriate
424 //       replacing with logging and die_freepbx (which should log also)
425 //
426 function fatal($text,$log=true) {
427   echo "[FATAL] ".$text.EOL;
428   if ($log) {
429     freepbx_log(FPBX_LOG_FATAL,$text);
430   }
431   exit(1);
432 }
433
434 // TODO: used in retrieve_conf, scan code base and remove if appropriate
435 //
436 function debug($text,$log=true) {
437   global $debug;
438  
439   if ($debug) echo "[DEBUG-preDB] ".$text.EOL;
440   if ($log) {
441     dbug($text);
442   }
443 }
444
445 /** like file_get_contents designed to work with url only, will try
446  * wget if fails or if MODULEADMINWGET set to true. If it detects
447  * failure, will set MODULEADMINWGET to true for future improvements.
448  *
449  * @param   mixed   url to be fetches or array of multiple urls to try
450  * @return  mixed   content of first successful url, boolean false if it failed.
451  */
452 function file_get_contents_url($file_url) {
453   global $amp_conf;
454   $contents = '';
455
456   if (!is_array($file_url)) {
457     $file_url = array($file_url);
458   }
459
460   foreach ($file_url as $fn) {
461     if (!$amp_conf['MODULEADMINWGET']) {
462       ini_set('user_agent','Wget/1.10.2 (Red Hat modified)');
463       $contents = @ file_get_contents($fn);
464     }
465     if (empty($contents)) {
466       $fn2 = str_replace('&','\\&',$fn);
467       exec("wget --tries=1 --timeout=30 -O - $fn2 2>> /dev/null", $data_arr, $retcode);
468       if ($retcode) {
469         // if server isn't available for some reason should return non-zero
470         // so we return and we don't set the flag below
471         freepbx_log(FPBX_LOG_ERROR,sprintf(_('Failed to get remote file, mirror site may be down: %s'),$fn));
472         continue;
473
474         // We are here if contents were blank. It's possible that whatever we were getting were suppose to be blank
475         // so we only auto set the WGET var if we received something so as to not false trigger. If there are issues
476         // with content filters that this is designed to get around, we will eventually get a non-empty file which
477         // will trigger this for now and the future.
478       } elseif (!empty($data_arr) && !$amp_conf['MODULEADMINWGET']) {
479         $freepbx_conf =& freepbx_conf::create();
480         $freepbx_conf->set_conf_values(array('MODULEADMINWGET' => true),true);
481
482         $nt =& notifications::create($db);
483         $text = sprintf(_("Forced %s to true"),'MODULEADMINWGET');
484         $extext = sprintf(_("The system detected a problem trying to access external server data and changed internal setting %s (Use wget For Module Admin) to true, see the tooltip in Advanced Settings for more details."),'MODULEADMINWGET');
485         $nt->add_warning('freepbx', 'MODULEADMINWGET', $text, $extext, '', false, true);
486       }
487       $contents = implode("\n",$data_arr);
488       return $contents;
489     } else {
490       return $contents;
491     }
492     // we get here if all wget's fail
493     return false;
494   }
495 }
496
497 /**
498  * function generate_module_repo_url
499  * short create array of full URLs to get a file from repo
500  * use this function to generate an array of URLs for all configured REPOs
501  * @author Philippe Lindheimer
502  *
503  * @pram string
504  * @returns string
505  */
506 function generate_module_repo_url($path) {
507   global $amp_conf;
508   $urls = array();
509
510   $repos = explode(',', $amp_conf['MODULE_REPO']);
511   foreach ($repos as $repo) {
512     $urls[] = $repo . $path;
513   }
514   return $urls;
515 }
516
517 /**
518  * function edit crontab
519  * short Add/removes stuff rom conrtab
520  * long Use this function to programmatically add/remove data from the crontab
521  * will always run as the asterisk user
522  * @author Moshe Brevda mbrevda => gmail ~ com
523  *
524  * @pram string
525  * @pram mixed
526  * @returns bool
527  */
528
529 function edit_crontab($remove = '', $add = '') {
530   global $amp_conf;
531   $cron_out = array();
532   $cron_add = false;
533
534   //if were running as root (i.e. uid === 0), use the asterisk users crontab. If were running as the asterisk user,
535   //that will happen automatically. If were anyone else, this cron entry will go the current user
536   //and run as them
537   $current_user = posix_getpwuid(posix_geteuid());
538   if ($current_user['uid'] === 0) {
539     $cron_user = '-u' . $amp_conf['AMPASTERISKWEBUSER'] . ' ';
540   } else {
541     $cron_user = '';
542   }
543
544   //get all crontabs
545   $exec = '/usr/bin/crontab -l ' . $cron_user;
546   exec($exec, $cron_out, $ret);
547
548   //make sure the command was executed successfully before continuing
549   if ($ret > 0) {
550     return false;
551   }
552
553   //remove anythign that nteeds to be removed
554   foreach ($cron_out as $my => $c) {
555     //ignore comments
556     if (substr($c, 0, 1) == '#') {
557       continue;
558     }
559
560     //remove blank lines
561     if (!$c) {
562       unset($cron_out[$my]);
563     }
564
565     //remove $remove
566     if ($remove) {
567       if (strpos($c, $remove)) {
568         unset($cron_out[$my]);
569       }
570     }
571   }
572
573   //if we have $add and its an array, parse it & fill in the missing options
574   //if its a string, add it as is
575
576   if($add) {
577     if (is_array($add)) {
578       if (isset($add['command'])) {
579         //see if we have a one word event such as daily, weekly, anually, etc
580         if (isset($add['event'])) {
581           $cron_add['event'] = '@' . trim($add['event'], '@');
582         } else {
583           $cron_add['minute']   = isset($add['minute']) && $add['minute'] !== '' 
584                         ? $add['minute']
585                         : '*';
586           $cron_add['hour']   = isset($add['hour']) && $add['hour'] !== ''
587                         ? $add['hour']
588                         : '*';
589           $cron_add['dom']    = isset($add['dom']) && $add['dom'] !== ''
590                         ? $add['dom']
591                         : '*';
592           $cron_add['month']    = isset($add['month']) && $add['month'] !== ''
593                         ? $add['month']
594                         : '*';
595           $cron_add['dow']    = isset($add['dow']) && $add['dow'] !== ''
596                         ? $add['dow']
597                         : '*';
598         }
599         $cron_add['command']  = $add['command'];
600         $cron_add = implode(' ', $cron_add);
601       } else {
602         //no command? No cron!
603         $cron_add = '';
604       }
605     } else {
606       //no array? Just use the string
607       $cron_add = $add;
608     }
609   }
610
611   //if we have soemthing to add
612   if ($cron_add) {
613     $cron_out[] = $cron_add;
614   }
615
616   //write out crontab
617   $exec = '/bin/echo "' . implode("\n", $cron_out) . '" | /usr/bin/crontab ' . $cron_user . '-';
618   //dbug('writing crontab', $exec);
619   exec($exec, $out_arr, $ret);
620
621   return ($ret > 0 ? false : true);
622 }
623
624 /**
625  *
626  * @author Moshe Brevda mbrevda => gmail ~ com
627  */
628 function dbug_write($txt, $check = false){
629   global $amp_conf;
630
631   // dbug can be used prior to bootstrapping and initialization, so we set
632   // it if not defined here to a default.
633   //
634   if (!isset($amp_conf['FPBXDBUGFILE'])) {
635     $amp_conf['FPBXDBUGFILE'] = '/var/log/asterisk/freepbx_debug';
636   }
637
638 // If not check set max size just under 2G which is the php limit before it gets upset
639   if($check) { $max_size = 52428800; } else { $max_size = 2000000000; }
640   //optionaly ensure that dbug file is smaller than $max_size
641   $size = file_exists($amp_conf['FPBXDBUGFILE']) ? sprintf("%u", filesize($amp_conf['FPBXDBUGFILE'])) + strlen($txt) : 0;
642   if ($size > $max_size) {
643     file_put_contents($amp_conf['FPBXDBUGFILE'], $txt);
644   } else {
645     file_put_contents($amp_conf['FPBXDBUGFILE'], $txt, FILE_APPEND);
646   }
647 }
648
649 /**
650  * this function can print a json object in a "pretty" (i.e. human-readbale) format
651  * @author Moshe Brevda mbrevda => gmail ~ com
652  *
653  * @pram string - json string
654  * @pram string - string to use for indentation
655  *
656  */
657 function json_print_pretty($json, $indent = "\t") {
658   $f      = '';
659   $len    = strlen($json);
660   $depth    = 0;
661   $newline  = false;
662
663   for ($i = 0; $i < $len; ++$i) {
664     if ($newline) {
665       $f .= "\n";
666       $f .= str_repeat($indent, $depth);
667       $newline = false;
668     }
669
670     $c = $json[$i];
671     if ($c == '{' || $c == '[') {
672       $f .= $c;
673       $depth++;
674       $newline = true;
675     } else if ($c == '}' || $c == ']') {
676       $depth--;
677       $f .= "\n";
678       $f .= str_repeat($indent, $depth);
679       $f .= $c;
680     } else if ($c == '"') {
681       $s = $i;
682       do {
683         $c = $json[++$i];
684         if ($c == '\\') {
685           $i += 2;
686           $c = $json[$i];
687         }
688       } while ($c != '"');
689       $f .= substr($json, $s, $i-$s+1);
690     } else if ($c == ':') {
691       $f .= ': ';
692     } else if ($c == ',') {
693       $f .= ',';
694       $newline = true;
695     } else {
696       $f .= $c;
697     }
698   }
699   return $f;
700 }
701
702 /**
703  *
704  * @author Moshe Brevda mbrevda => gmail ~ com
705  */
706 function astdb_get($exclude = array()) {
707   global $astman;
708   $db     = $astman->database_show();
709   $astdb    = array();
710  
711   foreach ($db as $k => $v) {
712     if (!in_array($k, $exclude)) {
713       $key = explode('/', trim($k, '/'), 2);
714       //dbug($k, $key[1]);
715       $astdb[$key[0]][$key[1]] = $v;
716     }
717   }
718  
719   return $astdb;
720 }
721
722 /**
723  *
724  * @author Moshe Brevda mbrevda => gmail ~ com
725  */
726 function astdb_put($astdb, $exclude = array()) {
727   global $astman;
728   $db = $astman->database_show();
729
730   foreach ($astdb as $family => $key) {
731    
732     if ($family && !in_array($family, $exclude)) {
733       $astman->database_deltree($family);
734     }
735
736     foreach($key as $k => $v) {
737       //if ($k == 'Array' && $v == '<bad value>') continue;
738       $astman->database_put($family, $k, $v);
739     }
740    
741   }
742   return true;
743 }
744
745 /**
746  * function scandirr
747  * scans a directory just like scandir(), only recursively
748  * returns a hierarchical array representing the directory structure
749  *
750  * @pram string - directory to scan
751  * @pram strin - retirn absolute paths
752  * @returns array
753  *
754  * @author Moshe Brevda mbrevda => gmail ~ com
755  */
756 function scandirr($dir, $absolute = false) {
757   $list = array();
758   if ($absolute) {
759     global $list;
760   }
761  
762  
763   //get directory contents
764   foreach (scandir($dir) as $d) {
765    
766     //ignore any of the files in the array
767     if (in_array($d, array('.', '..'))) {
768       continue;
769     }
770    
771     //if current file ($d) is a directory, call scandirr
772     if (is_dir($dir . '/' . $d)) {
773       if ($absolute) {
774         scandirr($dir . '/' . $d, $absolute);
775       } else {
776         $list[$d] = scandirr($dir . '/' . $d, $absolute);
777       }
778      
779    
780       //otherwise, add the file to the list
781     } elseif (is_file($dir . '/' . $d) || is_link($dir . '/' . $d)) {
782       if ($absolute) {
783         $list[] = $dir . '/' . $d;
784       } else {
785         $list[] = $d;
786       }
787      
788     }
789   }
790
791   return $list;
792 }
793
794 /**
795  * Prints an array as a "tree" of data
796  */
797 function dbug_printtree($dir, $indent = "\t") {
798   static $t = 0;
799   $foo = '';
800   foreach ($dir as $key => $val) {
801     //if this item is an array, its probobly a direcotry
802     if (is_array($val)) {
803       for ($i = 0; $i < $t; $i++) {
804         $foo .= $indent;
805       }
806       //return the directory name
807       $foo .= '[' . $key . ']' . "\n";
808       ++$t;
809       printtree($val, $indent);
810       --$t;
811     } else {
812       for ($i = 0; $i < $t; $i++) {
813         $foo .= $indent;
814       }
815       //return file name
816       $foo .= $val . "\n";
817     }
818   }
819 }
820
821 /**
822  * returns the absolute path to a system application
823  *
824  * @author Moshe Brevda mbrevda => gmail ~ com
825  * @pram string
826  * @retruns string
827  */
828 function fpbx_which($app) {
829   // don't know if we will always have an open class and not even sure if
830   // $amp_conf will be set so to be safe deal with it all here.
831   //
832   $freepbx_conf =& freepbx_conf::create();
833   $which = $freepbx_conf->get_conf_setting('WHICH_' . $app);
834
835   //if we have the location cached return it
836   if ($which) {
837     return $which;
838    
839     //otherwise, search for it
840   } else {
841     //ist of posible plases to find which
842    
843     $which = array(
844         'which',
845         '/usr/bin/which' //centos/mac osx
846     );
847    
848     foreach ($which as $w) {
849       exec($w . ' ' . $app, $path, $ret);
850      
851       //exit if we have a posotive find
852       if ($ret === 0) {
853         break;
854       }
855     }
856    
857     if($path[0]) {
858       //if we have a path add it to freepbx settings
859       $set = array(
860           'value'     => $path[0],
861           'defaultval'  => $path[0],
862           'readonly'    => 1,
863           'hidden'    => 0,
864           'level'     => 2,
865           'module'    => '',
866           'category'    => 'System Apps',
867           'emptyok'   => 1,
868           'name'      => 'Path for ' . $app,
869           'description' => 'The path to ' . $app
870                   . ' as auto-determined by the system.'
871                   . ' Overwrite as necessary.',
872           'type'      => CONF_TYPE_TEXT
873       );
874       $freepbx_conf->define_conf_setting('WHICH_' . $app, $set);
875       $freepbx_conf->commit_conf_settings();
876      
877       //return the path
878       return $path[0];
879     } else {
880       return false;
881     }
882   }
883 }
884
885
886 /**
887  * http://php.net/manual/en/function.getopt.php
888  * temporary polyfill for proper working of getopt()
889  * will revert to the native function if php >= 5.3.0
890  *
891  *
892  * ===============================================================
893  * THIS FUNCTION SHOULD NOT BE RELIED UPON AS IT WILL REMOVED
894  * ONCE THE PROJECT REQUIRES PHP 5.3.0
895  * if you must, call like:
896  * $getopts = (function_exists('_getopt') ? '_' : '') . 'getopt';
897  * $vars = $getopts($short = '', $long = array('id::'));
898  * ===============================================================
899  *
900  *
901  * http://www.ntu.beautifulworldco.com/weblog/?p=526
902  */
903 function _getopt() {
904   if (func_num_args() == 1) {
905     $flag = $flag_array = $GLOBALS['argv'];
906     $short_option   = func_get_arg(0);
907     $long_option    = array();
908   } elseif (func_num_args() == 2) {
909     if (is_array(func_get_arg(1))) {
910       $flag = $GLOBALS['argv'];
911       $short_option = func_get_arg(0);
912       $long_option  = func_get_arg(1);
913     } else {
914       $flag     = func_get_arg(0);
915       $short_option = func_get_arg(1);
916       $long_option  = array ();
917     }
918   } else if ( func_num_args() == 3 ) {
919     $flag       = func_get_arg(0);
920     $short_option   = func_get_arg(1);
921     $long_option    = func_get_arg(2);
922   } else {
923     exit ( "wrong options\n" );
924   }
925   if (PHP_VERSION_ID >= 50300) {
926     return getopt($short_option, $long_option);
927   }
928   $short_option     = trim ( $short_option );
929   $short_no_value     = array();
930   $short_required_value = array();
931   $short_optional_value = array();
932   $long_no_value      = array();
933   $long_required_value  = array();
934   $long_optional_value  = array();
935   $options        = array();
936
937   for ($i = 0; $i < strlen ($short_option);) {
938     if ($short_option{$i} != ":") {
939       if ($i == strlen ($short_option) - 1) {
940         $short_no_value[] = $short_option{$i};
941         break;
942       } else if ($short_option{$i+1} != ":") {
943         $short_no_value[] = $short_option{$i};
944         $i++;
945         continue;
946       } elseif ($short_option{$i+1} == ":" && $short_option{$i+2} != ":") {
947         $short_required_value[] = $short_option{$i};
948         $i += 2;
949         continue;
950         } elseif ($short_option{$i+1} == ":" && $short_option{$i+2} == ":") {
951         $short_optional_value[] = $short_option{$i};
952         $i += 3;
953         continue;
954       }
955     } else {
956       continue;
957     }
958   }
959
960   foreach ($long_option as $a) {
961     if ( substr( $a, -2 ) == "::" ) {
962       $long_optional_value[] = substr($a, 0, -2);
963       continue;
964     } elseif (substr( $a, -1 ) == ":") {
965       $long_required_value[] = substr($a, 0, -1 );
966       continue;
967     } else {
968       $long_no_value[] = $a;
969       continue;
970     }
971   }
972
973   if (is_array ($flag)) {
974     $flag_array = $flag;
975   } else {
976     $flag = "- $flag";
977     $flag_array = split_para($flag);
978   }
979
980   for ($i = 0; $i < count($flag_array);) {
981
982     if ($i >= count ($flag_array) )
983       break;
984
985     if (!$flag_array[$i] || $flag_array[$i] == "-") {
986       $i++;
987       continue;
988     }
989
990     if ($flag_array[$i]{0} != "-") {
991       $i++;
992       continue;
993     }
994
995     if (substr( $flag_array[$i], 0, 2 ) == "--") {
996       if (strpos($flag_array[$i], '=') != false) {
997         list($key, $value) = explode('=', substr($flag_array[$i], 2), 2);
998         if (in_array($key, $long_required_value) || in_array($key, $long_optional_value)) {
999           $options[$key][] = $value;
1000         }
1001         $i++;
1002         continue;
1003       }
1004       if (strpos($flag_array[$i], '=') == false) {
1005         $key = substr( $flag_array[$i], 2 );
1006         if ( in_array( substr( $flag_array[$i], 2 ), $long_required_value ) ) {
1007           $options[$key][] = $flag_array[$i+1];
1008           $i += 2;
1009           continue;
1010         } elseif (in_array(substr($flag_array[$i], 2), $long_optional_value)) {
1011           if ($flag_array[$i+1] != "" && $flag_array[$i+1]{0} != "-") {
1012             $options[$key][] = $flag_array[$i+1];
1013             $i += 2;
1014           } else {
1015             $options[$key][] = FALSE;
1016             $i ++;
1017           }
1018           continue;
1019         } else if (in_array(substr( $flag_array[$i], 2 ), $long_no_value ) ) {
1020           $options[$key][] = FALSE;
1021           $i++;
1022           continue;
1023         } else {
1024           $i++;
1025           continue;
1026         }
1027       }
1028     } else if ( $flag_array[$i]{0} == "-" && $flag_array[$i]{1} != "-" ) {
1029       for ( $j=1; $j < strlen($flag_array[$i]); $j++ ) {
1030         if ( in_array( $flag_array[$i]{$j}, $short_required_value ) || in_array( $flag_array[$i]{$j}, $short_optional_value )) {
1031
1032           if ( $j == strlen($flag_array[$i]) - 1  ) {
1033             if ( in_array( $flag_array[$i]{$j}, $short_required_value ) ) {
1034               $options[$flag_array[$i]{$j}][] = $flag_array[$i+1];
1035               $i += 2;
1036             } else if (in_array($flag_array[$i]{$j}, $short_optional_value ) && $flag_array[$i+1] != "" && $flag_array[$i+1]{0} != "-" ) {
1037               $options[$flag_array[$i]{$j}][] = $flag_array[$i+1];
1038               $i += 2;
1039             } else {
1040               $options[$flag_array[$i]{$j}][] = FALSE;
1041               $i ++;
1042             }
1043             $plus_i = 0;
1044             break;
1045           } else {
1046             $options[$flag_array[$i]{$j}][] = substr ( $flag_array[$i], $j + 1 );
1047               $i ++;
1048             $plus_i = 0;
1049             break;
1050           }
1051         } else if(in_array($flag_array[$i]{$j}, $short_no_value)) {
1052           $options[$flag_array[$i]{$j}][] = FALSE;
1053           $plus_i = 1;
1054           continue;
1055         }
1056       }
1057       $i += $plus_i;
1058       continue;
1059     }
1060     $i++;
1061     continue;
1062   }
1063
1064   foreach ($options as $key => $value) {
1065     if (count ( $value ) == 1) {
1066       $options[ $key ] = $value[0];
1067     }
1068   }
1069
1070   return $options;
1071
1072 }
1073
1074 /**
1075  * returns a rounded string representation of a byte size
1076  *
1077  * @author http://us2.php.net/manual/en/function.memory-get-usage.php#96280
1078  * @pram int
1079  * @retruns string
1080  */
1081 function bytes2string($size){
1082     $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
1083     return round($size / pow(1024, ($i = floor(log($size, 1024))))) . ' ' . $unit[$i];
1084  }
1085
1086 /**
1087  * returns the absolute path to a system application
1088  *
1089  * @author Moshe Brevda mbrevda => gmail ~ com
1090  * @pram string
1091  * @pram string, optional
1092  * @returns string
1093  */
1094 function string2bytes($str, $type = ''){
1095   if (!$type) {
1096     $str  = explode(' ', $str);
1097     $type = strtolower($str[1]);
1098     $str  = $str[0];
1099   }
1100  
1101     $units  = array(
1102           'b'   => 1,
1103           'kb'  => 1024,
1104           'mb'  => 1024 * 1024,
1105           'gb'  => 1024 * 1024 * 1024,
1106           'tb'  => 1024 * 1024 * 1024 * 1024,
1107           'pb'  => 1024 * 1024 * 1024 * 1024 * 1024
1108       );
1109  
1110     return isset($str, $units[$type])
1111       ? round($str * $units[$type])
1112       : false;
1113  }
1114
1115 /**
1116  * downloads a file to the browser (i.e. sends the file to the browser)
1117  *
1118  * @author Moshe Brevda mbrevda => gmail ~ com
1119  * @pram string - absolute path to file
1120  * @pram string, optional - file name as it will be downloaded
1121  * @pram string, optional - content mime type
1122  * @pram bool, optional - true will force the file to be download.
1123  *            False allows the browser to attempt to display the file
1124  *            Correct mime type ($type) snesesary for proper broswer interpretation!
1125  *
1126  */
1127 function download_file($file, $name = '', $type = '', $force_download = false) {
1128   if (file_exists($file)) {
1129     //set the filename to the current filename if no name is specified
1130     $name = $name ? $name : basename($file);
1131    
1132     //sanitize filename
1133     $name = preg_replace('/[^A-Za-z0-9_\.-]/', '', $name);
1134    
1135     //attempt to set file mime type if it isn't already set
1136     if (!$type) {
1137       if (class_exists('finfo')) {
1138         $finfo = new finfo(FILEINFO_MIME);
1139         $type = $finfo->file($file);
1140       } else {
1141         exec(fpbx_which('file') . ' -ib ' . $file, $res);
1142         $type = $res[0];
1143       }
1144     }
1145
1146     //failsafe for false or blank results
1147     $type = $type ? $type : 'application/octet-stream';
1148    
1149     $disposition = $force_download ? 'attachment' : 'inline';
1150    
1151     //send headers
1152     header('Content-Description: File Transfer');
1153     header('Content-Type: ' . $type);
1154     header('Content-Disposition: ' . $disposition . '; filename=' . $name);
1155     header('Content-Transfer-Encoding: binary');
1156     header('Expires: 0');
1157     header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1158     header('Pragma: public');
1159     header('Content-Length: ' . filesize($file));
1160    
1161     //clear all buffers
1162     while (ob_get_level()) {
1163       ob_end_clean();
1164     }
1165     flush();
1166    
1167     //send the file!
1168     readfile($file);
1169    
1170     //return immediately
1171     exit;
1172   } else {
1173     return false;
1174   }
1175 }
1176
1177
1178 /**
1179  * Get data from a pdf file. Requires pdfinfo
1180  *
1181  * @author Moshe Brevda mbrevda => gmail ~ com
1182  * @pram string - /path/to/file
1183  * @returns array - details about the pdf.
1184  * The following details are returned
1185  *    (values returned are depndant on the pdfinfo binary)
1186  *    author
1187  *    creationdate
1188  *    creator
1189  *    encrypted
1190  *    filesize
1191  *    moddate
1192  *    optimized
1193  *    pages
1194  *    pagesize
1195  *    pdfversion
1196  *    producer
1197  *    tagged
1198  *    title
1199  */
1200 function fpbx_pdfinfo($pdf) {
1201   $pdfinfo = array();
1202   exec(fpbx_which('pdfinfo') . ' ' . $pdf, $pdf_details, $ret_code);
1203  
1204   if($ret_code !== 0) {
1205     return false;
1206   }
1207  
1208   foreach($pdf_details as $detail) {
1209     list($key, $value) = preg_split('/:\s*/', $detail, 2);
1210     $pdfinfo[strtolower(preg_replace('/[^A-Za-z]/', '', $key))] = $value;
1211   }
1212   ksort($pdfinfo);
1213   return $pdfinfo;
1214 }
1215
1216 /**
1217  * Update AMI credentials in manager.conf
1218  *
1219  * @author Philippe Lindheimer
1220  * @pram string
1221  * @pram string
1222  * @returns boolean
1223  *
1224  * allows FreePBX to update the manager credentials primarily used by Advanced Settings and Backup and Restore.
1225  */
1226 function fpbx_ami_update($user=false, $pass=false, $writetimeout = false) {
1227   global $amp_conf, $astman;
1228   $conf_file = $amp_conf['ASTETCDIR'] . '/manager.conf';
1229   $ret = $ret2 = 0;
1230   $output = array();
1231  
1232   if ($user !== false && $user != '') {
1233     exec('sed -i.bak "s/\s*\[general\].*$/TEMPCONTEXT/;s/\[.*\]/\[' . $amp_conf['AMPMGRUSER'] . '\]/;s/^TEMPCONTEXT$/\[general\]/" '. $conf_file, $output, $ret);
1234     if ($ret) {
1235       dbug($output);
1236       dbug($ret);
1237       freepbx_log(FPBX_LOG_ERROR,sprintf(_("Failed changing AMI user to [%s], internal failure details follow:"),$amp_conf['AMPMGRUSER']));
1238       foreach ($output as $line) {
1239         freepbx_log(FPBX_LOG_ERROR,sprintf(_("AMI failure details:"),$line));
1240       }
1241     }
1242   }
1243
1244   if ($pass !== false && $pass != '') {
1245     unset($output);
1246     exec('sed -i.bak "s/secret\s*=.*$/secret = ' . $amp_conf['AMPMGRPASS'] . '/" ' . $conf_file, $output, $ret2);
1247     if ($ret2) {
1248       dbug($output);
1249       dbug($ret2);
1250       freepbx_log(FPBX_LOG_ERROR,sprintf(_("Failed changing AMI password to [%s], internal failure details follow:"),$amp_conf['AMPMGRPASS']));
1251       foreach ($output as $line) {
1252         freepbx_log(FPBX_LOG_ERROR,sprintf(_("AMI failure details:"),$line));
1253       }
1254     }
1255   }
1256  
1257   //attempt to set writetimeout
1258   unset($output);
1259   if ($writetimeout) {
1260     exec('sed -i.bak "s/writetimeout\s*=.*$/writetimeout = '
1261       . $amp_conf['ASTMGRWRITETIMEOUT'] . '/" ' . $conf_file, $output, $ret3);
1262     if ($ret3) {
1263       dbug($output);
1264       dbug($ret3);
1265       freepbx_log(FPBX_LOG_ERROR,sprintf(_("Failed changing AMI writetimout to [%s], internal failure details follow:"),$amp_conf['ASTMGRWRITETIMEOUT']));
1266       foreach ($output as $line) {
1267         freepbx_log(FPBX_LOG_ERROR,sprintf(_("AMI failure details:"),$line));
1268       }
1269     }
1270   }
1271   if ($ret || $ret2 || $ret3) {
1272     dbug("aborting early because previous errors");
1273     return false;
1274   }
1275   if (!empty($astman)) {
1276     $ast_ret = $astman->Command('module reload manager');
1277   } else {
1278     unset($output);
1279     dbug("no astman connection so trying to force through linux command line");
1280     exec(fpbx_which('asterisk') . " -rx 'module reload manager'", $output, $ret2);
1281     if ($ret2) {
1282       dbug($output);
1283       dbug($ret2);
1284       freepbx_log(FPBX_LOG_ERROR,_("Failed to reload AMI, manual reload will be necessary, try: [asterisk -rx 'module reload manager']"));
1285     }
1286   }
1287   return true;
1288 }
1289
1290 /**
1291  * Outbound Callerid Sanatizer
1292  * @author mbrevda@gmail.com
1293  * @param string
1294  * @return string
1295  *
1296  * Bell Canada BID-0011, Enhanced Call Management Service, May, 1992
1297  * 5.2.7: "The field can contain any displayable ASCII character"
1298  * http://www.bell.cdn-telco.com/bid/bid-0011.pdf
1299  * referencing Bellcore TR-TSY-000031, which I could not find -MB
1300  *
1301  * Please note: instead of using this all over the place, it would
1302  * make much more sense to do sanitization one time in the dial plan
1303  * just before a call is sent out a trunk. Hoever, there doesnt seem
1304  * to be a simple way to do this in asterisk.
1305  *
1306  */
1307 function sanitize_outbound_callerid($cid) {
1308   return preg_replace('/[^[:print:]]/', '', $cid);
1309 }
1310
1311 /**
1312  * Recursivly remove a directory
1313  * @param string - dirname
1314  *
1315  * @return bool
1316  */
1317 function rrmdir($dir) {
1318   foreach(glob($dir . '/*') as $file) {
1319     if(is_dir($file))
1320       rrmdir($file);
1321     else
1322       unlink($file);
1323     }
1324     rmdir($dir);
1325
1326   return !is_dir($dir);
1327 }
1328
1329 /**
1330  * Run bootstrap hooks as provided by module.xml
1331  *
1332  * We currently support hooking at two points: before modules are loaded and after modules are loaded
1333  * Before we load ANY modules, we will include all "all_mods" hooks
1334  * Before we load an indevidual module, we will load there specifc hook
1335  *
1336  * @param string - hook type
1337  * @param string - module name
1338  *
1339  */
1340 function bootstrap_include_hooks($hook_type, $module) {
1341   global $amp_conf;
1342   //first parse and load all hook info
1343   if (!isset($hooks)) {
1344     static $hooks = '';
1345     $hooks = _bootstrap_parse_hooks();
1346    
1347   }
1348  
1349   if (isset($hooks[$hook_type][$module])) {
1350     foreach ($hooks[$hook_type][$module] as $hook) {
1351       if (file_exists($hook)) {
1352         require_once($hook);
1353       } elseif(file_exists($amp_conf['AMPWEBROOT'] . '/admin/' . $hook)) {
1354         require_once($amp_conf['AMPWEBROOT'] . '/admin/' . $hook);
1355       }
1356      
1357     }
1358   }
1359  
1360   return true;
1361 }
1362
1363 /**
1364  * Helper function to laod hooks for bootstrap_include_hooks()
1365  */
1366 function _bootstrap_parse_hooks() {
1367   $hooks    = array();
1368  
1369   $modules  = module_getinfo(false, MODULE_STATUS_ENABLED);
1370   foreach ($modules as $mymod => $mod) {
1371     if (isset($mod['bootstrap_hooks'])) {
1372       foreach ($mod['bootstrap_hooks'] as $type => $type_mods) {
1373         switch ($type) {
1374           case 'pre_module_load':
1375           case 'post_module_load':
1376             //first get all_mods
1377             if (isset($type_mods['all_mods'])) {
1378              
1379               $hooks[$type]['all_mods'] = isset($hooks[$type]['all_mods'])
1380                             ? array_merge($hooks[$type]['all_mods'],
1381                              (array)$type_mods['all_mods'])
1382                             : (array)$type_mods['all_mods'];
1383               unset($type_mods['all_mods']); 
1384             }
1385             if (!isset($type_mods)) {
1386               break;//break if there are no more hooks to include
1387             }
1388             //now load all remaining modules
1389             foreach ($type_mods as $type_mod) {
1390               $hooks[$type][$mymod] = isset($hooks[$type][$mymod])
1391                           ? array_merge($hooks[$type][$mymod],
1392                           (array)$type_mod)
1393                           : (array)$type_mod;
1394             }
1395             break;
1396           default:
1397             break;
1398         }
1399       }
1400     }
1401   }
1402   return $hooks;
1403 }
Note: See TracBrowser for help on using the browser.