/** * Searches for purchased items in the WoltLab Plugin-Store. * * @return array<string> */ public function searchForPurchasedItems() { if (!RemoteFile::supportsSSL()) { return array('noSSL' => WCF::getLanguage()->get('wcf.acp.pluginStore.api.noSSL')); } if (empty($this->parameters['username']) || empty($this->parameters['password'])) { return array('template' => $this->renderAuthorizationDialog(false)); } $request = new HTTPRequest('https://api.woltlab.com/1.0/customer/purchases/list.json', array('method' => 'POST'), array('username' => $this->parameters['username'], 'password' => $this->parameters['password'], 'wcfVersion' => WCF_VERSION)); $request->execute(); $reply = $request->getReply(); $response = JSON::decode($reply['body']); $code = isset($response['status']) ? $response['status'] : 500; switch ($code) { case 200: if (empty($response['products'])) { return array('noResults' => WCF::getLanguage()->get('wcf.acp.pluginStore.purchasedItems.noResults')); } else { WCF::getSession()->register('__pluginStoreProducts', $response['products']); WCF::getSession()->register('__pluginStoreWcfMajorReleases', $response['wcfMajorReleases']); return array('redirectURL' => LinkHandler::getInstance()->getLink('PluginStorePurchasedItems')); } break; // authentication error // authentication error case 401: return array('template' => $this->renderAuthorizationDialog(true)); break; // any other kind of errors // any other kind of errors default: throw new SystemException(WCF::getLanguage()->getDynamicVariable('wcf.acp.pluginStore.api.error', array('status' => $code))); break; } }
/** * @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\system\event\IEventListener::execute() */ public function execute($eventObj, $className, $eventName) { $this->eventObj = $eventObj; // set variables required for the smartbanner feature $functionCallAfterWindowLoad = 0; $app_forum_name = WCF::getLanguage()->get(PAGE_TITLE); $board_url = WCF::getPath('wbb'); $tapatalk_dir = WBB_TAPATALK_DIR; $tapatalk_dir_url = $board_url . $tapatalk_dir; $app_location_url = $this->getSchemeURL($page_type); $app_banner_message = defined('WBB_TAPATALK_APP_BANNER_MESSAGE') ? WBB_TAPATALK_APP_BANNER_MESSAGE : WCF::getLanguage()->get('wcf.user.3rdparty.tapatalk.app_banner_message'); $app_ios_id = StringUtil::trim(defined('WBB_TAPATALK_APP_IOS_ID') ? WBB_TAPATALK_APP_IOS_ID : ''); $app_android_id = StringUtil::trim(defined('WBB_TAPATALK_APP_ANDROID_ID') ? WBB_TAPATALK_APP_ANDROID_ID : ''); $app_kindle_url = StringUtil::trim(defined('WBB_TAPATALK_APP_KINDLE_URL') ? WBB_TAPATALK_APP_KINDLE_URL : ''); // for full view ads $api_key = StringUtil::trim(defined('WBB_TAPATALK_API_KEY') ? WBB_TAPATALK_API_KEY : ''); $app_ads_enable = defined('WBB_TAPATALK_APP_FULL_BANNER') ? WBB_TAPATALK_APP_FULL_BANNER : 1; $app_banner_enable = defined('WBB_TAPATALK_APP_SMART_BANNER') ? WBB_TAPATALK_APP_SMART_BANNER : 1; $twitterfacebook_card_enabled = defined('WBB_TAPATALK_APP_FACEBOOK_TWITTER_DEEP_LINKING') ? WBB_TAPATALK_APP_FACEBOOK_TWITTER_DEEP_LINKING : 1; $banner_control = defined('WBB_TAPATALK_BANNER_CONTROL') ? WBB_TAPATALK_BANNER_CONTROL : 1; if (WBB_TAPATALK_BANNER_LAST_CHECK == 0 || TIME_NOW - WBB_TAPATALK_BANNER_LAST_CHECK > 1) { try { // fetch access_token $request = new HTTPRequest('https://tapatalk.com/get_forum_info.php', array(), array('key' => md5(StringUtil::trim(WBB_TAPATALK_API_KEY)), 'url' => $board_url)); $request->execute(); $reply = $request->getReply(); $response = $reply['body']; } catch (\Exception $e) { die($e->getMessage()); } if (!empty($response)) { $result = explode(':', $response); if ($result[0] == 'banner_control') { if ($banner_control != $result[1]) { $options = array('wbb_tapatalk_banner_last_check' => TIME_NOW, 'wbb_tapatalk_banner_control' => $banner_control); OptionEditor::import($options); } } } } if (!$banner_control) { $app_ads_enable = $app_banner_enable = 1; } if (file_exists(WBB_TAPATALK_DIR . '/smartbanner/head.inc.php')) { include WBB_TAPATALK_DIR . '/smartbanner/head.inc.php'; } if (isset($app_head_include)) { // rebuild the output HTML since we must place the meta tags for Twitter somewhere else WCF::getTPL()->assign(array('tapatalkSmartbanner' => isset($app_banner_head) ? $app_banner_head : '', 'tapatalkTwitterAppCard' => isset($app_head_include) ? $app_head_include : '')); } }
/** * 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' => '' )); }
/** * Validates response. * * @param string $response */ public function validate($response) { // fail if response is empty to avoid sending api requests if (empty($response)) { throw new UserInputException('recaptchaString', 'false'); } $request = new HTTPRequest('https://www.google.com/recaptcha/api/siteverify?secret=' . rawurlencode(RECAPTCHA_PRIVATEKEY) . '&response=' . rawurlencode($response) . '&remoteip=' . rawurlencode(UserUtil::getIpAddress()), array('timeout' => 10)); try { $request->execute(); $reply = $request->getReply(); $data = JSON::decode($reply['body']); if ($data['success']) { // yeah } else { throw new UserInputException('recaptchaString', 'false'); } } catch (SystemException $e) { // log error, but accept captcha $e->getExceptionID(); } WCF::getSession()->register('recaptchaDone', true); }
/** * @see \cms\system\content\type\IContentType::getOutput() */ public function getOutput(Content $content) { $rssURL = $content->url; //try { $request = new HTTPRequest($rssURL); $request->execute(); $feedData = $request->getReply(); $feedData = $feedData['body']; //} //catch (SystemException $e) { //// log error //$e->getExceptionID(); //return; //} if (!($xml = simplexml_load_string($feedData))) { return; } $feed = array(); $i = $content->limit; $feedType = $this->getFeedType($xml); $feed = $this->getFeedData($xml, $i, $feedType); WCF::getTPL()->assign(array('rssFeed' => $feed)); return parent::getOutput($content); }
/** * Queries server to verify successful response. * * @param string $challenge * @param string $response */ protected function verify($challenge, $response) { $request = new HTTPRequest('http://www.google.com/recaptcha/api/verify', array('timeout' => 10), array('privatekey' => $this->privateKey, 'remoteip' => UserUtil::getIpAddress(), 'challenge' => $challenge, 'response' => $response)); try { $request->execute(); $reply = $request->getReply(); $reCaptchaResponse = explode("\n", $reply['body']); if (StringUtil::trim($reCaptchaResponse[0]) === "true") { return self::VALID_ANSWER; } else { return StringUtil::trim($reCaptchaResponse[1]); } } catch (SystemException $e) { return self::ERROR_NOT_REACHABLE; } }
/** * @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; }
/** * Tries to download a package from available update servers. * * @param string $package package identifier * @param array $packageUpdateVersions package update versions * @param boolean $validateInstallInstructions * @return string tmp filename of a downloaded package */ protected function downloadPackage($package, $packageUpdateVersions, $validateInstallInstructions = false) { // get download from cache if ($filename = $this->getCachedDownload($package, $packageUpdateVersions[0]['package'])) { return $filename; } // download file foreach ($packageUpdateVersions as $packageUpdateVersion) { // get auth data $authData = $this->getAuthData($packageUpdateVersion); if ($packageUpdateVersion['filename']) { $request = new HTTPRequest($packageUpdateVersion['filename'], !empty($authData) ? array('auth' => $authData) : array(), array('apiVersion' => PackageUpdate::API_VERSION)); } else { // create request $request = new HTTPRequest($this->packageUpdateServers[$packageUpdateVersion['packageUpdateServerID']]->getDownloadURL(), !empty($authData) ? array('auth' => $authData) : array(), array('apiVersion' => PackageUpdate::API_VERSION, 'packageName' => $packageUpdateVersion['package'], 'packageVersion' => $packageUpdateVersion['packageVersion'])); } try { $request->execute(); } catch (HTTPUnauthorizedException $e) { throw new PackageUpdateUnauthorizedException($request, $this->packageUpdateServers[$packageUpdateVersion['packageUpdateServerID']], $packageUpdateVersion); } $response = $request->getReply(); // check response if ($response['statusCode'] != 200) { throw new SystemException(WCF::getLanguage()->getDynamicVariable('wcf.acp.package.error.downloadFailed', array('__downloadPackage' => $package)) . ' (' . $response['body'] . ')'); } // write content to tmp file $filename = FileUtil::getTemporaryFilename('package_'); $file = new File($filename); $file->write($response['body']); $file->close(); unset($response['body']); // test package $archive = new PackageArchive($filename); $archive->openArchive(); // check install instructions if ($validateInstallInstructions) { $installInstructions = $archive->getInstallInstructions(); if (empty($installInstructions)) { throw new SystemException("Package '" . $archive->getLocalizedPackageInfo('packageName') . "' (" . $archive->getPackageInfo('name') . ") does not contain valid installation instructions."); } } $archive->getTar()->close(); // cache download in session PackageUpdateDispatcher::getInstance()->cacheDownload($package, $packageUpdateVersion['packageVersion'], $filename); return $filename; } return false; }
/** * @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(); // 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; }
/** * Downloads a package archive from an http URL and returns the path to * the downloaded file. * * @param string $httpUrl * @param string $prefix * @param array $options * @param array $postParameters * @param array $headers empty array or a not initialized variable * @return string * @deprecated This method currently only is a wrapper around \wcf\util\HTTPRequest. Please use * HTTPRequest from now on, as this method may be removed in the future. */ public static function downloadFileFromHttp($httpUrl, $prefix = 'package', array $options = array(), array $postParameters = array(), &$headers = array()) { $request = new HTTPRequest($httpUrl, $options, $postParameters); $request->execute(); $reply = $request->getReply(); $newFileName = self::getTemporaryFilename($prefix.'_'); file_put_contents($newFileName, $reply['body']); // the file to write. $tmp = $reply['headers']; // copy variable, to avoid problems with the reference $headers = $tmp; return $newFileName; }
/** * Gets the package_update.xml from an update server. * * @param \wcf\data\package\update\server\PackageUpdateServer $updateServer * @param boolean $forceHTTP */ protected function getPackageUpdateXML(PackageUpdateServer $updateServer, $forceHTTP = false) { $settings = array(); $authData = $updateServer->getAuthData(); if ($authData) { $settings['auth'] = $authData; } $secureConnection = $updateServer->attemptSecureConnection(); if ($secureConnection && !$forceHTTP) { $settings['timeout'] = 5; } $request = new HTTPRequest($updateServer->getListURL($forceHTTP), $settings); if ($updateServer->apiVersion == '2.1') { $metaData = $updateServer->getMetaData(); if (isset($metaData['list']['etag'])) { $request->addHeader('if-none-match', $metaData['list']['etag']); } if (isset($metaData['list']['lastModified'])) { $request->addHeader('if-modified-since', $metaData['list']['lastModified']); } } try { $request->execute(); $reply = $request->getReply(); } catch (HTTPUnauthorizedException $e) { throw new PackageUpdateUnauthorizedException($request, $updateServer); } catch (SystemException $e) { $reply = $request->getReply(); $statusCode = is_array($reply['statusCode']) ? reset($reply['statusCode']) : $reply['statusCode']; // status code 0 is a connection timeout if (!$statusCode && $secureConnection) { if (preg_match('~https?://(?:update|store)\\.woltlab\\.com~', $updateServer->serverURL)) { // woltlab.com servers are most likely to be available, thus we assume that SSL connections are dropped RemoteFile::disableSSL(); } // retry via http $this->getPackageUpdateXML($updateServer, true); return; } throw new SystemException(WCF::getLanguage()->get('wcf.acp.package.update.error.listNotFound') . ' (' . $statusCode . ')'); } // parse given package update xml $allNewPackages = false; if ($updateServer->apiVersion == '2.0' || $reply['statusCode'] != 304) { $allNewPackages = $this->parsePackageUpdateXML($reply['body']); } $data = array('lastUpdateTime' => TIME_NOW, 'status' => 'online', 'errorMessage' => ''); // check if server indicates support for a newer API if ($updateServer->apiVersion == '2.0' && !empty($reply['httpHeaders']['wcf-update-server-api'])) { $apiVersions = explode(' ', reset($reply['httpHeaders']['wcf-update-server-api'])); if (in_array('2.1', $apiVersions)) { $data['apiVersion'] = '2.1'; } } $metaData = array(); if ($updateServer->apiVersion == '2.1' || isset($data['apiVersion']) && $data['apiVersion'] == '2.1') { if (empty($reply['httpHeaders']['etag']) && empty($reply['httpHeaders']['last-modified'])) { throw new SystemException("Missing required HTTP headers 'etag' and 'last-modified'."); } else { if (empty($reply['httpHeaders']['wcf-update-server-ssl'])) { throw new SystemException("Missing required HTTP header 'wcf-update-server-ssl'."); } } $metaData['list'] = array(); if (!empty($reply['httpHeaders']['etag'])) { $metaData['list']['etag'] = reset($reply['httpHeaders']['etag']); } if (!empty($reply['httpHeaders']['last-modified'])) { $metaData['list']['lastModified'] = reset($reply['httpHeaders']['last-modified']); } $metaData['ssl'] = reset($reply['httpHeaders']['wcf-update-server-ssl']) == 'true' ? true : false; } $data['metaData'] = serialize($metaData); unset($request, $reply); if ($allNewPackages !== false) { // purge package list $sql = "DELETE FROM\twcf" . WCF_N . "_package_update\n\t\t\t\tWHERE\t\tpackageUpdateServerID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($updateServer->packageUpdateServerID)); // save packages if (!empty($allNewPackages)) { $this->savePackageUpdates($allNewPackages, $updateServer->packageUpdateServerID); } unset($allNewPackages); } // update server status $updateServerEditor = new PackageUpdateServerEditor($updateServer); $updateServerEditor->update($data); }
/** * Fetches an avatar from a remote server and sets it for given user. */ public function fetchRemoteAvatar() { $avatarID = 0; $filename = ''; // fetch avatar from URL try { $request = new HTTPRequest($this->parameters['url']); $request->execute(); $reply = $request->getReply(); $filename = FileUtil::getTemporaryFilename('avatar_'); file_put_contents($filename, $reply['body']); $imageData = getimagesize($filename); if ($imageData === false) { throw new SystemException('Downloaded file is not an image'); } } catch (\Exception $e) { if (!empty($filename)) { @unlink($filename); } return; } // rescale avatar if required try { $newFilename = $this->enforceDimensions($filename); if ($newFilename !== $filename) { @unlink($filename); } $filename = $newFilename; $imageData = getimagesize($filename); if ($imageData === false) { throw new SystemException('Rescaled file is not an image'); } } catch (\Exception $e) { @unlink($filename); return; } $tmp = parse_url($this->parameters['url']); if (!isset($tmp['path'])) { @unlink($filename); return; } $tmp = pathinfo($tmp['path']); if (!isset($tmp['basename']) || !isset($tmp['extension'])) { @unlink($filename); return; } $data = array('avatarName' => $tmp['basename'], 'avatarExtension' => $tmp['extension'], 'width' => $imageData[0], 'height' => $imageData[1], 'userID' => $this->parameters['userEditor']->userID, 'fileHash' => sha1_file($filename)); // 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($filename, $avatar->getLocation())) { @unlink($filename); // create thumbnails $action = new UserAvatarAction(array($avatar), 'generateThumbnails'); $action->executeAction(); $avatarID = $avatar->avatarID; } else { @unlink($filename); // moving failed; delete avatar $editor = new UserAvatarEditor($avatar); $editor->delete(); } // update user if ($avatarID) { $this->parameters['userEditor']->update(array('avatarID' => $avatarID, 'enableGravatar' => 0)); // delete old avatar if ($this->parameters['userEditor']->avatarID) { $action = new UserAvatarAction(array($this->parameters['userEditor']->avatarID), 'delete'); $action->executeAction(); } } // reset user storage UserStorageHandler::getInstance()->reset(array($this->parameters['userEditor']->userID), 'avatar'); }
/** * @see \wcf\action\IAction::execute() */ public function execute() { parent::execute(); // check response $processor = null; try { // post back to paypal to validate $content = ''; try { $url = 'https://www.paypal.com/cgi-bin/webscr'; if (!empty($_POST['test_ipn'])) { // IPN simulator notification $url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; } $request = new HTTPRequest($url, array(), array_merge(array('cmd' => '_notify-validate'), $_POST)); $request->execute(); $reply = $request->getReply(); $content = $reply['body']; } catch (SystemException $e) { throw new SystemException('connection to paypal.com failed: ' . $e->getMessage()); } if (strstr($content, "VERIFIED") === false) { throw new SystemException('request not validated'); } // fix encoding if (!empty($_POST['charset']) && strtoupper($_POST['charset']) != 'UTF-8') { foreach ($_POST as &$value) { $value = StringUtil::convertEncoding(strtoupper($_POST['charset']), 'UTF-8', $value); } } // Check that receiver_email is your Primary PayPal email if (strtolower($_POST['business']) != strtolower(PAYPAL_EMAIL_ADDRESS) && strtolower($_POST['receiver_email']) != strtolower(PAYPAL_EMAIL_ADDRESS)) { throw new SystemException('invalid business or receiver_email'); } // get token if (!isset($_POST['custom'])) { throw new SystemException('invalid custom item'); } $tokenParts = explode(':', $_POST['custom'], 2); if (count($tokenParts) != 2) { throw new SystemException('invalid custom item'); } // get payment type object type $objectType = ObjectTypeCache::getInstance()->getObjectType(intval($tokenParts[0])); if ($objectType === null || !$objectType->getProcessor() instanceof IPaymentType) { throw new SystemException('invalid payment type id'); } $processor = $objectType->getProcessor(); // get status $transactionType = !empty($_POST['txn_type']) ? $_POST['txn_type'] : ''; $paymentStatus = !empty($_POST['payment_status']) ? $_POST['payment_status'] : ''; $status = ''; if ($transactionType == 'web_accept' || $transactionType == 'subscr_payment') { if ($paymentStatus == 'Completed') { $status = 'completed'; } } if ($paymentStatus == 'Refunded' || $paymentStatus == 'Reversed') { $status = 'reversed'; } if ($paymentStatus == 'Canceled_Reversal') { $status = 'canceled_reversal'; } if ($status) { $processor->processTransaction(ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.payment.method', 'com.woltlab.wcf.payment.method.paypal'), $tokenParts[1], $_POST['mc_gross'], $_POST['mc_currency'], $_POST['txn_id'], $status, $_POST); } } catch (SystemException $e) { @header('HTTP/1.1 500 Internal Server Error'); echo $e->getMessage(); 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; }