Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

r2007@opsdev009 (orig r97648): srush | 2008-05-08 14:12:37 -0700

 Added php4 client
  • Loading branch information...
commit 145a9f409bdabead1d99b8a2db0a1afab3b7f497 1 parent 4757500
authored May 08, 2008
292  clients/php4/trunk/facebook.php
... ...
@@ -0,0 +1,292 @@
  1
+<?php
  2
+//
  3
+// +---------------------------------------------------------------------------+
  4
+// | Facebook Platform PHP4 client                                             |
  5
+// +---------------------------------------------------------------------------+
  6
+// | Copyright (c) 2007 Facebook, Inc.                                         |
  7
+// | All rights reserved.                                                      |
  8
+// |                                                                           |
  9
+// | Redistribution and use in source and binary forms, with or without        |
  10
+// | modification, are permitted provided that the following conditions        |
  11
+// | are met:                                                                  |
  12
+// |                                                                           |
  13
+// | 1. Redistributions of source code must retain the above copyright         |
  14
+// |    notice, this list of conditions and the following disclaimer.          |
  15
+// | 2. Redistributions in binary form must reproduce the above copyright      |
  16
+// |    notice, this list of conditions and the following disclaimer in the    |
  17
+// |    documentation and/or other materials provided with the distribution.   |
  18
+// |                                                                           |
  19
+// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      |
  20
+// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
  21
+// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   |
  22
+// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  23
+// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  |
  24
+// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  25
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
  26
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
  27
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  |
  28
+// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         |
  29
+// +---------------------------------------------------------------------------+
  30
+// | For help with this library, contact developers-help@facebook.com          |
  31
+// +---------------------------------------------------------------------------+
  32
+//
  33
+
  34
+include_once 'facebookapi_php4_restlib.php';
  35
+
  36
+class Facebook {
  37
+  var $api_client;
  38
+
  39
+  var $api_key;
  40
+  var $secret;
  41
+  var $generate_session_secret;
  42
+  var $session_expires;
  43
+
  44
+  var $fb_params;
  45
+  var $user;
  46
+
  47
+  var $ec;
  48
+
  49
+  function Facebook($api_key, $secret, $generate_session_secret=false) {
  50
+    $this->api_key                 = $api_key;
  51
+    $this->secret                  = $secret;
  52
+    $this->generate_session_secret = $generate_session_secret;
  53
+
  54
+    $this->api_client = new FacebookRestClient($api_key, $secret, $this);
  55
+    $this->ec         = new FacebookAPIErrorCodes();
  56
+
  57
+    $this->validate_fb_params();
  58
+
  59
+    if (isset($this->fb_params['friends'])) {
  60
+      $this->api_client->friends_list = explode(',', $this->fb_params['friends']);
  61
+    }
  62
+    if (isset($this->fb_params['added'])) {
  63
+      $this->api_client->added = $this->fb_params['added'];
  64
+    }
  65
+  }
  66
+
  67
+  function validate_fb_params($resolve_auth_token=true) {
  68
+    $this->fb_params = $this->get_valid_fb_params($_POST, 48*3600, 'fb_sig');
  69
+    if (!$this->fb_params) {
  70
+      $this->fb_params = $this->get_valid_fb_params($_GET, 48*3600, 'fb_sig');
  71
+    }
  72
+    if ($this->fb_params) {
  73
+      // If we got any fb_params passed in at all, then either:
  74
+      //  - they included an fb_user / fb_session_key, which we should assume to be correct
  75
+      //  - they didn't include an fb_user / fb_session_key, which means the user doesn't have a
  76
+      //    valid session and if we want to get one we'll need to use require_login().  (Calling
  77
+      //    set_user with null values for user/session_key will work properly.)
  78
+      // Note that we should *not* use our cookies in this scenario, since they may be referring to
  79
+      // the wrong user.
  80
+      $user        = isset($this->fb_params['user'])        ? $this->fb_params['user'] : null;
  81
+      $session_key = isset($this->fb_params['session_key']) ? $this->fb_params['session_key'] : null;
  82
+      $expires     = isset($this->fb_params['expires'])     ? $this->fb_params['expires'] : null;
  83
+      $this->set_user($user, $session_key, $expires);
  84
+    } else if (!empty($_COOKIE) && $cookies = $this->get_valid_fb_params($_COOKIE, null, $this->api_key)) {
  85
+      // use $api_key . '_' as a prefix for the cookies in case there are
  86
+      // multiple facebook clients on the same domain.
  87
+      $expires = isset($cookies['expires']) ? $cookies['expires'] : null;
  88
+      $this->set_user($cookies['user'], $cookies['session_key'], $expires);
  89
+    } else if (isset($_GET['auth_token']) && $resolve_auth_token &&
  90
+               $session = $this->do_get_session($_GET['auth_token'])) {
  91
+      $session_secret = ($this->generate_session_secret && !empty($session['secret'])) ? $session['secret'] : null;
  92
+      $this->set_user($session['uid'], $session['session_key'], $session['expires'], $session_secret);
  93
+    }
  94
+
  95
+    return !empty($this->fb_params);
  96
+  }
  97
+
  98
+  // Store a temporary session secret for the current session
  99
+  // for use with the JS client library
  100
+  function promote_session() {
  101
+    $session_secret = $this->api_client->auth_promoteSession();
  102
+    if (!$this->in_fb_canvas()) {
  103
+      $this->set_cookies($this->user, $this->api_client->session_key, $this->session_expires, $session_secret);
  104
+    }
  105
+    return $session_secret;
  106
+  }
  107
+
  108
+  function do_get_session($auth_token) {
  109
+    $res = $this->api_client->auth_getSession($auth_token, $this->generate_session_secret);
  110
+    if (is_array($res)) {
  111
+      return $res;
  112
+    }
  113
+    return false;
  114
+  }
  115
+
  116
+  // Invalidate the session currently being used, and clear any state associated with it
  117
+  function expire_session() {
  118
+    if ($this->api_client->auth_expireSession()) {
  119
+      // To clear the state, essentially perform the opposite of set_user
  120
+      if (!$this->in_fb_canvas() && (isset($_COOKIE[$this->api_key . '_user']))) {
  121
+        $cookies = array('user', 'session_key', 'expires', 'ss');
  122
+        foreach ($cookies as $name) {
  123
+          setcookie($this->api_key . '_' . $name, false, time() - 3600);
  124
+          unset($_COOKIE[$this->api_key . '_' . $name]);
  125
+        }
  126
+        setcookie($this->api_key, false, time() - 3600);
  127
+        unset($_COOKIE[$this->api_key]);
  128
+      }
  129
+
  130
+      // now, clear the rest of the stored state
  131
+      $this->user = 0;
  132
+      $this->api_client->session_key = 0;
  133
+      return true;
  134
+    } else {
  135
+      return false;
  136
+    }
  137
+  }
  138
+
  139
+  function redirect($url) {
  140
+    if ($this->in_fb_canvas()) {
  141
+      echo '<fb:redirect url="' . $url . '"/>';
  142
+    } else if (preg_match('/^https?:\/\/([^\/]*\.)?facebook\.com(:\d+)?/i', $url)) {
  143
+      // make sure facebook.com url's load in the full frame so that we don't
  144
+      // get a frame within a frame.
  145
+      echo "<script type=\"text/javascript\">\ntop.location.href = \"$url\";\n</script>";
  146
+    } else {
  147
+      http_header('Location', $url);
  148
+    }
  149
+    exit;
  150
+  }
  151
+
  152
+  function in_frame() {
  153
+    return isset($this->fb_params['in_canvas']) || isset($this->fb_params['in_iframe']);
  154
+  }
  155
+  function in_fb_canvas() {
  156
+    return isset($this->fb_params['in_canvas']);
  157
+  }
  158
+
  159
+  function get_loggedin_user() {
  160
+    return $this->user;
  161
+  }
  162
+
  163
+  function current_url() {
  164
+    return 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  165
+  }
  166
+
  167
+  function require_login() {
  168
+    if ($user = $this->get_loggedin_user()) {
  169
+      return $user;
  170
+    }
  171
+    $this->redirect($this->get_login_url($this->current_url(), $this->in_frame()));
  172
+  }
  173
+
  174
+  function require_install() {
  175
+    // this was renamed, keeping for compatibility's sake
  176
+    return $this->require_add();
  177
+  }
  178
+
  179
+  function require_add() {
  180
+    if ($user = $this->get_loggedin_user()) {
  181
+      if ($this->fb_params['added']) {
  182
+        return $user;
  183
+      }
  184
+    }
  185
+    $this->redirect($this->get_add_url($this->current_url()));
  186
+  }
  187
+
  188
+  function require_frame() {
  189
+    if (!$this->in_frame()) {
  190
+      $this->redirect($this->get_login_url($this->current_url(), true));
  191
+    }
  192
+  }
  193
+
  194
+  function get_facebook_url($subdomain='www') {
  195
+    return 'http://' . $subdomain . '.facebook.com';
  196
+  }
  197
+
  198
+  function get_install_url($next=null) {
  199
+    // this was renamed, keeping for compatibility's sake
  200
+    return $this->get_add_url($next);
  201
+  }
  202
+
  203
+  function get_add_url($next=null) {
  204
+    return $this->get_facebook_url().'/add.php?api_key='.$this->api_key .
  205
+      ($next ? '&next=' . urlencode($next) : '');
  206
+  }
  207
+
  208
+  function get_login_url($next, $canvas) {
  209
+    return $this->get_facebook_url().'/login.php?v=1.0&api_key=' . $this->api_key .
  210
+      ($next ? '&next=' . urlencode($next)  : '') .
  211
+      ($canvas ? '&canvas' : '');
  212
+  }
  213
+
  214
+  function generate_sig($params_array, $secret) {
  215
+    $str = '';
  216
+
  217
+    ksort($params_array);
  218
+    // Note: make sure that the signature parameter is not already included in
  219
+    //       $params_array.
  220
+    foreach ($params_array as $k=>$v) {
  221
+      $str .= "$k=$v";
  222
+    }
  223
+    $str .= $secret;
  224
+
  225
+    return md5($str);
  226
+  }
  227
+
  228
+  function set_user($user, $session_key, $expires=null, $session_secret=null) {
  229
+    if (!$this->in_fb_canvas() && (!isset($_COOKIE[$this->api_key . '_user'])
  230
+                                   || $_COOKIE[$this->api_key . '_user'] != $user)) {
  231
+      $this->set_cookies($user, $session_key, $expires, $session_secret);
  232
+    }
  233
+    $this->user = $user;
  234
+    $this->api_client->session_key = $session_key;
  235
+    $this->session_expires = $expires;
  236
+  }
  237
+
  238
+  function set_cookies($user, $session_key, $expires=null, $session_secret=null) {
  239
+    $cookies = array();
  240
+    $cookies['user'] = $user;
  241
+    $cookies['session_key'] = $session_key;
  242
+    if ($expires != null) {
  243
+      $cookies['expires'] = $expires;
  244
+    }
  245
+    if ($session_secret != null) {
  246
+      $cookies['ss'] = $session_secret;
  247
+    }
  248
+    foreach ($cookies as $name => $val) {
  249
+      setcookie($this->api_key . '_' . $name, $val, (int)$expires);
  250
+      $_COOKIE[$this->api_key . '_' . $name] = $val;
  251
+    }
  252
+    $sig = $this->generate_sig($cookies, $this->secret);
  253
+    setcookie($this->api_key, $sig, (int)$expires);
  254
+    $_COOKIE[$this->api_key] = $sig;
  255
+  }
  256
+
  257
+  /**
  258
+   * Tries to undo the badness of magic quotes as best we can
  259
+   * @param     string   $val   Should come directly from $_GET, $_POST, etc.
  260
+   * @return    string   val without added slashes
  261
+   */
  262
+  function no_magic_quotes($val) {
  263
+    if (get_magic_quotes_gpc()) {
  264
+      return stripslashes($val);
  265
+    } else {
  266
+      return $val;
  267
+    }
  268
+  }
  269
+
  270
+  function get_valid_fb_params($params, $timeout=null, $namespace='fb_sig') {
  271
+    $prefix = $namespace . '_';
  272
+    $prefix_len = strlen($prefix);
  273
+    $fb_params = array();
  274
+    foreach ($params as $name => $val) {
  275
+      if (strpos($name, $prefix) === 0) {
  276
+        $fb_params[substr($name, $prefix_len)] = $this->no_magic_quotes($val);
  277
+      }
  278
+    }
  279
+    if ($timeout && (!isset($fb_params['time']) || time() - $fb_params['time'] > $timeout)) {
  280
+      return array();
  281
+    }
  282
+    if (!isset($params[$namespace]) || !$this->verify_signature($fb_params, $params[$namespace])) {
  283
+      return array();
  284
+    }
  285
+    return $fb_params;
  286
+  }
  287
+
  288
+  function verify_signature($fb_params, $expected_sig) {
  289
+    return $this->generate_sig($fb_params, $this->secret) == $expected_sig;
  290
+  }
  291
+}
  292
+
1,736  clients/php4/trunk/facebookapi_php4_restlib.php
... ...
@@ -0,0 +1,1736 @@
  1
+<?php
  2
+//
  3
+// +---------------------------------------------------------------------------+
  4
+// | Facebook Platform PHP4 client                                 |
  5
+// +---------------------------------------------------------------------------+
  6
+// | Copyright (c) 2007 Facebook, Inc.                                         |
  7
+// | All rights reserved.                                                      |
  8
+// |                                                                           |
  9
+// | Redistribution and use in source and binary forms, with or without        |
  10
+// | modification, are permitted provided that the following conditions        |
  11
+// | are met:                                                                  |
  12
+// |                                                                           |
  13
+// | 1. Redistributions of source code must retain the above copyright         |
  14
+// |    notice, this list of conditions and the following disclaimer.          |
  15
+// | 2. Redistributions in binary form must reproduce the above copyright      |
  16
+// |    notice, this list of conditions and the following disclaimer in the    |
  17
+// |    documentation and/or other materials provided with the distribution.   |
  18
+// |                                                                           |
  19
+// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      |
  20
+// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
  21
+// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   |
  22
+// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  23
+// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  |
  24
+// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  25
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
  26
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
  27
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  |
  28
+// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         |
  29
+// +---------------------------------------------------------------------------+
  30
+// | For help with this library, contact developers-help@facebook.com          |
  31
+// +---------------------------------------------------------------------------+
  32
+//
  33
+
  34
+include_once 'simplexml44-0_4_4/class/IsterXmlSimpleXMLImpl.php';
  35
+
  36
+class FacebookRestClient {
  37
+  var $secret;
  38
+  var $session_key;
  39
+  var $api_key;
  40
+  var $facebook;
  41
+  var $error_code;
  42
+  var $friends_list; // to save making the friends.get api call, this will get prepopulated on canvas pages
  43
+  var $added;        // to save making the users.isAppAdded api call, this will get prepopulated on canvas pages
  44
+  var $call_as_apikey;
  45
+
  46
+  /**
  47
+   * Create the client.
  48
+   * @param string $session_key if you haven't gotten a session key yet, leave
  49
+   *                            this as null and then set it later by just
  50
+   *                            directly accessing the $session_key member
  51
+   *                            variable.
  52
+   */
  53
+  function FacebookRestClient($api_key, $secret, &$facebook, $session_key=null) {
  54
+    $this->secret       = $secret;
  55
+    $this->session_key  = $session_key;
  56
+    $this->api_key      = $api_key;
  57
+    $this->last_call_id = 0;
  58
+    $this->facebook     = &$facebook;
  59
+    $this->error_code   = 0;
  60
+    $this->call_as_apikey = '';
  61
+    $this->server_addr  = $this->facebook->get_facebook_url('api') . '/restserver.php';
  62
+    if (!empty($GLOBALS['facebook_config']['debug'])) {
  63
+      $this->cur_id = 0;
  64
+      ?>
  65
+<script type="text/javascript">
  66
+var types = ['params', 'xml', 'php', 'sxml'];
  67
+function getStyle(elem, style) {
  68
+  if (elem.getStyle) {
  69
+    return elem.getStyle(style);
  70
+  } else {
  71
+    return elem.style[style];
  72
+  }
  73
+}
  74
+function setStyle(elem, style, value) {
  75
+  if (elem.setStyle) {
  76
+    elem.setStyle(style, value);
  77
+  } else {
  78
+    elem.style[style] = value;
  79
+  }
  80
+}
  81
+function toggleDisplay(id, type) {
  82
+  for (var i = 0; i < types.length; i++) {
  83
+    var t = types[i];
  84
+    var pre = document.getElementById(t + id);
  85
+    if (pre) {
  86
+      if (t != type || getStyle(pre, 'display') == 'block') {
  87
+        setStyle(pre, 'display', 'none');
  88
+      } else {
  89
+        setStyle(pre, 'display', 'block');
  90
+      }
  91
+    }
  92
+  }
  93
+  return false;
  94
+}
  95
+</script>
  96
+<?php
  97
+    }
  98
+  }
  99
+
  100
+  function begin_permissions_mode($permissions_apikey) {
  101
+    $this->call_as_apikey = $permissions_apikey;
  102
+  }
  103
+
  104
+  function end_permissions_mode() {
  105
+    $this->call_as_apikey = '';
  106
+  }
  107
+
  108
+  /**
  109
+   * Returns the session information available after current user logs in.
  110
+   * @param string $auth_token the token returned by auth_createToken or
  111
+   *  passed back to your callback_url.
  112
+   * @param bool   $generate_session_secret  whether the session returned should include a session secret
  113
+   * @return assoc array containing session_key, uid
  114
+   */
  115
+  function auth_getSession($auth_token, $generate_session_secret=false) {
  116
+    $result = $this->call_method('facebook.auth.getSession',
  117
+        array('auth_token'=>$auth_token, 'generate_session_secret' => $generate_session_secret));
  118
+    $this->session_key = $result['session_key'];
  119
+    if (!empty($result['secret']) && !$generate_session_secret) {
  120
+      // desktop apps have a special secret
  121
+      $this->secret = $result['secret'];
  122
+    }
  123
+    return $result;
  124
+  }
  125
+
  126
+  /**
  127
+   * Generates a session specific secret. This is for integration with client-side API calls, such as the
  128
+   * JS library.
  129
+   * @error API_EC_PARAM_SESSION_KEY
  130
+   *        API_EC_PARAM_UNKNOWN
  131
+   * @return session secret for the current promoted session
  132
+   */
  133
+  function auth_promoteSession() {
  134
+    return $this->call_method('facebook.auth.promoteSession', array());
  135
+  }
  136
+
  137
+  /**
  138
+   * Expires the session that is currently being used.  If this call is successful, no further calls to the
  139
+   * API (which require a session) can be made until a valid session is created.
  140
+   *
  141
+   * @return bool  true if session expiration was successful, false otherwise
  142
+   */
  143
+  function auth_expireSession() {
  144
+    return $this->call_method('facebook.auth.expireSession', array());
  145
+  }
  146
+
  147
+
  148
+  /**
  149
+   * Returns events according to the filters specified.
  150
+   * @param int $uid Optional: User associated with events.
  151
+   *   A null parameter will default to the session user.
  152
+   * @param array $eids Optional: Filter by these event ids.
  153
+   *   A null parameter will get all events for the user.
  154
+   * @param int $start_time Optional: Filter with this UTC as lower bound.
  155
+   *   A null or zero parameter indicates no lower bound.
  156
+   * @param int $end_time Optional: Filter with this UTC as upper bound.
  157
+   *   A null or zero parameter indicates no upper bound.
  158
+   * @param string $rsvp_status Optional: Only show events where the given uid
  159
+   *   has this rsvp status.  This only works if you have specified a value for
  160
+   *   $uid.  Values are as in events.getMembers.  Null indicates to ignore
  161
+   *   rsvp status when filtering.
  162
+   * @return array of events
  163
+   */
  164
+  function events_get($uid, $eids, $start_time, $end_time, $rsvp_status) {
  165
+    return $this->call_method('facebook.events.get',
  166
+        array(
  167
+        'uid' => $uid,
  168
+        'eids' => $eids,
  169
+        'start_time' => $start_time,
  170
+        'end_time' => $end_time,
  171
+        'rsvp_status' => $rsvp_status));
  172
+  }
  173
+
  174
+  /**
  175
+   * Returns membership list data associated with an event
  176
+   * @param int $eid : event id
  177
+   * @return assoc array of four membership lists, with keys 'attending',
  178
+   *  'unsure', 'declined', and 'not_replied'
  179
+   */
  180
+  function events_getMembers($eid) {
  181
+    return $this->call_method('facebook.events.getMembers',
  182
+      array('eid' => $eid));
  183
+  }
  184
+
  185
+  /**
  186
+   * Makes an FQL query.  This is a generalized way of accessing all the data
  187
+   * in the API, as an alternative to most of the other method calls.  More
  188
+   * info at http://developers.facebook.com/documentation.php?v=1.0&doc=fql
  189
+   * @param string $query the query to evaluate
  190
+   * @return generalized array representing the results
  191
+   */
  192
+  function fql_query($query) {
  193
+    return $this->call_method('facebook.fql.query',
  194
+      array('query' => $query));
  195
+  }
  196
+
  197
+  function feed_publishStoryToUser($title, $body,
  198
+                                   $image_1=null, $image_1_link=null,
  199
+                                   $image_2=null, $image_2_link=null,
  200
+                                   $image_3=null, $image_3_link=null,
  201
+                                   $image_4=null, $image_4_link=null) {
  202
+    return $this->call_method('facebook.feed.publishStoryToUser',
  203
+      array('title' => $title,
  204
+            'body' => $body,
  205
+            'image_1' => $image_1,
  206
+            'image_1_link' => $image_1_link,
  207
+            'image_2' => $image_2,
  208
+            'image_2_link' => $image_2_link,
  209
+            'image_3' => $image_3,
  210
+            'image_3_link' => $image_3_link,
  211
+            'image_4' => $image_4,
  212
+            'image_4_link' => $image_4_link));
  213
+  }
  214
+
  215
+  function feed_publishActionOfUser($title, $body,
  216
+                                    $image_1=null, $image_1_link=null,
  217
+                                    $image_2=null, $image_2_link=null,
  218
+                                    $image_3=null, $image_3_link=null,
  219
+                                    $image_4=null, $image_4_link=null) {
  220
+    return $this->call_method('facebook.feed.publishActionOfUser',
  221
+      array('title' => $title,
  222
+            'body' => $body,
  223
+            'image_1' => $image_1,
  224
+            'image_1_link' => $image_1_link,
  225
+            'image_2' => $image_2,
  226
+            'image_2_link' => $image_2_link,
  227
+            'image_3' => $image_3,
  228
+            'image_3_link' => $image_3_link,
  229
+            'image_4' => $image_4,
  230
+            'image_4_link' => $image_4_link));
  231
+  }
  232
+
  233
+  function feed_publishTemplatizedAction($title_template, $title_data,
  234
+                                         $body_template, $body_data, $body_general,
  235
+                                         $image_1=null, $image_1_link=null,
  236
+                                         $image_2=null, $image_2_link=null,
  237
+                                         $image_3=null, $image_3_link=null,
  238
+                                         $image_4=null, $image_4_link=null,
  239
+                                         $target_ids='', $page_actor_id=null) {
  240
+    return $this->call_method('facebook.feed.publishTemplatizedAction',
  241
+      array('title_template' => $title_template,
  242
+            'title_data' => $title_data,
  243
+            'body_template' => $body_template,
  244
+            'body_data' => $body_data,
  245
+            'body_general' => $body_general,
  246
+            'image_1' => $image_1,
  247
+            'image_1_link' => $image_1_link,
  248
+            'image_2' => $image_2,
  249
+            'image_2_link' => $image_2_link,
  250
+            'image_3' => $image_3,
  251
+            'image_3_link' => $image_3_link,
  252
+            'image_4' => $image_4,
  253
+            'image_4_link' => $image_4_link,
  254
+            'target_ids' => $target_ids,
  255
+            'page_actor_id' => $page_actor_id));
  256
+  }
  257
+
  258
+  /**
  259
+   * Returns whether or not pairs of users are friends.
  260
+   * Note that the Facebook friend relationship is symmetric.
  261
+   * @param array $uids1: array of ids (id_1, id_2,...) of some length X
  262
+   * @param array $uids2: array of ids (id_A, id_B,...) of SAME length X
  263
+   * @return array of uid pairs with bool, true if pair are friends, e.g.
  264
+   *   array( 0 => array('uid1' => id_1, 'uid2' => id_A, 'are_friends' => 1),
  265
+   *          1 => array('uid1' => id_2, 'uid2' => id_B, 'are_friends' => 0)
  266
+   *         ...)
  267
+   */
  268
+  function friends_areFriends($uids1, $uids2) {
  269
+    return $this->call_method('facebook.friends.areFriends',
  270
+        array('uids1'=>$uids1, 'uids2'=>$uids2));
  271
+  }
  272
+
  273
+  /**
  274
+   * Returns the friends of the current session user.
  275
+   * @return array of friends
  276
+   */
  277
+  function friends_get() {
  278
+    if (isset($this->friends_list)) {
  279
+      return $this->friends_list;
  280
+    }
  281
+    return $this->call_method('facebook.friends.get', array());
  282
+  }
  283
+
  284
+  /**
  285
+   * Returns the friends of the session user, who are also users
  286
+   * of the calling application.
  287
+   * @return array of friends
  288
+   */
  289
+  function friends_getAppUsers() {
  290
+    return $this->call_method('facebook.friends.getAppUsers', array());
  291
+  }
  292
+
  293
+  /**
  294
+   * Returns groups according to the filters specified.
  295
+   * @param int $uid Optional: User associated with groups.
  296
+   *  A null parameter will default to the session user.
  297
+   * @param array $gids Optional: group ids to query.
  298
+   *   A null parameter will get all groups for the user.
  299
+   * @return array of groups
  300
+   */
  301
+  function groups_get($uid, $gids) {
  302
+    return $this->call_method('facebook.groups.get',
  303
+        array(
  304
+        'uid' => $uid,
  305
+        'gids' => $gids));
  306
+  }
  307
+
  308
+  /**
  309
+   * Returns the membership list of a group
  310
+   * @param int $gid : Group id
  311
+   * @return assoc array of four membership lists, with keys
  312
+   *  'members', 'admins', 'officers', and 'not_replied'
  313
+   */
  314
+  function groups_getMembers($gid) {
  315
+    return $this->call_method('facebook.groups.getMembers',
  316
+      array('gid' => $gid));
  317
+  }
  318
+
  319
+  /**
  320
+   * Returns cookies according to the filters specified.
  321
+   * @param int $uid Required: User for which the cookies are needed.
  322
+   * @param string $name Optional:
  323
+   *   A null parameter will get all cookies for the user.
  324
+   * @return array of cookies
  325
+   */
  326
+  function data_getCookies($uid, $name) {
  327
+    return $this->call_method('facebook.data.getCookies',
  328
+        array(
  329
+        'uid' => $uid,
  330
+        'name' => $name));
  331
+  }
  332
+
  333
+  /**
  334
+   * Sets cookies according to the params specified.
  335
+   * @param int $uid Required: User for which the cookies are needed.
  336
+   * @param string $name Required: name of the cookie
  337
+   * @param string $value Optional if expires specified and is in the past
  338
+   * @param int$expires Optional
  339
+   * @param string $path Optional
  340
+   *
  341
+   * @return bool
  342
+   */
  343
+  function data_setCookie($uid, $name, $value, $expires, $path) {
  344
+    return $this->call_method('facebook.data.setCookie',
  345
+        array(
  346
+        'uid' => $uid,
  347
+        'name' => $name,
  348
+        'value' => $value,
  349
+        'expires' => $expires,
  350
+        'path' => $path));
  351
+  }
  352
+
  353
+  /**
  354
+   * Permissions API
  355
+   */
  356
+
  357
+  /**
  358
+   * Checks API-access granted by self to the specified application
  359
+   * @param string $permissions_apikey: Required
  360
+   *
  361
+   * @return array: API methods/namespaces which are allowed access
  362
+   */
  363
+  function permissions_checkGrantedApiAccess($permissions_apikey) {
  364
+    return $this->call_method('facebook.permissions.checkGrantedApiAccess',
  365
+        array(
  366
+        'permissions_apikey' => $permissions_apikey));
  367
+  }
  368
+
  369
+  /**
  370
+   * Checks API-access granted to self by the specified application
  371
+   * @param string $permissions_apikey: Required
  372
+   *
  373
+   * @return array: API methods/namespaces which are allowed access
  374
+   */
  375
+  function permissions_checkAvailableApiAccess($permissions_apikey) {
  376
+    return $this->call_method('facebook.permissions.checkAvailableApiAccess',
  377
+        array(
  378
+        'permissions_apikey' => $permissions_apikey));
  379
+  }
  380
+
  381
+  /**
  382
+   * Grant API-access to the specified methods/namespaces to the specified application
  383
+   * @param string $permissions_apikey: Required
  384
+   * @param array(string) : Optional: API methods/namespaces to be allowed
  385
+   *
  386
+   * @return array: API methods/namespaces which are allowed access
  387
+   */
  388
+  function permissions_grantApiAccess($permissions_apikey, $method_arr) {
  389
+    return $this->call_method('facebook.permissions.grantApiAccess',
  390
+        array(
  391
+        'permissions_apikey' => $permissions_apikey,
  392
+        'method_arr' => $method_arr));
  393
+  }
  394
+
  395
+  /**
  396
+   * Revoke API-access granted to the specified application
  397
+   * @param string $permissions_apikey: Required
  398
+   *
  399
+   * @return bool
  400
+   */
  401
+  function permissions_revokeApiAccess($permissions_apikey) {
  402
+    return $this->call_method('facebook.permissions.revokeApiAccess',
  403
+        array(
  404
+        'permissions_apikey' => $permissions_apikey));
  405
+  }
  406
+
  407
+
  408
+  /**
  409
+   * Returns the outstanding notifications for the session user.
  410
+   * @return assoc array of
  411
+   *  notification count objects for 'messages', 'pokes' and 'shares',
  412
+   *  a uid list of 'friend_requests', a gid list of 'group_invites',
  413
+   *  and an eid list of 'event_invites'
  414
+   */
  415
+  function notifications_get() {
  416
+    return $this->call_method('facebook.notifications.get', array());
  417
+  }
  418
+
  419
+  /**
  420
+   * Sends a notification to the specified users.
  421
+   * @return (nothing)
  422
+   */
  423
+  function notifications_send($to_ids, $notification) {
  424
+    return $this->call_method('facebook.notifications.send',
  425
+                              array('to_ids' => $to_ids, 'notification' => $notification));
  426
+  }
  427
+
  428
+  /**
  429
+   * Sends an email to the specified user of the application.
  430
+   * @param array $recipients : ids of the recipients
  431
+   * @param string $subject : subject of the email
  432
+   * @param string $text : (plain text) body of the email
  433
+   * @param string $fbml : fbml markup if you want an html version of the email
  434
+   * @return comma separated list of successful recipients
  435
+   */
  436
+  function notifications_sendEmail($recipients, $subject, $text, $fbml) {
  437
+    return $this->call_method('facebook.notifications.sendEmail',
  438
+                              array('recipients' => $recipients,
  439
+                                    'subject' => $subject,
  440
+                                    'text' => $text,
  441
+                                    'fbml' => $fbml));
  442
+  }
  443
+
  444
+  /**
  445
+   * Returns the requested info fields for the requested set of pages
  446
+   * @param array $page_ids an array of page ids
  447
+   * @param array $fields an array of strings describing the info fields desired
  448
+   * @param int $uid   Optionally, limit results to pages of which this user is a fan.
  449
+   * @param string type  limits results to a particular type of page.
  450
+   * @return array of pages
  451
+   */
  452
+  function pages_getInfo($page_ids, $fields, $uid, $type) {
  453
+    return $this->call_method('facebook.pages.getInfo', array('page_ids' => $page_ids, 'fields' => $fields, 'uid' => $uid, 'type' => $type));
  454
+  }
  455
+
  456
+  /**
  457
+   * Returns true if logged in user is an admin for the passed page
  458
+   * @param int $page_id target page id
  459
+   * @return boolean
  460
+   */
  461
+  function pages_isAdmin($page_id) {
  462
+    return $this->call_method('facebook.pages.isAdmin', array('page_id' => $page_id));
  463
+  }
  464
+
  465
+  /**
  466
+   * Returns whether or not the page corresponding to the current session object has the app installed
  467
+   * @return boolean
  468
+   */
  469
+  function pages_isAppAdded() {
  470
+    if (isset($this->added)) {
  471
+      return $this->added;
  472
+    }
  473
+    return $this->call_method('facebook.pages.isAppAdded', array());
  474
+  }
  475
+
  476
+  /**
  477
+   * Returns true if logged in user is a fan for the passed page
  478
+   * @param int $page_id target page id
  479
+   * @param int $uid user to compare.  If empty, the logged in user.
  480
+   * @return bool
  481
+   */
  482
+  function pages_isFan($page_id, $uid) {
  483
+    return $this->call_method('facebook.pages.isFan', array('page_id' => $page_id, 'uid' => $uid));
  484
+  }
  485
+
  486
+  /**
  487
+   * Returns photos according to the filters specified.
  488
+   * @param int $subj_id Optional: Filter by uid of user tagged in the photos.
  489
+   * @param int $aid Optional: Filter by an album, as returned by
  490
+   *  photos_getAlbums.
  491
+   * @param array $pids Optional: Restrict to a list of pids
  492
+   * Note that at least one of these parameters needs to be specified, or an
  493
+   * error is returned.
  494
+   * @return array of photo objects.
  495
+   */
  496
+  function photos_get($subj_id, $aid, $pids) {
  497
+    return $this->call_method('facebook.photos.get',
  498
+      array('subj_id' => $subj_id, 'aid' => $aid, 'pids' => $pids));
  499
+  }
  500
+
  501
+  /**
  502
+   * Returns the albums created by the given user.
  503
+   * @param int $uid Optional: the uid of the user whose albums you want.
  504
+   *   A null value will return the albums of the session user.
  505
+   * @param array $aids Optional: a list of aids to restrict the query.
  506
+   * Note that at least one of the (uid, aids) parameters must be specified.
  507
+   * @returns an array of album objects.
  508
+   */
  509
+  function photos_getAlbums($uid, $aids) {
  510
+    return $this->call_method('facebook.photos.getAlbums',
  511
+      array('uid' => $uid,
  512
+            'aids' => $aids));
  513
+  }
  514
+
  515
+  /**
  516
+   * Returns the tags on all photos specified.
  517
+   * @param string $pids : a list of pids to query
  518
+   * @return array of photo tag objects, with include pid, subject uid,
  519
+   *  and two floating-point numbers (xcoord, ycoord) for tag pixel location
  520
+   */
  521
+  function photos_getTags($pids) {
  522
+    return $this->call_method('facebook.photos.getTags',
  523
+      array('pids' => $pids));
  524
+  }
  525
+
  526
+  /**
  527
+   * Returns the requested info fields for the requested set of users
  528
+   * @param array $uids an array of user ids
  529
+   * @param array $fields an array of strings describing the info fields desired
  530
+   * @return array of users
  531
+   */
  532
+  function users_getInfo($uids, $fields) {
  533
+    return $this->call_method('facebook.users.getInfo', array('uids' => $uids, 'fields' => $fields));
  534
+  }
  535
+
  536
+  /**
  537
+   * Returns the user corresponding to the current session object.
  538
+   * @return integer uid
  539
+   */
  540
+  function users_getLoggedInUser() {
  541
+    return $this->call_method('facebook.users.getLoggedInUser', array());
  542
+  }
  543
+
  544
+
  545
+  /**
  546
+   * Returns whether or not the user corresponding to the current session object has the app installed
  547
+   * @return boolean
  548
+   */
  549
+  function users_isAppAdded($uid=null) {
  550
+    if (isset($this->added)) {
  551
+      return $this->added;
  552
+    }
  553
+    return $this->call_method('facebook.users.isAppAdded', array('uid' => $uid));
  554
+  }
  555
+
  556
+  /**
  557
+   * Sets the FBML for the profile of the user attached to this session
  558
+   * @param   string   $markup     The FBML that describes the profile presence of this app for the user
  559
+   * @param   int      $uid              The user
  560
+   * @param   string   $profile          Profile FBML
  561
+   * @param   string   $profile_action   Profile action FBML
  562
+   * @param   string   $mobile_profile   Mobile profile FBML
  563
+   * @return  array    A list of strings describing any compile errors for the submitted FBML
  564
+   */
  565
+  function profile_setFBML($markup, $uid = null, $profile='', $profile_action='', $mobile_profile='') {
  566
+    return $this->call_method('facebook.profile.setFBML', array('markup' => $markup,
  567
+                                                                'uid' => $uid,
  568
+                                                                'profile' => $profile,
  569
+                                                                'profile_action' => $profile_action,
  570
+                                                                'mobile_profile' => $mobile_profile));
  571
+  }
  572
+
  573
+  function profile_getFBML($uid) {
  574
+    return $this->call_method('facebook.profile.getFBML', array('uid' => $uid));
  575
+  }
  576
+
  577
+  function fbml_refreshImgSrc($url) {
  578
+    return $this->call_method('facebook.fbml.refreshImgSrc', array('url' => $url));
  579
+  }
  580
+
  581
+  function fbml_refreshRefUrl($url) {
  582
+    return $this->call_method('facebook.fbml.refreshRefUrl', array('url' => $url));
  583
+  }
  584
+
  585
+  function fbml_setRefHandle($handle, $fbml) {
  586
+    return $this->call_method('facebook.fbml.setRefHandle', array('handle' => $handle, 'fbml' => $fbml));
  587
+  }
  588
+
  589
+  /**
  590
+   * Get all the marketplace categories
  591
+   *
  592
+   * @return array  A list of category names
  593
+   */
  594
+  function marketplace_getCategories() {
  595
+    return $this->call_method('facebook.marketplace.getCategories', array());
  596
+  }
  597
+
  598
+  /**
  599
+   * Get all the marketplace subcategories for a particular category
  600
+   *
  601
+   * @param  category  The category for which we are pulling subcategories
  602
+   * @return array     A list of subcategory names
  603
+   */
  604
+  function marketplace_getSubCategories($category) {
  605
+    return $this->call_method('facebook.marketplace.getSubCategories', array('category' => $category));
  606
+  }
  607
+
  608
+  /**
  609
+   * Get listings by either listing_id or user
  610
+   *
  611
+   * @param listing_ids   An array of listing_ids (optional)
  612
+   * @param uids          An array of user ids (optional)
  613
+   * @return array        The data for matched listings
  614
+   */
  615
+  function marketplace_getListings($listing_ids, $uids) {
  616
+    return $this->call_method('facebook.marketplace.getListings', array('listing_ids' => $listing_ids, 'uids' => $uids));
  617
+  }
  618
+
  619
+  /**
  620
+   * Search for Marketplace listings.  All arguments are optional, though at least
  621
+   * one must be filled out to retrieve results.
  622
+   *
  623
+   * @param category     The category in which to search (optional)
  624
+   * @param subcategory  The subcategory in which to search (optional)
  625
+   * @param query        A query string (optional)
  626
+   * @return array       The data for matched listings
  627
+   */
  628
+  function marketplace_search($category, $subcategory, $query) {
  629
+    return $this->call_method('facebook.marketplace.search', array('category' => $category, 'subcategory' => $subcategory, 'query' => $query));
  630
+  }
  631
+
  632
+  /**
  633
+   * Remove a listing from Marketplace
  634
+   *
  635
+   * @param listing_id  The id of the listing to be removed
  636
+   * @param status      'SUCCESS', 'NOT_SUCCESS', or 'DEFAULT'
  637
+   * @return bool       True on success
  638
+   */
  639
+  function marketplace_removeListing($listing_id, $status='DEFAULT', $uid=null) {
  640
+    return $this->call_method('facebook.marketplace.removeListing',
  641
+                              array('listing_id'=>$listing_id,
  642
+                                    'status'=>$status,
  643
+                                    'uid' => $uid));
  644
+  }
  645
+
  646
+  /**
  647
+   * Create/modify a Marketplace listing for the loggedinuser
  648
+   *
  649
+   * @param int              listing_id   The id of a listing to be modified, 0 for a new listing.
  650
+   * @param show_on_profile  bool         Should we show this listing on the user's profile
  651
+   * @param attrs            array        An array of the listing data
  652
+   * @return                 int          The listing_id (unchanged if modifying an existing listing)
  653
+   */
  654
+  function marketplace_createListing($listing_id, $show_on_profile, $attrs, $uid=null) {
  655
+    return $this->call_method('facebook.marketplace.createListing',
  656
+                              array('listing_id'=>$listing_id,
  657
+                                    'show_on_profile'=>$show_on_profile,
  658
+                                    'listing_attrs'=>json_encode($attrs),
  659
+                                    'uid' => $uid));
  660
+  }
  661
+
  662
+
  663
+  /////////////////////////////////////////////////////////////////////////////
  664
+  // Data Store API
  665
+
  666
+  /**
  667
+   * Set a user preference.
  668
+   *
  669
+   * @param  pref_id    preference identifier (0-200)
  670
+   * @param  value      preferece's value
  671
+   * @error
  672
+   *    API_EC_DATA_DATABASE_ERROR
  673
+   *    API_EC_PARAM
  674
+   *    API_EC_DATA_QUOTA_EXCEEDED
  675
+   *    API_EC_DATA_UNKNOWN_ERROR
  676
+   */
  677
+  function data_setUserPreference($pref_id, $value) {
  678
+    return $this->call_method
  679
+      ('facebook.data.setUserPreference',
  680
+       array('pref_id' => $pref_id,
  681
+             'value' => $value));
  682
+  }
  683
+
  684
+  /**
  685
+   * Set a user's all preferences for this application.
  686
+   *
  687
+   * @param  values     preferece values in an associative arrays
  688
+   * @param  replace    whether to replace all existing preferences or
  689
+   *                    merge into them.
  690
+   * @error
  691
+   *    API_EC_DATA_DATABASE_ERROR
  692
+   *    API_EC_PARAM
  693
+   *    API_EC_DATA_QUOTA_EXCEEDED
  694
+   *    API_EC_DATA_UNKNOWN_ERROR
  695
+   */
  696
+  function data_setUserPreferences($values, $replace = false) {
  697
+    return $this->call_method
  698
+      ('facebook.data.setUserPreferences',
  699
+       array('values' => json_encode($values),
  700
+             'replace' => $replace));
  701
+  }
  702
+
  703
+  /**
  704
+   * Get a user preference.
  705
+   *
  706
+   * @param  pref_id    preference identifier (0-200)
  707
+   * @return            preference's value
  708
+   * @error
  709
+   *    API_EC_DATA_DATABASE_ERROR
  710
+   *    API_EC_PARAM
  711
+   *    API_EC_DATA_QUOTA_EXCEEDED
  712
+   *    API_EC_DATA_UNKNOWN_ERROR
  713
+   */
  714
+  function data_getUserPreference($pref_id) {
  715
+    return $this->call_method
  716
+      ('facebook.data.getUserPreference',
  717
+       array('pref_id' => $pref_id));
  718
+  }
  719
+
  720
+  /**
  721
+   * Get a user preference.
  722
+   *
  723
+   * @return           preference values
  724
+   * @error
  725
+   *    API_EC_DATA_DATABASE_ERROR
  726
+   *    API_EC_DATA_QUOTA_EXCEEDED
  727
+   *    API_EC_DATA_UNKNOWN_ERROR
  728
+   */
  729
+  function data_getUserPreferences() {
  730
+    return $this->call_method
  731
+      ('facebook.data.getUserPreferences',
  732
+       array());
  733
+  }
  734
+
  735
+  /**
  736
+   * Create a new object type.
  737
+   *
  738
+   * @param  name       object type's name
  739
+   * @error
  740
+   *    API_EC_DATA_DATABASE_ERROR
  741
+   *    API_EC_DATA_OBJECT_ALREADY_EXISTS
  742
+   *    API_EC_PARAM
  743
+   *    API_EC_PERMISSION
  744
+   *    API_EC_DATA_INVALID_OPERATION
  745
+   *    API_EC_DATA_QUOTA_EXCEEDED
  746
+   *    API_EC_DATA_UNKNOWN_ERROR
  747
+   */
  748
+  function data_createObjectType($name) {
  749
+    return $this->call_method
  750
+      ('facebook.data.createObjectType',
  751
+       array('name' => $name));
  752
+  }
  753
+
  754
+  /**
  755
+   * Delete an object type.
  756
+   *
  757
+   * @param  obj_type       object type's name
  758
+   * @error
  759
+   *    API_EC_DATA_DATABASE_ERROR
  760
+   *    API_EC_DATA_OBJECT_NOT_FOUND
  761
+   *    API_EC_PARAM
  762
+   *    API_EC_PERMISSION
  763
+   *    API_EC_DATA_INVALID_OPERATION
  764
+   *    API_EC_DATA_QUOTA_EXCEEDED
  765
+   *    API_EC_DATA_UNKNOWN_ERROR
  766
+   */
  767
+  function data_dropObjectType($obj_type) {
  768
+    return $this->call_method
  769
+      ('facebook.data.dropObjectType',
  770
+       array('obj_type' => $obj_type));
  771
+  }
  772
+
  773
+  /**
  774
+   * Rename an object type.
  775
+   *
  776
+   * @param  obj_type       object type's name
  777
+   * @param  new_name       new object type's name
  778
+   * @error
  779
+   *    API_EC_DATA_DATABASE_ERROR
  780
+   *    API_EC_DATA_OBJECT_NOT_FOUND
  781
+   *    API_EC_DATA_OBJECT_ALREADY_EXISTS
  782
+   *    API_EC_PARAM
  783
+   *    API_EC_PERMISSION
  784
+   *    API_EC_DATA_INVALID_OPERATION
  785
+   *    API_EC_DATA_QUOTA_EXCEEDED
  786
+   *    API_EC_DATA_UNKNOWN_ERROR
  787
+   */
  788
+  function data_renameObjectType($obj_type, $new_name) {
  789
+    return $this->call_method
  790
+      ('facebook.data.renameObjectType',
  791
+       array('obj_type' => $obj_type,
  792
+             'new_name' => $new_name));
  793
+  }
  794
+
  795
+  /**
  796
+   * Add a new property to an object type.
  797
+   *
  798
+   * @param  obj_type       object type's name
  799
+   * @param  prop_name      name of the property to add
  800
+   * @param  prop_type      1: integer; 2: string; 3: text blob
  801
+   * @error
  802
+   *    API_EC_DATA_DATABASE_ERROR
  803
+   *    API_EC_DATA_OBJECT_ALREADY_EXISTS
  804
+   *    API_EC_PARAM
  805
+   *    API_EC_PERMISSION