Bladeren bron

Facebook athentification plugin 2.0

baelmyhu 9 jaren geleden
bovenliggende
commit
bc19d977eb
39 gewijzigde bestanden met toevoegingen van 4766 en 62 verwijderingen
  1. 70 0
      main/auth/external_login/facebook-php-sdk/autoload.php
  2. 380 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/Entities/AccessToken.php
  3. 386 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/Entities/SignedRequest.php
  4. 33 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookAuthorizationException.php
  5. 60 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookCanvasLoginHelper.php
  6. 33 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookClientException.php
  7. 45 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookJavaScriptLoginHelper.php
  8. 33 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookOtherException.php
  9. 102 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookPageTabHelper.php
  10. 33 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookPermissionException.php
  11. 324 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookRedirectLoginHelper.php
  12. 313 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookRequest.php
  13. 222 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookRequestException.php
  14. 206 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookResponse.php
  15. 33 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookSDKException.php
  16. 33 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookServerException.php
  17. 367 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookSession.php
  18. 166 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookSignedRequestFromInputHelper.php
  19. 33 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookThrottleException.php
  20. 173 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/GraphAlbum.php
  21. 105 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/GraphLocation.php
  22. 171 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/GraphObject.php
  23. 64 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/GraphPage.php
  24. 115 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/GraphSessionInfo.php
  25. 135 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/GraphUser.php
  26. 84 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/GraphUserPage.php
  27. 129 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurl.php
  28. 329 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php
  29. 134 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php
  30. 68 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookHttpable.php
  31. 79 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookStream.php
  32. 190 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php
  33. 23 0
      main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pem
  34. 85 44
      main/auth/external_login/facebook.inc.php
  35. 5 10
      main/auth/external_login/facebook.init.php
  36. BIN
      plugin/add_facebook_login_button/img/cnx_fb.png
  37. 1 2
      plugin/add_facebook_login_button/index.php
  38. 1 1
      plugin/add_facebook_login_button/plugin.php
  39. 3 5
      plugin/add_facebook_login_button/template.tpl

+ 70 - 0
main/auth/external_login/facebook-php-sdk/autoload.php

@@ -0,0 +1,70 @@
+<?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.
+ *
+ */
+
+/**
+ * You only need this file if you are not using composer.
+ * Why are you not using composer?
+ * https://getcomposer.org/
+ */
+
+if (version_compare(PHP_VERSION, '5.4.0', '<')) {
+  throw new Exception('The Facebook SDK v4 requires PHP version 5.4 or higher.');
+}
+
+/**
+ * Register the autoloader for the Facebook SDK classes.
+ * Based off the official PSR-4 autoloader example found here:
+ * https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
+ *
+ * @param string $class The fully-qualified class name.
+ * @return void
+ */
+spl_autoload_register(function ($class)
+{
+  // project-specific namespace prefix
+  $prefix = 'Facebook\\';
+
+  // base directory for the namespace prefix
+  $base_dir = defined('FACEBOOK_SDK_V4_SRC_DIR') ? FACEBOOK_SDK_V4_SRC_DIR : __DIR__ . '/src/Facebook/';
+
+  // does the class use the namespace prefix?
+  $len = strlen($prefix);
+  if (strncmp($prefix, $class, $len) !== 0) {
+    // no, move to the next registered autoloader
+    return;
+  }
+
+  // get the relative class name
+  $relative_class = substr($class, $len);
+
+  // replace the namespace prefix with the base directory, replace namespace
+  // separators with directory separators in the relative class name, append
+  // with .php
+  $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
+
+  // if the file exists, require it
+  if (file_exists($file)) {
+    require $file;
+  }
+});

+ 380 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/Entities/AccessToken.php

@@ -0,0 +1,380 @@
+<?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;
+  }
+
+  /**
+   * Returns true if the access token is an app session token.
+   *
+   * @return bool
+   */
+  public function isAppSession()
+  {
+    return strpos($this->accessToken, "|") !== false;
+  }
+
+}

+ 386 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/Entities/SignedRequest.php

@@ -0,0 +1,386 @@
+<?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
+    );
+  }
+
+}

+ 33 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookAuthorizationException.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * Class FacebookAuthorizationException
+ * @package Facebook
+ */
+class FacebookAuthorizationException extends FacebookRequestException
+{
+
+}

+ 60 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookCanvasLoginHelper.php

@@ -0,0 +1,60 @@
+<?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;
+
+/**
+ * Class FacebookCanvasLoginHelper
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class FacebookCanvasLoginHelper extends FacebookSignedRequestFromInputHelper
+{
+
+  /**
+   * Returns the app data value.
+   *
+   * @return mixed|null
+   */
+  public function getAppData()
+  {
+    return $this->signedRequest ? $this->signedRequest->get('app_data') : null;
+  }
+
+  /**
+   * Get raw signed request from POST.
+   *
+   * @return string|null
+   */
+  public function getRawSignedRequest()
+  {
+    $rawSignedRequest = $this->getRawSignedRequestFromPost();
+    if ($rawSignedRequest) {
+      return $rawSignedRequest;
+    }
+
+    return null;
+  }
+
+}

+ 33 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookClientException.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * Class FacebookClientException
+ * @package Facebook
+ */
+class FacebookClientException extends FacebookRequestException
+{
+
+}

+ 45 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookJavaScriptLoginHelper.php

@@ -0,0 +1,45 @@
+<?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;
+
+/**
+ * Class FacebookJavaScriptLoginHelper
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class FacebookJavaScriptLoginHelper extends FacebookSignedRequestFromInputHelper
+{
+
+  /**
+   * Get raw signed request from the cookie.
+   *
+   * @return string|null
+   */
+  public function getRawSignedRequest()
+  {
+    return $this->getRawSignedRequestFromCookie();
+  }
+
+}

+ 33 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookOtherException.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * Class FacebookOtherException
+ * @package Facebook
+ */
+class FacebookOtherException extends FacebookRequestException
+{
+
+}

+ 102 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookPageTabHelper.php

@@ -0,0 +1,102 @@
+<?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;
+
+/**
+ * Class FacebookPageTabHelper
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ */
+class FacebookPageTabHelper extends FacebookCanvasLoginHelper
+{
+
+  /**
+   * @var array|null
+   */
+  protected $pageData;
+
+  /**
+   * Initialize the helper and process available signed request data.
+   *
+   * @param string|null $appId
+   * @param string|null $appSecret
+   */
+  public function __construct($appId = null, $appSecret = null)
+  {
+    parent::__construct($appId, $appSecret);
+
+    if (!$this->signedRequest) {
+      return;
+    }
+
+    $this->pageData = $this->signedRequest->get('page');
+  }
+
+  /**
+   * Returns a value from the page data.
+   *
+   * @param string $key
+   * @param mixed|null $default
+   *
+   * @return mixed|null
+   */
+  public function getPageData($key, $default = null)
+  {
+    if (isset($this->pageData[$key])) {
+      return $this->pageData[$key];
+    }
+    return $default;
+  }
+
+  /**
+   * Returns true if the page is liked by the user.
+   *
+   * @return boolean
+   */
+  public function isLiked()
+  {
+    return $this->getPageData('liked') === true;
+  }
+
+  /**
+   * Returns true if the user is an admin.
+   *
+   * @return boolean
+   */
+  public function isAdmin()
+  {
+    return $this->getPageData('admin') === true;
+  }
+
+  /**
+   * Returns the page id if available.
+   *
+   * @return string|null
+   */
+  public function getPageId()
+  {
+    return $this->getPageData('id');
+  }
+
+}

+ 33 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookPermissionException.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * Class FacebookPermissionException
+ * @package Facebook
+ */
+class FacebookPermissionException extends FacebookRequestException
+{
+
+}

+ 324 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookRedirectLoginHelper.php

@@ -0,0 +1,324 @@
+<?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;
+
+/**
+ * Class FacebookRedirectLoginHelper
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class FacebookRedirectLoginHelper
+{
+
+  /**
+   * @var string The application id
+   */
+  private $appId;
+
+  /**
+   * @var string The application secret
+   */
+  private $appSecret;
+
+  /**
+   * @var string The redirect URL for the application
+   */
+  private $redirectUrl;
+
+  /**
+   * @var string Prefix to use for session variables
+   */
+  private $sessionPrefix = 'FBRLH_';
+
+  /**
+   * @var string State token for CSRF validation
+   */
+  protected $state;
+
+  /**
+   * @var boolean Toggle for PHP session status check
+   */
+  protected $checkForSessionStatus = true;
+
+  /**
+   * Constructs a RedirectLoginHelper for a given appId and redirectUrl.
+   *
+   * @param string $redirectUrl The URL Facebook should redirect users to
+   *                            after login
+   * @param string $appId The application id
+   * @param string $appSecret The application secret
+   */
+  public function __construct($redirectUrl, $appId = null, $appSecret = null)
+  {
+    $this->appId = FacebookSession::_getTargetAppId($appId);
+    $this->appSecret = FacebookSession::_getTargetAppSecret($appSecret);
+    $this->redirectUrl = $redirectUrl;
+  }
+
+  /**
+   * Stores CSRF state and returns a URL to which the user should be sent to
+   *   in order to continue the login process with Facebook.  The
+   *   provided redirectUrl should invoke the handleRedirect method.
+   *
+   * @param array $scope List of permissions to request during login
+   * @param string $version Optional Graph API version if not default (v2.0)
+   * @param boolean $displayAsPopup Indicate if the page will be displayed as a popup
+   *
+   * @return string
+   */
+  public function getLoginUrl($scope = array(), $version = null, $displayAsPopup = false)
+  {
+
+    $version = ($version ?: FacebookRequest::GRAPH_API_VERSION);
+    $this->state = $this->random(16);
+    $this->storeState($this->state);
+
+    $params = array(
+      'client_id' => $this->appId,
+      'redirect_uri' => $this->redirectUrl,
+      'state' => $this->state,
+      'sdk' => 'php-sdk-' . FacebookRequest::VERSION,
+      'scope' => implode(',', $scope)
+    );
+    
+    if ($displayAsPopup)
+    {
+      $params['display'] = 'popup';
+    }
+    
+    return 'https://www.facebook.com/' . $version . '/dialog/oauth?' .
+      http_build_query($params, null, '&');
+  }
+
+  /**
+   * Returns a URL to which the user should be sent to re-request permissions.
+   *
+   * @param array $scope List of permissions to re-request
+   * @param string $version Optional Graph API version if not default (v2.0)
+   *
+   * @return string
+   */
+  public function getReRequestUrl($scope = array(), $version = null)
+  {
+    $version = ($version ?: FacebookRequest::GRAPH_API_VERSION);
+    $this->state = $this->random(16);
+    $this->storeState($this->state);
+    $params = array(
+      'client_id' => $this->appId,
+      'redirect_uri' => $this->redirectUrl,
+      'state' => $this->state,
+      'sdk' => 'php-sdk-' . FacebookRequest::VERSION,
+      'auth_type' => 'rerequest',
+      'scope' => implode(',', $scope)
+    );
+    return 'https://www.facebook.com/' . $version . '/dialog/oauth?' .
+      http_build_query($params, null, '&');
+  }
+
+  /**
+   * Returns the URL to send the user in order to log out of Facebook.
+   *
+   * @param FacebookSession $session The session that will be logged out
+   * @param string $next The url Facebook should redirect the user to after
+   *   a successful logout
+   *
+   * @return string
+   *
+   * @throws FacebookSDKException
+   */
+  public function getLogoutUrl(FacebookSession $session, $next)
+  {
+    if ($session->getAccessToken()->isAppSession()) {
+      throw new FacebookSDKException(
+        'Cannot generate a Logout URL with an App Session.', 722
+      );
+    }
+    $params = array(
+      'next' => $next,
+      'access_token' => $session->getToken()
+    );
+    return 'https://www.facebook.com/logout.php?' . http_build_query($params, null, '&');
+  }
+
+  /**
+   * Handles a response from Facebook, including a CSRF check, and returns a
+   *   FacebookSession.
+   *
+   * @return FacebookSession|null
+   */
+  public function getSessionFromRedirect()
+  {
+    $this->loadState();
+    if ($this->isValidRedirect()) {
+	
+      $params = array(
+        'client_id' => FacebookSession::_getTargetAppId($this->appId),
+        'redirect_uri' => $this->redirectUrl,
+        'client_secret' =>
+          FacebookSession::_getTargetAppSecret($this->appSecret),
+        'code' => $this->getCode()
+      );
+
+      $response = (new FacebookRequest(
+        FacebookSession::newAppSession($this->appId, $this->appSecret),
+        'GET',
+        '/oauth/access_token',
+        $params
+      ))->execute()->getResponse();
+		
+      if (isset($response['access_token'])) {
+        return new FacebookSession($response['access_token']);
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Check if a redirect has a valid state.
+   *
+   * @return bool
+   */
+  protected function isValidRedirect()
+  {
+    return $this->getCode() && isset($_GET['state'])
+        && $_GET['state'] == $this->state;
+  }
+
+  /**
+   * Return the code.
+   *
+   * @return string|null
+   */
+  protected function getCode()
+  {
+
+    return isset($_GET['code']) ? $_GET['code'] : null;
+  }
+
+  /**
+   * Stores a state string in session storage for CSRF protection.
+   * Developers should subclass and override this method if they want to store
+   *   this state in a different location.
+   *
+   * @param string $state
+   *
+   * @throws FacebookSDKException
+   */
+  protected function storeState($state)
+  {
+    if ($this->checkForSessionStatus === true
+      && session_status() !== PHP_SESSION_ACTIVE) {
+      throw new FacebookSDKException(
+        'Session not active, could not store state.', 720
+      );
+    }
+    $_SESSION[$this->sessionPrefix . 'state'] = $state;
+  }
+
+  /**
+   * Loads a state string from session storage for CSRF validation.  May return
+   *   null if no object exists.  Developers should subclass and override this
+   *   method if they want to load the state from a different location.
+   *
+   * @return string|null
+   *
+   * @throws FacebookSDKException
+   */
+  protected function loadState()
+  {
+	
+    if ($this->checkForSessionStatus === true
+      && session_status() !== PHP_SESSION_ACTIVE) {
+      throw new FacebookSDKException(
+        'Session not active, could not load state.', 721
+      );
+    }
+    if (isset($_SESSION[$this->sessionPrefix . 'state'])) {
+      $this->state = $_SESSION[$this->sessionPrefix . 'state'];
+      return $this->state;
+    }
+    return null;
+  }
+  
+  /**
+   * Generate a cryptographically secure pseudrandom number
+   * 
+   * @param integer $bytes - number of bytes to return
+   * 
+   * @return string
+   * 
+   * @throws FacebookSDKException
+   * 
+   * @todo Support Windows platforms
+   */
+  public function random($bytes)
+  {
+    if (!is_numeric($bytes)) {
+      throw new FacebookSDKException(
+        "random() expects an integer"
+      );
+    }
+    if ($bytes < 1) {
+      throw new FacebookSDKException(
+        "random() expects an integer greater than zero"
+      );
+    }
+    $buf = '';
+    // http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
+    if (!ini_get('open_basedir')
+      && is_readable('/dev/urandom')) {
+      $fp = fopen('/dev/urandom', 'rb');
+      if ($fp !== FALSE) {
+        $buf = fread($fp, $bytes);
+        fclose($fp);
+        if($buf !== FALSE) {
+          return bin2hex($buf);
+        }
+      }
+    }
+
+    if (function_exists('mcrypt_create_iv')) {
+        $buf = mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
+        if ($buf !== FALSE) {
+          return bin2hex($buf);
+        }
+    }
+    
+    while (strlen($buf) < $bytes) {
+      $buf .= md5(uniqid(mt_rand(), true), true); 
+      // We are appending raw binary
+    }
+    return bin2hex(substr($buf, 0, $bytes));
+  }
+
+  /**
+   * Disables the session_status() check when using $_SESSION
+   */
+  public function disableSessionStatusCheck()
+  {
+    $this->checkForSessionStatus = false;
+  }
+
+}

+ 313 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookRequest.php

@@ -0,0 +1,313 @@
+<?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;
+
+use Facebook\HttpClients\FacebookHttpable;
+use Facebook\HttpClients\FacebookCurlHttpClient;
+use Facebook\HttpClients\FacebookStreamHttpClient;
+
+/**
+ * Class FacebookRequest
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class FacebookRequest
+{
+
+  /**
+   * @const string Version number of the Facebook PHP SDK.
+   */
+  const VERSION = '4.0.15';
+
+  /**
+   * @const string Default Graph API version for requests
+   */
+  const GRAPH_API_VERSION = 'v2.2';
+
+  /**
+   * @const string Graph API URL
+   */
+  const BASE_GRAPH_URL = 'https://graph.facebook.com';
+
+  /**
+   * @var FacebookSession The session used for this request
+   */
+  private $session;
+
+  /**
+   * @var string The HTTP method for the request
+   */
+  private $method;
+
+  /**
+   * @var string The path for the request
+   */
+  private $path;
+
+  /**
+   * @var array The parameters for the request
+   */
+  private $params;
+
+  /**
+   * @var string The Graph API version for the request
+   */
+  private $version;
+
+  /**
+   * @var string ETag sent with the request
+   */
+  private $etag;
+
+  /**
+   * @var FacebookHttpable HTTP client handler
+   */
+  private static $httpClientHandler;
+
+  /**
+   * @var int The number of calls that have been made to Graph.
+   */
+  public static $requestCount = 0;
+
+  /**
+   * getSession - Returns the associated FacebookSession.
+   *
+   * @return FacebookSession
+   */
+  public function getSession()
+  {
+    return $this->session;
+  }
+
+  /**
+   * getPath - Returns the associated path.
+   *
+   * @return string
+   */
+  public function getPath()
+  {
+    return $this->path;
+  }
+
+  /**
+   * getParameters - Returns the associated parameters.
+   *
+   * @return array
+   */
+  public function getParameters()
+  {
+    return $this->params;
+  }
+
+  /**
+   * getMethod - Returns the associated method.
+   *
+   * @return string
+   */
+  public function getMethod()
+  {
+    return $this->method;
+  }
+
+  /**
+   * getETag - Returns the ETag sent with the request.
+   *
+   * @return string
+   */
+  public function getETag()
+  {
+    return $this->etag;
+  }
+
+  /**
+   * setHttpClientHandler - Returns an instance of the HTTP client
+   * handler
+   *
+   * @param \Facebook\HttpClients\FacebookHttpable
+   */
+  public static function setHttpClientHandler(FacebookHttpable $handler)
+  {
+    static::$httpClientHandler = $handler;
+  }
+
+  /**
+   * getHttpClientHandler - Returns an instance of the HTTP client
+   * data handler
+   *
+   * @return FacebookHttpable
+   */
+  public static function getHttpClientHandler()
+  {
+    if (static::$httpClientHandler) {
+      return static::$httpClientHandler;
+    }
+    return function_exists('curl_init') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient();
+  }
+
+  /**
+   * FacebookRequest - Returns a new request using the given session.  optional
+   *   parameters hash will be sent with the request.  This object is
+   *   immutable.
+   *
+   * @param FacebookSession $session
+   * @param string $method
+   * @param string $path
+   * @param array|null $parameters
+   * @param string|null $version
+   * @param string|null $etag
+   */
+  public function __construct(
+    FacebookSession $session, $method, $path, $parameters = null, $version = null, $etag = null
+  )
+  {
+    $this->session = $session;
+    $this->method = $method;
+    $this->path = $path;
+    if ($version) {
+      $this->version = $version;
+    } else {
+      $this->version = static::GRAPH_API_VERSION;
+    }
+    $this->etag = $etag;
+
+    $params = ($parameters ?: array());
+    if ($session
+      && !isset($params["access_token"])) {
+      $params["access_token"] = $session->getToken();
+    }
+    if (FacebookSession::useAppSecretProof()
+      && !isset($params["appsecret_proof"])) {
+      $params["appsecret_proof"] = $this->getAppSecretProof(
+        $params["access_token"]
+      );
+    }
+    $this->params = $params;
+  }
+
+  /**
+   * Returns the base Graph URL.
+   *
+   * @return string
+   */
+  protected function getRequestURL()
+  {
+    return static::BASE_GRAPH_URL . '/' . $this->version . $this->path;
+  }
+
+  /**
+   * execute - Makes the request to Facebook and returns the result.
+   *
+   * @return FacebookResponse
+   *
+   * @throws FacebookSDKException
+   * @throws FacebookRequestException
+   */
+  public function execute()
+  {
+    $url = $this->getRequestURL();
+    $params = $this->getParameters();
+
+    if ($this->method === "GET") {
+      $url = self::appendParamsToUrl($url, $params);
+      $params = array();
+    }
+
+    $connection = self::getHttpClientHandler();
+    $connection->addRequestHeader('User-Agent', 'fb-php-' . self::VERSION);
+    $connection->addRequestHeader('Accept-Encoding', '*'); // Support all available encodings.
+
+    // ETag
+    if (isset($this->etag)) {
+      $connection->addRequestHeader('If-None-Match', $this->etag);
+    }
+
+    // Should throw `FacebookSDKException` exception on HTTP client error.
+    // Don't catch to allow it to bubble up.
+    $result = $connection->send($url, $this->method, $params);
+
+    static::$requestCount++;
+
+    $etagHit = 304 == $connection->getResponseHttpStatusCode();
+
+    $headers = $connection->getResponseHeaders();
+    $etagReceived = isset($headers['ETag']) ? $headers['ETag'] : null;
+
+    $decodedResult = json_decode($result);
+    if ($decodedResult === null) {
+      $out = array();
+      parse_str($result, $out);
+      return new FacebookResponse($this, $out, $result, $etagHit, $etagReceived);
+    }
+    if (isset($decodedResult->error)) {
+      throw FacebookRequestException::create(
+        $result,
+        $decodedResult->error,
+        $connection->getResponseHttpStatusCode()
+      );
+    }
+
+    return new FacebookResponse($this, $decodedResult, $result, $etagHit, $etagReceived);
+  }
+
+  /**
+   * Generate and return the appsecret_proof value for an access_token
+   *
+   * @param string $token
+   *
+   * @return string
+   */
+  public function getAppSecretProof($token)
+  {
+    return hash_hmac('sha256', $token, FacebookSession::_getTargetAppSecret());
+  }
+
+  /**
+   * appendParamsToUrl - Gracefully appends params to the URL.
+   *
+   * @param string $url
+   * @param array $params
+   *
+   * @return string
+   */
+  public static function appendParamsToUrl($url, $params = array())
+  {
+    if (!$params) {
+      return $url;
+    }
+
+    if (strpos($url, '?') === false) {
+      return $url . '?' . http_build_query($params, null, '&');
+    }
+
+    list($path, $query_string) = explode('?', $url, 2);
+    parse_str($query_string, $query_array);
+
+    // Favor params from the original URL over $params
+    $params = array_merge($params, $query_array);
+
+    return $path . '?' . http_build_query($params, null, '&');
+  }
+
+}

+ 222 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookRequestException.php

@@ -0,0 +1,222 @@
+<?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;
+
+/**
+ * Class FacebookRequestException
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class FacebookRequestException extends FacebookSDKException
+{
+
+  /**
+   * @var int Status code for the response causing the exception
+   */
+  private $statusCode;
+
+  /**
+   * @var string Raw response
+   */
+  private $rawResponse;
+
+  /**
+   * @var array Decoded response
+   */
+  private $responseData;
+
+  /**
+   * Creates a FacebookRequestException.
+   *
+   * @param string $rawResponse The raw response from the Graph API
+   * @param array $responseData The decoded response from the Graph API
+   * @param int $statusCode
+   */
+  public function __construct($rawResponse, $responseData, $statusCode)
+  {
+    $this->rawResponse = $rawResponse;
+    $this->statusCode = $statusCode;
+    $this->responseData = self::convertToArray($responseData);
+    parent::__construct(
+      $this->get('message', 'Unknown Exception'), $this->get('code', -1), null
+    );
+  }
+
+  /**
+   * Process an error payload from the Graph API and return the appropriate
+   *   exception subclass.
+   *
+   * @param string $raw the raw response from the Graph API
+   * @param array $data the decoded response from the Graph API
+   * @param int $statusCode the HTTP response code
+   *
+   * @return FacebookRequestException
+   */
+  public static function create($raw, $data, $statusCode)
+  {
+    $data = self::convertToArray($data);
+    if (!isset($data['error']['code']) && isset($data['code'])) {
+      $data = array('error' => $data);
+    }
+    $code = (isset($data['error']['code']) ? $data['error']['code'] : null);
+
+    if (isset($data['error']['error_subcode'])) {
+      switch ($data['error']['error_subcode']) {
+        // Other authentication issues
+        case 458:
+        case 459:
+        case 460:
+        case 463:
+        case 464:
+        case 467:
+          return new FacebookAuthorizationException($raw, $data, $statusCode);
+          break;
+      }
+    }
+
+    switch ($code) {
+      // Login status or token expired, revoked, or invalid
+      case 100:
+      case 102:
+      case 190:
+        return new FacebookAuthorizationException($raw, $data, $statusCode);
+        break;
+
+      // Server issue, possible downtime
+      case 1:
+      case 2:
+        return new FacebookServerException($raw, $data, $statusCode);
+        break;
+
+      // API Throttling
+      case 4:
+      case 17:
+      case 341:
+        return new FacebookThrottleException($raw, $data, $statusCode);
+        break;
+
+      // Duplicate Post
+      case 506:
+        return new FacebookClientException($raw, $data, $statusCode);
+        break;
+    }
+
+    // Missing Permissions
+    if ($code == 10 || ($code >= 200 && $code <= 299)) {
+      return new FacebookPermissionException($raw, $data, $statusCode);
+    }
+
+    // OAuth authentication error
+    if (isset($data['error']['type'])
+      and $data['error']['type'] === 'OAuthException') {
+      return new FacebookAuthorizationException($raw, $data, $statusCode);
+    }
+
+    // All others
+    return new FacebookOtherException($raw, $data, $statusCode);
+  }
+
+  /**
+   * Checks isset and returns that or a default value.
+   *
+   * @param string $key
+   * @param mixed $default
+   *
+   * @return mixed
+   */
+  private function get($key, $default = null)
+  {
+    if (isset($this->responseData['error'][$key])) {
+      return $this->responseData['error'][$key];
+    }
+    return $default;
+  }
+
+  /**
+   * Returns the HTTP status code
+   *
+   * @return int
+   */
+  public function getHttpStatusCode()
+  {
+    return $this->statusCode;
+  }
+
+  /**
+   * Returns the sub-error code
+   *
+   * @return int
+   */
+  public function getSubErrorCode()
+  {
+    return $this->get('error_subcode', -1);
+  }
+
+  /**
+   * Returns the error type
+   *
+   * @return string
+   */
+  public function getErrorType()
+  {
+    return $this->get('type', '');
+  }
+
+  /**
+   * Returns the raw response used to create the exception.
+   *
+   * @return string
+   */
+  public function getRawResponse()
+  {
+    return $this->rawResponse;
+  }
+
+  /**
+   * Returns the decoded response used to create the exception.
+   *
+   * @return array
+   */
+  public function getResponse()
+  {
+    return $this->responseData;
+  }
+
+  /**
+   * Converts a stdClass object to an array
+   *
+   * @param mixed $object
+   *
+   * @return array
+   */
+  private static function convertToArray($object)
+  {
+    if ($object instanceof \stdClass) {
+      return get_object_vars($object);
+    }
+    return $object;
+  }
+
+}

+ 206 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookResponse.php

@@ -0,0 +1,206 @@
+<?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;
+
+/**
+ * Class FacebookResponse
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class FacebookResponse
+{
+
+  /**
+   * @var FacebookRequest The request which produced this response
+   */
+  private $request;
+
+  /**
+   * @var array The decoded response from the Graph API
+   */
+  private $responseData;
+
+  /**
+   * @var string The raw response from the Graph API
+   */
+  private $rawResponse;
+
+  /**
+   * @var bool Indicates whether sent ETag matched the one on the FB side
+   */
+  private $etagHit;
+
+  /**
+   * @var string ETag received with the response. `null` in case of ETag hit.
+   */
+  private $etag;
+
+  /**
+   * Creates a FacebookResponse object for a given request and response.
+   *
+   * @param FacebookRequest $request
+   * @param array $responseData JSON Decoded response data
+   * @param string $rawResponse Raw string response
+   * @param bool $etagHit Indicates whether sent ETag matched the one on the FB side
+   * @param string|null $etag ETag received with the response. `null` in case of ETag hit.
+   */
+  public function __construct($request, $responseData, $rawResponse, $etagHit = false, $etag = null)
+  {
+    $this->request = $request;
+    $this->responseData = $responseData;
+    $this->rawResponse = $rawResponse;
+    $this->etagHit = $etagHit;
+    $this->etag = $etag;
+  }
+
+  /**
+   * Returns the request which produced this response.
+   *
+   * @return FacebookRequest
+   */
+  public function getRequest()
+  {
+    return $this->request;
+  }
+
+  /**
+   * Returns the decoded response data.
+   *
+   * @return array
+   */
+  public function getResponse()
+  {
+    return $this->responseData;
+  }
+
+  /**
+   * Returns the raw response
+   *
+   * @return string
+   */
+  public function getRawResponse()
+  {
+    return $this->rawResponse;
+  }
+
+  /**
+   * Returns true if ETag matched the one sent with a request
+   *
+   * @return bool
+   */
+  public function isETagHit()
+  {
+    return $this->etagHit;
+  }
+
+  /**
+   * Returns the ETag
+   *
+   * @return string
+   */
+  public function getETag()
+  {
+    return $this->etag;
+  }
+
+  /**
+   * Gets the result as a GraphObject.  If a type is specified, returns the
+   *   strongly-typed subclass of GraphObject for the data.
+   *
+   * @param string $type
+   *
+   * @return mixed
+   */
+  public function getGraphObject($type = 'Facebook\GraphObject') {
+    return (new GraphObject($this->responseData))->cast($type);
+  }
+
+  /**
+   * Returns an array of GraphObject returned by the request.  If a type is
+   * specified, returns the strongly-typed subclass of GraphObject for the data.
+   *
+   * @param string $type
+   *
+   * @return mixed
+   */
+  public function getGraphObjectList($type = 'Facebook\GraphObject') {
+    $out = array();
+    $data = $this->responseData->data;
+    $dataLength = count($data);
+    for ($i = 0; $i < $dataLength; $i++) {
+      $out[] = (new GraphObject($data[$i]))->cast($type);
+    }
+    return $out;
+  }
+
+  /**
+   * If this response has paginated data, returns the FacebookRequest for the
+   *   next page, or null.
+   *
+   * @return FacebookRequest|null
+   */
+  public function getRequestForNextPage()
+  {
+    return $this->handlePagination('next');
+  }
+
+  /**
+   * If this response has paginated data, returns the FacebookRequest for the
+   *   previous page, or null.
+   *
+   * @return FacebookRequest|null
+   */
+  public function getRequestForPreviousPage()
+  {
+    return $this->handlePagination('previous');
+  }
+
+  /**
+   * Returns the FacebookRequest for the previous or next page, or null.
+   *
+   * @param string $direction
+   *
+   * @return FacebookRequest|null
+   */
+  private function handlePagination($direction) {
+    if (isset($this->responseData->paging->$direction)) {
+      $url = parse_url($this->responseData->paging->$direction);
+      parse_str($url['query'], $params);
+
+      if (isset($params['type']) && strpos($this->request->getPath(), $params['type']) !== false){
+        unset($params['type']);
+      }
+      return new FacebookRequest(
+        $this->request->getSession(),
+        $this->request->getMethod(),
+        $this->request->getPath(),
+        $params
+      );
+    } else {
+      return null;
+    }
+  }
+
+}

+ 33 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookSDKException.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * Class FacebookSDKException
+ * @package Facebook
+ */
+class FacebookSDKException extends \Exception
+{
+
+}

+ 33 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookServerException.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * Class FacebookServerException
+ * @package Facebook
+ */
+class FacebookServerException extends FacebookRequestException
+{
+
+}

+ 367 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookSession.php

@@ -0,0 +1,367 @@
+<?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;
+
+use Facebook\Entities\AccessToken;
+use Facebook\Entities\SignedRequest;
+
+/**
+ * Class FacebookSession
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class FacebookSession
+{
+
+  /**
+   * @var string
+   */
+  private static $defaultAppId;
+
+  /**
+   * @var string
+   */
+  private static $defaultAppSecret;
+
+  /**
+   * @var AccessToken The AccessToken entity for this connection.
+   */
+  private $accessToken;
+
+  /**
+   * @var SignedRequest
+   */
+  private $signedRequest;
+
+  /**
+   * @var bool
+   */
+  protected static $useAppSecretProof = true;
+
+  /**
+   * When creating a Session from an access_token, use:
+   *   var $session = new FacebookSession($accessToken);
+   * This will validate the token and provide a Session object ready for use.
+   * It will throw a SessionException in case of error.
+   *
+   * @param AccessToken|string $accessToken
+   * @param SignedRequest $signedRequest The SignedRequest entity
+   */
+  public function __construct($accessToken, SignedRequest $signedRequest = null)
+  {
+    $this->accessToken = $accessToken instanceof AccessToken ? $accessToken : new AccessToken($accessToken);
+    $this->signedRequest = $signedRequest;
+  }
+
+  /**
+   * Returns the access token.
+   *
+   * @return string
+   */
+  public function getToken()
+  {
+    return (string) $this->accessToken;
+  }
+
+  /**
+   * Returns the access token entity.
+   *
+   * @return AccessToken
+   */
+  public function getAccessToken()
+  {
+    return $this->accessToken;
+  }
+
+  /**
+   * Returns the SignedRequest entity.
+   *
+   * @return SignedRequest
+   */
+  public function getSignedRequest()
+  {
+    return $this->signedRequest;
+  }
+
+  /**
+   * Returns the signed request payload.
+   *
+   * @return null|array
+   */
+  public function getSignedRequestData()
+  {
+    return $this->signedRequest ? $this->signedRequest->getPayload() : null;
+  }
+
+  /**
+   * Returns a property from the signed request data if available.
+   *
+   * @param string $key
+   *
+   * @return null|mixed
+   */
+  public function getSignedRequestProperty($key)
+  {
+    return $this->signedRequest ? $this->signedRequest->get($key) : null;
+  }
+
+  /**
+   * Returns user_id from signed request data if available.
+   *
+   * @return null|string
+   */
+  public function getUserId()
+  {
+    return $this->signedRequest ? $this->signedRequest->getUserId() : null;
+  }
+
+  // @TODO Remove getSessionInfo() in 4.1: can be accessed from AccessToken directly
+  /**
+   * getSessionInfo - Makes a request to /debug_token with the appropriate
+   *   arguments to get debug information about the sessions token.
+   *
+   * @param string|null $appId
+   * @param string|null $appSecret
+   *
+   * @return GraphSessionInfo
+   */
+  public function getSessionInfo($appId = null, $appSecret = null)
+  {
+    return $this->accessToken->getInfo($appId, $appSecret);
+  }
+
+  // @TODO Remove getLongLivedSession() in 4.1: can be accessed from AccessToken directly
+  /**
+   * getLongLivedSession - Returns a new Facebook session resulting from
+   *   extending a short-lived access token.  If this session is not
+   *   short-lived, returns $this.
+   *
+   * @param string|null $appId
+   * @param string|null $appSecret
+   *
+   * @return FacebookSession
+   */
+  public function getLongLivedSession($appId = null, $appSecret = null)
+  {
+    $longLivedAccessToken = $this->accessToken->extend($appId, $appSecret);
+    return new static($longLivedAccessToken, $this->signedRequest);
+  }
+
+  // @TODO Remove getExchangeToken() in 4.1: can be accessed from AccessToken directly
+  /**
+   * getExchangeToken - Returns an exchange token string which can be sent
+   *   back to clients and exchanged for a device-linked access token.
+   *
+   * @param string|null $appId
+   * @param string|null $appSecret
+   *
+   * @return string
+   */
+  public function getExchangeToken($appId = null, $appSecret = null)
+  {
+    return AccessToken::getCodeFromAccessToken($this->accessToken, $appId, $appSecret);
+  }
+
+  // @TODO Remove validate() in 4.1: can be accessed from AccessToken directly
+  /**
+   * validate - Ensures the current session is valid, throwing an exception if
+   *   not.  Fetches token info from Facebook.
+   *
+   * @param string|null $appId Application ID to use
+   * @param string|null $appSecret App secret value to use
+   * @param string|null $machineId
+   *
+   * @return boolean
+   *
+   * @throws FacebookSDKException
+   */
+  public function validate($appId = null, $appSecret = null, $machineId = null)
+  {
+    if ($this->accessToken->isValid($appId, $appSecret, $machineId)) {
+      return true;
+    }
+
+    // @TODO For v4.1 this should not throw an exception, but just return false.
+    throw new FacebookSDKException(
+      'Session has expired, or is not valid for this app.', 601
+    );
+  }
+
+  // @TODO Remove validateSessionInfo() in 4.1: can be accessed from AccessToken directly
+  /**
+   * validateTokenInfo - Ensures the provided GraphSessionInfo object is valid,
+   *   throwing an exception if not.  Ensures the appId matches,
+   *   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
+   *
+   * @throws FacebookSDKException
+   */
+  public static function validateSessionInfo(GraphSessionInfo $tokenInfo,
+                                           $appId = null,
+                                           $machineId = null)
+  {
+    if (AccessToken::validateAccessToken($tokenInfo, $appId, $machineId)) {
+      return true;
+    }
+
+    // @TODO For v4.1 this should not throw an exception, but just return false.
+    throw new FacebookSDKException(
+      'Session has expired, or is not valid for this app.', 601
+    );
+  }
+
+  /**
+   * newSessionFromSignedRequest - Returns a FacebookSession for a
+   *   given signed request.
+   *
+   * @param SignedRequest $signedRequest
+   *
+   * @return FacebookSession
+   */
+  public static function newSessionFromSignedRequest(SignedRequest $signedRequest)
+  {
+    if ($signedRequest->get('code')
+      && !$signedRequest->get('oauth_token')) {
+      return self::newSessionAfterValidation($signedRequest);
+    }
+    $accessToken = $signedRequest->get('oauth_token');
+    $expiresAt = $signedRequest->get('expires', 0);
+    $accessToken = new AccessToken($accessToken, $expiresAt);
+    return new static($accessToken, $signedRequest);
+  }
+
+  /**
+   * newSessionAfterValidation - Returns a FacebookSession for a
+   *   validated & parsed signed request.
+   *
+   * @param SignedRequest $signedRequest
+   *
+   * @return FacebookSession
+   */
+  protected static function newSessionAfterValidation(SignedRequest $signedRequest)
+  {
+    $code = $signedRequest->get('code');
+    $accessToken = AccessToken::getAccessTokenFromCode($code);
+    return new static($accessToken, $signedRequest);
+  }
+
+  /**
+   * newAppSession - Returns a FacebookSession configured with a token for the
+   *   application which can be used for publishing and requesting app-level
+   *   information.
+   *
+   * @param string|null $appId Application ID to use
+   * @param string|null $appSecret App secret value to use
+   *
+   * @return FacebookSession
+   */
+  public static function newAppSession($appId = null, $appSecret = null)
+  {
+    $targetAppId = static::_getTargetAppId($appId);
+    $targetAppSecret = static::_getTargetAppSecret($appSecret);
+    return new FacebookSession(
+      $targetAppId . '|' . $targetAppSecret
+    );
+  }
+
+  /**
+   * setDefaultApplication - Will set the static default appId and appSecret
+   *   to be used for API requests.
+   *
+   * @param string $appId Application ID to use by default
+   * @param string $appSecret App secret value to use by default
+   */
+  public static function setDefaultApplication($appId, $appSecret)
+  {
+    self::$defaultAppId = $appId;
+    self::$defaultAppSecret = $appSecret;
+  }
+
+  /**
+   * _getTargetAppId - Will return either the provided app Id or the default,
+   *   throwing if neither are populated.
+   *
+   * @param string $appId
+   *
+   * @return string
+   *
+   * @throws FacebookSDKException
+   */
+  public static function _getTargetAppId($appId = null) {
+    $target = ($appId ?: self::$defaultAppId);
+    if (!$target) {
+      throw new FacebookSDKException(
+        'You must provide or set a default application id.', 700
+      );
+    }
+    return $target;
+  }
+
+  /**
+   * _getTargetAppSecret - Will return either the provided app secret or the
+   *   default, throwing if neither are populated.
+   *
+   * @param string $appSecret
+   *
+   * @return string
+   *
+   * @throws FacebookSDKException
+   */
+  public static function _getTargetAppSecret($appSecret = null) {
+    $target = ($appSecret ?: self::$defaultAppSecret);
+    if (!$target) {
+      throw new FacebookSDKException(
+        'You must provide or set a default application secret.', 701
+      );
+    }
+    return $target;
+  }
+
+  /**
+   * Enable or disable sending the appsecret_proof with requests.
+   *
+   * @param bool $on
+   */
+  public static function enableAppSecretProof($on = true)
+  {
+    static::$useAppSecretProof = ($on ? true : false);
+  }
+
+  /**
+   * Get whether or not appsecret_proof should be sent with requests.
+   *
+   * @return bool
+   */
+  public static function useAppSecretProof()
+  {
+    return static::$useAppSecretProof;
+  }
+
+}

+ 166 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookSignedRequestFromInputHelper.php

@@ -0,0 +1,166 @@
+<?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;
+
+use Facebook\Entities\SignedRequest;
+
+/**
+ * Class FacebookSignedRequestFromInputHelper
+ * @package Facebook
+ */
+abstract class FacebookSignedRequestFromInputHelper
+{
+
+  /**
+   * @var \Facebook\Entities\SignedRequest|null
+   */
+  protected $signedRequest;
+
+  /**
+   * @var string the app id
+   */
+  protected $appId;
+
+  /**
+   * @var string the app secret
+   */
+  protected $appSecret;
+
+  /**
+   * @var string|null Random string to prevent CSRF.
+   */
+  public $state = null;
+
+  /**
+   * Initialize the helper and process available signed request data.
+   *
+   * @param string|null $appId
+   * @param string|null $appSecret
+   */
+  public function __construct($appId = null, $appSecret = null)
+  {
+    $this->appId = FacebookSession::_getTargetAppId($appId);
+    $this->appSecret = FacebookSession::_getTargetAppSecret($appSecret);
+
+    $this->instantiateSignedRequest();
+  }
+
+  /**
+   * Instantiates a new SignedRequest entity.
+   *
+   * @param string|null
+   */
+  public function instantiateSignedRequest($rawSignedRequest = null)
+  {
+    $rawSignedRequest = $rawSignedRequest ?: $this->getRawSignedRequest();
+
+    if (!$rawSignedRequest) {
+      return;
+    }
+
+    $this->signedRequest = new SignedRequest($rawSignedRequest, $this->state, $this->appSecret);
+  }
+
+  /**
+   * Instantiates a FacebookSession from the signed request from input.
+   *
+   * @return FacebookSession|null
+   */
+  public function getSession()
+  {
+    if ($this->signedRequest && $this->signedRequest->hasOAuthData()) {
+      return FacebookSession::newSessionFromSignedRequest($this->signedRequest);
+    }
+    return null;
+  }
+
+  /**
+   * Returns the SignedRequest entity.
+   *
+   * @return \Facebook\Entities\SignedRequest|null
+   */
+  public function getSignedRequest()
+  {
+    return $this->signedRequest;
+  }
+
+  /**
+   * Returns the user_id if available.
+   *
+   * @return string|null
+   */
+  public function getUserId()
+  {
+    return $this->signedRequest ? $this->signedRequest->getUserId() : null;
+  }
+
+  /**
+   * Get raw signed request from input.
+   *
+   * @return string|null
+   */
+  abstract public function getRawSignedRequest();
+
+  /**
+   * Get raw signed request from GET input.
+   *
+   * @return string|null
+   */
+  public function getRawSignedRequestFromGet()
+  {
+    if (isset($_GET['signed_request'])) {
+      return $_GET['signed_request'];
+    }
+
+    return null;
+  }
+
+  /**
+   * Get raw signed request from POST input.
+   *
+   * @return string|null
+   */
+  public function getRawSignedRequestFromPost()
+  {
+    if (isset($_POST['signed_request'])) {
+      return $_POST['signed_request'];
+    }
+
+    return null;
+  }
+
+  /**
+   * Get raw signed request from cookie set from the Javascript SDK.
+   *
+   * @return string|null
+   */
+  public function getRawSignedRequestFromCookie()
+  {
+    if (isset($_COOKIE['fbsr_' . $this->appId])) {
+      return $_COOKIE['fbsr_' . $this->appId];
+    }
+    return null;
+  }
+
+}

+ 33 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/FacebookThrottleException.php

@@ -0,0 +1,33 @@
+<?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;
+
+/**
+ * Class FacebookThrottleException
+ * @package Facebook
+ */
+class FacebookThrottleException extends FacebookRequestException
+{
+
+}

+ 173 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/GraphAlbum.php

@@ -0,0 +1,173 @@
+<?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;
+
+/**
+ * Class GraphAlbum
+ * @package Facebook
+ * @author Daniele Grosso <daniele.grosso@gmail.com>
+ */
+
+class GraphAlbum extends GraphObject
+{
+    /**
+     * Returns the ID for the album.
+     *
+     * @return string|null
+     */
+    public function getId()
+    {
+        return $this->getProperty('id');
+    }
+
+    /**
+     * Returns whether the viewer can upload photos to this album.
+     *
+     * @return boolean|null
+     */
+    public function canUpload()
+    {
+        return $this->getProperty('can_upload');
+    }
+
+    /**
+     * Returns the number of photos in this album.
+     *
+     * @return int|null
+     */
+    public function getCount()
+    {
+        return $this->getProperty('count');
+    }
+
+    /**
+     * Returns the ID of the album's cover photo.
+     *
+     * @return string|null
+     */
+    public function getCoverPhoto()
+    {
+        return $this->getProperty('cover_photo');
+    }
+
+    /**
+     * Returns the time the album was initially created.
+     *
+     * @return \DateTime|null
+     */
+    public function getCreatedTime()
+    {
+        $value = $this->getProperty('created_time');
+        if ($value) {
+            return new \DateTime($value);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the time the album was updated.
+     *
+     * @return \DateTime|null
+     */
+    public function getUpdatedTime()
+    {
+        $value = $this->getProperty('updated_time');
+        if ($value) {
+            return new \DateTime($value);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the description of the album.
+     *
+     * @return string|null
+     */
+    public function getDescription()
+    {
+        return $this->getProperty('description');
+    }
+
+    /**
+     * Returns profile that created the album.
+     *
+     * @return GraphUser|null
+     */
+    public function getFrom()
+    {
+      return  $this->getProperty('from', GraphUser::className());
+    }
+
+    /**
+     * Returns a link to this album on Facebook.
+     *
+     * @return string|null
+     */
+    public function getLink()
+    {
+        return $this->getProperty('link');
+    }
+
+    /**
+     * Returns the textual location of the album.
+     *
+     * @return string|null
+     */
+    public function getLocation()
+    {
+        return $this->getProperty('location');
+    }
+
+    /**
+     * Returns the title of the album.
+     *
+     * @return string|null
+     */
+    public function getName()
+    {
+        return $this->getProperty('name');
+    }
+
+    /**
+     * Returns the privacy settings for the album.
+     *
+     * @return string|null
+     */
+    public function getPrivacy()
+    {
+        return $this->getProperty('privacy');
+    }
+
+    /**
+     * Returns the type of the album. enum{profile, mobile, wall, normal, album}
+     *
+     * @return string|null
+     */
+    public function getType()
+    {
+        return $this->getProperty('type');
+    }
+
+    //TODO: public function getPlace() that should return GraphPage
+}

+ 105 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/GraphLocation.php

@@ -0,0 +1,105 @@
+<?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;
+
+/**
+ * Class GraphLocation
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class GraphLocation extends GraphObject
+{
+
+  /**
+   * Returns the street component of the location
+   *
+   * @return string|null
+   */
+  public function getStreet()
+  {
+    return $this->getProperty('street');
+  }
+
+  /**
+   * Returns the city component of the location
+   *
+   * @return string|null
+   */
+  public function getCity()
+  {
+    return $this->getProperty('city');
+  }
+
+  /**
+   * Returns the state component of the location
+   *
+   * @return string|null
+   */
+  public function getState()
+  {
+    return $this->getProperty('state');
+  }
+
+  /**
+   * Returns the country component of the location
+   *
+   * @return string|null
+   */
+  public function getCountry()
+  {
+    return $this->getProperty('country');
+  }
+
+  /**
+   * Returns the zipcode component of the location
+   *
+   * @return string|null
+   */
+  public function getZip()
+  {
+    return $this->getProperty('zip');
+  }
+
+  /**
+   * Returns the latitude component of the location
+   *
+   * @return float|null
+   */
+  public function getLatitude()
+  {
+    return $this->getProperty('latitude');
+  }
+
+  /**
+   * Returns the street component of the location
+   *
+   * @return float|null
+   */
+  public function getLongitude()
+  {
+    return $this->getProperty('longitude');
+  }
+
+}

+ 171 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/GraphObject.php

@@ -0,0 +1,171 @@
+<?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;
+
+/**
+ * Class GraphObject
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class GraphObject
+{
+
+  /**
+   * @var array - Holds the raw associative data for this object
+   */
+  protected $backingData;
+
+  /**
+   * Creates a GraphObject using the data provided.
+   *
+   * @param array $raw
+   */
+  public function __construct($raw)
+  {
+    if ($raw instanceof \stdClass) {
+      $raw = get_object_vars($raw);
+    }
+    $this->backingData = $raw;
+
+    if (isset($this->backingData['data']) && count($this->backingData) === 1) {
+      if ($this->backingData['data'] instanceof \stdClass) {
+        $this->backingData = get_object_vars($this->backingData['data']);
+      } else {
+        $this->backingData = $this->backingData['data'];
+      }
+    }
+  }
+
+  /**
+   * cast - Return a new instance of a FacebookGraphObject subclass for this
+   *   objects underlying data.
+   *
+   * @param string $type The GraphObject subclass to cast to
+   *
+   * @return GraphObject
+   *
+   * @throws FacebookSDKException
+   */
+  public function cast($type)
+  {
+    if ($this instanceof $type) {
+      return $this;
+    }
+    if (is_subclass_of($type, GraphObject::className())) {
+      return new $type($this->backingData);
+    } else {
+      throw new FacebookSDKException(
+        'Cannot cast to an object that is not a GraphObject subclass', 620
+      );
+    }
+  }
+
+  /**
+   * asArray - Return a key-value associative array for the given graph object.
+   *
+   * @return array
+   */
+  public function asArray()
+  {
+    return $this->backingData;
+  }
+
+  /**
+   * getProperty - Gets the value of the named property for this graph object,
+   *   cast to the appropriate subclass type if provided.
+   *
+   * @param string $name The property to retrieve
+   * @param string $type The subclass of GraphObject, optionally
+   *
+   * @return mixed
+   */
+  public function getProperty($name, $type = 'Facebook\GraphObject')
+  {
+    if (isset($this->backingData[$name])) {
+      $value = $this->backingData[$name];
+      if (is_scalar($value)) {
+        return $value;
+      } else {
+        return (new GraphObject($value))->cast($type);
+      }
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * getPropertyAsArray - Get the list value of a named property for this graph
+   *   object, where each item has been cast to the appropriate subclass type
+   *   if provided.
+   *
+   * Calling this for a property that is not an array, the behavior
+   *   is undefined, so don’t do this.
+   *
+   * @param string $name The property to retrieve
+   * @param string $type The subclass of GraphObject, optionally
+   *
+   * @return array
+   */
+  public function getPropertyAsArray($name, $type = 'Facebook\GraphObject')
+  {
+    $target = array();
+    if (isset($this->backingData[$name]['data'])) {
+      $target = $this->backingData[$name]['data'];
+    } else if (isset($this->backingData[$name])
+      && !is_scalar($this->backingData[$name])) {
+      $target = $this->backingData[$name];
+    }
+    $out = array();
+    foreach ($target as $key => $value) {
+      if (is_scalar($value)) {
+        $out[$key] = $value;
+      } else {
+        $out[$key] = (new GraphObject($value))->cast($type);
+      }
+    }
+    return $out;
+  }
+
+  /**
+   * getPropertyNames - Returns a list of all properties set on the object.
+   *
+   * @return array
+   */
+  public function getPropertyNames()
+  {
+    return array_keys($this->backingData);
+  }
+
+  /**
+   * Returns the string class name of the GraphObject or subclass.
+   *
+   * @return string
+   */
+  public static function className()
+  {
+    return get_called_class();
+  }
+
+}

+ 64 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/GraphPage.php

@@ -0,0 +1,64 @@
+<?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;
+
+/**
+ * Class GraphPage
+ * @package Facebook
+ * @author Artur Luiz <artur@arturluiz.com.br>
+ */
+class GraphPage extends GraphObject
+{
+
+  /**
+   * Returns the ID for the user's page as a string if present.
+   *
+   * @return string|null
+   */
+  public function getId()
+  {
+    return $this->getProperty('id');
+  }
+
+  /**
+   * Returns the Category for the user's page as a string if present.
+   *
+   * @return string|null
+   */
+  public function getCategory()
+  {
+    return $this->getProperty('category');
+  }
+
+  /**
+   * Returns the Name of the user's page as a string if present.
+   *
+   * @return string|null
+   */
+  public function getName()
+  {
+    return $this->getProperty('name');
+  }
+
+}

+ 115 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/GraphSessionInfo.php

@@ -0,0 +1,115 @@
+<?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;
+
+/**
+ * Class GraphSessionInfo
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class GraphSessionInfo extends GraphObject
+{
+
+  /**
+   * Returns the application id the token was issued for.
+   *
+   * @return string|null
+   */
+  public function getAppId()
+  {
+    return $this->getProperty('app_id');
+  }
+
+  /**
+   * Returns the application name the token was issued for.
+   *
+   * @return string|null
+   */
+  public function getApplication()
+  {
+    return $this->getProperty('application');
+  }
+
+  /**
+   * Returns the date & time that the token expires.
+   *
+   * @return \DateTime|null
+   */
+  public function getExpiresAt()
+  {
+    $stamp = $this->getProperty('expires_at');
+    if ($stamp) {
+      return (new \DateTime())->setTimestamp($stamp);
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * Returns whether the token is valid.
+   *
+   * @return boolean
+   */
+  public function isValid()
+  {
+    return $this->getProperty('is_valid');
+  }
+
+  /**
+   * Returns the date & time the token was issued at.
+   *
+   * @return \DateTime|null
+   */
+  public function getIssuedAt()
+  {
+    $stamp = $this->getProperty('issued_at');
+    if ($stamp) {
+      return (new \DateTime())->setTimestamp($stamp);
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * Returns the scope permissions associated with the token.
+   *
+   * @return array
+   */
+  public function getScopes()
+  {
+    return $this->getPropertyAsArray('scopes');
+  }
+
+  /**
+   * Returns the login id of the user associated with the token.
+   *
+   * @return string|null
+   */
+  public function getId()
+  {
+    return $this->getProperty('user_id');
+  }
+
+}

+ 135 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/GraphUser.php

@@ -0,0 +1,135 @@
+<?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;
+
+/**
+ * Class GraphUser
+ * @package Facebook
+ * @author Fosco Marotto <fjm@fb.com>
+ * @author David Poll <depoll@fb.com>
+ */
+class GraphUser extends GraphObject
+{
+
+  /**
+   * Returns the ID for the user as a string if present.
+   *
+   * @return string|null
+   */
+  public function getId()
+  {
+    return $this->getProperty('id');
+  }
+
+  /**
+   * Returns the name for the user as a string if present.
+   *
+   * @return string|null
+   */
+  public function getName()
+  {
+    return $this->getProperty('name');
+  }
+  
+  public function getEmail()
+  {
+    return $this->getProperty('email');
+  }
+
+  /**
+   * Returns the first name for the user as a string if present.
+   *
+   * @return string|null
+   */
+  public function getFirstName()
+  {
+    return $this->getProperty('first_name');
+  }
+
+  /**
+   * Returns the middle name for the user as a string if present.
+   *
+   * @return string|null
+   */
+  public function getMiddleName()
+  {
+    return $this->getProperty('middle_name');
+  }
+
+  /**
+   * Returns the last name for the user as a string if present.
+   *
+   * @return string|null
+   */
+  public function getLastName()
+  {
+    return $this->getProperty('last_name');
+  }
+  
+  /**
+   * Returns the gender for the user as a string if present.
+   *
+   * @return string|null
+   */
+  public function getGender()
+  {
+    return $this->getProperty('gender');
+  }
+
+  /**
+   * Returns the Facebook URL for the user as a string if available.
+   *
+   * @return string|null
+   */
+  public function getLink()
+  {
+    return $this->getProperty('link');
+  }
+
+  /**
+   * Returns the users birthday, if available.
+   *
+   * @return \DateTime|null
+   */
+  public function getBirthday()
+  {
+    $value = $this->getProperty('birthday');
+    if ($value) {
+      return new \DateTime($value);
+    }
+    return null;
+  }
+
+  /**
+   * Returns the current location of the user as a FacebookGraphLocation
+   *   if available.
+   *
+   * @return GraphLocation|null
+   */
+  public function getLocation()
+  {
+    return $this->getProperty('location', GraphLocation::className());
+  }
+
+}

+ 84 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/GraphUserPage.php

@@ -0,0 +1,84 @@
+<?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;
+
+/**
+ * Class GraphUserPage
+ * @package Facebook
+ * @author Artur Luiz <artur@arturluiz.com.br>
+ */
+class GraphUserPage extends GraphObject
+{
+
+  /**
+   * Returns the ID for the user's page as a string if present.
+   *
+   * @return string|null
+   */
+  public function getId()
+  {
+    return $this->getProperty('id');
+  }
+
+  /**
+   * Returns the Category for the user's page as a string if present.
+   *
+   * @return string|null
+   */
+  public function getCategory()
+  {
+    return $this->getProperty('category');
+  }
+
+  /**
+   * Returns the Name of the user's page as a string if present.
+   *
+   * @return string|null
+   */
+  public function getName()
+  {
+    return $this->getProperty('name');
+  }
+
+  /**
+   * Returns the Access Token used to access the user's page as a string if present.
+   *
+   * @return string|null
+   */
+  public function getAccessToken()
+  {
+    return $this->getProperty('access_token');
+  }
+  
+  /**
+   * Returns the Permissions for the user's page as an array if present.
+   *
+   * @return array|null
+   */
+  public function getPermissions()
+  {
+    return $this->getProperty('perms');
+  }
+
+}

+ 129 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurl.php

@@ -0,0 +1,129 @@
+<?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\HttpClients;
+
+/**
+ * Class FacebookCurl
+ * Abstraction for the procedural curl elements so that curl can be mocked
+ * and the implementation can be tested.
+ * @package Facebook
+ */
+class FacebookCurl
+{
+
+  /**
+   * @var resource Curl resource instance
+   */
+  protected $curl;
+
+  /**
+   * Make a new curl reference instance
+   */
+  public function init()
+  {
+    $this->curl = curl_init();
+  }
+
+  /**
+   * Set a curl option
+   *
+   * @param $key
+   * @param $value
+   */
+  public function setopt($key, $value)
+  {
+    curl_setopt($this->curl, $key, $value);
+  }
+
+  /**
+   * Set an array of options to a curl resource
+   *
+   * @param array $options
+   */
+  public function setopt_array(array $options)
+  {
+    curl_setopt_array($this->curl, $options);
+  }
+
+  /**
+   * Send a curl request
+   *
+   * @return mixed
+   */
+  public function exec()
+  {
+    return curl_exec($this->curl);
+  }
+
+  /**
+   * Return the curl error number
+   *
+   * @return int
+   */
+  public function errno()
+  {
+    return curl_errno($this->curl);
+  }
+
+  /**
+   * Return the curl error message
+   *
+   * @return string
+   */
+  public function error()
+  {
+    return curl_error($this->curl);
+  }
+
+  /**
+   * Get info from a curl reference
+   *
+   * @param $type
+   *
+   * @return mixed
+   */
+  public function getinfo($type)
+  {
+    return curl_getinfo($this->curl, $type);
+  }
+
+  /**
+   * Get the currently installed curl version
+   *
+   * @return array
+   */
+  public function version()
+  {
+    return curl_version();
+  }
+
+  /**
+   * Close the resource connection to curl
+   */
+  public function close()
+  {
+    curl_close($this->curl);
+  }
+
+}

+ 329 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.php

@@ -0,0 +1,329 @@
+<?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\HttpClients;
+
+use Facebook\FacebookSDKException;
+
+/**
+ * Class FacebookCurlHttpClient
+ * @package Facebook
+ */
+class FacebookCurlHttpClient implements FacebookHttpable
+{
+
+  /**
+   * @var array The headers to be sent with the request
+   */
+  protected $requestHeaders = array();
+
+  /**
+   * @var array The headers received from the response
+   */
+  protected $responseHeaders = array();
+
+  /**
+   * @var int The HTTP status code returned from the server
+   */
+  protected $responseHttpStatusCode = 0;
+
+  /**
+   * @var string The client error message
+   */
+  protected $curlErrorMessage = '';
+
+  /**
+   * @var int The curl client error code
+   */
+  protected $curlErrorCode = 0;
+
+  /**
+   * @var string|boolean The raw response from the server
+   */
+  protected $rawResponse;
+
+  /**
+   * @var FacebookCurl Procedural curl as object
+   */
+  protected static $facebookCurl;
+
+  /**
+   * @var boolean If IPv6 should be disabled
+   */
+  protected static $disableIPv6;
+
+  /**
+   * @const Curl Version which is unaffected by the proxy header length error.
+   */
+  const CURL_PROXY_QUIRK_VER = 0x071E00;
+
+  /**
+   * @const "Connection Established" header text
+   */
+  const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n";
+
+  /**
+   * @param FacebookCurl|null Procedural curl as object
+   */
+  public function __construct(FacebookCurl $facebookCurl = null)
+  {
+    self::$facebookCurl = $facebookCurl ?: new FacebookCurl();
+    self::$disableIPv6 = self::$disableIPv6 ?: false;
+  }
+
+  /**
+   * Disable IPv6 resolution
+   */
+  public function disableIPv6()
+  {
+    self::$disableIPv6 = true;
+  }
+
+  /**
+   * The headers we want to send with the request
+   *
+   * @param string $key
+   * @param string $value
+   */
+  public function addRequestHeader($key, $value)
+  {
+    $this->requestHeaders[$key] = $value;
+  }
+
+  /**
+   * The headers returned in the response
+   *
+   * @return array
+   */
+  public function getResponseHeaders()
+  {
+    return $this->responseHeaders;
+  }
+
+  /**
+   * The HTTP status response code
+   *
+   * @return int
+   */
+  public function getResponseHttpStatusCode()
+  {
+    return $this->responseHttpStatusCode;
+  }
+
+  /**
+   * Sends a request to the server
+   *
+   * @param string $url The endpoint to send the request to
+   * @param string $method The request method
+   * @param array  $parameters The key value pairs to be sent in the body
+   *
+   * @return string Raw response from the server
+   *
+   * @throws \Facebook\FacebookSDKException
+   */
+  public function send($url, $method = 'GET', $parameters = array())
+  {
+    $this->openConnection($url, $method, $parameters);
+    $this->tryToSendRequest();
+
+    if ($this->curlErrorCode) {
+      throw new FacebookSDKException($this->curlErrorMessage, $this->curlErrorCode);
+    }
+
+    // Separate the raw headers from the raw body
+    list($rawHeaders, $rawBody) = $this->extractResponseHeadersAndBody();
+
+    $this->responseHeaders = self::headersToArray($rawHeaders);
+
+    $this->closeConnection();
+
+    return $rawBody;
+  }
+
+  /**
+   * Opens a new curl connection
+   *
+   * @param string $url The endpoint to send the request to
+   * @param string $method The request method
+   * @param array  $parameters The key value pairs to be sent in the body
+   */
+  public function openConnection($url, $method = 'GET', $parameters = array())
+  {
+    $options = array(
+      CURLOPT_URL            => $url,
+      CURLOPT_CONNECTTIMEOUT => 10,
+      CURLOPT_TIMEOUT        => 60,
+      CURLOPT_RETURNTRANSFER => true, // Follow 301 redirects
+      CURLOPT_HEADER         => true, // Enable header processing
+      CURLOPT_SSL_VERIFYHOST => 2,
+      CURLOPT_SSL_VERIFYPEER => true,
+      CURLOPT_CAINFO         => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',
+    );
+
+    if ($method !== "GET") {
+      $options[CURLOPT_POSTFIELDS] = $parameters;
+    }
+    if ($method === 'DELETE' || $method === 'PUT') {
+      $options[CURLOPT_CUSTOMREQUEST] = $method;
+    }
+
+    if (!empty($this->requestHeaders)) {
+      $options[CURLOPT_HTTPHEADER] = $this->compileRequestHeaders();
+    }
+
+    if (self::$disableIPv6) {
+      $options[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
+    }
+
+    self::$facebookCurl->init();
+    self::$facebookCurl->setopt_array($options);
+  }
+
+  /**
+   * Closes an existing curl connection
+   */
+  public function closeConnection()
+  {
+    self::$facebookCurl->close();
+  }
+
+  /**
+   * Try to send the request
+   */
+  public function tryToSendRequest()
+  {
+    $this->sendRequest();
+    $this->curlErrorMessage = self::$facebookCurl->error();
+    $this->curlErrorCode = self::$facebookCurl->errno();
+    $this->responseHttpStatusCode = self::$facebookCurl->getinfo(CURLINFO_HTTP_CODE);
+  }
+
+  /**
+   * Send the request and get the raw response from curl
+   */
+  public function sendRequest()
+  {
+    $this->rawResponse = self::$facebookCurl->exec();
+  }
+
+  /**
+   * Compiles the request headers into a curl-friendly format
+   *
+   * @return array
+   */
+  public function compileRequestHeaders()
+  {
+    $return = array();
+
+    foreach ($this->requestHeaders as $key => $value) {
+      $return[] = $key . ': ' . $value;
+    }
+
+    return $return;
+  }
+
+  /**
+   * Extracts the headers and the body into a two-part array
+   *
+   * @return array
+   */
+  public function extractResponseHeadersAndBody()
+  {
+    $headerSize = self::getHeaderSize();
+
+    $rawHeaders = mb_substr($this->rawResponse, 0, $headerSize);
+    $rawBody = mb_substr($this->rawResponse, $headerSize);
+
+    return array(trim($rawHeaders), trim($rawBody));
+  }
+
+  /**
+   * Converts raw header responses into an array
+   *
+   * @param string $rawHeaders
+   *
+   * @return array
+   */
+  public static function headersToArray($rawHeaders)
+  {
+    $headers = array();
+
+    // Normalize line breaks
+    $rawHeaders = str_replace("\r\n", "\n", $rawHeaders);
+
+    // There will be multiple headers if a 301 was followed
+    // or a proxy was followed, etc
+    $headerCollection = explode("\n\n", trim($rawHeaders));
+    // We just want the last response (at the end)
+    $rawHeader = array_pop($headerCollection);
+
+    $headerComponents = explode("\n", $rawHeader);
+    foreach ($headerComponents as $line) {
+      if (strpos($line, ': ') === false) {
+        $headers['http_code'] = $line;
+      } else {
+        list ($key, $value) = explode(': ', $line);
+        $headers[$key] = $value;
+      }
+    }
+
+    return $headers;
+  }
+
+  /**
+   * Return proper header size
+   *
+   * @return integer
+   */
+  private function getHeaderSize()
+  {
+    $headerSize = self::$facebookCurl->getinfo(CURLINFO_HEADER_SIZE);
+    // This corrects a Curl bug where header size does not account
+    // for additional Proxy headers.
+    if ( self::needsCurlProxyFix() ) {
+      // Additional way to calculate the request body size.
+      if (preg_match('/Content-Length: (\d+)/', $this->rawResponse, $m)) {
+          $headerSize = mb_strlen($this->rawResponse) - $m[1];
+      } elseif (stripos($this->rawResponse, self::CONNECTION_ESTABLISHED) !== false) {
+          $headerSize += mb_strlen(self::CONNECTION_ESTABLISHED);
+      }
+    }
+
+    return $headerSize;
+  }
+
+  /**
+   * Detect versions of Curl which report incorrect header lengths when
+   * using Proxies.
+   *
+   * @return boolean
+   */
+  private static function needsCurlProxyFix()
+  {
+    $ver = self::$facebookCurl->version();
+    $version = $ver['version_number'];
+
+    return $version < self::CURL_PROXY_QUIRK_VER;
+  }
+
+}

+ 134 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.php

@@ -0,0 +1,134 @@
+<?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\HttpClients;
+
+use Facebook\FacebookSDKException;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\AdapterException;
+use GuzzleHttp\Exception\RequestException;
+
+class FacebookGuzzleHttpClient implements FacebookHttpable {
+
+  /**
+   * @var array The headers to be sent with the request
+   */
+  protected $requestHeaders = array();
+
+  /**
+   * @var array The headers received from the response
+   */
+  protected $responseHeaders = array();
+
+  /**
+   * @var int The HTTP status code returned from the server
+   */
+  protected $responseHttpStatusCode = 0;
+
+  /**
+   * @var \GuzzleHttp\Client The Guzzle client
+   */
+  protected static $guzzleClient;
+
+  /**
+   * @param \GuzzleHttp\Client|null The Guzzle client
+   */
+  public function __construct(Client $guzzleClient = null)
+  {
+    self::$guzzleClient = $guzzleClient ?: new Client();
+  }
+
+  /**
+   * The headers we want to send with the request
+   *
+   * @param string $key
+   * @param string $value
+   */
+  public function addRequestHeader($key, $value)
+  {
+    $this->requestHeaders[$key] = $value;
+  }
+
+  /**
+   * The headers returned in the response
+   *
+   * @return array
+   */
+  public function getResponseHeaders()
+  {
+    return $this->responseHeaders;
+  }
+
+  /**
+   * The HTTP status response code
+   *
+   * @return int
+   */
+  public function getResponseHttpStatusCode()
+  {
+    return $this->responseHttpStatusCode;
+  }
+
+  /**
+   * Sends a request to the server
+   *
+   * @param string $url The endpoint to send the request to
+   * @param string $method The request method
+   * @param array  $parameters The key value pairs to be sent in the body
+   *
+   * @return string Raw response from the server
+   *
+   * @throws \Facebook\FacebookSDKException
+   */
+  public function send($url, $method = 'GET', $parameters = array())
+  {
+    $options = array();
+    if ($parameters) {
+      $options = array('body' => $parameters);
+    }
+
+    $options['verify'] = __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem';
+
+    $request = self::$guzzleClient->createRequest($method, $url, $options);
+
+    foreach($this->requestHeaders as $k => $v) {
+      $request->setHeader($k, $v);
+    }
+
+    try {
+      $rawResponse = self::$guzzleClient->send($request);
+    } catch (RequestException $e) {
+      if ($e->getPrevious() instanceof AdapterException) {
+        throw new FacebookSDKException($e->getMessage(), $e->getCode());
+      }
+      $rawResponse = $e->getResponse();
+    }
+
+    $this->responseHttpStatusCode = $rawResponse->getStatusCode();
+    $this->responseHeaders = $rawResponse->getHeaders();
+
+    return $rawResponse->getBody();
+  }
+
+}

+ 68 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookHttpable.php

@@ -0,0 +1,68 @@
+<?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\HttpClients;
+
+/**
+ * Interface FacebookHttpable
+ * @package Facebook
+ */
+interface FacebookHttpable
+{
+
+  /**
+   * The headers we want to send with the request
+   *
+   * @param string $key
+   * @param string $value
+   */
+  public function addRequestHeader($key, $value);
+
+  /**
+   * The headers returned in the response
+   *
+   * @return array
+   */
+  public function getResponseHeaders();
+
+  /**
+   * The HTTP status response code
+   *
+   * @return int
+   */
+  public function getResponseHttpStatusCode();
+
+  /**
+   * Sends a request to the server
+   *
+   * @param string $url The endpoint to send the request to
+   * @param string $method The request method
+   * @param array  $parameters The key value pairs to be sent in the body
+   *
+   * @return string Raw response from the server
+   *
+   * @throws \Facebook\FacebookSDKException
+   */
+  public function send($url, $method = 'GET', $parameters = array());
+
+}

+ 79 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookStream.php

@@ -0,0 +1,79 @@
+<?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\HttpClients;
+
+/**
+ * Class FacebookStream
+ * Abstraction for the procedural stream elements so that the functions can be
+ * mocked and the implementation can be tested.
+ * @package Facebook
+ */
+class FacebookStream
+{
+
+  /**
+   * @var resource Context stream resource instance
+   */
+  protected $stream;
+
+  /**
+   * @var array Response headers from the stream wrapper
+   */
+  protected $responseHeaders;
+
+  /**
+   * Make a new context stream reference instance
+   *
+   * @param array $options
+   */
+  public function streamContextCreate(array $options)
+  {
+    $this->stream = stream_context_create($options);
+  }
+
+  /**
+   * The response headers from the stream wrapper
+   *
+   * @return array|null
+   */
+  public function getResponseHeaders()
+  {
+    return $this->responseHeaders;
+  }
+
+  /**
+   * Send a stream wrapped request
+   *
+   * @param string $url
+   *
+   * @return mixed
+   */
+  public function fileGetContents($url)
+  {
+    $rawResponse = file_get_contents($url, false, $this->stream);
+    $this->responseHeaders = $http_response_header;
+    return $rawResponse;
+  }
+
+}

+ 190 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.php

@@ -0,0 +1,190 @@
+<?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\HttpClients;
+
+use Facebook\FacebookSDKException;
+
+class FacebookStreamHttpClient implements FacebookHttpable {
+
+  /**
+   * @var array The headers to be sent with the request
+   */
+  protected $requestHeaders = array();
+
+  /**
+   * @var array The headers received from the response
+   */
+  protected $responseHeaders = array();
+
+  /**
+   * @var int The HTTP status code returned from the server
+   */
+  protected $responseHttpStatusCode = 0;
+
+  /**
+   * @var FacebookStream Procedural stream wrapper as object
+   */
+  protected static $facebookStream;
+
+  /**
+   * @param FacebookStream|null Procedural stream wrapper as object
+   */
+  public function __construct(FacebookStream $facebookStream = null)
+  {
+    self::$facebookStream = $facebookStream ?: new FacebookStream();
+  }
+
+  /**
+   * The headers we want to send with the request
+   *
+   * @param string $key
+   * @param string $value
+   */
+  public function addRequestHeader($key, $value)
+  {
+    $this->requestHeaders[$key] = $value;
+  }
+
+  /**
+   * The headers returned in the response
+   *
+   * @return array
+   */
+  public function getResponseHeaders()
+  {
+    return $this->responseHeaders;
+  }
+
+  /**
+   * The HTTP status response code
+   *
+   * @return int
+   */
+  public function getResponseHttpStatusCode()
+  {
+    return $this->responseHttpStatusCode;
+  }
+
+  /**
+   * Sends a request to the server
+   *
+   * @param string $url The endpoint to send the request to
+   * @param string $method The request method
+   * @param array  $parameters The key value pairs to be sent in the body
+   *
+   * @return string Raw response from the server
+   *
+   * @throws \Facebook\FacebookSDKException
+   */
+  public function send($url, $method = 'GET', $parameters = array())
+  {
+    $options = array(
+      'http' => array(
+        'method' => $method,
+        'timeout' => 60,
+        'ignore_errors' => true
+      ),
+      'ssl' => array(
+        'verify_peer' => true,
+        'verify_peer_name' => true,
+        'allow_self_signed' => true, // All root certificates are self-signed
+        'cafile' => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',
+      ),
+    );
+
+    if ($parameters) {
+      $options['http']['content'] = http_build_query($parameters, null, '&');
+
+      $this->addRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+    }
+
+    $options['http']['header'] = $this->compileHeader();
+
+    self::$facebookStream->streamContextCreate($options);
+    $rawResponse = self::$facebookStream->fileGetContents($url);
+    $rawHeaders = self::$facebookStream->getResponseHeaders();
+
+    if ($rawResponse === false || !$rawHeaders) {
+      throw new FacebookSDKException('Stream returned an empty response', 660);
+    }
+
+    $this->responseHeaders = self::formatHeadersToArray($rawHeaders);
+    $this->responseHttpStatusCode = self::getStatusCodeFromHeader($this->responseHeaders['http_code']);
+
+    return $rawResponse;
+  }
+
+  /**
+   * Formats the headers for use in the stream wrapper
+   *
+   * @return string
+   */
+  public function compileHeader()
+  {
+    $header = [];
+    foreach($this->requestHeaders as $k => $v) {
+      $header[] = $k . ': ' . $v;
+    }
+
+    return implode("\r\n", $header);
+  }
+
+  /**
+   * Converts array of headers returned from the wrapper into
+   * something standard
+   *
+   * @param array $rawHeaders
+   *
+   * @return array
+   */
+  public static function formatHeadersToArray(array $rawHeaders)
+  {
+    $headers = array();
+
+    foreach ($rawHeaders as $line) {
+      if (strpos($line, ':') === false) {
+        $headers['http_code'] = $line;
+      } else {
+        list ($key, $value) = explode(': ', $line);
+        $headers[$key] = $value;
+      }
+    }
+
+    return $headers;
+  }
+
+  /**
+   * Pulls out the HTTP status code from a response header
+   *
+   * @param string $header
+   *
+   * @return int
+   */
+  public static function getStatusCodeFromHeader($header)
+  {
+    preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $header, $match);
+    return (int) $match[1];
+  }
+
+}

+ 23 - 0
main/auth/external_login/facebook-php-sdk/src/Facebook/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pem

@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----

+ 85 - 44
main/auth/external_login/facebook.inc.php

@@ -1,46 +1,71 @@
 <?php
-
 /**
- * Licence: GPL 
+ * Licence: GPL
  * Please contact CBlue regarding any licences issues.
  * Author: noel@cblue.be
  *  Copyright: CBlue SPRL, 20XX
  *
  * External login module : FACEBOOK
  *
- * This files provides the facebook_connect()  and facebook_get_url functions
+ * This files provides the facebookConnect()  and facebook_get_url functions
  * Please edit the facebook.conf.php file to adapt it to your fb application parameter
  * */
+
 require_once dirname(__FILE__) . '/../../inc/global.inc.php';
 require_once dirname(__FILE__) . '/facebook.init.php';
-require_once dirname(__FILE__) . '/facebook-php-sdk/src/facebook.php';
+
+require_once dirname(__FILE__) . '/facebook-php-sdk/autoload.php';
+
+use Facebook\FacebookSession;
+use Facebook\FacebookRedirectLoginHelper;
+use Facebook\FacebookRequest;
+use Facebook\FacebookResponse;
+use Facebook\FacebookSDKException;
+use Facebook\FacebookRequestException;
+use Facebook\FacebookAuthorizationException;
+use Facebook\GraphObject;
+use Facebook\Entities\AccessToken;
+use Facebook\HttpClients\FacebookCurlHttpClient;
+use Facebook\HttpClients\FacebookHttpable;
+
 require_once dirname(__FILE__) . '/functions.inc.php';
 
+FacebookSession::setDefaultApplication( $facebook_config['appId'],$facebook_config['secret']);
+
 /**
  * This function connect to facebook and retrieves the user info
  * If user does not exist in chamilo, it creates it and logs in
  * If user already exists, it updates his info
- * */
-function facebook_connect() {
-    global $facebook;
-    // See if there is a user from a cookie
-    $user = $facebook->getUser();
-    if ($user) {
-        try {
-            //Gets facebook user info
-            $fu = $facebook->api('/me');
-            $username = $fu['username'];
-            if (api_get_setting('login_is_email') == 'true' || empty($fu['username'])) {
-                $username = change_to_valid_chamilo_login($fu['email']);
-            }
+ */
+function facebookConnect()
+{
+    global $facebook_config;
+    global $helper;
+
+    try {
+        $helper = new FacebookRedirectLoginHelper($facebook_config['return_url']);
+        $session = $helper->getSessionFromRedirect();
+        // see if we have a session
+        if (isset($session)) {
+            // graph api request for user data
+            $request = new FacebookRequest($session, 'GET', '/me');
+            $response = $request->execute();
+            // get response
+            $graphObject = $response->getGraphObject();
+            $username = changeToValidChamiloLogin($graphObject->getProperty('email'));
+            $email = $graphObject->getProperty('email');
+            $locale = $graphObject->getProperty('locale');
+            $language = getLanguageForFacebook($locale);
+            if(!$language)$language='pl_PL';
+
             //Checks if user already exists in chamilo
             $u = array(
-                'firstname' => $fu['first_name'],
-                'lastname' => $fu['last_name'],
+                'firstname' => $graphObject->getProperty('first_name'),
+                'lastname' => $graphObject->getProperty('last_name'),
                 'status' => STUDENT,
-                'email' => $fu['email'],
+                'email' => $graphObject->getProperty('email'),
                 'username' => $username,
-                'language' => 'french',
+                'language' => $language,
                 'password' => DEFAULT_PASSWORD,
                 'auth_source' => 'facebook',
                 //'courses' => $user_info['courses'],
@@ -49,9 +74,9 @@ function facebook_connect() {
                 //'manager' => $user_info['manager'],
                 'extra' => array()
             );
-            $cu = api_get_user_info_from_username($username);
-            $chamilo_uinfo = api_get_user_info_from_username($username);
-            if ($chamilo_uinfo === false) {
+
+            $chamiloUinfo = api_get_user_info_from_email($email);
+            if ($chamiloUinfo === false) {
                 //we have to create the user
                 $chamilo_uid = external_add_user($u);
                 if ($chamilo_uid !== false) {
@@ -64,7 +89,7 @@ function facebook_connect() {
                     return false;
                 }
             } else {//User already exists, update info and login
-                $chamilo_uid = $chamilo_uinfo['user_id'];
+                $chamilo_uid = $chamiloUinfo['user_id'];
                 $u['user_id'] = $chamilo_uid;
                 external_update_user($u);
                 $_user['user_id'] = $chamilo_uid;
@@ -73,34 +98,50 @@ function facebook_connect() {
                 header('Location:' . api_get_path(WEB_PATH));
                 exit();
             }
-        } catch (FacebookApiException $e) {
-            echo '<pre>' . htmlspecialchars(print_r($e, true)) . '</pre>';
-            $user = null;
         }
+    } catch( FacebookRequestException $ex ) {
+        echo $ex;
+    } catch( Exception $ex ) {
+        // When validation fails or other local issues
     }
 }
 
 /**
  * Get facebook login url for the platform
- * */
-function facebook_get_login_url() {
-    global $facebook, $facebook_config;
-
-    $login_url = $facebook->getLoginUrl(
-            array(
-                'scope' => 'email,publish_stream',
-                'redirect_uri' => $facebook_config['return_url']
-            )
-    );
-    return $login_url;
+ * @return mixed
+ */
+function facebookGetLoginUrl()
+{
+    global $facebook_config;
+    $helper = new FacebookRedirectLoginHelper($facebook_config['return_url']);
+    $loginUrl =   $helper->getLoginUrl(array(
+        'scope' => 'email'));
+    return $loginUrl;
 }
 
 /**
- * @input : a string
- * @return : a string containing valid chamilo login characters
  * Chamilo login only use characters lettres, des chiffres et les signes _ . -
- * */
-function change_to_valid_chamilo_login($in_txt) {
+ * return a string containing valid chamilo login characters
+ * @param $in_txt
+ * @return mixed
+ */
+function changeToValidChamiloLogin($in_txt)
+{
     return preg_replace("/[^a-zA-Z1-9_\-.]/", "_", $in_txt);
-    exit;
+}
+
+/**
+ * Get user language
+ * @param string $language
+ * @return bool
+ */
+function getLanguageForFacebook($language = 'en_US')
+{
+    $language = substr($language, 0, 2);
+    $sqlResult = Database::query("SELECT english_name FROM ".Database::get_main_table(TABLE_MAIN_LANGUAGE)." WHERE available = 1 AND isocode = '$language'");
+    if (Database::num_rows($sqlResult)) {
+        $result = Database::fetch_array($sqlResult);
+        return $result['english_name'];
+    }
+    return false;
 }

+ 5 - 10
main/auth/external_login/facebook.init.php

@@ -14,19 +14,14 @@
 /**
  * Facebook application setting
  * */
-require_once dirname(__FILE__) . '/facebook-php-sdk/src/facebook.php';
 
-global $facebook_config;
 
-//Loads the portal facebook settings
-$conf = dirname(__FILE__) . '../../inc/conf/auth.conf.php';
 
+
+//Loads the portal facebook settings
 /**
  * See facebook section of the auth.conf.php file
  */
-global $facebook;
-$facebook = new Facebook(array(
-            'appId' => $facebook_config['appId'],
-            'secret' => $facebook_config['secret']
-        ));
-require_once dirname(__FILE__) . '/facebook.inc.php';
+
+require_once dirname(__FILE__) . '/../../inc/conf/auth.conf.php';
+

BIN
plugin/add_facebook_login_button/img/cnx_fb.png


+ 1 - 2
plugin/add_facebook_login_button/index.php

@@ -1,11 +1,10 @@
 <?php
 // Show the FACEBOOK login button
-
 $_template['show_message']   = false;
 
 //if (api_is_anonymous() && api_get_setting('facebook_login_activate') == 'true') {
 if (api_is_anonymous()) {
-    require_once api_get_path(SYS_CODE_PATH)."auth/external_login/facebook.init.php";
+    require_once api_get_path(SYS_CODE_PATH)."auth/external_login/facebook.inc.php";
     $_template['show_message']   = true;
     // the default title
     $button_url = api_get_path(WEB_PLUGIN_PATH)."add_facebook_login_button/img/cnx_fb.png";

+ 1 - 1
plugin/add_facebook_login_button/plugin.php

@@ -17,7 +17,7 @@ $plugin_info['comment'] = "If Facebook authntification is activated, this plugin
 //the plugin version
 $plugin_info['version'] = '1.0';
 //the plugin author
-$plugin_info['author'] = 'Hubert Borderiou';
+$plugin_info['author'] = 'Konrad Banasiak, Hubert Borderiou';
 //the plugin configuration
 $form = new FormValidator('add_facebook_button_form');
 $form->addElement(

+ 3 - 5
plugin/add_facebook_login_button/template.tpl

@@ -1,7 +1,5 @@
 {% if add_facebook_login_button.show_message %}
-    <div class="well">
-        <a href="{{add_facebook_login_button.facebook_href_link}}">
-            <img src="{{add_facebook_login_button.facebook_button_url}}"/>
-        </a>
-    </div>
+<a href="{{add_facebook_login_button.facebook_href_link}}">
+    <img src="{{add_facebook_login_button.facebook_button_url}}" style="margin-left:15px; border-radius:0"/>
+</a>
 {% endif %}