/** * @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; }
/** * @see \wcf\system\bbcode\highlighter\Highlighter::cacheQuotes() */ protected function cacheQuotes($string) { if ($this->quotesRegEx !== null) { $string = $this->quotesRegEx->replace($string, new Callback(function (array $matches) { return StringStack::pushToStringStack('<span class="hlQuotes">' . StringUtil::encodeHTML($matches[0]) . '</span>', 'highlighterQuotes', ""); })); } return $string; }
/** * 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; })); }
/** * Callback function used in fixQuery() */ private static function replaceQuotesCallback($matches) { return StringStack::pushToStringStack($matches[0], 'postgresQuotes'); }
/** * Caches all bbcodes that contain URLs. */ protected function cacheURLBBCodes() { static $bbcodeRegex = null; static $callback = null; if ($bbcodeRegex === null) { $bbcodeRegex = new Regex("\n\t\t\t\t(?:\\[quote\n\t\t\t\t(?:=\n\t\t\t\t\t(?:\\'[^\\'\\\\]*(?:\\\\.[^\\'\\\\]*)*\\'|[^,\\]]*)\n\t\t\t\t\t(?:,(?:\\'[^\\'\\\\]*(?:\\\\.[^\\'\\\\]*)*\\'|[^,\\]]*))*\n\t\t\t\t)?\\])\n\t\t\t\t|\n\t\t\t\t(?:\\[(url|media|email|img)\n\t\t\t\t(?:=\n\t\t\t\t\t(?:\\'[^\\'\\\\]*(?:\\\\.[^\\'\\\\]*)*\\'|[^,\\]]*)\n\t\t\t\t\t(?:,(?:\\'[^\\'\\\\]*(?:\\\\.[^\\'\\\\]*)*\\'|[^,\\]]*))*\n\t\t\t\t)?\\])\n\t\t\t\t(.*?)\n\t\t\t\t(?:\\[/\\1\\])", Regex::DOT_ALL | Regex::IGNORE_WHITESPACE | Regex::CASE_INSENSITIVE); $callback = new Callback(function ($matches) { return '[' . StringStack::pushToStringStack(mb_substr($matches[0], 1, -1), 'urlBBCodes', "") . ']'; }); } $this->text = $bbcodeRegex->replace($this->text, $callback); }
/** * @see \wcf\system\event\listener\IParameterizedEventListener::execute() */ public function execute($eventObj, $className, $eventName, array &$parameters) { if (!$eventObj->text) { return; } // check if needed url BBCode is allowed if ($eventObj->allowedBBCodes !== null && !BBCode::isAllowedBBCode('url', $eventObj->allowedBBCodes)) { return; } static $userRegex = null; if ($userRegex === null) { $userRegex = new Regex("\n\t\t\t\t(?:^|(?<=\\s|\\]))\t\t\t\t\t# either at start of string, or after whitespace\n\t\t\t\t@\n\t\t\t\t(\n\t\t\t\t\t([^',\\s][^,\\s]{2,})(?:\\s[^,\\s]+)?\t# either at most two strings, not containing\n\t\t\t\t\t\t\t\t\t\t# whitespace or the comma, not starting with a single quote\n\t\t\t\t\t\t\t\t\t\t# separated by a single whitespace character\n\t\t\t\t|\n\t\t\t\t\t'(?:''|[^']){3,}'\t\t\t# or a string delimited by single quotes\n\t\t\t\t)\n\t\t\t", Regex::IGNORE_WHITESPACE); } // cache quotes // @see \wcf\system\bbcode\BBCodeParser::buildTagArray() $pattern = '~\\[(?:/(?:quote)|(?:quote) (?:= (?:\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|[^,\\]]*) (?:,(?:\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|[^,\\]]*))* )?)\\]~ix'; preg_match_all($pattern, $eventObj->text, $quoteMatches); $textArray = preg_split($pattern, $eventObj->text); $text = $textArray[0]; $openQuotes = 0; $quote = ''; foreach ($quoteMatches[0] as $i => $quoteTag) { if (mb_substr($quoteTag, 1, 1) == '/') { $openQuotes--; $quote .= $quoteTag; if ($openQuotes) { $quote .= $textArray[$i + 1]; } else { $text .= StringStack::pushToStringStack($quote, 'preParserUserMentions', '@@@') . $textArray[$i + 1]; $quote = ''; } } else { $openQuotes++; $quote .= $quoteTag . $textArray[$i + 1]; } } if ($quote) { $text .= $quote; } $userRegex->match($text, true, Regex::ORDER_MATCH_BY_SET); $matches = $userRegex->getMatches(); if (!empty($matches)) { $usernames = array(); foreach ($matches as $match) { // we don't care about the full match array_shift($match); foreach ($match as $username) { $username = self::getUsername($username); if (!in_array($username, $usernames)) { $usernames[] = $username; } } } if (!empty($usernames)) { // fetch users $userList = new UserList(); $userList->getConditionBuilder()->add('user_table.username IN (?)', array($usernames)); $userList->readObjects(); $users = array(); foreach ($userList as $user) { $users[mb_strtolower($user->username)] = $user; } $text = $userRegex->replace($text, new Callback(function ($matches) use($users) { // containing the full match $usernames = array($matches[1]); // containing only the part before the first space if (isset($matches[2])) { $usernames[] = $matches[2]; } $usernames = array_map(array('\\wcf\\system\\event\\listener\\PreParserAtUserListener', 'getUsername'), $usernames); foreach ($usernames as $username) { if (!isset($users[$username])) { continue; } $link = LinkHandler::getInstance()->getLink('User', array('appendSession' => false, 'object' => $users[$username])); $mention = "[url='" . $link . "']@" . $users[$username]->username . '[/url]'; // check if only the part before the first space matched, in that case append the second word if (isset($matches[2]) && strcasecmp($matches[2], $username) === 0) { $mention .= mb_substr($matches[1], strlen($matches[2])); } return $mention; } return $matches[0]; })); } } // reinsert cached quotes $eventObj->text = StringStack::reinsertStrings($text, 'preParserUserMentions'); }
/** * Callback function used in replaceConstants() */ private function replaceConstantsCallback($matches) { return StringStack::pushToStringStack($matches[1], 'constants'); }