From 64925a275e8393a234183e0b97c0711ed56876a6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 4 Mar 2011 15:26:25 -0500 Subject: [PATCH 01/42] format Atom datetimes as UTC --- lib/activity.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/activity.php b/lib/activity.php index b781e49846..837be94ece 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -708,7 +708,6 @@ class Activity { $dateStr = date('d F Y H:i:s', $tm); $d = new DateTime($dateStr, new DateTimeZone('UTC')); - $d->setTimezone(new DateTimeZone(common_timezone())); return $d->format('c'); } } From 316fd01e20830c4c4afb3fbe4fd1a367a24de779 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 4 Mar 2011 15:26:25 -0500 Subject: [PATCH 02/42] format Atom datetimes as UTC --- lib/activity.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/activity.php b/lib/activity.php index b781e49846..837be94ece 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -708,7 +708,6 @@ class Activity { $dateStr = date('d F Y H:i:s', $tm); $d = new DateTime($dateStr, new DateTimeZone('UTC')); - $d->setTimezone(new DateTimeZone(common_timezone())); return $d->format('c'); } } From 4d5f8e7876e291bd309963e9a56dc1a8ad5a5f89 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 9 Mar 2011 15:46:24 -0800 Subject: [PATCH 03/42] Ticket #3076: fix regression in password recovery when email address given that doesn't match Was triggering errors due to use of common_canonical_nickname() on arbitrary input without checking for exceptions about invalid nicknames (which didn't exist long ago in the before time) --- actions/recoverpassword.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/actions/recoverpassword.php b/actions/recoverpassword.php index 9019d6fb22..a73872bfdb 100644 --- a/actions/recoverpassword.php +++ b/actions/recoverpassword.php @@ -282,7 +282,11 @@ class RecoverpasswordAction extends Action $user = User::staticGet('email', common_canonical_email($nore)); if (!$user) { - $user = User::staticGet('nickname', common_canonical_nickname($nore)); + try { + $user = User::staticGet('nickname', common_canonical_nickname($nore)); + } catch (NicknameException $e) { + // invalid + } } # See if it's an unconfirmed email address From 1d7f54ee386c667e3d373bb7dd1dbed31d996391 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 10 Mar 2011 18:08:14 +0000 Subject: [PATCH 04/42] Show a reasonable error message when an image is bad, instead of letting the exception continue bubbling up. --- actions/newapplication.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/actions/newapplication.php b/actions/newapplication.php index eb13593536..657c7bcb71 100644 --- a/actions/newapplication.php +++ b/actions/newapplication.php @@ -22,7 +22,7 @@ * @category Applications * @package StatusNet * @author Zach Copley - * @copyright 2008-2009 StatusNet, Inc. + * @copyright 2008-2011 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/ */ @@ -290,7 +290,13 @@ class NewApplicationAction extends OwnerDesignAction $app->query('ROLLBACK'); } - $app->uploadLogo(); + try { + $app->uploadLogo(); + } catch (Exception $e) { + $app->query('ROLLBACK'); + $this->showForm(_('Invalid image.')); + return; + } $app->query('COMMIT'); From b7548fb9e2236c20271a40a39b721e314478c431 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 10 Mar 2011 18:08:14 +0000 Subject: [PATCH 05/42] Show a reasonable error message when an image is bad, instead of letting the exception continue bubbling up. --- actions/newapplication.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/actions/newapplication.php b/actions/newapplication.php index eb13593536..657c7bcb71 100644 --- a/actions/newapplication.php +++ b/actions/newapplication.php @@ -22,7 +22,7 @@ * @category Applications * @package StatusNet * @author Zach Copley - * @copyright 2008-2009 StatusNet, Inc. + * @copyright 2008-2011 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/ */ @@ -290,7 +290,13 @@ class NewApplicationAction extends OwnerDesignAction $app->query('ROLLBACK'); } - $app->uploadLogo(); + try { + $app->uploadLogo(); + } catch (Exception $e) { + $app->query('ROLLBACK'); + $this->showForm(_('Invalid image.')); + return; + } $app->query('COMMIT'); From e985a41a7ee56a81bbc3150cbb2abb9cf69b0d8a Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 15 Mar 2011 10:09:20 -0700 Subject: [PATCH 06/42] Suppress PHP warnings/notices during AtomPub XML parsing to avoid HTTP header problems when given bad input. If display_errors is on, typical settings would cause PHP error messages to spew to output before the HTTP headers for setting a 400 error go through. Also switched from deprecated static DOMDocument::loadXML() to non-static call. --- actions/apitimelineuser.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index 66984b5abd..3fe73c691c 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -322,8 +322,11 @@ class ApiTimelineUserAction extends ApiBareAuthAction $this->clientError(_('Atom post must not be empty.')); } - $dom = DOMDocument::loadXML($xml); - if (!$dom) { + $old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE)); + $dom = new DOMDocument(); + $ok = $dom->loadXML($xml); + error_reporting($old); + if (!$ok) { // TRANS: Client error displayed attempting to post an API that is not well-formed XML. $this->clientError(_('Atom post must be well-formed XML.')); } From 3883b5d7319899ea8619739664455863ab260f97 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 17 Mar 2011 09:57:31 -0400 Subject: [PATCH 07/42] 0.9.7 release notes --- README | 93 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/README b/README index c27182395c..726ef165af 100644 --- a/README +++ b/README @@ -2,8 +2,8 @@ README ------ -StatusNet 0.9.6 "Man on the Moon" -29 October 2010 +StatusNet 0.9.7 "World Leader Pretend" +17 March 2011 This is the README file for StatusNet, the Open Source microblogging platform. It includes installation instructions, descriptions of @@ -96,43 +96,47 @@ for additional terms. New this version ================ -This is a security, bug and feature release since version 0.9.5 released on -10 September 2010. +This is a security, bug and feature release since version 0.9.6 released on +23 October 2010. -For best compatibility with client software and site federation, and a lot of -bug fixes, it is highly recommended that all public sites upgrade to the new -version. +For best compatibility with client software and site federation, and a +lot of bug fixes, it is highly recommended that all public sites +upgrade to the new version. Upgrades require new database indexes for +best performance; see Upgrade below. Notable changes this version: -- Site moderators can now delete groups. -- New themes: clean, shiny, mnml, victorian -- New YammerImport plugin allows site admins to import non-private profiles and - message from an authenticated Yammer site. -- New experimental plugins: AnonFavorites, SlicedFavorites, GroupFavorited, - ForceGroup, ShareNotice -- OAuth upgraded to 1.0a -- Localization updates now include plugins, thanks to translatewiki.net! -- SSL link generation should be more consistent; alternate SSL URLs can be - set in the admin UI for more parts of the system. -- Experimental backupuser.php, restoreuser.php command-line scripts to - dump/restore a user's complete activity stream. Can be used to transfer - accounts manually between sites, or to save a backup before deleting. -- Unicode fixes for OStatus notices -- Header metadata on notice pages to aid in manual reposting on Facebook -- Lots of little fixes... +- GroupPrivateMessage plugin lets users send private messages + to a group. (Similar to "private groups" on Yammer.) +- Support for Twitter streaming API in Twitter bridge plugin +- Support for a new Activity Streams-based API using AtomPub, allowing + richer API data. See http://status.net/wiki/AtomPub for details. +- Unified Facebook plugin, replacing previous Facebook application + and Facebook Connect plugin. +- A plugin to send out a daily summary email to network users. +- In-line thumbnails of some attachments (video, images) and oEmbed objects. +- Local copies of remote profiles to let moderators manage OStatus users. +- Upgrade upstream JS, minify everything. +- Allow pushing plugin JS, CSS, and static files to a CDN. +- Configurable nickname rules. +- Better support for bit.ly URL shortener. +- InProcessCache plugin for additional caching on top of memcached. +- Support for Activity Streams JSON feeds on many streams. +- User-initiated backup and restore of account data in Activity Streams + format. +- Bookmark plugin for making del.icio.us-like social bookmarking sites, + including del.icio.us backup file import. Supports OStatus. +- SQLProfile plugin to tune SQL queries. +- Better sorting on timelines to support restored or imported data. +- Hundreds of translations from http://translatewiki.net/ +- Hundreds of performance tunings, bug fixes, and UI improvements. +- Remove deprecated data from Activity Streams Atom output, to the + extent possible. +- NewMenu plugin for new layout of menu items. +- Experimental support for moving an account from one server to + another, using new AtomPub API. -Changes from 0.9.6 release candidate 1: -- fix for broken group pages when logged out -- fix for stuck ping queue entries when bad profile -- fix for bogus single-user nickname config entry error -- i18n updates -- nofollow updates -- SSL-only mode secure cookie fix -- experimental ApiLogger plugin for usage data gathering -- experimental follow-everyone plugin - -A full changelog is available at http://status.net/wiki/StatusNet_0.9.6. +A full changelog is available at http://status.net/wiki/StatusNet_0.9.7. Prerequisites ============= @@ -243,9 +247,9 @@ especially if you've previously installed PHP/MySQL packages. 1. Unpack the tarball you downloaded on your Web server. Usually a command like this will work: - tar zxf statusnet-0.9.6.tar.gz + tar zxf statusnet-0.9.7.tar.gz - ...which will make a statusnet-0.9.6 subdirectory in your current + ...which will make a statusnet-0.9.7 subdirectory in your current directory. (If you don't have shell access on your Web server, you may have to unpack the tarball on your local computer and FTP the files to the server.) @@ -253,7 +257,7 @@ especially if you've previously installed PHP/MySQL packages. 2. Move the tarball to a directory of your choosing in your Web root directory. Usually something like this will work: - mv statusnet-0.9.6 /var/www/statusnet + mv statusnet-0.9.7 /var/www/statusnet This will make your StatusNet instance available in the statusnet path of your server, like "http://example.net/statusnet". "microblog" or @@ -668,7 +672,7 @@ with this situation. If you've been using StatusNet 0.7, 0.6, 0.5 or lower, or if you've been tracking the "git" version of the software, you will probably want to upgrade and keep your existing data. There is no automated -upgrade procedure in StatusNet 0.9.6. Try these step-by-step +upgrade procedure in StatusNet 0.9.7. Try these step-by-step instructions; read to the end first before trying them. 0. Download StatusNet and set up all the prerequisites as if you were @@ -689,25 +693,30 @@ instructions; read to the end first before trying them. 5. Once all writing processes to your site are turned off, make a final backup of the Web directory and database. 6. Move your StatusNet directory to a backup spot, like "statusnet.bak". -7. Unpack your StatusNet 0.9.6 tarball and move it to "statusnet" or +7. Unpack your StatusNet 0.9.7 tarball and move it to "statusnet" or wherever your code used to be. 8. Copy the config.php file and the contents of the avatar/, background/, file/, and local/ subdirectories from your old directory to your new directory. 9. Copy htaccess.sample to .htaccess in the new directory. Change the RewriteBase to use the correct path. -10. Rebuild the database. (You can safely skip this step and go to #12 - if you're upgrading from another 0.9.x version). +10. Rebuild the database. NOTE: this step is destructive and cannot be reversed. YOU CAN EASILY DESTROY YOUR SITE WITH THIS STEP. Don't do it without a known-good backup! - If your database is at version 0.8.0 or above, you can run a + If your database is at version 0.8.0 or higher in the 0.8.x line, you can run a special upgrade script: mysql -u -p db/08to09.sql + If you are upgrading from any 0.9.x version like 0.9.6, run this script: + + mysql -u -p db/096to097.sql + + Despite the name, it should work for any 0.9.x branch. + Otherwise, go to your StatusNet directory and AFTER YOU MAKE A BACKUP run the rebuilddb.sh script like this: From 531400be6f3cba904eaa20dbd62fea45a6090877 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 17 Mar 2011 09:58:41 -0400 Subject: [PATCH 08/42] upgrade lifecycle to release --- lib/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common.php b/lib/common.php index 900ce9fa5b..473956478d 100644 --- a/lib/common.php +++ b/lib/common.php @@ -23,7 +23,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } if (isset($_REQUEST['p']) && $_REQUEST['p'] == 'check-fancy') { exit; } define('STATUSNET_BASE_VERSION', '0.9.7'); -define('STATUSNET_LIFECYCLE', 'beta3'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release' +define('STATUSNET_LIFECYCLE', ''); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', '' for release define('STATUSNET_VERSION', STATUSNET_BASE_VERSION . STATUSNET_LIFECYCLE); define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility From a4305401557f56656d98e1bb22dd68e83a5622c7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 17 Mar 2011 11:31:43 -0400 Subject: [PATCH 09/42] configuration option to bust frames or not --- README | 3 +++ lib/action.php | 4 +++- lib/default.php | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README b/README index c27182395c..58ebd290b0 100644 --- a/README +++ b/README @@ -1139,6 +1139,9 @@ ssl: Whether to use SSL for JavaScript files. Default is null, which means sslserver: SSL server to use when page is HTTPS-encrypted. If unspecified, site ssl server and so on will be used. sslpath: If sslserver if defined, path to use when page is HTTPS-encrypted. +bustframes: If true, all web pages will break out of framesets. If false, + can comfortably live in a frame or iframe... probably. Default + to true. xmpp ---- diff --git a/lib/action.php b/lib/action.php index 173e2c2a58..fef4259264 100644 --- a/lib/action.php +++ b/lib/action.php @@ -298,7 +298,9 @@ class Action extends HTMLOutputter // lawsuit $this->script('util.min.js'); $this->showScriptMessages(); // Frame-busting code to avoid clickjacking attacks. - $this->inlineScript('if (window.top !== window.self) { window.top.location.href = window.self.location.href; }'); + if (common_config('javascript', 'bustframes')) { + $this->inlineScript('if (window.top !== window.self) { window.top.location.href = window.self.location.href; }'); + } Event::handle('EndShowStatusNetScripts', array($this)); Event::handle('EndShowLaconicaScripts', array($this)); } diff --git a/lib/default.php b/lib/default.php index 124c90c998..c1dfcbc87d 100644 --- a/lib/default.php +++ b/lib/default.php @@ -154,7 +154,8 @@ $default = 'javascript' => array('server' => null, 'path'=> null, - 'ssl' => null), + 'ssl' => null, + 'bustframes' => true), 'local' => // To override path/server for themes in 'local' dir (not currently applied to local plugins) array('server' => null, 'dir' => null, From df4afee86ce847e26f76a075c8f676ca56c736fa Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 18 Mar 2011 13:58:13 -0700 Subject: [PATCH 10/42] Tickets #1610, #1949: show permalinks on Popular Notices, attachments aside sections These mini notice lists were previously not actually showing links to the notices, making them hard to use. There was code to output a link, but it had been unused due to the config options triggering it not being set. The links also looked bad ("( see )" with bad spacing). Replaced that code with a call into NoticeListItem's existing code to format a relative timestamp with the notice permalink, which looks nice. Used a div rather than p to avoid clearing the float, so it flows nicely. --- lib/noticesection.php | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/lib/noticesection.php b/lib/noticesection.php index 7157feafc5..ceb0bb36f8 100644 --- a/lib/noticesection.php +++ b/lib/noticesection.php @@ -39,6 +39,8 @@ define('NOTICES_PER_SECTION', 6); * These are the widgets that show interesting data about a person * group, or site. * + * @todo migrate this to use a variant of NoticeList + * * @category Widget * @package StatusNet * @author Evan Prodromou @@ -97,38 +99,14 @@ class NoticeSection extends Section $this->out->elementStart('p', 'entry-content'); $this->out->raw($notice->rendered); - - $notice_link_cfg = common_config('site', 'notice_link'); - if ('direct' === $notice_link_cfg) { - $this->out->text(' ('); - $this->out->element('a', array('href' => $notice->uri), 'see'); - $this->out->text(')'); - } elseif ('attachment' === $notice_link_cfg) { - if ($count = $notice->hasAttachments()) { - // link to attachment(s) pages - if (1 === $count) { - $f2p = File_to_post::staticGet('post_id', $notice->id); - $href = common_local_url('attachment', array('attachment' => $f2p->file_id)); - $att_class = 'attachment'; - } else { - $href = common_local_url('attachments', array('notice' => $notice->id)); - $att_class = 'attachments'; - } - - $clip = Theme::path('images/icons/clip.png', 'base'); - $this->out->elementStart('a', array('class' => $att_class, 'style' => "font-style: italic;", 'href' => $href, 'title' => "# of attachments: $count")); - $this->out->raw(" ($count "); - $this->out->element('img', array('style' => 'display: inline', 'align' => 'top', 'width' => 20, 'height' => 20, 'src' => $clip, 'alt' => 'alt')); - $this->out->text(')'); - $this->out->elementEnd('a'); - } else { - $this->out->text(' ('); - $this->out->element('a', array('href' => $notice->uri), 'see'); - $this->out->text(')'); - } - } - $this->out->elementEnd('p'); + + $this->out->elementStart('div', 'entry_content'); + get_class('NoticeList'); + $nli = new NoticeListItem($notice, $this->out); + $nli->showNoticeLink(); + $this->out->elementEnd('div'); + if (!empty($notice->value)) { $this->out->elementStart('p'); $this->out->text($notice->value); From 119d0f7dbab40f30170ba263de78d7e9cea984db Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 18 Mar 2011 16:23:22 -0700 Subject: [PATCH 11/42] fix ModPlus 'remote profile options' popup for Realtime Switched from one-time setup to live stuff that'll work without per-notice setup. Used to not matter because Realtime wouldn't include the extra stuff, but new Realtime pulls the full rendering, so yay! --- plugins/ModPlus/modplus.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/plugins/ModPlus/modplus.js b/plugins/ModPlus/modplus.js index 2e90de4f19..023dee5762 100644 --- a/plugins/ModPlus/modplus.js +++ b/plugins/ModPlus/modplus.js @@ -4,20 +4,18 @@ */ $(function() { - function ModPlus_setup(notice) { - if ($(notice).find('.remote-profile-options').size()) { - var $options = $(notice).find('.remote-profile-options'); - $options.prepend($()) - $(notice).find('.author').mouseenter(function(event) { - $(notice).find('.remote-profile-options').fadeIn(); - }); - $(notice).mouseleave(function(event) { - $(notice).find('.remote-profile-options').fadeOut(); - }); + $('.notice .author').live('mouseenter', function(e) { + var notice = $(this).closest('.notice'); + var popup = notice.find('.remote-profile-options'); + if (popup.length) { + popup.fadeIn(); + } + }); + $('.notice').live('mouseleave', function(e) { + var notice = $(this); + var popup = notice.find('.remote-profile-options'); + if (popup.length) { + popup.fadeOut(); } - } - - $('.notice').each(function() { - ModPlus_setup(this); }); }); From afd92957b43aedf8dfb38b0c03aa0461ca27974a Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 18 Mar 2011 16:35:50 -0700 Subject: [PATCH 12/42] ModPlus plugin -- Ticket #3095: add remote profile options popup to group membership and other profile lists Popup remote profile options menu now shown on profile lists as well as notice lists. --- plugins/ModPlus/ModPlusPlugin.php | 39 +++++++++++++++++++++++++++---- plugins/ModPlus/modplus.js | 18 ++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/plugins/ModPlus/ModPlusPlugin.php b/plugins/ModPlus/ModPlusPlugin.php index d2b7c09346..f8351f0988 100644 --- a/plugins/ModPlus/ModPlusPlugin.php +++ b/plugins/ModPlus/ModPlusPlugin.php @@ -84,7 +84,7 @@ class ModPlusPlugin extends Plugin } /** - * Add OpenID-related paths to the router table + * Add ModPlus-related paths to the router table * * Hook for RouterInitialized event. * @@ -101,16 +101,45 @@ class ModPlusPlugin extends Plugin return true; } + /** + * Add per-profile info popup menu for author on notice lists. + * + * @param NoticeListItem $item + * @return boolean hook value + */ function onStartShowNoticeItem($item) { - $profile = $item->profile; + $this->showProfileOptions($item->out, $item->profile); + return true; + } + + /** + * Add per-profile info popup menu on profile lists. + * + * @param ProfileListItem $item + */ + function onStartProfileListItemProfile($item) + { + $this->showProfileOptions($item->out, $item->profile); + return true; + } + + /** + * Build common remote-profile options structure. + * Currently only adds output for remote profiles, nothing for local users. + * + * @param HTMLOutputter $out + * @param Profile $profile + */ + protected function showProfileOptions(HTMLOutputter $out, Profile $profile) + { $isRemote = !(User::staticGet('id', $profile->id)); if ($isRemote) { $target = common_local_url('remoteprofile', array('id' => $profile->id)); $label = _m('Remote profile options...'); - $item->out->elementStart('div', 'remote-profile-options'); - $item->out->element('a', array('href' => $target), $label); - $item->out->elementEnd('div'); + $out->elementStart('div', 'remote-profile-options'); + $out->element('a', array('href' => $target), $label); + $out->elementEnd('div'); } } } diff --git a/plugins/ModPlus/modplus.js b/plugins/ModPlus/modplus.js index 023dee5762..511e8ee144 100644 --- a/plugins/ModPlus/modplus.js +++ b/plugins/ModPlus/modplus.js @@ -4,6 +4,7 @@ */ $(function() { + // Notice lists... $('.notice .author').live('mouseenter', function(e) { var notice = $(this).closest('.notice'); var popup = notice.find('.remote-profile-options'); @@ -18,4 +19,21 @@ $(function() { popup.fadeOut(); } }); + + // Profile lists... + $('.profile .avatar').live('mouseenter', function(e) { + var profile = $(this).closest('.profile'); + var popup = profile.find('.remote-profile-options'); + if (popup.length) { + popup.fadeIn(); + } + }); + $('.profile').live('mouseleave', function(e) { + var profile = $(this); + var popup = profile.find('.remote-profile-options'); + if (popup.length) { + popup.fadeOut(); + } + }); + }); From 9fc6de6b370a7f970e72be8d1f40f31958e0e40f Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 21 Mar 2011 11:18:38 -0700 Subject: [PATCH 13/42] remove type hinting -- fails when ArrayWrapper gets passed in some profile list pages --- plugins/ModPlus/ModPlusPlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ModPlus/ModPlusPlugin.php b/plugins/ModPlus/ModPlusPlugin.php index f8351f0988..ed478c27b8 100644 --- a/plugins/ModPlus/ModPlusPlugin.php +++ b/plugins/ModPlus/ModPlusPlugin.php @@ -129,9 +129,9 @@ class ModPlusPlugin extends Plugin * Currently only adds output for remote profiles, nothing for local users. * * @param HTMLOutputter $out - * @param Profile $profile + * @param Profile $profile (may also be an ArrayWrapper... sigh) */ - protected function showProfileOptions(HTMLOutputter $out, Profile $profile) + protected function showProfileOptions(HTMLOutputter $out, $profile) { $isRemote = !(User::staticGet('id', $profile->id)); if ($isRemote) { From 089c10d5d893a4aa3b94c08fd105c87600afb130 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 21 Mar 2011 11:43:02 -0700 Subject: [PATCH 14/42] get_class -> class_exists for class loading hack (fixme for 1.0: make sure all these classes are in own files) --- lib/noticesection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/noticesection.php b/lib/noticesection.php index ceb0bb36f8..2342abe19d 100644 --- a/lib/noticesection.php +++ b/lib/noticesection.php @@ -102,7 +102,7 @@ class NoticeSection extends Section $this->out->elementEnd('p'); $this->out->elementStart('div', 'entry_content'); - get_class('NoticeList'); + class_exists('NoticeList'); $nli = new NoticeListItem($notice, $this->out); $nli->showNoticeLink(); $this->out->elementEnd('div'); From a2212593283a0051e9de78ceb922ae3fe9cf6f64 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 23 Mar 2011 13:00:44 -0400 Subject: [PATCH 15/42] group private message email notification fix --- plugins/GroupPrivateMessage/Group_message_profile.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/GroupPrivateMessage/Group_message_profile.php b/plugins/GroupPrivateMessage/Group_message_profile.php index bd778b815a..e0c1e06785 100644 --- a/plugins/GroupPrivateMessage/Group_message_profile.php +++ b/plugins/GroupPrivateMessage/Group_message_profile.php @@ -156,9 +156,7 @@ class Group_message_profile extends Memcached_DataObject // TRANS: Subject for direct-message notification email. // TRANS: %s is the sending user's nickname. - $subject = sprintf(_('New private message from %s to group %s'), $from->nickname, $group->nickname); - - $from_profile = $from->getProfile(); + $subject = sprintf(_('New private message from %s to group %s'), $from_profile->nickname, $group->nickname); // TRANS: Body for direct-message notification email. // TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname, @@ -174,13 +172,13 @@ class Group_message_profile extends Memcached_DataObject "With kind regards,\n". "%6\$s\n"), $from_profile->getBestName(), - $from->nickname, + $from_profile->nickname, $group->nickname, $this->content, - common_local_url('newmessage', array('to' => $from->id)), + common_local_url('newmessage', array('to' => $from_profile->id)), common_config('site', 'name')); - $headers = _mail_prepare_headers('message', $to->nickname, $from->nickname); + $headers = _mail_prepare_headers('message', $to->nickname, $from_profile->nickname); common_switch_locale(); From acd594c9a6485e1f0010df6a21b8e56c7b6ebb02 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 23 Mar 2011 13:58:36 -0400 Subject: [PATCH 16/42] put correct content into the group private message update --- plugins/GroupPrivateMessage/Group_message_profile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GroupPrivateMessage/Group_message_profile.php b/plugins/GroupPrivateMessage/Group_message_profile.php index e0c1e06785..c5832a9294 100644 --- a/plugins/GroupPrivateMessage/Group_message_profile.php +++ b/plugins/GroupPrivateMessage/Group_message_profile.php @@ -174,7 +174,7 @@ class Group_message_profile extends Memcached_DataObject $from_profile->getBestName(), $from_profile->nickname, $group->nickname, - $this->content, + $gm->content, common_local_url('newmessage', array('to' => $from_profile->id)), common_config('site', 'name')); From dc73cf0b059c40ca18f6dc3f842228095cf34b6f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 23 Mar 2011 14:24:07 -0400 Subject: [PATCH 17/42] don't send group private message mail notification to the author --- plugins/GroupPrivateMessage/Group_message_profile.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/GroupPrivateMessage/Group_message_profile.php b/plugins/GroupPrivateMessage/Group_message_profile.php index c5832a9294..3214fba5b3 100644 --- a/plugins/GroupPrivateMessage/Group_message_profile.php +++ b/plugins/GroupPrivateMessage/Group_message_profile.php @@ -127,7 +127,10 @@ class Group_message_profile extends Memcached_DataObject $gmp->insert(); - $gmp->notify(); + // If it's not for the author, send email notification + if ($gm->from_profile != $profile->id) { + $gmp->notify(); + } return $gmp; } From fd4d535d9175f9491c756779fc2f9e451aec7feb Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 23 Mar 2011 14:34:32 -0400 Subject: [PATCH 18/42] add a fix1 to the version number --- lib/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common.php b/lib/common.php index 473956478d..17375c4b62 100644 --- a/lib/common.php +++ b/lib/common.php @@ -23,7 +23,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } if (isset($_REQUEST['p']) && $_REQUEST['p'] == 'check-fancy') { exit; } define('STATUSNET_BASE_VERSION', '0.9.7'); -define('STATUSNET_LIFECYCLE', ''); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', '' for release +define('STATUSNET_LIFECYCLE', 'fix1'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', '' for release define('STATUSNET_VERSION', STATUSNET_BASE_VERSION . STATUSNET_LIFECYCLE); define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility From e68271c47120971bac0c59228dd382216a1f52e1 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 24 Mar 2011 18:41:25 -0700 Subject: [PATCH 19/42] TwitterBridge: discard outgoing queue items instead of retrying when Twitter API returns HTTP 400 or 404 error codes We get HTTP 400 for various cases of invalid data, where retrying doesn't help at all -- previously those would loop forever, or until something died at least. :) 400 is also used for rate limiting, but retrying *immediately* will just hit the rate limit again, so better to discard if we're going over for now. --- plugins/TwitterBridge/twitter.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index f5a0b62588..2c68f89f16 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -320,7 +320,20 @@ function process_error($e, $flink, $notice) common_log(LOG_WARNING, $logmsg); + // http://dev.twitter.com/pages/responses_errors switch($code) { + case 400: + // Probably invalid data (bad Unicode chars or coords) that + // cannot be resolved by just sending again. + // + // It could also be rate limiting, but retrying immediately + // won't help much with that, so we'll discard for now. + // If a facility for retrying things later comes up in future, + // we can detect the rate-limiting headers and use that. + // + // Discard the message permanently. + return true; + break; case 401: // Probably a revoked or otherwise bad access token - nuke! remove_twitter_link($flink); @@ -330,6 +343,13 @@ function process_error($e, $flink, $notice) // User has exceeder her rate limit -- toss the notice return true; break; + case 404: + // Resource not found. Shouldn't happen much on posting, + // but just in case! + // + // Consider it a matter for tossing the notice. + return true; + break; default: // For every other case, it's probably some flakiness so try From 83d1997f59e984753982d92373deccdb2c737c88 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 30 Mar 2011 10:58:28 -0400 Subject: [PATCH 20/42] incorrect name for bookmark plugin --- plugins/Bookmark/BookmarkPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index 2e6baf5e4e..339b03e056 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -450,7 +450,7 @@ class BookmarkPlugin extends Plugin function onPluginVersion(&$versions) { - $versions[] = array('name' => 'Sample', + $versions[] = array('name' => 'Bookmark', 'version' => self::VERSION, 'author' => 'Evan Prodromou', 'homepage' => 'http://status.net/wiki/Plugin:Bookmark', From 02c2c3a6cca741967c1b2136453067da958b613d Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 30 Mar 2011 14:18:29 -0700 Subject: [PATCH 21/42] Provisional workaround for router inconsistencies in background processes that switch site configs. Ensure that router is cleared when we do site setup; we can still fetch the data from cache, so it should stay fast, but should ensure that we don't end up with someone else's routes still set up, which may be an issue breaking some of the bookmark handling that needs routing with a rare plugin. --- lib/router.php | 9 +++++++++ lib/statusnet.php | 2 ++ 2 files changed, 11 insertions(+) diff --git a/lib/router.php b/lib/router.php index e956b02c63..e3a9203e4d 100644 --- a/lib/router.php +++ b/lib/router.php @@ -126,6 +126,15 @@ class Router return Router::$inst; } + /** + * Clear the global singleton instance for this class. + * Needed to ensure reset when switching site configurations. + */ + static function clear() + { + Router::$inst = null; + } + function __construct() { if (empty($this->m)) { diff --git a/lib/statusnet.php b/lib/statusnet.php index 85b46bbb3f..2c38fc205f 100644 --- a/lib/statusnet.php +++ b/lib/statusnet.php @@ -107,6 +107,8 @@ class StatusNet */ public static function init($server=null, $path=null, $conffile=null) { + Router::clear(); + StatusNet::initDefaults($server, $path); StatusNet::loadConfigFile($conffile); From 347b57f72a705a0a1572de6b4ed43bddb1c3793b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 30 Mar 2011 17:01:06 -0700 Subject: [PATCH 22/42] Provisional fix for ticket #3108: Facebook bridge sends "likes" as the notice's original poster instead of as the person doing the liking. Adds optional $profile parameter for Facebookclient constructor and uses that for the foreign_link lookup if provided instead of the notice's poster. --- plugins/FacebookBridge/FacebookBridgePlugin.php | 4 ++-- plugins/FacebookBridge/lib/facebookclient.php | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/FacebookBridge/FacebookBridgePlugin.php b/plugins/FacebookBridge/FacebookBridgePlugin.php index 37b931e23e..5d2442d579 100644 --- a/plugins/FacebookBridge/FacebookBridgePlugin.php +++ b/plugins/FacebookBridge/FacebookBridgePlugin.php @@ -526,7 +526,7 @@ ENDOFSCRIPT; */ function onEndFavorNotice(Profile $profile, Notice $notice) { - $client = new Facebookclient($notice); + $client = new Facebookclient($notice, $profile); $client->like(); return true; @@ -542,7 +542,7 @@ ENDOFSCRIPT; */ function onEndDisfavorNotice(Profile $profile, Notice $notice) { - $client = new Facebookclient($notice); + $client = new Facebookclient($notice, $profile); $client->unLike(); return true; diff --git a/plugins/FacebookBridge/lib/facebookclient.php b/plugins/FacebookBridge/lib/facebookclient.php index 516f252d98..37d6a0a7a0 100644 --- a/plugins/FacebookBridge/lib/facebookclient.php +++ b/plugins/FacebookBridge/lib/facebookclient.php @@ -48,7 +48,12 @@ class Facebookclient protected $notice = null; // The user's notice protected $user = null; // Sender of the notice - function __construct($notice) + /** + * + * @param Notice $notice the notice to manipulate + * @param Profile $profile local user to act as; if left empty, the notice's poster will be used. + */ + function __construct($notice, $profile=null) { $this->facebook = self::getFacebook(); @@ -60,8 +65,9 @@ class Facebookclient $this->notice = $notice; + $profile_id = $profile ? $profile->id : $notice->profile_id; $this->flink = Foreign_link::getByUserID( - $notice->profile_id, + $profile_id, FACEBOOK_SERVICE ); From 2411caa000a490b9afce2398fefb4110e92e0f11 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 31 Mar 2011 11:20:24 -0400 Subject: [PATCH 23/42] If Router is mucked up, force URI for Bookmark --- plugins/Bookmark/Bookmark.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/plugins/Bookmark/Bookmark.php b/plugins/Bookmark/Bookmark.php index 777b50f724..48709d1387 100644 --- a/plugins/Bookmark/Bookmark.php +++ b/plugins/Bookmark/Bookmark.php @@ -238,8 +238,23 @@ class Bookmark extends Memcached_DataObject if (array_key_exists('uri', $options)) { $nb->uri = $options['uri']; } else { - $nb->uri = common_local_url('showbookmark', - array('id' => $nb->id)); + // FIXME: hacks to work around router bugs in + // queue daemons + + $r = Router::get(); + + $path = $r->build('showbookmark', + array('id' => $nb->id)); + + if (empty($path)) { + $nb->uri = common_path('bookmark/'.$nb->id, false, false); + } else { + $nb->uri = common_local_url('showbookmark', + array('id' => $nb->id), + null, + null, + false); + } } $nb->insert(); From 61fe49b100dbc3cf646fe90b563ea4a7c3090a8c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 31 Mar 2011 13:53:17 -0400 Subject: [PATCH 24/42] ActivityImporter gives up on any exception --- lib/activityimporter.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/activityimporter.php b/lib/activityimporter.php index aa9b95e084..b1f30fa4bf 100644 --- a/lib/activityimporter.php +++ b/lib/activityimporter.php @@ -83,15 +83,9 @@ class ActivityImporter extends QueueHandler Event::handle('EndImportActivity', array($user, $author, $activity, $trusted)); $done = true; - } catch (ClientException $ce) { - common_log(LOG_WARNING, $ce->getMessage()); - $done = true; - } catch (ServerException $se) { - common_log(LOG_ERR, $se->getMessage()); - $done = false; } catch (Exception $e) { common_log(LOG_ERR, $e->getMessage()); - $done = false; + $done = true; } } return $done; From f5801470582ba96a431e66bff9612b917512357d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 31 Mar 2011 16:15:05 -0400 Subject: [PATCH 25/42] Clear ;last version of stream if importing old stuff --- classes/Notice.php | 57 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 141ae8fd44..d513695192 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -445,19 +445,19 @@ class Notice extends Memcached_DataObject function blowOnInsert($conversation = false) { - self::blow('profile:notice_ids:%d', $this->profile_id); + $this->blowStream('profile:notice_ids:%d', $this->profile_id); if ($this->isPublic()) { - self::blow('public'); + $this->blowStream('public'); } // XXX: Before we were blowing the casche only if the notice id // was not the root of the conversation. What to do now? - self::blow('notice:conversation_ids:%d', $this->conversation); + $this->blowStream('notice:conversation_ids:%d', $this->conversation); if (!empty($this->repeat_of)) { - self::blow('notice:repeats:%d', $this->repeat_of); + $this->blowStream('notice:repeats:%d', $this->repeat_of); } $original = Notice::staticGet('id', $this->repeat_of); @@ -465,11 +465,12 @@ class Notice extends Memcached_DataObject if (!empty($original)) { $originalUser = User::staticGet('id', $original->profile_id); if (!empty($originalUser)) { - self::blow('user:repeats_of_me:%d', $originalUser->id); + $this->blowStream('user:repeats_of_me:%d', $originalUser->id); } } $profile = Profile::staticGet($this->profile_id); + if (!empty($profile)) { $profile->blowNoticeCount(); } @@ -490,6 +491,42 @@ class Notice extends Memcached_DataObject } } + function blowStream() + { + $c = self::memcache(); + + if (empty($c)) { + return false; + } + + $args = func_get_args(); + + $format = array_shift($args); + + $keyPart = vsprintf($format, $args); + + $cacheKey = Cache::key($keyPart); + + $c->delete($cacheKey); + + // delete the "last" stream, too, if this notice is + // older than the top of that stream + + $lastKey = $cacheKey.';last'; + + $lastStr = $c->get($lastKey); + + if ($lastStr !== false) { + $window = explode(',', $lastStr); + $lastID = $window[0]; + $lastNotice = Notice::staticGet('id', $lastID); + if (empty($lastNotice) // just weird + || strtotime($lastNotice->created) >= strtotime($this->created)) { + $c->delete($lastKey); + } + } + } + /** save all urls in the notice to the db * * follow redirects and save all available file information @@ -1513,22 +1550,22 @@ class Notice extends Memcached_DataObject } $laststr = $cache->get($idkey.';last'); - + if ($laststr !== false) { $window = explode(',', $laststr); $last_id = $window[0]; $new_ids = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, $last_id, 0, null))); - + $new_window = array_merge($new_ids, $window); $new_windowstr = implode(',', $new_window); - + $result = $cache->set($idkey, $new_windowstr); $result = $cache->set($idkey . ';last', $new_windowstr); - + $ids = array_slice($new_window, $offset, $limit); - + return $ids; } From d5a38c62f47168f9be9ea859aa447636a80bb94a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 31 Mar 2011 16:15:30 -0400 Subject: [PATCH 26/42] Don't try to import a
without a
from delicious --- plugins/Bookmark/deliciousbackupimporter.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/Bookmark/deliciousbackupimporter.php b/plugins/Bookmark/deliciousbackupimporter.php index 197c7a143b..7439c8f853 100644 --- a/plugins/Bookmark/deliciousbackupimporter.php +++ b/plugins/Bookmark/deliciousbackupimporter.php @@ -79,6 +79,12 @@ class DeliciousBackupImporter extends QueueHandler $doc = $this->importHTML($body); + // If we can't parse it, it's no good + + if (empty($doc)) { + return true; + } + $dls = $doc->getElementsByTagName('dl'); if ($dls->length != 1) { @@ -112,9 +118,11 @@ class DeliciousBackupImporter extends QueueHandler case 'dd': $dd = $child; - // This
contains a description for the bookmark in - // the preceding
node. - $saved = $this->importBookmark($user, $dt, $dd); + if (!empty($dt)) { + // This
contains a description for the bookmark in + // the preceding
node. + $saved = $this->importBookmark($user, $dt, $dd); + } $dt = null; $dd = null; From a84d584971dd1eedab20094da60d31fa93659c84 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 Apr 2011 09:30:25 -0400 Subject: [PATCH 27/42] delete the Bookmark if Notice::saveNew() fails --- plugins/Bookmark/Bookmark.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/plugins/Bookmark/Bookmark.php b/plugins/Bookmark/Bookmark.php index 48709d1387..b83aca62df 100644 --- a/plugins/Bookmark/Bookmark.php +++ b/plugins/Bookmark/Bookmark.php @@ -329,11 +329,20 @@ class Bookmark extends Memcached_DataObject $options['uri'] = $nb->uri; } - $saved = Notice::saveNew($profile->id, - $content, - array_key_exists('source', $options) ? - $options['source'] : 'web', - $options); + try { + $saved = Notice::saveNew($profile->id, + $content, + array_key_exists('source', $options) ? + $options['source'] : 'web', + $options); + } catch (Exception $e) { + $nb->delete(); + throw $e; + } + + if (empty($saved)) { + $nb->delete(); + } return $saved; } From 580986f007cf7ae128754b8cc40fb1b268cb93fa Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 Apr 2011 13:34:55 -0400 Subject: [PATCH 28/42] Plugin to put the sitenotice in the sidebar --- .../SiteNoticeInSidebarPlugin.php | 92 +++++++++++++++++++ .../SiteNoticeInSidebar/sitenoticesection.php | 67 ++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 plugins/SiteNoticeInSidebar/SiteNoticeInSidebarPlugin.php create mode 100644 plugins/SiteNoticeInSidebar/sitenoticesection.php diff --git a/plugins/SiteNoticeInSidebar/SiteNoticeInSidebarPlugin.php b/plugins/SiteNoticeInSidebar/SiteNoticeInSidebarPlugin.php new file mode 100644 index 0000000000..4e6aade2a5 --- /dev/null +++ b/plugins/SiteNoticeInSidebar/SiteNoticeInSidebarPlugin.php @@ -0,0 +1,92 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Put the site notice in the sidebar + * + * @category General + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class SiteNoticeInSidebarPlugin extends Plugin +{ + /** + * Function comment + * + * @param + * + * @return + */ + + function onStartShowSiteNotice($action) + { + return false; + } + + function onStartShowSections($action) + { + $text = common_config('site', 'notice'); + if (!empty($text)) { + $sns = new SiteNoticeSection($action, $text); + $sns->show(); + } + return true; + } + + function onEndShowStyles($action) + { + $action->element('style', null, '#site_notice { width: 100% }'); + return true; + } + + function onAutoload($cls) + { + $dir = dirname(__FILE__); + + switch ($cls) + { + case 'SiteNoticeSection': + include_once $dir . '/'.strtolower($cls).'.php'; + return false; + default: + return true; + } + } +} diff --git a/plugins/SiteNoticeInSidebar/sitenoticesection.php b/plugins/SiteNoticeInSidebar/sitenoticesection.php new file mode 100644 index 0000000000..37c37edaf2 --- /dev/null +++ b/plugins/SiteNoticeInSidebar/sitenoticesection.php @@ -0,0 +1,67 @@ +. + * + * @category Site + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Site notice section + * + * @category Site + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class SiteNoticeSection extends Section +{ + var $text; + + function __construct($action, $text) + { + parent::__construct($action); + $this->text = $text; + } + + function title() + { + return _('Site notice'); + } + + function showContent() + { + $this->out->raw($this->text); + } +} From f1a14ba8015b690a10099f5d1e41ff320d2b6b88 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 4 Apr 2011 12:07:35 -0400 Subject: [PATCH 29/42] add rss.me to notice source list --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index dec8080a01..70b926730e 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -47,6 +47,7 @@ VALUES ('qwit', 'Qwit', 'http://code.google.com/p/qwit/', now()), ('royalewithcheese','Royale With Cheese','http://p.hellyeah.org/', now()), ('rssdent','rssdent','http://github.com/zcopley/rssdent/tree/master', now()), + ('rss.me','rss.me','http://rss.me/', now()), ('rygh.no','rygh.no','http://rygh.no/', now()), ('ryghsms','ryghsms','http://sms.rygh.no/', now()), ('smob','SMOB','http://smob.sioc-project.org/', now()), From 2d420b46611682d250bb23032fcb5d0376fb6460 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 27 Apr 2011 19:40:43 +0000 Subject: [PATCH 30/42] Fix URLs to reflect change in reCAPTCHA API --- plugins/Recaptcha/RecaptchaPlugin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/Recaptcha/RecaptchaPlugin.php b/plugins/Recaptcha/RecaptchaPlugin.php index 0c46a33e0b..4e28e850cc 100644 --- a/plugins/Recaptcha/RecaptchaPlugin.php +++ b/plugins/Recaptcha/RecaptchaPlugin.php @@ -77,10 +77,10 @@ class RecaptchaPlugin extends Plugin { if (isset($action->recaptchaPluginNeedsOutput) && $action->recaptchaPluginNeedsOutput) { // Load the AJAX API - if ($this->checkssl()) { - $url = "https://api-secure.recaptcha.net/js/recaptcha_ajax.js"; + if (StatusNet::isHTTPS()) { + $url = "https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"; } else { - $url = "http://api.recaptcha.net/js/recaptcha_ajax.js"; + $url = "http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"; } $action->script($url); From 83397e28b8459962ae291a45e6c566bccb93a454 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 27 Apr 2011 19:40:43 +0000 Subject: [PATCH 31/42] Fix URLs to reflect change in reCAPTCHA API --- plugins/Recaptcha/RecaptchaPlugin.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/Recaptcha/RecaptchaPlugin.php b/plugins/Recaptcha/RecaptchaPlugin.php index 0c46a33e0b..4e28e850cc 100644 --- a/plugins/Recaptcha/RecaptchaPlugin.php +++ b/plugins/Recaptcha/RecaptchaPlugin.php @@ -77,10 +77,10 @@ class RecaptchaPlugin extends Plugin { if (isset($action->recaptchaPluginNeedsOutput) && $action->recaptchaPluginNeedsOutput) { // Load the AJAX API - if ($this->checkssl()) { - $url = "https://api-secure.recaptcha.net/js/recaptcha_ajax.js"; + if (StatusNet::isHTTPS()) { + $url = "https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"; } else { - $url = "http://api.recaptcha.net/js/recaptcha_ajax.js"; + $url = "http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"; } $action->script($url); From 6b1732d9a2e7084b571051406f5f115f391c5030 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 10:43:47 -0700 Subject: [PATCH 32/42] remove object nav for search --- lib/searchaction.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/searchaction.php b/lib/searchaction.php index 030d2bb724..fd5f0b3ff5 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -62,20 +62,6 @@ class SearchAction extends Action $this->showPage(); } - /** - * Show tabset for this page - * - * Uses the SearchGroupNav widget - * - * @return void - * @see SearchGroupNav - */ - function showObjectNav() - { - $nav = new SearchGroupNav($this, $this->trimmed('q')); - $nav->show(); - } - function showTop($arr=null) { $error = null; From f67607d2f1371e3991042aecea8e1d9fb68bf1ad Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 10:48:12 -0700 Subject: [PATCH 33/42] change 'You and friends' to 'Home' --- actions/all.php | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/actions/all.php b/actions/all.php index f558c3925f..388f24daad 100644 --- a/actions/all.php +++ b/actions/all.php @@ -84,12 +84,12 @@ class AllAction extends ProfileAction function title() { - if ($this->page > 1) { - // TRANS: Page title. %1$s is user nickname, %2$d is page number - return sprintf(_('%1$s and friends, page %2$d'), $this->user->nickname, $this->page); + $user = common_current_user(); + if ($user->id == $this->user->id) { + return _('Home'); } else { - // TRANS: Page title. %s is user nickname - return sprintf(_("%s and friends"), $this->user->nickname); + $profile = $this->user->getProfile(); + return sprintf(_("%s's Home"), $profile->getBestName()); } } @@ -190,18 +190,6 @@ class AllAction extends ProfileAction // $pop = new InboxTagCloudSection($this, $this->user); // $pop->show(); } - - function showPageTitle() - { - $user = common_current_user(); - if ($user && ($user->id == $this->user->id)) { - // TRANS: H1 text for page when viewing a list for self. - $this->element('h1', null, _("You and friends")); - } else { - // TRANS: H1 text for page. %s is a user nickname. - $this->element('h1', null, sprintf(_('%s and friends'), $this->user->nickname)); - } - } } class ThreadingInboxNoticeStream extends ThreadingNoticeStream From be57e253fb40097864cfbcde8efa71e6a187fd94 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 10:49:46 -0700 Subject: [PATCH 34/42] 'Home' to 'Home timeline' --- actions/all.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/all.php b/actions/all.php index 388f24daad..8ee3ec3fa6 100644 --- a/actions/all.php +++ b/actions/all.php @@ -86,10 +86,10 @@ class AllAction extends ProfileAction { $user = common_current_user(); if ($user->id == $this->user->id) { - return _('Home'); + return _('Home timeline'); } else { $profile = $this->user->getProfile(); - return sprintf(_("%s's Home"), $profile->getBestName()); + return sprintf(_("%s's home timeline"), $profile->getBestName()); } } From 914de296a15593a3df2ded680c177aaf24b727c7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 11:05:38 -0700 Subject: [PATCH 35/42] send a confirmation email when registering by script --- plugins/EmailRegistration/scripts/registeremailuser.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/EmailRegistration/scripts/registeremailuser.php b/plugins/EmailRegistration/scripts/registeremailuser.php index a8c942d3dd..a9eff9a848 100644 --- a/plugins/EmailRegistration/scripts/registeremailuser.php +++ b/plugins/EmailRegistration/scripts/registeremailuser.php @@ -20,11 +20,14 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); +$shortoptions = 'w'; +$longoptions = array('welcome'); + $helptext = << Options: --e --email Send a confirmation message to the email address +-w --welcome Send a welcome email register a new user by email address. @@ -40,7 +43,7 @@ $email = $args[0]; $confirm = EmailRegistrationPlugin::registerEmail($email); -if (have_option('e', 'email')) { +if (have_option('w', 'welcome')) { EmailRegistrationPlugin::sendConfirmEmail($confirm); } From b432cc72c91793c24981d799a0eabbf03d5132da Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 11:10:21 -0700 Subject: [PATCH 36/42] optionally send welcome email in installforemail.php --- .../DomainStatusNetwork/scripts/installforemail.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/DomainStatusNetwork/scripts/installforemail.php b/plugins/DomainStatusNetwork/scripts/installforemail.php index a1f7a65cd3..037e0cad1f 100644 --- a/plugins/DomainStatusNetwork/scripts/installforemail.php +++ b/plugins/DomainStatusNetwork/scripts/installforemail.php @@ -22,8 +22,15 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); +$shortoptions = 'w'; +$longoptions = array('welcome'); + $helptext = << +Create a new account and, if necessary, a new network for the given email address + +-w --welcome Send a welcome email END_OF_INSTALLFOREMAIL_HELP; @@ -54,6 +61,10 @@ StatusNet::switchSite($sn->nickname); $confirm = EmailRegistrationPlugin::registerEmail($email); +if (have_option('w', 'welcome')) { + EmailRegistrationPlugin::sendConfirmEmail($confirm); +} + $confirmUrl = common_local_url('register', array('code' => $confirm->code)); print $confirmUrl."\n"; From c46406b209d36f697d419e2bcb6c4e37a3e660fd Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 11:28:49 -0700 Subject: [PATCH 37/42] low-level hook for loading templates --- lib/docfile.php | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/docfile.php b/lib/docfile.php index 982177315a..e396870695 100644 --- a/lib/docfile.php +++ b/lib/docfile.php @@ -63,24 +63,29 @@ class DocFile $filename = null; - foreach ($paths as $path) { + if (Event::handle('StartDocFileForTitle', array($title, &$paths, &$filename))) { - $def = $path.'/'.$title; + foreach ($paths as $path) { - if (!file_exists($def)) { - $def = null; + $def = $path.'/'.$title; + + if (!file_exists($def)) { + $def = null; + } + + $lang = glob($path.'/'.$title.'.*'); + + if ($lang === false) { + $lang = array(); + } + + if (!empty($lang) || !empty($def)) { + $filename = self::negotiateLanguage($lang, $def); + break; + } } - $lang = glob($path.'/'.$title.'.*'); - - if ($lang === false) { - $lang = array(); - } - - if (!empty($lang) || !empty($def)) { - $filename = self::negotiateLanguage($lang, $def); - break; - } + Event::handle('EndDocFileForTitle', array($title, $paths, &$filename)); } if (empty($filename)) { From 332b9400c65bb85a7ccc8e6a873be9e7f4e1776a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 11:30:56 -0700 Subject: [PATCH 38/42] Document new docfile events --- EVENTS.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/EVENTS.txt b/EVENTS.txt index 5bf6078a1c..e1620a7e2a 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -1381,3 +1381,13 @@ StartRegisterSuccess: Before showing the registration success message StartRegisterSuccess: After showing the registration success message - $action: the registration action + +StartDocFileForTitle: Before searching for a doc or mail template +- $title: Title we're looking for +- &$paths: Paths we're searching +- &$filename: Filename so far (set this if you want) + +EndDocFileForTitle: After searching for a doc or mail template +- $title: Title we looked for +- $paths: Paths we searched +- &$filename: Filename so far (set this if you want) From 1b5bd8991bfb3e0b6891b464e9b1f172ce79f72e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 11:37:03 -0700 Subject: [PATCH 39/42] use a template for confirmation email --- .../EmailRegistrationPlugin.php | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/plugins/EmailRegistration/EmailRegistrationPlugin.php b/plugins/EmailRegistration/EmailRegistrationPlugin.php index 548702514a..8759614129 100644 --- a/plugins/EmailRegistration/EmailRegistrationPlugin.php +++ b/plugins/EmailRegistration/EmailRegistrationPlugin.php @@ -155,7 +155,7 @@ class EmailRegistrationPlugin extends Plugin return $nickname; } - static function sendConfirmEmail($confirm) + static function sendConfirmEmail($confirm, $title=null) { $sitename = common_config('site', 'name'); @@ -165,25 +165,31 @@ class EmailRegistrationPlugin extends Plugin $headers['To'] = trim($confirm->address); // TRANS: Subject for confirmation e-mail. // TRANS: %s is the StatusNet sitename. - $headers['Subject'] = sprintf(_m('Confirm your registration on %s'), $sitename); + $headers['Subject'] = sprintf(_m('Welcome to %s'), $sitename); + $headers['Content-Type'] = 'text/html; charset=UTF-8'; $confirmUrl = common_local_url('register', array('code' => $confirm->code)); - // TRANS: Body for confirmation e-mail. - // TRANS: %1$s is the StatusNet sitename, %2$s is the confirmation URL. - $body = sprintf(_m('Someone (probably you) has requested an account on %1$s using this email address.'. - "\n". - 'To confirm the address, click the following URL or copy it into the address bar of your browser.'. - "\n". - '%2$s'. - "\n". - 'If it was not you, you can safely ignore this message.'), - $sitename, - $confirmUrl); + if (empty($title)) { + $title = 'confirmemailreg'; + } + + $confirmTemplate = DocFile::forTitle($title, DocFile::mailPaths()); + + $body = $confirmTemplate->toHTML(array('confirmurl' => $confirmUrl)); mail_send($recipients, $headers, $body); } + function onEndDocFileForTitle($title, $paths, &$filename) + { + if ($title == 'confirmemailreg' && empty($filename)) { + $filename = dirname(__FILE__).'/mail-src/'.$title; + return false; + } + return true; + } + function onPluginVersion(&$versions) { $versions[] = array('name' => 'EmailRegistration', From aef62ccbcc5930692b86c2136fe15df6b9b0cbea Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 11:37:32 -0700 Subject: [PATCH 40/42] Option for custom template for confirmation email --- .../scripts/installforemail.php | 15 +++++++++++---- .../scripts/registeremailuser.php | 15 +++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/plugins/DomainStatusNetwork/scripts/installforemail.php b/plugins/DomainStatusNetwork/scripts/installforemail.php index 037e0cad1f..98ce620c28 100644 --- a/plugins/DomainStatusNetwork/scripts/installforemail.php +++ b/plugins/DomainStatusNetwork/scripts/installforemail.php @@ -22,15 +22,16 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); -$shortoptions = 'w'; -$longoptions = array('welcome'); +$shortoptions = 'wt::'; +$longoptions = array('welcome', 'template='); $helptext = << Create a new account and, if necessary, a new network for the given email address --w --welcome Send a welcome email +-w --welcome Send a welcome email +-t --template= Use this email template END_OF_INSTALLFOREMAIL_HELP; @@ -62,7 +63,13 @@ StatusNet::switchSite($sn->nickname); $confirm = EmailRegistrationPlugin::registerEmail($email); if (have_option('w', 'welcome')) { - EmailRegistrationPlugin::sendConfirmEmail($confirm); + if (have_option('t', 'template')) { + // use the provided template + EmailRegistrationPlugin::sendConfirmEmail($confirm, get_option_value('t', 'template')); + } else { + // use the default template + EmailRegistrationPlugin::sendConfirmEmail($confirm); + } } $confirmUrl = common_local_url('register', array('code' => $confirm->code)); diff --git a/plugins/EmailRegistration/scripts/registeremailuser.php b/plugins/EmailRegistration/scripts/registeremailuser.php index a9eff9a848..02915240d3 100644 --- a/plugins/EmailRegistration/scripts/registeremailuser.php +++ b/plugins/EmailRegistration/scripts/registeremailuser.php @@ -20,14 +20,15 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); -$shortoptions = 'w'; -$longoptions = array('welcome'); +$shortoptions = 'wt::'; +$longoptions = array('welcome', 'template='); $helptext = << Options: --w --welcome Send a welcome email +-w --welcome Send a welcome email +-t --template= Use this email template register a new user by email address. @@ -44,7 +45,13 @@ $email = $args[0]; $confirm = EmailRegistrationPlugin::registerEmail($email); if (have_option('w', 'welcome')) { - EmailRegistrationPlugin::sendConfirmEmail($confirm); + if (have_option('t', 'template')) { + // use the provided template + EmailRegistrationPlugin::sendConfirmEmail($confirm, get_option_value('t', 'template')); + } else { + // use the default template + EmailRegistrationPlugin::sendConfirmEmail($confirm); + } } $confirmUrl = common_local_url('register', array('code' => $confirm->code)); From 7e1ae44fad9dba14fc3bac75a9fcc666f210b82e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 12:25:34 -0700 Subject: [PATCH 41/42] source for registration email confirmation --- plugins/EmailRegistration/mail-src/confirmemailreg | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 plugins/EmailRegistration/mail-src/confirmemailreg diff --git a/plugins/EmailRegistration/mail-src/confirmemailreg b/plugins/EmailRegistration/mail-src/confirmemailreg new file mode 100644 index 0000000000..954a2c0dfc --- /dev/null +++ b/plugins/EmailRegistration/mail-src/confirmemailreg @@ -0,0 +1,7 @@ +Someone (probably you) has requested an account on %%site.name%% using this email address. + +To confirm the address, click the following URL or copy it into the address bar of your browser. + +> [%%arg.confirmurl%%](%%arg.confirmurl%%) + +If it was not you, you can safely ignore this message. From d8151311ee3aa4e69e7910e97687da9d5def3970 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 4 May 2011 14:46:26 -0700 Subject: [PATCH 42/42] Revert "add rss.me to notice source list" This reverts commit f1a14ba8015b690a10099f5d1e41ff320d2b6b88. --- db/notice_source.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/db/notice_source.sql b/db/notice_source.sql index 70b926730e..dec8080a01 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -47,7 +47,6 @@ VALUES ('qwit', 'Qwit', 'http://code.google.com/p/qwit/', now()), ('royalewithcheese','Royale With Cheese','http://p.hellyeah.org/', now()), ('rssdent','rssdent','http://github.com/zcopley/rssdent/tree/master', now()), - ('rss.me','rss.me','http://rss.me/', now()), ('rygh.no','rygh.no','http://rygh.no/', now()), ('ryghsms','ryghsms','http://sms.rygh.no/', now()), ('smob','SMOB','http://smob.sioc-project.org/', now()),