/** * @see \wcf\system\bbcode\highlighter\Highlighter::highlight() */ public function highlight($code) { // add starting php tag $phpTagsAdded = false; if (mb_strpos($code, '<?') === false) { $phpTagsAdded = true; $code = '<?php ' . $code . ' ?>'; } // do highlight $highlightedCode = highlight_string($code, true); // clear code $highlightedCode = str_replace('<code>', '', $highlightedCode); $highlightedCode = str_replace('</code>', '', $highlightedCode); // remove added php tags if ($phpTagsAdded) { $regex = new Regex('([^\\2]*)(<\\?php )(.*)( .*\\?>)([^\\4]*)', Regex::CASE_INSENSITIVE | Regex::DOT_ALL); $highlightedCode = $regex->replace($highlightedCode, '\\1\\3\\5'); } // remove breaks $highlightedCode = str_replace("\n", "", $highlightedCode); $highlightedCode = str_replace('<br />', "\n", $highlightedCode); // get tabs back $highlightedCode = str_replace(' ', "\t", $highlightedCode); // replace non breaking space with normal space, white-space is preserved by CSS $highlightedCode = str_replace(' ', " ", $highlightedCode); // convert colors to classes $highlightedCode = strtr($highlightedCode, self::$colorToClass); // replace double quotes by entity return Regex::compile('(?<!\\<span class=)"(?!\\>)')->replace($highlightedCode, '"'); }
/** * Creates a new instance of memcached. */ public function __construct() { if (!class_exists('Memcached')) { throw new SystemException('memcached support is not enabled.'); } // init memcached $this->memcached = new \Memcached(); // add servers $tmp = explode("\n", StringUtil::unifyNewlines(CACHE_SOURCE_MEMCACHED_HOST)); $servers = array(); $defaultWeight = floor(100 / count($tmp)); $regex = new Regex('^\[([a-z0-9\:\.]+)\](?::([0-9]{1,5}))?(?::([0-9]{1,3}))?$', Regex::CASE_INSENSITIVE); foreach ($tmp as $server) { $server = StringUtil::trim($server); if (!empty($server)) { $host = $server; $port = 11211; // default memcached port $weight = $defaultWeight; // check for IPv6 if ($regex->match($host)) { $matches = $regex->getMatches(); $host = $matches[1]; if (isset($matches[2])) { $port = $matches[2]; } if (isset($matches[3])) { $weight = $matches[3]; } } else { // IPv4, try to get port and weight if (strpos($host, ':')) { $parsedHost = explode(':', $host); $host = $parsedHost[0]; $port = $parsedHost[1]; if (isset($parsedHost[2])) { $weight = $parsedHost[2]; } } } $servers[] = array($host, $port, $weight); } } $this->memcached->addServers($servers); // test connection $this->memcached->get('testing'); // set variable prefix to prevent collision $this->prefix = substr(sha1(WCF_DIR), 0, 8) . '_'; }
/** * 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(); }
/** * @see \wcf\system\database\editor\DatabaseEditor::getColumns() */ public function getColumns($tableName) { $columns = array(); $regex = new Regex('([a-z]+)\\(([0-9]+)\\)', Regex::CASE_INSENSITIVE); $sql = "SHOW COLUMNS FROM " . $tableName; $statement = $this->dbObj->prepareStatement($sql); $statement->execute(); while ($row = $statement->fetchArray()) { $regex->match($row['Type']); $typeMatches = $regex->getMatches(); $columns[] = array('name' => $row['Field'], 'data' => array('type' => empty($typeMatches) ? $row['Type'] : $typeMatches[1], 'length' => empty($typeMatches) ? '' : $typeMatches[2], 'notNull' => $row['Null'] == 'YES' ? false : true, 'key' => $row['Key'] == 'PRI' ? 'PRIMARY' : ($row['Key'] == 'UNI' ? 'UNIQUE' : ''), 'default' => $row['Default'], 'autoIncrement' => $row['Extra'] == 'auto_increment' ? true : false)); } return $columns; }
/** * @see \wcf\system\bbcode\highlighter\Highlighter::highlightKeywords() */ protected function highlightKeywords($string) { $string = Regex::compile('\\$([^\\$]*)\\$', Regex::DOT_ALL)->replace($string, '<span class="hlKeywords2">\\0</span>'); $string = Regex::compile('(\\\\(?:[a-z]+))(\\[[^\\]\\\\]+\\])?(\\{[^\\}]*\\})?', Regex::CASE_INSENSITIVE)->replace($string, '<span class="hlKeywords3">\\1</span><span class="hlKeywords4">\\2</span><span class="hlKeywords1">\\3</span>'); $string = str_replace('\\\\', '<span class="hlKeywords3">\\\\</span>', $string); return $string; }
/** * Returns true if given string equals a language variable. * * @param string $string * @return boolean */ protected function isLanguageVariable($string) { if ($this->regex === null) { $this->regex = new Regex('^([a-zA-Z0-9-_]+\\.)+[a-zA-Z0-9-_]+$'); } return $this->regex->match($string); }
/** * @see \wcf\form\IForm::validate() */ public function validate() { AbstractForm::validate(); if (empty($this->masterPassword)) { throw new UserInputException('masterPassword'); } // check password security if (mb_strlen($this->masterPassword) < 12) { throw new UserInputException('masterPassword', 'notSecure'); } // digits if (!Regex::compile('\\d')->match($this->masterPassword)) { throw new UserInputException('masterPassword', 'notSecure'); } // latin characters (lower-case) if (!Regex::compile('[a-z]')->match($this->masterPassword)) { throw new UserInputException('masterPassword', 'notSecure'); } // latin characters (upper-case) if (!Regex::compile('[A-Z]')->match($this->masterPassword)) { throw new UserInputException('masterPassword', 'notSecure'); } // password equals username if ($this->masterPassword == WCF::getUser()->username) { throw new UserInputException('masterPassword', 'notSecure'); } // confirm master password if (empty($this->confirmMasterPassword)) { throw new UserInputException('confirmMasterPassword'); } if ($this->confirmMasterPassword != $this->masterPassword) { throw new UserInputException('confirmMasterPassword', 'notEqual'); } }
/** * Caches scripts and styles in the given string. * * @param string $string * @return string */ protected function cacheScriptsAndStyles($string) { $regex = new Regex('(<(style|script)[^>]*>)(.*?)(</\\2>)', Regex::CASE_INSENSITIVE | Regex::DOT_ALL); return $regex->replace($string, new Callback(function ($matches) { $type = $matches[2] === 'script' ? 'js' : 'css'; // strip slashes $content = str_replace('\\"', '"', $matches[3]); $openingTag = str_replace('\\"', '"', $matches[1]); $closingTag = str_replace('\\"', '"', $matches[4]); if (StringUtil::trim($content) == '') { return $matches[0]; } $class = '\\wcf\\system\\bbcode\\highlighter\\' . ucfirst($type) . 'Highlighter'; return $openingTag . StringStack::pushToStringStack('<span class="' . $type . 'Highlighter">' . $class::getInstance()->highlight($content) . '</span>', 'htmlHighlighter' . ucfirst($type)) . $closingTag; })); }
/** * @see \wcf\system\bbcode\highlighter\Highlighter::highlightComments() */ protected function highlightComments($string) { $string = parent::highlightComments($string); // highlight template tags $string = Regex::compile('\\{(?=\\S).+?(?<=\\S)\\}', Regex::DOT_ALL)->replace($string, '<span class="hlKeywords3">\\0</span>'); return $string; }
/** * @see \wcf\system\bbcode\highlighter\Highlighter::cacheQuotes() */ protected function cacheQuotes($string) { $string = parent::cacheQuotes($string); // highlight CDATA-Tags as quotes $string = Regex::compile('<!\\[CDATA\\[.*?\\]\\]>', Regex::DOT_ALL)->replace($string, new Callback(function (array $matches) { return StringStack::pushToStringStack('<span class="hlQuotes">' . StringUtil::encodeHTML($matches[0]) . '</span>', 'highlighterQuotes'); })); return $string; }
/** * Checks whether this question matches the given message. * * @param string $message * @return boolean */ public function matches($message) { $lines = explode("\n", \wcf\util\StringUtil::unifyNewlines($this->questionMessage)); foreach ($lines as $line) { if (\wcf\system\Regex::compile($line)->match($message)) { return true; } } return false; }
/** * Handles the saved event. * * @param array $parameter */ protected function saved(array $parameter) { // get message, check by difference is quickreply or postadd $message = $parameter == null ? $this->eventObj->text : $parameter['message']->message; //if (!\wcf\system\Regex::compile('(^Butler.*$)')->match($message, true)) return; // get cached questions from cache, filter it by array functions, easier then foreach $questions = \wbb\data\post\butler\question\QuestionCache::getInstance()->getQuestions(); $questions = array_filter(array_map(function ($question) use($message) { if (!\wcf\system\Regex::compile(sprintf('(^%s.*$)', empty($question->prefixUsername) ? 'Butler' : $question->prefixUsername))->match($message, true)) { return false; } else { return $question->matches($message); } }, $questions), function ($value) { if ($value) { return $value; } }); // check if a value is given, otherwise abort continue of function if ($questions == null) { return; } else { $question = \wbb\data\post\butler\question\QuestionCache::getInstance()->getQuestionByID(array_rand($questions, 1)); } // get cached answers from cache, try to get only assigned answers $answers = \wbb\data\post\butler\answer\AnswerCache::getInstance()->getAnswers(); $answers = $answers[$question->questionID]; // check if a value is given and declare variable on success, otherwise abort function if ($answers == null) { return; } else { $answer = $answers[array_rand($answers, 1)]; } $threadID = 0; if ($parameter == null) { $threadActionObject = $this->eventObj->objectAction->getReturnValues(); $threadID = $threadActionObject['returnValues']->threadID; } else { $threadID = $this->eventObj->getContainer()->threadID; } $author = null; if ($question->prefixUserID > 0) { $author = \wcf\data\user\User::getUsers(array($question->prefixUserID)); if (count($author) == 1) { $author = array_shift($author); } } $postData = array('threadID' => $threadID, 'userID' => $question->prefixUserID == 0 ? null : $question->prefixUserID, 'username' => $author == null ? empty($question->prefixUsername) ? 'Butler' : $question->prefixUsername : $author->username, 'message' => $answer->getFormattedMessage(), 'time' => TIME_NOW, 'enableSmilies' => $answer->enableSmilies, 'enableHtml' => $answer->enableHtml, 'enableBBCodes' => $answer->enableBBCodes, 'showSignature' => 0); $objectAction = new \wbb\data\post\PostAction(array(), 'create', array('data' => $postData)); $objectAction->executeAction(); }
/** * Parses controller name. */ protected function parseController() { if ($this->controller === null) { $this->controller = ''; // resolve application and controller if ($this->menuItemController) { $parts = explode('\\', $this->menuItemController); $this->application = array_shift($parts); $menuItemController = array_pop($parts); // drop controller suffix $this->controller = Regex::compile('(Action|Form|Page)$')->replace($menuItemController, ''); } } }
/** * Gets the package_update.xml from an update server. * * @param wcf\data\package\update\server\PackageUpdateServer $updateServer */ protected function getPackageUpdateXML(PackageUpdateServer $updateServer) { $authData = $updateServer->getAuthData(); $settings = array(); if ($authData) $settings['auth'] = $authData; $postData = array( 'lastUpdateTime' => $updateServer->lastUpdateTime ); // append auth code if set and update server resolves to woltlab.com if (PACKAGE_SERVER_AUTH_CODE && Regex::compile('^https?://[a-z]+.woltlab.com/')->match($updateServer->serverURL)) { $postData['authCode'] = PACKAGE_SERVER_AUTH_CODE; } $request = new HTTPRequest($updateServer->serverURL, $settings, $postData); try { $request->execute(); $reply = $request->getReply(); } catch (SystemException $e) { $reply = $request->getReply(); if ($reply['statusCode'] == 401) { throw new PackageUpdateAuthorizationRequiredException($updateServer['packageUpdateServerID'], $updateServer['server'], $reply); } throw new SystemException(WCF::getLanguage()->get('wcf.acp.packageUpdate.error.listNotFound') . ' ('.reset($reply['headers']).')'); } // parse given package update xml $allNewPackages = $this->parsePackageUpdateXML($reply['body']); unset($request, $reply); // save packages if (!empty($allNewPackages)) { $this->savePackageUpdates($allNewPackages, $updateServer->packageUpdateServerID); } unset($allNewPackages); // update server status $updateServerEditor = new PackageUpdateServerEditor($updateServer); $updateServerEditor->update(array( 'lastUpdateTime' => TIME_NOW, 'status' => 'online', 'errorMessage' => '' )); }
/** * @see wcf\form\IForm::validate() */ public function validate() { ACPForm::validate(); if (empty($this->masterPassword)) { throw new UserInputException('masterPassword'); } // check password security if (StringUtil::length($this->masterPassword) < 8) { throw new UserInputException('masterPassword', 'notSecure'); } // digits if (!Regex::compile('\\d')->match($this->masterPassword)) { throw new UserInputException('masterPassword', 'notSecure'); } // latin characters (lower-case) if (!Regex::compile('[a-z]')->match($this->masterPassword)) { throw new UserInputException('masterPassword', 'notSecure'); } // latin characters (upper-case) if (!Regex::compile('[A-Z]')->match($this->masterPassword)) { throw new UserInputException('masterPassword', 'notSecure'); } // special characters if (!Regex::compile('[^0-9a-zA-Z]')->match($this->masterPassword)) { throw new UserInputException('masterPassword', 'notSecure'); } // password equals username if ($this->masterPassword == WCF::getUser()->username) { throw new UserInputException('masterPassword', 'notSecure'); } // search for identical admin passwords $sql = "SELECT\tpassword, salt\n\t\t\tFROM\twcf" . WCF_N . "_user\n\t\t\tWHERE\tuserID IN (\n\t\t\t\t\tSELECT\tuserID\n\t\t\t\t\tFROM\twcf" . WCF_N . "_user_to_group\n\t\t\t\t\tWHERE\tgroupID = 4\n\t\t\t\t)"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(); while ($row = $statement->fetchArray()) { if (StringUtil::getDoubleSaltedHash($this->masterPassword, $row['salt']) == $row['password']) { throw new UserInputException('masterPassword', 'notSecure'); } } // confirm master password if (empty($this->confirmMasterPassword)) { throw new UserInputException('confirmMasterPassword'); } if ($this->confirmMasterPassword != $this->masterPassword) { throw new UserInputException('confirmMasterPassword', 'notEqual'); } }
/** * Returns true if the given user input is an answer to this question. * * @param string $answer * @return boolean */ public function isAnswer($answer) { $answers = explode("\n", StringUtil::unifyNewlines(WCF::getLanguage()->get($this->answers))); foreach ($answers as $__answer) { if (mb_substr($__answer, 0, 1) == '~' && mb_substr($__answer, -1, 1) == '~') { if (Regex::compile(mb_substr($__answer, 1, mb_strlen($__answer) - 2))->match($answer)) { return true; } continue; } else { if ($__answer == $answer) { return true; } } } return false; }
/** * @see \wcf\form\IForm::validate() */ public function validate() { parent::validate(); // validate fields if (empty($this->title)) { throw new UserInputException('title'); } if (empty($this->regex)) { throw new UserInputException('regex'); } if (empty($this->html)) { throw new UserInputException('html'); } $lines = explode("\n", StringUtil::unifyNewlines($this->regex)); foreach ($lines as $line) { if (!Regex::compile($line)->isValid()) { throw new UserInputException('regex', 'notValid'); } } }
/** * @see \wcf\system\bbcode\highlighter\Highlighter::highlight() */ public function highlight($code) { // add starting php tag $phpTagsAdded = false; if (mb_strpos($code, '<?') === false) { $phpTagsAdded = true; $code = '<?php ' . $code . ' ?>'; } // do highlight $highlightedCode = highlight_string($code, true); // clear code $highlightedCode = str_replace('<code>', '', $highlightedCode); $highlightedCode = str_replace('</code>', '', $highlightedCode); // remove added php tags if ($phpTagsAdded) { // the opening and closing PHP tags were added previously, hence we actually do // know that the first (last for the closing tag) occurence is the one inserted // by us. The previously used regex was bad because it was significantly slower // and could easily hit the backtrace limit for larger inputs $openingTag = mb_strpos($highlightedCode, '<?php '); $closingTag = mb_strrpos($highlightedCode, '?>'); $tmp = mb_substr($highlightedCode, 0, $openingTag); $tmp .= mb_substr($highlightedCode, $openingTag + 14, $closingTag - $openingTag - 14); $tmp .= mb_substr($highlightedCode, $closingTag + 5); $highlightedCode = $tmp; } // remove breaks $highlightedCode = str_replace("\n", "", $highlightedCode); $highlightedCode = str_replace('<br />', "\n", $highlightedCode); // get tabs back $highlightedCode = str_replace(' ', "\t", $highlightedCode); // replace non breaking space with normal space, white-space is preserved by CSS $highlightedCode = str_replace(' ', " ", $highlightedCode); // convert colors to classes $highlightedCode = strtr($highlightedCode, self::$colorToClass); // replace double quotes by entity return Regex::compile('(?<!\\<span class=)"(?!\\>)')->replace($highlightedCode, '"'); }
/** * Returns true if given hash looks like a valid bcrypt hash. * * @param string $hash * @return boolean */ public static function isBlowfish($hash) { return Regex::compile('^\\$2[afxy]\\$')->match($hash) ? true : false; }
/** * @see \wcf\form\IForm::validate() */ public function validate() { parent::validate(); // validate group if (!$this->groupID) { throw new UserInputException('groupID'); } $groups = $this->labelGroupList->getObjects(); if (!isset($groups[$this->groupID])) { throw new UserInputException('groupID', 'notValid'); } // validate label if (!I18nHandler::getInstance()->validateValue('label')) { if (I18nHandler::getInstance()->isPlainValue('label')) { throw new UserInputException('label'); } else { throw new UserInputException('label', 'multilingual'); } } // validate class name if (empty($this->cssClassName)) { throw new UserInputException('cssClassName', 'empty'); } else { if (!in_array($this->cssClassName, $this->availableCssClassNames)) { throw new UserInputException('cssClassName', 'notValid'); } else { if ($this->cssClassName == 'custom') { if (!empty($this->customCssClassName) && !Regex::compile('^-?[_a-zA-Z]+[_a-zA-Z0-9-]+$')->match($this->customCssClassName)) { throw new UserInputException('cssClassName', 'notValid'); } } } } }
/** * 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))); }
/** * Assigns element values to template. Using request data once reading * initial database data is explicitly disallowed. * * @param boolean $useRequestData */ public function assignVariables($useRequestData = true) { $elementValues = array(); $elementValuesI18n = array(); foreach ($this->elementIDs as $elementID) { $value = ''; $i18nValues = array(); if (!$this->assignValueVariablesDisabled) { // use POST values instead of querying database if ($useRequestData) { if ($this->isPlainValue($elementID)) { $value = $this->getValue($elementID); } else { if ($this->hasI18nValues($elementID)) { $i18nValues = $this->i18nValues[$elementID]; // encoding the entries for javascript foreach ($i18nValues as $languageID => $value) { $i18nValues[$languageID] = StringUtil::encodeJS(StringUtil::unifyNewlines($value)); } } else { $i18nValues = array(); } } } else { $isI18n = Regex::compile('^'.$this->elementOptions[$elementID]['pattern'].'$')->match($this->elementOptions[$elementID]['value']); if (!$isI18n) { // check if it's a regular language variable $isI18n = Regex::compile('^([a-zA-Z0-9-_]+\.)+[a-zA-Z0-9-_]+$')->match($this->elementOptions[$elementID]['value']); } if ($isI18n) { // use i18n values from language items $sql = "SELECT languageID, languageItemValue FROM wcf".WCF_N."_language_item WHERE languageItem = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array( $this->elementOptions[$elementID]['value'] )); while ($row = $statement->fetchArray()) { $i18nValues[$row['languageID']] = StringUtil::encodeJS(StringUtil::unifyNewlines($row['languageItemValue'])); } } else { // use data provided by setOptions() $value = $this->elementOptions[$elementID]['value']; } } } $elementValues[$elementID] = $value; $elementValuesI18n[$elementID] = $i18nValues; } WCF::getTPL()->assign(array( 'availableLanguages' => $this->availableLanguages, 'i18nPlainValues' => $elementValues, 'i18nValues' => $elementValuesI18n )); }
/** * Parses the reply headers. */ private function parseReplyHeaders() { $headers = array(); $lastKey = ''; foreach ($this->replyHeaders as $header) { if (strpos($header, ':') === false) { $headers[trim($header)] = array(trim($header)); continue; } // 4.2 Header fields can be // extended over multiple lines by preceding each extra line with at // least one SP or HT. if (ltrim($header, "\t ") !== $header) { $headers[$lastKey][] = array_pop($headers[$lastKey]) . ' ' . trim($header); } else { list($key, $value) = explode(':', $header, 2); $lastKey = $key; if (!isset($headers[$key])) { $headers[$key] = array(); } $headers[$key][] = trim($value); } } // 4.2 Field names are case-insensitive. $this->replyHeaders = array_change_key_case($headers); if (isset($this->replyHeaders['transfer-encoding'])) { $this->replyHeaders['transfer-encoding'] = array(implode(',', $this->replyHeaders['transfer-encoding'])); } $this->legacyHeaders = array_map('end', $headers); // get status code $statusLine = reset($this->replyHeaders); $regex = new Regex('^HTTP/1.\\d+ +(\\d{3})'); if (!$regex->match($statusLine[0])) { throw new SystemException("Unexpected status '" . $statusLine . "'"); } $matches = $regex->getMatches(); $this->statusCode = $matches[1]; }
/** * 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); }
/** * Returns true if update server requires license data instead of username/password. * * @return integer */ public final function requiresLicense() { return Regex::compile('^https?://update.woltlab.com/')->match($this->serverURL); }
/** * Returns a sorted list of files, with DirectoryIterator object as value * * @param integer $order sort order * @param wcf\system\Regex $pattern pattern to match * @param boolean $negativeMatch should the pattern be inversed * @return array<\DirectoryIterator> */ public function getFileObjects($order = SORT_ASC, Regex $pattern = null, $negativeMatch = false) { // scan the folder $this->scanFileObjects(); $objects = $this->fileObjects; // sort out non matching files if ($pattern !== null) { foreach ($objects as $filename => $value) { if ((bool) $pattern->match($filename) === $negativeMatch) { unset($objects[$filename]); } } } if ($order == SORT_DESC) { krsort($objects, $order); } else { if ($order == SORT_ASC) { ksort($objects, $order); } else { if ($order == self::SORT_NONE) { // nothing to do here :) } else { throw new SystemException('The given sorting is not supported'); } } } return $objects; }
/** * Formats a message for search result output. * * @param string $text * @return string */ public function parse($text) { // remove nonessentials $text = Regex::compile('<!-- begin:parser_nonessential -->.*?<!-- end:parser_nonessential -->', Regex::DOT_ALL)->replace($text, ''); // remove html codes $text = StringUtil::stripHTML($text); // decode html $text = StringUtil::decodeHTML($text); // get abstract $text = $this->getMessageAbstract($text); // encode html $text = StringUtil::encodeHTML($text); // do highlighting return KeywordHighlighter::getInstance()->doHighlight($text); }
private static function fixBBCodes($message) { static $videoRegex = null; static $quoteRegex = null; static $quoteCallback = null; static $imgRegex = null; static $imgCallback = null; static $attachmentRegex = null; if ($videoRegex === null) { $videoRegex = new Regex('\\[video=[a-z]+\\]'); $quoteRegex = new Regex('\\[quote=\'(.*?)\' pid=\'(\\d+)\' dateline=\'\\d+\'\\]'); $quoteCallback = new Callback(function ($matches) { $username = str_replace(array("\\", "'"), array("\\\\", "\\'"), $matches[1]); $postID = $matches[2]; $postLink = LinkHandler::getInstance()->getLink('Thread', array('application' => 'wbb', 'postID' => $postID, 'forceFrontend' => true)) . '#post' . $postID; $postLink = str_replace(array("\\", "'"), array("\\\\", "\\'"), $postLink); return "[quote='" . $username . "','" . $postLink . "']"; }); $imgRegex = new Regex('\\[img(?:=(\\d)x\\d)?(?: align=(left|right))?\\](?:\\r\\n?|\\n?)(https?://(?:[^<>"\']+?))\\[/img\\]'); $imgCallback = new Callback(function ($matches) { $escapedLink = str_replace(array("\\", "'"), array("\\\\", "\\'"), $matches[3]); if ($matches[1] && $matches[2]) { return "[img='" . $escapedLink . "'," . $matches[2] . "," . $matches[1] . "][/img]"; } else { if ($matches[1]) { return "[img='" . $escapedLink . "',none," . $matches[1] . "][/img]"; } else { if ($matches[2]) { return "[img='" . $escapedLink . "'," . $matches[2] . "][/img]"; } else { return "[img]" . $matches[3] . "[/img]"; } } } }); $attachmentRegex = new Regex('\\[attachment=([0-9]+)\\]'); } // fix size bbcodes $message = preg_replace_callback('/\\[size=((?:xx?-)?(?:small|large)|medium)\\]/i', function ($matches) { $size = 12; switch ($matches[1]) { case 'xx-small': $size = 8; break; case 'x-small': $size = 10; break; case 'small': $size = 12; break; case 'medium': $size = 14; break; case 'large': $size = 18; break; case 'x-large': $size = 24; break; case 'xx-large': $size = 36; break; } return '[size=' . $size . ']'; }, $message); // attachment bbcodes $message = $attachmentRegex->replace($message, '[attach=\\1][/attach]'); // img bbcodes $message = $imgRegex->replace($message, $imgCallback); // code bbcodes $message = str_replace('[php]', '[code=php]', $message); // media bbcodes $message = $videoRegex->replace($message, '[media]\\1'); $message = str_replace('[/video]', '[/media]', $message); // quotes $message = $quoteRegex->replace($message, $quoteCallback); // remove crap $message = MessageUtil::stripCrap($message); return $message; }
/** * @see wcf\system\cache\source\ICacheSource::clear() */ public function removeKeys($pattern = null) { $regex = null; if ($pattern !== null) { $regex = new Regex('^'.$pattern.'$'); } $apcCacheInfo = apc_cache_info('user'); foreach ($apcCacheInfo['cache_list'] as $cache) { if ($regex === null) { if (StringUtil::startsWith($cache['info'], $this->prefix)) { apc_delete($cache['info']); } } else if ($regex->match($cache['info'])) { apc_delete($cache['info']); } } }
/** * Validates LESS-variable overrides. * * If an override is invalid, unknown or matches a variable covered by * the style editor itself, it will be silently discarded. */ protected function parseOverrides() { // get available variables $sql = "SELECT\tvariableName\n\t\t\tFROM\twcf" . WCF_N . "_style_variable"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(); $variables = array(); while ($row = $statement->fetchArray()) { $variables[] = $row['variableName']; } $lines = explode("\n", StringUtil::unifyNewlines($this->variables['overrideLess'])); $regEx = new Regex('^@([a-zA-Z]+): ?([@a-zA-Z0-9 ,\\.\\(\\)\\%\\#-]+);$'); $errors = array(); foreach ($lines as $index => &$line) { $line = StringUtil::trim($line); // ignore empty lines if (empty($line)) { unset($lines[$index]); continue; } if ($regEx->match($line)) { $matches = $regEx->getMatches(); // cannot override variables covered by style editor if (in_array($matches[1], $this->colors) || in_array($matches[1], $this->globals) || in_array($matches[1], $this->specialVariables)) { $errors[] = array('error' => 'predefined', 'text' => $matches[1]); } else { if (!in_array($matches[1], $variables)) { // unknown style variable $errors[] = array('error' => 'unknown', 'text' => $matches[1]); } else { $this->variables[$matches[1]] = $matches[2]; } } } else { // not valid $errors[] = array('error' => 'notValid', 'text' => $line); } } $this->variables['overrideLess'] = implode("\n", $lines); if (!empty($errors)) { throw new UserInputException('overrideLess', $errors); } }