18if (!function_exists(
'curl_init')) {
 
   19  throw new Exception(
'Facebook needs the CURL PHP extension.');
 
   21if (!function_exists(
'json_decode')) {
 
   22  throw new Exception(
'Facebook needs the JSON PHP extension.');
 
   47    if (isset(
$result[
'error_description'])) {
 
   49      $msg = 
$result[
'error_description'];
 
   50    } 
else if (isset(
$result[
'error']) && is_array(
$result[
'error'])) {
 
   52      $msg = 
$result[
'error'][
'message'];
 
   53    } 
else if (isset(
$result[
'error_msg'])) {
 
   57      $msg = 
'Unknown Error. Check getResult()';
 
   60    parent::__construct($msg, 
$code);
 
   79    if (isset($this->result[
'error'])) {
 
   80      $error = $this->result[
'error'];
 
   84      } 
else if (is_array(
$error)) {
 
   86        if (isset(
$error[
'type'])) {
 
  101    $str = $this->
getType() . 
': ';
 
  102    if ($this->code != 0) {
 
  103      $str .= $this->code . 
': ';
 
  134    CURLOPT_CONNECTTIMEOUT => 10,
 
  135    CURLOPT_RETURNTRANSFER => 
true,
 
  136    CURLOPT_TIMEOUT        => 60,
 
  137    CURLOPT_USERAGENT      => 
'facebook-php-3.2',
 
  154    'api'         => 
'https://api.facebook.com/',
 
  155    'api_video'   => 
'https://api-video.facebook.com/',
 
  156    'api_read'    => 
'https://api-read.facebook.com/',
 
  157    'graph'       => 
'https://graph.facebook.com/',
 
  158    'graph_video' => 
'https://graph-video.facebook.com/',
 
  159    'www'         => 
'https://www.facebook.com/',
 
  228    if (isset(
$config[
'fileUpload'])) {
 
  231    if (isset(
$config[
'trustForwarded']) && 
$config[
'trustForwarded']) {
 
  232      $this->trustForwarded = 
true;
 
  342    $this->accessToken = $access_token;
 
  356        $this->
getUrl(
'graph', 
'/oauth/access_token'),
 
  360          'grant_type' => 
'fb_exchange_token',
 
  371    if (empty($access_token_response)) {
 
  375    $response_params = array();
 
  376    parse_str($access_token_response, $response_params);
 
  378    if (!isset($response_params[
'access_token'])) {
 
  385      'access_token', $response_params[
'access_token']
 
  399    if ($this->accessToken !== 
null) {
 
  409    if ($user_access_token) {
 
  431    if ($signed_request) {
 
  433      if (array_key_exists(
'oauth_token', $signed_request)) {
 
  434        $access_token = $signed_request[
'oauth_token'];
 
  436        return $access_token;
 
  440      if (array_key_exists(
'code', $signed_request)) {
 
  441        $code = $signed_request[
'code'];
 
  451          return $access_token;
 
  468        return $access_token;
 
  490    if (!$this->signedRequest) {
 
  491      if (!empty($_REQUEST[
'signed_request'])) {
 
  493          $_REQUEST[
'signed_request']);
 
  509    if ($this->
user !== 
null) {
 
  529    if ($signed_request) {
 
  530      if (array_key_exists(
'user_id', $signed_request)) {
 
  531        $user = $signed_request[
'user_id'];
 
  555        !(
$user && $persisted_access_token == $access_token)) {
 
  585    if ($scopeParams && is_array($scopeParams)) {
 
  586      $params[
'scope'] = implode(
',', $scopeParams);
 
  594                    'redirect_uri' => $currentUrl, 
 
  595                    'state' => $this->state),
 
  633      'extern/login_status.php',
 
  639        'session_version' => 3,
 
  650    $args = func_get_args();
 
  651    if (is_array($args[0])) {
 
  654      return call_user_func_array(array($this, 
'_graph'), $args);
 
  668    return 'fbsr_'.$this->getAppId();
 
  679    return 'fbm_'.$this->getAppId();
 
  691    if (isset($_REQUEST[
'code'])) {
 
  692      if ($this->state !== 
null &&
 
  693          isset($_REQUEST[
'state']) &&
 
  694          $this->state === $_REQUEST[
'state']) {
 
  699        return $_REQUEST[
'code'];
 
  701        self::errorLog(
'CSRF state token does not match one provided. ' . $this->state . 
'!=' . $_REQUEST[
'state']);
 
  721      $user_info = $this->
api(
'/me');
 
  722      return $user_info[
'id'];
 
  745    if ($this->state === 
null) {
 
  746      $this->state = md5(uniqid(mt_rand(), 
true));
 
  768    if ($redirect_uri === 
null) {
 
  775      $access_token_response =
 
  777          $this->
getUrl(
'graph', 
'/oauth/access_token'),
 
  780                          'redirect_uri' => $redirect_uri,
 
  788    if (empty($access_token_response)) {
 
  792    $response_params = json_decode($access_token_response, 
true);
 
  793    if (!isset($response_params[
'access_token'])) {
 
  797    return $response_params[
'access_token'];
 
  811    $params[
'format'] = 
'json-strings';
 
  825    $method = strtolower(
$params[
'method']);
 
  826    if ($method === 
'auth.expiresession' ||
 
  827        $method === 
'auth.revokeauthorization') {
 
  843    if ($method == 
'POST' && preg_match(
"/^(\/)(.+)(\/)(videos)$/", 
$path)) {
 
  860    if (is_array($method) && empty(
$params)) {
 
  867      $domainKey = 
'graph_video';
 
  869      $domainKey = 
'graph';
 
  897    if (!isset(
$params[
'access_token'])) {
 
  903      if (!is_string($value)) {
 
  929      $opts[CURLOPT_POSTFIELDS] = 
$params;
 
  931      $opts[CURLOPT_POSTFIELDS] = http_build_query(
$params, 
null, 
'&');
 
  933    $opts[CURLOPT_URL] = 
$url;
 
  937    if (isset($opts[CURLOPT_HTTPHEADER])) {
 
  938      $existing_headers = $opts[CURLOPT_HTTPHEADER];
 
  939      $existing_headers[] = 
'Expect:';
 
  940      $opts[CURLOPT_HTTPHEADER] = $existing_headers;
 
  942      $opts[CURLOPT_HTTPHEADER] = array(
'Expect:');
 
  945    curl_setopt_array($ch, $opts);
 
  948    if (curl_errno($ch) == 60) { 
 
  950                     'using bundled information');
 
  951      curl_setopt($ch, CURLOPT_CAINFO,
 
  952                  dirname(__FILE__) . 
'/fb_ca_chain_bundle.crt');
 
  961    if (
$result === 
false && empty($opts[CURLOPT_IPRESOLVE])) {
 
  963        $regex = 
'/Failed to connect to ([^:].*): Network is unreachable/';
 
  964        if (preg_match($regex, curl_error($ch), $matches)) {
 
  965          if (strlen(@inet_pton($matches[1])) === 16) {
 
  967                           'Please disable or get native IPv6 on your server.');
 
  968            self::$CURL_OPTS[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
 
  969            curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
 
  977        'error_code' => curl_errno($ch),
 
  979        'message' => curl_error($ch),
 
  980        'type' => 
'CurlException',
 
  997    list($encoded_sig, $payload) = explode(
'.', $signed_request, 2);
 
 1001    $data = json_decode(self::base64UrlDecode($payload), 
true);
 
 1003    if (strtoupper(
$data[
'algorithm']) !== self::SIGNED_REQUEST_ALGORITHM) {
 
 1005        'Unknown algorithm. Expected ' . self::SIGNED_REQUEST_ALGORITHM);
 
 1010    $expected_sig = hash_hmac(
'sha256', $payload,
 
 1012    if ($sig !== $expected_sig) {
 
 1027    if (!is_array(
$data)) {
 
 1028      throw new InvalidArgumentException(
 
 1029        'makeSignedRequest expects an array. Got: ' . print_r(
$data, 
true));
 
 1032    $data[
'issued_at'] = time();
 
 1033    $json = json_encode(
$data);
 
 1035    $raw_sig = hash_hmac(
'sha256', $b64, $this->
getAppSecret(), $raw = 
true);
 
 1037    return $sig.
'.'.$b64;
 
 1047    static $READ_ONLY_CALLS =
 
 1048      array(
'admin.getallocation' => 1,
 
 1049            'admin.getappproperties' => 1,
 
 1050            'admin.getbannedusers' => 1,
 
 1051            'admin.getlivestreamvialink' => 1,
 
 1052            'admin.getmetrics' => 1,
 
 1053            'admin.getrestrictioninfo' => 1,
 
 1054            'application.getpublicinfo' => 1,
 
 1055            'auth.getapppublickey' => 1,
 
 1056            'auth.getsession' => 1,
 
 1057            'auth.getsignedpublicsessiondata' => 1,
 
 1058            'comments.get' => 1,
 
 1059            'connect.getunconnectedfriendscount' => 1,
 
 1060            'dashboard.getactivity' => 1,
 
 1061            'dashboard.getcount' => 1,
 
 1062            'dashboard.getglobalnews' => 1,
 
 1063            'dashboard.getnews' => 1,
 
 1064            'dashboard.multigetcount' => 1,
 
 1065            'dashboard.multigetnews' => 1,
 
 1066            'data.getcookies' => 1,
 
 1068            'events.getmembers' => 1,
 
 1069            'fbml.getcustomtags' => 1,
 
 1070            'feed.getappfriendstories' => 1,
 
 1071            'feed.getregisteredtemplatebundlebyid' => 1,
 
 1072            'feed.getregisteredtemplatebundles' => 1,
 
 1073            'fql.multiquery' => 1,
 
 1075            'friends.arefriends' => 1,
 
 1077            'friends.getappusers' => 1,
 
 1078            'friends.getlists' => 1,
 
 1079            'friends.getmutualfriends' => 1,
 
 1082            'groups.getmembers' => 1,
 
 1083            'intl.gettranslations' => 1,
 
 1086            'notifications.get' => 1,
 
 1087            'pages.getinfo' => 1,
 
 1088            'pages.isadmin' => 1,
 
 1089            'pages.isappadded' => 1,
 
 1091            'permissions.checkavailableapiaccess' => 1,
 
 1092            'permissions.checkgrantedapiaccess' => 1,
 
 1094            'photos.getalbums' => 1,
 
 1095            'photos.gettags' => 1,
 
 1096            'profile.getinfo' => 1,
 
 1097            'profile.getinfooptions' => 1,
 
 1099            'stream.getcomments' => 1,
 
 1100            'stream.getfilters' => 1,
 
 1101            'users.getinfo' => 1,
 
 1102            'users.getloggedinuser' => 1,
 
 1103            'users.getstandardinfo' => 1,
 
 1104            'users.hasapppermission' => 1,
 
 1105            'users.isappuser' => 1,
 
 1106            'users.isverified' => 1,
 
 1107            'video.getuploadlimits' => 1);
 
 1109    if (isset($READ_ONLY_CALLS[strtolower($method)])) {
 
 1111    } 
else if (strtolower($method) == 
'video.upload') {
 
 1112      $name = 
'api_video';
 
 1129      if (
$path[0] === 
'/') {
 
 1135      $url .= 
'?' . http_build_query(
$params, 
null, 
'&');
 
 1142    if ($this->trustForwarded && isset(
$_SERVER[
'HTTP_X_FORWARDED_HOST'])) {
 
 1143      return $_SERVER[
'HTTP_X_FORWARDED_HOST'];
 
 1149    if ($this->trustForwarded && isset(
$_SERVER[
'HTTP_X_FORWARDED_PROTO'])) {
 
 1150      if (
$_SERVER[
'HTTP_X_FORWARDED_PROTO'] === 
'https') {
 
 1161    if (isset(
$_SERVER[
'SERVER_PORT']) &&
 
 1162        (
$_SERVER[
'SERVER_PORT'] === 
'443')) {
 
 1175    if (array_key_exists(
'base_domain', 
$metadata) &&
 
 1177      return trim(
$metadata[
'base_domain'], 
'.');
 
 1191    $currentUrl = 
$protocol.$host.$_SERVER[
'REQUEST_URI'];
 
 1192    $parts = parse_url($currentUrl);
 
 1195    if (!empty($parts[
'query'])) {
 
 1197      $params = explode(
'&', $parts[
'query']);
 
 1198      $retained_params = array();
 
 1201          $retained_params[] = $param;
 
 1205      if (!empty($retained_params)) {
 
 1206        $query = 
'?'.implode($retained_params, 
'&');
 
 1212      isset($parts[
'port']) &&
 
 1213      ((
$protocol === 
'http://' && $parts[
'port'] !== 80) ||
 
 1214       (
$protocol === 
'https://' && $parts[
'port'] !== 443))
 
 1215      ? 
':' . $parts[
'port'] : 
'';
 
 1233    foreach (self::$DROP_QUERY_PARAMS as $drop_query_param) {
 
 1234      if (strpos($param, $drop_query_param.
'=') === 0) {
 
 1252    switch ($e->getType()) {
 
 1254      case 'OAuthException':
 
 1256      case 'invalid_token':
 
 1260        if ((strpos(
$message, 
'Error validating access token') !== 
false) ||
 
 1261            (strpos(
$message, 
'Invalid OAuth access token') !== 
false) ||
 
 1262            (strpos(
$message, 
'An active access token must be used') !== 
false)
 
 1281    if (php_sapi_name() != 
'cli') {
 
 1298    return base64_decode(strtr($input, 
'-_', 
'+/'));
 
 1311    $str = strtr(base64_encode($input), 
'+/', 
'-_');
 
 1312    $str = str_replace(
'=', 
'', $str);
 
 1320    $this->accessToken = 
null;
 
 1321    $this->signedRequest = 
null;
 
 1328    if (array_key_exists($cookie_name, 
$_COOKIE)) {
 
 1330      if (!headers_sent()) {
 
 1332        setcookie($cookie_name, 
'', 1, 
'/', 
'.'.$base_domain);
 
 1336          'There exists a cookie that we wanted to clear that we couldn\'t '.
 
 1337          'clear because headers was already sent. Make sure to do the first '.
 
 1338          'API call before outputing anything.' 
 1352    if (!array_key_exists($cookie_name, 
$_COOKIE)) {
 
 1357    $cookie_value = trim(
$_COOKIE[$cookie_name], 
'"');
 
 1359    if (empty($cookie_value)) {
 
 1363    $parts = explode(
'&', $cookie_value);
 
 1365    foreach ($parts as $part) {
 
 1366      $pair = explode(
'=', $part, 2);
 
 1367      if (!empty($pair[0])) {
 
 1369          (count($pair) > 1) ? urldecode($pair[1]) : 
'';
 
 1377    if ($big === $small) {
 
 1384    $len = strlen($small);
 
 1388    return substr($big, -$len) === $small;
 
$metadata['__DYNAMIC:1__']
Provides access to the Facebook Platform.
_graph($path, $method='GET', $params=array())
Invoke the Graph API.
parseSignedRequest($signed_request)
Parses a signed_request and validates the signature.
static $DOMAIN_MAP
Maps aliases to Facebook domains.
getApplicationAccessToken()
Returns the access token that should be used for logged out users when no authorization code is avail...
getAppId()
Get the Application ID.
makeSignedRequest($data)
Makes a signed_request blob using the given data.
getAccessToken()
Determines the access token that should be used for API calls.
useFileUploadSupport()
DEPRECATED! Please use getFileUploadSupport instead.
setPersistentData($key, $value)
Each of the following four methods should be overridden in a concrete subclass, as they are in the pr...
clearAllPersistentData()
Clear all data from the persistent storage.
_restserver($params)
Invoke the old restserver.php endpoint.
getFileUploadSupport()
Get the file upload support status.
setAccessToken($access_token)
Sets the access token for api calls.
getApiUrl($method)
Build the URL for api given parameters.
getLoginStatusUrl($params=array())
Get a login status URL to fetch the status from Facebook.
clearPersistentData($key)
Clear the data with $key from the persistent storage.
static endsWith($big, $small)
getUrl($name, $path='', $params=array())
Build the URL for given domain alias, path and parameters.
destroySession()
Destroy the current session.
establishCSRFTokenState()
Lays down a CSRF state token for this process.
static $DROP_QUERY_PARAMS
List of query parameters that get automatically dropped when rebuilding the current URL.
setAppId($appId)
Set the Application ID.
shouldRetainParam($param)
Returns true if and only if the key or key/value pair should be retained as part of the query string.
getCurrentUrl()
Returns the Current URL, stripping it of known FB parameters that should not persist.
getAccessTokenFromCode($code, $redirect_uri=null)
Retrieves an access token for the given authorization code (previously generated from www....
getCode()
Get the authorization code from the query parameters, if it exists, and otherwise return false to sig...
getBaseDomain()
Get the base domain used for the cookie.
getSignedRequestCookieName()
Constructs and returns the name of the cookie that potentially houses the signed request for the app ...
getLogoutUrl($params=array())
Get a Logout URL suitable for use with redirects.
throwAPIException($result)
Analyzes the supplied result to see if it was thrown because the access token is no longer valid.
_oauthRequest($url, $params)
Make a OAuth Request.
getUser()
Get the UID of the connected user, or 0 if the Facebook user is not connected.
$state
A CSRF state variable to assist in the defense against CSRF attacks.
static base64UrlDecode($input)
Base64 encoding that doesn't need to be urlencode()ed.
static errorLog($msg)
Prints to the error log if you aren't in command line mode.
$signedRequest
The data from the signed_request token.
const SIGNED_REQUEST_ALGORITHM
Signed Request Algorithm.
getMetadataCookie()
Parses the metadata cookie that our Javascript API set.
isVideoPost($path, $method='GET')
Return true if this is video post.
setFileUploadSupport($fileUploadSupport)
Set the file upload support status.
static base64UrlEncode($input)
Base64 encoding that doesn't need to be urlencode()ed.
getApiSecret()
Get the App Secret.
setAppSecret($appSecret)
Set the App Secret.
getUserFromAccessToken()
Retrieves the UID with the understanding that $this->accessToken has already been set and is seemingl...
getMetadataCookieName()
Constructs and returns the name of the coookie that potentially contain metadata.
makeRequest($url, $params, $ch=null)
Makes an HTTP request.
getPersistentData($key, $default=false)
Get the data for $key, persisted by BaseFacebook::setPersistentData()
getUserFromAvailableData()
Determines the connected user by first examining any signed requests, then considering an authorizati...
static $CURL_OPTS
Default options for curl.
getLoginUrl($params=array())
Get a Login URL for use with redirects.
getSignedRequest()
Retrieve the signed request, either from a request parameter or, if not present, from a cookie.
setExtendedAccessToken()
Extend an access token, while removing the short-lived token that might have been generated via clien...
getAppSecret()
Get the App Secret.
__construct($config)
Initialize a Facebook Application.
static isAllowedDomain($big, $small)
setApiSecret($apiSecret)
Set the App Secret.
getUserAccessToken()
Determines and returns the user access token, first using the signed request if present,...
An exception for terminatinating execution or to throw for unit testing.
Copyright 2011 Facebook, Inc.
getType()
Returns the associated type for the error.
$result
The result from the API server that represents the exception information.
__toString()
To make debugging easier.
__construct($result)
Make a new API Exception with the given result.
getResult()
Return the associated result object returned by the API server.
catch(Exception $e) $message
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']