root/freepbx/branches/2.10/amp_conf/bin/retrieve_conf

Revision 12802, 32.7 kB (checked in by p_lindheimer, 2 years ago)

remove FOP from framework and convert to real module

  • Property svn:mime-type set to text/html
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/php -q
2 <?php
3
4 //include bootstrapper
5 $bootstrap_settings['freepbx_auth'] = false;
6 if (!@include_once(getenv('FREEPBX_CONF') ? getenv('FREEPBX_CONF') : '/etc/freepbx.conf')) {
7   include_once('/etc/asterisk/freepbx.conf');
8 }
9
10 if (!$bootstrap_settings['astman_connected']) {
11   fatal(sprintf(_("Unable to connect to Asterisk Manager from %s, aborting"),__FILE__));
12 }
13
14 $freepbx_conf =& freepbx_conf::create();
15
16 class connectdirs {
17
18   var $nt;
19   var $symlink_dirs;
20   var $cp_dirs;
21
22   var $cp_errors = '';
23   var $symlink_error_modules = '';
24     
25   function &create() {
26     static $obj;
27     if (!isset($obj)) {
28       $obj = new connectdirs();
29     }
30     return $obj;
31   }
32
33   function connectdirs() {
34     global $amp_conf;
35     global $db;
36     $this->symlink_dirs['bin']        = $amp_conf['AMPBIN'];
37     $this->symlink_dirs['etc']        = $amp_conf['ASTETCDIR'];
38     $this->symlink_dirs['images']     = $amp_conf['AMPWEBROOT'] . "/admin/images";
39     $this->symlink_dirs['ari/modules']  = $amp_conf['AMPWEBROOT'] . "/recordings/modules";
40     $this->symlink_dirs['ari/theme']  = $amp_conf['AMPWEBROOT'] . "/recordings/theme";
41     $this->symlink_dirs['ari/js']   = $amp_conf['AMPWEBROOT'] . "/recordings/theme/js";
42     $this->symlink_dirs['ari/images'] = $amp_conf['AMPWEBROOT'] . "/recordings/theme/images";
43
44     $this->symlink_sound_dirs['sounds']     = $amp_conf['ASTVARLIBDIR'] . '/sounds';
45
46     $this->cp_dirs['agi-bin']       = $amp_conf['ASTAGIDIR'];
47
48     $this->nt = notifications::create($db);
49   }
50
51   function symlink_assets($module) {
52     global $amp_conf;
53
54     // e.g. /var/www/html/admin/modules/ringgroups/assets
55     // e.g. /var/www/html/admin/assets/ringgroups
56     //
57     $dir = $amp_conf['AMPWEBROOT'] . '/admin/modules/' . $module . '/assets';
58     $targetdir = $amp_conf['AMPWEBROOT'] . "/admin/assets/" . $module;
59
60     // if assets does not exists in the module then unlinkk it in assets had it
61     // been there already.
62     //
63     if (!is_dir($dir)) {
64       if (is_link($targetdir)) {
65         $this->err_unlink($targetdir);
66       }
67       return;
68     } elseif (!is_link($targetdir)) {
69       // The assets dir exists in the module but no symlink to it, so do that now
70       // e.g. ln -s /var/www/html/admin/modules/ringgroups/assets /var/www/html/admin/assets/ringgroups
71       //
72       if (!symlink($dir, $targetdir)) {
73         freepbx_log(FPBX_LOG_ERROR, "Can Not $dir to $targetdir");
74       }
75
76     }
77   }
78
79   function symlink_sound_dirs($moduledir) {
80     $language_dirs = array();
81     foreach ($this->symlink_sound_dirs as $subdir => $targetdir) {
82       $dir = addslash($moduledir).$subdir;
83       if (is_dir($dir)) {
84         $d = opendir($dir);
85         while ($file = readdir($d)) {
86           if ($file[0] != '.') {
87             // If this is a directory, then put it on the list of language directories to process
88             // otherwise symlink it
89             //
90             if (is_dir(addslash($dir).$file)) {
91               $language_dirs[] = $file;
92             } else {
93               $this->do_symlink(addslash($dir).$file, addslash($targetdir).$file, $subdir, $moduledir);
94             }
95           }
96         }
97         closedir($d);
98         // Now if we have any langauge directories, then check if they are installed on the target and
99         // if so symlink them over.
100         foreach ($language_dirs as $lang) {
101           if (is_dir(addslash($targetdir).$lang)) {
102             $d = opendir(addslash($dir).$lang);
103             while ($file = readdir($d)) {
104               if ($file[0] != '.') {
105                 $this->do_symlink(addslash($dir).addslash($lang).$file, addslash($targetdir).addslash($lang).$file, $subdir, $moduledir);
106               }
107             }
108           } else {
109             out("found language dir $lang for ".basename($moduledir).", not installed on system, skipping");
110           }
111         }
112       }
113     }
114   }
115
116   function symlink_subdirs($moduledir) {
117     foreach ($this->symlink_dirs as $subdir => $targetdir) {
118       $dir = addslash($moduledir).$subdir;
119       if (is_dir($dir)) {
120         $d = opendir($dir);
121         while ($file = readdir($d)) {
122           if ($file[0] != '.') {
123             $this->do_symlink(addslash($dir).$file, addslash($targetdir).$file, $subdir, $moduledir);
124           }
125         }
126         closedir($d);
127       }
128     }
129   }
130
131   function do_symlink($src, $dest, $subdir, $moduledir) {
132     if (file_exists_wrapper($dest)) {
133       if ((!is_link($dest) || readlink($dest) != $src) && (md5_file($src) == md5_file($dest))) {
134         // dbug('retrieve-conf', "Can't symlink $src to $dest but files are the same so ignoring");
135       } else if (!is_link($dest)) {
136         freepbx_log(FPBX_LOG_ERROR, $dest.' already exists, and is not a symlink!');
137         $this->symlink_error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest." from ".basename($moduledir)."/".$subdir." (Already exists, not a link)";
138       } else if (readlink($dest) != $src) {
139         // TODO : is this the proper handling? should we just overwrite..?
140         freepbx_log(FPBX_LOG_ERROR, $dest.' already exists, and is linked to something else!');
141         $this->symlink_error_modules .= "<br />&nbsp;&nbsp;&nbsp;".$dest." from ".basename($moduledir)."/".$subdir." (Already exists, linked to something else)";
142       }
143     } else {
144 //    // symlink, unlike copy, doesn't overwrite - have to delete first
145 //    if (is_link($dest) || file_exists($dest)) {
146 //      unlink($dest);
147 //    }
148       if (!symlink($src, $dest)) {
149         freepbx_log(FPBX_LOG_ERROR, 'Cannot symlink '.$src.' to '.$dest.'. Check Permissions?');
150       }
151     }
152   }
153
154   function symlink_check_errors() {
155     if ($this->symlink_error_modules) {
156       $this->nt->add_error('retrieve_conf', 'SYMLINK', _("Symlink from modules failed"), sprintf(_("retrieve_conf failed to sym link: %s<br \>This can result in FATAL failures to your PBX. If the target file exists and not identical, the symlink will not occur and you should rename the target file to allow the automatic sym link to occur and remove this error, unless this is an intentional customization."),$this->symlink_error_modules));
157     } else {
158       $this->nt->delete('retrieve_conf', 'SYMLINK');
159     }
160   }
161
162   function cp_subdirs($moduledir) {
163     foreach ($this->cp_dirs as $subdir => $targetdir) {
164       $dir = addslash($moduledir).$subdir;
165       if(is_dir($dir)){
166         foreach(listdir($dir) as $idx => $file){
167           $sourcefile = $file;
168           $filesubdir=str_replace($dir.'/', '', $file);
169           $targetfile = addslash($targetdir).$filesubdir;
170  
171           if (file_exists_wrapper($targetfile)) {
172             if (is_link($targetfile)) {
173               if (!$this->err_unlink($targetfile)) {
174                 freepbx_log(FPBX_LOG_ERROR, "$targetfile is a symblolic link, failed to unlink!");
175                 break;
176               }
177             }
178           }
179           // OK, now either the file is a regular file or isn't there, so proceed
180           //
181           if ($this->err_copy($sourcefile,$targetfile)) {
182             // copy was successful, make sure it has execute permissions
183             chmod($targetfile,0754);
184           } else {
185             freepbx_log(FPBX_LOG_ERROR, "$targetfile failed to copy from module directory");
186           }
187         }
188       }
189     }
190   }
191   function cp_check_errors() {
192     if ($this->cp_errors) {
193       $this->nt->add_error('retrieve_conf', 'CPAGIBIN', _("Failed to copy from module agi-bin"), sprintf(_("Retrieve conf failed to copy file(s) from a module's agi-bin dir: %s"),$this->cp_errors));
194     } else {
195       $this->nt->delete('retrieve_conf', 'CPAGIBIN');
196     }
197   }
198   function add_cp_error($string) {
199     $this->cp_errors .= $string;
200   }
201
202   // wrap copy with error handler
203   //
204   function err_copy($source, $dest) {
205     $ret = false;
206     set_error_handler("report_errors");
207       //if were copying a directory, just mkdir the directory
208     if (!is_dir($dest) && !is_file($dest) && !is_link($dest)) {
209       if(is_dir($source)){
210         $ret = mkdir($dest,0754);
211       }elseif(copy($source, $dest)) {
212         $ret = chmod($dest,0754);
213       }
214     }
215     restore_error_handler();
216     return $ret;
217     }
218
219   // wrap unlink with error handler
220   //
221   function err_unlink($dest) {
222     set_error_handler("report_errors");
223     $ret = unlink($dest);
224     restore_error_handler();
225     return $ret;
226   }
227 }
228
229 // I don't think this can be part of the class since it is called by an
230 // error function as a callback (otherwise, can move it into above).
231 //
232 function report_errors($errno, $errstr, $errfile, $errline) {
233   global $db;
234   $escaped_string = $db->escapeSimple($errstr);
235   freepbx_log(FPBX_LOG_ERROR, "php reported: '$escaped_string' after copy or unlink attempt!");
236   $conn_dirs = connectdirs::create();
237   $conn_dirs->add_cp_error($errstr."\n");
238 }
239
240 //define("ASTERISK_CONF", "/etc/asterisk/asterisk.conf");
241 define("WARNING_BANNER", _(";--------------------------------------------------------------------------------;\n; Do NOT edit this file as it is auto-generated by FreePBX. All modifications to ;\n; this file must be done via the web gui. There are alternative files to make    ;\n; custom modifications, details at: http://freepbx.org/configuration_files       ;\n;--------------------------------------------------------------------------------;\n;\n\n"));
242
243 function showHelp() {
244   out(_("Optional parameters:"),false);
245   out(_("  --help, -h, -?           Show this help"),false);
246   out(_("  --debug                  Enable debug output"),false);
247   out(_("  --dry-run                Don't actually do anything"),false);
248 }
249
250 /** Adds a trailing slash to a directory, if it doesn't already have one
251  */
252 function addslash($dir) {
253   return (($dir[ strlen($dir)-1 ] == '/') ? $dir : $dir.'/');
254 }
255
256
257 /********************************************************************************************************************/
258
259 $dryrun = false;
260 $run_install = false;
261 $skip_registry_checks = false;
262
263 // **** Make sure we have PEAR's GetOpts.php, and include it if we need to parse
264 //
265 if ($argc > 1) {
266   outn(_("Checking for PEAR Console::Getopt.."));
267   if (! @ include("Console/Getopt.php")) {
268     out(_("FAILED"));
269     fatal(sprintf(_("PEAR must be installed (requires Console/Getopt.php). Include path: %s"), ini_get("include_path")),true);
270   }
271   out(_("OK"));
272
273   // **** Parse out command-line options
274   $shortopts = "h?u:p:";
275   $longopts = array("help","debug","dry-run","run-install","amportalconf=","skip-registry-checks");
276
277   $args = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), $shortopts, $longopts);
278   if (is_object($args)) {
279     // assume it's PEAR_ERROR
280     out($args->message);
281     exit(255);
282   }
283
284   foreach ($args[0] as $arg) {
285     switch ($arg[0]) {
286       case "--help": case "h": case "?":
287         showHelp();
288         exit(10);
289       break;
290       case "--dry-run":
291         out(_("Dry-run only, no files will be written"),false);
292         $dryrun = true;
293       break;
294       case "--debug":
295         // set to false temporarily, not with freepbx_conf as we don't want it subsequently committed
296         //
297         $amp_conf['FPBXDBUGDISABLE'] = false;
298         debug(_("Debug mode enabled"),false);
299       break;
300       case "--run-install":
301         $run_install = true;
302         out(_("Running module install.php and install.sql scripts"),true);
303       break;
304       case "--amportalconf":
305         $amportalconf = $arg[1];
306         out(sprintf(_("Using %s configuration file"), $amportalconf),false);
307       break;
308       case "--skip-registry-checks":
309         $skip_registry_checks = true;
310         out(_("Skipping extension and destination registry checks"),true);
311       break;
312     }
313   }
314 }
315
316 // Define the notification class for logging to the dashboard
317 //
318 $nt = notifications::create($db);
319 $con_dirs = connectdirs::create();
320
321 /*
322 */
323 // Check and increase php memory_limit if needed and if allowed on the system
324 // TODO: should all be in bootstrap
325 $current_memory_limit = rtrim(ini_get('memory_limit'),'M');
326 $proper_memory_limit = '100';
327 if ($current_memory_limit < $proper_memory_limit) {
328   if (ini_set('memory_limit',$proper_memory_limit.'M') !== false) {
329     $nt->add_notice('core', 'MEMLIMIT', _("Memory Limit Changed"), sprintf(_("Your memory_limit, %sM, is set too low and has been increased to %sM. You may want to change this in you php.ini config file"),$current_memory_limit,$proper_memory_limit));
330   } else {
331     $nt->add_warning('core', 'MEMERR', _("Low Memory Limit"), sprintf(_("Your memory_limit, %sM, is set too low and may cause problems. FreePBX is not able to change this on your system. You should increase this to %sM in you php.ini config file"),$current_memory_limit,$proper_memory_limit));
332   }
333 } else {
334   $nt->delete('core', 'MEMLIMIT');
335 }
336
337
338 //Putting the core module last, to move outbound-allroutes
339 // last in from-internals-additional
340 if (array_key_exists('core', $active_modules)) {
341         $core_tmp = $active_modules['core'];
342         unset($active_modules['core']);
343         $active_modules['core'] = $core_tmp;
344 }
345
346 // include any module global functions
347 // $active_modules is provided by bootstrap now
348 //
349 if(is_array($active_modules)){
350   foreach($active_modules as $key => $module) {
351
352     $module_list[] = $key;
353
354     if ($run_install) module_install($key);
355
356     // create symlinks for files in appropriate sub directories
357     // don't symlink framework files, it is a special case module that happens to have
358     // some conflicting names
359     //
360     switch ($key) {
361       // TODO: these will go away once repositories are up-to-date but leave until 2.10
362       //       at that time the modtype tag will determine this
363       case 'framework':
364       case 'fw_fop':
365       case 'fw_ari':
366       case 'fw_langpacks':
367       break;
368       default:
369         if (isset($module['modtype']) && $module['modtype'] == 'framework') {
370           // don't copy or symlink from framework type modules as they are not real modules
371           break;
372         }
373         $con_dirs->symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key );
374         $con_dirs->symlink_sound_dirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key );
375         $con_dirs->symlink_assets($key);
376         $con_dirs->cp_subdirs( $amp_conf['AMPWEBROOT'].'/admin/modules/'.$key );
377       break;
378     }
379   }
380 }
381 // Now also make sure to symlink the CDR images which is not a proper module
382 //
383 $con_dirs->symlink_subdirs( $amp_conf['AMPWEBROOT'].'/admin/cdr/');
384
385 // Now that we have done all the symlinks and copies, we check and report if there were any errors
386 //
387 $con_dirs->symlink_check_errors();
388 $con_dirs->cp_check_errors();
389
390
391 // create an object of the extensions class
392 require_once($amp_conf['AMPWEBROOT']."/admin/libraries/extensions.class.php");
393 $ext = new extensions;
394
395 if ($amp_conf['DISABLECUSTOMCONTEXTS']) {
396   $ext->disableCustomContexts(true);
397 }
398
399 // create objects for any module classes
400 // currently only 1 class can be declared per module, not sure if that will be an issue
401 if(isset($module_list) && is_array($module_list)){
402   foreach($module_list as $active_module) {
403     $classname = $active_module."_conf";
404     if(class_exists($classname)) {
405       ${$classname} = new $classname;
406     }
407   }
408 }
409
410 $engineinfo = engine_getinfo();
411 if($engineinfo['version'] == 0){
412   fatal(_("retreive_conf failed to get engine information and cannot configure up a softwitch with out it. Error: {$engineinfo['engine']}"),true);
413 }
414 // was setting these variables before, assume we still need them
415 $engine = $engineinfo['engine'];
416 $version = $engineinfo['version'];
417 $chan_dahdi = ast_with_dahdi();
418
419 // If BROWSER_STATS is set to true (default) and we have never provided a notice (NOTICE_BROWSER_STATS false) then do so one time only so
420 // they are aware and can choose to opt out.
421 if (!$amp_conf['NOTICE_BROWSER_STATS'] && $amp_conf['BROWSER_STATS']) {
422   $nt->add_notice('framework', 'BROWSER_STATS', _("Collecting Anonymous Browser Stats"), _("The FreePBX project is collecting anonymous browser statistics using google analytics. These are used to focus development efforts based on real user input. All information is anonymous. You can disable this in Advanced Settings with the Browser Stats setting."));
423   $freepbx_conf->set_conf_values(array('NOTICE_BROWSER_STATS' => true), true, true);
424 }
425
426
427 if (!$freepbx_conf->conf_setting_exists('AST_FUNC_DEVICE_STATE')) {
428   // AST_FUNC_DEVICE_STATE
429   //
430   $set['value'] = '';
431   $set['defaultval'] =& $set['value'];
432   $set['options'] = '';
433   $set['readonly'] = 1;
434   $set['hidden'] = 1;
435   $set['level'] = 10;
436   $set['module'] = '';
437   $set['category'] = 'Internal Use';
438   $set['emptyok'] = 1;
439   $set['name'] = 'Asterisk Function DEVICE_STATE';
440   $set['description'] = "Set to the function name if the function is present in this Asterisk install";
441   $set['type'] = CONF_TYPE_TEXT;
442   $freepbx_conf->define_conf_setting('AST_FUNC_DEVICE_STATE',$set);
443 }
444 if (!$freepbx_conf->conf_setting_exists('AST_FUNC_EXTENSION_STATE')) {
445   // AST_FUNC_EXTENSION_STATE
446   //
447   $set['value'] = '';
448   $set['defaultval'] =& $set['value'];
449   $set['options'] = '';
450   $set['readonly'] = 1;
451   $set['hidden'] = 1;
452   $set['level'] = 10;
453   $set['module'] = '';
454   $set['category'] = 'Internal Use';
455   $set['emptyok'] = 1;
456   $set['name'] = 'Asterisk Function EXTENSION_STATE';
457   $set['description'] = "Set to the function name if the function is present in this Asterisk install";
458   $set['type'] = CONF_TYPE_TEXT;
459   $freepbx_conf->define_conf_setting('AST_FUNC_EXTENSION_STATE',$set);
460 }
461 if (!$freepbx_conf->conf_setting_exists('AST_FUNC_SHARED')) {
462   // AST_FUNC_SHARED
463   //
464   $set['value'] = '';
465   $set['defaultval'] =& $set['value'];
466   $set['options'] = '';
467   $set['readonly'] = 1;
468   $set['hidden'] = 1;
469   $set['level'] = 10;
470   $set['module'] = '';
471   $set['category'] = 'Internal Use';
472   $set['emptyok'] = 1;
473   $set['name'] = 'Asterisk Function SHARED';
474   $set['description'] = "Set to the function name if the function is present in this Asterisk install";
475   $set['type'] = CONF_TYPE_TEXT;
476   $freepbx_conf->define_conf_setting('AST_FUNC_SHARED',$set);
477 }
478 if (!$freepbx_conf->conf_setting_exists('AST_FUNC_CONNECTEDLINE')) {
479   // AST_FUNC_CONNECTEDLINE
480   //
481   $set['value'] = '';
482   $set['defaultval'] =& $set['value'];
483   $set['options'] = '';
484   $set['readonly'] = 1;
485   $set['hidden'] = 1;
486   $set['level'] = 10;
487   $set['module'] = '';
488   $set['category'] = 'Internal Use';
489   $set['emptyok'] = 1;
490   $set['name'] = 'Asterisk Function CONNECTEDLINE';
491   $set['description'] = "Set to the function name if the function is present in this Asterisk install";
492   $set['type'] = CONF_TYPE_TEXT;
493   $freepbx_conf->define_conf_setting('AST_FUNC_CONNECTEDLINE',$set);
494 }
495 if (!$freepbx_conf->conf_setting_exists('AST_FUNC_MASTER_CHANNEL')) {
496   // AST_FUNC_MASTER_CHANNEL
497   //
498   $set['value'] = '';
499   $set['defaultval'] =& $set['value'];
500   $set['options'] = '';
501   $set['readonly'] = 1;
502   $set['hidden'] = 1;
503   $set['level'] = 10;
504   $set['module'] = '';
505   $set['category'] = 'Internal Use';
506   $set['emptyok'] = 1;
507   $set['name'] = 'Asterisk Function MASTER_CHANNEL';
508   $set['description'] = "Set to the function name if the function is present in this Asterisk install";
509   $set['type'] = CONF_TYPE_TEXT;
510   $freepbx_conf->define_conf_setting('AST_FUNC_MASTER_CHANNEL',$set);
511 }
512 if (!$freepbx_conf->conf_setting_exists('AST_APP_VQA')) {
513   // AST_APP_VQA
514   //
515   $set['value'] = '';
516   $set['defaultval'] =& $set['value'];
517   $set['options'] = '';
518   $set['readonly'] = 1;
519   $set['hidden'] = 1;
520   $set['level'] = 10;
521   $set['module'] = '';
522   $set['category'] = 'Internal Use';
523   $set['emptyok'] = 1;
524   $set['name'] = 'Asterisk Application VQA';
525   $set['description'] = "Set to the application name if the application is present in this Asterisk install";
526   $set['type'] = CONF_TYPE_TEXT;
527   $freepbx_conf->define_conf_setting('AST_APP_VQA',$set);
528 }
529 // Since modules can be loaded in a current version, we check these each time
530 // DEVICE_STATE exists in two flavors, DEVSTATE and DEVICE_STATE, the latter is the official one
531 // but back ports exists with the former with both.
532 //
533 if ($astman->func_exists('DEVICE_STATE')) {
534   $update_arr['AST_FUNC_DEVICE_STATE'] = 'DEVICE_STATE';
535 } else {
536   $update_arr['AST_FUNC_DEVICE_STATE'] = $astman->func_exists('DEVSTATE') ? 'DEVSTATE' : '';
537   // If they don't have DEVICE_STATE loaded in some form, force USEDEVSTATE off
538   if ($amp_conf['USEDEVSTATE'] && !$update_arr['AST_FUNC_DEVICE_STATE']) {
539     $update_arr['USEDEVSTATE'] = false;
540   }
541 }
542 $func_arr = array('EXTENSION_STATE', 'SHARED', 'CONNECTEDLINE', 'MASTER_CHANNEL');
543 foreach ($func_arr as $func) {
544   $update_arr['AST_FUNC_'.$func] = $astman->func_exists($func) ? $func : '';
545 }
546
547 $app_arr = array('VQA');
548 foreach ($app_arr as $app) {
549   $update_arr['AST_APP_'.$app] = $astman->app_exists($app) ? $app : '';
550 }
551 $freepbx_conf->set_conf_values($update_arr, true, true);
552
553 // Check for and report any extension conflicts
554 //
555
556 $extens_ok = true;
557 $dests_ok = true;
558
559 $nt = notifications::create($db);
560
561 $my_hash = array_flip($module_list);
562 $my_prob_extens = $skip_registry_checks ? false : framework_list_extension_conflicts($my_hash);
563
564 if (empty($my_prob_extens)) {
565   $nt->delete('retrieve_conf', 'XTNCONFLICT');
566 } else {
567   $previous = null;
568   $str = null;
569   $count = 0;
570   foreach ($my_prob_extens as $extens) {
571     foreach ($extens as $exten => $details) {
572       if ($exten != $previous) {
573         $str .=  "Extension: $exten:<br />";
574         $count++;
575       }
576       $str .= sprintf("%8s: %s<br />",$details['status'], $details['description']);
577       $previous = $exten;
578     }
579   }
580   $nt->add_error('retrieve_conf', 'XTNCONFLICT', sprintf(_("There are %s conflicting extensions"),$count), $str);
581   $extens_ok = false;
582 }
583
584 // Check for and report any bogus destinations
585 //
586 $my_probs = $skip_registry_checks ? false : framework_list_problem_destinations($my_hash, !$amp_conf['CUSTOMASERROR']);
587
588 if (empty($my_probs)) {
589   $nt->delete('retrieve_conf', 'BADDEST');
590 } else {
591   $results = array();
592   $count = 0;
593   $str = null;
594   foreach ($my_probs as $problem) {
595     //print_r($problem);
596     $results[$problem['status']][] = $problem['description'];
597     $count++;
598   }
599   foreach ($results as $status => $subjects) {
600     $str .= sprintf(_("DEST STATUS: %s%s"),$status,"\n");
601     foreach ($subjects as $subject) {
602       //$str .= $subject."<br />";
603       $str .= "   ".$subject."\n";
604     }
605   }
606   $nt->add_error('retrieve_conf', 'BADDEST', sprintf(_("There are %s bad destinations"),$count), $str);
607   $dests_ok = false;
608 }
609
610 if ((!$extens_ok && $amp_conf['XTNCONFLICTABORT']) || (!$dests_ok && $amp_conf['BADDESTABORT'])) {
611   out(_("Aborting reload because extension conflicts or bad destinations"));
612   exit(20);
613 }
614
615 // run all of the *_get_config and _hookGet_config functions, which will populate the appropriate objects
616 if(isset($module_list) && is_array($module_list)){
617   foreach($module_list as $module) {
618     $funcname = $module."_get_config";
619     if (function_exists($funcname)) {
620       $funcname($engine);
621     }
622   }
623   foreach($module_list as $module) {
624     $funcname = $module."_hookGet_config";
625     if (function_exists($funcname)) {
626       $funcname($engine);
627     }
628   }
629 }
630
631 // extensions_additional.conf
632 // create the from-internal-additional contexts so other can add to it
633 $ext->add('from-internal-additional', 'h', '', new ext_hangup(''));
634 $ext->add('from-internal-noxfer-additional', 'h', '', new ext_hangup(''));
635 //echo $ext->get_filename();
636 //echo $ext->generateConf();
637 write_file($ext->get_filename(),$ext->generateConf());
638
639 // now we write out our conf files for modules
640 // check for any objects for each of the active modules
641 // ** conferences is an example of a module that write a conf
642 if(isset($module_list) && is_array($module_list)){
643   foreach($module_list as $active_module) {
644     $classname = $active_module."_conf";
645     if(class_exists($classname) && get_class(${$classname}) !== false) {
646       //echo ${$classname}->get_filename();
647       //echo ${$classname}->generateConf();
648       
649       // if the module returns an array, it wants to write multiple files
650       // ** pinsets is an example of a module that does this
651       if (is_array(${$classname}->get_filename())) {
652         foreach(${$classname}->get_filename() as $modconf) {
653           if (isset(${$classname}->use_warning_banner)) {
654             write_file($modconf,${$classname}->generateConf($modconf),${$classname}->use_warning_banner);
655           } else {
656             write_file($modconf,${$classname}->generateConf($modconf));
657           }
658         }
659       } else {
660         if (isset(${$classname}->use_warning_banner)) {
661           write_file(${$classname}->get_filename(),${$classname}->generateConf(),${$classname}->use_warning_banner);
662         } else {
663           write_file(${$classname}->get_filename(),${$classname}->generateConf());
664         }
665       }
666     }
667   }
668 }
669 // Now we write on amportal.conf if it is writable, which allows legacy applications in the
670 // eco-system to take advantage of the settings.
671 // we write out the error message here instead of in freepbx_settings so that we don't hit the db every single page load
672 //
673 if ($freepbx_conf->amportal_canwrite()) {
674   file_put_contents('/etc/amportal.conf',$freepbx_conf->amportal_generate(true));
675   $nt->delete('framework', 'AMPORTAL_NO_WRITE');
676 } elseif (!$nt->exists('framework', 'AMPORTAL_NO_WRITE')) {
677   $nt->add_error('framework', 'AMPORTAL_NO_WRITE', _("amportal.conf not writeable"), _("Your amportal.conf file is not writeable. FreePBX is running in a crippled mode until changed. You can run 'amportal chown' from the Linux command line to rectify this."),true);
678 }
679
680 // Let's move some more of our checks to retrieve_conf so that we are not constantly checking these on page loads
681 //
682
683 // Warn about default Manager Interface Password
684 //
685 if ($amp_conf['AMPMGRPASS'] == $freepbx_conf->get_conf_default_setting('AMPMGRPASS')) {
686   if (!$nt->exists('core', 'AMPMGRPASS')) {
687     $nt->add_warning('core', 'AMPMGRPASS', _("Default Asterisk Manager Password Used"), _("You are using the default Asterisk Manager password that is widely known, you should set a secure password"));
688   }
689 } else {
690   $nt->delete('core', 'AMPMGRPASS');
691 }
692  
693 // Warn about default ARI Admin Password
694 //
695 if ($amp_conf['ARI_ADMIN_PASSWORD'] == $freepbx_conf->get_conf_default_setting('ARI_ADMIN_PASSWORD')) {
696   if (!$nt->exists('ari', 'ARI_ADMIN_PASSWORD')) {
697     $nt->add_warning('ari', 'ARI_ADMIN_PASSWORD', _("Default ARI Admin password Used"), _("You are using the default ARI Admin password that is widely known, you should change to a new password. Do this in Advanced Settings"));
698   }
699 } else {
700   $nt->delete('ari', 'ARI_ADMIN_PASSWORD');
701 }
702  
703 // Warn about default Database Password
704 //
705 if ($amp_conf['AMPDBPASS'] == $freepbx_conf->get_conf_default_setting('AMPDBPASS')) {
706   if (!$nt->exists('core', 'AMPDBPASS')) {
707     $nt->add_warning('core', 'AMPDBPASS', _("Default SQL Password Used"), _("You are using the default SQL password that is widely known, you should set a secure password"));
708   }
709 } else {
710   $nt->delete('core', 'AMPDBPASS');
711 }
712
713 // Warn if in deviceanduser mode and not using DYNAMICHINTS
714 //
715 if ($amp_conf['AMPEXTENSIONS'] == 'deviceanduser' && !$amp_conf['DYNAMICHINTS']) {
716   if (!$nt->exists('framework', 'NO_DYNAMICHINTS')) {
717     $nt->add_warning('framework', 'NO_DYNAMICHINTS', _("Device & User Hints Issue"), _("You are set to Device and User mode but are not set to 'Dynamically Generate Hints' which can result in improper phone state behavior. This can be changed on the Advanced Settings page, check the tooltip for specific configuration details."));
718   }
719 } else {
720   $nt->delete('framework', 'NO_DYNAMICHINTS');
721 }
722
723 function write_file($filename,$contents,$use_warning_banner=true) {
724   global $asterisk_conf;
725   if (isset($filename) && !empty($filename)) {
726     if ($fd = fopen(addslash($asterisk_conf['astetcdir']).$filename, "w")) {
727       if ($use_warning_banner) {
728         fwrite($fd, WARNING_BANNER );
729       }
730       fwrite($fd, $contents);
731       fclose($fd);
732     }
733   }
734 }
735
736 /* file_exists_wrapper()
737  * wrapper for file_exists() with the following additonal functionality.
738  * if the file is a symlink, it will check if the link exists and if not
739  * it will try to remove this file. It returns a false (file does not exists)
740  * if the file is successfully removed, true if not. If not a symlink, just
741  * returns file_exists()
742  */
743 function file_exists_wrapper($string) {
744   if (is_link($string)) {
745     $linkinfo = readlink($string);
746     if ($linkinfo === false) {
747       //TODO: throw error?
748       return !unlink($string);
749     } else {
750       if (file_exists($linkinfo)) {
751         return true;
752       } else {
753         return !unlink($string);
754       }
755     }
756   } else {
757     return file_exists($string);
758   }
759 }
760
761 //based on: http://snippets.dzone.com/posts/show/155
762 function listdir($directory, $recursive=true) {
763   $array_items = array();
764     if ($handle = opendir($directory)) {
765       while (false !== ($file = readdir($handle))) {
766         if ($file != "." && $file != "..") {
767           if (is_dir($directory. "/" . $file)) {
768             if($recursive) {
769               $array_items = array_merge($array_items, listdir($directory. "/" . $file, $recursive));
770             }
771           $file = $directory . "/" . $file;
772           $array_items[] = preg_replace("/\/\//si", "/", $file);
773         }else{
774           $file = $directory . "/" . $file;
775           $array_items[] = preg_replace("/\/\//si", "/", $file);
776         }
777       }
778     }
779     closedir($handle);
780   }
781   return array_reverse($array_items);//reverse so that we get directories BEFORE the files that are in them
782 }
783
784 /** Check if there is a job running, if one is found then all is good, if one is not found, it will be added and a
785  *  notification will be sent.
786  */
787 function install_cron_scheduler() {
788   global $amp_conf;
789   global $nt;
790
791   // crontab appears to return an error when no entries, os only fail if error returned AND a list of entries.
792   // Don't know if this will ever happen, but a failure and a list could indicate something wrong.
793   //
794   $outlines = array();
795   exec("/usr/bin/crontab -l", $outlines, $ret);
796   if ($ret && count($outlines)) {
797     $nt->add_error('retrieve_conf', 'CRONMGR', _("Failed to check crontab for cron manager"), sprintf(_("crontab returned %s error code when checking for crontab entries to start freepbx-cron-scheduler.php crontab manager"),$ret));
798   } else {
799     $nt->delete('retrieve_conf', 'CRONMGR');
800     $outlines2 = preg_grep("/freepbx-cron-scheduler.php/",$outlines);
801     $cnt = count($outlines2);
802     switch ($cnt) {
803       case 0:
804         /** grab any other cronjobs that are running as asterisk and NOT associated with backups
805         *  this code was taken from the backup module for the most part. But seems to work...
806         */
807         $outlines = array();
808         exec("/usr/bin/crontab -l | grep -v ^#\ DO\ NOT | grep -v ^#\ \( |  grep -v freepbx-cron-scheduler.php", $outlines, $ret);
809         $crontab_entry = "";
810         foreach ($outlines as $line) {
811           $crontab_entry .= $line."\n";
812         }
813         // schedule to run hourly, at a random time. The random time is explicit to accomodate things like module_admin online update checking
814         // since we will want a random access to the server. In the case of module_admin, that will also be scheduled randomly within the hour
815         // that it is to run
816         //
817         $crontab_entry .= rand(0,59)." * * * * ".$amp_conf['AMPBIN']."/freepbx-cron-scheduler.php";
818         system("/bin/echo '$crontab_entry' | /usr/bin/crontab -");
819         break;
820       case 1:
821         // already running, nothing to do
822         break;
823       default:
824         // error, there should never be more than one running
825         echo "TODO: deal with error here\n";
826         $nt->add_error('retrieve_conf', 'CRONMGR', _("Multiple freepbx-cron-scheduler.php running"), sprintf(_("There were %s freepbx-cron-scheduler.php instances running. There should be only 1."),$cnt));
827     }
828   }
829 }
830
831 // Check and install the freepbx-cron-scheduler.php manager
832 //
833 install_cron_scheduler();
834
835
836 // run retrieve_conf_post_custom
837 // If the following file exists, it will be run. This allows customization to be run automatically after the normal
838 // processing. Caution should be taken using this as it is only deisgned for expert usage. Errors in the code will
839 // have bad consequences and can cripple the system.
840 //
841 if ($amp_conf['AMPLOCALBIN']) {
842 $post_custom = $amp_conf['AMPLOCALBIN'].'/retrieve_conf_post_custom';
843   if (file_exists($post_custom)) {
844     outn(sprintf(_("Found script %s, executing.."), $post_custom));
845     include($post_custom);
846     out(_("OK"));
847   }
848 }
849
850 /* As of Asterisk 1.4.16 or there abouts, a missing #include file will make the reload fail. So
851    we need to make sure that we have such for everything that is in our configs. We will simply
852    look for the #include statements and touch the files vs. trying to inventory everything we may
853    need and then forgetting something.
854 */
855
856 $output = array();
857 exec("grep '#include' ".$amp_conf['ASTETCDIR']."/*.conf | sed 's/;.*//; s/#include//'",$output,$retcode);
858 if ($retcode != 0) {
859   error("Error code $retcode: trying to search for missing #include files");
860 }
861
862 foreach($output as $file) {
863   if (trim($file) == '') {
864     continue;
865   }
866   $parse1 = explode(':',$file);
867   $parse2 = explode(';',$parse1[1]);
868   $rawfile = trim($parse2[0]);
869   if ($rawfile == '') {
870     continue;
871   }
872
873   $target = ($rawfile[0] == '/') ? $rawfile : $amp_conf['ASTETCDIR']."/$rawfile";
874
875   if (!file_exists($target)) {
876     $output = array();
877     exec("touch $target", $output, $retcode);
878     if ($retcode != 0) {
879       error("Error code $retcode: trying to create empty file $target");
880     }
881   }
882 }
883
884 // Some later versions of Aserisk require the existence of a cdr.conf file or no CDR
885 // incuding MySQL logging will work (see #3940)
886 //
887 $target = $amp_conf['ASTETCDIR']."/cdr.conf";
888 if (!file_exists($target)) {
889   $output = array();
890   exec("touch $target", $output, $retcode);
891   if ($retcode != 0) {
892     error("Error code $retcode: trying to create empty file $target");
893   }
894 }
895
896 // **** Set reload flag for AMP admin
897 needreload();
898 if (isset($amp_conf["AMPWEBADDRESS"]) && $amp_conf["AMPWEBADDRESS"])
899 {
900   out(sprintf(_("Please update your modules and reload Asterisk by visiting %s"), "http://".$amp_conf["AMPWEBADDRESS"]."/admin"),false);
901 }
902 else
903 {
904   out(_("Please update your modules and reload Asterisk by browsing to your server."),false);
905 }
906   $nt->delete('retrieve_conf', 'FATAL');
907 ?>
Note: See TracBrowser for help on using the browser.