include_once $dir . '/extlib/facebookapi_php5_restlib.php';
return false;
case 'FacebookloginAction':
- case 'FacebookregisterAction':
+ case 'FacebookfinishloginAction':
case 'FacebookadminpanelAction':
case 'FacebooksettingsAction':
include_once $dir . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
function needsScripts($action)
{
static $needy = array(
- 'FacebookloginAction',
- 'FacebookregisterAction',
+ //'FacebookloginAction',
+ 'FacebookfinishloginAction',
'FacebookadminpanelAction',
'FacebooksettingsAction'
);
if (in_array(get_class($action), $needy)) {
+ common_debug("needs scripts!");
return true;
} else {
+ common_debug("doesn't need scripts!");
return false;
}
}
array('action' => 'facebooklogin')
);
$m->connect(
- 'main/facebookregister',
- array('action' => 'facebookregister')
+ 'main/facebookfinishlogin',
+ array('action' => 'facebookfinishlogin')
);
$m->connect(
function onStartShowHeader($action)
{
- if ($this->needsScripts($action)) {
+ // output <div id="fb-root"></div> as close to <body> as possible
+ $action->element('div', array('id' => 'fb-root'));
+ return true;
+ }
- // output <div id="fb-root"></div> as close to <body> as possible
- $action->element('div', array('id' => 'fb-root'));
+ function onEndShowScripts($action)
+ {
+ if ($this->needsScripts($action)) {
- $dir = dirname(__FILE__);
+ $action->script('https://connect.facebook.net/en_US/all.js');
$script = <<<ENDOFSCRIPT
-window.fbAsyncInit = function() {
-
- FB.init({
- appId : %s,
- session : %s, // don't refetch the session when PHP already has it
- status : true, // check login status
- cookie : true, // enable cookies to allow the server to access the session
- xfbml : true // parse XFBML
- });
-
- // whenever the user logs in, refresh the page
- FB.Event.subscribe(
- 'auth.login',
- function() {
- window.location.reload();
+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)
}
- );
-};
-
-(function() {
- var e = document.createElement('script');
- e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
- e.async = true;
- document.getElementById('fb-root').appendChild(e);
-}());
+ }, {perms:'read_stream,publish_stream,offline_access,user_status,user_location,user_website'});
+});
ENDOFSCRIPT;
$action->inlineScript(
sprintf($script,
json_encode($this->facebook->getAppId()),
- json_encode($this->facebook->getSession())
+ json_encode($this->facebook->getSession()),
+ common_local_url('facebookfinishlogin')
)
);
}
-
- return true;
}
/*
--- /dev/null
+<?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') {
+
+ $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')
+ );
+ }
+ } else {
+
+ $this->tryLogin();
+ }
+ }
+
+ 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['firstname'] . ' ' . $this->fbuser['lastname'],
+ // XXX: Figure out how to get email
+ 'homepage' => $this->fbuser['link'],
+ 'bio' => $this->fbuser['about'],
+ 'location' => $this->fbuser['location']['name']
+ );
+
+ 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;
+ }
+
+ common_set_user($user);
+ common_real_login(true);
+
+ common_log(
+ LOG_INFO,
+ sprintf(
+ 'Registered new user %d from Facebook user %s',
+ $user->id,
+ $this->fbuid
+ ),
+ __FILE__
+ );
+
+ common_redirect(
+ common_local_url(
+ 'showstream',
+ array('nickname' => $user->nickname)
+ ),
+ 303
+ );
+ }
+
+ 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('Facebook Connect Plugin - ' .
+ "Legit user to connect to Facebook: $nickname");
+ }
+
+ $result = $this->flinkUser($user->id, $this->fbuid);
+
+ if (!$result) {
+ $this->serverError(_m('Error connecting user to Facebook.'));
+ return;
+ }
+
+ common_debug('Facebook Connnect Plugin - ' .
+ "Connected Facebook user $this->fbuid to local user $user->id");
+
+ common_set_user($user);
+ common_real_login(true);
+
+ $this->goHome($user->nickname);
+ }
+
+ function connectUser()
+ {
+ $user = common_current_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 to local user %d',
+ $this->fbuid,
+ $user->id
+ ),
+ __FILE__
+ );
+
+ // Return to Facebook connection settings tab
+ common_redirect(common_local_url('facebookfinishlogin'), 303);
+ }
+
+ 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['firstname'] .
+ ' ' . $this->fbuser['lastname']);
+
+ 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);
+ }
+
+ 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;
+ }
+
+}
parent::handle($args);
if (common_is_real_login()) {
-
$this->clientError(_m('Already logged in.'));
-
- } else {
-
- $facebook = new Facebook(
- array(
- 'appId' => common_config('facebook', 'appid'),
- 'secret' => common_config('facebook', 'secret'),
- 'cookie' => true,
- )
- );
-
- $session = $facebook->getSession();
- $fbuser = null;
-
- if ($session) {
- try {
- $fbuid = $facebook->getUser();
- $fbuser = $facebook->api('/me');
- } catch (FacebookApiException $e) {
- common_log(LOG_ERROR, $e);
- }
- }
-
- if (!empty($fbuser)) {
- common_debug("Found a valid Facebook user", __FILE__);
-
- // Check to see if we have a foreign link already
- $flink = Foreign_link::getByForeignId($fbuid, FACEBOOK_SERVICE);
-
- if (empty($flink)) {
-
- // See if the user would like to register a new local
- // account
- common_redirect(
- common_local_url('facebookregister'),
- 303
- );
-
- } else {
-
- // Log our user in!
- $user = $flink->getUser();
-
- if (!empty($user)) {
-
- common_log(
- LOG_INFO,
- sprintf(
- 'Logged in Facebook user %s as user %s (%s)',
- $fbuid,
- $user->id,
- $user->nickname
- ),
- __FILE__
- );
-
- common_set_user($user);
- common_real_login(true);
- $this->goHome($user->nickname);
- }
- }
-
- }
- }
-
- $this->showPage();
- }
-
- 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)
- );
+ $this->showPage();
}
-
- common_redirect($url, 303);
}
function getInstructions()
$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(
- //'show-faces' => 'true',
- //'max-rows' => '4',
- //'width' => '600',
- 'perms' => 'user_location,user_website,offline_access,publish_stream'
+ 'src' => common_path(
+ 'plugins/FacebookSSO/images/login-button.png',
+ true
+ ),
+ 'alt' => 'Login with Facebook',
+ 'title' => 'Login with Facebook'
);
- $this->element('fb:login-button', $attrs);
+ $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');
}
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Register a local user and connect it to a Facebook account
- *
- * 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 FacebookregisterAction 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') {
-
- $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')
- );
- }
- } else {
-
- $this->tryLogin();
- }
- }
-
- 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('facebookregister')));
- $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['firstname'] . ' ' . $this->fbuser['lastname'],
- // XXX: Figure out how to get email
- 'homepage' => $this->fbuser['link'],
- 'bio' => $this->fbuser['about'],
- 'location' => $this->fbuser['location']['name']
- );
-
- 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;
- }
-
- common_set_user($user);
- common_real_login(true);
-
- common_log(
- LOG_INFO,
- sprintf(
- 'Registered new user %d from Facebook user %s',
- $user->id,
- $this->fbuid
- ),
- __FILE__
- );
-
- common_redirect(
- common_local_url(
- 'showstream',
- array('nickname' => $user->nickname)
- ),
- 303
- );
- }
-
- 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('Facebook Connect Plugin - ' .
- "Legit user to connect to Facebook: $nickname");
- }
-
- $result = $this->flinkUser($user->id, $this->fbuid);
-
- if (!$result) {
- $this->serverError(_m('Error connecting user to Facebook.'));
- return;
- }
-
- common_debug('Facebook Connnect Plugin - ' .
- "Connected Facebook user $this->fbuid to local user $user->id");
-
- common_set_user($user);
- common_real_login(true);
-
- $this->goHome($user->nickname);
- }
-
- function connectUser()
- {
- $user = common_current_user();
-
- $result = $this->flinkUser($user->id, $this->fbuid);
-
- if (empty($result)) {
- $this->serverError(_m('Error connecting user to Facebook.'));
- return;
- }
-
- common_debug('Facebook Connect Plugin - ' .
- "Connected Facebook user $this->fbuid to local user $user->id");
-
- // Return to Facebook connection settings tab
- common_redirect(common_local_url('FBConnectSettings'), 303);
- }
-
- function tryLogin()
- {
- common_debug('Facebook Connect Plugin - ' .
- "Trying login for Facebook user $this->fbuid.");
-
- $flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_CONNECT_SERVICE);
-
- if (!empty($flink)) {
- $user = $flink->getUser();
-
- if (!empty($user)) {
-
- common_debug('Facebook Connect Plugin - ' .
- "Logged in Facebook user $flink->foreign_id as user $user->id ($user->nickname)");
-
- common_set_user($user);
- common_real_login(true);
- $this->goHome($user->nickname);
- }
-
- } else {
-
- common_debug('Facebook Connect Plugin - ' .
- "No flink found for fbuid: $this->fbuid - new user");
-
- $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['firstname'] .
- ' ' . $this->fbuser['lastname']);
-
- 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);
- }
-
- 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;
- }
-
-}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Class for communicating with 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 Plugin
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Zach Copley <zach@status.net>
+ * @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/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Class for communication with Facebook
+ *
+ * @category Plugin
+ * @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 Facebookclient
+{
+ protected $facebook = null; // Facebook Graph client obj
+ protected $flink = null; // Foreign_link StatusNet -> Facebook
+ protected $notice = null; // The user's notice
+ protected $user = null; // Sender of the notice
+ protected $oldRestClient = null; // Old REST API client
+
+ function __constructor($notice)
+ {
+ $this->facebook = self::getFacebook();
+ $this->notice = $notice;
+
+ $this->flink = Foreign_link::getByUserID(
+ $notice->profile_id,
+ FACEBOOK_SERVICE
+ );
+
+ $this->user = $this->flink->getUser();
+
+ $this->oldRestClient = self::getOldRestClient();
+ }
+
+ /*
+ * Get and instance of the old REST API client for sending notices from
+ * users with Facebook links that pre-exist the Graph API
+ */
+ static function getOldRestClient()
+ {
+ $apikey = common_config('facebook', 'apikey');
+ $secret = common_config('facebook', 'secret');
+
+ // If there's no app key and secret set in the local config, look
+ // for a global one
+ if (empty($apikey) || empty($secret)) {
+ $apikey = common_config('facebook', 'global_apikey');
+ $secret = common_config('facebook', 'global_secret');
+ }
+
+ return new FacebookRestClient($apikey, $secret, null);
+ }
+
+ /*
+ * Get an instance of the Facebook Graph SDK object
+ *
+ * @param string $appId Application
+ * @param string $secret Facebook API secret
+ *
+ * @return Facebook A Facebook SDK obj
+ */
+ static function getFacebook($appId = null, $secret = null)
+ {
+ // Check defaults and configuration for application ID and secret
+ if (empty($appId)) {
+ $appId = common_config('facebook', 'appid');
+ }
+
+ if (empty($secret)) {
+ $secret = common_config('facebook', 'secret');
+ }
+
+ // If there's no app ID and secret set in the local config, look
+ // for a global one
+ if (empty($appId) || empty($secret)) {
+ $appId = common_config('facebook', 'global_appid');
+ $secret = common_config('facebook', 'global_secret');
+ }
+
+ return new Facebook(
+ array(
+ 'appId' => $appId,
+ 'secret' => $secret,
+ 'cookie' => true
+ )
+ );
+ }
+
+ /*
+ * Broadcast a notice to Facebook
+ *
+ * @param Notice $notice the notice to send
+ */
+ static function facebookBroadcastNotice($notice)
+ {
+ $client = new Facebookclient($notice);
+ $client->sendNotice();
+ }
+
+ /*
+ * Should the notice go to Facebook?
+ */
+ function isFacebookBound() {
+
+ if (empty($this->flink)) {
+ common_log(
+ LOG_WARN,
+ sprintf(
+ "No Foreign_link to Facebook for the author of notice %d.",
+ $this->notice->id
+ ),
+ __FILE__
+ );
+ return false;
+ }
+
+ // Avoid a loop
+ if ($this->notice->source == 'Facebook') {
+ common_log(
+ LOG_INFO,
+ sprintf(
+ 'Skipping notice %d because its source is Facebook.',
+ $this->notice->id
+ ),
+ __FILE__
+ );
+ return false;
+ }
+
+ // If the user does not want to broadcast to Facebook, move along
+ if (!($this->flink->noticesync & FOREIGN_NOTICE_SEND == FOREIGN_NOTICE_SEND)) {
+ common_log(
+ LOG_INFO,
+ sprintf(
+ 'Skipping notice %d because user has FOREIGN_NOTICE_SEND bit off.',
+ $this->notice->id
+ ),
+ __FILE__
+ );
+ return false;
+ }
+
+ // If it's not a reply, or if the user WANTS to send @-replies,
+ // then, yeah, it can go to Facebook.
+ if (!preg_match('/@[a-zA-Z0-9_]{1,15}\b/u', $this->notice->content) ||
+ ($this->flink->noticesync & FOREIGN_NOTICE_SEND_REPLY)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /*
+ * Determine whether we should send this notice using the Graph API or the
+ * old REST API and then dispatch
+ */
+ function sendNotice()
+ {
+ // If there's nothing in the credentials field try to send via
+ // the Old Rest API
+
+ if (empty($this->flink->credentials)) {
+ $this->sendOldRest();
+ } else {
+
+ // Otherwise we most likely have an access token
+ $this->sendGraph();
+ }
+ }
+
+ /*
+ * Send a notice to Facebook using the Graph API
+ */
+ function sendGraph()
+ {
+ common_debug("Send notice via Graph API", __FILE__);
+ }
+
+ /*
+ * Send a notice to Facebook using the deprecated Old REST API. We need this
+ * for backwards compatibility. Users who signed up for Facebook bridging
+ * using the old Facebook Canvas application do not have an OAuth 2.0
+ * access token.
+ */
+ function sendOldRest()
+ {
+ if (isFacebookBound()) {
+
+ try {
+
+ $canPublish = $this->checkPermission('publish_stream');
+ $canUpdate = $this->checkPermission('status_update');
+
+ // Post to Facebook
+ if ($notice->hasAttachments() && $canPublish == 1) {
+ $this->restPublishStream();
+ } elseif ($canUpdate == 1 || $canPublish == 1) {
+ $this->restStatusUpdate();
+ } else {
+
+ $msg = 'Not sending notice %d to Facebook because user %s '
+ . '(%d), fbuid %s, does not have \'status_update\' '
+ . 'or \'publish_stream\' permission.';
+
+ common_log(
+ LOG_WARNING,
+ sprintf(
+ $msg,
+ $this->notice->id,
+ $this->user->nickname,
+ $this->user->id,
+ $this->flink->foreign_id
+ ),
+ __FILE__
+ );
+ }
+
+ } catch (FacebookRestClientException $e) {
+ return $this->handleFacebookError($e);
+ }
+ }
+
+ return true;
+ }
+
+ /*
+ * Query Facebook to to see if a user has permission
+ *
+ *
+ *
+ * @param $permission the permission to check for - must be either
+ * public_stream or status_update
+ *
+ * @return boolean result
+ */
+ function checkPermission($permission)
+ {
+
+ if (!in_array($permission, array('publish_stream', 'status_update'))) {
+ throw new ServerExpception("No such permission!");
+ }
+
+ $fbuid = $this->flink->foreign_link;
+
+ common_debug(
+ sprintf(
+ 'Checking for %s permission for user %s (%d), fbuid %s',
+ $permission,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+
+ // NOTE: $this->oldRestClient->users_hasAppPermission() has been
+ // returning bogus results, so we're using FQL to check for
+ // permissions
+
+ $fql = sprintf(
+ "SELECT %s FROM permissions WHERE uid = %s",
+ $permission,
+ $fbuid
+ );
+
+ $result = $this->oldRestClient->fql_query($fql);
+
+ $hasPermission = 0;
+
+ if (isset($result[0][$permission])) {
+ $canPublish = $result[0][$permission];
+ }
+
+ if ($hasPermission == 1) {
+
+ common_debug(
+ sprintf(
+ '%s (%d), fbuid %s has %s permission',
+ $permission,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+
+ return true;
+
+ } else {
+
+ $logMsg = '%s (%d), fbuid $fbuid does NOT have %s permission.'
+ . 'Facebook returned: %s';
+
+ common_debug(
+ sprintf(
+ $logMsg,
+ $this->user->nickname,
+ $this->user->id,
+ $permission,
+ $fbuid,
+ var_export($result, true)
+ ),
+ __FILE__
+ );
+
+ return false;
+
+ }
+
+ }
+
+ function handleFacebookError($e)
+ {
+ $fbuid = $this->flink->foreign_id;
+ $code = $e->getCode();
+ $errmsg = $e->getMessage();
+
+ // XXX: Check for any others?
+ switch($code) {
+ case 100: // Invalid parameter
+ $msg = 'Facebook claims notice %d was posted with an invalid '
+ . 'parameter (error code 100 - %s) Notice details: '
+ . '[nickname=%s, user id=%d, fbuid=%d, content="%s"]. '
+ . 'Dequeing.';
+ common_log(
+ LOG_ERR, sprintf(
+ $msg,
+ $this->notice->id,
+ $errmsg,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid,
+ $this->notice->content
+ ),
+ __FILE__
+ );
+ return true;
+ break;
+ case 200: // Permissions error
+ case 250: // Updating status requires the extended permission status_update
+ $this->disconnect();
+ return true; // dequeue
+ break;
+ case 341: // Feed action request limit reached
+ $msg = '%s (userid=%d, fbuid=%d) has exceeded his/her limit '
+ . 'for posting notices to Facebook today. Dequeuing '
+ . 'notice %d';
+ common_log(
+ LOG_INFO, sprintf(
+ $msg,
+ $user->nickname,
+ $user->id,
+ $fbuid,
+ $this->notice->id
+ ),
+ __FILE__
+ );
+ // @fixme: We want to rety at a later time when the throttling has expired
+ // instead of just giving up.
+ return true;
+ break;
+ default:
+ $msg = 'Facebook returned an error we don\'t know how to deal with '
+ . 'when posting notice %d. Error code: %d, error message: "%s"'
+ . ' Notice details: [nickname=%s, user id=%d, fbuid=%d, '
+ . 'notice content="%s"]. Dequeing.';
+ common_log(
+ LOG_ERR, sprintf(
+ $msg,
+ $this->notice->id,
+ $code,
+ $errmsg,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid,
+ $this->notice->content
+ ),
+ __FILE__
+ );
+ return true; // dequeue
+ break;
+ }
+ }
+
+ function restStatusUpdate()
+ {
+ $fbuid = $this->flink->foreign_id;
+
+ common_debug(
+ sprintf(
+ "Attempting to post notice %d as a status update for %s (%d), fbuid %s",
+ $this->notice->id,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+
+ $result = $this->oldRestClient->users_setStatus(
+ $this->notice->content,
+ $fbuid,
+ false,
+ true
+ );
+
+ common_log(
+ LOG_INFO,
+ sprintf(
+ "Posted notice %s as a status update for %s (%d), fbuid %s",
+ $this->notice->id,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+ }
+
+ function restPublishStream()
+ {
+ $fbuid = $this->flink->foreign_id;
+
+ common_debug(
+ sprintf(
+ 'Attempting to post notice %d as stream item with attachment for '
+ . '%s (%d) fbuid %s',
+ $this->notice->id,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+
+ $fbattachment = format_attachments($notice->attachments());
+
+ $this->oldRestClient->stream_publish(
+ $this->notice->content,
+ $fbattachment,
+ null,
+ null,
+ $fbuid
+ );
+
+ common_log(
+ LOG_INFO,
+ sprintf(
+ 'Posted notice %d as a stream item with attachment for %s '
+ . '(%d), fbuid %s',
+ $this->notice->id,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+
+ }
+
+ function format_attachments($attachments)
+ {
+ $fbattachment = array();
+ $fbattachment['media'] = array();
+
+ foreach($attachments as $attachment)
+ {
+ if($enclosure = $attachment->getEnclosure()){
+ $fbmedia = get_fbmedia_for_attachment($enclosure);
+ }else{
+ $fbmedia = get_fbmedia_for_attachment($attachment);
+ }
+ if($fbmedia){
+ $fbattachment['media'][]=$fbmedia;
+ }else{
+ $fbattachment['name'] = ($attachment->title ?
+ $attachment->title : $attachment->url);
+ $fbattachment['href'] = $attachment->url;
+ }
+ }
+ if(count($fbattachment['media'])>0){
+ unset($fbattachment['name']);
+ unset($fbattachment['href']);
+ }
+ return $fbattachment;
+ }
+
+ /**
+ * given an File objects, returns an associative array suitable for Facebook media
+ */
+ function get_fbmedia_for_attachment($attachment)
+ {
+ $fbmedia = array();
+
+ if (strncmp($attachment->mimetype, 'image/', strlen('image/')) == 0) {
+ $fbmedia['type'] = 'image';
+ $fbmedia['src'] = $attachment->url;
+ $fbmedia['href'] = $attachment->url;
+ } else if ($attachment->mimetype == 'audio/mpeg') {
+ $fbmedia['type'] = 'mp3';
+ $fbmedia['src'] = $attachment->url;
+ }else if ($attachment->mimetype == 'application/x-shockwave-flash') {
+ $fbmedia['type'] = 'flash';
+
+ // http://wiki.developers.facebook.com/index.php/Attachment_%28Streams%29
+ // says that imgsrc is required... but we have no value to put in it
+ // $fbmedia['imgsrc']='';
+
+ $fbmedia['swfsrc'] = $attachment->url;
+ }else{
+ return false;
+ }
+ return $fbmedia;
+ }
+
+ function disconnect()
+ {
+ $fbuid = $this->flink->foreign_link;
+
+ common_log(
+ LOG_INFO,
+ sprintf(
+ 'Removing Facebook link for %s (%d), fbuid %s',
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+
+ $result = $flink->delete();
+
+ if (empty($result)) {
+ common_log(
+ LOG_ERR,
+ sprintf(
+ 'Could not remove Facebook link for %s (%d), fbuid %s',
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+ common_log_db_error($flink, 'DELETE', __FILE__);
+ }
+
+ // Notify the user that we are removing their Facebook link
+
+ $result = $this->mailFacebookDisconnect();
+
+ if (!$result) {
+
+ $msg = 'Unable to send email to notify %s (%d), fbuid %s '
+ . 'about his/her Facebook link being removed.';
+
+ common_log(
+ LOG_WARNING,
+ sprintf(
+ $msg,
+ $this->user->nickname,
+ $this->user->id,
+ $fbuid
+ ),
+ __FILE__
+ );
+ }
+ }
+
+ /**
+ * Send a mail message to notify a user that her Facebook link
+ * has been terminated.
+ *
+ * @return boolean success flag
+ */
+ function mailFacebookDisconnect()
+ {
+ $profile = $user->getProfile();
+
+ $siteName = common_config('site', 'name');
+
+ common_switch_locale($user->language);
+
+ $subject = sprintf(
+ _m('Your Facebook connection has been removed'),
+ $siteName
+ );
+
+ $msg = <<<BODY
+Hi, %1$s. We're sorry to inform you we are unable to publish your notice to
+Facebook, and have removed the connection between your %2$s account and Facebook.
+
+This may have happened because you have removed permission for %2$s to post on
+your behalf, or perhaps you have deactivated your Facebook account. You can
+reconnect your %s account to Facebook at any time by logging in with Facebook
+again.
+BODY;
+ $body = sprintf(
+ _m($msg),
+ $this->user->nickname,
+ $siteName
+ );
+
+ common_switch_locale();
+
+ return mail_to_user($this->user, $subject, $body);
+ }
+
+}
--- /dev/null
+<?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);
+}
+
+require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
+
+class FacebookQueueHandler extends QueueHandler
+{
+ function transport()
+ {
+ return 'facebook';
+ }
+
+ function handle($notice)
+ {
+ if ($this->_isLocal($notice)) {
+ return 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);
+ }
+}