]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Update to external Facebook libs
authorZach Copley <zach@status.net>
Wed, 30 Dec 2009 20:33:10 +0000 (20:33 +0000)
committerZach Copley <zach@status.net>
Thu, 31 Dec 2009 22:39:01 +0000 (22:39 +0000)
plugins/Facebook/facebook/facebook.php
plugins/Facebook/facebook/facebook_desktop.php
plugins/Facebook/facebook/facebook_mobile.php [new file with mode: 0644]
plugins/Facebook/facebook/facebookapi_php5_restlib.php

index 016e8e8e0d4931d888b68d8051107d36045fc143..440706cbc3fdb5543001003e88e2bc9721414192 100644 (file)
@@ -82,7 +82,8 @@ class Facebook {
 
 
     if (isset($this->fb_params['friends'])) {
-      $this->api_client->friends_list = explode(',', $this->fb_params['friends']);
+      $this->api_client->friends_list =
+        array_filter(explode(',', $this->fb_params['friends']));
     }
     if (isset($this->fb_params['added'])) {
       $this->api_client->added = $this->fb_params['added'];
@@ -215,11 +216,15 @@ class Facebook {
   // Invalidate the session currently being used, and clear any state associated
   // with it. Note that the user will still remain logged into Facebook.
   public function expire_session() {
-    if ($this->api_client->auth_expireSession()) {
+    try {
+      if ($this->api_client->auth_expireSession()) {
+        $this->clear_cookie_state();
+        return true;
+      } else {
+        return false;
+      }
+    } catch (Exception $e) {
       $this->clear_cookie_state();
-      return true;
-    } else {
-      return false;
     }
   }
 
@@ -249,10 +254,14 @@ class Facebook {
     if (!$this->in_fb_canvas() && isset($_COOKIE[$this->api_key . '_user'])) {
        $cookies = array('user', 'session_key', 'expires', 'ss');
        foreach ($cookies as $name) {
-         setcookie($this->api_key . '_' . $name, false, time() - 3600);
+         setcookie($this->api_key . '_' . $name,
+                   false,
+                   time() - 3600,
+                   '',
+                   $this->base_domain);
          unset($_COOKIE[$this->api_key . '_' . $name]);
        }
-       setcookie($this->api_key, false, time() - 3600);
+       setcookie($this->api_key, false, time() - 3600, '', $this->base_domain);
        unset($_COOKIE[$this->api_key]);
      }
 
index e79a2ca3433819126fef76d29ea6251dbdaceb76..ed4762215bf53cec4211ea05b30037e2f221e34a 100644 (file)
@@ -60,7 +60,7 @@ class FacebookDesktop extends Facebook {
 
   public function set_session_secret($session_secret) {
     $this->secret = $session_secret;
-    $this->api_client->secret = $session_secret;
+    $this->api_client->use_session_secret($session_secret);
   }
 
   public function require_login() {
diff --git a/plugins/Facebook/facebook/facebook_mobile.php b/plugins/Facebook/facebook/facebook_mobile.php
new file mode 100644 (file)
index 0000000..5ee7f4e
--- /dev/null
@@ -0,0 +1,260 @@
+<?php
+// Copyright 2004-2009 Facebook. All Rights Reserved.
+//
+// +---------------------------------------------------------------------------+
+// | Facebook Platform PHP5 client                                             |
+// +---------------------------------------------------------------------------+
+// | Copyright (c) 2007 Facebook, Inc.                                         |
+// | All rights reserved.                                                      |
+// |                                                                           |
+// | Redistribution and use in source and binary forms, with or without        |
+// | modification, are permitted provided that the following conditions        |
+// | are met:                                                                  |
+// |                                                                           |
+// | 1. Redistributions of source code must retain the above copyright         |
+// |    notice, this list of conditions and the following disclaimer.          |
+// | 2. Redistributions in binary form must reproduce the above copyright      |
+// |    notice, this list of conditions and the following disclaimer in the    |
+// |    documentation and/or other materials provided with the distribution.   |
+// |                                                                           |
+// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      |
+// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
+// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   |
+// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          |
+// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  |
+// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  |
+// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         |
+// +---------------------------------------------------------------------------+
+// | For help with this library, contact developers-help@facebook.com          |
+// +---------------------------------------------------------------------------+
+//
+/**
+ *  This class extends and modifies the "Facebook" class to better suit wap
+ *  apps. Since there is no javascript support, we need to use server redirect
+ *  to implement Facebook connect functionalities such as authenticate,
+ *  authorize, feed form etc.. This library provide many helper functions for
+ *  wap developer to locate the right wap url. The url here is targed at
+ *  facebook wap site or wap-friendly url.
+ */
+class FacebookMobile extends Facebook {
+  // the application secret, which differs from the session secret
+
+  public function __construct($api_key, $secret, $generate_session_secret=false) {
+    parent::__construct($api_key, $secret, $generate_session_secret);
+  }
+
+  public function redirect($url) {
+    header('Location: '. $url);
+  }
+
+  public function get_m_url($action, $params) {
+    $page = parent::get_facebook_url('m'). '/' .$action;
+    foreach($params as $key => $val) {
+      if (!$val) {
+        unset($params[$key]);
+      }
+    }
+    return $page . '?' . http_build_query($params);
+  }
+
+  public function get_www_url($action, $params) {
+    $page = parent::get_facebook_url('www'). '/' .$action;
+    foreach($params as $key => $val) {
+      if (!$val) {
+        unset($params[$key]);
+      }
+    }
+    return $page . '?' . http_build_query($params);
+  }
+
+  public function get_add_url($next=null) {
+
+    return $this->get_m_url('add.php', array('api_key' => $this->api_key,
+                                             'next'    => $next));
+  }
+
+  public function get_tos_url($next=null, $cancel = null, $canvas=null) {
+    return $this->get_m_url('tos.php', array('api_key' => $this->api_key,
+                                             'v'       => '1.0',
+                                             'next'    => $next,
+                                             'canvas'  => $canvas,
+                                             'cancel'   => $cancel));
+  }
+
+  public function get_logout_url($next=null) {
+    $params = array('api_key'     => $this->api_key,
+                    'session_key' => $this->api_client->session_key,
+                   );
+
+    if ($next) {
+      $params['connect_next'] = 1;
+      $params['next'] = $next;
+    }
+
+    return $this->get_m_url('logout.php', $params);
+  }
+  public function get_register_url($next=null, $cancel_url=null) {
+    return $this->get_m_url('r.php',
+      array('fbconnect' => 1,
+            'api_key' => $this->api_key,
+            'next' => $next ? $next : parent::current_url(),
+            'cancel_url' => $cancel_url ? $cancel_url : parent::current_url()));
+  }
+  /**
+   * These set of fbconnect style url redirect back to the application current
+   * page when the action is done. Developer can also use the non fbconnect
+   * style url and provide their own redirect link by giving the right parameter
+   * to $next and/or $cancel_url
+   */
+  public function get_fbconnect_register_url() {
+    return $this->get_register_url(parent::current_url(), parent::current_url());
+  }
+  public function get_fbconnect_tos_url() {
+    return $this->get_tos_url(parent::current_url(), parent::current_url(), $this->in_frame());
+  }
+
+  public function get_fbconnect_logout_url() {
+    return $this->get_logout_url(parent::current_url());
+  }
+
+  public function logout_user() {
+    $this->user = null;
+  }
+
+  public function get_prompt_permissions_url($ext_perm,
+                                             $next=null,
+                                             $cancel_url=null) {
+
+    return $this->get_www_url('connect/prompt_permissions.php',
+      array('api_key' => $this->api_key,
+            'ext_perm' => $ext_perm,
+            'next' => $next ? $next : parent::current_url(),
+            'cancel' => $cancel_url ? $cancel_url : parent::current_url(),
+            'display' => 'wap'));
+
+  }
+
+  /**
+   * support both prompt_permissions.php and authorize.php for now.
+   * authorized.php is to be deprecate though.
+   */
+  public function get_extended_permission_url($ext_perm,
+                                              $next=null,
+                                              $cancel_url=null) {
+    $next = $next ? $next : parent::current_url();
+    $cancel_url = $cancel_url ? $cancel_url : parent::current_url();
+
+    return $this->get_m_url('authorize.php',
+                      array('api_key' => $this->api_key,
+                            'ext_perm' => $ext_perm,
+                            'next' => $next,
+                            'cancel_url' => $cancel_url));
+
+  }
+
+  public function render_prompt_feed_url($action_links=NULL,
+                                         $target_id=NULL,
+                                         $message='',
+                                         $user_message_prompt='',
+                                         $caption=NULL,
+                                         $callback ='',
+                                         $cancel='',
+                                         $attachment=NULL,
+                                         $preview=true) {
+
+    $params = array('api_key'     => $this->api_key,
+                    'session_key' => $this->api_client->session_key,
+                   );
+    if (!empty($attachment)) {
+      $params['attachment'] = urlencode(json_encode($attachment));
+    } else {
+      $attachment = new stdClass();
+      $app_display_info = $this->api_client->admin_getAppProperties(array('application_name',
+                                                                          'callback_url',
+                                                                          'description',
+                                                                          'logo_url'));
+      $app_display_info = $app_display_info;
+      $attachment->name = $app_display_info['application_name'];
+      $attachment->caption = !empty($caption) ? $caption : 'Just see what\'s new!';
+      $attachment->description = $app_display_info['description'];
+      $attachment->href = $app_display_info['callback_url'];
+      if (!empty($app_display_info['logo_url'])) {
+        $logo = new stdClass();
+        $logo->type = 'image';
+        $logo->src = $app_display_info['logo_url'];
+        $logo->href = $app_display_info['callback_url'];
+        $attachment->media = array($logo);
+      }
+      $params['attachment'] = urlencode(json_encode($attachment));
+    }
+    $params['preview'] = $preview;
+    $params['message'] = $message;
+    $params['user_message_prompt'] = $user_message_prompt;
+    if (!empty($callback)) {
+      $params['callback'] = $callback;
+    } else {
+      $params['callback'] = $this->current_url();
+    }
+    if (!empty($cancel)) {
+      $params['cancel'] = $cancel;
+    } else {
+      $params['cancel'] = $this->current_url();
+    }
+
+    if (!empty($target_id)) {
+      $params['target_id'] = $target_id;
+    }
+    if (!empty($action_links)) {
+      $params['action_links'] = urlencode(json_encode($action_links));
+    }
+
+    $params['display'] = 'wap';
+    header('Location: '. $this->get_www_url('connect/prompt_feed.php', $params));
+  }
+
+//use template_id
+  public function render_feed_form_url($template_id=NULL,
+                                       $template_data=NULL,
+                                       $user_message=NULL,
+                                       $body_general=NULL,
+                                       $user_message_prompt=NULL,
+                                       $target_id=NULL,
+                                       $callback=NULL,
+                                       $cancel=NULL,
+                                       $preview=true) {
+
+    $params = array('api_key' => $this->api_key);
+    $params['preview'] = $preview;
+    if (isset($template_id) && $template_id) {
+      $params['template_id'] = $template_id;
+    }
+    $params['message'] = $user_message ? $user_message['value'] : '';
+    if (isset($body_general) && $body_general) {
+      $params['body_general'] = $body_general;
+    }
+    if (isset($user_message_prompt) && $user_message_prompt) {
+      $params['user_message_prompt'] = $user_message_prompt;
+    }
+    if (isset($callback) && $callback) {
+      $params['callback'] = $callback;
+    } else {
+      $params['callback'] = $this->current_url();
+    }
+    if (isset($cancel) && $cancel) {
+      $params['cancel'] = $cancel;
+    } else {
+      $params['cancel'] = $this->current_url();
+    }
+    if (isset($template_data) && $template_data) {
+      $params['template_data'] = $template_data;
+    }
+    if (isset($target_id) && $target_id) {
+      $params['to_ids'] = $target_id;
+    }
+    $params['display'] = 'wap';
+    header('Location: '. $this->get_www_url('connect/prompt_feed.php', $params));
+  }
+}
index 55cb7fb86a9a7f23b4a2f6a44ae9c5bb733dcddd..fa1088cd00bffedbcd3d7af4593b5d4e998b7c1f 100755 (executable)
@@ -56,6 +56,8 @@ class FacebookRestClient {
   private $call_as_apikey;
   private $use_curl_if_available;
   private $format = null;
+  private $using_session_secret = false;
+  private $rawData = null;
 
   const BATCH_MODE_DEFAULT = 0;
   const BATCH_MODE_SERVER_PARALLEL = 0;
@@ -76,7 +78,10 @@ class FacebookRestClient {
     $this->last_call_id = 0;
     $this->call_as_apikey = '';
     $this->use_curl_if_available = true;
-    $this->server_addr  = Facebook::get_facebook_url('api') . '/restserver.php';
+    $this->server_addr =
+      Facebook::get_facebook_url('api') . '/restserver.php';
+    $this->photo_server_addr =
+      Facebook::get_facebook_url('api-photo') . '/restserver.php';
 
     if (!empty($GLOBALS['facebook_config']['debug'])) {
       $this->cur_id = 0;
@@ -128,6 +133,16 @@ function toggleDisplay(id, type) {
     $this->user = $uid;
   }
 
+
+  /**
+   * Switch to use the session secret instead of the app secret,
+   * for desktop and unsecured environment
+   */
+  public function use_session_secret($session_secret) {
+    $this->secret = $session_secret;
+    $this->using_session_secret = true;
+  }
+
   /**
    * Normally, if the cURL library/PHP extension is available, it is used for
    * HTTP transactions.  This allows that behavior to be overridden, falling
@@ -270,25 +285,35 @@ function toggleDisplay(id, type) {
   /**
    * Returns the session information available after current user logs in.
    *
-   * @param string $auth_token             the token returned by
-   *                                       auth_createToken or passed back to
-   *                                       your callback_url.
-   * @param bool $generate_session_secret  whether the session returned should
-   *                                       include a session secret
+   * @param string $auth_token the token returned by auth_createToken or
+   *               passed back to your callback_url.
+   * @param bool $generate_session_secret whether the session returned should
+   *             include a session secret
+   * @param string $host_url the connect site URL for which the session is
+   *               being generated.  This parameter is optional, unless
+   *               you want Facebook to determine which of several base domains
+   *               to choose from.  If this third argument isn't provided but
+   *               there are several base domains, the first base domain is
+   *               chosen.
    *
    * @return array  An assoc array containing session_key, uid
    */
-  public function auth_getSession($auth_token, $generate_session_secret=false) {
+  public function auth_getSession($auth_token,
+                                  $generate_session_secret = false,
+                                  $host_url = null) {
     if (!$this->pending_batch()) {
-      $result = $this->call_method('facebook.auth.getSession',
-          array('auth_token' => $auth_token,
-                'generate_session_secret' => $generate_session_secret));
+      $result = $this->call_method(
+        'facebook.auth.getSession',
+        array('auth_token' => $auth_token,
+              'generate_session_secret' => $generate_session_secret,
+              'host_url' => $host_url));
       $this->session_key = $result['session_key'];
 
-    if (!empty($result['secret']) && !$generate_session_secret) {
-      // desktop apps have a special secret
-      $this->secret = $result['secret'];
-    }
+      if (!empty($result['secret']) && !$generate_session_secret) {
+        // desktop apps have a special secret
+        $this->secret = $result['secret'];
+      }
+
       return $result;
     }
   }
@@ -519,13 +544,34 @@ function toggleDisplay(id, type) {
       return $this->call_upload_method('facebook.events.create',
         array('event_info' => $event_info),
         $file,
-        Facebook::get_facebook_url('api-photo') . '/restserver.php');
+        $this->photo_server_addr);
     } else {
       return $this->call_method('facebook.events.create',
         array('event_info' => $event_info));
     }
   }
 
+  /**
+   * Invites users to an event. If a session user exists, the session user
+   * must have permissions to invite friends to the event and $uids must contain
+   * a list of friend ids. Otherwise, the event must have been
+   * created by the app and $uids must contain users of the app.
+   * This method requires the 'create_event' extended permission to
+   * invite people on behalf of a user.
+   *
+   * @param $eid   the event id
+   * @param $uids  an array of users to invite
+   * @param $personal_message  a string containing the user's message
+   *                           (text only)
+   *
+   */
+  public function events_invite($eid, $uids, $personal_message) {
+    return $this->call_method('facebook.events.invite',
+                              array('eid' => $eid,
+                                    'uids' => $uids,
+                                    'personal_message', $personal_message));
+  }
+
   /**
    * Edits an existing event. Only works for events where application is admin.
    *
@@ -540,7 +586,7 @@ function toggleDisplay(id, type) {
       return $this->call_upload_method('facebook.events.edit',
         array('eid' => $eid, 'event_info' => $event_info),
         $file,
-        Facebook::get_facebook_url('api-photo') . '/restserver.php');
+        $this->photo_server_addr);
     } else {
       return $this->call_method('facebook.events.edit',
         array('eid' => $eid,
@@ -576,21 +622,7 @@ function toggleDisplay(id, type) {
         array('url' => $url));
   }
 
-  /**
-   * Lets you insert text strings in their native language into the Facebook
-   * Translations database so they can be translated.
-   *
-   * @param array $native_strings  An array of maps, where each map has a 'text'
-   *                               field and a 'description' field.
-   *
-   * @return int  Number of strings uploaded.
-   */
-  public function &fbml_uploadNativeStrings($native_strings) {
-    return $this->call_method('facebook.fbml.uploadNativeStrings',
-        array('native_strings' => json_encode($native_strings)));
-  }
-
-  /**
+ /**
    * Associates a given "handle" with FBML markup so that the handle can be
    * used within the fb:ref FBML tag. A handle is unique within an application
    * and allows an application to publish identical FBML to many user profiles
@@ -668,7 +700,44 @@ function toggleDisplay(id, type) {
                               array('tag_names' => json_encode($tag_names)));
   }
 
+  /**
+   * Gets the best translations for native strings submitted by an application
+   * for translation. If $locale is not specified, only native strings and their
+   * descriptions are returned. If $all is true, then unapproved translations
+   * are returned as well, otherwise only approved translations are returned.
+   *
+   * A mapping of locale codes -> language names is available at
+   * http://wiki.developers.facebook.com/index.php/Facebook_Locales
+   *
+   * @param string $locale the locale to get translations for, or 'all' for all
+   *                       locales, or 'en_US' for native strings
+   * @param bool   $all    whether to return all or only approved translations
+   *
+   * @return array (locale, array(native_strings, array('best translation
+   *                available given enough votes or manual approval', approval
+   *                                                                  status)))
+   * @error API_EC_PARAM
+   * @error API_EC_PARAM_BAD_LOCALE
+   */
+  public function &intl_getTranslations($locale = 'en_US', $all = false) {
+    return $this->call_method('facebook.intl.getTranslations',
+                              array('locale' => $locale,
+                                    'all'    => $all));
+  }
 
+  /**
+   * Lets you insert text strings in their native language into the Facebook
+   * Translations database so they can be translated.
+   *
+   * @param array $native_strings  An array of maps, where each map has a 'text'
+   *                               field and a 'description' field.
+   *
+   * @return int  Number of strings uploaded.
+   */
+  public function &intl_uploadNativeStrings($native_strings) {
+    return $this->call_method('facebook.intl.uploadNativeStrings',
+        array('native_strings' => json_encode($native_strings)));
+  }
 
   /**
    * This method is deprecated for calls made on behalf of users. This method
@@ -1248,6 +1317,87 @@ function toggleDisplay(id, type) {
               'test_mode' => $test_mode)), true);
   }
 
+  /**
+   * Gifts API
+   */
+
+  /**
+   * Get Gifts associated with an app
+   *
+   * @return             array of gifts
+   */
+  public function gifts_get() {
+    return json_decode(
+        $this->call_method('facebook.gifts.get',
+                           array()),
+        true
+        );
+  }
+
+  /*
+   * Update gifts stored by an app
+   *
+   * @param array containing gift_id => gift_data to be updated
+   * @return array containing gift_id => true/false indicating success
+   *                                     in updating that gift
+   */
+  public function gifts_update($update_array) {
+    return json_decode(
+      $this->call_method('facebook.gifts.update',
+                         array('update_str' => json_encode($update_array))
+                        ),
+      true
+    );
+  }
+
+  /**
+   * Dashboard API
+   */
+
+  /**
+   * Set the news for the specified user.
+   *
+   * @param int    $uid     The user for whom you are setting news for
+   * @param string $news    Text of news to display
+   *
+   * @return bool   Success
+   */
+  public function dashboard_setNews($uid, $news) {
+    return $this->call_method('facebook.dashboard.setNews',
+                              array('uid'  => $uid,
+                                    'news' => $news)
+                             );
+  }
+
+  /**
+   * Get the current news of the specified user.
+   *
+   * @param int    $uid     The user to get the news of
+   *
+   * @return string   The text of the current news for the user
+   */
+  public function dashboard_getNews($uid) {
+    return json_decode(
+      $this->call_method('facebook.dashboard.getNews',
+                         array('uid' => $uid)
+                        ), true);
+  }
+
+  /**
+   * Set the news for the specified user.
+   *
+   * @param int    $uid     The user you are clearing the news of
+   *
+   * @return bool   Success
+   */
+  public function dashboard_clearNews($uid) {
+    return $this->call_method('facebook.dashboard.clearNews',
+                              array('uid' => $uid)
+                             );
+  }
+
+
+
   /**
    * Creates a note with the specified title and content.
    *
@@ -1795,14 +1945,20 @@ function toggleDisplay(id, type) {
                               $start_time = 0,
                               $end_time = 0,
                               $limit = 30,
-                              $filter_key = '') {
+                              $filter_key = '',
+                              $exportable_only = false,
+                              $metadata = null,
+                              $post_ids = null) {
     $args = array(
       'viewer_id'  => $viewer_id,
       'source_ids' => $source_ids,
       'start_time' => $start_time,
       'end_time'   => $end_time,
       'limit'      => $limit,
-      'filter_key' => $filter_key);
+      'filter_key' => $filter_key,
+      'exportable_only' => $exportable_only,
+      'metadata' => $metadata,
+      'post_ids' => $post_ids);
     return $this->call_method('facebook.stream.get', $args);
   }
 
@@ -1949,97 +2105,6 @@ function toggleDisplay(id, type) {
               'options' => json_encode($options)));
   }
 
-  /**
-   * Get all the marketplace categories.
-   *
-   * @return array  A list of category names
-   */
-  function marketplace_getCategories() {
-    return $this->call_method('facebook.marketplace.getCategories',
-        array());
-  }
-
-  /**
-   * Get all the marketplace subcategories for a particular category.
-   *
-   * @param  category  The category for which we are pulling subcategories
-   *
-   * @return array A list of subcategory names
-   */
-  function marketplace_getSubCategories($category) {
-    return $this->call_method('facebook.marketplace.getSubCategories',
-        array('category' => $category));
-  }
-
-  /**
-   * Get listings by either listing_id or user.
-   *
-   * @param listing_ids   An array of listing_ids (optional)
-   * @param uids          An array of user ids (optional)
-   *
-   * @return array  The data for matched listings
-   */
-  function marketplace_getListings($listing_ids, $uids) {
-    return $this->call_method('facebook.marketplace.getListings',
-        array('listing_ids' => $listing_ids, 'uids' => $uids));
-  }
-
-  /**
-   * Search for Marketplace listings.  All arguments are optional, though at
-   * least one must be filled out to retrieve results.
-   *
-   * @param category     The category in which to search (optional)
-   * @param subcategory  The subcategory in which to search (optional)
-   * @param query        A query string (optional)
-   *
-   * @return array  The data for matched listings
-   */
-  function marketplace_search($category, $subcategory, $query) {
-    return $this->call_method('facebook.marketplace.search',
-        array('category' => $category,
-              'subcategory' => $subcategory,
-              'query' => $query));
-  }
-
-  /**
-   * Remove a listing from Marketplace.
-   *
-   * @param listing_id  The id of the listing to be removed
-   * @param status      'SUCCESS', 'NOT_SUCCESS', or 'DEFAULT'
-   *
-   * @return bool  True on success
-   */
-  function marketplace_removeListing($listing_id,
-                                     $status='DEFAULT',
-                                     $uid=null) {
-    return $this->call_method('facebook.marketplace.removeListing',
-        array('listing_id' => $listing_id,
-              'status' => $status,
-              'uid' => $uid));
-  }
-
-  /**
-   * Create/modify a Marketplace listing for the loggedinuser.
-   *
-   * @param int              listing_id  The id of a listing to be modified, 0
-   *                                     for a new listing.
-   * @param show_on_profile  bool        Should we show this listing on the
-   *                                     user's profile
-   * @param listing_attrs    array       An array of the listing data
-   *
-   * @return int  The listing_id (unchanged if modifying an existing listing).
-   */
-  function marketplace_createListing($listing_id,
-                                     $show_on_profile,
-                                     $attrs,
-                                     $uid=null) {
-    return $this->call_method('facebook.marketplace.createListing',
-        array('listing_id' => $listing_id,
-              'show_on_profile' => $show_on_profile,
-              'listing_attrs' => json_encode($attrs),
-              'uid' => $uid));
-  }
-
   /////////////////////////////////////////////////////////////////////////////
   // Data Store API
 
@@ -2875,6 +2940,35 @@ function toggleDisplay(id, type) {
        array('properties' => json_encode($properties)));
   }
 
+  /**
+   * Sets href and text for a Live Stream Box xid's via link
+   *
+   * @param  string  $xid       xid of the Live Stream
+   * @param  string  $via_href  Href for the via link
+   * @param  string  $via_text  Text for the via link
+   *
+   * @return boolWhether the set was successful
+   */
+  public function admin_setLiveStreamViaLink($xid, $via_href, $via_text) {
+    return $this->call_method('facebook.admin.setLiveStreamViaLink',
+                              array('xid'      => $xid,
+                                    'via_href' => $via_href,
+                                    'via_text' => $via_text));
+  }
+
+  /**
+   * Gets href and text for a Live Stream Box xid's via link
+   *
+   * @param  string  $xid  xid of the Live Stream
+   *
+   * @return Array  Associative array with keys 'via_href' and 'via_text'
+   *                False if there was an error.
+   */
+  public function admin_getLiveStreamViaLink($xid) {
+    return $this->call_method('facebook.admin.getLiveStreamViaLink',
+                              array('xid' => $xid));
+  }
+
   /**
    * Returns the allocation limit value for a specified integration point name
    * Integration point names are defined in lib/api/karma/constants.php in the
@@ -3012,6 +3106,7 @@ function toggleDisplay(id, type) {
         $params['call_as_apikey'] = $this->call_as_apikey;
       }
       $data = $this->post_request($method, $params);
+      $this->rawData = $data;
       $result = $this->convert_result($data, $method, $params);
       if (is_array($result) && isset($result['error_code'])) {
         throw new FacebookRestClientException($result['error_msg'],
@@ -3053,6 +3148,16 @@ function toggleDisplay(id, type) {
     return $this->format;
   }
 
+  /**
+   * Returns the raw JSON or XML output returned by the server in the most
+   * recent API call.
+   *
+   * @return string
+   */
+   public function getRawData() {
+     return $this->rawData;
+   }
+
   /**
    * Calls the specified file-upload POST method with the specified parameters
    *
@@ -3144,6 +3249,10 @@ function toggleDisplay(id, type) {
     if ($this->call_as_apikey) {
       $get['call_as_apikey'] = $this->call_as_apikey;
     }
+    if ($this->using_session_secret) {
+      $get['ss'] = '1';
+    }
+
     $get['method'] = $method;
     $get['session_key'] = $this->session_key;
     $get['api_key'] = $this->api_key;
@@ -3241,7 +3350,7 @@ function toggleDisplay(id, type) {
       return $result;
   }
 
-  private function post_upload_request($method, $params, $file, $server_addr = null) {
+  protected function post_upload_request($method, $params, $file, $server_addr = null) {
     $server_addr = $server_addr ? $server_addr : $this->server_addr;
     list($get, $post) = $this->finalize_params($method, $params);
     $get_string = $this->create_url_string($get);
@@ -3345,6 +3454,8 @@ class FacebookAPIErrorCodes {
   const API_EC_VERSION = 12;
   const API_EC_INTERNAL_FQL_ERROR = 13;
   const API_EC_HOST_PUP = 14;
+  const API_EC_SESSION_SECRET_NOT_ALLOWED = 15;
+  const API_EC_HOST_READONLY = 16;
 
   /*
    * PARAMETER ERRORS
@@ -3372,6 +3483,8 @@ class FacebookAPIErrorCodes {
   const API_EC_PARAM_BAD_EID = 150;
   const API_EC_PARAM_UNKNOWN_CITY = 151;
   const API_EC_PARAM_BAD_PAGE_TYPE = 152;
+  const API_EC_PARAM_BAD_LOCALE = 170;
+  const API_EC_PARAM_BLOCKED_NOTIFICATION = 180;
 
   /*
    * USER PERMISSIONS ERRORS
@@ -3394,6 +3507,7 @@ class FacebookAPIErrorCodes {
   const API_EC_PERMISSION_EVENT = 290;
   const API_EC_PERMISSION_LARGE_FBML_TEMPLATE = 291;
   const API_EC_PERMISSION_LIVEMESSAGE = 292;
+  const API_EC_PERMISSION_CREATE_EVENT = 296;
   const API_EC_PERMISSION_RSVP_EVENT = 299;
 
   /*
@@ -3469,6 +3583,8 @@ class FacebookAPIErrorCodes {
   const FQL_EC_EXTENDED_PERMISSION = 612;
   const FQL_EC_RATE_LIMIT_EXCEEDED = 613;
   const FQL_EC_UNRESOLVED_DEPENDENCY = 614;
+  const FQL_EC_INVALID_SEARCH = 615;
+  const FQL_EC_CONTAINS_ERROR = 616;
 
   const API_EC_REF_SET_FAILED = 700;
 
@@ -3506,6 +3622,7 @@ class FacebookAPIErrorCodes {
    * EVENT API ERRORS
    */
   const API_EC_EVENT_INVALID_TIME = 1000;
+  const API_EC_EVENT_NAME_LOCKED  = 1001;
 
   /*
    * INFO BOX ERRORS
@@ -3566,6 +3683,21 @@ class FacebookAPIErrorCodes {
   const API_EC_COMMENTS_INVALID_POST = 1705;
   const API_EC_COMMENTS_INVALID_REMOVE = 1706;
 
+  /*
+   * GIFTS
+   */
+  const API_EC_GIFTS_UNKNOWN = 1900;
+
+  /*
+   * APPLICATION MORATORIUM ERRORS
+   */
+  const API_EC_DISABLED_ALL = 2000;
+  const API_EC_DISABLED_STATUS = 2001;
+  const API_EC_DISABLED_FEED_STORIES = 2002;
+  const API_EC_DISABLED_NOTIFICATIONS = 2003;
+  const API_EC_DISABLED_REQUESTS = 2004;
+  const API_EC_DISABLED_EMAIL = 2005;
+
   /**
    * This array is no longer maintained; to view the description of an error
    * code, please look at the message element of the API response or visit