/** * @see wcf\system\package\plugin\IPackageInstallationPlugin::uninstall() */ public function uninstall() { // create ACP-templates list $templates = array(); // get ACP-templates from log $sql = "SELECT * FROM wcf".WCF_N."_acp_template WHERE packageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->installation->getPackageID())); while ($row = $statement->fetchArray()) { // store acp template with suffix (_$packageID) $templates[] = 'acp/templates/'.$row['templateName'].'.tpl'; } if (!empty($templates)) { // delete template files $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir)); $deleteEmptyDirectories = $this->installation->getPackage()->isApplication; $this->installation->deleteFiles($packageDir, $templates, false, $deleteEmptyDirectories); // delete log entries parent::uninstall(); } }
/** * @see \wcf\system\option\IOptionType::getData() */ public function getData(Option $option, $newValue) { $this->createUploadHandler($option); if ($this->uploadHandlers[$option->optionName] === null) { return ''; } $files = $this->uploadHandlers[$option->optionName]->getFiles(); $file = reset($files); // check if file has been uploaded if (!$file->getFilename()) { // if checkbox is checked, remove file if ($newValue) { @unlink($option->optionValue); return ''; } // use old value return $option->optionValue; } else { if ($option->optionValue) { // delete old file first @unlink($option->optionValue); } } // determine location the file will be stored at $package = PackageCache::getInstance()->getPackage($option->packageID); $fileLocation = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $package->packageDir)) . $option->filelocation . '.' . $file->getFileExtension(); // save file move_uploaded_file($file->getLocation(), $fileLocation); // return file location as the value to store in the database return $fileLocation; }
/** * Creates a new Installer object. * * @param string $targetDir * @param string $source * @param \wcf\system\setup\IFileHandler $fileHandler * @param string $folder */ public function __construct($targetDir, $source, $fileHandler = null, $folder = '') { $this->targetDir = FileUtil::addTrailingSlash($targetDir); $this->source = $source; $this->folder = $folder; $this->fileHandler = $fileHandler; $this->install(); }
/** * 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(); }
/** * Extracts all files to the given destination. * The directory-structure inside the .zip is preserved. * * @param string $destination where to extract */ public function extractAll($destination) { $destination = FileUtil::addTrailingSlash($destination); $this->seek(0); while ($this->isFile()) { $offset = $this->tell(); $file = $this->readFile(); $filename = $file['header']['filename']; $this->extract($offset, $destination . $filename); } }
/** * @see wcf\system\cache\source\ICacheSource::clear() */ public function clear($directory, $filepattern) { $pattern = preg_quote(FileUtil::addTrailingSlash($directory), '%') . str_replace('*', '.*', str_replace('.', '\\.', $filepattern)); $apcinfo = apc_cache_info('user'); $cacheList = $apcinfo['cache_list']; foreach ($cacheList as $cache) { if (preg_match('%^' . $pattern . '$%i', $cache['info'])) { apc_delete($cache['info']); } } }
/** * 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(); }
/** * Writes the given e-mail in a log file. * * @param Mail $mail */ public function sendMail(Mail $mail) { if ($this->log === null) { $logFilePath = ''; if (MAIL_DEBUG_LOGFILE_PATH) { $logFilePath = FileUtil::addTrailingSlash(MAIL_DEBUG_LOGFILE_PATH); } else { $logFilePath = WCF_DIR . 'log/'; } $this->log = new File($logFilePath . 'mail.log', 'ab'); } $this->log->write($this->printMail($mail)); }
/** * @see \wcf\form\IForm::readFormParameters() */ public function readFormParameters() { parent::readFormParameters(); if (isset($_POST['templateGroupName'])) { $this->templateGroupName = StringUtil::trim($_POST['templateGroupName']); } if (!empty($_POST['templateGroupFolderName'])) { $this->templateGroupFolderName = StringUtil::trim($_POST['templateGroupFolderName']); if ($this->templateGroupFolderName) { $this->templateGroupFolderName = FileUtil::addTrailingSlash($this->templateGroupFolderName); } } if (isset($_POST['parentTemplateGroupID'])) { $this->parentTemplateGroupID = intval($_POST['parentTemplateGroupID']); } }
/** * Adds a folder to the Zip archive. * * @param string $name dirname */ public function addDir($name, $date = TIME_NOW) { // replace backward slashes with forward slashes in the dirname $name = str_replace("\\", "/", $name); $name = FileUtil::addTrailingSlash($name); // construct the general header information for the directory $header = "PK"; $header .= "\n"; $header .= ""; $header .= ""; // construct the directory header specific information $header .= pack("V", 0); $header .= pack("V", 0); $header .= pack("V", 0); $header .= pack("v", strlen($name)); $header .= pack("v", 0); $header .= $name; $header .= pack("V", 0); $header .= pack("V", 0); $header .= pack("V", 0); // store the complete header information into the $headers array $this->headers[] = $header; // calculate the new offset that will be used the next time a segment is added $newOffset = strlen(implode('', $this->headers)); // construct the general header for the central index record $record = "PK"; $record .= "\n"; $record .= ""; //$record .= "\x00\x00\x00\x00"; $record .= $this->getDosDatetime($date); $record .= pack("V", 0); $record .= pack("V", 0); $record .= pack("V", 0); $record .= pack("v", strlen($name)); $record .= pack("v", 0); $record .= pack("v", 0); $record .= pack("v", 0); $record .= pack("v", 0); //$ext = "\x00\x00\x10\x00"; //$ext = "\xff\xff\xff\xff"; $record .= pack("V", 16); $record .= pack("V", $this->lastOffset); $record .= $name; // save the central index record in the array $data $this->data[] = $record; $this->lastOffset = $newOffset; }
/** * Returns the directory of the application with the given abbrevation. * * @param string $abbreviation * @return string */ public static function getDirectory($abbreviation) { if (static::$directories === null) { static::$directories = array(); // read application directories $packageList = new PackageList(); $packageList->getConditionBuilder()->add('package.isApplication = ?', array(1)); $packageList->readObjects(); foreach ($packageList as $package) { $abbr = Package::getAbbreviation($package->package); static::$directories[$abbr] = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $package->packageDir)); } } if (!isset(static::$directories[$abbreviation])) { throw new SystemException("Unknown application '" . $abbreviation . "'"); } return static::$directories[$abbreviation]; }
/** * Uninstalls the files of this package. */ public function uninstall() { // get absolute package dir $packageDir = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator(realpath(WCF_DIR . $this->installation->getPackage()->packageDir))); // create file list $files = array(); // get files from log $sql = "SELECT\t*\n\t\t\tFROM\twcf" . WCF_N . "_package_installation_file_log\n\t\t\tWHERE \tpackageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->installation->getPackageID())); while ($row = $statement->fetchArray()) { $files[] = $row['filename']; } if (count($files) > 0) { // delete files $this->installation->deleteFiles($packageDir, $files); // delete log entries parent::uninstall(); } }
/** * Uninstalls the templates of this package. */ public function uninstall() { // create templates list $templates = array(); // get templates from log $sql = "SELECT\ttemplateName\n\t\t\tFROM\twcf" . WCF_N . "_template\n\t\t\tWHERE \tpackageID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->installation->getPackageID())); while ($row = $statement->fetchArray()) { $templates[] = 'templates/' . $row['templateName'] . '.tpl'; } if (count($templates) > 0) { // delete template files $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $this->installation->getPackage()->packageDir)); $deleteEmptyDirectories = $this->installation->getPackage()->isApplication; $this->installation->deleteFiles($packageDir, $templates, false, $deleteEmptyDirectories); // delete log entries parent::uninstall(); } }
/** * Compiles LESS stylesheets. * * @param \wcf\data\style\Style $style */ public function compile(Style $style) { // read stylesheets by dependency order $conditions = new PreparedStatementConditionBuilder(); $conditions->add("filename REGEXP ?", array('style/([a-zA-Z0-9\\_\\-\\.]+)\\.less')); $sql = "SELECT\t\tfilename, application\n\t\t\tFROM\t\twcf" . WCF_N . "_package_installation_file_log\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\tpackageID"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $files = array(); while ($row = $statement->fetchArray()) { $files[] = Application::getDirectory($row['application']) . $row['filename']; } // get style variables $variables = $style->getVariables(); $individualLess = ''; if (isset($variables['individualLess'])) { $individualLess = $variables['individualLess']; unset($variables['individualLess']); } // add style image path $imagePath = '../images/'; if ($style->imagePath) { $imagePath = FileUtil::getRelativePath(WCF_DIR . 'style/', WCF_DIR . $style->imagePath); $imagePath = FileUtil::addTrailingSlash(FileUtil::unifyDirSeparator($imagePath)); } $variables['style_image_path'] = "'{$imagePath}'"; // apply overrides if (isset($variables['overrideLess'])) { $lines = explode("\n", StringUtil::unifyNewlines($variables['overrideLess'])); foreach ($lines as $line) { if (preg_match('~^@([a-zA-Z]+): ?([@a-zA-Z0-9 ,\\.\\(\\)\\%\\#-]+);$~', $line, $matches)) { $variables[$matches[1]] = $matches[2]; } } unset($variables['overrideLess']); } $this->compileStylesheet(WCF_DIR . 'style/style-' . $style->styleID, $files, $variables, $individualLess, new Callback(function ($content) use($style) { return "/* stylesheet for '" . $style->styleName . "', generated on " . gmdate('r') . " -- DO NOT EDIT */\n\n" . $content; })); }
/** * @see wcf\data\IEditableCachedObject::resetCache() */ public static function resetCache() { // reset cache CacheHandler::getInstance()->clear(WCF_DIR . 'cache', 'cache.option-*.php'); // reset options.inc.php files $sql = "SELECT\tpackage, packageID, packageDir\n\t\t\tFROM\twcf" . WCF_N . "_package\n\t\t\tWHERE\tisApplication = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array(1)); while ($row = $statement->fetchArray()) { if ($row['package'] == 'com.woltlab.wcf') { $packageDir = WCF_DIR; } else { $packageDir = FileUtil::getRealPath(WCF_DIR . $row['packageDir']); } $filename = FileUtil::addTrailingSlash($packageDir) . self::FILENAME; if (file_exists($filename)) { if (!@touch($filename, 1)) { if (!@unlink($filename)) { self::rebuildFile($filename, $row['packageID']); } } } } }
/** * 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))); }
/** * Compiles LESS stylesheets. * * @param \cms\data\stylesheet\Stylesheet $stylesheet * @param integer $styleID */ public function compile(Stylesheet $stylesheet, $styleID = null) { $styles = StyleHandler::getInstance()->getStyles(); // compile stylesheet for all installed styles if ($styleID === null) { foreach ($styles as $style) { $this->compile($stylesheet, $style->styleID); } return; } $style = $styles[$styleID]; // get style variables $variables = $style->getVariables(); if (isset($variables['individualLess'])) { unset($variables['individualLess']); } // add style image path $imagePath = '../images/'; if ($style->imagePath) { $imagePath = FileUtil::getRelativePath(WCF_DIR . 'style/', WCF_DIR . $style->imagePath); $imagePath = FileUtil::addTrailingSlash(FileUtil::unifyDirSeparator($imagePath)); } $variables['style_image_path'] = "'{$imagePath}'"; // apply overrides if (isset($variables['overrideLess'])) { $lines = explode("\n", StringUtil::unifyNewlines($variables['overrideLess'])); foreach ($lines as $line) { if (preg_match('~^@([a-zA-Z]+): ?([@a-zA-Z0-9 ,\\.\\(\\)\\%\\#-]+);$~', $line, $matches)) { $variables[$matches[1]] = $matches[2]; } } unset($variables['overrideLess']); } // add options as LESS variables foreach (Option::getOptions() as $constantName => $option) { if (in_array($option->optionType, array('boolean', 'integer'))) { $variables['wcf_option_' . mb_strtolower($constantName)] = '~"' . $option->optionValue . '"'; } } // compile $this->compiler->setVariables($variables); $content = "/* stylesheet for '" . $stylesheet->getTitle() . "', generated on " . gmdate('r') . " -- DO NOT EDIT */\n\n"; $content .= $this->compiler->compile($stylesheet->less); // compress stylesheet $lines = explode("\n", $content); $content = $lines[0] . "\n" . $lines[1] . "\n"; for ($i = 2, $length = count($lines); $i < $length; $i++) { $line = trim($lines[$i]); $content .= $line; switch (substr($line, -1)) { case ',': $content .= ' '; break; case '}': $content .= "\n"; break; } if (substr($line, 0, 6) == '@media') { $content .= "\n"; } } // write stylesheet $filename = $stylesheet->getLocation($styleID); file_put_contents($filename, $content); FileUtil::makeWritable($filename); // write rtl stylesheet $content = StyleUtil::convertCSSToRTL($content); $filename = $stylesheet->getLocation($styleID, true); file_put_contents($filename, $content); FileUtil::makeWritable($filename); }
/** * Exports this style. * * @param boolean $templates * @param boolean $images * @param string $packageName */ public function export($templates = false, $images = false, $packageName = '') { // create style tar $styleTarName = FileUtil::getTemporaryFilename('style_', '.tgz'); $styleTar = new TarWriter($styleTarName, true); // append style preview image if ($this->image && @file_exists(WCF_DIR . 'images/' . $this->image)) { $styleTar->add(WCF_DIR . 'images/' . $this->image, '', FileUtil::addTrailingSlash(dirname(WCF_DIR . 'images/' . $this->image))); } // fetch style description $sql = "SELECT\t\tlanguage.languageCode, language_item.languageItemValue\n\t\t\tFROM\t\twcf" . WCF_N . "_language_item language_item\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_language language\n\t\t\tON\t\t(language.languageID = language_item.languageID)\n\t\t\tWHERE\t\tlanguage_item.languageItem = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->styleDescription)); $styleDescriptions = array(); while ($row = $statement->fetchArray()) { $styleDescriptions[$row['languageCode']] = $row['languageItemValue']; } // create style info file $xml = new XMLWriter(); $xml->beginDocument('style', 'http://www.woltlab.com', 'http://www.woltlab.com/XSD/maelstrom/style.xsd'); // general block $xml->startElement('general'); $xml->writeElement('stylename', $this->styleName); // style description foreach ($styleDescriptions as $languageCode => $value) { $xml->writeElement('description', $value, array('language' => $languageCode)); } $xml->writeElement('date', $this->styleDate); $xml->writeElement('version', $this->styleVersion); if ($this->image) { $xml->writeElement('image', $this->image); } if ($this->copyright) { $xml->writeElement('copyright', $this->copyright); } if ($this->license) { $xml->writeElement('license', $this->license); } $xml->endElement(); // author block $xml->startElement('author'); $xml->writeElement('authorname', $this->authorName); if ($this->authorURL) { $xml->writeElement('authorurl', $this->authorURL); } $xml->endElement(); // files block $xml->startElement('files'); $xml->writeElement('variables', 'variables.xml'); if ($templates) { $xml->writeElement('templates', 'templates.tar'); } if ($images) { $xml->writeElement('images', 'images.tar', array('path' => $this->imagePath)); } $xml->endElement(); // append style info file to style tar $styleTar->addString(self::INFO_FILE, $xml->endDocument()); unset($string); // create variable list $xml->beginDocument('variables', 'http://www.woltlab.com', 'http://www.woltlab.com/XSD/maelstrom/styleVariables.xsd'); // get variables $sql = "SELECT\t\tvariable.variableName, value.variableValue\n\t\t\tFROM\t\twcf" . WCF_N . "_style_variable_value value\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_style_variable variable\n\t\t\tON\t\t(variable.variableID = value.variableID)\n\t\t\tWHERE\t\tvalue.styleID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->styleID)); while ($row = $statement->fetchArray()) { $xml->writeElement('variable', $row['variableValue'], array('name' => $row['variableName'])); } // append variable list to style tar $styleTar->addString('variables.xml', $xml->endDocument()); unset($string); if ($templates && $this->templateGroupID) { $templateGroup = new TemplateGroup($this->templateGroupID); // create templates tar $templatesTarName = FileUtil::getTemporaryFilename('templates', '.tar'); $templatesTar = new TarWriter($templatesTarName); FileUtil::makeWritable($templatesTarName); // append templates to tar // get templates $sql = "SELECT\t\ttemplate.*, package.package\n\t\t\t\tFROM\t\twcf" . WCF_N . "_template template\n\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_package package\n\t\t\t\tON\t\t(package.packageID = template.packageID)\n\t\t\t\tWHERE\t\ttemplate.templateGroupID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->templateGroupID)); while ($row = $statement->fetchArray()) { $packageDir = 'com.woltlab.wcf'; $package = null; if ($row['application'] != 'wcf') { $application = ApplicationHandler::getInstance()->getApplication($row['application']); $package = PackageCache::getInstance()->getPackage($application->packageID); $packageDir = $package->package; } else { $application = ApplicationHandler::getInstance()->getWCF(); $package = PackageCache::getInstance()->getPackage($application->packageID); } $filename = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $package->packageDir . 'templates/' . $templateGroup->templateGroupFolderName)) . $row['templateName'] . '.tpl'; $templatesTar->add($filename, $packageDir, dirname($filename)); } // append templates tar to style tar $templatesTar->create(); $styleTar->add($templatesTarName, 'templates.tar', $templatesTarName); @unlink($templatesTarName); } if ($images && ($this->imagePath && $this->imagePath != 'images/')) { // create images tar $imagesTarName = FileUtil::getTemporaryFilename('images_', '.tar'); $imagesTar = new TarWriter($imagesTarName); FileUtil::makeWritable($imagesTarName); // append images to tar $path = FileUtil::addTrailingSlash(WCF_DIR . $this->imagePath); if (file_exists($path) && is_dir($path)) { $handle = opendir($path); $regEx = new Regex('\\.(jpg|jpeg|gif|png|svg)$', Regex::CASE_INSENSITIVE); while (($file = readdir($handle)) !== false) { if (is_file($path . $file) && $regEx->match($file)) { $imagesTar->add($path . $file, '', $path); } } } // append images tar to style tar $imagesTar->create(); $styleTar->add($imagesTarName, 'images.tar', $imagesTarName); @unlink($imagesTarName); } // output file content $styleTar->create(); // export as style package if (empty($packageName)) { readfile($styleTarName); } else { // export as package // create package tar $packageTarName = FileUtil::getTemporaryFilename('package_', '.tar.gz'); $packageTar = new TarWriter($packageTarName, true); // append style tar $styleTarName = FileUtil::unifyDirSeparator($styleTarName); $packageTar->add($styleTarName, '', FileUtil::addTrailingSlash(dirname($styleTarName))); // create package.xml $xml->beginDocument('package', 'http://www.woltlab.com', 'http://www.woltlab.com/XSD/maelstrom/package.xsd', array('name' => $packageName)); $xml->startElement('packageinformation'); $xml->writeElement('packagename', $this->styleName); // description foreach ($styleDescriptions as $languageCode => $value) { $xml->writeElement('packagedescription', $value, array('language' => $languageCode)); } $xml->writeElement('version', $this->styleVersion); $xml->writeElement('date', $this->styleDate); $xml->endElement(); $xml->startElement('authorinformation'); $xml->writeElement('author', $this->authorName); if ($this->authorURL) { $xml->writeElement('authorurl', $this->authorURL); } $xml->endElement(); $xml->startElement('requiredpackages'); $xml->writeElement('requiredpackage', 'com.woltlab.wcf', array('minversion' => PackageCache::getInstance()->getPackageByIdentifier('com.woltlab.wcf')->packageVersion)); $xml->endElement(); $xml->startElement('excludedpackages'); $xml->writeElement('excludedpackage', 'com.woltlab.wcf', array('version' => self::EXCLUDE_WCF_VERSION)); $xml->endElement(); $xml->startElement('instructions', array('type' => 'install')); $xml->writeElement('instruction', basename($styleTarName), array('type' => 'style')); $xml->endElement(); // append package info file to package tar $packageTar->addString(PackageArchive::INFO_FILE, $xml->endDocument()); $packageTar->create(); readfile($packageTarName); @unlink($packageTarName); } @unlink($styleTarName); }
/** * @see wcf\system\cache\source\ICacheSource::clear() */ public function clear($directory, $filepattern) { $this->loadLog(); $pattern = preg_quote(FileUtil::addTrailingSlash($directory), '%') . str_replace('*', '.*', str_replace('.', '\\.', $filepattern)); foreach ($this->cacheResources as $cacheResource) { if (preg_match('%^' . $pattern . '$%i', $cacheResource)) { $this->getAdapter()->getMemcache()->delete($cacheResource); $this->removeFromLog($cacheResource); } } }
/** * Returns the list endpoint for package servers. * * @param boolean $forceHTTP * @return string */ public function getListURL($forceHTTP = false) { if ($this->apiVersion == '2.0') { return $this->serverURL; } $serverURL = FileUtil::addTrailingSlash($this->serverURL) . 'list/' . WCF::getLanguage()->getFixedLanguageCode() . '.xml'; $metaData = $this->getMetaData(); if ($forceHTTP || !RemoteFile::supportsSSL() || !$metaData['ssl']) { return preg_replace('~^https://~', 'http://', $serverURL); } return preg_replace('~^http://~', 'https://', $serverURL); }
/** * Redirects the user agent. * * @param string $location * @param boolean $prependDir * @param boolean $sendStatusCode */ public static function redirect($location, $prependDir = true, $sendStatusCode = false) { if ($prependDir) { // remove path info from request URI $requestURI = WCF::getSession()->requestURI; if (($pos = strpos($requestURI, '.php')) !== false) { $requestURI = substr($requestURI, 0, $pos + 4); } $location = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator(dirname($requestURI))) . $location; } //if ($sendStatusCode) @header('HTTP/1.0 301 Moved Permanently'); if ($sendStatusCode) { @header('HTTP/1.1 307 Temporary Redirect'); } header('Location: ' . $location); }
protected function exportAttachments($conversation, $offset, $limit) { static $upload_path = null; if ($upload_path === null) { $sql = "SELECT\tconfig_name, config_value\n\t\t\t\tFROM\t" . $this->databasePrefix . "config\n\t\t\t\tWHERE\tconfig_name IN (?)"; $statement = $this->database->prepareStatement($sql); $statement->execute(array('upload_path')); while ($row = $statement->fetchArray()) { ${$row}['config_name'] = $row['config_value']; } } $sql = "SELECT\t\t*\n\t\t\tFROM\t\t" . $this->databasePrefix . "attachments\n\t\t\tWHERE\t\tin_message = ?\n\t\t\tORDER BY\tattach_id DESC"; $statement = $this->database->prepareStatement($sql, $limit, $offset); $statement->execute(array($conversation ? 1 : 0)); while ($row = $statement->fetchArray()) { $fileLocation = FileUtil::addTrailingSlash($this->fileSystemPath . $upload_path) . $row['physical_filename']; $isImage = 0; if ($row['mimetype'] == 'image/jpeg' || $row['mimetype'] == 'image/png' || $row['mimetype'] == 'image/gif') { $isImage = 1; } ImportHandler::getInstance()->getImporter('com.woltlab.' . ($conversation ? 'wcf.conversation' : 'wbb') . '.attachment')->import(0, array('objectID' => $row['post_msg_id'], 'userID' => $row['poster_id'] ?: null, 'filename' => $row['real_filename'], 'filesize' => $row['filesize'], 'fileType' => $row['mimetype'], 'isImage' => $isImage, 'downloads' => $row['download_count'], 'uploadTime' => $row['filetime']), array('fileLocation' => $fileLocation)); } }
/** * Builds a new request. * * @param string $application */ protected function buildRequest($application) { try { $routeData = RouteHandler::getInstance()->getRouteData(); // handle landing page for frontend requests if (!$this->isACPRequest()) { $this->handleDefaultController($application, $routeData); // check if accessing from the wrong domain (e.g. "www." omitted but domain was configured with) if (!defined('WCF_RUN_MODE') || WCF_RUN_MODE != 'embedded') { $applicationObject = ApplicationHandler::getInstance()->getApplication($application); if ($applicationObject->domainName != $_SERVER['HTTP_HOST']) { // build URL, e.g. http://example.net/forum/ $url = FileUtil::addTrailingSlash(RouteHandler::getProtocol() . $applicationObject->domainName . RouteHandler::getPath()); if (URL_LEGACY_MODE) { // add path info, e.g. index.php/Board/2/ $pathInfo = RouteHandler::getPathInfo(); if (!empty($pathInfo)) { $url .= 'index.php' . $pathInfo; } } // query string, e.g. ?foo=bar if (!empty($_SERVER['QUERY_STRING'])) { $url .= '?' . $_SERVER['QUERY_STRING']; } HeaderUtil::redirect($url, true); exit; } } // handle controller aliasing if (empty($routeData['isImplicitController']) && !URL_LEGACY_MODE && isset($routeData['controller'])) { $ciController = mb_strtolower($routeData['controller']); // aliased controller, redirect to new URL $alias = $this->getAliasByController($ciController); if ($alias !== null) { $this->redirect($routeData, $application); } $controller = $this->getControllerByAlias($ciController); if ($controller !== null) { // check if controller was provided explicitly as it should $alias = $this->getAliasByController($controller); if ($alias != $routeData['controller']) { $routeData['controller'] = $controller; $this->redirect($routeData, $application); } $routeData['controller'] = $controller; } } } else { if (empty($routeData['controller'])) { $routeData['controller'] = 'Index'; } } $controller = $routeData['controller']; // validate class name if (!preg_match('~^[a-z0-9-]+$~i', $controller)) { throw new SystemException("Illegal class name '" . $controller . "'"); } // work-around for WCFSetup if (!PACKAGE_ID) { $parts = explode('-', $controller); $parts = array_map(function ($part) { return ucfirst($part); }, $parts); $controller = implode('', $parts); } // find class $classData = $this->getClassData($controller, 'page', $application); if ($classData === null) { $classData = $this->getClassData($controller, 'form', $application); } if ($classData === null) { $classData = $this->getClassData($controller, 'action', $application); } if ($classData === null) { throw new SystemException("unable to find class for controller '" . $controller . "'"); } else { if (!class_exists($classData['className'])) { throw new SystemException("unable to find class '" . $classData['className'] . "'"); } } // check if controller was provided exactly as it should if (!URL_LEGACY_MODE && !$this->isACPRequest()) { if (preg_match('~([A-Za-z0-9]+)(?:Action|Form|Page)$~', $classData['className'], $matches)) { $realController = self::getTokenizedController($matches[1]); if ($controller != $realController) { $this->redirect($routeData, $application, $matches[1]); } } } $this->activeRequest = new Request($classData['className'], $classData['controller'], $classData['pageType']); } catch (SystemException $e) { throw new IllegalLinkException(); } }
/** * Prompts for a text input for package directory (applies for applications only) * * @return wcf\system\form\FormDocument */ protected function promptPackageDir() { if (!PackageInstallationFormManager::findForm($this->queue, 'packageDir')) { $container = new GroupFormElementContainer(); $packageDir = new TextInputFormElement($container); $packageDir->setName('packageDir'); $packageDir->setLabel(WCF::getLanguage()->get('wcf.acp.package.packageDir.input')); $path = RouteHandler::getPath(array('wcf', 'acp')); $defaultPath = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator($_SERVER['DOCUMENT_ROOT'] . $path)); $packageDir->setValue($defaultPath); $container->appendChild($packageDir); $document = new FormDocument('packageDir'); $document->appendContainer($container); PackageInstallationFormManager::registerForm($this->queue, $document); return $document; } else { $document = PackageInstallationFormManager::getForm($this->queue, 'packageDir'); $document->handleRequest(); $packageDir = $document->getValue('packageDir'); if ($packageDir !== null) { // validate package dir if (file_exists(FileUtil::addTrailingSlash($packageDir) . 'global.php')) { $document->setError('packageDir', WCF::getLanguage()->get('wcf.acp.package.packageDir.notAvailable')); return $document; } // set package dir $packageEditor = new PackageEditor($this->getPackage()); $packageEditor->update(array( 'packageDir' => FileUtil::getRelativePath(WCF_DIR, $packageDir) )); // parse domain path $domainPath = FileUtil::getRelativePath(FileUtil::unifyDirSeperator($_SERVER['DOCUMENT_ROOT']), FileUtil::unifyDirSeperator($packageDir)); // work-around for applications installed in document root if ($domainPath == './') { $domainPath = ''; } $domainPath = FileUtil::addLeadingSlash(FileUtil::addTrailingSlash($domainPath)); // update application path $application = new Application($this->getPackage()->packageID); $applicationEditor = new ApplicationEditor($application); $applicationEditor->update(array( 'domainPath' => $domainPath, 'cookiePath' => $domainPath )); // create directory and set permissions @mkdir($packageDir, 0777, true); @chmod($packageDir, 0777); } return null; } }
/** * Returns the storage path. * * @return string */ public static function getStorage() { if (ATTACHMENT_STORAGE) { return FileUtil::addTrailingSlash(ATTACHMENT_STORAGE); } return WCF_DIR . 'attachments/'; }
/** * Scans the given dir for installed files. * * @param string $dir */ protected function getInstalledFiles($dir) { if ($files = glob($dir . '*')) { foreach ($files as $file) { if (is_dir($file)) { $this->getInstalledFiles(FileUtil::addTrailingSlash($file)); } else { self::$installedFiles[] = FileUtil::unifyDirSeparator($file); } } } }
/** * Exports attachments. */ public function exportAttachments($offset, $limit) { $sql = "SELECT\t\t*\n\t\t\tFROM\t\t" . $this->databasePrefix . "kunena_attachments\n\t\t\tWHERE\t\tid BETWEEN ? AND ?\n\t\t\tORDER BY\tid"; $statement = $this->database->prepareStatement($sql); $statement->execute(array($offset + 1, $offset + $limit)); while ($row = $statement->fetchArray()) { $fileLocation = FileUtil::addTrailingSlash($this->fileSystemPath . $row['folder']) . $row['filename']; $isImage = 0; if ($row['filetype'] == 'image/jpeg' || $row['filetype'] == 'image/png' || $row['filetype'] == 'image/gif') { $isImage = 1; } ImportHandler::getInstance()->getImporter('com.woltlab.wbb.attachment')->import($row['id'], array('objectID' => $row['mesid'], 'userID' => $row['userid'] ?: null, 'filename' => $row['filename'], 'filesize' => $row['size'], 'fileType' => $row['filetype'], 'isImage' => $isImage), array('fileLocation' => $fileLocation)); } }
/** * Returns absolute domain path. * * @param array $removeComponents * @return string */ public static function getPath(array $removeComponents = array()) { if (empty(self::$path)) { self::$path = FileUtil::addTrailingSlash(dirname($_SERVER['SCRIPT_NAME'])); } if (!empty($removeComponents)) { $path = explode('/', self::$path); foreach ($path as $index => $component) { if (empty($path[$index])) { unset($path[$index]); } if (in_array($component, $removeComponents)) { unset($path[$index]); } } return '/' . implode('/', $path) . '/'; } return self::$path; }
/** * Writes the config.inc.php for an application. * * @param integer $packageID */ public static function writeConfigFile($packageID) { $package = new Package($packageID); $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$package->packageDir)); $file = new File($packageDir.PackageInstallationDispatcher::CONFIG_FILE); $file->write("<?php\n"); $prefix = strtoupper(self::getAbbreviation($package->package)); $file->write("// ".$package->package." (packageID ".$package->packageID.")\n"); $file->write("if (!defined('".$prefix."_DIR')) define('".$prefix."_DIR', dirname(__FILE__).'/');\n"); $file->write("if (!defined('RELATIVE_".$prefix."_DIR')) define('RELATIVE_".$prefix."_DIR', '');\n"); $file->write("\n"); // write general information $file->write("// general info\n"); $file->write("if (!defined('RELATIVE_WCF_DIR')) define('RELATIVE_WCF_DIR', RELATIVE_".$prefix."_DIR.'".FileUtil::getRelativePath($packageDir, WCF_DIR)."');\n"); $file->write("if (!defined('PACKAGE_ID')) define('PACKAGE_ID', ".$packageID.");\n"); $file->write("if (!defined('PACKAGE_NAME')) define('PACKAGE_NAME', '".str_replace("'", "\'", $package->getName())."');\n"); $file->write("if (!defined('PACKAGE_VERSION')) define('PACKAGE_VERSION', '".$package->packageVersion."');\n"); // write end $file->close(); }
/** * Exports post attachments. */ public function exportPostAttachments($offset, $limit) { static $uploadsPath = null; if ($uploadsPath === null) { $sql = "SELECT\tvalue\n\t\t\t\tFROM\t" . $this->databasePrefix . "settings\n\t\t\t\tWHERE\tname = ?"; $statement = $this->database->prepareStatement($sql); $statement->execute(array('uploadspath')); $row = $statement->fetchArray(); $uploadsPath = $row['value']; if (!StringUtil::startsWith($uploadsPath, '/')) { $uploadsPath = realpath($this->fileSystemPath . $uploadsPath); } } $sql = "SELECT\t\t*\n\t\t\tFROM\t\t" . $this->databasePrefix . "attachments\n\t\t\tWHERE\t\taid BETWEEN ? AND ?\n\t\t\tORDER BY\taid"; $statement = $this->database->prepareStatement($sql); $statement->execute(array($offset + 1, $offset + $limit)); while ($row = $statement->fetchArray()) { $fileLocation = FileUtil::addTrailingSlash($uploadsPath) . $row['attachname']; if (!file_exists($fileLocation)) { continue; } if ($imageSize = @getimagesize($fileLocation)) { $row['isImage'] = 1; $row['width'] = $imageSize[0]; $row['height'] = $imageSize[1]; } else { $row['isImage'] = $row['width'] = $row['height'] = 0; } ImportHandler::getInstance()->getImporter('com.woltlab.wbb.attachment')->import($row['aid'], array('objectID' => $row['pid'], 'userID' => $row['uid'] ?: null, 'filename' => $row['filename'], 'filesize' => $row['filesize'], 'fileType' => $row['filetype'], 'isImage' => $row['isImage'], 'width' => $row['width'], 'height' => $row['height'], 'downloads' => $row['downloads'], 'uploadTime' => $row['dateuploaded']), array('fileLocation' => $fileLocation)); } }