diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index a584eae2b..69542e1ea 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -913,7 +913,7 @@ EOF $aParamValues = array( 'db_server' => $oWizard->GetParameter('db_server', ''), 'db_user' => $oWizard->GetParameter('db_user', ''), - 'db_pwd' => $oWizard->GetParameter('db_server', ''), + 'db_pwd' => $oWizard->GetParameter('db_pwd', ''), 'db_name' => $oWizard->GetParameter('db_name', ''), 'db_prefix' => $oWizard->GetParameter('db_prefix', ''), 'source_dir' => APPROOT.'datamodel', @@ -921,9 +921,149 @@ EOF $oConfig->UpdateFromParams($aParamValues, 'datamodel'); $oProductionEnv = new RunTimeEnvironment(); - $oConfig = new Config(); $aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, 'datamodel'); return $aAvailableModules; - } + } + + /** + * Checks if the content of a directory matches the given manifest + * @param string $sBaseDir Path to the root directory of iTop + * @param string $sSourceDir Relative path to the directory to check under $sBaseDir + * @param Array $aDOMManifest Array of array('path' => relative_path 'size'=> iSize, 'md5' => sHexMD5) + * @param Hash $aResult Used for recursion + * @return hash Hash array ('added' => array(), 'removed' => array(), 'modified' => array()) + */ + public static function CheckDirAgainstManifest($sBaseDir, $sSourceDir, $aManifest, $aExcludeNames = array('.svn'), $aResult = null) + { + if ($aResult === null) + { + $aResult = array('added' => array(), 'removed' => array(), 'modified' => array()); + } + + if (substr($sSourceDir, 0, 1) == '/') + { + $sSourceDir = substr($sSourceDir, 1); + } + + // Manifest limited to all the files supposed to be located in this directory + $aDirManifest = array(); + foreach($aManifest as $aFileInfo) + { + $sDir = dirname($aFileInfo['path']); + if ($sDir == '.') + { + // Hmm... the file seems located at the root of iTop + $sDir = ''; + } + if ($sDir == $sSourceDir) + { + $aDirManifest[basename($aFileInfo['path'])] = $aFileInfo; + } + } + + // Read the content of the directory + foreach(glob($sBaseDir.'/'.$sSourceDir .'/*') as $sFilePath) + { + $sFile = basename($sFilePath); + + if (in_array(basename($sFile), $aExcludeNames)) continue; + + if(is_dir($sFilePath)) + { + $aResult = self::CheckDirAgainstManifest($sBaseDir, $sSourceDir.'/'.$sFile, $aManifest, $aExcludeNames, $aResult); + } + else + { + if (!array_key_exists($sFile, $aDirManifest)) + { +//echo "New file ".$sFile." in $sSourceDir\n"; + $aResult['added'][$sSourceDir.'/'.$sFile] = true; + } + else + { + $aStats = stat($sFilePath); + if ($aStats['size'] != $aDirManifest[$sFile]['size']) + { + // Different sizes + $aResult['modified'][$sSourceDir.'/'.$sFile] = 'Different sizes. Original size: '.$aDirManifest[$sFile]['size'].' bytes, actual file size on disk: '.$aStats['size'].' bytes.'; + } + else + { + // Same size, compare the md5 signature + $sMD5 = md5_file($sFilePath); + if ($sMD5 != $aDirManifest[$sFile]['md5']) + { + $aResult['modified'][$sSourceDir.'/'.$sFile] = 'Content modified (MD5 checksums differ).'; + } +//else +//{ +// echo $sSourceDir.'/'.$sFile." unmodified ($sMD5 == {$aDirManifest[$sFile]['md5']})\n"; +//} + } +//echo "Removing ".$sFile." from aDirManifest\n"; + unset($aDirManifest[$sFile]); + } + } + } + // What remains in the array are files that were deleted + foreach($aDirManifest as $sDeletedFile => $void) + { + $aResult['removed'][$sSourceDir.'/'.$sDeletedFile] = true; + } + return $aResult; + } + + public static function CheckDataModelFiles($sManifestFile, $sBaseDir) + { + $oXML = simplexml_load_file($sManifestFile); + $aManifest = array(); + foreach($oXML as $oFileInfo) + { + $aManifest[] = array('path' => (string)$oFileInfo->path, 'size' => (int)$oFileInfo->size, 'md5' => (string)$oFileInfo->md5); + } + + $aResults = self::CheckDirAgainstManifest($sBaseDir, 'modules', $aManifest); + +// echo "
Comparison of ".dirname($sBaseDir)."/modules:\n".print_r($aResults, true).""; + return $aResults; + } + + public static function CheckPortalFiles($sManifestFile, $sBaseDir) + { + $oXML = simplexml_load_file($sManifestFile); + $aManifest = array(); + foreach($oXML as $oFileInfo) + { + $aManifest[] = array('path' => (string)$oFileInfo->path, 'size' => (int)$oFileInfo->size, 'md5' => (string)$oFileInfo->md5); + } + + $aResults = self::CheckDirAgainstManifest($sBaseDir, 'portal', $aManifest); + +// echo "
Comparison of ".dirname($sBaseDir)."/portal:\n".print_r($aResults, true).""; + return $aResults; + } + + public static function CheckApplicationFiles($sManifestFile, $sBaseDir) + { + $oXML = simplexml_load_file($sManifestFile); + $aManifest = array(); + foreach($oXML as $oFileInfo) + { + $aManifest[] = array('path' => (string)$oFileInfo->path, 'size' => (int)$oFileInfo->size, 'md5' => (string)$oFileInfo->md5); + } + + $aResults = array('added' => array(), 'removed' => array(), 'modified' => array()); + foreach(array('addons', 'core', 'dictionaries', 'js', 'application', 'css', 'pages', 'synchro', 'webservices') as $sDir) + { + $aTmp = self::CheckDirAgainstManifest($sBaseDir, 'portal', $aManifest); + $aResults['added'] = array_merge($aResults['added'], $aTmp['added']); + $aResults['modified'] = array_merge($aResults['modified'], $aTmp['modified']); + $aResults['removed'] = array_merge($aResults['removed'], $aTmp['removed']); + } + +// echo "
Comparison of ".dirname($sBaseDir)."/portal:\n".print_r($aResults, true).""; + return $aResults; + } + } \ No newline at end of file diff --git a/setup/wizardsteps.class.inc.php b/setup/wizardsteps.class.inc.php index aa821718f..de8adceee 100644 --- a/setup/wizardsteps.class.inc.php +++ b/setup/wizardsteps.class.inc.php @@ -377,6 +377,36 @@ class WizStepDetectedInfo extends WizardStep public function Display(WebPage $oPage) { $oPage->p('Info about the detected version'); + $sSourceDir = $this->oWizard->GetParameter('source_dir', ''); + $aInstalledModules = SetupUtils::AnalyzeInstallation($this->oWizard); + $sVersion = $aInstalledModules[ROOT_MODULE]['version_db']; + + if (preg_match('/^([0-9]+)\.([0-9]+)\.([0-9]+)\.(.*)$/', $sVersion, $aMatches)) + { + $sVersion = $aMatches[1].'.'.$aMatches[2].'.'.$aMatches[3]; + } + + $sKnownManifestFile = APPROOT.'setup/known-versions/'.$sVersion.'/manifest.xml'; + if ($sSourceDir != '') + { + if (file_exists($sKnownManifestFile)) + { + $aDMchanges = SetupUtils::CheckDataModelFiles($sKnownManifestFile, $sSourceDir); + $aPortalChanges = SetupUtils::CheckPortalFiles($sKnownManifestFile, $sSourceDir); + $aCodeChanges = SetupUtils::CheckApplicationFiles($sKnownManifestFile, $sSourceDir); + + $oPage->add("Changes detected compared to $sVersion:
".print_r($aDMchanges, true)."
".print_r($aPortalChanges, true)."
".print_r($aCodeChanges, true).""); + } + else + { + $oPage->p("Unknown version $sVersion. Do you want to upgrade anyway ??? NOT GUARANTEED AT ALL !!!"); + } + } + else + { + $oPage->p("No source dir provided assuming that the installed version '$sVersion' is genuine iTop build..."); + } + } }