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;');
 }
	/**
	 * 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;
 }
Example #5
0
 /**
  * @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;
 }
Example #6
0
 /**
  * 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;
     }));
 }
Example #9
0
 /**
  * @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;
 }
Example #10
0
 /**
  * @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();
 }
Example #13
0
 /**
  * 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');
     }
 }
Example #16
0
 /**
  * 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');
         }
     }
 }
Example #18
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) {
         // 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, '&lt;?php&nbsp;');
         $closingTag = mb_strrpos($highlightedCode, '?&gt;');
         $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('&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;');
 }
Example #19
0
 /**
  * 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;
 }
Example #20
0
 /**
  * @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');
                 }
             }
         }
     }
 }
Example #21
0
 /**
  * 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)));
 }
Example #22
0
	/**
	 * 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
		));
	}
Example #23
0
 /**
  * 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];
 }
Example #24
0
 /**
  * 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);
 }
Example #26
0
 /**
  * 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;
 }
Example #29
0
	/**
	 * @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']);
			}
		}
	}
Example #30
0
 /**
  * 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);
     }
 }