/** * Assigns a list of applications to a group and computes cookie domain and path. */ public function rebuild() { if (empty($this->objects)) { $this->readObjects(); } $sql = "UPDATE wcf".WCF_N."_application SET cookieDomain = ?, cookiePath = ? WHERE packageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); // calculate cookie path $domains = array(); foreach ($this->objects as $application) { if (!isset($domains[$application->domainName])) { $domains[$application->domainName] = array(); } $domains[$application->domainName][$application->packageID] = explode('/', FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash($application->domainPath))); } WCF::getDB()->beginTransaction(); foreach ($domains as $domainName => $data) { $path = null; foreach ($data as $domainPath) { if ($path === null) { $path = $domainPath; } else { foreach ($path as $i => $part) { if (!isset($domainPath[$i]) || $domainPath[$i] != $part) { // remove all following elements including current one foreach ($path as $j => $innerPart) { if ($j >= $i) { unset($path[$j]); } } // skip to next domain continue 2; } } } } $path = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash(implode('/', $path))); foreach (array_keys($data) as $packageID) { $statement->execute(array( $domainName, $path, $packageID )); } } WCF::getDB()->commitTransaction(); }
/** * Assigns a list of applications to a group and computes cookie domain and path. */ public function rebuild() { if (empty($this->objects)) { $this->readObjects(); } $sql = "UPDATE\twcf" . WCF_N . "_application\n\t\t\tSET\tcookieDomain = ?,\n\t\t\t\tcookiePath = ?\n\t\t\tWHERE\tpackageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); // calculate cookie path $domains = array(); $regex = new Regex(':[0-9]+'); foreach ($this->objects as $application) { $domainName = $application->domainName; if (StringUtil::endsWith($regex->replace($domainName, ''), $application->cookieDomain)) { $domainName = $application->cookieDomain; } if (!isset($domains[$domainName])) { $domains[$domainName] = array(); } $domains[$domainName][$application->packageID] = explode('/', FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash($application->domainPath))); } WCF::getDB()->beginTransaction(); foreach ($domains as $domainName => $data) { $path = null; foreach ($data as $domainPath) { if ($path === null) { $path = $domainPath; } else { foreach ($path as $i => $part) { if (!isset($domainPath[$i]) || $domainPath[$i] != $part) { // remove all following elements including current one foreach ($path as $j => $innerPart) { if ($j >= $i) { unset($path[$j]); } } // skip to next domain continue 2; } } } } $path = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash(implode('/', $path))); foreach (array_keys($data) as $packageID) { $statement->execute(array($domainName, $path, $packageID)); } } WCF::getDB()->commitTransaction(); // rebuild templates LanguageFactory::getInstance()->deleteLanguageCache(); // reset application cache ApplicationCacheBuilder::getInstance()->reset(); }
/** * Copies a style. * * @return array<string> */ public function copy() { // get unique style name $sql = "SELECT\tstyleName\n\t\t\tFROM\twcf" . WCF_N . "_style\n\t\t\tWHERE\tstyleName LIKE ?\n\t\t\t\tAND styleID <> ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->styleEditor->styleName . '%', $this->styleEditor->styleID)); $numbers = array(); $regEx = new Regex('\\((\\d+)\\)$'); while ($row = $statement->fetchArray()) { $styleName = $row['styleName']; if ($regEx->match($styleName)) { $matches = $regEx->getMatches(); // check if name matches the pattern 'styleName (x)' if ($styleName == $this->styleEditor->styleName . ' (' . $matches[1] . ')') { $numbers[] = $matches[1]; } } } $number = count($numbers) ? max($numbers) + 1 : 2; $styleName = $this->styleEditor->styleName . ' (' . $number . ')'; // create the new style $newStyle = StyleEditor::create(array('styleName' => $styleName, 'templateGroupID' => $this->styleEditor->templateGroupID, 'isDisabled' => 1, 'styleDescription' => $this->styleEditor->styleDescription, 'styleVersion' => $this->styleEditor->styleVersion, 'styleDate' => $this->styleEditor->styleDate, 'copyright' => $this->styleEditor->copyright, 'license' => $this->styleEditor->license, 'authorName' => $this->styleEditor->authorName, 'authorURL' => $this->styleEditor->authorURL, 'imagePath' => $this->styleEditor->imagePath)); // check if style description uses i18n if (preg_match('~^wcf.style.styleDescription\\d+$~', $newStyle->styleDescription)) { $styleDescription = 'wcf.style.styleDescription' . $newStyle->styleID; // copy language items $sql = "INSERT INTO\twcf" . WCF_N . "_language_item\n\t\t\t\t\t\t(languageID, languageItem, languageItemValue, languageItemOriginIsSystem, languageCategoryID, packageID)\n\t\t\t\tSELECT\t\tlanguageID, '" . $styleDescription . "', languageItemValue, 0, languageCategoryID, packageID\n\t\t\t\tFROM\t\twcf" . WCF_N . "_language_item\n\t\t\t\tWHERE\t\tlanguageItem = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($newStyle->styleDescription)); // update style description $styleEditor = new StyleEditor($newStyle); $styleEditor->update(array('styleDescription' => $styleDescription)); } // copy style variables $sql = "INSERT INTO\twcf" . WCF_N . "_style_variable_value\n\t\t\t\t\t(styleID, variableID, variableValue)\n\t\t\tSELECT\t\t" . $newStyle->styleID . " AS styleID, value.variableID, value.variableValue\n\t\t\tFROM\t\twcf" . WCF_N . "_style_variable_value value\n\t\t\tWHERE\t\tvalue.styleID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->styleEditor->styleID)); // copy preview image if ($this->styleEditor->image) { // get extension $fileExtension = mb_substr($this->styleEditor->image, mb_strrpos($this->styleEditor->image, '.')); // copy existing preview image if (@copy(WCF_DIR . 'images/' . $this->styleEditor->image, WCF_DIR . 'images/stylePreview-' . $newStyle->styleID . $fileExtension)) { // bypass StyleEditor::update() to avoid scaling of already fitting image $sql = "UPDATE\twcf" . WCF_N . "_style\n\t\t\t\t\tSET\timage = ?\n\t\t\t\t\tWHERE\tstyleID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array('stylePreview-' . $newStyle->styleID . $fileExtension, $newStyle->styleID)); } } // copy images if ($this->styleEditor->imagePath && is_dir(WCF_DIR . $this->styleEditor->imagePath)) { $path = FileUtil::removeTrailingSlash($this->styleEditor->imagePath); $newPath = ''; $i = 2; while (true) { $newPath = "{$path}-{$i}/"; if (!file_exists(WCF_DIR . $newPath)) { break; } $i++; } if (!FileUtil::makePath(WCF_DIR . $newPath)) { $newPath = ''; } if ($newPath) { $src = FileUtil::addTrailingSlash(WCF_DIR . $this->styleEditor->imagePath); $dst = WCF_DIR . $newPath; $dir = opendir($src); while (($file = readdir($dir)) !== false) { if ($file != '.' && $file != '..' && !is_dir($file)) { @copy($src . $file, $dst . $file); } } closedir($dir); } $sql = "UPDATE\twcf" . WCF_N . "_style\n\t\t\t\tSET\timagePath = ?\n\t\t\t\tWHERE\tstyleID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($newPath, $newStyle->styleID)); } StyleCacheBuilder::getInstance()->reset(); return array('redirectURL' => LinkHandler::getInstance()->getLink('StyleEdit', array('id' => $newStyle->styleID))); }
/** * Returns available location path. * * @param string $location * @return string */ protected static function getFileLocation($location) { $location = FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash($location)); $location = WCF_DIR . $location; $index = null; do { $directory = $location . ($index === null ? '' : $index); if (!is_dir($directory)) { @mkdir($directory, 0777, true); FileUtil::makeWritable($directory); return FileUtil::addTrailingSlash($directory); } $index = $index === null ? 2 : $index + 1; } while (true); }
/** * Starts the extracting of the files. */ protected function install() { $this->createTargetDir(); // open source archive $tar = new Tar($this->source); // distinct directories and files $directories = array(); $files = array(); foreach ($tar->getContentList() as $index => $file) { if (empty($this->folder) || mb_strpos($file['filename'], $this->folder) === 0) { if (!empty($this->folder)) { $file['filename'] = str_replace($this->folder, '', $file['filename']); } // remove leading slash $file['filename'] = FileUtil::removeLeadingSlash($file['filename']); if ($file['type'] == 'folder') { // remove trailing slash $directories[] = FileUtil::removeTrailingSlash($file['filename']); } else { $files[$index] = $file['filename']; } } } $this->checkFiles($files); // now create the directories $errors = array(); foreach ($directories as $dir) { try { $this->createDir($dir); } catch (SystemException $e) { $errors[] = $e->getMessage(); } } // now untar all files foreach ($files as $index => $file) { try { $this->createFile($file, $index, $tar); } catch (SystemException $e) { $errors[] = $e->getMessage(); } } if (!empty($errors)) { throw new SystemException('error(s) during the installation of the files.', 0, implode("<br />", $errors)); } $this->logFiles($files); // close tar $tar->close(); }
/** * Searches the wcf dir. */ protected function searchWcfDir() { if (self::$wcfDir) { $wcfDir = self::$wcfDir; } else { $wcfDir = FileUtil::unifyDirSeparator(INSTALL_SCRIPT_DIR) . 'wcf/'; } $invalidDirectory = false; if (@is_file($wcfDir . 'lib/system/WCF.class.php')) { $invalidDirectory = true; } // domain $domainName = ''; if (!empty($_SERVER['SERVER_NAME'])) { $domainName = 'http://' . $_SERVER['SERVER_NAME']; } // port if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != 80) { $domainName .= ':' . $_SERVER['SERVER_PORT']; } // script url $installScriptUrl = ''; if (!empty($_SERVER['REQUEST_URI'])) { $installScriptUrl = FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash(FileUtil::unifyDirSeparator(dirname($_SERVER['REQUEST_URI'])))); } WCF::getTPL()->assign(array('nextStep' => 'unzipFiles', 'invalidDirectory' => $invalidDirectory, 'wcfDir' => $wcfDir, 'domainName' => $domainName, 'installScriptUrl' => $installScriptUrl, 'installScriptDir' => FileUtil::unifyDirSeparator(INSTALL_SCRIPT_DIR))); WCF::getTPL()->display('stepSearchWcfDir'); }
/** * Searches the wcf dir. */ protected function searchWcfDir() { $foundDirectory = ''; if (self::$wcfDir) { $wcfDir = self::$wcfDir; } else { if ($foundDirectory = FileUtil::scanFolder(INSTALL_SCRIPT_DIR, "WCF.class.php", true)) { $foundDirectory = $wcfDir = FileUtil::unifyDirSeperator(dirname(dirname(dirname($foundDirectory))) . '/'); if (dirname(dirname($wcfDir)) . '/' == TMP_DIR) { $foundDirectory = false; $wcfDir = FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR) . 'wcf/'; } } else { $wcfDir = FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR) . 'wcf/'; } } // domain $domainName = ''; if (!empty($_SERVER['SERVER_NAME'])) { $domainName = 'http://' . $_SERVER['SERVER_NAME']; } // port if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != 80) { $domainName .= ':' . $_SERVER['SERVER_PORT']; } // script url $installScriptUrl = ''; if (!empty($_SERVER['REQUEST_URI'])) { $installScriptUrl = FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash(FileUtil::unifyDirSeperator(dirname($_SERVER['REQUEST_URI'])))); } WCF::getTPL()->assign(array('nextStep' => 'unzipFiles', 'foundDirectory' => $foundDirectory, 'wcfDir' => $wcfDir, 'domainName' => $domainName, 'installScriptUrl' => $installScriptUrl, 'installScriptDir' => FileUtil::unifyDirSeperator(INSTALL_SCRIPT_DIR))); WCF::getTPL()->display('stepSearchWcfDir'); }
/** * @see wcf\form\IForm::validate() */ public function validate() { parent::validate(); if (empty($this->domainName)) { throw new UserInputException('domainName'); } else { $regex = new Regex('^https?\://'); $this->domainName = FileUtil::removeTrailingSlash($regex->replace($this->domainName, '')); $this->cookieDomain = FileUtil::removeTrailingSlash($regex->replace($this->cookieDomain, '')); // domain may not contain path components $regex = new Regex('[/#\?&]'); if ($regex->match($this->domainName)) { throw new UserInputException('domainName', 'containsPath'); } else if ($regex->match($this->cookieDomain)) { throw new UserInputException('cookieDomain', 'containsPath'); } // check if cookie domain shares the same domain (may exclude subdomains) if (!StringUtil::endsWith($this->domainName, $this->cookieDomain)) { throw new UserInputException('cookieDomain', 'notValid'); } } if (empty($this->domainPath)) { $this->cookiePath = ''; } else { // strip first and last slash $this->domainPath = FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash($this->domainPath)); $this->cookiePath = FileUtil::removeLeadingSlash(FileUtil::removeTrailingSlash($this->cookiePath)); if (!empty($this->cookiePath) && ($this->domainPath != $this->cookiePath)) { // check if cookie path is contained within domain path if (!StringUtil::startsWith($this->domainPath, $this->cookiePath)) { throw new UserInputException('cookiePath', 'notValid'); } } } // add slashes $this->domainPath = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash($this->domainPath)); $this->cookiePath = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash($this->cookiePath)); }
/** * @see \wcf\form\IForm::validate() */ public function validate() { parent::validate(); if (empty($this->domainName)) { throw new UserInputException('domainName'); } else { $regex = new Regex('^https?\\://'); $this->domainName = FileUtil::removeTrailingSlash($regex->replace($this->domainName, '')); $this->cookieDomain = FileUtil::removeTrailingSlash($regex->replace($this->cookieDomain, '')); // domain may not contain path components $regex = new Regex('[/#\\?&]'); if ($regex->match($this->domainName)) { throw new UserInputException('domainName', 'containsPath'); } else { if ($regex->match($this->cookieDomain)) { throw new UserInputException('cookieDomain', 'containsPath'); } } // strip port from cookie domain $regex = new Regex(':[0-9]+$'); $this->cookieDomain = $regex->replace($this->cookieDomain, ''); // check if cookie domain shares the same domain (may exclude subdomains) if (!StringUtil::endsWith($regex->replace($this->domainName, ''), $this->cookieDomain)) { throw new UserInputException('cookieDomain', 'notValid'); } } // add slashes $this->domainPath = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash($this->domainPath)); // search for other applications with the same domain and path $sql = "SELECT\tpackageID\n\t\t\tFROM\twcf" . WCF_N . "_application\n\t\t\tWHERE\tdomainName = ?\n\t\t\t\tAND domainPath = ?\n\t\t\t\tAND packageID <> ?"; $statement = WCF::getDB()->prepareStatement($sql, 1); $statement->execute(array($this->domainName, $this->domainPath, $this->application->packageID)); $row = $statement->fetchArray(); if ($row) { WCF::getTPL()->assign('conflictApplication', PackageCache::getInstance()->getPackage($row['packageID'])); throw new UserInputException('domainPath', 'conflict'); } }