You are here

fb_settings.inc in Drupal for Facebook 7.3

This file is to be included from your sites/.../settings.php file.

In this code we set up special session management and url rewriting. These things must be done before modules are loaded, so the code is here instead of fb.module. And that is why this must be included from settings.php.

File

fb_settings.inc
View source
<?php

/**
 * @file
 * This file is to be included from your sites/.../settings.php file.
 *
 * In this code we set up special session management and url
 * rewriting.  These things must be done before modules are loaded, so
 * the code is here instead of fb.module. And that is why this
 * must be included from settings.php.
 *
 */

// Each of these are things we can learn and store in fb_settings().
// The CB (callback) values are learned via URL rewriting.
// Include fb_url_rewrite.inc in your settings.php to enable this.
define('FB_SETTINGS_CB', 'fb_cb');

// The app id.
define('FB_SETTINGS_CB_PAGE', 'fb_page');

// Page id, for tabs.
define('FB_SETTINGS_CB_TYPE', 'fb_cb_type');

// For iframes within FBML canvas pages, now DEPRECATED.
define('FB_SETTINGS_CB_SESSION', 'fb_sess');

// For embedding session id within URL.
// Things we can learn from the facebook session.
define('FB_SETTINGS_APIKEY', 'apikey');
define('FB_SETTINGS_ID', 'app_id');
define('FB_SETTINGS_PAGE_ID', 'page_id');
define('FB_SETTINGS_FBU', 'fbu');
define('FB_SETTINGS_TOKEN', 'token');
define('FB_SETTINGS_TYPE', 'type');

// page type not same as cb type
define('FB_SETTINGS_COOKIE_DOMAIN', 'cookie_domain');

// Possible values for page type.
define('FB_SETTINGS_TYPE_CANVAS', 'canvas');
define('FB_SETTINGS_TYPE_CONNECT', 'connect');
define('FB_SETTINGS_TYPE_PROFILE', 'profile');

// deprecated, FBML tab
define('FB_SETTINGS_TYPE_PAGE_TAB', 'page_tab');

// iframe tab

/**
 * Helper function to remember values as we learn them.
 */
function fb_settings($key = NULL, $value = NULL) {
  static $cache = array();
  if (isset($value)) {
    $cache[$key] = $value;
  }
  if (isset($key)) {
    return isset($cache[$key]) ? $cache[$key] : NULL;
  }
  else {
    return $cache;
  }
}

/**
 * Helpers to parse signed_session.  Copied from facebook.php.
 */

/**
 * Base64 encoding that doesn't need to be urlencode()ed.
 * Exactly the same as base64_encode except it uses
 *   - instead of +
 *   _ instead of /
 *
 * @param String base64UrlEncodeded string
 */
function _fb_settings_base64_url_decode($input) {
  return base64_decode(strtr($input, '-_', '+/'));
}

/**
 * See https://developers.facebook.com/docs/authentication/signed_request/ for
 * a more reliable version of this function.  We skip validation because we do
 * not yet know the app secret.
 */
function _fb_settings_parse_signed_request($signed_request) {
  list($encoded_sig, $payload) = explode('.', $signed_request, 2);

  // decode the data
  $sig = _fb_settings_base64_url_decode($encoded_sig);
  $data = json_decode(_fb_settings_base64_url_decode($payload), TRUE);
  return $data;
}

/**
 * Get the fb_settings from a parsed signed request.
 * http://developers.facebook.com/docs/authentication/canvas
 * signed request will be found on canvas pages, and some connect pages and ajax callbacks.
 */
function _fb_settings_honor_signed_request($sr) {
  if (isset($sr['page'])) {

    // Iframe page tab.
    fb_settings(FB_SETTINGS_CB_PAGE, $sr['page']['id']);
    fb_settings(FB_SETTINGS_PAGE_ID, $sr['page']['id']);
    fb_settings(FB_SETTINGS_TYPE, FB_SETTINGS_TYPE_PAGE_TAB);
    if (isset($sr['user_id'])) {
      fb_settings(FB_SETTINGS_FBU, $sr['user_id']);
    }
  }
  if (isset($sr['profile_id'])) {

    // Only on old FBML tabs.  Deprecated now that iframe tabs are preferred.
    fb_settings(FB_SETTINGS_CB_PAGE, $sr['profile_id']);
    fb_settings(FB_SETTINGS_CB_PAGE, $sr['profile_id']);
    fb_settings(FB_SETTINGS_TYPE, FB_SETTINGS_TYPE_PROFILE);
    if ($sr['user_id'] != $sr['profile_id']) {
      fb_settings(FB_SETTINGS_FBU, $sr['user_id']);
    }
  }
  elseif (isset($sr['user_id'])) {
    fb_settings(FB_SETTINGS_FBU, $sr['user_id']);
  }
  if (isset($sr['oauth_token'])) {
    fb_settings(FB_SETTINGS_TOKEN, $sr['oauth_token']);
    if (!fb_settings(FB_SETTINGS_ID)) {

      // Prefer app id learned from url rewriting over that learned from signed request (because sr may be encrypted).
      $tokens = explode('|', $sr['oauth_token']);
      if (($app_id = $tokens[0]) && !empty($tokens[1])) {
        fb_settings(FB_SETTINGS_ID, $app_id);
      }
    }
  }
}

/**
 * The current format of the cookie is a signed request.
 *
 * Facebook doesn't document the cookie name or format, so basically we just
 * have to hope this works.
 */
function fb_settings_get_facebook_cookie($app_id, $application_secret = NULL) {
  if (!isset($_COOKIE['fbsr_' . $app_id])) {
    return;
  }
  $sr = _fb_settings_parse_signed_request($_COOKIE['fbsr_' . $app_id]);
  return $sr;
}

/**
 * By changing the $cookie_domain, we force drupal to use a different session
 * when a user is logged into a facebook application.  We base the
 * $cookie_domain on the id of the application, if we can learn it.
 *
 * Facebook provides a number of "migrations" and historically has offered
 * different data to applications.  So the code below tries a variety of ways
 * to learn the settings.
 */
if (function_exists('_fb_settings_parse') && ($id = _fb_settings_parse(FB_SETTINGS_CB))) {

  // Learned id from url rewrite.
  // Either canvas page or profile tab.
  fb_settings(FB_SETTINGS_ID, $id);
  if ($page_id = _fb_settings_parse(FB_SETTINGS_CB_PAGE)) {
    fb_settings(FB_SETTINGS_TYPE, FB_SETTINGS_TYPE_PAGE_TAB);
    fb_settings(FB_SETTINGS_PAGE_ID, $page_id);
  }
  else {
    fb_settings(FB_SETTINGS_TYPE, FB_SETTINGS_TYPE_CANVAS);
  }
  if (isset($_REQUEST['signed_request']) && ($sr = _fb_settings_parse_signed_request($_REQUEST['signed_request']))) {

    // Prefer signed request data to cookie data.
    _fb_settings_honor_signed_request($sr);
  }
  else {
    $data = fb_settings_get_facebook_cookie($id);
    if (isset($data)) {
      if (isset($data['uid'])) {
        fb_settings(FB_SETTINGS_FBU, $data['uid']);
      }
    }
  }
}
elseif (isset($_REQUEST['signed_request']) && ($sr = _fb_settings_parse_signed_request($_REQUEST['signed_request']))) {

  // Reach this clause on canvas page when admin has not enabled url_rewrite.
  // http://developers.facebook.com/docs/authentication/canvas
  // We get useful info from signed_request only when user is logged in and
  // therefore oauth_token is set.
  _fb_settings_honor_signed_request($sr);

  // Once upon a time, signed_request was only passed on canvas pages.  No longer true.
  // @TODO - somehow detect whether a signed request indicates canvas page or not.

  //fb_settings(FB_SETTINGS_TYPE, FB_SETTINGS_TYPE_CANVAS);
}
else {

  // We're not in a canvas page.
  // We might be in a facebook connect page.  We have to inspect cookies to make sure.
  $id = isset($conf['fb_id']) ? $conf['fb_id'] : NULL;
  $secret = isset($conf['fb_secret']) ? $conf['fb_secret'] : NULL;
  if ($id) {
    if ($sr = fb_settings_get_facebook_cookie($id, $secret)) {
      _fb_settings_honor_signed_request($sr);
    }
  }
}
if (fb_settings(FB_SETTINGS_TYPE) && fb_settings(FB_SETTINGS_TYPE) != FB_SETTINGS_TYPE_CONNECT) {

  // Cookie domain unique to app and page type, and fbu to detect logout when on canvas pages.
  $unique_id = fb_settings(FB_SETTINGS_TYPE) . fb_settings(FB_SETTINGS_ID) . '_' . fb_settings(FB_SETTINGS_FBU);
  $cookie_domain = isset($cookie_domain) ? $cookie_domain : $unique_id;
  fb_settings(FB_SETTINGS_COOKIE_DOMAIN, $cookie_domain);

  // for debugging.
}
if (fb_settings(FB_SETTINGS_FBU)) {

  // Tells Drupal, don't pull from (or save to) cache when logged into facebook.
  $conf['cache'] = 0;

  // CACHE_DISABLED == 0
}

Functions

Namesort descending Description
fb_settings Helper function to remember values as we learn them.
fb_settings_get_facebook_cookie The current format of the cookie is a signed request.
_fb_settings_base64_url_decode Base64 encoding that doesn't need to be urlencode()ed. Exactly the same as base64_encode except it uses
_fb_settings_honor_signed_request Get the fb_settings from a parsed signed request. http://developers.facebook.com/docs/authentication/canvas signed request will be found on canvas pages, and some connect pages and ajax callbacks.
_fb_settings_parse_signed_request See https://developers.facebook.com/docs/authentication/signed_request/ for a more reliable version of this function. We skip validation because we do not yet know the app secret.

Constants