/** * Check install parameters * * @param $array, install command to check, view documentation for format * @param $errorsInfo array, infos on errors found in checked install commands. Returned by reference. * @return string errors found in install array * @access public */ function checkInstall(&$array, &$errorsInfo) { if (is_array($array)) { $errorsInfo = array(); $error = ''; foreach ($array as $line => $aInstallCheck) { $line++; //to have the correct line number //remove blank lines if (!$aInstallCheck) { unset($array[$line - 1]); continue; } $installParams = array_map("trim", explode("\t", $aInstallCheck)); //read UPDATE.DENY file $updateDenyFile = new CMS_file(UPDATE_DENY, CMS_file::WEBROOT); if ($updateDenyFile->exists()) { $updateDeny = $updateDenyFile->readContent("array"); } else { $this->raiseError("File " . UPDATE_DENY . " does not exist"); return false; } //if we don't have parameter and line not a comment if (!isset($installParams[1]) && io::substr($installParams[0], 0, 1) != '#' && $installParams[0] != 'rc') { $error .= "Error at line : " . $line . " missing file parameter<br />"; $errorsInfo[] = array('no' => 1, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } else { //first check needed file existence if ($installParams[0] != 'ex') { $originalFile = isset($installParams[1]) ? PATH_REALROOT_FS . $installParams[1] : PATH_REALROOT_FS; $patchFile = isset($installParams[1]) ? PATH_TMP_FS . $installParams[1] : PATH_TMP_FS; } $filesExists = true; switch ($installParams[0]) { //check only patch file existence case "x": case ">": case "+": if (!file_exists($patchFile)) { $error .= "Error at line : " . $line . ", patch file " . $patchFile . " does not exist<br />"; $filesExists = false; $errorsInfo[] = array('no' => 2, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } break; //check only original file existence //check only original file existence case "ch": case "co": case "cg": if (io::strpos($originalFile, '*') === false) { if (!file_exists($originalFile)) { $error .= "Error at line : " . $line . ", file " . $originalFile . " does not exist<br />"; $errorsInfo[] = array('no' => 3, 'line' => $line, 'command' => $aInstallCheck); $filesExists = false; //in this 2 case don't unset this command if it has an error because the file needed may be created by this script if ($installParams[0] != 'co' && $installParams[0] != 'cg') { unset($array[$line - 1]); } } } break; } if ($filesExists) { //then if files are ok, check installation request switch ($installParams[0]) { case ">": //add or update a file or folder if (in_array($installParams[1], $updateDeny) && !is_file($patchFile . '.updated')) { $error .= "Error at line : " . $line . ", file " . $installParams[1] . " is in the UPDATE.DENY list<br />"; $errorsInfo[] = array('no' => 5, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } else { if (file_exists($originalFile)) { //check if file is writable if (!CMS_FILE::makeWritable($originalFile)) { $error .= "Error at line : " . $line . ", file " . $originalFile . " is not writable<br />"; $errorsInfo[] = array('no' => 6, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } else { //check if parent directory is writable $parent = CMS_file::getParent($originalFile); if (!CMS_FILE::makeWritable($parent)) { $error .= "Error at line : " . $line . ", file " . dirname($originalFile) . " is not writable<br />"; $errorsInfo[] = array('no' => 7, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } } //check right presence and format if (isset($installParams[2]) && $installParams[2]) { if (!$this->_checkRightFormat($installParams[2])) { $error .= "Error at line : " . $line . ", right command malformed<br />"; $errorsInfo[] = array('no' => 8, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } break; case "<": //delete a file or folder (recursively) if (in_array($installParams[1], $updateDeny)) { $error .= "Error at line : " . $line . ", file " . $installParams[1] . " is in the UPDATE.DENY list<br />"; $errorsInfo[] = array('no' => 9, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } else { if (file_exists($originalFile)) { //check if file or directory is deletable if (is_file($originalFile)) { if (!CMS_FILE::makeWritable($originalFile)) { $error .= "Error at line : " . $line . ", file " . $originalFile . " is not deletable<br />"; $errorsInfo[] = array('no' => 10, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } elseif (is_dir($originalFile)) { if (!CMS_FILE::deltreeSimulation($originalFile, true)) { $error .= "Error at line : " . $line . ", directory " . $originalFile . " is not deletable<br />"; $errorsInfo[] = array('no' => 11, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } else { $error .= "Error at line : " . $line . ", what is " . $originalFile . " ???<br />"; $errorsInfo[] = array('no' => 12, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } } break; case "+": //concatenate module xml file //check extension of source file if (io::substr($patchFile, -4, 4) != '.xml') { $error .= "Error at line : " . $line . ", XML file to append " . $patchFile . " does not seem to be an XML file<br />"; $errorsInfo[] = array('no' => 14, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } //Check XML validity of source file $sourceXML = new CMS_file($patchFile); $domdocument = new CMS_DOMDocument(); try { $domdocument->loadXML($sourceXML->readContent("string")); } catch (DOMException $e) { $error .= "Error at line : " . $line . ", XML parse error on file " . $patchFile . " : " . $e->getMessage() . "<br />"; $errorsInfo[] = array('no' => 15, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } //check module to apply XML modifications if ($installParams[2]) { $module = CMS_modulesCatalog::getByCodename($installParams[2]); if ($module === false) { $error .= "Error at line : " . $line . ", module " . $installParams[2] . " does not exist<br />"; $errorsInfo[] = array('no' => 16, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); $filesExists = false; } elseif (!$module->hasParameters()) { $error .= "Error at line : " . $line . ", module " . $installParams[2] . " does not have parameters<br />"; $errorsInfo[] = array('no' => 17, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); $filesExists = false; } } else { $error .= "Error at line : " . $line . ", need module codename<br />"; $errorsInfo[] = array('no' => 18, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); $filesExists = false; } break; case "x": //execute SQL or PHP file //only check extension for the moment if (io::substr($patchFile, -4, 4) != '.sql' && io::substr($patchFile, -4, 4) != '.php') { $error .= "Error at line : " . $line . ", file to execute " . $patchFile . " does not seem to be an SQL or PHP file<br />"; $errorsInfo[] = array('no' => 19, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } if (io::substr($patchFile, -4, 4) == '.sql') { //make a simulation on the sql script if (!$this->executeSqlScript($patchFile, true)) { $error .= "Error at line : " . $line . ", on " . $patchFile . ", no SQL request found..."; $errorsInfo[] = array('no' => 20, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } break; case "ch": //execute chmod //only check right presence and format if (!$installParams[2]) { $error .= "Error at line : " . $line . ", command does not have right<br />"; $errorsInfo[] = array('no' => 21, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } else { if (!$this->_checkRightFormat($installParams[2])) { $error .= "Error at line : " . $line . ", right command malformed<br />"; $errorsInfo[] = array('no' => 22, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } } break; case "co": //execute change owner //execute change owner case "cg": //execute change group //only check right presence if (!$installParams[2]) { $error .= "Error at line : " . $line . ", command does not have right<br />"; $errorsInfo[] = array('no' => 23, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } break; case "rc": //do nothing break; case "htaccess": if (!$installParams[2]) { $error .= "Error at line : " . $line . ", missing htaccess type<br />"; $errorsInfo[] = array('no' => 26, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } elseif (!is_file(PATH_HTACCESS_FS . '/htaccess_' . $installParams[2])) { $error .= "Error at line : " . $line . ", unknown htaccess type : " . $installParams[2] . "<br />"; $errorsInfo[] = array('no' => 26, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } break; default: if (io::substr($installParams[0], 0, 1) != '#') { $error .= "Error at line : " . $line . ", \tunknown parameter : " . $installParams[0] . "<br />"; $errorsInfo[] = array('no' => 25, 'line' => $line, 'command' => $aInstallCheck); unset($array[$line - 1]); } break; } } } } return $error; } else { $this->raiseError("Param must be an array"); return false; } }
/** * function getParent * Get the first parent dir who exists of a file * @param string $file, the full filename of the file to get * @return string : the parent dir filename * @static */ function getParent($file) { if (@file_exists(dirname(realpath($file)))) { return dirname($file); } else { return CMS_file::getParent(dirname($file)); } }