Example #1
0
 /**
  * @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]*)(&lt;\\?php&nbsp;)(.*)(&nbsp;.*\\?&gt;)([^\\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('&nbsp;&nbsp;&nbsp;&nbsp;', "\t", $highlightedCode);
     // replace non breaking space with normal space, white-space is preserved by CSS
     $highlightedCode = str_replace('&nbsp;', " ", $highlightedCode);
     // convert colors to classes
     $highlightedCode = strtr($highlightedCode, self::$colorToClass);
     // replace double quotes by entity
     return Regex::compile('(?<!\\<span class=)"(?!\\>)')->replace($highlightedCode, '&quot;');
 }
 /**
  * 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();
 }
Example #3
0
 /**
  * @see	\wcf\system\bbcode\highlighter\Highlighter::highlightKeywords()
  */
 protected function highlightKeywords($string)
 {
     $string = parent::highlightKeywords($string);
     // find tags
     $regex = new Regex('&lt;(?:/|\\!|\\?)?[a-z0-9]+(?:\\s+' . self::XML_ATTRIBUTE_NAME . '(?:=[^\\s/\\?&]+)?)*(?:\\s+/|\\?)?&gt;', Regex::CASE_INSENSITIVE);
     $string = $regex->replace($string, new Callback(function ($matches) {
         // highlight attributes
         $tag = Regex::compile(XmlHighlighter::XML_ATTRIBUTE_NAME . '(?:=[^\\s/\\?&]+)?(?=\\s|&)', Regex::CASE_INSENSITIVE)->replace($matches[0], '<span class="hlKeywords2">\\0</span>');
         // highlight tag
         return '<span class="hlKeywords1">' . $tag . '</span>';
     }));
     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;
     }));
 }
Example #5
0
 /**
  * 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);
 }
Example #6
0
 /**
  * Executes the HTTP request.
  */
 public function execute()
 {
     // connect
     $remoteFile = new RemoteFile(($this->useSSL ? 'ssl://' : '') . $this->host, $this->port, $this->options['timeout'], array('ssl' => array('peer_name' => $this->originHost)));
     if ($this->originUseSSL && PROXY_SERVER_HTTP) {
         if ($this->useSSL) {
             throw new SystemException("Unable to proxy HTTPS when using TLS for proxy connection");
         }
         $request = "CONNECT " . $this->originHost . ":" . $this->originPort . " HTTP/1.0\r\n";
         if (isset($this->headers['user-agent'])) {
             $request .= 'user-agent: ' . reset($this->headers['user-agent']) . "\r\n";
         }
         $request .= "Host: " . $this->originHost . ":" . $this->originPort . "\r\n";
         $request .= "\r\n";
         $remoteFile->puts($request);
         $this->replyHeaders = array();
         while (!$remoteFile->eof()) {
             $line = $remoteFile->gets();
             if (rtrim($line) === '') {
                 $this->parseReplyHeaders();
                 break;
             }
             $this->replyHeaders[] = $line;
         }
         if ($this->statusCode != 200) {
             throw new SystemException("Expected 200 Ok as reply to my CONNECT, got '" . $this->statusCode . "'");
         }
         $remoteFile->setTLS(true);
     }
     $request = $this->options['method'] . " " . $this->path . ($this->query ? '?' . $this->query : '') . " HTTP/1.1\r\n";
     // add headers
     foreach ($this->headers as $name => $values) {
         foreach ($values as $value) {
             $request .= $name . ": " . $value . "\r\n";
         }
     }
     $request .= "\r\n";
     // add post parameters
     if ($this->options['method'] !== 'GET') {
         $request .= $this->body . "\r\n\r\n";
     }
     $remoteFile->puts($request);
     $inHeader = true;
     $this->replyHeaders = array();
     $this->replyBody = '';
     $chunkLength = 0;
     $bodyLength = 0;
     $chunkedTransferRegex = new Regex('(^|,)[ \\t]*chunked[ \\t]*$', Regex::CASE_INSENSITIVE);
     // read http response, until one of is true
     // a) EOF is reached
     // b) bodyLength is at least maxLength
     // c) bodyLength is at least Content-Length
     while (!($remoteFile->eof() || isset($this->options['maxLength']) && $bodyLength >= $this->options['maxLength'] || isset($this->replyHeaders['content-length']) && $bodyLength >= end($this->replyHeaders['content-length']))) {
         if ($chunkLength) {
             if (isset($this->options['maxLength'])) {
                 $chunkLength = min($chunkLength, $this->options['maxLength'] - $bodyLength);
             }
             $line = $remoteFile->read($chunkLength);
         } else {
             if (!$inHeader && (!isset($this->replyHeaders['transfer-encoding']) || !$chunkedTransferRegex->match(end($this->replyHeaders['transfer-encoding'])))) {
                 $length = 1024;
                 if (isset($this->options['maxLength'])) {
                     $length = min($length, $this->options['maxLength'] - $bodyLength);
                 }
                 if (isset($this->replyHeaders['content-length'])) {
                     $length = min($length, end($this->replyHeaders['content-length']) - $bodyLength);
                 }
                 $line = $remoteFile->read($length);
             } else {
                 $line = $remoteFile->gets();
             }
         }
         if ($inHeader) {
             if (rtrim($line) === '') {
                 $inHeader = false;
                 $this->parseReplyHeaders();
                 continue;
             }
             $this->replyHeaders[] = $line;
         } else {
             if (isset($this->replyHeaders['transfer-encoding']) && $chunkedTransferRegex->match(end($this->replyHeaders['transfer-encoding']))) {
                 // last chunk finished
                 if ($chunkLength === 0) {
                     // read hex data and trash chunk-extension
                     list($hex) = explode(';', $line, 2);
                     $chunkLength = hexdec($hex);
                     // $chunkLength === 0 -> no more data
                     if ($chunkLength === 0) {
                         // clear remaining response
                         while (!$remoteFile->gets(1024)) {
                         }
                         // remove chunked from transfer-encoding
                         $this->replyHeaders['transfer-encoding'] = array_filter(array_map(function ($element) use($chunkedTransferRegex) {
                             return $chunkedTransferRegex->replace($element, '');
                         }, $this->replyHeaders['transfer-encoding']), 'trim');
                         if (empty($this->replyHeaders['transfer-encoding'])) {
                             unset($this->replyHeaders['transfer-encoding']);
                         }
                         // break out of main reading loop
                         break;
                     }
                 } else {
                     $this->replyBody .= $line;
                     $chunkLength -= strlen($line);
                     $bodyLength += strlen($line);
                     if ($chunkLength === 0) {
                         $remoteFile->read(2);
                     }
                     // CRLF
                 }
             } else {
                 $this->replyBody .= $line;
                 $bodyLength += strlen($line);
             }
         }
     }
     if (isset($this->options['maxLength'])) {
         $this->replyBody = substr($this->replyBody, 0, $this->options['maxLength']);
     }
     $remoteFile->close();
     $this->parseReply();
 }
 protected static function convertMarkdown($message)
 {
     static $parsedown = null;
     static $codeRegex = null;
     static $imgRegex = null;
     static $urlRegex = null;
     if ($parsedown === null) {
         require_once WCF_DIR . 'lib/system/api/parsedown/Parsedown.php';
         $parsedown = new \Parsedown();
         $codeRegex = new Regex('<pre><code class="language-([a-z]+)">');
         $imgRegex = new Regex('<img src="([^"]+)"(?: alt="(?:[^"]+)")? />');
         $urlRegex = new Regex('<a href="([^"]+)">');
     }
     $out = $parsedown->text($message);
     $out = $codeRegex->replace($out, '[code=\\1]');
     $out = strtr($out, array('<p>' => '', '</p>' => '', '<br />' => '', '<strong>' => '[b]', '</strong>' => '[/b]', '<em>' => '[i]', '</em>' => '[/i]', '<ol>' => '[list=1]', '</ol>' => '[/list]', '<ul>' => '[list]', '</ul>' => '[/list]', '<li>' => '[*]', '</li>' => '', '<pre><code>' => '[code]', '</code></pre>' => '[/code]', '<code>' => '[tt]', '</code>' => '[/tt]', '<blockquote>' => '[quote]', '</blockquote>' => '[/quote]', '</a>' => '[/url]'));
     $out = $imgRegex->replace($out, '[img]\\1[/img]');
     $out = $urlRegex->replace($out, '[url=\\1]');
     return $out;
 }
Example #8
0
 /**
  * Caches quotes.
  */
 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;
 }
 private static function fixComment($message)
 {
     static $mentionRegex = null;
     if ($mentionRegex === null) {
         $mentionRegex = new Regex('@\\[\\d+:(@[^\\]]+)\\]');
     }
     return $mentionRegex->replace($message, "\\1");
 }
 /**
  * Returns true if given $url is an internal URL.
  * 
  * @param	string		$url
  * @return	boolean
  */
 public function isInternalURL($url)
 {
     $protocolRegex = new Regex('^https(?=://)');
     if (empty($this->pageURLs)) {
         foreach ($this->getApplications() as $application) {
             $this->pageURLs[] = preg_replace('~/$~', '', $protocolRegex->replace($application->getPageURL(), 'http'));
         }
     }
     foreach ($this->pageURLs as $pageURL) {
         if (stripos($protocolRegex->replace($url, 'http'), $pageURL) === 0) {
             return true;
         }
     }
     // relative urls contain no protocol, including implied
     if (!preg_match('~^([a-z]+)?://~', $url)) {
         return true;
     }
     return false;
 }
 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\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');
     }
 }
Example #13
0
	/**
	 * @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\page\IPage::readData()
     */
    public function readData()
    {
        AbstractPage::readData();
        $fileNameRegex = new Regex('(?:^|/)\\d{4}-\\d{2}-\\d{2}\\.txt$');
        $this->logFiles = DirectoryUtil::getInstance(WCF_DIR . 'log/')->getFiles(SORT_DESC, $fileNameRegex);
        if ($this->exceptionID) {
            // search the appropriate file
            foreach ($this->logFiles as $logFile) {
                $contents = file_get_contents($logFile);
                if (mb_strpos($contents, '<<<<<<<<' . $this->exceptionID . '<<<<') !== false) {
                    $fileNameRegex->match($logFile);
                    $matches = $fileNameRegex->getMatches();
                    $this->logFile = $matches[0];
                    break;
                }
                unset($contents);
            }
            if (!isset($contents)) {
                $this->logFile = '';
                return;
            }
        } else {
            if ($this->logFile) {
                if (!$fileNameRegex->match(basename($this->logFile))) {
                    throw new IllegalLinkException();
                }
                if (!file_exists(WCF_DIR . 'log/' . $this->logFile)) {
                    throw new IllegalLinkException();
                }
                $contents = file_get_contents(WCF_DIR . 'log/' . $this->logFile);
            } else {
                return;
            }
        }
        // unify newlines
        $contents = StringUtil::unifyNewlines($contents);
        // split contents
        $split = new Regex('(?:^|\\n<<<<\\n\\n)(?:<<<<<<<<([a-f0-9]{40})<<<<\\n|$)');
        $contents = $split->split($contents, Regex::SPLIT_NON_EMPTY_ONLY | Regex::CAPTURE_SPLIT_DELIMITER);
        // even items become keys, odd items become values
        try {
            $this->exceptions = call_user_func_array('array_merge', array_map(function ($v) {
                return array($v[0] => $v[1]);
            }, array_chunk($contents, 2)));
        } catch (\Exception $e) {
            // logfile contents are pretty malformed, abort
            return;
        }
        if ($this->exceptionID) {
            $this->searchPage($this->exceptionID);
        }
        $this->calculateNumberOfPages();
        $i = 0;
        $exceptionRegex = new Regex('(?P<date>[MTWFS][a-z]{2}, \\d{1,2} [JFMASOND][a-z]{2} \\d{4} \\d{2}:\\d{2}:\\d{2} [+-]\\d{4})
Message: (?P<message>.*?)
File: (?P<file>.*?) \\((?P<line>\\d+)\\)
PHP version: (?P<phpVersion>.*?)
WCF version: (?P<wcfVersion>.*?)
Request URI: (?P<requestURI>.*?)
Referrer: (?P<referrer>.*?)
User-Agent: (?P<userAgent>.*?)
Information: (?P<information>.*?)
Stacktrace: 
(?P<stacktrace>.*)', Regex::DOT_ALL);
        $stackTraceFormatter = new Regex('^\\s+(#\\d+)', Regex::MULTILINE);
        foreach ($this->exceptions as $key => $val) {
            $i++;
            if ($i < $this->startIndex || $i > $this->endIndex) {
                unset($this->exceptions[$key]);
                continue;
            }
            if (!$exceptionRegex->match($val)) {
                unset($this->exceptions[$key]);
                continue;
            }
            $this->exceptions[$key] = $exceptionRegex->getMatches();
            $this->exceptions[$key]['stacktrace'] = explode("\n", $stackTraceFormatter->replace(StringUtil::encodeHTML($this->exceptions[$key]['stacktrace']), '<strong>\\1</strong>'));
            $this->exceptions[$key]['information'] = JSON::decode($this->exceptions[$key]['information']);
        }
    }
    /**
     * @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');
    }
 private static function fixBBCodes($message)
 {
     static $quoteRegex = null;
     static $quoteCallback = null;
     static $imgRegex = null;
     static $mediaRegex = null;
     if ($quoteRegex === null) {
         $quoteRegex = new Regex('\\[quote=(.*?);n(\\d+)\\]', Regex::CASE_INSENSITIVE);
         $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 width=(\\d+) height=\\d+\\](.*?)\\[/img\\]');
         $mediaRegex = new Regex('\\[video=([a-z]+);([a-z0-9-_]+)\\]', Regex::CASE_INSENSITIVE);
     }
     // use proper WCF 2 bbcode
     $replacements = array('[left]' => '[align=left]', '[/left]' => '[/align]', '[right]' => '[align=right]', '[/right]' => '[/align]', '[center]' => '[align=center]', '[/center]' => '[/align]', '[php]' => '[code=php]', '[/php]' => '[/code]', '[html]' => '[code=html]', '[/html]' => '[/code]', '[/video]' => '[/media]');
     $message = str_ireplace(array_keys($replacements), array_values($replacements), $message);
     // quotes
     $message = $quoteRegex->replace($message, $quoteCallback);
     // img
     $message = $imgRegex->replace($message, "[img='\\2',none,\\1][/img]");
     // fix size bbcodes
     $message = preg_replace_callback('/\\[size=\'?(\\d+)\'?\\]/i', function ($matches) {
         $size = 36;
         switch ($matches[1]) {
             case 1:
                 $size = 8;
                 break;
             case 2:
                 $size = 10;
                 break;
             case 3:
                 $size = 12;
                 break;
             case 4:
                 $size = 14;
                 break;
             case 5:
                 $size = 18;
                 break;
             case 6:
                 $size = 24;
                 break;
         }
         return '[size=' . $size . ']';
     }, $message);
     // media
     $message = $mediaRegex->replace($message, '[media]');
     $message = MessageUtil::stripCrap($message);
     return $message;
 }
Example #17
0
 /**
  * Fixes markup that every line has proper number of opening and closing tags
  * 
  * @param	array<string>	$lines
  */
 public static function fixMarkup(array $lines)
 {
     static $spanRegex = null;
     static $emptyTagRegex = null;
     if ($spanRegex === null) {
         $spanRegex = new Regex('(?:<span(?: class="(?:[^"])*")?>|</span>)');
         $emptyTagRegex = new Regex('<span(?: class="(?:[^"])*")?></span>');
     }
     $openTags = array();
     foreach ($lines as &$line) {
         $spanRegex->match($line, true);
         // open all tags again
         $line = implode('', $openTags) . $line;
         $matches = $spanRegex->getMatches();
         // parse opening and closing spans
         foreach ($matches[0] as $match) {
             if ($match === '</span>') {
                 array_pop($openTags);
             } else {
                 array_push($openTags, $match);
             }
         }
         // close all tags
         $line .= str_repeat('</span>', count($openTags));
         // remove empty tags to avoid cluttering the output
         $line = $emptyTagRegex->replace($line, '');
     }
     unset($line);
     return $lines;
 }
 private static function fixBBCodes($message)
 {
     static $quoteRegex = null;
     static $quoteCallback = null;
     if ($quoteRegex === null) {
         $quoteRegex = new Regex('\\[quote="(.*?)" post=(\\d+)\\]', Regex::CASE_INSENSITIVE);
         $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 . "']";
         });
     }
     // use proper WCF 2 bbcode
     $replacements = array('[left]' => '[align=left]', '[/left]' => '[/align]', '[right]' => '[align=right]', '[/right]' => '[/align]', '[center]' => '[align=center]', '[/center]' => '[/align]', '[/video]' => '[/media]', '[attachment' => '[attach', '[/attachment]' => '[/attach]');
     $message = str_ireplace(array_keys($replacements), array_values($replacements), $message);
     // fix size bbcodes
     $message = preg_replace_callback('/\\[size=\'?(\\d+)\'?\\]/i', function ($matches) {
         $size = 36;
         switch ($matches[1]) {
             case 1:
                 $size = 8;
                 break;
             case 2:
                 $size = 10;
                 break;
             case 3:
                 $size = 12;
                 break;
             case 4:
                 $size = 14;
                 break;
             case 5:
                 $size = 18;
                 break;
             case 6:
                 $size = 24;
                 break;
         }
         return '[size=' . $size . ']';
     }, $message);
     // video
     $message = preg_replace('/\\[video[^\\]]*\\]/i', '[media]', $message);
     // img
     $message = preg_replace('/\\[img size=[^\\]]*\\]/i', '[img]', $message);
     // quotes
     $message = $quoteRegex->replace($message, $quoteCallback);
     return $message;
 }
 private static function fixBBCodes($message)
 {
     static $sizeRegex = null;
     static $quoteRegex = null;
     static $quoteCallback = null;
     if ($sizeRegex === null) {
         $quoteRegex = new Regex('\\[quote author=(.*?) link=topic=\\d+\\.msg(\\d+)#msg\\2 date=\\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 . "']";
         });
         $sizeRegex = new Regex('\\[size=(8|10|12|14|18|24|34)pt\\]');
     }
     // use proper WCF 2 bbcode
     $message = strtr($message, array('<br />' => "\n", '[iurl]' => '[url]', '[/iurl]' => '[/url]', '[left]' => '[align=left]', '[/left]' => '[/align]', '[right]' => '[align=right]', '[/right]' => '[/align]', '[center]' => '[align=center]', '[/center]' => '[/align]', '[ftp]' => '[url]', '[/ftp]' => '[/url]', '[php]' => '[code=php]', '[/php]' => '[/code]'));
     // fix size bbcode
     $message = $sizeRegex->replace($message, '[size=\\1]');
     // convert html entities in text
     $message = StringUtil::decodeHTML($message);
     // quotes
     $message = $quoteRegex->replace($message, $quoteCallback);
     // remove crap
     $message = MessageUtil::stripCrap($message);
     return $message;
 }