Esempio n. 1
0
 /**
  * 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;
     }
 }
 /**
  * Sends a JSON-encoded response.
  * 
  * @param	array		$data
  */
 protected function sendJsonResponse(array $data)
 {
     $json = JSON::encode($data);
     // send JSON response
     header('Content-type: application/json');
     echo $json;
     exit;
 }
Esempio n. 3
0
	/**
	 * @see	wcf\action\AJAXInvokeAction::sendResponse()
	 */
	protected function sendResponse() {
		if (!isset($_POST['isFallback'])) {
			parent::sendResponse();
		}
		
		// IE9 is mad if iframe response is application/json
		header('Content-type: text/plain');
		echo JSON::encode($this->response);
		exit;
	}
Esempio n. 4
0
	/**
	 * @see	wcf\action\Action::execute()
	 */
	public function execute() {
		AbstractSecureAction::execute();
		
		// execute clipboard action
		$this->executeAction();
		
		// get editor items
		$returnValues = $this->getEditorItems();
		// send JSON response
		header('Content-type: application/json');
		echo JSON::encode($returnValues);
		exit;
	}
 /**
  * @see	\wcf\action\IAction::execute()
  */
 public final function execute()
 {
     parent::execute();
     $methodName = 'step' . StringUtil::firstCharToUpperCase($this->step);
     if (!method_exists($this, $methodName)) {
         throw new AJAXException("Class '" . get_class($this) . "' does not implement the required method '" . $methodName . "'");
     }
     // execute step
     $this->{$methodName}();
     $this->executed();
     // send JSON-encoded response
     header('Content-type: application/json');
     echo JSON::encode($this->data);
     exit;
 }
 /**
  * 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);
 }
 /**
  * Displays an error message.
  * 
  * @param	string	$name
  * @param	array	$parameters
  */
 public function error($name, array $parameters = array())
 {
     Log::error('package.' . $name . ':' . JSON::encode($parameters));
     if ($parameters) {
         throw new ArgvException(CLIWCF::getLanguage()->getDynamicVariable('wcf.acp.package.error.' . $name, $parameters), $this->getUsage());
     } else {
         throw new ArgvException(CLIWCF::getLanguage()->get('wcf.acp.package.error.' . $name), $this->argv->getUsageMessage());
     }
 }
Esempio n. 8
0
 /**
  * @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;
 }
Esempio n. 9
0
 /**
  * @see	wcf\action\IAction::execute()
  */
 public function execute()
 {
     parent::execute();
     // validate class name
     if (!class_exists($this->className)) {
         throw new SystemException("unknown class '" . $this->className . "'");
     }
     if (!ClassUtil::isInstanceOf($this->className, 'wcf\\data\\IDatabaseObjectAction')) {
         throw new SystemException("'" . $this->className . "' should implement wcf\\system\\IDatabaseObjectAction");
     }
     // create object action instance
     $this->objectAction = new $this->className($this->objectIDs, $this->actionName, $this->parameters);
     // validate action
     try {
         $this->objectAction->validateAction();
     } catch (UserInputException $e) {
         $this->throwException($e);
     } catch (ValidateActionException $e) {
         $this->throwException($e);
     }
     // execute action
     try {
         $this->response = $this->objectAction->executeAction();
     } catch (\Exception $e) {
         $this->throwException($e);
     }
     $this->executed();
     // send JSON-encoded response
     header('Content-type: application/json');
     echo JSON::encode($this->response);
     exit;
 }
Esempio n. 10
0
 /**
  * Writes an error to log file.
  */
 protected function logError()
 {
     if (!empty($this->exceptionID)) {
         return;
     }
     $logFile = WCF_DIR . 'log/' . gmdate('Y-m-d', TIME_NOW) . '.txt';
     // try to create file
     @touch($logFile);
     // validate if file exists and is accessible for us
     if (!file_exists($logFile) || !is_writable($logFile)) {
         /*
         	We cannot recover if we reached this point, the server admin
         	is urged to fix his pretty much broken configuration.
         	
         	GLaDOS: Look at you, sailing through the air majestically, like an eagle... piloting a blimp.
         */
         return;
     }
     $e = $this->getPrevious() ?: $this;
     // don't forget to update ExceptionLogViewPage, when changing the log file format
     $message = gmdate('r', TIME_NOW) . "\n" . 'Message: ' . $e->getMessage() . "\n" . 'File: ' . $e->getFile() . ' (' . $e->getLine() . ")\n" . 'PHP version: ' . phpversion() . "\n" . 'WCF version: ' . WCF_VERSION . "\n" . 'Request URI: ' . (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '') . "\n" . 'Referrer: ' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . "\n" . 'User-Agent: ' . (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '') . "\n" . 'Information: ' . JSON::encode($this->information) . "\n" . "Stacktrace: \n  " . implode("\n  ", explode("\n", $this->__getTraceAsString())) . "\n";
     // calculate Exception-ID
     $this->exceptionID = StringUtil::getHash($message);
     $message = "<<<<<<<<" . $this->exceptionID . "<<<<\n" . $message . "<<<<\n\n";
     // append
     @file_put_contents($logFile, $message, FILE_APPEND);
 }
 /**
  * @see	wcf\action\IAction::execute()
  */
 public function execute()
 {
     parent::execute();
     // get object ids
     $objectIDs = $this->getObjectIDs();
     // create object action instance
     $this->objectAction = new $this->parameters['className']($objectIDs, $this->parameters['actionName']);
     // validate action
     try {
         $this->objectAction->validateAction();
     } catch (ValidateActionException $e) {
         throw new AJAXException("validation failed: " . $e->getMessage());
     }
     // execute action
     try {
         $this->response = $this->objectAction->executeAction();
     } catch (\Exception $e) {
         throw new AJAXException('unknown exception caught: ' . $e->getMessage());
     }
     $this->executed();
     // send JSON-encoded response
     header('Content-type: application/json');
     echo JSON::encode($this->response);
     exit;
 }
Esempio n. 12
0
 /**
  * Initializes command handling.
  */
 protected function initCommands()
 {
     // add command name completer
     self::getReader()->addCompleter(new CLICommandNameCompleter());
     while (true) {
         // roll back open transactions of the previous command, as they are dangerous in a long living script
         if (WCF::getDB()->rollBackTransaction()) {
             Log::warn('Previous command had an open transaction.');
         }
         self::getReader()->setHistoryEnabled(true);
         $line = self::getReader()->readLine('>');
         if ($line === null) {
             exit;
         }
         $line = StringUtil::trim($line);
         try {
             $command = CLICommandHandler::getCommand($line);
             $command->execute(CLICommandHandler::getParameters($line));
         } catch (IllegalLinkException $e) {
             Log::error('notFound:' . JSON::encode(array('command' => $line)));
             self::getReader()->println(WCF::getLanguage()->getDynamicVariable('wcf.cli.error.command.notFound', array('command' => $line)));
             if (self::getArgvParser()->exitOnFail) {
                 exit(1);
             }
             continue;
         } catch (PermissionDeniedException $e) {
             Log::error('permissionDenied');
             self::getReader()->println(WCF::getLanguage()->getDynamicVariable('wcf.global.error.permissionDenied'));
             if (self::getArgvParser()->exitOnFail) {
                 exit(1);
             }
             continue;
         } catch (ArgvException $e) {
             // show error message and usage
             if ($e->getMessage()) {
                 echo $e->getMessage() . PHP_EOL;
             }
             echo $e->getUsageMessage();
             if (self::getArgvParser()->exitOnFail) {
                 exit(1);
             }
             continue;
         } catch (\Exception $e) {
             Log::error($e);
             if (self::getArgvParser()->exitOnFail) {
                 exit(1);
             }
             continue;
         }
     }
 }
Esempio n. 13
0
	/**
	 * Throws a JSON-encoded error message
	 * 
	 * @param	string		$message
	 * @param	boolean		$isDoomsday
	 * @param	string		$stacktrace
	 * @param	array<mixed>	$returnValues
	 */
	public function __construct($message, $errorType = self::INTERNAL_ERROR, $stacktrace = null, $returnValues = array()) {
		if ($stacktrace === null) $stacktrace = $this->getTraceAsString();
		
		if (WCF::debugModeIsEnabled()) {
			$responseData = array(
				'message' => $message,
				'stacktrace' => nl2br($stacktrace)
			);
		}
		else {
			$responseData = array(
				'message' => $this->_getMessage()
			);
		}
		
		$responseData['code'] = $errorType;
		$responseData['returnValues'] = $returnValues;
		
		$statusHeader = '';
		switch ($errorType) {
			case self::MISSING_PARAMETERS:
				$statusHeader = 'HTTP/1.0 400 Bad Request';
				$responseData['message'] = WCF::getLanguage()->get('wcf.ajax.error.badRequest');
				
				$this->logError();
			break;
			
			case self::SESSION_EXPIRED:
				$statusHeader = 'HTTP/1.0 401 Unauthorized';
			break;
			
			case self::INSUFFICIENT_PERMISSIONS:
				$statusHeader = 'HTTP/1.0 403 Forbidden';
			break;
			
			case self::BAD_PARAMETERS:
				$statusHeader = 'HTTP/1.0 412 Precondition Failed';
			break;
			
			default:
			case self::INTERNAL_ERROR:
				//header('HTTP/1.0 418 I\'m a Teapot');
				header('HTTP/1.0 503 Service Unavailable');
				
				$responseData['code'] = self::INTERNAL_ERROR;
				if (!WCF::debugModeIsEnabled()) {
					$responseData['message'] = WCF::getLanguage()->get('wcf.ajax.error.internalError');
				}
				
				$this->logError();
			break;
		}
		
		header($statusHeader);
		header('Content-type: application/json');
		echo JSON::encode($responseData);
		exit;
	}
    /**
     * @see	\wcf\page\IPage::readData()
     */
    public function readData()
    {
        AbstractPage::readData();
        $fileNameRegex = new Regex('(?:^|/)\\d{4}-\\d{2}-\\d{2}\\.txt$');
        $this->logFiles = DirectoryUtil::getInstance(WCF_DIR . 'log/')->getFiles(SORT_DESC, $fileNameRegex);
        if ($this->exceptionID) {
            // search the appropriate file
            foreach ($this->logFiles as $logFile) {
                $contents = file_get_contents($logFile);
                if (mb_strpos($contents, '<<<<<<<<' . $this->exceptionID . '<<<<') !== false) {
                    $fileNameRegex->match($logFile);
                    $matches = $fileNameRegex->getMatches();
                    $this->logFile = $matches[0];
                    break;
                }
                unset($contents);
            }
            if (!isset($contents)) {
                $this->logFile = '';
                return;
            }
        } else {
            if ($this->logFile) {
                if (!$fileNameRegex->match(basename($this->logFile))) {
                    throw new IllegalLinkException();
                }
                if (!file_exists(WCF_DIR . 'log/' . $this->logFile)) {
                    throw new IllegalLinkException();
                }
                $contents = file_get_contents(WCF_DIR . 'log/' . $this->logFile);
            } else {
                return;
            }
        }
        // unify newlines
        $contents = StringUtil::unifyNewlines($contents);
        // split contents
        $split = new Regex('(?:^|\\n<<<<\\n\\n)(?:<<<<<<<<([a-f0-9]{40})<<<<\\n|$)');
        $contents = $split->split($contents, Regex::SPLIT_NON_EMPTY_ONLY | Regex::CAPTURE_SPLIT_DELIMITER);
        // even items become keys, odd items become values
        try {
            $this->exceptions = call_user_func_array('array_merge', array_map(function ($v) {
                return array($v[0] => $v[1]);
            }, array_chunk($contents, 2)));
        } catch (\Exception $e) {
            // logfile contents are pretty malformed, abort
            return;
        }
        if ($this->exceptionID) {
            $this->searchPage($this->exceptionID);
        }
        $this->calculateNumberOfPages();
        $i = 0;
        $exceptionRegex = new Regex('(?P<date>[MTWFS][a-z]{2}, \\d{1,2} [JFMASOND][a-z]{2} \\d{4} \\d{2}:\\d{2}:\\d{2} [+-]\\d{4})
Message: (?P<message>.*?)
File: (?P<file>.*?) \\((?P<line>\\d+)\\)
PHP version: (?P<phpVersion>.*?)
WCF version: (?P<wcfVersion>.*?)
Request URI: (?P<requestURI>.*?)
Referrer: (?P<referrer>.*?)
User-Agent: (?P<userAgent>.*?)
Information: (?P<information>.*?)
Stacktrace: 
(?P<stacktrace>.*)', Regex::DOT_ALL);
        $stackTraceFormatter = new Regex('^\\s+(#\\d+)', Regex::MULTILINE);
        foreach ($this->exceptions as $key => $val) {
            $i++;
            if ($i < $this->startIndex || $i > $this->endIndex) {
                unset($this->exceptions[$key]);
                continue;
            }
            if (!$exceptionRegex->match($val)) {
                unset($this->exceptions[$key]);
                continue;
            }
            $this->exceptions[$key] = $exceptionRegex->getMatches();
            $this->exceptions[$key]['stacktrace'] = explode("\n", $stackTraceFormatter->replace(StringUtil::encodeHTML($this->exceptions[$key]['stacktrace']), '<strong>\\1</strong>'));
            $this->exceptions[$key]['information'] = JSON::decode($this->exceptions[$key]['information']);
        }
    }
Esempio n. 15
0
 /**
  * Throws a JSON-encoded error message
  * 
  * @param	string		$message
  * @param	boolean		$isDoomsday
  * @param	string		$stacktrace
  * @param	array		$returnValues
  * @param	string		$exceptionID
  * @param	array<mixed>	$returnValues
  */
 public function __construct($message, $errorType = self::INTERNAL_ERROR, $stacktrace = null, $returnValues = array(), $exceptionID = '')
 {
     if ($stacktrace === null) {
         $stacktrace = $this->getTraceAsString();
     }
     $responseData = array('code' => $errorType, 'message' => $message, 'returnValues' => $returnValues);
     // include a stacktrace if:
     // - debug mode is enabled
     // - within ACP and a SystemException was thrown
     if (WCF::debugModeIsEnabled(false) || WCF::debugModeIsEnabled() && self::INTERNAL_ERROR) {
         $responseData['stacktrace'] = nl2br($stacktrace);
     }
     $statusHeader = '';
     switch ($errorType) {
         case self::MISSING_PARAMETERS:
             $statusHeader = 'HTTP/1.0 400 Bad Request';
             $responseData['exceptionID'] = $exceptionID;
             $responseData['message'] = WCF::getLanguage()->get('wcf.ajax.error.badRequest');
             break;
         case self::SESSION_EXPIRED:
             $statusHeader = 'HTTP/1.0 409 Conflict';
             break;
         case self::INSUFFICIENT_PERMISSIONS:
             $statusHeader = 'HTTP/1.0 403 Forbidden';
             break;
         case self::BAD_PARAMETERS:
             $statusHeader = 'HTTP/1.0 431 Bad Parameters';
             $responseData['exceptionID'] = $exceptionID;
             break;
         default:
         case self::INTERNAL_ERROR:
             //header('HTTP/1.0 418 I\'m a Teapot');
             header('HTTP/1.0 503 Service Unavailable');
             $responseData['code'] = self::INTERNAL_ERROR;
             $responseData['exceptionID'] = $exceptionID;
             if (!WCF::debugModeIsEnabled()) {
                 $responseData['message'] = WCF::getLanguage()->get('wcf.ajax.error.internalError');
             }
             break;
     }
     header($statusHeader);
     header('Content-type: application/json');
     echo JSON::encode($responseData);
     exit;
 }
Esempio n. 16
0
 /**
  * @see	\wcf\action\IAction::execute()
  */
 public function execute()
 {
     AbstractAction::execute();
     $returnValues = null;
     switch ($this->actionName) {
         case 'count':
             $returnValues = array('count' => $this->count());
             break;
         case 'getQuotes':
             $returnValues = array('template' => $this->getQuotes());
             break;
         case 'markForRemoval':
             $this->markForRemoval();
             break;
         case 'remove':
             $returnValues = array('count' => $this->remove());
             break;
         case 'removeMarkedQuotes':
             $returnValues = array('count' => $this->removeMarkedQuotes());
             break;
         default:
             throw new SystemException("Unknown action '" . $this->actionName . "'");
             break;
     }
     if (is_array($returnValues) && $this->_getFullQuoteObjectIDs) {
         $returnValues['fullQuoteObjectIDs'] = $this->getFullQuoteObjectIDs();
     }
     $this->executed();
     // force session update
     WCF::getSession()->update();
     WCF::getSession()->disableUpdate();
     if ($returnValues !== null) {
         // send JSON-encoded response
         header('Content-type: application/json');
         echo JSON::encode($returnValues);
     }
     exit;
 }
Esempio n. 17
0
 /**
  * @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;
 }
Esempio n. 18
0
 /**
  * @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;
 }
Esempio n. 19
0
	/**
	 * Sends JSON-Encoded response.
	 */
	protected function sendResponse() {
		header('Content-type: application/json');
		echo JSON::encode($this->response);
		exit;
	}
Esempio n. 20
0
 /**
  * @see	\wcf\action\IAction::execute()
  */
 public function execute()
 {
     AbstractAction::execute();
     $returnValues = array('actionName' => $this->actionName, 'pollID' => $this->pollID);
     switch ($this->actionName) {
         case 'getResult':
             $this->getResult($returnValues);
             break;
         case 'getVote':
             $this->getVote($returnValues);
             break;
         case 'vote':
             $this->vote($returnValues);
             break;
     }
     $this->executed();
     // send JSON-encoded response
     header('Content-type: application/json');
     echo JSON::encode($returnValues);
     exit;
 }
Esempio n. 21
0
 /**
  * Sends a JSON-encoded response.
  * 
  * @param	integer		$progress
  * @param	array		$parameters
  * @param	string		$proceedURL
  */
 protected function sendResponse($progress = 0, array $parameters = null, $proceedURL = '')
 {
     if ($parameters === null) {
         $parameters = $this->parameters;
     }
     // build return values
     $returnValues = array('className' => $this->className, 'loopCount' => $this->loopCount + 1, 'parameters' => $parameters, 'proceedURL' => $proceedURL, 'progress' => $progress);
     // include template on startup
     if ($this->loopCount == -1) {
         $returnValues['template'] = WCF::getTPL()->fetch('worker');
     }
     // send JSON-encoded response
     header('Content-type: application/json');
     echo JSON::encode($returnValues);
     exit;
 }
 /**
  * Reads a value and validates it. If you set $allowEmpty to true, no exception will
  * be thrown if the variable evaluates to 0 (integer) or '' (string). Furthermore the
  * variable will be always created with a sane value if it does not exist.
  * 
  * @param	string		$variableName
  * @param	boolean		$allowEmpty
  * @param	string		$arrayIndex
  * @param	integer		$type
  */
 protected function readValue($variableName, $allowEmpty, $arrayIndex, $type)
 {
     if ($arrayIndex) {
         if (!isset($this->parameters[$arrayIndex])) {
             throw new SystemException("Corrupt parameters, index '" . $arrayIndex . "' is missing");
         }
         $target =& $this->parameters[$arrayIndex];
     } else {
         $target =& $this->parameters;
     }
     switch ($type) {
         case self::TYPE_INTEGER:
             if (!isset($target[$variableName])) {
                 if ($allowEmpty) {
                     $target[$variableName] = 0;
                 } else {
                     throw new UserInputException($variableName);
                 }
             } else {
                 $target[$variableName] = intval($target[$variableName]);
                 if (!$allowEmpty && !$target[$variableName]) {
                     throw new UserInputException($variableName);
                 }
             }
             break;
         case self::TYPE_STRING:
             if (!isset($target[$variableName])) {
                 if ($allowEmpty) {
                     $target[$variableName] = '';
                 } else {
                     throw new UserInputException($variableName);
                 }
             } else {
                 $target[$variableName] = StringUtil::trim($target[$variableName]);
                 if (!$allowEmpty && empty($target[$variableName])) {
                     throw new UserInputException($variableName);
                 }
             }
             break;
         case self::TYPE_BOOLEAN:
             if (!isset($target[$variableName])) {
                 if ($allowEmpty) {
                     $target[$variableName] = false;
                 } else {
                     throw new UserInputException($variableName);
                 }
             } else {
                 if (is_numeric($target[$variableName])) {
                     $target[$variableName] = (bool) $target[$variableName];
                 } else {
                     $target[$variableName] = $target[$variableName] != 'false';
                 }
             }
             break;
         case self::TYPE_JSON:
             if (!isset($target[$variableName])) {
                 if ($allowEmpty) {
                     $target[$variableName] = array();
                 } else {
                     throw new UserInputException($variableName);
                 }
             } else {
                 try {
                     $target[$variableName] = JSON::decode($target[$variableName]);
                 } catch (SystemException $e) {
                     throw new UserInputException($variableName);
                 }
                 if (!$allowEmpty && empty($target[$variableName])) {
                     throw new UserInputException($variableName);
                 }
             }
             break;
     }
 }