From f55ef878f603d81857509f42f50c1a28b1a8e1f2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 18 Feb 2010 01:47:44 +0000 Subject: [PATCH 01/74] Fix for cross site OMB posting problem --- lib/omb.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/omb.php b/lib/omb.php index 0f38a49369..17132a594f 100644 --- a/lib/omb.php +++ b/lib/omb.php @@ -29,11 +29,9 @@ require_once 'Auth/Yadis/Yadis.php'; function omb_oauth_consumer() { - static $con = null; - if (is_null($con)) { - $con = new OAuthConsumer(common_root_url(), ''); - } - return $con; + // Don't try to make this static. Leads to issues in + // multi-site setups - Z + return new OAuthConsumer(common_root_url(), ''); } function omb_oauth_server() From c30f95c55cb4fcdde53c0549335d29ed6849cf95 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 22 Jan 2010 10:12:26 -0500 Subject: [PATCH 02/74] Updated some references to the long gnone "isEnclosure" function to the new "getEnclosure" --- classes/File.php | 2 ++ lib/apiaction.php | 9 +++++---- lib/util.php | 15 ++++----------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/classes/File.php b/classes/File.php index 91b12d2e28..189e04ce02 100644 --- a/classes/File.php +++ b/classes/File.php @@ -279,6 +279,8 @@ class File extends Memcached_DataObject if($oembed->modified) $enclosure->modified=$oembed->modified; unset($oembed->size); } + } else { + return false; } } } diff --git a/lib/apiaction.php b/lib/apiaction.php index 8049c09016..f71432e032 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 ($attachment_enclosure) { $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/util.php b/lib/util.php index 439db581a5..add1b0ae67 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; } } } From 09705a1e989d202859d637f8a84383f365b7906a Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 22 Jan 2010 10:40:21 -0500 Subject: [PATCH 03/74] stupid mistake... let's not talk about this. --- lib/apiaction.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/apiaction.php b/lib/apiaction.php index f71432e032..eef0ba637d 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -292,7 +292,7 @@ class ApiAction extends Action foreach ($attachments as $attachment) { $enclosure_o=$attachment->getEnclosure(); - if ($attachment_enclosure) { + if ($enclosure_o) { $enclosure = array(); $enclosure['url'] = $enclosure_o->url; $enclosure['mimetype'] = $enclosure_o->mimetype; From 9f94d6defa0d2536cb1f20a4c1c44ff78fd3f039 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 2 Mar 2010 19:15:24 -0500 Subject: [PATCH 04/74] Changed the geo location cookie Expire to Session. --- js/util.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/util.js b/js/util.js index 949aec957d..d08c46fe64 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' } @@ -494,7 +494,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 +537,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: '/' }); }); } From 79ffebb51b1141791d5ee7478e3a7beaa9fe8faa Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 2 Mar 2010 16:30:09 -0800 Subject: [PATCH 05/74] OStatus: save file records for enclosures Also stripping id from foreign HTML messages (could interfere with UI) and disabled failing attachment popup for a.attachment links that don't have a proper id, so you can click through instead of getting an error. Issues: * any other links aren't marked and saved * inconsistent behavior between local and remote attachments (local displays in lightbox, remote doesn't) * if the enclosure'd object isn't referenced in the content, you won't be offered a link to it in our UI --- classes/File.php | 7 ++++++ classes/Notice.php | 28 +++++++++++++++++++-- js/util.js | 7 ++++-- lib/activity.php | 5 ++++ plugins/OStatus/classes/Ostatus_profile.php | 12 +++++++-- 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/classes/File.php b/classes/File.php index 189e04ce02..1b8ef1b3ee 100644 --- a/classes/File.php +++ b/classes/File.php @@ -286,5 +286,12 @@ class File extends Memcached_DataObject } 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 63dc968972..c1263c7821 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); diff --git a/js/util.js b/js/util.js index d08c46fe64..3efda0d7b9 100644 --- a/js/util.js +++ b/js/util.js @@ -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) { diff --git a/lib/activity.php b/lib/activity.php index b201532138..ce14fa2546 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -1044,6 +1044,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 into a magical activity @@ -1140,6 +1141,10 @@ class Activity $this->categories[] = new AtomCategory($catEl); } } + + foreach (ActivityUtils::getLinks($entry, 'enclosure') as $link) { + $this->enclosures[] = $link->getAttribute('href'); + } } /** diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index a33e95d932..059c19e7c2 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); } From ca21f1da8603be348c1a34a8bcc3e7610b9a395d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 2 Mar 2010 16:49:29 -0800 Subject: [PATCH 06/74] - Have Twitter bridge check for a global key and secret if it can't find one in the local config - Refuse to work at all if the consumer key and secret aren't set --- plugins/TwitterBridge/README | 17 +++- plugins/TwitterBridge/TwitterBridgePlugin.php | 98 +++++++++++++------ plugins/TwitterBridge/twitteroauthclient.php | 21 +++- 3 files changed, 101 insertions(+), 35 deletions(-) diff --git a/plugins/TwitterBridge/README b/plugins/TwitterBridge/README index 72278b32e6..5117cf69ac 100644 --- a/plugins/TwitterBridge/README +++ b/plugins/TwitterBridge/README @@ -20,7 +20,7 @@ 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. +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: @@ -42,11 +42,26 @@ To enable the plugin, add the following to your config.php: ) ); +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 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. +** For multi-site setups you can also set a global consumer key and 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 -------------------- diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php index 6ce69d5e2b..bc702e745b 100644 --- a/plugins/TwitterBridge/TwitterBridgePlugin.php +++ b/plugins/TwitterBridge/TwitterBridgePlugin.php @@ -79,6 +79,30 @@ class TwitterBridgePlugin extends Plugin } } + /** + * Check to see if there is a consumer key and secret defined + * for Twitter integration. + * + * @return boolean result + */ + + static function hasKeys() + { + $key = common_config('twitter', 'consumer_key'); + $secret = common_config('twitter', 'consumer_secret'); + + if (empty($key) && empty($secret)) { + $key = common_config('twitter', 'global_consumer_key'); + $secret = common_config('twitter', 'global_consumer_secret'); + } + + if (!empty($key) && !empty($secret)) { + return true; + } + + return false; + } + /** * Add Twitter-related paths to the router table * @@ -91,14 +115,22 @@ class TwitterBridgePlugin extends Plugin function onRouterInitialized($m) { - $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')); + 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') + ); + } } $m->connect('admin/twitter', array('action' => 'twitteradminpanel')); @@ -117,7 +149,7 @@ class TwitterBridgePlugin extends Plugin { $action_name = $action->trimmed('action'); - if (common_config('twitter', 'signin')) { + if (self::hasKeys() && common_config('twitter', 'signin')) { $action->menuItem( common_local_url('twitterlogin'), _m('Twitter'), @@ -138,15 +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; } @@ -188,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; } @@ -206,18 +239,19 @@ class TwitterBridgePlugin extends Plugin */ function onGetValidDaemons($daemons) { - array_push( - $daemons, - INSTALLDIR - . '/plugins/TwitterBridge/daemons/synctwitterfriends.php' - ); - - if (common_config('twitterimport', 'enabled')) { + if (self::hasKeys()) { array_push( $daemons, INSTALLDIR - . '/plugins/TwitterBridge/daemons/twitterstatusfetcher.php' + . '/plugins/TwitterBridge/daemons/synctwitterfriends.php' ); + if (common_config('twitterimport', 'enabled')) { + array_push( + $daemons, + INSTALLDIR + . '/plugins/TwitterBridge/daemons/twitterstatusfetcher.php' + ); + } } return true; @@ -232,7 +266,9 @@ class TwitterBridgePlugin extends Plugin */ function onEndInitializeQueueManager($manager) { - $manager->connect('twitter', 'TwitterQueueHandler'); + if (self::hasKeys()) { + $manager->connect('twitter', 'TwitterQueueHandler'); + } return true; } diff --git a/plugins/TwitterBridge/twitteroauthclient.php b/plugins/TwitterBridge/twitteroauthclient.php index ba45b533dc..93f6aadd1e 100644 --- a/plugins/TwitterBridge/twitteroauthclient.php +++ b/plugins/TwitterBridge/twitteroauthclient.php @@ -22,7 +22,7 @@ * @category Integration * @package StatusNet * @author Zach Copley - * @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 From 08422dfa17a5c52d51f21087be0f1d8d602ed0af Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 2 Mar 2010 16:53:37 -0800 Subject: [PATCH 07/74] Remove double word from Twitter bridge README --- plugins/TwitterBridge/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/TwitterBridge/README b/plugins/TwitterBridge/README index 5117cf69ac..d0d34b7ef2 100644 --- a/plugins/TwitterBridge/README +++ b/plugins/TwitterBridge/README @@ -55,7 +55,7 @@ unless you configure it with a consumer key and secret.) password under an older version of StatusNet, but all new Twitter bridge connections will use OAuth. -** For multi-site setups you can also set a global consumer key and and +** 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.: From 32c08f53de83cbc512b0e69fc0994601f67d9582 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 01:49:14 +0000 Subject: [PATCH 08/74] Show global key and secret, if defined, in Twitter bridge admin panel --- plugins/TwitterBridge/TwitterBridgePlugin.php | 16 +++---- plugins/TwitterBridge/twitteradminpanel.php | 43 +++++++++++++++++++ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php index bc702e745b..1a0a69682a 100644 --- a/plugins/TwitterBridge/TwitterBridgePlugin.php +++ b/plugins/TwitterBridge/TwitterBridgePlugin.php @@ -88,15 +88,15 @@ class TwitterBridgePlugin extends Plugin static function hasKeys() { - $key = common_config('twitter', 'consumer_key'); - $secret = common_config('twitter', 'consumer_secret'); + $ckey = common_config('twitter', 'consumer_key'); + $csecret = common_config('twitter', 'consumer_secret'); - if (empty($key) && empty($secret)) { - $key = common_config('twitter', 'global_consumer_key'); - $secret = common_config('twitter', 'global_consumer_secret'); + if (empty($ckey) && empty($csecret)) { + $ckey = common_config('twitter', 'global_consumer_key'); + $csecret = common_config('twitter', 'global_consumer_secret'); } - if (!empty($key) && !empty($secret)) { + if (!empty($ckey) && !empty($csecret)) { return true; } @@ -115,6 +115,8 @@ class TwitterBridgePlugin extends Plugin function onRouterInitialized($m) { + $m->connect('admin/twitter', array('action' => 'twitteradminpanel')); + if (self::hasKeys()) { $m->connect( 'twitter/authorization', @@ -133,8 +135,6 @@ class TwitterBridgePlugin extends Plugin } } - $m->connect('admin/twitter', array('action' => 'twitteradminpanel')); - return true; } diff --git a/plugins/TwitterBridge/twitteradminpanel.php b/plugins/TwitterBridge/twitteradminpanel.php index b22e6d99fe..0ed53bc05b 100644 --- a/plugins/TwitterBridge/twitteradminpanel.php +++ b/plugins/TwitterBridge/twitteradminpanel.php @@ -225,6 +225,49 @@ class TwitterAdminPanelForm extends AdminForm ); $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', From f7ba5566bc1e2bad262b948c92d8167e27e147bc Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 2 Mar 2010 18:27:37 -0800 Subject: [PATCH 09/74] Make Facebook plugin look for API key and secret before doing anything --- plugins/Facebook/FacebookPlugin.php | 161 +++++++++++++++++----------- 1 file changed, 99 insertions(+), 62 deletions(-) diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php index 014d0d1970..90ed7351f3 100644 --- a/plugins/Facebook/FacebookPlugin.php +++ b/plugins/Facebook/FacebookPlugin.php @@ -79,6 +79,25 @@ class FacebookPlugin extends Plugin } } + /** + * 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 * @@ -91,23 +110,26 @@ class FacebookPlugin extends Plugin function onStartInitializeRouter($m) { - - // Facebook App 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('admin/facebook', array('action' => 'facebookadminpanel')); - // Facebook Connect stuff + if (self::hasKeys()) { - $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 App 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')); + + // 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; } @@ -338,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 @@ -410,42 +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'; - } + $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'); + + } } } @@ -462,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; } @@ -483,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; } @@ -503,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; } @@ -562,7 +595,9 @@ class FacebookPlugin extends Plugin function onStartEnqueueNotice($notice, &$transports) { - array_push($transports, 'facebook'); + if (self::hasKeys()) { + array_push($transports, 'facebook'); + } return true; } @@ -575,7 +610,9 @@ class FacebookPlugin extends Plugin */ function onEndInitializeQueueManager($manager) { - $manager->connect('facebook', 'FacebookQueueHandler'); + if (self::hasKeys()) { + $manager->connect('facebook', 'FacebookQueueHandler'); + } return true; } From 1a4652b1ade6ea4de842835a7d2a011845a1cd62 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 10:32:54 -0500 Subject: [PATCH 10/74] Changed label text for remote subscription to something similar. Given that this button will be used within context of subscriptions, 'New' works along with the '+' icon. --- plugins/OStatus/OStatusPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index 7b6d22acf3..b5e6867c87 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -727,7 +727,7 @@ 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'); } From 06fb1124f5cd328bc0b3028a0cc0499b1c916653 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 11:14:39 -0500 Subject: [PATCH 11/74] Added event hooks for start and end of subscriptions mini list --- EVENTS.txt | 6 ++++++ lib/profileaction.php | 35 +++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/EVENTS.txt b/EVENTS.txt index bb4936b354..a40855134e 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -776,6 +776,12 @@ StartShowAllContent: before showing the all (you and friends) content 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/lib/profileaction.php b/lib/profileaction.php index 2d4d232655..2bda8b07c9 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'); } From ea10805e3f68f5781321e7c93144242478081a1f Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 11:22:21 -0500 Subject: [PATCH 12/74] Moved the remote subscription button to subscription mini list --- plugins/OStatus/OStatusPlugin.php | 2 +- plugins/OStatus/theme/base/css/ostatus.css | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index b5e6867c87..eb777c6b2f 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -711,7 +711,7 @@ class OStatusPlugin extends Plugin return true; } - function onStartShowAllContent($action) + function onEndShowSubscriptionsMiniList($action) { $this->showEntityRemoteSubscribe($action); diff --git a/plugins/OStatus/theme/base/css/ostatus.css b/plugins/OStatus/theme/base/css/ostatus.css index 13e30ef5df..40cdfcef13 100644 --- a/plugins/OStatus/theme/base/css/ostatus.css +++ b/plugins/OStatus/theme/base/css/ostatus.css @@ -41,8 +41,22 @@ min-width:96px; #entity_remote_subscribe { padding:0; float:right; +position:relative; } -#all #entity_remote_subscribe { -margin-top:-52px; +.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; } From b65ee23e8293c301f8b142320eabff6c4acdfcfe Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 12:01:38 -0500 Subject: [PATCH 13/74] Added event hooks for group subscribe --- EVENTS.txt | 8 ++++++++ actions/showgroup.php | 24 +++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/EVENTS.txt b/EVENTS.txt index a40855134e..2c3863f228 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.) diff --git a/actions/showgroup.php b/actions/showgroup.php index 4e1fcb6c7b..a1dc3865bd 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'); } From 11750e832f994013b2fbce860bd24d24f49a14db Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 12:02:10 -0500 Subject: [PATCH 14/74] Added remote join action for group profile --- plugins/OStatus/OStatusPlugin.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index eb777c6b2f..014fb0b380 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. * From ffa1931c9dafea385e8f30c53ea079e2425a0786 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 09:31:14 -0800 Subject: [PATCH 15/74] Avoid warning/notice spew in XRD parser. Not all DOM nodes are elements. --- plugins/OStatus/lib/xrd.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/OStatus/lib/xrd.php b/plugins/OStatus/lib/xrd.php index 85df26c54c..f00e1f8096 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; + } } } From 1e63fda6695c8ab06f2cd8181de26f03f7f7a5d4 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 09:32:25 -0800 Subject: [PATCH 16/74] Clean up OStatus mentions finding; separate regexes keeps the code paths a bit clearer. Also switched to hitting HTTP profile first; as the common case it'll be faster. --- plugins/OStatus/OStatusPlugin.php | 86 +++++++++++++++---------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index 7b6d22acf3..f435d6283f 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -233,70 +233,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; } From f3cea2430497e751bc7776fe3abf0603e2b55f8b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 09:36:26 -0800 Subject: [PATCH 17/74] Fix for hcard parsing: typo caused notice spew accessing unset array index --- plugins/OStatus/classes/Ostatus_profile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index 059c19e7c2..7ab031aa59 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -1500,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]; } From 15574c59def8160020d367bd441a55f2d0afe6b6 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 12:55:01 -0500 Subject: [PATCH 18/74] Added event hooks at the start and end of groups mini list --- EVENTS.txt | 6 ++++++ lib/profileaction.php | 37 +++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/EVENTS.txt b/EVENTS.txt index 2c3863f228..47c67512ac 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -790,6 +790,12 @@ StartShowSubscriptionsMiniList: at the start of subscriptions mini list EndShowSubscriptionsMiniList: at the end of subscriptions mini list - $action: the current action +StartShowGroupsMiniList: at the start of groups mini list +- $action: the current action + +EndShowGroupsMiniList: at the end of groups 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/lib/profileaction.php b/lib/profileaction.php index 2bda8b07c9..029c21845d 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -105,7 +105,6 @@ class ProfileAction extends OwnerDesignAction $this->elementStart('div', array('id' => 'entity_subscriptions', 'class' => 'section')); - if (Event::handle('StartShowSubscriptionsMiniList', array($this))) { $this->element('h2', null, _('Subscriptions')); @@ -229,27 +228,29 @@ class ProfileAction extends OwnerDesignAction $this->elementStart('div', array('id' => 'entity_groups', 'class' => 'section')); + if (Event::handle('StartShowGroupsMiniList', array($this))) { + $this->element('h2', null, _('Groups')); - $this->element('h2', null, _('Groups')); - - if ($groups) { - $gml = new GroupMiniList($groups, $this->user, $this); - $cnt = $gml->show(); - if ($cnt == 0) { - $this->element('p', null, _('(None)')); + if ($groups) { + $gml = new GroupMiniList($groups, $this->user, $this); + $cnt = $gml->show(); + if ($cnt == 0) { + $this->element('p', null, _('(None)')); + } } - } - if ($cnt > GROUPS_PER_MINILIST) { - $this->elementStart('p'); - $this->element('a', array('href' => common_local_url('usergroups', - array('nickname' => $this->profile->nickname)), - 'class' => 'more'), - _('All groups')); - $this->elementEnd('p'); - } + if ($cnt > GROUPS_PER_MINILIST) { + $this->elementStart('p'); + $this->element('a', array('href' => common_local_url('usergroups', + array('nickname' => $this->profile->nickname)), + 'class' => 'more'), + _('All groups')); + $this->elementEnd('p'); + } - $this->elementEnd('div'); + Event::handle('EndShowGroupsMiniList', array($this)); + } + $this->elementEnd('div'); } } From c8bdf3cacbff1e5ce92b4553480e44d9f0053158 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 12:56:19 -0500 Subject: [PATCH 19/74] Added group subscription button to groups mini list --- plugins/OStatus/OStatusPlugin.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index 014fb0b380..38f5e8d41a 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -738,6 +738,13 @@ class OStatusPlugin extends Plugin return true; } + function onEndShowGroupsMiniList($action) + { + $this->showEntityRemoteSubscribe($action); + + return true; + } + function showEntityRemoteSubscribe($action) { $user = common_current_user(); From 7d7847295afb6b801b1a904c257a7ac5531b806e Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 13:17:00 -0500 Subject: [PATCH 20/74] Using position relative only for the remote subscription in section --- plugins/OStatus/theme/base/css/ostatus.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/OStatus/theme/base/css/ostatus.css b/plugins/OStatus/theme/base/css/ostatus.css index 40cdfcef13..d1c60cc0d5 100644 --- a/plugins/OStatus/theme/base/css/ostatus.css +++ b/plugins/OStatus/theme/base/css/ostatus.css @@ -41,6 +41,9 @@ min-width:96px; #entity_remote_subscribe { padding:0; float:right; +} + +.section #entity_remote_subscribe { position:relative; } From 61ada4558d69901c71b6542c16d43b5ea75ea3b3 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 10:19:14 -0800 Subject: [PATCH 21/74] Fix for disappearing 'connect' menu if xmpp and sms are disabled. All 'connect' menu panels used to be optional, so Action tried to figure out what the first item on the 'connect' menu should be. This is no longer necessary because we have the non-optional OAuth client connections panel now, which is not optional and can't be turned off. --- lib/action.php | 13 ++----------- plugins/Facebook/FacebookPlugin.php | 10 ---------- plugins/MobileProfile/MobileProfilePlugin.php | 11 +---------- 3 files changed, 3 insertions(+), 31 deletions(-) diff --git a/lib/action.php b/lib/action.php index 0918c68582..816086d202 100644 --- a/lib/action.php +++ b/lib/action.php @@ -420,13 +420,6 @@ class Action extends HTMLOutputter // lawsuit function showPrimaryNav() { $user = common_current_user(); - $connect = ''; - if (common_config('xmpp', 'enabled')) { - $connect = 'imsettings'; - } else if (common_config('sms', 'enabled')) { - $connect = 'smssettings'; - } - $this->elementStart('dl', array('id' => 'site_nav_global_primary')); $this->element('dt', null, _('Primary site navigation')); $this->elementStart('dd'); @@ -437,10 +430,8 @@ class Action extends HTMLOutputter // lawsuit _('Home'), _('Personal profile and friends timeline'), false, 'nav_home'); $this->menuItem(common_local_url('profilesettings'), _('Account'), _('Change your email, avatar, password, profile'), false, 'nav_account'); - if ($connect) { - $this->menuItem(common_local_url($connect), - _('Connect'), _('Connect to services'), false, 'nav_connect'); - } + $this->menuItem(common_local_url('oauthconnectionssettings'), + _('Connect'), _('Connect to services'), false, 'nav_connect'); if ($user->hasRight(Right::CONFIGURESITE)) { $this->menuItem(common_local_url('siteadminpanel'), _('Admin'), _('Change site configuration'), false, 'nav_admin'); diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php index 90ed7351f3..65d4409b5e 100644 --- a/plugins/Facebook/FacebookPlugin.php +++ b/plugins/Facebook/FacebookPlugin.php @@ -436,16 +436,7 @@ class FacebookPlugin extends Plugin function onStartPrimaryNav($action) { if (self::hasKeys()) { - $user = common_current_user(); - - $connect = 'FBConnectSettings'; - if (common_config('xmpp', 'enabled')) { - $connect = 'imsettings'; - } else if (common_config('sms', 'enabled')) { - $connect = 'smssettings'; - } - if (!empty($user)) { $fbuid = $this->loggedIn(); @@ -472,7 +463,6 @@ class FacebookPlugin extends Plugin 'src' => $iconurl)); $action->elementEnd('li'); - } } } diff --git a/plugins/MobileProfile/MobileProfilePlugin.php b/plugins/MobileProfile/MobileProfilePlugin.php index f788639aed..0b37734b7d 100644 --- a/plugins/MobileProfile/MobileProfilePlugin.php +++ b/plugins/MobileProfile/MobileProfilePlugin.php @@ -307,23 +307,14 @@ class MobileProfilePlugin extends WAP20Plugin function _showPrimaryNav($action) { $user = common_current_user(); - $connect = ''; - if (common_config('xmpp', 'enabled')) { - $connect = 'imsettings'; - } else if (common_config('sms', 'enabled')) { - $connect = 'smssettings'; - } - $action->elementStart('ul', array('id' => 'site_nav_global_primary')); if ($user) { $action->menuItem(common_local_url('all', array('nickname' => $user->nickname)), _('Home')); $action->menuItem(common_local_url('profilesettings'), _('Account')); - if ($connect) { - $action->menuItem(common_local_url($connect), + $action->menuItem(common_local_url('oauthconnectionssettings'), _('Connect')); - } if ($user->hasRight(Right::CONFIGURESITE)) { $action->menuItem(common_local_url('siteadminpanel'), _('Admin'), _('Change site configuration'), false, 'nav_admin'); From 023b9bb00f096a532218b6689c1f035051653c8e Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 13:30:14 -0500 Subject: [PATCH 22/74] Renamed subscribe button from New to Remote since it only does remote subscriptions at the moment. --- plugins/OStatus/OStatusPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index 9d5613b200..e371f72f98 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -754,7 +754,7 @@ class OStatusPlugin extends Plugin 'class' => 'entity_subscribe')); $action->element('a', array('href' => common_local_url('ostatussub'), 'class' => 'entity_remote_subscribe') - , _m('New')); + , _m('Remote')); $action->elementEnd('p'); $action->elementEnd('div'); } From 3bb42d117027ebf610481ca3b0733854e0127e56 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 19:00:02 +0000 Subject: [PATCH 23/74] Use poster's subscribed groups to disambiguate group linking when a remote group and a local group exist with the same name. (If you're a member of two groups with the same name though, there's not a defined winner.) --- classes/Notice.php | 2 +- classes/Profile.php | 26 ++++++++++++++++++++++++++ classes/User.php | 24 ++---------------------- classes/User_group.php | 20 +++++++++++++++++--- lib/util.php | 2 +- 5 files changed, 47 insertions(+), 27 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index c1263c7821..97cb3b8fbe 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -877,7 +877,7 @@ class Notice extends Memcached_DataObject foreach (array_unique($match[1]) as $nickname) { /* XXX: remote groups. */ - $group = User_group::getForNickname($nickname); + $group = User_group::getForNickname($nickname, $profile); if (empty($group)) { continue; diff --git a/classes/Profile.php b/classes/Profile.php index 470ef33207..9c2fa7a0c5 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -282,6 +282,32 @@ class Profile extends Memcached_DataObject } } + function getGroups($offset=0, $limit=null) + { + $qry = + 'SELECT user_group.* ' . + 'FROM user_group JOIN group_member '. + 'ON user_group.id = group_member.group_id ' . + 'WHERE group_member.profile_id = %d ' . + 'ORDER BY group_member.created DESC '; + + if ($offset>0 && !is_null($limit)) { + if ($offset) { + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + } + } + + $groups = new User_group(); + + $cnt = $groups->query(sprintf($qry, $this->id)); + + return $groups; + } + function avatarUrl($size=AVATAR_PROFILE_SIZE) { $avatar = $this->getAvatar($size); diff --git a/classes/User.php b/classes/User.php index 57d76731b8..aa9fbf9483 100644 --- a/classes/User.php +++ b/classes/User.php @@ -612,28 +612,8 @@ class User extends Memcached_DataObject function getGroups($offset=0, $limit=null) { - $qry = - 'SELECT user_group.* ' . - 'FROM user_group JOIN group_member '. - 'ON user_group.id = group_member.group_id ' . - 'WHERE group_member.profile_id = %d ' . - 'ORDER BY group_member.created DESC '; - - if ($offset>0 && !is_null($limit)) { - if ($offset) { - if (common_config('db','type') == 'pgsql') { - $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; - } else { - $qry .= ' LIMIT ' . $offset . ', ' . $limit; - } - } - } - - $groups = new User_group(); - - $cnt = $groups->query(sprintf($qry, $this->id)); - - return $groups; + $profile = $this->getProfile(); + return $profile->getGroups($offset, $limit); } function getSubscriptions($offset=0, $limit=null) diff --git a/classes/User_group.php b/classes/User_group.php index 64fe024b34..1a5ddf2533 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -279,12 +279,26 @@ class User_group extends Memcached_DataObject return true; } - static function getForNickname($nickname) + static function getForNickname($nickname, $profile=null) { $nickname = common_canonical_nickname($nickname); - $group = User_group::staticGet('nickname', $nickname); + + // Are there any matching remote groups this profile's in? + if ($profile) { + $group = $profile->getGroups(); + while ($group->fetch()) { + if ($group->nickname == $nickname) { + // @fixme is this the best way? + return clone($group); + } + } + } + + // If not, check local groups. + + $group = Local_group::staticGet('nickname', $nickname); if (!empty($group)) { - return $group; + return User_group::staticGet('id', $group->group_id); } $alias = Group_alias::staticGet('alias', $nickname); if (!empty($alias)) { diff --git a/lib/util.php b/lib/util.php index add1b0ae67..46be920fa7 100644 --- a/lib/util.php +++ b/lib/util.php @@ -853,7 +853,7 @@ function common_valid_profile_tag($str) function common_group_link($sender_id, $nickname) { $sender = Profile::staticGet($sender_id); - $group = User_group::getForNickname($nickname); + $group = User_group::getForNickname($nickname, $sender); if ($sender && $group && $sender->isMember($group)) { $attrs = array('href' => $group->permalink(), 'class' => 'url'); From 33af29b47cb4009dc89b5431597bfda14dccfe65 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 19:22:22 +0000 Subject: [PATCH 24/74] Fix for 4113f2884113f288: show regular subscribe form for all non-OMB profiles. We can't initiate remote sub for an OMB from our end, so dropping there. --- lib/profilelist.php | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/profilelist.php b/lib/profilelist.php index 4f1e84a6af..d970e605ad 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -273,18 +273,12 @@ class ProfileListItem extends Widget $usf = new UnsubscribeForm($this->out, $this->profile); $usf->show(); } else { - $other = User::staticGet('id', $this->profile->id); - if (!empty($other)) { + // We can't initiate sub for a remote OMB profile. + $remote = Remote_profile::staticGet('id', $this->profile->id); + if (empty($remote)) { $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'); } From ccd0db1e0a928fe914c894966ecf2260964a68f0 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 3 Mar 2010 14:32:03 -0500 Subject: [PATCH 25/74] add remote subscribe button for not-logged-in users looking a profile list with local users in it --- plugins/OStatus/OStatusPlugin.php | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index e371f72f98..da7ca2fe2b 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -111,11 +111,11 @@ class OStatusPlugin extends Plugin $acct = 'acct:'. $action->profile->nickname .'@'. common_config('site', 'server'); $url = common_local_url('xrd'); $url.= '?uri='. $acct; - + header('Link: <'.$url.'>; rel="'. Discovery::LRDD_REL.'"; type="application/xrd+xml"'); } } - + /** * Set up a PuSH hub link to our internal link for canonical timeline * Atom feeds for users and groups. @@ -229,7 +229,6 @@ class OStatusPlugin extends Plugin return false; } - /** * Check if we've got remote replies to send via Salmon. * @@ -587,7 +586,6 @@ class OStatusPlugin extends Plugin // Drop the PuSH subscription if there are no other subscribers. $oprofile->garbageCollect(); - $member = Profile::staticGet($user->id); $act = new Activity(); @@ -806,4 +804,28 @@ class OStatusPlugin extends Plugin return true; } + + function onStartProfileListItemActionElements($item) + { + if (!common_logged_in()) { + + $profileUser = User::staticGet('id', $item->profile->id); + + if (!empty($profileUser)) { + + $output = $item->out; + + // Add an OStatus subscribe + $output->elementStart('li', 'entity_subscribe'); + $url = common_local_url('ostatusinit', + array('nickname' => $profileUser->nickname)); + $output->element('a', array('href' => $url, + 'class' => 'entity_remote_subscribe'), + _m('Subscribe')); + $output->elementEnd('li'); + } + } + + return true; + } } From c82efb7fd8ba28b854020821246878fc0a8cec2b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 3 Mar 2010 15:09:07 -0500 Subject: [PATCH 26/74] subscribers list wasn't firing correct events --- actions/subscribers.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/actions/subscribers.php b/actions/subscribers.php index cd3e2ee5be..4bced62840 100644 --- a/actions/subscribers.php +++ b/actions/subscribers.php @@ -143,9 +143,12 @@ class SubscribersListItem extends SubscriptionListItem function showActions() { $this->startActions(); - $this->showSubscribeButton(); - // Relevant code! - $this->showBlockForm(); + if (Event::handle('StartProfileListItemActionElements', array($this))) { + $this->showSubscribeButton(); + // Relevant code! + $this->showBlockForm(); + Event::handle('EndProfileListItemActionElements', array($this)); + } $this->endActions(); } From 2f167f2663b2731d9f5d21bb9893aebff4dcf6f0 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 12:10:21 -0800 Subject: [PATCH 27/74] Fix syntax errors --- actions/oauthconnectionssettings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/oauthconnectionssettings.php b/actions/oauthconnectionssettings.php index b1467f0d04..f125f4c631 100644 --- a/actions/oauthconnectionssettings.php +++ b/actions/oauthconnectionssettings.php @@ -99,7 +99,7 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction $application = $profile->getApplications($offset, $limit); - $cnt == 0; + $cnt = 0; if (!empty($application)) { $al = new ApplicationList($application, $user, $this, true); @@ -112,7 +112,7 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction $this->pagination($this->page > 1, $cnt > APPS_PER_PAGE, $this->page, 'connectionssettings', - array('nickname' => $this->user->nickname)); + array('nickname' => $user->nickname)); } /** From 0881eba80eabfea65919be2f3d65235ccd0b5eb6 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 12:08:07 -0800 Subject: [PATCH 28/74] Language setting fixes: - switch 'en_US' to 'en', fixes the "admin panel switches to Arabic" bug - tweak setting descriptions to clarify that most of the time we'll be using browser language - add a backend switch to disable language detection (should this be exposed to ui?) --- actions/siteadminpanel.php | 4 ++-- index.php | 1 + lib/default.php | 3 ++- lib/util.php | 12 +++++++----- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/actions/siteadminpanel.php b/actions/siteadminpanel.php index 8c8f8b3742..4b29819b71 100644 --- a/actions/siteadminpanel.php +++ b/actions/siteadminpanel.php @@ -277,8 +277,8 @@ class SiteAdminPanelForm extends AdminForm $this->unli(); $this->li(); - $this->out->dropdown('language', _('Language'), - get_nice_language_list(), _('Default site language'), + $this->out->dropdown('language', _('Default language'), + get_nice_language_list(), _('Site language when autodetection from browser settings is not available'), false, $this->value('language')); $this->unli(); diff --git a/index.php b/index.php index 06ff9900fd..a46bc084d5 100644 --- a/index.php +++ b/index.php @@ -253,6 +253,7 @@ function main() $user = common_current_user(); // initialize language env +common_log(LOG_DEBUG, "XXX: WAIII"); common_init_language(); diff --git a/lib/default.php b/lib/default.php index 7b50242ae2..b7216045ce 100644 --- a/lib/default.php +++ b/lib/default.php @@ -40,7 +40,8 @@ $default = 'logdebug' => false, 'fancy' => false, 'locale_path' => INSTALLDIR.'/locale', - 'language' => 'en_US', + 'language' => 'en', + 'langdetect' => true, 'languages' => get_all_languages(), 'email' => array_key_exists('SERVER_ADMIN', $_SERVER) ? $_SERVER['SERVER_ADMIN'] : null, diff --git a/lib/util.php b/lib/util.php index 46be920fa7..da2799d4f9 100644 --- a/lib/util.php +++ b/lib/util.php @@ -105,11 +105,13 @@ function common_language() // Otherwise, find the best match for the languages requested by the // user's browser... - $httplang = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : null; - if (!empty($httplang)) { - $language = client_prefered_language($httplang); - if ($language) - return $language; + if (common_config('site', 'langdetect')) { + $httplang = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : null; + if (!empty($httplang)) { + $language = client_prefered_language($httplang); + if ($language) + return $language; + } } // Finally, if none of the above worked, use the site's default... From c7d390e4949b28c28c95375bfe4523de05af7808 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 12:18:20 -0800 Subject: [PATCH 29/74] Add class="admin" to the content div of admin panels for styling --- lib/adminpanelaction.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/adminpanelaction.php b/lib/adminpanelaction.php index 536d97cdf5..9ea4fe2066 100644 --- a/lib/adminpanelaction.php +++ b/lib/adminpanelaction.php @@ -171,6 +171,24 @@ class AdminPanelAction extends Action $this->showForm(); } + /** + * Show content block. Overrided just to add a special class + * to the content div to allow styling. + * + * @return nothing + */ + function showContentBlock() + { + $this->elementStart('div', array('id' => 'content', 'class' => 'admin')); + $this->showPageTitle(); + $this->showPageNoticeBlock(); + $this->elementStart('div', array('id' => 'content_inner')); + // show the actual content (forms, lists, whatever) + $this->showContent(); + $this->elementEnd('div'); + $this->elementEnd('div'); + } + /** * show human-readable instructions for the page, or * a success/failure on save. From 2ce9ae004d1f15ea4181f9fa686a73817ee45474 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 15:29:51 -0500 Subject: [PATCH 30/74] Added event hooks for before and after user groups content --- EVENTS.txt | 6 ++++++ actions/usergroups.php | 28 ++++++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/EVENTS.txt b/EVENTS.txt index 47c67512ac..2da6f3da61 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -778,6 +778,12 @@ StartShowSubscriptionsContent: before showing the subscriptions content EndShowSubscriptionsContent: after showing the subscriptions content - $action: the current action +StartShowUserGroupsContent: before showing the user groups content +- $action: the current action + +EndShowUserGroupsContent: after showing the user groups content +- $action: the current action + StartShowAllContent: before showing the all (you and friends) content - $action: the current action diff --git a/actions/usergroups.php b/actions/usergroups.php index 97faabae65..29bda0a765 100644 --- a/actions/usergroups.php +++ b/actions/usergroups.php @@ -130,22 +130,26 @@ class UsergroupsAction extends OwnerDesignAction _('Search for more groups')); $this->elementEnd('p'); - $offset = ($this->page-1) * GROUPS_PER_PAGE; - $limit = GROUPS_PER_PAGE + 1; + if (Event::handle('StartShowUserGroupsContent', array($this))) { + $offset = ($this->page-1) * GROUPS_PER_PAGE; + $limit = GROUPS_PER_PAGE + 1; - $groups = $this->user->getGroups($offset, $limit); + $groups = $this->user->getGroups($offset, $limit); - if ($groups) { - $gl = new GroupList($groups, $this->user, $this); - $cnt = $gl->show(); - if (0 == $cnt) { - $this->showEmptyListMessage(); + if ($groups) { + $gl = new GroupList($groups, $this->user, $this); + $cnt = $gl->show(); + if (0 == $cnt) { + $this->showEmptyListMessage(); + } } - } - $this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE, - $this->page, 'usergroups', - array('nickname' => $this->user->nickname)); + $this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE, + $this->page, 'usergroups', + array('nickname' => $this->user->nickname)); + + Event::handle('EndShowUserGroupsContent', array($this)); + } } function showEmptyListMessage() From 3c55edde39086918eea8c1adba5d01a026e230a3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 15:30:43 -0500 Subject: [PATCH 31/74] Showing the remote subscribe button on the user groups page --- plugins/OStatus/OStatusPlugin.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index da7ca2fe2b..dc502e52c4 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -729,6 +729,13 @@ class OStatusPlugin extends Plugin return true; } + function onStartShowUserGroupsContent($action) + { + $this->showEntityRemoteSubscribe($action); + + return true; + } + function onEndShowSubscriptionsMiniList($action) { $this->showEntityRemoteSubscribe($action); From d3c1888256e32495cb0db9065ff7a03e105299a3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 15:31:16 -0500 Subject: [PATCH 32/74] Generalized style for remote subscription button --- plugins/OStatus/theme/base/css/ostatus.css | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/OStatus/theme/base/css/ostatus.css b/plugins/OStatus/theme/base/css/ostatus.css index d1c60cc0d5..3b8928a3a9 100644 --- a/plugins/OStatus/theme/base/css/ostatus.css +++ b/plugins/OStatus/theme/base/css/ostatus.css @@ -41,9 +41,6 @@ min-width:96px; #entity_remote_subscribe { padding:0; float:right; -} - -.section #entity_remote_subscribe { position:relative; } @@ -55,11 +52,10 @@ margin-bottom:0; border-color:#AAAAAA; } -.section #entity_remote_subscribe .dialogbox { +#entity_remote_subscribe .dialogbox { width:405px; } - .aside #entity_subscriptions .more { float:left; } From ef6bf8f331175374af6889df82927b3cf6757b8a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 15:42:34 -0500 Subject: [PATCH 33/74] Removed aside container from output for the admin panel sections --- lib/adminpanelaction.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/adminpanelaction.php b/lib/adminpanelaction.php index 9ea4fe2066..1d9c425635 100644 --- a/lib/adminpanelaction.php +++ b/lib/adminpanelaction.php @@ -189,6 +189,16 @@ class AdminPanelAction extends Action $this->elementEnd('div'); } + /** + * There is no data for aside, so, we don't output + * + * @return nothing + */ + function showAside() + { + + } + /** * show human-readable instructions for the page, or * a success/failure on save. From 5c70481d30a82c3f2fe91ef5b24be29b8464ae49 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 15:43:02 -0500 Subject: [PATCH 34/74] Using the full width for the content area for the admin section. It also makes the local navigation's tabs stay in context with the content --- theme/base/css/display.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index f32c57ea45..b8dd561ccc 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -452,6 +452,13 @@ width:100%; float:left; } +#content.admin { +width:95.5%; +} +#content.admin #content_inner { +width:66.3%; +} + #aside_primary { width:27.917%; min-height:259px; From 7e5bf39f768e3c97ddb5b82ad20a690b674f1f47 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 12:57:40 -0800 Subject: [PATCH 35/74] Avoid notice on local group creation when uri isn't passed in at create time (needs to be generated) --- classes/User_group.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/classes/User_group.php b/classes/User_group.php index 1a5ddf2533..0460c9870a 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -455,6 +455,11 @@ class User_group extends Memcached_DataObject $group = new User_group(); $group->query('BEGIN'); + + if (empty($uri)) { + // fill in later... + $uri = null; + } $group->nickname = $nickname; $group->fullname = $fullname; From c04c8ae59a7953a21cc464a49b657dfdc926e009 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 13:00:09 -0800 Subject: [PATCH 36/74] quick fix: skip notice from unused variable on group atom feed generation --- actions/apitimelinegroup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index d0af49844c..e30a08fb5d 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -140,7 +140,7 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction // @todo set all this Atom junk up inside the feed class - $atom->setId($id); + #$atom->setId($id); $atom->setTitle($title); $atom->setSubtitle($subtitle); $atom->setLogo($logo); From 339b0b0a4d506638b7b3457db295ab7969e2a9df Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 13:05:11 -0800 Subject: [PATCH 37/74] Don't expose global Twitter consumer key and secret, because that would be idiotic. --- plugins/TwitterBridge/twitteradminpanel.php | 40 ++------------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/plugins/TwitterBridge/twitteradminpanel.php b/plugins/TwitterBridge/twitteradminpanel.php index 0ed53bc05b..a78a92c667 100644 --- a/plugins/TwitterBridge/twitteradminpanel.php +++ b/plugins/TwitterBridge/twitteradminpanel.php @@ -225,46 +225,12 @@ class TwitterAdminPanelForm extends AdminForm ); $this->unli(); - $globalConsumerKey = common_config('twitter', 'global_consumer_key'); + $globalConsumerKey = common_config('twitter', 'global_consumer_key'); $globalConsumerSec = common_config('twitter', 'global_consumer_secret'); - if (!empty($globalConsumerKey)) { + if (!empty($globalConsumerKey) && !empty($globalConsumerSec)) { $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->out->element('p', 'form_guide', _('Note: a global consumer key and secret are set.')); $this->unli(); } From 6ff994b14c93c51f1af1a52d568ffb3391d9c6db Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 16:25:17 -0500 Subject: [PATCH 38/74] Fix to group join event position. --- actions/showgroup.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/actions/showgroup.php b/actions/showgroup.php index a1dc3865bd..5704b13d14 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -300,8 +300,8 @@ class ShowgroupAction extends GroupDesignAction $this->elementStart('div', 'entity_actions'); $this->element('h2', null, _('Group actions')); $this->elementStart('ul'); + $this->elementStart('li', 'entity_subscribe'); if (Event::handle('StartGroupSubscribe', array($this, $this->group))) { - $this->elementStart('li', 'entity_subscribe'); $cur = common_current_user(); if ($cur) { if ($cur->isMember($this->group)) { @@ -312,10 +312,9 @@ class ShowgroupAction extends GroupDesignAction $jf->show(); } } - $this->elementEnd('li'); Event::handle('EndGroupSubscribe', array($this, $this->group)); } - + $this->elementEnd('li'); $this->elementEnd('ul'); $this->elementEnd('div'); } From 219e15ac64b0ceefcd714af27b9bbb53123dbe71 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 16:26:02 -0500 Subject: [PATCH 39/74] Returning true instead for group remote subscription. If not logged in, it gives the chance to use the logged in join/leave instead. --- plugins/OStatus/OStatusPlugin.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index dc502e52c4..d28260a4aa 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -216,17 +216,14 @@ class OStatusPlugin extends Plugin 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; + return true; } /** From a42d1116db06539f2da4eb5332bbdbef5beda3fe Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 13:40:26 -0800 Subject: [PATCH 40/74] Separate the UI paths for ostatussub and ostatusgroup. They'll redirect to each other transparently if they find you've put a remote entity of the other type. --- plugins/OStatus/OStatusPlugin.php | 12 +- plugins/OStatus/actions/ostatusgroup.php | 181 +++++++++++++++++++++++ plugins/OStatus/actions/ostatussub.php | 134 +++++------------ 3 files changed, 224 insertions(+), 103 deletions(-) create mode 100644 plugins/OStatus/actions/ostatusgroup.php diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index dc502e52c4..b4b446a7fa 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -51,8 +51,8 @@ class OStatusPlugin extends Plugin array('action' => 'ostatusinit'), array('nickname' => '[A-Za-z0-9_-]+')); $m->connect('main/ostatussub', array('action' => 'ostatussub')); - $m->connect('main/ostatussub', - array('action' => 'ostatussub'), array('feed' => '[A-Za-z0-9\.\/\:]+')); + $m->connect('main/ostatusgroup', + array('action' => 'ostatusgroup')); // PuSH actions $m->connect('main/push/hub', array('action' => 'pushhub')); @@ -731,7 +731,7 @@ class OStatusPlugin extends Plugin function onStartShowUserGroupsContent($action) { - $this->showEntityRemoteSubscribe($action); + $this->showEntityRemoteSubscribe($action, 'ostatusgroup'); return true; } @@ -745,19 +745,19 @@ class OStatusPlugin extends Plugin function onEndShowGroupsMiniList($action) { - $this->showEntityRemoteSubscribe($action); + $this->showEntityRemoteSubscribe($action, 'ostatusgroup'); return true; } - function showEntityRemoteSubscribe($action) + function showEntityRemoteSubscribe($action, $target='ostatussub') { $user = common_current_user(); if ($user && ($user->id == $action->profile->id)) { $action->elementStart('div', 'entity_actions'); $action->elementStart('p', array('id' => 'entity_remote_subscribe', 'class' => 'entity_subscribe')); - $action->element('a', array('href' => common_local_url('ostatussub'), + $action->element('a', array('href' => common_local_url($target), 'class' => 'entity_remote_subscribe') , _m('Remote')); $action->elementEnd('p'); diff --git a/plugins/OStatus/actions/ostatusgroup.php b/plugins/OStatus/actions/ostatusgroup.php new file mode 100644 index 0000000000..4fcd0eb39a --- /dev/null +++ b/plugins/OStatus/actions/ostatusgroup.php @@ -0,0 +1,181 @@ +. + */ + +/** + * @package OStatusPlugin + * @maintainer Brion Vibber + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } + +/** + * Key UI methods: + * + * showInputForm() - form asking for a remote profile account or URL + * We end up back here on errors + * + * showPreviewForm() - surrounding form for preview-and-confirm + * preview() - display profile for a remote group + * + * success() - redirects to groups page on join + */ +class OStatusGroupAction extends OStatusSubAction +{ + protected $profile_uri; // provided acct: or URI of remote entity + protected $oprofile; // Ostatus_profile of remote entity, if valid + + + function validateRemoteProfile() + { + if (!$this->oprofile->isGroup()) { + // Send us to the user subscription form for conf + $target = common_local_url('ostatussub', array(), array('profile' => $this->profile_uri)); + common_redirect($target, 303); + } + } + + /** + * Show the initial form, when we haven't yet been given a valid + * remote profile. + */ + function showInputForm() + { + $user = common_current_user(); + + $profile = $user->getProfile(); + + $this->elementStart('form', array('method' => 'post', + 'id' => 'form_ostatus_sub', + 'class' => 'form_settings', + 'action' => $this->selfLink())); + + $this->hidden('token', common_session_token()); + + $this->elementStart('fieldset', array('id' => 'settings_feeds')); + + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->input('profile', + _m('Group profile URL'), + $this->profile_uri, + _m('Enter the profile URL of a group on another StatusNet site')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + + $this->submit('validate', _m('Continue')); + + $this->elementEnd('fieldset'); + + $this->elementEnd('form'); + } + + /** + * Show a preview for a remote group's profile + * @return boolean true if we're ok to try joining + */ + function preview() + { + $oprofile = $this->oprofile; + $group = $oprofile->localGroup(); + + $cur = common_current_user(); + if ($cur->isMember($group)) { + $this->element('div', array('class' => 'error'), + _m("You are already a member of this group.")); + $ok = false; + } else { + $ok = true; + } + + $this->showEntity($group, + $group->getProfileUrl(), + $group->homepage_logo, + $group->description); + return $ok; + } + + /** + * Redirect on successful remote group join + */ + function success() + { + $cur = common_current_user(); + $url = common_local_url('usergroups', array('nickname' => $cur->nickname)); + common_redirect($url, 303); + } + + /** + * Attempt to finalize subscription. + * validateFeed must have been run first. + * + * Calls showForm on failure or success on success. + */ + function saveFeed() + { + $user = common_current_user(); + $group = $this->oprofile->localGroup(); + if ($user->isMember($group)) { + // TRANS: OStatus remote group subscription dialog error. + $this->showForm(_m('Already a member!')); + return; + } + + if (Event::handle('StartJoinGroup', array($group, $user))) { + $ok = Group_member::join($this->oprofile->group_id, $user->id); + if ($ok) { + Event::handle('EndJoinGroup', array($group, $user)); + $this->success(); + } else { + // TRANS: OStatus remote group subscription dialog error. + $this->showForm(_m('Remote group join failed!')); + } + } else { + // TRANS: OStatus remote group subscription dialog error. + $this->showForm(_m('Remote group join aborted!')); + } + } + + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + // TRANS: Page title for OStatus remote group join form + return _m('Confirm joining remote group'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _m('You can subscribe to groups from other supported sites. Paste the group\'s profile URI below:'); + } + + function selfLink() + { + return common_local_url('ostatusgroup'); + } +} diff --git a/plugins/OStatus/actions/ostatussub.php b/plugins/OStatus/actions/ostatussub.php index e318701a24..542f7e20ca 100644 --- a/plugins/OStatus/actions/ostatussub.php +++ b/plugins/OStatus/actions/ostatussub.php @@ -1,7 +1,7 @@ elementStart('form', array('method' => 'post', 'id' => 'form_ostatus_sub', 'class' => 'form_settings', - 'action' => - common_local_url('ostatussub'))); + 'action' => $this->selfLink())); $this->hidden('token', common_session_token()); @@ -87,11 +84,7 @@ class OStatusSubAction extends Action */ function showPreviewForm() { - if ($this->oprofile->isGroup()) { - $ok = $this->previewGroup(); - } else { - $ok = $this->previewUser(); - } + $ok = $this->preview(); if (!$ok) { // @fixme maybe provide a cancel button or link back? return; @@ -104,7 +97,7 @@ class OStatusSubAction extends Action 'id' => 'form_ostatus_sub', 'class' => 'form_remote_authorize', 'action' => - common_local_url('ostatussub'))); + $this->selfLink())); $this->elementStart('fieldset'); $this->hidden('token', common_session_token()); $this->hidden('profile', $this->profile_uri); @@ -126,7 +119,7 @@ class OStatusSubAction extends Action * Show a preview for a remote user's profile * @return boolean true if we're ok to try subscribing */ - function previewUser() + function preview() { $oprofile = $this->oprofile; $profile = $oprofile->localProfile(); @@ -150,32 +143,6 @@ class OStatusSubAction extends Action return $ok; } - /** - * Show a preview for a remote group's profile - * @return boolean true if we're ok to try joining - */ - function previewGroup() - { - $oprofile = $this->oprofile; - $group = $oprofile->localGroup(); - - $cur = common_current_user(); - if ($cur->isMember($group)) { - $this->element('div', array('class' => 'error'), - _m("You are already a member of this group.")); - $ok = false; - } else { - $ok = true; - } - - $this->showEntity($group, - $group->getProfileUrl(), - $group->homepage_logo, - $group->description); - return $ok; - } - - function showEntity($entity, $profile, $avatar, $note) { $nickname = $entity->nickname; @@ -254,23 +221,13 @@ class OStatusSubAction extends Action /** * Redirect on successful remote user subscription */ - function successUser() + function success() { $cur = common_current_user(); $url = common_local_url('subscriptions', array('nickname' => $cur->nickname)); common_redirect($url, 303); } - /** - * Redirect on successful remote group join - */ - function successGroup() - { - $cur = common_current_user(); - $url = common_local_url('usergroups', array('nickname' => $cur->nickname)); - common_redirect($url, 303); - } - /** * Pull data for a remote profile and check if it's valid. * Fills out error UI string in $this->error @@ -278,16 +235,9 @@ class OStatusSubAction extends Action * * @return boolean */ - function validateFeed() + function pullRemoteProfile() { - $profile_uri = trim($this->arg('profile')); - - if ($profile_uri == '') { - $this->showForm(_m('Empty remote profile URL!')); - return; - } - $this->profile_uri = $profile_uri; - + $this->profile_uri = $this->trimmed('profile'); try { if (Validate::email($this->profile_uri)) { $this->oprofile = Ostatus_profile::ensureWebfinger($this->profile_uri); @@ -318,48 +268,34 @@ class OStatusSubAction extends Action return false; } + function validateRemoteProfile() + { + if ($this->oprofile->isGroup()) { + // Send us to the group subscription form for conf + $target = common_local_url('ostatusgroup', array(), array('profile' => $this->profile_uri)); + common_redirect($target, 303); + } + } + /** * Attempt to finalize subscription. * validateFeed must have been run first. * - * Calls showForm on failure or successUser/successGroup on success. + * Calls showForm on failure or success on success. */ function saveFeed() { // And subscribe the current user to the local profile $user = common_current_user(); - - if ($this->oprofile->isGroup()) { - $group = $this->oprofile->localGroup(); - if ($user->isMember($group)) { - // TRANS: OStatus remote group subscription dialog error. - $this->showForm(_m('Already a member!')); - return; - } - if (Event::handle('StartJoinGroup', array($group, $user))) { - $ok = Group_member::join($this->oprofile->group_id, $user->id); - if ($ok) { - Event::handle('EndJoinGroup', array($group, $user)); - $this->successGroup(); - } else { - // TRANS: OStatus remote group subscription dialog error. - $this->showForm(_m('Remote group join failed!')); - } - } else { - // TRANS: OStatus remote group subscription dialog error. - $this->showForm(_m('Remote group join aborted!')); - } + $local = $this->oprofile->localProfile(); + if ($user->isSubscribed($local)) { + // TRANS: OStatus remote subscription dialog error. + $this->showForm(_m('Already subscribed!')); + } elseif ($this->oprofile->subscribeLocalToRemote($user)) { + $this->success(); } else { - $local = $this->oprofile->localProfile(); - if ($user->isSubscribed($local)) { - // TRANS: OStatus remote subscription dialog error. - $this->showForm(_m('Already subscribed!')); - } elseif ($this->oprofile->subscribeLocalToRemote($user)) { - $this->successUser(); - } else { - // TRANS: OStatus remote subscription dialog error. - $this->showForm(_m('Remote subscription failed!')); - } + // TRANS: OStatus remote subscription dialog error. + $this->showForm(_m('Remote subscription failed!')); } } @@ -376,7 +312,9 @@ class OStatusSubAction extends Action return false; } - $this->profile_uri = $this->arg('profile'); + if ($this->pullRemoteProfile()) { + $this->validateRemoteProfile(); + } return true; } @@ -390,9 +328,6 @@ class OStatusSubAction extends Action if ($_SERVER['REQUEST_METHOD'] == 'POST') { $this->handlePost(); } else { - if ($this->arg('profile')) { - $this->validateFeed(); - } $this->showForm(); } } @@ -414,7 +349,7 @@ class OStatusSubAction extends Action return; } - if ($this->validateFeed()) { + if ($this->oprofile) { if ($this->arg('submit')) { $this->saveFeed(); return; @@ -500,4 +435,9 @@ class OStatusSubAction extends Action parent::showScripts(); $this->autofocus('feedurl'); } + + function selfLink() + { + return common_local_url('ostatussub'); + } } From 628338265c1607000eaffc42418c63092b019720 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 14:06:05 -0800 Subject: [PATCH 41/74] OStatus: fix up remote join button on group profiles --- plugins/OStatus/OStatusPlugin.php | 4 +- plugins/OStatus/actions/ostatusinit.php | 51 ++++++++++++++++++++----- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index ca6786a267..cc7e759764 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -49,6 +49,8 @@ class OStatusPlugin extends Plugin array('action' => 'ostatusinit')); $m->connect('main/ostatus?nickname=:nickname', array('action' => 'ostatusinit'), array('nickname' => '[A-Za-z0-9_-]+')); + $m->connect('main/ostatus?group=:group', + array('action' => 'ostatusinit'), array('group' => '[A-Za-z0-9_-]+')); $m->connect('main/ostatussub', array('action' => 'ostatussub')); $m->connect('main/ostatusgroup', @@ -217,7 +219,7 @@ class OStatusPlugin extends Plugin if (empty($cur)) { // Add an OStatus subscribe $url = common_local_url('ostatusinit', - array('nickname' => $group->nickname)); + array('group' => $group->nickname)); $output->element('a', array('href' => $url, 'class' => 'entity_remote_subscribe'), _m('Join')); diff --git a/plugins/OStatus/actions/ostatusinit.php b/plugins/OStatus/actions/ostatusinit.php index 8ba8dcdcc7..1e45025b09 100644 --- a/plugins/OStatus/actions/ostatusinit.php +++ b/plugins/OStatus/actions/ostatusinit.php @@ -29,6 +29,7 @@ class OStatusInitAction extends Action { var $nickname; + var $group; var $profile; var $err; @@ -41,8 +42,9 @@ class OStatusInitAction extends Action return false; } - // Local user the remote wants to subscribe to + // Local user or group the remote wants to subscribe to $this->nickname = $this->trimmed('nickname'); + $this->group = $this->trimmed('group'); // Webfinger or profile URL of the remote user $this->profile = $this->trimmed('profile'); @@ -89,25 +91,33 @@ class OStatusInitAction extends Action function showContent() { + if ($this->group) { + $header = sprintf(_m('Join group %s'), $this->group); + $submit = _m('Join'); + } else { + $header = sprintf(_m('Subscribe to %s'), $this->nickname); + $submit = _m('Subscribe'); + } $this->elementStart('form', array('id' => 'form_ostatus_connect', 'method' => 'post', 'class' => 'form_settings', 'action' => common_local_url('ostatusinit'))); $this->elementStart('fieldset'); - $this->element('legend', null, sprintf(_m('Subscribe to %s'), $this->nickname)); + $this->element('legend', null, $header); $this->hidden('token', common_session_token()); $this->elementStart('ul', 'form_data'); $this->elementStart('li', array('id' => 'ostatus_nickname')); $this->input('nickname', _m('User nickname'), $this->nickname, _m('Nickname of the user you want to follow')); + $this->hidden('group', $this->group); // pass-through for magic links $this->elementEnd('li'); $this->elementStart('li', array('id' => 'ostatus_profile')); $this->input('profile', _m('Profile Account'), $this->profile, _m('Your account id (i.e. user@identi.ca)')); $this->elementEnd('li'); $this->elementEnd('ul'); - $this->submit('submit', _m('Subscribe')); + $this->submit('submit', $submit); $this->elementEnd('fieldset'); $this->elementEnd('form'); } @@ -131,19 +141,17 @@ class OStatusInitAction extends Action function connectWebfinger($acct) { - $disco = new Discovery; + $target_profile = $this->targetProfile(); + $disco = new Discovery; $result = $disco->lookup($acct); if (!$result) { $this->clientError(_m("Couldn't look up OStatus account profile.")); } + foreach ($result->links as $link) { if ($link['rel'] == 'http://ostatus.org/schema/1.0/subscribe') { // We found a URL - let's redirect! - - $user = User::staticGet('nickname', $this->nickname); - $target_profile = common_local_url('userbyid', array('id' => $user->id)); - $url = Discovery::applyTemplate($link['template'], $target_profile); common_log(LOG_INFO, "Sending remote subscriber $acct to $url"); common_redirect($url, 303); @@ -155,8 +163,7 @@ class OStatusInitAction extends Action function connectProfile($subscriber_profile) { - $user = User::staticGet('nickname', $this->nickname); - $target_profile = common_local_url('userbyid', array('id' => $user->id)); + $target_profile = $this->targetProfile(); // @fixme hack hack! We should look up the remote sub URL from XRDS $suburl = preg_replace('!^(.*)/(.*?)$!', '$1/main/ostatussub', $subscriber_profile); @@ -166,6 +173,30 @@ class OStatusInitAction extends Action common_redirect($suburl, 303); } + /** + * Build the canonical profile URI+URL of the requested user or group + */ + function targetProfile() + { + if ($this->nickname) { + $user = User::staticGet('nickname', $this->nickname); + if ($user) { + return common_local_url('userbyid', array('id' => $user->id)); + } else { + $this->clientError("No such user."); + } + } else if ($this->group) { + $group = Local_group::staticGet('id', $this->group); + if ($group) { + return common_local_url('groupbyid', array('id' => $group->group_id)); + } else { + $this->clientError("No such group."); + } + } else { + $this->clientError("No local user or group nickname provided."); + } + } + function title() { return _m('OStatus Connect'); From 337b1aaaa16bde80b42a9902ebeb299f8f13a226 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 14:32:14 -0800 Subject: [PATCH 42/74] Site-wide notice text admin panel --- actions/sitenoticeadminpanel.php | 201 +++++++++++++++++++++++++++++++ lib/adminpanelaction.php | 15 ++- lib/default.php | 7 +- lib/router.php | 1 + 4 files changed, 216 insertions(+), 8 deletions(-) create mode 100644 actions/sitenoticeadminpanel.php diff --git a/actions/sitenoticeadminpanel.php b/actions/sitenoticeadminpanel.php new file mode 100644 index 0000000000..613a2e96be --- /dev/null +++ b/actions/sitenoticeadminpanel.php @@ -0,0 +1,201 @@ +. + * + * @category Settings + * @package StatusNet + * @author Zach Copley + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php'; + +/** + * Update the site-wide notice text + * + * @category Admin + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class SitenoticeadminpanelAction extends AdminPanelAction +{ + /** + * Returns the page title + * + * @return string page title + */ + + function title() + { + return _('Site Notice'); + } + + /** + * Instructions for using this form. + * + * @return string instructions + */ + + function getInstructions() + { + return _('Edit site-wide message'); + } + + /** + * Show the site notice admin panel form + * + * @return void + */ + + function showForm() + { + $form = new SiteNoticeAdminPanelForm($this); + $form->show(); + return; + } + + /** + * Save settings from the form + * + * @return void + */ + + function saveSettings() + { + $siteNotice = $this->trimmed('site-notice'); + + // assert(all values are valid); + // This throws an exception on validation errors + + $this->validate(&$siteNotice); + + $config = new Config(); + + $result = Config::save('site', 'notice', $siteNotice); + + if (!result) { + $this->ServerError(_("Unable to save site notice.")); + } + } + + function validate(&$siteNotice) + { + // Validate notice text + + if (mb_strlen($siteNotice) > 255) { + $this->clientError( + _('Max length for the site-wide notice is 255 chars') + ); + } + + // scrub HTML input + + $config = array( + 'safe' => 1, + 'deny_attribute' => 'id,style,on*' + ); + + $siteNotice = htmLawed($siteNotice, $config); + } +} + +class SiteNoticeAdminPanelForm extends AdminForm +{ + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + return 'form_site_notice_admin_panel'; + } + + /** + * 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('sitenoticeadminpanel'); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->elementStart('ul', 'form_data'); + + $this->out->elementStart('li'); + $this->out->textarea( + 'site-notice', + _('Site notice text'), + common_config('site', 'notice'), + _('Site-wide notice text (255 chars max; HTML okay)') + ); + $this->out->elementEnd('li'); + + $this->out->elementEnd('ul'); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit( + 'submit', + _('Save'), + 'submit', + null, + _('Save site notice') + ); + } +} diff --git a/lib/adminpanelaction.php b/lib/adminpanelaction.php index 1d9c425635..eb622871e7 100644 --- a/lib/adminpanelaction.php +++ b/lib/adminpanelaction.php @@ -173,7 +173,7 @@ class AdminPanelAction extends Action /** * Show content block. Overrided just to add a special class - * to the content div to allow styling. + * to the content div to allow styling. * * @return nothing */ @@ -358,22 +358,27 @@ class AdminPanelNav extends Widget if (AdminPanelAction::canAdmin('user')) { $this->out->menuItem(common_local_url('useradminpanel'), _('User'), - _('User configuration'), $action_name == 'useradminpanel', 'nav_design_admin_panel'); + _('User configuration'), $action_name == 'useradminpanel', 'nav_user_admin_panel'); } if (AdminPanelAction::canAdmin('access')) { $this->out->menuItem(common_local_url('accessadminpanel'), _('Access'), - _('Access configuration'), $action_name == 'accessadminpanel', 'nav_design_admin_panel'); + _('Access configuration'), $action_name == 'accessadminpanel', 'nav_access_admin_panel'); } if (AdminPanelAction::canAdmin('paths')) { $this->out->menuItem(common_local_url('pathsadminpanel'), _('Paths'), - _('Paths configuration'), $action_name == 'pathsadminpanel', 'nav_design_admin_panel'); + _('Paths configuration'), $action_name == 'pathsadminpanel', 'nav_paths_admin_panel'); } if (AdminPanelAction::canAdmin('sessions')) { $this->out->menuItem(common_local_url('sessionsadminpanel'), _('Sessions'), - _('Sessions configuration'), $action_name == 'sessionsadminpanel', 'nav_design_admin_panel'); + _('Sessions configuration'), $action_name == 'sessionsadminpanel', 'nav_sessions_admin_panel'); + } + + if (AdminPanelAction::canAdmin('sitenotice')) { + $this->out->menuItem(common_local_url('sitenoticeadminpanel'), _('Site notice'), + _('Edit site notice'), $action_name == 'sitenoticeadminpanel', 'nav_sitenotice_admin_panel'); } Event::handle('EndAdminPanelNav', array($this)); diff --git a/lib/default.php b/lib/default.php index b7216045ce..8e99a0e1c3 100644 --- a/lib/default.php +++ b/lib/default.php @@ -54,10 +54,11 @@ $default = 'ssl' => 'never', 'sslserver' => null, 'shorturllength' => 30, - 'dupelimit' => 60, # default for same person saying the same thing + 'dupelimit' => 60, // default for same person saying the same thing 'textlimit' => 140, 'indent' => true, - 'use_x_sendfile' => false + 'use_x_sendfile' => false, + 'notice' => null // site wide notice text ), 'db' => array('database' => 'YOU HAVE TO SET THIS IN config.php', @@ -283,7 +284,7 @@ $default = 'OpenID' => null), ), 'admin' => - array('panels' => array('design', 'site', 'user', 'paths', 'access', 'sessions')), + array('panels' => array('design', 'site', 'user', 'paths', 'access', 'sessions', 'sitenotice')), 'singleuser' => array('enabled' => false, 'nickname' => null), diff --git a/lib/router.php b/lib/router.php index abbce041db..7e8e22a7db 100644 --- a/lib/router.php +++ b/lib/router.php @@ -649,6 +649,7 @@ class Router $m->connect('admin/access', array('action' => 'accessadminpanel')); $m->connect('admin/paths', array('action' => 'pathsadminpanel')); $m->connect('admin/sessions', array('action' => 'sessionsadminpanel')); + $m->connect('admin/sitenotice', array('action' => 'sitenoticeadminpanel')); $m->connect('getfile/:filename', array('action' => 'getfile'), From b3969be85ae37b2b3e8abfce2c545866dd910af7 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 17:48:00 -0500 Subject: [PATCH 43/74] Updated remote subscribe button style in aside --- plugins/OStatus/theme/base/css/ostatus.css | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/plugins/OStatus/theme/base/css/ostatus.css b/plugins/OStatus/theme/base/css/ostatus.css index 3b8928a3a9..ac668623d8 100644 --- a/plugins/OStatus/theme/base/css/ostatus.css +++ b/plugins/OStatus/theme/base/css/ostatus.css @@ -48,10 +48,6 @@ position:relative; margin-bottom:0; } -.section #entity_remote_subscribe .entity_remote_subscribe { -border-color:#AAAAAA; -} - #entity_remote_subscribe .dialogbox { width:405px; } @@ -59,3 +55,19 @@ width:405px; .aside #entity_subscriptions .more { float:left; } + +.section #entity_remote_subscribe { +border:0; +} + +.section .entity_remote_subscribe { +color:#002FA7; +box-shadow:none; +-moz-box-shadow:none; +-webkit-box-shadow:none; +background-color:transparent; +background-position:0 -1183px; +padding:0 0 0 23px; +border:0; + +} From 06db00d303bda500eec578b490c12d2bf389c853 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 15:15:46 -0800 Subject: [PATCH 44/74] remove debug line --- index.php | 1 - 1 file changed, 1 deletion(-) diff --git a/index.php b/index.php index a46bc084d5..06ff9900fd 100644 --- a/index.php +++ b/index.php @@ -253,7 +253,6 @@ function main() $user = common_current_user(); // initialize language env -common_log(LOG_DEBUG, "XXX: WAIII"); common_init_language(); From 4103e8584c7ccfb444af0814345104afedd2c6fc Mon Sep 17 00:00:00 2001 From: James Walker Date: Wed, 3 Mar 2010 18:16:56 -0500 Subject: [PATCH 45/74] Making one time passwords work on private sites --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 06ff9900fd..36ba3a0d21 100644 --- a/index.php +++ b/index.php @@ -185,7 +185,7 @@ function checkMirror($action_obj, $args) function isLoginAction($action) { - static $loginActions = array('login', 'recoverpassword', 'api', 'doc', 'register', 'publicxrds'); + static $loginActions = array('login', 'recoverpassword', 'api', 'doc', 'register', 'publicxrds', 'otp'); $login = null; From 4a2511139eaafcbe93a2e720e0c6f170ecb00d77 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 15:43:49 -0800 Subject: [PATCH 46/74] Initial user role controls on profile pages, for owner to add/remove administrator and moderator options. Buttons need to be themed. --- actions/grantrole.php | 99 ++++++++++++++++++++++++++++++++++++++++ actions/revokerole.php | 99 ++++++++++++++++++++++++++++++++++++++++ classes/Profile.php | 4 ++ classes/Profile_role.php | 17 +++++++ lib/grantroleform.php | 93 +++++++++++++++++++++++++++++++++++++ lib/revokeroleform.php | 93 +++++++++++++++++++++++++++++++++++++ lib/right.php | 2 + lib/router.php | 1 + lib/userprofile.php | 26 +++++++++++ 9 files changed, 434 insertions(+) create mode 100644 actions/grantrole.php create mode 100644 actions/revokerole.php create mode 100644 lib/grantroleform.php create mode 100644 lib/revokeroleform.php diff --git a/actions/grantrole.php b/actions/grantrole.php new file mode 100644 index 0000000000..cd6bd4d79a --- /dev/null +++ b/actions/grantrole.php @@ -0,0 +1,99 @@ +. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 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); +} + +/** + * Sandbox a user. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class GrantRoleAction extends ProfileFormAction +{ + /** + * Check parameters + * + * @param array $args action arguments (URL, GET, POST) + * + * @return boolean success flag + */ + + function prepare($args) + { + if (!parent::prepare($args)) { + return false; + } + + $this->role = $this->arg('role'); + if (!Profile_role::isValid($this->role)) { + $this->clientError(_("Invalid role.")); + return false; + } + if (!Profile_role::isSettable($this->role)) { + $this->clientError(_("This role is reserved and cannot be set.")); + return false; + } + + $cur = common_current_user(); + + assert(!empty($cur)); // checked by parent + + if (!$cur->hasRight(Right::GRANTROLE)) { + $this->clientError(_("You cannot grant user roles on this site.")); + return false; + } + + assert(!empty($this->profile)); // checked by parent + + if ($this->profile->hasRole($this->role)) { + $this->clientError(_("User already has this role.")); + return false; + } + + return true; + } + + /** + * Sandbox a user. + * + * @return void + */ + + function handlePost() + { + $this->profile->grantRole($this->role); + } +} diff --git a/actions/revokerole.php b/actions/revokerole.php new file mode 100644 index 0000000000..b78c1c25a4 --- /dev/null +++ b/actions/revokerole.php @@ -0,0 +1,99 @@ +. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 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); +} + +/** + * Sandbox a user. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class RevokeRoleAction extends ProfileFormAction +{ + /** + * Check parameters + * + * @param array $args action arguments (URL, GET, POST) + * + * @return boolean success flag + */ + + function prepare($args) + { + if (!parent::prepare($args)) { + return false; + } + + $this->role = $this->arg('role'); + if (!Profile_role::isValid($this->role)) { + $this->clientError(_("Invalid role.")); + return false; + } + if (!Profile_role::isSettable($this->role)) { + $this->clientError(_("This role is reserved and cannot be set.")); + return false; + } + + $cur = common_current_user(); + + assert(!empty($cur)); // checked by parent + + if (!$cur->hasRight(Right::REVOKEROLE)) { + $this->clientError(_("You cannot revoke user roles on this site.")); + return false; + } + + assert(!empty($this->profile)); // checked by parent + + if (!$this->profile->hasRole($this->role)) { + $this->clientError(_("User doesn't have this role.")); + return false; + } + + return true; + } + + /** + * Sandbox a user. + * + * @return void + */ + + function handlePost() + { + $this->profile->revokeRole($this->role); + } +} diff --git a/classes/Profile.php b/classes/Profile.php index 9c2fa7a0c5..0322c93588 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -743,6 +743,10 @@ class Profile extends Memcached_DataObject case Right::CONFIGURESITE: $result = $this->hasRole(Profile_role::ADMINISTRATOR); break; + case Right::GRANTROLE: + case Right::REVOKEROLE: + $result = $this->hasRole(Profile_role::OWNER); + break; case Right::NEWNOTICE: case Right::NEWMESSAGE: case Right::SUBSCRIBE: diff --git a/classes/Profile_role.php b/classes/Profile_role.php index bf2c453ed0..d0a0b31f0f 100644 --- a/classes/Profile_role.php +++ b/classes/Profile_role.php @@ -53,4 +53,21 @@ class Profile_role extends Memcached_DataObject const ADMINISTRATOR = 'administrator'; const SANDBOXED = 'sandboxed'; const SILENCED = 'silenced'; + + public static function isValid($role) + { + // @fixme could probably pull this from class constants + $known = array(self::OWNER, + self::MODERATOR, + self::ADMINISTRATOR, + self::SANDBOXED, + self::SILENCED); + return in_array($role, $known); + } + + public static function isSettable($role) + { + $allowedRoles = array('administrator', 'moderator'); + return self::isValid($role) && in_array($role, $allowedRoles); + } } diff --git a/lib/grantroleform.php b/lib/grantroleform.php new file mode 100644 index 0000000000..b5f952746e --- /dev/null +++ b/lib/grantroleform.php @@ -0,0 +1,93 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou , Brion Vibber + * @copyright 2009-2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Form for sandboxing a user + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see UnSandboxForm + */ + +class GrantRoleForm extends ProfileActionForm +{ + function __construct($role, $label, $writer, $profile, $r2args) + { + parent::__construct($writer, $profile, $r2args); + $this->role = $role; + $this->label = $label; + } + + /** + * Action this form provides + * + * @return string Name of the action, lowercased. + */ + + function target() + { + return 'grantrole'; + } + + /** + * Title of the form + * + * @return string Title of the form, internationalized + */ + + function title() + { + return $this->label; + } + + function formData() + { + parent::formData(); + $this->out->hidden('role', $this->role); + } + + /** + * Description of the form + * + * @return string description of the form, internationalized + */ + + function description() + { + return sprintf(_('Grant this user the "%s" role'), $this->label); + } +} diff --git a/lib/revokeroleform.php b/lib/revokeroleform.php new file mode 100644 index 0000000000..ec24b99101 --- /dev/null +++ b/lib/revokeroleform.php @@ -0,0 +1,93 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou , Brion Vibber + * @copyright 2009-2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Form for sandboxing a user + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see UnSandboxForm + */ + +class RevokeRoleForm extends ProfileActionForm +{ + function __construct($role, $label, $writer, $profile, $r2args) + { + parent::__construct($writer, $profile, $r2args); + $this->role = $role; + $this->label = $label; + } + + /** + * Action this form provides + * + * @return string Name of the action, lowercased. + */ + + function target() + { + return 'revokerole'; + } + + /** + * Title of the form + * + * @return string Title of the form, internationalized + */ + + function title() + { + return $this->label; + } + + function formData() + { + parent::formData(); + $this->out->hidden('role', $this->role); + } + + /** + * Description of the form + * + * @return string description of the form, internationalized + */ + + function description() + { + return sprintf(_('Revoke the "%s" role from this user'), $this->label); + } +} diff --git a/lib/right.php b/lib/right.php index 4e9c5a918d..deb451fde9 100644 --- a/lib/right.php +++ b/lib/right.php @@ -58,5 +58,7 @@ class Right const EMAILONSUBSCRIBE = 'emailonsubscribe'; const EMAILONFAVE = 'emailonfave'; const MAKEGROUPADMIN = 'makegroupadmin'; + const GRANTROLE = 'grantrole'; + const REVOKEROLE = 'revokerole'; } diff --git a/lib/router.php b/lib/router.php index 7e8e22a7db..15f88c959d 100644 --- a/lib/router.php +++ b/lib/router.php @@ -98,6 +98,7 @@ class Router 'groupblock', 'groupunblock', 'sandbox', 'unsandbox', 'silence', 'unsilence', + 'grantrole', 'revokerole', 'repeat', 'deleteuser', 'geocode', diff --git a/lib/userprofile.php b/lib/userprofile.php index 43dfd05be5..8464c24464 100644 --- a/lib/userprofile.php +++ b/lib/userprofile.php @@ -346,6 +346,16 @@ class UserProfile extends Widget $this->out->elementEnd('ul'); $this->out->elementEnd('li'); } + + if ($cur->hasRight(Right::GRANTROLE)) { + $this->out->elementStart('li', 'entity_role'); + $this->out->element('p', null, _('User role')); + $this->out->elementStart('ul'); + $this->roleButton('administrator', _m('role', 'Administrator')); + $this->roleButton('moderator', _m('role', 'Moderator')); + $this->out->elementEnd('ul'); + $this->out->elementEnd('li'); + } } } @@ -359,6 +369,22 @@ class UserProfile extends Widget } } + function roleButton($role, $label) + { + list($action, $r2args) = $this->out->returnToArgs(); + $r2args['action'] = $action; + + $this->out->elementStart('li', "entity_role_$role"); + if ($this->user->hasRole($role)) { + $rf = new RevokeRoleForm($role, $label, $this->out, $this->profile, $r2args); + $rf->show(); + } else { + $rf = new GrantRoleForm($role, $label, $this->out, $this->profile, $r2args); + $rf->show(); + } + $this->out->elementEnd('li'); + } + function showRemoteSubscribeLink() { $url = common_local_url('remotesubscribe', From 610238442e211940716c83126526a42079007fea Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 19:24:18 -0500 Subject: [PATCH 47/74] Added styles for User Role --- theme/base/css/display.css | 15 ++++++++------ theme/base/images/icons/icons-01.gif | Bin 3740 -> 3788 bytes .../images/icons/twotone/green/clipboard.gif | Bin 0 -> 80 bytes theme/default/css/display.css | 19 +++++++++++++++++- 4 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 theme/base/images/icons/twotone/green/clipboard.gif diff --git a/theme/base/css/display.css b/theme/base/css/display.css index b8dd561ccc..01d5dd134d 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -771,10 +771,12 @@ display:none; text-align:center; } -.entity_moderation { +.entity_moderation, +.entity_role { position:relative; } -.entity_moderation p { +.entity_moderation p, +.entity_role p { border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; @@ -782,13 +784,14 @@ font-weight:bold; padding-bottom:2px; margin-bottom:7px; } -.entity_moderation ul { +.entity_moderation ul, +.entity_role ul { display:none; } -.entity_moderation:hover ul { +.entity_moderation:hover ul, +.entity_role:hover ul { display:block; -min-width:21%; -width:100%; +width:110%; padding:11px; position:absolute; top:-1px; diff --git a/theme/base/images/icons/icons-01.gif b/theme/base/images/icons/icons-01.gif index be884ff48944d2ec4694f426ada7644b0aa0e101..deba4970ded5878546d57a08bd48bfd4c926b290 100644 GIT binary patch delta 107 zcmV-x0F?in9n2jJM@dFFIbj+AmjJ4cqs-P6s&GEs^ljPv=wjXeLDg#Z8lulSRNk&EF!gAM}_0Hrp|GXLOWY?&;^ N*TCi;&&bGN4FFdt5x@Wd diff --git a/theme/base/images/icons/twotone/green/clipboard.gif b/theme/base/images/icons/twotone/green/clipboard.gif new file mode 100644 index 0000000000000000000000000000000000000000..9317bdcd083856423ed6cc5b1c3f377f12ff14f6 GIT binary patch literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%P+`a gc){}R;x2QZs@NHpDL?1V&f26IdDKXlo0Y*D0L~K_-T(jq literal 0 HcmV?d00001 diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 8ae2b40141..8ca267c338 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -49,6 +49,7 @@ box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3); .pagination .nav_next a, .form_settings fieldset fieldset, .entity_moderation:hover ul, +.entity_role:hover ul, .dialogbox { border-color:#DDDDDD; } @@ -67,6 +68,7 @@ input.submit, .entity_actions a, .entity_actions input, .entity_moderation p, +.entity_role p, button { box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); -moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); @@ -127,7 +129,8 @@ a, .notice-options input, .entity_actions a, .entity_actions input, -.entity_moderation p { +.entity_moderation p, +.entity_role p { color:#002FA7; } @@ -190,6 +193,9 @@ button.close, .entity_sandbox input.submit, .entity_silence input.submit, .entity_delete input.submit, +.entity_role p, +.entity_role_administrator input.submit, +.entity_role_moderator input.submit, .notice-options .repeated, .form_notice label[for=notice_data-geo], button.minimize, @@ -229,6 +235,7 @@ border-color:transparent; #site_nav_local_views .current a, .entity_send-a-message .form_notice, .entity_moderation:hover ul, +.entity_role:hover ul, .dialogbox { background-color:#FFFFFF; } @@ -319,6 +326,7 @@ background-position: 5px -852px; } .entity_send-a-message .form_notice, .entity_moderation:hover ul, +.entity_role:hover ul, .dialogbox { box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7); -moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7); @@ -350,6 +358,15 @@ background-position: 5px -1445px; .entity_delete input.submit { background-position: 5px -1511px; } +.entity_role p { +background-position: 5px -2436px; +} +.entity_role_administrator input.submit { +background-position: 5px -983px; +} +.entity_role_moderator input.submit { +background-position: 5px -1313px; +} .form_reset_key input.submit { background-position: 5px -1973px; } From 6ebc0f87231de8f6c4acd28ecbddca227e4b3007 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 19:28:54 -0500 Subject: [PATCH 48/74] Updated identica theme for User Role styles --- theme/identica/css/display.css | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 737e3a1032..bc27cfb4d0 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -49,6 +49,7 @@ box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3); .pagination .nav_next a, .form_settings fieldset fieldset, .entity_moderation:hover ul, +.entity_role:hover ul, .dialogbox { border-color:#DDDDDD; } @@ -67,6 +68,7 @@ input.submit, .entity_actions a, .entity_actions input, .entity_moderation p, +.entity_role p, button { box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); -moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3); @@ -128,7 +130,8 @@ a, .notice-options input, .entity_actions a, .entity_actions input, -.entity_moderation p { +.entity_moderation p, +.entity_role p { color:#002FA7; } @@ -191,6 +194,9 @@ button.close, .entity_sandbox input.submit, .entity_silence input.submit, .entity_delete input.submit, +.entity_role p, +.entity_role_administrator input.submit, +.entity_role_moderator input.submit, .notice-options .repeated, .form_notice label[for=notice_data-geo], button.minimize, @@ -230,6 +236,7 @@ border-color:transparent; #site_nav_local_views .current a, .entity_send-a-message .form_notice, .entity_moderation:hover ul, +.entity_role:hover ul, .dialogbox { background-color:#FFFFFF; } @@ -319,6 +326,7 @@ background-position: 5px -852px; } .entity_send-a-message .form_notice, .entity_moderation:hover ul, +.entity_role:hover ul, .dialogbox { box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7); -moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7); @@ -350,6 +358,15 @@ background-position: 5px -1445px; .entity_delete input.submit { background-position: 5px -1511px; } +.entity_role p { +background-position: 5px -2436px; +} +.entity_role_administrator input.submit { +background-position: 5px -983px; +} +.entity_role_moderator input.submit { +background-position: 5px -1313px; +} .form_reset_key input.submit { background-position: 5px -1973px; } From 04e474c98c9b907fe2d0f263fad79018a15c0783 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 19:29:59 -0500 Subject: [PATCH 49/74] Updated icons README --- theme/base/images/icons/README | 1 + 1 file changed, 1 insertion(+) diff --git a/theme/base/images/icons/README b/theme/base/images/icons/README index ea582149f5..0451fda494 100644 --- a/theme/base/images/icons/README +++ b/theme/base/images/icons/README @@ -25,6 +25,7 @@ White reject with green background White play with green background White pause with green background + White clipboard with green background */ From 9fadf8da1164d620284917b829329e195aa2a226 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 12:51:23 -0800 Subject: [PATCH 50/74] Put all required field setup into AtomUserNoticeFeed and AtomGroupNoticeFeed, consolidating some code. (RSS feeds pulling title, logo etc from the Atom data structure so we don't dupe it.) OStatus now calling the feed classes directly instead of faking a call into the API, should be less flakey. --- actions/apitimelinegroup.php | 45 ++++-------------- actions/apitimelineuser.php | 51 ++++----------------- lib/atom10feed.php | 20 ++++++-- lib/atomgroupnoticefeed.php | 32 ++++++++++++- lib/atomusernoticefeed.php | 41 ++++++++++++++++- plugins/OStatus/lib/ostatusqueuehandler.php | 39 +++------------- 6 files changed, 113 insertions(+), 115 deletions(-) diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index e30a08fb5d..8f971392bf 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -104,30 +104,21 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction function showTimeline() { - $sitename = common_config('site', 'name'); - $avatar = $this->group->homepage_logo; - $title = sprintf(_("%s timeline"), $this->group->nickname); - - $subtitle = sprintf( - _('Updates from %1$s on %2$s!'), - $this->group->nickname, - $sitename - ); - - $logo = ($avatar) ? $avatar : User_group::defaultLogo(AVATAR_PROFILE_SIZE); + // We'll pull common formatting out of this for other formats + $atom = new AtomGroupNoticeFeed($this->group); switch($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': - $this->showRssTimeline( + $this->showRssTimeline( $this->notices, - $title, + $atom->title, $this->group->homeUrl(), - $subtitle, + $atom->subtitle, null, - $logo + $atom->logo ); break; case 'atom': @@ -136,38 +127,22 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction try { - $atom = new AtomGroupNoticeFeed($this->group); - - // @todo set all this Atom junk up inside the feed class - - #$atom->setId($id); - $atom->setTitle($title); - $atom->setSubtitle($subtitle); - $atom->setLogo($logo); - $atom->setUpdated('now'); - $atom->addAuthorRaw($this->group->asAtomAuthor()); $atom->setActivitySubject($this->group->asActivitySubject()); - $atom->addLink($this->group->homeUrl()); - $id = $this->arg('id'); $aargs = array('format' => 'atom'); if (!empty($id)) { $aargs['id'] = $id; } + $self = $this->getSelfUri('ApiTimelineGroup', $aargs); - $atom->setId($this->getSelfUri('ApiTimelineGroup', $aargs)); - - $atom->addLink( - $this->getSelfUri('ApiTimelineGroup', $aargs), - array('rel' => 'self', 'type' => 'application/atom+xml') - ); + $atom->setId($self); + $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); - //$this->raw($atom->getString()); - print $atom->getString(); // temp hack until PuSH feeds are redone cleanly + $this->raw($atom->getString()); } catch (Atom10FeedException $e) { $this->serverError( diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index 94491946c2..2d0047c046 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -112,19 +112,17 @@ class ApiTimelineUserAction extends ApiBareAuthAction function showTimeline() { $profile = $this->user->getProfile(); - $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); - $sitename = common_config('site', 'name'); - $title = sprintf(_("%s timeline"), $this->user->nickname); + // We'll use the shared params from the Atom stub + // for other feed types. + $atom = new AtomUserNoticeFeed($this->user); + $title = $atom->title; $link = common_local_url( 'showstream', array('nickname' => $this->user->nickname) ); - $subtitle = sprintf( - _('Updates from %1$s on %2$s!'), - $this->user->nickname, $sitename - ); - $logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); + $subtitle = $atom->subtitle; + $logo = $atom->logo; // FriendFeed's SUP protocol // Also added RSS and Atom feeds @@ -146,47 +144,18 @@ class ApiTimelineUserAction extends ApiBareAuthAction header('Content-Type: application/atom+xml; charset=utf-8'); - // @todo set all this Atom junk up inside the feed class - - $atom = new AtomUserNoticeFeed($this->user); - - $atom->setTitle($title); - $atom->setSubtitle($subtitle); - $atom->setLogo($logo); - $atom->setUpdated('now'); - - $atom->addLink( - common_local_url( - 'showstream', - array('nickname' => $this->user->nickname) - ) - ); - $id = $this->arg('id'); $aargs = array('format' => 'atom'); if (!empty($id)) { $aargs['id'] = $id; } - - $atom->setId($this->getSelfUri('ApiTimelineUser', $aargs)); - - $atom->addLink( - $this->getSelfUri('ApiTimelineUser', $aargs), - array('rel' => 'self', 'type' => 'application/atom+xml') - ); - - $atom->addLink( - $suplink, - array( - 'rel' => 'http://api.friendfeed.com/2008/03#sup', - 'type' => 'application/json' - ) - ); + $self = $this->getSelfUri('ApiTimelineUser', $aargs); + $atom->setId($self); + $atom->setSelfLink($self); $atom->addEntryFromNotices($this->notices); - #$this->raw($atom->getString()); - print $atom->getString(); // temporary for output buffering + $this->raw($atom->getString()); break; case 'json': diff --git a/lib/atom10feed.php b/lib/atom10feed.php index 8842840d56..c1fdeaae93 100644 --- a/lib/atom10feed.php +++ b/lib/atom10feed.php @@ -49,6 +49,8 @@ class Atom10FeedException extends Exception class Atom10Feed extends XMLStringer { public $xw; + + // @fixme most of these should probably be read-only properties private $namespaces; private $authors; private $subject; @@ -57,10 +59,12 @@ class Atom10Feed extends XMLStringer private $generator; private $icon; private $links; - private $logo; + private $selfLink; + private $selfLinkType; + public $logo; private $rights; - private $subtitle; - private $title; + public $subtitle; + public $title; private $published; private $updated; private $entries; @@ -184,6 +188,10 @@ class Atom10Feed extends XMLStringer $this->renderAuthors(); + if ($this->selfLink) { + $this->addLink($this->selfLink, array('rel' => 'self', + 'type' => $this->selfLinkType)); + } $this->renderLinks(); } @@ -253,6 +261,12 @@ class Atom10Feed extends XMLStringer $this->id = $id; } + function setSelfLink($url, $type='application/atom+xml') + { + $this->selfLink = $url; + $this->selfLinkType = $type; + } + function setTitle($title) { $this->title = $title; diff --git a/lib/atomgroupnoticefeed.php b/lib/atomgroupnoticefeed.php index 52ee4c7d6e..08c1c707c5 100644 --- a/lib/atomgroupnoticefeed.php +++ b/lib/atomgroupnoticefeed.php @@ -49,14 +49,42 @@ class AtomGroupNoticeFeed extends AtomNoticeFeed /** * Constructor * - * @param Group $group the group for the feed (optional) + * @param Group $group the group for the feed * @param boolean $indent flag to turn indenting on or off * * @return void */ - function __construct($group = null, $indent = true) { + function __construct($group, $indent = true) { parent::__construct($indent); $this->group = $group; + + $title = sprintf(_("%s timeline"), $group->nickname); + $this->setTitle($title); + + $sitename = common_config('site', 'name'); + $subtitle = sprintf( + _('Updates from %1$s on %2$s!'), + $group->nickname, + $sitename + ); + $this->setSubtitle($subtitle); + + $avatar = $group->homepage_logo; + $logo = ($avatar) ? $avatar : User_group::defaultLogo(AVATAR_PROFILE_SIZE); + $this->setLogo($logo); + + $this->setUpdated('now'); + + $self = common_local_url('ApiTimelineGroup', + array('id' => $group->id, + 'format' => 'atom')); + $this->setId($self); + $this->setSelfLink($self); + + $this->addAuthorRaw($group->asAtomAuthor()); + $this->setActivitySubject($group->asActivitySubject()); + + $this->addLink($group->homeUrl()); } function getGroup() diff --git a/lib/atomusernoticefeed.php b/lib/atomusernoticefeed.php index 2ad8de4550..55cebef6df 100644 --- a/lib/atomusernoticefeed.php +++ b/lib/atomusernoticefeed.php @@ -49,19 +49,56 @@ class AtomUserNoticeFeed extends AtomNoticeFeed /** * Constructor * - * @param User $user the user for the feed (optional) + * @param User $user the user for the feed * @param boolean $indent flag to turn indenting on or off * * @return void */ - function __construct($user = null, $indent = true) { + function __construct($user, $indent = true) { parent::__construct($indent); $this->user = $user; if (!empty($user)) { $profile = $user->getProfile(); $this->addAuthor($profile->nickname, $user->uri); } + + $title = sprintf(_("%s timeline"), $user->nickname); + $this->setTitle($title); + + $sitename = common_config('site', 'name'); + $subtitle = sprintf( + _('Updates from %1$s on %2$s!'), + $user->nickname, $sitename + ); + $this->setSubtitle($subtitle); + + $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); + $logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); + $this->setLogo($logo); + + $this->setUpdated('now'); + + $this->addLink( + common_local_url( + 'showstream', + array('nickname' => $user->nickname) + ) + ); + + $self = common_local_url('ApiTimelineUser', + array('id' => $user->id, + 'format' => 'atom')); + $this->setId($self); + $this->setSelfLink($self); + + $this->addLink( + common_local_url('sup', null, null, $user->id), + array( + 'rel' => 'http://api.friendfeed.com/2008/03#sup', + 'type' => 'application/json' + ) + ); } function getUser() diff --git a/plugins/OStatus/lib/ostatusqueuehandler.php b/plugins/OStatus/lib/ostatusqueuehandler.php index 6ca31c485c..d1e58f1d68 100644 --- a/plugins/OStatus/lib/ostatusqueuehandler.php +++ b/plugins/OStatus/lib/ostatusqueuehandler.php @@ -164,46 +164,21 @@ class OStatusQueueHandler extends QueueHandler */ function userFeedForNotice() { - // @fixme this feels VERY hacky... - // should probably be a cleaner way to do it + $atom = new AtomUserNoticeFeed($this->user); + $atom->addEntryFromNotice($this->notice); + $feed = $atom->getString(); - ob_start(); - $api = new ApiTimelineUserAction(); - $api->prepare(array('id' => $this->notice->profile_id, - 'format' => 'atom', - 'max_id' => $this->notice->id, - 'since_id' => $this->notice->id - 1)); - $api->showTimeline(); - $feed = ob_get_clean(); - - // ...and override the content-type back to something normal... eww! - // hope there's no other headers that got set while we weren't looking. - header('Content-Type: text/html; charset=utf-8'); - - common_log(LOG_DEBUG, $feed); return $feed; } function groupFeedForNotice($group_id) { - // @fixme this feels VERY hacky... - // should probably be a cleaner way to do it + $group = User_group::staticGet('id', $group_id); - ob_start(); - $api = new ApiTimelineGroupAction(); - $args = array('id' => $group_id, - 'format' => 'atom', - 'max_id' => $this->notice->id, - 'since_id' => $this->notice->id - 1); - $api->prepare($args); - $api->handle($args); - $feed = ob_get_clean(); - - // ...and override the content-type back to something normal... eww! - // hope there's no other headers that got set while we weren't looking. - header('Content-Type: text/html; charset=utf-8'); + $atom = new AtomGroupNoticeFeed($group); + $atom->addEntryFromNotice($this->notice); + $feed = $atom->getString(); - common_log(LOG_DEBUG, $feed); return $feed; } From 8436306d2872db2d1a50fdaef3cc1f2c8fb0d114 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 16:38:51 -0800 Subject: [PATCH 51/74] Fix notice warning in RSS friends timeline --- actions/allrss.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/allrss.php b/actions/allrss.php index 28b1be27d8..01e737ad7b 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -83,6 +83,7 @@ class AllrssAction extends Rss10Action function getNotices($limit=0) { $cur = common_current_user(); + $user = $this->user; if (!empty($cur) && $cur->id == $user->id) { $notice = $this->user->noticeInbox(0, $limit); @@ -90,7 +91,6 @@ class AllrssAction extends Rss10Action $notice = $this->user->noticesWithFriends(0, $limit); } - $user = $this->user; $notice = $user->noticesWithFriends(0, $limit); $notices = array(); From 61de37ec7bfb620288d3bc3b1fcdfb66725f0f99 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 16:47:27 -0800 Subject: [PATCH 52/74] Move snapshot configuration to its own admin panel Turn on with: $config['admin']['panels'][] = 'snapshot'; --- actions/siteadminpanel.php | 56 +------- actions/snapshotadminpanel.php | 251 +++++++++++++++++++++++++++++++++ lib/adminpanelaction.php | 5 + lib/router.php | 1 + 4 files changed, 263 insertions(+), 50 deletions(-) create mode 100644 actions/snapshotadminpanel.php diff --git a/actions/siteadminpanel.php b/actions/siteadminpanel.php index 4b29819b71..cb3c2e8fde 100644 --- a/actions/siteadminpanel.php +++ b/actions/siteadminpanel.php @@ -66,7 +66,7 @@ class SiteadminpanelAction extends AdminPanelAction function getInstructions() { - return _('Basic settings for this StatusNet site.'); + return _('Basic settings for this StatusNet site'); } /** @@ -90,10 +90,11 @@ class SiteadminpanelAction extends AdminPanelAction function saveSettings() { - static $settings = array('site' => array('name', 'broughtby', 'broughtbyurl', - 'email', 'timezone', 'language', - 'site', 'textlimit', 'dupelimit'), - 'snapshot' => array('run', 'reporturl', 'frequency')); + static $settings = array( + 'site' => array('name', 'broughtby', 'broughtbyurl', + 'email', 'timezone', 'language', + 'site', 'textlimit', 'dupelimit'), + ); $values = array(); @@ -158,25 +159,6 @@ class SiteadminpanelAction extends AdminPanelAction $this->clientError(sprintf(_('Unknown language "%s".'), $values['site']['language'])); } - // Validate report URL - - if (!is_null($values['snapshot']['reporturl']) && - !Validate::uri($values['snapshot']['reporturl'], array('allowed_schemes' => array('http', 'https')))) { - $this->clientError(_("Invalid snapshot report URL.")); - } - - // Validate snapshot run value - - if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) { - $this->clientError(_("Invalid snapshot run value.")); - } - - // Validate snapshot run value - - if (!Validate::number($values['snapshot']['frequency'])) { - $this->clientError(_("Snapshot frequency must be a number.")); - } - // Validate text limit if (!Validate::number($values['site']['textlimit'], array('min' => 140))) { @@ -285,32 +267,6 @@ class SiteAdminPanelForm extends AdminForm $this->out->elementEnd('ul'); $this->out->elementEnd('fieldset'); - $this->out->elementStart('fieldset', array('id' => 'settings_admin_snapshots')); - $this->out->element('legend', null, _('Snapshots')); - $this->out->elementStart('ul', 'form_data'); - $this->li(); - $snapshot = array('web' => _('Randomly during Web hit'), - 'cron' => _('In a scheduled job'), - 'never' => _('Never')); - $this->out->dropdown('run', _('Data snapshots'), - $snapshot, _('When to send statistical data to status.net servers'), - false, $this->value('run', 'snapshot')); - $this->unli(); - - $this->li(); - $this->input('frequency', _('Frequency'), - _('Snapshots will be sent once every N web hits'), - 'snapshot'); - $this->unli(); - - $this->li(); - $this->input('reporturl', _('Report URL'), - _('Snapshots will be sent to this URL'), - 'snapshot'); - $this->unli(); - $this->out->elementEnd('ul'); - $this->out->elementEnd('fieldset'); - $this->out->elementStart('fieldset', array('id' => 'settings_admin_limits')); $this->out->element('legend', null, _('Limits')); $this->out->elementStart('ul', 'form_data'); diff --git a/actions/snapshotadminpanel.php b/actions/snapshotadminpanel.php new file mode 100644 index 0000000000..a0c2315bc1 --- /dev/null +++ b/actions/snapshotadminpanel.php @@ -0,0 +1,251 @@ +. + * + * @category Settings + * @package StatusNet + * @author Zach Copley + * @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); +} + +/** + * Manage snapshots + * + * @category Admin + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class SnapshotadminpanelAction extends AdminPanelAction +{ + /** + * Returns the page title + * + * @return string page title + */ + + function title() + { + return _('Snapshots'); + } + + /** + * Instructions for using this form. + * + * @return string instructions + */ + + function getInstructions() + { + return _('Manage snapshot configuration'); + } + + /** + * Show the snapshots admin panel form + * + * @return void + */ + + function showForm() + { + $form = new SnapshotAdminPanelForm($this); + $form->show(); + return; + } + + /** + * Save settings from the form + * + * @return void + */ + + function saveSettings() + { + static $settings = array( + 'snapshot' => array('run', 'reporturl', 'frequency') + ); + + $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 snapshot run value + + if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) { + $this->clientError(_("Invalid snapshot run value.")); + } + + // Validate snapshot frequency value + + if (!Validate::number($values['snapshot']['frequency'])) { + $this->clientError(_("Snapshot frequency must be a number.")); + } + + // Validate report URL + + if (!is_null($values['snapshot']['reporturl']) + && !Validate::uri( + $values['snapshot']['reporturl'], + array('allowed_schemes' => array('http', 'https') + ) + )) { + $this->clientError(_("Invalid snapshot report URL.")); + } + } +} + +class SnapshotAdminPanelForm extends AdminForm +{ + /** + * ID of the form + * + * @return int ID of the form + */ + + function id() + { + return 'form_snapshot_admin_panel'; + } + + /** + * 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('snapshotadminpanel'); + } + + /** + * Data elements of the form + * + * @return void + */ + + function formData() + { + $this->out->elementStart( + 'fieldset', + array('id' => 'settings_admin_snapshots') + ); + $this->out->element('legend', null, _('Snapshots')); + $this->out->elementStart('ul', 'form_data'); + $this->li(); + $snapshot = array( + 'web' => _('Randomly during Web hit'), + 'cron' => _('In a scheduled job'), + 'never' => _('Never') + ); + $this->out->dropdown( + 'run', + _('Data snapshots'), + $snapshot, + _('When to send statistical data to status.net servers'), + false, + $this->value('run', 'snapshot') + ); + $this->unli(); + + $this->li(); + $this->input( + 'frequency', + _('Frequency'), + _('Snapshots will be sent once every N web hits'), + 'snapshot' + ); + $this->unli(); + + $this->li(); + $this->input( + 'reporturl', + _('Report URL'), + _('Snapshots will be sent to this URL'), + 'snapshot' + ); + $this->unli(); + $this->out->elementEnd('ul'); + $this->out->elementEnd('fieldset'); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit( + 'submit', + _('Save'), + 'submit', + null, + _('Save snapshot settings') + ); + } +} diff --git a/lib/adminpanelaction.php b/lib/adminpanelaction.php index eb622871e7..d1aab3dfcb 100644 --- a/lib/adminpanelaction.php +++ b/lib/adminpanelaction.php @@ -381,6 +381,11 @@ class AdminPanelNav extends Widget _('Edit site notice'), $action_name == 'sitenoticeadminpanel', 'nav_sitenotice_admin_panel'); } + if (AdminPanelAction::canAdmin('snapshot')) { + $this->out->menuItem(common_local_url('snapshotadminpanel'), _('Snapshots'), + _('Snapshots configuration'), $action_name == 'snapshotadminpanel', 'nav_snapshot_admin_panel'); + } + Event::handle('EndAdminPanelNav', array($this)); } $this->action->elementEnd('ul'); diff --git a/lib/router.php b/lib/router.php index 15f88c959d..706120e0bf 100644 --- a/lib/router.php +++ b/lib/router.php @@ -651,6 +651,7 @@ class Router $m->connect('admin/paths', array('action' => 'pathsadminpanel')); $m->connect('admin/sessions', array('action' => 'sessionsadminpanel')); $m->connect('admin/sitenotice', array('action' => 'sitenoticeadminpanel')); + $m->connect('admin/snapshot', array('action' => 'snapshotadminpanel')); $m->connect('getfile/:filename', array('action' => 'getfile'), From a26d23b39515e42a2f5437203d90d583d9a1be89 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 19:51:41 -0500 Subject: [PATCH 53/74] Changed clipboard icon to magic wand for user role button --- theme/base/images/icons/README | 2 +- theme/base/images/icons/icons-01.gif | Bin 3788 -> 3792 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/images/icons/README b/theme/base/images/icons/README index 0451fda494..2e17826029 100644 --- a/theme/base/images/icons/README +++ b/theme/base/images/icons/README @@ -25,7 +25,6 @@ White reject with green background White play with green background White pause with green background - White clipboard with green background */ @@ -46,6 +45,7 @@ White pin with green background White underscore with green background White C with green background + White magic wand with green background */ Created by various authors diff --git a/theme/base/images/icons/icons-01.gif b/theme/base/images/icons/icons-01.gif index deba4970ded5878546d57a08bd48bfd4c926b290..210c44511d9ca31b2b359df4b8b8a60ca9f71100 100644 GIT binary patch delta 86 zcmV-c0IC1X9nc*NM@dFFIbj+Am9kr>I3Uu2WIm5&`&fob`YmKP8JJ356SKL7v# delta 82 zcmV-Y0ImPf9n2jJM@dFFIbj+Am45{OgO{n4^oW@<$(5U_nMTQ(APJgi*^ZD{asdGVJC^kxga7~l From 1761b185bfc275157906c086b20fb469edc37987 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 19:53:09 -0500 Subject: [PATCH 54/74] Removed clipboard icon from core --- .../base/images/icons/twotone/green/clipboard.gif | Bin 80 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 theme/base/images/icons/twotone/green/clipboard.gif diff --git a/theme/base/images/icons/twotone/green/clipboard.gif b/theme/base/images/icons/twotone/green/clipboard.gif deleted file mode 100644 index 9317bdcd083856423ed6cc5b1c3f377f12ff14f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%P+`a gc){}R;x2QZs@NHpDL?1V&f26IdDKXlo0Y*D0L~K_-T(jq From 6a5a629afac881fdc8369dfef2924f7f62949fab Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 20:08:55 -0500 Subject: [PATCH 55/74] Updated label and note text for user and group remote subscribe forms --- plugins/OStatus/actions/ostatusgroup.php | 4 ++-- plugins/OStatus/actions/ostatussub.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/OStatus/actions/ostatusgroup.php b/plugins/OStatus/actions/ostatusgroup.php index 4fcd0eb39a..f325ba0532 100644 --- a/plugins/OStatus/actions/ostatusgroup.php +++ b/plugins/OStatus/actions/ostatusgroup.php @@ -72,9 +72,9 @@ class OStatusGroupAction extends OStatusSubAction $this->elementStart('ul', 'form_data'); $this->elementStart('li'); $this->input('profile', - _m('Group profile URL'), + _m('Join group'), $this->profile_uri, - _m('Enter the profile URL of a group on another StatusNet site')); + _m("OStatus group's address, like http://example.net/group/nickname")); $this->elementEnd('li'); $this->elementEnd('ul'); diff --git a/plugins/OStatus/actions/ostatussub.php b/plugins/OStatus/actions/ostatussub.php index 542f7e20ca..7ca8a7869a 100644 --- a/plugins/OStatus/actions/ostatussub.php +++ b/plugins/OStatus/actions/ostatussub.php @@ -62,9 +62,9 @@ class OStatusSubAction extends Action $this->elementStart('ul', 'form_data'); $this->elementStart('li'); $this->input('profile', - _m('Address or profile URL'), + _m('Subscribe to'), $this->profile_uri, - _m('Enter the profile URL of a PubSubHubbub-enabled feed')); + _m("OStatus user's address, like nickname@example.com or http://example.net/user/nickname")); $this->elementEnd('li'); $this->elementEnd('ul'); From a4d9171306a06983094fdc90dbf040335c4f803f Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 18:23:28 -0800 Subject: [PATCH 56/74] Fix up catching of webfinger setup fails --- plugins/OStatus/actions/ostatussub.php | 3 +-- plugins/OStatus/classes/Ostatus_profile.php | 13 ++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/plugins/OStatus/actions/ostatussub.php b/plugins/OStatus/actions/ostatussub.php index 7ca8a7869a..e8a2c78ae0 100644 --- a/plugins/OStatus/actions/ostatussub.php +++ b/plugins/OStatus/actions/ostatussub.php @@ -260,7 +260,7 @@ class OStatusSubAction extends Action $this->error = _m('Could not find a feed linked from this URL.'); } catch (FeedSubUnrecognizedTypeException $e) { $this->error = _m('Not a recognized feed type.'); - } catch (FeedSubException $e) { + } catch (Exception $e) { // Any new ones we forgot about $this->error = sprintf(_m('Bad feed URL: %s %s'), get_class($e), $e->getMessage()); } @@ -315,7 +315,6 @@ class OStatusSubAction extends Action if ($this->pullRemoteProfile()) { $this->validateRemoteProfile(); } - return true; } diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index 7ab031aa59..b3b4336b52 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -1267,6 +1267,11 @@ class Ostatus_profile extends Memcached_DataObject } } + /** + * @param string $addr webfinger address + * @return Ostatus_profile + * @throws Exception on error conditions + */ public static function ensureWebfinger($addr) { // First, try the cache @@ -1275,7 +1280,8 @@ class Ostatus_profile extends Memcached_DataObject if ($uri !== false) { if (is_null($uri)) { - return null; + // Negative cache entry + throw new Exception('Not a valid webfinger address.'); } $oprofile = Ostatus_profile::staticGet('uri', $uri); if (!empty($oprofile)) { @@ -1299,8 +1305,9 @@ class Ostatus_profile extends Memcached_DataObject try { $result = $disco->lookup($addr); } catch (Exception $e) { + // Save negative cache entry so we don't waste time looking it up again. self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null); - return null; + throw new Exception('Not a valid webfinger address.'); } foreach ($result->links as $link) { @@ -1410,7 +1417,7 @@ class Ostatus_profile extends Memcached_DataObject return $oprofile; } - return null; + throw new Exception("Couldn't find a valid profile for '$addr'"); } function saveHTMLFile($title, $rendered) From 14065ca350cae576461f1a2db33694e38cebf751 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 18:28:39 -0800 Subject: [PATCH 57/74] OStatus: code cleanup on webfinger fallback path --- plugins/OStatus/classes/Ostatus_profile.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index b3b4336b52..fcca1a2521 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -1306,20 +1306,23 @@ class Ostatus_profile extends Memcached_DataObject $result = $disco->lookup($addr); } catch (Exception $e) { // Save negative cache entry so we don't waste time looking it up again. + // @fixme distinguish temporary failures? self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null); throw new Exception('Not a valid webfinger address.'); } + $hints = array('webfinger' => $addr); + foreach ($result->links as $link) { switch ($link['rel']) { case Discovery::PROFILEPAGE: - $profileUrl = $link['href']; + $hints['profileurl'] = $profileUrl = $link['href']; break; case Salmon::NS_REPLIES: - $salmonEndpoint = $link['href']; + $hints['salmon'] = $salmonEndpoint = $link['href']; break; case Discovery::UPDATESFROM: - $feedUrl = $link['href']; + $hints['feedurl'] = $feedUrl = $link['href']; break; case Discovery::HCARD: $hcardUrl = $link['href']; @@ -1330,11 +1333,6 @@ class Ostatus_profile extends Memcached_DataObject } } - $hints = array('webfinger' => $addr, - 'profileurl' => $profileUrl, - 'feedurl' => $feedUrl, - 'salmon' => $salmonEndpoint); - if (isset($hcardUrl)) { $hcardHints = self::slurpHcard($hcardUrl); // Note: Webfinger > hcard From 24835c1164251e48037f6ddee14e4b696fe57320 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 3 Mar 2010 18:31:35 -0800 Subject: [PATCH 58/74] OStatus: catchable exception instead of fatal when parsing valid XML that isn't a valid XRD doc --- plugins/OStatus/lib/xrd.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/OStatus/lib/xrd.php b/plugins/OStatus/lib/xrd.php index f00e1f8096..aa13ef0242 100644 --- a/plugins/OStatus/lib/xrd.php +++ b/plugins/OStatus/lib/xrd.php @@ -57,6 +57,9 @@ class XRD throw new Exception("Invalid XML"); } $xrd_element = $dom->getElementsByTagName('XRD')->item(0); + if (!$xrd_element) { + throw new Exception("Invalid XML, missing XRD root"); + } // Check for host-meta host $host = $xrd_element->getElementsByTagName('Host')->item(0); From de687d00c0ebe8bf5d185b7037df7f1edfd368a3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 22:56:50 -0500 Subject: [PATCH 59/74] Updated OStatus subscription error messages to be more user friendly. Hopefully. --- plugins/OStatus/actions/ostatussub.php | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/OStatus/actions/ostatussub.php b/plugins/OStatus/actions/ostatussub.php index e8a2c78ae0..bee48a8aed 100644 --- a/plugins/OStatus/actions/ostatussub.php +++ b/plugins/OStatus/actions/ostatussub.php @@ -64,7 +64,7 @@ class OStatusSubAction extends Action $this->input('profile', _m('Subscribe to'), $this->profile_uri, - _m("OStatus user's address, like nickname@example.com or http://example.net/user/nickname")); + _m("OStatus user's address, like nickname@example.com or http://example.net/nickname")); $this->elementEnd('li'); $this->elementEnd('ul'); @@ -244,25 +244,33 @@ class OStatusSubAction extends Action } else if (Validate::uri($this->profile_uri)) { $this->oprofile = Ostatus_profile::ensureProfile($this->profile_uri); } else { - $this->error = _m("Invalid address format."); + $this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname"); + common_debug('Invalid address format.', __FILE__); return false; } return true; } catch (FeedSubBadURLException $e) { - $this->error = _m('Invalid URL or could not reach server.'); + $this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname"); + common_debug('Invalid URL or could not reach server.', __FILE__); } catch (FeedSubBadResponseException $e) { - $this->error = _m('Cannot read feed; server returned error.'); + $this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later."); + common_debug('Cannot read feed; server returned error.', __FILE__); } catch (FeedSubEmptyException $e) { - $this->error = _m('Cannot read feed; server returned an empty page.'); + $this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later."); + common_debug('Cannot read feed; server returned an empty page.', __FILE__); } catch (FeedSubBadHTMLException $e) { - $this->error = _m('Bad HTML, could not find feed link.'); + $this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later."); + common_debug('Bad HTML, could not find feed link.', __FILE__); } catch (FeedSubNoFeedException $e) { - $this->error = _m('Could not find a feed linked from this URL.'); + $this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later."); + common_debug('Could not find a feed linked from this URL.', __FILE__); } catch (FeedSubUnrecognizedTypeException $e) { - $this->error = _m('Not a recognized feed type.'); + $this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later."); + common_debug('Not a recognized feed type.', __FILE__); } catch (Exception $e) { // Any new ones we forgot about - $this->error = sprintf(_m('Bad feed URL: %s %s'), get_class($e), $e->getMessage()); + $this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname"); + common_debug(sprintf('Bad feed URL: %s %s', get_class($e), $e->getMessage()), __FILE__); } return false; From 1c8399fde123fa2bc7b4ebf21fb323d215a9e7b4 Mon Sep 17 00:00:00 2001 From: James Walker Date: Wed, 3 Mar 2010 23:20:04 -0500 Subject: [PATCH 60/74] refactor xrd to allow for ownerxrd - xrd document for the site owner. introduced $config['webfinger']['owner'] for a custom xrd subject --- plugins/OStatus/OStatusPlugin.php | 4 +- plugins/OStatus/actions/ownerxrd.php | 56 +++++++++++++++++++ plugins/OStatus/actions/userxrd.php | 48 ++++++++++++++++ .../{actions/xrd.php => lib/xrdaction.php} | 32 ++++------- 4 files changed, 119 insertions(+), 21 deletions(-) create mode 100644 plugins/OStatus/actions/ownerxrd.php create mode 100644 plugins/OStatus/actions/userxrd.php rename plugins/OStatus/{actions/xrd.php => lib/xrdaction.php} (86%) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index cc7e759764..8baa857d8c 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -44,7 +44,9 @@ class OStatusPlugin extends Plugin $m->connect('.well-known/host-meta', array('action' => 'hostmeta')); $m->connect('main/xrd', - array('action' => 'xrd')); + array('action' => 'userxrd')); + $m->connect('main/ownerxrd', + array('action' => 'ownerxrd')); $m->connect('main/ostatus', array('action' => 'ostatusinit')); $m->connect('main/ostatus?nickname=:nickname', diff --git a/plugins/OStatus/actions/ownerxrd.php b/plugins/OStatus/actions/ownerxrd.php new file mode 100644 index 0000000000..9c141d8c79 --- /dev/null +++ b/plugins/OStatus/actions/ownerxrd.php @@ -0,0 +1,56 @@ +. + */ + +/** + * @package OStatusPlugin + * @maintainer James Walker + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } + +class OwnerxrdAction extends XrdAction +{ + + public $uri; + + function prepare($args) + { + $this->user = User::siteOwner(); + + if (!$this->user) { + $this->clientError(_('No such user.'), 404); + return false; + } + + $nick = common_canonical_nickname($this->user->nickname); + $acct = 'acct:' . $nick . '@' . common_config('site', 'server'); + + $this->xrd = new XRD(); + + // Check to see if a $config['webfinger']['owner'] has been set + if ($owner = common_config('webfinger', 'owner')) { + $this->xrd->subject = Discovery::normalize($owner); + $this->xrd->alias[] = $acct; + } else { + $this->xrd->subject = $acct; + } + + return true; + } +} diff --git a/plugins/OStatus/actions/userxrd.php b/plugins/OStatus/actions/userxrd.php new file mode 100644 index 0000000000..414de9364b --- /dev/null +++ b/plugins/OStatus/actions/userxrd.php @@ -0,0 +1,48 @@ +. + */ + +/** + * @package OStatusPlugin + * @maintainer James Walker + */ + +if (!defined('STATUSNET')) { exit(1); } + +class UserxrdAction extends XrdAction +{ + + function prepare($args) + { + parent::prepare($args); + + $this->uri = $this->trimmed('uri'); + $acct = Discovery::normalize($this->uri); + + list($nick, $domain) = explode('@', substr(urldecode($acct), 5)); + $nick = common_canonical_nickname($nick); + + $this->user = User::staticGet('nickname', $nick); + if (!$this->user) { + $this->clientError(_('No such user.'), 404); + return false; + } + + return true; + } +} diff --git a/plugins/OStatus/actions/xrd.php b/plugins/OStatus/lib/xrdaction.php similarity index 86% rename from plugins/OStatus/actions/xrd.php rename to plugins/OStatus/lib/xrdaction.php index f574b60ee1..6881292add 100644 --- a/plugins/OStatus/actions/xrd.php +++ b/plugins/OStatus/lib/xrdaction.php @@ -28,32 +28,24 @@ class XrdAction extends Action { public $uri; + + public $user; - function prepare($args) - { - parent::prepare($args); - - $this->uri = $this->trimmed('uri'); - - return true; - } - + public $xrd; + function handle() { - $acct = Discovery::normalize($this->uri); + $nick = $this->user->nickname; - $xrd = new XRD(); - - list($nick, $domain) = explode('@', substr(urldecode($acct), 5)); - $nick = common_canonical_nickname($nick); - - $this->user = User::staticGet('nickname', $nick); - if (!$this->user) { - $this->clientError(_('No such user.'), 404); - return false; + if (empty($this->xrd)) { + $xrd = new XRD(); + } else { + $xrd = $this->xrd; } - $xrd->subject = $this->uri; + if (empty($xrd->subject)) { + $xrd->subject = Discovery::normalize($this->uri); + } $xrd->alias[] = common_profile_url($nick); $xrd->links[] = array('rel' => Discovery::PROFILEPAGE, 'type' => 'text/html', From 38503096d905fbb4db8552eeb59afc12d4b5e903 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 23:34:48 -0500 Subject: [PATCH 61/74] Puts All groups and Remote sub button in the mini list on the same line --- plugins/OStatus/theme/base/css/ostatus.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/OStatus/theme/base/css/ostatus.css b/plugins/OStatus/theme/base/css/ostatus.css index ac668623d8..f7d9853cf7 100644 --- a/plugins/OStatus/theme/base/css/ostatus.css +++ b/plugins/OStatus/theme/base/css/ostatus.css @@ -52,7 +52,8 @@ margin-bottom:0; width:405px; } -.aside #entity_subscriptions .more { +.aside #entity_subscriptions .more, +.aside #entity_groups .more { float:left; } From b97ac60209fdec3f2d521f7c9d54acca6d00d274 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 3 Mar 2010 23:47:27 -0500 Subject: [PATCH 62/74] Changed text for authorizing/confirming remote profile --- plugins/OStatus/actions/ostatussub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/OStatus/actions/ostatussub.php b/plugins/OStatus/actions/ostatussub.php index bee48a8aed..65dee2392f 100644 --- a/plugins/OStatus/actions/ostatussub.php +++ b/plugins/OStatus/actions/ostatussub.php @@ -398,7 +398,7 @@ class OStatusSubAction extends Action function title() { // TRANS: Page title for OStatus remote subscription form - return _m('Authorize subscription'); + return _m('Confirm'); } /** From f210cadfecc4f87e1fb8e35cd784a7010c443c31 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 17:35:18 -0800 Subject: [PATCH 63/74] Revert "Revert "Show and no activity actors for user feed"" This reverts commit e2578cfad68c45ca177c51997c4cc7c0abafbd9a. --- classes/Notice.php | 8 +++++--- lib/atomnoticefeed.php | 16 +++++++++++++--- lib/atomusernoticefeed.php | 11 +++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 97cb3b8fbe..4c7e6ab4b7 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1106,7 +1106,7 @@ class Notice extends Memcached_DataObject return $groups; } - function asAtomEntry($namespace=false, $source=false) + function asAtomEntry($namespace=false, $source=false, $author=true) { $profile = $this->getProfile(); @@ -1151,8 +1151,10 @@ class Notice extends Memcached_DataObject $xs->element('title', null, $this->content); - $xs->raw($profile->asAtomAuthor()); - $xs->raw($profile->asActivityActor()); + if ($author) { + $xs->raw($profile->asAtomAuthor()); + $xs->raw($profile->asActivityActor()); + } $xs->element('link', array('rel' => 'alternate', 'type' => 'text/html', diff --git a/lib/atomnoticefeed.php b/lib/atomnoticefeed.php index 3c3556cb95..e4df731fe0 100644 --- a/lib/atomnoticefeed.php +++ b/lib/atomnoticefeed.php @@ -107,9 +107,19 @@ class AtomNoticeFeed extends Atom10Feed */ function addEntryFromNotice($notice) { - $this->addEntryRaw($notice->asAtomEntry()); + $source = $this->showSource(); + $author = $this->showAuthor(); + + $this->addEntryRaw($notice->asAtomEntry(false, $source, $author)); } + function showSource() + { + return true; + } + + function showAuthor() + { + return true; + } } - - diff --git a/lib/atomusernoticefeed.php b/lib/atomusernoticefeed.php index 55cebef6df..428cc2de2f 100644 --- a/lib/atomusernoticefeed.php +++ b/lib/atomusernoticefeed.php @@ -61,6 +61,7 @@ class AtomUserNoticeFeed extends AtomNoticeFeed if (!empty($user)) { $profile = $user->getProfile(); $this->addAuthor($profile->nickname, $user->uri); + $this->setActivitySubject($profile->asActivityNoun('subject')); } $title = sprintf(_("%s timeline"), $user->nickname); @@ -105,4 +106,14 @@ class AtomUserNoticeFeed extends AtomNoticeFeed { return $this->user; } + + function showSource() + { + return false; + } + + function showAuthor() + { + return false; + } } From 0e360ad23da4404c47bdb074a1afdb2eed873ecd Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 20:07:13 -0800 Subject: [PATCH 64/74] Test a small user feed to ensure we're taking the activity actor from the subject --- tests/UserFeedParseTest.php | 131 ++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 tests/UserFeedParseTest.php diff --git a/tests/UserFeedParseTest.php b/tests/UserFeedParseTest.php new file mode 100644 index 0000000000..b3f9a64171 --- /dev/null +++ b/tests/UserFeedParseTest.php @@ -0,0 +1,131 @@ +assertFalse(empty($dom)); + + $entries = $dom->getElementsByTagName('entry'); + + $entry1 = $entries->item(0); + $this->assertFalse(empty($entry1)); + + $feedEl = $dom->getElementsByTagName('feed')->item(0); + $this->assertFalse(empty($feedEl)); + + // Test actor (from activity:subject) + + $act1 = new Activity($entry1, $feedEl); + $this->assertFalse(empty($act1)); + $this->assertFalse(empty($act1->actor)); + $this->assertEquals($act1->actor->type, ActivityObject::PERSON); + $this->assertEquals($act1->actor->title, 'Zach Copley'); + $this->assertEquals($act1->actor->id, 'http://localhost/statusnet/user/1'); + $this->assertEquals($act1->actor->link, 'http://localhost/statusnet/zach'); + + $avatars = $act1->actor->avatarLinks; + + $this->assertEquals( + $avatars[0]->url, + 'http://localhost/statusnet/theme/default/default-avatar-profile.png' + ); + + $this->assertEquals( + $avatars[1]->url, + 'http://localhost/statusnet/theme/default/default-avatar-stream.png' + ); + + $this->assertEquals( + $avatars[2]->url, + 'http://localhost/statusnet/theme/default/default-avatar-mini.png' + ); + + $this->assertEquals($act1->actor->displayName, 'Zach Copley'); + + $poco = $act1->actor->poco; + $this->assertEquals($poco->preferredUsername, 'zach'); + $this->assertEquals($poco->address->formatted, 'El Cerrito, CA'); + $this->assertEquals($poco->urls[0]->type, 'homepage'); + $this->assertEquals($poco->urls[0]->value, 'http://zach.copley.name'); + $this->assertEquals($poco->urls[0]->primary, 'true'); + $this->assertEquals($poco->note, 'Zach Hack Attack'); + + // test the post + + //var_export($act1); + $this->assertEquals($act1->object->type, 'http://activitystrea.ms/schema/1.0/note'); + $this->assertEquals($act1->object->title, 'And now for something completely insane...'); + + $this->assertEquals($act1->object->content, 'And now for something completely insane...'); + $this->assertEquals($act1->object->id, 'http://localhost/statusnet/notice/3'); + + } + +} + +$_testfeed1 = << + + http://localhost/statusnet/api/statuses/user_timeline/1.atom + zach timeline + Updates from zach on Zach Dev! + http://localhost/statusnet/theme/default/default-avatar-profile.png + 2010-03-04T01:41:14+00:00 + + zach + http://localhost/statusnet/user/1 + + + + + + + + + + http://activitystrea.ms/schema/1.0/person + http://localhost/statusnet/user/1 + Zach Copley + + + + + +zach +Zach Copley +Zach Hack Attack + + El Cerrito, CA + + + homepage + http://zach.copley.name + true + + + + + And now for something completely insane... + + http://localhost/statusnet/notice/3 + 2010-03-04T01:41:07+00:00 + 2010-03-04T01:41:07+00:00 + + And now for something completely insane... + + + +TESTFEED1; From 8ffb34a90c78502843aabaac71963d2f40c505d8 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 20:55:53 -0800 Subject: [PATCH 65/74] Temp fix for problem getting actor from PuSH updates where actor is only specified in subject --- lib/activity.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/activity.php b/lib/activity.php index ce14fa2546..e1bce6f190 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -1060,6 +1060,18 @@ class Activity } $this->entry = $entry; + + // @fixme Don't send in a DOMDocument + if ($feed instanceof DOMDocument) { + common_log( + LOG_WARNING, + 'Activity::__construct() - ' + . 'DOMDocument passed in for feed by mistake. ' + . "Expecting a 'feed' DOMElement." + ); + $feed = $feed->getElementsByTagName('feed')->item(0); + } + $this->feed = $feed; $pubEl = $this->_child($entry, self::PUBLISHED, self::ATOM); From ce9d1618851156cc225a56980c4268a5fe102806 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 4 Mar 2010 00:29:13 -0500 Subject: [PATCH 66/74] Added the inverse icons for badge, sandbox, speech, admin --- theme/base/images/icons/README | 4 ++++ theme/base/images/icons/icons-01.gif | Bin 3792 -> 4095 bytes 2 files changed, 4 insertions(+) diff --git a/theme/base/images/icons/README b/theme/base/images/icons/README index 2e17826029..f701959ca0 100644 --- a/theme/base/images/icons/README +++ b/theme/base/images/icons/README @@ -46,6 +46,10 @@ White underscore with green background White C with green background White magic wand with green background + Green badge with white background + Green sandbox with white background + Green speech bubble broken with white background + Green person with tie with white background */ Created by various authors diff --git a/theme/base/images/icons/icons-01.gif b/theme/base/images/icons/icons-01.gif index 210c44511d9ca31b2b359df4b8b8a60ca9f71100..7c22356738044fb15b7643bcff012f74d216766b 100644 GIT binary patch delta 364 zcmV-y0h9jF9seH;M@dFFIbj+ApbF>yu?+qK6#xJKA^8LW3IP8AEC2ui02%SdS3PO}PXpy>knYbC8zqyeM zNSwwQl>QK$m8qP|*_#~coXq){xe1+GDVx@5kG$wfAhd~{+}WKCIGf=4oUd7)=6Rk` zG@j)7o$5KA-HDtQc%0U0moUhH#CeqTd7l}GkNWACfBZS0Klz{R>6gZtp8$HB_IaT7 zDW3x>LJ7*A%!K0RTG@2d+o} delta 59 zcmew_e?gYV-P6s&GEs_Q2Iq7CjXeLDMB=9iDE?$& Date: Thu, 4 Mar 2010 00:48:48 -0500 Subject: [PATCH 67/74] Updated styles for unsandbox, unsilence, revoke administrator and moderator icons --- theme/base/images/icons/icons-01.gif | Bin 4095 -> 4080 bytes theme/default/css/display.css | 16 ++++++++++++++-- theme/identica/css/display.css | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/theme/base/images/icons/icons-01.gif b/theme/base/images/icons/icons-01.gif index 7c22356738044fb15b7643bcff012f74d216766b..bf0f1230e5e16d75e630a487708d8a45ed4f6abf 100644 GIT binary patch delta 296 zcmV+@0oVTjAMhWr(hh$ad?$I7FbG07IGZX|n zQTbSt59pg27?i|$nZw!)!CVy+PQ&{SaPo!p5i&44>V%k>7CZu zoyhr{ei@uc*`Cm8moT`T@kyPQ`JCM8mp@6L`MIC>xt@MGobZ3ypE@|8Y=n;}$e#zw zo(hUb=h>iu^q}~umgHHX7J8uxbcRcH{t%p%shrE%n;hw!%=wtP37uLgo7QQMyy!_Fw27VE*_{nIo8bAJuUVevd7e=; zp5*zR>N%a=iJTUAoYrZVFvx(!d6e{dpBadc`stVaIiElIpX`6>m&Tc&0D7DDd7$+v zp93mF3Cf=1>7KMHp5Td|7J8u=sz7MSAZYkC3(}$e@S)FFLn2CziC3bw23sgaq#0VIMtY5{jGQ znVtOTodcqjREjSWw@IH-3ZWG$rTbZ(Tw0f4TBXsMoa>3DWeTOtS)5x+rb^1C@7bhd JIv@c706W8cnn?fv diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 8ca267c338..be341813a5 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -358,15 +358,27 @@ background-position: 5px -1445px; .entity_delete input.submit { background-position: 5px -1511px; } +.entity_sandbox .form_user_unsandbox input.submit { +background-position: 5px -2568px; +} +.entity_silence .form_user_unsilence input.submit { +background-position: 5px -2633px; +} .entity_role p { background-position: 5px -2436px; } -.entity_role_administrator input.submit { +.entity_role_administrator .form_user_grantrole input.submit { background-position: 5px -983px; } -.entity_role_moderator input.submit { +.entity_role_moderator .form_user_grantrole input.submit { background-position: 5px -1313px; } +.entity_role_administrator .form_user_revokerole input.submit { +background-position: 5px -2699px; +} +.entity_role_moderator .form_user_revokerole input.submit { +background-position: 5px -2501px; +} .form_reset_key input.submit { background-position: 5px -1973px; } diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index bc27cfb4d0..db85408ebd 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -358,15 +358,27 @@ background-position: 5px -1445px; .entity_delete input.submit { background-position: 5px -1511px; } +.entity_sandbox .form_user_unsandbox input.submit { +background-position: 5px -2568px; +} +.entity_silence .form_user_unsilence input.submit { +background-position: 5px -2633px; +} .entity_role p { background-position: 5px -2436px; } -.entity_role_administrator input.submit { +.entity_role_administrator .form_user_grantrole input.submit { background-position: 5px -983px; } -.entity_role_moderator input.submit { +.entity_role_moderator .form_user_grantrole input.submit { background-position: 5px -1313px; } +.entity_role_administrator .form_user_revokerole input.submit { +background-position: 5px -2699px; +} +.entity_role_moderator .form_user_revokerole input.submit { +background-position: 5px -2501px; +} .form_reset_key input.submit { background-position: 5px -1973px; } From 849f5783c445934da370769310b3b0382bc5d303 Mon Sep 17 00:00:00 2001 From: James Walker Date: Thu, 4 Mar 2010 01:30:15 -0500 Subject: [PATCH 68/74] update xrd -> userxrd --- plugins/OStatus/OStatusPlugin.php | 2 +- plugins/OStatus/actions/hostmeta.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index 8baa857d8c..ad4f613891 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -113,7 +113,7 @@ class OStatusPlugin extends Plugin { if ($action instanceof ShowstreamAction) { $acct = 'acct:'. $action->profile->nickname .'@'. common_config('site', 'server'); - $url = common_local_url('xrd'); + $url = common_local_url('userxrd'); $url.= '?uri='. $acct; header('Link: <'.$url.'>; rel="'. Discovery::LRDD_REL.'"; type="application/xrd+xml"'); diff --git a/plugins/OStatus/actions/hostmeta.php b/plugins/OStatus/actions/hostmeta.php index 3d00b98ae0..6d35ada6c6 100644 --- a/plugins/OStatus/actions/hostmeta.php +++ b/plugins/OStatus/actions/hostmeta.php @@ -32,7 +32,7 @@ class HostMetaAction extends Action parent::handle(); $domain = common_config('site', 'server'); - $url = common_local_url('xrd'); + $url = common_local_url('userxrd'); $url.= '?uri={uri}'; $xrd = new XRD(); From ddc4a7d2ffde5a925c2cfe7b57e51cd0b2cf0153 Mon Sep 17 00:00:00 2001 From: James Walker Date: Thu, 4 Mar 2010 01:46:34 -0500 Subject: [PATCH 69/74] Catch a previously uncaught exception and add some additional debug logs for signature verification --- plugins/OStatus/lib/magicenvelope.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php index 230d81ba1f..fb8c57c718 100644 --- a/plugins/OStatus/lib/magicenvelope.php +++ b/plugins/OStatus/lib/magicenvelope.php @@ -156,18 +156,32 @@ class MagicEnvelope public function verify($env) { if ($env['alg'] != 'RSA-SHA256') { + common_log(LOG_DEBUG, "Salmon error: bad algorithm"); return false; } if ($env['encoding'] != MagicEnvelope::ENCODING) { + common_log(LOG_DEBUG, "Salmon error: bad encoding"); return false; } $text = base64_decode($env['data']); $signer_uri = $this->getAuthor($text); - $verifier = Magicsig::fromString($this->getKeyPair($signer_uri)); + try { + $keypair = $this->getKeyPair($signer_uri); + } catch (Exception $e) { + common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage()); + return false; + } + + $verifier = Magicsig::fromString($keypair); + if (!$verifier) { + common_log(LOG_DEBUG, "Salmon error: unable to parse keypair"); + return false; + } + return $verifier->verify($env['data'], $env['sig']); } From 37b106d49c7e6c563a1e7e4932ab5f458572964f Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 22:22:57 -0800 Subject: [PATCH 70/74] Fix variable name in NoConfigException --- lib/statusnet.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/statusnet.php b/lib/statusnet.php index 7c4df84b4a..eba9ab9b8e 100644 --- a/lib/statusnet.php +++ b/lib/statusnet.php @@ -354,10 +354,10 @@ class StatusNet class NoConfigException extends Exception { - public $config_files; + public $configFiles; - function __construct($msg, $config_files) { + function __construct($msg, $configFiles) { parent::__construct($msg); - $this->config_files = $config_files; + $this->configFiles = $configFiles; } } From 44462ac617b315b206f757e3ee7932feabb3ca14 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 3 Mar 2010 23:26:45 -0800 Subject: [PATCH 71/74] Create an initial user during install, and grant owner, moderator and administrator roles. --- install.php | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/install.php b/install.php index 435f6d63bf..6c0b8d8e6d 100644 --- a/install.php +++ b/install.php @@ -31,6 +31,7 @@ * @author Robin Millette * @author Sarven Capadisli * @author Tom Adams + * @author Zach Copley * @license GNU Affero General Public License http://www.gnu.org/licenses/ * @version 0.9.x * @link http://status.net @@ -490,15 +491,25 @@ function showForm()

Database name

  • - +

    Database username

  • - +

    Database password (optional)

  • +
  • + + +

    Nickname for the initial StatusNet user (administrator)

    +
  • +
  • + + +

    Password for the initial StatusNet user (administrator)

    +
  • @@ -521,6 +532,10 @@ function handlePost() $password = $_POST['password']; $sitename = $_POST['sitename']; $fancy = !empty($_POST['fancy']); + + $adminNick = $_POST['admin_nickname']; + $adminPass = $_POST['admin_password']; + $server = $_SERVER['HTTP_HOST']; $path = substr(dirname($_SERVER['PHP_SELF']), 1); @@ -552,6 +567,16 @@ STR; $fail = true; } + if (empty($adminNick)) { + updateStatus("No initial StatusNet user nickname specified.", true); + $fail = true; + } + + if (empty($adminPass)) { + updateStatus("No initial StatusNet user password specified.", true); + $fail = true; + } + if ($fail) { showForm(); return; @@ -574,13 +599,29 @@ STR; return; } + // Okay, cross fingers and try to register an initial user + if (registerInitialUser($adminNick, $adminPass)) { + updateStatus( + "An initial user with the administrator role has been created." + ); + } else { + updateStatus( + "Could not create initial StatusNet user (administrator).", + true + ); + showForm(); + return; + } + /* TODO https needs to be considered */ $link = "http://".$server.'/'.$path; updateStatus("StatusNet has been installed at $link"); - updateStatus("You can visit your new StatusNet site."); + updateStatus( + "You can visit your new StatusNet site (login as '$adminNick')." + ); } function Pgsql_Db_installer($host, $database, $username, $password) @@ -756,6 +797,33 @@ function runDbScript($filename, $conn, $type = 'mysqli') return true; } +function registerInitialUser($nickname, $password) +{ + define('STATUSNET', true); + define('LACONICA', true); // compatibility + + require_once INSTALLDIR . '/lib/common.php'; + + $user = User::register( + array('nickname' => $nickname, + 'password' => $password, + 'fullname' => $nickname + ) + ); + + if (empty($user)) { + return false; + } + + // give initial user carte blanche + + $user->grantRole('owner'); + $user->grantRole('moderator'); + $user->grantRole('administrator'); + + return true; +} + ?> xml version="1.0" encoding="UTF-8" "; ?> Date: Wed, 3 Mar 2010 23:59:10 -0800 Subject: [PATCH 72/74] Couple of tweaks to the HTML to try and make installer look bettter. This still needs some work. --- install.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/install.php b/install.php index 6c0b8d8e6d..41024c901f 100644 --- a/install.php +++ b/install.php @@ -833,10 +833,10 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" Install StatusNet - - - - + + + + @@ -852,8 +852,10 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    -

    Install StatusNet

    +
    +

    Install StatusNet

    +
    From 79b392a39e9a847c398b697cf8f982a6b220ed56 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 4 Mar 2010 01:16:25 -0800 Subject: [PATCH 73/74] Add generator tag into Atom feeds. --- lib/atom10feed.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/atom10feed.php b/lib/atom10feed.php index c1fdeaae93..2d342e7854 100644 --- a/lib/atom10feed.php +++ b/lib/atom10feed.php @@ -176,6 +176,14 @@ class Atom10Feed extends XMLStringer } $this->elementStart('feed', $commonAttrs); + $this->element( + 'generator', array( + 'url' => 'http://status.net', + 'version' => STATUSNET_VERSION + ), + 'StatusNet' + ); + $this->element('id', null, $this->id); $this->element('title', null, $this->title); $this->element('subtitle', null, $this->subtitle); From 14d7f4a598d0e24467fe3eafd9a02b0e651edad8 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 4 Mar 2010 01:23:02 -0800 Subject: [PATCH 74/74] Removed unused stub class --- lib/atom10entry.php | 105 -------------------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 lib/atom10entry.php diff --git a/lib/atom10entry.php b/lib/atom10entry.php deleted file mode 100644 index f8f16d5946..0000000000 --- a/lib/atom10entry.php +++ /dev/null @@ -1,105 +0,0 @@ -. - * - * @category Feed - * @package StatusNet - * @author Zach Copley - * @copyright 2010 StatusNet, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -if (!defined('STATUSNET')) { - exit(1); -} - -class Atom10EntryException extends Exception -{ -} - -/** - * Class for manipulating an Atom entry in memory. Get the entry as an XML - * string with Atom10Entry::getString(). - * - * @category Feed - * @package StatusNet - * @author Zach Copley - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ -class Atom10Entry extends XMLStringer -{ - private $namespaces; - private $categories; - private $content; - private $contributors; - private $id; - private $links; - private $published; - private $rights; - private $source; - private $summary; - private $title; - - function __construct($indent = true) { - parent::__construct($indent); - $this->namespaces = array(); - } - - function addNamespace($namespace, $uri) - { - $ns = array($namespace => $uri); - $this->namespaces = array_merge($this->namespaces, $ns); - } - - function initEntry() - { - - } - - function endEntry() - { - - } - - /** - * Check that all required elements have been set, etc. - * Throws an Atom10EntryException if something's missing. - * - * @return void - */ - function validate() - { - - } - - function getString() - { - $this->validate(); - - $this->initEntry(); - $this->renderEntries(); - $this->endEntry(); - - return $this->xw->outputMemory(); - } - -} \ No newline at end of file