diff --git a/install/scripts/switch-server-ip.php b/install/scripts/switch-server-ip.php new file mode 100644 index 00000000..506cca9f --- /dev/null +++ b/install/scripts/switch-server-ip.php @@ -0,0 +1,412 @@ +#!/usr/bin/php + (2016-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron + * + */ + +// give control to command line handler +try { + CmdLineHandler::processParameters($argc, $argv); +} catch (Exception $e) { + CmdLineHandler::printerr($e->getMessage()); +} + +class CmdLineHandler +{ + + /** + * internal variable for passed arguments + * + * @var array + */ + private static $args = null; + + /** + * Action object read from commandline/config + * + * @var Action + */ + private $_action = null; + + /** + * list of valid parameters/switches + */ + public static $switches = array( + /* 'd', // debug / output information for everything */ + 'h' + ); + // same as --help + public static $params = array( + 'switch', + 'list', + 'froxlor-dir', + 'help' + ); + + /** + * Returns a CmdLineHandler object with given + * arguments from command line + * + * @param int $argc + * @param array $argv + * + * @return CmdLineHandler + */ + public static function processParameters($argc, $argv) + { + return new CmdLineHandler($argc, $argv); + } + + /** + * returns the Action object generated in + * the class constructor + * + * @return Action + */ + public function getAction() + { + return $this->_action; + } + + /** + * class constructor, validates the command line parameters + * and sets the Action-object if valid + * + * @param int $argc + * @param string[] $argv + * + * @return null + * @throws Exception + */ + private function __construct($argc, $argv) + { + self::$args = $this->_parseArgs($argv); + $this->_action = $this->_createAction(); + } + + /** + * Parses the arguments given via the command line; + * three types are supported: + * 1. + * --parm1 or --parm2=value + * 2. -xyz (multiple switches in one) or -a=value + * 3. parm1 parm2 + * + * The 1. will be mapped as + * ["parm1"] => true, ["parm2"] => "value" + * The 2. as + * ["x"] => true, ["y"] => true, ["z"] => true, ["a"] => "value" + * And the 3. as + * [0] => "parm1", [1] => "parm2" + * + * @param array $argv + * + * @return array + */ + private function _parseArgs($argv) + { + array_shift($argv); + $o = array(); + foreach ($argv as $a) { + if (substr($a, 0, 2) == '--') { + $eq = strpos($a, '='); + if ($eq !== false) { + $o[substr($a, 2, $eq - 2)] = substr($a, $eq + 1); + } else { + $k = substr($a, 2); + if (! isset($o[$k])) { + $o[$k] = true; + } + } + } else + if (substr($a, 0, 1) == '-') { + if (substr($a, 2, 1) == '=') { + $o[substr($a, 1, 1)] = substr($a, 3); + } else { + foreach (str_split(substr($a, 1)) as $k) { + if (! isset($o[$k])) { + $o[$k] = true; + } + } + } + } else { + $o[] = $a; + } + } + return $o; + } + + /** + * Creates an Action-Object for the Action-Handler + * + * @return Action + * @throws Exception + */ + private function _createAction() + { + + // Test for help-switch + if (empty(self::$args) || array_key_exists("help", self::$args) || array_key_exists("h", self::$args)) { + self::printHelp(); + // end of execution + } + // check if no unknown parameters are present + foreach (self::$args as $arg => $value) { + + if (is_numeric($arg)) { + throw new Exception("Unknown parameter '" . $value . "' in argument list"); + } elseif (! in_array($arg, self::$params) && ! in_array($arg, self::$switches)) { + throw new Exception("Unknown parameter '" . $arg . "' in argument list"); + } + } + + // set debugger switch + if (isset(self::$args["d"]) && self::$args["d"] == true) { + // Debugger::getInstance()->setEnabled(true); + // Debugger::getInstance()->debug("debug output enabled"); + } + + return new Action(self::$args); + } + + public static function printHelp() + { + self::println(""); + self::println("Help / command line parameters:"); + self::println(""); + // commands + self::println("--switch\t\tlets you switch ip-address A with ip-address B"); + self::println("\t\t\tExample: --switch=A,B"); + self::println("\t\t\tExample: --switch=\"A1,B1 A2,B2 A3,B3 ...\""); + self::println(""); + self::println("--list\t\t\tshow all currently used ip-addresses in froxlor"); + self::println(""); + self::println("--froxlor-dir\t\tpath to froxlor installation"); + self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/"); + self::println(""); + self::println("--help\t\t\tshow help screen (this)"); + self::println(""); + // switches + // self::println("-d\t\t\tenable debug output"); + self::println("-h\t\t\tsame as --help"); + self::println(""); + + die(); // end of execution + } + + public static function println($msg = "") + { + print $msg . PHP_EOL; + } + + private static function _printcolor($msg = "", $color = "0") + { + print "\033[" . $color . "m" . $msg . "\033[0m" . PHP_EOL; + } + + public static function printerr($msg = "") + { + self::_printcolor($msg, "31"); + } + + public static function printsucc($msg = "") + { + self::_printcolor($msg, "32"); + } + + public static function printwarn($msg = "") + { + self::_printcolor($msg, "33"); + } +} + +class Action +{ + + private $_args = null; + + private $_name = null; + + private $_db = null; + + public function __construct($args) + { + $this->_args = $args; + $this->_validate(); + } + + public function getActionName() + { + return $this->_name; + } + + /** + * validates the parsed command line parameters + * + * @throws Exception + */ + private function _validate() + { + $need_config = false; + if (array_key_exists("list", $this->_args) || array_key_exists("switch", $this->_args)) { + $need_config = true; + } + + $this->_checkConfigParam($need_config); + + $this->_parseConfig(); + + if (array_key_exists("list", $this->_args)) { + $this->_listIPs(); + } + if (array_key_exists("switch", $this->_args)) { + $this->_switchIPs(); + } + } + + private function _listIPs() + { + $sel_stmt = Database::prepare("SELECT * FROM panel_ipsandports ORDER BY ip ASC, port ASC"); + Database::pexecute($sel_stmt); + $ips = $sel_stmt->fetchAll(PDO::FETCH_ASSOC); + $mask = "|%-10.10s |%-50.50s | %10.10s |\n"; + printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10)); + printf($mask, 'id', 'IP address', 'port'); + printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10)); + foreach ($ips as $ipdata) { + printf($mask, $ipdata['id'], $ipdata['ip'], $ipdata['port']); + } + printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10)); + echo PHP_EOL . PHP_EOL; + } + + private function _switchIPs() + { + $ip_list = $this->_args['switch']; + + if (empty($ip_list) || is_bool($ip_list)) { + throw new Exception("No paramters given for --switch action."); + } + + $ips_to_switch = array(); + $ip_list = explode(" ", $ip_list); + foreach ($ip_list as $ips_combo) { + $ip_pair = explode(",", $ips_combo); + if (count($ip_pair) != 2) { + throw new Exception("Invalid parameter given for --switch"); + } else { + if (filter_var($ip_pair[0], FILTER_VALIDATE_IP) == false) { + throw new Exception("Invalid source ip address: " . $ip_pair[0]); + } + if (filter_var($ip_pair[1], FILTER_VALIDATE_IP) == false) { + throw new Exception("Invalid target ip address: " . $ip_pair[1]); + } + if ($ip_pair[0] == $ip_pair[1]) { + throw new Exception("Source and target ip address are equal"); + } + } + $ips_to_switch[] = $ip_pair; + } + + if (count($ips_to_switch) > 0) { + $upd_stmt = Database::prepare("UPDATE panel_ipsandports SET `ip` = :newip WHERE `ip` = :oldip"); + + // system.ipaddress + $check_sysip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'"); + $check_sysip = Database::pexecute_first($check_sysip_stmt); + + // system.mysql_access_host + $check_mysqlip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'"); + $check_mysqlip = Database::pexecute_first($check_mysqlip_stmt); + + // system.axfrservers + $check_axfrip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'"); + $check_axfrip = Database::pexecute_first($check_axfrip_stmt); + + foreach ($ips_to_switch as $ip_pair) { + echo "Switching IP \033[1m" . $ip_pair[0] . "\033[0m to IP \033[1m" . $ip_pair[1] . "\033[0m" . PHP_EOL; + Database::pexecute($upd_stmt, array( + 'newip' => $ip_pair[1], + 'oldip' => $ip_pair[0] + )); + $rows_updated = $upd_stmt->rowCount(); + + if ($rows_updated == 0) { + CmdLineHandler::printwarn("Note: " . $ip_pair[0] . " not updated to " . $ip_pair[1] . " (possibly no entry found in froxlor database. Use --list to see what IP addresses are added in froxlor"); + } + + // check whether the system.ipaddress needs updating + if ($check_sysip['value'] == $ip_pair[0]) { + $upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newip WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'"); + Database::pexecute($upd2_stmt, array( + 'newip' => $ip_pair[1] + )); + CmdLineHandler::printsucc("Updated system-ipaddress from '" . $ip_pair[0] . "' to '" . $ip_pair[1] . "'"); + } + + // check whether the system.mysql_access_host needs updating + if (strstr($check_mysqlip['value'], $ip_pair[0]) !== false) { + $new_mysqlip = str_replace($ip_pair[0], $ip_pair[1], $check_mysqlip['value']); + $upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newmysql WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'"); + Database::pexecute($upd2_stmt, array( + 'newmysql' => $new_mysqlip + )); + CmdLineHandler::printsucc("Updated mysql_access_host from '" . $check_mysqlip['value'] . "' to '" . $new_mysqlip . "'"); + } + + // check whether the system.axfrservers needs updating + if (strstr($check_axfrip['value'], $ip_pair[0]) !== false) { + $new_axfrip = str_replace($ip_pair[0], $ip_pair[1], $check_axfrip['value']); + $upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newaxfr WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'"); + Database::pexecute($upd2_stmt, array( + 'newaxfr' => $new_axfrip + )); + CmdLineHandler::printsucc("Updated axfrservers from '" . $check_axfrip['value'] . "' to '" . $new_axfrip . "'"); + } + } + } + + echo PHP_EOL; + CmdLineHandler::printwarn("*** ATTENTION *** Remember to replace IP addresses in configuration files if used anywhere."); + CmdLineHandler::printsucc("IP addresses updated"); + } + + private function _parseConfig() + { + define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']); + if (!file_exists(FROXLOR_INSTALL_DIR . '/lib/classes/database/class.Database.php')) { + throw new Exception("Could not find froxlor's Database class. Is froxlor really installed to '".FROXLOR_INSTALL_DIR."'?"); + } + if (!file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) { + throw new Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system."); + } + require FROXLOR_INSTALL_DIR . '/lib/classes/database/class.Database.php'; + } + + private function _checkConfigParam($needed = false) + { + if ($needed) { + if (! isset($this->_args["froxlor-dir"])) { + throw new Exception("No configuration given (missing --froxlor-dir parameter?)"); + } elseif (! is_dir($this->_args["froxlor-dir"])) { + throw new Exception("Given --froxlor-dir parameter is not a directory"); + } elseif (! file_exists($this->_args["froxlor-dir"])) { + throw new Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')"); + } elseif (! is_readable($this->_args["froxlor-dir"])) { + throw new Exception("Given froxlor direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')"); + } + } + } +}