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
|
RouterInitialized: After the router instance has been initialized
|
||||||
- $m: the Net_URL_Mapper that has just been set up
|
- $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()) {
|
if (!common_logged_in()) {
|
||||||
$this->clientError(_('Not logged in.'));
|
$this->clientError(_('Not logged in.'));
|
||||||
} else {
|
} else {
|
||||||
common_set_user(null);
|
if (Event::handle('StartLogout', array($this))) {
|
||||||
common_real_login(false); // not logged in
|
$this->logout();
|
||||||
common_forgetme(); // don't log back in!
|
}
|
||||||
|
Event::handle('EndLogout', array($this));
|
||||||
|
|
||||||
common_redirect(common_local_url('public'), 303);
|
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']['apikey'] = 'APIKEY';
|
||||||
#$config['facebook']['secret'] = 'SECRET';
|
#$config['facebook']['secret'] = 'SECRET';
|
||||||
|
|
||||||
|
# Facebook Connect plugin (Needs valid APIKEY above)
|
||||||
|
#require_once(INSTALLDIR.'/plugins/FBConnect/FBConnectPlugin.php');
|
||||||
|
#$fbc = new FBConnectPlugin();
|
||||||
|
|
||||||
# Add Google Analytics
|
# Add Google Analytics
|
||||||
# require_once('plugins/GoogleAnalyticsPlugin.php');
|
# require_once('plugins/GoogleAnalyticsPlugin.php');
|
||||||
# $ga = new GoogleAnalyticsPlugin('your secret code');
|
# $ga = new GoogleAnalyticsPlugin('your secret code');
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
// Copyright 2004-2008 Facebook. All Rights Reserved.
|
// Copyright 2004-2009 Facebook. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// +---------------------------------------------------------------------------+
|
// +---------------------------------------------------------------------------+
|
||||||
// | Facebook Platform PHP5 client |
|
// | Facebook Platform PHP5 client |
|
||||||
|
@ -30,13 +30,12 @@
|
||||||
// +---------------------------------------------------------------------------+
|
// +---------------------------------------------------------------------------+
|
||||||
// | For help with this library, contact developers-help@facebook.com |
|
// | For help with this library, contact developers-help@facebook.com |
|
||||||
// +---------------------------------------------------------------------------+
|
// +---------------------------------------------------------------------------+
|
||||||
//
|
|
||||||
include_once 'facebookapi_php5_restlib.php';
|
include_once 'facebookapi_php5_restlib.php';
|
||||||
|
|
||||||
define('FACEBOOK_API_VALIDATION_ERROR', 1);
|
define('FACEBOOK_API_VALIDATION_ERROR', 1);
|
||||||
class Facebook {
|
class Facebook {
|
||||||
public $api_client;
|
public $api_client;
|
||||||
|
|
||||||
public $api_key;
|
public $api_key;
|
||||||
public $secret;
|
public $secret;
|
||||||
public $generate_session_secret;
|
public $generate_session_secret;
|
||||||
|
@ -213,28 +212,55 @@ 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() {
|
public function expire_session() {
|
||||||
if ($this->api_client->auth_expireSession()) {
|
if ($this->api_client->auth_expireSession()) {
|
||||||
if (!$this->in_fb_canvas() && isset($_COOKIE[$this->api_key . '_user'])) {
|
$this->clear_cookie_state();
|
||||||
$cookies = array('user', 'session_key', 'expires', 'ss');
|
|
||||||
foreach ($cookies as $name) {
|
|
||||||
setcookie($this->api_key . '_' . $name, false, time() - 3600);
|
|
||||||
unset($_COOKIE[$this->api_key . '_' . $name]);
|
|
||||||
}
|
|
||||||
setcookie($this->api_key, false, time() - 3600);
|
|
||||||
unset($_COOKIE[$this->api_key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now, clear the rest of the stored state
|
|
||||||
$this->user = 0;
|
|
||||||
$this->api_client->session_key = 0;
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
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) {
|
||||||
|
setcookie($this->api_key . '_' . $name, false, time() - 3600);
|
||||||
|
unset($_COOKIE[$this->api_key . '_' . $name]);
|
||||||
|
}
|
||||||
|
setcookie($this->api_key, false, time() - 3600);
|
||||||
|
unset($_COOKIE[$this->api_key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now, clear the rest of the stored state
|
||||||
|
$this->user = 0;
|
||||||
|
$this->api_client->session_key = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public function redirect($url) {
|
public function redirect($url) {
|
||||||
if ($this->in_fb_canvas()) {
|
if ($this->in_fb_canvas()) {
|
||||||
echo '<fb:redirect url="' . $url . '"/>';
|
echo '<fb:redirect url="' . $url . '"/>';
|
||||||
|
@ -249,7 +275,8 @@ class Facebook {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function in_frame() {
|
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() {
|
public function in_fb_canvas() {
|
||||||
return isset($this->fb_params['in_canvas']);
|
return isset($this->fb_params['in_canvas']);
|
||||||
|
@ -296,14 +323,42 @@ class Facebook {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_add_url($next=null) {
|
public function get_add_url($next=null) {
|
||||||
return self::get_facebook_url().'/add.php?api_key='.$this->api_key .
|
$page = self::get_facebook_url().'/add.php';
|
||||||
($next ? '&next=' . urlencode($next) : '');
|
$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) {
|
public function get_login_url($next, $canvas) {
|
||||||
return self::get_facebook_url().'/login.php?v=1.0&api_key=' . $this->api_key .
|
$page = self::get_facebook_url().'/login.php';
|
||||||
($next ? '&next=' . urlencode($next) : '') .
|
$params = array('api_key' => $this->api_key,
|
||||||
($canvas ? '&canvas' : '');
|
'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) {
|
public function set_user($user, $session_key, $expires=null, $session_secret=null) {
|
||||||
|
@ -410,7 +465,20 @@ class Facebook {
|
||||||
return $fb_params;
|
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.
|
* Validates that a given set of parameters match their signature.
|
||||||
* Parameters all match a given input prefix, such as "fb_sig".
|
* 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;
|
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.
|
* Generate a signature using the application secret key.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
// Copyright 2004-2008 Facebook. All Rights Reserved.
|
// Copyright 2004-2009 Facebook. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// +---------------------------------------------------------------------------+
|
// +---------------------------------------------------------------------------+
|
||||||
// | Facebook Platform PHP5 client |
|
// | Facebook Platform PHP5 client |
|
||||||
|
|
1026
extlib/facebook/facebookapi_php5_restlib.php
Normal file → Executable file
1026
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()
|
function getFacebook()
|
||||||
{
|
{
|
||||||
|
static $facebook = null;
|
||||||
|
|
||||||
$apikey = common_config('facebook', 'apikey');
|
$apikey = common_config('facebook', 'apikey');
|
||||||
$secret = common_config('facebook', 'secret');
|
$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) {
|
function updateProfileBox($facebook, $flink, $notice) {
|
||||||
|
@ -92,7 +104,6 @@ function isFacebookBound($notice, $flink) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function facebookBroadcastNotice($notice)
|
function facebookBroadcastNotice($notice)
|
||||||
{
|
{
|
||||||
$facebook = getFacebook();
|
$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