Merge branch '0.9.x' of gitorious.org:statusnet/mainline into 0.9.x
This commit is contained in:
commit
3ed5673058
@ -379,6 +379,14 @@ GetValidDaemons: Just before determining which daemons to run
|
||||
HandleQueuedNotice: Handle a queued notice at queue time (or immediately if no queue)
|
||||
- &$notice: notice to handle
|
||||
|
||||
StartHtmlElement: Reight before outputting the HTML element - allows plugins to add namespaces
|
||||
- $action: the current action
|
||||
- &$attrs: attributes for the HTML element
|
||||
|
||||
EndHtmlElement: Right after outputting the HTML element
|
||||
- $action: the current action
|
||||
- &$attrs: attributes for the HTML element
|
||||
|
||||
StartShowHeadElements: Right after the <head> tag
|
||||
- $action: the current action
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 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/
|
||||
*/
|
||||
@ -40,12 +40,33 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <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/
|
||||
*
|
||||
*/
|
||||
class CurrentUserDesignAction extends Action
|
||||
{
|
||||
|
||||
protected $cur = null; // The current user
|
||||
|
||||
/**
|
||||
* For initializing members of the class. Set a the
|
||||
* current user here.
|
||||
*
|
||||
* @param array $argarray misc. arguments
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function prepare($argarray)
|
||||
{
|
||||
parent::prepare($argarray);
|
||||
|
||||
$this->cur = common_current_user();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A design for this action
|
||||
*
|
||||
@ -55,11 +76,9 @@ class CurrentUserDesignAction extends Action
|
||||
*/
|
||||
function getDesign()
|
||||
{
|
||||
$cur = common_current_user();
|
||||
if (!empty($this->cur)) {
|
||||
|
||||
if (!empty($cur)) {
|
||||
|
||||
$design = $cur->getDesign();
|
||||
$design = $this->cur->getDesign();
|
||||
|
||||
if (!empty($design)) {
|
||||
return $design;
|
||||
@ -68,4 +87,10 @@ class CurrentUserDesignAction extends Action
|
||||
|
||||
return parent::getDesign();
|
||||
}
|
||||
|
||||
function getCurrentUser()
|
||||
{
|
||||
return $this->cur;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,9 +119,16 @@ class HTMLOutputter extends XMLOutputter
|
||||
|
||||
$language = $this->getLanguage();
|
||||
|
||||
$this->elementStart('html', array('xmlns' => 'http://www.w3.org/1999/xhtml',
|
||||
$attrs = array(
|
||||
'xmlns' => 'http://www.w3.org/1999/xhtml',
|
||||
'xml:lang' => $language,
|
||||
'lang' => $language));
|
||||
'lang' => $language
|
||||
);
|
||||
|
||||
if (Event::handle('StartHtmlElement', array($this, &$attrs))) {
|
||||
$this->elementStart('html', $attrs);
|
||||
Event::handle('EndHtmlElement', array($this, &$attrs));
|
||||
}
|
||||
}
|
||||
|
||||
function getLanguage()
|
||||
|
@ -1501,6 +1501,7 @@ function common_request_id()
|
||||
function common_log($priority, $msg, $filename=null)
|
||||
{
|
||||
if(Event::handle('StartLog', array(&$priority, &$msg, &$filename))){
|
||||
$msg = (empty($filename)) ? $msg : basename($filename) . ' - ' . $msg;
|
||||
$msg = '[' . common_request_id() . '] ' . $msg;
|
||||
$logfile = common_config('site', 'logfile');
|
||||
if ($logfile) {
|
||||
|
539
plugins/FacebookBridge/FacebookBridgePlugin.php
Normal file
539
plugins/FacebookBridge/FacebookBridgePlugin.php
Normal file
@ -0,0 +1,539 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* A plugin for integrating Facebook with StatusNet. Includes single-sign-on
|
||||
* and publishing notices to Facebook using Facebook's Graph API.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* 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 Pugin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
define("FACEBOOK_SERVICE", 2);
|
||||
|
||||
/**
|
||||
* Main class for Facebook plugin
|
||||
*
|
||||
* @category Plugin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
class FacebookBridgePlugin extends Plugin
|
||||
{
|
||||
public $appId = null; // Facebook application ID
|
||||
public $secret = null; // Facebook application secret
|
||||
public $facebook = null; // Facebook application instance
|
||||
public $dir = null; // Facebook SSO plugin dir
|
||||
|
||||
/**
|
||||
* Initializer for this plugin
|
||||
*
|
||||
* Gets an instance of the Facebook API client object
|
||||
*
|
||||
* @return boolean hook value; true means continue processing, false means stop.
|
||||
*/
|
||||
function initialize()
|
||||
{
|
||||
$this->facebook = Facebookclient::getFacebook(
|
||||
$this->appId,
|
||||
$this->secret
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load related modules when needed
|
||||
*
|
||||
* @param string $cls Name of the class to be loaded
|
||||
*
|
||||
* @return boolean hook value; true means continue processing, false means stop.
|
||||
*/
|
||||
function onAutoload($cls)
|
||||
{
|
||||
|
||||
$dir = dirname(__FILE__);
|
||||
|
||||
//common_debug("class = " . $cls);
|
||||
|
||||
switch ($cls)
|
||||
{
|
||||
case 'Facebook': // Facebook PHP SDK
|
||||
include_once $dir . '/extlib/facebook.php';
|
||||
return false;
|
||||
case 'FacebookloginAction':
|
||||
case 'FacebookfinishloginAction':
|
||||
case 'FacebookadminpanelAction':
|
||||
case 'FacebooksettingsAction':
|
||||
case 'FacebookdeauthorizeAction':
|
||||
include_once $dir . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
|
||||
return false;
|
||||
case 'Facebookclient':
|
||||
case 'FacebookQueueHandler':
|
||||
include_once $dir . '/lib/' . strtolower($cls) . '.php';
|
||||
return false;
|
||||
case 'Notice_to_item':
|
||||
include_once $dir . '/classes/' . $cls . '.php';
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Database schema setup
|
||||
*
|
||||
* We maintain a table mapping StatusNet notices to Facebook items
|
||||
*
|
||||
* @see Schema
|
||||
* @see ColumnDef
|
||||
*
|
||||
* @return boolean hook value; true means continue processing, false means stop.
|
||||
*/
|
||||
function onCheckSchema()
|
||||
{
|
||||
$schema = Schema::get();
|
||||
$schema->ensureTable('notice_to_item', Notice_to_item::schemaDef());
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does this $action need the Facebook JavaScripts?
|
||||
*/
|
||||
function needsScripts($action)
|
||||
{
|
||||
static $needy = array(
|
||||
'FacebookloginAction',
|
||||
'FacebookfinishloginAction',
|
||||
'FacebookadminpanelAction',
|
||||
'FacebooksettingsAction'
|
||||
);
|
||||
|
||||
if (in_array(get_class($action), $needy)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map URLs to actions
|
||||
*
|
||||
* @param Net_URL_Mapper $m path-to-action mapper
|
||||
*
|
||||
* @return boolean hook value; true means continue processing, false means stop.
|
||||
*/
|
||||
function onRouterInitialized($m)
|
||||
{
|
||||
// Always add the admin panel route
|
||||
$m->connect('admin/facebook', array('action' => 'facebookadminpanel'));
|
||||
|
||||
// Only add these routes if an application has been setup on
|
||||
// Facebook for the plugin to use.
|
||||
if ($this->hasApplication()) {
|
||||
|
||||
$m->connect(
|
||||
'main/facebooklogin',
|
||||
array('action' => 'facebooklogin')
|
||||
);
|
||||
$m->connect(
|
||||
'main/facebookfinishlogin',
|
||||
array('action' => 'facebookfinishlogin')
|
||||
);
|
||||
$m->connect(
|
||||
'settings/facebook',
|
||||
array('action' => 'facebooksettings')
|
||||
);
|
||||
$m->connect(
|
||||
'facebook/deauthorize',
|
||||
array('action' => 'facebookdeauthorize')
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a login tab for Facebook, but only if there's a Facebook
|
||||
* application defined for the plugin to use.
|
||||
*
|
||||
* @param Action &action the current action
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function onEndLoginGroupNav(&$action)
|
||||
{
|
||||
$action_name = $action->trimmed('action');
|
||||
|
||||
if ($this->hasApplication()) {
|
||||
|
||||
$action->menuItem(
|
||||
common_local_url('facebooklogin'),
|
||||
_m('MENU', 'Facebook'),
|
||||
// TRANS: Tooltip for menu item "Facebook".
|
||||
_m('Login or register using Facebook'),
|
||||
'facebooklogin' === $action_name
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Facebook tab to the admin panels
|
||||
*
|
||||
* @param Widget $nav Admin panel nav
|
||||
*
|
||||
* @return boolean hook value
|
||||
*/
|
||||
function onEndAdminPanelNav($nav)
|
||||
{
|
||||
if (AdminPanelAction::canAdmin('facebook')) {
|
||||
|
||||
$action_name = $nav->action->trimmed('action');
|
||||
|
||||
$nav->out->menuItem(
|
||||
common_local_url('facebookadminpanel'),
|
||||
// TRANS: Menu item.
|
||||
_m('MENU','Facebook'),
|
||||
// TRANS: Tooltip for menu item "Facebook".
|
||||
_m('Facebook integration configuration'),
|
||||
$action_name == 'facebookadminpanel',
|
||||
'nav_facebook_admin_panel'
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a tab for user-level Facebook settings if the user
|
||||
* has a link to Facebook
|
||||
*
|
||||
* @param Action &action the current action
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function onEndConnectSettingsNav(&$action)
|
||||
{
|
||||
if ($this->hasApplication()) {
|
||||
$action_name = $action->trimmed('action');
|
||||
|
||||
// CurrentUserDesignAction stores the current user in $cur
|
||||
$user = $action->getCurrentUser();
|
||||
|
||||
$flink = null;
|
||||
|
||||
if (!empty($user)) {
|
||||
$flink = Foreign_link::getByUserID(
|
||||
$user->id,
|
||||
FACEBOOK_SERVICE
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($flink)) {
|
||||
|
||||
$action->menuItem(
|
||||
common_local_url('facebooksettings'),
|
||||
// TRANS: Menu item tab.
|
||||
_m('MENU','Facebook'),
|
||||
// TRANS: Tooltip for menu item "Facebook".
|
||||
_m('Facebook settings'),
|
||||
$action_name === 'facebooksettings'
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Is there a Facebook application for the plugin to use?
|
||||
*
|
||||
* Checks to see if a Facebook application ID and secret
|
||||
* have been configured and a valid Facebook API client
|
||||
* object exists.
|
||||
*
|
||||
*/
|
||||
function hasApplication()
|
||||
{
|
||||
if (!empty($this->facebook)) {
|
||||
|
||||
$appId = $this->facebook->getAppId();
|
||||
$secret = $this->facebook->getApiSecret();
|
||||
|
||||
if (!empty($appId) && !empty($secret)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a Facebook div for the Facebook JavaSsript SDK to use
|
||||
*
|
||||
* @param Action $action the current action
|
||||
*
|
||||
*/
|
||||
function onStartShowHeader($action)
|
||||
{
|
||||
// output <div id="fb-root"></div> as close to <body> as possible
|
||||
$action->element('div', array('id' => 'fb-root'));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the Facebook JavaScript SDK on pages that need them.
|
||||
*
|
||||
* @param Action $action the current action
|
||||
*
|
||||
*/
|
||||
function onEndShowScripts($action)
|
||||
{
|
||||
if ($this->needsScripts($action)) {
|
||||
|
||||
$action->script('https://connect.facebook.net/en_US/all.js');
|
||||
|
||||
$script = <<<ENDOFSCRIPT
|
||||
FB.init({appId: %1\$s, session: %2\$s, status: true, cookie: true, xfbml: true});
|
||||
|
||||
$('#facebook_button').bind('click', function(event) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
FB.login(function(response) {
|
||||
if (response.session && response.perms) {
|
||||
window.location.href = '%3\$s';
|
||||
} else {
|
||||
// NOP (user cancelled login)
|
||||
}
|
||||
}, {perms:'read_stream,publish_stream,offline_access,user_status,user_location,user_website,email'});
|
||||
});
|
||||
ENDOFSCRIPT;
|
||||
|
||||
$action->inlineScript(
|
||||
sprintf($script,
|
||||
json_encode($this->facebook->getAppId()),
|
||||
json_encode($this->facebook->getSession()),
|
||||
common_local_url('facebookfinishlogin')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Log the user out of Facebook, per the Facebook authentication guide
|
||||
*
|
||||
* @param Action action the current action
|
||||
*/
|
||||
function onEndLogout($action)
|
||||
{
|
||||
if ($this->hasApplication()) {
|
||||
$session = $this->facebook->getSession();
|
||||
$fbuser = null;
|
||||
$fbuid = null;
|
||||
|
||||
if ($session) {
|
||||
try {
|
||||
$fbuid = $this->facebook->getUser();
|
||||
$fbuser = $this->facebook->api('/me');
|
||||
} catch (FacebookApiException $e) {
|
||||
common_log(LOG_ERROR, $e, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($fbuser)) {
|
||||
|
||||
$logoutUrl = $this->facebook->getLogoutUrl(
|
||||
array('next' => common_local_url('public'))
|
||||
);
|
||||
|
||||
common_log(
|
||||
LOG_INFO,
|
||||
sprintf(
|
||||
"Logging user out of Facebook (fbuid = %s)",
|
||||
$fbuid
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
common_debug("LOGOUT URL = $logoutUrl");
|
||||
common_redirect($logoutUrl, 303);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add fbml namespace to our HTML, so Facebook's JavaScript SDK can parse
|
||||
* and render XFBML tags
|
||||
*
|
||||
* @param Action $action the current action
|
||||
* @param array $attrs array of attributes for the HTML tag
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
function onStartHtmlElement($action, $attrs) {
|
||||
|
||||
if ($this->needsScripts($action)) {
|
||||
$attrs = array_merge(
|
||||
$attrs,
|
||||
array('xmlns:fb' => 'http://www.facebook.com/2008/fbml')
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Facebook queue item for each notice
|
||||
*
|
||||
* @param Notice $notice the notice
|
||||
* @param array &$transports the list of transports (queues)
|
||||
*
|
||||
* @return boolean hook return
|
||||
*/
|
||||
function onStartEnqueueNotice($notice, &$transports)
|
||||
{
|
||||
if (self::hasApplication() && $notice->isLocal()) {
|
||||
array_push($transports, 'facebook');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Facebook notice queue handler
|
||||
*
|
||||
* @param QueueManager $manager
|
||||
*
|
||||
* @return boolean hook return
|
||||
*/
|
||||
function onEndInitializeQueueManager($manager)
|
||||
{
|
||||
if (self::hasApplication()) {
|
||||
$manager->connect('facebook', 'FacebookQueueHandler');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use SSL for Facebook stuff
|
||||
*
|
||||
* @param string $action name
|
||||
* @param boolean $ssl outval to force SSL
|
||||
* @return mixed hook return value
|
||||
*/
|
||||
function onSensitiveAction($action, &$ssl)
|
||||
{
|
||||
$sensitive = array(
|
||||
'facebookadminpanel',
|
||||
'facebooksettings',
|
||||
'facebooklogin',
|
||||
'facebookfinishlogin'
|
||||
);
|
||||
|
||||
if (in_array($action, $sensitive)) {
|
||||
$ssl = true;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a notice gets deleted, remove the Notice_to_item mapping and
|
||||
* delete the item on Facebook
|
||||
*
|
||||
* @param User $user The user doing the deleting
|
||||
* @param Notice $notice The notice getting deleted
|
||||
*
|
||||
* @return boolean hook value
|
||||
*/
|
||||
function onStartDeleteOwnNotice(User $user, Notice $notice)
|
||||
{
|
||||
$client = new Facebookclient($notice);
|
||||
$client->streamRemove();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify remote users when their notices get favorited.
|
||||
*
|
||||
* @param Profile or User $profile of local user doing the faving
|
||||
* @param Notice $notice being favored
|
||||
* @return hook return value
|
||||
*/
|
||||
function onEndFavorNotice(Profile $profile, Notice $notice)
|
||||
{
|
||||
$client = new Facebookclient($notice);
|
||||
$client->like();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify remote users when their notices get de-favorited.
|
||||
*
|
||||
* @param Profile $profile Profile person doing the de-faving
|
||||
* @param Notice $notice Notice being favored
|
||||
*
|
||||
* @return hook return value
|
||||
*/
|
||||
function onEndDisfavorNotice(Profile $profile, Notice $notice)
|
||||
{
|
||||
$client = new Facebookclient($notice);
|
||||
$client->unLike();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add version info for this plugin
|
||||
*
|
||||
* @param array &$versions plugin version descriptions
|
||||
*/
|
||||
function onPluginVersion(&$versions)
|
||||
{
|
||||
$versions[] = array(
|
||||
'name' => 'Facebook Single-Sign-On',
|
||||
'version' => STATUSNET_VERSION,
|
||||
'author' => 'Craig Andrews, Zach Copley',
|
||||
'homepage' => 'http://status.net/wiki/Plugin:FacebookBridge',
|
||||
'rawdescription' =>
|
||||
_m('A plugin for integrating StatusNet with Facebook.')
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
212
plugins/FacebookBridge/actions/facebookadminpanel.php
Normal file
212
plugins/FacebookBridge/actions/facebookadminpanel.php
Normal file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Facebook integration administration panel
|
||||
*
|
||||
* 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 Settings
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Administer global Facebook integration settings
|
||||
*
|
||||
* @category Admin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <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/
|
||||
*/
|
||||
class FacebookadminpanelAction extends AdminPanelAction
|
||||
{
|
||||
/**
|
||||
* Returns the page title
|
||||
*
|
||||
* @return string page title
|
||||
*/
|
||||
function title()
|
||||
{
|
||||
return _m('Facebook');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for using this form.
|
||||
*
|
||||
* @return string instructions
|
||||
*/
|
||||
function getInstructions()
|
||||
{
|
||||
return _m('Facebook integration settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Facebook admin panel form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showForm()
|
||||
{
|
||||
$form = new FacebookAdminPanelForm($this);
|
||||
$form->show();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings from the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function saveSettings()
|
||||
{
|
||||
static $settings = array(
|
||||
'facebook' => array('appid', 'secret'),
|
||||
);
|
||||
|
||||
$values = array();
|
||||
|
||||
foreach ($settings as $section => $parts) {
|
||||
foreach ($parts as $setting) {
|
||||
$values[$section][$setting]
|
||||
= $this->trimmed($setting);
|
||||
}
|
||||
}
|
||||
|
||||
// This throws an exception on validation errors
|
||||
$this->validate($values);
|
||||
|
||||
// assert(all values are valid);
|
||||
|
||||
$config = new Config();
|
||||
|
||||
$config->query('BEGIN');
|
||||
|
||||
foreach ($settings as $section => $parts) {
|
||||
foreach ($parts as $setting) {
|
||||
Config::save($section, $setting, $values[$section][$setting]);
|
||||
}
|
||||
}
|
||||
|
||||
$config->query('COMMIT');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
function validate(&$values)
|
||||
{
|
||||
// appId, key and secret (can't be too long)
|
||||
|
||||
if (mb_strlen($values['facebook']['appid']) > 255) {
|
||||
$this->clientError(
|
||||
_m("Invalid Facebook ID. Max length is 255 characters.")
|
||||
);
|
||||
}
|
||||
|
||||
if (mb_strlen($values['facebook']['secret']) > 255) {
|
||||
$this->clientError(
|
||||
_m("Invalid Facebook secret. Max length is 255 characters.")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FacebookAdminPanelForm extends AdminForm
|
||||
{
|
||||
/**
|
||||
* ID of the form
|
||||
*
|
||||
* @return int ID of the form
|
||||
*/
|
||||
function id()
|
||||
{
|
||||
return 'facebookadminpanel';
|
||||
}
|
||||
|
||||
/**
|
||||
* class of the form
|
||||
*
|
||||
* @return string class of the form
|
||||
*/
|
||||
function formClass()
|
||||
{
|
||||
return 'form_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Action of the form
|
||||
*
|
||||
* @return string URL of the action
|
||||
*/
|
||||
function action()
|
||||
{
|
||||
return common_local_url('facebookadminpanel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data elements of the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function formData()
|
||||
{
|
||||
$this->out->elementStart(
|
||||
'fieldset',
|
||||
array('id' => 'settings_facebook-application')
|
||||
);
|
||||
$this->out->element('legend', null, _m('Facebook application settings'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
|
||||
$this->li();
|
||||
$this->input(
|
||||
'appid',
|
||||
_m('Application ID'),
|
||||
_m('ID of your Facebook application'),
|
||||
'facebook'
|
||||
);
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input(
|
||||
'secret',
|
||||
_m('Secret'),
|
||||
_m('Application secret'),
|
||||
'facebook'
|
||||
);
|
||||
$this->unli();
|
||||
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function formActions()
|
||||
{
|
||||
$this->out->submit('submit', _m('Save'), 'submit', null, _m('Save Facebook settings'));
|
||||
}
|
||||
}
|
144
plugins/FacebookBridge/actions/facebookdeauthorize.php
Normal file
144
plugins/FacebookBridge/actions/facebookdeauthorize.php
Normal file
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* An action that handles deauthorize callbacks from Facebook
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Action class for handling deauthorize callbacks from Facebook. If the user
|
||||
* doesn't have a password let her know she'll need to contact the site
|
||||
* admin to get back into her account (if possible).
|
||||
*/
|
||||
class FacebookdeauthorizeAction extends Action
|
||||
{
|
||||
private $facebook;
|
||||
|
||||
/**
|
||||
* For initializing members of the class.
|
||||
*
|
||||
* @param array $args misc. arguments
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
$this->facebook = Facebookclient::getFacebook();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler method
|
||||
*
|
||||
* @param array $args is ignored since it's now passed in in prepare()
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
$data = $this->facebook->getSignedRequest();
|
||||
|
||||
if (isset($data['user_id'])) {
|
||||
|
||||
$fbuid = $data['user_id'];
|
||||
|
||||
$flink = Foreign_link::getByForeignID($fbuid, FACEBOOK_SERVICE);
|
||||
$user = $flink->getUser();
|
||||
|
||||
// Remove the link to Facebook
|
||||
$result = $flink->delete();
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($flink, 'DELETE', __FILE__);
|
||||
common_log(
|
||||
LOG_WARNING,
|
||||
sprintf(
|
||||
'Unable to delete Facebook foreign link '
|
||||
. 'for %s (%d), fbuid %d',
|
||||
$user->nickname,
|
||||
$user->id,
|
||||
$fbuid
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
common_log(
|
||||
LOG_INFO,
|
||||
sprintf(
|
||||
'Facebook callback: %s (%d), fbuid %d has deauthorized '
|
||||
. 'the Facebook application.',
|
||||
$user->nickname,
|
||||
$user->id,
|
||||
$fbuid
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
|
||||
// Warn the user about being locked out of their account
|
||||
// if we can.
|
||||
if (empty($user->password) && !empty($user->email)) {
|
||||
Facebookclient::emailWarn($user);
|
||||
} else {
|
||||
common_log(
|
||||
LOG_WARNING,
|
||||
sprintf(
|
||||
'%s (%d), fbuid %d has deauthorized his/her Facebook '
|
||||
. 'connection but hasn\'t set a password so s/he '
|
||||
. 'is locked out.',
|
||||
$user->nickname,
|
||||
$user->id,
|
||||
$fbuid
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!empty($data)) {
|
||||
common_log(
|
||||
LOG_WARNING,
|
||||
sprintf(
|
||||
'Facebook called the deauthorize callback '
|
||||
. ' but didn\'t provide a user ID.'
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
} else {
|
||||
// It probably wasn't Facebook that hit this action,
|
||||
// so redirect to the public timeline
|
||||
common_redirect(common_local_url('public'), 303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
688
plugins/FacebookBridge/actions/facebookfinishlogin.php
Normal file
688
plugins/FacebookBridge/actions/facebookfinishlogin.php
Normal file
@ -0,0 +1,688 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Login or register a local user based on a Facebook user
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class FacebookfinishloginAction extends Action
|
||||
{
|
||||
private $facebook = null; // Facebook client
|
||||
private $fbuid = null; // Facebook user ID
|
||||
private $fbuser = null; // Facebook user object (JSON)
|
||||
|
||||
function prepare($args) {
|
||||
|
||||
parent::prepare($args);
|
||||
|
||||
$this->facebook = new Facebook(
|
||||
array(
|
||||
'appId' => common_config('facebook', 'appid'),
|
||||
'secret' => common_config('facebook', 'secret'),
|
||||
'cookie' => true,
|
||||
)
|
||||
);
|
||||
|
||||
// Check for a Facebook user session
|
||||
|
||||
$session = $this->facebook->getSession();
|
||||
$me = null;
|
||||
|
||||
if ($session) {
|
||||
try {
|
||||
$this->fbuid = $this->facebook->getUser();
|
||||
$this->fbuser = $this->facebook->api('/me');
|
||||
} catch (FacebookApiException $e) {
|
||||
common_log(LOG_ERROR, $e, __FILE__);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->fbuser)) {
|
||||
|
||||
// OKAY, all is well... proceed to register
|
||||
|
||||
common_debug("Found a valid Facebook user.", __FILE__);
|
||||
} else {
|
||||
|
||||
// This shouldn't happen in the regular course of things
|
||||
|
||||
list($proxy, $ip) = common_client_ip();
|
||||
|
||||
common_log(
|
||||
LOG_WARNING,
|
||||
sprintf(
|
||||
'Failed Facebook authentication attempt, proxy = %s, ip = %s.',
|
||||
$proxy,
|
||||
$ip
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
|
||||
$this->clientError(
|
||||
_m('You must be logged into Facebook to register a local account using Facebook.')
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (common_is_real_login()) {
|
||||
|
||||
// User is already logged in, are her accounts already linked?
|
||||
|
||||
$flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
|
||||
|
||||
if (!empty($flink)) {
|
||||
|
||||
// User already has a linked Facebook account and shouldn't be here!
|
||||
|
||||
common_debug(
|
||||
sprintf(
|
||||
'There\'s already a local user %d linked with Facebook user %s.',
|
||||
$flink->user_id,
|
||||
$this->fbuid
|
||||
)
|
||||
);
|
||||
|
||||
$this->clientError(
|
||||
_m('There is already a local account linked with that Facebook account.')
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
// Possibly reconnect an existing account
|
||||
|
||||
$this->connectUser();
|
||||
}
|
||||
|
||||
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$this->handlePost();
|
||||
} else {
|
||||
$this->tryLogin();
|
||||
}
|
||||
}
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
$token = $this->trimmed('token');
|
||||
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(
|
||||
_m('There was a problem with your session token. Try again, please.')
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->arg('create')) {
|
||||
|
||||
if (!$this->boolean('license')) {
|
||||
$this->showForm(
|
||||
_m('You can\'t register if you don\'t agree to the license.'),
|
||||
$this->trimmed('newname')
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// We has a valid Facebook session and the Facebook user has
|
||||
// agreed to the SN license, so create a new user
|
||||
$this->createNewUser();
|
||||
|
||||
} else if ($this->arg('connect')) {
|
||||
|
||||
$this->connectNewUser();
|
||||
|
||||
} else {
|
||||
|
||||
$this->showForm(
|
||||
_m('An unknown error has occured.'),
|
||||
$this->trimmed('newname')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
if ($this->error) {
|
||||
|
||||
$this->element('div', array('class' => 'error'), $this->error);
|
||||
|
||||
} else {
|
||||
|
||||
$this->element(
|
||||
'div', 'instructions',
|
||||
// TRANS: %s is the site name.
|
||||
sprintf(
|
||||
_m('This is the first time you\'ve logged into %s so we must connect your Facebook to a local account. You can either create a new local account, or connect with an existing local account.'),
|
||||
common_config('site', 'name')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
// TRANS: Page title.
|
||||
return _m('Facebook Setup');
|
||||
}
|
||||
|
||||
function showForm($error=null, $username=null)
|
||||
{
|
||||
$this->error = $error;
|
||||
$this->username = $username;
|
||||
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showPage()
|
||||
{
|
||||
parent::showPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @fixme much of this duplicates core code, which is very fragile.
|
||||
* Should probably be replaced with an extensible mini version of
|
||||
* the core registration form.
|
||||
*/
|
||||
function showContent()
|
||||
{
|
||||
if (!empty($this->message_text)) {
|
||||
$this->element('p', null, $this->message);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'form_settings_facebook_connect',
|
||||
'class' => 'form_settings',
|
||||
'action' => common_local_url('facebookfinishlogin')));
|
||||
$this->elementStart('fieldset', array('id' => 'settings_facebook_connect_options'));
|
||||
// TRANS: Legend.
|
||||
$this->element('legend', null, _m('Connection options'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->element('input', array('type' => 'checkbox',
|
||||
'id' => 'license',
|
||||
'class' => 'checkbox',
|
||||
'name' => 'license',
|
||||
'value' => 'true'));
|
||||
$this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
|
||||
// TRANS: %s is the name of the license used by the user for their status updates.
|
||||
$message = _m('My text and files are available under %s ' .
|
||||
'except this private data: password, ' .
|
||||
'email address, IM address, and phone number.');
|
||||
$link = '<a href="' .
|
||||
htmlspecialchars(common_config('license', 'url')) .
|
||||
'">' .
|
||||
htmlspecialchars(common_config('license', 'title')) .
|
||||
'</a>';
|
||||
$this->raw(sprintf(htmlspecialchars($message), $link));
|
||||
$this->elementEnd('label');
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
|
||||
$this->elementStart('fieldset');
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->element('legend', null,
|
||||
// TRANS: Legend.
|
||||
_m('Create new account'));
|
||||
$this->element('p', null,
|
||||
_m('Create a new user with this nickname.'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
// TRANS: Field label.
|
||||
$this->input('newname', _m('New nickname'),
|
||||
($this->username) ? $this->username : '',
|
||||
_m('1-64 lowercase letters or numbers, no punctuation or spaces'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
// TRANS: Submit button.
|
||||
$this->submit('create', _m('BUTTON','Create'));
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
$this->elementStart('fieldset');
|
||||
// TRANS: Legend.
|
||||
$this->element('legend', null,
|
||||
_m('Connect existing account'));
|
||||
$this->element('p', null,
|
||||
_m('If you already have an account, login with your username and password to connect it to your Facebook.'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
// TRANS: Field label.
|
||||
$this->input('nickname', _m('Existing nickname'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->password('password', _m('Password'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
// TRANS: Submit button.
|
||||
$this->submit('connect', _m('BUTTON','Connect'));
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
||||
function message($msg)
|
||||
{
|
||||
$this->message_text = $msg;
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function createNewUser()
|
||||
{
|
||||
if (common_config('site', 'closed')) {
|
||||
// TRANS: Client error trying to register with registrations not allowed.
|
||||
$this->clientError(_m('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = null;
|
||||
|
||||
if (common_config('site', 'inviteonly')) {
|
||||
$code = $_SESSION['invitecode'];
|
||||
if (empty($code)) {
|
||||
// TRANS: Client error trying to register with registrations 'invite only'.
|
||||
$this->clientError(_m('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = Invitation::staticGet($code);
|
||||
|
||||
if (empty($invite)) {
|
||||
// TRANS: Client error trying to register with an invalid invitation code.
|
||||
$this->clientError(_m('Not a valid invitation code.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$nickname = $this->trimmed('newname');
|
||||
|
||||
if (!Validate::string($nickname, array('min_length' => 1,
|
||||
'max_length' => 64,
|
||||
'format' => NICKNAME_FMT))) {
|
||||
$this->showForm(_m('Nickname must have only lowercase letters and numbers and no spaces.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!User::allowed_nickname($nickname)) {
|
||||
$this->showForm(_m('Nickname not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (User::staticGet('nickname', $nickname)) {
|
||||
$this->showForm(_m('Nickname already in use. Try another one.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'nickname' => $nickname,
|
||||
'fullname' => $this->fbuser['first_name']
|
||||
. ' ' . $this->fbuser['last_name'],
|
||||
'homepage' => $this->fbuser['website'],
|
||||
'bio' => $this->fbuser['about'],
|
||||
'location' => $this->fbuser['location']['name']
|
||||
);
|
||||
|
||||
// It's possible that the email address is already in our
|
||||
// DB. It's a unique key, so we need to check
|
||||
if ($this->isNewEmail($this->fbuser['email'])) {
|
||||
$args['email'] = $this->fbuser['email'];
|
||||
$args['email_confirmed'] = true;
|
||||
}
|
||||
|
||||
if (!empty($invite)) {
|
||||
$args['code'] = $invite->code;
|
||||
}
|
||||
|
||||
$user = User::register($args);
|
||||
$result = $this->flinkUser($user->id, $this->fbuid);
|
||||
|
||||
if (!$result) {
|
||||
$this->serverError(_m('Error connecting user to Facebook.'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a Foreign_user record
|
||||
Facebookclient::addFacebookUser($this->fbuser);
|
||||
|
||||
$this->setAvatar($user);
|
||||
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
|
||||
common_log(
|
||||
LOG_INFO,
|
||||
sprintf(
|
||||
'Registered new user %s (%d) from Facebook user %s, (fbuid %d)',
|
||||
$user->nickname,
|
||||
$user->id,
|
||||
$this->fbuser['name'],
|
||||
$this->fbuid
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
|
||||
$this->goHome($user->nickname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to download the user's Facebook picture and create a
|
||||
* StatusNet avatar for the new user.
|
||||
*/
|
||||
function setAvatar($user)
|
||||
{
|
||||
$picUrl = sprintf(
|
||||
'http://graph.facebook.com/%s/picture?type=large',
|
||||
$this->fbuid
|
||||
);
|
||||
|
||||
// fetch the picture from Facebook
|
||||
$client = new HTTPClient();
|
||||
|
||||
// fetch the actual picture
|
||||
$response = $client->get($picUrl);
|
||||
|
||||
if ($response->isOk()) {
|
||||
|
||||
$finalUrl = $client->getUrl();
|
||||
|
||||
// Make sure the filename is unique becuase it's possible for a user
|
||||
// to deauthorize our app, and then come back in as a new user but
|
||||
// have the same Facebook picture (avatar URLs have a unique index
|
||||
// and their URLs are based on the filenames).
|
||||
$filename = 'facebook-' . common_good_rand(4) . '-'
|
||||
. substr(strrchr($finalUrl, '/'), 1);
|
||||
|
||||
$ok = file_put_contents(
|
||||
Avatar::path($filename),
|
||||
$response->getBody()
|
||||
);
|
||||
|
||||
if (!$ok) {
|
||||
common_log(
|
||||
LOG_WARNING,
|
||||
sprintf(
|
||||
'Couldn\'t save Facebook avatar %s',
|
||||
$tmp
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
// save it as an avatar
|
||||
$profile = $user->getProfile();
|
||||
|
||||
if ($profile->setOriginal($filename)) {
|
||||
common_log(
|
||||
LOG_INFO,
|
||||
sprintf(
|
||||
'Saved avatar for %s (%d) from Facebook picture for '
|
||||
. '%s (fbuid %d), filename = %s',
|
||||
$user->nickname,
|
||||
$user->id,
|
||||
$this->fbuser['name'],
|
||||
$this->fbuid,
|
||||
$filename
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function connectNewUser()
|
||||
{
|
||||
$nickname = $this->trimmed('nickname');
|
||||
$password = $this->trimmed('password');
|
||||
|
||||
if (!common_check_user($nickname, $password)) {
|
||||
$this->showForm(_m('Invalid username or password.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$user = User::staticGet('nickname', $nickname);
|
||||
|
||||
if (!empty($user)) {
|
||||
common_debug(
|
||||
sprintf(
|
||||
'Found a legit user to connect to Facebook: %s (%d)',
|
||||
$user->nickname,
|
||||
$user->id
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
}
|
||||
|
||||
$this->tryLinkUser($user);
|
||||
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
|
||||
$this->goHome($user->nickname);
|
||||
}
|
||||
|
||||
function connectUser()
|
||||
{
|
||||
$user = common_current_user();
|
||||
$this->tryLinkUser($user);
|
||||
common_redirect(common_local_url('facebookfinishlogin'), 303);
|
||||
}
|
||||
|
||||
function tryLinkUser($user)
|
||||
{
|
||||
$result = $this->flinkUser($user->id, $this->fbuid);
|
||||
|
||||
if (empty($result)) {
|
||||
$this->serverError(_m('Error connecting user to Facebook.'));
|
||||
return;
|
||||
}
|
||||
|
||||
common_debug(
|
||||
sprintf(
|
||||
'Connected Facebook user %s (fbuid %d) to local user %s (%d)',
|
||||
$this->fbuser['name'],
|
||||
$this->fbuid,
|
||||
$user->nickname,
|
||||
$user->id
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
}
|
||||
|
||||
function tryLogin()
|
||||
{
|
||||
common_debug(
|
||||
sprintf(
|
||||
'Trying login for Facebook user %s',
|
||||
$this->fbuid
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
|
||||
$flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
|
||||
|
||||
if (!empty($flink)) {
|
||||
$user = $flink->getUser();
|
||||
|
||||
if (!empty($user)) {
|
||||
|
||||
common_log(
|
||||
LOG_INFO,
|
||||
sprintf(
|
||||
'Logged in Facebook user %s as user %d (%s)',
|
||||
$this->fbuid,
|
||||
$user->nickname,
|
||||
$user->id
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
$this->goHome($user->nickname);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
common_debug(
|
||||
sprintf(
|
||||
'No flink found for fbuid: %s - new user',
|
||||
$this->fbuid
|
||||
),
|
||||
__FILE__
|
||||
);
|
||||
|
||||
$this->showForm(null, $this->bestNewNickname());
|
||||
}
|
||||
}
|
||||
|
||||
function goHome($nickname)
|
||||
{
|
||||
$url = common_get_returnto();
|
||||
if ($url) {
|
||||
// We don't have to return to it again
|
||||
common_set_returnto(null);
|
||||
} else {
|
||||
$url = common_local_url('all',
|
||||
array('nickname' =>
|
||||
$nickname));
|
||||
}
|
||||
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
|
||||
function flinkUser($user_id, $fbuid)
|
||||
{
|
||||
$flink = new Foreign_link();
|
||||
$flink->user_id = $user_id;
|
||||
$flink->foreign_id = $fbuid;
|
||||
$flink->service = FACEBOOK_SERVICE;
|
||||
|
||||
// Pull the access token from the Facebook cookies
|
||||
$flink->credentials = $this->facebook->getAccessToken();
|
||||
|
||||
$flink->created = common_sql_now();
|
||||
|
||||
$flink_id = $flink->insert();
|
||||
|
||||
return $flink_id;
|
||||
}
|
||||
|
||||
function bestNewNickname()
|
||||
{
|
||||
if (!empty($this->fbuser['name'])) {
|
||||
$nickname = $this->nicknamize($this->fbuser['name']);
|
||||
if ($this->isNewNickname($nickname)) {
|
||||
return $nickname;
|
||||
}
|
||||
}
|
||||
|
||||
// Try the full name
|
||||
|
||||
$fullname = trim($this->fbuser['first_name'] .
|
||||
' ' . $this->fbuser['last_name']);
|
||||
|
||||
if (!empty($fullname)) {
|
||||
$fullname = $this->nicknamize($fullname);
|
||||
if ($this->isNewNickname($fullname)) {
|
||||
return $fullname;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, try to make it work as a nickname
|
||||
*/
|
||||
function nicknamize($str)
|
||||
{
|
||||
$str = preg_replace('/\W/', '', $str);
|
||||
return strtolower($str);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the desired nickname already taken?
|
||||
*
|
||||
* @return boolean result
|
||||
*/
|
||||
function isNewNickname($str)
|
||||
{
|
||||
if (
|
||||
!Validate::string(
|
||||
$str,
|
||||
array(
|
||||
'min_length' => 1,
|
||||
'max_length' => 64,
|
||||
'format' => NICKNAME_FMT
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!User::allowed_nickname($str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (User::staticGet('nickname', $str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we already have a user record with this email?
|
||||
* (emails have to be unique but they can change)
|
||||
*
|
||||
* @param string $email the email address to check
|
||||
*
|
||||
* @return boolean result
|
||||
*/
|
||||
function isNewEmail($email)
|
||||
{
|
||||
// we shouldn't have to validate the format
|
||||
$result = User::staticGet('email', $email);
|
||||
|
||||
if (empty($result)) {
|
||||
common_debug("XXXXXXXXXXXXXXXXXX We've never seen this email before!!!");
|
||||
return true;
|
||||
}
|
||||
common_debug("XXXXXXXXXXXXXXXXXX dupe email address!!!!");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
122
plugins/FacebookBridge/actions/facebooklogin.php
Normal file
122
plugins/FacebookBridge/actions/facebooklogin.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* An action for logging in with Facebook
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class FacebookloginAction extends Action
|
||||
{
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (common_is_real_login()) {
|
||||
$this->clientError(_m('Already logged in.'));
|
||||
} else {
|
||||
$this->showPage();
|
||||
}
|
||||
}
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
// TRANS: Instructions.
|
||||
return _m('Login with your Facebook Account');
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
$instr = $this->getInstructions();
|
||||
$output = common_markup_to_html($instr);
|
||||
$this->elementStart('div', 'instructions');
|
||||
$this->raw($output);
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
// TRANS: Page title.
|
||||
return _m('Login with Facebook');
|
||||
}
|
||||
|
||||
function showContent() {
|
||||
|
||||
$this->elementStart('fieldset');
|
||||
|
||||
$facebook = Facebookclient::getFacebook();
|
||||
|
||||
// Degrade to plain link if JavaScript is not available
|
||||
$this->elementStart(
|
||||
'a',
|
||||
array(
|
||||
'href' => $facebook->getLoginUrl(
|
||||
array(
|
||||
'next' => common_local_url('facebookfinishlogin'),
|
||||
'cancel' => common_local_url('facebooklogin')
|
||||
)
|
||||
),
|
||||
'id' => 'facebook_button'
|
||||
)
|
||||
);
|
||||
|
||||
$attrs = array(
|
||||
'src' => common_path(
|
||||
'plugins/FacebookBridge/images/login-button.png',
|
||||
true
|
||||
),
|
||||
'alt' => 'Login with Facebook',
|
||||
'title' => 'Login with Facebook'
|
||||
);
|
||||
|
||||
$this->element('img', $attrs);
|
||||
|
||||
$this->elementEnd('a');
|
||||
|
||||
/*
|
||||
$this->element('div', array('id' => 'fb-root'));
|
||||
$this->script(
|
||||
sprintf(
|
||||
'http://connect.facebook.net/en_US/all.js#appId=%s&xfbml=1',
|
||||
common_config('facebook', 'appid')
|
||||
)
|
||||
);
|
||||
$this->element('fb:facepile', array('max-rows' => '2', 'width' =>'300'));
|
||||
*/
|
||||
$this->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
{
|
||||
$nav = new LoginGroupNav($this);
|
||||
$nav->show();
|
||||
}
|
||||
}
|
||||
|
271
plugins/FacebookBridge/actions/facebooksettings.php
Normal file
271
plugins/FacebookBridge/actions/facebooksettings.php
Normal file
@ -0,0 +1,271 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Edit user settings for Facebook
|
||||
*
|
||||
* 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 Settings
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit user settings for Facebook
|
||||
*
|
||||
* @category Settings
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <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 SettingsAction
|
||||
*/
|
||||
class FacebooksettingsAction extends ConnectSettingsAction {
|
||||
|
||||
private $facebook; // Facebook PHP-SDK client obj
|
||||
private $flink;
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* For initializing members of the class.
|
||||
*
|
||||
* @param array $argarray misc. arguments
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function prepare($args) {
|
||||
parent::prepare($args);
|
||||
|
||||
$this->facebook = new Facebook(
|
||||
array(
|
||||
'appId' => common_config('facebook', 'appid'),
|
||||
'secret' => common_config('facebook', 'secret'),
|
||||
'cookie' => true,
|
||||
)
|
||||
);
|
||||
|
||||
$this->user = common_current_user();
|
||||
|
||||
$this->flink = Foreign_link::getByUserID(
|
||||
$this->user->id,
|
||||
FACEBOOK_SERVICE
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the sessions token and dispatch
|
||||
*/
|
||||
function handlePost($args) {
|
||||
// CSRF protection
|
||||
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(
|
||||
_m('There was a problem with your session token. Try again, please.')
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->arg('save')) {
|
||||
$this->saveSettings();
|
||||
} else if ($this->arg('disconnect')) {
|
||||
$this->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page title
|
||||
*
|
||||
* @return string page title
|
||||
*/
|
||||
function title() {
|
||||
// TRANS: Page title for Facebook settings.
|
||||
return _m('Facebook settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for use
|
||||
*
|
||||
* @return instructions for use
|
||||
*/
|
||||
function getInstructions() {
|
||||
return _('Facebook settings');
|
||||
}
|
||||
|
||||
/*
|
||||
* Show the settings form if he/she has a link to Facebook
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showContent() {
|
||||
|
||||
if (!empty($this->flink)) {
|
||||
|
||||
$this->elementStart(
|
||||
'form',
|
||||
array(
|
||||
'method' => 'post',
|
||||
'id' => 'form_settings_facebook',
|
||||
'class' => 'form_settings',
|
||||
'action' => common_local_url('facebooksettings')
|
||||
)
|
||||
);
|
||||
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
$this->element('p', 'form_note', _m('Connected Facebook user'));
|
||||
|
||||
$this->elementStart('p', array('class' => 'facebook-user-display'));
|
||||
|
||||
$this->element(
|
||||
'fb:profile-pic',
|
||||
array(
|
||||
'uid' => $this->flink->foreign_id,
|
||||
'size' => 'small',
|
||||
'linked' => 'true',
|
||||
'facebook-logo' => 'true'
|
||||
)
|
||||
);
|
||||
|
||||
$this->element(
|
||||
'fb:name',
|
||||
array('uid' => $this->flink->foreign_id, 'useyou' => 'false')
|
||||
);
|
||||
|
||||
$this->elementEnd('p');
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
|
||||
$this->elementStart('li');
|
||||
|
||||
$this->checkbox(
|
||||
'noticesync',
|
||||
_m('Publish my notices to Facebook.'),
|
||||
($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND) : true
|
||||
);
|
||||
|
||||
$this->elementEnd('li');
|
||||
|
||||
$this->elementStart('li');
|
||||
|
||||
$this->checkbox(
|
||||
'replysync',
|
||||
_m('Send "@" replies to Facebook.'),
|
||||
($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) : true
|
||||
);
|
||||
|
||||
$this->elementEnd('li');
|
||||
|
||||
$this->elementStart('li');
|
||||
|
||||
// TRANS: Submit button to save synchronisation settings.
|
||||
$this->submit('save', _m('BUTTON', 'Save'));
|
||||
|
||||
$this->elementEnd('li');
|
||||
|
||||
$this->elementEnd('ul');
|
||||
|
||||
$this->elementStart('fieldset');
|
||||
|
||||
// TRANS: Legend.
|
||||
$this->element('legend', null, _m('Disconnect my account from Facebook'));
|
||||
|
||||
if (empty($this->user->password)) {
|
||||
|
||||
$this->elementStart('p', array('class' => 'form_guide'));
|
||||
|
||||
$msg = sprintf(
|
||||
_m(
|
||||
'Disconnecting your Faceboook would make it impossible to '
|
||||
. 'log in! Please [set a password](%s) first.'
|
||||
),
|
||||
common_local_url('passwordsettings')
|
||||
);
|
||||
|
||||
$this->raw(common_markup_to_html($msg));
|
||||
$this->elementEnd('p');
|
||||
|
||||
} else {
|
||||
|
||||
$msg = sprintf(
|
||||
_m(
|
||||
'Keep your %1$s account but disconnect from Facebook. ' .
|
||||
'You\'ll use your 1%$s password to log in.'
|
||||
),
|
||||
common_config('site', 'name')
|
||||
);
|
||||
|
||||
// TRANS: Submit button.
|
||||
$this->submit('disconnect', _m('BUTTON', 'Disconnect'));
|
||||
}
|
||||
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the user's Facebook settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function saveSettings() {
|
||||
|
||||
$noticesync = $this->boolean('noticesync');
|
||||
$replysync = $this->boolean('replysync');
|
||||
|
||||
$original = clone($this->flink);
|
||||
$this->flink->set_flags($noticesync, false, $replysync, false);
|
||||
$result = $this->flink->update($original);
|
||||
|
||||
if ($result === false) {
|
||||
$this->showForm(_m('There was a problem saving your sync preferences.'));
|
||||
} else {
|
||||
// TRANS: Confirmation that synchronisation settings have been saved into the system.
|
||||
$this->showForm(_m('Sync preferences saved.'), true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disconnect the user's Facebook account - deletes the Foreign_link
|
||||
* and shows the user a success message if all goes well.
|
||||
*/
|
||||
function disconnect() {
|
||||
|
||||
$result = $this->flink->delete();
|
||||
$this->flink = null;
|
||||
|
||||
if ($result === false) {
|
||||
common_log_db_error($user, 'DELETE', __FILE__);
|
||||
$this->serverError(_m('Couldn\'t delete link to Facebook.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->showForm(_m('You have disconnected from Facebook.'), true);
|
||||
}
|
||||
|
||||
}
|
190
plugins/FacebookBridge/classes/Notice_to_item.php
Normal file
190
plugins/FacebookBridge/classes/Notice_to_item.php
Normal file
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/**
|
||||
* Data class for storing notice-to-Facebook-item mappings
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Data
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
|
||||
|
||||
/**
|
||||
* Data class for mapping notices to Facebook stream items
|
||||
*
|
||||
* Note that notice_id is unique only within a single database; if you
|
||||
* want to share this data for some reason, get the notice's URI and use
|
||||
* that instead, since it's universally unique.
|
||||
*
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*
|
||||
* @see DB_DataObject
|
||||
*/
|
||||
|
||||
class Notice_to_item extends Memcached_DataObject
|
||||
{
|
||||
public $__table = 'notice_to_item'; // table name
|
||||
public $notice_id; // int(4) primary_key not_null
|
||||
public $item_id; // varchar(255) not null
|
||||
public $created; // datetime
|
||||
|
||||
/**
|
||||
* Get an instance by key
|
||||
*
|
||||
* This is a utility method to get a single instance with a given key value.
|
||||
*
|
||||
* @param string $k Key to use to lookup
|
||||
* @param mixed $v Value to lookup
|
||||
*
|
||||
* @return Notice_to_item object found, or null for no hits
|
||||
*
|
||||
*/
|
||||
|
||||
function staticGet($k, $v=null)
|
||||
{
|
||||
return Memcached_DataObject::staticGet('Notice_to_item', $k, $v);
|
||||
}
|
||||
|
||||
/**
|
||||
* return table definition for DB_DataObject
|
||||
*
|
||||
* DB_DataObject needs to know something about the table to manipulate
|
||||
* instances. This method provides all the DB_DataObject needs to know.
|
||||
*
|
||||
* @return array array of column definitions
|
||||
*/
|
||||
|
||||
function table()
|
||||
{
|
||||
return array(
|
||||
'notice_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
|
||||
'item_id' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
|
||||
'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL
|
||||
);
|
||||
}
|
||||
|
||||
static function schemaDef()
|
||||
{
|
||||
return array(
|
||||
new ColumnDef('notice_id', 'integer', null, false, 'PRI'),
|
||||
new ColumnDef('item_id', 'varchar', 255, false, 'UNI'),
|
||||
new ColumnDef('created', 'datetime', null, false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* return key definitions for DB_DataObject
|
||||
*
|
||||
* DB_DataObject needs to know about keys that the table has, since it
|
||||
* won't appear in StatusNet's own keys list. In most cases, this will
|
||||
* simply reference your keyTypes() function.
|
||||
*
|
||||
* @return array list of key field names
|
||||
*/
|
||||
|
||||
function keys()
|
||||
{
|
||||
return array_keys($this->keyTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* return key definitions for Memcached_DataObject
|
||||
*
|
||||
* Our caching system uses the same key definitions, but uses a different
|
||||
* method to get them. This key information is used to store and clear
|
||||
* cached data, so be sure to list any key that will be used for static
|
||||
* lookups.
|
||||
*
|
||||
* @return array associative array of key definitions, field name to type:
|
||||
* 'K' for primary key: for compound keys, add an entry for each component;
|
||||
* 'U' for unique keys: compound keys are not well supported here.
|
||||
*/
|
||||
|
||||
function keyTypes()
|
||||
{
|
||||
return array('notice_id' => 'K', 'item_id' => 'U');
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic formula for non-autoincrementing integer primary keys
|
||||
*
|
||||
* If a table has a single integer column as its primary key, DB_DataObject
|
||||
* assumes that the column is auto-incrementing and makes a sequence table
|
||||
* to do this incrementation. Since we don't need this for our class, we
|
||||
* overload this method and return the magic formula that DB_DataObject needs.
|
||||
*
|
||||
* @return array magic three-false array that stops auto-incrementing.
|
||||
*/
|
||||
|
||||
function sequenceKey()
|
||||
{
|
||||
return array(false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a mapping between a notice and a Facebook item
|
||||
*
|
||||
* @param integer $notice_id ID of the notice in StatusNet
|
||||
* @param integer $item_id ID of the stream item on Facebook
|
||||
*
|
||||
* @return Notice_to_item new object for this value
|
||||
*/
|
||||
|
||||
static function saveNew($notice_id, $item_id)
|
||||
{
|
||||
$n2i = Notice_to_item::staticGet('notice_id', $notice_id);
|
||||
|
||||
if (!empty($n2i)) {
|
||||
return $n2i;
|
||||
}
|
||||
|
||||
$n2i = Notice_to_item::staticGet('item_id', $item_id);
|
||||
|
||||
if (!empty($n2i)) {
|
||||
return $n2i;
|
||||
}
|
||||
|
||||
common_debug(
|
||||
"Mapping notice {$notice_id} to Facebook item {$item_id}",
|
||||
__FILE__
|
||||
);
|
||||
|
||||
$n2i = new Notice_to_item();
|
||||
|
||||
$n2i->notice_id = $notice_id;
|
||||
$n2i->item_id = $item_id;
|
||||
$n2i->created = common_sql_now();
|
||||
|
||||
$n2i->insert();
|
||||
|
||||
return $n2i;
|
||||
}
|
||||
}
|
963
plugins/FacebookBridge/extlib/facebook.php
Normal file
963
plugins/FacebookBridge/extlib/facebook.php
Normal file
@ -0,0 +1,963 @@
|
||||
<?php
|
||||
|
||||
if (!function_exists('curl_init')) {
|
||||
throw new Exception('Facebook needs the CURL PHP extension.');
|
||||
}
|
||||
if (!function_exists('json_decode')) {
|
||||
throw new Exception('Facebook needs the JSON PHP extension.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when an API call returns an exception.
|
||||
*
|
||||
* @author Naitik Shah <naitik@facebook.com>
|
||||
*/
|
||||
class FacebookApiException extends Exception
|
||||
{
|
||||
/**
|
||||
* The result from the API server that represents the exception information.
|
||||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* Make a new API Exception with the given result.
|
||||
*
|
||||
* @param Array $result the result from the API server
|
||||
*/
|
||||
public function __construct($result) {
|
||||
$this->result = $result;
|
||||
|
||||
$code = isset($result['error_code']) ? $result['error_code'] : 0;
|
||||
|
||||
if (isset($result['error_description'])) {
|
||||
// OAuth 2.0 Draft 10 style
|
||||
$msg = $result['error_description'];
|
||||
} else if (isset($result['error']) && is_array($result['error'])) {
|
||||
// OAuth 2.0 Draft 00 style
|
||||
$msg = $result['error']['message'];
|
||||
} else if (isset($result['error_msg'])) {
|
||||
// Rest server style
|
||||
$msg = $result['error_msg'];
|
||||
} else {
|
||||
$msg = 'Unknown Error. Check getResult()';
|
||||
}
|
||||
|
||||
parent::__construct($msg, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated result object returned by the API server.
|
||||
*
|
||||
* @returns Array the result from the API server
|
||||
*/
|
||||
public function getResult() {
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated type for the error. This will default to
|
||||
* 'Exception' when a type is not available.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public function getType() {
|
||||
if (isset($this->result['error'])) {
|
||||
$error = $this->result['error'];
|
||||
if (is_string($error)) {
|
||||
// OAuth 2.0 Draft 10 style
|
||||
return $error;
|
||||
} else if (is_array($error)) {
|
||||
// OAuth 2.0 Draft 00 style
|
||||
if (isset($error['type'])) {
|
||||
return $error['type'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'Exception';
|
||||
}
|
||||
|
||||
/**
|
||||
* To make debugging easier.
|
||||
*
|
||||
* @returns String the string representation of the error
|
||||
*/
|
||||
public function __toString() {
|
||||
$str = $this->getType() . ': ';
|
||||
if ($this->code != 0) {
|
||||
$str .= $this->code . ': ';
|
||||
}
|
||||
return $str . $this->message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the Facebook Platform.
|
||||
*
|
||||
* @author Naitik Shah <naitik@facebook.com>
|
||||
*/
|
||||
class Facebook
|
||||
{
|
||||
/**
|
||||
* Version.
|
||||
*/
|
||||
const VERSION = '2.1.2';
|
||||
|
||||
/**
|
||||
* Default options for curl.
|
||||
*/
|
||||
public static $CURL_OPTS = array(
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 60,
|
||||
CURLOPT_USERAGENT => 'facebook-php-2.0',
|
||||
);
|
||||
|
||||
/**
|
||||
* List of query parameters that get automatically dropped when rebuilding
|
||||
* the current URL.
|
||||
*/
|
||||
protected static $DROP_QUERY_PARAMS = array(
|
||||
'session',
|
||||
'signed_request',
|
||||
);
|
||||
|
||||
/**
|
||||
* Maps aliases to Facebook domains.
|
||||
*/
|
||||
public static $DOMAIN_MAP = array(
|
||||
'api' => 'https://api.facebook.com/',
|
||||
'api_read' => 'https://api-read.facebook.com/',
|
||||
'graph' => 'https://graph.facebook.com/',
|
||||
'www' => 'https://www.facebook.com/',
|
||||
);
|
||||
|
||||
/**
|
||||
* The Application ID.
|
||||
*/
|
||||
protected $appId;
|
||||
|
||||
/**
|
||||
* The Application API Secret.
|
||||
*/
|
||||
protected $apiSecret;
|
||||
|
||||
/**
|
||||
* The active user session, if one is available.
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* The data from the signed_request token.
|
||||
*/
|
||||
protected $signedRequest;
|
||||
|
||||
/**
|
||||
* Indicates that we already loaded the session as best as we could.
|
||||
*/
|
||||
protected $sessionLoaded = false;
|
||||
|
||||
/**
|
||||
* Indicates if Cookie support should be enabled.
|
||||
*/
|
||||
protected $cookieSupport = false;
|
||||
|
||||
/**
|
||||
* Base domain for the Cookie.
|
||||
*/
|
||||
protected $baseDomain = '';
|
||||
|
||||
/**
|
||||
* Indicates if the CURL based @ syntax for file uploads is enabled.
|
||||
*/
|
||||
protected $fileUploadSupport = false;
|
||||
|
||||
/**
|
||||
* Initialize a Facebook Application.
|
||||
*
|
||||
* The configuration:
|
||||
* - appId: the application ID
|
||||
* - secret: the application secret
|
||||
* - cookie: (optional) boolean true to enable cookie support
|
||||
* - domain: (optional) domain for the cookie
|
||||
* - fileUpload: (optional) boolean indicating if file uploads are enabled
|
||||
*
|
||||
* @param Array $config the application configuration
|
||||
*/
|
||||
public function __construct($config) {
|
||||
$this->setAppId($config['appId']);
|
||||
$this->setApiSecret($config['secret']);
|
||||
if (isset($config['cookie'])) {
|
||||
$this->setCookieSupport($config['cookie']);
|
||||
}
|
||||
if (isset($config['domain'])) {
|
||||
$this->setBaseDomain($config['domain']);
|
||||
}
|
||||
if (isset($config['fileUpload'])) {
|
||||
$this->setFileUploadSupport($config['fileUpload']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Application ID.
|
||||
*
|
||||
* @param String $appId the Application ID
|
||||
*/
|
||||
public function setAppId($appId) {
|
||||
$this->appId = $appId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Application ID.
|
||||
*
|
||||
* @return String the Application ID
|
||||
*/
|
||||
public function getAppId() {
|
||||
return $this->appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the API Secret.
|
||||
*
|
||||
* @param String $appId the API Secret
|
||||
*/
|
||||
public function setApiSecret($apiSecret) {
|
||||
$this->apiSecret = $apiSecret;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the API Secret.
|
||||
*
|
||||
* @return String the API Secret
|
||||
*/
|
||||
public function getApiSecret() {
|
||||
return $this->apiSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Cookie Support status.
|
||||
*
|
||||
* @param Boolean $cookieSupport the Cookie Support status
|
||||
*/
|
||||
public function setCookieSupport($cookieSupport) {
|
||||
$this->cookieSupport = $cookieSupport;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Cookie Support status.
|
||||
*
|
||||
* @return Boolean the Cookie Support status
|
||||
*/
|
||||
public function useCookieSupport() {
|
||||
return $this->cookieSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base domain for the Cookie.
|
||||
*
|
||||
* @param String $domain the base domain
|
||||
*/
|
||||
public function setBaseDomain($domain) {
|
||||
$this->baseDomain = $domain;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base domain for the Cookie.
|
||||
*
|
||||
* @return String the base domain
|
||||
*/
|
||||
public function getBaseDomain() {
|
||||
return $this->baseDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file upload support status.
|
||||
*
|
||||
* @param String $domain the base domain
|
||||
*/
|
||||
public function setFileUploadSupport($fileUploadSupport) {
|
||||
$this->fileUploadSupport = $fileUploadSupport;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file upload support status.
|
||||
*
|
||||
* @return String the base domain
|
||||
*/
|
||||
public function useFileUploadSupport() {
|
||||
return $this->fileUploadSupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data from a signed_request token
|
||||
*
|
||||
* @return String the base domain
|
||||
*/
|
||||
public function getSignedRequest() {
|
||||
if (!$this->signedRequest) {
|
||||
if (isset($_REQUEST['signed_request'])) {
|
||||
$this->signedRequest = $this->parseSignedRequest(
|
||||
$_REQUEST['signed_request']);
|
||||
}
|
||||
}
|
||||
return $this->signedRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Session.
|
||||
*
|
||||
* @param Array $session the session
|
||||
* @param Boolean $write_cookie indicate if a cookie should be written. this
|
||||
* value is ignored if cookie support has been disabled.
|
||||
*/
|
||||
public function setSession($session=null, $write_cookie=true) {
|
||||
$session = $this->validateSessionObject($session);
|
||||
$this->sessionLoaded = true;
|
||||
$this->session = $session;
|
||||
if ($write_cookie) {
|
||||
$this->setCookieFromSession($session);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session object. This will automatically look for a signed session
|
||||
* sent via the signed_request, Cookie or Query Parameters if needed.
|
||||
*
|
||||
* @return Array the session
|
||||
*/
|
||||
public function getSession() {
|
||||
if (!$this->sessionLoaded) {
|
||||
$session = null;
|
||||
$write_cookie = true;
|
||||
|
||||
// try loading session from signed_request in $_REQUEST
|
||||
$signedRequest = $this->getSignedRequest();
|
||||
if ($signedRequest) {
|
||||
// sig is good, use the signedRequest
|
||||
$session = $this->createSessionFromSignedRequest($signedRequest);
|
||||
}
|
||||
|
||||
// try loading session from $_REQUEST
|
||||
if (!$session && isset($_REQUEST['session'])) {
|
||||
$session = json_decode(
|
||||
get_magic_quotes_gpc()
|
||||
? stripslashes($_REQUEST['session'])
|
||||
: $_REQUEST['session'],
|
||||
true
|
||||
);
|
||||
$session = $this->validateSessionObject($session);
|
||||
}
|
||||
|
||||
// try loading session from cookie if necessary
|
||||
if (!$session && $this->useCookieSupport()) {
|
||||
$cookieName = $this->getSessionCookieName();
|
||||
if (isset($_COOKIE[$cookieName])) {
|
||||
$session = array();
|
||||
parse_str(trim(
|
||||
get_magic_quotes_gpc()
|
||||
? stripslashes($_COOKIE[$cookieName])
|
||||
: $_COOKIE[$cookieName],
|
||||
'"'
|
||||
), $session);
|
||||
$session = $this->validateSessionObject($session);
|
||||
// write only if we need to delete a invalid session cookie
|
||||
$write_cookie = empty($session);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setSession($session, $write_cookie);
|
||||
}
|
||||
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UID from the session.
|
||||
*
|
||||
* @return String the UID if available
|
||||
*/
|
||||
public function getUser() {
|
||||
$session = $this->getSession();
|
||||
return $session ? $session['uid'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a OAuth access token.
|
||||
*
|
||||
* @return String the access token
|
||||
*/
|
||||
public function getAccessToken() {
|
||||
$session = $this->getSession();
|
||||
// either user session signed, or app signed
|
||||
if ($session) {
|
||||
return $session['access_token'];
|
||||
} else {
|
||||
return $this->getAppId() .'|'. $this->getApiSecret();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Login URL for use with redirects. By default, full page redirect is
|
||||
* assumed. If you are using the generated URL with a window.open() call in
|
||||
* JavaScript, you can pass in display=popup as part of the $params.
|
||||
*
|
||||
* The parameters:
|
||||
* - next: the url to go to after a successful login
|
||||
* - cancel_url: the url to go to after the user cancels
|
||||
* - req_perms: comma separated list of requested extended perms
|
||||
* - display: can be "page" (default, full page) or "popup"
|
||||
*
|
||||
* @param Array $params provide custom parameters
|
||||
* @return String the URL for the login flow
|
||||
*/
|
||||
public function getLoginUrl($params=array()) {
|
||||
$currentUrl = $this->getCurrentUrl();
|
||||
return $this->getUrl(
|
||||
'www',
|
||||
'login.php',
|
||||
array_merge(array(
|
||||
'api_key' => $this->getAppId(),
|
||||
'cancel_url' => $currentUrl,
|
||||
'display' => 'page',
|
||||
'fbconnect' => 1,
|
||||
'next' => $currentUrl,
|
||||
'return_session' => 1,
|
||||
'session_version' => 3,
|
||||
'v' => '1.0',
|
||||
), $params)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Logout URL suitable for use with redirects.
|
||||
*
|
||||
* The parameters:
|
||||
* - next: the url to go to after a successful logout
|
||||
*
|
||||
* @param Array $params provide custom parameters
|
||||
* @return String the URL for the logout flow
|
||||
*/
|
||||
public function getLogoutUrl($params=array()) {
|
||||
return $this->getUrl(
|
||||
'www',
|
||||
'logout.php',
|
||||
array_merge(array(
|
||||
'next' => $this->getCurrentUrl(),
|
||||
'access_token' => $this->getAccessToken(),
|
||||
), $params)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a login status URL to fetch the status from facebook.
|
||||
*
|
||||
* The parameters:
|
||||
* - ok_session: the URL to go to if a session is found
|
||||
* - no_session: the URL to go to if the user is not connected
|
||||
* - no_user: the URL to go to if the user is not signed into facebook
|
||||
*
|
||||
* @param Array $params provide custom parameters
|
||||
* @return String the URL for the logout flow
|
||||
*/
|
||||
public function getLoginStatusUrl($params=array()) {
|
||||
return $this->getUrl(
|
||||
'www',
|
||||
'extern/login_status.php',
|
||||
array_merge(array(
|
||||
'api_key' => $this->getAppId(),
|
||||
'no_session' => $this->getCurrentUrl(),
|
||||
'no_user' => $this->getCurrentUrl(),
|
||||
'ok_session' => $this->getCurrentUrl(),
|
||||
'session_version' => 3,
|
||||
), $params)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API call.
|
||||
*
|
||||
* @param Array $params the API call parameters
|
||||
* @return the decoded response
|
||||
*/
|
||||
public function api(/* polymorphic */) {
|
||||
$args = func_get_args();
|
||||
if (is_array($args[0])) {
|
||||
return $this->_restserver($args[0]);
|
||||
} else {
|
||||
return call_user_func_array(array($this, '_graph'), $args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the old restserver.php endpoint.
|
||||
*
|
||||
* @param Array $params method call object
|
||||
* @return the decoded response object
|
||||
* @throws FacebookApiException
|
||||
*/
|
||||
protected function _restserver($params) {
|
||||
// generic application level parameters
|
||||
$params['api_key'] = $this->getAppId();
|
||||
$params['format'] = 'json-strings';
|
||||
|
||||
$result = json_decode($this->_oauthRequest(
|
||||
$this->getApiUrl($params['method']),
|
||||
$params
|
||||
), true);
|
||||
|
||||
// results are returned, errors are thrown
|
||||
if (is_array($result) && isset($result['error_code'])) {
|
||||
throw new FacebookApiException($result);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the Graph API.
|
||||
*
|
||||
* @param String $path the path (required)
|
||||
* @param String $method the http method (default 'GET')
|
||||
* @param Array $params the query/post data
|
||||
* @return the decoded response object
|
||||
* @throws FacebookApiException
|
||||
*/
|
||||
protected function _graph($path, $method='GET', $params=array()) {
|
||||
if (is_array($method) && empty($params)) {
|
||||
$params = $method;
|
||||
$method = 'GET';
|
||||
}
|
||||
$params['method'] = $method; // method override as we always do a POST
|
||||
|
||||
$result = json_decode($this->_oauthRequest(
|
||||
$this->getUrl('graph', $path),
|
||||
$params
|
||||
), true);
|
||||
|
||||
// results are returned, errors are thrown
|
||||
if (is_array($result) && isset($result['error'])) {
|
||||
$e = new FacebookApiException($result);
|
||||
switch ($e->getType()) {
|
||||
// OAuth 2.0 Draft 00 style
|
||||
case 'OAuthException':
|
||||
// OAuth 2.0 Draft 10 style
|
||||
case 'invalid_token':
|
||||
$this->setSession(null);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a OAuth Request
|
||||
*
|
||||
* @param String $path the path (required)
|
||||
* @param Array $params the query/post data
|
||||
* @return the decoded response object
|
||||
* @throws FacebookApiException
|
||||
*/
|
||||
protected function _oauthRequest($url, $params) {
|
||||
if (!isset($params['access_token'])) {
|
||||
$params['access_token'] = $this->getAccessToken();
|
||||
}
|
||||
|
||||
// json_encode all params values that are not strings
|
||||
foreach ($params as $key => $value) {
|
||||
if (!is_string($value)) {
|
||||
$params[$key] = json_encode($value);
|
||||
}
|
||||
}
|
||||
return $this->makeRequest($url, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an HTTP request. This method can be overriden by subclasses if
|
||||
* developers want to do fancier things or use something other than curl to
|
||||
* make the request.
|
||||
*
|
||||
* @param String $url the URL to make the request to
|
||||
* @param Array $params the parameters to use for the POST body
|
||||
* @param CurlHandler $ch optional initialized curl handle
|
||||
* @return String the response text
|
||||
*/
|
||||
protected function makeRequest($url, $params, $ch=null) {
|
||||
if (!$ch) {
|
||||
$ch = curl_init();
|
||||
}
|
||||
|
||||
$opts = self::$CURL_OPTS;
|
||||
if ($this->useFileUploadSupport()) {
|
||||
$opts[CURLOPT_POSTFIELDS] = $params;
|
||||
} else {
|
||||
$opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&');
|
||||
}
|
||||
$opts[CURLOPT_URL] = $url;
|
||||
|
||||
// disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
|
||||
// for 2 seconds if the server does not support this header.
|
||||
if (isset($opts[CURLOPT_HTTPHEADER])) {
|
||||
$existing_headers = $opts[CURLOPT_HTTPHEADER];
|
||||
$existing_headers[] = 'Expect:';
|
||||
$opts[CURLOPT_HTTPHEADER] = $existing_headers;
|
||||
} else {
|
||||
$opts[CURLOPT_HTTPHEADER] = array('Expect:');
|
||||
}
|
||||
|
||||
curl_setopt_array($ch, $opts);
|
||||
$result = curl_exec($ch);
|
||||
|
||||
if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
|
||||
self::errorLog('Invalid or no certificate authority found, using bundled information');
|
||||
curl_setopt($ch, CURLOPT_CAINFO,
|
||||
dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
|
||||
$result = curl_exec($ch);
|
||||
}
|
||||
|
||||
if ($result === false) {
|
||||
$e = new FacebookApiException(array(
|
||||
'error_code' => curl_errno($ch),
|
||||
'error' => array(
|
||||
'message' => curl_error($ch),
|
||||
'type' => 'CurlException',
|
||||
),
|
||||
));
|
||||
curl_close($ch);
|
||||
throw $e;
|
||||
}
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the Cookie that contains the session.
|
||||
*
|
||||
* @return String the cookie name
|
||||
*/
|
||||
protected function getSessionCookieName() {
|
||||
return 'fbs_' . $this->getAppId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JS Cookie based on the _passed in_ session. It does not use the
|
||||
* currently stored session -- you need to explicitly pass it in.
|
||||
*
|
||||
* @param Array $session the session to use for setting the cookie
|
||||
*/
|
||||
protected function setCookieFromSession($session=null) {
|
||||
if (!$this->useCookieSupport()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cookieName = $this->getSessionCookieName();
|
||||
$value = 'deleted';
|
||||
$expires = time() - 3600;
|
||||
$domain = $this->getBaseDomain();
|
||||
if ($session) {
|
||||
$value = '"' . http_build_query($session, null, '&') . '"';
|
||||
if (isset($session['base_domain'])) {
|
||||
$domain = $session['base_domain'];
|
||||
}
|
||||
$expires = $session['expires'];
|
||||
}
|
||||
|
||||
// prepend dot if a domain is found
|
||||
if ($domain) {
|
||||
$domain = '.' . $domain;
|
||||
}
|
||||
|
||||
// if an existing cookie is not set, we dont need to delete it
|
||||
if ($value == 'deleted' && empty($_COOKIE[$cookieName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (headers_sent()) {
|
||||
self::errorLog('Could not set cookie. Headers already sent.');
|
||||
|
||||
// ignore for code coverage as we will never be able to setcookie in a CLI
|
||||
// environment
|
||||
// @codeCoverageIgnoreStart
|
||||
} else {
|
||||
setcookie($cookieName, $value, $expires, '/', $domain);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a session_version=3 style session object.
|
||||
*
|
||||
* @param Array $session the session object
|
||||
* @return Array the session object if it validates, null otherwise
|
||||
*/
|
||||
protected function validateSessionObject($session) {
|
||||
// make sure some essential fields exist
|
||||
if (is_array($session) &&
|
||||
isset($session['uid']) &&
|
||||
isset($session['access_token']) &&
|
||||
isset($session['sig'])) {
|
||||
// validate the signature
|
||||
$session_without_sig = $session;
|
||||
unset($session_without_sig['sig']);
|
||||
$expected_sig = self::generateSignature(
|
||||
$session_without_sig,
|
||||
$this->getApiSecret()
|
||||
);
|
||||
if ($session['sig'] != $expected_sig) {
|
||||
self::errorLog('Got invalid session signature in cookie.');
|
||||
$session = null;
|
||||
}
|
||||
// check expiry time
|
||||
} else {
|
||||
$session = null;
|
||||
}
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns something that looks like our JS session object from the
|
||||
* signed token's data
|
||||
*
|
||||
* TODO: Nuke this once the login flow uses OAuth2
|
||||
*
|
||||
* @param Array the output of getSignedRequest
|
||||
* @return Array Something that will work as a session
|
||||
*/
|
||||
protected function createSessionFromSignedRequest($data) {
|
||||
if (!isset($data['oauth_token'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$session = array(
|
||||
'uid' => $data['user_id'],
|
||||
'access_token' => $data['oauth_token'],
|
||||
'expires' => $data['expires'],
|
||||
);
|
||||
|
||||
// put a real sig, so that validateSignature works
|
||||
$session['sig'] = self::generateSignature(
|
||||
$session,
|
||||
$this->getApiSecret()
|
||||
);
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a signed_request and validates the signature.
|
||||
* Then saves it in $this->signed_data
|
||||
*
|
||||
* @param String A signed token
|
||||
* @param Boolean Should we remove the parts of the payload that
|
||||
* are used by the algorithm?
|
||||
* @return Array the payload inside it or null if the sig is wrong
|
||||
*/
|
||||
protected function parseSignedRequest($signed_request) {
|
||||
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
|
||||
|
||||
// decode the data
|
||||
$sig = self::base64UrlDecode($encoded_sig);
|
||||
$data = json_decode(self::base64UrlDecode($payload), true);
|
||||
|
||||
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
|
||||
self::errorLog('Unknown algorithm. Expected HMAC-SHA256');
|
||||
return null;
|
||||
}
|
||||
|
||||
// check sig
|
||||
$expected_sig = hash_hmac('sha256', $payload,
|
||||
$this->getApiSecret(), $raw = true);
|
||||
if ($sig !== $expected_sig) {
|
||||
self::errorLog('Bad Signed JSON signature!');
|
||||
return null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the URL for api given parameters.
|
||||
*
|
||||
* @param $method String the method name.
|
||||
* @return String the URL for the given parameters
|
||||
*/
|
||||
protected function getApiUrl($method) {
|
||||
static $READ_ONLY_CALLS =
|
||||
array('admin.getallocation' => 1,
|
||||
'admin.getappproperties' => 1,
|
||||
'admin.getbannedusers' => 1,
|
||||
'admin.getlivestreamvialink' => 1,
|
||||
'admin.getmetrics' => 1,
|
||||
'admin.getrestrictioninfo' => 1,
|
||||
'application.getpublicinfo' => 1,
|
||||
'auth.getapppublickey' => 1,
|
||||
'auth.getsession' => 1,
|
||||
'auth.getsignedpublicsessiondata' => 1,
|
||||
'comments.get' => 1,
|
||||
'connect.getunconnectedfriendscount' => 1,
|
||||
'dashboard.getactivity' => 1,
|
||||
'dashboard.getcount' => 1,
|
||||
'dashboard.getglobalnews' => 1,
|
||||
'dashboard.getnews' => 1,
|
||||
'dashboard.multigetcount' => 1,
|
||||
'dashboard.multigetnews' => 1,
|
||||
'data.getcookies' => 1,
|
||||
'events.get' => 1,
|
||||
'events.getmembers' => 1,
|
||||
'fbml.getcustomtags' => 1,
|
||||
'feed.getappfriendstories' => 1,
|
||||
'feed.getregisteredtemplatebundlebyid' => 1,
|
||||
'feed.getregisteredtemplatebundles' => 1,
|
||||
'fql.multiquery' => 1,
|
||||
'fql.query' => 1,
|
||||
'friends.arefriends' => 1,
|
||||
'friends.get' => 1,
|
||||
'friends.getappusers' => 1,
|
||||
'friends.getlists' => 1,
|
||||
'friends.getmutualfriends' => 1,
|
||||
'gifts.get' => 1,
|
||||
'groups.get' => 1,
|
||||
'groups.getmembers' => 1,
|
||||
'intl.gettranslations' => 1,
|
||||
'links.get' => 1,
|
||||
'notes.get' => 1,
|
||||
'notifications.get' => 1,
|
||||
'pages.getinfo' => 1,
|
||||
'pages.isadmin' => 1,
|
||||
'pages.isappadded' => 1,
|
||||
'pages.isfan' => 1,
|
||||
'permissions.checkavailableapiaccess' => 1,
|
||||
'permissions.checkgrantedapiaccess' => 1,
|
||||
'photos.get' => 1,
|
||||
'photos.getalbums' => 1,
|
||||
'photos.gettags' => 1,
|
||||
'profile.getinfo' => 1,
|
||||
'profile.getinfooptions' => 1,
|
||||
'stream.get' => 1,
|
||||
'stream.getcomments' => 1,
|
||||
'stream.getfilters' => 1,
|
||||
'users.getinfo' => 1,
|
||||
'users.getloggedinuser' => 1,
|
||||
'users.getstandardinfo' => 1,
|
||||
'users.hasapppermission' => 1,
|
||||
'users.isappuser' => 1,
|
||||
'users.isverified' => 1,
|
||||
'video.getuploadlimits' => 1);
|
||||
$name = 'api';
|
||||
if (isset($READ_ONLY_CALLS[strtolower($method)])) {
|
||||
$name = 'api_read';
|
||||
}
|
||||
return self::getUrl($name, 'restserver.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the URL for given domain alias, path and parameters.
|
||||
*
|
||||
* @param $name String the name of the domain
|
||||
* @param $path String optional path (without a leading slash)
|
||||
* @param $params Array optional query parameters
|
||||
* @return String the URL for the given parameters
|
||||
*/
|
||||
protected function getUrl($name, $path='', $params=array()) {
|
||||
$url = self::$DOMAIN_MAP[$name];
|
||||
if ($path) {
|
||||
if ($path[0] === '/') {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
$url .= $path;
|
||||
}
|
||||
if ($params) {
|
||||
$url .= '?' . http_build_query($params, null, '&');
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Current URL, stripping it of known FB parameters that should
|
||||
* not persist.
|
||||
*
|
||||
* @return String the current URL
|
||||
*/
|
||||
protected function getCurrentUrl() {
|
||||
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
|
||||
? 'https://'
|
||||
: 'http://';
|
||||
$currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||
$parts = parse_url($currentUrl);
|
||||
|
||||
// drop known fb params
|
||||
$query = '';
|
||||
if (!empty($parts['query'])) {
|
||||
$params = array();
|
||||
parse_str($parts['query'], $params);
|
||||
foreach(self::$DROP_QUERY_PARAMS as $key) {
|
||||
unset($params[$key]);
|
||||
}
|
||||
if (!empty($params)) {
|
||||
$query = '?' . http_build_query($params, null, '&');
|
||||
}
|
||||
}
|
||||
|
||||
// use port if non default
|
||||
$port =
|
||||
isset($parts['port']) &&
|
||||
(($protocol === 'http://' && $parts['port'] !== 80) ||
|
||||
($protocol === 'https://' && $parts['port'] !== 443))
|
||||
? ':' . $parts['port'] : '';
|
||||
|
||||
// rebuild
|
||||
return $protocol . $parts['host'] . $port . $parts['path'] . $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a signature for the given params and secret.
|
||||
*
|
||||
* @param Array $params the parameters to sign
|
||||
* @param String $secret the secret to sign with
|
||||
* @return String the generated signature
|
||||
*/
|
||||
protected static function generateSignature($params, $secret) {
|
||||
// work with sorted data
|
||||
ksort($params);
|
||||
|
||||
// generate the base string
|
||||
$base_string = '';
|
||||
foreach($params as $key => $value) {
|
||||
$base_string .= $key . '=' . $value;
|
||||
}
|
||||
$base_string .= $secret;
|
||||
|
||||
return md5($base_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints to the error log if you aren't in command line mode.
|
||||
*
|
||||
* @param String log message
|
||||
*/
|
||||
protected static function errorLog($msg) {
|
||||
// disable error log if we are running in a CLI environment
|
||||
// @codeCoverageIgnoreStart
|
||||
if (php_sapi_name() != 'cli') {
|
||||
error_log($msg);
|
||||
}
|
||||
// uncomment this if you want to see the errors on the page
|
||||
// print 'error_log: '.$msg."\n";
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64 encoding that doesn't need to be urlencode()ed.
|
||||
* Exactly the same as base64_encode except it uses
|
||||
* - instead of +
|
||||
* _ instead of /
|
||||
*
|
||||
* @param String base64UrlEncodeded string
|
||||
*/
|
||||
protected static function base64UrlDecode($input) {
|
||||
return base64_decode(strtr($input, '-_', '+/'));
|
||||
}
|
||||
}
|
121
plugins/FacebookBridge/extlib/fb_ca_chain_bundle.crt
Normal file
121
plugins/FacebookBridge/extlib/fb_ca_chain_bundle.crt
Normal file
@ -0,0 +1,121 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFgjCCBGqgAwIBAgIQDKKbZcnESGaLDuEaVk6fQjANBgkqhkiG9w0BAQUFADBm
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||
ZSBDQS0zMB4XDTEwMDExMzAwMDAwMFoXDTEzMDQxMTIzNTk1OVowaDELMAkGA1UE
|
||||
BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVBhbG8gQWx0bzEX
|
||||
MBUGA1UEChMORmFjZWJvb2ssIEluYy4xFzAVBgNVBAMUDiouZmFjZWJvb2suY29t
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9rzj7QIuLM3sdHu1HcI1VcR3g
|
||||
b5FExKNV646agxSle1aQ/sJev1mh/u91ynwqd2BQmM0brZ1Hc3QrfYyAaiGGgEkp
|
||||
xbhezyfeYhAyO0TKAYxPnm2cTjB5HICzk6xEIwFbA7SBJ2fSyW1CFhYZyo3tIBjj
|
||||
19VjKyBfpRaPkzLmRwIDAQABo4ICrDCCAqgwHwYDVR0jBBgwFoAUUOpzidsp+xCP
|
||||
nuUBINTeeZlIg/cwHQYDVR0OBBYEFPp+tsFBozkjrHlEnZ9J4cFj2eM0MA4GA1Ud
|
||||
DwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMF8GA1UdHwRYMFYwKaAnoCWGI2h0dHA6
|
||||
Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9jYTMtZmIuY3JsMCmgJ6AlhiNodHRwOi8vY3Js
|
||||
NC5kaWdpY2VydC5jb20vY2EzLWZiLmNybDCCAcYGA1UdIASCAb0wggG5MIIBtQYL
|
||||
YIZIAYb9bAEDAAEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0
|
||||
LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIB
|
||||
UgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkA
|
||||
YwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEA
|
||||
bgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMA
|
||||
UABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkA
|
||||
IABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwA
|
||||
aQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8A
|
||||
cgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMA
|
||||
ZQAuMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQUF
|
||||
AAOCAQEACOkTIdxMy11+CKrbGNLBSg5xHaTvu/v1wbyn3dO/mf68pPfJnX6ShPYy
|
||||
4XM4Vk0x4uaFaU4wAGke+nCKGi5dyg0Esg7nemLNKEJaFAJZ9enxZm334lSCeARy
|
||||
wlDtxULGOFRyGIZZPmbV2eNq5xdU/g3IuBEhL722mTpAye9FU/J8Wsnw54/gANyO
|
||||
Gzkewigua8ip8Lbs9Cht399yAfbfhUP1DrAm/xEcnHrzPr3cdCtOyJaM6SRPpRqH
|
||||
ITK5Nc06tat9lXVosSinT3KqydzxBYua9gCFFiR3x3DgZfvXkC6KDdUlDrNcJUub
|
||||
a1BHnLLP4mxTHL6faAXYd05IxNn/IA==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGVTCCBT2gAwIBAgIQCFH5WYFBRcq94CTiEsnCDjANBgkqhkiG9w0BAQUFADBs
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
|
||||
ZSBFViBSb290IENBMB4XDTA3MDQwMzAwMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
|
||||
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
|
||||
LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
|
||||
Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
|
||||
CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
|
||||
KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
|
||||
BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
|
||||
1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
|
||||
zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
|
||||
32duXvsCAwEAAaOCAvcwggLzMA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
|
||||
ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
|
||||
LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
|
||||
AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
|
||||
AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
|
||||
AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
|
||||
AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
|
||||
AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
|
||||
AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
|
||||
AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
|
||||
AHIAZQBuAGMAZQAuMA8GA1UdEwEB/wQFMAMBAf8wNAYIKwYBBQUHAQEEKDAmMCQG
|
||||
CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSBhzCB
|
||||
hDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFz
|
||||
c3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQu
|
||||
Y29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSMEGDAW
|
||||
gBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUBINTe
|
||||
eZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAF1PhPGoiNOjsrycbeUpSXfh59bcqdg1
|
||||
rslx3OXb3J0kIZCmz7cBHJvUV5eR13UWpRLXuT0uiT05aYrWNTf58SHEW0CtWakv
|
||||
XzoAKUMncQPkvTAyVab+hA4LmzgZLEN8rEO/dTHlIxxFVbdpCJG1z9fVsV7un5Tk
|
||||
1nq5GMO41lJjHBC6iy9tXcwFOPRWBW3vnuzoYTYMFEuFFFoMg08iXFnLjIpx2vrF
|
||||
EIRYzwfu45DC9fkpx1ojcflZtGQriLCnNseaIGHr+k61rmsb5OPs4tk8QUmoIKRU
|
||||
9ZKNu8BVIASm2LAXFszj0Mi0PeXZhMbT9m5teMl5Q+h6N/9cNUm/ocU=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEQjCCA6ugAwIBAgIEQoclDjANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
|
||||
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
|
||||
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
|
||||
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
|
||||
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEy
|
||||
MjIxNTI3MjdaFw0xNDA3MjIxNTU3MjdaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
|
||||
EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNV
|
||||
BAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD
|
||||
1ZQ0Z6IKHLBfaaZAscS3so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80lt
|
||||
cZF+Y7arpl/DpIT4T2JRvvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46
|
||||
OFBbdzEbjbPHJEWap6xtABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZd
|
||||
HFMsfpjNGgYWpGhz0DQEE1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdm
|
||||
t4i3ePLKCqg4qwpkwr9mXZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjggET
|
||||
MIIBDzASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggr
|
||||
BgEFBQcDAgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdo
|
||||
dHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8v
|
||||
Y3JsLmVudHJ1c3QubmV0L3NlcnZlcjEuY3JsMB0GA1UdDgQWBBSxPsNpA/i/RwHU
|
||||
mCYaCALvY2QrwzALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7
|
||||
UISX8+1i0BowGQYJKoZIhvZ9B0EABAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEF
|
||||
BQADgYEAUuVY7HCc/9EvhaYzC1rAIo348LtGIiMduEl5Xa24G8tmJnDioD2GU06r
|
||||
1kjLX/ktCdpdBgXadbjtdrZXTP59uN0AXlsdaTiFufsqVLPvkp5yMnqnuI3E2o6p
|
||||
NpAkoQSbB6kUCNnXcW26valgOjDLZFOnr241QiwdBAJAAE/rRa8=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
|
||||
VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
|
||||
ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
|
||||
KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
|
||||
ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
|
||||
MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
|
||||
ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
|
||||
b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
|
||||
bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
|
||||
U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
|
||||
A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
|
||||
I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
|
||||
wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
|
||||
AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
|
||||
oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
|
||||
BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
|
||||
dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
|
||||
MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
|
||||
b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
|
||||
dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
|
||||
MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
|
||||
E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
|
||||
MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
|
||||
hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
|
||||
95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
|
||||
2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
|
||||
-----END CERTIFICATE-----
|
BIN
plugins/FacebookBridge/images/login-button.png
Normal file
BIN
plugins/FacebookBridge/images/login-button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
1121
plugins/FacebookBridge/lib/facebookclient.php
Normal file
1121
plugins/FacebookBridge/lib/facebookclient.php
Normal file
File diff suppressed because it is too large
Load Diff
61
plugins/FacebookBridge/lib/facebookqueuehandler.php
Normal file
61
plugins/FacebookBridge/lib/facebookqueuehandler.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Queuehandler for Facebook transport
|
||||
*
|
||||
* 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 Plugin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class FacebookQueueHandler extends QueueHandler
|
||||
{
|
||||
function transport()
|
||||
{
|
||||
return 'facebook';
|
||||
}
|
||||
|
||||
function handle($notice)
|
||||
{
|
||||
if ($this->_isLocal($notice)) {
|
||||
return Facebookclient::facebookBroadcastNotice($notice);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the notice was locally created
|
||||
*
|
||||
* @param Notice $notice the notice
|
||||
*
|
||||
* @return boolean locality
|
||||
*/
|
||||
function _isLocal($notice)
|
||||
{
|
||||
return ($notice->is_local == Notice::LOCAL_PUBLIC ||
|
||||
$notice->is_local == Notice::LOCAL_NONPUBLIC);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user