diff options
Diffstat (limited to 'plugins/Facebook')
-rw-r--r-- | plugins/Facebook/facebook/facebook.php | 23 | ||||
-rw-r--r-- | plugins/Facebook/facebook/facebook_desktop.php | 2 | ||||
-rw-r--r-- | plugins/Facebook/facebook/facebook_mobile.php | 260 | ||||
-rwxr-xr-x | plugins/Facebook/facebook/facebookapi_php5_restlib.php | 382 | ||||
-rw-r--r-- | plugins/Facebook/facebookaction.php | 96 | ||||
-rw-r--r-- | plugins/Facebook/facebooknoticeform.php | 206 | ||||
-rw-r--r-- | plugins/Facebook/facebookutil.php | 16 |
7 files changed, 751 insertions, 234 deletions
diff --git a/plugins/Facebook/facebook/facebook.php b/plugins/Facebook/facebook/facebook.php index 016e8e8e0..440706cbc 100644 --- a/plugins/Facebook/facebook/facebook.php +++ b/plugins/Facebook/facebook/facebook.php @@ -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]); } diff --git a/plugins/Facebook/facebook/facebook_desktop.php b/plugins/Facebook/facebook/facebook_desktop.php index e79a2ca34..ed4762215 100644 --- a/plugins/Facebook/facebook/facebook_desktop.php +++ b/plugins/Facebook/facebook/facebook_desktop.php @@ -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 index 000000000..5ee7f4ed5 --- /dev/null +++ b/plugins/Facebook/facebook/facebook_mobile.php @@ -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)); + } +} diff --git a/plugins/Facebook/facebook/facebookapi_php5_restlib.php b/plugins/Facebook/facebook/facebookapi_php5_restlib.php index 55cb7fb86..fa1088cd0 100755 --- a/plugins/Facebook/facebook/facebookapi_php5_restlib.php +++ b/plugins/Facebook/facebook/facebookapi_php5_restlib.php @@ -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,7 +544,7 @@ 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)); @@ -527,6 +552,27 @@ function toggleDisplay(id, type) { } /** + * 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. * * @param int $eid event id @@ -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 @@ -1249,6 +1318,87 @@ function toggleDisplay(id, type) { } /** + * 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. * * @param string $title Title of the note. @@ -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 @@ -2876,6 +2941,35 @@ function toggleDisplay(id, type) { } /** + * 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 * limit_map. @@ -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'], @@ -3054,6 +3149,16 @@ function toggleDisplay(id, type) { } /** + * 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 * * @param string $method Name of the Facebook method to invoke @@ -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 diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php index 24bf215fd..bf9c037a5 100644 --- a/plugins/Facebook/facebookaction.php +++ b/plugins/Facebook/facebookaction.php @@ -32,7 +32,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { } require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php'; -require_once INSTALLDIR . '/lib/noticeform.php'; +require_once INSTALLDIR . '/plugins/Facebook/facebooknoticeform.php'; class FacebookAction extends Action { @@ -294,63 +294,7 @@ class FacebookAction extends Action $app_props = $this->facebook->api_client->Admin_getAppProperties(array('icon_url')); $icon_url = $app_props['icon_url']; - $style = '<style> - .entry-title *, - .entry-content * { - font-size:14px; - font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif; - } - .entry-title a, - .entry-content a { - color:#002E6E; - } - - .entry-title .vcard .photo { - float:left; - display:inline; - margin-right:11px; - margin-bottom:11px - } - .entry-title { - margin-bottom:11px; - } - .entry-title p.entry-content { - display:inline; - margin-left:5px; - } - - div.entry-content { - clear:both; - } - div.entry-content dl, - div.entry-content dt, - div.entry-content dd { - display:inline; - text-transform:lowercase; - } - - div.entry-content dd, - div.entry-content .device dt { - margin-left:0; - margin-right:5px; - } - div.entry-content dl.timestamp dt, - div.entry-content dl.response dt { - display:none; - } - div.entry-content dd a { - display:inline-block; - } - - #facebook_statusnet_app { - text-indent:-9999px; - height:16px; - width:16px; - display:block; - background:url('.$icon_url.') no-repeat 0 0; - float:right; - } - </style>'; + $style = '<style> .entry-title *, .entry-content * { font-size:14px; font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif; } .entry-title a, .entry-content a { color:#002E6E; } .entry-title .vcard .photo { float:left; display:inline; margin-right:11px; margin-bottom:11px } .entry-title { margin-bottom:11px; } .entry-title p.entry-content { display:inline; margin-left:5px; } div.entry-content { clear:both; } div.entry-content dl, div.entry-content dt, div.entry-content dd { display:inline; text-transform:lowercase; } div.entry-content dd, div.entry-content .device dt { margin-left:0; margin-right:5px; } div.entry-content dl.timestamp dt, div.entry-content dl.response dt { display:none; } div.entry-content dd a { display:inline-block; } #facebook_statusnet_app { text-indent:-9999px; height:16px; width:16px; display:block; background:url('.$icon_url.') no-repeat 0 0; float:right; } </style>'; $this->xw->openMemory(); @@ -455,42 +399,6 @@ class FacebookAction extends Action common_broadcast_notice($notice); - // Also update the user's Facebook status - facebookBroadcastNotice($notice); - - } - -} - -class FacebookNoticeForm extends NoticeForm -{ - - var $post_action = null; - - /** - * Constructor - * - * @param HTMLOutputter $out output channel - * @param string $action action to return to, if any - * @param string $content content to pre-fill - */ - - function __construct($out=null, $action=null, $content=null, - $post_action=null, $user=null) - { - parent::__construct($out, $action, $content, $user); - $this->post_action = $post_action; - } - - /** - * Action of the form - * - * @return string URL of the action - */ - - function action() - { - return $this->post_action; } } diff --git a/plugins/Facebook/facebooknoticeform.php b/plugins/Facebook/facebooknoticeform.php new file mode 100644 index 000000000..5989147f4 --- /dev/null +++ b/plugins/Facebook/facebooknoticeform.php @@ -0,0 +1,206 @@ +<?php +/** + * StatusNet, the distributed open-source microblogging tool + * + * Form for posting a notice from within the Facebook App. + * + * This is a stripped down version of the normal NoticeForm (sans + * location stuff and media upload stuff). I'm not sure we can share the + * location (from FB) and they don't allow posting multipart form data + * to Facebook canvas pages, so that won't work anyway. --Zach + * + * PHP version 5 + * + * LICENCE: This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou <evan@status.net> + * @author Sarven Capadisli <csarven@status.net> + * @author Zach Copley <zach@status.net> + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/form.php'; + +/** + * Form for posting a notice from within the Facebook app + * + * @category Form + * @package StatusNet + * @author Evan Prodromou <evan@status.net> + * @author Sarven Capadisli <csarven@status.net> + * @author Zach Copey <zach@status.net> + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see HTMLOutputter + */ + +class FacebookNoticeForm extends Form +{ + /** + * Current action, used for returning to this page. + */ + + var $action = null; + + /** + * Pre-filled content of the form + */ + + var $content = null; + + /** + * The current user + */ + + var $user = null; + + /** + * The notice being replied to + */ + + var $inreplyto = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param string $action action to return to, if any + * @param string $content content to pre-fill + */ + + function __construct($out=null, $action=null, $content=null, $post_action=null, $user=null, $inreplyto=null) + { + parent::__construct($out); + + $this->action = $action; + $this->post_action = $post_action; + $this->content = $content; + $this->inreplyto = $inreplyto; + + if ($user) { + $this->user = $user; + } else { + $this->user = common_current_user(); + } + + // Note: Facebook doesn't allow multipart/form-data posting to + // canvas pages, so don't try to set it--no file uploads, at + // least not this way. It can be done using multiple servers + // and iFrames, but it's a pretty hacky process. + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'form_notice'; + } + + /** + * Class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_notice'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return $this->post_action; + } + + /** + * Legend of the Form + * + * @return void + */ + function formLegend() + { + $this->out->element('legend', null, _('Send a notice')); + } + + /** + * Data elements + * + * @return void + */ + + function formData() + { + if (Event::handle('StartShowNoticeFormData', array($this))) { + $this->out->element('label', array('for' => 'notice_data-text'), + sprintf(_('What\'s up, %s?'), $this->user->nickname)); + // XXX: vary by defined max size + $this->out->element('textarea', array('id' => 'notice_data-text', + 'cols' => 35, + 'rows' => 4, + 'name' => 'status_textarea'), + ($this->content) ? $this->content : ''); + + $contentLimit = Notice::maxContent(); + + if ($contentLimit > 0) { + $this->out->elementStart('dl', 'form_note'); + $this->out->element('dt', null, _('Available characters')); + $this->out->element('dd', array('id' => 'notice_text-count'), + $contentLimit); + $this->out->elementEnd('dl'); + } + + if ($this->action) { + $this->out->hidden('notice_return-to', $this->action, 'returnto'); + } + $this->out->hidden('notice_in-reply-to', $this->inreplyto, 'inreplyto'); + + Event::handle('StartShowNoticeFormData', array($this)); + } + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->element('input', array('id' => 'notice_action-submit', + 'class' => 'submit', + 'name' => 'status_submit', + 'type' => 'submit', + 'value' => _('Send'))); + } +} diff --git a/plugins/Facebook/facebookutil.php b/plugins/Facebook/facebookutil.php index 2ec6db6b8..ac532e18b 100644 --- a/plugins/Facebook/facebookutil.php +++ b/plugins/Facebook/facebookutil.php @@ -138,21 +138,23 @@ function facebookBroadcastNotice($notice) $code = $e->getCode(); - common_log(LOG_WARNING, 'Facebook returned error code ' . - $code . ': ' . $e->getMessage()); - common_log(LOG_WARNING, - 'Unable to update Facebook status for ' . - "$user->nickname (user id: $user->id)!"); + $msg = "Facebook returned error code $code: " . + $e->getMessage() . ' - ' . + "Unable to update Facebook status (notice $notice->id) " . + "for $user->nickname (user id: $user->id)!"; - if ($code == 200 || $code == 250) { + common_log(LOG_WARNING, $msg); + if ($code == 100 || $code == 200 || $code == 250) { + + // 100 The account is 'inactive' (probably - this is not well documented) // 200 The application does not have permission to operate on the passed in uid parameter. // 250 Updating status requires the extended permission status_update or publish_stream. // see: http://wiki.developers.facebook.com/index.php/Users.setStatus#Example_Return_XML remove_facebook_app($flink); - } else { + } else { // Try sending again later. |