From 3d62c1cf5114760c0a7b97cd69ba363ac059e215 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 29 Dec 2010 16:15:57 -0800 Subject: [PATCH 01/31] 0.9.7alpha1 --- lib/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common.php b/lib/common.php index 5505dc39da..22890b5cb7 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'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release' +define('STATUSNET_LIFECYCLE', 'alpha1'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release' define('STATUSNET_VERSION', STATUSNET_BASE_VERSION . STATUSNET_LIFECYCLE); define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility From 3b5c3d2c8428e1072a2944f0b8adfa79574bf1f6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 30 Dec 2010 12:15:34 -0800 Subject: [PATCH 02/31] UUID-generation tools --- lib/uuid.php | 109 +++++++++++++++++++++++++++++++++++++++++++++ tests/UUIDTest.php | 25 +++++++++++ 2 files changed, 134 insertions(+) create mode 100644 lib/uuid.php create mode 100644 tests/UUIDTest.php diff --git a/lib/uuid.php b/lib/uuid.php new file mode 100644 index 0000000000..93153504f2 --- /dev/null +++ b/lib/uuid.php @@ -0,0 +1,109 @@ +. + * + * @category UUID + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 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); +} + +/** + * UUID generation + * + * @category General + * @package StatusNet + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class UUID +{ + protected $str = null; + + /** + * Constructor for a UUID + * + * Uses gen() to create a new UUID + */ + + function __construct() + { + $this->str = self::gen(); + } + + /** + * For serializing to a string + * + * @return string version of self + */ + + function __toString() + { + return $this->str; + } + + /** + * For serializing to a string + * + * @return string version of self + */ + + function getString() + { + return $this->str; + } + + /** + * Generate a new UUID + * + * @return 36-char v4 (random-ish) UUID + */ + + static function gen() + { + return sprintf('%s-%s-%04x-%04x-%s', + // 32 bits for "time_low" + common_good_rand(4), + // 16 bits for "time_mid" + common_good_rand(2), + // 16 bits for "time_hi_and_version", + // four most significant bits holds version number 4 + (hexdec(common_good_rand(2)) & 0x0fff) | 0x4000, + // 16 bits, 8 bits for "clk_seq_hi_res", + // 8 bits for "clk_seq_low", + // two most significant bits holds zero and one + // for variant DCE1.1 + (hexdec(common_good_rand(2)) & 0x3fff) | 0x8000, + // 48 bits for "node" + common_good_rand(6)); + } +} diff --git a/tests/UUIDTest.php b/tests/UUIDTest.php new file mode 100644 index 0000000000..de256ffa1f --- /dev/null +++ b/tests/UUIDTest.php @@ -0,0 +1,25 @@ +assertRegExp('/^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/', + $result); + // Check version number + $this->assertEquals(0x4000, hexdec(substr($result, 14, 4)) & 0xF000); + $this->assertEquals(0x8000, hexdec(substr($result, 19, 4)) & 0xC000); + } +} + From 6fc7e5b05b1106cfcb2bf61cb788dd3aa38fa6f7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 30 Dec 2010 13:21:14 -0800 Subject: [PATCH 03/31] Use UUIDs for Bookmark unique ID I was trying to generate URIs for Bookmarks based on (profile, crc32(url), created). I failed at that. CRC32s are unsigned ints, and our schema code didn't like that. On top of that, my code to encode and restore created timestamps was problematic. So, I switched back to using a meaningless unique ID for Bookmarks. One way to do this would be to use an auto-incrementing integer ID. However, we've been kind of crabbed out a few times for exposing auto-incrementing integer IDs as URIs, so I thought maybe using a random UUID would be a better way to do it. So, this patch sets random UUIDs for URIs of bookmarks. --- plugins/Bookmark/Bookmark.php | 69 +++++++---------------------- plugins/Bookmark/BookmarkPlugin.php | 31 +++++-------- plugins/Bookmark/showbookmark.php | 52 +++++++--------------- 3 files changed, 43 insertions(+), 109 deletions(-) diff --git a/plugins/Bookmark/Bookmark.php b/plugins/Bookmark/Bookmark.php index 61fe3c5b97..4ee287fb65 100644 --- a/plugins/Bookmark/Bookmark.php +++ b/plugins/Bookmark/Bookmark.php @@ -46,13 +46,13 @@ if (!defined('STATUSNET')) { class Bookmark extends Memcached_DataObject { public $__table = 'bookmark'; // table name - public $profile_id; // int(4) primary_key not_null - public $url; // varchar(255) primary_key not_null - public $title; // varchar(255) - public $description; // text - public $uri; // varchar(255) - public $url_crc32; // int(4) not_null - public $created; // datetime + public $id; // char(36) primary_key not_null + public $profile_id; // int(4) not_null + public $url; // varchar(255) not_null + public $title; // varchar(255) + public $description; // text + public $uri; // varchar(255) + public $created; // datetime /** * Get an instance by key @@ -100,12 +100,12 @@ class Bookmark extends Memcached_DataObject function table() { - return array('profile_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, + return array('id' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL, + 'profile_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, 'url' => DB_DATAOBJECT_STR, 'title' => DB_DATAOBJECT_STR, 'description' => DB_DATAOBJECT_STR, 'uri' => DB_DATAOBJECT_STR, - 'url_crc32' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, 'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL); } @@ -129,8 +129,7 @@ class Bookmark extends Memcached_DataObject function keyTypes() { - return array('profile_id' => 'K', - 'url' => 'K', + return array('id' => 'K', 'uri' => 'U'); } @@ -169,36 +168,16 @@ class Bookmark extends Memcached_DataObject static function getByURL($profile, $url) { - return self::pkeyGet(array('profile_id' => $profile->id, - 'url' => $url)); - return null; - } - - /** - * Get the bookmark that a user made for an URL - * - * @param Profile $profile Profile to check for - * @param integer $crc32 CRC-32 of URL to check for - * - * @return array Bookmark objects found (usually 1 or 0) - */ - - static function getByCRC32($profile, $crc32) - { - $bookmarks = array(); - $nb = new Bookmark(); $nb->profile_id = $profile->id; - $nb->url_crc32 = $crc32; + $nb->url = $url; - if ($nb->find()) { - while ($nb->fetch()) { - $bookmarks[] = clone($nb); - } + if ($nb->find(true)) { + return $nb; + } else { + return null; } - - return $bookmarks; } /** @@ -240,11 +219,11 @@ class Bookmark extends Memcached_DataObject $nb = new Bookmark(); + $nb->id = UUID::gen(); $nb->profile_id = $profile->id; $nb->url = $url; $nb->title = $title; $nb->description = $description; - $nb->url_crc32 = crc32($nb->url); if (array_key_exists('created', $options)) { $nb->created = $options['created']; @@ -255,22 +234,8 @@ class Bookmark extends Memcached_DataObject if (array_key_exists('uri', $options)) { $nb->uri = $options['uri']; } else { - $dt = new DateTime($nb->created, new DateTimeZone('UTC')); - - // I posit that it's sufficiently impossible - // for the same user to generate two CRC-32-clashing - // URLs in the same second that this is a safe unique identifier. - // If you find a real counterexample, contact me at acct:evan@status.net - // and I will publicly apologize for my hubris. - - $created = $dt->format('YmdHis'); - - $crc32 = sprintf('%08x', $nb->url_crc32); - $nb->uri = common_local_url('showbookmark', - array('user' => $profile->id, - 'created' => $created, - 'crc32' => $crc32)); + array('id' => $nb->id)); } $nb->insert(); diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index 4f31349801..99f25c64b8 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -86,16 +86,21 @@ class BookmarkPlugin extends Plugin // For storing user-submitted flags on profiles $schema->ensureTable('bookmark', - array(new ColumnDef('profile_id', + array(new ColumnDef('id', + 'char', + 36, + false, + 'PRI'), + new ColumnDef('profile_id', 'integer', null, false, - 'PRI'), + 'MUL'), new ColumnDef('url', 'varchar', 255, false, - 'PRI'), + 'MUL'), new ColumnDef('title', 'varchar', 255), @@ -106,26 +111,12 @@ class BookmarkPlugin extends Plugin 255, false, 'UNI'), - new ColumnDef('url_crc32', - 'integer unsigned', - null, - false, - 'MUL'), new ColumnDef('created', 'datetime', null, false, 'MUL'))); - try { - $schema->createIndex('bookmark', - array('profile_id', - 'url_crc32'), - 'bookmark_profile_url_idx'); - } catch (Exception $e) { - common_log(LOG_ERR, $e->getMessage()); - } - return true; } @@ -216,11 +207,9 @@ class BookmarkPlugin extends Plugin $m->connect('main/bookmark/import', array('action' => 'importdelicious')); - $m->connect('bookmark/:user/:created/:crc32', + $m->connect('bookmark/:id', array('action' => 'showbookmark'), - array('user' => '[0-9]+', - 'created' => '[0-9]{14}', - 'crc32' => '[0-9a-f]{8}')); + array('id' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')); $m->connect('notice/by-url/:id', array('action' => 'noticebyurl'), diff --git a/plugins/Bookmark/showbookmark.php b/plugins/Bookmark/showbookmark.php index e9e656f84c..6bebffb68e 100644 --- a/plugins/Bookmark/showbookmark.php +++ b/plugins/Bookmark/showbookmark.php @@ -61,7 +61,22 @@ class ShowbookmarkAction extends ShownoticeAction { OwnerDesignAction::prepare($argarray); - $this->user = User::staticGet('id', $this->trimmed('user')); + $this->id = $this->trimmed('id'); + + $this->bookmark = Bookmark::staticGet('id', $this->id); + + if (empty($this->bookmark)) { + throw new ClientException(_('No such bookmark.'), 404); + } + + $this->notice = Notice::staticGet('uri', $this->bookmark->uri); + + if (empty($this->notice)) { + // Did we used to have it, and it got deleted? + throw new ClientException(_('No such bookmark.'), 404); + } + + $this->user = User::staticGet('id', $this->bookmark->profile_id); if (empty($this->user)) { throw new ClientException(_('No such user.'), 404); @@ -75,41 +90,6 @@ class ShowbookmarkAction extends ShownoticeAction $this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE); - sscanf($this->trimmed('crc32'), '%08x', $crc32); - - if (empty($crc32)) { - throw new ClientException(_('No such URL.'), 404); - } - - $dt = new DateTime($this->trimmed('created'), - new DateTimeZone('UTC')); - - if (empty($dt)) { - throw new ClientException(_('No such create date.'), 404); - } - - $bookmarks = Bookmark::getByCRC32($this->profile, - $crc32); - - foreach ($bookmarks as $bookmark) { - $bdt = new DateTime($bookmark->created, new DateTimeZone('UTC')); - if ($bdt->format('U') == $dt->format('U')) { - $this->bookmark = $bookmark; - break; - } - } - - if (empty($this->bookmark)) { - throw new ClientException(_('No such bookmark.'), 404); - } - - $this->notice = Notice::staticGet('uri', $this->bookmark->uri); - - if (empty($this->notice)) { - // Did we used to have it, and it got deleted? - throw new ClientException(_('No such bookmark.'), 404); - } - return true; } From 63c95484bd658056f36b726f1751ad310a85f5b9 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 30 Dec 2010 13:21:59 -0800 Subject: [PATCH 04/31] Update ActivityCreationTests for our switch away from the obsolete --- tests/ActivityGenerationTests.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/ActivityGenerationTests.php b/tests/ActivityGenerationTests.php index b9e74a570a..8cf1b009ed 100644 --- a/tests/ActivityGenerationTests.php +++ b/tests/ActivityGenerationTests.php @@ -194,7 +194,7 @@ class ActivityGenerationTests extends PHPUnit_Framework_TestCase $actor = ActivityUtils::child($element, 'actor', Activity::SPEC); $this->assertFalse(is_null($author)); - $this->assertFalse(is_null($actor)); + $this->assertTrue(is_null($actor)); // is obsolete, no longer added } public function testAuthorContent() @@ -213,6 +213,9 @@ class ActivityGenerationTests extends PHPUnit_Framework_TestCase $this->assertEquals($this->author1->uri, ActivityUtils::childContent($author, 'uri')); } + /** + * We no longer create entries, they have merged to + */ public function testActorContent() { $notice = $this->_fakeNotice(); @@ -225,8 +228,7 @@ class ActivityGenerationTests extends PHPUnit_Framework_TestCase $actor = ActivityUtils::child($element, 'actor', Activity::SPEC); - $this->assertEquals($this->author1->uri, ActivityUtils::childContent($actor, 'id')); - $this->assertEquals($this->author1->nickname, ActivityUtils::childContent($actor, 'title')); + $this->assertEquals($actor, null); } public function testReplyLink() From b00a3cd4e4b279b075e7786d850f63dacdd9ee98 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 30 Dec 2010 13:37:05 -0800 Subject: [PATCH 05/31] Make sure the UUIDs are unique too :) --- tests/UUIDTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/UUIDTest.php b/tests/UUIDTest.php index de256ffa1f..e78d5ce1bc 100644 --- a/tests/UUIDTest.php +++ b/tests/UUIDTest.php @@ -21,5 +21,17 @@ class UUIDTest extends PHPUnit_Framework_TestCase $this->assertEquals(0x4000, hexdec(substr($result, 14, 4)) & 0xF000); $this->assertEquals(0x8000, hexdec(substr($result, 19, 4)) & 0xC000); } + + public function testUnique() + { + $reps = 100; + $ids = array(); + + for ($i = 0; $i < $reps; $i++) { + $ids[] = UUID::gen(); + } + + $this->assertEquals(count($ids), count(array_unique($ids)), "UUIDs must be unique"); + } } From b71a09a1a9a8eedcd0e2214c5c998b0707a2ee70 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 30 Dec 2010 16:14:41 -0800 Subject: [PATCH 06/31] Tweak the post-form return on bookmarklet if we're not in a popup that we can close --- plugins/Bookmark/bookmarkpopup.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/Bookmark/bookmarkpopup.js b/plugins/Bookmark/bookmarkpopup.js index 29f314ed06..4904b07e24 100644 --- a/plugins/Bookmark/bookmarkpopup.js +++ b/plugins/Bookmark/bookmarkpopup.js @@ -2,6 +2,13 @@ $(document).ready( function() { var form = $('#form_new_bookmark'); form.append(''); + function doClose() { + self.close(); + // If in popup blocker situation, we'll have to redirect back. + setTimeout(function() { + window.location = $('#url').val(); + }, 100); + } form.ajaxForm({dataType: 'xml', timeout: '60000', beforeSend: function(formData) { @@ -11,12 +18,12 @@ $(document).ready( error: function (xhr, textStatus, errorThrown) { form.removeClass('processing'); form.find('#submit').removeClass('disabled'); - self.close(); + doClose(); }, success: function(data, textStatus) { form.removeClass('processing'); form.find('#submit').removeClass('disabled'); - self.close(); + doClose(); }}); } From 682e11bb8b09588d92960d45c08c2a828be0a374 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 30 Dec 2010 16:21:22 -0800 Subject: [PATCH 07/31] don't show some bookmark elements if empty --- plugins/Bookmark/BookmarkPlugin.php | 79 +++++++++++++++++------------ plugins/Bookmark/bookmark.css | 1 + 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index 99f25c64b8..e6590bce34 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -263,13 +263,15 @@ class BookmarkPlugin extends Plugin $att->noticeCount()); } - $out->elementStart('ul', array('class' => 'bookmark_tags')); - // Replies look like "for:" tags $replies = $nli->notice->getReplies(); + $tags = $nli->notice->getTags(); - if (!empty($replies)) { + if (!empty($replies) || !empty($tags)) { + + $out->elementStart('ul', array('class' => 'bookmark_tags')); + foreach ($replies as $reply) { $other = Profile::staticGet('id', $reply); $out->elementStart('li'); @@ -280,45 +282,59 @@ class BookmarkPlugin extends Plugin $out->elementEnd('li'); $out->text(' '); } + + foreach ($tags as $tag) { + $out->elementStart('li'); + $out->element('a', + array('rel' => 'tag', + 'href' => Notice_tag::url($tag)), + $tag); + $out->elementEnd('li'); + $out->text(' '); + } + + $out->elementEnd('ul'); } - $tags = $nli->notice->getTags(); - - foreach ($tags as $tag) { - $out->elementStart('li'); - $out->element('a', - array('rel' => 'tag', - 'href' => Notice_tag::url($tag)), - $tag); - $out->elementEnd('li'); - $out->text(' '); + if (!empty($nb->description)) { + $out->element('p', + array('class' => 'bookmark_description'), + $nb->description); } - $out->elementEnd('ul'); - - $out->element('p', - array('class' => 'bookmark_description'), - $nb->description); - if (common_config('attachments', 'show_thumbs')) { - $al = new InlineAttachmentList($notice, $out); - $al->show(); + $haveThumbs = false; + foreach ($atts as $check) { + $thumbnail = File_thumbnail::staticGet('file_id', $check->id); + if (!empty($thumbnail)) { + $haveThumbs = true; + break; + } + } + if ($haveThumbs) { + $al = new InlineAttachmentList($notice, $out); + $al->show(); + } } - $out->elementStart('p', array('style' => 'float: left')); + $out->elementStart('p', array('class' => 'bookmark_info')); $avatar = $profile->getAvatar(AVATAR_MINI_SIZE); - $out->element('img', array('src' => ($avatar) ? - $avatar->displayUrl() : - Avatar::defaultImage(AVATAR_MINI_SIZE), - 'class' => 'avatar photo bookmark_avatar', - 'width' => AVATAR_MINI_SIZE, - 'height' => AVATAR_MINI_SIZE, - 'alt' => $profile->getBestName())); + $out->element('img', + array('src' => ($avatar) ? + $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_MINI_SIZE), + 'class' => 'avatar photo bookmark_avatar', + 'width' => AVATAR_MINI_SIZE, + 'height' => AVATAR_MINI_SIZE, + 'alt' => $profile->getBestName())); + $out->raw(' '); - $out->element('a', array('href' => $profile->profileurl, - 'title' => $profile->getBestName()), + + $out->element('a', + array('href' => $profile->profileurl, + 'title' => $profile->getBestName()), $profile->nickname); $nli->showNoticeLink(); @@ -758,4 +774,3 @@ class BookmarkPlugin extends Plugin $activity->objects[0]->type == ActivityObject::BOOKMARK); } } - diff --git a/plugins/Bookmark/bookmark.css b/plugins/Bookmark/bookmark.css index b86e749fd9..22e7f99ce4 100644 --- a/plugins/Bookmark/bookmark.css +++ b/plugins/Bookmark/bookmark.css @@ -2,3 +2,4 @@ .bookmark_mentions li { display: inline; } .bookmark_avatar { float: left } .bookmark_notice_count { float: right } +.bookmark_info { float: left } From 5d7f5212f0147a5d2b98fbeda9e97ede0a1cdfc6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 30 Dec 2010 16:54:01 -0800 Subject: [PATCH 08/31] switch bookmark CSS classes to use dash instead of underscore --- plugins/Bookmark/BookmarkPlugin.php | 13 +++++++------ plugins/Bookmark/bookmark.css | 11 ++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index e6590bce34..faddf5aafa 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -251,14 +251,15 @@ class BookmarkPlugin extends Plugin } else { $out->elementStart('h3'); $out->element('a', - array('href' => $att->url), + array('href' => $att->url, + 'class' => 'bookmark-title entry-title'), $nb->title); $out->elementEnd('h3'); $countUrl = common_local_url('noticebyurl', array('id' => $att->id)); - $out->element('a', array('class' => 'bookmark_notice_count', + $out->element('a', array('class' => 'bookmark-notice-count', 'href' => $countUrl), $att->noticeCount()); } @@ -270,7 +271,7 @@ class BookmarkPlugin extends Plugin if (!empty($replies) || !empty($tags)) { - $out->elementStart('ul', array('class' => 'bookmark_tags')); + $out->elementStart('ul', array('class' => 'bookmark-tags')); foreach ($replies as $reply) { $other = Profile::staticGet('id', $reply); @@ -298,7 +299,7 @@ class BookmarkPlugin extends Plugin if (!empty($nb->description)) { $out->element('p', - array('class' => 'bookmark_description'), + array('class' => 'bookmark-description'), $nb->description); } @@ -317,7 +318,7 @@ class BookmarkPlugin extends Plugin } } - $out->elementStart('p', array('class' => 'bookmark_info')); + $out->elementStart('p', array('class' => 'bookmark-info')); $avatar = $profile->getAvatar(AVATAR_MINI_SIZE); @@ -325,7 +326,7 @@ class BookmarkPlugin extends Plugin array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_MINI_SIZE), - 'class' => 'avatar photo bookmark_avatar', + 'class' => 'avatar photo bookmark-avatar', 'width' => AVATAR_MINI_SIZE, 'height' => AVATAR_MINI_SIZE, 'alt' => $profile->getBestName())); diff --git a/plugins/Bookmark/bookmark.css b/plugins/Bookmark/bookmark.css index 22e7f99ce4..6743622d2f 100644 --- a/plugins/Bookmark/bookmark.css +++ b/plugins/Bookmark/bookmark.css @@ -1,5 +1,6 @@ -.bookmark_tags li { display: inline; } -.bookmark_mentions li { display: inline; } -.bookmark_avatar { float: left } -.bookmark_notice_count { float: right } -.bookmark_info { float: left } +.bookmark-tags li { display: inline; } +.bookmark-mentions li { display: inline; } +.bookmark-avatar { float: left; } +.bookmark-notice-count { float: right; } +.bookmark-info { float: left; } +.bookmark-title { margin-left: 0px } From 66f6b2a3427212de020694cde1385eeb44f1ccd6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 30 Dec 2010 16:57:05 -0800 Subject: [PATCH 09/31] Events to hook for NoticeListElement
  • generation --- EVENTS.txt | 12 ++++++++++++ lib/noticelist.php | 16 ++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/EVENTS.txt b/EVENTS.txt index f7cc7df67c..6719ba737a 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -1045,3 +1045,15 @@ StartProfileSettingsActions: when we're showing account-management action list EndProfileSettingsActions: when we're showing account-management action list - $action: Action being shown (use for output) + +StartOpenNoticeListItemElement: Before the opening
  • of a notice list element +- $nli: The notice list item being shown + +EndOpenNoticeListItemElement: After the opening
  • of a notice list element +- $nli: The notice list item being shown + +StartCloseNoticeListItemElement: Before the closing
  • of a notice list element +- $nli: The notice list item being shown + +EndCloseNoticeListItemElement: After the closing of a notice list element +- $nli: The notice list item being shown diff --git a/lib/noticelist.php b/lib/noticelist.php index c6f964662f..7b2fbb1e7c 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -263,11 +263,12 @@ class NoticeListItem extends Widget function showStart() { - // XXX: RDFa - // TODO: add notice_type class e.g., notice_video, notice_image - $id = (empty($this->repeat)) ? $this->notice->id : $this->repeat->id; - $this->out->elementStart('li', array('class' => 'hentry notice', - 'id' => 'notice-' . $id)); + if (Event::handle('StartOpenNoticeListItemElement', array($this))) { + $id = (empty($this->repeat)) ? $this->notice->id : $this->repeat->id; + $this->out->elementStart('li', array('class' => 'hentry notice', + 'id' => 'notice-' . $id)); + Event::handle('EndOpenNoticeListItemElement', array($this)); + } } /** @@ -706,6 +707,9 @@ class NoticeListItem extends Widget function showEnd() { - $this->out->elementEnd('li'); + if (Event::handle('StartCloseNoticeListItemElement', array($this))) { + $this->out->elementEnd('li'); + Event::handle('EndCloseNoticeListItemElement', array($this)); + } } } From 5dfc9e1b185d841cbc4b3b85e984bf63dfa6508d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 30 Dec 2010 16:57:28 -0800 Subject: [PATCH 10/31] Generated an extra class on bookmark notice
  • s --- plugins/Bookmark/BookmarkPlugin.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index faddf5aafa..8eef609751 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -648,6 +648,27 @@ class BookmarkPlugin extends Plugin return true; } + /** + * Output our CSS class for bookmark notice list elements + * + * @param NoticeListItem $nli The item being shown + * + * @return boolean hook value + */ + + function onStartOpenNoticeListItemElement($nli) + { + $nb = Bookmark::getByNotice($nli->notice); + if (!empty($nb)) { + $id = (empty($nli->repeat)) ? $nli->notice->id : $nli->repeat->id; + $nli->out->elementStart('li', array('class' => 'hentry notice bookmark', + 'id' => 'notice-' . $id)); + Event::handle('EndOpenNoticeListItemElement', array($nli)); + return false; + } + return true; + } + /** * Save a remote bookmark (from Salmon or PuSH) * From 80e2f4f529cac935d69dfb42a5bfdef82aa00dad Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 30 Dec 2010 17:11:16 -0800 Subject: [PATCH 11/31] Fix up edge case in nickname processing: overlong display forms should be rejected before normalization (storage of display forms will also have fields with limited length) --- lib/nickname.php | 10 ++++++---- tests/NicknameTest.php | 9 +++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/nickname.php b/lib/nickname.php index 562f1e2052..4d3795e392 100644 --- a/lib/nickname.php +++ b/lib/nickname.php @@ -103,15 +103,17 @@ class Nickname */ public static function normalize($str) { + if (mb_strlen($str) > self::MAX_LEN) { + // Display forms must also fit! + throw new NicknameTooLongException(); + } + $str = trim($str); $str = str_replace('_', '', $str); $str = mb_strtolower($str); - $len = mb_strlen($str); - if ($len < 1) { + if (mb_strlen($str) < 1) { throw new NicknameEmptyException(); - } else if ($len > self::MAX_LEN) { - throw new NicknameTooLongException(); } if (!self::isCanonical($str)) { throw new NicknameInvalidException(); diff --git a/tests/NicknameTest.php b/tests/NicknameTest.php index f49aeba602..66e883c049 100644 --- a/tests/NicknameTest.php +++ b/tests/NicknameTest.php @@ -33,9 +33,14 @@ class NicknameTest extends PHPUnit_Framework_TestCase if ($expected === false) { if ($expectedException) { + if ($exception) { + $stuff = get_class($exception) . ': ' . $exception->getMessage(); + } else { + $stuff = var_export($exception, true); + } $this->assertTrue($exception && $exception instanceof $expectedException, "invalid input '$input' expected to fail with $expectedException, " . - "got " . get_class($exception) . ': ' . $exception->getMessage()); + "got $stuff"); } else { $this->assertTrue($normalized == false, "invalid input '$input' expected to fail"); @@ -104,7 +109,7 @@ class NicknameTest extends PHPUnit_Framework_TestCase array('', false, 'NicknameEmptyException'), array('___', false, 'NicknameEmptyException'), array('eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'), // 64 chars - array('eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_', 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'), // the _ will be trimmed off, remaining valid + array('eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee_', false, 'NicknameTooLongException'), // the _ is too long... array('eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', false, 'NicknameTooLongException'), // 65 chars -- too long ); } From 56875318489b11c96d0360f7458bb3c6f1a25dc9 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 31 Dec 2010 12:09:15 -0800 Subject: [PATCH 12/31] Bookmark plugin: graceful error out for failure to import a delicious bookmark due to it being already bookmarked --- .../Bookmark/deliciousbookmarkimporter.php | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/Bookmark/deliciousbookmarkimporter.php b/plugins/Bookmark/deliciousbookmarkimporter.php index 297ef81246..545c336860 100644 --- a/plugins/Bookmark/deliciousbookmarkimporter.php +++ b/plugins/Bookmark/deliciousbookmarkimporter.php @@ -96,13 +96,19 @@ class DeliciousBookmarkImporter extends QueueHandler $addDate = $a->getAttribute('add_date'); $created = common_sql_date(intval($addDate)); - $saved = Bookmark::saveNew($user->getProfile(), - $title, - $url, - $tags, - $description, - array('created' => $created, - 'distribute' => false)); + try { + $saved = Bookmark::saveNew($user->getProfile(), + $title, + $url, + $tags, + $description, + array('created' => $created, + 'distribute' => false)); + } catch (ClientException $e) { + // Most likely a duplicate -- continue on with the rest! + common_log(LOG_ERR, "Error importing delicious bookmark to $url: " . $e->getMessage()); + return true; + } return true; } From fedfde9bbb3c898328c6395a41c3243d6e97a2bf Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 31 Dec 2010 12:09:54 -0800 Subject: [PATCH 13/31] Bookmark plugin: fixes for bad DOM element nesting in delicious import data delicious bookmark exports use the godawful HTML bookmark file format that ancient versions of Netscape used (and has thus been the common import/export format for bookmarks since the dark ages of the web :) This arranges bookmark entries as an HTML definition list, using a lot of implied close tags (leaving off the and ). DOMDocument->loadHTML() uses libxml2's HTML mode, which generally does ok with muddling through things but apparently is really, really bad about handling those implied close tags. Sequences of adjacent
    elements (eg bookmark without a description, followed by another bookmark "
    "), end up interpreted as nested ("
    ") instead of as siblings ("
    "). The first round of code tried to resolve the nesting inline, but ended up a bit funky in places. I've replaced this with a standalone run through the data to re-order the elements, based on our knowing that
    and
    cannot directly contain one another; once that's done, our main logic loop can be a bit cleaner. I'm not 100% sure it's doing nested sublists correctly, but these don't seem to show up in delicious export (and even if they do, with the way we flatten the input it shouldn't make a difference). Also fixed a clearer edge case where some bookmarks didn't get imported when missing descriptions. --- plugins/Bookmark/deliciousbackupimporter.php | 117 ++++++++++++++++--- 1 file changed, 101 insertions(+), 16 deletions(-) diff --git a/plugins/Bookmark/deliciousbackupimporter.php b/plugins/Bookmark/deliciousbackupimporter.php index 1b55115d6d..bc5a91be80 100644 --- a/plugins/Bookmark/deliciousbackupimporter.php +++ b/plugins/Bookmark/deliciousbackupimporter.php @@ -65,7 +65,7 @@ class DeliciousBackupImporter extends QueueHandler * and import to StatusNet as Bookmark activities. * * The document format is terrible. It consists of a
    with - * a bunch of
    's, occasionally with
    's. + * a bunch of
    's, occasionally with
    's adding descriptions. * There are sometimes

    's lost inside. * * @param array $data pair of user, text @@ -99,6 +99,9 @@ class DeliciousBackupImporter extends QueueHandler } switch (strtolower($child->tagName)) { case 'dt': + //

    nodes contain primary information about a bookmark. + // We can't import the current one just yet though, since + // it may be followed by a
    . if (!empty($dt)) { // No DD provided $this->importBookmark($user, $dt); @@ -109,10 +112,13 @@ 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); $dt = null; $dd = null; + break; case 'p': common_log(LOG_INFO, 'Skipping the

    in the

    .'); break; @@ -126,6 +132,14 @@ class DeliciousBackupImporter extends QueueHandler $dt = $dd = null; } } + if (!empty($dt)) { + // There was a final bookmark without a description. + try { + $this->importBookmark($user, $dt); + } catch (Exception $e) { + common_log(LOG_ERR, $e->getMessage()); + } + } return true; } @@ -148,21 +162,6 @@ class DeliciousBackupImporter extends QueueHandler function importBookmark($user, $dt, $dd = null) { - // We have to go squirrelling around in the child nodes - // on the off chance that we've received another
    - // as a child. - - for ($i = 0; $i < $dt->childNodes->length; $i++) { - $child = $dt->childNodes->item($i); - if ($child->nodeType == XML_ELEMENT_NODE) { - if ($child->tagName == 'dt' && !is_null($dd)) { - $this->importBookmark($user, $dt); - $this->importBookmark($user, $child, $dd); - return; - } - } - } - $qm = QueueManager::get(); $qm->enqueue(array($user, $dt, $dd), 'dlcsbkmk'); @@ -188,9 +187,95 @@ class DeliciousBackupImporter extends QueueHandler error_reporting($old); if ($ok) { + foreach ($dom->getElementsByTagName('body') as $node) { + $this->fixListsIn($node); + } return $dom; } else { return null; } } + + + function fixListsIn(DOMNode $body) { + $toFix = array(); + + foreach ($body->childNodes as $node) { + if ($node->nodeType == XML_ELEMENT_NODE) { + $el = strtolower($node->nodeName); + if ($el == 'dl') { + $toFix[] = $node; + } + } + } + + foreach ($toFix as $node) { + $this->fixList($node); + } + } + + function fixList(DOMNode $list) { + $toFix = array(); + + foreach ($list->childNodes as $node) { + if ($node->nodeType == XML_ELEMENT_NODE) { + $el = strtolower($node->nodeName); + if ($el == 'dt' || $el == 'dd') { + $toFix[] = $node; + } + if ($el == 'dl') { + // Sublist. + // Technically, these can only appear inside a
    ... + $this->fixList($node); + } + } + } + + foreach ($toFix as $node) { + $this->fixListItem($node); + } + } + + function fixListItem(DOMNode $item) { + // The HTML parser in libxml2 doesn't seem to properly handle + // many cases of implied close tags, apparently because it doesn't + // understand the nesting rules specified in the HTML DTD. + // + // This leads to sequences of adjacent
    s or
    s being incorrectly + // interpreted as parent->child trees instead of siblings: + // + // When parsing this input: "
    aaa
    bbb" + // should be equivalent to: "
    aaa
    bbb
    " + // but we're seeing instead: "
    aaa
    bbb
    " + // + // It does at least know that going from dt to dd, or dd to dt, + // should make a break. + + $toMove = array(); + + foreach ($item->childNodes as $node) { + if ($node->nodeType == XML_ELEMENT_NODE) { + $el = strtolower($node->nodeName); + if ($el == 'dt' || $el == 'dd') { + // dt & dd cannot contain each other; + // This node was incorrectly placed; move it up a level! + $toMove[] = $node; + } + if ($el == 'dl') { + // Sublist. + // Technically, these can only appear inside a
    . + $this->fixList($node); + } + } + } + + $parent = $item->parentNode; + $next = $item->nextSibling; + foreach ($toMove as $node) { + $item->removeChild($node); + $parent->insertBefore($node, $next); + $this->fixListItem($node); + } + } + } From 3368c33be776e41d603ab1c2149fe8b111877beb Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 31 Dec 2010 12:33:51 -0800 Subject: [PATCH 14/31] Bookmark plugin: fix for delicious import with queues enabled We were passing DOM nodes directly into the queues for the final bookmark import stage; unfortunately these don't actually survive serialization. Moved the extraction of properties from the HTML up to the first-stage handler, so now we don't have to worry about moving DOM nodes from one handler to the next. Instead passing an associative array of properties, which is fed into the Bookmark::saveNew by the per-bookmark handler. --- plugins/Bookmark/deliciousbackupimporter.php | 33 +++++++++++++- .../Bookmark/deliciousbookmarkimporter.php | 44 ++++--------------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/plugins/Bookmark/deliciousbackupimporter.php b/plugins/Bookmark/deliciousbackupimporter.php index bc5a91be80..197c7a143b 100644 --- a/plugins/Bookmark/deliciousbackupimporter.php +++ b/plugins/Bookmark/deliciousbackupimporter.php @@ -162,9 +162,38 @@ class DeliciousBackupImporter extends QueueHandler function importBookmark($user, $dt, $dd = null) { + $as = $dt->getElementsByTagName('a'); + + if ($as->length == 0) { + throw new ClientException(_("No tag in a
    .")); + } + + $a = $as->item(0); + + $private = $a->getAttribute('private'); + + if ($private != 0) { + throw new ClientException(_('Skipping private bookmark.')); + } + + if (!empty($dd)) { + $description = $dd->nodeValue; + } else { + $description = null; + } + $addDate = $a->getAttribute('add_date'); + + $data = array( + 'profile_id' => $user->id, + 'title' => $a->nodeValue, + 'description' => $description, + 'url' => $a->getAttribute('href'), + 'tags' => $a->getAttribute('tags'), + 'created' => common_sql_date(intval($addDate)) + ); + $qm = QueueManager::get(); - - $qm->enqueue(array($user, $dt, $dd), 'dlcsbkmk'); + $qm->enqueue($data, 'dlcsbkmk'); } /** diff --git a/plugins/Bookmark/deliciousbookmarkimporter.php b/plugins/Bookmark/deliciousbookmarkimporter.php index 545c336860..018239f49d 100644 --- a/plugins/Bookmark/deliciousbookmarkimporter.php +++ b/plugins/Bookmark/deliciousbookmarkimporter.php @@ -61,52 +61,26 @@ class DeliciousBookmarkImporter extends QueueHandler /** * Handle the data * - * @param array $data array of user, dt, dd + * @param array $data associative array of user & bookmark info from DeliciousBackupImporter::importBookmark() * * @return boolean success value */ function handle($data) { - list($user, $dt, $dd) = $data; - - $as = $dt->getElementsByTagName('a'); - - if ($as->length == 0) { - throw new ClientException(_("No tag in a
    .")); - } - - $a = $as->item(0); - - $private = $a->getAttribute('private'); - - if ($private != 0) { - throw new ClientException(_('Skipping private bookmark.')); - } - - if (!empty($dd)) { - $description = $dd->nodeValue; - } else { - $description = null; - } - - $title = $a->nodeValue; - $url = $a->getAttribute('href'); - $tags = $a->getAttribute('tags'); - $addDate = $a->getAttribute('add_date'); - $created = common_sql_date(intval($addDate)); + $profile = Profile::staticGet('id', $data['profile_id']); try { - $saved = Bookmark::saveNew($user->getProfile(), - $title, - $url, - $tags, - $description, - array('created' => $created, + $saved = Bookmark::saveNew($profile, + $data['title'], + $data['url'], + $data['tags'], + $data['description'], + array('created' => $data['created'], 'distribute' => false)); } catch (ClientException $e) { // Most likely a duplicate -- continue on with the rest! - common_log(LOG_ERR, "Error importing delicious bookmark to $url: " . $e->getMessage()); + common_log(LOG_ERR, "Error importing delicious bookmark to $data[url]: " . $e->getMessage()); return true; } From ae59046b1e5dd2c55e074e8e3d24e04ce8001b8e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 31 Dec 2010 12:42:26 -0800 Subject: [PATCH 15/31] Bookmark plugin: tweak post-upload success message to distinguish between "already done" (UnQueueManager) and "started, should finish eventually" (other queue manager) --- plugins/Bookmark/importdelicious.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/Bookmark/importdelicious.php b/plugins/Bookmark/importdelicious.php index f8529cc914..b98b215717 100644 --- a/plugins/Bookmark/importdelicious.php +++ b/plugins/Bookmark/importdelicious.php @@ -48,6 +48,7 @@ if (!defined('STATUSNET')) { class ImportdeliciousAction extends Action { protected $success = false; + private $inprogress = false; /** * Return the title of the page @@ -191,7 +192,13 @@ class ImportdeliciousAction extends Action $qm = QueueManager::get(); $qm->enqueue(array(common_current_user(), $html), 'dlcsback'); - $this->success = true; + if ($qm instanceof UnQueueManager) { + // No active queuing means we've actually just completed the job! + $this->success = true; + } else { + // We've fed data into background queues, and it's probably still running. + $this->inprogress = true; + } $this->showPage(); @@ -212,8 +219,10 @@ class ImportdeliciousAction extends Action { if ($this->success) { $this->element('p', null, - _('Feed will be restored. '. - 'Please wait a few minutes for results.')); + _('Bookmarks have been imported. Your bookmarks should now appear in search and your profile page.')); + } else if ($this->inprogress) { + $this->element('p', null, + _('Bookmarks are being imported. Please wait a few minutes for results.')); } else { $form = new ImportDeliciousForm($this); $form->show(); From 98a0d7f538bad0b365adb1ec7eacb8c86c15384b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 3 Jan 2011 10:38:32 -0800 Subject: [PATCH 16/31] Configuration options for using an HTTP proxy We can make a lot of HTTP requests from the server side. This change adds some configuration options for using an HTTP proxy, which can cache hits from multiple sites (good for status.net-like services, for example). --- README | 16 ++++++++++++++++ lib/default.php | 5 +++++ lib/httpclient.php | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/README b/README index e2e4c580ef..d972bf5676 100644 --- a/README +++ b/README @@ -1556,6 +1556,22 @@ cache: whether to cache the router in memcache (or another caching router cached) or others who see strange behavior. You're unlikely to need this unless you're a developer. +http +---- + +Settings for the HTTP client. + +ssl_cafile: location of the CA file for SSL. If not set, won't verify + SSL peers. Default unset. +curl: Use cURL for doing HTTP calls. You must + have the PHP curl extension installed for this to work. +proxy_host: Host to use for proxying HTTP requests. If unset, doesn't + do any HTTP proxy stuff. Default unset. +proxy_port: Port to use to connect to HTTP proxy host. Default null. +proxy_user: Username to use for authenticating to the HTTP proxy. Default null. +proxy_password: Password to use for authenticating to the HTTP proxy. Default null. +proxy_auth_scheme: Scheme to use for authenticating to the HTTP proxy. Default null. + Plugins ======= diff --git a/lib/default.php b/lib/default.php index 6d57c4ef02..ce61de5ea5 100644 --- a/lib/default.php +++ b/lib/default.php @@ -331,6 +331,11 @@ $default = 'http' => // HTTP client settings when contacting other sites array('ssl_cafile' => false, // To enable SSL cert validation, point to a CA bundle (eg '/usr/lib/ssl/certs/ca-certificates.crt') 'curl' => false, // Use CURL backend for HTTP fetches if available. (If not, PHP's socket streams will be used.) + 'proxy_host' => null, + 'proxy_port' => null, + 'proxy_user' => null, + 'proxy_password' => null, + 'proxy_auth_scheme' => null, ), 'router' => array('cache' => true), // whether to cache the router object. Defaults to true, turn off for devel diff --git a/lib/httpclient.php b/lib/httpclient.php index 514a5afeb2..04e2b9ac65 100644 --- a/lib/httpclient.php +++ b/lib/httpclient.php @@ -149,6 +149,14 @@ class HTTPClient extends HTTP_Request2 $this->config['adapter'] = 'HTTP_Request2_Adapter_Curl'; } + foreach (array('host', 'port', 'user', 'password', 'auth_scheme') as $cf) { + $k = 'proxy_'.$cf; + $v = common_config('http', $k); + if (!empty($v)) { + $this->config[$k] = $v; + } + } + parent::__construct($url, $method, $config); $this->setHeader('User-Agent', $this->userAgent()); } From fd205546512b75016b1e055aec24eab586ae818b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 3 Jan 2011 10:51:29 -0800 Subject: [PATCH 17/31] Revert "0.9.7alpha1" This reverts commit 3d62c1cf5114760c0a7b97cd69ba363ac059e215. --- lib/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common.php b/lib/common.php index 22890b5cb7..5505dc39da 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', 'alpha1'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release' +define('STATUSNET_LIFECYCLE', 'dev'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release' define('STATUSNET_VERSION', STATUSNET_BASE_VERSION . STATUSNET_LIFECYCLE); define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility From 523d27501b05512c255b3488f94ae0922330cf0d Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 4 Jan 2011 11:03:42 -0800 Subject: [PATCH 18/31] Typo fix: http://status.net/open-source/issues/2976 --- locale/fr/LC_MESSAGES/statusnet.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/fr/LC_MESSAGES/statusnet.po b/locale/fr/LC_MESSAGES/statusnet.po index ee415abb4f..32c774597d 100644 --- a/locale/fr/LC_MESSAGES/statusnet.po +++ b/locale/fr/LC_MESSAGES/statusnet.po @@ -8247,7 +8247,7 @@ msgstr "" #: lib/mail.php:680 #, php-format msgid "%1$s (@%2$s) sent a notice to your attention" -msgstr "%1$s (@%2$s) a envoyé un avis à vote attention" +msgstr "%1$s (@%2$s) a envoyé un avis à votre attention" #. TRANS: Body of @-reply notification e-mail. #. TRANS: %1$s is the sending user's long name, $2$s is the StatusNet sitename, From fb9ecddbf16ad3b33466732334aaafdd92719c30 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 4 Jan 2011 12:04:11 -0800 Subject: [PATCH 19/31] Ticket #2649: fix for undefined $base_url in lighttpd code path The $base_url var is never defined, and the code has actually always been wrong since it was added. Just removing it seems to work fine :) --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 9501e2275d..b2cf2d4a9d 100644 --- a/index.php +++ b/index.php @@ -204,7 +204,7 @@ function main() { // fake HTTP redirects using lighttpd's 404 redirects if (strpos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false) { - $_lighty_url = $base_url.$_SERVER['REQUEST_URI']; + $_lighty_url = $_SERVER['REQUEST_URI']; $_lighty_url = @parse_url($_lighty_url); if ($_lighty_url['path'] != '/index.php' && $_lighty_url['path'] != '/') { From af1cbc6fe32c3d181e1a6d7315634a975cb91c17 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 4 Jan 2011 13:09:44 -0800 Subject: [PATCH 20/31] Fix ticket #2181: Can't save #000000 (black) in color fields on design page It seems to have actually been saving correctly, but the update of the colors on the form success page wasn't working properly. When a design object is pulled out of the database, the numeric fields are read in as strings, so black comes back as "0". But, when we populate the new object and then stick it live, we've populated it with actual integers; with memcache on these might live for a while in the cache... The fallback code in Design::toWebColor() did a check ($color == null) which would be false for the string "0", but counts as true for the *integer* 0. Thus, the display code would initially interpret the correctly-saved black color as "use default". Changing the check to === against null and "" empty string avoids the false positive on integers, and lets us see our nice black text immediately after save. --- classes/Design.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Design.php b/classes/Design.php index a8fdb72191..f4834c714e 100644 --- a/classes/Design.php +++ b/classes/Design.php @@ -107,7 +107,7 @@ class Design extends Memcached_DataObject static function toWebColor($color) { - if ($color == null) { + if ($color === null || $color === '') { return null; } From 3dcf8f1ef6116077343295ad087f8f0d55807477 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 4 Jan 2011 13:10:32 -0800 Subject: [PATCH 21/31] change bookmark-info from a

    to a

    --- plugins/Bookmark/BookmarkPlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index 8eef609751..800a26e795 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -318,7 +318,7 @@ class BookmarkPlugin extends Plugin } } - $out->elementStart('p', array('class' => 'bookmark-info')); + $out->elementStart('div', array('class' => 'bookmark-info entry-content')); $avatar = $profile->getAvatar(AVATAR_MINI_SIZE); @@ -344,7 +344,7 @@ class BookmarkPlugin extends Plugin $nli->showContext(); $nli->showRepeat(); - $out->elementEnd('p'); + $out->elementEnd('div'); $nli->showNoticeOptions(); From b1e42115da24a53136c592e89f8fbec830142abf Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 4 Jan 2011 19:32:36 -0800 Subject: [PATCH 22/31] new menu layout plugin --- plugins/NewMenu/NewMenuPlugin.php | 181 ++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 plugins/NewMenu/NewMenuPlugin.php diff --git a/plugins/NewMenu/NewMenuPlugin.php b/plugins/NewMenu/NewMenuPlugin.php new file mode 100644 index 0000000000..5754e34b7f --- /dev/null +++ b/plugins/NewMenu/NewMenuPlugin.php @@ -0,0 +1,181 @@ +. + * + * @category Sample + * @package StatusNet + * @author Brion Vibber + * @author Evan Prodromou + * @copyright 2010 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); +} + +/** + * Somewhat different menu navigation + * + * We have a new menu layout coming in StatusNet 1.0. This plugin gets + * some of the new navigation in, although third-level menus aren't enabled. + * + * @category NewMenu + * @package StatusNet + * @author Brion Vibber + * @author Evan Prodromou + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ +class NewMenuPlugin extends Plugin +{ + /** + * Load related modules when needed + * + * @param string $cls Name of the class to be loaded + * + * @return boolean hook value; true means continue processing, false means stop. + */ + + function onAutoload($cls) + { + $dir = dirname(__FILE__); + + switch ($cls) + { + case 'HelloAction': + include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; + return false; + case 'User_greeting_count': + include_once $dir . '/'.$cls.'.php'; + return false; + default: + return true; + } + } + + /** + * Modify the default menu + * + * @param Action $action The current action handler. Use this to + * do any output. + * + * @return boolean hook value; true means continue processing, false means stop. + * + * @see Action + */ + + function onStartPrimaryNav($action) + { + $user = common_current_user(); + + if (!empty($user)) { + $action->menuItem(common_local_url('all', + array('nickname' => $user->nickname)), + _m('Home'), + _m('Friends timeline'), + false, + 'nav_home'); + $action->menuItem(common_local_url('showstream', + array('nickname' => $user->nickname)), + _m('Profile'), + _m('Your profile'), + false, + 'nav_profile'); + $action->menuItem(common_local_url('public'), + _m('Everyone'), + _m('Everyone on this site'), + false, + 'nav_public'); + $action->menuItem(common_local_url('profilesettings'), + _m('Settings'), + _m('Change your personal settings'), + false, + 'nav_account'); + if ($user->hasRight(Right::CONFIGURESITE)) { + $action->menuItem(common_local_url('siteadminpanel'), + _m('Admin'), + _m('Site configuration'), + false, + 'nav_admin'); + } + $action->menuItem(common_local_url('logout'), + _m('Logout'), + _m('Logout from the site'), + false, + 'nav_logout'); + } else { + $action->menuItem(common_local_url('public'), + _m('Everyone'), + _m('Everyone on this site'), + false, + 'nav_public'); + $action->menuItem(common_local_url('login'), + _m('Login'), + _m('Login to the site'), + false, + 'nav_login'); + } + + $action->menuItem(common_local_url('doc', + array('title' => 'help')), + _m('Help'), + _m('Help using this site'), + false, + 'nav_help'); + + if (!empty($user) || !common_config('site', 'private')) { + $action->menuItem(common_local_url('noticesearch'), + _m('Search'), + _m('Search the site'), + false, + 'nav_search'); + } + + Event::handle('EndPrimaryNav', array($action)); + + return false; + } + + /** + * Return version information for this plugin + * + * @param array &$versions Version info; add to this array + * + * @return boolean hook value + */ + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'NewMenu', + 'version' => STATUSNET_VERSION, + 'author' => 'Evan Prodromou', + 'homepage' => 'http://status.net/wiki/Plugin:NewMenu', + 'description' => + _m('A preview of the new menu '. + 'layout in StatusNet 1.0.')); + return true; + } +} From 19a3b28898d1e5c390d76dca49ae32b02def1806 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 5 Jan 2011 09:39:36 -0800 Subject: [PATCH 23/31] Remove json2 author's "don't hotlink my script pls" alert line from our local copy of json2.js :D Added json2.min.js to the makefile so it can be updated easily when json2.js changes. --- js/Makefile | 9 ++++++--- js/json2.js | 1 - js/json2.min.js | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/js/Makefile b/js/Makefile index e7ae44e421..2f3dfcdf70 100644 --- a/js/Makefile +++ b/js/Makefile @@ -1,12 +1,15 @@ .fake: all clean -TARGETS=util.min.js -SOURCES=util.js xbImportNode.js geometa.js +TARGETS=util.min.js json2.min.js +UTIL_SOURCES=util.js xbImportNode.js geometa.js all: $(TARGETS) clean: rm -f $(TARGETS) -util.min.js: $(SOURCES) +util.min.js: $(UTIL_SOURCES) cat $+ | yui-compressor --type js > $@ + +json2.min.js: json2.js + yui-compressor $+ > $@ diff --git a/js/json2.js b/js/json2.js index e9ccc0d376..6bdea10e51 100644 --- a/js/json2.js +++ b/js/json2.js @@ -1,4 +1,3 @@ -alert('IMPORTANT: Remove this line from json2.js before deployment.'); /* http://www.JSON.org/json2.js 2010-08-25 diff --git a/js/json2.min.js b/js/json2.min.js index e84c5f70fc..08977b590c 100644 --- a/js/json2.min.js +++ b/js/json2.min.js @@ -1 +1 @@ -alert("IMPORTANT: Remove this line from json2.js before deployment.");if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i Date: Wed, 5 Jan 2011 13:13:45 -0500 Subject: [PATCH 24/31] Add Dialog Axiata to SMS carriers --- db/sms_carrier.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/sms_carrier.sql b/db/sms_carrier.sql index 0e94df296e..14074e7189 100644 --- a/db/sms_carrier.sql +++ b/db/sms_carrier.sql @@ -62,4 +62,5 @@ VALUES (100114, 'Vodafone Germany', '%s@vodafone-sms.de', now()), (100115, 'E-Plus', '%s@smsmail.eplus.de', now()), (100116, 'Cellular South', '%s@csouth1.com', now()), - (100117, 'ChinaMobile (139)', '%s@139.com', now()); + (100117, 'ChinaMobile (139)', '%s@139.com', now()), + (100118, 'Dialog Axiata', '%s@dialog.lk', now()); From 75dd361d29926a8e4db670412da2a277d38ad712 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 5 Jan 2011 11:24:24 -0800 Subject: [PATCH 25/31] move profile to subgroupnav --- plugins/NewMenu/NewMenuPlugin.php | 125 ++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/plugins/NewMenu/NewMenuPlugin.php b/plugins/NewMenu/NewMenuPlugin.php index 5754e34b7f..c5af61f632 100644 --- a/plugins/NewMenu/NewMenuPlugin.php +++ b/plugins/NewMenu/NewMenuPlugin.php @@ -159,6 +159,131 @@ class NewMenuPlugin extends Plugin return false; } + function onStartPersonalGroupNav($menu) + { + $user = null; + + // FIXME: we should probably pass this in + + $action = $menu->action->trimmed('action'); + $nickname = $menu->action->trimmed('nickname'); + + if ($nickname) { + $user = User::staticGet('nickname', $nickname); + $user_profile = $user->getProfile(); + $name = $user_profile->getBestName(); + } else { + // @fixme can this happen? is this valid? + $user_profile = false; + $name = $nickname; + } + + $menu->out->menuItem(common_local_url('all', array('nickname' => + $nickname)), + _('Home'), + sprintf(_('%s and friends'), $name), + $action == 'all', 'nav_timeline_personal'); + $menu->out->menuItem(common_local_url('replies', array('nickname' => + $nickname)), + _('Replies'), + sprintf(_('Replies to %s'), $name), + $action == 'replies', 'nav_timeline_replies'); + $menu->out->menuItem(common_local_url('showfavorites', array('nickname' => + $nickname)), + _('Favorites'), + sprintf(_('%s\'s favorite notices'), ($user_profile) ? $name : _('User')), + $action == 'showfavorites', 'nav_timeline_favorites'); + + $cur = common_current_user(); + + if ($cur && $cur->id == $user->id && + !common_config('singleuser', 'enabled')) { + + $menu->out->menuItem(common_local_url('inbox', array('nickname' => + $nickname)), + _('Inbox'), + _('Your incoming messages'), + $action == 'inbox'); + $menu->out->menuItem(common_local_url('outbox', array('nickname' => + $nickname)), + _('Outbox'), + _('Your sent messages'), + $action == 'outbox'); + } + Event::handle('EndPersonalGroupNav', array($menu)); + return false; + } + + function onStartSubGroupNav($menu) + { + $cur = common_current_user(); + $action = $menu->action->trimmed('action'); + + $profile = $menu->user->getProfile(); + + $menu->out->menuItem(common_local_url('showstream', array('nickname' => + $menu->user->nickname)), + _('Profile'), + (empty($profile)) ? $menu->user->nickname : $profile->getBestName(), + $action == 'showstream', + 'nav_profile'); + $menu->out->menuItem(common_local_url('subscriptions', + array('nickname' => + $menu->user->nickname)), + _('Subscriptions'), + sprintf(_('People %s subscribes to'), + $menu->user->nickname), + $action == 'subscriptions', + 'nav_subscriptions'); + $menu->out->menuItem(common_local_url('subscribers', + array('nickname' => + $menu->user->nickname)), + _('Subscribers'), + sprintf(_('People subscribed to %s'), + $menu->user->nickname), + $action == 'subscribers', + 'nav_subscribers'); + $menu->out->menuItem(common_local_url('usergroups', + array('nickname' => + $menu->user->nickname)), + _('Groups'), + sprintf(_('Groups %s is a member of'), + $menu->user->nickname), + $action == 'usergroups', + 'nav_usergroups'); + if (common_config('invite', 'enabled') && !is_null($cur) && $menu->user->id === $cur->id) { + $menu->out->menuItem(common_local_url('invite'), + _('Invite'), + sprintf(_('Invite friends and colleagues to join you on %s'), + common_config('site', 'name')), + $action == 'invite', + 'nav_invite'); + } + + Event::handle('EndSubGroupNav', array($menu)); + return false; + } + + function onStartShowLocalNavBlock($action) + { + $actionName = $action->trimmed('action'); + + if ($actionName == 'showstream') { + $action->elementStart('dl', array('id' => 'site_nav_local_views')); + // TRANS: DT element for local views block. String is hidden in default CSS. + $action->element('dt', null, _('Local views')); + $action->elementStart('dd'); + $nav = new SubGroupNav($action, $action->user); + $nav->show(); + $action->elementEnd('dd'); + $action->elementEnd('dl'); + Event::handle('EndShowLocalNavBlock', array($action)); + return false; + } + + return true; + } + /** * Return version information for this plugin * From f3d48d2dfef7537b31a1d942f6c04b9e85dec090 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 5 Jan 2011 15:34:10 -0800 Subject: [PATCH 26/31] Add README with intallation/upgrade instructions to the Facebook Bridge plugin --- plugins/Facebook/README | 6 ++ plugins/FacebookBridge/README | 108 ++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 plugins/FacebookBridge/README diff --git a/plugins/Facebook/README b/plugins/Facebook/README index 532f1d82e4..454dd44e79 100644 --- a/plugins/Facebook/README +++ b/plugins/Facebook/README @@ -1,3 +1,9 @@ +*** WARNING *** +This plugin is deprecated as of StatusNet 0.9.7, and will soon be removed +completely from the StatusNet codebase. Please install or upgrade to the +new "Facebook Bridge" (plugins/FacebookBridge) plugin ASAP. +*************** + Facebook Plugin =============== diff --git a/plugins/FacebookBridge/README b/plugins/FacebookBridge/README new file mode 100644 index 0000000000..54de8633a2 --- /dev/null +++ b/plugins/FacebookBridge/README @@ -0,0 +1,108 @@ +Facebook Bridge Plugin + +The Facebook Bridge plugin allows you to integrate your StatusNet site +with Facebook. It uses Facebook's new SDKs, the Graph API and OAuth +2.0, and supercedes the previous "Facebook" plugin, which relied on the +Facebook's now deprecated "Old REST API". The other major difference is +the troublesome and confusing Facebook Canvas Application has been +removed. + +Note: Do NOT try to run the old Facebook plugin and this plugin at the same +time. It won't work. + +Features for the new Facebook Bridge Plugin: + +- "Login with Facebook" (AKA single-sign-on using Facebook Connect for + authentication). + +- Registration with Facebook Connect, including automatic profile creation + based on users' Facebook accounts. + +- Post mirroring -- posting a notice on StatusNet automatically creates a post + on Facebook, deleting it on StatusNet deletes it on Facebook, and faving it + "likes" it on Facebook. + + +Upgrading from the old Facebook plugin +====================================== + +Remove the addPlugin('Facebook') statement for the old Facebook plugin +from your config.php and adjust your existing Facebook application using +the setup instructions below as a guide, then enable the new plugin (also +described below). Existing users who have setup post mirroring shouldn't +have to do anything. The new Facebook Bridge plugin will keep their notices +flowing to Facebook. + +Setup +===== + +There are two parts configuring the Facebook Bridge plugin -- setup on the +Facebook side, and setup on the StatusNet side. + +Setup (Facebook side) +===================== + +The first step is to login to Facebook and register a Facebook application +to get an application ID and secret. + +Use the handy Facebook application setup wizard: + +http://developers.facebook.com/setup/ + +Once you've set up your application, you'll need to enter the Facebook Developer +dashboard (http://www.facebook.com/developers/editapp.php?app_id=YOUR_APPLICATION_ID) +and customize a few things: + +About tab +--------- + +Set your logos, application description, etc. as you see fit. + +Web Site tab +------------ + +Make a note of the "Application ID" and "Application Secret" Facebook generated +for your application. You'll need both of those later. + +Make sure "Site URL" points to your StatusNet installation +(e.g.: http://example.net/). + +- Special Note for multi-site Status Networks: enter your domain (SLD and TLD) + in the "Site Domain" field. (e.g.: status.net). This will allow a single + Facebook Application to work with all your network subdomains (*.status.net). + +Facebook Integration tab +------------------------ + +Use the default settings. + +Mobile and Devices tab +---------------------- + +Use the default settings. + +Advanced tab +------------ + +In the Authentication section, set the "Deauthorize Callback" to +http://YOURSITE/facebook/deauthorize (e.g.: http://example.net/facebook/deauthorize). + +In the Migrations section, ensure that "OAuth 2.0 for Canvas" is set to +"Enabled". It probably already will be, but double check. + +The default settings should suffice for everything else. + +Setup (StatusNet side) +====================== + +To enable the Facebook Bridge plugin, add + + addPlugin('FacebookBridge'); + +to you config.php. + +Next login to your StatusNet site as a user with the administrator role, and +navigate to the admin menu. You should see a new tab for the Facebook admin +panel, titled "Facebook". Enter your Facebook application ID and secret in +that admin panel and hit save. After that, the Facebook Bridge Plugin should +be ready to use. From 77eda410305fca74968e9e99d25b2a9699432d32 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 6 Jan 2011 12:15:59 -0800 Subject: [PATCH 27/31] Added Start/EndRegistrationTry events to Facebook Bridge's user registration --- plugins/FacebookBridge/actions/facebookfinishlogin.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/FacebookBridge/actions/facebookfinishlogin.php b/plugins/FacebookBridge/actions/facebookfinishlogin.php index 349acd7e22..022c1e98b1 100644 --- a/plugins/FacebookBridge/actions/facebookfinishlogin.php +++ b/plugins/FacebookBridge/actions/facebookfinishlogin.php @@ -299,6 +299,10 @@ class FacebookfinishloginAction extends Action function createNewUser() { + if (!Event::handle('StartRegistrationTry', array($this))) { + return; + } + if (common_config('site', 'closed')) { // TRANS: Client error trying to register with registrations not allowed. $this->clientError(_m('Registration not allowed.')); @@ -389,6 +393,8 @@ class FacebookfinishloginAction extends Action __FILE__ ); + Event::handle('EndRegistrationTry', array($this)); + $this->goHome($user->nickname); } From 9af50406930c54cb5be378f1801892665158e009 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 7 Jan 2011 18:56:18 -0500 Subject: [PATCH 28/31] combine account and connect menus --- plugins/NewMenu/NewMenuPlugin.php | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/plugins/NewMenu/NewMenuPlugin.php b/plugins/NewMenu/NewMenuPlugin.php index c5af61f632..19049f463e 100644 --- a/plugins/NewMenu/NewMenuPlugin.php +++ b/plugins/NewMenu/NewMenuPlugin.php @@ -284,6 +284,76 @@ class NewMenuPlugin extends Plugin return true; } + function onStartAccountSettingsNav(&$action) + { + $this->_settingsMenu($action); + return false; + } + + function onStartConnectSettingsNav(&$action) + { + $this->_settingsMenu($action); + return false; + } + + private function _settingsMenu(&$action) + { + $actionName = $action->trimmed('action'); + + $action->menuItem(common_local_url('profilesettings'), + _('Profile'), + _('Change your profile settings'), + $actionName == 'profilesettings'); + + $action->menuItem(common_local_url('avatarsettings'), + _('Avatar'), + _('Upload an avatar'), + $actionName == 'avatarsettings'); + + $action->menuItem(common_local_url('passwordsettings'), + _('Password'), + _('Change your password'), + $actionName == 'passwordsettings'); + + $action->menuItem(common_local_url('emailsettings'), + _('Email'), + _('Change email handling'), + $actionName == 'emailsettings'); + + $action->menuItem(common_local_url('userdesignsettings'), + _('Design'), + _('Design your profile'), + $actionName == 'userdesignsettings'); + + $action->menuItem(common_local_url('othersettings'), + _('Other'), + _('Other options'), + $actionName == 'othersettings'); + + Event::handle('EndAccountSettingsNav', array(&$action)); + + if (common_config('xmpp', 'enabled')) { + $action->menuItem(common_local_url('imsettings'), + _m('IM'), + _('Updates by instant messenger (IM)'), + $actionName == 'imsettings'); + } + + if (common_config('sms', 'enabled')) { + $action->menuItem(common_local_url('smssettings'), + _m('SMS'), + _('Updates by SMS'), + $actionName == 'smssettings'); + } + + $action->menuItem(common_local_url('oauthconnectionssettings'), + _('Connections'), + _('Authorized connected applications'), + $actionName == 'oauthconnectionsettings'); + + Event::handle('EndConnectSettingsNav', array(&$action)); + } + /** * Return version information for this plugin * From 66ed9c7f302e8148861987d6b12abbc013172215 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 7 Jan 2011 18:57:34 -0500 Subject: [PATCH 29/31] change 'Everyone' to 'Public' --- plugins/NewMenu/NewMenuPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/NewMenu/NewMenuPlugin.php b/plugins/NewMenu/NewMenuPlugin.php index 19049f463e..3d19d909a1 100644 --- a/plugins/NewMenu/NewMenuPlugin.php +++ b/plugins/NewMenu/NewMenuPlugin.php @@ -105,7 +105,7 @@ class NewMenuPlugin extends Plugin false, 'nav_profile'); $action->menuItem(common_local_url('public'), - _m('Everyone'), + _m('Public'), _m('Everyone on this site'), false, 'nav_public'); From 16cf7d8d406f7bcf8699b76d18f3a8b72a2a4778 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 7 Jan 2011 19:22:27 -0500 Subject: [PATCH 30/31] Show some menu fixup for settings for some themes --- plugins/NewMenu/NewMenuPlugin.php | 14 +++++++++ plugins/NewMenu/newmenu.css | 47 +++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 plugins/NewMenu/newmenu.css diff --git a/plugins/NewMenu/NewMenuPlugin.php b/plugins/NewMenu/NewMenuPlugin.php index 3d19d909a1..7397d4fbc9 100644 --- a/plugins/NewMenu/NewMenuPlugin.php +++ b/plugins/NewMenu/NewMenuPlugin.php @@ -51,6 +51,8 @@ if (!defined('STATUSNET')) { */ class NewMenuPlugin extends Plugin { + public $loadCSS = false; + /** * Load related modules when needed * @@ -354,6 +356,18 @@ class NewMenuPlugin extends Plugin Event::handle('EndConnectSettingsNav', array(&$action)); } + function onEndShowStyles($action) + { + if (($this->showCSS || + in_array(common_config('site', 'theme'), + array('default', 'identica', 'h4ck3r'))) && + ($action instanceof AccountSettingsAction || + $action instanceof ConnectSettingsAction)) { + $action->cssLink(common_path('plugins/NewMenu/newmenu.css')); + } + return true; + } + /** * Return version information for this plugin * diff --git a/plugins/NewMenu/newmenu.css b/plugins/NewMenu/newmenu.css new file mode 100644 index 0000000000..f700fdcc45 --- /dev/null +++ b/plugins/NewMenu/newmenu.css @@ -0,0 +1,47 @@ +body[id$=settings] #site_nav_local_views { +position:relative; +z-index:9; +float:right; +margin-right:10.65%; +width:22.25%; +} +body[id$=settings] #site_nav_local_views li { +width:100%; +margin-right:0; +margin-bottom:7px; +} +body[id$=settings] #site_nav_local_views a { +display:block; +width:80%; +padding-right:10%; +padding-left:10%; +border-radius-toprleft:0; +-moz-border-radius-topleft:0; +-webkit-border-top-left-radius:0; +border-radius-topright:4px; +-moz-border-radius-topright:4px; +-webkit-border-top-right-radius:4px; +border-radius-bottomright:4px; +-moz-border-radius-bottomright:4px; +-webkit-border-bottom-right-radius:4px; +} +body[id$=settings] #site_nav_local_views li.current { +box-shadow:none; +-moz-box-shadow:none; +-webkit-box-shadow:none; +} + +body[id$=settings] #content { +border-radius-topleft:7px; +border-radius-topright:7px; +-moz-border-radius-topleft:7px; +-moz-border-radius-topright:7px; +-webkit-border-top-left-radius:7px; +-webkit-border-top-right-radius:7px; +border-radius-topright:0; +-moz-border-radius-topright:0; +-webkit-border-top-right-radius:0; +} +body[id$=settings] #aside_primary { +display:none; +} From 5d439239419b5a6b0c709f8622da41b5a8af68af Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 7 Jan 2011 19:27:59 -0500 Subject: [PATCH 31/31] remove help link; Everyone => Public; Logo goes home --- plugins/NewMenu/NewMenuPlugin.php | 61 +++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/plugins/NewMenu/NewMenuPlugin.php b/plugins/NewMenu/NewMenuPlugin.php index 7397d4fbc9..cdcea5cd92 100644 --- a/plugins/NewMenu/NewMenuPlugin.php +++ b/plugins/NewMenu/NewMenuPlugin.php @@ -130,7 +130,7 @@ class NewMenuPlugin extends Plugin 'nav_logout'); } else { $action->menuItem(common_local_url('public'), - _m('Everyone'), + _m('Public'), _m('Everyone on this site'), false, 'nav_public'); @@ -141,13 +141,6 @@ class NewMenuPlugin extends Plugin 'nav_login'); } - $action->menuItem(common_local_url('doc', - array('title' => 'help')), - _m('Help'), - _m('Help using this site'), - false, - 'nav_help'); - if (!empty($user) || !common_config('site', 'private')) { $action->menuItem(common_local_url('noticesearch'), _m('Search'), @@ -368,6 +361,58 @@ class NewMenuPlugin extends Plugin return true; } + function onStartAddressData($action) + { + if (common_config('singleuser', 'enabled')) { + $user = User::singleUser(); + $url = common_local_url('showstream', + array('nickname' => $user->nickname)); + } else if (common_logged_in()) { + $cur = common_current_user(); + $url = common_local_url('all', array('nickname' => $cur->nickname)); + } else { + $url = common_local_url('public'); + } + + $action->elementStart('a', array('class' => 'url home bookmark', + 'href' => $url)); + + if (StatusNet::isHTTPS()) { + $logoUrl = common_config('site', 'ssllogo'); + if (empty($logoUrl)) { + // if logo is an uploaded file, try to fall back to HTTPS file URL + $httpUrl = common_config('site', 'logo'); + if (!empty($httpUrl)) { + $f = File::staticGet('url', $httpUrl); + if (!empty($f) && !empty($f->filename)) { + // this will handle the HTTPS case + $logoUrl = File::url($f->filename); + } + } + } + } else { + $logoUrl = common_config('site', 'logo'); + } + + if (empty($logoUrl) && file_exists(Theme::file('logo.png'))) { + // This should handle the HTTPS case internally + $logoUrl = Theme::path('logo.png'); + } + + if (!empty($logoUrl)) { + $action->element('img', array('class' => 'logo photo', + 'src' => $logoUrl, + 'alt' => common_config('site', 'name'))); + } + + $action->text(' '); + $action->element('span', array('class' => 'fn org'), common_config('site', 'name')); + $action->elementEnd('a'); + + Event::handle('EndAddressData', array($action)); + return false; + } + /** * Return version information for this plugin *