Merge branch '0.8.x' of git@gitorious.org:~evan/laconica/dev into 0.8.x
This commit is contained in:
commit
a325144fa0
@ -103,3 +103,9 @@ EndPublicGroupNav: At the end of the public group nav menu
|
||||
RouterInitialized: After the router instance has been initialized
|
||||
- $m: the Net_URL_Mapper that has just been set up
|
||||
|
||||
StartLogout: Before logging out
|
||||
- $action: the logout action
|
||||
|
||||
EndLogout: After logging out
|
||||
- $action: the logout action
|
||||
|
||||
|
@ -70,10 +70,20 @@ class LogoutAction extends Action
|
||||
if (!common_logged_in()) {
|
||||
$this->clientError(_('Not logged in.'));
|
||||
} else {
|
||||
common_set_user(null);
|
||||
common_real_login(false); // not logged in
|
||||
common_forgetme(); // don't log back in!
|
||||
if (Event::handle('StartLogout', array($this))) {
|
||||
$this->logout();
|
||||
}
|
||||
Event::handle('EndLogout', array($this));
|
||||
|
||||
common_redirect(common_local_url('public'), 303);
|
||||
}
|
||||
}
|
||||
|
||||
function logout()
|
||||
{
|
||||
common_set_user(null);
|
||||
common_real_login(false); // not logged in
|
||||
common_forgetme(); // don't log back in!
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -172,6 +172,10 @@ $config['sphinx']['port'] = 3312;
|
||||
#$config['facebook']['apikey'] = 'APIKEY';
|
||||
#$config['facebook']['secret'] = 'SECRET';
|
||||
|
||||
# Facebook Connect plugin (Needs valid APIKEY above)
|
||||
#require_once(INSTALLDIR.'/plugins/FBConnect/FBConnectPlugin.php');
|
||||
#$fbc = new FBConnectPlugin();
|
||||
|
||||
# Add Google Analytics
|
||||
# require_once('plugins/GoogleAnalyticsPlugin.php');
|
||||
# $ga = new GoogleAnalyticsPlugin('your secret code');
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright 2004-2008 Facebook. All Rights Reserved.
|
||||
// Copyright 2004-2009 Facebook. All Rights Reserved.
|
||||
//
|
||||
// +---------------------------------------------------------------------------+
|
||||
// | Facebook Platform PHP5 client |
|
||||
@ -30,13 +30,12 @@
|
||||
// +---------------------------------------------------------------------------+
|
||||
// | For help with this library, contact developers-help@facebook.com |
|
||||
// +---------------------------------------------------------------------------+
|
||||
//
|
||||
|
||||
include_once 'facebookapi_php5_restlib.php';
|
||||
|
||||
define('FACEBOOK_API_VALIDATION_ERROR', 1);
|
||||
class Facebook {
|
||||
public $api_client;
|
||||
|
||||
public $api_key;
|
||||
public $secret;
|
||||
public $generate_session_secret;
|
||||
@ -213,9 +212,40 @@ class Facebook {
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate the session currently being used, and clear any state associated with it
|
||||
// Invalidate the session currently being used, and clear any state associated
|
||||
// with it. Note that the user will still remain logged into Facebook.
|
||||
public function expire_session() {
|
||||
if ($this->api_client->auth_expireSession()) {
|
||||
$this->clear_cookie_state();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Logs the user out of all temporary application sessions as well as their
|
||||
* Facebook session. Note this will only work if the user has a valid current
|
||||
* session with the application.
|
||||
*
|
||||
* @param string $next URL to redirect to upon logging out
|
||||
*
|
||||
*/
|
||||
public function logout($next) {
|
||||
$logout_url = $this->get_logout_url($next);
|
||||
|
||||
// Clear any stored state
|
||||
$this->clear_cookie_state();
|
||||
|
||||
$this->redirect($logout_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any persistent state stored about the user, including
|
||||
* cookies and information related to the current session in the
|
||||
* client.
|
||||
*
|
||||
*/
|
||||
public function clear_cookie_state() {
|
||||
if (!$this->in_fb_canvas() && isset($_COOKIE[$this->api_key . '_user'])) {
|
||||
$cookies = array('user', 'session_key', 'expires', 'ss');
|
||||
foreach ($cookies as $name) {
|
||||
@ -229,10 +259,6 @@ class Facebook {
|
||||
// now, clear the rest of the stored state
|
||||
$this->user = 0;
|
||||
$this->api_client->session_key = 0;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function redirect($url) {
|
||||
@ -249,7 +275,8 @@ class Facebook {
|
||||
}
|
||||
|
||||
public function in_frame() {
|
||||
return isset($this->fb_params['in_canvas']) || isset($this->fb_params['in_iframe']);
|
||||
return isset($this->fb_params['in_canvas'])
|
||||
|| isset($this->fb_params['in_iframe']);
|
||||
}
|
||||
public function in_fb_canvas() {
|
||||
return isset($this->fb_params['in_canvas']);
|
||||
@ -296,14 +323,42 @@ class Facebook {
|
||||
}
|
||||
|
||||
public function get_add_url($next=null) {
|
||||
return self::get_facebook_url().'/add.php?api_key='.$this->api_key .
|
||||
($next ? '&next=' . urlencode($next) : '');
|
||||
$page = self::get_facebook_url().'/add.php';
|
||||
$params = array('api_key' => $this->api_key);
|
||||
|
||||
if ($next) {
|
||||
$params['next'] = $next;
|
||||
}
|
||||
|
||||
return $page . '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
public function get_login_url($next, $canvas) {
|
||||
return self::get_facebook_url().'/login.php?v=1.0&api_key=' . $this->api_key .
|
||||
($next ? '&next=' . urlencode($next) : '') .
|
||||
($canvas ? '&canvas' : '');
|
||||
$page = self::get_facebook_url().'/login.php';
|
||||
$params = array('api_key' => $this->api_key,
|
||||
'v' => '1.0');
|
||||
|
||||
if ($next) {
|
||||
$params['next'] = $next;
|
||||
}
|
||||
if ($canvas) {
|
||||
$params['canvas'] = '1';
|
||||
}
|
||||
|
||||
return $page . '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
public function get_logout_url($next) {
|
||||
$page = self::get_facebook_url().'/logout.php';
|
||||
$params = array('app_key' => $this->api_key,
|
||||
'session_key' => $this->api_client->session_key);
|
||||
|
||||
if ($next) {
|
||||
$params['connect_next'] = 1;
|
||||
$params['next'] = $next;
|
||||
}
|
||||
|
||||
return $page . '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
public function set_user($user, $session_key, $expires=null, $session_secret=null) {
|
||||
@ -410,7 +465,20 @@ class Facebook {
|
||||
return $fb_params;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Validates the account that a user was trying to set up an
|
||||
* independent account through Facebook Connect.
|
||||
*
|
||||
* @param user The user attempting to set up an independent account.
|
||||
* @param hash The hash passed to the reclamation URL used.
|
||||
* @return bool True if the user is the one that selected the
|
||||
* reclamation link.
|
||||
*/
|
||||
public function verify_account_reclamation($user, $hash) {
|
||||
return $hash == md5($user . $this->secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a given set of parameters match their signature.
|
||||
* Parameters all match a given input prefix, such as "fb_sig".
|
||||
*
|
||||
@ -422,6 +490,37 @@ class Facebook {
|
||||
return self::generate_sig($fb_params, $this->secret) == $expected_sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given signed public session data structure with
|
||||
* public key of the app that
|
||||
* the session proof belongs to.
|
||||
*
|
||||
* @param $signed_data the session info that is passed by another app
|
||||
* @param string $public_key Optional public key of the app. If this
|
||||
* is not passed, function will make an API call to get it.
|
||||
* return true if the session proof passed verification.
|
||||
*/
|
||||
public function verify_signed_public_session_data($signed_data,
|
||||
$public_key = null) {
|
||||
|
||||
// If public key is not already provided, we need to get it through API
|
||||
if (!$public_key) {
|
||||
$public_key = $this->api_client->auth_getAppPublicKey(
|
||||
$signed_data['api_key']);
|
||||
}
|
||||
|
||||
// Create data to verify
|
||||
$data_to_serialize = $signed_data;
|
||||
unset($data_to_serialize['sig']);
|
||||
$serialized_data = implode('_', $data_to_serialize);
|
||||
|
||||
// Decode signature
|
||||
$signature = base64_decode($signed_data['sig']);
|
||||
$result = openssl_verify($serialized_data, $signature, $public_key,
|
||||
OPENSSL_ALGO_SHA1);
|
||||
return $result == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a signature using the application secret key.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright 2004-2008 Facebook. All Rights Reserved.
|
||||
// Copyright 2004-2009 Facebook. All Rights Reserved.
|
||||
//
|
||||
// +---------------------------------------------------------------------------+
|
||||
// | Facebook Platform PHP5 client |
|
||||
|
1012
extlib/facebook/facebookapi_php5_restlib.php
Normal file → Executable file
1012
extlib/facebook/facebookapi_php5_restlib.php
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@ -27,9 +27,21 @@ define("FACEBOOK_PROMPTED_UPDATE_PREF", 2);
|
||||
|
||||
function getFacebook()
|
||||
{
|
||||
static $facebook = null;
|
||||
|
||||
$apikey = common_config('facebook', 'apikey');
|
||||
$secret = common_config('facebook', 'secret');
|
||||
return new Facebook($apikey, $secret);
|
||||
|
||||
if ($facebook === null) {
|
||||
$facebook = new Facebook($apikey, $secret);
|
||||
}
|
||||
|
||||
if (!$facebook) {
|
||||
common_log(LOG_ERR, 'Could not make new Facebook client obj!',
|
||||
__FILE__);
|
||||
}
|
||||
|
||||
return $facebook;
|
||||
}
|
||||
|
||||
function updateProfileBox($facebook, $flink, $notice) {
|
||||
@ -92,7 +104,6 @@ function isFacebookBound($notice, $flink) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
function facebookBroadcastNotice($notice)
|
||||
{
|
||||
$facebook = getFacebook();
|
||||
|
372
plugins/FBConnect/FBConnectLogin.php
Normal file
372
plugins/FBConnect/FBConnectLogin.php
Normal file
@ -0,0 +1,372 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to enable Facebook Connect
|
||||
*
|
||||
* 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 Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @copyright 2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
require_once INSTALLDIR . '/plugins/FBConnect/FBConnectLogin.php';
|
||||
require_once INSTALLDIR . '/lib/facebookutil.php';
|
||||
|
||||
class FBConnectloginAction extends Action
|
||||
{
|
||||
|
||||
var $fbuid = null;
|
||||
var $fb_fields = null;
|
||||
|
||||
function prepare($args) {
|
||||
parent::prepare($args);
|
||||
|
||||
$this->fbuid = getFacebook()->get_loggedin_user();
|
||||
$this->fb_fields = $this->getFacebookFields($this->fbuid,
|
||||
array('first_name', 'last_name', 'name'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (common_is_real_login()) {
|
||||
$this->clientError(_('Already logged in.'));
|
||||
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(_('There was a problem with your session token. Try again, please.'));
|
||||
return;
|
||||
}
|
||||
if ($this->arg('create')) {
|
||||
if (!$this->boolean('license')) {
|
||||
$this->showForm(_('You can\'t register if you don\'t agree to the license.'),
|
||||
$this->trimmed('newname'));
|
||||
return;
|
||||
}
|
||||
$this->createNewUser();
|
||||
} else if ($this->arg('connect')) {
|
||||
$this->connectUser();
|
||||
} else {
|
||||
common_debug(print_r($this->args, true), __FILE__);
|
||||
$this->showForm(_('Something weird happened.'),
|
||||
$this->trimmed('newname'));
|
||||
}
|
||||
} else {
|
||||
$this->tryLogin();
|
||||
}
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
if ($this->error) {
|
||||
$this->element('div', array('class' => 'error'), $this->error);
|
||||
} else {
|
||||
$this->element('div', 'instructions',
|
||||
sprintf(_('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 account, or connect with your existing account, if you have one.'), common_config('site', 'name')));
|
||||
}
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('Facebook Account Setup');
|
||||
}
|
||||
|
||||
function showForm($error=null, $username=null)
|
||||
{
|
||||
$this->error = $error;
|
||||
$this->username = $username;
|
||||
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showPage()
|
||||
{
|
||||
parent::showPage();
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
if (!empty($this->message_text)) {
|
||||
$this->element('p', null, $this->message);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'account_connect',
|
||||
'action' => common_local_url('fbconnectlogin')));
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->element('h2', null,
|
||||
_('Create new account'));
|
||||
$this->element('p', null,
|
||||
_('Create a new user with this nickname.'));
|
||||
$this->input('newname', _('New nickname'),
|
||||
($this->username) ? $this->username : '',
|
||||
_('1-64 lowercase letters or numbers, no punctuation or spaces'));
|
||||
$this->elementStart('p');
|
||||
$this->element('input', array('type' => 'checkbox',
|
||||
'id' => 'license',
|
||||
'name' => 'license',
|
||||
'value' => 'true'));
|
||||
$this->text(_('My text and files are available under '));
|
||||
$this->element('a', array('href' => common_config('license', 'url')),
|
||||
common_config('license', 'title'));
|
||||
$this->text(_(' except this private data: password, email address, IM address, phone number.'));
|
||||
$this->elementEnd('p');
|
||||
$this->submit('create', _('Create'));
|
||||
$this->element('h2', null,
|
||||
_('Connect existing account'));
|
||||
$this->element('p', null,
|
||||
_('If you already have an account, login with your username and password to connect it to your Facebook.'));
|
||||
$this->input('nickname', _('Existing nickname'));
|
||||
$this->password('password', _('Password'));
|
||||
$this->submit('connect', _('Connect'));
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
||||
function message($msg)
|
||||
{
|
||||
$this->message_text = $msg;
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function createNewUser()
|
||||
{
|
||||
|
||||
if (common_config('site', 'closed')) {
|
||||
$this->clientError(_('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = null;
|
||||
|
||||
if (common_config('site', 'inviteonly')) {
|
||||
$code = $_SESSION['invitecode'];
|
||||
if (empty($code)) {
|
||||
$this->clientError(_('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = Invitation::staticGet($code);
|
||||
|
||||
if (empty($invite)) {
|
||||
$this->clientError(_('Not a valid invitation code.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$nickname = $this->trimmed('newname');
|
||||
|
||||
if (!Validate::string($nickname, array('min_length' => 1,
|
||||
'max_length' => 64,
|
||||
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||
$this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!User::allowed_nickname($nickname)) {
|
||||
$this->showForm(_('Nickname not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (User::staticGet('nickname', $nickname)) {
|
||||
$this->showForm(_('Nickname already in use. Try another one.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$fullname = trim($this->fb_fields['firstname'] .
|
||||
' ' . $this->fb_fields['lastname']);
|
||||
|
||||
$args = array('nickname' => $nickname, 'fullname' => $fullname);
|
||||
|
||||
if (!empty($invite)) {
|
||||
$args['code'] = $invite->code;
|
||||
}
|
||||
|
||||
$user = User::register($args);
|
||||
|
||||
$result = $this->flinkUser($user->id, $this->fbuid);
|
||||
|
||||
if (!$result) {
|
||||
$this->serverError(_('Error connecting user to Facebook.'));
|
||||
return;
|
||||
}
|
||||
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
|
||||
common_debug("Registered new user $user->id from Facebook user $this->fbuid");
|
||||
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
|
||||
function connectUser()
|
||||
{
|
||||
$nickname = $this->trimmed('nickname');
|
||||
$password = $this->trimmed('password');
|
||||
|
||||
if (!common_check_user($nickname, $password)) {
|
||||
$this->showForm(_('Invalid username or password.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$user = User::staticGet('nickname', $nickname);
|
||||
|
||||
if ($user) {
|
||||
common_debug("Legit user to connect to Facebook: $nickname");
|
||||
}
|
||||
|
||||
$result = $this->flinkUser($user->id, $this->fbuid);
|
||||
|
||||
if (!$result) {
|
||||
$this->serverError(_('Error connecting user to Facebook.'));
|
||||
return;
|
||||
}
|
||||
|
||||
common_debug("Connected Facebook user $this->fbuid to local user $user->id");
|
||||
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
|
||||
$this->goHome($user->nickname);
|
||||
}
|
||||
|
||||
function tryLogin()
|
||||
{
|
||||
$flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
|
||||
|
||||
if ($flink) {
|
||||
$user = $flink->getUser();
|
||||
|
||||
if ($user) {
|
||||
|
||||
common_debug("Logged in Facebook user $flink->foreign_id as user $user->id");
|
||||
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
$this->goHome($user->nickname);
|
||||
}
|
||||
|
||||
} else {
|
||||
$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;
|
||||
$flink->created = common_sql_now();
|
||||
|
||||
$flink_id = $flink->insert();
|
||||
|
||||
return $flink_id;
|
||||
}
|
||||
|
||||
function bestNewNickname()
|
||||
{
|
||||
|
||||
common_debug("bestNewNickname()");
|
||||
common_debug(print_r($this->fb_fields, true));
|
||||
|
||||
if (!empty($this->fb_fields['name'])) {
|
||||
$nickname = $this->nicknamize($this->fb_fields['name']);
|
||||
if ($this->isNewNickname($nickname)) {
|
||||
return $nickname;
|
||||
}
|
||||
}
|
||||
|
||||
// Try the full name
|
||||
|
||||
$fullname = trim($this->fb_fields['firstname'] .
|
||||
' ' . $this->fb_fields['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' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||
return false;
|
||||
}
|
||||
if (!User::allowed_nickname($str)) {
|
||||
return false;
|
||||
}
|
||||
if (User::staticGet('nickname', $str)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX: Consider moving this to lib/facebookutil.php
|
||||
function getFacebookFields($fb_uid, $fields) {
|
||||
try {
|
||||
$infos = getFacebook()->api_client->users_getInfo($fb_uid, $fields);
|
||||
|
||||
if (empty($infos)) {
|
||||
return null;
|
||||
}
|
||||
return reset($infos);
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("Failure in the api when requesting " . join(",", $fields)
|
||||
." on uid " . $fb_uid . " : ". $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
278
plugins/FBConnect/FBConnectPlugin.php
Normal file
278
plugins/FBConnect/FBConnectPlugin.php
Normal file
@ -0,0 +1,278 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Plugin to enable Facebook Connect
|
||||
*
|
||||
* 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 Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @copyright 2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/plugins/FBConnect/FBConnectLogin.php';
|
||||
require_once INSTALLDIR . '/lib/facebookutil.php';
|
||||
|
||||
/**
|
||||
* Plugin to enable Facebook Connect
|
||||
*
|
||||
* @category Plugin
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class FBConnectPlugin extends Plugin
|
||||
{
|
||||
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// Hook in new actions
|
||||
function onRouterInitialized(&$m) {
|
||||
$m->connect('main/facebookconnect', array('action' => 'fbconnectlogin'));
|
||||
}
|
||||
|
||||
// Add in xmlns:fb
|
||||
function onStartShowHTML($action)
|
||||
{
|
||||
|
||||
// XXX: This is probably a bad place to do general processing
|
||||
// so maybe I need to make some new events? Maybe in
|
||||
// Action::prepare?
|
||||
|
||||
$name = get_class($action);
|
||||
|
||||
common_debug("action: $name");
|
||||
|
||||
// Avoid a redirect loop
|
||||
if ($name != 'FBConnectloginAction') {
|
||||
|
||||
$this->checkFacebookUser($action);
|
||||
|
||||
}
|
||||
|
||||
$httpaccept = isset($_SERVER['HTTP_ACCEPT']) ?
|
||||
$_SERVER['HTTP_ACCEPT'] : null;
|
||||
|
||||
// XXX: allow content negotiation for RDF, RSS, or XRDS
|
||||
|
||||
$cp = common_accept_to_prefs($httpaccept);
|
||||
$sp = common_accept_to_prefs(PAGE_TYPE_PREFS);
|
||||
|
||||
$type = common_negotiate_type($cp, $sp);
|
||||
|
||||
if (!$type) {
|
||||
throw new ClientException(_('This page is not available in a '.
|
||||
'media type you accept'), 406);
|
||||
}
|
||||
|
||||
|
||||
header('Content-Type: '.$type);
|
||||
|
||||
$action->extraHeaders();
|
||||
|
||||
$action->startXML('html',
|
||||
'-//W3C//DTD XHTML 1.0 Strict//EN',
|
||||
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
|
||||
|
||||
$language = $action->getLanguage();
|
||||
|
||||
$action->elementStart('html', array('xmlns' => 'http://www.w3.org/1999/xhtml',
|
||||
'xmlns:fb' => 'http://www.facebook.com/2008/fbml',
|
||||
'xml:lang' => $language,
|
||||
'lang' => $language));
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function onEndShowLaconicaScripts($action)
|
||||
{
|
||||
|
||||
$action->element('script',
|
||||
array('type' => 'text/javascript',
|
||||
'src' => 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php'),
|
||||
' ');
|
||||
|
||||
$apikey = common_config('facebook', 'apikey');
|
||||
$plugin_path = common_path('plugins/FBConnect');
|
||||
|
||||
$login_url = common_get_returnto() || common_local_url('public');
|
||||
|
||||
$html = sprintf('<script type="text/javascript">FB.init("%s", "%s/xd_receiver.htm");
|
||||
|
||||
function refresh_page() {
|
||||
window.location = "%s";
|
||||
}
|
||||
|
||||
</script>', $apikey, $plugin_path, $login_url);
|
||||
|
||||
|
||||
$action->raw($html);
|
||||
}
|
||||
|
||||
function onStartPrimaryNav($action)
|
||||
{
|
||||
$user = common_current_user();
|
||||
|
||||
if ($user) {
|
||||
$action->menuItem(common_local_url('all', array('nickname' => $user->nickname)),
|
||||
_('Home'), _('Personal profile and friends timeline'), false, 'nav_home');
|
||||
$action->menuItem(common_local_url('profilesettings'),
|
||||
_('Account'), _('Change your email, avatar, password, profile'), false, 'nav_account');
|
||||
if (common_config('xmpp', 'enabled')) {
|
||||
$action->menuItem(common_local_url('imsettings'),
|
||||
_('Connect'), _('Connect to IM, SMS, Twitter'), false, 'nav_connect');
|
||||
} else {
|
||||
$action->menuItem(common_local_url('smssettings'),
|
||||
_('Connect'), _('Connect to SMS, Twitter'), false, 'nav_connect');
|
||||
}
|
||||
$action->menuItem(common_local_url('invite'),
|
||||
_('Invite'),
|
||||
sprintf(_('Invite friends and colleagues to join you on %s'),
|
||||
common_config('site', 'name')),
|
||||
false, 'nav_invitecontact');
|
||||
|
||||
// Need to override the Logout link to make it do FB stuff
|
||||
|
||||
$logout_url = common_local_url('logout');
|
||||
$title = _('Logout from the site');
|
||||
$text = _('Logout');
|
||||
|
||||
$html = sprintf('<li id="nav_logout"><a href="%s" title="%s" ' .
|
||||
'onclick="FB.Connect.logoutAndRedirect(\'%s\')">%s</a></li>',
|
||||
$logout_url, $title, $logout_url, $text);
|
||||
|
||||
$action->raw($html);
|
||||
|
||||
}
|
||||
else {
|
||||
if (!common_config('site', 'closed')) {
|
||||
$action->menuItem(common_local_url('register'),
|
||||
_('Register'), _('Create an account'), false, 'nav_register');
|
||||
}
|
||||
$action->menuItem(common_local_url('openidlogin'),
|
||||
_('OpenID'), _('Login with OpenID'), false, 'nav_openid');
|
||||
$action->menuItem(common_local_url('login'),
|
||||
_('Login'), _('Login to the site'), false, 'nav_login');
|
||||
}
|
||||
|
||||
$action->menuItem(common_local_url('doc', array('title' => 'help')),
|
||||
_('Help'), _('Help me!'), false, 'nav_help');
|
||||
$action->menuItem(common_local_url('peoplesearch'),
|
||||
_('Search'), _('Search for people or text'), false, 'nav_search');
|
||||
|
||||
// Tack on "Connect with Facebook" button
|
||||
|
||||
// XXX: Maybe this looks bad and should not go here. Where should it go?
|
||||
|
||||
if (!$user) {
|
||||
$action->elementStart('li');
|
||||
$action->element('fb:login-button', array('onlogin' => 'refresh_page()',
|
||||
'length' => 'long'));
|
||||
$action->elementEnd('li');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkFacebookUser() {
|
||||
|
||||
try {
|
||||
|
||||
$facebook = getFacebook();
|
||||
$fbuid = $facebook->get_loggedin_user();
|
||||
$user = common_current_user();
|
||||
|
||||
// If you're a Facebook user and you're logged in do nothing
|
||||
|
||||
// If you're a Facebook user and you're not logged in
|
||||
// redirect to Facebook connect login page because that means you have clicked
|
||||
// the 'connect with Facebook' button and have cookies
|
||||
|
||||
if ($fbuid > 0) {
|
||||
|
||||
if ($facebook->api_client->users_isAppUser($fbuid) ||
|
||||
$facebook->api_client->added) {
|
||||
|
||||
// user should be connected...
|
||||
|
||||
common_debug("Facebook user found: $fbuid");
|
||||
|
||||
if ($user) {
|
||||
common_debug("Facebook user is logged in.");
|
||||
return;
|
||||
|
||||
} else {
|
||||
common_debug("Facebook user is NOT logged in.");
|
||||
common_redirect(common_local_url('fbconnectlogin'), 303);
|
||||
}
|
||||
|
||||
} else {
|
||||
common_debug("No Facebook connect user found.");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
common_debug('Expired FB session.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function onStartLogout($action)
|
||||
{
|
||||
common_debug("onEndLogout()");
|
||||
|
||||
common_set_user(null);
|
||||
common_real_login(false); // not logged in
|
||||
common_forgetme(); // don't log back in!
|
||||
|
||||
try {
|
||||
|
||||
$facebook = getFacebook();
|
||||
$fbuid = $facebook->get_loggedin_user();
|
||||
|
||||
// XXX: ARGGGH this doesn't work right!
|
||||
|
||||
if ($fbuid) {
|
||||
$facebook->expire_session();
|
||||
$facebook->logout(common_local_url('public'));
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
common_debug('Problem expiring FB session');
|
||||
}
|
||||
|
||||
common_debug("logged out.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
10
plugins/FBConnect/xd_receiver.htm
Normal file
10
plugins/FBConnect/xd_receiver.htm
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" >
|
||||
<head>
|
||||
<title>cross domain receiver page</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.debug.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user