root/freepbx/tags/pre-2.3beta/install_amp

Revision 4083, 37.0 kB (checked in by p_lindheimer, 6 years ago)

#2007: fix version checking to allow Asterisk 1.4 properly

  • Property svn:mime-type set to text/plain
  • 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 # constants
5 define("AMP_CONF", "/etc/amportal.conf");
6 define("ASTERISK_CONF", "/etc/asterisk/asterisk.conf");
7 define("UPGRADE_DIR", dirname(__FILE__)."/upgrades");
8
9 # semi constants
10 $webroot  = "/var/www/html/";
11 $fopwebroot = "";       // if blank, will use $webroot/panel
12 $bin_dir  = "/var/lib/asterisk/bin/";
13 $sbin_dir = "/usr/sbin/";
14 $asterisk_user  = "asteriskuser";
15 $asterisk_pass  = "amp109";
16
17 // WTF is this?
18 $system_config  = "";
19
20
21 // define versions. latest version must be last
22 $versions = array(
23     '1.10.005',
24     '1.10.006',
25     '1.10.007beta1',
26     '1.10.007beta2',
27     '1.10.007',
28     '1.10.007a',
29     '1.10.008beta1',
30     '1.10.008beta2',
31     '1.10.008beta3',
32     '1.10.008',
33     '1.10.009beta1',
34     '1.10.009beta2',
35     '1.10.009',
36     '1.10.010beta1',
37     '1.10.010',
38     '2.0beta1',
39     '2.0beta2',
40     '2.0beta3',
41     '2.0beta4',
42     '2.0beta5',
43     '2.0.0',
44     '2.0.1',
45     '2.1beta1',
46     '2.1beta2',
47     '2.1beta3',
48     '2.1.0',
49     '2.1.1',
50     '2.1.2',
51     '2.1.3',
52     '2.2.0beta1',
53     '2.2.0beta2',
54     '2.2.0beta3',
55     '2.2.0rc1',
56     '2.2.0rc2',
57     '2.2.0rc3',
58     '2.2.0',
59     '2.2.1',
60     '2.2.2',
61     '2.3.0alpha'
62   );
63
64
65 /********************************************************************************************************************/
66
67 function out($text) {
68   echo $text."\n";
69 }
70
71 function outn($text) {
72   echo $text;
73 }
74
75 function error($text) {
76   echo "[ERROR] ".$text."\n";
77 }
78
79 function fatal($text) {
80   echo "[FATAL] ".$text."\n";
81   exit(1);
82 }
83
84 function debug($text) {
85   global $debug;
86  
87   if ($debug) echo "[DEBUG-preDB] ".$text."\n";
88 }
89
90 function showHelp() {
91   out("Optional parameters:");
92   out("  --help, -h, -?           Show this help");
93   out("  --dbhost <ip address>    Use a remote database server");
94   out("  --dbname databasename    Use database name specified, instead of 'asterisk'");
95   out("  --username <user>        Use <user> to connect to db and write config");
96   out("  --password <pass>        Use <pass> to connect to db and write config");
97   out("  --fopwebroot <path>      Web path where fop will be installed");
98   out("  --webroot <path>         Web root where freepbx will be installed");
99   out("  --cgibin <path>          Path where cgi-bin's lives");
100   out("  --bin <path>             Path of asterisk binaries");
101   out("  --sbin <path>            Path of system admin binaries");
102   out("  --asteriskuser <user>    Asterisk Manager username");
103   out("  --asteriskpass <pass>    Asterisk Manager password");
104   out("  --systemconfig <path>    System config files");
105   out("  --debug                  Enable debug output");
106   out("  --dry-run                Don't actually do anything");
107   out("  --force-version <ver>    Force upgrade from version <ver>");
108   out("  --no-files               Just run updates without installing files");
109   out("  --install-moh            Install default music-on-hold files (normally doesn't, unless ");
110   out("                           it's a new installation)");
111   out("  --my-svn-is-correct      Ignore Asterisk version, assume it is correct");
112   out("  --engine <name>          Use the specified PBX Engine ('asterisk', 'asterisk14' or 'openpbx')");
113 }
114
115 function install_parse_amportal_conf($filename) {
116   $file = file($filename);
117   foreach ($file as $line) {
118     if (preg_match("/^\s*([a-zA-Z0-9]+)\s*=\s*(.*)\s*([;#].*)?/",$line,$matches)) {
119       $conf[ $matches[1] ] = $matches[2];
120     }
121   }
122
123   // use same defaults as function.inc.php
124   if ( !isset($conf["AMPDBENGINE"]) || ($conf["AMPDBENGINE"] == "")) {
125     $conf["AMPDBENGINE"] = "mysql";
126   }
127  
128   if ( !isset($conf["AMPDBNAME"]) || ($conf["AMPDBNAME"] == "")) {
129     $conf["AMPDBNAME"] = "asterisk";
130   }
131  
132   if ( !isset($conf["AMPENGINE"]) || ($conf["AMPENGINE"] == "")) {
133     $conf["AMPENGINE"] = "asterisk";
134   }
135
136   return $conf;
137 }
138
139 function install_parse_asterisk_conf($filename) {
140   $file = file($filename);
141   foreach ($file as $line) {
142     if (preg_match("/^\s*([a-zA-Z0-9]+)\s* => \s*(.*)\s*([;#].*)?/",$line,$matches)) {
143       $conf[ $matches[1] ] = $matches[2];
144     }
145   }
146   return $conf;
147 }
148
149 //get the version number
150 function install_getversion() {
151   global $db;
152   $sql = "SELECT value FROM admin WHERE variable = 'version'";
153   $results = $db->getAll($sql);
154   if(DB::IsError($results)) {
155     return false;
156   }
157   return $results[0][0];
158 }
159
160 //set the version number
161 function setversion($version) {
162   global $db;
163   $sql = "UPDATE admin SET value = '".$version."' WHERE variable = 'version'";
164   debug($sql);
165   $result = $db->query($sql);
166   if(DB::IsError($result)) {     
167     die($result->getMessage());
168   }
169 }
170
171 function write_amportal_conf($filename, $conf) {
172   $file = file($filename);
173   // parse through the file
174   foreach (array_keys($file) as $key) {
175     if (preg_match("/^\s*([a-zA-Z0-9]+)\s*=\s*(.*)\s*([;#].*)?/",$file[$key],$matches)) {
176       // this is an option=value line
177       if (isset($conf[ $matches[1] ])) {
178         // rewrite the line, if we have this in $conf
179         $file[$key] = $matches[1]."=".$conf[ $matches[1] ]."\n";
180         // unset it so we know what's new
181         unset($conf[ $matches[1] ]);
182       }
183     }
184   }
185  
186   // add new entries
187   foreach ($conf as $key=>$val) {
188     $file[] = $key."=".$val."\n";
189   }
190  
191   // write the file
192   if (!$fd = fopen($filename, "w")) {
193     fatal("Could not open ".$filename." for writing");
194   }
195   fwrite($fd, implode("",$file));
196   fclose($fd);
197 }
198
199 function ask_overwrite($file1, $file2) {
200   global $check_md5s;
201   do {
202     out($file2." has been changed from the original version.");
203     outn("Overwrite (y=yes/a=all/n=no/d=diff/s=shell/x=exit)? ");
204     $key = fgets(STDIN,1024);
205     switch (strtolower($key[0])) {
206       case "y": return true;
207       case "a": $check_md5s=false; return true;
208       case "n": return false;
209       case "d":
210         out("");
211         // w = ignore whitespace, u = unified
212         passthru("diff -wu ".escapeshellarg($file2)." ".escapeshellarg($file1));
213       break;
214       case "s":
215         if (function_exists("pcntl_fork")) {
216           out("");
217           $shell = (isset($_ENV["SHELL"]) ? $_ENV["SHELL"] : "/bin/bash");
218           out("Dropping to shell. Type 'exit' to return");
219           out("-> Original file:  ".$file2);
220           out("-> New file:       ".$file1);
221          
222           $pid = pcntl_fork();
223           if ($pid == -1) {
224             out("[ERROR] cannot fork");
225           } else if ($pid) {
226             // parent
227             pcntl_waitpid($pid, $status);
228             // we wait till the child exits/dies/whatever
229           } else {
230             pcntl_exec($shell, array(), $_ENV);
231           }
232          
233           out("Returned from shell");
234         } else {
235           out("[ERROR] PHP not built with process control (--enable-pcntl) support: cannot spawn shell");
236         }
237        
238       break;
239       case "x":
240         out("-> Original file:  ".$file2);
241         out("-> New file:       ".$file1);
242         out("Exiting install program.");
243         exit(1);
244       break;
245     }
246     out("");
247   } while(1);
248 }
249
250 function checkDiff($file1, $file2) {
251   // diff, ignore whitespace and be quiet
252   exec("diff -wq ".escapeshellarg($file2)." ".escapeshellarg($file1), $output, $retVal);
253   return ($retVal != 0);
254 }
255
256 function amp_mkdir($directory, $mode = "0755", $recursive = false) {
257   debug("mkdir ".$directory.", ".$mode);
258   $ntmp = sscanf($mode,"%o",$modenum); //assumes all inputs are octal
259   if (version_compare(phpversion(), 5.0) < 0) {
260     // php <5 can't recursively create directories
261     if ($recursive) {
262       $output = false;
263       $return_value = false;
264       exec("mkdir -m ".$mode." -p ".$directory,  $output, $return_value);
265       return ($return_value == 0);
266     } else {
267       return mkdir($directory, $modenum);
268     }
269   } else {
270     return mkdir($directory, $modenum, $recursive);
271   }
272 }
273
274 /** Recursively copy a directory
275  */
276 function recursive_copy($dirsourceparent, $dirdest, &$md5sums, $dirsource = "") {
277   global $dryrun;
278   global $check_md5s;
279   global $amp_conf;
280   global $asterisk_conf;
281   global $install_moh;
282
283   // total # files, # actually copied
284   $num_files = $num_copied = 0;
285  
286   if ($dirsource && ($dirsource[0] != "/")) $dirsource = "/".$dirsource;
287  
288   if (is_dir($dirsourceparent.$dirsource)) $dir_handle = opendir($dirsourceparent.$dirsource);
289  
290   /*
291   echo "dirsourceparent: "; var_dump($dirsourceparent);
292   echo "dirsource: "; var_dump($dirsource);
293   echo "dirdest: "; var_dump($dirdest);
294   */
295  
296   while (isset($dir_handle) && ($file = readdir($dir_handle))) {
297     if (($file!=".") && ($file!="..") && ($file != "CVS") && ($file != ".svn")) {
298       $source = $dirsourceparent.$dirsource."/".$file;
299       $destination =  $dirdest.$dirsource."/".$file;
300      
301       if ($dirsource == "" && $file == "mohmp3" && !$install_moh) {
302         // skip to the next dir
303         continue;
304       }
305
306      
307       // configurable in amportal.conf
308       if (strpos($destination,"htdocs_panel")) {
309         $destination=str_replace("/htdocs_panel",trim($amp_conf["FOPWEBROOT"]),$destination);
310       } else {
311         $destination=str_replace("/htdocs",trim($amp_conf["AMPWEBROOT"]),$destination);
312       }
313       $destination=str_replace("/htdocs_panel",trim($amp_conf["FOPWEBROOT"]),$destination);
314 //      $destination=str_replace("/cgi-bin",trim($amp_conf["AMPCGIBIN"]),$destination);
315       if(strpos($dirsource, 'modules') === false) $destination=str_replace("/bin",trim($amp_conf["AMPBIN"]),$destination);
316       $destination=str_replace("/sbin",trim($amp_conf["AMPSBIN"]),$destination);
317      
318       // the following are configurable in asterisk.conf
319       $destination=str_replace("/astetc",trim($asterisk_conf["astetcdir"]),$destination);
320       $destination=str_replace("/mohmp3",trim($asterisk_conf["astvarlibdir"])."/mohmp3",$destination);
321       $destination=str_replace("/astvarlib",trim($asterisk_conf["astvarlibdir"]),$destination);
322       if(strpos($dirsource, 'modules') === false) $destination=str_replace("/agi-bin",trim($asterisk_conf["astagidir"]),$destination);
323       if(strpos($dirsource, 'modules') === false) $destination=str_replace("/sounds",trim($asterisk_conf["astvarlibdir"])."/sounds",$destination);
324
325       // if this is a directory, ensure destination exists
326       if (is_dir($source)) {
327         if (!file_exists($destination)) {
328           if ((!$dryrun) && ($destination != "")) {
329             amp_mkdir($destination, "0750", true);
330           }
331         }
332       }
333      
334       //var_dump($md5sums);
335       if (!is_dir($source)) {
336         $md5_source = preg_replace("|^/?amp_conf/|", "/", $source);
337
338         if ($check_md5s && file_exists($destination) && isset($md5sums[$md5_source]) && (md5_file($destination) != $md5sums[$md5_source])) {
339           // double check using diff utility (and ignoring whitespace)
340           // This is a somewhat edge case (eg, the file doesn't match
341           // it's md5 sum from the previous version, but no substantial
342           // changes exist compared to the current version), but it
343           // pervents a useless prompt to the user.
344           if (checkDiff($source, $destination)) {
345             $overwrite = ask_overwrite($source, $destination);
346           } else {
347             debug("NOTE: MD5 for ".$destination." was different, but `diff` did not detect any (non-whitespace) changes: overwriting");
348             $overwrite = true;
349           }
350         } else {
351           $overwrite = true;
352         }
353        
354         $num_files++;
355         if ($overwrite) {
356           debug("copy ".$source." -> ".$destination);
357           if (!$dryrun) {
358             copy($source, $destination);
359             $num_copied++;
360           }
361         } else {
362           debug("not overwriting ".$destination);
363         }
364       } else {
365         //echo "recursive_copy($dirsourceparent, $dirdest, $md5sums, $dirsource/$file)";
366         list($tmp_num_files, $tmp_num_copied) = recursive_copy($dirsourceparent, $dirdest, $md5sums, $dirsource."/".$file);
367         $num_files += $tmp_num_files;
368         $num_copied += $tmp_num_copied;
369       }
370     }
371   }
372  
373   if (isset($dir_handle)) closedir($dir_handle);
374  
375   return array($num_files, $num_copied);
376 }
377
378 function read_md5_file($filename) {
379   $md5 = array();
380   if (file_exists($filename)) {
381     foreach (file($filename) as $line) {
382       if (preg_match("/^([a-f0-9]{32})\s+(.*)$/", $line, $matches)) {
383         $md5[ "/".$matches[2] ] = $matches[1];
384       }
385     }
386   }
387   return $md5;
388 }
389
390 /** Include a .php file
391  * This is a function just to keep a seperate context
392  */
393 function run_included($file) {
394   global $db;
395   global $amp_conf;
396  
397   include($file);
398 }
399
400
401 function install_sqlupdate( $version, $file )
402 {
403   global $db;
404   global $dryrun;
405
406   out("-> Running SQL script ".UPGRADE_DIR."/".$version."/".$file);
407   // run sql script
408   $fd = fopen(UPGRADE_DIR."/".$version."/".$file, "r");
409   $data = "";
410   while (!feof($fd)) {
411     $data .= fread($fd, 1024);
412   }
413   fclose($fd);
414
415   preg_match_all("/((SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER).*);\s*\n/Us", $data, $matches);
416  
417   foreach ($matches[1] as $sql) {
418     debug($sql);
419     if (!$dryrun) {
420       $result = $db->query($sql);
421       if(DB::IsError($result)) {     
422         fatal($result->getDebugInfo()."\" while running ".$file."\n");
423       }
424     }
425   }
426 }
427
428 /** Install a particular version
429  */
430 function install_upgrade($version) {
431   global $db;
432   global $dryrun;
433   global $amp_conf;
434  
435   $db_engine = $amp_conf["AMPDBENGINE"];
436  
437   if (is_dir(UPGRADE_DIR."/".$version)) {
438     // sql scripts first
439     $dir = opendir(UPGRADE_DIR."/".$version);
440     while ($file = readdir($dir)) {
441       if (($file[0] != ".") && is_file(UPGRADE_DIR."/".$version."/".$file)) {
442         if ( (strtolower(substr($file,-4)) == ".sqlite") && ($db_engine == "sqlite") ) {
443           install_sqlupdate( $version, $file );
444         }
445         elseif ((strtolower(substr($file,-4)) == ".sql") &&
446             ( ($db_engine  == "mysql")  ||  ($db_engine  == "pgsql") || ($db_engine == "sqlite3") ) ) {
447           install_sqlupdate( $version, $file );
448         }
449       }
450     }
451
452                 // now non sql scripts
453                 $dir = opendir(UPGRADE_DIR."/".$version);
454                 while ($file = readdir($dir)) {
455                         if (($file[0] != ".") && is_file(UPGRADE_DIR."/".$version."/".$file)) {
456                                 if ((strtolower(substr($file,-4)) == ".sql") || (strtolower(substr($file,-7)) == ".sqlite")) {
457                                         // sql scripts were dealt with first
458                                 } else if (strtolower(substr($file,-4)) == ".php") {
459                                         out("-> Running PHP script ".UPGRADE_DIR."/".$version."/".$file);
460                                         if (!$dryrun) {
461                                                 run_included(UPGRADE_DIR."/".$version."/".$file);
462                                         }
463
464                                 } else if (is_executable(UPGRADE_DIR."/".$version."/".$file)) {
465                                         out("-> Executing ".UPGRADE_DIR."/".$version."/".$file);
466                                         if (!$dryrun) {
467                                                 exec(UPGRADE_DIR."/".$version."/".$file);
468                                         }
469                                 } else {
470                                         error("-> Don't know what to do with ".UPGRADE_DIR."/".$version."/".$file);
471                                 }
472                         }
473                 }
474
475   }
476 }
477
478 /** Set base of core and framework to the main release and make sure enabled
479  *
480  * TODO: CHANGE THIS, SET BASE VERSION BASED ON WHAT IS PACKAGED SINCE SVN INSTALLS WILL BE DIFFERENT
481  */
482 function set_base_version() {
483   global $dryrun;
484
485   outn("Checking framework.. ");
486   if (!$dryrun) {
487     out(set_module_version('framework'));
488   } else {
489     out("Dry Run Not Updated");
490   }
491
492   outn("Checking core.. ");
493   if (!$dryrun) {
494     out(set_module_version('core'));
495   } else {
496     out("Dry Run Not Updated");
497   }
498
499 }
500
501 /** Set the module version number to the packaged version and enable
502  *  module must require not install.php or install.sql script
503  *  this is primarily to package core and framework with freepbx tarballs
504  *
505  */
506 function set_module_version($module) {
507   global $db;
508
509   $module_dir = dirname(__FILE__)."/amp_conf/htdocs/admin/modules/";
510   $file_path = $module_dir.$module."/module.xml";
511   if (file_exists($file_path)) {
512     // TODO: this is bad, there are other version tags (depends on) but this
513     //       is equivalnet to what publish.pl does, so it expects this to be
514     //       at the top.
515     //
516     $module_xml = file_get_contents($file_path);
517     if (preg_match('/<version>(.+)<\/version>/', $module_xml, $matches)) {
518       $version = $matches[1];
519     } else {
520       die("ERROR: $file_path found but no verison information");
521     }
522   } else {
523     return  "not packaged, no updating needed";
524   }
525
526   // If we didn't return above, then we found the package as part of the install
527   // tarball and want to update the version info since this might be overwriting
528   // and existing install that has a newever version.
529   //
530   $sql = "SELECT version FROM modules WHERE modulename = '$module'";
531   $result = $db->getCol($sql);
532   if(DB::IsError($result)) {     
533     die($result->getMessage());
534   }
535   $sql = "";
536   if (count($result) == 0) {
537     $sql = "INSERT INTO modules (modulename, version, enabled) VALUES ('$module', '$version', 1)";
538   } else if ($result[0] != $version) {
539     $sql = "UPDATE modules SET version = '$version', enabled = 1 WHERE modulename = '$module'";
540   }
541   if ($sql) {
542     debug($sql);
543     $result = $db->query($sql);
544     if(DB::IsError($result)) {     
545       die($result->getMessage());
546     }
547   }
548   return "updated to $version";
549 }
550
551 /** Invoke upgrades
552  * @param $versions array The version upgrade scripts to run
553  */
554 function run_upgrade($versions) {
555   global $dryrun;
556  
557   foreach ($versions as $version) {
558     out("Upgrading to ".$version."..");
559     install_upgrade($version);
560     if (!$dryrun) {
561       setversion($version);
562     }
563     out("Upgrading to ".$version."..OK");
564   }
565 }
566
567 /** Write AMP-generated configuration files
568  */
569 function generate_configs() {
570   global $amp_conf;
571   global $dryrun;
572   global $debug;
573  
574   out("Generating Configurations.conf..");
575   if (!$dryrun)
576     // added --run-install to make it work like it has been working since retrieve_conf changed to not run module install scripts by default
577     passthru("su - asterisk -c \"".trim($amp_conf["AMPBIN"])."/retrieve_conf --run-install ".($debug ? ' --debug' : '').'"');
578 }
579
580
581 /** Set reload flag for AMP admin
582  */
583 function install_needreload() {
584   global $db;
585   $sql = "UPDATE admin SET value = 'true' WHERE variable = 'need_reload'";
586   $result = $db->query($sql);
587   if(DB::IsError($result)) {     
588     die($result->getMessage());
589   }
590 }
591
592
593 /** Collect AMP settings
594  */
595 function collect_settings($filename, $dbhost = '', $dbuser = '', $dbpass = '', $dbname = 'asterisk') {
596   out("Creating new $filename");
597  
598   outn("Enter your USERNAME to connect to the '$dbname' database:\n [".($dbuser ? $dbuser : $asterisk_user) . "] ");
599   $key = trim(fgets(STDIN,1024));
600   if (preg_match('/^$/',$key))
601     $amp_conf["AMPDBUSER"] = ($dbuser ? $dbuser : "asteriskuser");
602   else
603     $amp_conf["AMPDBUSER"] = $key;
604  
605   outn("Enter your PASSWORD to connect to the '$dbname' database:\n [".($dbpass ? $dbpass : $asterisk_pass)."] ");
606   $key = trim(fgets(STDIN,1024));
607   if (preg_match('/^$/',$key))
608     $amp_conf["AMPDBPASS"] = ($dbpass ? $dbpass : $asterisk_pas);
609   else
610     $amp_conf["AMPDBPASS"] = $key;
611  
612   outn("Enter the hostname of the '$dbname' database:\n [".($dbhost ? $dbhost : "localhost")."] ");
613   $key = trim(fgets(STDIN,1024));
614   if (preg_match('/^$/',$key))
615     $amp_conf["AMPDBHOST"] = ($dbhost ? $dbhost : "localhost");
616   else
617     $amp_conf["AMPDBHOST"] = $key;
618  
619   outn("Enter a USERNAME to connect to the Asterisk Manager interface:\n [admin] ");
620   $key = trim(fgets(STDIN,1024));
621   if (preg_match('/^$/',$key)) $amp_conf["AMPMGRUSER"] = "admin";
622   else $amp_conf["AMPMGRUSER"] = $key;
623  
624   outn("Enter a PASSWORD to connect to the Asterisk Manager interface:\n [amp111] ");
625   $key = trim(fgets(STDIN,1024));
626   if (preg_match('/^$/',$key)) $amp_conf["AMPMGRPASS"] = "amp111";
627   else $amp_conf["AMPMGRPASS"] = $key;
628  
629   do {
630     out("Enter the path to use for your AMP web root:\n [$webroot] ");
631     $key = trim(fgets(STDIN,1024));
632     if (preg_match('/^$/',$key))
633       $amp_conf["AMPWEBROOT"] = "$webroot";
634     else
635       $amp_conf["AMPWEBROOT"] = rtrim($key,'/');
636
637     if (is_dir($amp_conf["AMPWEBROOT"])) {
638       break;
639     } else if (amp_mkdir($amp_conf["AMPWEBROOT"],"0755",true)){
640       out("Created ".$amp_conf["AMPWEBROOT"]);
641       break;
642     } else {
643       fatal("Cannot create ".$amp_conf["AMPWEBROOT"]."!");
644     }
645   } while(1);
646  
647   // Really no need to ask, is there.
648   if (is_empty($fopwebroot))
649     $amp_conf["FOPWEBROOT"] = $amp_conf["AMPWEBROOT"];
650   else
651     $amp_conf["FOPWEBROOT"] = $fopwebroot;
652  
653   outn("Enter the IP ADDRESS or hostname used to access the AMP web-admin:\n [xx.xx.xx.xx] ");
654   $key = trim(fgets(STDIN,1024));
655   if (preg_match('/^$/',$key)) $amp_conf["AMPWEBADDRESS"] = "xx.xx.xx.xx";
656   else $amp_conf["AMPWEBADDRESS"] = $key;
657  
658   outn("Enter a PASSWORD to perform call transfers with the Flash Operator Panel:\n [passw0rd] ");
659   $key = trim(fgets(STDIN,1024));
660   if (preg_match('/^$/',$key)) $amp_conf["FOPPASSWORD"] = "passw0rd";
661   else $amp_conf["FOPPASSWORD"] = $key;
662  
663   outn("Use simple Extensions [extensions] admin or separate Devices and Users [deviceanduser]?\n [extensions] ");
664   $key = trim(fgets(STDIN,1024));
665   if (preg_match('/^$/',$key)) $amp_conf["AMPEXTENSIONS"] = "extensions";
666   else $amp_conf["AMPEXTENSIONS"] = $key;
667  
668   do {
669     out("Enter directory in which to store AMP executable scripts:\n [$ampbin_dir] ");
670     $key = trim(fgets(STDIN,1024));
671     if (preg_match('/^$/',$key))
672       $amp_conf["AMPBIN"] = $ampbin_di;
673     else
674       $amp_conf["AMPBIN"] = rtrim($key,'/');
675
676     if (is_dir($amp_conf["AMPBIN"])) {
677       break;
678     } else if (amp_mkdir($amp_conf["AMPBIN"],"0755",true)){
679       out("Created ".$amp_conf["AMPBIN"]);
680       break;
681     } else {
682       fatal("Cannot create ".$amp_conf["AMPBIN"]."!");
683     }
684   } while(1);
685  
686   do {
687     out("Enter directory in which to store super-user scripts:\n [$ampsbin_dir] ");
688     $key = trim(fgets(STDIN,1024));
689     if (preg_match('/^$/',$key))
690       $amp_conf["AMPSBIN"] = "$ampsbin_dir";
691     else
692       $amp_conf["AMPSBIN"] = rtrim($key,'/');
693
694     if (is_dir($amp_conf["AMPSBIN"])) {
695       break;
696     } else if (amp_mkdir($amp_conf["AMPSBIN"],"0755",true)){
697       out("Created ".$amp_conf["AMPSBIN"]);
698       break;
699     } else {
700       fatal("Cannot create ".$amp_conf["AMPSBIN"]."!");
701     }
702   } while(1);
703  
704   // write amportal.conf
705   write_amportal_conf($filename, $amp_conf);
706   outn(AMP_CONF." written");
707 }
708
709 /********************************************************************************************************************/
710
711 // **** Make sure we have STDIN etc
712
713 // from  ben-php dot net at efros dot com   at  php.net/install.unix.commandline
714 if (version_compare(phpversion(),'4.3.0','<') || !defined("STDIN")) {
715   define('STDIN',fopen("php://stdin","r"));
716   define('STDOUT',fopen("php://stdout","r"));
717   define('STDERR',fopen("php://stderr","r"));
718   register_shutdown_function( create_function( '' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;' ) );
719 }
720    
721 // **** Make sure we have PEAR's DB.php, and include it
722
723 outn("Checking for PEAR DB..");
724 if (! @ include('DB.php')) {
725   out("FAILED");
726   fatal("PEAR must be installed (requires DB.php). Include path: ".ini_get("include_path"));
727 }
728 out("OK");
729
730 // **** Make sure we have PEAR's GetOpts.php, and include it
731
732 outn("Checking for PEAR Console::Getopt..");
733 if (! @ include("Console/Getopt.php")) {
734   out("FAILED");
735   fatal("PEAR must be installed (requires Console/Getopt.php). Include path: ".ini_get("include_path"));
736 }
737 out("OK");
738
739 // **** Parse out command-line options
740 $shortopts = "h?u:p:";
741 $longopts = array("help","debug","dry-run","username=","password=","force-version=","dbhost=","no-files","dbname=","my-svn-is-correct","engine=","install-moh");
742
743 $args = Console_Getopt::getopt(Console_Getopt::readPHPArgv(), $shortopts, $longopts);
744 if (is_object($args)) {
745   // assume it's PEAR_ERROR
746   out($args->message);
747   exit(255);
748 }
749
750 $debug = false;
751 $dryrun = false;
752 $install_files = true;
753 $override_astvers = false;
754
755 $install_moh = false;
756
757 //initialize variables to avoid php notices
758 $dbhost = null;
759 $dbname = null;
760 $new_username = null;
761 $new_password = null;
762
763 foreach ($args[0] as $arg) {
764   switch ($arg[0]) {
765     case "--help": case "h": case "?":
766       showHelp();
767       exit(10);
768     break;
769     case "--dry-run":
770       out("Dry-run only, nothing will be changed");
771       $dryrun = true;
772     break;
773     case "--debug":
774       $debug = true;
775       debug("Debug mode enabled");
776     break;
777     case "--username": case "u":
778       out("Using username: ".$arg[1]);
779       $new_username = $arg[1];
780     break;
781     case "--password": case "p":
782       out("Using password: ".str_repeat("*",strlen($arg[1])));
783       $new_password = $arg[1];
784     break;
785     case "--force-version":
786       $version = $arg[1];
787       out("Forcing upgrade from version ".$version);
788     break;
789     case "--dbhost":
790       $dbhost = $arg[1];
791       out("Using remote database server at ".$dbhost);
792     break;
793     case "--dbname":
794       $dbname = $arg[1];
795       out("Using database ".$dbname);
796     break;
797     case "--no-files":
798       $install_files = false;
799       out("Running upgrade only, without installing files.");
800     break;
801     case "--my-svn-is-correct":
802       $override_astvers = true;
803     break;
804     case "--engine":
805       if ($arg[1] != 'asterisk' && $arg[1] != 'asterisk14' && $arg[1] != 'openpbx') {
806         fatal('Currently only "asterisk", "asterisk14" or "openpbx" are supported as a PBX engine');
807       }
808       $pbx_engine = $arg[1];
809     break;
810     case "--install-moh":
811       $install_moh = true;
812     break;
813     case "--fopwebroot":
814       $fopwebroot = $arg[1];
815       out("Using fop at ".$fopwebroot);
816     break;
817     case "--webroot":
818       $webroot = $arg[1];
819       out("Using Webroot at ".$webroot);
820     break;
821     case "--cgibin":
822       $cgibin = $arg[1];
823       out("Using CGI-BIN at ".$cgibin);
824     break;
825     case "--bin":
826       $ampbin_dir = $arg[1];
827       out("Using bin at ".$ampbin_dir);
828     break;
829     case "--sbin":
830       $ampsbin_dir = $arg[1];
831       out("Using sbin ar ".$ampsbin_dir);
832     break;
833     case "--asteriskuser":
834       $asterisk_user = $arg[1];
835       out("Using Asterisk user ".$asterisk_user);
836     break;
837     case "--asteriskpass":
838       $asterisk_pass = $arg[1];
839       out("Using asteriskpass ".str_repeat("*",strlen($arg[1])));
840     break;
841
842 /*    do we need this ?
843     case "--systemconfig":
844       $systemconfig = $arg[1];
845       out("Using system config at ". $systemconfig);
846     break;
847 */
848
849   }
850 }
851
852
853 // **** Look for user = root
854
855 outn("Checking user..");
856 //$current_user=(isset($_ENV["USER"]) ? $_ENV["USER"] : exec('whoami',$output));
857 $euid = (posix_getpwuid(posix_geteuid()));
858 $current_user = $euid['name'];
859 if ($current_user != "root"){
860   out("FAILED");
861   fatal($argv[0]." must be run as root");
862 }
863 out("OK");
864
865
866 // **** Check for amportal.conf, create if necessary
867
868 outn("Checking for ".AMP_CONF."..");
869 if (!file_exists(AMP_CONF)) {
870   out(AMP_CONF." does not exist, copying default");
871   copy("amportal.conf", AMP_CONF);
872
873   // this file contains password and should not be a+r
874   // this addresses http://freepbx.org/trac/ticket/1878
875   chown(AMP_CONF, "asterisk");
876   chgrp(AMP_CONF, "asterisk");
877   chmod(AMP_CONF, 0640);
878
879   collect_settings(AMP_CONF, $dbhost, $new_username, $new_password, 'asterisk');
880
881   out("Assuming new install, --install-moh added to command line");
882   $install_moh = true;
883 }
884 out("OK");
885
886 // **** read amportal.conf
887
888 outn("Reading ".AMP_CONF."..");
889 $amp_conf = install_parse_amportal_conf(AMP_CONF);
890 if (count($amp_conf) == 0) {
891   fatal("FAILED");
892 }
893 out("OK");
894
895 // Ensure our "critical" variables are set.  We absolutely need these to copy in files.
896
897 if (!array_key_exists("AMPWEBROOT",$amp_conf)) {
898   out("Adding AMPWEBROOT option to amportal.conf - using AMP default");
899   $amp_conf["AMPWEBROOT"] = "/var/www/html";
900 }
901
902 if (!array_key_exists("FOPWEBROOT",$amp_conf)) {
903   out("Adding FOPWEBROOT option to amportal.conf - using AMP default");
904   $amp_conf["FOPWEBROOT"] = $amp_conf["AMPWEBROOT"]."/panel";
905 }
906
907 if (!array_key_exists("AMPBIN",$amp_conf)) {
908   out("Adding AMPBIN option to amportal.conf - using AMP default");
909   $amp_conf["AMPBIN"] = "/var/lib/asterisk/bin";
910 }
911
912 if (!array_key_exists("AMPSBIN",$amp_conf)) {
913   out("Adding AMPSBIN option to amportal.conf - using AMP default");
914   $amp_conf["AMPSBIN"] = "/usr/sbin";
915 }
916
917 if (!array_key_exists("AMPDBENGINE",$amp_conf)) {
918   out("Adding AMPDBENGINE option to amportal.conf - using AMP default");
919   $amp_conf["AMPDBENGINE"] = "mysql";
920 }
921 if (!array_key_exists("AMPDBNAME",$amp_conf)) {
922   out("Adding AMPDBNAME option to amportal.conf - using AMP default");
923   $amp_conf["AMPDBNAME"] = "asterisk";
924 }
925
926 if (isset($new_username)) {
927   $amp_conf["AMPDBUSER"] = $new_username;
928 }
929
930 if (isset($new_password)) {
931   $amp_conf["AMPDBPASS"] = $new_password;
932 }
933
934 if (isset($dbhost)) {
935   $amp_conf["AMPDBHOST"] = $dbhost;
936 }
937
938 if (isset($dbname)) {
939   $amp_conf["AMPDBNAME"] = $dbname;
940 }
941  
942 // write amportal.conf
943 write_amportal_conf(AMP_CONF, $amp_conf);
944
945 // **** Check for amportal.conf, create if necessary
946
947 outn("Checking for ".ASTERISK_CONF."..");
948 if (!file_exists(ASTERISK_CONF)) {
949   out(ASTERISK_CONF." does not exist, copying default");
950   copy("asterisk.conf", ASTERISK_CONF);
951 }
952 out("OK");
953
954 // **** read asterisk.conf
955
956 outn("Reading ".ASTERISK_CONF."..");
957 $asterisk_conf = install_parse_asterisk_conf(ASTERISK_CONF);
958 if (count($asterisk_conf) == 0) {
959   fatal("FAILED. Have you installed Asterisk?");
960 }
961 out("OK");
962
963 /* deprecated on freepbx 2.2, from now pages need to read this information
964    from $asterik_conf and not $amp_conf.
965    
966    this code will stay in 2.2, but in 2.3 it will be gone. developers - please
967    update your code
968  */
969 if (isset($asterisk_conf['astetcdir'])) { $amp_conf['ASTETCDIR'] = $asterisk_conf['astetcdir']; }
970 if (isset($asterisk_conf['astmoddir'])) { $amp_conf['ASTMODDIR'] = $asterisk_conf['astmoddir']; }
971 if (isset($asterisk_conf['astvarlibdir'])) { $amp_conf['ASTVARLIBDIR'] = $asterisk_conf['astvarlibdir']; }
972 if (isset($asterisk_conf['astagidir'])) { $amp_conf['ASTAGIDIR'] = $asterisk_conf['astagidir']; }
973 if (isset($asterisk_conf['astspooldir'])) { $amp_conf['ASTSPOOLDIR'] = $asterisk_conf['astspooldir']; }
974 if (isset($asterisk_conf['astrundir'])) { $amp_conf['ASTRUNDIR'] = $asterisk_conf['astrundir']; }
975 if (isset($asterisk_conf['astlogdir'])) { $amp_conf['ASTLOGDIR'] = $asterisk_conf['astlogdir']; }
976
977 if (!isset($pbx_engine)) { $pbx_engine='asterisk'; }
978 out("Using $pbx_engine as PBX Engine");
979 $amp_conf["AMPENGINE"]=$pbx_engine;
980
981 write_amportal_conf(AMP_CONF, $amp_conf);
982
983
984 // **** Write asterisk version to ASTETCDIR/version
985
986 $tmpoutput = '';
987 $tmpout = exec("asterisk -V", $tmpoutput, $exitcode);
988 if ($exitcode != 0) {
989   fatal("Error executing asterisk: be sure Asterisk is installed and in the path");
990 }
991 if (!$fd = fopen($amp_conf['ASTETCDIR'].'/version','w')) {
992   fatal('Cannot open '.$amp_conf['ASTETCDIR'].'/version for writing');
993 }
994 fwrite($fd, $tmpout);
995 fclose($fd);
996 // change to read-only
997 chmod($amp_conf['ASTETCDIR'].'/version',0444);
998
999
1000 // normally this would be the contents of ASTETCDIR/version, but this is for simplicity, as we just read it above
1001 $verinfo = $tmpout;
1002
1003 // **** Check asterisk verison
1004 //  Set the 'engine' to be 'asterisk14' if using asterisk 1.4, otherwise
1005 //  'asterisk'
1006 outn("Checking for Asterisk version..");
1007 if ((preg_match('/^Asterisk (\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches)) ||
1008     (preg_match('/^Asterisk SVN-(\d+(\.\d+)*)(-?(.*))$/', $verinfo, $matches))) {
1009
1010   if (version_compare($matches[1], "1.2") < 0) {
1011     fatal("Asterisk 1.2 or 1.4 is required for this version of freePBX. Detected version is: ".$matches[1]);
1012   }
1013   if (version_compare($matches[1], "1.5", "ge")) {
1014     fatal("Asterisk 1.2 or 1.4 is required for this version of freePBX. Detected version is: ".$matches[1]);
1015   }
1016 } elseif (preg_match('/^Asterisk SVN.+/', $verinfo)) {
1017   out("FAIL");
1018   out("*** WARNING ***");
1019   out("You are not using a released version of Asterisk. We are unable to verify");
1020   out("that your Asterisk version is compatible with FreePBX. Whilst this probably");
1021   out("won't cause any problems, YOU NEED TO BE CERTAIN that it is compatible");
1022   out("with at least the released Asterisk version 1.2" );
1023   if ($override_astvers==false) {
1024     out("If you are SURE that this is compatible, you can re-run ".$argv[0]." with");
1025     out("the parameter --my-svn-is-correct");
1026     exit;
1027   } else {
1028     out("--my-svn-is-correct specified, continuing");
1029   }
1030 } else {
1031   fatal("Could not determine asterisk version (got: \"".$verinfo."\" please report this)");
1032 }
1033
1034 // **** Make sure selinux isn't enabled
1035
1036 outn("Checking for selinux..");
1037 $tmpoutput = '';
1038 $tmpout = exec("selinuxenabled 2>&1", $tmpoutput, $sereturn);
1039 if ($sereturn == 0) {
1040   fatal("selinux is ENABLED. This is not supported. Please disable selinux before using freePBX");
1041 }
1042 out("OK");
1043
1044 // **** Connect to database
1045
1046 outn("Connecting to database..");
1047
1048 $db_user = $amp_conf["AMPDBUSER"];
1049 $db_pass = $amp_conf["AMPDBPASS"];
1050 $db_host = $amp_conf["AMPDBHOST"];
1051 $db_engine = $amp_conf["AMPDBENGINE"];
1052 $db_name = $amp_conf["AMPDBNAME"];
1053
1054 // we still support older configurations,  and fall back
1055 // into mysql when no other engine is defined
1056 if ($db_engine == "")
1057 {
1058   $db_engine = "mysql";
1059 }
1060  
1061 switch ($db_engine)
1062 {
1063   case "pgsql":
1064   case "mysql":
1065     // datasource in in this style: dbengine://username:password@host/database
1066     if (!function_exists($db_engine.'_connect')) {
1067       out("FAILED");
1068       fatal($db_engine." PHP libraries not installed");
1069     }
1070  
1071     $datasource = $db_engine.'://'.$db_user.':'.$db_pass.'@'.$db_host.'/'.$db_name;
1072     $db = DB::connect($datasource); // attempt connection
1073     break;
1074  
1075   case "sqlite":
1076     if (! @ include('DB/sqlite.php'))
1077     {
1078       out("FAILED");
1079       fatal( "Your PHP installation lacks SQLite support" );
1080     }
1081  
1082     if (!isset($amp_conf["AMPDBFILE"]))
1083       die("You must setup properly AMPDBFILE in ".AMP_CONF);
1084  
1085     if (isset($amp_conf["AMPDBFILE"]) == "")
1086       die("AMPDBFILE in ".AMP_CONF." cannot be blank");
1087  
1088     $DSN = array (
1089       "database" => $amp_conf["AMPDBFILE"],
1090       "mode" => 0666
1091     );
1092  
1093     $db = new DB_sqlite();
1094     $db->connect( $DSN );
1095     break;
1096  
1097   case "sqlite3":
1098     if (!isset($amp_conf["AMPDBFILE"]))
1099       die("You must setup properly AMPDBFILE in /etc/amportal.conf");
1100      
1101     if (isset($amp_conf["AMPDBFILE"]) == "")
1102       die("AMPDBFILE in /etc/amportal.conf cannot be blank");
1103
1104     require_once('DB/sqlite3.php');
1105     $datasource = "sqlite3:///" . $amp_conf["AMPDBFILE"] . "?mode=0666";
1106     $db = DB::connect($datasource);
1107     break;
1108
1109   default:
1110     die( "Unknown SQL engine: [$db_engine]");
1111 }
1112
1113 if(DB::isError($db)) {
1114   out("FAILED");
1115   debug($db->userinfo);
1116   out("Try running ".$argv[0]." --username=user --password=pass  (using your own user and pass)");
1117   fatal("Cannot connect to database");
1118  
1119 }
1120 out("OK");
1121
1122
1123 // **** Read DB for version info
1124
1125 if (!isset($version)) {
1126   outn("Checking current version of AMP..");
1127   $version = install_getversion();
1128   if (!$version) {
1129     out("no version information");
1130     out("Assuming new installation");
1131   } else {
1132     out($version);
1133   }
1134 }
1135
1136
1137 // **** Copy files
1138
1139 if ($install_files)
1140 {
1141   outn("Installing new freePBX files..");
1142   $check_md5s=true;
1143   $md5sums = read_md5_file(UPGRADE_DIR."/".$version.".md5");
1144   list($num_files, $num_copied) = recursive_copy("amp_conf", "", $md5sums);
1145   if (!is_file("/etc/asterisk/voicemail.conf")) copy("/etc/asterisk/voicemail.conf.template","/etc/asterisk/voicemail.conf");
1146   if (!is_dir("/var/spool/asterisk/voicemail/device")) amp_mkdir("/var/spool/asterisk/voicemail/device", "0755", true);
1147   out("OK (".$num_copied." files copied, ".($num_files-$num_copied)." skipped)");
1148 }
1149
1150 // **** Apply amportal.conf configuration to files
1151 debug("Running ".dirname(__FILE__)."/apply_conf.sh");
1152 outn("Configuring install for your environment..");
1153 if (!$dryrun) {
1154   if (file_exists($amp_conf["AMPSBIN"]."/amportal"))
1155     exec("chmod u+x ".$amp_conf["AMPSBIN"]."/amportal");
1156   exec(dirname(__FILE__)."/apply_conf.sh");
1157 }
1158 out("OK");
1159
1160 // **** Create spool directories for monitor and fax
1161 if (!is_dir($asterisk_conf["astspooldir"]."/monitor"))
1162   amp_mkdir($asterisk_conf["astspooldir"]."/monitor","0766",true);
1163 if (!is_dir($asterisk_conf["astspooldir"]."/fax"))
1164   amp_mkdir($asterisk_conf["astspooldir"]."/fax","0766",true);
1165
1166
1167 // **** Set permissions all files
1168
1169 if ($install_files)
1170 {
1171   outn("Setting permissions on files..");
1172   if (!$dryrun) {
1173     exec($amp_conf["AMPSBIN"]."/amportal chown");
1174   }
1175   out("OK");
1176 }
1177
1178
1179 // **** Read upgrades/ directory
1180
1181 outn("Checking for upgrades..");
1182
1183 // read it from ugprades/ unless $version has already been defined
1184 if (!isset($versions)) {
1185   $versions = array();
1186   $dir = opendir(UPGRADE_DIR);
1187   while ($file = readdir($dir)) {
1188     if (($file[0] != ".") && is_dir(UPGRADE_DIR."/".$file)) {
1189       $versions[] = $file;
1190     }
1191   }
1192   closedir($dir);
1193
1194   // callback to use php's version_compare() to sort 
1195   usort($versions, "version_compare");
1196 }
1197
1198 if (false !== ($pos = array_search($version, $versions))) {
1199   $upgrades = array_slice($versions, $pos+1);
1200   out(count($upgrades)." found");
1201  
1202   run_upgrade($upgrades);
1203
1204   /* Set the base version of key modules, currenlty core and framework, to the
1205    * Version packaged with this tarball, if any. The expectation is that the
1206    * packaging scripts will make these module version numbers the same as the
1207    * release plus a '.0' which can be incremented for bug fixes delivered through
1208    * the online system between main releases.
1209    *
1210    */
1211
1212   /*
1213    * COMMENT OUT UNTIL READY
1214   set_base_version();
1215   */
1216
1217 } else {
1218   out("Current version not found");
1219 }
1220
1221
1222 // **** Generate AMP configs
1223 out("Generating AMP configs..");
1224 generate_configs();
1225 out("Generating AMP configs..OK");
1226
1227 // **** Bounce FOP
1228 outn("Restarting Flash Operator Panel..");
1229 exec('su - asterisk -c "'.$amp_conf["AMPWEBROOT"].'/admin/bounce_op.sh"');
1230 out("OK");
1231
1232 $version = install_getversion();
1233 $filename = $amp_conf["AMPWEBROOT"]."/admin/version.txt";
1234 if (!$fd = fopen($filename, "w")) {
1235   fatal("Could not open ".$filename." for writing");
1236 }
1237 fwrite($fd, $version);
1238 fclose($fd);
1239
1240
1241
1242 // **** Set reload flag for AMP admin
1243 install_needreload();
1244
1245 if ($amp_conf["AMPWEBADDRESS"])
1246 {
1247   out("Please update your modules and reload Asterisk by visiting http://".$amp_conf["AMPWEBADDRESS"]."/admin");
1248 }
1249 else
1250 {
1251   out("Please update your modules and reload Asterisk by browsing to your server.");
1252 }
1253
1254 out("");
1255 out("*************************************************************************");
1256 out("* Note: It's possible that if you click the red 'Update Now' bar BEFORE *");
1257 out("* updating your modules, your machine will start dropping calls. Ensure *");
1258 out("* that all modules are up to date BEFORE YOU CLICK THE RED BAR. As long *");
1259 out("* as this is observed, your machine will be fully functional whilst the *");
1260 out("* upgrade is in progress.                                               *");
1261 out("*************************************************************************");
1262 ?>
Note: See TracBrowser for help on using the browser.