예제 #1
0
	/**
	 * @see	wcf\system\cache\source\ICacheSource::flush()
	 */
	public function flush($cacheName, $useWildcard) {
		if (isset($this->cache[$cacheName])) {
			unset($this->cache[$cacheName]);
		}
		
		if ($useWildcard) {
			$cacheName .= '-';
			foreach (array_keys($this->cache) as $key) {
				if (StringUtil::startsWith($key, $cacheName)) {
					unset($this->cache[$key]);
				}
			}
		} 
	}
예제 #2
0
 /**
  * @see	\wcf\form\IForm::save()
  */
 public function save()
 {
     parent::save();
     $success = array();
     $updateParameters = array();
     // quit
     if (WCF::getSession()->getPermission('user.profile.canQuit')) {
         if (!WCF::getUser()->quitStarted && $this->quit == 1) {
             $updateParameters['quitStarted'] = TIME_NOW;
             $this->quitStarted = TIME_NOW;
             $success[] = 'wcf.user.quit.success';
         } else {
             if (WCF::getUser()->quitStarted && $this->cancelQuit == 1) {
                 $updateParameters['quitStarted'] = 0;
                 $this->quitStarted = 0;
                 $success[] = 'wcf.user.quit.cancel.success';
             }
         }
     }
     // user name
     if (WCF::getSession()->getPermission('user.profile.canRename') && $this->username != WCF::getUser()->username) {
         if (mb_strtolower($this->username) != mb_strtolower(WCF::getUser()->username)) {
             $updateParameters['lastUsernameChange'] = TIME_NOW;
             $updateParameters['oldUsername'] = WCF::getUser()->username;
         }
         $updateParameters['username'] = $this->username;
         $success[] = 'wcf.user.changeUsername.success';
     }
     // email
     if (WCF::getSession()->getPermission('user.profile.canChangeEmail') && $this->email != WCF::getUser()->email && $this->email != WCF::getUser()->newEmail) {
         if (REGISTER_ACTIVATION_METHOD == 0 || REGISTER_ACTIVATION_METHOD == 2 || mb_strtolower($this->email) == mb_strtolower(WCF::getUser()->email)) {
             // update email
             $updateParameters['email'] = $this->email;
             $success[] = 'wcf.user.changeEmail.success';
         } else {
             if (REGISTER_ACTIVATION_METHOD == 1) {
                 // get reactivation code
                 $activationCode = UserRegistrationUtil::getActivationCode();
                 // save as new email
                 $updateParameters['reactivationCode'] = $activationCode;
                 $updateParameters['newEmail'] = $this->email;
                 $messageData = array('username' => WCF::getUser()->username, 'userID' => WCF::getUser()->userID, 'activationCode' => $activationCode);
                 $mail = new Mail(array(WCF::getUser()->username => $this->email), WCF::getLanguage()->getDynamicVariable('wcf.user.changeEmail.needReactivation.mail.subject'), WCF::getLanguage()->getDynamicVariable('wcf.user.changeEmail.needReactivation.mail', $messageData));
                 $mail->send();
                 $success[] = 'wcf.user.changeEmail.needReactivation';
             }
         }
     }
     // password
     if (!WCF::getUser()->authData) {
         if (!empty($this->newPassword) || !empty($this->confirmNewPassword)) {
             $updateParameters['password'] = $this->newPassword;
             $success[] = 'wcf.user.changePassword.success';
         }
     }
     // 3rdParty
     if (GITHUB_PUBLIC_KEY !== '' && GITHUB_PRIVATE_KEY !== '') {
         if ($this->githubConnect && WCF::getSession()->getVar('__githubToken')) {
             $updateParameters['authData'] = 'github:' . WCF::getSession()->getVar('__githubToken');
             $success[] = 'wcf.user.3rdparty.github.connect.success';
             WCF::getSession()->unregister('__githubToken');
             WCF::getSession()->unregister('__githubUsername');
         }
     }
     if ($this->githubDisconnect && StringUtil::startsWith(WCF::getUser()->authData, 'github:')) {
         $updateParameters['authData'] = '';
         $success[] = 'wcf.user.3rdparty.github.disconnect.success';
     }
     if (TWITTER_PUBLIC_KEY !== '' && TWITTER_PRIVATE_KEY !== '') {
         if ($this->twitterConnect && WCF::getSession()->getVar('__twitterData')) {
             $twitterData = WCF::getSession()->getVar('__twitterData');
             $updateParameters['authData'] = 'twitter:' . $twitterData['user_id'];
             $success[] = 'wcf.user.3rdparty.twitter.connect.success';
             WCF::getSession()->unregister('__twitterData');
             WCF::getSession()->unregister('__twitterUsername');
         }
     }
     if ($this->twitterDisconnect && StringUtil::startsWith(WCF::getUser()->authData, 'twitter:')) {
         $updateParameters['authData'] = '';
         $success[] = 'wcf.user.3rdparty.twitter.disconnect.success';
     }
     if (FACEBOOK_PUBLIC_KEY !== '' && FACEBOOK_PRIVATE_KEY !== '') {
         if ($this->facebookConnect && WCF::getSession()->getVar('__facebookData')) {
             $facebookData = WCF::getSession()->getVar('__facebookData');
             $updateParameters['authData'] = 'facebook:' . $facebookData['id'];
             $success[] = 'wcf.user.3rdparty.facebook.connect.success';
             WCF::getSession()->unregister('__facebookData');
             WCF::getSession()->unregister('__facebookUsername');
         }
     }
     if ($this->facebookDisconnect && StringUtil::startsWith(WCF::getUser()->authData, 'facebook:')) {
         $updateParameters['authData'] = '';
         $success[] = 'wcf.user.3rdparty.facebook.disconnect.success';
     }
     if (GOOGLE_PUBLIC_KEY !== '' && GOOGLE_PRIVATE_KEY !== '') {
         if ($this->googleConnect && WCF::getSession()->getVar('__googleData')) {
             $googleData = WCF::getSession()->getVar('__googleData');
             $updateParameters['authData'] = 'google:' . $googleData['id'];
             $success[] = 'wcf.user.3rdparty.google.connect.success';
             WCF::getSession()->unregister('__googleData');
             WCF::getSession()->unregister('__googleUsername');
         }
     }
     if ($this->googleDisconnect && StringUtil::startsWith(WCF::getUser()->authData, 'google:')) {
         $updateParameters['authData'] = '';
         $success[] = 'wcf.user.3rdparty.google.disconnect.success';
     }
     $data = array();
     if (!empty($updateParameters) || !empty($this->additionalFields)) {
         $data['data'] = array_merge($this->additionalFields, $updateParameters);
     }
     $this->objectAction = new UserAction(array(WCF::getUser()), 'update', $data);
     $this->objectAction->executeAction();
     // update cookie
     if (isset($_COOKIE[COOKIE_PREFIX . 'password']) && isset($updateParameters['password'])) {
         // reload user
         $user = new User(WCF::getUser()->userID);
         HeaderUtil::setCookie('password', PasswordUtil::getSaltedHash($updateParameters['password'], $user->password), TIME_NOW + 365 * 24 * 3600);
     }
     $this->saved();
     $success = array_merge($success, WCF::getTPL()->get('success') ?: array());
     // show success message
     WCF::getTPL()->assign('success', $success);
     // reset password
     $this->password = '';
     $this->newPassword = $this->confirmNewPassword = '';
 }
 /**
  * Exports post attachments.
  */
 public function exportPostAttachments($offset, $limit)
 {
     static $uploadsPath = null;
     if ($uploadsPath === null) {
         $sql = "SELECT\tvalue\n\t\t\t\tFROM\t" . $this->databasePrefix . "settings\n\t\t\t\tWHERE\tname = ?";
         $statement = $this->database->prepareStatement($sql);
         $statement->execute(array('uploadspath'));
         $row = $statement->fetchArray();
         $uploadsPath = $row['value'];
         if (!StringUtil::startsWith($uploadsPath, '/')) {
             $uploadsPath = realpath($this->fileSystemPath . $uploadsPath);
         }
     }
     $sql = "SELECT\t\t*\n\t\t\tFROM\t\t" . $this->databasePrefix . "attachments\n\t\t\tWHERE\t\taid BETWEEN ? AND ?\n\t\t\tORDER BY\taid";
     $statement = $this->database->prepareStatement($sql);
     $statement->execute(array($offset + 1, $offset + $limit));
     while ($row = $statement->fetchArray()) {
         $fileLocation = FileUtil::addTrailingSlash($uploadsPath) . $row['attachname'];
         if (!file_exists($fileLocation)) {
             continue;
         }
         if ($imageSize = @getimagesize($fileLocation)) {
             $row['isImage'] = 1;
             $row['width'] = $imageSize[0];
             $row['height'] = $imageSize[1];
         } else {
             $row['isImage'] = $row['width'] = $row['height'] = 0;
         }
         ImportHandler::getInstance()->getImporter('com.woltlab.wbb.attachment')->import($row['aid'], array('objectID' => $row['pid'], 'userID' => $row['uid'] ?: null, 'filename' => $row['filename'], 'filesize' => $row['filesize'], 'fileType' => $row['filetype'], 'isImage' => $row['isImage'], 'width' => $row['width'], 'height' => $row['height'], 'downloads' => $row['downloads'], 'uploadTime' => $row['dateuploaded']), array('fileLocation' => $fileLocation));
     }
 }
예제 #4
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']);
			}
		}
	}
예제 #5
0
 /**
  * Compiles LESS stylesheets into one CSS-stylesheet and writes them
  * to filesystem. Please be aware not to append '.css' within $filename!
  * 
  * @param	string			$filename
  * @param	array<string>		$files
  * @param	array<string>		$variables
  * @param	string			$individualLess
  * @param	\wcf\system\Callback	$callback
  */
 protected function compileStylesheet($filename, array $files, array $variables, $individualLess, Callback $callback)
 {
     foreach ($variables as &$value) {
         if (StringUtil::startsWith($value, '../')) {
             $value = '~"' . $value . '"';
         }
     }
     unset($value);
     // add options as LESS variables
     if (PACKAGE_ID) {
         foreach (Option::getOptions() as $constantName => $option) {
             if (in_array($option->optionType, static::$supportedOptionType)) {
                 $variables['wcf_option_' . mb_strtolower($constantName)] = '~"' . $option->optionValue . '"';
             }
         }
     } else {
         // workaround during setup
         $variables['wcf_option_attachment_thumbnail_height'] = '~"210"';
         $variables['wcf_option_attachment_thumbnail_width'] = '~"280"';
         $variables['wcf_option_signature_max_image_height'] = '~"150"';
     }
     // build LESS bootstrap
     $less = $this->bootstrap($variables);
     foreach ($files as $file) {
         $less .= $this->prepareFile($file);
     }
     // append individual CSS/LESS
     if ($individualLess) {
         $less .= $individualLess;
     }
     try {
         $content = $this->compiler->compile($less);
     } catch (\Exception $e) {
         throw new SystemException("Could not compile LESS: " . $e->getMessage(), 0, '', $e);
     }
     $content = $callback($content);
     // compress stylesheet
     $lines = explode("\n", $content);
     $content = $lines[0] . "\n" . $lines[1] . "\n";
     for ($i = 2, $length = count($lines); $i < $length; $i++) {
         $line = trim($lines[$i]);
         $content .= $line;
         switch (substr($line, -1)) {
             case ',':
                 $content .= ' ';
                 break;
             case '}':
                 $content .= "\n";
                 break;
         }
         if (substr($line, 0, 6) == '@media') {
             $content .= "\n";
         }
     }
     // write stylesheet
     file_put_contents($filename . '.css', $content);
     FileUtil::makeWritable($filename . '.css');
     // convert stylesheet to RTL
     $content = StyleUtil::convertCSSToRTL($content);
     // write stylesheet for RTL
     file_put_contents($filename . '-rtl.css', $content);
     FileUtil::makeWritable($filename . '-rtl.css');
 }
예제 #6
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));
	}
예제 #7
0
 /**
  * Returns true if the current user is connected with Twitter.
  * 
  * @return	boolean
  */
 public function isConnectedWithTwitter()
 {
     return StringUtil::startsWith($this->authData, 'twitter:');
 }
 /**
  * Exports user avatars.
  */
 public function exportUserAvatars($offset, $limit)
 {
     $sql = "SELECT\t\tcustomavatar.*, user.avatarrevision\n\t\t\tFROM\t\t" . $this->databasePrefix . "customavatar customavatar\n\t\t\tLEFT JOIN\t" . $this->databasePrefix . "user user\n\t\t\tON\t\tuser.userid = customavatar.userid\n\t\t\tWHERE\t\tcustomavatar.userid BETWEEN ? AND ?\n\t\t\tORDER BY\tcustomavatar.userid";
     $statement = $this->database->prepareStatement($sql);
     $statement->execute(array($offset + 1, $offset + $limit));
     while ($row = $statement->fetchArray()) {
         $file = null;
         try {
             // TODO: not yet supported
             if (false && $this->readOption('usefileavatar')) {
                 $file = $this->readOption('avatarpath');
                 if (!StringUtil::startsWith($file, '/')) {
                     $file = realpath($this->fileSystemPath . $file);
                 }
                 $file = FileUtil::addTrailingSlash($file) . 'avatar' . $row['userid'] . '_' . $row['avatarrevision'] . '.gif';
             } else {
                 $file = FileUtil::getTemporaryFilename('avatar_');
                 file_put_contents($file, $row['filedata']);
             }
             ImportHandler::getInstance()->getImporter('com.woltlab.wcf.user.avatar')->import($row['userid'], array('avatarName' => $row['filename'], 'avatarExtension' => pathinfo($row['filename'], PATHINFO_EXTENSION), 'width' => $row['width'], 'height' => $row['height'], 'userID' => $row['userid']), array('fileLocation' => $file));
             if (!$this->readOption('usefileavatar')) {
                 unlink($file);
             }
         } catch (\Exception $e) {
             if (!$this->readOption('usefileavatar') && $file) {
                 @unlink($file);
             }
             throw $e;
         }
     }
 }
 /**
  * Exports gallery images.
  */
 public function exportGalleryImages($offset, $limit)
 {
     try {
         // vb 3
         $sql = "SELECT\t\tpicture.*, album.albumid, album.dateline, user.username\n\t\t\t\tFROM\t\t" . $this->databasePrefix . "picture picture\n\t\t\t\tLEFT JOIN\t" . $this->databasePrefix . "albumpicture album\n\t\t\t\tON\t\tpicture.pictureid = album.pictureid\n\t\t\t\tLEFT JOIN\t" . $this->databasePrefix . "user user\n\t\t\t\tON\t\tpicture.userid = user.userid\n\t\t\t\tORDER BY\tpicture.pictureid";
         $statement = $this->database->prepareStatement($sql, $limit, $offset);
         $statement->execute();
         $vB = 3;
     } catch (DatabaseException $e) {
         // vb 4
         $sql = "SELECT\t\tattachment.*, attachment.contentid AS albumid, filedata.filedata, filedata.extension,\n\t\t\t\t\t\tfiledata.filesize, filedata.width, filedata.height, user.username\n\t\t\t\tFROM\t\t" . $this->databasePrefix . "attachment attachment\n\t\t\t\tLEFT JOIN\t" . $this->databasePrefix . "filedata filedata\n\t\t\t\tON\t\tattachment.filedataid = filedata.filedataid\n\t\t\t\tLEFT JOIN\t" . $this->databasePrefix . "user user\n\t\t\t\tON\t\tattachment.userid = user.userid\n\t\t\t\tWHERE\t\tattachment.contenttypeid = (SELECT contenttypeid FROM " . $this->databasePrefix . "contenttype contenttype WHERE contenttype.class = 'Album')\n\t\t\t\tORDER BY\tattachment.attachmentid";
         $statement = $this->database->prepareStatement($sql, $limit, $offset);
         $statement->execute();
         $vB = 4;
     }
     while ($row = $statement->fetchArray()) {
         try {
             if ($vB === 4) {
                 switch ($this->readOption('attachfile')) {
                     case self::ATTACHFILE_DATABASE:
                         $file = FileUtil::getTemporaryFilename('attachment_');
                         file_put_contents($file, $row['filedata']);
                         break;
                     case self::ATTACHFILE_FILESYSTEM:
                         $file = $this->readOption('attachpath');
                         if (!StringUtil::startsWith($file, '/')) {
                             $file = realpath($this->fileSystemPath . $file);
                         }
                         $file = FileUtil::addTrailingSlash($file);
                         $file .= $row['userid'] . '/' . (isset($row['filedataid']) ? $row['filedataid'] : $row['attachmentid']) . '.attach';
                         break;
                     case self::ATTACHFILE_FILESYSTEM_SUBFOLDER:
                         $file = $this->readOption('attachpath');
                         if (!StringUtil::startsWith($file, '/')) {
                             $file = realpath($this->fileSystemPath . $file);
                         }
                         $file = FileUtil::addTrailingSlash($file);
                         $file .= implode('/', str_split($row['userid'])) . '/' . (isset($row['filedataid']) ? $row['filedataid'] : $row['attachmentid']) . '.attach';
                         break;
                 }
             } else {
                 switch ($this->readOption('album_dataloc')) {
                     case self::GALLERY_DATABASE:
                         $file = FileUtil::getTemporaryFilename('attachment_');
                         file_put_contents($file, $row['filedata']);
                         break;
                     case self::GALLERY_FILESYSTEM:
                     case self::GALLERY_FILESYSTEM_DIRECT_THUMBS:
                         $file = $this->readOption('album_picpath');
                         if (!StringUtil::startsWith($file, '/')) {
                             $file = realpath($this->fileSystemPath . $file);
                         }
                         $file = FileUtil::addTrailingSlash($file);
                         $file .= floor($row['pictureid'] / 1000) . '/' . $row['pictureid'] . '.picture';
                         break;
                 }
             }
             $additionalData = array('fileLocation' => $file);
             ImportHandler::getInstance()->getImporter('com.woltlab.gallery.image')->import(isset($row['pictureid']) ? $row['pictureid'] : $row['filedataid'], array('userID' => $row['userid'] ?: null, 'username' => $row['username'] ?: '', 'albumID' => $row['albumid'] ?: null, 'title' => $row['caption'], 'description' => '', 'filename' => isset($row['filename']) ? $row['filename'] : '', 'fileExtension' => $row['extension'], 'filesize' => $row['filesize'], 'uploadTime' => $row['dateline'], 'creationTime' => $row['dateline'], 'width' => $row['width'], 'height' => $row['height']), $additionalData);
         } catch (\Exception $e) {
             if ($vB === 3 && $this->readOption('album_dataloc') == self::GALLERY_DATABASE && $file) {
                 @unlink($file);
             }
             if ($vB === 4 && $this->readOption('attachfile') == self::ATTACHFILE_DATABASE && $file) {
                 @unlink($file);
             }
             throw $e;
         }
     }
 }
예제 #10
0
 /**
  * @see	\wcf\system\mail\MailSender::sendMail()
  */
 public function sendMail(Mail $mail)
 {
     $this->recipients = array();
     if (count($mail->getTo()) > 0) {
         $this->recipients = $mail->getTo();
     }
     if (count($mail->getCC()) > 0) {
         $this->recipients = array_merge($this->recipients, $mail->getCC());
     }
     if (count($mail->getBCC()) > 0) {
         $this->recipients = array_merge($this->recipients, $mail->getBCC());
     }
     // apply connection
     if ($this->connection === null) {
         $this->connect();
     }
     // send mail
     $this->write('MAIL FROM:<' . $mail->getFrom() . '>');
     $this->getSMTPStatus();
     if ($this->statusCode != 250) {
         $this->abort();
         throw new SystemException($this->formatError("wrong from format '" . $mail->getFrom() . "'"));
     }
     // recipients
     $recipientCounter = 0;
     foreach ($this->recipients as $recipient) {
         $this->write('RCPT TO:<' . $recipient . '>');
         $this->getSMTPStatus();
         if ($this->statusCode != 250 && $this->statusCode != 251) {
             if ($this->statusCode < 550) {
                 $this->abort();
                 throw new SystemException($this->formatError("wrong recipient format '" . $recipient . "'"));
             }
             continue;
         }
         $recipientCounter++;
     }
     if (!$recipientCounter) {
         $this->abort();
         return;
     }
     // data
     $this->write("DATA");
     $this->getSMTPStatus();
     if ($this->statusCode != 354 && $this->statusCode != 250) {
         $this->abort();
         throw new SystemException($this->formatError("smtp error"));
     }
     $serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
     if (empty($serverName)) {
         $serverName = gethostname();
         if ($serverName === false) {
             $serverName = 'localhost';
         }
     }
     $header = "Date: " . gmdate('r') . Mail::$lineEnding . "To: " . $mail->getToString() . Mail::$lineEnding . "Message-ID: <" . md5(uniqid()) . "@" . $serverName . ">" . Mail::$lineEnding . "Subject: " . Mail::encodeMIMEHeader($mail->getSubject()) . Mail::$lineEnding . $mail->getHeader();
     $this->write($header);
     $this->write("");
     $lines = explode(Mail::$lineEnding, $mail->getBody());
     foreach ($lines as $line) {
         // 4.5.2 Transparency
         // o  Before sending a line of mail text, the SMTP client checks the
         //    first character of the line.  If it is a period, one additional
         //    period is inserted at the beginning of the line.
         if (StringUtil::startsWith($line, '.')) {
             $line = '.' . $line;
         }
         $this->write($line);
     }
     $this->write(".");
     $this->getSMTPStatus();
     if ($this->statusCode != 250) {
         $this->abort();
         throw new SystemException($this->formatError("message sending failed"));
     }
 }