From d7c94726fd605fe68c2c454170927475dee71177 Mon Sep 17 00:00:00 2001 From: "Florian Aders (EleRas)" Date: Fri, 7 Feb 2014 18:25:35 +0100 Subject: [PATCH] Add a basic integritychecker after every update Signed-off-by: Florian Aders (EleRas) --- install/updatesql.php | 17 +++ .../integrity/class.IntegrityCheck.php | 129 ++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 lib/classes/integrity/class.IntegrityCheck.php diff --git a/install/updatesql.php b/install/updatesql.php index 312dd52c..7f3a03e5 100644 --- a/install/updatesql.php +++ b/install/updatesql.php @@ -44,6 +44,23 @@ if(!isFroxlor()) { if (isFroxlor()) { include_once (makeCorrectFile(dirname(__FILE__).'/updates/froxlor/0.9/update_0.9.inc.php')); + + // Check Froxlor - database integrity (only happens after all updates are done, so we know the db-layout is okay) + showUpdateStep("Checking database integrity"); + + $integrity = new IntegrityCheck(); + if (!$integrity->checkAll()) { + lastStepStatus(2, 'Monkeys ate the integrity'); + showUpdateStep("Trying to remove monkeys, feeding bananas"); + if(!$integrity->fixAll()) { + lastStepStatus(2, 'Some monkeys just would not move'); + } else { + lastStepStatus(0); + } + } else { + lastStepStatus(0); + } + $filelog->logAction(ADM_ACTION, LOG_WARNING, '--------------- END LOG ---------------'); unset($filelog); } diff --git a/lib/classes/integrity/class.IntegrityCheck.php b/lib/classes/integrity/class.IntegrityCheck.php new file mode 100644 index 00000000..9dde20c2 --- /dev/null +++ b/lib/classes/integrity/class.IntegrityCheck.php @@ -0,0 +1,129 @@ + + * @author Froxlor team (2014-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Integrity + * + * IntegrityCheck - class + */ + +class IntegrityCheck { + + /** + * Check all occuring integrity problems at once + */ + public function checkAll() { + $integrityok = true; + $integrityok = $this->DomainIpTable() ? $integrityok : false; + return $integrityok; + } + + /** + * Fix all occuring integrity problems at once with default settings + */ + public function fixAll() { + $integrityok = true; + $integrityok = $this->DomainIpTable(true) ? $integrityok : false; + return $integrityok; + } + + /** + * Check the integrity of the domain to ip/port - association + * @param $fix Fix everything found directly + */ + public function DomainIpTable($fix = false) { + $ips = array(); + $domains = array(); + $ipstodomains = array(); + $admips = array(); + + if ($fix) { + // Prepare insert / delete statement for the fixes + $del_stmt = Database::prepare(" + DELETE FROM `" . TABLE_DOMAINTOIP . "` + WHERE `id_domain` = :domainid AND `id_ipandports` = :ipandportid " + ); + $ins_stmt = Database::prepare(" + INSERT INTO `" . TABLE_DOMAINTOIP . "` + SET `id_domain` = :domainid, `id_ipandports` = :ipandportid " + ); + + // Cache all IPs the admins have assigned + $adm_stmt = Database::prepare("SELECT `adminid`, `ip` FROM `" . TABLE_PANEL_ADMINS . "` ORDER BY `adminid` ASC"); + Database::pexecute($adm_stmt); + while ($row = $adm_stmt->fetch(PDO::FETCH_ASSOC)) { + if ($row['ip'] == -1) { + // Admin uses default-IP + $admips[$row['adminid']] = Settings::Get('system.defaultip'); + } else { + $admips[$row['adminid']] = $row['ip']; + } + } + } + + // Cache all available ip/port - combinations + $result_stmt = Database::prepare("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `id` ASC"); + Database::pexecute($result_stmt); + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $ips[$row['id']] = $row['ip'] . ':' . $row['port']; + } + + // Cache all configured domains + $result_stmt = Database::prepare("SELECT `id`, `adminid` FROM `" . TABLE_PANEL_DOMAINS . "` ORDER BY `id` ASC"); + Database::pexecute($result_stmt); + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $domains[$row['id']] = $row['adminid']; + } + + // Check if every domain to ip/port - association is valid in TABLE_DOMAINTOIP + $result_stmt = Database::prepare("SELECT `id_domain`, `id_ipandports` FROM `" . TABLE_DOMAINTOIP . "`"); + Database::pexecute($result_stmt); + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + if (!array_key_exists($row['id_ipandports'], $ips)) { + if ($fix) { + Database::pexecute($del_stmt, array('domainid' => $row['id_domain'], 'ipandportid' => $row['id_ipandports'])); + } else { + return false; + } + } + if (!array_key_exists($row['id_domain'], $domains)) { + if ($fix) { + Database::pexecute($del_stmt, array('domainid' => $row['id_domain'], 'ipandportid' => $row['id_ipandports'])); + } else { + return false; + } + } + // Save one IP/Port combination per domain, so we know, if one domain is missing an IP + $ipstodomains[$row['id_domain']] = $row['id_ipandports']; + } + + // Check that all domains have at least one IP/Port combination + foreach ($domains as $domainid => $adminid) { + if (!array_key_exists($domainid, $ipstodomains)) { + if ($fix) { + Database::pexecute($ins_stmt, array('domainid' => $domainid, 'ipandportid' => $admips[$adminid])); + } else { + return false; + } + } + } + + if ($fix) { + return $this->DomainIpTable(); + } else { + return true; + } + } + +}