Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1aaeb0b2 authored by Pierre-Alain Bandinelli's avatar Pierre-Alain Bandinelli
Browse files

Bumping to 1.11.0.203

parent 0b17b5d8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
1.10.4.183
 No newline at end of file
1.11.0.203
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
1.10.4.183
 No newline at end of file
1.11.0.203
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

if (!defined('APP_VERSION'))
{
	define('APP_VERSION', '1.10.5.192');
	define('APP_VERSION', '1.11.0.203');
	define('APP_VERSION_TYPE', 'community');
	define('APP_INDEX_ROOT_FILE', __FILE__);
	define('APP_INDEX_ROOT_PATH', str_replace('\\', '/', rtrim(dirname(__FILE__), '\\/').'/'));
+0 −370
Original line number Diff line number Diff line
<?php
/**
 * Copyright 2014 Facebook, Inc.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
namespace Facebook\Entities;

use Facebook\FacebookRequest;
use Facebook\FacebookRequestException;
use Facebook\FacebookSession;
use Facebook\GraphSessionInfo;

/**
 * Class AccessToken
 * @package Facebook
 */
class AccessToken
{

  /**
   * The access token.
   *
   * @var string
   */
  protected $accessToken;

  /**
   * A unique ID to identify a client.
   *
   * @var string
   */
  protected $machineId;

  /**
   * Date when token expires.
   *
   * @var \DateTime|null
   */
  protected $expiresAt;

  /**
   * Create a new access token entity.
   *
   * @param string $accessToken
   * @param int $expiresAt
   * @param string|null machineId
   */
  public function __construct($accessToken, $expiresAt = 0, $machineId = null)
  {
    $this->accessToken = $accessToken;
    if ($expiresAt) {
      $this->setExpiresAtFromTimeStamp($expiresAt);
    }
    $this->machineId = $machineId;
  }

  /**
   * Setter for expires_at.
   *
   * @param int $timeStamp
   */
  protected function setExpiresAtFromTimeStamp($timeStamp)
  {
    $dt = new \DateTime();
    $dt->setTimestamp($timeStamp);
    $this->expiresAt = $dt;
  }

  /**
   * Getter for expiresAt.
   *
   * @return \DateTime|null
   */
  public function getExpiresAt()
  {
    return $this->expiresAt;
  }

  /**
   * Getter for machineId.
   *
   * @return string|null
   */
  public function getMachineId()
  {
    return $this->machineId;
  }

  /**
   * Determines whether or not this is a long-lived token.
   *
   * @return bool
   */
  public function isLongLived()
  {
    if ($this->expiresAt) {
      return $this->expiresAt->getTimestamp() > time() + (60 * 60 * 2);
    }
    return false;
  }

  /**
   * Checks the validity of the access token.
   *
   * @param string|null $appId Application ID to use
   * @param string|null $appSecret App secret value to use
   * @param string|null $machineId
   *
   * @return boolean
   */
  public function isValid($appId = null, $appSecret = null, $machineId = null)
  {
    $accessTokenInfo = $this->getInfo($appId, $appSecret);
    $machineId = $machineId ?: $this->machineId;
    return static::validateAccessToken($accessTokenInfo, $appId, $machineId);
  }

  /**
   * Ensures the provided GraphSessionInfo object is valid,
   *   throwing an exception if not.  Ensures the appId matches,
   *   that the machineId matches if it's being used,
   *   that the token is valid and has not expired.
   *
   * @param GraphSessionInfo $tokenInfo
   * @param string|null $appId Application ID to use
   * @param string|null $machineId
   *
   * @return boolean
   */
  public static function validateAccessToken(GraphSessionInfo $tokenInfo,
                                             $appId = null, $machineId = null)
  {
    $targetAppId = FacebookSession::_getTargetAppId($appId);

    $appIdIsValid = $tokenInfo->getAppId() == $targetAppId;
    $machineIdIsValid = $tokenInfo->getProperty('machine_id') == $machineId;
    $accessTokenIsValid = $tokenInfo->isValid();

    // Not all access tokens return an expiration. E.g. an app access token.
    if ($tokenInfo->getExpiresAt() instanceof \DateTime) {
      $accessTokenIsStillAlive = $tokenInfo->getExpiresAt()->getTimestamp() >= time();
    } else {
      $accessTokenIsStillAlive = true;
    }

    return $appIdIsValid && $machineIdIsValid && $accessTokenIsValid && $accessTokenIsStillAlive;
  }

  /**
   * Get a valid access token from a code.
   *
   * @param string $code
   * @param string|null $appId
   * @param string|null $appSecret
   * @param string|null $machineId
   *
   * @return AccessToken
   */
  public static function getAccessTokenFromCode($code, $appId = null, $appSecret = null, $machineId = null)
  {
    $params = array(
      'code' => $code,
      'redirect_uri' => '',
    );

    if ($machineId) {
      $params['machine_id'] = $machineId;
    }

    return static::requestAccessToken($params, $appId, $appSecret);
  }

  /**
   * Get a valid code from an access token.
   *
   * @param AccessToken|string $accessToken
   * @param string|null $appId
   * @param string|null $appSecret
   *
   * @return AccessToken
   */
  public static function getCodeFromAccessToken($accessToken, $appId = null, $appSecret = null)
  {
    $accessToken = (string) $accessToken;

    $params = array(
      'access_token' => $accessToken,
      'redirect_uri' => '',
    );

    return static::requestCode($params, $appId, $appSecret);
  }

  /**
   * Exchanges a short lived access token with a long lived access token.
   *
   * @param string|null $appId
   * @param string|null $appSecret
   *
   * @return AccessToken
   */
  public function extend($appId = null, $appSecret = null)
  {
    $params = array(
      'grant_type' => 'fb_exchange_token',
      'fb_exchange_token' => $this->accessToken,
    );

    return static::requestAccessToken($params, $appId, $appSecret);
  }

  /**
   * Request an access token based on a set of params.
   *
   * @param array $params
   * @param string|null $appId
   * @param string|null $appSecret
   *
   * @return AccessToken
   *
   * @throws FacebookRequestException
   */
  public static function requestAccessToken(array $params, $appId = null, $appSecret = null)
  {
    $response = static::request('/oauth/access_token', $params, $appId, $appSecret);
    $data = $response->getResponse();

    /**
     * @TODO fix this malarkey - getResponse() should always return an object
     * @see https://github.com/facebook/facebook-php-sdk-v4/issues/36
     */
    if (is_array($data)) {
      if (isset($data['access_token'])) {
        $expiresAt = isset($data['expires']) ? time() + $data['expires'] : 0;
        return new static($data['access_token'], $expiresAt);
      }
    } elseif($data instanceof \stdClass) {
      if (isset($data->access_token)) {
        $expiresAt = isset($data->expires_in) ? time() + $data->expires_in : 0;
        $machineId = isset($data->machine_id) ? (string) $data->machine_id : null;
        return new static((string) $data->access_token, $expiresAt, $machineId);
      }
    }

    throw FacebookRequestException::create(
      $response->getRawResponse(),
      $data,
      401
    );
  }

  /**
   * Request a code from a long lived access token.
   *
   * @param array $params
   * @param string|null $appId
   * @param string|null $appSecret
   *
   * @return string
   *
   * @throws FacebookRequestException
   */
  public static function requestCode(array $params, $appId = null, $appSecret = null)
  {
    $response = static::request('/oauth/client_code', $params, $appId, $appSecret);
    $data = $response->getResponse();

    if (isset($data->code)) {
      return (string) $data->code;
    }

    throw FacebookRequestException::create(
      $response->getRawResponse(),
      $data,
      401
    );
  }

  /**
   * Send a request to Graph with an app access token.
   *
   * @param string $endpoint
   * @param array $params
   * @param string|null $appId
   * @param string|null $appSecret
   *
   * @return \Facebook\FacebookResponse
   *
   * @throws FacebookRequestException
   */
  protected static function request($endpoint, array $params, $appId = null, $appSecret = null)
  {
    $targetAppId = FacebookSession::_getTargetAppId($appId);
    $targetAppSecret = FacebookSession::_getTargetAppSecret($appSecret);

    if (!isset($params['client_id'])) {
      $params['client_id'] = $targetAppId;
    }
    if (!isset($params['client_secret'])) {
      $params['client_secret'] = $targetAppSecret;
    }

    // The response for this endpoint is not JSON, so it must be handled
    //   differently, not as a GraphObject.
    $request = new FacebookRequest(
      FacebookSession::newAppSession($targetAppId, $targetAppSecret),
      'GET',
      $endpoint,
      $params
    );
    return $request->execute();
  }

  /**
   * Get more info about an access token.
   *
   * @param string|null $appId
   * @param string|null $appSecret
   *
   * @return GraphSessionInfo
   */
  public function getInfo($appId = null, $appSecret = null)
  {
    $params = array('input_token' => $this->accessToken);

    $request = new FacebookRequest(
      FacebookSession::newAppSession($appId, $appSecret),
      'GET',
      '/debug_token',
      $params
    );
    $response = $request->execute()->getGraphObject(GraphSessionInfo::className());

    // Update the data on this token
    if ($response->getExpiresAt()) {
      $this->expiresAt = $response->getExpiresAt();
    }

    return $response;
  }

  /**
   * Returns the access token as a string.
   *
   * @return string
   */
  public function __toString()
  {
    return $this->accessToken;
  }

}
+0 −386
Original line number Diff line number Diff line
<?php
/**
 * Copyright 2014 Facebook, Inc.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
 * use, copy, modify, and distribute this software in source code or binary
 * form for use in connection with the web services and APIs provided by
 * Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use
 * of this software is subject to the Facebook Developer Principles and
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
 * shall be included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
namespace Facebook\Entities;

use Facebook\FacebookSDKException;
use Facebook\FacebookSession;

/**
 * Class SignedRequest
 * @package Facebook
 */
class SignedRequest
{

  /**
   * @var string
   */
  public $rawSignedRequest;

  /**
   * @var array
   */
  public $payload;

  /**
   * Instantiate a new SignedRequest entity.
   *
   * @param string|null $rawSignedRequest The raw signed request.
   * @param string|null $state random string to prevent CSRF.
   * @param string|null $appSecret
   */
  public function __construct($rawSignedRequest = null, $state = null, $appSecret = null)
  {
    if (!$rawSignedRequest) {
      return;
    }

    $this->rawSignedRequest = $rawSignedRequest;
    $this->payload = static::parse($rawSignedRequest, $state, $appSecret);
  }

  /**
   * Returns the raw signed request data.
   *
   * @return string|null
   */
  public function getRawSignedRequest()
  {
    return $this->rawSignedRequest;
  }

  /**
   * Returns the parsed signed request data.
   *
   * @return array|null
   */
  public function getPayload()
  {
    return $this->payload;
  }

  /**
   * Returns a property from the signed request data if available.
   *
   * @param string $key
   * @param mixed|null $default
   *
   * @return mixed|null
   */
  public function get($key, $default = null)
  {
    if (isset($this->payload[$key])) {
      return $this->payload[$key];
    }
    return $default;
  }

  /**
   * Returns user_id from signed request data if available.
   *
   * @return string|null
   */
  public function getUserId()
  {
    return $this->get('user_id');
  }

  /**
   * Checks for OAuth data in the payload.
   *
   * @return boolean
   */
  public function hasOAuthData()
  {
    return isset($this->payload['oauth_token']) || isset($this->payload['code']);
  }

  /**
   * Creates a signed request from an array of data.
   *
   * @param array $payload
   * @param string|null $appSecret
   *
   * @return string
   */
  public static function make(array $payload, $appSecret = null)
  {
    $payload['algorithm'] = 'HMAC-SHA256';
    $payload['issued_at'] = time();
    $encodedPayload = static::base64UrlEncode(json_encode($payload));

    $hashedSig = static::hashSignature($encodedPayload, $appSecret);
    $encodedSig = static::base64UrlEncode($hashedSig);

    return $encodedSig.'.'.$encodedPayload;
  }

  /**
   * Validates and decodes a signed request and returns
   * the payload as an array.
   *
   * @param string $signedRequest
   * @param string|null $state
   * @param string|null $appSecret
   *
   * @return array
   */
  public static function parse($signedRequest, $state = null, $appSecret = null)
  {
    list($encodedSig, $encodedPayload) = static::split($signedRequest);

    // Signature validation
    $sig = static::decodeSignature($encodedSig);
    $hashedSig = static::hashSignature($encodedPayload, $appSecret);
    static::validateSignature($hashedSig, $sig);

    // Payload validation
    $data = static::decodePayload($encodedPayload);
    static::validateAlgorithm($data);
    if ($state) {
      static::validateCsrf($data, $state);
    }

    return $data;
  }

  /**
   * Validates the format of a signed request.
   *
   * @param string $signedRequest
   *
   * @throws FacebookSDKException
   */
  public static function validateFormat($signedRequest)
  {
    if (strpos($signedRequest, '.') !== false) {
      return;
    }

    throw new FacebookSDKException(
      'Malformed signed request.', 606
    );
  }

  /**
   * Decodes a raw valid signed request.
   *
   * @param string $signedRequest
   *
   * @returns array
   */
  public static function split($signedRequest)
  {
    static::validateFormat($signedRequest);

    return explode('.', $signedRequest, 2);
  }

  /**
   * Decodes the raw signature from a signed request.
   *
   * @param string $encodedSig
   *
   * @returns string
   *
   * @throws FacebookSDKException
   */
  public static function decodeSignature($encodedSig)
  {
    $sig = static::base64UrlDecode($encodedSig);

    if ($sig) {
      return $sig;
    }

    throw new FacebookSDKException(
      'Signed request has malformed encoded signature data.', 607
    );
  }

  /**
   * Decodes the raw payload from a signed request.
   *
   * @param string $encodedPayload
   *
   * @returns array
   *
   * @throws FacebookSDKException
   */
  public static function decodePayload($encodedPayload)
  {
    $payload = static::base64UrlDecode($encodedPayload);

    if ($payload) {
      $payload = json_decode($payload, true);
    }

    if (is_array($payload)) {
      return $payload;
    }

    throw new FacebookSDKException(
      'Signed request has malformed encoded payload data.', 607
    );
  }

  /**
   * Validates the algorithm used in a signed request.
   *
   * @param array $data
   *
   * @throws FacebookSDKException
   */
  public static function validateAlgorithm(array $data)
  {
    if (isset($data['algorithm']) && $data['algorithm'] === 'HMAC-SHA256') {
      return;
    }

    throw new FacebookSDKException(
      'Signed request is using the wrong algorithm.', 605
    );
  }

  /**
   * Hashes the signature used in a signed request.
   *
   * @param string $encodedData
   * @param string|null $appSecret
   *
   * @return string
   *
   * @throws FacebookSDKException
   */
  public static function hashSignature($encodedData, $appSecret = null)
  {
    $hashedSig = hash_hmac(
      'sha256', $encodedData, FacebookSession::_getTargetAppSecret($appSecret), $raw_output = true
    );

    if ($hashedSig) {
      return $hashedSig;
    }

    throw new FacebookSDKException(
      'Unable to hash signature from encoded payload data.', 602
    );
  }

  /**
   * Validates the signature used in a signed request.
   *
   * @param string $hashedSig
   * @param string $sig
   *
   * @throws FacebookSDKException
   */
  public static function validateSignature($hashedSig, $sig)
  {
    if (mb_strlen($hashedSig) === mb_strlen($sig)) {
      $validate = 0;
      for ($i = 0; $i < mb_strlen($sig); $i++) {
        $validate |= ord($hashedSig[$i]) ^ ord($sig[$i]);
      }
      if ($validate === 0) {
        return;
      }
    }

    throw new FacebookSDKException(
      'Signed request has an invalid signature.', 602
    );
  }

  /**
   * Validates a signed request against CSRF.
   *
   * @param array $data
   * @param string $state
   *
   * @throws FacebookSDKException
   */
  public static function validateCsrf(array $data, $state)
  {
    if (isset($data['state']) && $data['state'] === $state) {
      return;
    }

    throw new FacebookSDKException(
      'Signed request did not pass CSRF validation.', 604
    );
  }

  /**
   * Base64 decoding which replaces characters:
   *   + instead of -
   *   / instead of _
   * @link http://en.wikipedia.org/wiki/Base64#URL_applications
   *
   * @param string $input base64 url encoded input
   *
   * @return string decoded string
   */
  public static function base64UrlDecode($input)
  {
    $urlDecodedBase64 = strtr($input, '-_', '+/');
    static::validateBase64($urlDecodedBase64);
    return base64_decode($urlDecodedBase64);
  }

  /**
   * Base64 encoding which replaces characters:
   *   + instead of -
   *   / instead of _
   * @link http://en.wikipedia.org/wiki/Base64#URL_applications
   *
   * @param string $input string to encode
   *
   * @return string base64 url encoded input
   */
  public static function base64UrlEncode($input)
  {
    return strtr(base64_encode($input), '+/', '-_');
  }

  /**
   * Validates a base64 string.
   *
   * @param string $input base64 value to validate
   *
   * @throws FacebookSDKException
   */
  public static function validateBase64($input)
  {
    $pattern = '/^[a-zA-Z0-9\/\r\n+]*={0,2}$/';
    if (preg_match($pattern, $input)) {
      return;
    }

    throw new FacebookSDKException(
      'Signed request contains malformed base64 encoding.', 608
    );
  }

}
Loading