source: npl/mailserver/z_merge_agent/autocheck.php @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100755
File size: 17.9 KB
Line 
1#!/usr/bin/php
2<?php
3/**
4 * Zarafa Z-Merge
5 *
6 * Copyright (C) 2005 - 2008  Zarafa B.V.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License, version 3,
10 * and under the terms of the GNU General Public License, version 3,
11 * as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU (Affero) General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * and the GNU General Public License along with this program. 
20 * If not, see <http://www.gnu.org/licenses/>.
21 * 
22 * Created on 07.11.2007 by Sebastian Kummer & Manfred Kutas
23 *
24 * @package Z-Merge
25 */
26
27
28echo "\n\n";
29echo "Step 1 - Check configuration\n----------------------------------------------------------------------------\n";
30define('BASEP', dirname($_SERVER['SCRIPT_FILENAME']) . "/");
31
32echo "parsing of configuration: ";
33$incfile = BASEP. '../z-merge.inc.php';
34if (!file_exists($incfile)) die ("failed\n\nThe file $incfile could not be found");
35       
36exec('php '.$incfile, &$ret);
37if (!empty($ret)) {
38        echo "Configuration error! System claimed:\n";
39        echo $ret[0] . $ret[1] . "\n\n";
40        exit;   
41}
42require_once($incfile);
43echo "ok\n";
44
45
46//initialize logging
47$log =& LoggerManager::getLogger('main');
48$log->info("initializing check tool");
49
50
51echo "checking ZMERGE_DIR: ";
52if (!file_exists(ZMERGE_DIR . "/z-merge.php")) die("Main directory: " . ZMERGE_DIR . " doesn't exist or agent not found\n\n");
53echo "ok\n";
54
55
56echo "checking ZMERGE_LOGFILE: ";
57if (!file_exists(ZMERGE_LOGFILE)) {
58        system("touch ". ZMERGE_LOGFILE);       
59        if (!file_exists(ZMERGE_LOGFILE ))
60                die("Logfile: ". ZMERGE_LOGFILE ." doesn't exist and directory isn't writable\n\n");   
61}
62echo "ok\n";
63
64echo "checking ZMERGE_ERRORLOGFILE: ";
65if (!file_exists(ZMERGE_ERRORLOGFILE )) {
66        system("touch ". ZMERGE_ERRORLOGFILE); 
67        if (!file_exists(ZMERGE_ERRORLOGFILE))
68                die("Logfile: " . ZMERGE_ERRORLOGFILE ." doesn't exist and directory isn't writable\n\n");     
69}
70echo "ok\n";
71
72echo "checking ZMERGE_SENDERRORS emailaddress: ";
73if (ZMERGE_SENDERRORS !== false && !checkEmail(ZMERGE_SENDERRORS))
74        die(ZMERGE_SENDERRORS ." invalid or domain not reachable\n\n");
75echo "ok\n";   
76
77echo "\n\n";           
78echo "Step 2 - Check agent database connection\n----------------------------------------------------------------------------\n";
79echo "connecting to database: ";
80$logFake = new LogFake(); // prints logentries to the STDOUT
81$db = new Database($logFake, false);
82if ($logFake->hasError()) {
83        if ($logFake->dbMissing()) {
84                echo "fail\n\n";
85                if (question("The database '". $db_dsn['database'] . "' not found. Would you like to create it? (y/n):", "ny") === false) {
86                        $logFake->printErrors();
87                        die("\n");
88                }
89                else {
90                        system("echo \"CREATE DATABASE {$db_dsn['database']};\" | mysql -h{$db_dsn['hostspec']} -u{$db_dsn['username']} -p{$db_dsn['password']}");                     
91                        system("mysql -h{$db_dsn['hostspec']} -u{$db_dsn['username']} -p{$db_dsn['password']} -D{$db_dsn['database']} < " . ZMERGE_DIR . "/tools/db.sql");
92                }
93               
94                // retry connect
95                echo "connecting to database (2): ";
96                $logFake = new LogFake();
97                $db = new Database($logFake, false);
98                if ($logFake->dbMissing()) {
99                        echo "fail\n\n";
100                        echo "unsuccessfully creating the database\n";
101                        $logFake->printErrors();
102                        die("\n");
103                }
104        }
105}
106// shutdown the logFake
107$logFake->disable();
108
109echo "database structure: \n";
110checkTable("lastmodes");
111checkTable("objectmapping");
112checkTable("usermapping");
113checkTable("zmerge");
114
115echo "\n\n";           
116echo "Step 3 - Connector status and test\n----------------------------------------------------------------------------\n";
117echo "loading connectors..";
118
119try {
120        $serv = MergeAgent::loadServers($servers, $log, $db);
121}
122catch (DynamicClassInstantiationZException $dci) {
123        echo "\n\n". $dci->getTraceAsString();
124        die("DynamicClassInstantiationZException: " . $dci->getMessage(). "\n");               
125}
126catch (AuthenticationZException $ae) {
127        die("\n\nAuthentication error: ".$ae->getMessage(). "\n");
128}
129echo "ok\n";
130
131
132// general check of the servers
133$servVal = array();
134foreach ($serv as $s) {
135        echo "\nchecking server ------- \"". $s->getName() . "\"\n";
136        $sp = "           ";
137        $stat = getServerInfo($s);
138                $servVal[$s->getName()] = $stat;
139        if (array_search("failed", $stat['info'])) {
140            echo $sp . "The connector presents ERRORS!! \n";
141            echo $sp . "Please check the values below and consult the installation manual troubleshooting area!\n\n";
142        }
143        else {
144                echo $sp . "The connector test was completed sucessfully.\n\n";
145        }
146        foreach ($stat['info'] as $k=>$v) {
147                if (substr($k, -1) == "2") continue;
148
149                echo $sp . "- ". strip_tags($k);
150                echo str_repeat(" ", 30 - strlen($k) + 6);
151                echo strip_tags($v) . "\n";
152                // print detailed information if available
153                if (isset($stat['info'][$k . "2"])) {
154                        echo $sp . "  " .str_repeat("^", strlen($k)). "--->";
155                        echo str_repeat(" ", 30 - strlen($k) + 2);
156                        echo strip_tags($stat['info'][$k . "2"]) . "\n";
157                }
158        }
159
160        echo "\n" . $sp . "Users on the system: ". count($stat['users']) ."\n";
161
162       
163        if (isset($stat['appointments'])) {
164                echo "\n" . $sp . "Statistics\n";
165                echo $sp . "  - Appointments  : ". $stat['appointments'] . "\n";
166        }
167        if (isset($stat['contacts']))
168                echo $sp . "  - Contacts      : ". $stat['contacts'] . "\n";
169        if (isset($stat['tasks'])) 
170                echo $sp . "  - Tasks         : ". $stat['tasks'] . "\n";
171        if (isset($stat['notes']))
172                echo $sp . "  - Notes         : ". $stat['notes'] . "\n";
173
174}
175
176
177echo "\n\n";           
178echo "Step 4: Automap users for connectors\n----------------------------------------------------------------------------\n";
179
180// check for potential groups or double mapping
181$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";
182if ($db->executeStatement($stmt, false) > 0) {
183        echo "Usermapping contains double mapping or virtual groups. Automapping not possible.\n";
184}
185
186// no potential problems found.. try automap
187else {
188        $users_ids = array();
189       
190        // build list of already mapped users
191        foreach ($serv as $s) {
192                // get the userlist for this server
193                $users = $servVal[$s->getName()]['users'];
194                // loop through users and check if they are already mapped
195                foreach ($users as $u) {
196                        $userid = getUserMapping($s->getName(), $u);
197       
198                        // save userid for other servers
199                        if ($userid !== false) $users_ids[$u] = array(true, $userid);
200                }
201        }
202       
203        // now look for unmapped users
204        foreach ($serv as $s) {
205                // get the userlist for this server
206                $users = $servVal[$s->getName()]['users'];
207                echo "\nprocessing ". count($users) . " users from \"" . $s->getName() . "\"\n";
208               
209                // loop through users and check if they are already mapped
210                foreach ($users as $u) {
211                        $userid = getUserMapping($s->getName(), $u);
212       
213                        // look for unmapped users
214                        if ($userid == false) {
215                                $users_found = &$users_ids[$u];
216                               
217                                if (is_array($users_found) && $users_found[0] == true) {
218                                        // user already mapped,but not for this server.. just add mapping
219                                        echo "User '$u' from \"" . $s->getName() . "\" is already mapped on another server. \n";
220       
221                                $a = question("Do you want to automap this user? (y/n) ", "yn");
222                                if ($a === false) {echo "\n\n"; continue;}
223                               
224                                // MAP user!!!
225                                if ($a == "y") {
226                                                addUserMapping($s->getName(), $u, $users_found[1]);
227                                                echo " --> user '$u' mapped for '{$s->getName()}'\n";
228                                }                                       
229                                }
230                                // user found on other server, but not already mapped
231                                else if (is_array($users_found) && $users_found[0] == false) {
232                                        $users_found[1]++;
233                                }
234                                // completely new
235                                else {
236                                        $users_ids[$u] = array(false, 1);
237                                }
238                        }       
239                       
240                }
241        }
242       
243       
244        echo "\n";
245        $unmapped = array();
246        foreach ($users_ids as $user=>$found) {
247                if ($found[0] == true) echo " -> username '$user' mapped for at least one system\n";
248                else {
249                        if ($found[1] == 1)     
250                                $unmapped[] = "'" . $user . "'";
251                        else {
252                                echo "Found possible new user mapping. The username '$user' is available on {$found[1]} systems!\n";
253       
254                        $a = question("Do you want to automap this user? (y/n) ", "yn");
255                        if ($a === false) {echo "\n\n"; continue;}
256                       
257                        // MAP user!!!
258                        if ($a == "y") {
259                                        $newId = false;
260                                        foreach ($serv as $s) {
261                                                $users = $servVal[$s->getName()]['users'];
262                                                // user available for that server?
263                                                if (in_array($user, $users)) {
264                                                        if (! $newId) $newId = addUserMapping($s->getName(), $user, false);
265                                                        else              $newId = addUserMapping($s->getName(), $user, $newId);
266                                                        echo " --> user '$user' mapped for '{$s->getName()}'\n";
267                                                }
268                                        }                       
269                        }
270                        echo "\n";
271                        }               
272                }       
273        }
274       
275       
276        echo "\nThe username(s) ".implode(', ', $unmapped)." were found each only on one system. No mapping possible.\n";
277} // end if no groups
278
279
280
281echo "\n\n";           
282echo "Step 5: Check the agents last-modification-ids\n----------------------------------------------------------------------------\n";
283
284
285// get lastmodes of every server
286foreach ($serv as $s) {
287        foreach ($serv as $s2) {
288                // don't query yourself
289                if ($s->getName() == $s2->getName()) continue;
290                $lastmod = $s->getLastModID($s2);
291                                $fromConnId = $servVal[$s2->getName()]['modid'];                       
292
293                                if (!is_numeric($fromConnId))
294                        die("The connector from '{$s2->getName()}' hasn't reported an modification id. \n\nThe installation is NOT complete. Exiting.\n\n");
295
296                if ($lastmod !== false && ($fromConnId - $lastmod) >= 0) {
297                        echo "Overview for syncs to '{$s->getName()}' from '{$s2->getName()}'\n";
298                        echo "     id saved by agent: $lastmod\n";
299                        echo "       id on connector: $fromConnId\n";
300                        echo "   unprocessed changes: " . ($fromConnId - $lastmod) . "\n\n";
301                }
302                // modid resetted on the connector
303                else if (($fromConnId - $lastmod) < 0) {
304                        echo "The modificationID for '{$s->getName()}' from '{$s2->getName()}' is greater than the id reported by the connector!!\n";
305                        echo "That is not a normal behaviour. The connectors installation was changed. You must reinitialize the ids.\n";
306                         
307                       
308                        echo "\nDo you want to set: \n";
309                        echo "   (0) modificationID to zero (will produce $fromConnId changes when starting the agent!!)\n";
310                        echo "   (c) to the last value reported from the connector (no old changes found when starting the agent)\n";
311                        echo "   (n) do nothing (exit - installation incomplete)\n";
312                        $a = question("Please choose (0/c/n) ", "0nc");
313                        if ($a === false) {echo "\n\n"; continue;}
314
315                        // insert into lastmods table
316                        if ($a == "0" || $a == "c") {
317                                                if ($a == "c") $a = $fromConnId;
318                                echo "inserted into lastmodes: ".
319                                        ($db->executeStatement("UPDATE lastmodes SET lastmod = $a WHERE servername = '{$s->getName()}' AND targetserver = '{$s2->getName()}'"))
320                                                ?"ok\n\n":"fail\n\n";
321                        }                       
322                }
323                else {
324                        echo "The modificationID for '{$s->getName()}' from '{$s2->getName()}' could not be found!!\n";
325                        echo "The value reported from '{$s2->getName()}' is: ". $fromConnId . "\n";
326                         
327                       
328                        echo "\nDo you want to set: \n";
329                        echo "   (0) modificationID to zero (will produce $fromConnId changes when starting the agent!!)\n";
330                        echo "   (c) to the last value reported from the connector (no old changes found when starting the agent)\n";
331                        echo "   (n) do nothing (exit - installation incomplete)\n";
332                        $a = question("Please choose (0/c/n) ", "0nc");
333                        if ($a === false) {echo "\n\n"; continue;}
334
335                        // insert into lastmods table
336                        if ($a == "0" || $a == "c") {
337                                                if ($a == "c") $a = $fromConnId;
338                                echo "inserted into lastmodes: ".
339                                        ($db->executeStatement("INSERT INTO lastmodes (servername,targetserver,lastmod) VALUES('{$s->getName()}','{$s2->getName()}',$a)"))
340                                                ?"ok\n\n":"fail\n\n";
341                        }
342
343                }
344        }
345}
346
347
348
349
350function checkTable($table) {
351        global $db;
352
353        echo "   $table";
354        echo str_repeat(" ", 13 - strlen($table));
355        echo "      : ";
356        if ($db->tableExists($table))
357                echo "ok\n";
358        else
359                die("fail\n\nDatabase structure compromised");
360}
361
362
363
364function getUserMapping($serverName, $serveruser) {
365        global $db;
366        return $db->executeStatement("SELECT userid FROM usermapping WHERE servername='$serverName' AND serveruser='$serveruser' LIMIT 1", false);
367}
368
369function addUserMapping($serverName, $serveruser, $newId) {
370        global $db;
371       
372        if ($newId === false) {
373                // get the next user id! (not threadsafe, but should not be a problem)
374                $newId = $db->executeStatement("SELECT MAX(userid)+1 FROM usermapping", false);
375                if (! $newId) $newId = 1;
376        }
377
378        $db->executeStatement("INSERT INTO usermapping (userid, servername, serveruser) VALUES($newId, '$serverName', '$serveruser')", false);
379        return $newId;
380}
381
382function checkEmail($email) {
383        if(preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/" , $email)){
384                list($username,$domain)=split('@',$email);
385                if(!checkdnsrr($domain,'MX')) return false;
386                return true;
387        }
388        return false;
389}
390
391
392
393function question($question, $validanswers) {
394        if (!in_array("--auto", $_SERVER['argv']))
395        {
396                while(!isset($k) || strpos($k, $validanswers) !== false) {
397                        echo $question;
398                        fscanf(STDIN, "%s", $k);
399                        $k = trim($k);
400                }
401        }
402        else
403        {
404            $k=$validanswers[0];
405            echo "$question (automaticly choosing default: $k)\n";
406        }
407        if ($k == "n") return false;
408        return $k;
409}
410
411// contact servers
412function getServerInfo($serverProfile) {
413        // connect to the check script
414        try {
415                        $serverProfile->getConnection()->initializeConnection("check");
416                }
417                catch (AuthenticationZException $ae) {
418                        die("\n\nAuthentication error: ".$ae->getMessage(). "\n");
419                }               
420
421        $stat = array();
422        $info = array();
423        $users = array();
424        if (! ($serverProfile->getConnection()->getRawError())) {
425                        $result = $serverProfile->getConnection()->soapCall('check');
426
427                if (!$serverProfile->getConnection()->getRawFault()) {
428                        if ($err = $serverProfile->getConnection()->getRawError()) {
429
430                                echo "Could not connect to the server \"{$serverProfile->getName()}\" - Error: $err\n";
431                                $response = strip_tags($serverProfile->getConnection()->getRawResponse());
432
433                                if ((preg_match("/HTTP\/1.+(\d{3}.*)/", $response, &$errs) && $errs[1] != 200) ||
434                                         preg_match("/Fatal error:.((\w| |\.|\/|-|,|\(|\)|\[|\]|:|'|=)*)/", $response, &$errs) ||
435                                         preg_match("/Parse error:.((\w| |\.|\/|-|,|\(|\)|\[|\]|:|'|=)*)/", $response, &$errs) ||
436                                         preg_match("/Warning:.((\w| |\.|\/|-|,|\(|\)|\[|\]|:|'|=)*)/", $response, &$errs) ||
437                                                                         preg_match("/(.+)$/", $response, &$errs)                                         
438                                        ) {
439                                        echo "Server \"{$serverProfile->getName()}\" said: " . $errs[1] . "\n";
440                                }
441                               
442                                die();
443                        }
444                        else {
445                                foreach ($result as $kv) {
446                                        $n = $kv['name'];
447                                        if ($n == 'modid' || $n == 'contacts' || $n == 'notes' || $n == 'tasks' || $n == 'appointments') {
448                                                $stat[$n] = $kv['value'];
449                                        }
450                                        else if (stripos($n,'usr_') === 0) {
451                                                $users[] = $kv['value'];
452                                        }
453                                        else {
454                                                $info[$n] = $kv['value'];
455                                        }
456                                }
457                                $stat['info'] = $info;
458                                $stat['users'] = $users;
459                                return $stat;
460                        }
461                }
462                else echo "SOAP-Fault: ". $serverProfile->getConnection()->getRawFault . "\n";
463                die();
464        }
465}
466
467class LogFake {
468        private $_err;
469        private $_errors;
470       
471        function LogFake() {
472                $this->_err = 0;
473                $this->_errors = array();
474                $this->_print = true;
475        }
476       
477        function info($string) {
478                if ($this->_print) echo $string . "\n";
479        }
480       
481        function debug($string) {
482                if ($this->_print) echo $string . "\n";
483        }
484       
485        function warn($string) {
486                if ($this->_print) echo $string . "\n";
487        }
488               
489        function error($string) {
490                if ($this->_print) {
491                        $this->_errors[] = $string;
492                        $this->_err++; 
493                }
494        }
495       
496        function hasError() {
497                return ($this->_err > 0);
498        }
499       
500        function dbMissing() {
501                $dbMiss = false;
502                foreach ($this->_errors as $e) {
503                        if (stripos($e, "not select") !== true ||  stripos($e, "Unknown database") !== true)
504                                $dbMiss = true;
505                }                               
506                return $dbMiss;
507        }
508
509        function printErrors() {
510                foreach ($this->_errors as $e) echo $e ."\n";
511        }
512       
513        function disable() {
514                $this->_print = false;
515        }
516}
517
518?>
Note: See TracBrowser for help on using the repository browser.