#!/usr/bin/php . * * Created on 07.11.2007 by Sebastian Kummer & Manfred Kutas * * @package Z-Merge */ echo "\n\n"; echo "Step 1 - Check configuration\n----------------------------------------------------------------------------\n"; define('BASEP', dirname($_SERVER['SCRIPT_FILENAME']) . "/"); echo "parsing of configuration: "; $incfile = BASEP. '../z-merge.inc.php'; if (!file_exists($incfile)) die ("failed\n\nThe file $incfile could not be found"); exec('php '.$incfile, &$ret); if (!empty($ret)) { echo "Configuration error! System claimed:\n"; echo $ret[0] . $ret[1] . "\n\n"; exit; } require_once($incfile); echo "ok\n"; //initialize logging $log =& LoggerManager::getLogger('main'); $log->info("initializing check tool"); echo "checking ZMERGE_DIR: "; if (!file_exists(ZMERGE_DIR . "/z-merge.php")) die("Main directory: " . ZMERGE_DIR . " doesn't exist or agent not found\n\n"); echo "ok\n"; echo "checking ZMERGE_LOGFILE: "; if (!file_exists(ZMERGE_LOGFILE)) { system("touch ". ZMERGE_LOGFILE); if (!file_exists(ZMERGE_LOGFILE )) die("Logfile: ". ZMERGE_LOGFILE ." doesn't exist and directory isn't writable\n\n"); } echo "ok\n"; echo "checking ZMERGE_ERRORLOGFILE: "; if (!file_exists(ZMERGE_ERRORLOGFILE )) { system("touch ". ZMERGE_ERRORLOGFILE); if (!file_exists(ZMERGE_ERRORLOGFILE)) die("Logfile: " . ZMERGE_ERRORLOGFILE ." doesn't exist and directory isn't writable\n\n"); } echo "ok\n"; echo "checking ZMERGE_SENDERRORS emailaddress: "; if (ZMERGE_SENDERRORS !== false && !checkEmail(ZMERGE_SENDERRORS)) die(ZMERGE_SENDERRORS ." invalid or domain not reachable\n\n"); echo "ok\n"; echo "\n\n"; echo "Step 2 - Check agent database connection\n----------------------------------------------------------------------------\n"; echo "connecting to database: "; $logFake = new LogFake(); // prints logentries to the STDOUT $db = new Database($logFake, false); if ($logFake->hasError()) { if ($logFake->dbMissing()) { echo "fail\n\n"; if (question("The database '". $db_dsn['database'] . "' not found. Would you like to create it? (y/n):", "ny") === false) { $logFake->printErrors(); die("\n"); } else { system("echo \"CREATE DATABASE {$db_dsn['database']};\" | mysql -h{$db_dsn['hostspec']} -u{$db_dsn['username']} -p{$db_dsn['password']}"); system("mysql -h{$db_dsn['hostspec']} -u{$db_dsn['username']} -p{$db_dsn['password']} -D{$db_dsn['database']} < " . ZMERGE_DIR . "/tools/db.sql"); } // retry connect echo "connecting to database (2): "; $logFake = new LogFake(); $db = new Database($logFake, false); if ($logFake->dbMissing()) { echo "fail\n\n"; echo "unsuccessfully creating the database\n"; $logFake->printErrors(); die("\n"); } } } // shutdown the logFake $logFake->disable(); echo "database structure: \n"; checkTable("lastmodes"); checkTable("objectmapping"); checkTable("usermapping"); checkTable("zmerge"); echo "\n\n"; echo "Step 3 - Connector status and test\n----------------------------------------------------------------------------\n"; echo "loading connectors.."; try { $serv = MergeAgent::loadServers($servers, $log, $db); } catch (DynamicClassInstantiationZException $dci) { echo "\n\n". $dci->getTraceAsString(); die("DynamicClassInstantiationZException: " . $dci->getMessage(). "\n"); } catch (AuthenticationZException $ae) { die("\n\nAuthentication error: ".$ae->getMessage(). "\n"); } echo "ok\n"; // general check of the servers $servVal = array(); foreach ($serv as $s) { echo "\nchecking server ------- \"". $s->getName() . "\"\n"; $sp = " "; $stat = getServerInfo($s); $servVal[$s->getName()] = $stat; if (array_search("failed", $stat['info'])) { echo $sp . "The connector presents ERRORS!! \n"; echo $sp . "Please check the values below and consult the installation manual troubleshooting area!\n\n"; } else { echo $sp . "The connector test was completed sucessfully.\n\n"; } foreach ($stat['info'] as $k=>$v) { if (substr($k, -1) == "2") continue; echo $sp . "- ". strip_tags($k); echo str_repeat(" ", 30 - strlen($k) + 6); echo strip_tags($v) . "\n"; // print detailed information if available if (isset($stat['info'][$k . "2"])) { echo $sp . " " .str_repeat("^", strlen($k)). "--->"; echo str_repeat(" ", 30 - strlen($k) + 2); echo strip_tags($stat['info'][$k . "2"]) . "\n"; } } echo "\n" . $sp . "Users on the system: ". count($stat['users']) ."\n"; if (isset($stat['appointments'])) { echo "\n" . $sp . "Statistics\n"; echo $sp . " - Appointments : ". $stat['appointments'] . "\n"; } if (isset($stat['contacts'])) echo $sp . " - Contacts : ". $stat['contacts'] . "\n"; if (isset($stat['tasks'])) echo $sp . " - Tasks : ". $stat['tasks'] . "\n"; if (isset($stat['notes'])) echo $sp . " - Notes : ". $stat['notes'] . "\n"; } echo "\n\n"; echo "Step 4: Automap users for connectors\n----------------------------------------------------------------------------\n"; // check for potential groups or double mapping $stmt = "SELECT count(*) as c FROM usermapping u1, usermapping u2 WHERE u1.servername = u2.servername AND u1.serveruser = u2.serveruser AND u1.userid <> u2.userid"; if ($db->executeStatement($stmt, false) > 0) { echo "Usermapping contains double mapping or virtual groups. Automapping not possible.\n"; } // no potential problems found.. try automap else { $users_ids = array(); // build list of already mapped users foreach ($serv as $s) { // get the userlist for this server $users = $servVal[$s->getName()]['users']; // loop through users and check if they are already mapped foreach ($users as $u) { $userid = getUserMapping($s->getName(), $u); // save userid for other servers if ($userid !== false) $users_ids[$u] = array(true, $userid); } } // now look for unmapped users foreach ($serv as $s) { // get the userlist for this server $users = $servVal[$s->getName()]['users']; echo "\nprocessing ". count($users) . " users from \"" . $s->getName() . "\"\n"; // loop through users and check if they are already mapped foreach ($users as $u) { $userid = getUserMapping($s->getName(), $u); // look for unmapped users if ($userid == false) { $users_found = &$users_ids[$u]; if (is_array($users_found) && $users_found[0] == true) { // user already mapped,but not for this server.. just add mapping echo "User '$u' from \"" . $s->getName() . "\" is already mapped on another server. \n"; $a = question("Do you want to automap this user? (y/n) ", "yn"); if ($a === false) {echo "\n\n"; continue;} // MAP user!!! if ($a == "y") { addUserMapping($s->getName(), $u, $users_found[1]); echo " --> user '$u' mapped for '{$s->getName()}'\n"; } } // user found on other server, but not already mapped else if (is_array($users_found) && $users_found[0] == false) { $users_found[1]++; } // completely new else { $users_ids[$u] = array(false, 1); } } } } echo "\n"; $unmapped = array(); foreach ($users_ids as $user=>$found) { if ($found[0] == true) echo " -> username '$user' mapped for at least one system\n"; else { if ($found[1] == 1) $unmapped[] = "'" . $user . "'"; else { echo "Found possible new user mapping. The username '$user' is available on {$found[1]} systems!\n"; $a = question("Do you want to automap this user? (y/n) ", "yn"); if ($a === false) {echo "\n\n"; continue;} // MAP user!!! if ($a == "y") { $newId = false; foreach ($serv as $s) { $users = $servVal[$s->getName()]['users']; // user available for that server? if (in_array($user, $users)) { if (! $newId) $newId = addUserMapping($s->getName(), $user, false); else $newId = addUserMapping($s->getName(), $user, $newId); echo " --> user '$user' mapped for '{$s->getName()}'\n"; } } } echo "\n"; } } } echo "\nThe username(s) ".implode(', ', $unmapped)." were found each only on one system. No mapping possible.\n"; } // end if no groups echo "\n\n"; echo "Step 5: Check the agents last-modification-ids\n----------------------------------------------------------------------------\n"; // get lastmodes of every server foreach ($serv as $s) { foreach ($serv as $s2) { // don't query yourself if ($s->getName() == $s2->getName()) continue; $lastmod = $s->getLastModID($s2); $fromConnId = $servVal[$s2->getName()]['modid']; if (!is_numeric($fromConnId)) die("The connector from '{$s2->getName()}' hasn't reported an modification id. \n\nThe installation is NOT complete. Exiting.\n\n"); if ($lastmod !== false && ($fromConnId - $lastmod) >= 0) { echo "Overview for syncs to '{$s->getName()}' from '{$s2->getName()}'\n"; echo " id saved by agent: $lastmod\n"; echo " id on connector: $fromConnId\n"; echo " unprocessed changes: " . ($fromConnId - $lastmod) . "\n\n"; } // modid resetted on the connector else if (($fromConnId - $lastmod) < 0) { echo "The modificationID for '{$s->getName()}' from '{$s2->getName()}' is greater than the id reported by the connector!!\n"; echo "That is not a normal behaviour. The connectors installation was changed. You must reinitialize the ids.\n"; echo "\nDo you want to set: \n"; echo " (0) modificationID to zero (will produce $fromConnId changes when starting the agent!!)\n"; echo " (c) to the last value reported from the connector (no old changes found when starting the agent)\n"; echo " (n) do nothing (exit - installation incomplete)\n"; $a = question("Please choose (0/c/n) ", "0nc"); if ($a === false) {echo "\n\n"; continue;} // insert into lastmods table if ($a == "0" || $a == "c") { if ($a == "c") $a = $fromConnId; echo "inserted into lastmodes: ". ($db->executeStatement("UPDATE lastmodes SET lastmod = $a WHERE servername = '{$s->getName()}' AND targetserver = '{$s2->getName()}'")) ?"ok\n\n":"fail\n\n"; } } else { echo "The modificationID for '{$s->getName()}' from '{$s2->getName()}' could not be found!!\n"; echo "The value reported from '{$s2->getName()}' is: ". $fromConnId . "\n"; echo "\nDo you want to set: \n"; echo " (0) modificationID to zero (will produce $fromConnId changes when starting the agent!!)\n"; echo " (c) to the last value reported from the connector (no old changes found when starting the agent)\n"; echo " (n) do nothing (exit - installation incomplete)\n"; $a = question("Please choose (0/c/n) ", "0nc"); if ($a === false) {echo "\n\n"; continue;} // insert into lastmods table if ($a == "0" || $a == "c") { if ($a == "c") $a = $fromConnId; echo "inserted into lastmodes: ". ($db->executeStatement("INSERT INTO lastmodes (servername,targetserver,lastmod) VALUES('{$s->getName()}','{$s2->getName()}',$a)")) ?"ok\n\n":"fail\n\n"; } } } } function checkTable($table) { global $db; echo " $table"; echo str_repeat(" ", 13 - strlen($table)); echo " : "; if ($db->tableExists($table)) echo "ok\n"; else die("fail\n\nDatabase structure compromised"); } function getUserMapping($serverName, $serveruser) { global $db; return $db->executeStatement("SELECT userid FROM usermapping WHERE servername='$serverName' AND serveruser='$serveruser' LIMIT 1", false); } function addUserMapping($serverName, $serveruser, $newId) { global $db; if ($newId === false) { // get the next user id! (not threadsafe, but should not be a problem) $newId = $db->executeStatement("SELECT MAX(userid)+1 FROM usermapping", false); if (! $newId) $newId = 1; } $db->executeStatement("INSERT INTO usermapping (userid, servername, serveruser) VALUES($newId, '$serverName', '$serveruser')", false); return $newId; } function checkEmail($email) { if(preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/" , $email)){ list($username,$domain)=split('@',$email); if(!checkdnsrr($domain,'MX')) return false; return true; } return false; } function question($question, $validanswers) { if (!in_array("--auto", $_SERVER['argv'])) { while(!isset($k) || strpos($k, $validanswers) !== false) { echo $question; fscanf(STDIN, "%s", $k); $k = trim($k); } } else { $k=$validanswers[0]; echo "$question (automaticly choosing default: $k)\n"; } if ($k == "n") return false; return $k; } // contact servers function getServerInfo($serverProfile) { // connect to the check script try { $serverProfile->getConnection()->initializeConnection("check"); } catch (AuthenticationZException $ae) { die("\n\nAuthentication error: ".$ae->getMessage(). "\n"); } $stat = array(); $info = array(); $users = array(); if (! ($serverProfile->getConnection()->getRawError())) { $result = $serverProfile->getConnection()->soapCall('check'); if (!$serverProfile->getConnection()->getRawFault()) { if ($err = $serverProfile->getConnection()->getRawError()) { echo "Could not connect to the server \"{$serverProfile->getName()}\" - Error: $err\n"; $response = strip_tags($serverProfile->getConnection()->getRawResponse()); if ((preg_match("/HTTP\/1.+(\d{3}.*)/", $response, &$errs) && $errs[1] != 200) || preg_match("/Fatal error:.((\w| |\.|\/|-|,|\(|\)|\[|\]|:|'|=)*)/", $response, &$errs) || preg_match("/Parse error:.((\w| |\.|\/|-|,|\(|\)|\[|\]|:|'|=)*)/", $response, &$errs) || preg_match("/Warning:.((\w| |\.|\/|-|,|\(|\)|\[|\]|:|'|=)*)/", $response, &$errs) || preg_match("/(.+)$/", $response, &$errs) ) { echo "Server \"{$serverProfile->getName()}\" said: " . $errs[1] . "\n"; } die(); } else { foreach ($result as $kv) { $n = $kv['name']; if ($n == 'modid' || $n == 'contacts' || $n == 'notes' || $n == 'tasks' || $n == 'appointments') { $stat[$n] = $kv['value']; } else if (stripos($n,'usr_') === 0) { $users[] = $kv['value']; } else { $info[$n] = $kv['value']; } } $stat['info'] = $info; $stat['users'] = $users; return $stat; } } else echo "SOAP-Fault: ". $serverProfile->getConnection()->getRawFault . "\n"; die(); } } class LogFake { private $_err; private $_errors; function LogFake() { $this->_err = 0; $this->_errors = array(); $this->_print = true; } function info($string) { if ($this->_print) echo $string . "\n"; } function debug($string) { if ($this->_print) echo $string . "\n"; } function warn($string) { if ($this->_print) echo $string . "\n"; } function error($string) { if ($this->_print) { $this->_errors[] = $string; $this->_err++; } } function hasError() { return ($this->_err > 0); } function dbMissing() { $dbMiss = false; foreach ($this->_errors as $e) { if (stripos($e, "not select") !== true || stripos($e, "Unknown database") !== true) $dbMiss = true; } return $dbMiss; } function printErrors() { foreach ($this->_errors as $e) echo $e ."\n"; } function disable() { $this->_print = false; } } ?>