/** * Sends a new password to the given user. * * @param \wcf\data\user\UserEditor $userEditor */ protected function sendNewPassword(UserEditor $userEditor) { $newPassword = PasswordUtil::getRandomPassword(REGISTER_PASSWORD_MIN_LENGTH > 12 ? REGISTER_PASSWORD_MIN_LENGTH : 12); $userAction = new UserAction(array($userEditor), 'update', array('data' => array('password' => $newPassword))); $userAction->executeAction(); // send mail $mail = new Mail(array($userEditor->username => $userEditor->email), $userEditor->getLanguage()->getDynamicVariable('wcf.acp.user.sendNewPassword.mail.subject'), $userEditor->getLanguage()->getDynamicVariable('wcf.acp.user.sendNewPassword.mail', array('password' => $newPassword, 'username' => $userEditor->username))); $mail->send(); }
/** * @see wcf\data\AbstractDatabaseObjectAction::create() */ public function create() { $statement = parent::create(); if (isset($this->parameters['changeBalance']) && $this->parameters['changeBalance']) { $user = new User($this->parameters['data']['userID']); $userEditor = new UserEditor($user); $userEditor->updateCounters(array('jCoinsBalance' => $statement->sum)); } return $statement; }
/** * @see wcf\form\IForm::save() */ public function save() { AbstractForm::save(); // add default groups $defaultGroups = UserGroup::getAccessibleGroups(array(UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS)); $oldGroupIDs = $this->user->getGroupIDs(); foreach ($oldGroupIDs as $oldGroupID) { if (isset($defaultGroups[$oldGroupID])) { $this->groupIDs[] = $oldGroupID; } } $this->groupIDs = array_unique($this->groupIDs); // save user $saveOptions = $this->optionHandler->save(); $this->additionalFields['languageID'] = $this->languageID; $data = array( 'data' => array_merge($this->additionalFields, array( 'username' => $this->username, 'email' => $this->email, 'password' => $this->password, )), 'groups' => $this->groupIDs, 'languages' => $this->visibleLanguages, 'options' => $saveOptions ); $this->objectAction = new UserAction(array($this->userID), 'update', $data); $this->objectAction->executeAction(); $this->saved(); // reset password $this->password = $this->confirmPassword = ''; // show success message WCF::getTPL()->assign('success', true); }
/** * Deletes this session and it's related data. */ public function delete() { // clear storage if ($this->user->userID) { self::resetSessions(array($this->user->userID)); // update last activity time if (!class_exists('\\wcf\\system\\WCFACP', false)) { $editor = new UserEditor($this->user); $editor->update(array('lastActivityTime' => TIME_NOW)); } } // 1st: Change user to guest, otherwise other the entire session, including // all virtual sessions of the user will be deleted $this->changeUser(new User(null)); // 2nd: Actually remove session $sessionEditor = new $this->sessionEditorClassName($this->session); $sessionEditor->delete(); // disable update $this->disableUpdate(); }
/** * @see \wcf\action\IAction::execute() */ public function execute() { parent::execute(); $callbackURL = LinkHandler::getInstance()->getLink('FacebookAuth'); // Work around Facebook performing an illegal substitution of the Slash // by '%2F' when entering redirect URI (RFC 3986 sect. 2.2, sect. 3.4) $callbackURL = preg_replace_callback('/(?<=\\?).*/', function ($matches) { return rawurlencode($matches[0]); }, $callbackURL); // user accepted the connection if (isset($_GET['code'])) { try { // fetch access_token $request = new HTTPRequest('https://graph.facebook.com/oauth/access_token?client_id=' . StringUtil::trim(FACEBOOK_PUBLIC_KEY) . '&redirect_uri=' . rawurlencode($callbackURL) . '&client_secret=' . StringUtil::trim(FACEBOOK_PRIVATE_KEY) . '&code=' . rawurlencode($_GET['code'])); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } // validate state, validation of state is executed after fetching the access_token to invalidate 'code' if (!isset($_GET['state']) || $_GET['state'] != WCF::getSession()->getVar('__facebookInit')) { throw new IllegalLinkException(); } WCF::getSession()->unregister('__facebookInit'); parse_str($content, $data); try { // fetch userdata $request = new HTTPRequest('https://graph.facebook.com/me?access_token=' . rawurlencode($data['access_token']) . '&fields=birthday,bio,email,gender,id,location,name,picture.type(large),website'); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } $userData = JSON::decode($content); // check whether a user is connected to this facebook account $user = $this->getUser($userData['id']); if ($user->userID) { // a user is already connected, but we are logged in, break if (WCF::getUser()->userID) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.facebook.connect.error.inuse')); } else { if (UserAuthenticationFactory::getInstance()->getUserAuthentication()->supportsPersistentLogins()) { $password = StringUtil::getRandomID(); $userEditor = new UserEditor($user); $userEditor->update(array('password' => $password)); // reload user to retrieve salt $user = new User($user->userID); UserAuthenticationFactory::getInstance()->getUserAuthentication()->storeAccessData($user, $user->username, $password); } WCF::getSession()->changeUser($user); WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink()); } } else { WCF::getSession()->register('__3rdPartyProvider', 'facebook'); // save data for connection if (WCF::getUser()->userID) { WCF::getSession()->register('__facebookUsername', $userData['name']); WCF::getSession()->register('__facebookData', $userData); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('AccountManagement') . '#3rdParty'); } else { WCF::getSession()->register('__username', $userData['name']); if (isset($userData['email'])) { WCF::getSession()->register('__email', $userData['email']); } WCF::getSession()->register('__facebookData', $userData); // we assume that bots won't register on facebook first // thus no need for a captcha if (REGISTER_USE_CAPTCHA) { WCF::getSession()->register('noRegistrationCaptcha', true); } WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Register')); } } $this->executed(); exit; } // user declined or any other error that may occur if (isset($_GET['error'])) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.facebook.login.error.' . $_GET['error'])); } // start auth by redirecting to facebook $token = StringUtil::getRandomID(); WCF::getSession()->register('__facebookInit', $token); HeaderUtil::redirect("https://www.facebook.com/dialog/oauth?client_id=" . StringUtil::trim(FACEBOOK_PUBLIC_KEY) . "&redirect_uri=" . rawurlencode($callbackURL) . "&state=" . $token . "&scope=email,user_about_me,user_birthday,user_location,user_website"); $this->executed(); exit; }
/** * @see \wcf\action\IAction::execute() */ public function execute() { parent::execute(); if ($this->user->enableGravatar) { $fileExtension = $this->user->gravatarFileExtension ?: 'png'; // try to use cached gravatar $cachedFilename = sprintf(Gravatar::GRAVATAR_CACHE_LOCATION, md5(mb_strtolower($this->user->email)), $this->size, $fileExtension); if (file_exists(WCF_DIR . $cachedFilename) && filemtime(WCF_DIR . $cachedFilename) > TIME_NOW - Gravatar::GRAVATAR_CACHE_EXPIRE * 86400) { @header('Content-Type: image/png'); @readfile(WCF_DIR . $cachedFilename); exit; } // try to download new version $gravatarURL = sprintf(Gravatar::GRAVATAR_BASE, md5(mb_strtolower($this->user->email)), $this->size, GRAVATAR_DEFAULT_TYPE); try { $request = new HTTPRequest($gravatarURL); $request->execute(); $reply = $request->getReply(); // get mime type and file extension $fileExtension = 'png'; $mimeType = 'image/png'; if (isset($reply['headers']['Content-Type'])) { switch ($reply['headers']['Content-Type']) { case 'image/jpeg': $mimeType = 'image/jpeg'; $fileExtension = 'jpg'; break; case 'image/gif': $mimeType = 'image/gif'; $fileExtension = 'gif'; break; } } // save file $cachedFilename = sprintf(Gravatar::GRAVATAR_CACHE_LOCATION, md5(mb_strtolower($this->user->email)), $this->size, $fileExtension); file_put_contents(WCF_DIR . $cachedFilename, $reply['body']); FileUtil::makeWritable(WCF_DIR . $cachedFilename); // update file extension if ($fileExtension != $this->user->gravatarFileExtension) { $editor = new UserEditor($this->user); $editor->update(array('gravatarFileExtension' => $fileExtension)); } @header('Content-Type: ' . $mimeType); @readfile(WCF_DIR . $cachedFilename); exit; } catch (SystemException $e) { // disable gravatar $editor = new UserEditor($this->user); $editor->update(array('enableGravatar' => 0)); } } // fallback to default avatar @header('Content-Type: image/svg+xml'); @readfile(WCF_DIR . 'images/avatars/avatar-default.svg'); exit; }
/** * @see wcf\form\IForm::save() */ public function save() { parent::save(); // build conditions $this->conditions = new PreparedStatementConditionBuilder(); // static fields if (!empty($this->username)) { $this->conditions->add("user.username LIKE ?", array('%'.addcslashes($this->username, '_%').'%')); } if (!empty($this->email)) { $this->conditions->add("user.email LIKE ?", array('%'.addcslashes($this->email, '_%').'%')); } if (!empty($this->groupIDArray)) { $this->conditions->add("user.userID ".($this->invertGroupIDs == 1 ? 'NOT ' : '')."IN (SELECT userID FROM wcf".WCF_N."_user_to_group WHERE groupID IN (?))", array($this->groupIDArray)); } if (!empty($this->languageIDArray)) { $this->conditions->add("user.languageID IN (?)", array($this->languageIDArray)); } // dynamic fields foreach ($this->activeOptions as $name => $option) { $value = isset($this->values[$option['optionName']]) ? $this->values[$option['optionName']] : null; $this->getTypeObject($option['optionType'])->getCondition($this->conditions, $option, $value); } // call buildConditions event EventHandler::getInstance()->fireAction($this, 'buildConditions'); // execute action switch ($this->action) { case 'sendMail': WCF::getSession()->checkPermissions(array('admin.user.canMailUser')); // get user ids $userIDArray = array(); $sql = "SELECT user.userID FROM wcf".WCF_N."_user LEFT JOIN wcf".WCF_N."_user_option_value option_value ON (option_value.userID = user.userID)". $this->conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($this->conditions->getParameters()); while ($row = $statement->fetchArray()) { $userIDArray[] = $row['userID']; $this->affectedUsers++; } // save config in session $userMailData = WCF::getSession()->getVar('userMailData'); if ($userMailData === null) $userMailData = array(); $mailID = count($userMailData); $userMailData[$mailID] = array( 'action' => '', 'userIDs' => implode(',', $userIDArray), 'groupIDs' => '', 'subject' => $this->subject, 'text' => $this->text, 'from' => $this->from, 'enableHTML' => $this->enableHTML ); WCF::getSession()->register('userMailData', $userMailData); $this->saved(); $url = LinkHandler::getInstance()->getLink('UserMail', array('id' => $mailID)); // show worker template WCF::getTPL()->assign(array( 'pageTitle' => WCF::getLanguage()->get('wcf.acp.user.sendMail'), 'url' => $url )); WCF::getTPL()->display('worker'); exit; break; case 'exportMailAddress': WCF::getSession()->checkPermissions(array('admin.user.canMailUser')); // send content type header('Content-Type: text/'.$this->fileType.'; charset=UTF-8'); header('Content-Disposition: attachment; filename="export.'.$this->fileType.'"'); if ($this->fileType == 'xml') { echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<addresses>\n"; } // count users $sql = "SELECT COUNT(*) AS count FROM wcf".WCF_N."_user user LEFT JOIN wcf".WCF_N."_user_option_value option_value ON (option_value.userID = user.userID) ".$this->conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($this->conditions->getParameters()); $count = $statement->fetchArray(); // get users $sql = "SELECT user.email FROM wcf".WCF_N."_user user LEFT JOIN wcf".WCF_N."_user_option_value option_value ON (option_value.userID = user.userID) ".$this->conditions." ORDER BY user.email"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($this->conditions->getParameters()); $i = 0; while ($row = $statement->fetchArray()) { if ($this->fileType == 'xml') echo "<address><![CDATA[".StringUtil::escapeCDATA($row['email'])."]]></address>\n"; else echo $this->textSeparator . $row['email'] . $this->textSeparator . ($i < $count['count'] ? $this->separator : ''); $i++; $this->affectedUsers++; } if ($this->fileType == 'xml') { echo "</addresses>"; } $this->saved(); exit; break; case 'assignToGroup': WCF::getSession()->checkPermissions(array('admin.user.canEditUser')); $userIDArray = $this->fetchUsers(function($userID, array $userData) { $user = new UserEditor(new User(null, $userData)); $user->addToGroups($this->assignToGroupIDArray, false, false); }); UserStorageHandler::getInstance()->reset($userIDArray, 'groupIDs', 1); break; case 'delete': WCF::getSession()->checkPermissions(array('admin.user.canDeleteUser')); $userIDArray = $this->fetchUsers(); UserEditor::deleteUsers($userIDArray); break; } $this->saved(); WCF::getTPL()->assign('affectedUsers', $this->affectedUsers); }
/** * @see \wcf\action\IAction::execute() */ public function execute() { parent::execute(); // user accepted the connection if (isset($_GET['code'])) { try { // fetch access_token $request = new HTTPRequest('https://github.com/login/oauth/access_token', array(), array('client_id' => StringUtil::trim(GITHUB_PUBLIC_KEY), 'client_secret' => StringUtil::trim(GITHUB_PRIVATE_KEY), 'code' => $_GET['code'])); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } // validate state, validation of state is executed after fetching the access_token to invalidate 'code' if (!isset($_GET['state']) || $_GET['state'] != WCF::getSession()->getVar('__githubInit')) { throw new IllegalLinkException(); } WCF::getSession()->unregister('__githubInit'); parse_str($content, $data); // check whether the token is okay if (isset($data['error'])) { throw new IllegalLinkException(); } // check whether a user is connected to this github account $user = $this->getUser($data['access_token']); if ($user->userID) { // a user is already connected, but we are logged in, break if (WCF::getUser()->userID) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.github.connect.error.inuse')); } else { if (UserAuthenticationFactory::getInstance()->getUserAuthentication()->supportsPersistentLogins()) { $password = StringUtil::getRandomID(); $userEditor = new UserEditor($user); $userEditor->update(array('password' => $password)); // reload user to retrieve salt $user = new User($user->userID); UserAuthenticationFactory::getInstance()->getUserAuthentication()->storeAccessData($user, $user->username, $password); } WCF::getSession()->changeUser($user); WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink()); } } else { try { // fetch userdata $request = new HTTPRequest('https://api.github.com/user?access_token=' . $data['access_token']); $request->execute(); $reply = $request->getReply(); $userData = JSON::decode(StringUtil::trim($reply['body'])); } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } WCF::getSession()->register('__3rdPartyProvider', 'github'); // save data for connection if (WCF::getUser()->userID) { WCF::getSession()->register('__githubUsername', $userData['login']); WCF::getSession()->register('__githubToken', $data['access_token']); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('AccountManagement') . '#3rdParty'); } else { WCF::getSession()->register('__githubData', $userData); WCF::getSession()->register('__username', $userData['login']); // check whether user has entered a public email if (isset($userData) && isset($userData['email']) && $userData['email'] !== null) { WCF::getSession()->register('__email', $userData['email']); } else { try { $request = new HTTPRequest('https://api.github.com/user/emails?access_token=' . $data['access_token']); $request->execute(); $reply = $request->getReply(); $emails = JSON::decode(StringUtil::trim($reply['body'])); // handle future response as well a current response (see. http://developer.github.com/v3/users/emails/) if (is_string($emails[0])) { $email = $emails[0]; } else { $email = $emails[0]['email']; foreach ($emails as $tmp) { if ($tmp['primary']) { $email = $tmp['email']; } break; } } WCF::getSession()->register('__email', $email); } catch (SystemException $e) { } } WCF::getSession()->register('__githubToken', $data['access_token']); // we assume that bots won't register on github first // thus no need for a captcha if (REGISTER_USE_CAPTCHA) { WCF::getSession()->register('noRegistrationCaptcha', true); } WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Register')); } } $this->executed(); exit; } // user declined or any other error that may occur if (isset($_GET['error'])) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.github.login.error.' . $_GET['error'])); } // start auth by redirecting to github $token = StringUtil::getRandomID(); WCF::getSession()->register('__githubInit', $token); HeaderUtil::redirect("https://github.com/login/oauth/authorize?client_id=" . rawurlencode(StringUtil::trim(GITHUB_PUBLIC_KEY)) . "&scope=" . rawurlencode('user:email') . "&state=" . $token); $this->executed(); exit; }
/** * @see \wcf\form\IForm::save() */ public function save() { parent::save(); // build conditions $this->conditions = new PreparedStatementConditionBuilder(); // deny self delete if ($this->action == 'delete') { $this->conditions->add("user_table.userID <> ?", array(WCF::getUser()->userID)); } // static fields if (!empty($this->username)) { $this->conditions->add("user_table.username LIKE ?", array('%' . addcslashes($this->username, '_%') . '%')); } if (!empty($this->email)) { $this->conditions->add("user_table.email LIKE ?", array('%' . addcslashes($this->email, '_%') . '%')); } if (!empty($this->groupIDs)) { $this->conditions->add("user_table.userID " . ($this->invertGroupIDs == 1 ? 'NOT ' : '') . "IN (SELECT userID FROM wcf" . WCF_N . "_user_to_group WHERE groupID IN (?))", array($this->groupIDs)); } if (!empty($this->languageIDs)) { $this->conditions->add("user_table.languageID IN (?)", array($this->languageIDs)); } // registration date if ($startDate = @strtotime($this->registrationDateStart)) { $this->conditions->add('user_table.registrationDate >= ?', array($startDate)); } if ($endDate = @strtotime($this->registrationDateEnd)) { $this->conditions->add('user_table.registrationDate <= ?', array($endDate)); } if ($this->banned) { $this->conditions->add('user_table.banned = ?', array(1)); } if ($this->notBanned) { $this->conditions->add('user_table.banned = ?', array(0)); } // last activity time if ($startDate = @strtotime($this->lastActivityTimeStart)) { $this->conditions->add('user_table.lastActivityTime >= ?', array($startDate)); } if ($endDate = @strtotime($this->lastActivityTimeEnd)) { $this->conditions->add('user_table.lastActivityTime <= ?', array($endDate)); } if ($this->enabled) { $this->conditions->add('user_table.activationCode = ?', array(0)); } if ($this->disabled) { $this->conditions->add('user_table.activationCode <> ?', array(0)); } // dynamic fields foreach ($this->activeOptions as $name => $option) { $value = isset($this->values[$option['optionName']]) ? $this->values[$option['optionName']] : null; $this->getTypeObject($option['optionType'])->getCondition($this->conditions, $option, $value); } // call buildConditions event EventHandler::getInstance()->fireAction($this, 'buildConditions'); // execute action switch ($this->action) { case 'sendMail': WCF::getSession()->checkPermissions(array('admin.user.canMailUser')); // get user ids $userIDs = array(); $sql = "SELECT\t\tuser_table.userID\n\t\t\t\t\tFROM\t\twcf" . WCF_N . "_user user_table\n\t\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_user_option_value option_value\n\t\t\t\t\tON\t\t(option_value.userID = user_table.userID)" . $this->conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($this->conditions->getParameters()); while ($row = $statement->fetchArray()) { $userIDs[] = $row['userID']; $this->affectedUsers++; } if (!empty($userIDs)) { // save config in session $userMailData = WCF::getSession()->getVar('userMailData'); if ($userMailData === null) { $userMailData = array(); } $mailID = count($userMailData); $userMailData[$mailID] = array('action' => '', 'userIDs' => $userIDs, 'groupIDs' => '', 'subject' => $this->subject, 'text' => $this->text, 'from' => $this->from, 'enableHTML' => $this->enableHTML); WCF::getSession()->register('userMailData', $userMailData); WCF::getTPL()->assign('mailID', $mailID); } break; case 'exportMailAddress': WCF::getSession()->checkPermissions(array('admin.user.canMailUser')); // send content type header('Content-Type: text/' . $this->fileType . '; charset=UTF-8'); header('Content-Disposition: attachment; filename="export.' . $this->fileType . '"'); if ($this->fileType == 'xml') { echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<addresses>\n"; } // count users $sql = "SELECT\t\tCOUNT(*) AS count\n\t\t\t\t\tFROM\t\twcf" . WCF_N . "_user user_table\n\t\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_user_option_value option_value\n\t\t\t\t\tON\t\t(option_value.userID = user_table.userID)\n\t\t\t\t\t" . $this->conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($this->conditions->getParameters()); $count = $statement->fetchArray(); // get users $sql = "SELECT\t\tuser_table.email\n\t\t\t\t\tFROM\t\twcf" . WCF_N . "_user user_table\n\t\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_user_option_value option_value\n\t\t\t\t\tON\t\t(option_value.userID = user_table.userID)\n\t\t\t\t\t" . $this->conditions . "\n\t\t\t\t\tORDER BY\tuser_table.email"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($this->conditions->getParameters()); $i = 0; while ($row = $statement->fetchArray()) { if ($this->fileType == 'xml') { echo "<address><![CDATA[" . StringUtil::escapeCDATA($row['email']) . "]]></address>\n"; } else { echo $this->textSeparator . $row['email'] . $this->textSeparator . ($i < $count['count'] ? $this->separator : ''); } $i++; $this->affectedUsers++; } if ($this->fileType == 'xml') { echo "</addresses>"; } $this->saved(); exit; break; case 'assignToGroup': WCF::getSession()->checkPermissions(array('admin.user.canEditUser')); $_this = $this; $userIDs = $this->fetchUsers(function ($userID, array $userData) use($_this) { $user = new UserEditor(new User(null, $userData)); $user->addToGroups($_this->assignToGroupIDs, false, false); }); if (!empty($userIDs)) { UserStorageHandler::getInstance()->reset($userIDs, 'groupIDs', 1); } break; case 'delete': WCF::getSession()->checkPermissions(array('admin.user.canDeleteUser')); $userIDs = $this->fetchUsers(); if (!empty($userIDs)) { $userAction = new UserAction($userIDs, 'delete'); $userAction->executeAction(); } break; } $this->saved(); WCF::getTPL()->assign('affectedUsers', $this->affectedUsers); }
/** * Handles uploaded attachments. */ public function upload() { // save files $files = $this->parameters['__files']->getFiles(); $userID = !empty($this->parameters['userID']) ? intval($this->parameters['userID']) : WCF::getUser()->userID; $user = $userID != WCF::getUser()->userID ? new User($userID) : WCF::getUser(); $file = $files[0]; try { if (!$file->getValidationErrorType()) { // shrink avatar if necessary $fileLocation = $this->enforceDimensions($file->getLocation()); $imageData = getimagesize($fileLocation); $data = array('avatarName' => $file->getFilename(), 'avatarExtension' => $file->getFileExtension(), 'width' => $imageData[0], 'height' => $imageData[1], 'userID' => $userID, 'fileHash' => sha1_file($fileLocation)); // create avatar $avatar = UserAvatarEditor::create($data); // check avatar directory // and create subdirectory if necessary $dir = dirname($avatar->getLocation()); if (!@file_exists($dir)) { FileUtil::makePath($dir, 0777); } // move uploaded file if (@copy($fileLocation, $avatar->getLocation())) { @unlink($fileLocation); // create thumbnails $action = new UserAvatarAction(array($avatar), 'generateThumbnails'); $action->executeAction(); // delete old avatar if ($user->avatarID) { $action = new UserAvatarAction(array($user->avatarID), 'delete'); $action->executeAction(); } // update user $userEditor = new UserEditor($user); $userEditor->update(array('avatarID' => $avatar->avatarID, 'enableGravatar' => 0)); // reset user storage UserStorageHandler::getInstance()->reset(array($userID), 'avatar'); // return result return array('avatarID' => $avatar->avatarID, 'canCrop' => $avatar->canCrop(), 'url' => $avatar->getURL(96)); } else { // moving failed; delete avatar $editor = new UserAvatarEditor($avatar); $editor->delete(); throw new UserInputException('avatar', 'uploadFailed'); } } } catch (UserInputException $e) { $file->setValidationErrorType($e->getType()); } return array('errorType' => $file->getValidationErrorType()); }
/** * Removes all likes for given objects. * * @param string $objectType * @param array<integer> $objectIDs * @param array<string> $notificationObjectTypes */ public function removeLikes($objectType, array $objectIDs, array $notificationObjectTypes = array()) { $objectTypeObj = $this->getObjectType($objectType); // get like objects $likeObjectList = new LikeObjectList(); $likeObjectList->getConditionBuilder()->add('like_object.objectTypeID = ?', array($objectTypeObj->objectTypeID)); $likeObjectList->getConditionBuilder()->add('like_object.objectID IN (?)', array($objectIDs)); $likeObjectList->readObjects(); $likeObjects = $likeObjectList->getObjects(); $likeObjectIDs = $likeObjectList->getObjectIDs(); // reduce count of received users $users = array(); foreach ($likeObjects as $likeObject) { if ($likeObject->likes) { if (!isset($users[$likeObject->objectUserID])) { $users[$likeObject->objectUserID] = 0; } $users[$likeObject->objectUserID] += $likeObject->likes; } } foreach ($users as $userID => $receivedLikes) { $userEditor = new UserEditor(new User(null, array('userID' => $userID))); $userEditor->updateCounters(array('likesReceived' => $receivedLikes * -1)); } // get like ids $likeList = new LikeList(); $likeList->getConditionBuilder()->add('like_table.objectTypeID = ?', array($objectTypeObj->objectTypeID)); $likeList->getConditionBuilder()->add('like_table.objectID IN (?)', array($objectIDs)); $likeList->readObjects(); if (count($likeList)) { $likeData = array(); foreach ($likeList as $like) { $likeData[$like->likeID] = $like->userID; } // delete like notifications if (!empty($notificationObjectTypes)) { foreach ($notificationObjectTypes as $notificationObjectType) { UserNotificationHandler::getInstance()->removeNotifications($notificationObjectType, $likeList->getObjectIDs()); } } else { if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType . '.notification')) { UserNotificationHandler::getInstance()->removeNotifications($objectType . '.notification', $likeList->getObjectIDs()); } } // revoke activity points UserActivityPointHandler::getInstance()->removeEvents('com.woltlab.wcf.like.activityPointEvent.receivedLikes', $likeData); // delete likes LikeEditor::deleteAll(array_keys($likeData)); } // delete like objects if (!empty($likeObjectIDs)) { LikeObjectEditor::deleteAll($likeObjectIDs); } // delete activity events if (UserActivityEventHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.recentActivityEvent')) { UserActivityEventHandler::getInstance()->removeEvents($objectTypeObj->objectType . '.recentActivityEvent', $objectIDs); } }
/** * @see \wcf\system\importer\IImporter::import() */ public function import($oldID, array $data, array $additionalData = array()) { // whether to perform a merge $performMerge = false; // fetch user with same username $conflictingUser = User::getUserByUsername($data['username']); switch (ImportHandler::getInstance()->getUserMergeMode()) { case self::MERGE_MODE_USERNAME_OR_EMAIL: // merge target will be the conflicting user $targetUser = $conflictingUser; // check whether user exists if ($targetUser->userID) { $performMerge = true; break; } case self::MERGE_MODE_EMAIL: // fetch merge target $targetUser = User::getUserByEmail($data['email']); // if it exists: perform a merge if ($targetUser->userID) { $performMerge = true; } break; } // merge should be performed if ($performMerge) { ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.user', $oldID, $targetUser->userID); return 0; } // a conflict arose, but no merge was performed, resolve if ($conflictingUser->userID) { // rename user $data['username'] = self::resolveDuplicate($data['username']); } // check existing user id if (is_numeric($oldID)) { $user = new User($oldID); if (!$user->userID) { $data['userID'] = $oldID; } } // handle user options $userOptions = array(); if (isset($additionalData['options'])) { foreach ($additionalData['options'] as $optionName => $optionValue) { if (is_int($optionName)) { $optionID = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user.option', $optionName); } else { $optionID = User::getUserOptionID($optionName); } if ($optionID) { $userOptions[$optionID] = $optionValue; } } // fix option values foreach ($userOptions as $optionID => &$optionValue) { switch ($this->userOptions[$optionID]->optionType) { case 'boolean': if ($optionValue) { $optionValue = 1; } else { $optionValue = 0; } break; case 'integer': $optionValue = intval($optionValue); if ($optionValue > 2147483647) { $optionValue = 2147483647; } break; case 'float': $optionValue = floatval($optionValue); break; case 'textarea': if (strlen($optionValue) > 16777215) { $optionValue = substr($optionValue, 0, 16777215); } break; case 'birthday': case 'date': if (!preg_match('/^\\d{4}\\-\\d{2}\\-\\d{2}$/', $optionValue)) { $optionValue = '0000-00-00'; } break; default: if (strlen($optionValue) > 65535) { $optionValue = substr($optionValue, 0, 65535); } } } } $languageIDs = array(); if (isset($additionalData['languages'])) { foreach ($additionalData['languages'] as $languageCode) { $language = LanguageFactory::getInstance()->getLanguageByCode($languageCode); if ($language !== null) { $languageIDs[] = $language->languageID; } } } if (empty($languageIDs)) { $languageIDs[] = LanguageFactory::getInstance()->getDefaultLanguageID(); } // assign an interface language $data['languageID'] = reset($languageIDs); // create user $user = UserEditor::create($data); $userEditor = new UserEditor($user); // updates user options $userEditor->updateUserOptions($userOptions); // save user groups $groupIDs = array(); if (isset($additionalData['groupIDs'])) { foreach ($additionalData['groupIDs'] as $oldGroupID) { $newGroupID = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user.group', $oldGroupID); if ($newGroupID) { $groupIDs[] = $newGroupID; } } } if (!$user->activationCode) { $defaultGroupIDs = UserGroup::getGroupIDsByType(array(UserGroup::EVERYONE, UserGroup::USERS)); } else { $defaultGroupIDs = UserGroup::getGroupIDsByType(array(UserGroup::EVERYONE, UserGroup::GUESTS)); } $groupIDs = array_merge($groupIDs, $defaultGroupIDs); $sql = "INSERT IGNORE INTO\twcf" . WCF_N . "_user_to_group\n\t\t\t\t\t\t(userID, groupID)\n\t\t\tVALUES\t\t\t(?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); foreach ($groupIDs as $groupID) { $statement->execute(array($user->userID, $groupID)); } // save languages $sql = "INSERT IGNORE INTO\twcf" . WCF_N . "_user_to_language\n\t\t\t\t\t\t(userID, languageID)\n\t\t\tVALUES\t\t\t(?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); foreach ($languageIDs as $languageID) { $statement->execute(array($user->userID, $languageID)); } // save default user events $sql = "INSERT IGNORE INTO\twcf" . WCF_N . "_user_notification_event_to_user\n\t\t\t\t\t\t(userID, eventID)\n\t\t\tVALUES\t\t\t(?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); foreach ($this->eventIDs as $eventID) { $statement->execute(array($user->userID, $eventID)); } // save mapping ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.user', $oldID, $user->userID); return $user->userID; }
/** * @see wcf\form\IForm::save() */ public function save() { parent::save(); $conditions = new PreparedStatementConditionBuilder(); $conditions->add("userID IN (?)", array($this->userIDs)); $sql = "SELECT\tuserID, groupID\n\t\t\tFROM\twcf" . WCF_N . "_user_to_group\n\t\t\t" . $conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $groups = array(); while ($row = $statement->fetchArray()) { $groups[$row['userID']][] = $row['groupID']; } foreach ($this->users as $user) { if (!UserGroup::isAccessibleGroup($groups[$user->userID])) { throw new PermissionDeniedException(); } $groupsIDs = array_merge($groups[$user->userID], $this->groupIDs); $groupsIDs = array_unique($groupsIDs); $userEditor = new UserEditor($user); $userEditor->addToGroups($groupsIDs, true, false); } ClipboardHandler::getInstance()->removeItems($this->typeID); SessionHandler::resetSessions($this->userIDs); $this->saved(); WCF::getTPL()->assign('message', 'wcf.acp.user.assignToGroup.success'); WCF::getTPL()->display('success'); exit; }
/** * @see \wcf\action\IAction::execute() */ public function execute() { parent::execute(); $callbackURL = LinkHandler::getInstance()->getLink('GoogleAuth', array('appendSession' => false)); // user accepted the connection if (isset($_GET['code'])) { try { // fetch access_token $request = new HTTPRequest('https://accounts.google.com/o/oauth2/token', array(), array('code' => $_GET['code'], 'client_id' => StringUtil::trim(GOOGLE_PUBLIC_KEY), 'client_secret' => StringUtil::trim(GOOGLE_PRIVATE_KEY), 'redirect_uri' => $callbackURL, 'grant_type' => 'authorization_code')); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } // validate state, validation of state is executed after fetching the access_token to invalidate 'code' if (!isset($_GET['state']) || $_GET['state'] != WCF::getSession()->getVar('__googleInit')) { throw new IllegalLinkException(); } WCF::getSession()->unregister('__googleInit'); $data = JSON::decode($content); try { // fetch userdata $request = new HTTPRequest('https://www.googleapis.com/plus/v1/people/me'); $request->addHeader('Authorization', 'Bearer ' . $data['access_token']); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } $userData = JSON::decode($content); // check whether a user is connected to this google account $user = $this->getUser($userData['id']); if ($user->userID) { // a user is already connected, but we are logged in, break if (WCF::getUser()->userID) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.google.connect.error.inuse')); } else { if (UserAuthenticationFactory::getInstance()->getUserAuthentication()->supportsPersistentLogins()) { $password = StringUtil::getRandomID(); $userEditor = new UserEditor($user); $userEditor->update(array('password' => $password)); // reload user to retrieve salt $user = new User($user->userID); UserAuthenticationFactory::getInstance()->getUserAuthentication()->storeAccessData($user, $user->username, $password); } WCF::getSession()->changeUser($user); WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink()); } } else { WCF::getSession()->register('__3rdPartyProvider', 'google'); // save data for connection if (WCF::getUser()->userID) { WCF::getSession()->register('__googleUsername', $userData['displayName']); WCF::getSession()->register('__googleData', $userData); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('AccountManagement') . '#3rdParty'); } else { WCF::getSession()->register('__username', $userData['displayName']); if (isset($userData['emails'][0]['value'])) { WCF::getSession()->register('__email', $userData['emails'][0]['value']); } WCF::getSession()->register('__googleData', $userData); // we assume that bots won't register on google first // thus no need for a captcha if (REGISTER_USE_CAPTCHA) { WCF::getSession()->register('noRegistrationCaptcha', true); } WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Register')); } } $this->executed(); exit; } // user declined or any other error that may occur if (isset($_GET['error'])) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.google.login.error.' . $_GET['error'])); } // start auth by redirecting to google $token = StringUtil::getRandomID(); WCF::getSession()->register('__googleInit', $token); HeaderUtil::redirect("https://accounts.google.com/o/oauth2/auth?client_id=" . rawurlencode(StringUtil::trim(GOOGLE_PUBLIC_KEY)) . "&redirect_uri=" . rawurlencode($callbackURL) . "&state=" . $token . "&scope=profile+email&response_type=code"); $this->executed(); exit; }
/** * @see \wcf\system\cronjob\ICronjob::execute() */ public function execute(Cronjob $cronjob) { parent::execute($cronjob); // get user ids $userIDs = array(); $sql = "SELECT\tDISTINCT userID\n\t\t\tFROM\twcf" . WCF_N . "_user_notification\n\t\t\tWHERE\tmailNotified = ?\n\t\t\t\tAND time < ?\n\t\t\t\tAND confirmTime = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array(0, TIME_NOW - 3600 * 23, 0)); while ($row = $statement->fetchArray()) { $userIDs[] = $row['userID']; } if (empty($userIDs)) { return; } // get users $userList = new UserList(); $userList->setObjectIDs($userIDs); $userList->readObjects(); $users = $userList->getObjects(); // get notifications $conditions = new PreparedStatementConditionBuilder(); $conditions->add("notification.userID IN (?)", array($userIDs)); $conditions->add("notification.mailNotified = ?", array(0)); $conditions->add("notification.confirmTime = ?", array(0)); $sql = "SELECT\t\tnotification.*, notification_event.eventID, object_type.objectType\n\t\t\tFROM\t\twcf" . WCF_N . "_user_notification notification\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_user_notification_event notification_event\n\t\t\tON\t\t(notification_event.eventID = notification.eventID)\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_object_type object_type\n\t\t\tON\t\t(object_type.objectTypeID = notification_event.objectTypeID)\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\tnotification.time"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); // mark notifications as done $conditions = new PreparedStatementConditionBuilder(); $conditions->add("userID IN (?)", array($userIDs)); $conditions->add("mailNotified = ?", array(0)); $sql = "UPDATE\twcf" . WCF_N . "_user_notification\n\t\t\tSET\tmailNotified = 1\n\t\t\t" . $conditions; $statement2 = WCF::getDB()->prepareStatement($sql); $statement2->execute($conditions->getParameters()); // collect data $eventsToUser = $objectTypes = $eventIDs = $notificationObjects = array(); $availableObjectTypes = UserNotificationHandler::getInstance()->getAvailableObjectTypes(); while ($row = $statement->fetchArray()) { if (!isset($eventsToUser[$row['userID']])) { $eventsToUser[$row['userID']] = array(); } $eventsToUser[$row['userID']][] = $row['notificationID']; // cache object types if (!isset($objectTypes[$row['objectType']])) { $objectTypes[$row['objectType']] = array('objectType' => $availableObjectTypes[$row['objectType']], 'objectIDs' => array(), 'objects' => array()); } $objectTypes[$row['objectType']]['objectIDs'][] = $row['objectID']; $eventIDs[] = $row['eventID']; $notificationObjects[$row['notificationID']] = new UserNotification(null, $row); } // load authors $conditions = new PreparedStatementConditionBuilder(); $conditions->add("notificationID IN (?)", array(array_keys($notificationObjects))); $sql = "SELECT\t\tnotificationID, authorID\n\t\t\tFROM\t\twcf" . WCF_N . "_user_notification_author\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\ttime ASC"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $authorIDs = $authorToNotification = array(); while ($row = $statement->fetchArray()) { if ($row['authorID']) { $authorIDs[] = $row['authorID']; } if (!isset($authorToNotification[$row['notificationID']])) { $authorToNotification[$row['notificationID']] = array(); } $authorToNotification[$row['notificationID']][] = $row['authorID']; } // load authors $authors = UserProfile::getUserProfiles($authorIDs); $unknownAuthor = new UserProfile(new User(null, array('userID' => null, 'username' => WCF::getLanguage()->get('wcf.user.guest')))); // load objects associated with each object type foreach ($objectTypes as $objectType => $objectData) { $objectTypes[$objectType]['objects'] = $objectData['objectType']->getObjectsByIDs($objectData['objectIDs']); } // load required events $eventList = new UserNotificationEventList(); $eventList->getConditionBuilder()->add("user_notification_event.eventID IN (?)", array($eventIDs)); $eventList->readObjects(); $eventObjects = $eventList->getObjects(); foreach ($eventsToUser as $userID => $events) { if (!isset($users[$userID])) { continue; } $user = $users[$userID]; // no notifications for disabled or banned users if ($user->activationCode) { continue; } if ($user->banned) { continue; } // add mail header $message = $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.header', array('user' => $user)); foreach ($events as $notificationID) { $notification = $notificationObjects[$notificationID]; $className = $eventObjects[$notification->eventID]->className; $class = new $className($eventObjects[$notification->eventID]); $class->setObject($notification, $objectTypes[$notification->objectType]['objects'][$notification->objectID], isset($authors[$notification->authorID]) ? $authors[$notification->authorID] : $unknownAuthor, $notification->additionalData); $class->setLanguage($user->getLanguage()); if (isset($authorToNotification[$notification->notificationID])) { $eventAuthors = array(); foreach ($authorToNotification[$notification->notificationID] as $userID) { if (!$userID) { $eventAuthors[0] = $unknownAuthor; } else { if (isset($authors[$userID])) { $eventAuthors[$userID] = $authors[$userID]; } } } if (!empty($eventAuthors)) { $class->setAuthors($eventAuthors); } } $message .= "\n\n"; $message .= $class->getEmailMessage('daily'); } // append notification mail footer $token = $user->notificationMailToken; if (!$token) { // generate token if not present $token = mb_substr(StringUtil::getHash(serialize(array($user->userID, StringUtil::getRandomID()))), 0, 20); $editor = new UserEditor($user); $editor->update(array('notificationMailToken' => $token)); } $message .= "\n\n"; $message .= $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.daily.footer', array('user' => $user, 'token' => $token)); // build mail $mail = new Mail(array($user->username => $user->email), $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.daily.subject', array('count' => count($events))), $message); $mail->setLanguage($user->getLanguage()); $mail->send(); } }
/** * @see \wcf\form\IForm::save() */ public function save() { AbstractForm::save(); // handle avatar if ($this->avatarType != 'custom') { // delete custom avatar if ($this->user->avatarID) { $action = new UserAvatarAction(array($this->user->avatarID), 'delete'); $action->executeAction(); } } switch ($this->avatarType) { case 'none': $avatarData = array('avatarID' => null, 'enableGravatar' => 0); break; case 'custom': $avatarData = array('enableGravatar' => 0); break; case 'gravatar': $avatarData = array('avatarID' => null, 'enableGravatar' => 1); break; } $this->additionalFields = array_merge($this->additionalFields, $avatarData); // add default groups $defaultGroups = UserGroup::getAccessibleGroups(array(UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS)); $oldGroupIDs = $this->user->getGroupIDs(); foreach ($oldGroupIDs as $oldGroupID) { if (isset($defaultGroups[$oldGroupID])) { $this->groupIDs[] = $oldGroupID; } } $this->groupIDs = array_unique($this->groupIDs); // save user $saveOptions = $this->optionHandler->save(); $data = array('data' => array_merge($this->additionalFields, array('username' => $this->username, 'email' => $this->email, 'password' => $this->password, 'languageID' => $this->languageID, 'userTitle' => $this->userTitle, 'signature' => $this->signature, 'signatureEnableBBCodes' => $this->signatureEnableBBCodes, 'signatureEnableSmilies' => $this->signatureEnableSmilies, 'signatureEnableHtml' => $this->signatureEnableHtml)), 'groups' => $this->groupIDs, 'languageIDs' => $this->visibleLanguages, 'options' => $saveOptions); // handle ban if (WCF::getSession()->getPermission('admin.user.canBanUser')) { if ($this->banExpires) { $this->banExpires = strtotime($this->banExpires); } else { $this->banExpires = 0; } $data['data']['banned'] = $this->banned; $data['data']['banReason'] = $this->banReason; $data['data']['banExpires'] = $this->banExpires; } // handle disabled signature if (WCF::getSession()->getPermission('admin.user.canDisableSignature')) { if ($this->disableSignatureExpires) { $this->disableSignatureExpires = strtotime($this->disableSignatureExpires); } else { $this->disableSignatureExpires = 0; } $data['data']['disableSignature'] = $this->disableSignature; $data['data']['disableSignatureReason'] = $this->disableSignatureReason; $data['data']['disableSignatureExpires'] = $this->disableSignatureExpires; } // handle disabled avatar if (WCF::getSession()->getPermission('admin.user.canDisableAvatar')) { if ($this->disableAvatarExpires) { $this->disableAvatarExpires = strtotime($this->disableAvatarExpires); } else { $this->disableAvatarExpires = 0; } $data['data']['disableAvatar'] = $this->disableAvatar; $data['data']['disableAvatarReason'] = $this->disableAvatarReason; $data['data']['disableAvatarExpires'] = $this->disableAvatarExpires; } $this->objectAction = new UserAction(array($this->userID), 'update', $data); $this->objectAction->executeAction(); // update user rank $editor = new UserEditor(new User($this->userID)); if (MODULE_USER_RANK) { $action = new UserProfileAction(array($editor), 'updateUserRank'); $action->executeAction(); } if (MODULE_USERS_ONLINE) { $action = new UserProfileAction(array($editor), 'updateUserOnlineMarking'); $action->executeAction(); } // remove assignments $sql = "DELETE FROM\twcf" . WCF_N . "_moderation_queue_to_user\n\t\t\tWHERE\t\tuserID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->user->userID)); // reset moderation count ModerationQueueManager::getInstance()->resetModerationCount($this->user->userID); $this->saved(); // reset password $this->password = $this->confirmPassword = ''; // show success message WCF::getTPL()->assign('success', true); }
/** * Creates a new user. * * @return User */ public function create() { $user = parent::create(); $userEditor = new UserEditor($user); // updates user options if (isset($this->parameters['options'])) { $userEditor->updateUserOptions($this->parameters['options']); } // insert user groups $addDefaultGroups = isset($this->parameters['addDefaultGroups']) ? $this->parameters['addDefaultGroups'] : true; $groupIDs = isset($this->parameters['groups']) ? $this->parameters['groups'] : array(); $userEditor->addToGroups($groupIDs, false, $addDefaultGroups); // insert visible languages $languageIDs = isset($this->parameters['languages']) ? $this->parameters['languages'] : array(); $userEditor->addToLanguages($languageIDs); return $user; }
/** * Sends the mail notification. * * @param \wcf\data\user\notification\UserNotification $notification * @param \wcf\data\user\User $user * @param \wcf\system\user\notification\event\IUserNotificationEvent $event */ public function sendInstantMailNotification(UserNotification $notification, User $user, IUserNotificationEvent $event) { // no notifications for disabled or banned users if ($user->activationCode) { return; } if ($user->banned) { return; } // recipient's language $event->setLanguage($user->getLanguage()); // add mail header $message = $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.header', array('user' => $user)) . "\n\n"; // get message $message .= $event->getEmailMessage(); // append notification mail footer $token = $user->notificationMailToken; if (!$token) { // generate token if not present $token = mb_substr(StringUtil::getHash(serialize(array($user->userID, StringUtil::getRandomID()))), 0, 20); $editor = new UserEditor($user); $editor->update(array('notificationMailToken' => $token)); } $message .= "\n\n" . $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.footer', array('user' => $user, 'token' => $token, 'notification' => $notification)); // build mail $mail = new Mail(array($user->username => $user->email), $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.subject', array('title' => $event->getEmailTitle())), $message); $mail->setLanguage($user->getLanguage()); $mail->send(); }
/** * Copies likes from one object id to another. */ public function copy() { $sourceObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.like.likeableObject', $this->parameters['sourceObjectType']); $targetObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.like.likeableObject', $this->parameters['targetObjectType']); // // step 1) get data // // get like object $sql = "SELECT\t*\n\t\t\tFROM\twcf" . WCF_N . "_like_object\n\t\t\tWHERE\tobjectTypeID = ?\n\t\t\t\tAND objectID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($sourceObjectType->objectTypeID, $this->parameters['sourceObjectID'])); $row = $statement->fetchArray(); // no (dis-)likes at all if ($row === false) { return; } unset($row['likeObjectID']); $row['objectTypeID'] = $targetObjectType->objectTypeID; $row['objectID'] = $this->parameters['targetObjectID']; $newLikeObject = LikeObjectEditor::create($row); // // step 2) copy // $sql = "INSERT INTO\twcf" . WCF_N . "_like\n\t\t\t\t\t(objectID, objectTypeID, objectUserID, userID, time, likeValue)\n\t\t\tSELECT\t\t" . $this->parameters['targetObjectID'] . ", " . $targetObjectType->objectTypeID . ", objectUserID, userID, time, likeValue\n\t\t\tFROM\t\twcf" . WCF_N . "_like\n\t\t\tWHERE\t\tobjectTypeID = ?\n\t\t\t\t\tAND objectID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($sourceObjectType->objectTypeID, $this->parameters['sourceObjectID'])); // // step 3) update owner // if ($newLikeObject->objectUserID) { $sql = "SELECT\tCOUNT(*) AS count\n\t\t\t\tFROM\twcf" . WCF_N . "_like\n\t\t\t\tWHERE\tobjectTypeID = ?\n\t\t\t\t\tAND objectID = ?\n\t\t\t\t\tAND likeValue = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($targetObjectType->objectTypeID, $this->parameters['targetObjectID'], Like::LIKE)); $row = $statement->fetchArray(); if ($row['count']) { // update received likes $userEditor = new UserEditor(new User($newLikeObject->objectUserID)); $userEditor->updateCounters(array('likesReceived' => $row['count'])); // add activity points UserActivityPointHandler::getInstance()->fireEvents('com.woltlab.wcf.like.activityPointEvent.receivedLikes', array($newLikeObject->objectUserID => $row['count'])); } } }
/** * Returns true if the given password is the correct password for this user. * * @param string $password * @return boolean password correct */ public function checkPassword($password) { $isValid = false; $rebuild = false; // check if password is a valid bcrypt hash if (PasswordUtil::isBlowfish($this->password)) { if (PasswordUtil::isDifferentBlowfish($this->password)) { $rebuild = true; } // password is correct if (PasswordUtil::secureCompare($this->password, PasswordUtil::getDoubleSaltedHash($password, $this->password))) { $isValid = true; } } else { // different encryption type if (PasswordUtil::checkPassword($this->username, $password, $this->password)) { $isValid = true; $rebuild = true; } } // create new password hash, either different encryption or different blowfish cost factor if ($rebuild) { $userEditor = new UserEditor($this); $userEditor->update(array( 'password' => $password )); } return $isValid; }
public function saveSocialNetworkPrivacySettings() { $settings = array('facebook' => $this->parameters['facebook'], 'google' => $this->parameters['google'], 'reddit' => $this->parameters['reddit'], 'twitter' => $this->parameters['twitter']); $userEditor = new UserEditor(WCF::getUser()); $userEditor->update(array('socialNetworkPrivacySettings' => serialize($settings))); return array('settings' => $settings); }
/** * @see \wcf\action\IAction::execute() */ public function execute() { parent::execute(); // user accepted if (isset($_GET['oauth_token']) && isset($_GET['oauth_verifier'])) { // fetch data created in the first step $initData = WCF::getSession()->getVar('__twitterInit'); WCF::getSession()->unregister('__twitterInit'); if (!$initData) { throw new IllegalLinkException(); } // validate oauth_token if ($_GET['oauth_token'] !== $initData['oauth_token']) { throw new IllegalLinkException(); } try { // fetch access_token $oauthHeader = array('oauth_consumer_key' => StringUtil::trim(TWITTER_PUBLIC_KEY), 'oauth_nonce' => StringUtil::getRandomID(), 'oauth_signature_method' => 'HMAC-SHA1', 'oauth_timestamp' => TIME_NOW, 'oauth_version' => '1.0', 'oauth_token' => $initData['oauth_token']); $postData = array('oauth_verifier' => $_GET['oauth_verifier']); $signature = $this->createSignature('https://api.twitter.com/oauth/access_token', array_merge($oauthHeader, $postData)); $oauthHeader['oauth_signature'] = $signature; $request = new HTTPRequest('https://api.twitter.com/oauth/access_token', array(), $postData); $request->addHeader('Authorization', 'OAuth ' . $this->buildOAuthHeader($oauthHeader)); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } parse_str($content, $data); // check whether a user is connected to this twitter account $user = $this->getUser($data['user_id']); if ($user->userID) { // a user is already connected, but we are logged in, break if (WCF::getUser()->userID) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.twitter.connect.error.inuse')); } else { if (UserAuthenticationFactory::getInstance()->getUserAuthentication()->supportsPersistentLogins()) { $password = StringUtil::getRandomID(); $userEditor = new UserEditor($user); $userEditor->update(array('password' => $password)); // reload user to retrieve salt $user = new User($user->userID); UserAuthenticationFactory::getInstance()->getUserAuthentication()->storeAccessData($user, $user->username, $password); } WCF::getSession()->changeUser($user); WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink()); } } else { WCF::getSession()->register('__3rdPartyProvider', 'twitter'); // save data for connection if (WCF::getUser()->userID) { WCF::getSession()->register('__twitterUsername', $data['screen_name']); WCF::getSession()->register('__twitterData', $data); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('AccountManagement') . '#3rdParty'); } else { // fetch user data $twitterData = null; try { $request = new HTTPRequest('https://api.twitter.com/1.1/users/show.json?screen_name=' . $data['screen_name']); $request->execute(); $reply = $request->getReply(); $twitterData = json_decode($reply['body'], true); } catch (SystemException $e) { /* ignore errors */ } WCF::getSession()->register('__username', $data['screen_name']); if ($twitterData !== null) { $data = $twitterData; } WCF::getSession()->register('__twitterData', $data); // we assume that bots won't register on twitter first // thus no need for a captcha if (REGISTER_USE_CAPTCHA) { WCF::getSession()->register('noRegistrationCaptcha', true); } WCF::getSession()->update(); HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Register')); } } $this->executed(); exit; } // user declined if (isset($_GET['denied'])) { throw new NamedUserException(WCF::getLanguage()->get('wcf.user.3rdparty.twitter.login.error.denied')); } // start auth by fetching request_token try { $callbackURL = LinkHandler::getInstance()->getLink('TwitterAuth', array('appendSession' => false)); $oauthHeader = array('oauth_callback' => $callbackURL, 'oauth_consumer_key' => StringUtil::trim(TWITTER_PUBLIC_KEY), 'oauth_nonce' => StringUtil::getRandomID(), 'oauth_signature_method' => 'HMAC-SHA1', 'oauth_timestamp' => TIME_NOW, 'oauth_version' => '1.0'); $signature = $this->createSignature('https://api.twitter.com/oauth/request_token', $oauthHeader); $oauthHeader['oauth_signature'] = $signature; // call api $request = new HTTPRequest('https://api.twitter.com/oauth/request_token', array('method' => 'POST')); $request->addHeader('Authorization', 'OAuth ' . $this->buildOAuthHeader($oauthHeader)); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { // force logging $e->getExceptionID(); throw new IllegalLinkException(); } parse_str($content, $data); if ($data['oauth_callback_confirmed'] != 'true') { throw new IllegalLinkException(); } WCF::getSession()->register('__twitterInit', $data); // redirect to twitter HeaderUtil::redirect('https://api.twitter.com/oauth/authenticate?oauth_token=' . rawurlencode($data['oauth_token'])); $this->executed(); exit; }
/** * @see \wcf\page\IPage::show() */ public function show() { // update profile hits if ($this->user->userID != WCF::getUser()->userID && !WCF::getSession()->spiderID && !$this->user->isProtected()) { $editor = new UserEditor($this->user->getDecoratedObject()); $editor->updateCounters(array('profileHits' => 1)); // save visitor if (PROFILE_ENABLE_VISITORS && WCF::getUser()->userID && !WCF::getUser()->canViewOnlineStatus) { if (($visitor = UserProfileVisitor::getObject($this->user->userID, WCF::getUser()->userID)) !== null) { $editor = new UserProfileVisitorEditor($visitor); $editor->update(array('time' => TIME_NOW)); } else { UserProfileVisitorEditor::create(array('ownerID' => $this->user->userID, 'userID' => WCF::getUser()->userID, 'time' => TIME_NOW)); } } } parent::show(); }
/** * update email */ public function updateEmail($password, $email, &$resultMessage) { try { $oExttMbqUserAddForm = new ExttMbqUserAddForm(); try { $oUser = WCF::getSession()->getUser(); if ($oUser->checkPassword($password)) { $userEditor = new UserEditor($oUser); $userEditor->update(array('email' => $email)); } else { return "password is not valid"; } } catch (UserInputException $e) { return $e->getType(); } } catch (Exception $e) { return $e->getMessage(); } return true; }