summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrion Vibber <brion@pobox.com>2010-03-03 09:53:38 -0800
committerBrion Vibber <brion@pobox.com>2010-03-03 09:53:38 -0800
commit7313cd909479f771e960466d9194783c9a3158bb (patch)
tree318734efe06c9de904364f04cb76e1c54b75e269
parent49a872b56f82a3f1ba59f0751c11dfe7754393dd (diff)
parentf3cea2430497e751bc7776fe3abf0603e2b55f8b (diff)
Merge branch 'testing' of git@gitorious.org:statusnet/mainline
Conflicts: plugins/OStatus/OStatusPlugin.php
-rw-r--r--EVENTS.txt20
-rw-r--r--actions/all.php22
-rw-r--r--actions/showgroup.php24
-rw-r--r--classes/File.php9
-rw-r--r--classes/Notice.php29
-rw-r--r--js/util.js13
-rw-r--r--lib/action.php2
-rw-r--r--lib/activity.php5
-rw-r--r--lib/apiaction.php9
-rw-r--r--lib/default.php4
-rw-r--r--lib/profileaction.php35
-rw-r--r--lib/profilelist.php9
-rw-r--r--lib/util.php41
-rw-r--r--plugins/Facebook/FacebookPlugin.php244
-rw-r--r--plugins/Facebook/README84
-rw-r--r--plugins/Facebook/facebookadminpanel.php223
-rw-r--r--plugins/MobileProfile/MobileProfilePlugin.php2
-rw-r--r--plugins/OStatus/OStatusPlugin.php124
-rw-r--r--plugins/OStatus/actions/ostatussub.php2
-rw-r--r--plugins/OStatus/classes/Ostatus_profile.php14
-rw-r--r--plugins/OStatus/lib/xrd.php8
-rw-r--r--plugins/OStatus/theme/base/css/ostatus.css20
-rw-r--r--plugins/TwitterBridge/README120
-rw-r--r--plugins/TwitterBridge/TwitterBridgePlugin.php195
-rw-r--r--plugins/TwitterBridge/twitteradminpanel.php323
-rw-r--r--plugins/TwitterBridge/twitterauthorization.php2
-rw-r--r--plugins/TwitterBridge/twitteroauthclient.php21
27 files changed, 1301 insertions, 303 deletions
diff --git a/EVENTS.txt b/EVENTS.txt
index a2b405acc..2c3863f22 100644
--- a/EVENTS.txt
+++ b/EVENTS.txt
@@ -363,6 +363,14 @@ EndProfileRemoteSubscribe: After showing the link to remote subscription
- $userprofile: UserProfile widget
- &$profile: the profile being shown
+StartGroupSubscribe: Before showing the link to remote subscription
+- $action: the current action
+- $group: the group being shown
+
+EndGroupSubscribe: After showing the link to remote subscription
+- $action: the current action
+- $group: the group being shown
+
StartProfilePageProfileSection: Starting to show the section of the
profile page with the actual profile data;
hook to prevent showing the profile (e.g.)
@@ -770,6 +778,18 @@ StartShowSubscriptionsContent: before showing the subscriptions content
EndShowSubscriptionsContent: after showing the subscriptions content
- $action: the current action
+StartShowAllContent: before showing the all (you and friends) content
+- $action: the current action
+
+EndShowAllContent: after showing the all (you and friends) content
+- $action: the current action
+
+StartShowSubscriptionsMiniList: at the start of subscriptions mini list
+- $action: the current action
+
+EndShowSubscriptionsMiniList: at the end of subscriptions mini list
+- $action: the current action
+
StartDeleteUserForm: starting the data in the form for deleting a user
- $action: action being shown
- $user: user being deleted
diff --git a/actions/all.php b/actions/all.php
index 3eb185214..6be0c00e3 100644
--- a/actions/all.php
+++ b/actions/all.php
@@ -144,18 +144,22 @@ class AllAction extends ProfileAction
function showContent()
{
- $nl = new NoticeList($this->notice, $this);
+ if (Event::handle('StartShowAllContent', array($this))) {
+ $nl = new NoticeList($this->notice, $this);
- $cnt = $nl->show();
+ $cnt = $nl->show();
- if (0 == $cnt) {
- $this->showEmptyListMessage();
- }
+ if (0 == $cnt) {
+ $this->showEmptyListMessage();
+ }
- $this->pagination(
- $this->page > 1, $cnt > NOTICES_PER_PAGE,
- $this->page, 'all', array('nickname' => $this->user->nickname)
- );
+ $this->pagination(
+ $this->page > 1, $cnt > NOTICES_PER_PAGE,
+ $this->page, 'all', array('nickname' => $this->user->nickname)
+ );
+
+ Event::handle('EndShowAllContent', array($this));
+ }
}
function showPageTitle()
diff --git a/actions/showgroup.php b/actions/showgroup.php
index 4e1fcb6c7..a1dc3865b 100644
--- a/actions/showgroup.php
+++ b/actions/showgroup.php
@@ -300,20 +300,22 @@ class ShowgroupAction extends GroupDesignAction
$this->elementStart('div', 'entity_actions');
$this->element('h2', null, _('Group actions'));
$this->elementStart('ul');
- $this->elementStart('li', 'entity_subscribe');
- $cur = common_current_user();
- if ($cur) {
- if ($cur->isMember($this->group)) {
- $lf = new LeaveForm($this, $this->group);
- $lf->show();
- } else if (!Group_block::isBlocked($this->group, $cur->getProfile())) {
- $jf = new JoinForm($this, $this->group);
- $jf->show();
+ if (Event::handle('StartGroupSubscribe', array($this, $this->group))) {
+ $this->elementStart('li', 'entity_subscribe');
+ $cur = common_current_user();
+ if ($cur) {
+ if ($cur->isMember($this->group)) {
+ $lf = new LeaveForm($this, $this->group);
+ $lf->show();
+ } else if (!Group_block::isBlocked($this->group, $cur->getProfile())) {
+ $jf = new JoinForm($this, $this->group);
+ $jf->show();
+ }
}
+ $this->elementEnd('li');
+ Event::handle('EndGroupSubscribe', array($this, $this->group));
}
- $this->elementEnd('li');
-
$this->elementEnd('ul');
$this->elementEnd('div');
}
diff --git a/classes/File.php b/classes/File.php
index 91b12d2e2..1b8ef1b3e 100644
--- a/classes/File.php
+++ b/classes/File.php
@@ -279,10 +279,19 @@ class File extends Memcached_DataObject
if($oembed->modified) $enclosure->modified=$oembed->modified;
unset($oembed->size);
}
+ } else {
+ return false;
}
}
}
return $enclosure;
}
+
+ // quick back-compat hack, since there's still code using this
+ function isEnclosure()
+ {
+ $enclosure = $this->getEnclosure();
+ return !empty($enclosure);
+ }
}
diff --git a/classes/Notice.php b/classes/Notice.php
index 22dcbcd74..c1263c782 100644
--- a/classes/Notice.php
+++ b/classes/Notice.php
@@ -211,6 +211,8 @@ class Notice extends Memcached_DataObject
* extracting ! tags from content
* array 'tags' list of hashtag strings to save with the notice
* in place of extracting # tags from content
+ * array 'urls' list of attached/referred URLs to save with the
+ * notice in place of extracting links from content
* @fixme tag override
*
* @return Notice
@@ -380,8 +382,11 @@ class Notice extends Memcached_DataObject
$notice->saveTags();
}
- // @fixme pass in data for URLs too?
- $notice->saveUrls();
+ if (isset($urls)) {
+ $notice->saveKnownUrls($urls);
+ } else {
+ $notice->saveUrls();
+ }
// Prepare inbox delivery, may be queued to background.
$notice->distribute();
@@ -427,6 +432,25 @@ class Notice extends Memcached_DataObject
common_replace_urls_callback($this->content, array($this, 'saveUrl'), $this->id);
}
+ /**
+ * Save the given URLs as related links/attachments to the db
+ *
+ * follow redirects and save all available file information
+ * (mimetype, date, size, oembed, etc.)
+ *
+ * @return void
+ */
+ function saveKnownUrls($urls)
+ {
+ // @fixme validation?
+ foreach ($urls as $url) {
+ File::processNew($url, $this->id);
+ }
+ }
+
+ /**
+ * @private callback
+ */
function saveUrl($data) {
list($url, $notice_id) = $data;
File::processNew($url, $notice_id);
@@ -1126,7 +1150,6 @@ class Notice extends Memcached_DataObject
}
$xs->element('title', null, $this->content);
- $xs->element('summary', null, $this->content);
$xs->raw($profile->asAtomAuthor());
$xs->raw($profile->asActivityActor());
diff --git a/js/util.js b/js/util.js
index 949aec957..3efda0d7b 100644
--- a/js/util.js
+++ b/js/util.js
@@ -53,7 +53,7 @@ var SN = { // StatusNet
NoticeLocationNs: 'notice_data-location_ns',
NoticeGeoName: 'notice_data-geo_name',
NoticeDataGeo: 'notice_data-geo',
- NoticeDataGeoCookie: 'notice_data-geo_cookie',
+ NoticeDataGeoCookie: 'NoticeDataGeo',
NoticeDataGeoSelected: 'notice_data-geo_selected',
StatusNetInstance:'StatusNetInstance'
}
@@ -423,8 +423,11 @@ var SN = { // StatusNet
};
notice.find('a.attachment').click(function() {
- $().jOverlay({url: $('address .url')[0].href+'attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'});
- return false;
+ var attachId = ($(this).attr('id').substring('attachment'.length + 1));
+ if (attachId) {
+ $().jOverlay({url: $('address .url')[0].href+'attachment/' + attachId + '/ajax'});
+ return false;
+ }
});
if ($('#shownotice').length == 0) {
@@ -494,7 +497,7 @@ var SN = { // StatusNet
$('#'+SN.C.S.NoticeLocationId).val('');
$('#'+SN.C.S.NoticeDataGeo).attr('checked', false);
- $.cookie(SN.C.S.NoticeDataGeoCookie, 'disabled', { path: '/', expires: SN.U.GetFullYear(2029, 0, 1) });
+ $.cookie(SN.C.S.NoticeDataGeoCookie, 'disabled', { path: '/' });
}
function getJSONgeocodeURL(geocodeURL, data) {
@@ -537,7 +540,7 @@ var SN = { // StatusNet
NDG: true
};
- $.cookie(SN.C.S.NoticeDataGeoCookie, JSON.stringify(cookieValue), { path: '/', expires: SN.U.GetFullYear(2029, 0, 1) });
+ $.cookie(SN.C.S.NoticeDataGeoCookie, JSON.stringify(cookieValue), { path: '/' });
});
}
diff --git a/lib/action.php b/lib/action.php
index a7e0eb33b..0918c6858 100644
--- a/lib/action.php
+++ b/lib/action.php
@@ -425,8 +425,6 @@ class Action extends HTMLOutputter // lawsuit
$connect = 'imsettings';
} else if (common_config('sms', 'enabled')) {
$connect = 'smssettings';
- } else if (common_config('twitter', 'enabled')) {
- $connect = 'twittersettings';
}
$this->elementStart('dl', array('id' => 'site_nav_global_primary'));
diff --git a/lib/activity.php b/lib/activity.php
index 7926d0569..7334239ec 100644
--- a/lib/activity.php
+++ b/lib/activity.php
@@ -1048,6 +1048,7 @@ class Activity
public $id; // ID of the activity
public $title; // title of the activity
public $categories = array(); // list of AtomCategory objects
+ public $enclosures = array(); // list of enclosure URL references
/**
* Turns a regular old Atom <entry> into a magical activity
@@ -1144,6 +1145,10 @@ class Activity
$this->categories[] = new AtomCategory($catEl);
}
}
+
+ foreach (ActivityUtils::getLinks($entry, 'enclosure') as $link) {
+ $this->enclosures[] = $link->getAttribute('href');
+ }
}
/**
diff --git a/lib/apiaction.php b/lib/apiaction.php
index 8049c0901..eef0ba637 100644
--- a/lib/apiaction.php
+++ b/lib/apiaction.php
@@ -291,11 +291,12 @@ class ApiAction extends Action
$twitter_status['attachments'] = array();
foreach ($attachments as $attachment) {
- if ($attachment->isEnclosure()) {
+ $enclosure_o=$attachment->getEnclosure();
+ if ($enclosure_o) {
$enclosure = array();
- $enclosure['url'] = $attachment->url;
- $enclosure['mimetype'] = $attachment->mimetype;
- $enclosure['size'] = $attachment->size;
+ $enclosure['url'] = $enclosure_o->url;
+ $enclosure['mimetype'] = $enclosure_o->mimetype;
+ $enclosure['size'] = $enclosure_o->size;
$twitter_status['attachments'][] = $enclosure;
}
}
diff --git a/lib/default.php b/lib/default.php
index d849055c2..7b50242ae 100644
--- a/lib/default.php
+++ b/lib/default.php
@@ -177,8 +177,8 @@ $default =
array('source' => 'StatusNet', # source attribute for Twitter
'taguri' => null), # base for tag URIs
'twitter' =>
- array('enabled' => true,
- 'consumer_key' => null,
+ array('signin' => true,
+ 'consumer_key' => null,
'consumer_secret' => null),
'cache' =>
array('base' => null),
diff --git a/lib/profileaction.php b/lib/profileaction.php
index 2d4d23265..2bda8b07c 100644
--- a/lib/profileaction.php
+++ b/lib/profileaction.php
@@ -106,27 +106,30 @@ class ProfileAction extends OwnerDesignAction
$this->elementStart('div', array('id' => 'entity_subscriptions',
'class' => 'section'));
- $this->element('h2', null, _('Subscriptions'));
+ if (Event::handle('StartShowSubscriptionsMiniList', array($this))) {
+ $this->element('h2', null, _('Subscriptions'));
- $cnt = 0;
+ $cnt = 0;
- if (!empty($profile)) {
- $pml = new ProfileMiniList($profile, $this);
- $cnt = $pml->show();
- if ($cnt == 0) {
- $this->element('p', null, _('(None)'));
+ if (!empty($profile)) {
+ $pml = new ProfileMiniList($profile, $this);
+ $cnt = $pml->show();
+ if ($cnt == 0) {
+ $this->element('p', null, _('(None)'));
+ }
}
- }
- if ($cnt > PROFILES_PER_MINILIST) {
- $this->elementStart('p');
- $this->element('a', array('href' => common_local_url('subscriptions',
- array('nickname' => $this->profile->nickname)),
- 'class' => 'more'),
- _('All subscriptions'));
- $this->elementEnd('p');
- }
+ if ($cnt > PROFILES_PER_MINILIST) {
+ $this->elementStart('p');
+ $this->element('a', array('href' => common_local_url('subscriptions',
+ array('nickname' => $this->profile->nickname)),
+ 'class' => 'more'),
+ _('All subscriptions'));
+ $this->elementEnd('p');
+ }
+ Event::handle('EndShowSubscriptionsMiniList', array($this));
+ }
$this->elementEnd('div');
}
diff --git a/lib/profilelist.php b/lib/profilelist.php
index 693cd6449..4f1e84a6a 100644
--- a/lib/profilelist.php
+++ b/lib/profilelist.php
@@ -273,13 +273,18 @@ class ProfileListItem extends Widget
$usf = new UnsubscribeForm($this->out, $this->profile);
$usf->show();
} else {
- // Is it a local user? can't remote sub from a list
- // XXX: make that possible!
$other = User::staticGet('id', $this->profile->id);
if (!empty($other)) {
$sf = new SubscribeForm($this->out, $this->profile);
$sf->show();
}
+ else {
+ $url = common_local_url('remotesubscribe',
+ array('nickname' => $this->profile->nickname));
+ $this->out->element('a', array('href' => $url,
+ 'class' => 'entity_remote_subscribe'),
+ _('Subscribe'));
+ }
}
$this->out->elementEnd('li');
}
diff --git a/lib/util.php b/lib/util.php
index 485f6f0d9..add1b0ae6 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -770,20 +770,13 @@ function common_linkify($url) {
}
if (!empty($f)) {
- if ($f->isEnclosure()) {
+ if ($f->getEnclosure()) {
$is_attachment = true;
$attachment_id = $f->id;
- } else {
- $foe = File_oembed::staticGet('file_id', $f->id);
- if (!empty($foe)) {
- // if it has OEmbed info, it's an attachment, too
- $is_attachment = true;
- $attachment_id = $f->id;
-
- $thumb = File_thumbnail::staticGet('file_id', $f->id);
- if (!empty($thumb)) {
- $has_thumb = true;
- }
+
+ $thumb = File_thumbnail::staticGet('file_id', $f->id);
+ if (!empty($thumb)) {
+ $has_thumb = true;
}
}
}
@@ -809,8 +802,28 @@ function common_shorten_links($text)
function common_xml_safe_str($str)
{
- // Neutralize control codes and surrogates
- return preg_replace('/[\p{Cc}\p{Cs}]/u', '*', $str);
+ // Replace common eol and extra whitespace input chars
+ $unWelcome = array(
+ "\t", // tab
+ "\n", // newline
+ "\r", // cr
+ "\0", // null byte eos
+ "\x0B" // vertical tab
+ );
+
+ $replacement = array(
+ ' ', // single space
+ ' ',
+ '', // nothing
+ '',
+ ' '
+ );
+
+ $str = str_replace($unWelcome, $replacement, $str);
+
+ // Neutralize any additional control codes and UTF-16 surrogates
+ // (Twitter uses '*')
+ return preg_replace('/[\p{Cc}\p{Cs}]/u', '*', $str);
}
function common_tag_link($tag)
diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php
index 4266b886d..90ed7351f 100644
--- a/plugins/Facebook/FacebookPlugin.php
+++ b/plugins/Facebook/FacebookPlugin.php
@@ -22,7 +22,7 @@
* @category Plugin
* @package StatusNet
* @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
+ * @copyright 2009-2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
@@ -32,12 +32,12 @@ if (!defined('STATUSNET')) {
}
define("FACEBOOK_CONNECT_SERVICE", 3);
-define('FACEBOOKPLUGIN_VERSION', '0.9');
require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
/**
- * Facebook plugin to add a StatusNet Facebook application
+ * Facebook plugin to add a StatusNet Facebook canvas application
+ * and allow registration and authentication via Facebook Connect
*
* @category Plugin
* @package StatusNet
@@ -49,6 +49,55 @@ require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
class FacebookPlugin extends Plugin
{
+ const VERSION = STATUSNET_VERSION;
+
+ /**
+ * Initializer for the plugin.
+ */
+
+ function initialize()
+ {
+ // Allow the key and secret to be passed in
+ // Control panel will override
+
+ if (isset($this->apikey)) {
+ $key = common_config('facebook', 'apikey');
+ if (empty($key)) {
+ Config::save('facebook', 'apikey', $this->apikey);
+ }
+ }
+
+ if (isset($this->secret)) {
+ $secret = common_config('facebook', 'secret');
+ if (empty($secret)) {
+ Config::save(
+ 'facebook',
+ 'secret',
+ $this->secret
+ );
+ }
+ }
+ }
+
+ /**
+ * Check to see if there is an API key and secret defined
+ * for Facebook integration.
+ *
+ * @return boolean result
+ */
+
+ static function hasKeys()
+ {
+ $apiKey = common_config('facebook', 'apikey');
+ $apiSecret = common_config('facebook', 'secret');
+
+ if (!empty($apiKey) && !empty($apiSecret)) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Add Facebook app actions to the router table
*
@@ -61,22 +110,26 @@ class FacebookPlugin extends Plugin
function onStartInitializeRouter($m)
{
+ $m->connect('admin/facebook', array('action' => 'facebookadminpanel'));
- // Facebook App stuff
+ if (self::hasKeys()) {
- $m->connect('facebook/app', array('action' => 'facebookhome'));
- $m->connect('facebook/app/index.php', array('action' => 'facebookhome'));
- $m->connect('facebook/app/settings.php',
- array('action' => 'facebooksettings'));
- $m->connect('facebook/app/invite.php', array('action' => 'facebookinvite'));
- $m->connect('facebook/app/remove', array('action' => 'facebookremove'));
+ // Facebook App stuff
- // Facebook Connect stuff
+ $m->connect('facebook/app', array('action' => 'facebookhome'));
+ $m->connect('facebook/app/index.php', array('action' => 'facebookhome'));
+ $m->connect('facebook/app/settings.php',
+ array('action' => 'facebooksettings'));
+ $m->connect('facebook/app/invite.php', array('action' => 'facebookinvite'));
+ $m->connect('facebook/app/remove', array('action' => 'facebookremove'));
- $m->connect('main/facebookconnect', array('action' => 'FBConnectAuth'));
- $m->connect('main/facebooklogin', array('action' => 'FBConnectLogin'));
- $m->connect('settings/facebook', array('action' => 'FBConnectSettings'));
- $m->connect('xd_receiver.html', array('action' => 'FBC_XDReceiver'));
+ // Facebook Connect stuff
+
+ $m->connect('main/facebookconnect', array('action' => 'FBConnectAuth'));
+ $m->connect('main/facebooklogin', array('action' => 'FBConnectLogin'));
+ $m->connect('settings/facebook', array('action' => 'FBConnectSettings'));
+ $m->connect('xd_receiver.html', array('action' => 'FBC_XDReceiver'));
+ }
return true;
}
@@ -98,6 +151,7 @@ class FacebookPlugin extends Plugin
case 'FacebookinviteAction':
case 'FacebookremoveAction':
case 'FacebooksettingsAction':
+ case 'FacebookadminpanelAction':
include_once INSTALLDIR . '/plugins/Facebook/' .
strtolower(mb_substr($cls, 0, -6)) . '.php';
return false;
@@ -123,6 +177,32 @@ class FacebookPlugin extends Plugin
}
/**
+ * Add a Facebook tab to the admin panels
+ *
+ * @param Widget $nav Admin panel nav
+ *
+ * @return boolean hook value
+ */
+
+ function onEndAdminPanelNav($nav)
+ {
+ if (AdminPanelAction::canAdmin('facebook')) {
+
+ $action_name = $nav->action->trimmed('action');
+
+ $nav->out->menuItem(
+ common_local_url('facebookadminpanel'),
+ _m('Facebook'),
+ _m('Facebook integration configuration'),
+ $action_name == 'facebookadminpanel',
+ 'nav_facebook_admin_panel'
+ );
+ }
+
+ return true;
+ }
+
+ /**
* Override normal HTML output to force the content type to
* text/html and add in xmlns:fb
*
@@ -280,6 +360,9 @@ class FacebookPlugin extends Plugin
function reqFbScripts($action)
{
+ if (!self::hasKeys()) {
+ return false;
+ }
// If you're logged in w/FB Connect, you always need the FB stuff
@@ -352,44 +435,45 @@ class FacebookPlugin extends Plugin
function onStartPrimaryNav($action)
{
- $user = common_current_user();
+ if (self::hasKeys()) {
- $connect = 'FBConnectSettings';
- if (common_config('xmpp', 'enabled')) {
- $connect = 'imsettings';
- } else if (common_config('sms', 'enabled')) {
- $connect = 'smssettings';
- } else if (common_config('twitter', 'enabled')) {
- $connect = 'twittersettings';
- }
+ $user = common_current_user();
- if (!empty($user)) {
+ $connect = 'FBConnectSettings';
+ if (common_config('xmpp', 'enabled')) {
+ $connect = 'imsettings';
+ } else if (common_config('sms', 'enabled')) {
+ $connect = 'smssettings';
+ }
- $fbuid = $this->loggedIn();
+ if (!empty($user)) {
- if (!empty($fbuid)) {
+ $fbuid = $this->loggedIn();
- /* Default FB silhouette pic for FB users who haven't
- uploaded a profile pic yet. */
+ if (!empty($fbuid)) {
- $silhouetteUrl =
- 'http://static.ak.fbcdn.net/pics/q_silhouette.gif';
+ /* Default FB silhouette pic for FB users who haven't
+ uploaded a profile pic yet. */
- $url = $this->getProfilePicURL($fbuid);
+ $silhouetteUrl =
+ 'http://static.ak.fbcdn.net/pics/q_silhouette.gif';
- $action->elementStart('li', array('id' => 'nav_fb'));
+ $url = $this->getProfilePicURL($fbuid);
- $action->element('img', array('id' => 'fbc_profile-pic',
- 'src' => (!empty($url)) ? $url : $silhouetteUrl,
- 'alt' => 'Facebook Connect User',
- 'width' => '16'), '');
+ $action->elementStart('li', array('id' => 'nav_fb'));
- $iconurl = common_path('plugins/Facebook/fbfavicon.ico');
- $action->element('img', array('id' => 'fb_favicon',
- 'src' => $iconurl));
+ $action->element('img', array('id' => 'fbc_profile-pic',
+ 'src' => (!empty($url)) ? $url : $silhouetteUrl,
+ 'alt' => 'Facebook Connect User',
+ 'width' => '16'), '');
- $action->elementEnd('li');
+ $iconurl = common_path('plugins/Facebook/fbfavicon.ico');
+ $action->element('img', array('id' => 'fb_favicon',
+ 'src' => $iconurl));
+ $action->elementEnd('li');
+
+ }
}
}
@@ -406,14 +490,15 @@ class FacebookPlugin extends Plugin
function onEndLoginGroupNav(&$action)
{
+ if (self::hasKeys()) {
- $action_name = $action->trimmed('action');
-
- $action->menuItem(common_local_url('FBConnectLogin'),
- _m('Facebook'),
- _m('Login or register using Facebook'),
- 'FBConnectLogin' === $action_name);
+ $action_name = $action->trimmed('action');
+ $action->menuItem(common_local_url('FBConnectLogin'),
+ _m('Facebook'),
+ _m('Login or register using Facebook'),
+ 'FBConnectLogin' === $action_name);
+ }
return true;
}
@@ -427,13 +512,15 @@ class FacebookPlugin extends Plugin
function onEndConnectSettingsNav(&$action)
{
- $action_name = $action->trimmed('action');
+ if (self::hasKeys()) {
- $action->menuItem(common_local_url('FBConnectSettings'),
- _m('Facebook'),
- _m('Facebook Connect Settings'),
- $action_name === 'FBConnectSettings');
+ $action_name = $action->trimmed('action');
+ $action->menuItem(common_local_url('FBConnectSettings'),
+ _m('Facebook'),
+ _m('Facebook Connect Settings'),
+ $action_name === 'FBConnectSettings');
+ }
return true;
}
@@ -447,20 +534,22 @@ class FacebookPlugin extends Plugin
function onStartLogout($action)
{
- $action->logout();
- $fbuid = $this->loggedIn();
+ if (self::hasKeys()) {
- if (!empty($fbuid)) {
- try {
- $facebook = getFacebook();
- $facebook->expire_session();
- } catch (Exception $e) {
- common_log(LOG_WARNING, 'Facebook Connect Plugin - ' .
- 'Could\'t logout of Facebook: ' .
- $e->getMessage());
+ $action->logout();
+ $fbuid = $this->loggedIn();
+
+ if (!empty($fbuid)) {
+ try {
+ $facebook = getFacebook();
+ $facebook->expire_session();
+ } catch (Exception $e) {
+ common_log(LOG_WARNING, 'Facebook Connect Plugin - ' .
+ 'Could\'t logout of Facebook: ' .
+ $e->getMessage());
+ }
}
}
-
return true;
}
@@ -506,7 +595,9 @@ class FacebookPlugin extends Plugin
function onStartEnqueueNotice($notice, &$transports)
{
- array_push($transports, 'facebook');
+ if (self::hasKeys()) {
+ array_push($transports, 'facebook');
+ }
return true;
}
@@ -519,21 +610,26 @@ class FacebookPlugin extends Plugin
*/
function onEndInitializeQueueManager($manager)
{
- $manager->connect('facebook', 'FacebookQueueHandler');
+ if (self::hasKeys()) {
+ $manager->connect('facebook', 'FacebookQueueHandler');
+ }
return true;
}
function onPluginVersion(&$versions)
{
- $versions[] = array('name' => 'Facebook',
- 'version' => FACEBOOKPLUGIN_VERSION,
- 'author' => 'Zach Copley',
- 'homepage' => 'http://status.net/wiki/Plugin:Facebook',
- 'rawdescription' =>
- _m('The Facebook plugin allows you to integrate ' .
- 'your StatusNet instance with ' .
- '<a href="http://facebook.com/">Facebook</a> ' .
- 'and Facebook Connect.'));
+ $versions[] = array(
+ 'name' => 'Facebook',
+ 'version' => self::VERSION,
+ 'author' => 'Zach Copley',
+ 'homepage' => 'http://status.net/wiki/Plugin:Facebook',
+ 'rawdescription' => _m(
+ 'The Facebook plugin allows you to integrate ' .
+ 'your StatusNet instance with ' .
+ '<a href="http://facebook.com/">Facebook</a> ' .
+ 'and Facebook Connect.'
+ )
+ );
return true;
}
diff --git a/plugins/Facebook/README b/plugins/Facebook/README
index bf2f4a180..14c1d3241 100644
--- a/plugins/Facebook/README
+++ b/plugins/Facebook/README
@@ -1,6 +1,9 @@
-This plugin allows you to use Facebook Connect with StatusNet, provides a
-Facebook application for your users, and allows them to update their
-Facebook statuses from StatusNet.
+Facebook Plugin
+===============
+
+This plugin allows you to use Facebook Connect with StatusNet, provides
+a Facebook canvas application for your users, and allows them to update
+their Facebook statuses from StatusNet.
Facebook Connect
----------------
@@ -15,12 +18,12 @@ Facebook credentials. With Facebook Connect, your users can:
Built-in Facebook Application
-----------------------------
-The plugin also installs a StatusNet Facebook application that allows your
-users to automatically update their Facebook statuses with their latest
-notices, invite their friends to use the app (and thus your site), view
-their notice timelines, and post notices -- all from within Facebook. The
-application is built into the StatusNet Facebook plugin and runs on your
-host.
+The plugin also installs a StatusNet Facebook canvas application that
+allows your users to automatically update their Facebook status with
+their latest notices, invite their friends to use the app (and thus your
+site), view their notice timelines and post notices -- all from within
+Facebook. The application is built into the StatusNet Facebook plugin
+and runs on your host.
Quick setup instructions*
-------------------------
@@ -29,13 +32,9 @@ Install the Facebook Developer application on Facebook:
http://www.facebook.com/developers/
-Use it to create a new application and generate an API key and secret. Add a
-Facebook app section of your config.php and copy in the key and secret,
-e.g.:
-
- // Config section for the built-in Facebook application
- $config['facebook']['apikey'] = 'APIKEY';
- $config['facebook']['secret'] = 'SECRET';
+Use it to create a new application and generate an API key and secret.
+You will need the key and secret so cut-n-paste them into your text
+editor or write them down.
In Facebook's application editor, specify the following URLs for your app:
@@ -67,11 +66,36 @@ can be left with default values.
http://wiki.developers.facebook.com/index.php/Connect/Setting_Up_Your_Site
http://wiki.developers.facebook.com/index.php/Creating_your_first_application
-Finally you must activate the plugin by adding the following line to your
-config.php:
+Finally you must activate the plugin by adding it in your config.php
+(this is where you'll need the API key and secret generated earlier):
+
+ addPlugin(
+ 'Facebook',
+ array(
+ 'apikey' => 'YOUR_APIKEY',
+ 'secret' => 'YOUR_SECRET'
+ )
+ );
+
+Administration Panel
+--------------------
+
+As of StatusNet 0.9.0 you can alternatively specify the key and secret
+via a Facebook administration panel from within StatusNet, in which case
+you can just add:
addPlugin('Facebook');
+to activate the plugin.
+
+NOTE: To enable the administration panel you'll need to add it to the
+list of active administration panels, e.g.:
+
+ $config['admin']['panels'][] = 'facebook';
+
+and of course you'll need a user with the administrative role to access
+it and input the API key and secret (see: scripts/userrole.php).
+
Testing It Out
--------------
@@ -81,11 +105,11 @@ disconnect* to their Facebook accounts from it.
To try out the plugin, fire up your browser and connect to:
- http://SITE/PATH_TO_STATUSNET/main/facebooklogin
+ http://example.net/mublog/main/facebooklogin
or, if you do not have fancy URLs turned on:
- http://SITE/PATH_TO_STATUSNET/index.php/main/facebooklogin
+ http://example.net/mublog/index.php/main/facebooklogin
You should see a page with a blue button that says: "Connect with Facebook"
and you should be able to login or register.
@@ -101,7 +125,7 @@ the app, you are given the option to update their Facebook status via
StatusNet.
* Note: Before a user can disconnect from Facebook, she must set a normal
- StatusNet password. Otherwise, she might not be able to login in to her
+ StatusNet password. Otherwise, she might not be able to login in to her
account in the future. This is usually only required for users who have
used Facebook Connect to register their StatusNet account, and therefore
haven't already set a local password.
@@ -109,16 +133,20 @@ StatusNet.
Offline Queue Handling
----------------------
-For larger sites needing better performance it's possible to enable queuing
-and have users' notices posted to Facebook via a separate "offline"
-FacebookQueueHandler (facebookqueuhandler.php in the Facebook plugin
-directory), which will be started by the plugin along with their other
-daemons when you run scripts/startdaemons.sh. See the StatusNet README for
-more about queuing and daemons.
+For larger sites needing better performance it's possible to enable
+queuing and have users' notices posted to Facebook via a separate
+"offline" process -- FacebookQueueHandler (facebookqueuhandler.php in
+the Facebook plugin directory). It will run automatically if you have
+enabled StatusNet's offline queueing subsystem. See the "Queues and
+daemons" section in the StatusNet README for more about queuing.
+
TODO
----
+- Make Facebook Connect work for authentication for multi-site setups
+ (e.g.: *.status.net)
+- Posting to Facebook user streams using only Facebook Connect
- Invite Facebook friends to use your StatusNet installation via Facebook
Connect
- Auto-subscribe Facebook friends already using StatusNet
@@ -126,4 +154,4 @@ TODO
- Allow users to update their Facebook statuses once they have authenticated
with Facebook Connect (no need for them to use the Facebook app if they
don't want to).
-- Re-design the whole thing to support multiple instances of StatusNet
+- Import a user's Facebook updates into StatusNet
diff --git a/plugins/Facebook/facebookadminpanel.php b/plugins/Facebook/facebookadminpanel.php
new file mode 100644
index 000000000..ae1c7302f
--- /dev/null
+++ b/plugins/Facebook/facebookadminpanel.php
@@ -0,0 +1,223 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Facebook integration administration panel
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Settings
+ * @package StatusNet
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Administer global Facebook integration settings
+ *
+ * @category Admin
+ * @package StatusNet
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class FacebookadminpanelAction extends AdminPanelAction
+{
+ /**
+ * Returns the page title
+ *
+ * @return string page title
+ */
+
+ function title()
+ {
+ return _m('Facebook');
+ }
+
+ /**
+ * Instructions for using this form.
+ *
+ * @return string instructions
+ */
+
+ function getInstructions()
+ {
+ return _m('Facebook integration settings');
+ }
+
+ /**
+ * Show the Facebook admin panel form
+ *
+ * @return void
+ */
+
+ function showForm()
+ {
+ $form = new FacebookAdminPanelForm($this);
+ $form->show();
+ return;
+ }
+
+ /**
+ * Save settings from the form
+ *
+ * @return void
+ */
+
+ function saveSettings()
+ {
+ static $settings = array(
+ 'facebook' => array('apikey', 'secret'),
+ );
+
+ $values = array();
+
+ foreach ($settings as $section => $parts) {
+ foreach ($parts as $setting) {
+ $values[$section][$setting]
+ = $this->trimmed($setting);
+ }
+ }
+
+ // This throws an exception on validation errors
+
+ $this->validate($values);
+
+ // assert(all values are valid);
+
+ $config = new Config();
+
+ $config->query('BEGIN');
+
+ foreach ($settings as $section => $parts) {
+ foreach ($parts as $setting) {
+ Config::save($section, $setting, $values[$section][$setting]);
+ }
+ }
+
+ $config->query('COMMIT');
+
+ return;
+ }
+
+ function validate(&$values)
+ {
+ // Validate consumer key and secret (can't be too long)
+
+ if (mb_strlen($values['facebook']['apikey']) > 255) {
+ $this->clientError(
+ _m("Invalid Facebook API key. Max length is 255 characters.")
+ );
+ }
+
+ if (mb_strlen($values['facebook']['secret']) > 255) {
+ $this->clientError(
+ _m("Invalid Facebook API secret. Max length is 255 characters.")
+ );
+ }
+ }
+}
+
+class FacebookAdminPanelForm extends AdminForm
+{
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+
+ function id()
+ {
+ return 'facebookadminpanel';
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+
+ function formClass()
+ {
+ return 'form_settings';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return common_local_url('facebookadminpanel');
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ $this->out->elementStart(
+ 'fieldset',
+ array('id' => 'settings_facebook-application')
+ );
+ $this->out->element('legend', null, _m('Facebook application settings'));
+ $this->out->elementStart('ul', 'form_data');
+
+ $this->li();
+ $this->input(
+ 'apikey',
+ _m('API key'),
+ _m('API key provided by Facebook'),
+ 'facebook'
+ );
+ $this->unli();
+
+ $this->li();
+ $this->input(
+ 'secret',
+ _m('Secret'),
+ _m('API secret provided by Facebook'),
+ 'facebook'
+ );
+ $this->unli();
+
+ $this->out->elementEnd('ul');
+ $this->out->elementEnd('fieldset');
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->submit('submit', _('Save'), 'submit', null, _('Save Facebook settings'));
+ }
+}
diff --git a/plugins/MobileProfile/MobileProfilePlugin.php b/plugins/MobileProfile/MobileProfilePlugin.php
index cd2531fa7..f788639ae 100644
--- a/plugins/MobileProfile/MobileProfilePlugin.php
+++ b/plugins/MobileProfile/MobileProfilePlugin.php
@@ -312,8 +312,6 @@ class MobileProfilePlugin extends WAP20Plugin
$connect = 'imsettings';
} else if (common_config('sms', 'enabled')) {
$connect = 'smssettings';
- } else if (common_config('twitter', 'enabled')) {
- $connect = 'twittersettings';
}
$action->elementStart('ul', array('id' => 'site_nav_global_primary'));
diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php
index 4ffbba45b..95414e517 100644
--- a/plugins/OStatus/OStatusPlugin.php
+++ b/plugins/OStatus/OStatusPlugin.php
@@ -210,6 +210,26 @@ class OStatusPlugin extends Plugin
return false;
}
+ function onStartGroupSubscribe($output, $group)
+ {
+ $cur = common_current_user();
+
+ if (empty($cur)) {
+ // Add an OStatus subscribe
+ $output->elementStart('li', 'entity_subscribe');
+ $url = common_local_url('ostatusinit',
+ array('nickname' => $group->nickname));
+ $output->element('a', array('href' => $url,
+ 'class' => 'entity_remote_subscribe'),
+ _m('Join'));
+
+ $output->elementEnd('li');
+ }
+
+ return false;
+ }
+
+
/**
* Check if we've got remote replies to send via Salmon.
*
@@ -233,70 +253,70 @@ class OStatusPlugin extends Plugin
function onEndFindMentions($sender, $text, &$mentions)
{
- preg_match_all('!(?:^|\s+)
- @( # Webfinger:
- (?:\w+\.)*\w+ # user
- @ # @
- (?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+ # domain
- | # Profile:
- (?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+ # domain
- (?:/\w+)+ # /path1(/path2...)
- )!x',
+ $matches = array();
+
+ // Webfinger matches: @user@example.com
+ if (preg_match_all('!(?:^|\s+)@((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)!',
$text,
$wmatches,
- PREG_OFFSET_CAPTURE);
-
- foreach ($wmatches[1] as $wmatch) {
- $target = $wmatch[0];
- $oprofile = null;
-
- if (strpos($target, '/') === false) {
- $this->log(LOG_INFO, "Checking Webfinger for address '$target'");
+ PREG_OFFSET_CAPTURE)) {
+ foreach ($wmatches[1] as $wmatch) {
+ list($target, $pos) = $wmatch;
+ $this->log(LOG_INFO, "Checking webfinger '$target'");
try {
$oprofile = Ostatus_profile::ensureWebfinger($target);
+ if ($oprofile && !$oprofile->isGroup()) {
+ $profile = $oprofile->localProfile();
+ $matches[$pos] = array('mentioned' => array($profile),
+ 'text' => $target,
+ 'position' => $pos,
+ 'url' => $profile->profileurl);
+ }
} catch (Exception $e) {
$this->log(LOG_ERR, "Webfinger check failed: " . $e->getMessage());
}
- } else {
- $schemes = array('https', 'http');
+ }
+ }
+
+ // Profile matches: @example.com/mublog/user
+ if (preg_match_all('!(?:^|\s+)@((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)!',
+ $text,
+ $wmatches,
+ PREG_OFFSET_CAPTURE)) {
+ foreach ($wmatches[1] as $wmatch) {
+ list($target, $pos) = $wmatch;
+ $schemes = array('http', 'https');
foreach ($schemes as $scheme) {
$url = "$scheme://$target";
$this->log(LOG_INFO, "Checking profile address '$url'");
try {
$oprofile = Ostatus_profile::ensureProfile($url);
- if ($oprofile) {
- continue;
+ if ($oprofile && !$oprofile->isGroup()) {
+ $profile = $oprofile->localProfile();
+ $matches[$pos] = array('mentioned' => array($profile),
+ 'text' => $target,
+ 'position' => $pos,
+ 'url' => $profile->profileurl);
+ break;
}
} catch (Exception $e) {
$this->log(LOG_ERR, "Profile check failed: " . $e->getMessage());
}
}
}
+ }
- if (empty($oprofile)) {
- $this->log(LOG_INFO, "No Ostatus_profile found for address '$target'");
- } else {
-
- $this->log(LOG_INFO, "Ostatus_profile found for address '$target'");
-
- if ($oprofile->isGroup()) {
- continue;
- }
- $profile = $oprofile->localProfile();
-
- $pos = $wmatch[1];
- foreach ($mentions as $i => $other) {
- // If we share a common prefix with a local user, override it!
- if ($other['position'] == $pos) {
- unset($mentions[$i]);
- }
- }
- $mentions[] = array('mentioned' => array($profile),
- 'text' => $target,
- 'position' => $pos,
- 'url' => $profile->profileurl);
+ foreach ($mentions as $i => $other) {
+ // If we share a common prefix with a local user, override it!
+ $pos = $other['position'];
+ if (isset($matches[$pos])) {
+ $mentions[$i] = $matches[$pos];
+ unset($matches[$pos]);
}
}
+ foreach ($matches as $mention) {
+ $mentions[] = $mention;
+ }
return true;
}
@@ -706,6 +726,20 @@ class OStatusPlugin extends Plugin
function onStartShowSubscriptionsContent($action)
{
+ $this->showEntityRemoteSubscribe($action);
+
+ return true;
+ }
+
+ function onEndShowSubscriptionsMiniList($action)
+ {
+ $this->showEntityRemoteSubscribe($action);
+
+ return true;
+ }
+
+ function showEntityRemoteSubscribe($action)
+ {
$user = common_current_user();
if ($user && ($user->id == $action->profile->id)) {
$action->elementStart('div', 'entity_actions');
@@ -713,12 +747,10 @@ class OStatusPlugin extends Plugin
'class' => 'entity_subscribe'));
$action->element('a', array('href' => common_local_url('ostatussub'),
'class' => 'entity_remote_subscribe')
- , _m('Subscribe to remote user'));
+ , _m('New'));
$action->elementEnd('p');
$action->elementEnd('div');
}
-
- return true;
}
/**
diff --git a/plugins/OStatus/actions/ostatussub.php b/plugins/OStatus/actions/ostatussub.php
index f45e6a8d1..e318701a2 100644
--- a/plugins/OStatus/actions/ostatussub.php
+++ b/plugins/OStatus/actions/ostatussub.php
@@ -112,7 +112,7 @@ class OStatusSubAction extends Action
$this->submit('submit', _m('Join'), 'submit', null,
_m('Join this group'));
} else {
- $this->submit('submit', _m('Subscribe'), 'submit', null,
+ $this->submit('submit', _m('Confirm'), 'submit', null,
_m('Subscribe to this user'));
}
$this->elementEnd('fieldset');
diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php
index a33e95d93..7ab031aa5 100644
--- a/plugins/OStatus/classes/Ostatus_profile.php
+++ b/plugins/OStatus/classes/Ostatus_profile.php
@@ -550,7 +550,8 @@ class Ostatus_profile extends Memcached_DataObject
'rendered' => $rendered,
'replies' => array(),
'groups' => array(),
- 'tags' => array());
+ 'tags' => array(),
+ 'urls' => array());
// Check for optional attributes...
@@ -595,6 +596,12 @@ class Ostatus_profile extends Memcached_DataObject
}
}
+ // Atom enclosures -> attachment URLs
+ foreach ($activity->enclosures as $href) {
+ // @fixme save these locally or....?
+ $options['urls'][] = $href;
+ }
+
try {
$saved = Notice::saveNew($oprofile->profile_id,
$content,
@@ -620,7 +627,8 @@ class Ostatus_profile extends Memcached_DataObject
protected function purify($html)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
- $config = array('safe' => 1);
+ $config = array('safe' => 1,
+ 'deny_attribute' => 'id,style,on*');
return htmLawed($html, $config);
}
@@ -1492,7 +1500,7 @@ class Ostatus_profile extends Memcached_DataObject
if (array_key_exists('url', $hcard)) {
if (is_string($hcard['url'])) {
$hints['homepage'] = $hcard['url'];
- } else if (is_array($hcard['adr'])) {
+ } else if (is_array($hcard['url'])) {
// HACK get the last one; that's how our hcards look
$hints['homepage'] = $hcard['url'][count($hcard['url'])-1];
}
diff --git a/plugins/OStatus/lib/xrd.php b/plugins/OStatus/lib/xrd.php
index 85df26c54..f00e1f809 100644
--- a/plugins/OStatus/lib/xrd.php
+++ b/plugins/OStatus/lib/xrd.php
@@ -149,9 +149,11 @@ class XRD
$link['href'] = $element->getAttribute('href');
$link['template'] = $element->getAttribute('template');
foreach ($element->childNodes as $node) {
- switch($node->tagName) {
- case 'Title':
- $link['title'][] = $node->nodeValue;
+ if ($node instanceof DOMElement) {
+ switch($node->tagName) {
+ case 'Title':
+ $link['title'][] = $node->nodeValue;
+ }
}
}
diff --git a/plugins/OStatus/theme/base/css/ostatus.css b/plugins/OStatus/theme/base/css/ostatus.css
index feeeb47d3..40cdfcef1 100644
--- a/plugins/OStatus/theme/base/css/ostatus.css
+++ b/plugins/OStatus/theme/base/css/ostatus.css
@@ -38,11 +38,25 @@ display:none;
min-width:96px;
}
-#subscriptions #entity_remote_subscribe {
+#entity_remote_subscribe {
padding:0;
float:right;
+position:relative;
}
-#subscriptions .entity_remote_subscribe {
-float:right;
+.section .entity_actions {
+margin-bottom:0;
+}
+
+.section #entity_remote_subscribe .entity_remote_subscribe {
+border-color:#AAAAAA;
+}
+
+.section #entity_remote_subscribe .dialogbox {
+width:405px;
+}
+
+
+.aside #entity_subscriptions .more {
+float:left;
}
diff --git a/plugins/TwitterBridge/README b/plugins/TwitterBridge/README
index d3bcda598..d0d34b7ef 100644
--- a/plugins/TwitterBridge/README
+++ b/plugins/TwitterBridge/README
@@ -1,47 +1,104 @@
+Twitter Bridge Plugin
+=====================
+
This Twitter "bridge" plugin allows you to integrate your StatusNet
instance with Twitter. Installing it will allow your users to:
- - automatically post notices to thier Twitter accounts
+ - automatically post notices to their Twitter accounts
- automatically subscribe to other Twitter users who are also using
your StatusNet install, if possible (requires running a daemon)
- import their Twitter friends' tweets (requires running a daemon)
+ - allow users to authenticate using Twitter ('Sign in with Twitter')
Installation
------------
-To enable the plugin, add the following to your config.php:
-
- addPlugin("TwitterBridge");
-
-OAuth is used to to access protected resources on Twitter (as opposed to
-HTTP Basic Auth)*. To use Twitter bridging you will need to register
-your instance of StatusNet as an application on Twitter
-(http://twitter.com/apps), and update the following variables in your
-config.php with the consumer key and secret Twitter generates for you:
-
- $config['twitter']['consumer_key'] = 'YOURKEY';
- $config['twitter']['consumer_secret'] = 'YOURSECRET';
+OAuth 1.0a (http://oauth.net) is used to to access protected resources
+on Twitter (as opposed to HTTP Basic Auth)*. To use Twitter bridging
+you will need to register your instance of StatusNet as an application
+on Twitter (http://twitter.com/apps). During the application
+registration process your application will be assigned a "consumer" key
+and secret, which the plugin will use to make OAuth requests to Twitter.
+You can either pass the consumer key and secret in when you enable the
+plugin, or set it using the Twitter administration panel**.
When registering your application with Twitter set the type to "Browser"
and your Callback URL to:
http://example.org/mublog/twitter/authorization
-The default access type should be, "Read & Write".
+(Change "example.org" to your site domain and "mublog" to your site
+path.)
+
+The default access type should be "Read & Write".
+
+To enable the plugin, add the following to your config.php:
+
+ addPlugin(
+ 'TwitterBridge',
+ array(
+ 'consumer_key' => 'YOUR_CONSUMER_KEY',
+ 'consumer_secret' => 'YOUR_CONSUMER_SECRET'
+ )
+ );
+
+or just:
+
+ addPlugin('TwitterBridge');
+
+if you want to set the consumer key and secret from the Twitter bridge
+administration panel. (The Twitter bridge wont work at all
+unless you configure it with a consumer key and secret.)
* Note: The plugin will still push notices to Twitter for users who
- have previously setup the Twitter bridge using their Twitter name and
- password under an older versions of StatusNet, but all new Twitter
+ have previously set up the Twitter bridge using their Twitter name and
+ password under an older version of StatusNet, but all new Twitter
bridge connections will use OAuth.
-Deamons
+** For multi-site setups you can also set a global consumer key and
+ secret. The Twitter bridge will fall back on the global key pair if
+ it can't find a local pair, e.g.:
+
+ $config['twitter']['global_consumer_key'] = 'YOUR_CONSUMER_KEY'
+ $config['twitter']['global_consumer_secret'] = 'YOUR_CONSUMER_SECRET'
+
+Administration panel
+--------------------
+
+As of StatusNet 0.9.0 there is a new administration panel that allows
+you to configure Twitter bridge settings within StatusNet itself,
+instead of having to specify them manually in your config.php. To enable
+the administration panel, you will need to add it to the list of active
+administration panels. You can do this via your config.php. E.g.:
+
+ $config['admin']['panels'][] = 'twitter';
+
+And to access it, you'll need to use a user with the "administrator"
+role (see: scripts/userrole.php).
+
+Sign in with Twitter
+--------------------
+
+With 0.9.0, StatusNet optionally allows users to register and
+authenticate using their Twitter credentials via the "Sign in with
+Twitter" pattern described here:
+
+ http://apiwiki.twitter.com/Sign-in-with-Twitter
+
+The option is _on_ by default when you install the plugin, but it can
+disabled via the Twitter bridge administration panel, or by adding the
+following line to your config.php:
+
+ $config['twitter']['signin'] = false;
+
+Daemons
-------
-For friend syncing and importing notices running two additional daemon
-scripts is necessary (synctwitterfriends.php and
-twitterstatusfetcher.php).
+For friend syncing and importing Twitter tweets, running two
+additional daemon scripts is necessary: synctwitterfriends.php and
+twitterstatusfetcher.php.
-In the daemons subidrectory of the plugin are three scripts:
+In the daemons subdirectory of the plugin are three scripts:
* Twitter Friends Syncing (daemons/synctwitterfriends.php)
@@ -51,13 +108,13 @@ subscribe to "friends" (people they "follow") on Twitter who also have
accounts on your StatusNet system, and who have previously set up a link
for automatically posting notices to Twitter.
-The plugin will try to start this daemon when you run
-scripts/startdaemons.sh.
+The plugin will start this daemon when you run scripts/startdaemons.sh.
* Importing statuses from Twitter (daemons/twitterstatusfetcher.php)
-To allow your users to import their friends' Twitter statuses, you will
-need to enable the bidirectional Twitter bridge in your config.php:
+You can allow uses to enable importing of your friends' Twitter
+timelines either in the Twitter bridge administration panel or in your
+config.php using the following configuration line:
$config['twitterimport']['enabled'] = true;
@@ -66,8 +123,9 @@ other daemons when you run scripts/startdaemons.sh.
Additionally, you will want to set the integration source variable,
which will keep notices posted to Twitter via StatusNet from looping
-back. The integration source should be set to the name of your
-application, exactly as you specified it on the settings page for your
+back. You can do this in the Twitter bridge administration panel, or
+via config.php. The integration source should be set to the name of your
+application _exactly_ as you specified it on the settings page for your
StatusNet application on Twitter, e.g.:
$config['integration']['source'] = 'YourApp';
@@ -79,7 +137,9 @@ set up Twitter bridging.
It's not strictly necessary to run this queue handler, and sites that
haven't enabled queuing are still able to push notices to Twitter, but
-for larger sites and sites that wish to improve performance, this
-script allows notices to be sent "offline" via a separate process.
+for larger sites and sites that wish to improve performance the script
+allows notices to be sent "offline" via a separate process.
-The plugin will start this script when you run scripts/startdaemons.sh.
+StatusNet will automatically use the TwitterQueueHandler if you have
+enabled the queuing subsystem. See the "Queues and daemons" section of
+the main README file for more information about how to do that.
diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php
index c7f57ffc7..1a0a69682 100644
--- a/plugins/TwitterBridge/TwitterBridgePlugin.php
+++ b/plugins/TwitterBridge/TwitterBridgePlugin.php
@@ -23,7 +23,7 @@
* @author Julien C <chaumond@gmail.com>
* @copyright 2009-2010 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/
+ * @link http://status.net/
*/
if (!defined('STATUSNET')) {
@@ -32,8 +32,6 @@ if (!defined('STATUSNET')) {
require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php';
-define('TWITTERBRIDGEPLUGIN_VERSION', '0.9');
-
/**
* Plugin for sending and importing Twitter statuses
*
@@ -44,19 +42,65 @@ define('TWITTERBRIDGEPLUGIN_VERSION', '0.9');
* @author Zach Copley <zach@status.net>
* @author Julien C <chaumond@gmail.com>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://laconi.ca/
+ * @link http://status.net/
* @link http://twitter.com/
*/
class TwitterBridgePlugin extends Plugin
{
+
+ const VERSION = STATUSNET_VERSION;
+
/**
* Initializer for the plugin.
*/
- function __construct()
+ function initialize()
{
- parent::__construct();
+ // Allow the key and secret to be passed in
+ // Control panel will override
+
+ if (isset($this->consumer_key)) {
+ $key = common_config('twitter', 'consumer_key');
+ if (empty($key)) {
+ Config::save('twitter', 'consumer_key', $this->consumer_key);
+ }
+ }
+
+ if (isset($this->consumer_secret)) {
+ $secret = common_config('twitter', 'consumer_secret');
+ if (empty($secret)) {
+ Config::save(
+ 'twitter',
+ 'consumer_secret',
+ $this->consumer_secret
+ );
+ }
+ }
+ }
+
+ /**
+ * Check to see if there is a consumer key and secret defined
+ * for Twitter integration.
+ *
+ * @return boolean result
+ */
+
+ static function hasKeys()
+ {
+ $ckey = common_config('twitter', 'consumer_key');
+ $csecret = common_config('twitter', 'consumer_secret');
+
+ if (empty($ckey) && empty($csecret)) {
+ $ckey = common_config('twitter', 'global_consumer_key');
+ $csecret = common_config('twitter', 'global_consumer_secret');
+ }
+
+ if (!empty($ckey) && !empty($csecret)) {
+ return true;
+ }
+
+ return false;
}
/**
@@ -71,10 +115,25 @@ class TwitterBridgePlugin extends Plugin
function onRouterInitialized($m)
{
- $m->connect('twitter/authorization',
- array('action' => 'twitterauthorization'));
- $m->connect('settings/twitter', array('action' => 'twittersettings'));
- $m->connect('main/twitterlogin', array('action' => 'twitterlogin'));
+ $m->connect('admin/twitter', array('action' => 'twitteradminpanel'));
+
+ if (self::hasKeys()) {
+ $m->connect(
+ 'twitter/authorization',
+ array('action' => 'twitterauthorization')
+ );
+ $m->connect(
+ 'settings/twitter', array(
+ 'action' => 'twittersettings'
+ )
+ );
+ if (common_config('twitter', 'signin')) {
+ $m->connect(
+ 'main/twitterlogin',
+ array('action' => 'twitterlogin')
+ );
+ }
+ }
return true;
}
@@ -88,13 +147,16 @@ class TwitterBridgePlugin extends Plugin
*/
function onEndLoginGroupNav(&$action)
{
-
$action_name = $action->trimmed('action');
- $action->menuItem(common_local_url('twitterlogin'),
- _('Twitter'),
- _('Login or register using Twitter'),
- 'twitterlogin' === $action_name);
+ if (self::hasKeys() && common_config('twitter', 'signin')) {
+ $action->menuItem(
+ common_local_url('twitterlogin'),
+ _m('Twitter'),
+ _m('Login or register using Twitter'),
+ 'twitterlogin' === $action_name
+ );
+ }
return true;
}
@@ -108,13 +170,16 @@ class TwitterBridgePlugin extends Plugin
*/
function onEndConnectSettingsNav(&$action)
{
- $action_name = $action->trimmed('action');
-
- $action->menuItem(common_local_url('twittersettings'),
- _m('Twitter'),
- _m('Twitter integration options'),
- $action_name === 'twittersettings');
+ if (self::hasKeys()) {
+ $action_name = $action->trimmed('action');
+ $action->menuItem(
+ common_local_url('twittersettings'),
+ _m('Twitter'),
+ _m('Twitter integration options'),
+ $action_name === 'twittersettings'
+ );
+ }
return true;
}
@@ -132,6 +197,7 @@ class TwitterBridgePlugin extends Plugin
case 'TwittersettingsAction':
case 'TwitterauthorizationAction':
case 'TwitterloginAction':
+ case 'TwitteradminpanelAction':
include_once INSTALLDIR . '/plugins/TwitterBridge/' .
strtolower(mb_substr($cls, 0, -6)) . '.php';
return false;
@@ -155,12 +221,12 @@ class TwitterBridgePlugin extends Plugin
*/
function onStartEnqueueNotice($notice, &$transports)
{
- // Avoid a possible loop
-
- if ($notice->source != 'twitter') {
- array_push($transports, 'twitter');
+ if (self::hasKeys()) {
+ // Avoid a possible loop
+ if ($notice->source != 'twitter') {
+ array_push($transports, 'twitter');
+ }
}
-
return true;
}
@@ -173,12 +239,19 @@ class TwitterBridgePlugin extends Plugin
*/
function onGetValidDaemons($daemons)
{
- array_push($daemons, INSTALLDIR .
- '/plugins/TwitterBridge/daemons/synctwitterfriends.php');
-
- if (common_config('twitterimport', 'enabled')) {
- array_push($daemons, INSTALLDIR
- . '/plugins/TwitterBridge/daemons/twitterstatusfetcher.php');
+ if (self::hasKeys()) {
+ array_push(
+ $daemons,
+ INSTALLDIR
+ . '/plugins/TwitterBridge/daemons/synctwitterfriends.php'
+ );
+ if (common_config('twitterimport', 'enabled')) {
+ array_push(
+ $daemons,
+ INSTALLDIR
+ . '/plugins/TwitterBridge/daemons/twitterstatusfetcher.php'
+ );
+ }
}
return true;
@@ -193,21 +266,61 @@ class TwitterBridgePlugin extends Plugin
*/
function onEndInitializeQueueManager($manager)
{
- $manager->connect('twitter', 'TwitterQueueHandler');
+ if (self::hasKeys()) {
+ $manager->connect('twitter', 'TwitterQueueHandler');
+ }
return true;
}
+ /**
+ * Add a Twitter tab to the admin panel
+ *
+ * @param Widget $nav Admin panel nav
+ *
+ * @return boolean hook value
+ */
+
+ function onEndAdminPanelNav($nav)
+ {
+ if (AdminPanelAction::canAdmin('twitter')) {
+
+ $action_name = $nav->action->trimmed('action');
+
+ $nav->out->menuItem(
+ common_local_url('twitteradminpanel'),
+ _m('Twitter'),
+ _m('Twitter bridge configuration'),
+ $action_name == 'twitteradminpanel',
+ 'nav_twitter_admin_panel'
+ );
+ }
+
+ return true;
+ }
+
+ /**
+ * Plugin version data
+ *
+ * @param array &$versions array of version blocks
+ *
+ * @return boolean hook value
+ */
+
function onPluginVersion(&$versions)
{
- $versions[] = array('name' => 'TwitterBridge',
- 'version' => TWITTERBRIDGEPLUGIN_VERSION,
- 'author' => 'Zach Copley',
- 'homepage' => 'http://status.net/wiki/Plugin:TwitterBridge',
- 'rawdescription' =>
- _m('The Twitter "bridge" plugin allows you to integrate ' .
- 'your StatusNet instance with ' .
- '<a href="http://twitter.com/">Twitter</a>.'));
+ $versions[] = array(
+ 'name' => 'TwitterBridge',
+ 'version' => self::VERSION,
+ 'author' => 'Zach Copley, Julien C',
+ 'homepage' => 'http://status.net/wiki/Plugin:TwitterBridge',
+ 'rawdescription' => _m(
+ 'The Twitter "bridge" plugin allows you to integrate ' .
+ 'your StatusNet instance with ' .
+ '<a href="http://twitter.com/">Twitter</a>.'
+ )
+ );
return true;
}
}
+
diff --git a/plugins/TwitterBridge/twitteradminpanel.php b/plugins/TwitterBridge/twitteradminpanel.php
new file mode 100644
index 000000000..0ed53bc05
--- /dev/null
+++ b/plugins/TwitterBridge/twitteradminpanel.php
@@ -0,0 +1,323 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Twitter bridge administration panel
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Settings
+ * @package StatusNet
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Administer global Twitter bridge settings
+ *
+ * @category Admin
+ * @package StatusNet
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class TwitteradminpanelAction extends AdminPanelAction
+{
+ /**
+ * Returns the page title
+ *
+ * @return string page title
+ */
+
+ function title()
+ {
+ return _m('Twitter');
+ }
+
+ /**
+ * Instructions for using this form.
+ *
+ * @return string instructions
+ */
+
+ function getInstructions()
+ {
+ return _m('Twitter bridge settings');
+ }
+
+ /**
+ * Show the Twitter admin panel form
+ *
+ * @return void
+ */
+
+ function showForm()
+ {
+ $form = new TwitterAdminPanelForm($this);
+ $form->show();
+ return;
+ }
+
+ /**
+ * Save settings from the form
+ *
+ * @return void
+ */
+
+ function saveSettings()
+ {
+ static $settings = array(
+ 'twitter' => array('consumer_key', 'consumer_secret'),
+ 'integration' => array('source')
+ );
+
+ static $booleans = array(
+ 'twitter' => array('signin'),
+ 'twitterimport' => array('enabled')
+ );
+
+ $values = array();
+
+ foreach ($settings as $section => $parts) {
+ foreach ($parts as $setting) {
+ $values[$section][$setting]
+ = $this->trimmed($setting);
+ }
+ }
+
+ foreach ($booleans as $section => $parts) {
+ foreach ($parts as $setting) {
+ $values[$section][$setting]
+ = ($this->boolean($setting)) ? 1 : 0;
+ }
+ }
+
+ // This throws an exception on validation errors
+
+ $this->validate($values);
+
+ // assert(all values are valid);
+
+ $config = new Config();
+
+ $config->query('BEGIN');
+
+ foreach ($settings as $section => $parts) {
+ foreach ($parts as $setting) {
+ Config::save($section, $setting, $values[$section][$setting]);
+ }
+ }
+
+ foreach ($booleans as $section => $parts) {
+ foreach ($parts as $setting) {
+ Config::save($section, $setting, $values[$section][$setting]);
+ }
+ }
+
+ $config->query('COMMIT');
+
+ return;
+ }
+
+ function validate(&$values)
+ {
+ // Validate consumer key and secret (can't be too long)
+
+ if (mb_strlen($values['twitter']['consumer_key']) > 255) {
+ $this->clientError(
+ _m("Invalid consumer key. Max length is 255 characters.")
+ );
+ }
+
+ if (mb_strlen($values['twitter']['consumer_secret']) > 255) {
+ $this->clientError(
+ _m("Invalid consumer secret. Max length is 255 characters.")
+ );
+ }
+ }
+}
+
+class TwitterAdminPanelForm extends AdminForm
+{
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+
+ function id()
+ {
+ return 'twitteradminpanel';
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+
+ function formClass()
+ {
+ return 'form_settings';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return common_local_url('twitteradminpanel');
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ $this->out->elementStart(
+ 'fieldset',
+ array('id' => 'settings_twitter-application')
+ );
+ $this->out->element('legend', null, _m('Twitter application settings'));
+ $this->out->elementStart('ul', 'form_data');
+
+ $this->li();
+ $this->input(
+ 'consumer_key',
+ _m('Consumer key'),
+ _m('Consumer key assigned by Twitter'),
+ 'twitter'
+ );
+ $this->unli();
+
+ $this->li();
+ $this->input(
+ 'consumer_secret',
+ _m('Consumer secret'),
+ _m('Consumer secret assigned by Twitter'),
+ 'twitter'
+ );
+ $this->unli();
+
+ $globalConsumerKey = common_config('twitter', 'global_consumer_key');
+ $globalConsumerSec = common_config('twitter', 'global_consumer_secret');
+
+ if (!empty($globalConsumerKey)) {
+ $this->li();
+ $this->out->element(
+ 'label',
+ array('for' => 'global_consumer_key'),
+ ''
+ );
+ $this->out->element(
+ 'input',
+ array(
+ 'name' => 'global_consumer_key',
+ 'type' => 'text',
+ 'id' => 'global_consumer_key',
+ 'value' => $globalConsumerKey,
+ 'disabled' => 'true'
+ )
+ );
+ $this->out->element('p', 'form_guide', _('Global consumer key'));
+ $this->unli();
+
+ $this->li();
+ $this->out->element(
+ 'label',
+ array('for' => 'global_consumer_secret'),
+ ''
+ );
+ $this->out->element(
+ 'input',
+ array(
+ 'name' => 'global_consumer_secret',
+ 'type' => 'text',
+ 'id' => 'global_consumer_secret',
+ 'value' => $globalConsumerSec,
+ 'disabled' => 'true'
+ )
+ );
+ $this->out->element('p', 'form_guide', _('Global consumer secret'));
+ $this->unli();
+ }
+
+ $this->li();
+ $this->input(
+ 'source',
+ _m('Integration source'),
+ _m('Name of your Twitter application'),
+ 'integration'
+ );
+ $this->unli();
+
+ $this->out->elementEnd('ul');
+ $this->out->elementEnd('fieldset');
+
+ $this->out->elementStart(
+ 'fieldset',
+ array('id' => 'settings_twitter-options')
+ );
+ $this->out->element('legend', null, _m('Options'));
+
+ $this->out->elementStart('ul', 'form_data');
+
+ $this->li();
+
+ $this->out->checkbox(
+ 'signin', _m('Enable "Sign-in with Twitter"'),
+ (bool) $this->value('signin', 'twitter'),
+ _m('Allow users to login with their Twitter credentials')
+ );
+ $this->unli();
+
+ $this->li();
+ $this->out->checkbox(
+ 'enabled', _m('Enable Twitter import'),
+ (bool) $this->value('enabled', 'twitterimport'),
+ _m('Allow users to import their Twitter friends\' timelines')
+ );
+ $this->unli();
+
+ $this->out->elementEnd('ul');
+
+ $this->out->elementEnd('fieldset');
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->submit('submit', _('Save'), 'submit', null, _('Save Twitter settings'));
+ }
+}
diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php
index cabf69d7a..c93f6666b 100644
--- a/plugins/TwitterBridge/twitterauthorization.php
+++ b/plugins/TwitterBridge/twitterauthorization.php
@@ -47,7 +47,7 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php';
* @author Zach Copley <zach@status.net>
* @author Julien C <chaumond@gmail.com>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://laconi.ca/
+ * @link http://status.net/
*
*/
class TwitterauthorizationAction extends Action
diff --git a/plugins/TwitterBridge/twitteroauthclient.php b/plugins/TwitterBridge/twitteroauthclient.php
index ba45b533d..93f6aadd1 100644
--- a/plugins/TwitterBridge/twitteroauthclient.php
+++ b/plugins/TwitterBridge/twitteroauthclient.php
@@ -22,7 +22,7 @@
* @category Integration
* @package StatusNet
* @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
+ * @copyright 2009-2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
@@ -61,8 +61,23 @@ class TwitterOAuthClient extends OAuthClient
$consumer_key = common_config('twitter', 'consumer_key');
$consumer_secret = common_config('twitter', 'consumer_secret');
- parent::__construct($consumer_key, $consumer_secret,
- $oauth_token, $oauth_token_secret);
+ if (empty($consumer_key) && empty($consumer_secret)) {
+ $consumer_key = common_config(
+ 'twitter',
+ 'global_consumer_key'
+ );
+ $consumer_secret = common_config(
+ 'twitter',
+ 'global_consumer_secret'
+ );
+ }
+
+ parent::__construct(
+ $consumer_key,
+ $consumer_secret,
+ $oauth_token,
+ $oauth_token_secret
+ );
}
// XXX: the following two functions are to support the horrible hack