From 32f81b3c0e7be3da35d5813e5409fa3b65dc220e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 24 Jan 2009 18:38:12 +0100 Subject: [PATCH 001/503] Initial support for ping service It makes sense to use the weblogs.com ping service to alert people to changes on the site. So, we do. Includes an extra ping queue handler. --- lib/common.php | 2 + lib/ping.php | 79 ++++++++++++++++++++++++++++++++++++ lib/util.php | 2 +- scripts/pingqueuehandler.php | 64 +++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 lib/ping.php create mode 100644 scripts/pingqueuehandler.php diff --git a/lib/common.php b/lib/common.php index a2f9b9bfe7..cc82f8bd73 100644 --- a/lib/common.php +++ b/lib/common.php @@ -128,6 +128,8 @@ $config = array('enabled' => false, 'server' => 'localhost', 'port' => 11211), + 'ping' => + array('notify' => array()), 'inboxes' => array('enabled' => true), # on by default for new sites ); diff --git a/lib/ping.php b/lib/ping.php new file mode 100644 index 0000000000..32c0b9806a --- /dev/null +++ b/lib/ping.php @@ -0,0 +1,79 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +function ping_broadcast_notice($notice) { + if (!$notice->is_local) { + return; + } + + # Array of servers, URL => type + $notify = common_config('ping', 'notify'); + $profile = $notice->getProfile(); + $tags = ping_notice_tags($notice); + + foreach ($notify as $notify_url => $type) { + switch ($type) { + case 'xmlrpc': + case 'extended': + $req = xmlrpc_encode_request('weblogUpdates.ping', + array($profile->nickname, # site name + common_local_url('showstream', + array('nickname' => $profile->nickname)), + common_local_url('shownotice', + array('notice' => $notice->id)), + common_local_url('userrss', + array('nickname' => $profile->nickname)), + $tags)); + + # We re-use this tool's fetcher, since it's pretty good + + $fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); + + if (!$fetcher) { + common_log(LOG_WARNING, 'Failed to initialize Yadis fetcher.', __FILE__); + return false; + } + + $result = $fetcher->post($notify_url, + $req); + + case 'get': + case 'post': + default: + common_log(LOG_WARNING, 'Unknown notify type for ' . $notify_url . ': ' . $type); + } + } +} + +function ping_notice_tags($notice) { + $tag = new Notice_tag(); + $tag->notice_id = $notice->id; + $tags = array(); + if ($tag->find()) { + while ($tag->fetch()) { + $tags[] = $tag->tag; + } + $tag->free(); + unset($tag); + return implode('|', $tags); + } + return NULL; +} \ No newline at end of file diff --git a/lib/util.php b/lib/util.php index b5b194519e..419e21e828 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1124,7 +1124,7 @@ function common_twitter_broadcast($notice, $flink) function common_enqueue_notice($notice) { - foreach (array('jabber', 'omb', 'sms', 'public') as $transport) { + foreach (array('jabber', 'omb', 'sms', 'public', 'ping') as $transport) { $qi = new Queue_item(); $qi->notice_id = $notice->id; $qi->transport = $transport; diff --git a/scripts/pingqueuehandler.php b/scripts/pingqueuehandler.php new file mode 100644 index 0000000000..55a266e4a4 --- /dev/null +++ b/scripts/pingqueuehandler.php @@ -0,0 +1,64 @@ +#!/usr/bin/env php +. + */ + +# Abort if called from a web server +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); +require_once(INSTALLDIR . '/lib/ping.php'); +require_once(INSTALLDIR . '/lib/queuehandler.php'); + +set_error_handler('common_error_handler'); + +class PingQueueHandler extends QueueHandler { + + function transport() { + return 'ping'; + } + + function start() { + $this->log(LOG_INFO, "INITIALIZE"); + return true; + } + + function handle_notice($notice) { + return ping_broadcast_notice($notice); + } + + function finish() { + } +} + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +$id = ($argc > 1) ? $argv[1] : NULL; + +$handler = new PingQueueHandler($id); + +$handler->runOnce(); From 6e2f04583728714ff937eb1fa3ab34e99bcdb6a6 Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Mon, 9 Feb 2009 00:02:51 +1100 Subject: [PATCH 002/503] Add machine-readable pagination using HTML4.01 ``, etc. These extra `` elements only appear on pages where pagination makes sense. They trigger functionality in some user agents, such as Opera's Navigation Bar for more easily navigating forward and backwards across a paged set of notices, messages, or group lists, etc. --- actions/all.php | 22 ++++++++++++++++++++++ actions/favorited.php | 20 ++++++++++++++++++++ actions/groupmembers.php | 24 +++++++++++++++++++++++- actions/groups.php | 20 ++++++++++++++++++++ actions/inbox.php | 22 ++++++++++++++++++++++ actions/outbox.php | 22 ++++++++++++++++++++++ actions/public.php | 20 ++++++++++++++++++++ actions/replies.php | 22 ++++++++++++++++++++++ actions/showfavorites.php | 22 ++++++++++++++++++++++ actions/showgroup.php | 22 ++++++++++++++++++++++ actions/showstream.php | 22 ++++++++++++++++++++++ actions/tag.php | 22 ++++++++++++++++++++++ lib/action.php | 14 ++++++++++++++ 13 files changed, 273 insertions(+), 1 deletion(-) diff --git a/actions/all.php b/actions/all.php index d75d1b9461..76b1bbcdf8 100644 --- a/actions/all.php +++ b/actions/all.php @@ -78,6 +78,28 @@ class AllAction extends Action 'title' => sprintf(_('Feed for friends of %s'), $this->user->nickname))); } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('all', + array('nickname' => $this->user->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('all', + array('nickname' => $this->user->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Notices'))); + } + function showLocalNav() { $nav = new PersonalGroupNav($this); diff --git a/actions/favorited.php b/actions/favorited.php index fd5ff413cb..367fb6dd69 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -195,4 +195,24 @@ class FavoritedAction extends Action $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'favorited'); } + + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('favorited', + array('page' => $this->page - 1)), + 'title' => _('Next Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('favorited', + array('page' => $this->page + 1)), + 'title' => _('Previous Notices'))); + } } diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 00f43a9f55..2b2bdba93d 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -137,4 +137,26 @@ class GroupmembersAction extends Action $this->page, 'groupmembers', array('nickname' => $this->group->nickname)); } -} \ No newline at end of file + + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('groupmembers', + array('nickname' => $this->group->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Group Members'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('groupmembers', + array('nickname' => $this->group->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Group Members'))); + } +} diff --git a/actions/groups.php b/actions/groups.php index 39dc2232bc..b0bf7cfc2a 100644 --- a/actions/groups.php +++ b/actions/groups.php @@ -129,4 +129,24 @@ class GroupsAction extends Action $gbm = new GroupsByMembersSection($this); $gbm->show(); } + + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('groups', + array('page' => $this->page - 1)), + 'title' => _('Next Groups'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('groups', + array('page' => $this->page + 1)), + 'title' => _('Previous Groups'))); + } } diff --git a/actions/inbox.php b/actions/inbox.php index b553ab26ca..d12f3f20ae 100644 --- a/actions/inbox.php +++ b/actions/inbox.php @@ -63,6 +63,28 @@ class InboxAction extends MailboxAction } } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('inbox', + array('nickname' => $this->user->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Messages'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('inbox', + array('nickname' => $this->user->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Messages'))); + } + /** * Retrieve the messages for this user and this page * diff --git a/actions/outbox.php b/actions/outbox.php index c8d7f28125..043b74edc4 100644 --- a/actions/outbox.php +++ b/actions/outbox.php @@ -62,6 +62,28 @@ class OutboxAction extends MailboxAction } } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('outbox', + array('nickname' => $this->user->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Messages'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('outbox', + array('nickname' => $this->user->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Messages'))); + } + /** * retrieve the messages for this user and this page * diff --git a/actions/public.php b/actions/public.php index cc6537f74f..25889eee5a 100644 --- a/actions/public.php +++ b/actions/public.php @@ -127,6 +127,26 @@ class PublicAction extends Action 'title' => _('Public Stream Feed'))); } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('public', + array('page' => $this->page - 1)), + 'title' => _('Next Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('public', + array('page' => $this->page + 1)), + 'title' => _('Previous Notices'))); + } + /** * Extra head elements * diff --git a/actions/replies.php b/actions/replies.php index 7eff74a669..5ae99e1652 100644 --- a/actions/replies.php +++ b/actions/replies.php @@ -141,6 +141,28 @@ class RepliesAction extends Action 'title' => $rsstitle)); } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('replies', + array('nickname' => $this->user->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('replies', + array('nickname' => $this->user->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Notices'))); + } + /** * show the personal group nav * diff --git a/actions/showfavorites.php b/actions/showfavorites.php index 31479e1a78..f0297172a6 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -153,6 +153,28 @@ class ShowfavoritesAction extends Action 'title' => $feedtitle)); } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('showfavorites', + array('nickname' => $this->user->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Favorite Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('showfavorites', + array('nickname' => $this->user->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Favorite Notices'))); + } + /** * show the personal group nav * diff --git a/actions/showgroup.php b/actions/showgroup.php index 7bc68fbc64..7599a8de6e 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -326,6 +326,28 @@ class ShowgroupAction extends Action $this->group->nickname))); } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('showgroup', + array('nickname' => $this->group->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('showgroup', + array('nickname' => $this->group->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Notices'))); + } + /** * Fill in the sidebar. * diff --git a/actions/showstream.php b/actions/showstream.php index 28bb8453f8..11615ebb0d 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -195,6 +195,28 @@ class ShowstreamAction extends Action $this->user->nickname))); } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('showstream', + array('nickname' => $this->user->nickname, + 'page' => $this->page - 1)), + 'title' => _('Next Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('showstream', + array('nickname' => $this->user->nickname, + 'page' => $this->page + 1)), + 'title' => _('Previous Notices'))); + } + function extraHead() { // FOAF diff --git a/actions/tag.php b/actions/tag.php index 4401f892a9..f71f6d342f 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -69,6 +69,28 @@ class TagAction extends Action 'title' => sprintf(_('Feed for tag %s'), $this->tag))); } + /** + * Output document relationship links + * + * @return void + */ + function showRelationshipLinks() + { + // Machine-readable pagination + if ($this->page > 1) { + $this->element('link', array('rel' => 'next', + 'href' => common_local_url('tag', + array('tag' => $this->tag, + 'page' => $this->page - 1)), + 'title' => _('Next Notices'))); + } + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url('tag', + array('tag' => $this->tag, + 'page' => $this->page + 1)), + 'title' => _('Previous Notices'))); + } + function showPageNotice() { return sprintf(_('Messages tagged "%s", most recent first'), $this->tag); diff --git a/lib/action.php b/lib/action.php index c4172ada11..ab51d0252c 100644 --- a/lib/action.php +++ b/lib/action.php @@ -111,6 +111,7 @@ class Action extends HTMLOutputter // lawsuit $this->showTitle(); $this->showStylesheets(); $this->showScripts(); + $this->showRelationshipLinks(); $this->showOpenSearch(); $this->showFeeds(); $this->showDescription(); @@ -193,6 +194,19 @@ class Action extends HTMLOutputter // lawsuit ' '); } + /** + * Show document relationship links + * + * SHOULD overload + * + * @return nothing + */ + function showRelationshipLinks() + { + // output elements with appropriate HTML4.01 link types: + // http://www.w3.org/TR/html401/types.html#type-links + } + /** * Show OpenSearch headers * From b240a1719485b15c4a6497b6053c24e8a40a4e3c Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Tue, 10 Feb 2009 19:42:01 +1100 Subject: [PATCH 003/503] Beginning to refactor document relationship links to reduce common code. My attempts here are to mimic the `pagination()` method shared by actions. I'm tentatively adding the `$count` property to actions so that we can query the number of notices ''being displayed'' per page prior to calling the actual `pagination()` method itself, since document relationship `` elements need to be output inside of `showHead()`, before `showContent()`, which is where `pagination()` is, gets called. --- actions/all.php | 15 ++------------- actions/favorited.php | 13 ++----------- actions/groupmembers.php | 15 ++------------- actions/groups.php | 13 ++----------- actions/inbox.php | 15 ++------------- actions/outbox.php | 15 ++------------- actions/public.php | 25 ++++++++++++++----------- actions/replies.php | 15 ++------------- actions/showfavorites.php | 16 +++------------- actions/showgroup.php | 15 ++------------- actions/showstream.php | 15 ++------------- actions/tag.php | 15 ++------------- lib/action.php | 34 ++++++++++++++++++++++++++++++++++ 13 files changed, 71 insertions(+), 150 deletions(-) diff --git a/actions/all.php b/actions/all.php index 76b1bbcdf8..4a625207a4 100644 --- a/actions/all.php +++ b/actions/all.php @@ -85,19 +85,8 @@ class AllAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('all', - array('nickname' => $this->user->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('all', - array('nickname' => $this->user->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'all', array('nickname' => $this->user->nickname)); } function showLocalNav() diff --git a/actions/favorited.php b/actions/favorited.php index 367fb6dd69..74920ca7e4 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -203,16 +203,7 @@ class FavoritedAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('favorited', - array('page' => $this->page - 1)), - 'title' => _('Next Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('favorited', - array('page' => $this->page + 1)), - 'title' => _('Previous Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'favorited'); } } diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 2b2bdba93d..b80f3d90d1 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -145,18 +145,7 @@ class GroupmembersAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('groupmembers', - array('nickname' => $this->group->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Group Members'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('groupmembers', - array('nickname' => $this->group->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Group Members'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'groupmembers', array('nickname' => $this->group->nickname)); } } diff --git a/actions/groups.php b/actions/groups.php index b0bf7cfc2a..e158698de2 100644 --- a/actions/groups.php +++ b/actions/groups.php @@ -137,16 +137,7 @@ class GroupsAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('groups', - array('page' => $this->page - 1)), - 'title' => _('Next Groups'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('groups', - array('page' => $this->page + 1)), - 'title' => _('Previous Groups'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'groups', array('nickname' => $this->group->nickname)); } } diff --git a/actions/inbox.php b/actions/inbox.php index d12f3f20ae..7b5cf2d203 100644 --- a/actions/inbox.php +++ b/actions/inbox.php @@ -70,19 +70,8 @@ class InboxAction extends MailboxAction */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('inbox', - array('nickname' => $this->user->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Messages'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('inbox', - array('nickname' => $this->user->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Messages'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'inbox', array('nickname' => $this->user->nickname)); } /** diff --git a/actions/outbox.php b/actions/outbox.php index 043b74edc4..deef1cc870 100644 --- a/actions/outbox.php +++ b/actions/outbox.php @@ -69,19 +69,8 @@ class OutboxAction extends MailboxAction */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('outbox', - array('nickname' => $this->user->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Messages'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('outbox', - array('nickname' => $this->user->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Messages'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'outbox', array('nickname' => $this->user->nickname)); } /** diff --git a/actions/public.php b/actions/public.php index 25889eee5a..eb2a4b1b00 100644 --- a/actions/public.php +++ b/actions/public.php @@ -56,6 +56,18 @@ class PublicAction extends Action var $page = null; + /** + * Number of notices being shown on this page. + */ + // Does this need to be here? Should it be? + // If it does, this property needs to be + // added to other actions as well, like $page. + // I'm trying to find a way to capture the + // output of the $cnt variable from this + // action's showContent() method but need + // to do so earlier, I think...? + var $count = null; + function isReadOnly() { return true; @@ -134,17 +146,8 @@ class PublicAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('public', - array('page' => $this->page - 1)), - 'title' => _('Next Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('public', - array('page' => $this->page + 1)), - 'title' => _('Previous Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'public'); } /** diff --git a/actions/replies.php b/actions/replies.php index 5ae99e1652..7c24b554e0 100644 --- a/actions/replies.php +++ b/actions/replies.php @@ -148,19 +148,8 @@ class RepliesAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('replies', - array('nickname' => $this->user->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('replies', - array('nickname' => $this->user->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'replies', array('nickname' => $this->user->nickname)); } /** diff --git a/actions/showfavorites.php b/actions/showfavorites.php index f0297172a6..585b3b75ab 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -160,21 +160,11 @@ class ShowfavoritesAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('showfavorites', - array('nickname' => $this->user->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Favorite Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('showfavorites', - array('nickname' => $this->user->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Favorite Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'showfavorites', array('nickname' => $this->user->nickname)); } + /** * show the personal group nav * diff --git a/actions/showgroup.php b/actions/showgroup.php index 7599a8de6e..a2b40f9948 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -333,19 +333,8 @@ class ShowgroupAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('showgroup', - array('nickname' => $this->group->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('showgroup', - array('nickname' => $this->group->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'showgroup', array('nickname' => $this->group->nickname)); } /** diff --git a/actions/showstream.php b/actions/showstream.php index 0c8fea1821..1779c70f2c 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -202,19 +202,8 @@ class ShowstreamAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('showstream', - array('nickname' => $this->user->nickname, - 'page' => $this->page - 1)), - 'title' => _('Next Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('showstream', - array('nickname' => $this->user->nickname, - 'page' => $this->page + 1)), - 'title' => _('Previous Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'showstream', array('nickname' => $this->user->nickname)); } function extraHead() diff --git a/actions/tag.php b/actions/tag.php index f71f6d342f..2a564a25d4 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -76,19 +76,8 @@ class TagAction extends Action */ function showRelationshipLinks() { - // Machine-readable pagination - if ($this->page > 1) { - $this->element('link', array('rel' => 'next', - 'href' => common_local_url('tag', - array('tag' => $this->tag, - 'page' => $this->page - 1)), - 'title' => _('Next Notices'))); - } - $this->element('link', array('rel' => 'prev', - 'href' => common_local_url('tag', - array('tag' => $this->tag, - 'page' => $this->page + 1)), - 'title' => _('Previous Notices'))); + $this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME + $this->page, 'tag', array('tag' => $this->tag)); } function showPageNotice() diff --git a/lib/action.php b/lib/action.php index 8d0fea7afd..80a8969fa2 100644 --- a/lib/action.php +++ b/lib/action.php @@ -938,4 +938,38 @@ class Action extends HTMLOutputter // lawsuit $this->elementEnd('div'); } } + + /** + * Generate document metadata for sequential navigation + * + * @param boolean $have_before is there something before? + * @param boolean $have_after is there something after? + * @param integer $page current page + * @param string $action current action + * @param array $args rest of query arguments + * + * @return nothing + */ + function sequenceRelationships($have_next, $have_previous, $page, $action, $args=null) + { + // Outputs machine-readable pagination in elements. + // Pattern taken from $this->pagination() method. + + // "next" is equivalent to "after" + if ($have_next) { + $pargs = array('page' => $page-1); + $newargs = $args ? array_merge($args, $pargs) : $pargs; + $this->element('link', array('rel' => 'next', + 'href' => common_local_url($action, $newargs), + 'title' => _('Next'))); + } + // "previous" is equivalent to "before" + if ($have_previous=true) { // FIXME + $pargs = array('page' => $page+1); + $newargs = $args ? array_merge($args, $pargs) : $pargs; + $this->element('link', array('rel' => 'prev', + 'href' => common_local_url($action, $newargs), + 'title' => _('Previous'))); + } + } } From c9e8b1e5c380904e479927e2f24754d8709f590e Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Wed, 11 Feb 2009 03:03:16 +1100 Subject: [PATCH 004/503] Add streamlined mobile device-friendly styles when enabled in config. A new mobile-specific style sheet is added and loaded only if the `$config['site']['mobile']` configuration variable is set to true. --- config.php.sample | 2 ++ lib/action.php | 7 ++++++ theme/base/css/mobile.css | 48 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 theme/base/css/mobile.css diff --git a/config.php.sample b/config.php.sample index a2c5801f45..d1191ea01b 100644 --- a/config.php.sample +++ b/config.php.sample @@ -18,6 +18,8 @@ $config['site']['server'] = 'localhost'; $config['site']['path'] = 'laconica'; #$config['site']['fancy'] = false; #$config['site']['theme'] = 'default'; +#To enable the built-in mobile style sheet, defaults to false. +#$config['site']['mobile'] = true; #For contact email, defaults to $_SERVER["SERVER_ADMIN"] #$config['site']['email'] = 'admin@example.net'; #Brought by... diff --git a/lib/action.php b/lib/action.php index ce92addf5c..ce37f4760a 100644 --- a/lib/action.php +++ b/lib/action.php @@ -170,6 +170,13 @@ class Action extends HTMLOutputter // lawsuit } $this->comment('[if IE]>element('link', array('rel' => 'stylesheet', + 'type' => 'text/css', + 'href' => theme_path('css/mobile.css', 'base') . '?version=' . LACONICA_VERSION, + // TODO: "handheld" CSS for other mobile devices + 'media' => 'screen and (max-device-width: 480px)')); // Mobile WebKit + } } /** diff --git a/theme/base/css/mobile.css b/theme/base/css/mobile.css new file mode 100644 index 0000000000..6cd717a4df --- /dev/null +++ b/theme/base/css/mobile.css @@ -0,0 +1,48 @@ +/** theme: base + * + * @package Laconica + * @author Meitar Moscovitz + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +/* Go linear. */ +#header, +#header address, +#site_nav_global_primary, +#anon_notice, +#site_nav_local_views .nav, +#core, +#content_inner, +#notices_primary, +.notice, +.notice .entry-title, +.notice div.entry-content, +.pagination, +.pagination .nav, +.aside .section { float: none; } + +/* And liquid. */ +#wrap { width: 95%; } + +body { font-size: 2em; } /* Make things bigger on smaller screens. */ + +#site_nav_global_primary, #site_nav_global_secondary { text-align: center; } + +.notice div.entry-content { margin-left: 0; } +address { margin: 0; } + +#anon_notice, #footer { clear: left; width: auto; font-size: .5em; } + +#content { padding: 18px 0; width: 100%; } +#content h1, #page_notice, #content_inner { padding: 0 18px; } +#content_inner { width: auto; } +.pagination .nav { overflow: auto; } + +#aside_primary { margin: 10px 0 0 0; border: none; padding: 0; width: 100%; } +#popular_notices { float: none; width: auto; } +/* Columns for supplemental info. */ +.aside .section { clear: none; padding: 9px; width: 45%; } +#top_groups_by_post { float: left; } +#featured_users { float: right; } +#export_data { display: none; } From beddf906634054b115d41046ac112cd0264dbfe1 Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Wed, 11 Feb 2009 03:12:14 +1100 Subject: [PATCH 005/503] Trigger only on handheld device screens, not on browser screens, d'oh! --- lib/action.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/action.php b/lib/action.php index ce37f4760a..3e236d7146 100644 --- a/lib/action.php +++ b/lib/action.php @@ -175,7 +175,7 @@ class Action extends HTMLOutputter // lawsuit 'type' => 'text/css', 'href' => theme_path('css/mobile.css', 'base') . '?version=' . LACONICA_VERSION, // TODO: "handheld" CSS for other mobile devices - 'media' => 'screen and (max-device-width: 480px)')); // Mobile WebKit + 'media' => 'only screen and (max-device-width: 480px)')); // Mobile WebKit } } From 07c6537898a7c839469b50121b6c6d63be07613c Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Wed, 11 Feb 2009 23:35:58 +1100 Subject: [PATCH 006/503] Style the notice form and notices to better avoid need to scroll around. --- theme/base/css/mobile.css | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/theme/base/css/mobile.css b/theme/base/css/mobile.css index 6cd717a4df..3d0455a673 100644 --- a/theme/base/css/mobile.css +++ b/theme/base/css/mobile.css @@ -12,31 +12,55 @@ #site_nav_global_primary, #anon_notice, #site_nav_local_views .nav, +#form_notice, +#form_notice .form_data li, #core, #content_inner, #notices_primary, .notice, .notice .entry-title, .notice div.entry-content, +.notice-options, +.notice .notice-options a, .pagination, .pagination .nav, .aside .section { float: none; } +.notice-options .notice_reply, +.notice-options .notice_delete, +.notice-options .form_favor, +.notice-options .form_disfavor { position: static; } + +#form_notice, +#anon_notice, +#content_inner, +#footer { width: auto; } + /* And liquid. */ #wrap { width: 95%; } -body { font-size: 2em; } /* Make things bigger on smaller screens. */ +/* Make things bigger on smaller screens. */ +body { font-size: 2em; } +.notices { font-size: 1.5em; } #site_nav_global_primary, #site_nav_global_secondary { text-align: center; } .notice div.entry-content { margin-left: 0; } address { margin: 0; } -#anon_notice, #footer { clear: left; width: auto; font-size: .5em; } +#anon_notice, #footer { clear: left; font-size: .5em; } + +#form_notice textarea { width: 80%; height: 5em; } +#form_notice .form_note { right: 20%; top: 6em; } +#form_notice .form_actions input.submit { width: auto; } #content { padding: 18px 0; width: 100%; } #content h1, #page_notice, #content_inner { padding: 0 18px; } -#content_inner { width: auto; } +.notices .entry-title, .notices div.entry-content { width: 90%; } +.notice .author .photo { height: 4.5em; width: 4.5em; } /* about double physical size; TODO: do this scaling better */ +.notice-options { position: absolute; top: 0; right: 0; padding-left: 7%; width: 3%; } +.notice-options .notice_delete a { float: left; } /* Works, but feels like it shouldn't. */ +/* TODO: Make the icons of the notice options bigger. Probably with mobile-specific images. */ .pagination .nav { overflow: auto; } #aside_primary { margin: 10px 0 0 0; border: none; padding: 0; width: 100%; } From ed964ea980be63999860aaa5f39274768eca5d59 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 14 Feb 2009 21:55:25 -0500 Subject: [PATCH 007/503] Optionally ignore some notice sources for public page We optionally ignore some notice sources from the public page. Typically these are automatic notice sources like twitterfeed that don't usually represent the community on the site very well. --- classes/Notice.php | 4 +++- config.php.sample | 8 ++++++++ lib/common.php | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 3299883686..cc7de63c20 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -136,10 +136,12 @@ class Notice extends Memcached_DataObject $notice->profile_id = $profile_id; $blacklist = common_config('public', 'blacklist'); + $autosource = common_config('public', 'autosource'); # Blacklisted are non-false, but not 1, either - if ($blacklist && in_array($profile_id, $blacklist)) { + if (($blacklist && in_array($profile_id, $blacklist)) || + ($source && $autosource && in_array($source, $autosource))) { $notice->is_local = -1; } else { $notice->is_local = $is_local; diff --git a/config.php.sample b/config.php.sample index db1a216635..efb5aa4432 100644 --- a/config.php.sample +++ b/config.php.sample @@ -107,6 +107,14 @@ $config['sphinx']['port'] = 3312; #$config['public']['blacklist'][] = 123; #$config['public']['blacklist'][] = 2307; +#Mark certain notice sources as automatic and thus not +#appropriate for public feed +#$config['public]['autosource'][] = 'twitterfeed'; +#$config['public]['autosource'][] = 'rssdent'; +#$config['public]['autosource'][] = 'Ping.Fm'; +#$config['public]['autosource'][] = 'HelloTxt'; +#$config['public]['autosource'][] = 'Updating.Me'; + #Do notice broadcasts offline #If you use this, you must run the six offline daemons in the #background. See the README for details. diff --git a/lib/common.php b/lib/common.php index 5b4e3c40c8..bf49fff6b4 100644 --- a/lib/common.php +++ b/lib/common.php @@ -100,7 +100,8 @@ $config = array('server' => null), 'public' => array('localonly' => true, - 'blacklist' => array()), + 'blacklist' => array(), + 'autosource' => array()), 'theme' => array('server' => null), 'throttle' => From 9d81cef5cc2a0a197a0223206ba3d9a687065886 Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Mon, 16 Feb 2009 15:45:18 +1100 Subject: [PATCH 008/503] Add framebusting JavaScript to help avoid clickjacking attacks. --- lib/action.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/action.php b/lib/action.php index cd0db53999..48d5821a17 100644 --- a/lib/action.php +++ b/lib/action.php @@ -205,6 +205,9 @@ class Action extends HTMLOutputter // lawsuit $this->element('script', array('type' => 'text/javascript', 'src' => common_path('js/util.js?version='.LACONICA_VERSION)), ' '); + // Frame-busting code to avoid clickjacking attacks. + $this->element('script', array('type' => 'text/javascript'), + 'if (window.top !== window.self) { window.top.location.href = window.self.location.href; }'); Event::handle('EndShowLaconicaScripts', array($this)); } Event::handle('EndShowScripts', array($this)); From ab3c5d6f2d93843c199ebc4183f9ba307db1377d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 16 Feb 2009 17:58:24 -0800 Subject: [PATCH 009/503] Updated README with section about installing the Facebook app, and added info about twitterqueuehandler.php and facebookqueuehandler.php. --- README | 53 ++++++++++++++++++++++++++++++++++++++++++++++- config.php.sample | 2 +- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/README b/README index 989fcb7f0a..67dc9a66b3 100644 --- a/README +++ b/README @@ -507,7 +507,7 @@ server is probably a good idea for high-volume sites. needs as a parameter the install path; if you run it from the Laconica dir, "." should suffice. -This will run six (for now) queue handlers: +This will run eight (for now) queue handlers: * xmppdaemon.php - listens for new XMPP messages from users and stores them as notices in the database. @@ -521,6 +521,10 @@ This will run six (for now) queue handlers: of registered users. * xmppconfirmhandler.php - sends confirmation messages to registered users. +* twitterqueuehandler.php - sends queued notices to Twitter for user + who have opted to set up Twitter bridging. +* facebookqueuehandler.php - sends queued notices to Facebook for users + of the built-in Facebook application. Note that these queue daemons are pretty raw, and need your care. In particular, they leak memory, and you may want to restart them on a @@ -553,6 +557,53 @@ Sample cron job: # Update Twitter friends subscriptions every half hour 0,30 * * * * /path/to/php /path/to/laconica/scripts/synctwitterfriends.php>&/dev/null +Built-in Facebook Application +----------------------------- + +Laconica's Facebook application allows your users to automatically +update their Facebook statuses with their latest notices, invite +their friends to use the app (and thus your site), view their notice +timelines, and post notices -- all from within Facebook. The application +is built into Laconica and runs on your host. For automatic Facebook +status updating to work you will need to enable queuing and run the +facebookqueuehandler.php daemon (see the "Queues and daemons" section +above). + +Quick setup instructions*: + +Install the Facebook Developer application on Facebook: + + http://www.facebook.com/developers/ + +Use it to create a new application and generate an API key and secret. +Uncomment the Facebook app section of your config.php and copy in the +key and secret, e.g.: + + # Config section for the built-in Facebook application + $config['facebook']['apikey'] = 'APIKEY'; + $config['facebook']['secret'] = 'SECRET'; + +In Facebook's application editor, specify the following URLs for your app: + +- Callback URL: http://example.net/mublog/facebook/ +- Post-Remove URL: http://example.net/mublog/facebook/remove +- Post-Add Redirect URL: http://apps.facebook.com/yourapp/ +- Canvas URL: http://apps.facebook.com/yourapp/ + +(Replace 'example.net' with your host's URL, 'mublog' with the path +to your Laconica installation, and 'yourapp' with the name of the +Facebook application you created.) + +Additionally, Choose "Web" for Application type in the Advanced tab. +In the "Canvas setting" section, choose the "FBML" for Render Method, +"Smart Size" for IFrame size, and "Full width (760px)" for Canvas Width. +Everything else can be left with default values. + +*For more detailed instructions please see the installation guide on the +Laconica wiki: + + http://laconi.ca/trac/wiki/FacebookApplication + Sitemaps -------- diff --git a/config.php.sample b/config.php.sample index 3fa898e1be..da31545074 100644 --- a/config.php.sample +++ b/config.php.sample @@ -147,7 +147,7 @@ $config['sphinx']['port'] = 3312; #$config['profile']['banned'][] = 'hacker'; #$config['profile']['banned'][] = 12345; -# config section for the built-in Facebook application +# Config section for the built-in Facebook application #$config['facebook']['apikey'] = 'APIKEY'; #$config['facebook']['secret'] = 'SECRET'; From 4327ae19d49384ca2f4b65b04926fb2fbea7d28d Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Tue, 17 Feb 2009 18:37:02 +1100 Subject: [PATCH 010/503] Fixes ticket:1053; removes spacing between hash and tag on profile page. --- actions/showstream.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/actions/showstream.php b/actions/showstream.php index c736c99b5d..65482167e1 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -292,11 +292,11 @@ class ShowstreamAction extends Action $this->elementStart('ul', 'tags xoxo'); foreach ($tags as $tag) { $this->elementStart('li'); - $this->element('span', 'mark_hash', '#'); - $this->element('a', array('rel' => 'tag', - 'href' => common_local_url('peopletag', - array('tag' => $tag))), - $tag); + // Avoid space by using raw output. + $pt = '#'; + $this->raw($pt); $this->elementEnd('li'); } $this->elementEnd('ul'); From 75ebd45ebdcf26849e47d3c11a2cc2aa6e946c01 Mon Sep 17 00:00:00 2001 From: Sean Murphy Date: Mon, 9 Feb 2009 17:29:27 -0500 Subject: [PATCH 011/503] Fixed #1170: Auto-linking bug when URL cotains special chars. --- lib/util.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/util.php b/lib/util.php index 7ce4e229eb..5204693bc5 100644 --- a/lib/util.php +++ b/lib/util.php @@ -412,8 +412,8 @@ function common_replace_urls_callback($text, $callback) { // Then clean up what the regex left behind $offset = 0; - foreach($matches[0] as $url) { - $url = htmlspecialchars_decode($url); + foreach($matches[0] as $orig_url) { + $url = htmlspecialchars_decode($orig_url); // Make sure we didn't pick up an email address if (preg_match('#^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$#i', $url)) continue; @@ -456,6 +456,9 @@ function common_replace_urls_callback($text, $callback) { if (!in_array($url_parts[2], $tlds)) continue; + // Put the url back the way we found it. + $url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url); + // Call user specified func $modified_url = $callback($url); From 7bcfc9f6434e903936cbd6d47a2c25081f75eb04 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 17 Feb 2009 12:08:53 -0500 Subject: [PATCH 012/503] another system message --- scripts/xmppdaemon.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index 01fe8914f1..ef3f8c63d8 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -208,6 +208,8 @@ class XMPPDaemon extends Daemon { if (preg_match('/[\[\(]?[Aa]uto[-\s]?[Rr]e(ply|sponse)[\]\)]/', $txt)) { return true; + } else if (preg_match('/^System: Message wasn\'t delivered. Offline storage size was exceeded.$/', $txt)) { + return true; } else { return false; } From d8b6762e6dcb776571797f51d7c7d4cb99c9ef31 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 18 Feb 2009 09:35:59 -0500 Subject: [PATCH 013/503] move peoplesearchresults to its own module --- actions/peoplesearch.php | 26 +------------ lib/peoplesearchresults.php | 75 +++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 lib/peoplesearchresults.php diff --git a/actions/peoplesearch.php b/actions/peoplesearch.php index 615201c461..14177fcf0d 100644 --- a/actions/peoplesearch.php +++ b/actions/peoplesearch.php @@ -86,33 +86,9 @@ class PeoplesearchAction extends SearchAction } $profile->free(); - + $this->pagination($page > 1, $cnt > PROFILES_PER_PAGE, $page, 'peoplesearch', array('q' => $q)); } } -class PeopleSearchResults extends ProfileList -{ - var $terms = null; - var $pattern = null; - - function __construct($profile, $terms, $action) - { - parent::__construct($profile, $terms, $action); - $this->terms = array_map('preg_quote', - array_map('htmlspecialchars', $terms)); - $this->pattern = '/('.implode('|',$terms).')/i'; - } - - function highlight($text) - { - return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); - } - - function isReadOnly() - { - return true; - } -} - diff --git a/lib/peoplesearchresults.php b/lib/peoplesearchresults.php new file mode 100644 index 0000000000..f8ab7cf3b6 --- /dev/null +++ b/lib/peoplesearchresults.php @@ -0,0 +1,75 @@ + + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/profilelist.php'; + +/** + * People search results class + * + * Derivative of ProfileList with specialization for highlighting search terms. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @author Robin Millette + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * @see PeoplesearchAction + */ + +class PeopleSearchResults extends ProfileList +{ + var $terms = null; + var $pattern = null; + + function __construct($profile, $terms, $action) + { + parent::__construct($profile, $terms, $action); + $this->terms = array_map('preg_quote', + array_map('htmlspecialchars', $terms)); + $this->pattern = '/('.implode('|',$terms).')/i'; + } + + function highlight($text) + { + return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); + } + + function isReadOnly() + { + return true; + } +} + From 28e1c163e3e14b646851d7641c1c8a6a00de8fdc Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 18 Feb 2009 15:33:52 -0800 Subject: [PATCH 014/503] Open the /api/laconica/config.format API method so clients can determine whether a site is "private". --- actions/api.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actions/api.php b/actions/api.php index 21fe4eea32..a27d244929 100644 --- a/actions/api.php +++ b/actions/api.php @@ -131,13 +131,13 @@ class ApiAction extends Action 'statuses/followers', 'favorites/favorites'); - # If the site is "private", all API methods need authentication - - if (common_config('site', 'private')) { - return true; - } - $fullname = "$this->api_action/$this->api_method"; + + // If the site is "private", all API methods except laconica/config + // need authentication + if (common_config('site', 'private')) { + return $fullname != 'laconica/config' || false; + } if (in_array($fullname, $bareauth)) { # bareauth: only needs auth if without an argument From c9def4a8768239093823fbe34367d97f9e30d320 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 18 Feb 2009 23:43:26 +0000 Subject: [PATCH 015/503] more correct handling of etags and last-modified --- lib/action.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/action.php b/lib/action.php index e2d09ace2b..b1e700b670 100644 --- a/lib/action.php +++ b/lib/action.php @@ -209,12 +209,10 @@ class Action extends HTMLOutputter // lawsuit 'src' => common_path('js/jquery.form.js')), ' '); - $this->element('script', array('type' => 'text/javascript', 'src' => common_path('js/jquery.simplemodal-1.2.2.pack.js')), ' '); - Event::handle('EndShowJQueryScripts', array($this)); } if (Event::handle('StartShowLaconicaScripts', array($this))) { @@ -813,8 +811,10 @@ class Action extends HTMLOutputter // lawsuit if ($if_modified_since) { $ims = strtotime($if_modified_since); if ($lm <= $ims) { - if (!$etag || - $this->_hasEtag($etag, $_SERVER['HTTP_IF_NONE_MATCH'])) { + $if_none_match = $_SERVER['HTTP_IF_NONE_MATCH']; + if (!$if_none_match || + !$etag || + $this->_hasEtag($etag, $if_none_match)) { header('HTTP/1.1 304 Not Modified'); // Better way to do this? exit(0); @@ -832,9 +832,11 @@ class Action extends HTMLOutputter // lawsuit * * @return boolean */ + function _hasEtag($etag, $if_none_match) { - return ($if_none_match) && in_array($etag, explode(',', $if_none_match)); + $etags = explode(',', $if_none_match); + return in_array($etag, $etags) || in_array('*', $etags); } /** From 8fc7f5204e7ed07b9450b7650bce6317ea8e79ae Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 19 Feb 2009 02:55:04 +0000 Subject: [PATCH 016/503] Minor CSS cleanup. --- theme/base/css/display.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 5ce5ac884d..b5796374ec 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -27,7 +27,6 @@ overflow:hidden; } h1 { font-size:1.4em; -line-height:1; margin-bottom:18px; } h2 { font-size:1.3em; } @@ -365,7 +364,6 @@ margin-right:4px; #wrap { margin:0 auto; -width:71.714em; width:1003px; overflow:hidden; } From 1abeaf931e2e22806cbf747690df3a3350b401f8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 14:58:38 +0000 Subject: [PATCH 017/503] handle if-modified-since in RSS feeds --- lib/rssaction.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/rssaction.php b/lib/rssaction.php index 131e8ac65a..66c2d9e8cd 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -38,6 +38,7 @@ class Rss10Action extends Action var $creators = array(); var $limit = DEFAULT_RSS_LIMIT; + var $notices = null; /** * Constructor @@ -93,6 +94,9 @@ class Rss10Action extends Action function handle($args) { + // Get the list of notices + $this->notices = $this->getNotices(); + // Parent handling, including cache check parent::handle($args); $this->showRss($this->limit); } @@ -258,5 +262,25 @@ class Rss10Action extends Action { $this->elementEnd('rdf:RDF'); } + + /** + * When was this page last modified? + * + */ + + function lastModified() + { + if (empty($this->notices)) { + return null; + } + + if (count($this->notices) == 0) { + return null; + } + + // FIXME: doesn't handle modified profiles, avatars, deleted notices + + return strtotime($this->notices[0]->created); + } } From 5ec5a22dc75cb8f4d896b41ca24067c68d3e1de6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 10:04:28 -0500 Subject: [PATCH 018/503] make tagother work with router --- actions/tagother.php | 3 ++- lib/router.php | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/actions/tagother.php b/actions/tagother.php index 79151c9118..0d18945a09 100644 --- a/actions/tagother.php +++ b/actions/tagother.php @@ -135,7 +135,8 @@ class TagotherAction extends Action 'id' => 'form_tag_user', 'class' => 'form_settings', 'name' => 'tagother', - 'action' => $this->selfUrl())); + 'action' => common_local_url('tagother', array('id' => $this->profile->id)))); + $this->elementStart('fieldset'); $this->element('legend', null, _('Tag user')); $this->hidden('token', common_session_token()); diff --git a/lib/router.php b/lib/router.php index d47ad71183..e55b597f21 100644 --- a/lib/router.php +++ b/lib/router.php @@ -98,12 +98,14 @@ class Router $main = array('login', 'logout', 'register', 'subscribe', 'unsubscribe', 'confirmaddress', 'recoverpassword', 'invite', 'favor', 'disfavor', 'sup', - 'tagother', 'block'); + 'block'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); } + $m->connect('main/tagother/:id', array('action' => 'tagother')); + // these take a code foreach (array('register', 'confirmaddress', 'recoverpassword') as $c) { From 2ac684f53df3f76aacb4d1be79d7db64567f1964 Mon Sep 17 00:00:00 2001 From: Federico Marani Date: Fri, 20 Feb 2009 18:57:20 +0000 Subject: [PATCH 019/503] * implemented STOMP support for external message queueing systems * (ticket-724) * included PHP STOMP libraries (http://code.google.com/p/stompcli/) --- config.php.sample | 8 + extlib/Stomp.php | 594 +++++++++++++++++++++++++++++++++ extlib/Stomp/Exception.php | 57 ++++ extlib/Stomp/Frame.php | 80 +++++ extlib/Stomp/Message.php | 37 ++ extlib/Stomp/Message/Bytes.php | 47 +++ extlib/Stomp/Message/Map.php | 55 +++ lib/queuehandler.php | 74 +++- lib/util.php | 48 ++- 9 files changed, 980 insertions(+), 20 deletions(-) create mode 100644 extlib/Stomp.php create mode 100644 extlib/Stomp/Exception.php create mode 100644 extlib/Stomp/Frame.php create mode 100644 extlib/Stomp/Message.php create mode 100644 extlib/Stomp/Message/Bytes.php create mode 100644 extlib/Stomp/Message/Map.php diff --git a/config.php.sample b/config.php.sample index a2c5801f45..cc2e4c3c14 100644 --- a/config.php.sample +++ b/config.php.sample @@ -112,6 +112,14 @@ $config['sphinx']['port'] = 3312; #background. See the README for details. #$config['queue']['enabled'] = true; +#Queue subsystem +#subsystems: internal (default) or stomp +#using stomp requires an external message queue server +#$config['queue']['subsystem'] = 'stomp'; +#$config['queue']['stomp_server'] = 'tcp://localhost:61613'; +#use different queue_basename for each laconica instance managed by the server +#$config['queue']['queue_basename'] = 'laconica'; + #The following customise the behaviour of the various daemons: #$config['daemon']['piddir'] = '/var/run'; #$config['daemon']['user'] = false; diff --git a/extlib/Stomp.php b/extlib/Stomp.php new file mode 100644 index 0000000000..9e1c97b3b3 --- /dev/null +++ b/extlib/Stomp.php @@ -0,0 +1,594 @@ + + * @author Dejan Bosanac + * @author Michael Caplan + * @version $Revision: 43 $ + */ +class Stomp +{ + /** + * Perform request synchronously + * + * @var boolean + */ + public $sync = false; + + /** + * Default prefetch size + * + * @var int + */ + public $prefetchSize = 1; + + /** + * Client id used for durable subscriptions + * + * @var string + */ + public $clientId = null; + + protected $_brokerUri = null; + protected $_socket = null; + protected $_hosts = array(); + protected $_params = array(); + protected $_subscriptions = array(); + protected $_defaultPort = 61613; + protected $_currentHost = - 1; + protected $_attempts = 10; + protected $_username = ''; + protected $_password = ''; + protected $_sessionId; + protected $_read_timeout_seconds = 60; + protected $_read_timeout_milliseconds = 0; + + /** + * Constructor + * + * @param string $brokerUri Broker URL + * @throws Stomp_Exception + */ + public function __construct ($brokerUri) + { + $this->_brokerUri = $brokerUri; + $this->_init(); + } + /** + * Initialize connection + * + * @throws Stomp_Exception + */ + protected function _init () + { + $pattern = "|^(([a-zA-Z]+)://)+\(*([a-zA-Z0-9\.:/i,-]+)\)*\??([a-zA-Z0-9=]*)$|i"; + if (preg_match($pattern, $this->_brokerUri, $regs)) { + $scheme = $regs[2]; + $hosts = $regs[3]; + $params = $regs[4]; + if ($scheme != "failover") { + $this->_processUrl($this->_brokerUri); + } else { + $urls = explode(",", $hosts); + foreach ($urls as $url) { + $this->_processUrl($url); + } + } + if ($params != null) { + parse_str($params, $this->_params); + } + } else { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception("Bad Broker URL {$this->_brokerUri}"); + } + } + /** + * Process broker URL + * + * @param string $url Broker URL + * @throws Stomp_Exception + * @return boolean + */ + protected function _processUrl ($url) + { + $parsed = parse_url($url); + if ($parsed) { + array_push($this->_hosts, array($parsed['host'] , $parsed['port'] , $parsed['scheme'])); + } else { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception("Bad Broker URL $url"); + } + } + /** + * Make socket connection to the server + * + * @throws Stomp_Exception + */ + protected function _makeConnection () + { + if (count($this->_hosts) == 0) { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception("No broker defined"); + } + + // force disconnect, if previous established connection exists + $this->disconnect(); + + $i = $this->_currentHost; + $att = 0; + $connected = false; + while (! $connected && $att ++ < $this->_attempts) { + if (isset($this->_params['randomize']) && $this->_params['randomize'] == 'true') { + $i = rand(0, count($this->_hosts) - 1); + } else { + $i = ($i + 1) % count($this->_hosts); + } + $broker = $this->_hosts[$i]; + $host = $broker[0]; + $port = $broker[1]; + $scheme = $broker[2]; + if ($port == null) { + $port = $this->_defaultPort; + } + if ($this->_socket != null) { + fclose($this->_socket); + $this->_socket = null; + } + $this->_socket = @fsockopen($scheme . '://' . $host, $port); + if (!is_resource($this->_socket) && $att >= $this->_attempts && !array_key_exists($i + 1, $this->_hosts)) { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception("Could not connect to $host:$port ($att/{$this->_attempts})"); + } else if (is_resource($this->_socket)) { + $connected = true; + $this->_currentHost = $i; + break; + } + } + if (! $connected) { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception("Could not connect to a broker"); + } + } + /** + * Connect to server + * + * @param string $username + * @param string $password + * @return boolean + * @throws Stomp_Exception + */ + public function connect ($username = '', $password = '') + { + $this->_makeConnection(); + if ($username != '') { + $this->_username = $username; + } + if ($password != '') { + $this->_password = $password; + } + $headers = array('login' => $this->_username , 'passcode' => $this->_password); + if ($this->clientId != null) { + $headers["client-id"] = $this->clientId; + } + $frame = new Stomp_Frame("CONNECT", $headers); + $this->_writeFrame($frame); + $frame = $this->readFrame(); + if ($frame instanceof Stomp_Frame && $frame->command == 'CONNECTED') { + $this->_sessionId = $frame->headers["session"]; + return true; + } else { + require_once 'Stomp/Exception.php'; + if ($frame instanceof Stomp_Frame) { + throw new Stomp_Exception("Unexpected command: {$frame->command}", 0, $frame->body); + } else { + throw new Stomp_Exception("Connection not acknowledged"); + } + } + } + + /** + * Check if client session has ben established + * + * @return boolean + */ + public function isConnected () + { + return !empty($this->_sessionId) && is_resource($this->_socket); + } + /** + * Current stomp session ID + * + * @return string + */ + public function getSessionId() + { + return $this->_sessionId; + } + /** + * Send a message to a destination in the messaging system + * + * @param string $destination Destination queue + * @param string|Stomp_Frame $msg Message + * @param array $properties + * @param boolean $sync Perform request synchronously + * @return boolean + */ + public function send ($destination, $msg, $properties = null, $sync = null) + { + if ($msg instanceof Stomp_Frame) { + $msg->headers['destination'] = $destination; + $msg->headers = array_merge($msg->headers, $properties); + $frame = $msg; + } else { + $headers = $properties; + $headers['destination'] = $destination; + $frame = new Stomp_Frame('SEND', $headers, $msg); + } + $this->_prepareReceipt($frame, $sync); + $this->_writeFrame($frame); + return $this->_waitForReceipt($frame, $sync); + } + /** + * Prepair frame receipt + * + * @param Stomp_Frame $frame + * @param boolean $sync + */ + protected function _prepareReceipt (Stomp_Frame $frame, $sync) + { + $receive = $this->sync; + if ($sync !== null) { + $receive = $sync; + } + if ($receive == true) { + $frame->headers['receipt'] = md5(microtime()); + } + } + /** + * Wait for receipt + * + * @param Stomp_Frame $frame + * @param boolean $sync + * @return boolean + * @throws Stomp_Exception + */ + protected function _waitForReceipt (Stomp_Frame $frame, $sync) + { + + $receive = $this->sync; + if ($sync !== null) { + $receive = $sync; + } + if ($receive == true) { + $id = (isset($frame->headers['receipt'])) ? $frame->headers['receipt'] : null; + if ($id == null) { + return true; + } + $frame = $this->readFrame(); + if ($frame instanceof Stomp_Frame && $frame->command == 'RECEIPT') { + if ($frame->headers['receipt-id'] == $id) { + return true; + } else { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception("Unexpected receipt id {$frame->headers['receipt-id']}", 0, $frame->body); + } + } else { + require_once 'Stomp/Exception.php'; + if ($frame instanceof Stomp_Frame) { + throw new Stomp_Exception("Unexpected command {$frame->command}", 0, $frame->body); + } else { + throw new Stomp_Exception("Receipt not received"); + } + } + } + return true; + } + /** + * Register to listen to a given destination + * + * @param string $destination Destination queue + * @param array $properties + * @param boolean $sync Perform request synchronously + * @return boolean + * @throws Stomp_Exception + */ + public function subscribe ($destination, $properties = null, $sync = null) + { + $headers = array('ack' => 'client'); + $headers['activemq.prefetchSize'] = $this->prefetchSize; + if ($this->clientId != null) { + $headers["activemq.subcriptionName"] = $this->clientId; + } + if (isset($properties)) { + foreach ($properties as $name => $value) { + $headers[$name] = $value; + } + } + $headers['destination'] = $destination; + $frame = new Stomp_Frame('SUBSCRIBE', $headers); + $this->_prepareReceipt($frame, $sync); + $this->_writeFrame($frame); + if ($this->_waitForReceipt($frame, $sync) == true) { + $this->_subscriptions[$destination] = $properties; + return true; + } else { + return false; + } + } + /** + * Remove an existing subscription + * + * @param string $destination + * @param array $properties + * @param boolean $sync Perform request synchronously + * @return boolean + * @throws Stomp_Exception + */ + public function unsubscribe ($destination, $properties = null, $sync = null) + { + $headers = array(); + if (isset($properties)) { + foreach ($properties as $name => $value) { + $headers[$name] = $value; + } + } + $headers['destination'] = $destination; + $frame = new Stomp_Frame('UNSUBSCRIBE', $headers); + $this->_prepareReceipt($frame, $sync); + $this->_writeFrame($frame); + if ($this->_waitForReceipt($frame, $sync) == true) { + unset($this->_subscriptions[$destination]); + return true; + } else { + return false; + } + } + /** + * Start a transaction + * + * @param string $transactionId + * @param boolean $sync Perform request synchronously + * @return boolean + * @throws Stomp_Exception + */ + public function begin ($transactionId = null, $sync = null) + { + $headers = array(); + if (isset($transactionId)) { + $headers['transaction'] = $transactionId; + } + $frame = new Stomp_Frame('BEGIN', $headers); + $this->_prepareReceipt($frame, $sync); + $this->_writeFrame($frame); + return $this->_waitForReceipt($frame, $sync); + } + /** + * Commit a transaction in progress + * + * @param string $transactionId + * @param boolean $sync Perform request synchronously + * @return boolean + * @throws Stomp_Exception + */ + public function commit ($transactionId = null, $sync = null) + { + $headers = array(); + if (isset($transactionId)) { + $headers['transaction'] = $transactionId; + } + $frame = new Stomp_Frame('COMMIT', $headers); + $this->_prepareReceipt($frame, $sync); + $this->_writeFrame($frame); + return $this->_waitForReceipt($frame, $sync); + } + /** + * Roll back a transaction in progress + * + * @param string $transactionId + * @param boolean $sync Perform request synchronously + */ + public function abort ($transactionId = null, $sync = null) + { + $headers = array(); + if (isset($transactionId)) { + $headers['transaction'] = $transactionId; + } + $frame = new Stomp_Frame('ABORT', $headers); + $this->_prepareReceipt($frame, $sync); + $this->_writeFrame($frame); + return $this->_waitForReceipt($frame, $sync); + } + /** + * Acknowledge consumption of a message from a subscription + * Note: This operation is always asynchronous + * + * @param string|Stomp_Frame $messageMessage ID + * @param string $transactionId + * @return boolean + * @throws Stomp_Exception + */ + public function ack ($message, $transactionId = null) + { + if ($message instanceof Stomp_Frame) { + $frame = new Stomp_Frame('ACK', $message->headers); + $this->_writeFrame($frame); + return true; + } else { + $headers = array(); + if (isset($transactionId)) { + $headers['transaction'] = $transactionId; + } + $headers['message-id'] = $message; + $frame = new Stomp_Frame('ACK', $headers); + $this->_writeFrame($frame); + return true; + } + } + /** + * Graceful disconnect from the server + * + */ + public function disconnect () + { + $header = array(); + + if ($this->clientId != null) { + $headers["client-id"] = $this->clientId; + } + + if (is_resource($this->_socket)) { + $this->_writeFrame(new Stomp_Frame('DISCONNECT', $headers)); + fclose($this->_socket); + } + $this->_socket = null; + $this->_sessionId = null; + $this->_currentHost = -1; + $this->_subscriptions = array(); + $this->_username = ''; + $this->_password = ''; + } + /** + * Write frame to server + * + * @param Stomp_Frame $stompFrame + */ + protected function _writeFrame (Stomp_Frame $stompFrame) + { + if (!is_resource($this->_socket)) { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception('Socket connection hasn\'t been established'); + } + + $data = $stompFrame->__toString(); + $r = fwrite($this->_socket, $data, strlen($data)); + if ($r === false || $r == 0) { + $this->_reconnect(); + $this->_writeFrame($stompFrame); + } + } + + /** + * Set timeout to wait for content to read + * + * @param int $seconds_to_wait Seconds to wait for a frame + * @param int $milliseconds Milliseconds to wait for a frame + */ + public function setReadTimeout($seconds, $milliseconds = 0) + { + $this->_read_timeout_seconds = $seconds; + $this->_read_timeout_milliseconds = $milliseconds; + } + + /** + * Read responce frame from server + * + * @return Stomp_Frame|Stomp_Message_Map|boolean False when no frame to read + */ + public function readFrame () + { + if (!$this->hasFrameToRead()) { + return false; + } + + $rb = 1024; + $data = ''; + do { + $read = fgets($this->_socket, $rb); + if ($read === false) { + $this->_reconnect(); + return $this->readFrame(); + } + $data .= $read; + $len = strlen($data); + } while (($len < 2 || ! ($data[$len - 2] == "\x00" && $data[$len - 1] == "\n"))); + + list ($header, $body) = explode("\n\n", $data, 2); + $header = explode("\n", $header); + $headers = array(); + $command = null; + foreach ($header as $v) { + if (isset($command)) { + list ($name, $value) = explode(':', $v, 2); + $headers[$name] = $value; + } else { + $command = $v; + } + } + $frame = new Stomp_Frame($command, $headers, trim($body)); + if (isset($frame->headers['amq-msg-type']) && $frame->headers['amq-msg-type'] == 'MapMessage') { + require_once 'Stomp/Message/Map.php'; + return new Stomp_Message_Map($frame); + } else { + return $frame; + } + } + + /** + * Check if there is a frame to read + * + * @return boolean + */ + public function hasFrameToRead() + { + $read = array($this->_socket); + $write = null; + $except = null; + + $has_frame_to_read = stream_select($read, $write, $except, $this->_read_timeout_seconds, $this->_read_timeout_milliseconds); + + if ($has_frame_to_read === false) { + throw new Stomp_Exception('Check failed to determin if the socket is readable'); + } else if ($has_frame_to_read > 0) { + return true; + } else { + return false; + } + } + + /** + * Reconnects and renews subscriptions (if there were any) + * Call this method when you detect connection problems + */ + protected function _reconnect () + { + $subscriptions = $this->_subscriptions; + + $this->connect($this->_username, $this->_password); + foreach ($subscriptions as $dest => $properties) { + $this->subscribe($dest, $properties); + } + } + /** + * Graceful object desruction + * + */ + public function __destruct() + { + $this->disconnect(); + } +} +?> diff --git a/extlib/Stomp/Exception.php b/extlib/Stomp/Exception.php new file mode 100644 index 0000000000..e6870bc15d --- /dev/null +++ b/extlib/Stomp/Exception.php @@ -0,0 +1,57 @@ + + * @version $Revision: 23 $ + */ +class Stomp_Exception extends Exception +{ + protected $_details; + + /** + * Constructor + * + * @param string $message Error message + * @param int $code Error code + * @param string $details Stomp server error details + */ + public function __construct($message = null, $code = 0, $details = '') + { + $this->_details = $details; + + parent::__construct($message, $code); + } + + /** + * Stomp server error details + * + * @return string + */ + public function getDetails() + { + return $this->_details; + } +} +?> \ No newline at end of file diff --git a/extlib/Stomp/Frame.php b/extlib/Stomp/Frame.php new file mode 100644 index 0000000000..dc59c1cb7f --- /dev/null +++ b/extlib/Stomp/Frame.php @@ -0,0 +1,80 @@ + + * @author Dejan Bosanac + * @author Michael Caplan + * @version $Revision: 36 $ + */ +class Stomp_Frame +{ + public $command; + public $headers = array(); + public $body; + + /** + * Constructor + * + * @param string $command + * @param array $headers + * @param string $body + */ + public function __construct ($command = null, $headers = null, $body = null) + { + $this->_init($command, $headers, $body); + } + + protected function _init ($command = null, $headers = null, $body = null) + { + $this->command = $command; + if ($headers != null) { + $this->headers = $headers; + } + $this->body = $body; + + if ($this->command == 'ERROR') { + require_once 'Stomp/Exception.php'; + throw new Stomp_Exception($this->headers['message'], 0, $this->body); + } + } + + /** + * Convert frame to transportable string + * + * @return string + */ + public function __toString() + { + $data = $this->command . "\n"; + + foreach ($this->headers as $name => $value) { + $data .= $name . ": " . $value . "\n"; + } + + $data .= "\n"; + $data .= $this->body; + return $data .= "\x00\n"; + } +} +?> \ No newline at end of file diff --git a/extlib/Stomp/Message.php b/extlib/Stomp/Message.php new file mode 100644 index 0000000000..6bcad3efd9 --- /dev/null +++ b/extlib/Stomp/Message.php @@ -0,0 +1,37 @@ + + * @version $Revision: 23 $ + */ +class Stomp_Message extends Stomp_Frame +{ + public function __construct ($body, $headers = null) + { + $this->_init("SEND", $headers, $body); + } +} +?> \ No newline at end of file diff --git a/extlib/Stomp/Message/Bytes.php b/extlib/Stomp/Message/Bytes.php new file mode 100644 index 0000000000..c75f23e43a --- /dev/null +++ b/extlib/Stomp/Message/Bytes.php @@ -0,0 +1,47 @@ + + * @version $Revision: 23 $ + */ +class Stomp_Message_Bytes extends Stomp_Message +{ + /** + * Constructor + * + * @param string $body + * @param array $headers + */ + function __construct ($body, $headers = null) + { + $this->_init("SEND", $headers, $body); + if ($this->headers == null) { + $this->headers = array(); + } + $this->headers['content-length'] = count($body); + } +} +?> \ No newline at end of file diff --git a/extlib/Stomp/Message/Map.php b/extlib/Stomp/Message/Map.php new file mode 100644 index 0000000000..288456a849 --- /dev/null +++ b/extlib/Stomp/Message/Map.php @@ -0,0 +1,55 @@ + + * @version $Revision: 23 $ + */ +class Stomp_Message_Map extends Stomp_Message +{ + public $map; + + /** + * Constructor + * + * @param Stomp_Frame|string $msg + * @param array $headers + */ + function __construct ($msg, $headers = null) + { + if ($msg instanceof Stomp_Frame) { + $this->_init($msg->command, $msg->headers, $msg->body); + $this->map = json_decode($msg->body); + } else { + $this->_init("SEND", $headers, $msg); + if ($this->headers == null) { + $this->headers = array(); + } + $this->headers['amq-msg-type'] = 'MapMessage'; + $this->body = json_encode($msg); + } + } +} +?> \ No newline at end of file diff --git a/lib/queuehandler.php b/lib/queuehandler.php index 9ce9e32b3b..752bbc6d26 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -75,15 +75,9 @@ class QueueHandler extends Daemon return true; } - function run() - { - if (!$this->start()) { - return false; - } - $this->log(LOG_INFO, 'checking for queued notices'); - $transport = $this->transport(); + function db_dispatch() { do { - $qi = Queue_item::top($transport); + $qi = Queue_item::top($this->transport()); if ($qi) { $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($qi->created)); $notice = Notice::staticGet($qi->notice_id); @@ -115,6 +109,68 @@ class QueueHandler extends Daemon $this->idle(5); } } while (true); + } + + function stomp_dispatch() { + require("Stomp.php"); + $con = new Stomp(common_config('queue','stomp_server')); + if (!$con->connect()) { + $this->log(LOG_ERR, 'Failed to connect to queue server'); + return false; + } + $queue_basename = common_config('queue','queue_basename'); + // subscribe to the relevant queue (format: basename-transport) + $con->subscribe('/queue/'.$queue_basename.'-'.$this->transport()); + + do { + $frame = $con->readFrame(); + if ($frame) { + $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($frame->headers['created'])); + + // XXX: Now the queue handler receives only the ID of the + // notice, and it has to get it from the DB + // A massive improvement would be avoid DB query by transmitting + // all the notice details via queue server... + $notice = Notice::staticGet($frame->body); + + if ($notice) { + $this->log(LOG_INFO, 'broadcasting notice ID = ' . $notice->id); + $result = $this->handle_notice($notice); + if ($result) { + // if the msg has been handled positively, ack it + // and the queue server will remove it from the queue + $con->ack($frame); + $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); + } + else { + // no ack + $this->log(LOG_WARNING, 'Failed broadcast for notice ID = ' . $notice->id); + } + $notice->free(); + unset($notice); + $notice = null; + } else { + $this->log(LOG_WARNING, 'queue item for notice that does not exist'); + } + } + } while (true); + + $con->disconnect(); + } + + + function run() + { + if (!$this->start()) { + return false; + } + $this->log(LOG_INFO, 'checking for queued notices'); + if (common_config('queue','subsystem') == 'stomp') { + $this->stomp_dispatch(); + } + else { + $this->db_dispatch(); + } if (!$this->finish()) { return false; } @@ -143,4 +199,4 @@ class QueueHandler extends Daemon common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); } } - \ No newline at end of file + diff --git a/lib/util.php b/lib/util.php index c5a092f630..8ef19f5796 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1138,18 +1138,44 @@ function common_twitter_broadcast($notice, $flink) function common_enqueue_notice($notice) { - foreach (array('jabber', 'omb', 'sms', 'public') as $transport) { - $qi = new Queue_item(); - $qi->notice_id = $notice->id; - $qi->transport = $transport; - $qi->created = $notice->created; - $result = $qi->insert(); - if (!$result) { - $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError'); - common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message); - return false; + if (common_config('queue','subsystem') == 'stomp') { + // use an external message queue system via STOMP + require_once("Stomp.php"); + $con = new Stomp(common_config('queue','stomp_server')); + if (!$con->connect()) { + common_log(LOG_ERR, 'Failed to connect to queue server'); + return false; + } + $queue_basename = common_config('queue','queue_basename'); + foreach (array('jabber', 'omb', 'sms', 'public') as $transport) { + if (!$con->send( + '/queue/'.$queue_basename.'-'.$transport, // QUEUE + $notice->id, // BODY of the message + array ( // HEADERS of the msg + 'created' => $notice->created + ))) { + common_log(LOG_ERR, 'Error sending to '.$transport.' queue'); + return false; + } + common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' . $notice->id . ' for ' . $transport); + } + $result = true; + } + else { + // in any other case, 'internal' + foreach (array('jabber', 'omb', 'sms', 'public') as $transport) { + $qi = new Queue_item(); + $qi->notice_id = $notice->id; + $qi->transport = $transport; + $qi->created = $notice->created; + $result = $qi->insert(); + if (!$result) { + $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError'); + common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message); + return false; + } + common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport); } - common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport); } return $result; } From 4da4c94678fecb0fbf06eaba0b71d3206eb89377 Mon Sep 17 00:00:00 2001 From: Leslie Michael Orchard Date: Tue, 17 Feb 2009 23:24:10 -0500 Subject: [PATCH 020/503] Ignoring VIM swap files, log files, and httpd.conf --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f2e96d3eb6..83a53dfa3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ avatar/* files/* _darcs/* +logs/* config.php .htaccess +httpd.conf *.tmproj dataobject.ini *~ @@ -10,3 +12,4 @@ dataobject.ini *.orig *.rej .#* +*.swp From 17a6e6603058d412f3c3a7c6800f5d47fcf0def0 Mon Sep 17 00:00:00 2001 From: Leslie Michael Orchard Date: Tue, 17 Feb 2009 23:25:00 -0500 Subject: [PATCH 021/503] PROFILES_PER_PAGE already defined in lib/common.php --- lib/profilelist.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/profilelist.php b/lib/profilelist.php index 8bef49dcee..c2040fbc23 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -34,8 +34,6 @@ if (!defined('LACONICA')) { require_once INSTALLDIR.'/lib/widget.php'; -define('PROFILES_PER_PAGE', 20); - /** * Widget to show a list of profiles * From 9a0e71f9bf3329004949a0cef61abb5a354c7688 Mon Sep 17 00:00:00 2001 From: Leslie Michael Orchard Date: Tue, 17 Feb 2009 23:22:56 -0500 Subject: [PATCH 022/503] Fixing a bunch of undefined variable warnings in OpenID signup process --- actions/finishopenidlogin.php | 17 +++++++++++------ classes/User.php | 18 +++++++++--------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/actions/finishopenidlogin.php b/actions/finishopenidlogin.php index 1e7b73a7f3..6d92cb9aae 100644 --- a/actions/finishopenidlogin.php +++ b/actions/finishopenidlogin.php @@ -83,7 +83,7 @@ class FinishopenidloginAction extends Action function showContent() { - if ($this->message_text) { + if (!empty($this->message_text)) { $this->element('p', null, $this->message); return; } @@ -232,7 +232,8 @@ class FinishopenidloginAction extends Action return; } - if ($sreg['country']) { + $location = ''; + if (!empty($sreg['country'])) { if ($sreg['postcode']) { # XXX: use postcode to get city and region # XXX: also, store postcode somewhere -- it's valuable! @@ -242,12 +243,16 @@ class FinishopenidloginAction extends Action } } - if ($sreg['fullname'] && mb_strlen($sreg['fullname']) <= 255) { + if (!empty($sreg['fullname']) && mb_strlen($sreg['fullname']) <= 255) { $fullname = $sreg['fullname']; + } else { + $fullname = ''; } - if ($sreg['email'] && Validate::email($sreg['email'], true)) { + if (!empty($sreg['email']) && Validate::email($sreg['email'], true)) { $email = $sreg['email']; + } else { + $email = ''; } # XXX: add language @@ -328,7 +333,7 @@ class FinishopenidloginAction extends Action # Try the passed-in nickname - if ($sreg['nickname']) { + if (!empty($sreg['nickname'])) { $nickname = $this->nicknamize($sreg['nickname']); if ($this->isNewNickname($nickname)) { return $nickname; @@ -337,7 +342,7 @@ class FinishopenidloginAction extends Action # Try the full name - if ($sreg['fullname']) { + if (!empty($sreg['fullname'])) { $fullname = $this->nicknamize($sreg['fullname']); if ($this->isNewNickname($fullname)) { return $fullname; diff --git a/classes/User.php b/classes/User.php index 495a982360..40cf18df67 100644 --- a/classes/User.php +++ b/classes/User.php @@ -183,16 +183,16 @@ class User extends Memcached_DataObject $profile->nickname = $nickname; $profile->profileurl = common_profile_url($nickname); - if ($fullname) { + if (!empty($fullname)) { $profile->fullname = $fullname; } - if ($homepage) { + if (!empty($homepage)) { $profile->homepage = $homepage; } - if ($bio) { + if (!empty($bio)) { $profile->bio = $bio; } - if ($location) { + if (!empty($location)) { $profile->location = $location; } @@ -200,7 +200,7 @@ class User extends Memcached_DataObject $id = $profile->insert(); - if (!$id) { + if (empty($id)) { common_log_db_error($profile, 'INSERT', __FILE__); return false; } @@ -210,13 +210,13 @@ class User extends Memcached_DataObject $user->id = $id; $user->nickname = $nickname; - if ($password) { # may not have a password for OpenID users + if (!empty($password)) { # may not have a password for OpenID users $user->password = common_munge_password($password, $id); } # Users who respond to invite email have proven their ownership of that address - if ($code) { + if (!empty($code)) { $invite = Invitation::staticGet($code); if ($invite && $invite->address && $invite->address_type == 'email' && $invite->address == $email) { $user->email = $invite->address; @@ -253,7 +253,7 @@ class User extends Memcached_DataObject return false; } - if ($email && !$user->email) { + if (!empty($email) && !$user->email) { $confirm = new Confirm_address(); $confirm->code = common_confirmation_code(128); @@ -268,7 +268,7 @@ class User extends Memcached_DataObject } } - if ($code && $user->email) { + if (!empty($code) && $user->email) { $user->emailChanged(); } From 5bb32ccfd0d7bb813c8b35cfb0411625418c5402 Mon Sep 17 00:00:00 2001 From: Leslie Michael Orchard Date: Tue, 17 Feb 2009 23:09:57 -0500 Subject: [PATCH 023/503] Attempt to access non-existent OPENID_COOKIE_KEY cookie causing a warning --- lib/openid.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/openid.php b/lib/openid.php index 8605737026..5c3d460daf 100644 --- a/lib/openid.php +++ b/lib/openid.php @@ -64,6 +64,9 @@ function oid_set_last($openid_url) function oid_get_last() { + if (empty($_COOKIE[OPENID_COOKIE_KEY])) { + return null; + } $openid_url = $_COOKIE[OPENID_COOKIE_KEY]; if ($openid_url && strlen($openid_url) > 0) { return $openid_url; From 76d506cf1644390a073e5178774675c60e1c3332 Mon Sep 17 00:00:00 2001 From: Leslie Michael Orchard Date: Tue, 17 Feb 2009 22:59:48 -0500 Subject: [PATCH 024/503] NOTICES_PER_SECTION already defined in lib/noticesection.php, causing a warning --- lib/popularnoticesection.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/popularnoticesection.php b/lib/popularnoticesection.php index 5380563b9e..c7c7f02150 100644 --- a/lib/popularnoticesection.php +++ b/lib/popularnoticesection.php @@ -31,8 +31,6 @@ if (!defined('LACONICA')) { exit(1); } -define('NOTICES_PER_SECTION', 5); - /** * Base class for sections showing lists of notices * From 5c59c0d90c806636fc07ee9f2445407ad277de59 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 16:44:56 -0500 Subject: [PATCH 025/503] avoid notices on undefined array elements --- index.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index b180e2b653..a8890e9a3b 100644 --- a/index.php +++ b/index.php @@ -27,12 +27,13 @@ $action = null; function getPath($req) { - if (common_config('site', 'fancy')) { + if ((common_config('site', 'fancy') || !array_key_exists('PATH_INFO', $_SERVER)) + && array_key_exists('p', $req)) { return $req['p']; - } else if ($_SERVER['PATH_INFO']) { + } else if (array_key_exists('PATH_INFO', $_SERVER)) { return $_SERVER['PATH_INFO']; } else { - return $req['p']; + return null; } } From 424388611a347eeecd35be3a22984826dd2a503e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 16:46:26 -0500 Subject: [PATCH 026/503] accidentally used as a global in index.php --- index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index a8890e9a3b..914ba5bde1 100644 --- a/index.php +++ b/index.php @@ -116,8 +116,8 @@ function main() // XXX: find somewhere for this little block to live - if ($config['db']['mirror'] && $action_obj->isReadOnly()) { - if (is_array($config['db']['mirror'])) { + if (common_config('db', 'mirror') && $action_obj->isReadOnly()) { + if (is_array(common_config('db', 'mirror'))) { // "load balancing", ha ha $k = array_rand($config['db']['mirror']); From 85eb53247d7c0eac767de9fd79ba70183b7f57be Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 16:48:49 -0500 Subject: [PATCH 027/503] change static in router to var --- lib/router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/router.php b/lib/router.php index e55b597f21..0640a5911f 100644 --- a/lib/router.php +++ b/lib/router.php @@ -47,7 +47,7 @@ require_once 'Net/URL/Mapper.php'; class Router { - static $m = null; + var $m = null; static $inst = null; static function get() From a76099c59b616004886e3c7add06db1de53e4acf Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 16:50:05 -0500 Subject: [PATCH 028/503] make check for ->value better --- lib/noticesection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/noticesection.php b/lib/noticesection.php index 97b5175296..b31f187445 100644 --- a/lib/noticesection.php +++ b/lib/noticesection.php @@ -96,7 +96,7 @@ class NoticeSection extends Section $this->out->elementStart('p', 'entry-content'); $this->out->raw($notice->rendered); $this->out->elementEnd('p'); - if ($notice->value) { + if (!empty($notice->value)) { $this->out->elementStart('p'); $this->out->text($notice->value); $this->out->elementEnd('p'); From d5bf7e5cfb4b4de335cafec69d93c565e0c9d2f4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 16:51:39 -0500 Subject: [PATCH 029/503] fix notice in searchaction --- lib/searchaction.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/searchaction.php b/lib/searchaction.php index fdfb8dc5ad..df68764459 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -79,10 +79,11 @@ class SearchAction extends Action function showTop($arr=null) { + $error = null; if ($arr) { $error = $arr[1]; } - if ($error) { + if (!empty($error)) { $this->element('p', 'error', $error); } else { $instr = $this->getInstructions(); From 4aa9b95f51216edaffcd229d9c31a5f905a76b13 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 16:58:19 -0500 Subject: [PATCH 030/503] use return value of common_check_user() in login.php --- actions/login.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/actions/login.php b/actions/login.php index 71e4679292..b049791fb1 100644 --- a/actions/login.php +++ b/actions/login.php @@ -108,13 +108,15 @@ class LoginAction extends Action $nickname = common_canonical_nickname($this->trimmed('nickname')); $password = $this->arg('password'); - if (!common_check_user($nickname, $password)) { + $user = common_check_user($nickname, $password); + + if (!$user) { $this->showForm(_('Incorrect username or password.')); return; } // success! - if (!common_set_user($nickname)) { + if (!common_set_user($user)) { $this->serverError(_('Error setting user.')); return; } From 5845f19b051d440125f4921ad0a15184a993d287 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 17:02:34 -0500 Subject: [PATCH 031/503] fix some notices in omb.php --- lib/omb.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/omb.php b/lib/omb.php index f2dbef5ba9..29e14c75f7 100644 --- a/lib/omb.php +++ b/lib/omb.php @@ -239,7 +239,7 @@ function omb_broadcast_profile($profile) while ($sub->fetch()) { $rp = Remote_profile::staticGet('id', $sub->subscriber); if ($rp) { - if (!$updated[$rp->updateprofileurl]) { + if (!array_key_exists($rp->updateprofileurl, $updated)) { if (omb_update_profile($profile, $rp, $sub)) { $updated[$rp->updateprofileurl] = true; } @@ -295,7 +295,9 @@ function omb_update_profile($profile, $remote_profile, $subscription) common_debug('Got HTTP result "'.print_r($result,true).'"', __FILE__); - if ($result->status == 403) { # not authorized, don't send again + if (empty($result) || $result) { + common_debug("Unable to contact " . $req->get_normalized_http_url()); + } else if ($result->status == 403) { # not authorized, don't send again common_debug('403 result, deleting subscription', __FILE__); $subscription->delete(); return false; From 12636d9fb1c8d6bdcf27e068f3be2ad9c9636ee1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 17:14:13 -0500 Subject: [PATCH 032/503] don't use SUP in group rss --- actions/grouprss.php | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/actions/grouprss.php b/actions/grouprss.php index 1a7b858b1e..de76a59600 100644 --- a/actions/grouprss.php +++ b/actions/grouprss.php @@ -111,13 +111,13 @@ class groupRssAction extends Rss10Action { $group = $this->group; - + if (is_null($group)) { return null; } - + $notice = $group->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit); - + while ($notice->fetch()) { $notices[] = clone($notice); } @@ -141,13 +141,4 @@ class groupRssAction extends Rss10Action { return $this->group->homepage_logo; } - - # override parent to add X-SUP-ID URL - - function initRss($limit=0) - { - $url = common_local_url('sup', null, $this->group->id); - header('X-SUP-ID: '.$url); - parent::initRss($limit); - } } From f39dd40ffa9ae9e52fb0e83c2dfaae5f65ca5f80 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 17:29:40 -0500 Subject: [PATCH 033/503] fix notices in lib/grouplist.php --- lib/grouplist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/grouplist.php b/lib/grouplist.php index 6801ab4261..1b85474998 100644 --- a/lib/grouplist.php +++ b/lib/grouplist.php @@ -151,7 +151,7 @@ class GroupList extends Widget # If we're on a list with an owner (subscriptions or subscribers)... - if ($user && $user->id == $this->owner->id) { + if (!empty($user) && !empty($this->owner) && $user->id == $this->owner->id) { $this->showOwnerControls(); } From 3a999af4d905d3cd23ea9163f47b6ed5c35f606c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 20 Feb 2009 17:30:09 -0500 Subject: [PATCH 034/503] Change common_local_url() to take 4 arguments I changed common_local_url() to take an additional optional argument -- for query parameters. Being persnickety, I made it the third of four, and moved the last one ($fragment) down a slot. That required changing a couple of calls. --- actions/twitapistatuses.php | 2 +- actions/userrss.php | 11 +++++------ lib/router.php | 4 ++-- lib/util.php | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 18e24c0f58..51c2565892 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -204,7 +204,7 @@ class TwitapistatusesAction extends TwitterapiAction # FriendFeed's SUP protocol # Also added RSS and Atom feeds - $suplink = common_local_url('sup', null, $user->id); + $suplink = common_local_url('sup', null, null, $user->id); header('X-SUP-ID: '.$suplink); # XXX: since diff --git a/actions/userrss.php b/actions/userrss.php index 04855cccad..a3e5a3aab7 100644 --- a/actions/userrss.php +++ b/actions/userrss.php @@ -46,13 +46,13 @@ class UserrssAction extends Rss10Action { $user = $this->user; - + if (is_null($user)) { return null; } - + $notice = $user->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit); - + while ($notice->fetch()) { $notices[] = clone($notice); } @@ -87,10 +87,10 @@ class UserrssAction extends Rss10Action } # override parent to add X-SUP-ID URL - + function initRss($limit=0) { - $url = common_local_url('sup', null, $this->user->id); + $url = common_local_url('sup', null, null, $this->user->id); header('X-SUP-ID: '.$url); parent::initRss($limit); } @@ -100,4 +100,3 @@ class UserrssAction extends Rss10Action return true; } } - diff --git a/lib/router.php b/lib/router.php index 0640a5911f..85425bed29 100644 --- a/lib/router.php +++ b/lib/router.php @@ -350,7 +350,7 @@ class Router return $this->m->match($path); } - function build($action, $args=null, $fragment=null) + function build($action, $args=null, $params=null, $fragment=null) { $action_arg = array('action' => $action); @@ -360,6 +360,6 @@ class Router $args = $action_arg; } - return $this->m->generate($args, null, $fragment); + return $this->m->generate($args, $params, $fragment); } } \ No newline at end of file diff --git a/lib/util.php b/lib/util.php index 46aa7b9df9..5345a08bba 100644 --- a/lib/util.php +++ b/lib/util.php @@ -705,10 +705,10 @@ function common_relative_profile($sender, $nickname, $dt=null) return null; } -function common_local_url($action, $args=null, $fragment=null) +function common_local_url($action, $args=null, $params=null, $fragment=null) { $r = Router::get(); - $path = $r->build($action, $args, $fragment); + $path = $r->build($action, $args, $params, $fragment); if ($path) { } if (common_config('site','fancy')) { From 5e816d7be208fc24419288234559c78da7391c8b Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 20 Feb 2009 15:07:59 -0800 Subject: [PATCH 035/503] Fixed routing for direct messages and favorites in the API --- lib/router.php | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/lib/router.php b/lib/router.php index d47ad71183..9d0d3a3f06 100644 --- a/lib/router.php +++ b/lib/router.php @@ -226,20 +226,31 @@ class Router // direct messages - $m->connect('api/direct_messages/:method', - array('action' => 'api', - 'apiaction' => 'direct_messages'), - array('method' => '(sent|new)(\.(xml|json|atom|rss))?')); + foreach (array('xml', 'json') as $e) { + $m->connect('api/direct_messages/new.'.$e, + array('action' => 'api', + 'apiaction' => 'direct_messages', + 'method' => 'create.'.$e)); + } + + foreach (array('xml', 'json', 'rss', 'atom') as $e) { + $m->connect('api/direct_messages.'.$e, + array('action' => 'api', + 'apiaction' => 'direct_messages', + 'method' => 'direct_messages.'.$e)); + } + + foreach (array('xml', 'json', 'rss', 'atom') as $e) { + $m->connect('api/direct_message/sent.'.$e, + array('action' => 'api', + 'apiaction' => 'direct_messages', + 'method' => 'sent.'.$e)); + } $m->connect('api/direct_messages/destroy/:argument', array('action' => 'api', 'apiaction' => 'direct_messages')); - $m->connect('api/:method', - array('action' => 'api', - 'apiaction' => 'direct_messages'), - array('method' => 'direct_messages(\.(xml|json|atom|rss))?')); - // friendships $m->connect('api/friendships/:method/:argument', @@ -269,10 +280,12 @@ class Router 'apiaction' => 'favorites', 'method' => 'favorites')); - $m->connect('api/:method', - array('action' => 'api', - 'apiaction' => 'favorites'), - array('method' => 'favorites(\.(xml|json|rss|atom))?')); + foreach (array('xml', 'json', 'rss', 'atom') as $e) { + $m->connect('api/favorites.'.$e, + array('action' => 'api', + 'apiaction' => 'favorites', + 'method' => 'favorites.'.$e)); + } // notifications @@ -345,7 +358,16 @@ class Router function map($path) { - return $this->m->match($path); + try { + $match = $this->m->match($path); + } catch (Net_URL_Mapper_InvalidException $e) { + common_log(LOG_ERR, "Problem getting route for $path - " . + $e->getMessage()); + $cac = new ClientErrorAction("Page not found.", 404); + $cac->showPage(); + } + + return $match; } function build($action, $args=null, $fragment=null) From f75c2328ccb87650e107e90b89b4d2a16d7a29cd Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 20 Feb 2009 23:47:24 +0000 Subject: [PATCH 036/503] Hooks for: local navigation --- EVENTS.txt | 6 ++++++ lib/action.php | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/EVENTS.txt b/EVENTS.txt index af0bee587c..37e2203d50 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -82,3 +82,9 @@ StartNoticeSave: before inserting a notice (good place for content filters) EndNoticeSave: after inserting a notice and related code - $notice: notice that was saved (with ID and URI) +StartShowLocalNavBlock: Showing the local nav menu +- $action: the current action + +EndShowLocalNavBlock: At the end of the local nav menu +- $action: the current action + diff --git a/lib/action.php b/lib/action.php index b1e700b670..a468c638cd 100644 --- a/lib/action.php +++ b/lib/action.php @@ -474,7 +474,10 @@ class Action extends HTMLOutputter // lawsuit function showCore() { $this->elementStart('div', array('id' => 'core')); - $this->showLocalNavBlock(); + if (Event::handle('StartShowLocalNavBlock', array($this))) { + $this->showLocalNavBlock(); + Event::handle('EndShowLocalNavBlock', array($this)); + } if (Event::handle('StartShowContentBlock', array($this))) { $this->showContentBlock(); Event::handle('EndShowContentBlock', array($this)); From 85694e3fa6669e3d59155e32f2cc2f8df3b9f89c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 20 Feb 2009 23:54:17 +0000 Subject: [PATCH 037/503] Minor positioning: using absolute right instead of left --- theme/base/css/display.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index b5796374ec..be124f4330 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -900,7 +900,7 @@ left:0; left:29px; } .notice-options .notice_delete { -left:76px; +right:0; } .notice-options .notice_reply dt { display:none; From 1fdb35bbf105fe462dcc663ea20b6aa56d654001 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 20 Feb 2009 17:17:20 -0800 Subject: [PATCH 038/503] New doc page for Identi.ca badge and minor updates to badge's js --- doc-src/badge | 65 ++++++++++++++++++++++++++++++++++++++++++++ js/identica-badge.js | 3 +- lib/action.php | 2 ++ scripts/sitemap.php | 3 +- 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 doc-src/badge diff --git a/doc-src/badge b/doc-src/badge new file mode 100644 index 0000000000..1c368eb690 --- /dev/null +++ b/doc-src/badge @@ -0,0 +1,65 @@ +Install the %%site.name%% badge on you blog or web site to show the latest updates +from you and your friends! + + + + + +Things to try +-------------- + +* Click an avatar and the badge will refresh with that user's timeline +* Click a nickname to open a user's profile in your browser +* Click a notice's timestamp to view the notice in your browser +* @-replies and #tags are live links + +## Installation instructions + +Copy and paste the following JavaScript into an HTML page where +you want the badge to show up. Substitute your own ID in the user +parameter. + +
+	<script type="text/javascript" src="http://identi.ca/js/identica-badge.js">
+	{
+	   "user":"kentbrew",
+	   "server":"identi.ca",
+	   "headerText":" and friends"
+	}
+	</script>
+
+
+ + + +Valid parameters for the badge: +------------------------------- + +* user : defaults to 7000 (@kentbrew) +* headerText : defaults to empty +* height : defaults to 350px +* width : defaults to 300px +* background : defaults to #193441. If you set evenBackground, oddBackground, + and headerBackground, you won't see it at all. +* border : defaults to 1px solid black +* userColor : defaults to whatever link color is set to on your page +* headerBackground : defaults to transparent +* headerColor : defaults to white +* evenBackground : defaults to #fff +* oddBackground : defaults to #eee +* thumbnailBorder : 1px solid black +* thumbnailSize : defaults to 24px +* padding : defaults to 3px +* server : defaults to identi.ca + +Licence +------- + +Identi.ca badge by [Kent Brewster](http://kentbrewster.com/identica-badge/). +Licenced under [CC-BY-SA-3](http://kentbrewster.com/rights-and-permissions/). diff --git a/js/identica-badge.js b/js/identica-badge.js index 5c586b5d6a..869230b7a4 100644 --- a/js/identica-badge.js +++ b/js/identica-badge.js @@ -1,4 +1,5 @@ // identica badge -- updated to work with the native API, 12-4-2008 +// Modified to point to Identi.ca, 2-20-2009 by Zach // copyright Kent Brewster 2008 // see http://kentbrewster.com/identica-badge for info ( function() { @@ -127,7 +128,7 @@ var a = document.createElement('A'); a.innerHTML = 'get this'; a.target = '_blank'; - a.href = 'http://kentbrewster.com/identica-badge'; + a.href = 'http://identica/doc/badge'; $.s.f.appendChild(a); $.s.appendChild($.s.f); $.f.getUser(); diff --git a/lib/action.php b/lib/action.php index b1e700b670..0c4d0181db 100644 --- a/lib/action.php +++ b/lib/action.php @@ -657,6 +657,8 @@ class Action extends HTMLOutputter // lawsuit _('Source')); $this->menuItem(common_local_url('doc', array('title' => 'contact')), _('Contact')); + $this->menuItem(common_local_url('doc', array('title' => 'badge')), + _('Badge')); Event::handle('EndSecondaryNav', array($this)); } $this->elementEnd('ul'); diff --git a/scripts/sitemap.php b/scripts/sitemap.php index 51a9bbd757..39eb859bba 100755 --- a/scripts/sitemap.php +++ b/scripts/sitemap.php @@ -61,7 +61,8 @@ function standard_map() ) ); - $docs = array('about', 'faq', 'contact', 'im', 'openid', 'openmublog', 'privacy', 'source'); + $docs = array('about', 'faq', 'contact', 'im', 'openid', 'openmublog', + 'privacy', 'source', 'badge'); foreach($docs as $title) { $standard_map_urls .= url( From cdab8d55a96b61ce6cfbec697d95e3223751fd3f Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 22 Feb 2009 17:01:41 -0800 Subject: [PATCH 039/503] Ticket #925 - make verify_credentials return 'Authorized' if no return type specified --- actions/twitapiaccount.php | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/actions/twitapiaccount.php b/actions/twitapiaccount.php index b7c09cc9dc..c19cd370d9 100644 --- a/actions/twitapiaccount.php +++ b/actions/twitapiaccount.php @@ -24,20 +24,19 @@ require_once(INSTALLDIR.'/lib/twitterapi.php'); class TwitapiaccountAction extends TwitterapiAction { - function verify_credentials($args, $apidata) + function verify_credentials($args, $apidata) { - - if ($apidata['content-type'] == 'xml') { - header('Content-Type: application/xml; charset=utf-8'); - print 'true'; - } elseif ($apidata['content-type'] == 'json') { - header('Content-Type: application/json; charset=utf-8'); - print '{"authorized":true}'; - } else { - common_user_error(_('API method not found!'), $code=404); - } - - } + if ($apidata['content-type'] == 'xml') { + header('Content-Type: application/xml; charset=utf-8'); + print 'true'; + } elseif ($apidata['content-type'] == 'json') { + header('Content-Type: application/json; charset=utf-8'); + print '{"authorized":true}'; + } else { + header('Content-Type: text/html; charset=utf-8'); + print 'Authorized'; + } + } function end_session($args, $apidata) { From 5e646ead492fc62b52f67af6c3a23295ef502345 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 22 Feb 2009 18:01:55 -0800 Subject: [PATCH 040/503] Minor routing fix for friends_timeline API method --- lib/router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/router.php b/lib/router.php index e842604e9a..a41d35f22c 100644 --- a/lib/router.php +++ b/lib/router.php @@ -213,7 +213,7 @@ class Router $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(user_timeline|show|destroy|friends|followers)')); + array('method' => '(user_timeline|friends_timeline|show|destroy|friends|followers)')); // users From cab322d21b8c8077192a1396bf13050d734c2aba Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 22 Feb 2009 20:04:47 -0800 Subject: [PATCH 041/503] Ticket #1108 - Added 'social graph' methods to the API --- actions/twitapistatuses.php | 54 ++++++++++++++++++++++++++++++++----- lib/router.php | 27 +++++++++++++++++++ 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 51c2565892..216835026d 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -470,19 +470,28 @@ class TwitapistatusesAction extends TwitterapiAction return $this->subscriptions($apidata, 'subscribed', 'subscriber'); } + function friendsIDs($args, $apidata) + { + parent::handle($args); + return $this->subscriptions($apidata, 'subscribed', 'subscriber', true); + } + function followers($args, $apidata) { parent::handle($args); - return $this->subscriptions($apidata, 'subscriber', 'subscribed'); } - function subscriptions($apidata, $other_attr, $user_attr) + function followersIDs($args, $apidata) + { + parent::handle($args); + return $this->subscriptions($apidata, 'subscriber', 'subscribed', true); + } + + function subscriptions($apidata, $other_attr, $user_attr, $onlyIDs=false) { - # XXX: lite - - $this->auth_user = $apidate['user']; + $this->auth_user = $apidata['user']; $user = $this->get_user($apidata['api_arg'], $apidata); if (!$user) { @@ -514,7 +523,10 @@ class TwitapistatusesAction extends TwitterapiAction } $sub->orderBy('created DESC'); - $sub->limit(($page-1)*100, 100); + + if (!$onlyIDs) { + $sub->limit(($page-1)*100, 100); + } $others = array(); @@ -529,7 +541,13 @@ class TwitapistatusesAction extends TwitterapiAction $type = $apidata['content-type']; $this->init_document($type); - $this->show_profiles($others, $type); + + if ($onlyIDs) { + $this->showIDs($others, $type); + } else { + $this->show_profiles($others, $type); + } + $this->end_document($type); } @@ -555,6 +573,28 @@ class TwitapistatusesAction extends TwitterapiAction } } + function showIDs($profiles, $type) + { + switch ($type) { + case 'xml': + $this->elementStart('ids'); + foreach ($profiles as $profile) { + $this->element('id', null, $profile->id); + } + $this->elementEnd('ids'); + break; + case 'json': + $ids = array(); + foreach ($profiles as $profile) { + $ids[] = (int)$profile->id; + } + print json_encode($ids); + break; + default: + $this->clientError(_('unsupported file type')); + } + } + function featured($args, $apidata) { parent::handle($args); diff --git a/lib/router.php b/lib/router.php index a41d35f22c..b18a5523e9 100644 --- a/lib/router.php +++ b/lib/router.php @@ -265,6 +265,33 @@ class Router 'apiaction' => 'friendships'), array('method' => 'exists(\.(xml|json|rss|atom))')); + + // Social graph + + $m->connect('api/friends/ids/:argument', + array('action' => 'api', + 'apiaction' => 'statuses', + 'method' => 'friendsIDs')); + + foreach (array('xml', 'json') as $e) { + $m->connect('api/friends/ids.'.$e, + array('action' => 'api', + 'apiaction' => 'statuses', + 'method' => 'friendsIDs.'.$e)); + } + + $m->connect('api/followers/ids/:argument', + array('action' => 'api', + 'apiaction' => 'statuses', + 'method' => 'followersIDs')); + + foreach (array('xml', 'json') as $e) { + $m->connect('api/followers/ids.'.$e, + array('action' => 'api', + 'apiaction' => 'statuses', + 'method' => 'followersIDs.'.$e)); + } + // account $m->connect('api/account/:method', From 8c3fe83c645265a11a3fca80cac2ac48ea72cdab Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 23 Feb 2009 13:27:22 -0800 Subject: [PATCH 042/503] Make allrss.php work with phpcs --- actions/allrss.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/actions/allrss.php b/actions/allrss.php index 05787f3f73..0114c43962 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -53,7 +53,9 @@ class AllrssAction extends Rss10Action /** * Initialization. - * + * + * @param array $args Web and URL arguments + * * @return boolean false if user doesn't exist */ function prepare($args) @@ -81,7 +83,7 @@ class AllrssAction extends Rss10Action { $user = $this->user; $notice = $user->noticesWithFriends(0, $limit); - + while ($notice->fetch()) { $notices[] = clone($notice); } @@ -104,7 +106,8 @@ class AllrssAction extends Rss10Action 'link' => common_local_url('all', array('nickname' => $user->nickname)), - 'description' => sprintf(_('Feed for friends of %s'), $user->nickname)); + 'description' => sprintf(_('Feed for friends of %s'), + $user->nickname)); return $c; } @@ -123,10 +126,5 @@ class AllrssAction extends Rss10Action $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); return $avatar ? $avatar->url : null; } - - function isReadOnly() - { - return true; - } } From d30590de23f2b9a138ec6923016c4e9af6b9a989 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 24 Feb 2009 04:31:31 +0000 Subject: [PATCH 043/503] Print stylesheet --- lib/action.php | 4 ++++ theme/base/css/print.css | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 theme/base/css/print.css diff --git a/lib/action.php b/lib/action.php index 455ebeff0b..dd7dd44e7f 100644 --- a/lib/action.php +++ b/lib/action.php @@ -173,6 +173,10 @@ class Action extends HTMLOutputter // lawsuit // TODO: "handheld" CSS for other mobile devices 'media' => 'only screen and (max-device-width: 480px)')); // Mobile WebKit } + $this->element('link', array('rel' => 'stylesheet', + 'type' => 'text/css', + 'href' => theme_path('css/print.css', 'base') . '?version=' . LACONICA_VERSION, + 'media' => 'print')); Event::handle('EndShowLaconicaStyles', array($this)); } if (Event::handle('StartShowUAStyles', array($this))) { diff --git a/theme/base/css/print.css b/theme/base/css/print.css new file mode 100644 index 0000000000..cf3ac0391c --- /dev/null +++ b/theme/base/css/print.css @@ -0,0 +1,28 @@ +body { font-size:12pt; } +a:after { background-color:#fff; } +a:not([href^="#"]):after { content:" ( "attr(href)" ) "; } +a:not([href^="http:"]):after { content: " ( http://identi.ca/"attr(href)" ) "; } +a[href^="/"]:after { content: " ( http://identi.ca" attr(href) " ) "; } + +img { border:none; } +p { orphans: 2; widows: 1; } + +#site_nav_global_primary, +#site_nav_local_views, +#form_notice, +.pagination, +#site_nav_global_secondary, +.entity_actions, +.notice-options, +#aside_primary { +display:none; +} + +.timestamp dt, .timestamp dd, +.device dt, .device dd { +display:inline; +} + +.notices li { +margin-bottom:18px; +} From 240ea969214fe3d18c96d0f9ba1d2b5af63aa54d Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 24 Feb 2009 05:09:23 +0000 Subject: [PATCH 044/503] Print stylesheet - Added license and cleanup --- theme/base/css/print.css | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/theme/base/css/print.css b/theme/base/css/print.css index cf3ac0391c..2da3e5e444 100644 --- a/theme/base/css/print.css +++ b/theme/base/css/print.css @@ -1,8 +1,14 @@ -body { font-size:12pt; } +/** theme: base + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + a:after { background-color:#fff; } a:not([href^="#"]):after { content:" ( "attr(href)" ) "; } -a:not([href^="http:"]):after { content: " ( http://identi.ca/"attr(href)" ) "; } -a[href^="/"]:after { content: " ( http://identi.ca" attr(href) " ) "; } img { border:none; } p { orphans: 2; widows: 1; } @@ -14,7 +20,8 @@ p { orphans: 2; widows: 1; } #site_nav_global_secondary, .entity_actions, .notice-options, -#aside_primary { +#aside_primary, +.form_subcription_edit .submit { display:none; } @@ -23,6 +30,7 @@ display:none; display:inline; } +.profiles li, .notices li { margin-bottom:18px; } From 7af6f5392be2b847c4c026f2632fc1c900338b81 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 26 Feb 2009 19:56:31 +0000 Subject: [PATCH 045/503] Hook for setting document content type, charset, language, DOCTYPE and html element properties --- EVENTS.txt | 6 ++++++ lib/action.php | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/EVENTS.txt b/EVENTS.txt index 37e2203d50..ed461ee9fe 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -88,3 +88,9 @@ StartShowLocalNavBlock: Showing the local nav menu EndShowLocalNavBlock: At the end of the local nav menu - $action: the current action +StartShowHTML: Chance to set document content type, charset, language, DOCTYPE and html element properties +- $action: the current action + +EndShowHTML: Showing after the html element +- $action: the current action + diff --git a/lib/action.php b/lib/action.php index dd7dd44e7f..9c71a153dd 100644 --- a/lib/action.php +++ b/lib/action.php @@ -93,7 +93,10 @@ class Action extends HTMLOutputter // lawsuit */ function showPage() { - $this->startHTML(); + if (Event::handle('StartShowHTML', array($this))) { + $this->startHTML(); + Event::handle('EndShowHTML', array($this)); + } $this->showHead(); $this->showBody(); $this->endHTML(); From 478192fa3b2375a0ff0a5ff03956381e5da7a6ac Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 26 Feb 2009 13:22:41 -0800 Subject: [PATCH 046/503] add conversation id to notice --- db/laconica.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/laconica.sql b/db/laconica.sql index 012270b51e..254cf5fabf 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -114,8 +114,10 @@ create table notice ( reply_to integer comment 'notice replied to (usually a guess)' references notice (id), is_local tinyint default 0 comment 'notice was generated by a user', source varchar(32) comment 'source of comment, like "web", "im", or "clientname"', + conversation integer comment 'id of root notice in this conversation' references notice (id), index notice_profile_id_idx (profile_id), + index notice_conversation_idx (conversation), index notice_created_idx (created), FULLTEXT(content) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin; From 2bf5b23016ab4929a1c9197907d4a621bb888742 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 26 Feb 2009 13:36:10 -0800 Subject: [PATCH 047/503] fix notice in register --- actions/register.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/actions/register.php b/actions/register.php index 5d7a8ce690..5c6fe39d3d 100644 --- a/actions/register.php +++ b/actions/register.php @@ -131,11 +131,13 @@ class RegisterAction extends Action $code = $this->trimmed('code'); + $invite = null; + if ($code) { $invite = Invitation::staticGet($code); } - if (common_config('site', 'inviteonly') && !($code && $invite)) { + if (common_config('site', 'inviteonly') && !($code && !empty($invite))) { $this->clientError(_('Sorry, only invited people can register.')); return; } @@ -341,6 +343,8 @@ class RegisterAction extends Action { $code = $this->trimmed('code'); + $invite = null; + if ($code) { $invite = Invitation::staticGet($code); } @@ -377,7 +381,7 @@ class RegisterAction extends Action _('Same as password above. Required.')); $this->elementEnd('li'); $this->elementStart('li'); - if ($invite && $invite->address_type == 'email') { + if (!empty($invite) && $invite->address_type == 'email') { $this->input('email', _('Email'), $invite->address, _('Used only for updates, announcements, '. 'and password recovery')); From ee92d0b0a8870143ee462b5833b0adf47673a613 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 26 Feb 2009 13:36:27 -0800 Subject: [PATCH 048/503] fix notice in action with caching --- lib/action.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/action.php b/lib/action.php index 455ebeff0b..f19a047cfb 100644 --- a/lib/action.php +++ b/lib/action.php @@ -812,11 +812,12 @@ class Action extends HTMLOutputter // lawsuit } if ($lm) { header('Last-Modified: ' . date(DATE_RFC1123, $lm)); - $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; - if ($if_modified_since) { + if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { + $if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; $ims = strtotime($if_modified_since); if ($lm <= $ims) { - $if_none_match = $_SERVER['HTTP_IF_NONE_MATCH']; + $if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ? + $_SERVER['HTTP_IF_NONE_MATCH'] : null; if (!$if_none_match || !$etag || $this->_hasEtag($etag, $if_none_match)) { From 2674d40b62934a579c083f4f4f7f1173d64d777b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 26 Feb 2009 13:36:38 -0800 Subject: [PATCH 049/503] fix notice with twitter broadcast --- lib/twitter.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/twitter.php b/lib/twitter.php index deb6fd276b..8a54afb9c4 100644 --- a/lib/twitter.php +++ b/lib/twitter.php @@ -210,7 +210,7 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password) function is_twitter_bound($notice, $flink) { // Check to see if notice should go to Twitter - if (($flink->noticesync & FOREIGN_NOTICE_SEND)) { + if (!empty($flink) && ($flink->noticesync & FOREIGN_NOTICE_SEND)) { // If it's not a Twitter-style reply, or if the user WANTS to send replies. if (!preg_match('/^@[a-zA-Z0-9_]{1,15}\b/u', $notice->content) || @@ -218,7 +218,7 @@ function is_twitter_bound($notice, $flink) { return true; } } - + return false; } @@ -227,10 +227,10 @@ function broadcast_twitter($notice) global $config; $success = true; - $flink = Foreign_link::getByUserID($notice->profile_id, + $flink = Foreign_link::getByUserID($notice->profile_id, TWITTER_SERVICE); - - // XXX: Not sure WHERE to check whether a notice should go to + + // XXX: Not sure WHERE to check whether a notice should go to // Twitter. Should we even put in the queue if it shouldn't? --Zach if (is_twitter_bound($notice, $flink)) { @@ -245,7 +245,7 @@ function broadcast_twitter($notice) $options = array( CURLOPT_USERPWD => "$twitter_user:$twitter_password", CURLOPT_POST => true, - CURLOPT_POSTFIELDS => + CURLOPT_POSTFIELDS => array( 'status' => $statustxt, 'source' => $config['integration']['source'] @@ -293,7 +293,7 @@ function broadcast_twitter($notice) $success = false; } } - + return $success; } From d1f46d85521876678152f2d06b61cbf212356f6f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 26 Feb 2009 13:37:00 -0800 Subject: [PATCH 050/503] add conversation to notice class --- classes/Notice.php | 1 + classes/laconica.ini | 1 + 2 files changed, 2 insertions(+) diff --git a/classes/Notice.php b/classes/Notice.php index 8300667fa4..ce5243841f 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -46,6 +46,7 @@ class Notice extends Memcached_DataObject public $reply_to; // int(4) public $is_local; // tinyint(1) public $source; // varchar(32) + public $conversation; // int(4) /* Static get */ function staticGet($k,$v=NULL) { diff --git a/classes/laconica.ini b/classes/laconica.ini index 5fd2cd1f86..aaa7035a44 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -168,6 +168,7 @@ modified = 384 reply_to = 1 is_local = 17 source = 2 +conversation = 1 [notice__keys] id = N From baf5afb26339f410a24a7ae5064d6c7a9029e86c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 26 Feb 2009 13:45:43 -0800 Subject: [PATCH 051/503] save conversation id when saving a notice --- classes/Notice.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/classes/Notice.php b/classes/Notice.php index ce5243841f..c321311acc 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -156,13 +156,20 @@ class Notice extends Memcached_DataObject $notice->query('BEGIN'); - $notice->reply_to = $reply_to; $notice->created = common_sql_now(); $notice->content = common_shorten_links($content); $notice->rendered = common_render_content($notice->content, $notice); $notice->source = $source; $notice->uri = $uri; + if (!empty($reply_to)) { + $reply_notice = Notice::staticGet('id', $reply_to); + if (!empty($reply_notice)) { + $notice->reply_to = $reply_to; + $notice->conversation = $reply_notice->conversation; + } + } + if (Event::handle('StartNoticeSave', array(&$notice))) { $id = $notice->insert(); @@ -707,6 +714,7 @@ class Notice extends Memcached_DataObject if ($recipient_notice) { $orig = clone($this); $this->reply_to = $recipient_notice->id; + $this->conversation = $recipient_notice->conversation; $this->update($orig); } } @@ -756,6 +764,14 @@ class Notice extends Memcached_DataObject } } + // If it's not a reply, make it the root of a new conversation + + if (empty($this->conversation)) { + $orig = clone($this); + $this->conversation = $this->id; + $this->update($orig); + } + foreach (array_keys($replied) as $recipient) { $user = User::staticGet('id', $recipient); if ($user) { From 42eecfabca67e5caee1f4e5894b711cacd0a9f9d Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 21 Feb 2009 18:51:56 +0100 Subject: [PATCH 052/503] Adds some missing routes. --- lib/router.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/router.php b/lib/router.php index b18a5523e9..b142022f0a 100644 --- a/lib/router.php +++ b/lib/router.php @@ -117,6 +117,11 @@ class Router $m->connect('main/openid', array('action' => 'openidlogin')); $m->connect('main/remote', array('action' => 'remotesubscribe')); + foreach (array('requesttoken', 'accesstoken', 'userauthorization', + 'postnotice', 'updateprofile') as $action) { + $m->connect('index.php?action=' . $action, array('action' => $action)); + } + // settings foreach (array('profile', 'avatar', 'password', 'openid', 'im', @@ -411,4 +416,4 @@ class Router return $this->m->generate($args, $params, $fragment); } -} \ No newline at end of file +} From 89197210cf706683c8ab22deedc43724fa1fe235 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 21 Feb 2009 19:04:27 +0100 Subject: [PATCH 053/503] Fixes #1067: Avatar stretched on authorize remote subscription page. The img tag used a wrong class which had a width: 100% applied. --- actions/userauthorization.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/userauthorization.php b/actions/userauthorization.php index ed17ceec97..0dc1841d4f 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -105,7 +105,7 @@ class UserauthorizationAction extends Action $this->elementStart('div', 'profile'); if ($avatar) { $this->element('img', array('src' => $avatar, - 'class' => 'avatar profile', + 'class' => 'avatar', 'width' => AVATAR_PROFILE_SIZE, 'height' => AVATAR_PROFILE_SIZE, 'alt' => $nickname)); From 616fd16bc528ce78d7fc1fa8a6ad5a67f10ae5eb Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 21 Feb 2009 19:43:18 +0100 Subject: [PATCH 054/503] Auth_Yadis_Yadis::PlainHTTPFetcher expects plain arrays, not hashes. --- actions/finishremotesubscribe.php | 2 +- actions/remotesubscribe.php | 3 +-- lib/omb.php | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/actions/finishremotesubscribe.php b/actions/finishremotesubscribe.php index 76db887deb..acfacbdc1c 100644 --- a/actions/finishremotesubscribe.php +++ b/actions/finishremotesubscribe.php @@ -283,7 +283,7 @@ class FinishremotesubscribeAction extends Action $fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); $result = $fetcher->post($req->get_normalized_http_url(), $req->to_postdata(), - array('User-Agent' => 'Laconica/' . LACONICA_VERSION)); + array('User-Agent: Laconica/' . LACONICA_VERSION)); common_debug('got result: "'.print_r($result,true).'"', __FILE__); diff --git a/actions/remotesubscribe.php b/actions/remotesubscribe.php index f727a63b82..7ea7acd6d3 100644 --- a/actions/remotesubscribe.php +++ b/actions/remotesubscribe.php @@ -321,8 +321,7 @@ class RemotesubscribeAction extends Action $result = $fetcher->post($req->get_normalized_http_url(), $req->to_postdata(), - array('User-Agent' => 'Laconica/' . LACONICA_VERSION)); - + array('User-Agent: Laconica/' . LACONICA_VERSION)); if ($result->status != 200) { return null; } diff --git a/lib/omb.php b/lib/omb.php index 29e14c75f7..befcf4666a 100644 --- a/lib/omb.php +++ b/lib/omb.php @@ -206,7 +206,7 @@ function omb_post_notice_keys($notice, $postnoticeurl, $tk, $secret) $result = $fetcher->post($req->get_normalized_http_url(), $req->to_postdata(), - array('User-Agent' => 'Laconica/' . LACONICA_VERSION)); + array('User-Agent: Laconica/' . LACONICA_VERSION)); common_debug('Got HTTP result "'.print_r($result,true).'"', __FILE__); @@ -291,7 +291,7 @@ function omb_update_profile($profile, $remote_profile, $subscription) common_debug('postdata = '.$req->to_postdata(), __FILE__); $result = $fetcher->post($req->get_normalized_http_url(), $req->to_postdata(), - array('User-Agent' => 'Laconica/' . LACONICA_VERSION)); + array('User-Agent: Laconica/' . LACONICA_VERSION)); common_debug('Got HTTP result "'.print_r($result,true).'"', __FILE__); From d4b6e7266ad80add5ff29c947cfad4bd5dbd3c8a Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 21 Feb 2009 22:41:24 +0100 Subject: [PATCH 055/503] Correctly handle avatars at updateProfile --- actions/updateprofile.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/actions/updateprofile.php b/actions/updateprofile.php index 898c535432..4751a04ff3 100644 --- a/actions/updateprofile.php +++ b/actions/updateprofile.php @@ -162,7 +162,13 @@ class UpdateprofileAction extends Action if ($avatar) { $temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar'); copy($avatar, $temp_filename); - if (!$profile->setOriginal($temp_filename)) { + $imagefile = new ImageFile($profile->id, $temp_filename); + $filename = Avatar::filename($profile->id, + image_type_to_extension($imagefile->type), + null, + common_timestamp()); + rename($temp_filename, Avatar::path($filename)); + if (!$profile->setOriginal($filename)) { $this->serverError(_('Could not save avatar info'), 500); return false; } From c87349350d0422157575f93ab4dd9abc108cc8d8 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 21 Feb 2009 22:48:30 +0100 Subject: [PATCH 056/503] Add finishremotesubscribe to the unrouted actions list. --- lib/router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/router.php b/lib/router.php index b142022f0a..e5b8e7d236 100644 --- a/lib/router.php +++ b/lib/router.php @@ -118,7 +118,7 @@ class Router $m->connect('main/remote', array('action' => 'remotesubscribe')); foreach (array('requesttoken', 'accesstoken', 'userauthorization', - 'postnotice', 'updateprofile') as $action) { + 'postnotice', 'updateprofile', 'finishremotesubscribe') as $action) { $m->connect('index.php?action=' . $action, array('action' => $action)); } From a90a8da5c3c445b11e1e2bf0d0530eb48fa146c0 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 21 Feb 2009 22:50:59 +0100 Subject: [PATCH 057/503] Broadcast profile via OMB after avatar change. --- actions/avatarsettings.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actions/avatarsettings.php b/actions/avatarsettings.php index f38a44a24a..6545d94893 100644 --- a/actions/avatarsettings.php +++ b/actions/avatarsettings.php @@ -324,13 +324,12 @@ class AvatarsettingsAction extends AccountSettingsAction return; } - // If image is not being cropped assume pos & dimentions of original + // If image is not being cropped assume pos & dimensions of original. $dest_x = $this->arg('avatar_crop_x') ? $this->arg('avatar_crop_x'):0; $dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):0; $dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$filedata['width']; $dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$filedata['height']; - $size = min($dest_w, $dest_h); - $size = ($size > MAX_ORIGINAL) ? MAX_ORIGINAL:$size; + $size = min($dest_w, $dest_h, MAX_ORIGINAL); $user = common_current_user(); $profile = $user->getProfile(); @@ -343,6 +342,7 @@ class AvatarsettingsAction extends AccountSettingsAction unset($_SESSION['FILEDATA']); $this->mode = 'upload'; $this->showForm(_('Avatar updated.'), true); + common_broadcast_profile($profile); } else { $this->showForm(_('Failed updating avatar.')); } From fa82722e5abd2e1cbf75050aea594f65a384d8d7 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sun, 22 Feb 2009 13:31:50 +0100 Subject: [PATCH 058/503] More routes. --- lib/router.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/router.php b/lib/router.php index e5b8e7d236..f70b67f383 100644 --- a/lib/router.php +++ b/lib/router.php @@ -133,6 +133,7 @@ class Router foreach (array('group', 'people', 'notice') as $s) { $m->connect('search/'.$s, array('action' => $s.'search')); + $m->connect('search/'.$s.'?q=:q', array('action' => $s.'search'), array('q' => '.+')); } $m->connect('search/notice/rss', array('action' => 'noticesearchrss')); @@ -140,6 +141,9 @@ class Router // notice $m->connect('notice/new', array('action' => 'newnotice')); + $m->connect('notice/new?replyto=:replyto', + array('action' => 'newnotice'), + array('replyto' => '[A-Za-z0-9_-]+')); $m->connect('notice/:notice', array('action' => 'shownotice'), array('notice' => '[0-9]+')); From 210647a56c0ee917ec5bb7d4753ad2603d28d7c4 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sun, 22 Feb 2009 13:32:14 +0100 Subject: [PATCH 059/503] Fix replyto parameter in newnotice --- actions/newnotice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index 9face96443..9f44d25165 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -253,7 +253,7 @@ class NewnoticeAction extends Action } } - $notice_form = new NoticeForm($this, $content); + $notice_form = new NoticeForm($this, '', $content); $notice_form->show(); } From d005b370712943eed3edae2ff82d38dfa3d42a92 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sun, 22 Feb 2009 13:38:16 +0100 Subject: [PATCH 060/503] Fixes #1241: in-reply-to links were broken due to copy and paste error (Variable name was wrong). --- actions/noticesearch.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/noticesearch.php b/actions/noticesearch.php index dc58d7528a..0bbaa02560 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -201,7 +201,7 @@ class NoticesearchAction extends SearchAction if ($notice->reply_to) { $replyurl = common_local_url('shownotice', - array('notice' => $this->notice->reply_to)); + array('notice' => $notice->reply_to)); $this->elementStart('dl', 'response'); $this->element('dt', null, _('To')); $this->elementStart('dd'); From bdb8c12d975846ce128619e672b8064b8f5f890a Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sun, 22 Feb 2009 14:02:17 +0100 Subject: [PATCH 061/503] Completely refactored noticesearch list, now using subclassing for highlighting. Fixes #1240 and probably other bugs. --- actions/noticesearch.php | 152 +++++++++++---------------------------- 1 file changed, 41 insertions(+), 111 deletions(-) diff --git a/actions/noticesearch.php b/actions/noticesearch.php index 0bbaa02560..83e59dd9ae 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -113,123 +113,58 @@ class NoticesearchAction extends SearchAction } else { $cnt = $notice->find(); } - if ($cnt > 0) { - $terms = preg_split('/[\s,]+/', $q); - $this->elementStart('ul', array('class' => 'notices')); - for ($i = 0; $i < min($cnt, NOTICES_PER_PAGE); $i++) { - if ($notice->fetch()) { - $this->showNotice($notice, $terms); - } else { - // shouldn't happen! - break; - } - } - $this->elementEnd('ul'); - } else { + if ($cnt === 0) { $this->element('p', 'error', _('No results')); - } - - $this->pagination($page > 1, $cnt > NOTICES_PER_PAGE, - $page, 'noticesearch', array('q' => $q)); - } - - /** - * Show notice - * - * @param class $notice notice - * @param array $terms terms to highlight - * - * @return void - * - * @todo refactor and combine with StreamAction::showNotice() - */ - function showNotice($notice, $terms) - { - $profile = $notice->getProfile(); - if (!$profile) { - common_log_db_error($notice, 'SELECT', __FILE__); - $this->serverError(_('Notice without matching profile')); return; } - // XXX: RDFa - $this->elementStart('li', array('class' => 'hentry notice', - 'id' => 'notice-' . $notice->id)); + $terms = preg_split('/[\s,]+/', $q); + $nl = new SearchNoticeList($notice, $this, $terms); - $this->elementStart('div', 'entry-title'); - $this->elementStart('span', 'vcard author'); - $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); - $this->elementStart('a', array('href' => $profile->profileurl, - 'class' => 'url')); - $this->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE), - 'class' => 'avatar photo', - 'width' => AVATAR_STREAM_SIZE, - 'height' => AVATAR_STREAM_SIZE, - 'alt' => - ($profile->fullname) ? $profile->fullname : - $profile->nickname)); - $this->element('span', 'nickname fn', $profile->nickname); - $this->elementEnd('a'); - $this->elementEnd('span'); + $cnt = $nl->show(); + $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, + $this->page, 'noticesearch', array('q' => $q)); + } + function isReadOnly() + { + return true; + } +} + +class SearchNoticeList extends NoticeList { + function __construct($notice, $out=null, $terms) + { + parent::__construct($notice, $out); + $this->terms = $terms; + } + + function newListItem($notice) + { + return new SearchNoticeListItem($notice, $this->out, $this->terms); + } +} + +class SearchNoticeListItem extends NoticeListItem { + function __construct($notice, $out=null, $terms) + { + parent::__construct($notice, $out); + $this->terms = $terms; + } + + function showContent() + { // FIXME: URL, image, video, audio - $this->elementStart('p', array('class' => 'entry-content')); - if ($notice->rendered) { - $this->raw($this->highlight($notice->rendered, $terms)); + $this->out->elementStart('p', array('class' => 'entry-content')); + if ($this->notice->rendered) { + $this->out->raw($this->highlight($this->notice->rendered, $this->terms)); } else { // XXX: may be some uncooked notices in the DB, // we cook them right now. This should probably disappear in future // versions (>> 0.4.x) - $this->raw($this->highlight(common_render_content($notice->content, $notice), $terms)); + $this->out->raw($this->highlight(common_render_content($this->notice->content, $this->notice), $this->terms)); } - $this->elementEnd('p'); - $this->elementEnd('div'); + $this->out->elementEnd('p'); - $noticeurl = common_local_url('shownotice', array('notice' => $notice->id)); - $this->elementStart('div', 'entry-content'); - $this->elementStart('dl', 'timestamp'); - $this->element('dt', null, _('Published')); - $this->elementStart('dd', null); - $this->elementStart('a', array('rel' => 'bookmark', - 'href' => $noticeurl)); - $dt = common_date_iso8601($notice->created); - $this->element('abbr', array('class' => 'published', - 'title' => $dt), - common_date_string($notice->created)); - $this->elementEnd('a'); - $this->elementEnd('dd'); - $this->elementEnd('dl'); - - if ($notice->reply_to) { - $replyurl = common_local_url('shownotice', - array('notice' => $notice->reply_to)); - $this->elementStart('dl', 'response'); - $this->element('dt', null, _('To')); - $this->elementStart('dd'); - $this->element('a', array('href' => $replyurl, - 'rel' => 'in-reply-to'), - _('in reply to')); - $this->elementEnd('dd'); - $this->elementEnd('dl'); - } - $this->elementEnd('div'); - - $this->elementStart('div', 'notice-options'); - - $reply_url = common_local_url('newnotice', - array('replyto' => $profile->nickname)); - - $this->elementStart('dl', 'notice_reply'); - $this->element('dt', null, _('Reply to this notice')); - $this->elementStart('dd'); - $this->elementStart('a', array('href' => $reply_url, - 'title' => _('Reply to this notice'))); - $this->text(_('Reply')); - $this->element('span', 'notice_id', $notice->id); - $this->elementEnd('a'); - $this->elementEnd('dd'); - $this->elementEnd('dl'); - $this->elementEnd('div'); - $this->elementEnd('li'); } /** @@ -242,7 +177,7 @@ class NoticesearchAction extends SearchAction */ function highlight($text, $terms) { - /* Highligh serach terms */ + /* Highligh search terms */ $pattern = '/('.implode('|', array_map('htmlspecialchars', $terms)).')/i'; $result = preg_replace($pattern, '\\1', $text); @@ -253,10 +188,5 @@ class NoticesearchAction extends SearchAction } while ($count); return $result; } - - function isReadOnly() - { - return true; - } } From 32e0fb148312bb2a052111513ed71fc4948a9fb7 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sun, 22 Feb 2009 14:27:09 +0100 Subject: [PATCH 062/503] Route for remote subscribe link on profile page. --- lib/router.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/router.php b/lib/router.php index f70b67f383..95ce77e5ef 100644 --- a/lib/router.php +++ b/lib/router.php @@ -116,6 +116,7 @@ class Router $m->connect('main/openid', array('action' => 'openidlogin')); $m->connect('main/remote', array('action' => 'remotesubscribe')); + $m->connect('main/remote?nickname=:nickname', array('action' => 'remotesubscribe'), array('nickname' => '[A-Za-z0-9_-]+')); foreach (array('requesttoken', 'accesstoken', 'userauthorization', 'postnotice', 'updateprofile', 'finishremotesubscribe') as $action) { From 120eb77400843669980850882dfae83ca7f8e7e7 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sun, 22 Feb 2009 17:45:26 +0100 Subject: [PATCH 063/503] Fixes #1258: A period in a hashtag leads to the tag being interpreted as url and hence breaking the tag. --- lib/util.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/util.php b/lib/util.php index 5345a08bba..18e4f310ce 100644 --- a/lib/util.php +++ b/lib/util.php @@ -456,6 +456,9 @@ function common_replace_urls_callback($text, $callback) { if (!in_array($url_parts[2], $tlds)) continue; + // Make sure we didn't capture a hash tag + if (strpos($url, '#') === 0) continue; + // Put the url back the way we found it. $url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url); From 3f7d70c5e4c5e91d552cc629a9371109cb859bc3 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Wed, 25 Feb 2009 01:36:58 +0100 Subject: [PATCH 064/503] Hopefully fixes #1260: Mess with norwegian languages. Moreover corrected ltr/rtl for Italian and Hebrew and added Finnish. --- lib/language.php | 61 +++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/lib/language.php b/lib/language.php index a73b73f280..79e9030ae4 100644 --- a/lib/language.php +++ b/lib/language.php @@ -94,40 +94,43 @@ function get_nice_language_list() * Get a list of all languages that are enabled in the default config * * This should ONLY be called when setting up the default config in common.php. - * Any other attempt to get a list of lanugages should instead call + * Any other attempt to get a list of languages should instead call * common_config('site','languages') * * @return array mapping of language codes to language info */ function get_all_languages() { return array( - 'bg' => array('q' => 0.8, 'lang' => 'bg_BG', 'name' => 'Bulgarian', 'direction' => 'ltr'), - 'ca' => array('q' => 0.5, 'lang' => 'ca_ES', 'name' => 'Catalan', 'direction' => 'ltr'), - 'cs' => array('q' => 0.5, 'lang' => 'cs_CZ', 'name' => 'Czech', 'direction' => 'ltr'), - 'de' => array('q' => 0.5, 'lang' => 'de_DE', 'name' => 'German', 'direction' => 'ltr'), - 'el' => array('q' => 0.1, 'lang' => 'el', 'name' => 'Greek', 'direction' => 'ltr'), - 'en-us' => array('q' => 1, 'lang' => 'en_US', 'name' => 'English (US)', 'direction' => 'ltr'), - 'en-gb' => array('q' => 0.3, 'lang' => 'en_GB', 'name' => 'English (British)', 'direction' => 'ltr'), - 'en' => array('q' => 1, 'lang' => 'en', 'name' => 'English', 'direction' => 'ltr'), - 'es' => array('q' => 0.5, 'lang' => 'es', 'name' => 'Spanish', 'direction' => 'ltr'), - 'fr-fr' => array('q' => 0.2, 'lang' => 'fr_FR', 'name' => 'French', 'direction' => 'ltr'), - 'he' => array('q' => 0.5, 'lang' => 'he_IL', 'name' => 'Hebrew', 'direction' => 'ltr'), - 'it' => array('q' => 0.9, 'lang' => 'it_IT', 'name' => 'Italian', 'direction' => 'rtl'), - 'jp' => array('q' => 0.5, 'lang' => 'ja_JP', 'name' => 'Japanese', 'direction' => 'ltr'), -# 'ko' => array('q' => 0, 'lang' => 'ko', 'name' => 'Korean', 'direction' => 'ltr'), - 'mk' => array('q' => 0.5, 'lang' => 'mk_MK', 'name' => 'Macedonian', 'direction' => 'ltr'), - 'nb' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (bokmal)', 'direction' => 'ltr'), - 'nl' => array('q' => 0.5, 'lang' => 'nl_NL', 'name' => 'Dutch', 'direction' => 'ltr'), - 'pl' => array('q' => 0.5, 'lang' => 'pl_PL', 'name' => 'Polish', 'direction' => 'ltr'), -# 'pt' => array('q' => 0, 'lang' => 'pt', 'name' => 'Portuguese', 'direction' => 'ltr'), - 'pt-br' => array('q' => 0.7, 'lang' => 'pt_BR', 'name' => 'Portuguese Brazil', 'direction' => 'ltr'), - 'ru' => array('q' => 0.1, 'lang' => 'ru_RU', 'name' => 'Russian', 'direction' => 'ltr'), - 'sv' => array('q' => 0.9, 'lang' => 'sv_SE', 'name' => 'Swedish', 'direction' => 'ltr'), - 'te' => array('q' => 0.3, 'lang' => 'te_IN', 'name' => 'Telugu', 'direction' => 'ltr'), - 'tr' => array('q' => 0.5, 'lang' => 'tr_TR', 'name' => 'Turkish', 'direction' => 'ltr'), - 'uk' => array('q' => 0.7, 'lang' => 'uk_UA', 'name' => 'Ukrainian', 'direction' => 'ltr'), - 'vi' => array('q' => 0.7, 'lang' => 'vi_VN', 'name' => 'Vietnamese', 'direction' => 'ltr'), - 'zh-cn' => array('q' => 0.9, 'lang' => 'zh_CN', 'name' => 'Chinese (Simplified)', 'direction' => 'ltr'), - 'zh-hant' => array('q' => 0.2, 'lang' => 'zh_hant', 'name' => 'Chinese (Taiwanese)', 'direction' => 'ltr'), + 'bg' => array('q' => 0.8, 'lang' => 'bg_BG', 'name' => 'Bulgarian', 'direction' => 'ltr'), + 'ca' => array('q' => 0.5, 'lang' => 'ca_ES', 'name' => 'Catalan', 'direction' => 'ltr'), + 'cs' => array('q' => 0.5, 'lang' => 'cs_CZ', 'name' => 'Czech', 'direction' => 'ltr'), + 'de' => array('q' => 0.5, 'lang' => 'de_DE', 'name' => 'German', 'direction' => 'ltr'), + 'el' => array('q' => 0.1, 'lang' => 'el', 'name' => 'Greek', 'direction' => 'ltr'), + 'en-us' => array('q' => 1, 'lang' => 'en_US', 'name' => 'English (US)', 'direction' => 'ltr'), + 'en-gb' => array('q' => 0.3, 'lang' => 'en_GB', 'name' => 'English (British)', 'direction' => 'ltr'), + 'en' => array('q' => 1, 'lang' => 'en', 'name' => 'English', 'direction' => 'ltr'), + 'es' => array('q' => 0.5, 'lang' => 'es', 'name' => 'Spanish', 'direction' => 'ltr'), + 'fi' => array('q' => 0.5, 'lang' => 'fi', 'name' => 'Finnish', 'direction' => 'ltr'), + 'fr-fr' => array('q' => 0.2, 'lang' => 'fr_FR', 'name' => 'French', 'direction' => 'ltr'), + 'he' => array('q' => 0.5, 'lang' => 'he_IL', 'name' => 'Hebrew', 'direction' => 'rtl'), + 'it' => array('q' => 0.9, 'lang' => 'it_IT', 'name' => 'Italian', 'direction' => 'ltr'), + 'jp' => array('q' => 0.5, 'lang' => 'ja_JP', 'name' => 'Japanese', 'direction' => 'ltr'), +# 'ko' => array('q' => 0, 'lang' => 'ko', 'name' => 'Korean', 'direction' => 'ltr'), + 'mk' => array('q' => 0.5, 'lang' => 'mk_MK', 'name' => 'Macedonian', 'direction' => 'ltr'), + 'nb' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'), + 'no' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'), + 'nn' => array('q' => 0.1, 'lang' => 'nn_NO', 'name' => 'Norwegian (Nynorsk)', 'direction' => 'ltr'), + 'nl' => array('q' => 0.5, 'lang' => 'nl_NL', 'name' => 'Dutch', 'direction' => 'ltr'), + 'pl' => array('q' => 0.5, 'lang' => 'pl_PL', 'name' => 'Polish', 'direction' => 'ltr'), +# 'pt' => array('q' => 0, 'lang' => 'pt', 'name' => 'Portuguese', 'direction' => 'ltr'), + 'pt-br' => array('q' => 0.7, 'lang' => 'pt_BR', 'name' => 'Portuguese Brazil', 'direction' => 'ltr'), + 'ru' => array('q' => 0.1, 'lang' => 'ru_RU', 'name' => 'Russian', 'direction' => 'ltr'), + 'sv' => array('q' => 0.9, 'lang' => 'sv_SE', 'name' => 'Swedish', 'direction' => 'ltr'), + 'te' => array('q' => 0.3, 'lang' => 'te_IN', 'name' => 'Telugu', 'direction' => 'ltr'), + 'tr' => array('q' => 0.5, 'lang' => 'tr_TR', 'name' => 'Turkish', 'direction' => 'ltr'), + 'uk' => array('q' => 0.7, 'lang' => 'uk_UA', 'name' => 'Ukrainian', 'direction' => 'ltr'), + 'vi' => array('q' => 0.7, 'lang' => 'vi_VN', 'name' => 'Vietnamese', 'direction' => 'ltr'), + 'zh-cn' => array('q' => 0.9, 'lang' => 'zh_CN', 'name' => 'Chinese (Simplified)', 'direction' => 'ltr'), + 'zh-hant' => array('q' => 0.2, 'lang' => 'zh_hant', 'name' => 'Chinese (Taiwanese)', 'direction' => 'ltr'), ); } From d92beda526f1495d16b54880a40ebb3c7d7e5f2e Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Wed, 25 Feb 2009 16:59:32 +0100 Subject: [PATCH 065/503] Add route for new message to user. --- lib/router.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/router.php b/lib/router.php index 95ce77e5ef..4b70c01505 100644 --- a/lib/router.php +++ b/lib/router.php @@ -154,6 +154,7 @@ class Router array('notice' => '[0-9]+')); $m->connect('message/new', array('action' => 'newmessage')); + $m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => '[A-Za-z0-9_-]')); $m->connect('message/:message', array('action' => 'showmessage'), array('message' => '[0-9]+')); From 0a96edac9cd553cc0d1fa32defb80582699bcdd2 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sat, 28 Feb 2009 23:10:40 +0000 Subject: [PATCH 066/503] Slightly toned down the text-shadow on navigation --- theme/base/css/display.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index be124f4330..c741ed4cba 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -297,7 +297,7 @@ padding:4px 11px; border-width:1px; border-style:solid; border-bottom:0; -text-shadow: 4px 4px 4px #ddd; +text-shadow: 2px 2px 2px #ddd; font-weight:bold; } #site_nav_local_views .nav { From 02ba71b0f186b406071a97c3267603d4863a4b21 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Feb 2009 15:12:31 -0800 Subject: [PATCH 067/503] start conversation action --- actions/conversation.php | 123 +++++++++++++++++++++++++++++++++++++++ lib/router.php | 11 +++- 2 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 actions/conversation.php diff --git a/actions/conversation.php b/actions/conversation.php new file mode 100644 index 0000000000..0c22fe1238 --- /dev/null +++ b/actions/conversation.php @@ -0,0 +1,123 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + * + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Conversation tree in the browser + * + * @category Action + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://laconi.ca/ + */ +class ConversationAction extends Action +{ + var $id = null; + var $notices = null; + var $page = null; + + /** + * Initialization. + * + * @param array $args Web and URL arguments + * + * @return boolean false if id not passed in + */ + + function prepare($args) + { + parent::prepare($args); + $this->id = $this->trimmed('id'); + if (!$this->id) { + return false; + } + $this->notices = $this->getNotices(); + $this->page = $this->trimmed('page'); + if (empty($this->page)) { + $this->page = 1; + } + return true; + } + + /** + * Get notices + * + * @param integer $limit max number of notices to return + * + * @return array notices + */ + + function getNotices($limit=0) + { + $qry = 'SELECT notice.*, '. + 'FROM notice WHERE conversation = %d '. + 'ORDER BY created '; + + $offset = 0; + $limit = NOTICES_PER_PAGE + 1; + + if (common_config('db', 'type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + + return Notice::getStream(sprintf($qry, $this->id), + 'notice:conversation:'.$this->id, + $offset, $limit); + } + + function handle($args) + { + $this->showPage(); + } + + function title() + { + return _("Conversation"); + } + + function showContent() + { + // FIXME this needs to be a tree, not a list + + $nl = new NoticeList($this->notices, $this); + + $cnt = $nl->show(); + + $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, + $this->page, 'conversation', array('id' => $this->id)); + } + +} + diff --git a/lib/router.php b/lib/router.php index b18a5523e9..4c036e7b24 100644 --- a/lib/router.php +++ b/lib/router.php @@ -143,6 +143,12 @@ class Router array('action' => 'deletenotice'), array('notice' => '[0-9]+')); + // conversation + + $m->connect('conversation/:id', + array('action' => 'conversation'), + array('id' => '[0-9]+')); + $m->connect('message/new', array('action' => 'newmessage')); $m->connect('message/:message', array('action' => 'showmessage'), @@ -265,21 +271,20 @@ class Router 'apiaction' => 'friendships'), array('method' => 'exists(\.(xml|json|rss|atom))')); - // Social graph $m->connect('api/friends/ids/:argument', array('action' => 'api', 'apiaction' => 'statuses', 'method' => 'friendsIDs')); - + foreach (array('xml', 'json') as $e) { $m->connect('api/friends/ids.'.$e, array('action' => 'api', 'apiaction' => 'statuses', 'method' => 'friendsIDs.'.$e)); } - + $m->connect('api/followers/ids/:argument', array('action' => 'api', 'apiaction' => 'statuses', From 0369946b6d1b01a3d90fe641521a1ed117219d89 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Feb 2009 15:17:49 -0800 Subject: [PATCH 068/503] fix problem with dupe tags in profile --- classes/Profile_tag.php | 43 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/classes/Profile_tag.php b/classes/Profile_tag.php index cb60cbaec9..0a1ad9cd6b 100644 --- a/classes/Profile_tag.php +++ b/classes/Profile_tag.php @@ -4,7 +4,7 @@ */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -class Profile_tag extends Memcached_DataObject +class Profile_tag extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -23,45 +23,46 @@ class Profile_tag extends Memcached_DataObject ###END_AUTOCODE static function getTags($tagger, $tagged) { - + $tags = array(); # XXX: store this in memcached - + $profile_tag = new Profile_tag(); $profile_tag->tagger = $tagger; $profile_tag->tagged = $tagged; - + $profile_tag->find(); - + while ($profile_tag->fetch()) { $tags[] = $profile_tag->tag; } - + $profile_tag->free(); - + return $tags; } - + static function setTags($tagger, $tagged, $newtags) { - + + $newtags = array_unique($newtags); $oldtags = Profile_tag::getTags($tagger, $tagged); - + # Delete stuff that's old that not in new - + $to_delete = array_diff($oldtags, $newtags); - + # Insert stuff that's in new and not in old - + $to_insert = array_diff($newtags, $oldtags); - + $profile_tag = new Profile_tag(); - + $profile_tag->tagger = $tagger; $profile_tag->tagged = $tagged; - + $profile_tag->query('BEGIN'); - + foreach ($to_delete as $deltag) { $profile_tag->tag = $deltag; $result = $profile_tag->delete(); @@ -70,7 +71,7 @@ class Profile_tag extends Memcached_DataObject return false; } } - + foreach ($to_insert as $instag) { $profile_tag->tag = $instag; $result = $profile_tag->insert(); @@ -79,12 +80,12 @@ class Profile_tag extends Memcached_DataObject return false; } } - + $profile_tag->query('COMMIT'); - + return true; } - + # Return profiles with a given tag static function getTagged($tagger, $tag) { $profile = new Profile(); From 83b084e4ce2dea27c5f0ab3edfe2436fcf71e230 Mon Sep 17 00:00:00 2001 From: "ken.sedgwick" Date: Sat, 28 Feb 2009 17:33:20 -0800 Subject: [PATCH 069/503] Added RPM spec file. --- scripts/laconica.spec | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 scripts/laconica.spec diff --git a/scripts/laconica.spec b/scripts/laconica.spec new file mode 100644 index 0000000000..2e65b45496 --- /dev/null +++ b/scripts/laconica.spec @@ -0,0 +1,81 @@ +BuildRequires: php-pear +BuildRequires: httpd-devel + +Name: laconica +Version: 0.7.1 +Release: 1%{?dist} +License: GAGPL v3 or later +Source: laconica-0.7.1.tar.bz2 +Group: Applications/Internet +Summary: Laconica, the Open Source microblogging platform +BuildArch: noarch + +Requires: httpd +Requires: php >= 5 +Requires: php-pear-Mail-Mime +Requires: php-curl +Requires: php-mysql +Requires: php-mbstring +Requires: php-gettext + +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%define apache_serverroot %(/usr/sbin/apxs -q DATADIR) +%define apache_sysconfdir %(/usr/sbin/apxs -q SYSCONFDIR) +%define wwwpath %{apache_serverroot}/%{name} +%define confpath %{_sysconfdir}/%{name} + +%description +From the ABOUT file: Laconica (pronounced "luh-KAWN-ih-kuh") is a Free +and Open Source microblogging platform. It helps people in a +community, company or group to exchange short (140 character) messages +over the Web. Users can choose which people to "follow" and receive +only their friends' or colleagues' status messages. It provides a +similar service to sites like Twitter, Jaiku, and Plurk. + + +%prep +%setup -q + +%build + + +%install +mkdir -p %{buildroot}%{wwwpath} +cp -a * %{buildroot}%{wwwpath} + +mkdir -p %{buildroot}%{_datadir}/laconica +cp -a db %{buildroot}%{_datadir}/laconica/db + +mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d +cat > %{buildroot}%{_sysconfdir}/httpd/conf.d/laconica.conf <<"EOF" +Alias /laconica/ "/var/www/laconica/" + + + Options Indexes FollowSymLinks + AllowOverride All + Order allow,deny + Allow from all + +EOF + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +%dir %{wwwpath} +%{wwwpath}/* +%{_datadir}/laconica/* +%doc COPYING README doc-src/* +%config(noreplace) %{_sysconfdir}/httpd/conf.d/laconica.conf + +%changelog +* Sat Feb 28 2009 Ken Sedgwick - 0.7.1-1 +- Modified RPM for Fedora. + +* Thu Feb 13 2009 tuukka.pasanen@ilmi.fi +- packaged laconica version 0.7.1 + +* Wed Feb 04 2009 tuukka.pasanen@ilmi.fi +- packaged laconica version 0.7.0 using the buildservice spec file wizard From 3bf485ec95f3da56c779671b7a26f36085d93099 Mon Sep 17 00:00:00 2001 From: "ken.sedgwick" Date: Sat, 28 Feb 2009 17:35:36 -0800 Subject: [PATCH 070/503] Switched tarball ext ".bz2" -> ".gz" in spec file. --- scripts/laconica.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/laconica.spec b/scripts/laconica.spec index 2e65b45496..f3fa61904c 100644 --- a/scripts/laconica.spec +++ b/scripts/laconica.spec @@ -5,7 +5,7 @@ Name: laconica Version: 0.7.1 Release: 1%{?dist} License: GAGPL v3 or later -Source: laconica-0.7.1.tar.bz2 +Source: laconica-0.7.1.tar.gz Group: Applications/Internet Summary: Laconica, the Open Source microblogging platform BuildArch: noarch From f0d3ba2bc2b9a4391a89e343e9dea2622d7d9972 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Feb 2009 17:42:12 -0800 Subject: [PATCH 071/503] Add a flag for if there's no config file --- lib/common.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/common.php b/lib/common.php index 4fc749ca06..2298c5f88f 100644 --- a/lib/common.php +++ b/lib/common.php @@ -178,9 +178,12 @@ if (strlen($_path) > 0) { $_config_files[] = INSTALLDIR.'/config.php'; +$_have_a_config = false; + foreach ($_config_files as $_config_file) { if (file_exists($_config_file)) { include_once($_config_file); + $_have_a_config = true; } } From c77bb62f2d0a958e074ad0d9b1334d533cb33121 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Feb 2009 17:42:27 -0800 Subject: [PATCH 072/503] show a form for installation --- install.php | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 install.php diff --git a/install.php b/install.php new file mode 100644 index 0000000000..5ee6b10b3e --- /dev/null +++ b/install.php @@ -0,0 +1,68 @@ + +

Enter your database connection information below to initialize the database.

+
+
+
    +
  • + + +

    The name of your site

    +
  • +
  • +
  • + + +

    Database hostname

    +
  • +
  • +
  • + + +

    Database username

    +
  • +
  • + + +

    Database password

    +
  • +
+ +
+
+ + + + Install Laconica + + + + + +
+
+
+

Install Laconica

+ +
+
+
+ + \ No newline at end of file From 7fa6bb07d859d917080c6b110084ddedd5a772e8 Mon Sep 17 00:00:00 2001 From: "ken.sedgwick" Date: Sat, 28 Feb 2009 20:13:37 -0800 Subject: [PATCH 073/503] Added some missing php dependencies. Made the avatar directory apache owned. --- scripts/laconica.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/laconica.spec b/scripts/laconica.spec index f3fa61904c..2df41c9323 100644 --- a/scripts/laconica.spec +++ b/scripts/laconica.spec @@ -17,6 +17,8 @@ Requires: php-curl Requires: php-mysql Requires: php-mbstring Requires: php-gettext +Requires: php-xml +Requires: php-gd BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -67,6 +69,7 @@ rm -rf %buildroot %dir %{wwwpath} %{wwwpath}/* %{_datadir}/laconica/* +%attr(-,apache,apache) %dir %{_datadir}/laconica/avatar %doc COPYING README doc-src/* %config(noreplace) %{_sysconfdir}/httpd/conf.d/laconica.conf From b70218dc437c5decc8b27a2bb70e2e1b6ec6e9e3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Feb 2009 20:32:31 -0800 Subject: [PATCH 074/503] automatically handle non-laconica-named databases --- lib/common.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/common.php b/lib/common.php index 2298c5f88f..0fff3af2ea 100644 --- a/lib/common.php +++ b/lib/common.php @@ -187,6 +187,16 @@ foreach ($_config_files as $_config_file) { } } +// XXX: Throw a conniption if database not installed + +// Fixup for laconica.ini + +$_db_name = substr($config['db']['database'], strrpos($config['db']['database'], '/') + 1); + +if ($_db_name != 'laconica' && !array_key_exists('ini_'.$_db_name, $config['db'])) { + $config['db']['ini_'.$_db_name] = INSTALLDIR.'/classes/laconica.ini'; +} + // XXX: how many of these could be auto-loaded on use? require_once('Validate.php'); From 1d610d3c6f9bb15a5cea93758ddd8d0ce64099f6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Feb 2009 20:32:53 -0800 Subject: [PATCH 075/503] don't use semicolons in comments --- db/laconica.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/laconica.sql b/db/laconica.sql index dd93a727b7..c2cd887dee 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -171,7 +171,7 @@ create table token ( tok char(32) not null comment 'identifying value', secret char(32) not null comment 'secret value', type tinyint not null default 0 comment 'request or access', - state tinyint default 0 comment 'for requests; 0 = initial, 1 = authorized, 2 = used', + state tinyint default 0 comment 'for requests, 0 = initial, 1 = authorized, 2 = used', created datetime not null comment 'date this record was created', modified timestamp comment 'date this record was modified', @@ -344,7 +344,7 @@ create table notice_inbox ( user_id integer not null comment 'user receiving the message' references user (id), notice_id integer not null comment 'notice received' references notice (id), created datetime not null comment 'date the notice was created', - source tinyint default 1 comment 'reason it is in the inbox; 1=subscription', + source tinyint default 1 comment 'reason it is in the inbox, 1=subscription', constraint primary key (user_id, notice_id), index notice_inbox_notice_id_idx (notice_id) From 2ad667f704300dcb825a4822d567cbc8ebfebe02 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Feb 2009 20:33:22 -0800 Subject: [PATCH 076/503] first pass at a working install.php --- install.php | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/install.php b/install.php index 5ee6b10b3e..a34214c48a 100644 --- a/install.php +++ b/install.php @@ -1,6 +1,9 @@

Enter your database connection information below to initialize the database.

-
+
"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); /* * Sizzle CSS Selector Engine - v0.9.3 * Copyright 2009, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ -(function(){var Q=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,K=0,G=Object.prototype.toString;var F=function(X,T,aa,ab){aa=aa||[];T=T||document;if(T.nodeType!==1&&T.nodeType!==9){return[]}if(!X||typeof X!=="string"){return aa}var Y=[],V,ae,ah,S,ac,U,W=true;Q.lastIndex=0;while((V=Q.exec(X))!==null){Y.push(V[1]);if(V[2]){U=RegExp.rightContext;break}}if(Y.length>1&&L.exec(X)){if(Y.length===2&&H.relative[Y[0]]){ae=I(Y[0]+Y[1],T)}else{ae=H.relative[Y[0]]?[T]:F(Y.shift(),T);while(Y.length){X=Y.shift();if(H.relative[X]){X+=Y.shift()}ae=I(X,ae)}}}else{var ad=ab?{expr:Y.pop(),set:E(ab)}:F.find(Y.pop(),Y.length===1&&T.parentNode?T.parentNode:T,P(T));ae=F.filter(ad.expr,ad.set);if(Y.length>0){ah=E(ae)}else{W=false}while(Y.length){var ag=Y.pop(),af=ag;if(!H.relative[ag]){ag=""}else{af=Y.pop()}if(af==null){af=T}H.relative[ag](ah,af,P(T))}}if(!ah){ah=ae}if(!ah){throw"Syntax error, unrecognized expression: "+(ag||X)}if(G.call(ah)==="[object Array]"){if(!W){aa.push.apply(aa,ah)}else{if(T.nodeType===1){for(var Z=0;ah[Z]!=null;Z++){if(ah[Z]&&(ah[Z]===true||ah[Z].nodeType===1&&J(T,ah[Z]))){aa.push(ae[Z])}}}else{for(var Z=0;ah[Z]!=null;Z++){if(ah[Z]&&ah[Z].nodeType===1){aa.push(ae[Z])}}}}}else{E(ah,aa)}if(U){F(U,T,aa,ab)}return aa};F.matches=function(S,T){return F(S,null,null,T)};F.find=function(Z,S,aa){var Y,W;if(!Z){return[]}for(var V=0,U=H.order.length;V":function(X,T,Y){if(typeof T==="string"&&!/\W/.test(T)){T=Y?T:T.toUpperCase();for(var U=0,S=X.length;U=0){if(!U){S.push(X)}}else{if(U){T[W]=false}}}}return false},ID:function(S){return S[1].replace(/\\/g,"")},TAG:function(T,S){for(var U=0;S[U]===false;U++){}return S[U]&&P(S[U])?T[1]:T[1].toUpperCase()},CHILD:function(S){if(S[1]=="nth"){var T=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(S[2]=="even"&&"2n"||S[2]=="odd"&&"2n+1"||!/\D/.test(S[2])&&"0n+"+S[2]||S[2]);S[2]=(T[1]+(T[2]||1))-0;S[3]=T[3]-0}S[0]="done"+(K++);return S},ATTR:function(T){var S=T[1].replace(/\\/g,"");if(H.attrMap[S]){T[1]=H.attrMap[S]}if(T[2]==="~="){T[4]=" "+T[4]+" "}return T},PSEUDO:function(W,T,U,S,X){if(W[1]==="not"){if(W[3].match(Q).length>1){W[3]=F(W[3],null,null,T)}else{var V=F.filter(W[3],T,U,true^X);if(!U){S.push.apply(S,V)}return false}}else{if(H.match.POS.test(W[0])){return true}}return W},POS:function(S){S.unshift(true);return S}},filters:{enabled:function(S){return S.disabled===false&&S.type!=="hidden"},disabled:function(S){return S.disabled===true},checked:function(S){return S.checked===true},selected:function(S){S.parentNode.selectedIndex;return S.selected===true},parent:function(S){return !!S.firstChild},empty:function(S){return !S.firstChild},has:function(U,T,S){return !!F(S[3],U).length},header:function(S){return/h\d/i.test(S.nodeName)},text:function(S){return"text"===S.type},radio:function(S){return"radio"===S.type},checkbox:function(S){return"checkbox"===S.type},file:function(S){return"file"===S.type},password:function(S){return"password"===S.type},submit:function(S){return"submit"===S.type},image:function(S){return"image"===S.type},reset:function(S){return"reset"===S.type},button:function(S){return"button"===S.type||S.nodeName.toUpperCase()==="BUTTON"},input:function(S){return/input|select|textarea|button/i.test(S.nodeName)}},setFilters:{first:function(T,S){return S===0},last:function(U,T,S,V){return T===V.length-1},even:function(T,S){return S%2===0},odd:function(T,S){return S%2===1},lt:function(U,T,S){return TS[3]-0},nth:function(U,T,S){return S[3]-0==T},eq:function(U,T,S){return S[3]-0==T}},filter:{CHILD:function(S,V){var Y=V[1],Z=S.parentNode;var X=V[0];if(Z&&(!Z[X]||!S.nodeIndex)){var W=1;for(var T=Z.firstChild;T;T=T.nextSibling){if(T.nodeType==1){T.nodeIndex=W++}}Z[X]=W-1}if(Y=="first"){return S.nodeIndex==1}else{if(Y=="last"){return S.nodeIndex==Z[X]}else{if(Y=="only"){return Z[X]==1}else{if(Y=="nth"){var ab=false,U=V[2],aa=V[3];if(U==1&&aa==0){return true}if(U==0){if(S.nodeIndex==aa){ab=true}}else{if((S.nodeIndex-aa)%U==0&&(S.nodeIndex-aa)/U>=0){ab=true}}return ab}}}}},PSEUDO:function(Y,U,V,Z){var T=U[1],W=H.filters[T];if(W){return W(Y,V,U,Z)}else{if(T==="contains"){return(Y.textContent||Y.innerText||"").indexOf(U[3])>=0}else{if(T==="not"){var X=U[3];for(var V=0,S=X.length;V=0:V==="~="?(" "+X+" ").indexOf(T)>=0:!U[4]?S:V==="!="?X!=T:V==="^="?X.indexOf(T)===0:V==="$="?X.substr(X.length-T.length)===T:V==="|="?X===T||X.substr(0,T.length+1)===T+"-":false},POS:function(W,T,U,X){var S=T[2],V=H.setFilters[S];if(V){return V(W,U,T,X)}}}};var L=H.match.POS;for(var N in H.match){H.match[N]=RegExp(H.match[N].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(T,S){T=Array.prototype.slice.call(T);if(S){S.push.apply(S,T);return S}return T};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(M){E=function(W,V){var T=V||[];if(G.call(W)==="[object Array]"){Array.prototype.push.apply(T,W)}else{if(typeof W.length==="number"){for(var U=0,S=W.length;U";var S=document.documentElement;S.insertBefore(T,S.firstChild);if(!!document.getElementById(U)){H.find.ID=function(W,X,Y){if(typeof X.getElementById!=="undefined"&&!Y){var V=X.getElementById(W[1]);return V?V.id===W[1]||typeof V.getAttributeNode!=="undefined"&&V.getAttributeNode("id").nodeValue===W[1]?[V]:g:[]}};H.filter.ID=function(X,V){var W=typeof X.getAttributeNode!=="undefined"&&X.getAttributeNode("id");return X.nodeType===1&&W&&W.nodeValue===V}}S.removeChild(T)})();(function(){var S=document.createElement("div");S.appendChild(document.createComment(""));if(S.getElementsByTagName("*").length>0){H.find.TAG=function(T,X){var W=X.getElementsByTagName(T[1]);if(T[1]==="*"){var V=[];for(var U=0;W[U];U++){if(W[U].nodeType===1){V.push(W[U])}}W=V}return W}}S.innerHTML="";if(S.firstChild&&S.firstChild.getAttribute("href")!=="#"){H.attrHandle.href=function(T){return T.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var S=F,T=document.createElement("div");T.innerHTML="

";if(T.querySelectorAll&&T.querySelectorAll(".TEST").length===0){return}F=function(X,W,U,V){W=W||document;if(!V&&W.nodeType===9&&!P(W)){try{return E(W.querySelectorAll(X),U)}catch(Y){}}return S(X,W,U,V)};F.find=S.find;F.filter=S.filter;F.selectors=S.selectors;F.matches=S.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){H.order.splice(1,0,"CLASS");H.find.CLASS=function(S,T){return T.getElementsByClassName(S[1])}}function O(T,Z,Y,ac,aa,ab){for(var W=0,U=ac.length;W0){W=S;break}}}S=S[T]}ab[V]=W}}}var J=document.compareDocumentPosition?function(T,S){return T.compareDocumentPosition(S)&16}:function(T,S){return T!==S&&(T.contains?T.contains(S):true)};var P=function(S){return S.nodeType===9&&S.documentElement.nodeName!=="HTML"||!!S.ownerDocument&&P(S.ownerDocument)};var I=function(S,Z){var V=[],W="",X,U=Z.nodeType?[Z]:Z;while((X=H.match.PSEUDO.exec(S))){W+=X[0];S=S.replace(H.match.PSEUDO,"")}S=H.relative[S]?S+"*":S;for(var Y=0,T=U.length;Y=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}this[H].style.display=o.data(this[H],"olddisplay",K)}}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)==1){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(H,F){var E=H?"Left":"Top",G=H?"Right":"Bottom";o.fn["inner"+F]=function(){return this[F.toLowerCase()]()+j(this,"padding"+E)+j(this,"padding"+G)};o.fn["outer"+F]=function(J){return this["inner"+F]()+j(this,"border"+E+"Width")+j(this,"border"+G+"Width")+(J?j(this,"margin"+E)+j(this,"margin"+G):0)};var I=F.toLowerCase();o.fn[I]=function(J){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+F]||document.body["client"+F]:this[0]==document?Math.max(document.documentElement["client"+F],document.body["scroll"+F],document.documentElement["scroll"+F],document.body["offset"+F],document.documentElement["offset"+F]):J===g?(this.length?o.css(this[0],I):null):this.css(I,typeof J==="string"?J:J+"px")}})})(); \ No newline at end of file +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file From 148310e5fc78e69f6bde3683855009dc3d8d485b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 28 Mar 2009 17:36:39 -0400 Subject: [PATCH 250/503] welcome notice, default sub for new users --- README | 14 ++++++++++++++ classes/User.php | 42 ++++++++++++++++++++++++++++++++++++++++++ lib/common.php | 3 +++ lib/noticelist.php | 1 + 4 files changed, 60 insertions(+) diff --git a/README b/README index 71760ce4f8..73cb95367c 100644 --- a/README +++ b/README @@ -1169,6 +1169,20 @@ banned: an array of usernames and/or profile IDs of 'banned' profiles. not be accepted at all. (Compare with blacklisted users above, whose posts just won't show up in the public stream.) +newuser +------- + +Options with new users. + +subscribe: nickname of a user account to automatically subscribe new + users to. Typically this would be system account for e.g. + service updates or announcements. Users are able to unsub + if they want. Default is null; no auto subscribe. +welcome: nickname of a user account that sends welcome messages to new + users. Can be the same as 'subscribe' account, although on + busy servers it may be a good idea to keep that one just for + 'urgent' messages. Default is null; no message. + Troubleshooting =============== diff --git a/classes/User.php b/classes/User.php index d9f30bec58..e9e472fe1b 100644 --- a/classes/User.php +++ b/classes/User.php @@ -273,12 +273,54 @@ class User extends Memcached_DataObject $user->emailChanged(); } + // Default system subscription + + $defnick = common_config('newuser', 'default'); + + if (!empty($defnick)) { + $defuser = User::staticGet('nickname', $defnick); + if (empty($defuser)) { + common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick), + __FILE__); + } else { + $defsub = new Subscription(); + $defsub->subscriber = $user->id; + $defsub->subscribed = $defuser->id; + $defsub->created = $user->created; + + $result = $defsub->insert(); + + if (!$result) { + common_log_db_error($defsub, 'INSERT', __FILE__); + return false; + } + } + } + $profile->query('COMMIT'); if ($email && !$user->email) { mail_confirm_address($user, $confirm->code, $profile->nickname, $email); } + // Welcome message + + $welcome = common_config('newuser', 'welcome'); + + if (!empty($welcome)) { + $welcomeuser = User::staticGet('nickname', $welcome); + if (empty($welcomeuser)) { + common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick), + __FILE__); + } else { + $notice = Notice::saveNew($welcomeuser->id, + sprintf(_('Welcome to %1$s, @%2$s!'), + common_config('site', 'name'), + $user->nickname), + 'system'); + } + } + return $user; } diff --git a/lib/common.php b/lib/common.php index 1ca9e521b0..caad705a42 100644 --- a/lib/common.php +++ b/lib/common.php @@ -151,6 +151,9 @@ $config = array('notify' => array()), 'inboxes' => array('enabled' => true), # on by default for new sites + 'newuser' => + array('subscribe' => null, + 'welcome' => null), ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); diff --git a/lib/noticelist.php b/lib/noticelist.php index 8523f2e63e..4182d8808f 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -391,6 +391,7 @@ class NoticeListItem extends Widget case 'xmpp': case 'mail': case 'omb': + case 'system': case 'api': $this->out->element('dd', null, $source_name); break; From e00508d188de053caeb19595b94452973d87da3b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 30 Mar 2009 11:30:58 -0400 Subject: [PATCH 251/503] correct setting for default user --- README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README b/README index 95f9edceaf..f080d32bcc 100644 --- a/README +++ b/README @@ -1184,10 +1184,10 @@ newuser Options with new users. -subscribe: nickname of a user account to automatically subscribe new - users to. Typically this would be system account for e.g. - service updates or announcements. Users are able to unsub - if they want. Default is null; no auto subscribe. +default: nickname of a user account to automatically subscribe new + users to. Typically this would be system account for e.g. + service updates or announcements. Users are able to unsub + if they want. Default is null; no auto subscribe. welcome: nickname of a user account that sends welcome messages to new users. Can be the same as 'subscribe' account, although on busy servers it may be a good idea to keep that one just for From 47b89aa2c3a3e07d6dc63cd5be1d558af8ece233 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 30 Mar 2009 15:05:50 -0400 Subject: [PATCH 252/503] Changes to router setup to make notice search RSS feed work Conflicts: lib/router.php --- lib/router.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/router.php b/lib/router.php index 135e07a0f0..77794aaf70 100644 --- a/lib/router.php +++ b/lib/router.php @@ -136,10 +136,14 @@ class Router foreach (array('group', 'people', 'notice') as $s) { $m->connect('search/'.$s, array('action' => $s.'search')); - $m->connect('search/'.$s.'?q=:q', array('action' => $s.'search'), array('q' => '.+')); + $m->connect('search/'.$s.'?q=:q', array('action' => $s.'search'),array('q' => '.+')); } + // The second of these is needed to make the link work correctly + // when inserted into the page. The first is needed to match the + // route on the way in. Seems to be another Net_URL_Mapper bug to me. $m->connect('search/notice/rss', array('action' => 'noticesearchrss')); + $m->connect('search/notice/rss?q=:q', array('action' => 'noticesearchrss'),array('q' => '.+')); // notice From d5032a02774fcf2f01d92aa1c5ac182c9f2b618a Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 30 Mar 2009 19:47:55 +0000 Subject: [PATCH 253/503] trac#776 changed db collations from utf8_bin to utf8_general_ci for case insensitive search --- db/laconica.sql | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/db/laconica.sql b/db/laconica.sql index 098fa4fd1a..a790a3fd27 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -13,7 +13,7 @@ create table profile ( index profile_nickname_idx (nickname), FULLTEXT(nickname, fullname, location, bio, homepage) -) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin; +) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci; create table avatar ( profile_id integer not null comment 'foreign key to profile table' references profile (id), @@ -73,7 +73,7 @@ create table user ( modified timestamp comment 'date this record was modified', index user_smsemail_idx (smsemail) -) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; /* remote people */ @@ -103,7 +103,6 @@ create table subscription ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table notice ( - id integer auto_increment primary key comment 'unique identifier', profile_id integer not null comment 'who made the update' references profile (id), uri varchar(255) unique key comment 'universally unique identifier, usually a tag URI', @@ -119,7 +118,7 @@ create table notice ( index notice_profile_id_idx (profile_id), index notice_created_idx (created), FULLTEXT(content) -) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin; +) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci; create table notice_source ( code varchar(32) primary key not null comment 'source code', @@ -130,7 +129,6 @@ create table notice_source ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table reply ( - notice_id integer not null comment 'notice that is the reply' references notice (id), profile_id integer not null comment 'profile replied to' references profile (id), modified timestamp not null comment 'date this record was modified', @@ -144,7 +142,6 @@ create table reply ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table fave ( - notice_id integer not null comment 'notice that is the favorite' references notice (id), user_id integer not null comment 'user who likes this notice' references user (id), modified timestamp not null comment 'date this record was modified', @@ -321,7 +318,6 @@ create table invitation ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table message ( - id integer auto_increment primary key comment 'unique identifier', uri varchar(255) unique key comment 'universally unique identifier', from_profile integer not null comment 'who the message is from' references profile (id), @@ -336,10 +332,9 @@ create table message ( index message_from_idx (from_profile), index message_to_idx (to_profile), index message_created_idx (created) -) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; create table notice_inbox ( - user_id integer not null comment 'user receiving the message' references user (id), notice_id integer not null comment 'notice received' references notice (id), created datetime not null comment 'date the notice was created', @@ -362,7 +357,6 @@ create table profile_tag ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table profile_block ( - blocker integer not null comment 'user making the block' references user (id), blocked integer not null comment 'profile that is blocked' references profile (id), modified timestamp comment 'date of blocking', @@ -372,7 +366,6 @@ create table profile_block ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table user_group ( - id integer auto_increment primary key comment 'unique identifier', nickname varchar(64) unique key comment 'nickname for addressing', @@ -391,10 +384,9 @@ create table user_group ( index user_group_nickname_idx (nickname) -) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; create table group_member ( - group_id integer not null comment 'foreign key to user_group' references user_group (id), profile_id integer not null comment 'foreign key to profile table' references profile (id), is_admin boolean default false comment 'is this user an admin?', @@ -409,7 +401,6 @@ create table group_member ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table related_group ( - group_id integer not null comment 'foreign key to user_group' references user_group (id), related_group_id integer not null comment 'foreign key to user_group' references user_group (id), From 3861e348a4b4f00f3c0dcc5ba004e7dd80296078 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 30 Mar 2009 21:07:48 +0000 Subject: [PATCH 254/503] added filler text to public timeline for when it's empty, encouraging user to post and/or register. --- actions/public.php | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/actions/public.php b/actions/public.php index 9b22e0a2ce..96c766a57d 100644 --- a/actions/public.php +++ b/actions/public.php @@ -166,6 +166,50 @@ class PublicAction extends Action $nav->show(); } + function showPageNotice() + { + $notice = Notice::publicStream(0, 1); + + if (!$notice) { + $this->serverError(_('Could not retrieve public stream.')); + return; + } + + // no notices in the public stream, let's get out of here + if ($notice->count()) { + return; + } + + $message = _('This is the public timeline for %%site.name%% but noone has posted anything yet.') . ' '; + + if (common_logged_in()) { + $message .= _('Be the first to post!'); +/* + sprintf(_('You are logged in... %%%%site.name%%%% groups let you find and talk with ' . + 'people of similar interests. After you join a group ' . + 'you can send messages to all other members using the ' . + 'syntax "!groupname". Don\'t see a group you like? Try ' . + '[searching for one](%%%%action.groupsearch%%%%) or ' . + '[start your own!](%%%%action.newgroup%%%%)')); +*/ + } + else { + $message .= _('Why not [register an account](%%action.register%%) and be the first to post!'); +/* + sprintf(_('You are not logged in... %%%%site.name%%%% groups let you find and talk with ' . + 'people of similar interests. After you join a group ' . + 'you can send messages to all other members using the ' . + 'syntax "!groupname". Don\'t see a group you like? Try ' . + '[searching for one](%%%%action.groupsearch%%%%) or ' . + '[start your own!](%%%%action.newgroup%%%%)')); +*/ + } + + $this->elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } + /** * Fill the content area * From e149f3d64b5c0a58b299fb607824a1cd515836a4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 26 Mar 2009 15:03:59 -0400 Subject: [PATCH 255/503] Support SSL for some, all, or no pages Support SSL URLs either for all pages; no pages; or for sensitive pages accepting passwords, like login, registration, API, and others. --- README | 10 ++++++++++ config.php.sample | 10 ++++++++++ lib/common.php | 2 ++ lib/util.php | 31 ++++++++++++++++++++++++++----- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/README b/README index 73cb95367c..70815c1412 100644 --- a/README +++ b/README @@ -925,6 +925,16 @@ dupelimit: Time in which it's not OK for the same person to post the same notice; default = 60 seconds. logo: URL of an image file to use as the logo for the site. Overrides the logo in the theme, if any. +ssl: Whether to use SSL and https:// URLs for some or all pages. + Possible values are 'always' (use it for all pages), 'never' + (don't use it for any pages), or 'sometimes' (use it for + sensitive pages that include passwords like login and registration, + but not for regular pages). Default to 'never'. +sslserver: use an alternate server name for SSL URLs, like + 'secure.example.org'. You should be careful to set cookie + parameters correctly so that both the SSL server and the + "normal" server can access the session cookie and + preferably other cookies as well. db -- diff --git a/config.php.sample b/config.php.sample index 529e86f15f..d62a54fe74 100644 --- a/config.php.sample +++ b/config.php.sample @@ -174,3 +174,13 @@ $config['sphinx']['port'] = 3312; #http://taguri.org/ Examples: #$config['integration']['taguri'] = 'example.net,2008'; #$config['integration']['taguri'] = 'admin@example.net,2009-03-09' + +#Don't use SSL +#$config['site']['ssl'] = 'never'; +#Use SSL only for sensitive pages (like login, password change) +#$config['site']['ssl'] = 'sometimes'; +#Use SSL for all pages +#$config['site']['ssl'] = 'always'; + +#Use a different hostname for SSL-encrypted pages +#$config['site']['sslserver'] = 'secure.example.org'; diff --git a/lib/common.php b/lib/common.php index caad705a42..c2037c3ad6 100644 --- a/lib/common.php +++ b/lib/common.php @@ -87,6 +87,8 @@ $config = 'closed' => false, 'inviteonly' => false, 'private' => false, + 'ssl' => 'never', + 'sslserver' => null, 'dupelimit' => 60), # default for same person saying the same thing 'syslog' => array('appname' => 'laconica', # for syslog diff --git a/lib/util.php b/lib/util.php index ef73adc364..fdcae0aca0 100644 --- a/lib/util.php +++ b/lib/util.php @@ -721,25 +721,46 @@ function common_relative_profile($sender, $nickname, $dt=null) function common_local_url($action, $args=null, $params=null, $fragment=null) { + static $sensitive = array('login', 'register', 'passwordsettings', + 'twittersettings', 'finishopenidlogin', + 'api'); + $r = Router::get(); $path = $r->build($action, $args, $params, $fragment); + $ssl = in_array($action, $sensitive); + if (common_config('site','fancy')) { - $url = common_path(mb_substr($path, 1)); + $url = common_path(mb_substr($path, 1), $ssl); } else { if (mb_strpos($path, '/index.php') === 0) { - $url = common_path(mb_substr($path, 1)); + $url = common_path(mb_substr($path, 1), $ssl); } else { - $url = common_path('index.php'.$path); + $url = common_path('index.php'.$path, $ssl); } } return $url; } -function common_path($relative) +function common_path($relative, $ssl=false) { $pathpart = (common_config('site', 'path')) ? common_config('site', 'path')."/" : ''; - return "http://".common_config('site', 'server').'/'.$pathpart.$relative; + + if (($ssl && (common_config('site', 'ssl') === 'sometimes')) + || common_config('site', 'ssl') === 'always') { + $proto = 'https'; + if (is_string(common_config('site', 'sslserver')) && + mb_strlen(common_config('site', 'sslserver')) > 0) { + $serverpart = common_config('site', 'sslserver'); + } else { + $serverpart = common_config('site', 'server'); + } + } else { + $proto = 'http'; + $serverpart = common_config('site', 'server'); + } + + return $proto.'://'.$serverpart.'/'.$pathpart.$relative; } function common_date_string($dt) From 1fbf9a042e2e7ed1f67dfad9b7fe3b96019bd1a3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 31 Mar 2009 10:09:11 -0400 Subject: [PATCH 256/503] give the correct root url when SSL enabled --- lib/openid.php | 2 +- lib/util.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/openid.php b/lib/openid.php index 3aa488b6d4..f3769c6fce 100644 --- a/lib/openid.php +++ b/lib/openid.php @@ -160,7 +160,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false) $auth_request->addExtension($sreg_request); } - $trust_root = common_path(''); + $trust_root = common_root_url(true); $process_url = common_local_url($returnto); if ($auth_request->shouldSendRedirect()) { diff --git a/lib/util.php b/lib/util.php index fdcae0aca0..98a3ae8448 100644 --- a/lib/util.php +++ b/lib/util.php @@ -952,9 +952,9 @@ function common_profile_url($nickname) // Should make up a reasonable root URL -function common_root_url() +function common_root_url($ssl=false) { - return common_path(''); + return common_path('', $ssl); } // returns $bytes bytes of random data as a hexadecimal string From b112b326402200c164fc5c9678d4aff656f7afd4 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 1 Apr 2009 01:03:00 +0000 Subject: [PATCH 257/503] Selector to allow styles when a user is logged in. --- lib/action.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/action.php b/lib/action.php index f0baa062c2..5d0d5b7584 100644 --- a/lib/action.php +++ b/lib/action.php @@ -326,7 +326,9 @@ class Action extends HTMLOutputter // lawsuit */ function showBody() { - $this->elementStart('body', array('id' => $this->trimmed('action'))); + $this->elementStart('body', (common_current_user()) ? array('id' => $this->trimmed('action'), + 'class' => 'user_in') + : array('id' => $this->trimmed('action'))); $this->elementStart('div', array('id' => 'wrap')); if (Event::handle('StartShowHeader', array($this))) { $this->showHeader(); From 783d292739886811ab41215c614940d24214358f Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 1 Apr 2009 01:03:00 +0000 Subject: [PATCH 258/503] Selector to allow styles when a user is logged in. --- lib/action.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/action.php b/lib/action.php index 975c2bfcb8..f9f3c35d97 100644 --- a/lib/action.php +++ b/lib/action.php @@ -299,7 +299,9 @@ class Action extends HTMLOutputter // lawsuit */ function showBody() { - $this->elementStart('body', array('id' => $this->trimmed('action'))); + $this->elementStart('body', (common_current_user()) ? array('id' => $this->trimmed('action'), + 'class' => 'user_in') + : array('id' => $this->trimmed('action'))); $this->elementStart('div', array('id' => 'wrap')); if (Event::handle('StartShowHeader', array($this))) { $this->showHeader(); From e7381493ad036e686f82f432066f00ff911ad5d5 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Wed, 1 Apr 2009 18:11:02 +0100 Subject: [PATCH 259/503] Return redirect code correctly as HTTP status, not a header. Fixes ticket #1371 --- lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index fdcae0aca0..26f1ff179f 100644 --- a/lib/util.php +++ b/lib/util.php @@ -850,7 +850,7 @@ function common_redirect($url, $code=307) 303 => "See Other", 307 => "Temporary Redirect"); - header("Status: ${code} $status[$code]"); + header('HTTP/1.1 '.$code.' '.$status[$code]); header("Location: $url"); $xo = new XMLOutputter(); From e3d5f965ae3241a9786cdcc3783af67029af57e9 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Wed, 1 Apr 2009 18:11:02 +0100 Subject: [PATCH 260/503] Return redirect code correctly as HTTP status, not a header. Fixes ticket #1371 --- lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index 98a3ae8448..f08e707549 100644 --- a/lib/util.php +++ b/lib/util.php @@ -850,7 +850,7 @@ function common_redirect($url, $code=307) 303 => "See Other", 307 => "Temporary Redirect"); - header("Status: ${code} $status[$code]"); + header('HTTP/1.1 '.$code.' '.$status[$code]); header("Location: $url"); $xo = new XMLOutputter(); From c172cbafaa9ba17ff8ca5c6dd07741bd0de96871 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Apr 2009 15:30:59 -0400 Subject: [PATCH 261/503] Try to do intelligent redirect codes After fixing the redirect code output, there are a lot of weirdnesses with e.g. form handling. Try to add explicit redirect codes where needed -- principly when handling a POST. --- actions/block.php | 11 ++++++----- actions/deletenotice.php | 2 +- actions/disfavor.php | 5 +++-- actions/editgroup.php | 3 +-- actions/favor.php | 7 ++++--- actions/finishaddopenid.php | 2 +- actions/finishopenidlogin.php | 5 +++-- actions/finishremotesubscribe.php | 3 ++- actions/joingroup.php | 3 ++- actions/leavegroup.php | 3 ++- actions/login.php | 2 +- actions/logout.php | 8 ++++---- actions/newgroup.php | 2 +- actions/nudge.php | 7 ++++--- actions/remotesubscribe.php | 4 ++-- actions/smssettings.php | 3 ++- actions/subedit.php | 3 ++- actions/subscribe.php | 3 ++- actions/tag.php | 4 +++- actions/tagother.php | 3 ++- actions/unblock.php | 5 +++-- actions/unsubscribe.php | 3 ++- lib/openid.php | 2 +- lib/settingsaction.php | 4 ++-- 24 files changed, 56 insertions(+), 41 deletions(-) diff --git a/actions/block.php b/actions/block.php index e77b634c86..34f991dc61 100644 --- a/actions/block.php +++ b/actions/block.php @@ -93,7 +93,8 @@ class BlockAction extends Action if ($this->arg('no')) { $cur = common_current_user(); $other = Profile::staticGet('id', $this->arg('blockto')); - common_redirect(common_local_url('showstream', array('nickname' => $other->nickname))); + common_redirect(common_local_url('showstream', array('nickname' => $other->nickname)), + 303); } elseif ($this->arg('yes')) { $this->blockProfile(); } elseif ($this->arg('blockto')) { @@ -102,7 +103,6 @@ class BlockAction extends Action } } - function showContent() { $this->areYouSureForm(); } @@ -110,7 +110,7 @@ class BlockAction extends Action function title() { return _('Block user'); } - + function showNoticeForm() { // nop } @@ -178,10 +178,11 @@ class BlockAction extends Action } if ($action) { - common_redirect(common_local_url($action, $args)); + common_redirect(common_local_url($action, $args), 303); } else { common_redirect(common_local_url('subscriptions', - array('nickname' => $cur->nickname))); + array('nickname' => $cur->nickname)), + 303); } } } diff --git a/actions/deletenotice.php b/actions/deletenotice.php index 16e2df8899..6c350b33ab 100644 --- a/actions/deletenotice.php +++ b/actions/deletenotice.php @@ -141,6 +141,6 @@ class DeletenoticeAction extends DeleteAction $url = common_local_url('public'); } - common_redirect($url); + common_redirect($url, 303); } } diff --git a/actions/disfavor.php b/actions/disfavor.php index 90bab3ccae..bc13b09da5 100644 --- a/actions/disfavor.php +++ b/actions/disfavor.php @@ -49,7 +49,7 @@ class DisfavorAction extends Action { /** * Class handler. - * + * * @param array $args query arguments * * @return void @@ -100,7 +100,8 @@ class DisfavorAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('showfavorites', - array('nickname' => $user->nickname))); + array('nickname' => $user->nickname)), + 303); } } } diff --git a/actions/editgroup.php b/actions/editgroup.php index e7e79040a4..39dad0465e 100644 --- a/actions/editgroup.php +++ b/actions/editgroup.php @@ -166,7 +166,6 @@ class EditgroupAction extends Action return; } - $nickname = common_canonical_nickname($this->trimmed('nickname')); $fullname = $this->trimmed('fullname'); $homepage = $this->trimmed('homepage'); @@ -221,7 +220,7 @@ class EditgroupAction extends Action if ($this->group->nickname != $orig->nickname) { common_redirect(common_local_url('editgroup', array('nickname' => $nickname)), - 307); + 303); } else { $this->showForm(_('Options saved.')); } diff --git a/actions/favor.php b/actions/favor.php index 3940df6888..3b7d979ebc 100644 --- a/actions/favor.php +++ b/actions/favor.php @@ -52,7 +52,7 @@ class FavorAction extends Action { /** * Class handler. - * + * * @param array $args query arguments * * @return void @@ -100,13 +100,14 @@ class FavorAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('showfavorites', - array('nickname' => $user->nickname))); + array('nickname' => $user->nickname)), + 303); } } /** * Notifies a user when his notice is favorited. - * + * * @param class $notice favorited notice * @param class $user user declaring a favorite * diff --git a/actions/finishaddopenid.php b/actions/finishaddopenid.php index 8f10505cff..32bceecfd5 100644 --- a/actions/finishaddopenid.php +++ b/actions/finishaddopenid.php @@ -139,7 +139,7 @@ class FinishaddopenidAction extends Action oid_set_last($display); - common_redirect(common_local_url('openidsettings')); + common_redirect(common_local_url('openidsettings'), 303); } } diff --git a/actions/finishopenidlogin.php b/actions/finishopenidlogin.php index 52d9be29c1..952185742f 100644 --- a/actions/finishopenidlogin.php +++ b/actions/finishopenidlogin.php @@ -271,7 +271,8 @@ class FinishopenidloginAction extends Action common_rememberme($user); } unset($_SESSION['openid_rememberme']); - common_redirect(common_local_url('showstream', array('nickname' => $user->nickname))); + common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)), + 303); } function connectUser() @@ -324,7 +325,7 @@ class FinishopenidloginAction extends Action array('nickname' => $nickname)); } - common_redirect($url); + common_redirect($url, 303); } function bestNewNickname($display, $sreg) diff --git a/actions/finishremotesubscribe.php b/actions/finishremotesubscribe.php index eaf57c2d8f..d54c29a603 100644 --- a/actions/finishremotesubscribe.php +++ b/actions/finishremotesubscribe.php @@ -230,7 +230,8 @@ class FinishremotesubscribeAction extends Action # show up close to the top of the page common_redirect(common_local_url('subscribers', array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } function add_avatar($profile, $url) diff --git a/actions/joingroup.php b/actions/joingroup.php index eeea4a37bf..a5d82ddc77 100644 --- a/actions/joingroup.php +++ b/actions/joingroup.php @@ -143,7 +143,8 @@ class JoingroupAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('groupmembers', array('nickname' => - $this->group->nickname))); + $this->group->nickname)), + 303); } } } \ No newline at end of file diff --git a/actions/leavegroup.php b/actions/leavegroup.php index eb30d0e505..215ccd9017 100644 --- a/actions/leavegroup.php +++ b/actions/leavegroup.php @@ -147,7 +147,8 @@ class LeavegroupAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('groupmembers', array('nickname' => - $this->group->nickname))); + $this->group->nickname)), + 303); } } } diff --git a/actions/login.php b/actions/login.php index b049791fb1..59c6b4874b 100644 --- a/actions/login.php +++ b/actions/login.php @@ -138,7 +138,7 @@ class LoginAction extends Action $nickname)); } - common_redirect($url); + common_redirect($url, 303); } /** diff --git a/actions/logout.php b/actions/logout.php index 3977f90a03..b7681be382 100644 --- a/actions/logout.php +++ b/actions/logout.php @@ -46,10 +46,10 @@ require_once INSTALLDIR.'/lib/openid.php'; */ class LogoutAction extends Action { - + /** * This is read only. - * + * * @return boolean true */ function isReadOnly() @@ -59,7 +59,7 @@ class LogoutAction extends Action /** * Class handler. - * + * * @param array $args array of arguments * * @return nothing @@ -73,7 +73,7 @@ class LogoutAction extends Action common_set_user(null); common_real_login(false); // not logged in common_forgetme(); // don't log back in! - common_redirect(common_local_url('public')); + common_redirect(common_local_url('public'), 303); } } } diff --git a/actions/newgroup.php b/actions/newgroup.php index cbd8dfeec5..67cd6b2f18 100644 --- a/actions/newgroup.php +++ b/actions/newgroup.php @@ -193,7 +193,7 @@ class NewgroupAction extends Action $group->query('COMMIT'); - common_redirect($group->homeUrl(), 307); + common_redirect($group->homeUrl(), 303); } function nicknameExists($nickname) diff --git a/actions/nudge.php b/actions/nudge.php index bc3d484788..b4e5e01dd8 100644 --- a/actions/nudge.php +++ b/actions/nudge.php @@ -50,7 +50,7 @@ class NudgeAction extends Action { /** * Class handler. - * + * * @param array $args array of arguments * * @return nothing @@ -75,7 +75,7 @@ class NudgeAction extends Action // CSRF protection $token = $this->trimmed('token'); - + if (!$token || $token != common_session_token()) { $this->clientError(_('There was a problem with your session token. Try again, please.')); return; @@ -100,7 +100,8 @@ class NudgeAction extends Action } else { // display a confirmation to the user common_redirect(common_local_url('showstream', - array('nickname' => $other->nickname))); + array('nickname' => $other->nickname)), + 303); } } diff --git a/actions/remotesubscribe.php b/actions/remotesubscribe.php index af130f4258..2e721a38b0 100644 --- a/actions/remotesubscribe.php +++ b/actions/remotesubscribe.php @@ -99,7 +99,7 @@ class RemotesubscribeAction extends Action $this->elementStart('fieldset'); $this->element('legend', 'Subscribe to a remote user'); $this->hidden('token', common_session_token()); - + $this->elementStart('ul', 'form_data'); $this->elementStart('li'); $this->input('nickname', _('User nickname'), $this->nickname, @@ -407,7 +407,7 @@ class RemotesubscribeAction extends Action # Redirect to authorization service - common_redirect($req->to_url()); + common_redirect($req->to_url(), 303); return; } } diff --git a/actions/smssettings.php b/actions/smssettings.php index a5f75d266c..922bab9a4e 100644 --- a/actions/smssettings.php +++ b/actions/smssettings.php @@ -488,7 +488,8 @@ class SmssettingsAction extends ConnectSettingsAction } common_redirect(common_local_url('confirmaddress', - array('code' => $code))); + array('code' => $code)), + 303); } /** diff --git a/actions/subedit.php b/actions/subedit.php index 89081ffc76..8ca2d79146 100644 --- a/actions/subedit.php +++ b/actions/subedit.php @@ -85,7 +85,8 @@ class SubeditAction extends Action } common_redirect(common_local_url('subscriptions', - array('nickname' => $cur->nickname))); + array('nickname' => $cur->nickname)), + 303); } } } diff --git a/actions/subscribe.php b/actions/subscribe.php index f761992de4..0bc522867e 100644 --- a/actions/subscribe.php +++ b/actions/subscribe.php @@ -75,7 +75,8 @@ class SubscribeAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('subscriptions', array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } } } diff --git a/actions/tag.php b/actions/tag.php index 231f2c2992..d15f64498d 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -33,7 +33,9 @@ class TagAction extends Action } if ($this->tag != $taginput) { - common_redirect(common_local_url('tag', array('tag' => $this->tag))); + common_redirect(common_local_url('tag', array('tag' => $this->tag)), + 301); + return false; } $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; diff --git a/actions/tagother.php b/actions/tagother.php index 0d18945a09..0c5bb7cf3e 100644 --- a/actions/tagother.php +++ b/actions/tagother.php @@ -221,7 +221,8 @@ class TagotherAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url($action, array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } } diff --git a/actions/unblock.php b/actions/unblock.php index bad4963534..8573b2a873 100644 --- a/actions/unblock.php +++ b/actions/unblock.php @@ -116,10 +116,11 @@ class UnblockAction extends Action } } if ($action) { - common_redirect(common_local_url($action, $args)); + common_redirect(common_local_url($action, $args), 303); } else { common_redirect(common_local_url('subscriptions', - array('nickname' => $cur->nickname))); + array('nickname' => $cur->nickname)), + 303); } } } diff --git a/actions/unsubscribe.php b/actions/unsubscribe.php index b1e2b64256..7dcab04c04 100644 --- a/actions/unsubscribe.php +++ b/actions/unsubscribe.php @@ -77,7 +77,8 @@ class UnsubscribeAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('subscriptions', array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } } } diff --git a/lib/openid.php b/lib/openid.php index f3769c6fce..3af7a39cfa 100644 --- a/lib/openid.php +++ b/lib/openid.php @@ -171,7 +171,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false) } else if (Auth_OpenID::isFailure($redirect_url)) { return sprintf(_('Could not redirect to server: %s'), $redirect_url->message); } else { - common_redirect($redirect_url); + common_redirect($redirect_url, 303); } } else { // Generate form markup and render it. diff --git a/lib/settingsaction.php b/lib/settingsaction.php index 53c807c6f9..db20c58043 100644 --- a/lib/settingsaction.php +++ b/lib/settingsaction.php @@ -78,9 +78,9 @@ class SettingsAction extends Action common_set_returnto($this->selfUrl()); $user = common_current_user(); if ($user->hasOpenID()) { - common_redirect(common_local_url('openidlogin')); + common_redirect(common_local_url('openidlogin'), 303); } else { - common_redirect(common_local_url('login')); + common_redirect(common_local_url('login'), 303); } } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { $this->handlePost(); From 5067939e9abaa7451faa26a7246460214aafb320 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Apr 2009 15:30:59 -0400 Subject: [PATCH 262/503] Try to do intelligent redirect codes After fixing the redirect code output, there are a lot of weirdnesses with e.g. form handling. Try to add explicit redirect codes where needed -- principly when handling a POST. --- actions/block.php | 11 ++++++----- actions/deletenotice.php | 2 +- actions/disfavor.php | 5 +++-- actions/editgroup.php | 3 +-- actions/favor.php | 7 ++++--- actions/finishaddopenid.php | 2 +- actions/finishopenidlogin.php | 5 +++-- actions/finishremotesubscribe.php | 3 ++- actions/joingroup.php | 3 ++- actions/leavegroup.php | 3 ++- actions/login.php | 2 +- actions/logout.php | 8 ++++---- actions/newgroup.php | 2 +- actions/nudge.php | 7 ++++--- actions/remotesubscribe.php | 4 ++-- actions/smssettings.php | 3 ++- actions/subedit.php | 3 ++- actions/subscribe.php | 3 ++- actions/tag.php | 4 +++- actions/tagother.php | 3 ++- actions/unblock.php | 5 +++-- actions/unsubscribe.php | 3 ++- lib/openid.php | 2 +- lib/settingsaction.php | 4 ++-- 24 files changed, 56 insertions(+), 41 deletions(-) diff --git a/actions/block.php b/actions/block.php index e77b634c86..34f991dc61 100644 --- a/actions/block.php +++ b/actions/block.php @@ -93,7 +93,8 @@ class BlockAction extends Action if ($this->arg('no')) { $cur = common_current_user(); $other = Profile::staticGet('id', $this->arg('blockto')); - common_redirect(common_local_url('showstream', array('nickname' => $other->nickname))); + common_redirect(common_local_url('showstream', array('nickname' => $other->nickname)), + 303); } elseif ($this->arg('yes')) { $this->blockProfile(); } elseif ($this->arg('blockto')) { @@ -102,7 +103,6 @@ class BlockAction extends Action } } - function showContent() { $this->areYouSureForm(); } @@ -110,7 +110,7 @@ class BlockAction extends Action function title() { return _('Block user'); } - + function showNoticeForm() { // nop } @@ -178,10 +178,11 @@ class BlockAction extends Action } if ($action) { - common_redirect(common_local_url($action, $args)); + common_redirect(common_local_url($action, $args), 303); } else { common_redirect(common_local_url('subscriptions', - array('nickname' => $cur->nickname))); + array('nickname' => $cur->nickname)), + 303); } } } diff --git a/actions/deletenotice.php b/actions/deletenotice.php index 16e2df8899..6c350b33ab 100644 --- a/actions/deletenotice.php +++ b/actions/deletenotice.php @@ -141,6 +141,6 @@ class DeletenoticeAction extends DeleteAction $url = common_local_url('public'); } - common_redirect($url); + common_redirect($url, 303); } } diff --git a/actions/disfavor.php b/actions/disfavor.php index 90bab3ccae..bc13b09da5 100644 --- a/actions/disfavor.php +++ b/actions/disfavor.php @@ -49,7 +49,7 @@ class DisfavorAction extends Action { /** * Class handler. - * + * * @param array $args query arguments * * @return void @@ -100,7 +100,8 @@ class DisfavorAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('showfavorites', - array('nickname' => $user->nickname))); + array('nickname' => $user->nickname)), + 303); } } } diff --git a/actions/editgroup.php b/actions/editgroup.php index e7e79040a4..39dad0465e 100644 --- a/actions/editgroup.php +++ b/actions/editgroup.php @@ -166,7 +166,6 @@ class EditgroupAction extends Action return; } - $nickname = common_canonical_nickname($this->trimmed('nickname')); $fullname = $this->trimmed('fullname'); $homepage = $this->trimmed('homepage'); @@ -221,7 +220,7 @@ class EditgroupAction extends Action if ($this->group->nickname != $orig->nickname) { common_redirect(common_local_url('editgroup', array('nickname' => $nickname)), - 307); + 303); } else { $this->showForm(_('Options saved.')); } diff --git a/actions/favor.php b/actions/favor.php index 3940df6888..3b7d979ebc 100644 --- a/actions/favor.php +++ b/actions/favor.php @@ -52,7 +52,7 @@ class FavorAction extends Action { /** * Class handler. - * + * * @param array $args query arguments * * @return void @@ -100,13 +100,14 @@ class FavorAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('showfavorites', - array('nickname' => $user->nickname))); + array('nickname' => $user->nickname)), + 303); } } /** * Notifies a user when his notice is favorited. - * + * * @param class $notice favorited notice * @param class $user user declaring a favorite * diff --git a/actions/finishaddopenid.php b/actions/finishaddopenid.php index 8f10505cff..32bceecfd5 100644 --- a/actions/finishaddopenid.php +++ b/actions/finishaddopenid.php @@ -139,7 +139,7 @@ class FinishaddopenidAction extends Action oid_set_last($display); - common_redirect(common_local_url('openidsettings')); + common_redirect(common_local_url('openidsettings'), 303); } } diff --git a/actions/finishopenidlogin.php b/actions/finishopenidlogin.php index 52d9be29c1..952185742f 100644 --- a/actions/finishopenidlogin.php +++ b/actions/finishopenidlogin.php @@ -271,7 +271,8 @@ class FinishopenidloginAction extends Action common_rememberme($user); } unset($_SESSION['openid_rememberme']); - common_redirect(common_local_url('showstream', array('nickname' => $user->nickname))); + common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)), + 303); } function connectUser() @@ -324,7 +325,7 @@ class FinishopenidloginAction extends Action array('nickname' => $nickname)); } - common_redirect($url); + common_redirect($url, 303); } function bestNewNickname($display, $sreg) diff --git a/actions/finishremotesubscribe.php b/actions/finishremotesubscribe.php index eaf57c2d8f..d54c29a603 100644 --- a/actions/finishremotesubscribe.php +++ b/actions/finishremotesubscribe.php @@ -230,7 +230,8 @@ class FinishremotesubscribeAction extends Action # show up close to the top of the page common_redirect(common_local_url('subscribers', array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } function add_avatar($profile, $url) diff --git a/actions/joingroup.php b/actions/joingroup.php index eeea4a37bf..a5d82ddc77 100644 --- a/actions/joingroup.php +++ b/actions/joingroup.php @@ -143,7 +143,8 @@ class JoingroupAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('groupmembers', array('nickname' => - $this->group->nickname))); + $this->group->nickname)), + 303); } } } \ No newline at end of file diff --git a/actions/leavegroup.php b/actions/leavegroup.php index eb30d0e505..215ccd9017 100644 --- a/actions/leavegroup.php +++ b/actions/leavegroup.php @@ -147,7 +147,8 @@ class LeavegroupAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('groupmembers', array('nickname' => - $this->group->nickname))); + $this->group->nickname)), + 303); } } } diff --git a/actions/login.php b/actions/login.php index b049791fb1..59c6b4874b 100644 --- a/actions/login.php +++ b/actions/login.php @@ -138,7 +138,7 @@ class LoginAction extends Action $nickname)); } - common_redirect($url); + common_redirect($url, 303); } /** diff --git a/actions/logout.php b/actions/logout.php index 3977f90a03..b7681be382 100644 --- a/actions/logout.php +++ b/actions/logout.php @@ -46,10 +46,10 @@ require_once INSTALLDIR.'/lib/openid.php'; */ class LogoutAction extends Action { - + /** * This is read only. - * + * * @return boolean true */ function isReadOnly() @@ -59,7 +59,7 @@ class LogoutAction extends Action /** * Class handler. - * + * * @param array $args array of arguments * * @return nothing @@ -73,7 +73,7 @@ class LogoutAction extends Action common_set_user(null); common_real_login(false); // not logged in common_forgetme(); // don't log back in! - common_redirect(common_local_url('public')); + common_redirect(common_local_url('public'), 303); } } } diff --git a/actions/newgroup.php b/actions/newgroup.php index cbd8dfeec5..67cd6b2f18 100644 --- a/actions/newgroup.php +++ b/actions/newgroup.php @@ -193,7 +193,7 @@ class NewgroupAction extends Action $group->query('COMMIT'); - common_redirect($group->homeUrl(), 307); + common_redirect($group->homeUrl(), 303); } function nicknameExists($nickname) diff --git a/actions/nudge.php b/actions/nudge.php index bc3d484788..b4e5e01dd8 100644 --- a/actions/nudge.php +++ b/actions/nudge.php @@ -50,7 +50,7 @@ class NudgeAction extends Action { /** * Class handler. - * + * * @param array $args array of arguments * * @return nothing @@ -75,7 +75,7 @@ class NudgeAction extends Action // CSRF protection $token = $this->trimmed('token'); - + if (!$token || $token != common_session_token()) { $this->clientError(_('There was a problem with your session token. Try again, please.')); return; @@ -100,7 +100,8 @@ class NudgeAction extends Action } else { // display a confirmation to the user common_redirect(common_local_url('showstream', - array('nickname' => $other->nickname))); + array('nickname' => $other->nickname)), + 303); } } diff --git a/actions/remotesubscribe.php b/actions/remotesubscribe.php index af130f4258..2e721a38b0 100644 --- a/actions/remotesubscribe.php +++ b/actions/remotesubscribe.php @@ -99,7 +99,7 @@ class RemotesubscribeAction extends Action $this->elementStart('fieldset'); $this->element('legend', 'Subscribe to a remote user'); $this->hidden('token', common_session_token()); - + $this->elementStart('ul', 'form_data'); $this->elementStart('li'); $this->input('nickname', _('User nickname'), $this->nickname, @@ -407,7 +407,7 @@ class RemotesubscribeAction extends Action # Redirect to authorization service - common_redirect($req->to_url()); + common_redirect($req->to_url(), 303); return; } } diff --git a/actions/smssettings.php b/actions/smssettings.php index a5f75d266c..922bab9a4e 100644 --- a/actions/smssettings.php +++ b/actions/smssettings.php @@ -488,7 +488,8 @@ class SmssettingsAction extends ConnectSettingsAction } common_redirect(common_local_url('confirmaddress', - array('code' => $code))); + array('code' => $code)), + 303); } /** diff --git a/actions/subedit.php b/actions/subedit.php index 89081ffc76..8ca2d79146 100644 --- a/actions/subedit.php +++ b/actions/subedit.php @@ -85,7 +85,8 @@ class SubeditAction extends Action } common_redirect(common_local_url('subscriptions', - array('nickname' => $cur->nickname))); + array('nickname' => $cur->nickname)), + 303); } } } diff --git a/actions/subscribe.php b/actions/subscribe.php index f761992de4..0bc522867e 100644 --- a/actions/subscribe.php +++ b/actions/subscribe.php @@ -75,7 +75,8 @@ class SubscribeAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('subscriptions', array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } } } diff --git a/actions/tag.php b/actions/tag.php index 231f2c2992..d15f64498d 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -33,7 +33,9 @@ class TagAction extends Action } if ($this->tag != $taginput) { - common_redirect(common_local_url('tag', array('tag' => $this->tag))); + common_redirect(common_local_url('tag', array('tag' => $this->tag)), + 301); + return false; } $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; diff --git a/actions/tagother.php b/actions/tagother.php index 0d18945a09..0c5bb7cf3e 100644 --- a/actions/tagother.php +++ b/actions/tagother.php @@ -221,7 +221,8 @@ class TagotherAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url($action, array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } } diff --git a/actions/unblock.php b/actions/unblock.php index bad4963534..8573b2a873 100644 --- a/actions/unblock.php +++ b/actions/unblock.php @@ -116,10 +116,11 @@ class UnblockAction extends Action } } if ($action) { - common_redirect(common_local_url($action, $args)); + common_redirect(common_local_url($action, $args), 303); } else { common_redirect(common_local_url('subscriptions', - array('nickname' => $cur->nickname))); + array('nickname' => $cur->nickname)), + 303); } } } diff --git a/actions/unsubscribe.php b/actions/unsubscribe.php index b1e2b64256..7dcab04c04 100644 --- a/actions/unsubscribe.php +++ b/actions/unsubscribe.php @@ -77,7 +77,8 @@ class UnsubscribeAction extends Action $this->elementEnd('html'); } else { common_redirect(common_local_url('subscriptions', array('nickname' => - $user->nickname))); + $user->nickname)), + 303); } } } diff --git a/lib/openid.php b/lib/openid.php index f3769c6fce..3af7a39cfa 100644 --- a/lib/openid.php +++ b/lib/openid.php @@ -171,7 +171,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false) } else if (Auth_OpenID::isFailure($redirect_url)) { return sprintf(_('Could not redirect to server: %s'), $redirect_url->message); } else { - common_redirect($redirect_url); + common_redirect($redirect_url, 303); } } else { // Generate form markup and render it. diff --git a/lib/settingsaction.php b/lib/settingsaction.php index 53c807c6f9..db20c58043 100644 --- a/lib/settingsaction.php +++ b/lib/settingsaction.php @@ -78,9 +78,9 @@ class SettingsAction extends Action common_set_returnto($this->selfUrl()); $user = common_current_user(); if ($user->hasOpenID()) { - common_redirect(common_local_url('openidlogin')); + common_redirect(common_local_url('openidlogin'), 303); } else { - common_redirect(common_local_url('login')); + common_redirect(common_local_url('login'), 303); } } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { $this->handlePost(); From e28c4689cee5a832c281b0329c9d279e4bbd9d33 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Apr 2009 18:29:10 -0400 Subject: [PATCH 263/503] add sup with arguments --- actions/sup.php | 2 +- lib/router.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/actions/sup.php b/actions/sup.php index 8ef9207fac..246b3299d3 100644 --- a/actions/sup.php +++ b/actions/sup.php @@ -45,7 +45,7 @@ class SupAction extends Action function availablePeriods() { static $periods = array(86400, 43200, 21600, 7200, - 3600, 1800, 600, 300, 120, + 3600, 1800, 600, 300, 120, 60, 30, 15); $available = array(); foreach ($periods as $period) { diff --git a/lib/router.php b/lib/router.php index ae5b5e16bd..6fb2f94872 100644 --- a/lib/router.php +++ b/lib/router.php @@ -107,6 +107,9 @@ class Router $m->connect('main/'.$a, array('action' => $a)); } + $m->connect('main/sup/:seconds', array('action' => 'sup'), + array('seconds' => '[0-9]+')); + $m->connect('main/tagother/:id', array('action' => 'tagother')); // these take a code From 890a1e1339001a82a78f766a1d13103271aadd09 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Apr 2009 18:29:10 -0400 Subject: [PATCH 264/503] add sup with arguments --- actions/sup.php | 2 +- lib/router.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/actions/sup.php b/actions/sup.php index 8ef9207fac..246b3299d3 100644 --- a/actions/sup.php +++ b/actions/sup.php @@ -45,7 +45,7 @@ class SupAction extends Action function availablePeriods() { static $periods = array(86400, 43200, 21600, 7200, - 3600, 1800, 600, 300, 120, + 3600, 1800, 600, 300, 120, 60, 30, 15); $available = array(); foreach ($periods as $period) { diff --git a/lib/router.php b/lib/router.php index 77794aaf70..3c61837f81 100644 --- a/lib/router.php +++ b/lib/router.php @@ -107,6 +107,9 @@ class Router $m->connect('main/'.$a, array('action' => $a)); } + $m->connect('main/sup/:seconds', array('action' => 'sup'), + array('seconds' => '[0-9]+')); + $m->connect('main/tagother/:id', array('action' => 'tagother')); // these take a code From 36f73bffbc717d895370e905070c310062127529 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 2 Apr 2009 06:29:49 +0000 Subject: [PATCH 265/503] Better support for 800px ~ 1024px width viewport/screen resolutions. --- theme/base/css/display.css | 42 +++++++++++++++++----------------- theme/base/css/ie.css | 31 +++++++++++++++---------- theme/base/css/ie6.css | 16 +++++++++++++ theme/default/css/display.css | 2 +- theme/identica/css/display.css | 2 +- 5 files changed, 58 insertions(+), 35 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 9973424293..4c9b522549 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -250,6 +250,7 @@ position:absolute; top:65px; right:18px; width:250px; +width:24%; } #page_notice { clear:both; @@ -259,9 +260,8 @@ margin-bottom:18px; #anon_notice { float:left; -width:432px; -width:28.052em; -padding:11px; +width:43.2%; +padding:1.1%; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; @@ -369,7 +369,9 @@ margin-right:4px; #wrap { margin:0 auto; -width:1003px; +width:100%; +min-width:760px; +max-width:1003px; overflow:hidden; } @@ -381,14 +383,16 @@ margin-bottom:1em; } #content { -width:644px; -padding:18px; +width:64.009%; +padding:1.795%; float:left; border-radius:7px; -moz-border-radius:7px; -moz-border-radius-topleft:0; -webkit-border-radius:7px; -webkit-border-top-left-radius:0; +border-style:solid; +border-width:1px; } #content_inner { @@ -398,10 +402,10 @@ float:left; } #aside_primary { -width:280px; +width:27.917%; float:left; -margin-left:4px; -padding:18px; +margin-left:0.395%; +padding:1.795%; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; @@ -409,9 +413,8 @@ border-width:1px; border-style:solid; } -/*Start: FORM NOTICE*/ #form_notice { -width:458px; +width:45.664%; float:left; position:relative; line-height:1; @@ -428,7 +431,7 @@ float:left; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; -width:370px; +width:80.789%; height:67px; line-height:1.5; padding:7px 7px 16px 7px; @@ -458,8 +461,9 @@ line-height:1.15; padding:1px 2px; } #form_notice #notice_action-submit { -width:60px; -padding:8px; +width:14%; +height:47px; +padding:0; position:absolute; bottom:0; right:0; @@ -472,13 +476,12 @@ margin-bottom:7px; margin-left:18px; float:left; } -/*end FORM NOTICE*/ /* entity_profile */ .entity_profile { position:relative; -width:475px; +width:67.702%; min-height:123px; float:left; margin-bottom:18px; @@ -508,7 +511,6 @@ margin-bottom:18px; .entity_profile .entity_tags { margin-left:113px; margin-bottom:4px; -width:322px; } .entity_profile .entity_fn, @@ -536,14 +538,14 @@ display:none; .entity_profile h2 { display:none; } - /* entity_profile */ /*entity_actions*/ .entity_actions { float:right; -margin-left:28px; +margin-left:4.35%; +max-width:25%; } .entity_actions h2 { display:none; @@ -911,8 +913,6 @@ display:none; border:0; padding:0; } -/*END: NOTICES */ - #new_group, #group_search { diff --git a/theme/base/css/ie.css b/theme/base/css/ie.css index 45176a2019..5d8bea8ae3 100644 --- a/theme/base/css/ie.css +++ b/theme/base/css/ie.css @@ -1,8 +1,21 @@ /* IE specific styles */ - -#aside_primary { -padding-left:11px; +legend { +margin-left:-7px; } +input.checkbox { +top:0; +} +#form_notice textarea { +width:78%; +} +#form_notice #notice_action-submit { +width:17%; +max-width:17%; +} +#anon_notice { +max-width:39%; +} + .notice-options input.submit { font-size:0; margin-top:3px; @@ -11,15 +24,9 @@ text-align:right; text-indent:0; width:24px; } - -input.checkbox { -top:0; -} - -legend { -margin-left:-7px; -} - .notice div.entry-content .timestamp a { margin-right:4px; } +.entity_profile { +width:64%; +} diff --git a/theme/base/css/ie6.css b/theme/base/css/ie6.css index fa6ec92d2f..76a82c0042 100644 --- a/theme/base/css/ie6.css +++ b/theme/base/css/ie6.css @@ -1,4 +1,17 @@ /* IE6 specific styles */ +address { +margin-left:7px; +} +address .fn { +display:none; +} +#content { +width:70%; +} +#aside_primary { +padding:5%; +width:29.5%; +} .entity_profile .entity_nickname, .entity_profile .entity_location, .entity_profile .entity_url, @@ -9,6 +22,9 @@ margin-left:0; .entity_profile .entity_depiction { margin-bottom:123px; } +.entity_actions { +width:20%; +} .notice div.entry-content { width:63%; } diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 12303dd683..bf46fc6bfd 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -17,7 +17,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-size:1em; } address { -margin-right:71px; +margin-right:7.18%; } input, textarea, select, option { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 5235c34a45..9e7c10ac5a 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -17,7 +17,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; font-size:1em; } address { -margin-right:71px; +margin-right:7.18%; } input, textarea, select, option { From 26194cd1d6dbd7ceb021b8e215e7a7ad7b29116f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 2 Apr 2009 06:10:32 -0400 Subject: [PATCH 266/503] i18n for legend in remote sub form --- actions/remotesubscribe.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/remotesubscribe.php b/actions/remotesubscribe.php index 2e721a38b0..0b11748962 100644 --- a/actions/remotesubscribe.php +++ b/actions/remotesubscribe.php @@ -97,7 +97,7 @@ class RemotesubscribeAction extends Action 'class' => 'form_settings', 'action' => common_local_url('remotesubscribe'))); $this->elementStart('fieldset'); - $this->element('legend', 'Subscribe to a remote user'); + $this->element('legend', _('Subscribe to a remote user')); $this->hidden('token', common_session_token()); $this->elementStart('ul', 'form_data'); From bd120bc3153e3502790ec976769febd41f790568 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 12:45:54 -0400 Subject: [PATCH 267/503] reformat queuehandler.php --- lib/queuehandler.php | 79 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/lib/queuehandler.php b/lib/queuehandler.php index 752bbc6d26..f76f16e073 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -36,7 +36,7 @@ class QueueHandler extends Daemon $this->set_id($id); } } - + function class_name() { return ucfirst($this->transport()) . 'Handler'; @@ -46,7 +46,7 @@ class QueueHandler extends Daemon { return strtolower($this->class_name().'.'.$this->get_id()); } - + function get_id() { return $this->_id; @@ -56,16 +56,16 @@ class QueueHandler extends Daemon { $this->_id = $id; } - + function transport() { return null; } - + function start() { } - + function finish() { } @@ -74,7 +74,7 @@ class QueueHandler extends Daemon { return true; } - + function db_dispatch() { do { $qi = Queue_item::top($this->transport()); @@ -107,43 +107,43 @@ class QueueHandler extends Daemon } else { $this->clear_old_claims(); $this->idle(5); - } + } } while (true); } function stomp_dispatch() { - require("Stomp.php"); - $con = new Stomp(common_config('queue','stomp_server')); - if (!$con->connect()) { - $this->log(LOG_ERR, 'Failed to connect to queue server'); - return false; - } - $queue_basename = common_config('queue','queue_basename'); - // subscribe to the relevant queue (format: basename-transport) - $con->subscribe('/queue/'.$queue_basename.'-'.$this->transport()); + require("Stomp.php"); + $con = new Stomp(common_config('queue','stomp_server')); + if (!$con->connect()) { + $this->log(LOG_ERR, 'Failed to connect to queue server'); + return false; + } + $queue_basename = common_config('queue','queue_basename'); + // subscribe to the relevant queue (format: basename-transport) + $con->subscribe('/queue/'.$queue_basename.'-'.$this->transport()); do { $frame = $con->readFrame(); if ($frame) { $this->log(LOG_INFO, 'Got item enqueued '.common_exact_date($frame->headers['created'])); - // XXX: Now the queue handler receives only the ID of the - // notice, and it has to get it from the DB - // A massive improvement would be avoid DB query by transmitting - // all the notice details via queue server... + // XXX: Now the queue handler receives only the ID of the + // notice, and it has to get it from the DB + // A massive improvement would be avoid DB query by transmitting + // all the notice details via queue server... $notice = Notice::staticGet($frame->body); if ($notice) { $this->log(LOG_INFO, 'broadcasting notice ID = ' . $notice->id); $result = $this->handle_notice($notice); if ($result) { - // if the msg has been handled positively, ack it - // and the queue server will remove it from the queue - $con->ack($frame); - $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); - } - else { - // no ack + // if the msg has been handled positively, ack it + // and the queue server will remove it from the queue + $con->ack($frame); + $this->log(LOG_INFO, 'finished broadcasting notice ID = ' . $notice->id); + } + else { + // no ack $this->log(LOG_WARNING, 'Failed broadcast for notice ID = ' . $notice->id); } $notice->free(); @@ -152,12 +152,11 @@ class QueueHandler extends Daemon } else { $this->log(LOG_WARNING, 'queue item for notice that does not exist'); } - } + } } while (true); - - $con->disconnect(); + + $con->disconnect(); } - function run() { @@ -165,12 +164,12 @@ class QueueHandler extends Daemon return false; } $this->log(LOG_INFO, 'checking for queued notices'); - if (common_config('queue','subsystem') == 'stomp') { - $this->stomp_dispatch(); - } - else { - $this->db_dispatch(); - } + if (common_config('queue','subsystem') == 'stomp') { + $this->stomp_dispatch(); + } + else { + $this->db_dispatch(); + } if (!$this->finish()) { return false; } @@ -183,7 +182,7 @@ class QueueHandler extends Daemon sleep($timeout); } } - + function clear_old_claims() { $qi = new Queue_item(); @@ -193,10 +192,10 @@ class QueueHandler extends Daemon $qi->free(); unset($qi); } - + function log($level, $msg) { common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); } } - + From e2898db087c5ae43587235ce3c97b11fff5867a4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 12:51:43 -0400 Subject: [PATCH 268/503] add finishaddopenid to list of sensitive pages to use with ssl --- lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index f08e707549..73410e2891 100644 --- a/lib/util.php +++ b/lib/util.php @@ -723,7 +723,7 @@ function common_local_url($action, $args=null, $params=null, $fragment=null) { static $sensitive = array('login', 'register', 'passwordsettings', 'twittersettings', 'finishopenidlogin', - 'api'); + 'finishaddopenid', 'api'); $r = Router::get(); $path = $r->build($action, $args, $params, $fragment); From dfce4c012f118c020305b7ce2f3e4fde26fab7b2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 12:51:43 -0400 Subject: [PATCH 269/503] add finishaddopenid to list of sensitive pages to use with ssl --- lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index f08e707549..73410e2891 100644 --- a/lib/util.php +++ b/lib/util.php @@ -723,7 +723,7 @@ function common_local_url($action, $args=null, $params=null, $fragment=null) { static $sensitive = array('login', 'register', 'passwordsettings', 'twittersettings', 'finishopenidlogin', - 'api'); + 'finishaddopenid', 'api'); $r = Router::get(); $path = $r->build($action, $args, $params, $fragment); From 5f79653acb56867b6e31fd56f2d16cbc77622fbc Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 14:00:52 -0400 Subject: [PATCH 270/503] redirect FOAF file on non-canonical nickname --- actions/foaf.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/actions/foaf.php b/actions/foaf.php index 3a99835b4a..aa78b91c3e 100644 --- a/actions/foaf.php +++ b/actions/foaf.php @@ -33,7 +33,24 @@ class FoafAction extends Action function prepare($args) { parent::prepare($args); - $this->nickname = $this->trimmed('nickname'); + + $nickname_arg = $this->arg('nickname'); + + if (empty($nickname_arg)) { + $this->clientError(_('No such user.'), 404); + return false; + } + + $this->nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $this->nickname) { + common_redirect(common_local_url('foaf', + array('nickname' => $this->nickname)), + 301); + return false; + } $this->user = User::staticGet('nickname', $this->nickname); From 5eacffcb3a29e6a997e50483d99eb0bf15711b2c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 14:18:29 -0400 Subject: [PATCH 271/503] try to reduce memory usage in FOAF output --- actions/foaf.php | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/actions/foaf.php b/actions/foaf.php index aa78b91c3e..416935b1b7 100644 --- a/actions/foaf.php +++ b/actions/foaf.php @@ -139,20 +139,30 @@ class FoafAction extends Action if ($sub->find()) { while ($sub->fetch()) { - if ($sub->token) { + if (!empty($sub->token)) { $other = Remote_profile::staticGet('id', $sub->subscribed); } else { $other = User::staticGet('id', $sub->subscribed); } - if (!$other) { + if (empty($other)) { common_debug('Got a bad subscription: '.print_r($sub,true)); continue; } $this->element('knows', array('rdf:resource' => $other->uri)); - $person[$other->uri] = array(LISTENEE, $other); + $person[$other->uri] = array(LISTENEE, + $other->id, + $other->nickname, + (empty($sub->token)) ? 'User' : 'Remote_profile'); + $other->free(); + $other = null; + unset($other); } } + $sub->free(); + $sub = null; + unset($sub); + // Get people who subscribe to user $sub = new Subscription(); @@ -173,25 +183,36 @@ class FoafAction extends Action if (array_key_exists($other->uri, $person)) { $person[$other->uri][0] = BOTH; } else { - $person[$other->uri] = array(LISTENER, $other); + $person[$other->uri] = array(LISTENER, + $other->id, + $other->nickname, + (empty($sub->token)) ? 'User' : 'Remote_profile'); } + $other->free(); + $other = null; + unset($other); } } + $sub->free(); + $sub = null; + unset($sub); + $this->elementEnd('Person'); foreach ($person as $uri => $p) { $foaf_url = null; - if ($p[1] instanceof User) { - $foaf_url = common_local_url('foaf', array('nickname' => $p[1]->nickname)); + list($type, $id, $nickname, $cls) = $p; + if ($cls == 'User') { + $foaf_url = common_local_url('foaf', array('nickname' => $nickname)); } - $this->profile = Profile::staticGet($p[1]->id); + $profile = Profile::staticGet($id); $this->elementStart('Person', array('rdf:about' => $uri)); - if ($p[0] == LISTENER || $p[0] == BOTH) { + if ($type == LISTENER || $type == BOTH) { $this->element('knows', array('rdf:resource' => $this->user->uri)); } - $this->showMicrobloggingAccount($this->profile, ($p[1] instanceof User) ? - common_root_url() : null); + $this->showMicrobloggingAccount($profile, ($cls == 'User') ? + common_root_url() : null); if ($foaf_url) { $this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url)); } @@ -199,6 +220,9 @@ class FoafAction extends Action if ($foaf_url) { $this->showPpd($foaf_url, $uri); } + $profile->free(); + $profile = null; + unset($profile); } $this->elementEnd('rdf:RDF'); From 45d520550562691bebd17c3477eda1df049be0be Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 14:00:52 -0400 Subject: [PATCH 272/503] redirect FOAF file on non-canonical nickname --- actions/foaf.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/actions/foaf.php b/actions/foaf.php index 3a99835b4a..aa78b91c3e 100644 --- a/actions/foaf.php +++ b/actions/foaf.php @@ -33,7 +33,24 @@ class FoafAction extends Action function prepare($args) { parent::prepare($args); - $this->nickname = $this->trimmed('nickname'); + + $nickname_arg = $this->arg('nickname'); + + if (empty($nickname_arg)) { + $this->clientError(_('No such user.'), 404); + return false; + } + + $this->nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $this->nickname) { + common_redirect(common_local_url('foaf', + array('nickname' => $this->nickname)), + 301); + return false; + } $this->user = User::staticGet('nickname', $this->nickname); From 860d7f79a9da99a599037ca06ca8b55e4c954b63 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 14:18:29 -0400 Subject: [PATCH 273/503] try to reduce memory usage in FOAF output --- actions/foaf.php | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/actions/foaf.php b/actions/foaf.php index aa78b91c3e..416935b1b7 100644 --- a/actions/foaf.php +++ b/actions/foaf.php @@ -139,20 +139,30 @@ class FoafAction extends Action if ($sub->find()) { while ($sub->fetch()) { - if ($sub->token) { + if (!empty($sub->token)) { $other = Remote_profile::staticGet('id', $sub->subscribed); } else { $other = User::staticGet('id', $sub->subscribed); } - if (!$other) { + if (empty($other)) { common_debug('Got a bad subscription: '.print_r($sub,true)); continue; } $this->element('knows', array('rdf:resource' => $other->uri)); - $person[$other->uri] = array(LISTENEE, $other); + $person[$other->uri] = array(LISTENEE, + $other->id, + $other->nickname, + (empty($sub->token)) ? 'User' : 'Remote_profile'); + $other->free(); + $other = null; + unset($other); } } + $sub->free(); + $sub = null; + unset($sub); + // Get people who subscribe to user $sub = new Subscription(); @@ -173,25 +183,36 @@ class FoafAction extends Action if (array_key_exists($other->uri, $person)) { $person[$other->uri][0] = BOTH; } else { - $person[$other->uri] = array(LISTENER, $other); + $person[$other->uri] = array(LISTENER, + $other->id, + $other->nickname, + (empty($sub->token)) ? 'User' : 'Remote_profile'); } + $other->free(); + $other = null; + unset($other); } } + $sub->free(); + $sub = null; + unset($sub); + $this->elementEnd('Person'); foreach ($person as $uri => $p) { $foaf_url = null; - if ($p[1] instanceof User) { - $foaf_url = common_local_url('foaf', array('nickname' => $p[1]->nickname)); + list($type, $id, $nickname, $cls) = $p; + if ($cls == 'User') { + $foaf_url = common_local_url('foaf', array('nickname' => $nickname)); } - $this->profile = Profile::staticGet($p[1]->id); + $profile = Profile::staticGet($id); $this->elementStart('Person', array('rdf:about' => $uri)); - if ($p[0] == LISTENER || $p[0] == BOTH) { + if ($type == LISTENER || $type == BOTH) { $this->element('knows', array('rdf:resource' => $this->user->uri)); } - $this->showMicrobloggingAccount($this->profile, ($p[1] instanceof User) ? - common_root_url() : null); + $this->showMicrobloggingAccount($profile, ($cls == 'User') ? + common_root_url() : null); if ($foaf_url) { $this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url)); } @@ -199,6 +220,9 @@ class FoafAction extends Action if ($foaf_url) { $this->showPpd($foaf_url, $uri); } + $profile->free(); + $profile = null; + unset($profile); } $this->elementEnd('rdf:RDF'); From 4d4e6ead9c98afeb43e5913b734eea9b5c783955 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 3 Apr 2009 19:16:35 +0000 Subject: [PATCH 274/503] added filler text to public tagcloud for when it's empty, encouraging user to post and/or register. --- actions/public.php | 16 ---------------- actions/publictagcloud.php | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/actions/public.php b/actions/public.php index 96c766a57d..fca90488fe 100644 --- a/actions/public.php +++ b/actions/public.php @@ -184,25 +184,9 @@ class PublicAction extends Action if (common_logged_in()) { $message .= _('Be the first to post!'); -/* - sprintf(_('You are logged in... %%%%site.name%%%% groups let you find and talk with ' . - 'people of similar interests. After you join a group ' . - 'you can send messages to all other members using the ' . - 'syntax "!groupname". Don\'t see a group you like? Try ' . - '[searching for one](%%%%action.groupsearch%%%%) or ' . - '[start your own!](%%%%action.newgroup%%%%)')); -*/ } else { $message .= _('Why not [register an account](%%action.register%%) and be the first to post!'); -/* - sprintf(_('You are not logged in... %%%%site.name%%%% groups let you find and talk with ' . - 'people of similar interests. After you join a group ' . - 'you can send messages to all other members using the ' . - 'syntax "!groupname". Don\'t see a group you like? Try ' . - '[searching for one](%%%%action.groupsearch%%%%) or ' . - '[start your own!](%%%%action.newgroup%%%%)')); -*/ } $this->elementStart('div', 'blankfiller'); diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index 6f5fc75413..5322372b2a 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -62,6 +62,24 @@ class PublictagcloudAction extends Action $this->element('p', 'instructions', sprintf(_('These are most popular recent tags on %s '), common_config('site', 'name'))); + + $tags = new Notice_tag(); + if ($tags->count()) { + return; + } + + $message = _('Noone has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' '; + + if (common_logged_in()) { + $message .= _('Be the first to post one!'); + } + else { + $message .= _('Why not [register an account](%%action.register%%) and be the first to post one!'); + } + + $this->elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); } function showLocalNav() From fa3ca0548f12a7a8f7774cfa918cba426be45f96 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 16:12:33 -0400 Subject: [PATCH 275/503] fix output of conversation --- actions/conversation.php | 48 ++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/actions/conversation.php b/actions/conversation.php index 0c22fe1238..05cfb76e3c 100644 --- a/actions/conversation.php +++ b/actions/conversation.php @@ -31,6 +31,8 @@ if (!defined('LACONICA')) { exit(1); } +require_once(INSTALLDIR.'/lib/noticelist.php'); + /** * Conversation tree in the browser * @@ -43,7 +45,6 @@ if (!defined('LACONICA')) { class ConversationAction extends Action { var $id = null; - var $notices = null; var $page = null; /** @@ -58,10 +59,9 @@ class ConversationAction extends Action { parent::prepare($args); $this->id = $this->trimmed('id'); - if (!$this->id) { + if (empty($this->id)) { return false; } - $this->notices = $this->getNotices(); $this->page = $this->trimmed('page'); if (empty($this->page)) { $this->page = 1; @@ -69,36 +69,9 @@ class ConversationAction extends Action return true; } - /** - * Get notices - * - * @param integer $limit max number of notices to return - * - * @return array notices - */ - - function getNotices($limit=0) - { - $qry = 'SELECT notice.*, '. - 'FROM notice WHERE conversation = %d '. - 'ORDER BY created '; - - $offset = 0; - $limit = NOTICES_PER_PAGE + 1; - - if (common_config('db', 'type') == 'pgsql') { - $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; - } else { - $qry .= ' LIMIT ' . $offset . ', ' . $limit; - } - - return Notice::getStream(sprintf($qry, $this->id), - 'notice:conversation:'.$this->id, - $offset, $limit); - } - function handle($args) { + parent::handle($args); $this->showPage(); } @@ -111,7 +84,18 @@ class ConversationAction extends Action { // FIXME this needs to be a tree, not a list - $nl = new NoticeList($this->notices, $this); + $qry = 'SELECT * FROM notice WHERE conversation = %s '; + + $offset = ($this->page-1)*NOTICES_PER_PAGE; + $limit = NOTICES_PER_PAGE + 1; + + $txt = sprintf($qry, $this->id); + + $notices = Notice::getStream($txt, + 'notice:conversation:'.$this->id, + $offset, $limit); + + $nl = new NoticeList($notices, $this); $cnt = $nl->show(); From 95bb1c6a99766d065ffcde9523de05d8a1162c3d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 16:16:39 -0400 Subject: [PATCH 276/503] in context link for conversations --- lib/noticelist.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/noticelist.php b/lib/noticelist.php index 4182d8808f..8fccba73e1 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -197,7 +197,7 @@ class NoticeListItem extends Widget $this->out->elementStart('div', 'entry-content'); $this->showNoticeLink(); $this->showNoticeSource(); - $this->showReplyTo(); + $this->showContext(); $this->out->elementEnd('div'); } @@ -421,17 +421,18 @@ class NoticeListItem extends Widget * @return void */ - function showReplyTo() + function showContext() { - if ($this->notice->reply_to) { - $replyurl = common_local_url('shownotice', - array('notice' => $this->notice->reply_to)); + // XXX: also show context if there are replies to this notice + if (!empty($this->notice->conversation) + && $this->notice->conversation != $this->notice->id) { + $convurl = common_local_url('conversation', + array('id' => $this->notice->conversation)); $this->out->elementStart('dl', 'response'); $this->out->element('dt', null, _('To')); $this->out->elementStart('dd'); - $this->out->element('a', array('href' => $replyurl, - 'rel' => 'in-reply-to'), - _('in reply to')); + $this->out->element('a', array('href' => $convurl), + _('in context')); $this->out->elementEnd('dd'); $this->out->elementEnd('dl'); } From ab2946047cd08c6b66cbc57410fa8a99430530f6 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 3 Apr 2009 13:19:33 -0700 Subject: [PATCH 277/503] Only kill control and surrogates, leave UTF-8 formatting chars alone. --- lib/util.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/util.php b/lib/util.php index a43666fa5c..11f0f297e0 100644 --- a/lib/util.php +++ b/lib/util.php @@ -581,10 +581,8 @@ function common_shorten_link($url, $reverse = false) function common_xml_safe_str($str) { - $xmlStr = htmlentities(iconv('UTF-8', 'UTF-8//IGNORE', $str), ENT_NOQUOTES, 'UTF-8'); - - // Replace control, formatting, and surrogate characters with '*', ala Twitter - return preg_replace('/[\p{Cc}\p{Cf}\p{Cs}]/u', '*', $str); + // Neutralize control codes and surrogates + return preg_replace('/[\p{Cc}\p{Cs}]/u', '*', $str); } function common_tag_link($tag) From e1fec6db2fdc9c28878c8f87bd5b55d1b1e5e1fa Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 3 Apr 2009 20:34:27 +0000 Subject: [PATCH 278/503] Simplified code for empty public timeline. --- actions/public.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/actions/public.php b/actions/public.php index fca90488fe..5a2720a9ad 100644 --- a/actions/public.php +++ b/actions/public.php @@ -168,14 +168,13 @@ class PublicAction extends Action function showPageNotice() { - $notice = Notice::publicStream(0, 1); + $notice = new Notice; if (!$notice) { $this->serverError(_('Could not retrieve public stream.')); return; } - // no notices in the public stream, let's get out of here if ($notice->count()) { return; } From 96982477220316ee7af0326dc6ff42d2438b540e Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 3 Apr 2009 20:35:18 +0000 Subject: [PATCH 279/503] Added filler text to popular page for when it's empty, encouraging user to add favorites and/or register. --- actions/favorited.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/actions/favorited.php b/actions/favorited.php index 231b978973..20a354674f 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -143,6 +143,25 @@ class FavoritedAction extends Action $this->elementStart('div', 'instructions'); $this->raw($output); $this->elementEnd('div'); + + $favorite = new Fave; + + if ($favorite->count()) { + return; + } + + $message = _('Favorite notices appear on this page but noone has favorited one yet.') . ' '; + + if (common_logged_in()) { + $message .= _('Be the first to add a notice to your favorites by clicking the fave button next to any notice you like.'); + } + else { + $message .= _('Why not [register an account](%%action.register%%) and be the first to add a notice to your favorites!'); + } + + $this->elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); } /** From 439d521c86e07fc7bc0c84e62022fc160f8f0fcf Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 3 Apr 2009 20:37:29 +0000 Subject: [PATCH 280/503] Tiny change to the public tag cloud dealing with empty page. --- actions/publictagcloud.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index 5322372b2a..5bc7e0cbff 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -63,7 +63,7 @@ class PublictagcloudAction extends Action sprintf(_('These are most popular recent tags on %s '), common_config('site', 'name'))); - $tags = new Notice_tag(); + $tags = new Notice_tag; if ($tags->count()) { return; } From d83f6c32690b34a4aa283f8665c9fa2c4f7df185 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 3 Apr 2009 14:16:32 -0700 Subject: [PATCH 281/503] Add Yatca to notice sources --- db/notice_source.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/notice_source.sql b/db/notice_source.sql index d28a09383f..5d48e66b62 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -45,4 +45,5 @@ VALUES ('twitux','Twitux','http://live.gnome.org/DanielMorales/Twitux', now()), ('twitvim','TwitVim','http://vim.sourceforge.net/scripts/script.php?script_id=2204', now()), ('urfastr','urfastr','http://urfastr.net/', now()), - ('adium', 'Adium', 'http://www.adiumx.com/', now()); + ('adium', 'Adium', 'http://www.adiumx.com/', now()), + ('yatca','Yatca','http://www.yatca.com/', now()); From 61a08c91d5475a6eaedc56d999a8814b48a0fbb5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 3 Apr 2009 15:59:08 -0700 Subject: [PATCH 282/503] Bumped version number for upcoming 0.7.3 release --- scripts/laconica.spec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/laconica.spec b/scripts/laconica.spec index 0e51237a24..331e10671b 100644 --- a/scripts/laconica.spec +++ b/scripts/laconica.spec @@ -1,5 +1,5 @@ # This version needs to match the tarball and unpacked directory name. -%define LACVER 0.7.2.1 +%define LACVER 0.7.3 BuildRequires: php-pear BuildRequires: httpd-devel @@ -79,15 +79,15 @@ rm -rf %buildroot %config(noreplace) %{_sysconfdir}/httpd/conf.d/laconica.conf %changelog +* Wed Apr 03 2009 Zach Copley - 0.7.3 +- Changed version number to 0.7.3. + * Fri Mar 13 2009 Ken Sedgwick - 0.7.2.1-1 - Factored laconica version to the first line of the file. * Wed Mar 03 2009 Zach Copley - 0.7.2 - Changed version number to 0.7.2. -* Wed Mar 03 2009 Zach Copley - 0.7.2 -- Changed version number to 0.7.2. - * Sat Feb 28 2009 Ken Sedgwick - 0.7.1-1 - Modified RPM for Fedora. From bd52139436ba6e43ead6fd6acff43a90a1224f04 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sun, 5 Apr 2009 00:46:39 +0000 Subject: [PATCH 283/503] bookmarklet inspired by wordpress press this. --- doc-src/bookmarklet | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc-src/bookmarklet diff --git a/doc-src/bookmarklet b/doc-src/bookmarklet new file mode 100644 index 0000000000..03c0e97c9d --- /dev/null +++ b/doc-src/bookmarklet @@ -0,0 +1,8 @@ +A bookmarklet is a small piece of javascript code used as a bookmark. This one will let you post to %%site.name%% simply by selecting some text on a page and pressing the bookmarklet. + +Drag-and-drop the following link to your bookmarks bar or right-click it and add it to your browser favorites to keep it handy. + + +Post to %%site.name%% + + From 1ee24a2aaf6d07f0f6ffd4697da88c43b140bd13 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sun, 5 Apr 2009 23:11:40 +0000 Subject: [PATCH 284/503] added filler text to people search, suggesting other search options. --- actions/peoplesearch.php | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/actions/peoplesearch.php b/actions/peoplesearch.php index 9e515ade1a..6fbb19b882 100644 --- a/actions/peoplesearch.php +++ b/actions/peoplesearch.php @@ -60,14 +60,8 @@ class PeoplesearchAction extends SearchAction function showResults($q, $page) { - $profile = new Profile(); - - // lcase it for comparison - // $q = strtolower($q); - $search_engine = $profile->getSearchEngine('identica_people'); - $search_engine->set_sort_mode('chron'); // Ask for an extra to see if there's more. $search_engine->limit((($page-1)*PROFILES_PER_PAGE), PROFILES_PER_PAGE + 1); @@ -81,14 +75,34 @@ class PeoplesearchAction extends SearchAction $terms = preg_split('/[\s,]+/', $q); $results = new PeopleSearchResults($profile, $terms, $this); $results->show(); - } else { - $this->element('p', 'error', _('No results')); - } - - $profile->free(); - - $this->pagination($page > 1, $cnt > PROFILES_PER_PAGE, + $profile->free(); + $this->pagination($page > 1, $cnt > PROFILES_PER_PAGE, $page, 'peoplesearch', array('q' => $q)); + + } else { + $this->element('p', 'error', _('No results.')); + + $qe = urlencode($q); + $message = _(<<elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + $profile->free(); + } } } From 84d2aa7df49dc85603dd6c2d60c1f605800a458c Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 6 Apr 2009 01:14:59 +0000 Subject: [PATCH 285/503] refactored search suggestions and added forgotten sprintf. --- actions/peoplesearch.php | 21 ++------------------- lib/searchaction.php | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/actions/peoplesearch.php b/actions/peoplesearch.php index 6fbb19b882..3ce719dd55 100644 --- a/actions/peoplesearch.php +++ b/actions/peoplesearch.php @@ -82,25 +82,8 @@ class PeoplesearchAction extends SearchAction } else { $this->element('p', 'error', _('No results.')); - $qe = urlencode($q); - $message = _(<<elementStart('div', 'blankfiller'); - $this->raw(common_markup_to_html($message)); - $this->elementEnd('div'); +//TODO + $this->searchSuggestions($q); $profile->free(); } } diff --git a/lib/searchaction.php b/lib/searchaction.php index c762db16f0..697262ccdb 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -133,5 +133,28 @@ class SearchAction extends Action $this->showResults($q, $page); } } + + function searchSuggestions($q) { + $qe = urlencode($q); + $message = sprintf(_(<<elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } } From 9ad8307b7ee60b3263733b8b8c3d7ac6f350a452 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 6 Apr 2009 05:04:11 +0000 Subject: [PATCH 286/503] external search now depends on site.server. --- actions/peoplesearch.php | 2 -- lib/searchaction.php | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/actions/peoplesearch.php b/actions/peoplesearch.php index 3ce719dd55..65d970dd15 100644 --- a/actions/peoplesearch.php +++ b/actions/peoplesearch.php @@ -81,8 +81,6 @@ class PeoplesearchAction extends SearchAction } else { $this->element('p', 'error', _('No results.')); - -//TODO $this->searchSuggestions($q); $profile->free(); } diff --git a/lib/searchaction.php b/lib/searchaction.php index 697262ccdb..918f8dd9af 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -146,8 +146,8 @@ You can also try your search on other engines: * [Twingly](http://www.twingly.com/search?q=%s&content=microblog&site=identi.ca) * [Tweet scan](http://www.tweetscan.com/indexi.php?s=%s) -* [Google](http://www.google.com/search?q=site%%3Aidenti.ca+%s) -* [Yahoo](http://search.yahoo.com/search?p=site%%3Aidenti.ca+%s) +* [Google](http://www.google.com/search?q=site%%3A%%%%site.server%%%%+%s) +* [Yahoo](http://search.yahoo.com/search?p=site%%3A%%%%site.server%%%%+%s) E_O_T From f09886672bc03220768fd5818a9e74bb60cc3172 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 6 Apr 2009 15:51:57 -0400 Subject: [PATCH 287/503] add peoplebrowsr --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index d28a09383f..18ce1ecbe7 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -21,6 +21,7 @@ VALUES ('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()), ('Mobidentica', 'Mobidentica', 'http://www.substanceofcode.com/software/mobidentica/', now()), ('moconica','Moconica','http://moconica.com/', now()), + ('peoplebrowsr', 'PeopleBrowsr', 'http://www.peoplebrowsr.com/', now()), ('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()), ('posty','Posty','http://spreadingfunkyness.com/posty/', now()), ('royalewithcheese','Royale With Cheese','http://p.hellyeah.org/', now()), From 17fb51f747c023392cd6127abe9b019e693f0544 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 7 Apr 2009 03:26:33 +0000 Subject: [PATCH 288/503] added filler text to notice and group search, suggesting other search options. --- actions/groupsearch.php | 26 ++++++++++++++++---------- actions/noticesearch.php | 21 +++++++++++++-------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/actions/groupsearch.php b/actions/groupsearch.php index 109a53ce11..31c4ffd948 100644 --- a/actions/groupsearch.php +++ b/actions/groupsearch.php @@ -72,12 +72,23 @@ class GroupsearchAction extends SearchAction $terms = preg_split('/[\s,]+/', $q); $results = new GroupSearchResults($user_group, $terms, $this); $results->show(); - } else { - $this->element('p', 'error', _('No results')); - } - $user_group->free(); - $this->pagination($page > 1, $cnt > GROUPS_PER_PAGE, + $user_group->free(); + $this->pagination($page > 1, $cnt > GROUPS_PER_PAGE, $page, 'groupsearch', array('q' => $q)); + } else { + $this->element('p', 'error', _('No results.')); + $this->searchSuggestions($q); + if (common_logged_in()) { + $message = _('If you can\'t find the group you\'re looking for, you can [create it](%%action.newgroup%%) yourself.'); + } + else { + $message = _('Why not [register an account](%%action.register%%) and [create the group](%%action.newgroup%%) yourself!'); + } + $this->elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + $user_group->free(); + } } } @@ -98,10 +109,5 @@ class GroupSearchResults extends GroupList { return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); } - - function isReadOnly() - { - return true; - } } diff --git a/actions/noticesearch.php b/actions/noticesearch.php index 9058cf53c3..a4308450b4 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -114,22 +114,27 @@ class NoticesearchAction extends SearchAction $cnt = $notice->find(); } if ($cnt === 0) { - $this->element('p', 'error', _('No results')); + $this->element('p', 'error', _('No results.')); + + $this->searchSuggestions($q); + if (common_logged_in()) { + $message = sprintf(_('Be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'), urlencode($q)); + } + else { + $message = sprintf(_('Why not [register an account](%%%%action.register%%%%) and be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'), urlencode($q)); + } + + $this->elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); return; } $terms = preg_split('/[\s,]+/', $q); $nl = new SearchNoticeList($notice, $this, $terms); - $cnt = $nl->show(); - $this->pagination($page > 1, $cnt > NOTICES_PER_PAGE, $page, 'noticesearch', array('q' => $q)); } - - function isReadOnly() - { - return true; - } } class SearchNoticeList extends NoticeList { From 4cc6d0ea2c7bec551c7726d7a336afea17d27df8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 7 Apr 2009 11:40:13 -0400 Subject: [PATCH 289/503] make tags in list work --- lib/action.php | 4 ++++ lib/galleryaction.php | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/action.php b/lib/action.php index 5d0d5b7584..bba76d8332 100644 --- a/lib/action.php +++ b/lib/action.php @@ -921,11 +921,15 @@ class Action extends HTMLOutputter // lawsuit * * @return string current URL */ + function selfUrl() { $action = $this->trimmed('action'); $args = $this->args; unset($args['action']); + if (array_key_exists('submit', $args)) { + unset($args['submit']); + } foreach (array_keys($_COOKIE) as $cookie) { unset($args[$cookie]); } diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 25a5e3fd59..8e21d7393b 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -50,7 +50,7 @@ class GalleryAction extends Action if ($this->arg('page') && $this->arg('page') != 1) { $args['page'] = $this->arg['page']; } - common_redirect(common_local_url('subscriptions', $args), 301); + common_redirect(common_local_url($this->trimmed('action'), $args), 301); return false; } @@ -71,6 +71,7 @@ class GalleryAction extends Action $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; $this->tag = $this->trimmed('tag'); + $this->q = $this->trimmed('q'); return true; } @@ -87,7 +88,7 @@ class GalleryAction extends Action # Post from the tag dropdown; redirect to a GET if ($_SERVER['REQUEST_METHOD'] == 'POST') { - common_redirect($this->selfUrl(), 307); + common_redirect($this->selfUrl(), 303); return; } @@ -136,7 +137,7 @@ class GalleryAction extends Action 'method' => 'post')); $this->dropdown('tag', _('Tag'), $content, _('Choose a tag to narrow list'), false, $tag); - $this->submit('go', _('Go')); + $this->submit('submit', _('Go')); $this->elementEnd('form'); $this->elementEnd('li'); $this->elementEnd('ul'); From 640ae109354336a684c9b01e5d842b8aff4e0ea1 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 7 Apr 2009 16:11:03 +0000 Subject: [PATCH 290/503] added filler text to personal timeline. --- actions/all.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/actions/all.php b/actions/all.php index 8e67ec0f3b..5189f31f51 100644 --- a/actions/all.php +++ b/actions/all.php @@ -93,6 +93,32 @@ class AllAction extends Action $nav->show(); } + function showPageNotice() + { + $notice = $this->user->noticesWithFriends(0, 1); + if ($notice->count()) { + return; + } + + $message = sprintf(_('This is the timeline for %s and friends but noone has posted anything yet.'), $this->user->nickname) . ' '; + + if (common_logged_in()) { + $current_user = common_current_user(); + if ($this->user->id === $current_user->id) { + $message .= _('Try subscribing to more people, [join a group](%%action.groups) or post something yourself.'); + } else { + $message .= sprintf(_('You can try to [nudge %s](./) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, '@' . $this->user->nickname); + } + } + else { + $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); + } + + $this->elementStart('div', 'blankfiller'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } + function showContent() { $notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); From 7f5e2c5e57561a90478af1ce62b7a65641125568 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 18:08:56 +0000 Subject: [PATCH 291/503] Added Invite link to global navigation --- lib/action.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/action.php b/lib/action.php index 5d0d5b7584..4ea9ba4655 100644 --- a/lib/action.php +++ b/lib/action.php @@ -416,6 +416,11 @@ class Action extends HTMLOutputter // lawsuit $this->menuItem(common_local_url('smssettings'), _('Connect'), _('Connect to SMS, Twitter'), false, 'nav_connect'); } + $this->menuItem(common_local_url('invite'), + _('Invite'), + sprintf(_('Invite friends and colleagues to join you on %s'), + common_config('site', 'name')), + false, 'nav_invitecontact'); $this->menuItem(common_local_url('logout'), _('Logout'), _('Logout from the site'), false, 'nav_logout'); } else { From ef2d22a84b0b2cd35801bfbf3c9130826fec61bd Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 18:09:54 +0000 Subject: [PATCH 292/503] Rearranged the global navigation items for better usability. Reason a) placement of Search at the edge of the viewport for quicker access and b) placement of the links that are always available (whether user is logged in or not) in the same location (i.e., Login/Logout, Help, Search) --- lib/action.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/action.php b/lib/action.php index 4ea9ba4655..b93d8d21c7 100644 --- a/lib/action.php +++ b/lib/action.php @@ -402,13 +402,8 @@ class Action extends HTMLOutputter // lawsuit if ($user) { $this->menuItem(common_local_url('all', array('nickname' => $user->nickname)), _('Home'), _('Personal profile and friends timeline'), false, 'nav_home'); - } - $this->menuItem(common_local_url('peoplesearch'), - _('Search'), _('Search for people or text'), false, 'nav_search'); - if ($user) { $this->menuItem(common_local_url('profilesettings'), _('Account'), _('Change your email, avatar, password, profile'), false, 'nav_account'); - if (common_config('xmpp', 'enabled')) { $this->menuItem(common_local_url('imsettings'), _('Connect'), _('Connect to IM, SMS, Twitter'), false, 'nav_connect'); @@ -423,18 +418,21 @@ class Action extends HTMLOutputter // lawsuit false, 'nav_invitecontact'); $this->menuItem(common_local_url('logout'), _('Logout'), _('Logout from the site'), false, 'nav_logout'); - } else { - $this->menuItem(common_local_url('login'), - _('Login'), _('Login to the site'), false, 'nav_login'); + } + else { if (!common_config('site', 'closed')) { $this->menuItem(common_local_url('register'), _('Register'), _('Create an account'), false, 'nav_register'); } $this->menuItem(common_local_url('openidlogin'), _('OpenID'), _('Login with OpenID'), false, 'nav_openid'); + $this->menuItem(common_local_url('login'), + _('Login'), _('Login to the site'), false, 'nav_login'); } $this->menuItem(common_local_url('doc', array('title' => 'help')), _('Help'), _('Help me!'), false, 'nav_help'); + $this->menuItem(common_local_url('peoplesearch'), + _('Search'), _('Search for people or text'), false, 'nav_search'); Event::handle('EndPrimaryNav', array($this)); } $this->elementEnd('ul'); From 27a279e7c1185028783f8ed7afe02779e89fa34a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 18:16:16 +0000 Subject: [PATCH 293/503] Down playing the Register link's styles so it doesn't battle for attention when anon_notice is present. --- theme/default/css/display.css | 9 --------- theme/identica/css/display.css | 8 -------- 2 files changed, 17 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index bf46fc6bfd..e240f255fe 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -37,7 +37,6 @@ background:none; input.submit, #form_notice.warning #notice_text-count, -#nav_register a, .form_settings .form_note, .entity_remote_subscribe { background-color:#A9BF4F; @@ -48,7 +47,6 @@ input:focus, textarea:focus, select:focus, border-color:#A9BF4F; } input.submit, -#nav_register a, .entity_remote_subscribe { color:#fff; } @@ -97,13 +95,6 @@ cursor:wait; text-indent:-9999px; } - -#nav_register a { -text-decoration:none; -font-weight:bold; -padding:2px 4px; -} - #content, #site_nav_local_views a, #aside_primary { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 9e7c10ac5a..893942031c 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -37,7 +37,6 @@ background:none; input.submit, #form_notice.warning #notice_text-count, -#nav_register a, .form_settings .form_note, .entity_remote_subscribe { background-color:#9BB43E; @@ -48,7 +47,6 @@ input:focus, textarea:focus, select:focus, border-color:#9BB43E; } input.submit, -#nav_register a, .entity_remote_subscribe { color:#fff; } @@ -97,12 +95,6 @@ cursor:wait; text-indent:-9999px; } -#nav_register a { -text-decoration:none; -font-weight:bold; -padding:2px 4px; -} - #content, #site_nav_local_views a, #aside_primary { From c42995e3a2d4bd93881ffd5d3bfea4f6ce427d0a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 20:02:42 +0000 Subject: [PATCH 294/503] Minimum height for content and aside area. --- theme/base/css/display.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 4c9b522549..0ce80cdde4 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -384,6 +384,7 @@ margin-bottom:1em; #content { width:64.009%; +min-height:259px; padding:1.795%; float:left; border-radius:7px; @@ -403,6 +404,7 @@ float:left; #aside_primary { width:27.917%; +min-height:259px; float:left; margin-left:0.395%; padding:1.795%; From 658462ce855e5ce4325c1b7233dc83b10b14cced Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 21:02:47 +0000 Subject: [PATCH 295/503] Markup and styles for search help and errors --- lib/searchaction.php | 5 ++++- theme/base/css/display.css | 16 +++++++++++++--- theme/identica/css/display.css | 4 ++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/searchaction.php b/lib/searchaction.php index 918f8dd9af..e7ad4affda 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -152,8 +152,11 @@ You can also try your search on other engines: E_O_T ), $qe, $qe, $qe, $qe); - $this->elementStart('div', 'blankfiller'); + $this->elementStart('dl', array('id' => 'help_search', 'class' => 'help')); + $this->element('dt', null, _('Search help')); + $this->elementStart('dd', 'instructions'); $this->raw(common_markup_to_html($message)); + $this->elementEnd('dd'); $this->elementEnd('div'); } } diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 0ce80cdde4..6c3c7e9127 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -83,12 +83,13 @@ left:0; border:0; } -#page_notice .error, -#page_notice .success { +.error, +.success { padding:4px 7px; border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; +margin-bottom:18px; } form label.submit { display:none; @@ -1145,4 +1146,13 @@ clear:both; margin-bottom:0; } - +.instructions ul { +list-style-position:inside; +} +.instructions p, +.instructions ul { +margin-bottom:18px; +} +.help dt { +display:none; +} diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 893942031c..8edb005a68 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -113,10 +113,10 @@ background-color:rgba(255, 255, 255, 0.7); } -#page_notice .error { +.error { background-color:#F7E8E8; } -#page_notice .success { +.success { background-color:#EFF3DC; } From 5dfc09d9d265d1e2e918f9dd615f89909c6c4e74 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 21:04:24 +0000 Subject: [PATCH 296/503] Minor adjustment for error/success styles in default stylesheet --- theme/default/css/display.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index e240f255fe..42e29374f1 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -113,10 +113,10 @@ background-color:rgba(255, 255, 255, 0.7); } -#page_notice .error { +.error { background-color:#F7E8E8; } -#page_notice .success { +.success { background-color:#EFF3DC; } From a6e950b7a1ca7654613dd7f5cefcdae6a3a0f579 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 21:09:27 +0000 Subject: [PATCH 297/503] Renamed 'blankfiller' to 'guide'. --- actions/all.php | 2 +- actions/favorited.php | 2 +- actions/groupsearch.php | 2 +- actions/noticesearch.php | 2 +- actions/public.php | 2 +- actions/publictagcloud.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/actions/all.php b/actions/all.php index 5189f31f51..9c6182ccc7 100644 --- a/actions/all.php +++ b/actions/all.php @@ -114,7 +114,7 @@ class AllAction extends Action $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); } - $this->elementStart('div', 'blankfiller'); + $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } diff --git a/actions/favorited.php b/actions/favorited.php index 20a354674f..6935eda23a 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -159,7 +159,7 @@ class FavoritedAction extends Action $message .= _('Why not [register an account](%%action.register%%) and be the first to add a notice to your favorites!'); } - $this->elementStart('div', 'blankfiller'); + $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } diff --git a/actions/groupsearch.php b/actions/groupsearch.php index 31c4ffd948..06b4a77550 100644 --- a/actions/groupsearch.php +++ b/actions/groupsearch.php @@ -84,7 +84,7 @@ class GroupsearchAction extends SearchAction else { $message = _('Why not [register an account](%%action.register%%) and [create the group](%%action.newgroup%%) yourself!'); } - $this->elementStart('div', 'blankfiller'); + $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); $user_group->free(); diff --git a/actions/noticesearch.php b/actions/noticesearch.php index a4308450b4..095d0a454a 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -124,7 +124,7 @@ class NoticesearchAction extends SearchAction $message = sprintf(_('Why not [register an account](%%%%action.register%%%%) and be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'), urlencode($q)); } - $this->elementStart('div', 'blankfiller'); + $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); return; diff --git a/actions/public.php b/actions/public.php index 5a2720a9ad..d64b651fdb 100644 --- a/actions/public.php +++ b/actions/public.php @@ -188,7 +188,7 @@ class PublicAction extends Action $message .= _('Why not [register an account](%%action.register%%) and be the first to post!'); } - $this->elementStart('div', 'blankfiller'); + $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index 5bc7e0cbff..4ff41d2a6d 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -77,7 +77,7 @@ class PublictagcloudAction extends Action $message .= _('Why not [register an account](%%action.register%%) and be the first to post one!'); } - $this->elementStart('div', 'blankfiller'); + $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } From 60861760fc3bdc1cdea407e8ee21eb8c54e77b8f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 7 Apr 2009 17:10:54 -0400 Subject: [PATCH 298/503] Host multiple sites with the same codebase This is the beginning of the code for status.net and related status farms. It will read basic information about a site from a shared, central database and use the data stored there to switch on the hostname. --- classes/Status_network.php | 61 ++++++++++++++++++++++++++++++++++++++ classes/statusnet.ini | 17 +++++++++++ config.php.sample | 8 +++++ db/site.sql | 17 +++++++++++ 4 files changed, 103 insertions(+) create mode 100755 classes/Status_network.php create mode 100755 classes/statusnet.ini create mode 100644 db/site.sql diff --git a/classes/Status_network.php b/classes/Status_network.php new file mode 100755 index 0000000000..f7747f71d7 --- /dev/null +++ b/classes/Status_network.php @@ -0,0 +1,61 @@ +dbhost)) ? 'localhost' : $sn->dbhost; + $dbuser = (empty($sn->dbuser)) ? $sn->nickname : $sn->dbuser; + $dbpass = $sn->dbpass; + $dbname = (empty($sn->dbname)) ? $sn->nickname : $sn->dbname; + + $config['db']['database'] = "mysqli://$dbuser:$dbpass@$dbhost/$dbname"; + $config['site']['name'] = $sn->sitename; + return true; + } else { + return false; + } + } +} diff --git a/classes/statusnet.ini b/classes/statusnet.ini new file mode 100755 index 0000000000..a70cd41228 --- /dev/null +++ b/classes/statusnet.ini @@ -0,0 +1,17 @@ + +[status_network] +nickname = 130 +hostname = 2 +pathname = 2 +sitename = 2 +dbhost = 2 +dbuser = 2 +dbpass = 2 +dbname = 2 +created = 142 +modified = 384 + +[status_network__keys] +nickname = K +hostname = U +pathname = U diff --git a/config.php.sample b/config.php.sample index 59e0cc7126..eec2bb2c5d 100644 --- a/config.php.sample +++ b/config.php.sample @@ -192,3 +192,11 @@ $config['sphinx']['port'] = 3312; #Use a different hostname for SSL-encrypted pages #$config['site']['sslserver'] = 'secure.example.org'; + +#If you have a lot of status networks on the same server, you can +#store the site data in a database and switch as follows +#Status_network::setupDB('localhost', 'statusnet', 'statuspass', 'statusnet'); +#if (!Status_network::setupSite($_server, $_path)) { +# print "Error\n"; +# exit(1); +#} diff --git a/db/site.sql b/db/site.sql new file mode 100644 index 0000000000..660ba475bb --- /dev/null +++ b/db/site.sql @@ -0,0 +1,17 @@ +/* For managing multiple sites */ + +create table status_network ( + + nickname varchar(64) primary key comment 'nickname', + hostname varchar(255) unique key comment 'alternate hostname if any', + pathname varchar(255) unique key comment 'alternate pathname if any', + sitename varchar(255) comment 'display name', + dbhost varchar(255) comment 'database host', + dbuser varchar(255) comment 'database username', + dbpass varchar(255) comment 'database password', + dbname varchar(255) comment 'database name', + + created datetime not null comment 'date this record was created', + modified timestamp comment 'date this record was modified' + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; From 05b04b7970d1b0f1e35a64a5537ad61e2fb8db1c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 21:12:11 +0000 Subject: [PATCH 299/503] Changed text "noone" to "no one". --- actions/all.php | 2 +- actions/favorited.php | 2 +- actions/public.php | 2 +- actions/publictagcloud.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/all.php b/actions/all.php index 9c6182ccc7..9a16326704 100644 --- a/actions/all.php +++ b/actions/all.php @@ -100,7 +100,7 @@ class AllAction extends Action return; } - $message = sprintf(_('This is the timeline for %s and friends but noone has posted anything yet.'), $this->user->nickname) . ' '; + $message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->user->nickname) . ' '; if (common_logged_in()) { $current_user = common_current_user(); diff --git a/actions/favorited.php b/actions/favorited.php index 6935eda23a..27da25435b 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -150,7 +150,7 @@ class FavoritedAction extends Action return; } - $message = _('Favorite notices appear on this page but noone has favorited one yet.') . ' '; + $message = _('Favorite notices appear on this page but no one has favorited one yet.') . ' '; if (common_logged_in()) { $message .= _('Be the first to add a notice to your favorites by clicking the fave button next to any notice you like.'); diff --git a/actions/public.php b/actions/public.php index d64b651fdb..b7b7fc6b76 100644 --- a/actions/public.php +++ b/actions/public.php @@ -179,7 +179,7 @@ class PublicAction extends Action return; } - $message = _('This is the public timeline for %%site.name%% but noone has posted anything yet.') . ' '; + $message = _('This is the public timeline for %%site.name%% but no one has posted anything yet.') . ' '; if (common_logged_in()) { $message .= _('Be the first to post!'); diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index 4ff41d2a6d..0cd8940d4d 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -68,7 +68,7 @@ class PublictagcloudAction extends Action return; } - $message = _('Noone has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' '; + $message = _('No one has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' '; if (common_logged_in()) { $message .= _('Be the first to post one!'); From 50b32227d1c4bb6fa5c6f81077ddd4a21981e639 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 7 Apr 2009 17:47:08 -0400 Subject: [PATCH 300/503] Add subscribers, subscriptions, groups to personal page We show stats, subscriptions info on the personal page in the sidebar. Pushed code from showstream.php into a common parent class for personal and profile. --- actions/all.php | 20 +--- actions/showstream.php | 201 ++-------------------------------- lib/profileaction.php | 242 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+), 213 deletions(-) create mode 100644 lib/profileaction.php diff --git a/actions/all.php b/actions/all.php index 9a16326704..d457378dd7 100644 --- a/actions/all.php +++ b/actions/all.php @@ -23,31 +23,13 @@ require_once INSTALLDIR.'/lib/personalgroupnav.php'; require_once INSTALLDIR.'/lib/noticelist.php'; require_once INSTALLDIR.'/lib/feedlist.php'; -class AllAction extends Action +class AllAction extends ProfileAction { - var $user = null; - var $page = null; - function isReadOnly() { return true; } - function prepare($args) - { - parent::prepare($args); - $nickname = common_canonical_nickname($this->arg('nickname')); - $this->user = User::staticGet('nickname', $nickname); - $this->page = $this->trimmed('page'); - if (!$this->page) { - $this->page = 1; - } - - common_set_returnto($this->selfUrl()); - - return true; - } - function handle($args) { parent::handle($args); diff --git a/actions/showstream.php b/actions/showstream.php index f5886f3d33..3c6c060702 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -54,12 +54,8 @@ require_once INSTALLDIR.'/lib/feedlist.php'; * @link http://laconi.ca/ */ -class ShowstreamAction extends Action +class ShowstreamAction extends ProfileAction { - var $user = null; - var $page = null; - var $profile = null; - function isReadOnly() { return true; @@ -82,45 +78,6 @@ class ShowstreamAction extends Action } } - function prepare($args) - { - parent::prepare($args); - - $nickname_arg = $this->arg('nickname'); - $nickname = common_canonical_nickname($nickname_arg); - - // Permanent redirect on non-canonical nickname - - if ($nickname_arg != $nickname) { - $args = array('nickname' => $nickname); - if ($this->arg('page') && $this->arg('page') != 1) { - $args['page'] = $this->arg['page']; - } - common_redirect(common_local_url('showstream', $args), 301); - return false; - } - - $this->user = User::staticGet('nickname', $nickname); - - if (!$this->user) { - $this->clientError(_('No such user.'), 404); - return false; - } - - $this->profile = $this->user->getProfile(); - - if (!$this->profile) { - $this->serverError(_('User has no profile.')); - return false; - } - - $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; - - common_set_returnto($this->selfUrl()); - - return true; - } - function handle($args) { @@ -383,156 +340,6 @@ class ShowstreamAction extends Action 'showstream', array('nickname' => $this->user->nickname)); } - function showSections() - { - $this->showSubscriptions(); - $this->showSubscribers(); - $this->showGroups(); - $this->showStatistics(); - $cloud = new PersonalTagCloudSection($this, $this->user); - $cloud->show(); - } - - function showSubscriptions() - { - $profile = $this->user->getSubscriptions(0, PROFILES_PER_MINILIST + 1); - - $this->elementStart('div', array('id' => 'entity_subscriptions', - 'class' => 'section')); - - $this->element('h2', null, _('Subscriptions')); - - if ($profile) { - $pml = new ProfileMiniList($profile, $this->user, $this); - $cnt = $pml->show(); - if ($cnt == 0) { - $this->element('p', null, _('(None)')); - } - } - - if ($cnt > PROFILES_PER_MINILIST) { - $this->elementStart('p'); - $this->element('a', array('href' => common_local_url('subscriptions', - array('nickname' => $this->profile->nickname)), - 'class' => 'more'), - _('All subscriptions')); - $this->elementEnd('p'); - } - - $this->elementEnd('div'); - } - - function showSubscribers() - { - $profile = $this->user->getSubscribers(0, PROFILES_PER_MINILIST + 1); - - $this->elementStart('div', array('id' => 'entity_subscribers', - 'class' => 'section')); - - $this->element('h2', null, _('Subscribers')); - - if ($profile) { - $pml = new ProfileMiniList($profile, $this->user, $this); - $cnt = $pml->show(); - if ($cnt == 0) { - $this->element('p', null, _('(None)')); - } - } - - if ($cnt > PROFILES_PER_MINILIST) { - $this->elementStart('p'); - $this->element('a', array('href' => common_local_url('subscribers', - array('nickname' => $this->profile->nickname)), - 'class' => 'more'), - _('All subscribers')); - $this->elementEnd('p'); - } - - $this->elementEnd('div'); - } - - function showStatistics() - { - // XXX: WORM cache this - $subs = new Subscription(); - $subs->subscriber = $this->profile->id; - $subs_count = (int) $subs->count() - 1; - - $subbed = new Subscription(); - $subbed->subscribed = $this->profile->id; - $subbed_count = (int) $subbed->count() - 1; - - $notices = new Notice(); - $notices->profile_id = $this->profile->id; - $notice_count = (int) $notices->count(); - - $this->elementStart('div', array('id' => 'entity_statistics', - 'class' => 'section')); - - $this->element('h2', null, _('Statistics')); - - // Other stats...? - $this->elementStart('dl', 'entity_member-since'); - $this->element('dt', null, _('Member since')); - $this->element('dd', null, date('j M Y', - strtotime($this->profile->created))); - $this->elementEnd('dl'); - - $this->elementStart('dl', 'entity_subscriptions'); - $this->elementStart('dt'); - $this->element('a', array('href' => common_local_url('subscriptions', - array('nickname' => $this->profile->nickname))), - _('Subscriptions')); - $this->elementEnd('dt'); - $this->element('dd', null, (is_int($subs_count)) ? $subs_count : '0'); - $this->elementEnd('dl'); - - $this->elementStart('dl', 'entity_subscribers'); - $this->elementStart('dt'); - $this->element('a', array('href' => common_local_url('subscribers', - array('nickname' => $this->profile->nickname))), - _('Subscribers')); - $this->elementEnd('dt'); - $this->element('dd', 'subscribers', (is_int($subbed_count)) ? $subbed_count : '0'); - $this->elementEnd('dl'); - - $this->elementStart('dl', 'entity_notices'); - $this->element('dt', null, _('Notices')); - $this->element('dd', null, (is_int($notice_count)) ? $notice_count : '0'); - $this->elementEnd('dl'); - - $this->elementEnd('div'); - } - - function showGroups() - { - $groups = $this->user->getGroups(0, GROUPS_PER_MINILIST + 1); - - $this->elementStart('div', array('id' => 'entity_groups', - 'class' => 'section')); - - $this->element('h2', null, _('Groups')); - - if ($groups) { - $gml = new GroupMiniList($groups, $this->user, $this); - $cnt = $gml->show(); - if ($cnt == 0) { - $this->element('p', null, _('(None)')); - } - } - - if ($cnt > GROUPS_PER_MINILIST) { - $this->elementStart('p'); - $this->element('a', array('href' => common_local_url('usergroups', - array('nickname' => $this->profile->nickname)), - 'class' => 'more'), - _('All groups')); - $this->elementEnd('p'); - } - - $this->elementEnd('div'); - } - function showAnonymousMessage() { if (!(common_config('site','closed') || common_config('site','inviteonly'))) { @@ -550,6 +357,12 @@ class ShowstreamAction extends Action $this->elementEnd('div'); } + function showSections() + { + parent::showSections(); + $cloud = new PersonalTagCloudSection($this, $this->user); + $cloud->show(); + } } // We don't show the author for a profile, since we already know who it is! diff --git a/lib/profileaction.php b/lib/profileaction.php new file mode 100644 index 0000000000..c81924e316 --- /dev/null +++ b/lib/profileaction.php @@ -0,0 +1,242 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @author Sarven Capadisli + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/profileminilist.php'; +require_once INSTALLDIR.'/lib/groupminilist.php'; + +/** + * Profile action common superclass + * + * Abstracts out common code from profile and personal tabs + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class ProfileAction extends Action +{ + var $user = null; + var $page = null; + var $profile = null; + + function prepare($args) + { + parent::prepare($args); + + $nickname_arg = $this->arg('nickname'); + $nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $nickname) { + $args = array('nickname' => $nickname); + if ($this->arg('page') && $this->arg('page') != 1) { + $args['page'] = $this->arg['page']; + } + common_redirect(common_local_url($this->trimmed('action'), $args), 301); + return false; + } + + $this->user = User::staticGet('nickname', $nickname); + + if (!$this->user) { + $this->clientError(_('No such user.'), 404); + return false; + } + + $this->profile = $this->user->getProfile(); + + if (!$this->profile) { + $this->serverError(_('User has no profile.')); + return false; + } + + $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; + + common_set_returnto($this->selfUrl()); + + return true; + } + + function showSections() + { + $this->showSubscriptions(); + $this->showSubscribers(); + $this->showGroups(); + $this->showStatistics(); + } + + function showSubscriptions() + { + $profile = $this->user->getSubscriptions(0, PROFILES_PER_MINILIST + 1); + + $this->elementStart('div', array('id' => 'entity_subscriptions', + 'class' => 'section')); + + $this->element('h2', null, _('Subscriptions')); + + if ($profile) { + $pml = new ProfileMiniList($profile, $this->user, $this); + $cnt = $pml->show(); + if ($cnt == 0) { + $this->element('p', null, _('(None)')); + } + } + + if ($cnt > PROFILES_PER_MINILIST) { + $this->elementStart('p'); + $this->element('a', array('href' => common_local_url('subscriptions', + array('nickname' => $this->profile->nickname)), + 'class' => 'more'), + _('All subscriptions')); + $this->elementEnd('p'); + } + + $this->elementEnd('div'); + } + + function showSubscribers() + { + $profile = $this->user->getSubscribers(0, PROFILES_PER_MINILIST + 1); + + $this->elementStart('div', array('id' => 'entity_subscribers', + 'class' => 'section')); + + $this->element('h2', null, _('Subscribers')); + + if ($profile) { + $pml = new ProfileMiniList($profile, $this->user, $this); + $cnt = $pml->show(); + if ($cnt == 0) { + $this->element('p', null, _('(None)')); + } + } + + if ($cnt > PROFILES_PER_MINILIST) { + $this->elementStart('p'); + $this->element('a', array('href' => common_local_url('subscribers', + array('nickname' => $this->profile->nickname)), + 'class' => 'more'), + _('All subscribers')); + $this->elementEnd('p'); + } + + $this->elementEnd('div'); + } + + function showStatistics() + { + // XXX: WORM cache this + $subs = new Subscription(); + $subs->subscriber = $this->profile->id; + $subs_count = (int) $subs->count() - 1; + + $subbed = new Subscription(); + $subbed->subscribed = $this->profile->id; + $subbed_count = (int) $subbed->count() - 1; + + $notices = new Notice(); + $notices->profile_id = $this->profile->id; + $notice_count = (int) $notices->count(); + + $this->elementStart('div', array('id' => 'entity_statistics', + 'class' => 'section')); + + $this->element('h2', null, _('Statistics')); + + // Other stats...? + $this->elementStart('dl', 'entity_member-since'); + $this->element('dt', null, _('Member since')); + $this->element('dd', null, date('j M Y', + strtotime($this->profile->created))); + $this->elementEnd('dl'); + + $this->elementStart('dl', 'entity_subscriptions'); + $this->elementStart('dt'); + $this->element('a', array('href' => common_local_url('subscriptions', + array('nickname' => $this->profile->nickname))), + _('Subscriptions')); + $this->elementEnd('dt'); + $this->element('dd', null, (is_int($subs_count)) ? $subs_count : '0'); + $this->elementEnd('dl'); + + $this->elementStart('dl', 'entity_subscribers'); + $this->elementStart('dt'); + $this->element('a', array('href' => common_local_url('subscribers', + array('nickname' => $this->profile->nickname))), + _('Subscribers')); + $this->elementEnd('dt'); + $this->element('dd', 'subscribers', (is_int($subbed_count)) ? $subbed_count : '0'); + $this->elementEnd('dl'); + + $this->elementStart('dl', 'entity_notices'); + $this->element('dt', null, _('Notices')); + $this->element('dd', null, (is_int($notice_count)) ? $notice_count : '0'); + $this->elementEnd('dl'); + + $this->elementEnd('div'); + } + + function showGroups() + { + $groups = $this->user->getGroups(0, GROUPS_PER_MINILIST + 1); + + $this->elementStart('div', array('id' => 'entity_groups', + 'class' => 'section')); + + $this->element('h2', null, _('Groups')); + + if ($groups) { + $gml = new GroupMiniList($groups, $this->user, $this); + $cnt = $gml->show(); + if ($cnt == 0) { + $this->element('p', null, _('(None)')); + } + } + + if ($cnt > GROUPS_PER_MINILIST) { + $this->elementStart('p'); + $this->element('a', array('href' => common_local_url('usergroups', + array('nickname' => $this->profile->nickname)), + 'class' => 'more'), + _('All groups')); + $this->elementEnd('p'); + } + + $this->elementEnd('div'); + } +} \ No newline at end of file From c79bad0601512191f9b7523cea6a222444cb92d0 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 7 Apr 2009 22:16:09 +0000 Subject: [PATCH 301/503] fixed filler/guide text on personal timeline to take memcached into account. --- actions/all.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/actions/all.php b/actions/all.php index d457378dd7..dc5da3e005 100644 --- a/actions/all.php +++ b/actions/all.php @@ -75,13 +75,8 @@ class AllAction extends ProfileAction $nav->show(); } - function showPageNotice() + function showEmptyListMessage() { - $notice = $this->user->noticesWithFriends(0, 1); - if ($notice->count()) { - return; - } - $message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->user->nickname) . ' '; if (common_logged_in()) { @@ -109,6 +104,10 @@ class AllAction extends ProfileAction $cnt = $nl->show(); + if (0 == $cnt) { + $this->showEmptyListMessage(); + } + $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'all', array('nickname' => $this->user->nickname)); } From d704b3fa8ed8731251ff27919d447c8bd382383d Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 7 Apr 2009 23:14:02 +0000 Subject: [PATCH 302/503] added filler/guide text to user timeline. --- actions/showstream.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/actions/showstream.php b/actions/showstream.php index 3c6c060702..cb40d1302d 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -329,12 +329,37 @@ class ShowstreamAction extends ProfileAction _('Subscribe')); } + function showEmptyListMessage() + { + $message = sprintf(_('This is the timeline for %s but %s hasn\'t posted anything yet.'), $this->user->nickname, $this->user->nickname) . ' '; + + if (common_logged_in()) { + $current_user = common_current_user(); + if ($this->user->id === $current_user->id) { + $message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)'); + } else { + $message .= sprintf(_('You can try to nudge %s or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, '@' . $this->user->nickname); + } + } + else { + $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); + } + + $this->element('br', array('clear' => 'both')); + $this->elementStart('div', 'guide'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } + function showNotices() { $notice = $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); $pnl = new ProfileNoticeList($notice, $this); $cnt = $pnl->show(); + if (0 == $cnt) { + $this->showemptyListMessage(); + } $this->pagination($this->page>1, $cnt>NOTICES_PER_PAGE, $this->page, 'showstream', array('nickname' => $this->user->nickname)); From 79b1e3a488372065590700491320b9d3b0c74de4 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 7 Apr 2009 23:25:12 +0000 Subject: [PATCH 303/503] added filler/guide text to user replies timeline. --- actions/all.php | 2 +- actions/replies.php | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/actions/all.php b/actions/all.php index dc5da3e005..f5bbfe2e39 100644 --- a/actions/all.php +++ b/actions/all.php @@ -84,7 +84,7 @@ class AllAction extends ProfileAction if ($this->user->id === $current_user->id) { $message .= _('Try subscribing to more people, [join a group](%%action.groups) or post something yourself.'); } else { - $message .= sprintf(_('You can try to [nudge %s](./) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, '@' . $this->user->nickname); + $message .= sprintf(_('You can try to [nudge %s](../%s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); } } else { diff --git a/actions/replies.php b/actions/replies.php index 4ab9b14ed2..2769cb4227 100644 --- a/actions/replies.php +++ b/actions/replies.php @@ -166,12 +166,36 @@ class RepliesAction extends Action $nl = new NoticeList($notice, $this); $cnt = $nl->show(); + if (0 === $cnt) { + $this->showEmptyListMessage(); + } $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'replies', array('nickname' => $this->user->nickname)); } + function showEmptyListMessage() + { + $message = sprintf(_('This is the timeline showing replies to %s but %s hasn\'t received a notice to his attention yet.'), $this->user->nickname, $this->user->nickname) . ' '; + + if (common_logged_in()) { + $current_user = common_current_user(); + if ($this->user->id === $current_user->id) { + $message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).'); + } else { + $message .= sprintf(_('You can try to [nudge %s](../%s) or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); + } + } + else { + $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); + } + + $this->elementStart('div', 'guide'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } + function isReadOnly() { return true; From a839daad2ecbf8430f518e8690cc509885973e82 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 23:45:22 +0000 Subject: [PATCH 304/503] HTML br is not needed. Using 'clear' in CSS instead. --- actions/showstream.php | 1 - theme/base/css/display.css | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actions/showstream.php b/actions/showstream.php index cb40d1302d..4181a2bab9 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -345,7 +345,6 @@ class ShowstreamAction extends ProfileAction $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); } - $this->element('br', array('clear' => 'both')); $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 6c3c7e9127..dfac7712a4 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1156,3 +1156,6 @@ margin-bottom:18px; .help dt { display:none; } +.guide { +clear:both; +} From cc50031658f1665d60efdf8e3e5963e01584baf9 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 00:15:05 +0000 Subject: [PATCH 305/503] added filler/guide text to user favorites. --- actions/showfavorites.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/actions/showfavorites.php b/actions/showfavorites.php index d1c9283f0f..035b899d27 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -162,6 +162,25 @@ class ShowfavoritesAction extends Action $nav->show(); } + function showEmptyListMessage() + { + if (common_logged_in()) { + $current_user = common_current_user(); + if ($this->user->id === $current_user->id) { + $message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.'); + } else { + $message = sprintf(_('%s hasn\'t any notices to his favorites yet. Post something interesting they would add to their favorites :)'), $this->user->nickname); + } + } + else { + $message = sprintf(_('%s hasn\'t any notices to his favorites yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to thier favorites :)'), $this->user->nickname); + } + + $this->elementStart('div', 'guide'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } + /** * Show the content * @@ -183,9 +202,17 @@ class ShowfavoritesAction extends Action $nl = new NoticeList($notice, $this); $cnt = $nl->show(); + if (0 == $cnt) { + $this->showemptyListMessage(); + } $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'showfavorites', array('nickname' => $this->user->nickname)); } + + function showPageNotice() { + $this->element('p', 'instructions', _('This is a way to share what you like.')); + } } + From b20815e8e2d6d170fecc7143656b22bc68de3780 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 00:16:53 +0000 Subject: [PATCH 306/503] added missing word to user favorites guide. --- actions/showfavorites.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/showfavorites.php b/actions/showfavorites.php index 035b899d27..c4c91058f9 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -169,11 +169,11 @@ class ShowfavoritesAction extends Action if ($this->user->id === $current_user->id) { $message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.'); } else { - $message = sprintf(_('%s hasn\'t any notices to his favorites yet. Post something interesting they would add to their favorites :)'), $this->user->nickname); + $message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Post something interesting they would add to their favorites :)'), $this->user->nickname); } } else { - $message = sprintf(_('%s hasn\'t any notices to his favorites yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to thier favorites :)'), $this->user->nickname); + $message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to thier favorites :)'), $this->user->nickname); } $this->elementStart('div', 'guide'); From 1371a142b193673a9b3d0fc4766249215ae94992 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 00:27:12 +0000 Subject: [PATCH 307/503] added filler/guide text to inbox and outbox. --- lib/mailbox.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/mailbox.php b/lib/mailbox.php index d77234549a..01bbf5721a 100644 --- a/lib/mailbox.php +++ b/lib/mailbox.php @@ -137,6 +137,9 @@ class MailboxAction extends PersonalAction $message->free(); unset($message); } + else { + $this->element('p', 'guide', _('You have no private messages. You can send private message to engage other users in conversation. People can send you messages for your eyes only.')); + } } function getMessages() From 68ed6be71f24f5b434dfe8a5d3f28543d6bd2644 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 01:05:17 +0000 Subject: [PATCH 308/503] added filler/guide text to subscription list. --- actions/subscriptions.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/actions/subscriptions.php b/actions/subscriptions.php index 3fbea2039d..878fd0cd27 100644 --- a/actions/subscriptions.php +++ b/actions/subscriptions.php @@ -95,6 +95,9 @@ class SubscriptionsAction extends GalleryAction if ($subscriptions) { $subscriptions_list = new SubscriptionsList($subscriptions, $this->user, $this); $cnt = $subscriptions_list->show(); + if (0 == $cnt) { + $this->showEmptyListMessage(); + } } $subscriptions->free(); @@ -103,6 +106,25 @@ class SubscriptionsAction extends GalleryAction $this->page, 'subscriptions', array('nickname' => $this->user->nickname)); } + + function showEmptyListMessage() + { + if (common_logged_in()) { + $current_user = common_current_user(); + if ($this->user->id === $current_user->id) { + $message = _('You\'re not listening to anyone\'s notices right now, try subscribing to people you know. Try [people search](%%action.peoplesearch%%), look for members in groups you\'re interested in and in our [featured users](%%action.featured%%). If you\'re a [Twitter user](%%action.twittersettings%%), you can automatically subscribe to people you already follow there.'); + } else { + $message = sprintf(_('%s is not listening to anyone.'), $this->profile->nickname); + } + } + else { + $message = sprintf(_('%s is not listening to anyone.'), $this->profile->fullname); + } + + $this->elementStart('div', 'guide'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } } class SubscriptionsList extends ProfileList From 3fb6c8218a1c8dc2078bf244bcc937e36f1e0e0e Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 01:12:43 +0000 Subject: [PATCH 309/503] added filler/guide text to subscribers list. --- actions/subscribers.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/actions/subscribers.php b/actions/subscribers.php index 22faafaef9..7ebb54d33d 100644 --- a/actions/subscribers.php +++ b/actions/subscribers.php @@ -88,6 +88,9 @@ class SubscribersAction extends GalleryAction if ($subscribers) { $subscribers_list = new SubscribersList($subscribers, $this->user, $this); $cnt = $subscribers_list->show(); + if (0 == $cnt) { + $this->showEmptyListMessage(); + } } $subscribers->free(); @@ -96,6 +99,25 @@ class SubscribersAction extends GalleryAction $this->page, 'subscribers', array('nickname' => $this->user->nickname)); } + + function showEmptyListMessage() + { + if (common_logged_in()) { + $current_user = common_current_user(); + if ($this->user->id === $current_user->id) { + $message = _('You have no subscribers. Try subscribing to people you know and they might return the favor'); + } else { + $message = sprintf(_('%s has no subscribers. Want to be the first?'), $this->user->nickname); + } + } + else { + $message = sprintf(_('%s has no subscribers. Why not [register an account](%%%%action.register%%%%) and be the first?'), $this->user->nickname); + } + + $this->elementStart('div', 'guide'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } } class SubscribersList extends ProfileList From ddb59f72db7f3c6393c0fb245631117e29f093a8 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 01:13:37 +0000 Subject: [PATCH 310/503] text bugfix to guide text in subscription list. --- actions/subscriptions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/subscriptions.php b/actions/subscriptions.php index 878fd0cd27..b0c0a9b8df 100644 --- a/actions/subscriptions.php +++ b/actions/subscriptions.php @@ -114,11 +114,11 @@ class SubscriptionsAction extends GalleryAction if ($this->user->id === $current_user->id) { $message = _('You\'re not listening to anyone\'s notices right now, try subscribing to people you know. Try [people search](%%action.peoplesearch%%), look for members in groups you\'re interested in and in our [featured users](%%action.featured%%). If you\'re a [Twitter user](%%action.twittersettings%%), you can automatically subscribe to people you already follow there.'); } else { - $message = sprintf(_('%s is not listening to anyone.'), $this->profile->nickname); + $message = sprintf(_('%s is not listening to anyone.'), $this->user->nickname); } } else { - $message = sprintf(_('%s is not listening to anyone.'), $this->profile->fullname); + $message = sprintf(_('%s is not listening to anyone.'), $this->user->nickname); } $this->elementStart('div', 'guide'); From 5c876167785768c41c78a9819868aca17a91e41d Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 01:19:23 +0000 Subject: [PATCH 311/503] added filler/guide text to user groups list. --- actions/usergroups.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/actions/usergroups.php b/actions/usergroups.php index ded4ba76b1..06b2334bf5 100644 --- a/actions/usergroups.php +++ b/actions/usergroups.php @@ -139,10 +139,28 @@ class UsergroupsAction extends Action if ($groups) { $gl = new GroupList($groups, $this->user, $this); $cnt = $gl->show(); + if (0 == $cnt) { + $this->showEmptyListMessage(); + } } $this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE, $this->page, 'usergroups', array('nickname' => $this->user->nickname)); } + + function showEmptyListMessage() + { + $message = sprintf(_('%s is not a member of any group.'), $this->user->nickname) . ' '; + + if (common_logged_in()) { + $current_user = common_current_user(); + if ($this->user->id === $current_user->id) { + $message .= _('Try [searching for groups](%%action.groupsearch%%) and joining them.'); + } + } + $this->elementStart('div', 'guide'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } } From afebef50e46dc6285e3b3fcdf7907d26598a4e95 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 01:20:50 +0000 Subject: [PATCH 312/503] showemptListMessage -> showEmptyListMessage method name cleanup. --- actions/showfavorites.php | 2 +- actions/showstream.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/showfavorites.php b/actions/showfavorites.php index c4c91058f9..4d43495054 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -203,7 +203,7 @@ class ShowfavoritesAction extends Action $cnt = $nl->show(); if (0 == $cnt) { - $this->showemptyListMessage(); + $this->showEmptyListMessage(); } $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, diff --git a/actions/showstream.php b/actions/showstream.php index 4181a2bab9..ce237dae22 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -357,7 +357,7 @@ class ShowstreamAction extends ProfileAction $pnl = new ProfileNoticeList($notice, $this); $cnt = $pnl->show(); if (0 == $cnt) { - $this->showemptyListMessage(); + $this->showEmptyListMessage(); } $this->pagination($this->page>1, $cnt>NOTICES_PER_PAGE, $this->page, From 47d61ad21150358e223f5a9f78cec8f0870c90ea Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 7 Apr 2009 18:29:10 -0700 Subject: [PATCH 313/503] Major improvements to Twitter bridge friend syncing --- lib/twitter.php | 229 ++++++++++++++++++++++++++------- scripts/synctwitterfriends.php | 35 +++-- 2 files changed, 207 insertions(+), 57 deletions(-) diff --git a/lib/twitter.php b/lib/twitter.php index 7abb401516..01723bd83a 100644 --- a/lib/twitter.php +++ b/lib/twitter.php @@ -19,7 +19,7 @@ if (!defined('LACONICA')) { exit(1); } -define("TWITTER_SERVICE", 1); // Twitter is foreign_service ID 1 +define('TWITTER_SERVICE', 1); // Twitter is foreign_service ID 1 function get_twitter_data($uri, $screen_name, $password) { @@ -45,6 +45,10 @@ function get_twitter_data($uri, $screen_name, $password) if ($errmsg) { common_debug("Twitter bridge - cURL error: $errmsg - trying to load: $uri with user $screen_name.", __FILE__); + + if (SCRIPT_DEBUG) { + print "cURL error: $errmsg - trying to load: $uri with user $screen_name.\n"; + } } curl_close($ch); @@ -52,63 +56,141 @@ function get_twitter_data($uri, $screen_name, $password) return $data; } -function twitter_user_info($screen_name, $password) +function twitter_json_data($uri, $screen_name, $password) { + $json_data = get_twitter_data($uri, $screen_name, $password); - $uri = "http://twitter.com/users/show/$screen_name.json"; - $data = get_twitter_data($uri, $screen_name, $password); + if (!$json_data) { + return false; + } + + $data = json_decode($json_data); if (!$data) { return false; } - $twit_user = json_decode($data); - - if (!$twit_user) { - return false; - } - - return $twit_user; + return $data; } -function update_twitter_user($fuser, $twitter_id, $screen_name) +function twitter_user_info($screen_name, $password) { + $uri = "http://twitter.com/users/show/$screen_name.json"; + return twitter_json_data($uri, $screen_name, $password); +} - $original = clone($fuser); - $fuser->nickname = $screen_name; - $fuser->uri = 'http://twitter.com/' . $screen_name; - $result = $fuser->updateKeys($original); +function twitter_friends_ids($screen_name, $password) +{ + $uri = "http://twitter.com/friends/ids/$screen_name.json"; + return twitter_json_data($uri, $screen_name, $password); +} + +function update_twitter_user($twitter_id, $screen_name) +{ + $uri = 'http://twitter.com/' . $screen_name; + + $fuser = new Foreign_user(); + + $fuser->query('BEGIN'); + + // Dropping down to SQL because regular db_object udpate stuff doesn't seem + // to work so good with tables that have multiple column primary keys + + // Any time we update the uri for a forein user we have to make sure there + // are no dupe entries first -- unique constraint on the uri column + + $qry = 'UPDATE foreign_user set uri = \'\' WHERE uri = '; + $qry .= '\'' . $uri . '\'' . ' AND service = ' . TWITTER_SERVICE; + + $result = $fuser->query($qry); + + if ($result) { + common_debug("Removed uri ($uri) from another foreign_user who was squatting on it."); + if (SCRIPT_DEBUG) { + print("Removed uri ($uri) from another Twitter user who was squatting on it.\n"); + } + } + + // Update the user + $qry = 'UPDATE foreign_user SET nickname = '; + $qry .= '\'' . $screen_name . '\'' . ', uri = \'' . $uri . '\' '; + $qry .= 'WHERE id = ' . $twitter_id . ' AND service = ' . TWITTER_SERVICE; + + $result = $fuser->query($qry); if (!$result) { + common_log(LOG_WARNING, + "Couldn't update foreign_user data for Twitter user: $screen_name"); common_log_db_error($fuser, 'UPDATE', __FILE__); + if (SCRIPT_DEBUG) { + print "UPDATE failed: for Twitter user: $twitter_id - $screen_name. - "; + print common_log_objstring($fuser) . "\n"; + $error = &PEAR::getStaticProperty('DB_DataObject','lastError'); + print "DB_DataObject Error: " . $error->getMessage() . "\n"; + } return false; } + $fuser->query('COMMIT'); + + $fuser->free(); + unset($fuser); + return true; } function add_twitter_user($twitter_id, $screen_name) { + $new_uri = 'http://twitter.com/' . $screen_name; + + // Clear out any bad old foreign_users with the new user's legit URL + // This can happen when users move around or fakester accounts get + // repoed, and things like that. + $luser = new Foreign_user(); + $luser->uri = $new_uri; + $luser->service = TWITTER_SERVICE; + $result = $luser->delete(); + + if ($result) { + common_log(LOG_WARNING, + "Twitter bridge - removed invalid Twitter user squatting on uri: $new_uri"); + if (SCRIPT_DEBUG) { + print "Removed invalid Twitter user squatting on uri: $new_uri\n"; + } + } + + $luser->free(); + unset($luser); + // Otherwise, create a new Twitter user - $fuser = DB_DataObject::factory('foreign_user'); + $fuser = new Foreign_user(); $fuser->nickname = $screen_name; $fuser->uri = 'http://twitter.com/' . $screen_name; $fuser->id = $twitter_id; - $fuser->service = TWITTER_SERVICE; // Twitter + $fuser->service = TWITTER_SERVICE; $fuser->created = common_sql_now(); $result = $fuser->insert(); if (!$result) { - common_debug("Twitter bridge - failed to add new Twitter user: $twitter_id - $screen_name."); + common_log(LOG_WARNING, + "Twitter bridge - failed to add new Twitter user: $twitter_id - $screen_name."); common_log_db_error($fuser, 'INSERT', __FILE__); - return false; + if (SCRIPT_DEBUG) { + print "INSERT failed: could not add new Twitter user: $twitter_id - $screen_name. - "; + print common_log_objstring($fuser) . "\n"; + $error = &PEAR::getStaticProperty('DB_DataObject','lastError'); + print "DB_DataObject Error: " . $error->getMessage() . "\n"; + } + } else { + common_debug("Twitter bridge - Added new Twitter user: $screen_name ($twitter_id)."); + if (SCRIPT_DEBUG) { + print "Added new Twitter user: $screen_name ($twitter_id).\n"; + } } - common_debug("Twitter bridge - Added new Twitter user: $screen_name ($twitter_id)."); - - return true; + return $result; } // Creates or Updates a Twitter user @@ -117,53 +199,87 @@ function save_twitter_user($twitter_id, $screen_name) // Check to see whether the Twitter user is already in the system, // and update its screen name and uri if so. - $fuser = Foreign_user::getForeignUser($twitter_id, 1); + $fuser = Foreign_user::getForeignUser($twitter_id, TWITTER_SERVICE); if ($fuser) { + $result = true; + // Only update if Twitter screen name has changed if ($fuser->nickname != $screen_name) { + $result = update_twitter_user($twitter_id, $screen_name); common_debug('Twitter bridge - Updated nickname (and URI) for Twitter user ' . "$fuser->id to $screen_name, was $fuser->nickname"); - return update_twitter_user($fuser, $twitter_id, $screen_name); + if (SCRIPT_DEBUG) { + print 'Updated nickname (and URI) for Twitter user ' . + "$fuser->id to $screen_name, was $fuser->nickname\n"; + } } + return $result; + } else { return add_twitter_user($twitter_id, $screen_name); } + $fuser->free(); + unset($fuser); + return true; } function retreive_twitter_friends($twitter_id, $screen_name, $password) { + $friends = array(); $uri = "http://twitter.com/statuses/friends/$twitter_id.json?page="; - $twitter_user = twitter_user_info($screen_name, $password); + $friends_ids = twitter_friends_ids($screen_name, $password); - // Calculate how many pages to get... - $pages = ceil($twitter_user->friends_count / 100); - - if ($pages == 0) { - common_debug("Twitter bridge - Twitter user $screen_name has no friends! Lame."); + if (!$friends_ids) { + return $friends; } - $friends = array(); + if (SCRIPT_DEBUG) { + print "Twitter 'social graph' ids method says $screen_name has " . + count($friends_ids) . " friends.\n"; + } + + // Calculate how many pages to get... + $pages = ceil(count($friends_ids) / 100); + + if ($pages == 0) { + common_log(LOG_WARNING, + "Twitter bridge - $screen_name seems to have no friends."); + if (SCRIPT_DEBUG) { + print "$screen_name seems to have no friends.\n"; + } + } for ($i = 1; $i <= $pages; $i++) { $data = get_twitter_data($uri . $i, $screen_name, $password); if (!$data) { - return null; + common_log(LOG_WARNING, + "Twitter bridge - Couldn't retrieve page $i of $screen_name's friends."); + if (SCRIPT_DEBUG) { + print "Couldn't retrieve page $i of $screen_name's friends.\n"; + } + continue; } $more_friends = json_decode($data); if (!$more_friends) { - return null; + + common_log(LOG_WARNING, + "Twitter bridge - No data for page $i of $screen_name's friends."); + if (SCRIPT_DEBUG) { + print "No data for page $i of $screen_name's friends.\n"; + } + continue; } $friends = array_merge($friends, $more_friends); @@ -177,19 +293,27 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password) $friends = retreive_twitter_friends($twitter_id, $screen_name, $password); - if (is_null($friends)) { - common_debug("Twitter bridge - Couldn't get friends data from Twitter."); + if (empty($friends)) { + common_debug("Twitter bridge - Couldn't get friends data from Twitter for $screen_name."); + if (SCRIPT_DEBUG) { + print "Couldn't get friends data from Twitter for $screen_name.\n"; + } return false; } foreach ($friends as $friend) { $friend_name = $friend->screen_name; - $friend_id = $friend->id; + $friend_id = (int) $friend->id; // Update or create the Foreign_user record if (!save_twitter_user($friend_id, $friend_name)) { - return false; + common_log(LOG_WARNING, + "Twitter bridge - couldn't save $screen_name's friend, $friend_name."); + if (SCRIPT_DEBUG) { + print "Couldn't save $screen_name's friend, $friend_name.\n"; + } + continue; } // Check to see if there's a related local user @@ -199,8 +323,20 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password) // Get associated user and subscribe her $friend_user = User::staticGet('id', $flink->user_id); - subs_subscribe_to($user, $friend_user); - common_debug("Twitter bridge - subscribed $friend_user->nickname to $user->nickname."); + if (!empty($friend_user)) { + $result = subs_subscribe_to($user, $friend_user); + + if ($result === true) { + common_debug("Twitter bridge - subscribed $friend_user->nickname to $user->nickname."); + if (SCRIPT_DEBUG) { + print("Subscribed $friend_user->nickname to $user->nickname.\n"); + } + } else { + if (SCRIPT_DEBUG) { + print "$result ($friend_user->nickname to $user->nickname)\n"; + } + } + } } } @@ -218,7 +354,7 @@ function is_twitter_bound($notice, $flink) { return true; } } - + return false; } @@ -226,10 +362,10 @@ function broadcast_twitter($notice) { $success = true; - $flink = Foreign_link::getByUserID($notice->profile_id, + $flink = Foreign_link::getByUserID($notice->profile_id, TWITTER_SERVICE); - - // XXX: Not sure WHERE to check whether a notice should go to + + // XXX: Not sure WHERE to check whether a notice should go to // Twitter. Should we even put in the queue if it shouldn't? --Zach if (!is_null($flink) && is_twitter_bound($notice, $flink)) { @@ -244,7 +380,7 @@ function broadcast_twitter($notice) $options = array( CURLOPT_USERPWD => "$twitter_user:$twitter_password", CURLOPT_POST => true, - CURLOPT_POSTFIELDS => + CURLOPT_POSTFIELDS => array( 'status' => $statustxt, 'source' => common_config('integration', 'source') @@ -292,7 +428,6 @@ function broadcast_twitter($notice) $success = false; } } - + return $success; } - diff --git a/scripts/synctwitterfriends.php b/scripts/synctwitterfriends.php index 0ce34c2ae4..d108416f46 100755 --- a/scripts/synctwitterfriends.php +++ b/scripts/synctwitterfriends.php @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -# Abort if called from a web server +// Abort if called from a web server if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { print "This script must be run from the command line\n"; exit(); @@ -27,11 +27,16 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Set this to true to get useful console output +define('SCRIPT_DEBUG', false); + require_once(INSTALLDIR . '/lib/common.php'); $flink = new Foreign_link(); $flink->service = 1; // Twitter -$flink->find(); +$cnt = $flink->find(); + +print "Updating Twitter friends subscriptions for $cnt users.\n"; while ($flink->fetch()) { @@ -39,20 +44,30 @@ while ($flink->fetch()) { $user = User::staticGet($flink->user_id); - print "Updating Twitter friends for user $user->nickname ($user->id)\n"; + if (empty($user)) { + common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); + print "Unmatched user for ID $flink->user_id\n"; + continue; + } + + print "Updating Twitter friends for $user->nickname (Laconica ID: $user->id)... "; $fuser = $flink->getForeignUser(); - $result = save_twitter_friends($user, $fuser->id, $fuser->nickname, $flink->credentials); + if (empty($fuser)) { + common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); + print "Unmatched user for ID $flink->user_id\n"; + continue; + } - if ($result == false) { - print "Problems updating Twitter friends! Check the log.\n"; - exit(1); + $result = save_twitter_friends($user, $fuser->id, + $fuser->nickname, $flink->credentials); + if (SCRIPT_DEBUG) { + print "\nDONE\n"; + } else { + print "DONE\n"; } } - } exit(0); - - From 5666f0e0bd4134dfb86105f814bd4b32a6d8cea8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 7 Apr 2009 22:50:15 -0400 Subject: [PATCH 314/503] add bookmarklet to main help --- doc-src/help | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc-src/help b/doc-src/help index a8cfccd2b3..02cf0d14b0 100644 --- a/doc-src/help +++ b/doc-src/help @@ -30,3 +30,5 @@ Here are some documents that you might find helpful in understanding * [OpenMicroBlogging](%%doc.openmublog%%) - subscribing to remote users * [Privacy](%%doc.privacy%%) - %%site.name%%'s privacy policy * [Source](%%doc.source%%) - How to get the Laconica source code +* [Badge](%%doc.badge%%) - How to put a Laconica badge on your blog or homepage +* [Bookmarklet](%%doc.bookmarklet%%) - Bookmarklet for posting Web pages \ No newline at end of file From 8f40a1a30c44b5aa3fefb705f1343b691778bf02 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 7 Apr 2009 23:02:55 -0400 Subject: [PATCH 315/503] Update README and common for new version Update versions in README, add the new song title, and update the version stamp in the common.php file. --- README | 124 +++++++++++++------------------------------------ lib/common.php | 2 +- 2 files changed, 32 insertions(+), 94 deletions(-) diff --git a/README b/README index f080d32bcc..f18d9c7c16 100644 --- a/README +++ b/README @@ -2,8 +2,8 @@ README ------ -Laconica 0.7.2.1 ("Talk about the Passion") -11 March 2009 +Laconica 0.7.3 ("You Are The Everything") +7 April 2009 This is the README file for Laconica, the Open Source microblogging platform. It includes installation instructions, descriptions of @@ -71,93 +71,29 @@ for additional terms. New this version ================ -This is a minor bug-fix and feature release since version 0.7.1, -released Feb 9 2009. Notable changes this version: +This is a minor bug-fix and feature release since version 0.7.2.1, +released Mar 11 2009. Notable changes this version: -- First version of a web-based installer -- Use Net_URL_Mapper instead of mod_rewrite to map "fancy URLs", - for a much simpler installation and use of PATH_INFO on sites - that don't have mod_rewrite. -- A plugin framework for system events, to make it easier to build - server-side plugins. -- A plugin for Google Analytics -- A plugin to use blogspam.net to check notices for spam -- A plugin to send linkbacks for notices about blog posts -- Configurable check for duplicate notices in a specific time - period -- Better Atom feeds -- First implementation of Twitter Search API -- Add streamlined mobile device-friendly styles when enabled in config. -- A queue server for sending notices to Twitter -- A queue server for sending notices to Facebook -- A queue server for sending notices to a ping server -- Fixed a bug in nonces for OAuth in OpenMicroBlogging -- Fixed bugs in transfer of avatars in OpenMicroBlogging -- @-links go to permalinks for local users -- Better handling of DB errors (instead of dreaded DB_DataObject blank - screen) -- Initial version of an RPM spec file -- More consistent display of notices in notice search -- A stylesheet for printed output -- "Social graph" methods for Twitter API -- Documentation for the JavaScript badge -- Debugged a ton of problems that happened with E_NOTICE on -- Better caching in RSS feeds -- Optionally send email when an @-message is received -- Automatically add tags for every group message -- Add framebusting JavaScript to help avoid clickjacking attacks. -- Optionally ignore some notice sources for public page. -- Add default SMS carriers and notice sources to distribution file. -- Change titles to use mixed case instead of all uppercase. -- Use exceptions for error handling. - -Changes in version 0.7.1: - -- Vast improvement in auto-linking to URLs. -- Link to group search from user's group page -- Improved interface in Facebook application -- Fix bad redirects in delete notice -- Updated PostgreSQL database creation script -- Show filesize in avatar/logo upload -- Vastly improved avatar/logo upload -- Allow re-authentication with OpenID -- Correctly link hashtabs inside parens and brackets -- Group and avatar image transparency works -- Better handling of commands through the Web and Ajax channels -- Fix links for profile page feeds -- Fixed destroy method in API -- Fix endpoint of Connect menu when XMPP disabled -- Show number of group members -- Enable configuration files in /etc/laconica/ - -Changes in version 0.7.0: - -- Support for groups. Users can join groups and send themed notices - to those groups. All other members of the group receive the notices. -- Laconica-specific extensions to the Twitter API. -- A Facebook application. -- A massive UI redesign. The HTML generated by Laconica has changed - significantly, to make theming easier and to give a more open look - by default. Also, sidebar. -- Massive code hygiene changes to move towards compliance with the PEAR - coding standards and to support the new UI redesign. -- Began the breakup of util.php -- moved about 30% of code to a views - hierarchy. -- UI elements for statistical information (like top posters or most - popular groups) added in a sidebar. -- include Javascript badge by Kent Brewster. -- Updated online documentation. -- Cropping of user avatars using Jcrop. -- fix for Twitter bridge to not send "Expect:" headers. -- add 'dm' as a synonym for 'd' in commands. -- Upgrade upstream version of jQuery to 1.3. -- Upgrade upstream version of PHP-OpenID to 2.1.2. -- Move OpenMicroBlogging specification to its own repository. -- Make tag-based RSS streams work. -- Additional locales: Bulgarian, Catalan, Greek, Hebrew, simplified - Chinese, Telugu, Taiwanese Chinese, Vietnamese, -- PostgreSQL updates. -- Nasty bug in Twitter bridge that wouldn't verify with Twitter +- A plugin to allow a templating language for customization +- A plugin for Piwik Analytics engine +- A bookmarklet for posting a notice about a Web page you're reading +- A welcome notice ('welcomebot') and default subscription for new users +- Support for SSL for some or all pages on the site +- Better handling of empty notice lists on many pages +- Major improvements to the Twitter friend-sync offline processing +- subscribers, subscriptions, groups are listed on the Personal page. +- "Invite" link restored to main menu +- Better memory handling in FOAF output +- Fix for SUP support (FriendFeed) +- Correct and intelligent redirect HTTP status codes +- Fix DB collations for search and sort +- Better H1s and Titles using user full names +- Fixes to make the linkback plugin operational +- Better indication that a notice is being published by Ajax (spinner) +- Better and unified Atom output +- Hiding "register" and "join now" messages when site is closed +- ping, twitter and facebook queuehandlers working better +- Updated RPM spec Prerequisites ============= @@ -257,9 +193,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 laconica-0.7.2.1.tar.gz + tar zxf laconica-0.7.3.tar.gz - ...which will make a laconica-0.7.2.1 subdirectory in your current + ...which will make a laconica-0.7.3 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.) @@ -267,7 +203,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 laconica-0.7.2.1 /var/www/mublog + mv laconica-0.7.3 /var/www/mublog This will make your Laconica instance available in the mublog path of your server, like "http://example.net/mublog". "microblog" or @@ -757,7 +693,7 @@ Upgrading If you've been using Laconica 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 Laconica 0.7.2.1. Try these step-by-step instructions; read +procedure in Laconica 0.7.3. Try these step-by-step instructions; read to the end first before trying them. 0. Download Laconica and set up all the prerequisites as if you were @@ -1205,7 +1141,7 @@ repository (see below), and you get a compilation error ("unexpected T_STRING") in the browser, check to see that you don't have any conflicts in your code. -If you upgraded to Laconica 0.7.2.1 without reading the "Notice inboxes" +If you upgraded to Laconica 0.7.3 without reading the "Notice inboxes" section above, and all your users' 'Personal' tabs are empty, read the "Notice inboxes" section above. @@ -1294,6 +1230,8 @@ if anyone's been overlooked in error. * Leslie Michael Orchard * Eric Helgeson * Ken Sedgwick +* Brian Hendrickson +* Tobias Diekershoff Thanks also to the developers of our upstream library code and to the thousands of people who have tried out Identi.ca, installed Laconi.ca, diff --git a/lib/common.php b/lib/common.php index c2037c3ad6..b3882d2079 100644 --- a/lib/common.php +++ b/lib/common.php @@ -19,7 +19,7 @@ if (!defined('LACONICA')) { exit(1); } -define('LACONICA_VERSION', '0.7.2.1'); +define('LACONICA_VERSION', '0.7.3'); define('AVATAR_PROFILE_SIZE', 96); define('AVATAR_STREAM_SIZE', 48); From 579332aa247140d4da720b6c756c97bffdbf955d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 7 Apr 2009 23:57:45 -0400 Subject: [PATCH 316/503] don't use count() to check for empty page --- actions/favorited.php | 17 +++++++++-------- actions/public.php | 17 +++++------------ actions/publictagcloud.php | 10 +++++----- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/actions/favorited.php b/actions/favorited.php index 27da25435b..09ab1216a6 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -104,9 +104,9 @@ class FavoritedAction extends Action { parent::prepare($args); $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; - + common_set_returnto($this->selfUrl()); - + return true; } @@ -143,13 +143,10 @@ class FavoritedAction extends Action $this->elementStart('div', 'instructions'); $this->raw($output); $this->elementEnd('div'); + } - $favorite = new Fave; - - if ($favorite->count()) { - return; - } - + function showEmptyList() + { $message = _('Favorite notices appear on this page but no one has favorited one yet.') . ' '; if (common_logged_in()) { @@ -217,6 +214,10 @@ class FavoritedAction extends Action $cnt = $nl->show(); + if ($cnt == 0) { + $this->showEmptyList(); + } + $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'favorited'); } diff --git a/actions/public.php b/actions/public.php index b7b7fc6b76..5a380de9a8 100644 --- a/actions/public.php +++ b/actions/public.php @@ -166,19 +166,8 @@ class PublicAction extends Action $nav->show(); } - function showPageNotice() + function showEmptyList() { - $notice = new Notice; - - if (!$notice) { - $this->serverError(_('Could not retrieve public stream.')); - return; - } - - if ($notice->count()) { - return; - } - $message = _('This is the public timeline for %%site.name%% but no one has posted anything yet.') . ' '; if (common_logged_in()) { @@ -216,6 +205,10 @@ class PublicAction extends Action $cnt = $nl->show(); + if ($cnt == 0) { + $this->showEmptyList(); + } + $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'public'); } diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index 0cd8940d4d..855cfed9b5 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -62,12 +62,10 @@ class PublictagcloudAction extends Action $this->element('p', 'instructions', sprintf(_('These are most popular recent tags on %s '), common_config('site', 'name'))); + } - $tags = new Notice_tag; - if ($tags->count()) { - return; - } - + function showEmptyList() + { $message = _('No one has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' '; if (common_logged_in()) { @@ -144,6 +142,8 @@ class PublictagcloudAction extends Action $this->elementEnd('dd'); $this->elementEnd('dl'); $this->elementEnd('div'); + } else { + $this->showEmptyList(); } } From 60245f6a27a21ecfc90a2be76fee657e8c696f96 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 8 Apr 2009 04:10:58 +0000 Subject: [PATCH 317/503] bookmarklet now uses non-fancy URLs to make sure it works in all cases. --- doc-src/bookmarklet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc-src/bookmarklet b/doc-src/bookmarklet index 03c0e97c9d..a7f459eecc 100644 --- a/doc-src/bookmarklet +++ b/doc-src/bookmarklet @@ -3,6 +3,6 @@ A bookmarklet is a small piece of javascript code used as a bookmark. This one w Drag-and-drop the following link to your bookmarks bar or right-click it and add it to your browser favorites to keep it handy. -Post to %%site.name%% +Post to %%site.name%% From b8bfc8beaede4977573a978f825231347bf91385 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 8 Apr 2009 00:27:04 -0400 Subject: [PATCH 318/503] far fewer icons in the sidebar --- lib/groupminilist.php | 2 +- lib/profileminilist.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/groupminilist.php b/lib/groupminilist.php index fe38d03403..e8d3a4e3a2 100644 --- a/lib/groupminilist.php +++ b/lib/groupminilist.php @@ -33,7 +33,7 @@ if (!defined('LACONICA')) { require_once INSTALLDIR.'/lib/grouplist.php'; -define('GROUPS_PER_MINILIST', 80); +define('GROUPS_PER_MINILIST', 27); /** * Widget to show a list of groups, good for sidebar diff --git a/lib/profileminilist.php b/lib/profileminilist.php index 0d466bba81..57496d0e97 100644 --- a/lib/profileminilist.php +++ b/lib/profileminilist.php @@ -33,7 +33,7 @@ if (!defined('LACONICA')) { require_once INSTALLDIR.'/lib/profilelist.php'; -define('PROFILES_PER_MINILIST', 80); +define('PROFILES_PER_MINILIST', 27); /** * Widget to show a list of profiles, good for sidebar From 154e8bb858516e4c37427d837b506a48f1131b01 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 8 Apr 2009 00:32:28 -0400 Subject: [PATCH 319/503] use mini logo at mini size, not stream logo --- lib/groupminilist.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/groupminilist.php b/lib/groupminilist.php index e8d3a4e3a2..ae2d237f1d 100644 --- a/lib/groupminilist.php +++ b/lib/groupminilist.php @@ -75,8 +75,9 @@ class GroupMiniList extends GroupList 'href' => $this->group->homeUrl(), 'rel' => 'contact group', 'class' => 'url')); - $logo = ($this->group->stream_logo) ? - $this->group->stream_logo : User_group::defaultLogo(AVATAR_STREAM_SIZE); + + $logo = ($this->group->mini_logo) ? + $this->group->mini_logo : User_group::defaultLogo(AVATAR_MINI_SIZE); $this->out->element('img', array('src' => $logo, 'width' => AVATAR_MINI_SIZE, From 44006a35dd6a7e74f0e3218da54b31a0ea3f571b Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 8 Apr 2009 04:46:00 +0000 Subject: [PATCH 320/503] Better debugging output flag --- lib/twitter.php | 30 +++++++++++++++--------------- scripts/synctwitterfriends.php | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/twitter.php b/lib/twitter.php index 01723bd83a..ccc6c93cae 100644 --- a/lib/twitter.php +++ b/lib/twitter.php @@ -46,7 +46,7 @@ function get_twitter_data($uri, $screen_name, $password) common_debug("Twitter bridge - cURL error: $errmsg - trying to load: $uri with user $screen_name.", __FILE__); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "cURL error: $errmsg - trying to load: $uri with user $screen_name.\n"; } } @@ -106,7 +106,7 @@ function update_twitter_user($twitter_id, $screen_name) if ($result) { common_debug("Removed uri ($uri) from another foreign_user who was squatting on it."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print("Removed uri ($uri) from another Twitter user who was squatting on it.\n"); } } @@ -122,7 +122,7 @@ function update_twitter_user($twitter_id, $screen_name) common_log(LOG_WARNING, "Couldn't update foreign_user data for Twitter user: $screen_name"); common_log_db_error($fuser, 'UPDATE', __FILE__); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "UPDATE failed: for Twitter user: $twitter_id - $screen_name. - "; print common_log_objstring($fuser) . "\n"; $error = &PEAR::getStaticProperty('DB_DataObject','lastError'); @@ -155,7 +155,7 @@ function add_twitter_user($twitter_id, $screen_name) if ($result) { common_log(LOG_WARNING, "Twitter bridge - removed invalid Twitter user squatting on uri: $new_uri"); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "Removed invalid Twitter user squatting on uri: $new_uri\n"; } } @@ -177,7 +177,7 @@ function add_twitter_user($twitter_id, $screen_name) common_log(LOG_WARNING, "Twitter bridge - failed to add new Twitter user: $twitter_id - $screen_name."); common_log_db_error($fuser, 'INSERT', __FILE__); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "INSERT failed: could not add new Twitter user: $twitter_id - $screen_name. - "; print common_log_objstring($fuser) . "\n"; $error = &PEAR::getStaticProperty('DB_DataObject','lastError'); @@ -185,7 +185,7 @@ function add_twitter_user($twitter_id, $screen_name) } } else { common_debug("Twitter bridge - Added new Twitter user: $screen_name ($twitter_id)."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "Added new Twitter user: $screen_name ($twitter_id).\n"; } } @@ -212,7 +212,7 @@ function save_twitter_user($twitter_id, $screen_name) common_debug('Twitter bridge - Updated nickname (and URI) for Twitter user ' . "$fuser->id to $screen_name, was $fuser->nickname"); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print 'Updated nickname (and URI) for Twitter user ' . "$fuser->id to $screen_name, was $fuser->nickname\n"; } @@ -241,7 +241,7 @@ function retreive_twitter_friends($twitter_id, $screen_name, $password) return $friends; } - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "Twitter 'social graph' ids method says $screen_name has " . count($friends_ids) . " friends.\n"; } @@ -252,7 +252,7 @@ function retreive_twitter_friends($twitter_id, $screen_name, $password) if ($pages == 0) { common_log(LOG_WARNING, "Twitter bridge - $screen_name seems to have no friends."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "$screen_name seems to have no friends.\n"; } } @@ -264,7 +264,7 @@ function retreive_twitter_friends($twitter_id, $screen_name, $password) if (!$data) { common_log(LOG_WARNING, "Twitter bridge - Couldn't retrieve page $i of $screen_name's friends."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "Couldn't retrieve page $i of $screen_name's friends.\n"; } continue; @@ -276,7 +276,7 @@ function retreive_twitter_friends($twitter_id, $screen_name, $password) common_log(LOG_WARNING, "Twitter bridge - No data for page $i of $screen_name's friends."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "No data for page $i of $screen_name's friends.\n"; } continue; @@ -295,7 +295,7 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password) if (empty($friends)) { common_debug("Twitter bridge - Couldn't get friends data from Twitter for $screen_name."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "Couldn't get friends data from Twitter for $screen_name.\n"; } return false; @@ -310,7 +310,7 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password) if (!save_twitter_user($friend_id, $friend_name)) { common_log(LOG_WARNING, "Twitter bridge - couldn't save $screen_name's friend, $friend_name."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "Couldn't save $screen_name's friend, $friend_name.\n"; } continue; @@ -328,11 +328,11 @@ function save_twitter_friends($user, $twitter_id, $screen_name, $password) if ($result === true) { common_debug("Twitter bridge - subscribed $friend_user->nickname to $user->nickname."); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print("Subscribed $friend_user->nickname to $user->nickname.\n"); } } else { - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "$result ($friend_user->nickname to $user->nickname)\n"; } } diff --git a/scripts/synctwitterfriends.php b/scripts/synctwitterfriends.php index d108416f46..794301f0f0 100755 --- a/scripts/synctwitterfriends.php +++ b/scripts/synctwitterfriends.php @@ -27,8 +27,8 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); -// Set this to true to get useful console output -define('SCRIPT_DEBUG', false); +// Uncomment this to get useful console output +//define('SCRIPT_DEBUG', true); require_once(INSTALLDIR . '/lib/common.php'); @@ -62,7 +62,7 @@ while ($flink->fetch()) { $result = save_twitter_friends($user, $fuser->id, $fuser->nickname, $flink->credentials); - if (SCRIPT_DEBUG) { + if (defined('SCRIPT_DEBUG')) { print "\nDONE\n"; } else { print "DONE\n"; From 3d536300aae76f8e17229f9876b17b61ba09bc3b Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 8 Apr 2009 18:52:05 +0000 Subject: [PATCH 321/503] Minor update for 800px width viewport --- theme/base/css/display.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index dfac7712a4..03b6880737 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -407,7 +407,7 @@ float:left; width:27.917%; min-height:259px; float:left; -margin-left:0.395%; +margin-left:0.385%; padding:1.795%; border-radius:7px; -moz-border-radius:7px; From 7fc90d5c5c96a0304a2a668ed3e13549306b6460 Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Wed, 8 Apr 2009 15:26:27 -0400 Subject: [PATCH 322/503] Remove extranneous bottom margins on label; fix Safari layout bug. This margin causes a layout bug in Safari whereby the Inbox and Outbox pages have a notice form textarea that's too wide, causing it to slide beneath the "Send" button on those pages. Removing this margin seems to be completely innocuous in my tests, which covered Safari, Firefox, Opera, and Internet Explorer 7. Can less be more? :) --- theme/base/css/display.css | 1 - 1 file changed, 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 03b6880737..5d0ed99151 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -443,7 +443,6 @@ padding:7px 7px 16px 7px; display:block; float:left; font-size:1.3em; -margin-bottom:7px; } #form_notice #notice_submit label { display:none; From 1ac66b39969f8d67805afff5cca88040a625e30c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 8 Apr 2009 19:59:59 +0000 Subject: [PATCH 323/503] Using 800px width and using document.title if no text is selected. --- doc-src/bookmarklet | 3 +-- theme/base/css/display.css | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/doc-src/bookmarklet b/doc-src/bookmarklet index a7f459eecc..a2aaf943d8 100644 --- a/doc-src/bookmarklet +++ b/doc-src/bookmarklet @@ -3,6 +3,5 @@ A bookmarklet is a small piece of javascript code used as a bookmark. This one w Drag-and-drop the following link to your bookmarks bar or right-click it and add it to your browser favorites to keep it handy. -Post to %%site.name%% +Post to %%site.name%% - diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 03b6880737..aa5655369a 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1158,4 +1158,4 @@ display:none; } .guide { clear:both; -} +} \ No newline at end of file From 420c94e7d30745eabe18397a404f284e18bf6588 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 8 Apr 2009 20:36:50 +0000 Subject: [PATCH 324/503] Using encodeURIComponent for document.title --- doc-src/bookmarklet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc-src/bookmarklet b/doc-src/bookmarklet index a2aaf943d8..6cd2c08f90 100644 --- a/doc-src/bookmarklet +++ b/doc-src/bookmarklet @@ -3,5 +3,5 @@ A bookmarklet is a small piece of javascript code used as a bookmark. This one w Drag-and-drop the following link to your bookmarks bar or right-click it and add it to your browser favorites to keep it handy. -Post to %%site.name%% +Post to %%site.name%% From 070cd3533c3474dc065c6681befb92dac51f4bf7 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 8 Apr 2009 20:54:37 +0000 Subject: [PATCH 325/503] Fixes the issue mentioned in commit 7fc90d5. Changed the margin value that's specific to the Inbox/Outbox page only. --- theme/base/css/display.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 1166ae63b7..8ea2befb4c 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -443,6 +443,7 @@ padding:7px 7px 16px 7px; display:block; float:left; font-size:1.3em; +margin-bottom:7px; } #form_notice #notice_submit label { display:none; @@ -471,7 +472,7 @@ bottom:0; right:0; } #form_notice label[for=to] { -margin-top:11px; +margin-top:7px; } #form_notice select[id=to] { margin-bottom:7px; From 6afda46402694e42b0c2e6dfbcfcb2a17a60b2b0 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Thu, 9 Apr 2009 18:29:31 +0100 Subject: [PATCH 326/503] Corrected error in README relating to ['newuser']['welcome'] --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index f18d9c7c16..09d9d301c5 100644 --- a/README +++ b/README @@ -1125,7 +1125,7 @@ default: nickname of a user account to automatically subscribe new service updates or announcements. Users are able to unsub if they want. Default is null; no auto subscribe. welcome: nickname of a user account that sends welcome messages to new - users. Can be the same as 'subscribe' account, although on + users. Can be the same as 'default' account, although on busy servers it may be a good idea to keep that one just for 'urgent' messages. Default is null; no message. From 6cdc2ff444b8c76a3cdc5b8c6e9e7e7539d9b6cc Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Thu, 9 Apr 2009 13:52:39 -0400 Subject: [PATCH 327/503] Fixes ticket:1409; correct typo 'subcription' to 'subscription' in HTML and CSS. --- actions/subscriptions.php | 2 +- theme/base/css/display.css | 4 ++-- theme/base/css/print.css | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/subscriptions.php b/actions/subscriptions.php index b0c0a9b8df..e6f3c54db8 100644 --- a/actions/subscriptions.php +++ b/actions/subscriptions.php @@ -139,7 +139,7 @@ class SubscriptionsList extends ProfileList $this->out->elementStart('form', array('id' => 'subedit-' . $profile->id, 'method' => 'post', - 'class' => 'form_subcription_edit', + 'class' => 'form_subscription_edit', 'action' => common_local_url('subedit'))); $this->out->hidden('token', common_session_token()); $this->out->hidden('profile', $profile->id); diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 8ea2befb4c..3b4a2a4b30 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -689,7 +689,7 @@ float:none; .profile .entity_profile .entity_note, .profile .entity_profile .entity_url, .profile .entity_profile .entity_tags, -.profile .entity_profile .form_subcription_edit { +.profile .entity_profile .form_subscription_edit { margin-left:59px; clear:none; display:block; @@ -701,7 +701,7 @@ margin-right:11px; } -.profile .entity_profile .form_subcription_edit label { +.profile .entity_profile .form_subscription_edit label { font-weight:normal; margin-right:11px; } diff --git a/theme/base/css/print.css b/theme/base/css/print.css index 2da3e5e444..d76dd608c4 100644 --- a/theme/base/css/print.css +++ b/theme/base/css/print.css @@ -21,7 +21,7 @@ p { orphans: 2; widows: 1; } .entity_actions, .notice-options, #aside_primary, -.form_subcription_edit .submit { +.form_subscription_edit .submit { display:none; } From 08c08d02aa48e492eb40ad3790e4fb05c2b86a91 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 10 Apr 2009 10:47:53 -0400 Subject: [PATCH 328/503] Added maisha to notice_source --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index 52d555dbfe..76aadc6733 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -18,6 +18,7 @@ VALUES ('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()), ('identichat','identichat','http://identichat.prosody.im/', now()), ('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()), + ('maisha', 'Maisha', 'http://maisha.grango.org/', now()), ('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()), ('Mobidentica', 'Mobidentica', 'http://www.substanceofcode.com/software/mobidentica/', now()), ('moconica','Moconica','http://moconica.com/', now()), From fba02499327aa18083b590cf38ee6e144be06a6f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 10 Apr 2009 11:36:46 -0400 Subject: [PATCH 329/503] add cliqset --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index 76aadc6733..ac23f14aa1 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -14,6 +14,7 @@ VALUES ('Updating.Me','Updating.Me','http://updating.me/', now()), ('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()), ('bti','bti','http://gregkh.github.com/bti/', now()), + ('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()), ('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()), ('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()), ('identichat','identichat','http://identichat.prosody.im/', now()), From 3b9f235e42da7d862fae7b4da7ea008b98493832 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 10 Apr 2009 17:40:45 +0000 Subject: [PATCH 330/503] Trimming the accept header parts for better content type comparison. e.g., ' text/xml' != 'text/xml' --- lib/util.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util.php b/lib/util.php index 612aa31090..8887655482 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1152,7 +1152,7 @@ function common_accept_to_prefs($accept, $def = '*/*') foreach($parts as $part) { // FIXME: doesn't deal with params like 'text/html; level=1' - @list($value, $qpart) = explode(';', $part); + @list($value, $qpart) = explode(';', trim($part)); $match = array(); if(!isset($qpart)) { $prefs[$value] = 1; @@ -1391,4 +1391,4 @@ function common_database_tablename($tablename) } //table prefixes could be added here later return $tablename; -} \ No newline at end of file +} From 925ac16e1f878b44940b1a2970b91bcf9c09e314 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 10 Apr 2009 22:47:40 -0400 Subject: [PATCH 331/503] tag stream is read-only --- actions/tag.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/actions/tag.php b/actions/tag.php index d15f64498d..c413bf8c34 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -86,4 +86,9 @@ class TagAction extends Action $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->page, 'tag', array('tag' => $this->tag)); } + + function isReadOnly() + { + return true; + } } From 1f33df4715f4293787beb5b64721df6db3a2083c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sat, 11 Apr 2009 22:29:13 +0000 Subject: [PATCH 332/503] (Subjective) The dotted border style is less obtrusive (negative space) than the dotted border style. While present, the dotted blends away better. Observing 1 + 1 = 3 or more principle. --- theme/base/css/display.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 3b4a2a4b30..ec9e6097fa 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -717,7 +717,7 @@ clear:both; float:left; width:100%; border-top-width:1px; -border-top-style:dashed; +border-top-style:dotted; } .notices li { list-style-type:none; From 030477b02a1d00d4957bed88ba221c06e81abff3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 12 Apr 2009 02:08:55 +0000 Subject: [PATCH 333/503] Separation of themes (i.e., layout, typography) and skins (i.e., background images, colours). A theme can have multiple skins. Majority of the changes in this commit are due to restructuring the path/files for themes and skins. Both theme and skin will be set to 'default' if not set in config.php. This commit also allows each instance of this software to create its own theme without having to override any style from the default distribution. Added Cloudy theme. --- config.php.sample | 1 + lib/action.php | 16 +- lib/common.php | 1 + lib/theme.php | 29 +- theme/cloudy/base/css/display.css | 1235 +++++++++++++++++ theme/{ => cloudy}/base/css/facebookapp.css | 0 theme/{ => cloudy}/base/css/ie.css | 0 theme/{ => cloudy}/base/css/ie6.css | 0 theme/{ => cloudy}/base/css/jquery.Jcrop.css | 0 theme/{ => cloudy}/base/css/mobile.css | 0 theme/{ => cloudy}/base/css/print.css | 0 theme/{ => cloudy}/base/css/thickbox.css | 0 .../base/images/icons/icon_atom.png | Bin .../base/images/icons/icon_foaf.gif | Bin .../base/images/icons/icon_processing.gif | Bin .../base/images/icons/icon_rss.png | Bin .../base/images/icons/icon_vcard.gif | Bin .../base/images/illustrations/illu_jcrop.gif | Bin .../illu_progress_loading-01.gif | Bin theme/cloudy/default-avatar-mini.png | Bin 0 -> 1006 bytes theme/cloudy/default-avatar-profile.png | Bin 0 -> 9026 bytes theme/cloudy/default-avatar-stream.png | Bin 0 -> 2963 bytes theme/{identica => cloudy}/logo.png | Bin theme/cloudy/skin/default/css/display.css | 318 +++++ theme/cloudy/skin/default/css/ie.css | 34 + .../skin}/default/images/icons/icon_atom.jpg | Bin .../images/icons/icon_disfavourite.gif | Bin 0 -> 701 bytes .../default/images/icons/icon_favourite.gif | Bin 0 -> 397 bytes .../skin}/default/images/icons/icon_foaf.gif | Bin .../skin/default/images/icons/icon_reply.gif | Bin 0 -> 336 bytes .../skin}/default/images/icons/icon_rss.jpg | Bin .../skin/default/images/icons/icon_trash.gif | Bin 0 -> 148 bytes .../skin}/default/images/icons/icon_vcard.gif | Bin .../images/icons/twotone/green/arrow-left.gif | Bin .../icons/twotone/green/arrow-right.gif | Bin .../images/icons/twotone/green/edit.gif | Bin .../images/icons/twotone/green/mail.gif | Bin .../images/icons/twotone/green/news.gif | Bin .../images/icons/twotone/green/quote.gif | Bin .../images/icons/twotone/green/shield.gif | Bin .../images/illustrations/illu_arrow-up-01.gif | Bin 0 -> 68 bytes .../images/illustrations/illu_clouds-01.gif | Bin 0 -> 14251 bytes .../images/illustrations/illu_unicorn-01.png | Bin 0 -> 5695 bytes theme/{ => default}/base/css/display.css | 0 theme/default/base/css/facebookapp.css | 100 ++ theme/default/base/css/ie.css | 32 + theme/default/base/css/ie6.css | 30 + theme/default/base/css/jquery.Jcrop.css | 45 + theme/default/base/css/mobile.css | 150 ++ theme/default/base/css/print.css | 36 + theme/default/base/css/thickbox.css | 163 +++ theme/default/base/images/icons/icon_atom.png | Bin 0 -> 820 bytes .../base}/images/icons/icon_foaf.gif | Bin .../base/images/icons/icon_processing.gif | Bin 0 -> 673 bytes theme/default/base/images/icons/icon_rss.png | Bin 0 -> 777 bytes .../base}/images/icons/icon_vcard.gif | Bin .../base/images/illustrations/illu_jcrop.gif | Bin 0 -> 329 bytes .../illu_progress_loading-01.gif | Bin 0 -> 5886 bytes theme/default/logo.png | Bin 0 -> 4988 bytes .../{ => skin/default}/css/display.css | 8 +- theme/default/{ => skin/default}/css/ie.css | 0 .../skin/default}/images/icons/icon_atom.jpg | Bin .../skin/default/images/icons/icon_foaf.gif | Bin 0 -> 1144 bytes .../skin/default}/images/icons/icon_rss.jpg | Bin .../skin/default/images/icons/icon_vcard.gif | Bin 0 -> 331 bytes .../images/icons/twotone/green/against.gif | Bin .../images/icons/twotone/green/arrow-down.gif | Bin .../icons/twotone/green/arrow-downleft.gif | Bin .../icons/twotone/green/arrow-downright.gif | Bin .../images/icons/twotone/green/arrow-left.gif | Bin .../icons/twotone/green/arrow-right.gif | Bin .../images/icons/twotone/green/arrow-up.gif | Bin .../icons/twotone/green/arrow-upleft.gif | Bin .../icons/twotone/green/arrow-upright.gif | Bin .../images/icons/twotone/green/back-forth.gif | Bin .../images/icons/twotone/green/bookmark.gif | Bin .../images/icons/twotone/green/bulb.gif | Bin .../images/icons/twotone/green/calendar.gif | Bin .../images/icons/twotone/green/calendar2.gif | Bin .../images/icons/twotone/green/camera.gif | Bin .../images/icons/twotone/green/cart.gif | Bin .../images/icons/twotone/green/caution.gif | Bin .../images/icons/twotone/green/chart.gif | Bin .../images/icons/twotone/green/checkmark.gif | Bin .../images/icons/twotone/green/clipboard.gif | Bin .../images/icons/twotone/green/clock.gif | Bin .../icons/twotone/green/closed-folder.gif | Bin .../images/icons/twotone/green/database.gif | Bin .../icons/twotone/green/disfavourite.gif | Bin .../images/icons/twotone/green/diskette.gif | Bin .../images/icons/twotone/green/document.gif | Bin .../icons/twotone/green/double-arrow.gif | Bin .../images/icons/twotone/green/edit.gif | Bin .../images/icons/twotone/green/eject.gif | Bin .../images/icons/twotone/green/exclaim.gif | Bin .../icons/twotone/green/fastforward.gif | Bin .../images/icons/twotone/green/favourite.gif | Bin .../images/icons/twotone/green/flag.gif | Bin .../images/icons/twotone/green/graph.gif | Bin .../images/icons/twotone/green/grow.gif | Bin .../images/icons/twotone/green/headphones.gif | Bin .../images/icons/twotone/green/home.gif | Bin .../images/icons/twotone/green/hourglass.gif | Bin .../images/icons/twotone/green/info.gif | Bin .../images/icons/twotone/green/key.gif | Bin .../images/icons/twotone/green/lock.gif | Bin .../images/icons/twotone/green/mail.gif | Bin .../images/icons/twotone/green/move.gif | Bin .../images/icons/twotone/green/music.gif | Bin .../images/icons/twotone/green/news.gif | Bin .../images/icons/twotone/green/note.gif | Bin .../icons/twotone/green/open-folder.gif | Bin .../images/icons/twotone/green/paper-clip.gif | Bin .../icons/twotone/green/paper-clip2.gif | Bin .../images/icons/twotone/green/pause.gif | Bin .../images/icons/twotone/green/phone.gif | Bin .../images/icons/twotone/green/play.gif | Bin .../images/icons/twotone/green/plus.gif | Bin .../images/icons/twotone/green/print.gif | Bin .../icons/twotone/green/question-mark.gif | Bin .../images/icons/twotone/green/quote.gif | Bin .../images/icons/twotone/green/refresh.gif | Bin .../images/icons/twotone/green/reply.gif | Bin .../images/icons/twotone/green/repost.gif | Bin 0 -> 87 bytes .../images/icons/twotone/green/rewind.gif | Bin .../images/icons/twotone/green/search.gif | Bin .../images/icons/twotone/green/shield.gif | Bin .../images/icons/twotone/green/skip-back.gif | Bin .../images/icons/twotone/green/skip.gif | Bin .../images/icons/twotone/green/skull.gif | Bin .../images/icons/twotone/green/statusbar.gif | Bin .../images/icons/twotone/green/stop.gif | Bin .../images/icons/twotone/green/template.gif | Bin .../icons/twotone/green/text-bigger.gif | Bin .../icons/twotone/green/text-smaller.gif | Bin .../images/icons/twotone/green/trash.gif | Bin .../images/icons/twotone/green/two-docs.gif | Bin .../images/icons/twotone/green/twotone.gif | Bin .../images/icons/twotone/green/undo.gif | Bin .../images/icons/twotone/green/user.gif | Bin .../images/icons/twotone/green/vegetable.gif | Bin .../default}/images/icons/twotone/green/x.gif | Bin .../images/icons/twotone/green/zoom-in.gif | Bin .../images/icons/twotone/green/zoom-out.gif | Bin .../skin}/identica/css/display.css | 8 +- theme/{ => default/skin}/identica/css/ie.css | 0 .../skin/identica/images/icons/icon_atom.jpg | Bin 0 -> 1117 bytes .../skin/identica/images/icons/icon_foaf.gif | Bin 0 -> 1144 bytes .../skin/identica/images/icons/icon_rss.jpg | Bin 0 -> 1166 bytes .../skin/identica/images/icons/icon_vcard.gif | Bin 0 -> 331 bytes .../images/icons/twotone/green/against.gif | Bin .../images/icons/twotone/green/arrow-down.gif | Bin .../icons/twotone/green/arrow-downleft.gif | Bin .../icons/twotone/green/arrow-downright.gif | Bin .../images/icons/twotone/green/arrow-left.gif | Bin 0 -> 73 bytes .../icons/twotone/green/arrow-right.gif | Bin 0 -> 74 bytes .../images/icons/twotone/green/arrow-up.gif | Bin .../icons/twotone/green/arrow-upleft.gif | Bin .../icons/twotone/green/arrow-upright.gif | Bin .../images/icons/twotone/green/back-forth.gif | Bin .../images/icons/twotone/green/bookmark.gif | Bin .../images/icons/twotone/green/bulb.gif | Bin .../images/icons/twotone/green/calendar.gif | Bin .../images/icons/twotone/green/calendar2.gif | Bin .../images/icons/twotone/green/camera.gif | Bin .../images/icons/twotone/green/cart.gif | Bin .../images/icons/twotone/green/caution.gif | Bin .../images/icons/twotone/green/chart.gif | Bin .../images/icons/twotone/green/checkmark.gif | Bin .../images/icons/twotone/green/clipboard.gif | Bin .../images/icons/twotone/green/clock.gif | Bin .../icons/twotone/green/closed-folder.gif | Bin .../images/icons/twotone/green/database.gif | Bin .../icons/twotone/green/disfavourite.gif | Bin .../images/icons/twotone/green/diskette.gif | Bin .../images/icons/twotone/green/document.gif | Bin .../icons/twotone/green/double-arrow.gif | Bin .../images/icons/twotone/green/edit.gif | Bin 0 -> 75 bytes .../images/icons/twotone/green/eject.gif | Bin .../images/icons/twotone/green/exclaim.gif | Bin .../icons/twotone/green/fastforward.gif | Bin .../images/icons/twotone/green/favourite.gif | Bin .../images/icons/twotone/green/flag.gif | Bin .../images/icons/twotone/green/graph.gif | Bin .../images/icons/twotone/green/grow.gif | Bin .../images/icons/twotone/green/headphones.gif | Bin .../images/icons/twotone/green/home.gif | Bin .../images/icons/twotone/green/hourglass.gif | Bin .../images/icons/twotone/green/info.gif | Bin .../images/icons/twotone/green/key.gif | Bin .../images/icons/twotone/green/lock.gif | Bin .../images/icons/twotone/green/mail.gif | Bin 0 -> 82 bytes .../images/icons/twotone/green/move.gif | Bin .../images/icons/twotone/green/music.gif | Bin .../images/icons/twotone/green/news.gif | Bin 0 -> 76 bytes .../images/icons/twotone/green/note.gif | Bin .../icons/twotone/green/open-folder.gif | Bin .../images/icons/twotone/green/paper-clip.gif | Bin .../icons/twotone/green/paper-clip2.gif | Bin .../images/icons/twotone/green/pause.gif | Bin .../images/icons/twotone/green/phone.gif | Bin .../images/icons/twotone/green/play.gif | Bin .../images/icons/twotone/green/plus.gif | Bin .../images/icons/twotone/green/print.gif | Bin .../icons/twotone/green/question-mark.gif | Bin .../images/icons/twotone/green/quote.gif | Bin 0 -> 79 bytes .../images/icons/twotone/green/refresh.gif | Bin .../images/icons/twotone/green/reply.gif | Bin .../images/icons/twotone/green/repost.gif | Bin 0 -> 87 bytes .../images/icons/twotone/green/rewind.gif | Bin .../images/icons/twotone/green/search.gif | Bin .../images/icons/twotone/green/shield.gif | Bin 0 -> 85 bytes .../images/icons/twotone/green/skip-back.gif | Bin .../images/icons/twotone/green/skip.gif | Bin .../images/icons/twotone/green/skull.gif | Bin .../images/icons/twotone/green/statusbar.gif | Bin .../images/icons/twotone/green/stop.gif | Bin .../images/icons/twotone/green/template.gif | Bin .../icons/twotone/green/text-bigger.gif | Bin .../icons/twotone/green/text-smaller.gif | Bin .../images/icons/twotone/green/trash.gif | Bin .../images/icons/twotone/green/two-docs.gif | Bin .../images/icons/twotone/green/twotone.gif | Bin .../images/icons/twotone/green/undo.gif | Bin .../images/icons/twotone/green/user.gif | Bin .../images/icons/twotone/green/vegetable.gif | Bin .../identica/images/icons/twotone/green/x.gif | Bin .../images/icons/twotone/green/zoom-in.gif | Bin .../images/icons/twotone/green/zoom-out.gif | Bin theme/identica/default-avatar-mini.png | Bin 646 -> 0 bytes theme/identica/default-avatar-profile.png | Bin 2853 -> 0 bytes theme/identica/default-avatar-stream.png | Bin 1487 -> 0 bytes 232 files changed, 2189 insertions(+), 17 deletions(-) create mode 100644 theme/cloudy/base/css/display.css rename theme/{ => cloudy}/base/css/facebookapp.css (100%) rename theme/{ => cloudy}/base/css/ie.css (100%) rename theme/{ => cloudy}/base/css/ie6.css (100%) rename theme/{ => cloudy}/base/css/jquery.Jcrop.css (100%) rename theme/{ => cloudy}/base/css/mobile.css (100%) rename theme/{ => cloudy}/base/css/print.css (100%) rename theme/{ => cloudy}/base/css/thickbox.css (100%) rename theme/{ => cloudy}/base/images/icons/icon_atom.png (100%) rename theme/{ => cloudy}/base/images/icons/icon_foaf.gif (100%) rename theme/{ => cloudy}/base/images/icons/icon_processing.gif (100%) rename theme/{ => cloudy}/base/images/icons/icon_rss.png (100%) rename theme/{ => cloudy}/base/images/icons/icon_vcard.gif (100%) rename theme/{ => cloudy}/base/images/illustrations/illu_jcrop.gif (100%) rename theme/{ => cloudy}/base/images/illustrations/illu_progress_loading-01.gif (100%) create mode 100644 theme/cloudy/default-avatar-mini.png create mode 100644 theme/cloudy/default-avatar-profile.png create mode 100644 theme/cloudy/default-avatar-stream.png rename theme/{identica => cloudy}/logo.png (100%) create mode 100644 theme/cloudy/skin/default/css/display.css create mode 100644 theme/cloudy/skin/default/css/ie.css rename theme/{ => cloudy/skin}/default/images/icons/icon_atom.jpg (100%) create mode 100644 theme/cloudy/skin/default/images/icons/icon_disfavourite.gif create mode 100644 theme/cloudy/skin/default/images/icons/icon_favourite.gif rename theme/{ => cloudy/skin}/default/images/icons/icon_foaf.gif (100%) create mode 100644 theme/cloudy/skin/default/images/icons/icon_reply.gif rename theme/{ => cloudy/skin}/default/images/icons/icon_rss.jpg (100%) create mode 100644 theme/cloudy/skin/default/images/icons/icon_trash.gif rename theme/{ => cloudy/skin}/default/images/icons/icon_vcard.gif (100%) rename theme/{ => cloudy/skin}/default/images/icons/twotone/green/arrow-left.gif (100%) rename theme/{ => cloudy/skin}/default/images/icons/twotone/green/arrow-right.gif (100%) rename theme/{ => cloudy/skin}/default/images/icons/twotone/green/edit.gif (100%) rename theme/{ => cloudy/skin}/default/images/icons/twotone/green/mail.gif (100%) rename theme/{ => cloudy/skin}/default/images/icons/twotone/green/news.gif (100%) rename theme/{ => cloudy/skin}/default/images/icons/twotone/green/quote.gif (100%) rename theme/{ => cloudy/skin}/default/images/icons/twotone/green/shield.gif (100%) create mode 100644 theme/cloudy/skin/default/images/illustrations/illu_arrow-up-01.gif create mode 100644 theme/cloudy/skin/default/images/illustrations/illu_clouds-01.gif create mode 100644 theme/cloudy/skin/default/images/illustrations/illu_unicorn-01.png rename theme/{ => default}/base/css/display.css (100%) create mode 100644 theme/default/base/css/facebookapp.css create mode 100644 theme/default/base/css/ie.css create mode 100644 theme/default/base/css/ie6.css create mode 100644 theme/default/base/css/jquery.Jcrop.css create mode 100644 theme/default/base/css/mobile.css create mode 100644 theme/default/base/css/print.css create mode 100644 theme/default/base/css/thickbox.css create mode 100644 theme/default/base/images/icons/icon_atom.png rename theme/{identica => default/base}/images/icons/icon_foaf.gif (100%) create mode 100644 theme/default/base/images/icons/icon_processing.gif create mode 100644 theme/default/base/images/icons/icon_rss.png rename theme/{identica => default/base}/images/icons/icon_vcard.gif (100%) create mode 100644 theme/default/base/images/illustrations/illu_jcrop.gif create mode 100644 theme/default/base/images/illustrations/illu_progress_loading-01.gif create mode 100644 theme/default/logo.png rename theme/default/{ => skin/default}/css/display.css (94%) rename theme/default/{ => skin/default}/css/ie.css (100%) rename theme/{identica => default/skin/default}/images/icons/icon_atom.jpg (100%) create mode 100644 theme/default/skin/default/images/icons/icon_foaf.gif rename theme/{identica => default/skin/default}/images/icons/icon_rss.jpg (100%) create mode 100644 theme/default/skin/default/images/icons/icon_vcard.gif rename theme/default/{ => skin/default}/images/icons/twotone/green/against.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/arrow-down.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/arrow-downleft.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/arrow-downright.gif (100%) rename theme/{identica => default/skin/default}/images/icons/twotone/green/arrow-left.gif (100%) rename theme/{identica => default/skin/default}/images/icons/twotone/green/arrow-right.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/arrow-up.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/arrow-upleft.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/arrow-upright.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/back-forth.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/bookmark.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/bulb.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/calendar.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/calendar2.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/camera.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/cart.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/caution.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/chart.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/checkmark.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/clipboard.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/clock.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/closed-folder.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/database.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/disfavourite.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/diskette.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/document.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/double-arrow.gif (100%) rename theme/{identica => default/skin/default}/images/icons/twotone/green/edit.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/eject.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/exclaim.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/fastforward.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/favourite.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/flag.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/graph.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/grow.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/headphones.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/home.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/hourglass.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/info.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/key.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/lock.gif (100%) rename theme/{identica => default/skin/default}/images/icons/twotone/green/mail.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/move.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/music.gif (100%) rename theme/{identica => default/skin/default}/images/icons/twotone/green/news.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/note.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/open-folder.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/paper-clip.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/paper-clip2.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/pause.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/phone.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/play.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/plus.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/print.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/question-mark.gif (100%) rename theme/{identica => default/skin/default}/images/icons/twotone/green/quote.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/refresh.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/reply.gif (100%) create mode 100644 theme/default/skin/default/images/icons/twotone/green/repost.gif rename theme/default/{ => skin/default}/images/icons/twotone/green/rewind.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/search.gif (100%) rename theme/{identica => default/skin/default}/images/icons/twotone/green/shield.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/skip-back.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/skip.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/skull.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/statusbar.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/stop.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/template.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/text-bigger.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/text-smaller.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/trash.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/two-docs.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/twotone.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/undo.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/user.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/vegetable.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/x.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/zoom-in.gif (100%) rename theme/default/{ => skin/default}/images/icons/twotone/green/zoom-out.gif (100%) rename theme/{ => default/skin}/identica/css/display.css (94%) rename theme/{ => default/skin}/identica/css/ie.css (100%) create mode 100644 theme/default/skin/identica/images/icons/icon_atom.jpg create mode 100644 theme/default/skin/identica/images/icons/icon_foaf.gif create mode 100644 theme/default/skin/identica/images/icons/icon_rss.jpg create mode 100644 theme/default/skin/identica/images/icons/icon_vcard.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/against.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/arrow-down.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/arrow-downleft.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/arrow-downright.gif (100%) create mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-left.gif create mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-right.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/arrow-up.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/arrow-upleft.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/arrow-upright.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/back-forth.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/bookmark.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/bulb.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/calendar.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/calendar2.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/camera.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/cart.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/caution.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/chart.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/checkmark.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/clipboard.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/clock.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/closed-folder.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/database.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/disfavourite.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/diskette.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/document.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/double-arrow.gif (100%) create mode 100644 theme/default/skin/identica/images/icons/twotone/green/edit.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/eject.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/exclaim.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/fastforward.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/favourite.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/flag.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/graph.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/grow.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/headphones.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/home.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/hourglass.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/info.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/key.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/lock.gif (100%) create mode 100644 theme/default/skin/identica/images/icons/twotone/green/mail.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/move.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/music.gif (100%) create mode 100644 theme/default/skin/identica/images/icons/twotone/green/news.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/note.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/open-folder.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/paper-clip.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/paper-clip2.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/pause.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/phone.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/play.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/plus.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/print.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/question-mark.gif (100%) create mode 100644 theme/default/skin/identica/images/icons/twotone/green/quote.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/refresh.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/reply.gif (100%) create mode 100644 theme/default/skin/identica/images/icons/twotone/green/repost.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/rewind.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/search.gif (100%) create mode 100644 theme/default/skin/identica/images/icons/twotone/green/shield.gif rename theme/{ => default/skin}/identica/images/icons/twotone/green/skip-back.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/skip.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/skull.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/statusbar.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/stop.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/template.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/text-bigger.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/text-smaller.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/trash.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/two-docs.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/twotone.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/undo.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/user.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/vegetable.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/x.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/zoom-in.gif (100%) rename theme/{ => default/skin}/identica/images/icons/twotone/green/zoom-out.gif (100%) delete mode 100644 theme/identica/default-avatar-mini.png delete mode 100644 theme/identica/default-avatar-profile.png delete mode 100644 theme/identica/default-avatar-stream.png diff --git a/config.php.sample b/config.php.sample index fa35288353..6601acc7e9 100644 --- a/config.php.sample +++ b/config.php.sample @@ -18,6 +18,7 @@ $config['site']['server'] = 'localhost'; $config['site']['path'] = 'laconica'; #$config['site']['fancy'] = false; #$config['site']['theme'] = 'default'; +#$config['site']['skin'] = 'default'; #To enable the built-in mobile style sheet, defaults to false. #$config['site']['mobile'] = true; #For contact email, defaults to $_SERVER["SERVER_ADMIN"] diff --git a/lib/action.php b/lib/action.php index f2027e0f17..ecd1978f28 100644 --- a/lib/action.php +++ b/lib/action.php @@ -194,37 +194,37 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowLaconicaStyles', array($this))) { $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', - 'href' => theme_path('css/display.css', 'base') . '?version=' . LACONICA_VERSION, + 'href' => theme_path('base/css/display.css') . '?version=' . LACONICA_VERSION, 'media' => 'screen, projection, tv')); $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', - 'href' => theme_path('css/display.css', null) . '?version=' . LACONICA_VERSION, + 'href' => skin_path('css/display.css') . '?version=' . LACONICA_VERSION, 'media' => 'screen, projection, tv')); if (common_config('site', 'mobile')) { $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', - 'href' => theme_path('css/mobile.css', 'base') . '?version=' . LACONICA_VERSION, + 'href' => theme_path('base/css/mobile.css') . '?version=' . LACONICA_VERSION, // TODO: "handheld" CSS for other mobile devices 'media' => 'only screen and (max-device-width: 480px)')); // Mobile WebKit } $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', - 'href' => theme_path('css/print.css', 'base') . '?version=' . LACONICA_VERSION, + 'href' => theme_path('base/css/print.css') . '?version=' . LACONICA_VERSION, 'media' => 'print')); Event::handle('EndShowLaconicaStyles', array($this)); } if (Event::handle('StartShowUAStyles', array($this))) { $this->comment('[if IE]>comment('[if lte IE '.$ver.']>comment('[if IE]> 'Just another Laconica microblog', 'server' => $_server, 'theme' => 'default', + 'skin' => 'default', 'path' => $_path, 'logfile' => null, 'logo' => null, diff --git a/lib/theme.php b/lib/theme.php index 95030affed..bef660cbf5 100644 --- a/lib/theme.php +++ b/lib/theme.php @@ -69,4 +69,31 @@ function theme_path($relative, $theme=null) } else { return common_path('theme/'.$theme.'/'.$relative); } -} \ No newline at end of file +} + +/** + * Gets the full URL of a file in a skin dir based on its relative name + * + * @param string $relative relative path within the theme, skin directory + * @param string $theme name of the theme; defaults to current theme + * @param string $skin name of the skin; defaults to current theme + * + * @return string URL of the file + */ + +function skin_path($relative, $theme=null, $skin=null) +{ + if (!$theme) { + $theme = common_config('site', 'theme'); + } + if (!$skin) { + $skin = common_config('site', 'skin'); + } + $server = common_config('theme', 'server'); + if ($server) { + return 'http://'.$server.'/'.$theme.'/skin/'.$skin.'/'.$relative; + } else { + return common_path('theme/'.$theme.'/skin/'.$skin.'/'.$relative); + } +} + diff --git a/theme/cloudy/base/css/display.css b/theme/cloudy/base/css/display.css new file mode 100644 index 0000000000..8d34e8442b --- /dev/null +++ b/theme/cloudy/base/css/display.css @@ -0,0 +1,1235 @@ +/** theme: cloudy + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +* { margin:0; padding:0; } +img { display:block; border:0; } +a abbr { cursor: pointer; border-bottom:0; } +table { border-collapse:collapse; } +ol { list-style-position:inside; } +html { font-size: 100%; background-color:#fff; height:100%; } +body { +background-color:#fff; +color:#000; +font-family:sans-serif; +font-size:0.75em; +line-height:normal; +position:relative; +height:100%; +} +h1,h2,h3,h4,h5,h6 { +margin-bottom:7px; +overflow:hidden; +} +h1 { +font-size:1.4em; +margin-bottom:18px; +} +h2 { font-size:1.3em; } +h3 { font-size:1.2em; } +h4 { font-size:1.1em; } +h5 { font-size:1em; } +h6 { font-size:0.9em; } + +caption { +font-weight:bold; +} +legend { +font-weight:bold; +font-size:1.3em; +} +input, textarea, select, option { +padding:4px; +font-family:sans-serif; +font-size:1em; +} +input, textarea, select { +border-width:2px; +border-style: solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +input.submit { +font-weight:bold; +cursor:pointer; +} +textarea { +overflow:auto; +} +option { +padding-bottom:0; +} +fieldset { +padding:0; +border:0; +} +form ul li { +list-style-type:none; +margin:0 0 18px 0; +} +form label { +font-weight:bold; +} +input.checkbox { +position:relative; +top:2px; +left:0; +border:0; +} + +.error, +.success { +padding:4px 7px; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +margin-bottom:18px; +} +form label.submit { +display:none; +} + +.form_settings { +clear:both; +} + +.form_settings fieldset { +margin-bottom:29px; +} +.form_settings input.remove { +margin-left:11px; +} +.form_settings .form_data li { +width:100%; +float:left; +} +.form_settings .form_data label { +float:left; +} +.form_settings .form_data textarea, +.form_settings .form_data select, +.form_settings .form_data input { +margin-left:11px; +float:left; +} +.form_settings .form_data input.submit { +margin-left:0; +} + +.form_settings label { +margin-top:2px; +width:145px; +} + +.form_actions label { +display:none; +} +.form_guide { +font-style:italic; +} + +.form_settings #settings_autosubscribe label { +display:inline; +font-weight:bold; +} + +#form_settings_profile legend, +#form_login legend, +#form_register legend, +#form_password legend, +#form_settings_avatar legend, +#newgroup legend, +#editgroup legend, +#form_tag_user legend, +#form_remote_subscribe legend, +#form_openid_login legend, +#form_search legend, +#form_invite legend, +#form_notice_delete legend, +#form_password_recover legend, +#form_password_change legend { +display:none; +} + +.form_settings .form_data p.form_guide { +clear:both; +margin-left:155px; +margin-bottom:0; +} + +.form_settings p { +margin-bottom:11px; +} + +.form_settings input.checkbox { +margin-top:0; +margin-left:0; +} +.form_settings label.checkbox { +font-weight:normal; +margin-top:0; +margin-right:0; +margin-left:11px; +float:left; +width:90%; +} + + +#form_login p.form_guide, +#form_register #settings_rememberme p.form_guide, +#form_openid_login #settings_rememberme p.form_guide, +#settings_twitter_remove p.form_guide, +#form_search ul.form_data #q { +margin-left:0; +} + +.form_settings .form_note { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +padding:0 7px; +} + + +.form_settings input.form_action-secondary { +margin-left:29px; +padding:0; +} + +#form_search .submit { +margin-left:11px; +} + +address { +float:left; +margin-bottom:18px; +margin-left:18px; +} +address.vcard img.logo { +margin-right:0; +} +address .fn { +font-weight:bold; +} +address img + .fn { +display:none; +} + +#header { +width:100%; +position:relative; +float:left; +padding-top:18px; +margin-bottom:11px; +z-index:1; +} + +#site_nav_global_primary { +float:right; +margin-right:0; +margin-bottom:11px; +margin-left:18px; +padding-top:7px; +padding-bottom:7px; +padding-right:11px; +-moz-border-radius:4px; +border-radius:4px; +-webkit-border-radius:4px; +} +#site_nav_global_primary ul li { +display:inline; +margin-left:11px; +} +#site_nav_global_primary a { +text-decoration:none; +} + +.system_notice dt { +font-weight:bold; +text-transform:uppercase; +display:none; +} + +#site_notice { +position:absolute; +top:65px; +right:18px; +width:250px; +width:24%; +} +#page_notice { +clear:both; +margin-bottom:18px; +} + + +#anon_notice { +clear:both; +width:99.8%; +padding-top:36px; +line-height:1.5; +font-size:1.3em; +font-weight:bold; +} +#anon_notice p { +border-style:solid; +border-width:1px; +width:96%; +padding:2%; +} + +#footer { +float:left; +margin-bottom:1em; +padding:7px; +-moz-border-radius:4px; +border-radius:4px; +-webkit-border-radius:4px; +} +#footer a { +text-decoration:none; +} + +#site_nav_local_views { +width:203px; +float:right; +margin-right:0; +-moz-border-radius-topright:4px; +border-radius-topright:4px; +-webkit-border-top-right-radius:4px; +} +#site_nav_local_views dt { +display:none; +} +#site_nav_local_views li { +list-style-type:none; +padding:0; +border-width:1px; +border-style:solid; +border-top:0; +border-right:0; +} +#site_nav_local_views a { +text-decoration:none; +padding:13px; +border-width:1px; +border-style:solid; +border-bottom:0; +text-shadow: 2px 2px 2px #ddd; +font-weight:bold; +font-size:1em; +display:block; +} +#site_nav_local_views .nav { +float:left; +width:100%; +} + +#site_nav_global_primary dt, +#site_nav_global_secondary dt { +display:none; +} + +#site_nav_global_secondary { +margin-bottom:11px; +} + +#site_nav_global_secondary ul li { +display:inline; +margin-right:11px; +} +#export_data li a { +padding-left:20px; +} +#export_data li a.foaf { +padding-left:30px; +} +#export_data li a.export_vcard { +padding-left:28px; +} + +#export_data ul { +display:inline; +} +#export_data li { +list-style-type:none; +display:inline; +margin:0 18px 7px 0; +float:left; +} +#export_data li:first-child { +margin-left:0; +} + +#licenses { +font-size:0.9em; +} + +#licenses dt { +font-weight:bold; +display:none; +} +#licenses dd { +margin-bottom:11px; +line-height:1.5; +} + +#site_content_license_cc { +margin-bottom:0; +} +#site_content_license_cc img { +display:inline; +vertical-align:top; +margin-right:4px; +} + +#wrap { +margin:0 auto; +width: 763px; +min-width:760px; +max-width:1003px; +overflow:hidden; +} + +#core { +position:relative; +width:100%; +float:left; +margin-bottom:1em; +padding-top:10px; +} + +#content { +width:518px; +min-height:322px; +padding:20px; +float:left; +border-radius-topleft:4px; +-moz-border-radius-topleft:4px; +-webkit-border-top-left-radius:4px; +border-style:solid; +border-width:1px; +} + +#content_inner { +position:relative; +width:100%; +float:left; +} + +#aside_primary { +width:182px; +min-height:259px; +float:left; +margin-left:0; +padding:10px; +border-width:1px; +border-style:solid; +border-right:0; +border-top:0; +} + +#form_notice { +width:505px; +line-height:1; +position:absolute; +top:200px; +left:20px; +z-index:9; +} +#form_notice fieldset { +border:0; +padding:0 0 50px 0; +} +#form_notice legend { +display:none; +} +#form_notice textarea { +float:left; +width:505px; +height:45px; +line-height:1.5; +padding:5px; +border-width:1px; +} +#form_notice label { +display:block; +float:left; +font-size:1.3em; +margin-bottom:7px; +} +#form_notice #notice_submit label { +display:none; +} +#form_notice .form_note { +position:absolute; +top:-10px; +right:-10px; +z-index:9; +font-family:Georgia, serif; +font-size:1.7em; +} +#form_notice .form_note dt { +font-weight:bold; +display:none; +} +#notice_text-count { +font-weight:bold; +line-height:1.15; +padding:1px 2px; +} +#form_notice #notice_action-submit { +width:14%; +height:35px; +padding-top:0; +padding-bottom:0; +position:absolute; +bottom:10px; +right:-10px; +} +#form_notice label[for=to] { +margin-top:7px; +} +#form_notice select[id=to] { +margin-bottom:7px; +margin-left:18px; +float:left; +} + + +/* entity_profile */ +.entity_profile { +position:relative; +width:67.702%; +min-height:123px; +float:left; +margin-bottom:18px; +margin-left:0; +overflow:hidden; +} +.entity_profile dt, +#entity_statistics dt { +font-weight:bold; +} +.entity_profile dd { +display:inline; +} + +.entity_profile .entity_depiction { +float:left; +width:96px; +margin-right:18px; +margin-bottom:18px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:113px; +margin-bottom:4px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname { +margin-left:11px; +display:inline; +font-weight:bold; +} +.entity_profile .entity_nickname { +margin-left:0; +} + +.entity_profile .entity_fn dd:before { +content: "("; +font-weight:normal; +} +.entity_profile .entity_fn dd:after { +content: ")"; +font-weight:normal; +} + +.entity_profile dt { +display:none; +} +.entity_profile h2 { +display:none; +} +/* entity_profile */ + + +/*entity_actions*/ +.entity_actions { +float:right; +margin-left:4.35%; +max-width:25%; +} +.entity_actions h2 { +display:none; +} +.entity_actions ul { +list-style-type:none; +} +.entity_actions li { +margin-bottom:4px; +} +.entity_actions li:first-child { +border-top:0; +} +.entity_actions fieldset { +border:0; +padding:0; +} +.entity_actions legend { +display:none; +} + +.entity_actions input.submit { +display:block; +text-align:left; +width:100%; +} +.entity_actions a, +.entity_nudge p, +.entity_remote_subscribe { +text-decoration:none; +font-weight:bold; +display:block; +} + +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.entity_edit a, +.form_user_nudge input.submit, +.entity_nudge p { +border:0; +padding-left:20px; +} + +.entity_edit a, +.entity_send-a-message a, +.entity_nudge p { +padding:4px 4px 4px 23px; +} + +.entity_remote_subscribe { +padding:4px; +border-width:2px; +border-style:solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + + +.entity_tags ul { +list-style-type:none; +display:inline; +} +.entity_tags li { +display:inline; +margin-right:4px; +} + +.aside .section { +margin-bottom:18px; +clear:both; +float:left; +width:100%; +} +.aside .section h2 { +font-size:110%; +text-transform:none; +} + +#entity_statistics dt, +#entity_statistics dd { +display:inline; +} +#entity_statistics dt:after { +content: ":"; +} + +.section ul.entities { +float:left; +width:100%; +} +.section .entities li { +list-style-type:none; +float:left; +margin-right:7px; +margin-bottom:7px; +} +.section .entities li .photo { +margin-right:0; +margin-bottom:0; +} +.section .entities li .fn { +display:none; +} + +.aside .section p, +.aside .section .more { +clear:both; +} + +.profile .entity_profile { +margin-bottom:0; +min-height:60px; +} + + +.profile .form_group_join legend, +.profile .form_group_leave legend, +.profile .form_user_subscribe legend, +.profile .form_user_unsubscribe legend { +display:none; +} + +.profiles { +list-style-type:none; +} +.profile .entity_profile .entity_location { +width:auto; +clear:none; +margin-left:11px; +} +.profile .entity_profile dl, +.profile .entity_profile dd { +display:inline; +float:none; +} +.profile .entity_profile .entity_note, +.profile .entity_profile .entity_url, +.profile .entity_profile .entity_tags, +.profile .entity_profile .form_subscription_edit { +margin-left:59px; +clear:none; +display:block; +width:auto; +} +.profile .entity_profile .entity_tags dt { +display:inline; +margin-right:11px; +} + + +.profile .entity_profile .form_subscription_edit label { +font-weight:normal; +margin-right:11px; +} + + +/* NOTICE */ +.notice, +.profile { +position:relative; +padding-top:11px; +padding-bottom:11px; +clear:both; +float:left; +width:100%; +border-top-width:1px; +border-top-style:dotted; +font-size:1.2em; +} +.notices li { +list-style-type:none; +line-height:1.1; +width:94%; +padding-right:5%; +padding-left:1%; +min-height:47px; +} + + +/* NOTICES */ +#notices_primary { +float:left; +width:100%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +} +#notices_primary h2 { +display:none; +} +.notice-data a span { +display:block; +padding-left:28px; +} + +.notice .author { +margin-right:11px; +} + +.fn { +overflow:hidden; +} + +.notice .author .fn { +font-weight:bold; +} + +.notice .author .photo { +margin-bottom:0; +} + +.vcard .photo { +display:inline; +margin-right:11px; +margin-bottom:11px; +float:left; +} +.vcard .url { +text-decoration:none; +} +.vcard .url:hover { +text-decoration:underline; +} + +.notice .entry-title { +float:none; +display:inline; +width:100%; +overflow:hidden; +} +#shownotice .notice .entry-title { +font-size:2.2em; +} + +.notice p.entry-content { +display:inline; +} + +.notice p.entry-content .vcard a { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +.notice div.entry-content { +font-size:0.95em; +margin-left:59px; +margin-top:3px; +width:70%; +font-family:Georgia, serif; +font-style:italic; +font-size:0.8em; +display:block; +} +.notice div.entry-content a { +text-decoration:none; +} +.notice div.entry-content a:hover { +text-decoration:underline; +} +#showstream .notice div.entry-content { +margin-left:0; +} + +.notice .notice-options a, +.notice .notice-options input { +float:left; +font-size:1.025em; +} + +.notice div.entry-content dl, +.notice div.entry-content dt, +.notice div.entry-content dd { +display:inline; +} + +.notice div.entry-content .timestamp dt, +.notice div.entry-content .response dt { +display:none; +} +.notice div.entry-content .timestamp a { +display:inline-block; +} +.notice div.entry-content .device dt { +text-transform:lowercase; +} + + + +.notice-data { +position:absolute; +top:18px; +right:0; +min-height:50px; +margin-bottom:4px; +} +.notice .entry-content .notice-data dt { +display:none; +} + +.notice-data a { +display:block; +outline:none; +} + +.notice-options { +padding-left:2%; +float:left; +width:50%; +font-size:0.95em; +width:12.5%; +float:right; +display:none; +} +.notices li.hover div.notice-options { +display:block; +} + + +.notice-options a { +float:left; +} +.notice-options .notice_delete, +.notice-options .notice_reply, +.notice-options .form_favor, +.notice-options .form_disfavor { +position:absolute; +} +.notice-options .form_favor, +.notice-options .form_disfavor { +top:7px; +right:7px; +} +.notice-options .notice_reply { +top:30px; +right:7px; +} +.notice-options .notice_delete { +bottom:7px; +right:7px; +} +.notice-options .notice_reply dt { +display:none; +} + +.notice-options input, +.notice-options a { +text-indent:-9999px; +outline:none; +} + +.notice-options .notice_reply a, +.notice-options input.submit { +display:block; +border:0; +} +.notice-options .notice_reply a, +.notice-options .notice_delete a { +text-decoration:none; +padding-left:16px; +} + +.notice-options form input.submit { +width:16px; +padding:2px 0; +} + +.notice-options .notice_delete dt, +.notice-options .form_favor legend, +.notice-options .form_disfavor legend { +display:none; +} +.notice-options .notice_delete fieldset, +.notice-options .form_favor fieldset, +.notice-options .form_disfavor fieldset { +border:0; +padding:0; +} + + +#new_group, #group_search { +margin-bottom:18px; +} +#new_group a { +padding-left:20px; +} + + +#filter_tags { +margin-bottom:11px; +float:left; +} +#filter_tags dt { +display:none; +} +#filter_tags ul { +list-style-type:none; +} +#filter_tags ul li { +float:left; +margin-left:7px; +padding-left:7px; +border-left-width:1px; +border-left-style:solid; +} +#filter_tags ul li.child_1 { +margin-left:0; +border-left:0; +padding-left:0; +} +#filter_tags ul li#filter_tags_all a { +font-weight:bold; +margin-top:7px; +float:left; +} + +#filter_tags ul li#filter_tags_item label { +margin-right:7px; +} +#filter_tags ul li#filter_tags_item label, +#filter_tags ul li#filter_tags_item select { +display:inline; +} +#filter_tags ul li#filter_tags_item p { +float:left; +margin-left:38px; +} +#filter_tags ul li#filter_tags_item input { +position:relative; +top:3px; +left:3px; +} + + + +.pagination { +float:left; +clear:both; +width:100%; +margin-top:18px; +} + +.pagination dt { +font-weight:bold; +display:none; +} + +.pagination .nav { +float:left; +width:100%; +list-style-type:none; +} + +.pagination .nav_prev { +float:left; +} +.pagination .nav_next { +float:right; +} + +.pagination a { +display:block; +text-decoration:none; +font-weight:bold; +padding:7px; +border-width:1px; +border-style:solid; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-radius:7px; +} + +.pagination .nav_prev a { +padding-left:30px; +} +.pagination .nav_next a { +padding-right:30px; +} +/* END: NOTICE */ + + +.hentry .entry-content p { +margin-bottom:18px; +} +.hentry entry-content ol, +.hentry .entry-content ul { +list-style-position:inside; +} +.hentry .entry-content li { +margin-bottom:18px; +} +.hentry .entry-content li li { +margin-left:18px; +} + + + + +/* TOP_POSTERS */ +.section tbody td { +padding-right:11px; +padding-bottom:11px; +} +.section .vcard .photo { +margin-right:7px; +margin-bottom:0; +} + +.section .notice { +padding-top:7px; +padding-bottom:7px; +border-top:0; +} + +.section .notice:first-child { +padding-top:0; +} + +.section .notice .author { +margin-right:0; +} +.section .notice .author .fn { +display:none; +} + + +/* tagcloud */ +.tag-cloud { +list-style-type:none; +text-align:center; +} +.aside .tag-cloud { +font-size:0.8em; +} +.tag-cloud li { +display:inline; +margin-right:7px; +line-height:1.25; +} +.aside .tag-cloud li { +line-height:1.5; +} +.tag-cloud li a { +text-decoration:none; +} +#tagcloud.section dt { +text-transform:uppercase; +font-weight:bold; +} +.tag-cloud-1 { +font-size:1em; +} +.tag-cloud-2 { +font-size:1.25em; +} +.tag-cloud-3 { +font-size:1.75em; +} +.tag-cloud-4 { +font-size:2em; +} +.tag-cloud-5 { +font-size:2.25em; +} +.tag-cloud-6 { +font-size:2.75em; +} +.tag-cloud-7 { +font-size:3.25em; +} + +#publictagcloud #tagcloud.section dt { +display:none; +} + +#form_settings_photo .form_data { +clear:both; +} + +#form_settings_avatar li { +width:auto; +} +#form_settings_avatar input { +margin-left:0; +} +#avatar_original, +#avatar_preview { +float:left; +} +#avatar_preview { +margin-left:29px; +} +#avatar_preview_view { +height:96px; +width:96px; +margin-bottom:18px; +overflow:hidden; +} + +#settings_attach, +#form_settings_avatar .form_actions { +clear:both; +} + +#form_settings_avatar .form_actions { +margin-bottom:0; +} + +.instructions ul { +list-style-position:inside; +} +.instructions p, +.instructions ul { +margin-bottom:18px; +} +.help dt { +display:none; +} +.guide { +clear:both; +} + +#public.user_in #content, +#groups.user_in #content, +#publictagcloud.user_in #content, +#featured.user_in #content, +#favorited.user_in #content, +#all.user_in #content, +#replies.user_in #content, +#showstream.user_in #content, +#showfavorites.user_in #content, +#inbox.user_in #content, +#outbox.user_in #content, +#subscriptions.user_in #content, +#subscribers.user_in #content, +#showgroup.user_in #content { +padding-top:160px; +} + +#profilesettings #form_notice, +#avatarsettings #form_notice, +#passwordsettings #form_notice, +#emailsettings #form_notice, +#openidsettings #form_notice, +#othersettings #form_notice, +#smssettings #form_notice, +#twittersettings #form_notice, +#imsettings #form_notice, +#doc #form_notice, +#usergroups #form_notice, +#invite #form_notice, +#deletenotice #form_notice, +#newgroup #form_notice, +#register #form_notice, +#shownotice #form_notice, +#confirmaddress #form_notice, +#tag #form_notice { +display:none; +} diff --git a/theme/base/css/facebookapp.css b/theme/cloudy/base/css/facebookapp.css similarity index 100% rename from theme/base/css/facebookapp.css rename to theme/cloudy/base/css/facebookapp.css diff --git a/theme/base/css/ie.css b/theme/cloudy/base/css/ie.css similarity index 100% rename from theme/base/css/ie.css rename to theme/cloudy/base/css/ie.css diff --git a/theme/base/css/ie6.css b/theme/cloudy/base/css/ie6.css similarity index 100% rename from theme/base/css/ie6.css rename to theme/cloudy/base/css/ie6.css diff --git a/theme/base/css/jquery.Jcrop.css b/theme/cloudy/base/css/jquery.Jcrop.css similarity index 100% rename from theme/base/css/jquery.Jcrop.css rename to theme/cloudy/base/css/jquery.Jcrop.css diff --git a/theme/base/css/mobile.css b/theme/cloudy/base/css/mobile.css similarity index 100% rename from theme/base/css/mobile.css rename to theme/cloudy/base/css/mobile.css diff --git a/theme/base/css/print.css b/theme/cloudy/base/css/print.css similarity index 100% rename from theme/base/css/print.css rename to theme/cloudy/base/css/print.css diff --git a/theme/base/css/thickbox.css b/theme/cloudy/base/css/thickbox.css similarity index 100% rename from theme/base/css/thickbox.css rename to theme/cloudy/base/css/thickbox.css diff --git a/theme/base/images/icons/icon_atom.png b/theme/cloudy/base/images/icons/icon_atom.png similarity index 100% rename from theme/base/images/icons/icon_atom.png rename to theme/cloudy/base/images/icons/icon_atom.png diff --git a/theme/base/images/icons/icon_foaf.gif b/theme/cloudy/base/images/icons/icon_foaf.gif similarity index 100% rename from theme/base/images/icons/icon_foaf.gif rename to theme/cloudy/base/images/icons/icon_foaf.gif diff --git a/theme/base/images/icons/icon_processing.gif b/theme/cloudy/base/images/icons/icon_processing.gif similarity index 100% rename from theme/base/images/icons/icon_processing.gif rename to theme/cloudy/base/images/icons/icon_processing.gif diff --git a/theme/base/images/icons/icon_rss.png b/theme/cloudy/base/images/icons/icon_rss.png similarity index 100% rename from theme/base/images/icons/icon_rss.png rename to theme/cloudy/base/images/icons/icon_rss.png diff --git a/theme/base/images/icons/icon_vcard.gif b/theme/cloudy/base/images/icons/icon_vcard.gif similarity index 100% rename from theme/base/images/icons/icon_vcard.gif rename to theme/cloudy/base/images/icons/icon_vcard.gif diff --git a/theme/base/images/illustrations/illu_jcrop.gif b/theme/cloudy/base/images/illustrations/illu_jcrop.gif similarity index 100% rename from theme/base/images/illustrations/illu_jcrop.gif rename to theme/cloudy/base/images/illustrations/illu_jcrop.gif diff --git a/theme/base/images/illustrations/illu_progress_loading-01.gif b/theme/cloudy/base/images/illustrations/illu_progress_loading-01.gif similarity index 100% rename from theme/base/images/illustrations/illu_progress_loading-01.gif rename to theme/cloudy/base/images/illustrations/illu_progress_loading-01.gif diff --git a/theme/cloudy/default-avatar-mini.png b/theme/cloudy/default-avatar-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f1d411fdffd351fe16295c611f52d37be4fdf3 GIT binary patch literal 1006 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 JPDHLkV1gKF%uN6Q literal 0 HcmV?d00001 diff --git a/theme/identica/logo.png b/theme/cloudy/logo.png similarity index 100% rename from theme/identica/logo.png rename to theme/cloudy/logo.png diff --git a/theme/cloudy/skin/default/css/display.css b/theme/cloudy/skin/default/css/display.css new file mode 100644 index 0000000000..055e4fca20 --- /dev/null +++ b/theme/cloudy/skin/default/css/display.css @@ -0,0 +1,318 @@ +/** theme: twitter + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ +html, +body, +a:active { +background-color:#9AE4E8; +} +body { +font-family:'Lucida Grande',sans-serif; +background:#9AE4E8 url(../images/illustrations/illu_clouds-01.gif) 0 0 no-repeat; +color:#333333; +} +#core { +background:url(../images/illustrations/illu_arrow-up-01.gif) no-repeat 25px 0; +} + +input, textarea, select, option { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +} +input, textarea, select, +.entity_remote_subscribe { +border-color:#aaa; +} +#filter_tags ul li { +border-color:#ddd; +} + +.form_settings input.form_action-secondary { +background:none; +} + +input.submit, +#form_notice.warning #notice_text-count, +#nav_register a, +.form_settings .form_note, +.entity_remote_subscribe { +background-color:#9BB43E; +} + +input:focus, textarea:focus, select:focus, +#form_notice.warning #notice_data-text { +border-color:#9BB43E; +} +input.submit, +#nav_register a, +.entity_remote_subscribe { +color:#fff; +} + +a, +div.notice-options input, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.form_user_nudge input.submit, +.entity_nudge p, +.form_settings input.form_action-secondary { +color:#0084B4; +} + +.notice, +.profile { +border-top-color:#DDFFCC; +} +.section .profile { +border-top-color:#87B4C8; +} + + +#content .notice p.entry-content a:visited { +background-color:#fcfcfc; +} +#content .notice p.entry-content .vcard a { +background-color:#fcfffc; +} + +#aside_primary { +background-color:#DDFFCC; +} + + +#notice_text-count { +color:#333; +} +#form_notice.warning #notice_text-count { +color:#000; +} +#form_notice.processing #notice_action-submit { +background:#fff url(../../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +cursor:wait; +text-indent:-9999px; +} + +#content, +#site_nav_local_views a, +#aside_primary { +border-color:#fff; +} +#content, +#site_nav_local_views .current a { +background-color:#fff; +} + +#site_nav_local_views a { +background-color:rgba(135, 180, 200, 0.3); +} +#site_nav_local_views a:hover { +background-color:rgba(255, 255, 255, 0.7); +} + + +.error { +background-color:#F7E8E8; +} +.success { +background-color:#EFF3DC; +} + + +#anon_notice { +background-color:#FEFFDF; +color:#333; +border-color:#fff; +} + +#showstream #anon_notice { +background-color:#FEFFDF; +} + + +#export_data li a { +background-repeat:no-repeat; +background-position:0 45%; +} +#export_data li a.rss { +background-image:url(../../../base/images/icons/icon_rss.png); +} +#export_data li a.atom { +background-image:url(../../../base/images/icons/icon_atom.png); +} +#export_data li a.foaf { +background-image:url(../../../base/images/icons/icon_foaf.gif); +} + +.entity_edit a, +.entity_send-a-message a, +.form_user_nudge input.submit, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_nudge p { +background-position: 0 40%; +background-repeat: no-repeat; +background-color:transparent; +} +.form_group_join input.submit, +.form_group_leave input.submit +.form_user_subscribe input.submit, +.form_user_unsubscribe input.submit { +background-color:#9BB43E; +color:#fff; +} +.form_user_unsubscribe input.submit, +.form_group_leave input.submit { +background-color:#87B4C8; +} + +.entity_edit a { +background-image:url(../images/icons/twotone/green/edit.gif); +} +.entity_send-a-message a { +background-image:url(../images/icons/twotone/green/quote.gif); +} +.entity_nudge p, +.form_user_nudge input.submit { +background-image:url(../images/icons/twotone/green/mail.gif); +} +.form_user_block input.submit, +.form_user_unblock input.submit { +background-image:url(../images/icons/twotone/green/shield.gif); +} + + + +/* NOTICES */ +.notices li.over { +background-color:#fcfcfc; +} + +.notice-options .notice_reply a, +.notice-options form input.submit { +background-color:transparent; +} +.notice-options .notice_reply a { +background:transparent url(../images/icons/icon_reply.gif) no-repeat 0 45%; +} +.notice-options form.form_favor input.submit { +background:transparent url(../images/icons/icon_favourite.gif) no-repeat 0 45%; +} +.notice-options form.form_disfavor input.submit { +background:transparent url(../images/icons/icon_disfavourite.gif) no-repeat 0 45%; +} +.notice-options .notice_delete a { +background:transparent url(../images/icons/icon_trash.gif) no-repeat 0 45%; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:0.4; +} +.notices li.hover div.entry-content, +.notices li.hover div.notice-options { +opacity:1; +} +div.entry-content { +color:#333; +} +div.notice-options a, +div.notice-options input { +font-family:sans-serif; +} +.notices li.hover { +background-color:#fcfcfc; +} +/*END: NOTICES */ + + +#new_group a { +background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; +} +#usergroups #new_group { +float: left; +margin-right: 2em; +} + +.pagination .nav_prev a, +.pagination .nav_next a { +background-repeat:no-repeat; +border-color:#DDFFCC; +} +.pagination .nav_prev a { +background-image:url(../images/icons/twotone/green/arrow-left.gif); +background-position:10% 45%; +} +.pagination .nav_next a { +background-image:url(../images/icons/twotone/green/arrow-right.gif); +background-position:90% 45%; +} + + +/*--------------------------------------*/ + +#anon_notice { +background:url(../images/illustrations/illu_unicorn-01.png) no-repeat 0 0; +} +#showstream #anon_notice, +#content .notice p.entry-content a:visited, +content .notice p.entry-content .vcard a { +background-color:transparent; +} + +#anon_notice p { +background-color:#FEFFDF; +border-color:#FFFF00; +} + + +#form_notice .form_note { +color:#CCC; +} +input.submit { +background-color:#eee; +color:#666; +} + +.notices li.hover { +background-color:#F7F7F7; +} + + +.notice div.entry-content, +.notice div.entry-content a { +color:#999; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:1; +} + +#site_nav_local_views { +background-color:#DDFFCC; +} +#site_nav_local_views li, +#aside_primary { +border-color:#BDDCAD; +} +#site_nav_local_views a, +.aside .section h2 { +background-color:transparent; +border-color:transparent; +color:#4C4C4C; +} +#site_nav_local_views .current { +border-left-color:#fff; +} + +#site_nav_local_views .current a, +#site_nav_global_primary, +#footer { +background-color:#fff; +} + diff --git a/theme/cloudy/skin/default/css/ie.css b/theme/cloudy/skin/default/css/ie.css new file mode 100644 index 0000000000..0951221009 --- /dev/null +++ b/theme/cloudy/skin/default/css/ie.css @@ -0,0 +1,34 @@ +/* IE specific styles */ + +.notice-options input.submit { +color:#fff; +} + +#site_nav_local_views a { +background-color:#ddffcc; +} + +#aside_primary { +width:181px; +} + +#form_notice, +#anon_notice { +top:158px; +} + +#public #content, +#groups #content, +#publictagcloud #content, +#featured #content, +#favorited #content, +#all #content, +#replies #content, +#showstream #content, +#showfavorites #content, +#inbox #content, +#outbox #content, +#subscriptions #content, +#subscribers #content { +padding-top:138px; +} diff --git a/theme/default/images/icons/icon_atom.jpg b/theme/cloudy/skin/default/images/icons/icon_atom.jpg similarity index 100% rename from theme/default/images/icons/icon_atom.jpg rename to theme/cloudy/skin/default/images/icons/icon_atom.jpg diff --git a/theme/cloudy/skin/default/images/icons/icon_disfavourite.gif b/theme/cloudy/skin/default/images/icons/icon_disfavourite.gif new file mode 100644 index 0000000000000000000000000000000000000000..2b02ac8a6c75212efba9260be904e03f4c1fc77e GIT binary patch literal 701 zcmZ?wbhEHb6krfw_{PBS>;1i7Z?FA)ef{UFE5BZz{rTd=kLPE9JU#XO$;ls2j(vZ8 z`1`~C-ya;a>z&pApO}5Uwc+c{_5UAQe7(8&>y6d_ zADH}qVE*OCnlCq2eZ8^t|9z|f_YMEwv;240^8Y>4FV`0QyKDCMw&~}~GymN({d?2s z&ov-2{&a52=kwjauNeKhWb)&z-uKhyAC6UhJ8AL#l-|cDPp z+P>Qz^l5f?8OjkeZibt5mLJZ^xkclZBC;A(TM}6fmGHOu&`svg*{=Eu=4=Av}zvIkF(v&Jb+(}}Lq_a9jHu-k}exw&bJ jIQ57+IM}msd)wJ@cIXBQw#bG^bO=kZ78qyD;+ivPJId;=6*5=#<+bhCX$L1J=tssa@O7e2GNpca-Wq~@jADwQkQ+c7BqWMO1y zkYdmQxfB!(46Nk~)cT?vCum4nW_l+~zpzN)v&mA4W2zRqKy?bfeYk>KkPV^5qKq$d8z4wHO$qT90CmN!a}SJ j!af?@fnr?TVthhr8hnx#N=*Ec+?qT+D(v%>6d9}m>8^!| literal 0 HcmV?d00001 diff --git a/theme/default/images/icons/icon_foaf.gif b/theme/cloudy/skin/default/images/icons/icon_foaf.gif similarity index 100% rename from theme/default/images/icons/icon_foaf.gif rename to theme/cloudy/skin/default/images/icons/icon_foaf.gif diff --git a/theme/cloudy/skin/default/images/icons/icon_reply.gif b/theme/cloudy/skin/default/images/icons/icon_reply.gif new file mode 100644 index 0000000000000000000000000000000000000000..a4379a70b62b2f5fb3894d4fe37bbec2d48ff822 GIT binary patch literal 336 zcmZ?wbhEHb6krfw_{6}lb?esMyLTTxeE8Ikj=OT$TrAJ$;<|_}jm`@|bqKX+9)+}RS5LZKpX-F_Ih=wyT>@Y@%eGXz^1RB98cD^{x*a&PK zBaagU1M9v2|39lSFtATzVE8-n|Nq~M{{R2G7-$F39S3rfON+|DYJoZ#&oVH8-K+SM zg_D7SgFy!*1M)fpi<^LFx1^})fVNU=6 literal 0 HcmV?d00001 diff --git a/theme/default/images/icons/icon_rss.jpg b/theme/cloudy/skin/default/images/icons/icon_rss.jpg similarity index 100% rename from theme/default/images/icons/icon_rss.jpg rename to theme/cloudy/skin/default/images/icons/icon_rss.jpg diff --git a/theme/cloudy/skin/default/images/icons/icon_trash.gif b/theme/cloudy/skin/default/images/icons/icon_trash.gif new file mode 100644 index 0000000000000000000000000000000000000000..916a332a342a6556c4efce409fab9007de128728 GIT binary patch literal 148 zcmZ?wbhEHb6krfw_{_j?_3G8PZ{Oa(fB)jei??sz{`m3Zl`B^sJ$m%&)vL6$w3#z! z{{R1<0SPGnWMO1r;9<}KiGj>uU~!yq(sT9Rh;?&s#(DjSOqem}Sx_Tuk-#wn6|Jpv tD&lT?E#Tl{c+2#OvDJE>p@quVx-(CfaJUMI?wlO*`DLE<10NO!YXJHcKsf*a literal 0 HcmV?d00001 diff --git a/theme/default/images/icons/icon_vcard.gif b/theme/cloudy/skin/default/images/icons/icon_vcard.gif similarity index 100% rename from theme/default/images/icons/icon_vcard.gif rename to theme/cloudy/skin/default/images/icons/icon_vcard.gif diff --git a/theme/default/images/icons/twotone/green/arrow-left.gif b/theme/cloudy/skin/default/images/icons/twotone/green/arrow-left.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-left.gif rename to theme/cloudy/skin/default/images/icons/twotone/green/arrow-left.gif diff --git a/theme/default/images/icons/twotone/green/arrow-right.gif b/theme/cloudy/skin/default/images/icons/twotone/green/arrow-right.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-right.gif rename to theme/cloudy/skin/default/images/icons/twotone/green/arrow-right.gif diff --git a/theme/default/images/icons/twotone/green/edit.gif b/theme/cloudy/skin/default/images/icons/twotone/green/edit.gif similarity index 100% rename from theme/default/images/icons/twotone/green/edit.gif rename to theme/cloudy/skin/default/images/icons/twotone/green/edit.gif diff --git a/theme/default/images/icons/twotone/green/mail.gif b/theme/cloudy/skin/default/images/icons/twotone/green/mail.gif similarity index 100% rename from theme/default/images/icons/twotone/green/mail.gif rename to theme/cloudy/skin/default/images/icons/twotone/green/mail.gif diff --git a/theme/default/images/icons/twotone/green/news.gif b/theme/cloudy/skin/default/images/icons/twotone/green/news.gif similarity index 100% rename from theme/default/images/icons/twotone/green/news.gif rename to theme/cloudy/skin/default/images/icons/twotone/green/news.gif diff --git a/theme/default/images/icons/twotone/green/quote.gif b/theme/cloudy/skin/default/images/icons/twotone/green/quote.gif similarity index 100% rename from theme/default/images/icons/twotone/green/quote.gif rename to theme/cloudy/skin/default/images/icons/twotone/green/quote.gif diff --git a/theme/default/images/icons/twotone/green/shield.gif b/theme/cloudy/skin/default/images/icons/twotone/green/shield.gif similarity index 100% rename from theme/default/images/icons/twotone/green/shield.gif rename to theme/cloudy/skin/default/images/icons/twotone/green/shield.gif diff --git a/theme/cloudy/skin/default/images/illustrations/illu_arrow-up-01.gif b/theme/cloudy/skin/default/images/illustrations/illu_arrow-up-01.gif new file mode 100644 index 0000000000000000000000000000000000000000..577be18717b29f5d3533da39dd53b4ab7d1b6090 GIT binary patch literal 68 zcmZ?wbhEHb6lLIM_`tyM9}EBwT+d*8UO+w7mWY_ literal 0 HcmV?d00001 diff --git a/theme/cloudy/skin/default/images/illustrations/illu_clouds-01.gif b/theme/cloudy/skin/default/images/illustrations/illu_clouds-01.gif new file mode 100644 index 0000000000000000000000000000000000000000..41cd622cf07bf319bfea4178d6d3bbf30b17fd83 GIT binary patch literal 14251 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 OIyOrxehC2qJo-P%;mQX9 literal 0 HcmV?d00001 diff --git a/theme/cloudy/skin/default/images/illustrations/illu_unicorn-01.png b/theme/cloudy/skin/default/images/illustrations/illu_unicorn-01.png new file mode 100644 index 0000000000000000000000000000000000000000..6cb51b298f9380ad97389b24fa525de4d988dea3 GIT binary patch literal 5695 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∾g0mw;Lf^E!-f;T_czl z83BZb;@suSFqM^|qN3slHN@fJVGsaFqN1?qT^_*L9Jnw%9IUk2!1x0I%RpopJdm0S zkJ|%I5Fof*NKh&v4+#arWiWMh!Dg{w`~weQYeB(XlNJEvaye2{Q&Ck_g^Y|0oIiga zJv}{$j*iCOy?YTB8j7Qh4gdYxs#U(R27rz9`+aHv!7?7f9ET8w!BA~2n6@^gB_v>O zLITWIE1CgZvDx5_h(PM&kHhWr;p2}#zAZ?j(O}J*HBhV7cPe376ciL-{rdITvu6(y z6B7Xde!m~V!NFh{29ik5dpSXNN>o%JF*+KF@o`9uk4Iu`ET&AD00qaP;@UOT3|bL9 zZ5kYXeTW6XSgmk49N4mXGbHIBdH2jS&mcE97e3#eLG*gPShj2#7A{U1B0`csvLT4S{oD0HGEO=IZrm zYHo&Z?p*BJwF@UoO1>e;VzHp3qvK{F_!eq!Z^z=ri{Wy)zQI3s>=;BzL~`Pk^#J}j zRtLC@1q=RNu-oJk0X{*1I6MqTPYS;>eLBFq_Ri zwKY{qSu3(#qt1adEiKBH{sC09b)ep613PIFJSr75EQ<*q57H76Aov6%Joq5C6&8M{ z@c^)4!v>g4CKMMJL!;4*+JV~ITC}#dB0W8Q0?Wx(Z`@!A9rX!ZEGZe`d0r)oB6v~4 z?D&a*Pq+yyf`U-d-;bGTX~=l~d7Lf zYSG=@eG|6V)nRye7(CBIub;LS!25U20dO4Wb~vGv$uLu)K-z;3!tC`znUsvo%*=bj zIYmW9NKQ_M+vmG+=}O(-^vTJ1<&`@F8WR(P4?g$+k&%%Afcf+1BO@aNk|ZGz2#g9+ zu<7yf?uX;!V0XJwJ>tT3pAR$U%)yGREF3<3c+AF!hlgX_xN-1$y<{Eed(~tz6^f#W zmtTGv0HD=sA(P!4>$JAE!sT*d)22-TfEhDpAS){iXV0D;eJB3XY?fW>?SqTwku+@@ zwByHP>C&Y*dhFQPp)JGUrI%j9lqpkisjlw&b4&l_oJ=N}YHnztqM{2zaG*jraz zTpU>}7P49g1AjYurKP3a-ltZpX~~i$v|~pR zb#|GlrKQEQ_ru)>M&-bnlPA4hW;4C@)?37J+&vo)fb#P4h={1Zp|Ss#{4HCy#2h(t zUzP#St)jwo^HEa3ry2b?N^78Y^X0zRwDYe(@y;(uznzz0=U)mr5c>3$S z9Xoa`XIWNGMDCR zB6N0kcpSamJwMtX4vj`5{gA{3Kn%ms^5x5ki0F&b(y|}(4-K!?Y6Bd{{h(J#rBWgL l)oj@9cKC%r;Ky{}e*uq|^1Yj?ak>Bi002ovPDHLkV1kMw=Rp7f literal 0 HcmV?d00001 diff --git a/theme/base/css/display.css b/theme/default/base/css/display.css similarity index 100% rename from theme/base/css/display.css rename to theme/default/base/css/display.css diff --git a/theme/default/base/css/facebookapp.css b/theme/default/base/css/facebookapp.css new file mode 100644 index 0000000000..163b41fb4c --- /dev/null +++ b/theme/default/base/css/facebookapp.css @@ -0,0 +1,100 @@ +@import url("display.css"); +@import url("../../identica/css/display.css"); + +* { +font-size:14px; +font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif; +} + +#wrap { +background-color:#F0F2F5; +padding-left:18px; +padding-right:18px; +width:auto; +} + +p,label, +h1,h2,h3,h4,h5,h6 { +color:#000; +} + +#content { +width:95%; +} + +#site_nav_local_views a { +background-color:#D0DFE7; +} +#site_nav_local_views a:hover { +background-color:#FAFBFC; +} + +span.facebook-button { +border: 2px solid #aaa; +padding: 3px; +display: block; +float: left; +margin-right: 20px; +-moz-border-radius: 4px; +border-radius:4px; +-webkit-border-radius:4px; +font-weight: bold; +background-color:#A9BF4F; +color:#fff; +font-size:1.2em +} + +span.facebook-button a { color:#fff } + +.facebook_guide { +margin-bottom:18px; +} +.facebook_guide p { +font-weight:bold; +} + + +input { +height:auto !important; +} + +#facebook-friends { +float:left; +width:100%; +} + +#facebook-friends li { +float:left; +margin-right:2%; +margin-bottom:11px; +width:18%; +height:115px; +} +#facebook-friends li a { +float:left; +} + +#add_to_profile { +position:absolute; +right:18px; +top:10px; +z-index:2; +} + +.notice div.entry-content dl, +.notice div.entry-content dt, +.notice div.entry-content dd { +margin-right:5px; +} + +#content_inner p { +margin-bottom:18px; +} + +#content_inner ul { +list-style-type:none; +} + +.form_settings label { +margin-right:18px; +} diff --git a/theme/default/base/css/ie.css b/theme/default/base/css/ie.css new file mode 100644 index 0000000000..5d8bea8ae3 --- /dev/null +++ b/theme/default/base/css/ie.css @@ -0,0 +1,32 @@ +/* IE specific styles */ +legend { +margin-left:-7px; +} +input.checkbox { +top:0; +} +#form_notice textarea { +width:78%; +} +#form_notice #notice_action-submit { +width:17%; +max-width:17%; +} +#anon_notice { +max-width:39%; +} + +.notice-options input.submit { +font-size:0; +margin-top:3px; +height:16px; +text-align:right; +text-indent:0; +width:24px; +} +.notice div.entry-content .timestamp a { +margin-right:4px; +} +.entity_profile { +width:64%; +} diff --git a/theme/default/base/css/ie6.css b/theme/default/base/css/ie6.css new file mode 100644 index 0000000000..76a82c0042 --- /dev/null +++ b/theme/default/base/css/ie6.css @@ -0,0 +1,30 @@ +/* IE6 specific styles */ +address { +margin-left:7px; +} +address .fn { +display:none; +} +#content { +width:70%; +} +#aside_primary { +padding:5%; +width:29.5%; +} +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:0; +} +.entity_profile .entity_depiction { +margin-bottom:123px; +} +.entity_actions { +width:20%; +} +.notice div.entry-content { +width:63%; +} diff --git a/theme/default/base/css/jquery.Jcrop.css b/theme/default/base/css/jquery.Jcrop.css new file mode 100644 index 0000000000..6c6dfb503e --- /dev/null +++ b/theme/default/base/css/jquery.Jcrop.css @@ -0,0 +1,45 @@ +/* Fixes issue here http://code.google.com/p/jcrop/issues/detail?id=1 */ +.jcrop-holder +{ + text-align: left; +} + +.jcrop-vline, .jcrop-hline +{ + font-size: 0; + position: absolute; + background: #fff url(../images/illustrations/illu_jcrop.gif) top left repeat; + /* + opacity: .5; + *filter:alpha(opacity=50); + */ +} +.jcrop-vline { height: 100%; width: 1px !important; } +.jcrop-hline { width: 100%; height: 1px !important; } +.jcrop-handle { + font-size: 1px; + width: 7px !important; + height: 7px !important; + border: 1px #eee solid; + background-color: #333; + /*width: 9px; + height: 9px;*/ +} + +.jcrop-tracker { + /*background-color: gray;*/ + width: 100%; height: 100%; +} + +.custom .jcrop-vline, +.custom .jcrop-hline +{ + background: yellow; +} +.custom .jcrop-handle +{ + border-color: black; + background-color: #C7BB00; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} diff --git a/theme/default/base/css/mobile.css b/theme/default/base/css/mobile.css new file mode 100644 index 0000000000..eee98317cc --- /dev/null +++ b/theme/default/base/css/mobile.css @@ -0,0 +1,150 @@ +/** theme: base + * + * @package Laconica + * @author Meitar Moscovitz + * @author Sarven Capadisli + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +body { +font-size:2.5em; +} + +#wrap { +width:95%; +} + +#header, +#header address, +#anon_notice, +#site_nav_local_views .nav, +#form_notice, +#form_notice .form_data li, +#core, +#content_inner, +#notices_primary, +.notice, +.notice .entry-title, +.notice div.entry-content, +.notice-options, +.notice .notice-options a, +.pagination, +.pagination .nav, +.aside .section { +float:none; +} + +.notice-options .notice_reply, +.notice-options .notice_delete, +.notice-options .form_favor, +.notice-options .form_disfavor { +position:static; +} + +#form_notice, +#anon_notice, +#footer, +#form_notice .form_actions input.submit { +width:auto; +} + +.form_settings label { +width:25%; +} +.form_settings .form_data p.form_guide { +margin-left:26%; +} + +#site_nav_global_primary { +width:75%; +} + +.entity_profile { +width:65%; +} +.entity_actions { +margin-left:0; +} + +#form_notice, +#anon_notice { +clear:both; +} + +#content, +#aside_primary { +width:96%; +padding-left:2%; +padding-right:2%; +} + +#site_notice { +position:static; +float:right; +clear:right; +width:75%; +margin-right:0; +margin-bottom:11px; +} + +.notices { +font-size:1.5em; +} + +#form_notice textarea { +width:80%; +height:5em; +} +#form_notice .form_note { +right:20%; +top:6em; +} + + +.vcard .photo, +.section .vcard .photo { +margin-right:18px; +} +.notice, +.profile { +margin-bottom:18px; +} + +.notices .entry-title, +.notices div.entry-content { +width:90%; +} +.notice div.entry-content { +margin-left:0; +} + +.notice .author .photo { +height:4.5em; +width:4.5em; +} +.notice-options { +position:absolute; +top:0; +right:0; +padding-left:7%; +width:3%; +} + +.notice-options .notice_delete a { +float:left; +} +.pagination .nav { +overflow:auto; +} + +#export_data { +display:none; +} + +#site_nav_local_views li { +margin-right:4px; +} +#site_nav_local_views a { +padding:18px 11px; +} diff --git a/theme/default/base/css/print.css b/theme/default/base/css/print.css new file mode 100644 index 0000000000..d76dd608c4 --- /dev/null +++ b/theme/default/base/css/print.css @@ -0,0 +1,36 @@ +/** theme: base + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +a:after { background-color:#fff; } +a:not([href^="#"]):after { content:" ( "attr(href)" ) "; } + +img { border:none; } +p { orphans: 2; widows: 1; } + +#site_nav_global_primary, +#site_nav_local_views, +#form_notice, +.pagination, +#site_nav_global_secondary, +.entity_actions, +.notice-options, +#aside_primary, +.form_subscription_edit .submit { +display:none; +} + +.timestamp dt, .timestamp dd, +.device dt, .device dd { +display:inline; +} + +.profiles li, +.notices li { +margin-bottom:18px; +} diff --git a/theme/default/base/css/thickbox.css b/theme/default/base/css/thickbox.css new file mode 100644 index 0000000000..d24b9bedff --- /dev/null +++ b/theme/default/base/css/thickbox.css @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------------------------------------------*/ +/* ---------->>> global settings needed for thickbox <<<-----------------------------------------------------------*/ +/* ----------------------------------------------------------------------------------------------------------------*/ +*{padding: 0; margin: 0;} + +/* ----------------------------------------------------------------------------------------------------------------*/ +/* ---------->>> thickbox specific link and font settings <<<------------------------------------------------------*/ +/* ----------------------------------------------------------------------------------------------------------------*/ +#TB_window { + font: 12px Arial, Helvetica, sans-serif; + color: #333333; +} + +#TB_secondLine { + font: 10px Arial, Helvetica, sans-serif; + color:#666666; +} + +#TB_window a:link {color: #666666;} +#TB_window a:visited {color: #666666;} +#TB_window a:hover {color: #000;} +#TB_window a:active {color: #666666;} +#TB_window a:focus{color: #666666;} + +/* ----------------------------------------------------------------------------------------------------------------*/ +/* ---------->>> thickbox settings <<<-----------------------------------------------------------------------------*/ +/* ----------------------------------------------------------------------------------------------------------------*/ +#TB_overlay { + position: fixed; + z-index:100; + top: 0px; + left: 0px; + height:100%; + width:100%; +} + +.TB_overlayMacFFBGHack {background: url(macFFBgHack.png) repeat;} +.TB_overlayBG { + background-color:#000; + filter:alpha(opacity=75); + -moz-opacity: 0.75; + opacity: 0.75; +} + +* html #TB_overlay { /* ie6 hack */ + position: absolute; + height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); +} + +#TB_window { + position: fixed; + background: #ffffff; + z-index: 102; + color:#000000; + display:none; + border: 4px solid #525252; + text-align:left; + top:50%; + left:50%; +} + +* html #TB_window { /* ie6 hack */ +position: absolute; +margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px'); +} + +#TB_window img#TB_Image { + display:block; + margin: 15px 0 0 15px; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + border-top: 1px solid #666; + border-left: 1px solid #666; +} + +#TB_caption{ + height:25px; + padding:7px 30px 10px 25px; + float:left; +} + +#TB_closeWindow{ + height:25px; + padding:11px 25px 10px 0; + float:right; +} + +#TB_closeAjaxWindow{ + padding:7px 10px 5px 0; + margin-bottom:1px; + text-align:right; + float:right; +} + +#TB_ajaxWindowTitle{ + float:left; + padding:7px 0 5px 10px; + margin-bottom:1px; +} + +#TB_title{ + background-color:#e8e8e8; + height:27px; +} + +#TB_ajaxContent{ + clear:both; + padding:2px 15px 15px 15px; + overflow:auto; + text-align:left; + line-height:1.4em; +} + +#TB_ajaxContent.TB_modal{ + padding:15px; +} + +#TB_ajaxContent p{ + padding:5px 0px 5px 0px; +} + +#TB_load{ + position: fixed; + display:none; + height:13px; + width:208px; + z-index:103; + top: 50%; + left: 50%; + margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */ +} + +* html #TB_load { /* ie6 hack */ +position: absolute; +margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px'); +} + +#TB_HideSelect{ + z-index:99; + position:fixed; + top: 0; + left: 0; + background-color:#fff; + border:none; + filter:alpha(opacity=0); + -moz-opacity: 0; + opacity: 0; + height:100%; + width:100%; +} + +* html #TB_HideSelect { /* ie6 hack */ + position: absolute; + height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); +} + +#TB_iframeContent{ + clear:both; + border:none; + margin-bottom:-1px; + margin-top:1px; + _margin-bottom:1px; +} diff --git a/theme/default/base/images/icons/icon_atom.png b/theme/default/base/images/icons/icon_atom.png new file mode 100644 index 0000000000000000000000000000000000000000..6a001f11aa7d0ea8d7bccdd97c85adaa42457f8b GIT binary patch literal 820 zcmV-41Izr0P)Px%?ny*JR5;5$kv(r5RTzbz``(Y)*jC; z;iadSFk12Z(G07Fj?*|RI4w{35I)rULNrBT-}6Z@8k`oa6|51S8I-)fIiR#c01jpz zXEcQoj8+t`gAeg-V~q@wQdliqJ>SO~;b`XB9QHVx2aG5#t&~I{wop1DwUBa)vwCQZ zC<=Af`p%2%ESHA;X~VEj?2z0dARO`Bm@T71Za*kX(poY5GqSnXP#S}3?To^yX%vooow z;u&k3;nj=hD2?Watr1Pg)Zy{JyC*eQ20g66?VSnpCh~9=@G%qqmz8{Ms>*+TS~WMy z!aWZAkojj;aZ8QqJIx;tW;7uaQYM5JpE6cjf^TkWuDtQ%La(zCVmj|b?9b~!RR?Mx y**mG&Iyxo9M9!I+Z`3#dv5h=E26FfcG1 zbL_hF&)}42ws10s6^G;;cE1^EoUR)U5A70}d2pLv!jVIT7j&Z~EblI3x0K*v_sV|m z0kj3v921Z^em#l`(k(o@H$3ZdDRc@9NidXDNbqrumReCGv$gd8+e8WW28HVqkJ_9i zH>s*<31KtHjANIPvi2#*6BEu%3Dak5O_t&NBI)H?V$TxT}#l{vOTn5naXTfF^&~Hhq+NX@#Ccc>y7T?;vjI&jdhsDsPJyAw*m0Qz>i}K7# zL9w50Ng{fT}A5JUe8lRK1h7_Y2;BWJDd=c6f&i?Wv5(5q?6|P zQw{>maxZP<537OA37Uk}7@%_$4o$EWe_Zl>&#id|lE-BpDC#+Fn|msJ%_2h{Hg1vP z#N8WAzfWasG}yq|xqE)DrWaOofX=z|?*pgc%{ig5vl!pqDlC|q&~Z0$&Rvsft&VO- z4MZj+%-+Vx%W}v;V76hyp=;+R;x+~t^Q%*xuFTQAF2})fSfTHDAs>sO!OBw`)&)o$ c0!CNZt))x~rAZP^^P&YOFfdqy5)K#u0POD40{{R3 literal 0 HcmV?d00001 diff --git a/theme/default/base/images/icons/icon_rss.png b/theme/default/base/images/icons/icon_rss.png new file mode 100644 index 0000000000000000000000000000000000000000..0ccd1ce254370ad278a4c4cc9d0484b72a564bf5 GIT binary patch literal 777 zcmV+k1NQuhP)Px%!%0LzR5;6Rl1*q_RTRg6=YG7-OhcR0yaBbHq>YL~HBhUSRMCZ^P~EsNU9^n| zg$BAP+9E=6p)ULYw-Q$oR8S%msiI34f{@14el1$Dme4j#lNr%;CU4%m_qdoe7~4!#4zcGjyL5v^*Vu01Rps04*#X{po{lv~s{`^cXj1P`g z@2yQ{i%qN(j5k;>7`Oh46^!i`?}RefX0MLP+{xW_T3NcGI>5#!N71D^Vg4d<{yfI& z|H5J*bd*M2>&_*Qt2ak;xOfdQ@Cx9u7is#q5+Zl_eRv_?KNKQ#!dL0`|yvwhLn0C7KEQaAisEe z6%JV>HzkZ1FiuEnkFe>;DJn02jKBYB!liG>zur&0`70QQ-TNj~cdf!j7D2&?tTf3x zOz&3Qj;BbTeVfwgmq<@a`0*I=`WY~e4KKV)q)d@TVy?uf7*-U}xI%X7D8!%3-DtktW(GoflqW;H%75wlk_-9TcNtw>~Z=kIvX7g6ugD=vW{ua$Mq|}2O+)d0C zRk{|$3N{_Wjl7O|U>~w;oZ_zr+00h}_=lb&wAy69PXmzDhKYruT?MGI0?SS4ECCP~ zuTf-?&Xr#PaMd9~uH?7o0I-{@#6m$u<@!61*Zc3bsThd zkN})Ly!~LcmVV@%trC$Kx}P+z&8T*d*ZSWJi^m_Hxcd3O7Vc(}fM=Q^00000NkvXX Hu0mjfyta1= literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/icon_vcard.gif b/theme/default/base/images/icons/icon_vcard.gif similarity index 100% rename from theme/identica/images/icons/icon_vcard.gif rename to theme/default/base/images/icons/icon_vcard.gif diff --git a/theme/default/base/images/illustrations/illu_jcrop.gif b/theme/default/base/images/illustrations/illu_jcrop.gif new file mode 100644 index 0000000000000000000000000000000000000000..72ea7ccb5321d5384d70437cfaac73011237901e GIT binary patch literal 329 zcmZ?wbhEHb9b#5NV>2k zBC~b@b~P=nNfWAe-b%_i6tS^-1y(h@EsB~1TqDA_h@fkxG$bHgvj}VxE1JLgr!*!^ ILUxTc0Q$^Q5C8xG literal 0 HcmV?d00001 diff --git a/theme/default/base/images/illustrations/illu_progress_loading-01.gif b/theme/default/base/images/illustrations/illu_progress_loading-01.gif new file mode 100644 index 0000000000000000000000000000000000000000..82290f48334c81272ff5991962951758137a08ba GIT binary patch literal 5886 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 Dl)1NK literal 0 HcmV?d00001 diff --git a/theme/default/logo.png b/theme/default/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7c68b34f61008753d12394806c3cf46f7b04effd GIT binary patch literal 4988 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 literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/icon_rss.jpg b/theme/default/skin/default/images/icons/icon_rss.jpg similarity index 100% rename from theme/identica/images/icons/icon_rss.jpg rename to theme/default/skin/default/images/icons/icon_rss.jpg diff --git a/theme/default/skin/default/images/icons/icon_vcard.gif b/theme/default/skin/default/images/icons/icon_vcard.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d52947f3e96c0f74f00a80b430f99695e110e5e GIT binary patch literal 331 zcmV-R0kr-{Nk%w1VHW@n0K^{vi^LV;@6MUi1^D~(*6OmW*GsnCZu9x+db$Rr+7rg( zj*Y_!l*MRc(@bU8V@GBo706UV+d;tIe literal 0 HcmV?d00001 diff --git a/theme/default/images/icons/twotone/green/against.gif b/theme/default/skin/default/images/icons/twotone/green/against.gif similarity index 100% rename from theme/default/images/icons/twotone/green/against.gif rename to theme/default/skin/default/images/icons/twotone/green/against.gif diff --git a/theme/default/images/icons/twotone/green/arrow-down.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-down.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-down.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-down.gif diff --git a/theme/default/images/icons/twotone/green/arrow-downleft.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-downleft.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-downleft.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-downleft.gif diff --git a/theme/default/images/icons/twotone/green/arrow-downright.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-downright.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-downright.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-downright.gif diff --git a/theme/identica/images/icons/twotone/green/arrow-left.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-left.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-left.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-left.gif diff --git a/theme/identica/images/icons/twotone/green/arrow-right.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-right.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-right.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-right.gif diff --git a/theme/default/images/icons/twotone/green/arrow-up.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-up.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-up.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-up.gif diff --git a/theme/default/images/icons/twotone/green/arrow-upleft.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-upleft.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-upleft.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-upleft.gif diff --git a/theme/default/images/icons/twotone/green/arrow-upright.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-upright.gif similarity index 100% rename from theme/default/images/icons/twotone/green/arrow-upright.gif rename to theme/default/skin/default/images/icons/twotone/green/arrow-upright.gif diff --git a/theme/default/images/icons/twotone/green/back-forth.gif b/theme/default/skin/default/images/icons/twotone/green/back-forth.gif similarity index 100% rename from theme/default/images/icons/twotone/green/back-forth.gif rename to theme/default/skin/default/images/icons/twotone/green/back-forth.gif diff --git a/theme/default/images/icons/twotone/green/bookmark.gif b/theme/default/skin/default/images/icons/twotone/green/bookmark.gif similarity index 100% rename from theme/default/images/icons/twotone/green/bookmark.gif rename to theme/default/skin/default/images/icons/twotone/green/bookmark.gif diff --git a/theme/default/images/icons/twotone/green/bulb.gif b/theme/default/skin/default/images/icons/twotone/green/bulb.gif similarity index 100% rename from theme/default/images/icons/twotone/green/bulb.gif rename to theme/default/skin/default/images/icons/twotone/green/bulb.gif diff --git a/theme/default/images/icons/twotone/green/calendar.gif b/theme/default/skin/default/images/icons/twotone/green/calendar.gif similarity index 100% rename from theme/default/images/icons/twotone/green/calendar.gif rename to theme/default/skin/default/images/icons/twotone/green/calendar.gif diff --git a/theme/default/images/icons/twotone/green/calendar2.gif b/theme/default/skin/default/images/icons/twotone/green/calendar2.gif similarity index 100% rename from theme/default/images/icons/twotone/green/calendar2.gif rename to theme/default/skin/default/images/icons/twotone/green/calendar2.gif diff --git a/theme/default/images/icons/twotone/green/camera.gif b/theme/default/skin/default/images/icons/twotone/green/camera.gif similarity index 100% rename from theme/default/images/icons/twotone/green/camera.gif rename to theme/default/skin/default/images/icons/twotone/green/camera.gif diff --git a/theme/default/images/icons/twotone/green/cart.gif b/theme/default/skin/default/images/icons/twotone/green/cart.gif similarity index 100% rename from theme/default/images/icons/twotone/green/cart.gif rename to theme/default/skin/default/images/icons/twotone/green/cart.gif diff --git a/theme/default/images/icons/twotone/green/caution.gif b/theme/default/skin/default/images/icons/twotone/green/caution.gif similarity index 100% rename from theme/default/images/icons/twotone/green/caution.gif rename to theme/default/skin/default/images/icons/twotone/green/caution.gif diff --git a/theme/default/images/icons/twotone/green/chart.gif b/theme/default/skin/default/images/icons/twotone/green/chart.gif similarity index 100% rename from theme/default/images/icons/twotone/green/chart.gif rename to theme/default/skin/default/images/icons/twotone/green/chart.gif diff --git a/theme/default/images/icons/twotone/green/checkmark.gif b/theme/default/skin/default/images/icons/twotone/green/checkmark.gif similarity index 100% rename from theme/default/images/icons/twotone/green/checkmark.gif rename to theme/default/skin/default/images/icons/twotone/green/checkmark.gif diff --git a/theme/default/images/icons/twotone/green/clipboard.gif b/theme/default/skin/default/images/icons/twotone/green/clipboard.gif similarity index 100% rename from theme/default/images/icons/twotone/green/clipboard.gif rename to theme/default/skin/default/images/icons/twotone/green/clipboard.gif diff --git a/theme/default/images/icons/twotone/green/clock.gif b/theme/default/skin/default/images/icons/twotone/green/clock.gif similarity index 100% rename from theme/default/images/icons/twotone/green/clock.gif rename to theme/default/skin/default/images/icons/twotone/green/clock.gif diff --git a/theme/default/images/icons/twotone/green/closed-folder.gif b/theme/default/skin/default/images/icons/twotone/green/closed-folder.gif similarity index 100% rename from theme/default/images/icons/twotone/green/closed-folder.gif rename to theme/default/skin/default/images/icons/twotone/green/closed-folder.gif diff --git a/theme/default/images/icons/twotone/green/database.gif b/theme/default/skin/default/images/icons/twotone/green/database.gif similarity index 100% rename from theme/default/images/icons/twotone/green/database.gif rename to theme/default/skin/default/images/icons/twotone/green/database.gif diff --git a/theme/default/images/icons/twotone/green/disfavourite.gif b/theme/default/skin/default/images/icons/twotone/green/disfavourite.gif similarity index 100% rename from theme/default/images/icons/twotone/green/disfavourite.gif rename to theme/default/skin/default/images/icons/twotone/green/disfavourite.gif diff --git a/theme/default/images/icons/twotone/green/diskette.gif b/theme/default/skin/default/images/icons/twotone/green/diskette.gif similarity index 100% rename from theme/default/images/icons/twotone/green/diskette.gif rename to theme/default/skin/default/images/icons/twotone/green/diskette.gif diff --git a/theme/default/images/icons/twotone/green/document.gif b/theme/default/skin/default/images/icons/twotone/green/document.gif similarity index 100% rename from theme/default/images/icons/twotone/green/document.gif rename to theme/default/skin/default/images/icons/twotone/green/document.gif diff --git a/theme/default/images/icons/twotone/green/double-arrow.gif b/theme/default/skin/default/images/icons/twotone/green/double-arrow.gif similarity index 100% rename from theme/default/images/icons/twotone/green/double-arrow.gif rename to theme/default/skin/default/images/icons/twotone/green/double-arrow.gif diff --git a/theme/identica/images/icons/twotone/green/edit.gif b/theme/default/skin/default/images/icons/twotone/green/edit.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/edit.gif rename to theme/default/skin/default/images/icons/twotone/green/edit.gif diff --git a/theme/default/images/icons/twotone/green/eject.gif b/theme/default/skin/default/images/icons/twotone/green/eject.gif similarity index 100% rename from theme/default/images/icons/twotone/green/eject.gif rename to theme/default/skin/default/images/icons/twotone/green/eject.gif diff --git a/theme/default/images/icons/twotone/green/exclaim.gif b/theme/default/skin/default/images/icons/twotone/green/exclaim.gif similarity index 100% rename from theme/default/images/icons/twotone/green/exclaim.gif rename to theme/default/skin/default/images/icons/twotone/green/exclaim.gif diff --git a/theme/default/images/icons/twotone/green/fastforward.gif b/theme/default/skin/default/images/icons/twotone/green/fastforward.gif similarity index 100% rename from theme/default/images/icons/twotone/green/fastforward.gif rename to theme/default/skin/default/images/icons/twotone/green/fastforward.gif diff --git a/theme/default/images/icons/twotone/green/favourite.gif b/theme/default/skin/default/images/icons/twotone/green/favourite.gif similarity index 100% rename from theme/default/images/icons/twotone/green/favourite.gif rename to theme/default/skin/default/images/icons/twotone/green/favourite.gif diff --git a/theme/default/images/icons/twotone/green/flag.gif b/theme/default/skin/default/images/icons/twotone/green/flag.gif similarity index 100% rename from theme/default/images/icons/twotone/green/flag.gif rename to theme/default/skin/default/images/icons/twotone/green/flag.gif diff --git a/theme/default/images/icons/twotone/green/graph.gif b/theme/default/skin/default/images/icons/twotone/green/graph.gif similarity index 100% rename from theme/default/images/icons/twotone/green/graph.gif rename to theme/default/skin/default/images/icons/twotone/green/graph.gif diff --git a/theme/default/images/icons/twotone/green/grow.gif b/theme/default/skin/default/images/icons/twotone/green/grow.gif similarity index 100% rename from theme/default/images/icons/twotone/green/grow.gif rename to theme/default/skin/default/images/icons/twotone/green/grow.gif diff --git a/theme/default/images/icons/twotone/green/headphones.gif b/theme/default/skin/default/images/icons/twotone/green/headphones.gif similarity index 100% rename from theme/default/images/icons/twotone/green/headphones.gif rename to theme/default/skin/default/images/icons/twotone/green/headphones.gif diff --git a/theme/default/images/icons/twotone/green/home.gif b/theme/default/skin/default/images/icons/twotone/green/home.gif similarity index 100% rename from theme/default/images/icons/twotone/green/home.gif rename to theme/default/skin/default/images/icons/twotone/green/home.gif diff --git a/theme/default/images/icons/twotone/green/hourglass.gif b/theme/default/skin/default/images/icons/twotone/green/hourglass.gif similarity index 100% rename from theme/default/images/icons/twotone/green/hourglass.gif rename to theme/default/skin/default/images/icons/twotone/green/hourglass.gif diff --git a/theme/default/images/icons/twotone/green/info.gif b/theme/default/skin/default/images/icons/twotone/green/info.gif similarity index 100% rename from theme/default/images/icons/twotone/green/info.gif rename to theme/default/skin/default/images/icons/twotone/green/info.gif diff --git a/theme/default/images/icons/twotone/green/key.gif b/theme/default/skin/default/images/icons/twotone/green/key.gif similarity index 100% rename from theme/default/images/icons/twotone/green/key.gif rename to theme/default/skin/default/images/icons/twotone/green/key.gif diff --git a/theme/default/images/icons/twotone/green/lock.gif b/theme/default/skin/default/images/icons/twotone/green/lock.gif similarity index 100% rename from theme/default/images/icons/twotone/green/lock.gif rename to theme/default/skin/default/images/icons/twotone/green/lock.gif diff --git a/theme/identica/images/icons/twotone/green/mail.gif b/theme/default/skin/default/images/icons/twotone/green/mail.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/mail.gif rename to theme/default/skin/default/images/icons/twotone/green/mail.gif diff --git a/theme/default/images/icons/twotone/green/move.gif b/theme/default/skin/default/images/icons/twotone/green/move.gif similarity index 100% rename from theme/default/images/icons/twotone/green/move.gif rename to theme/default/skin/default/images/icons/twotone/green/move.gif diff --git a/theme/default/images/icons/twotone/green/music.gif b/theme/default/skin/default/images/icons/twotone/green/music.gif similarity index 100% rename from theme/default/images/icons/twotone/green/music.gif rename to theme/default/skin/default/images/icons/twotone/green/music.gif diff --git a/theme/identica/images/icons/twotone/green/news.gif b/theme/default/skin/default/images/icons/twotone/green/news.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/news.gif rename to theme/default/skin/default/images/icons/twotone/green/news.gif diff --git a/theme/default/images/icons/twotone/green/note.gif b/theme/default/skin/default/images/icons/twotone/green/note.gif similarity index 100% rename from theme/default/images/icons/twotone/green/note.gif rename to theme/default/skin/default/images/icons/twotone/green/note.gif diff --git a/theme/default/images/icons/twotone/green/open-folder.gif b/theme/default/skin/default/images/icons/twotone/green/open-folder.gif similarity index 100% rename from theme/default/images/icons/twotone/green/open-folder.gif rename to theme/default/skin/default/images/icons/twotone/green/open-folder.gif diff --git a/theme/default/images/icons/twotone/green/paper-clip.gif b/theme/default/skin/default/images/icons/twotone/green/paper-clip.gif similarity index 100% rename from theme/default/images/icons/twotone/green/paper-clip.gif rename to theme/default/skin/default/images/icons/twotone/green/paper-clip.gif diff --git a/theme/default/images/icons/twotone/green/paper-clip2.gif b/theme/default/skin/default/images/icons/twotone/green/paper-clip2.gif similarity index 100% rename from theme/default/images/icons/twotone/green/paper-clip2.gif rename to theme/default/skin/default/images/icons/twotone/green/paper-clip2.gif diff --git a/theme/default/images/icons/twotone/green/pause.gif b/theme/default/skin/default/images/icons/twotone/green/pause.gif similarity index 100% rename from theme/default/images/icons/twotone/green/pause.gif rename to theme/default/skin/default/images/icons/twotone/green/pause.gif diff --git a/theme/default/images/icons/twotone/green/phone.gif b/theme/default/skin/default/images/icons/twotone/green/phone.gif similarity index 100% rename from theme/default/images/icons/twotone/green/phone.gif rename to theme/default/skin/default/images/icons/twotone/green/phone.gif diff --git a/theme/default/images/icons/twotone/green/play.gif b/theme/default/skin/default/images/icons/twotone/green/play.gif similarity index 100% rename from theme/default/images/icons/twotone/green/play.gif rename to theme/default/skin/default/images/icons/twotone/green/play.gif diff --git a/theme/default/images/icons/twotone/green/plus.gif b/theme/default/skin/default/images/icons/twotone/green/plus.gif similarity index 100% rename from theme/default/images/icons/twotone/green/plus.gif rename to theme/default/skin/default/images/icons/twotone/green/plus.gif diff --git a/theme/default/images/icons/twotone/green/print.gif b/theme/default/skin/default/images/icons/twotone/green/print.gif similarity index 100% rename from theme/default/images/icons/twotone/green/print.gif rename to theme/default/skin/default/images/icons/twotone/green/print.gif diff --git a/theme/default/images/icons/twotone/green/question-mark.gif b/theme/default/skin/default/images/icons/twotone/green/question-mark.gif similarity index 100% rename from theme/default/images/icons/twotone/green/question-mark.gif rename to theme/default/skin/default/images/icons/twotone/green/question-mark.gif diff --git a/theme/identica/images/icons/twotone/green/quote.gif b/theme/default/skin/default/images/icons/twotone/green/quote.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/quote.gif rename to theme/default/skin/default/images/icons/twotone/green/quote.gif diff --git a/theme/default/images/icons/twotone/green/refresh.gif b/theme/default/skin/default/images/icons/twotone/green/refresh.gif similarity index 100% rename from theme/default/images/icons/twotone/green/refresh.gif rename to theme/default/skin/default/images/icons/twotone/green/refresh.gif diff --git a/theme/default/images/icons/twotone/green/reply.gif b/theme/default/skin/default/images/icons/twotone/green/reply.gif similarity index 100% rename from theme/default/images/icons/twotone/green/reply.gif rename to theme/default/skin/default/images/icons/twotone/green/reply.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/repost.gif b/theme/default/skin/default/images/icons/twotone/green/repost.gif new file mode 100644 index 0000000000000000000000000000000000000000..1fab5dcc7fe1dfd3a75d9dc886df5f38d4000dea GIT binary patch literal 87 zcmZ?wbhEHb6krfwSjfom|NsB^DFP6r_>+Z^fq{uZhXDvc@(fHGA$>EKz2#t<@&1gr k?6jS+w?iK-pOA3ERiJ7ef0ygV@3|(aU3`n#ofsLc0gB=r!2kdN literal 0 HcmV?d00001 diff --git a/theme/default/images/icons/twotone/green/rewind.gif b/theme/default/skin/default/images/icons/twotone/green/rewind.gif similarity index 100% rename from theme/default/images/icons/twotone/green/rewind.gif rename to theme/default/skin/default/images/icons/twotone/green/rewind.gif diff --git a/theme/default/images/icons/twotone/green/search.gif b/theme/default/skin/default/images/icons/twotone/green/search.gif similarity index 100% rename from theme/default/images/icons/twotone/green/search.gif rename to theme/default/skin/default/images/icons/twotone/green/search.gif diff --git a/theme/identica/images/icons/twotone/green/shield.gif b/theme/default/skin/default/images/icons/twotone/green/shield.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/shield.gif rename to theme/default/skin/default/images/icons/twotone/green/shield.gif diff --git a/theme/default/images/icons/twotone/green/skip-back.gif b/theme/default/skin/default/images/icons/twotone/green/skip-back.gif similarity index 100% rename from theme/default/images/icons/twotone/green/skip-back.gif rename to theme/default/skin/default/images/icons/twotone/green/skip-back.gif diff --git a/theme/default/images/icons/twotone/green/skip.gif b/theme/default/skin/default/images/icons/twotone/green/skip.gif similarity index 100% rename from theme/default/images/icons/twotone/green/skip.gif rename to theme/default/skin/default/images/icons/twotone/green/skip.gif diff --git a/theme/default/images/icons/twotone/green/skull.gif b/theme/default/skin/default/images/icons/twotone/green/skull.gif similarity index 100% rename from theme/default/images/icons/twotone/green/skull.gif rename to theme/default/skin/default/images/icons/twotone/green/skull.gif diff --git a/theme/default/images/icons/twotone/green/statusbar.gif b/theme/default/skin/default/images/icons/twotone/green/statusbar.gif similarity index 100% rename from theme/default/images/icons/twotone/green/statusbar.gif rename to theme/default/skin/default/images/icons/twotone/green/statusbar.gif diff --git a/theme/default/images/icons/twotone/green/stop.gif b/theme/default/skin/default/images/icons/twotone/green/stop.gif similarity index 100% rename from theme/default/images/icons/twotone/green/stop.gif rename to theme/default/skin/default/images/icons/twotone/green/stop.gif diff --git a/theme/default/images/icons/twotone/green/template.gif b/theme/default/skin/default/images/icons/twotone/green/template.gif similarity index 100% rename from theme/default/images/icons/twotone/green/template.gif rename to theme/default/skin/default/images/icons/twotone/green/template.gif diff --git a/theme/default/images/icons/twotone/green/text-bigger.gif b/theme/default/skin/default/images/icons/twotone/green/text-bigger.gif similarity index 100% rename from theme/default/images/icons/twotone/green/text-bigger.gif rename to theme/default/skin/default/images/icons/twotone/green/text-bigger.gif diff --git a/theme/default/images/icons/twotone/green/text-smaller.gif b/theme/default/skin/default/images/icons/twotone/green/text-smaller.gif similarity index 100% rename from theme/default/images/icons/twotone/green/text-smaller.gif rename to theme/default/skin/default/images/icons/twotone/green/text-smaller.gif diff --git a/theme/default/images/icons/twotone/green/trash.gif b/theme/default/skin/default/images/icons/twotone/green/trash.gif similarity index 100% rename from theme/default/images/icons/twotone/green/trash.gif rename to theme/default/skin/default/images/icons/twotone/green/trash.gif diff --git a/theme/default/images/icons/twotone/green/two-docs.gif b/theme/default/skin/default/images/icons/twotone/green/two-docs.gif similarity index 100% rename from theme/default/images/icons/twotone/green/two-docs.gif rename to theme/default/skin/default/images/icons/twotone/green/two-docs.gif diff --git a/theme/default/images/icons/twotone/green/twotone.gif b/theme/default/skin/default/images/icons/twotone/green/twotone.gif similarity index 100% rename from theme/default/images/icons/twotone/green/twotone.gif rename to theme/default/skin/default/images/icons/twotone/green/twotone.gif diff --git a/theme/default/images/icons/twotone/green/undo.gif b/theme/default/skin/default/images/icons/twotone/green/undo.gif similarity index 100% rename from theme/default/images/icons/twotone/green/undo.gif rename to theme/default/skin/default/images/icons/twotone/green/undo.gif diff --git a/theme/default/images/icons/twotone/green/user.gif b/theme/default/skin/default/images/icons/twotone/green/user.gif similarity index 100% rename from theme/default/images/icons/twotone/green/user.gif rename to theme/default/skin/default/images/icons/twotone/green/user.gif diff --git a/theme/default/images/icons/twotone/green/vegetable.gif b/theme/default/skin/default/images/icons/twotone/green/vegetable.gif similarity index 100% rename from theme/default/images/icons/twotone/green/vegetable.gif rename to theme/default/skin/default/images/icons/twotone/green/vegetable.gif diff --git a/theme/default/images/icons/twotone/green/x.gif b/theme/default/skin/default/images/icons/twotone/green/x.gif similarity index 100% rename from theme/default/images/icons/twotone/green/x.gif rename to theme/default/skin/default/images/icons/twotone/green/x.gif diff --git a/theme/default/images/icons/twotone/green/zoom-in.gif b/theme/default/skin/default/images/icons/twotone/green/zoom-in.gif similarity index 100% rename from theme/default/images/icons/twotone/green/zoom-in.gif rename to theme/default/skin/default/images/icons/twotone/green/zoom-in.gif diff --git a/theme/default/images/icons/twotone/green/zoom-out.gif b/theme/default/skin/default/images/icons/twotone/green/zoom-out.gif similarity index 100% rename from theme/default/images/icons/twotone/green/zoom-out.gif rename to theme/default/skin/default/images/icons/twotone/green/zoom-out.gif diff --git a/theme/identica/css/display.css b/theme/default/skin/identica/css/display.css similarity index 94% rename from theme/identica/css/display.css rename to theme/default/skin/identica/css/display.css index 8edb005a68..44ff2c9e85 100644 --- a/theme/identica/css/display.css +++ b/theme/default/skin/identica/css/display.css @@ -90,7 +90,7 @@ color:#333; color:#000; } #form_notice.processing #notice_action-submit { -background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +background:#fff url(../../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; cursor:wait; text-indent:-9999px; } @@ -137,13 +137,13 @@ background-repeat:no-repeat; background-position:0 45%; } #export_data li a.rss { -background-image:url(../../base/images/icons/icon_rss.png); +background-image:url(../../../base/images/icons/icon_rss.png); } #export_data li a.atom { -background-image:url(../../base/images/icons/icon_atom.png); +background-image:url(../../../base/images/icons/icon_atom.png); } #export_data li a.foaf { -background-image:url(../../base/images/icons/icon_foaf.gif); +background-image:url(../../../base/images/icons/icon_foaf.gif); } .entity_edit a, diff --git a/theme/identica/css/ie.css b/theme/default/skin/identica/css/ie.css similarity index 100% rename from theme/identica/css/ie.css rename to theme/default/skin/identica/css/ie.css diff --git a/theme/default/skin/identica/images/icons/icon_atom.jpg b/theme/default/skin/identica/images/icons/icon_atom.jpg new file mode 100644 index 0000000000000000000000000000000000000000..22853edc43ff04778001d28e5e14e64b32693f05 GIT binary patch literal 1117 zcmex=xE0R}-11_1^EW=25anV3L`8Hkvf zSy(w(Sy@>Qk2+yV?tKuefdm_beh zs;mXdF|Y`-3Mm>ovIz$!vMUve7&T5@$f4}C@t|nX#SbdRNkvVZTw>x9l2WQ_>Kd9_ zCZ=ZQ7M51dF0O9w9-dyoA)#U65s^{JDXD4c8JStdC8cHM6_r)ZEv;?s9i3g1CQq3< zZTgIvvlcC0vUJ(<6)RV5+Pr1!w(UE1?mBe%$kAiRPnGGAU*RJ2VdF$b$$4{O< zd;a3(tB;>PfBE|D`;VW$7#Wx$-T{&r{s9I*BNGb?GYdP&Ka5P}K+G)2!m4P(ZXWYowZ;xuvL#)F*7#z7xMlZq~KiK&=8RQ(9@64*z?d8mmjAHh8Y_s{=Z3_Q$? zz+}TL$Y9U#^*!s4{C`4kQ@{F)F8#NE<^7nNX{$BEX7;OWE|d3v8oxYgwT`W+-_*q- z+uzjLw=VzM)weYJobTH^U)E+Hs>*NOQoXkN(6;Tf#Fj2Ov+-`EuiCfmW$ej|9|&k>x-`dJy*iwaIS@snEOaP0Pi8o%z1YZ)MKM zRh|Np+Y=60roJjLZm^p5YSuI*^Cmyt+P{5LF*_nZUCA@@&Al93&$PVvpTfaM*5M!4 zAAY>*^{;80%VnnTYCTgO_i(zRpnz~I%X9Ugp$`rGx_=#0x)>OxdU^ku>!Q7(i@)aR QKG!^Hc0cZ<-tqr80k4%pzW@LL literal 0 HcmV?d00001 diff --git a/theme/default/skin/identica/images/icons/icon_foaf.gif b/theme/default/skin/identica/images/icons/icon_foaf.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8f78442355bf0d0b509536bca7c57b4eedab04a GIT binary patch literal 1144 zcmd^;?N1ta0Dyn!iB*(>T3&i*JrF8R7w1whHElM8C<3ml?j+W9-3dwyO`2L|HqDkn z5%F#4%5=zqhahRU8WmVVw{A%ro6Wr`PE6ceVj2??L*}%}w$5a?_V3v9;raf2cvR|! zleHa30UP`^2O^P(TCHAKSg=~He14Hqsif%uZ8F&hVl+)kq!MMLzPTBX#bWfui_Upx zD&?A({APN6nl_tVpScF^4um#Ch!`OgWH@Z1X>XUc>*oB;p^^I*kHugxqzIz#MkuV+ z27e0fbavY2Z0Yob-EJpWNrkE-kx0z`GV7<3B)Q`M(a*|fwO?ze5|oczl~rJTgzvcP zz!1czQbk)^OUg=ic0LdYc>Kb`Zg=9odT3ob5qn5U- zZT@vXO;3k^3m?hNp^{WgtIf?~Vi*>WTf)DFYicA*OYfDHpIEwZfu=*Xwa2whum5W{ zlO!obgc%u(w8@kv2n>cj-+78r7)Id$weIzL7Z!R>!0^-*v5e!F&8~w3Z(YM%0)Y@I zE{Nm!F$q#$j-}IMH89-M7w}AdKk~&$^8EQ0k%;<%3Q);-{B4CovDekr^qO&h-@R)# zADB!U?U`h6#s5A^?%aeE|u=?euQDt>S{El*K_kZ{mxHA zKZiIhc5pN3^BG3p|I*eU;lW3AS9DcXD27Q~_gwCYuVpe!2=hknj|h-5S$U0@T;=iD z)k0w^HAb$Gi#YE0tpNaNntta0C!(hi1AsYD`8@ym6W|aH&PB`*h_CXP`B1cFukIl$ zs|1(%WPd!$fVg5p|HQsAS^bi1b0#pP6%J=GW{H{G^{kf%TYUG<8ipXeV7Bse-~cv| zbFQln4K0m}iaXIuv5tC2w(J<*7GbcULq^Pkw5D#|;fUDp4ksPTyrZ@I+X3#gFQA-x zk0&Fbfm(V`Kb^8?Lhb_Ijq8^l&o~_g;dlNH1SJ|q-7P$;xu;vu8g;$-KF`Z%EK&)8HeT>g)Y#vUAp}MLgmL1PV~(!a7HD+ zI?Nr*lXC$Eu30nL$d)62zg!{*uVkS>^T@WwmwfEeqXVc$01lsS6Nu{>3~=f{5zlh9 literal 0 HcmV?d00001 diff --git a/theme/default/skin/identica/images/icons/icon_rss.jpg b/theme/default/skin/identica/images/icons/icon_rss.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da23422d0616d0d2925545214c2591b78dd1d6cb GIT binary patch literal 1166 zcmex=Qa5@J#!Vq&6< zKy9o*9jvTeqI^7je4?a+|3?@XF)%Q)GJ*jxbisg;3FsI$b`DN1ZUF`+pe0N!%pj)$ zRn`LK7+3^Zg%k}P*@OcV*_8@Kj2b5{ECr+Nabot8FYu9hwy!G(W<0ns_ zJ%91?)yGetzkL1n{m0K=j10^W?*K^*{{VxZk%@(cnS~wXA4aBfAZ8Y1VO2C_6LJh> zPb?HxGHT=yahkYr<3Ubk6e=l{~ZV&R(P($<#Tc_eT}|Zsr;?yuxz;gdKo>o08iH_ez(7J*Xx$0_w2DP{4nd=rPuyD z`a)(@-l|)kedxsE9m)%3QmU^v_nh7s>82){>G!efn0MO#wHIGL{c+0jtmNgD(xyum zefR%$bCwl<_gg!Wm##8d)9z_*-yNvB?~T)ip1kmw&vVT4op{R=4C8OwoLuR)CoA_` zOx3bo_v7ZyN>|fo)OqB&T-^0={g$N{mw&I*Tx@-;&iYcF!b_?4mOt{Tt77hWuXV3n z?EbBWV{xfmmW=#VXK{s+mvPsWMca>EoX5{A_C9zP*X`J>JyYMgG3%|L9@=ItsMRc(@bU8V@GBo706UV+d;tIe literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/twotone/green/against.gif b/theme/default/skin/identica/images/icons/twotone/green/against.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/against.gif rename to theme/default/skin/identica/images/icons/twotone/green/against.gif diff --git a/theme/identica/images/icons/twotone/green/arrow-down.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-down.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-down.gif rename to theme/default/skin/identica/images/icons/twotone/green/arrow-down.gif diff --git a/theme/identica/images/icons/twotone/green/arrow-downleft.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-downleft.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-downleft.gif rename to theme/default/skin/identica/images/icons/twotone/green/arrow-downleft.gif diff --git a/theme/identica/images/icons/twotone/green/arrow-downright.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-downright.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-downright.gif rename to theme/default/skin/identica/images/icons/twotone/green/arrow-downright.gif diff --git a/theme/default/skin/identica/images/icons/twotone/green/arrow-left.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-left.gif new file mode 100644 index 0000000000000000000000000000000000000000..afed190841f8b88f930d0dfe7030339f8aea296c GIT binary patch literal 73 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b*`erVB%fEOI ZBSY5uGcnueIVwI2eAel8Mn#0d8UQdZ7iIte literal 0 HcmV?d00001 diff --git a/theme/default/skin/identica/images/icons/twotone/green/arrow-right.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-right.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee1707ed96a315d287e778dd7650fdad9f5ccc55 GIT binary patch literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%fEOI a2ZPj`+FkFTWlpxJyV1Ff%b1gu!5RQfjTe{z literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/twotone/green/arrow-up.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-up.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-up.gif rename to theme/default/skin/identica/images/icons/twotone/green/arrow-up.gif diff --git a/theme/identica/images/icons/twotone/green/arrow-upleft.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-upleft.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-upleft.gif rename to theme/default/skin/identica/images/icons/twotone/green/arrow-upleft.gif diff --git a/theme/identica/images/icons/twotone/green/arrow-upright.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-upright.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/arrow-upright.gif rename to theme/default/skin/identica/images/icons/twotone/green/arrow-upright.gif diff --git a/theme/identica/images/icons/twotone/green/back-forth.gif b/theme/default/skin/identica/images/icons/twotone/green/back-forth.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/back-forth.gif rename to theme/default/skin/identica/images/icons/twotone/green/back-forth.gif diff --git a/theme/identica/images/icons/twotone/green/bookmark.gif b/theme/default/skin/identica/images/icons/twotone/green/bookmark.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/bookmark.gif rename to theme/default/skin/identica/images/icons/twotone/green/bookmark.gif diff --git a/theme/identica/images/icons/twotone/green/bulb.gif b/theme/default/skin/identica/images/icons/twotone/green/bulb.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/bulb.gif rename to theme/default/skin/identica/images/icons/twotone/green/bulb.gif diff --git a/theme/identica/images/icons/twotone/green/calendar.gif b/theme/default/skin/identica/images/icons/twotone/green/calendar.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/calendar.gif rename to theme/default/skin/identica/images/icons/twotone/green/calendar.gif diff --git a/theme/identica/images/icons/twotone/green/calendar2.gif b/theme/default/skin/identica/images/icons/twotone/green/calendar2.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/calendar2.gif rename to theme/default/skin/identica/images/icons/twotone/green/calendar2.gif diff --git a/theme/identica/images/icons/twotone/green/camera.gif b/theme/default/skin/identica/images/icons/twotone/green/camera.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/camera.gif rename to theme/default/skin/identica/images/icons/twotone/green/camera.gif diff --git a/theme/identica/images/icons/twotone/green/cart.gif b/theme/default/skin/identica/images/icons/twotone/green/cart.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/cart.gif rename to theme/default/skin/identica/images/icons/twotone/green/cart.gif diff --git a/theme/identica/images/icons/twotone/green/caution.gif b/theme/default/skin/identica/images/icons/twotone/green/caution.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/caution.gif rename to theme/default/skin/identica/images/icons/twotone/green/caution.gif diff --git a/theme/identica/images/icons/twotone/green/chart.gif b/theme/default/skin/identica/images/icons/twotone/green/chart.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/chart.gif rename to theme/default/skin/identica/images/icons/twotone/green/chart.gif diff --git a/theme/identica/images/icons/twotone/green/checkmark.gif b/theme/default/skin/identica/images/icons/twotone/green/checkmark.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/checkmark.gif rename to theme/default/skin/identica/images/icons/twotone/green/checkmark.gif diff --git a/theme/identica/images/icons/twotone/green/clipboard.gif b/theme/default/skin/identica/images/icons/twotone/green/clipboard.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/clipboard.gif rename to theme/default/skin/identica/images/icons/twotone/green/clipboard.gif diff --git a/theme/identica/images/icons/twotone/green/clock.gif b/theme/default/skin/identica/images/icons/twotone/green/clock.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/clock.gif rename to theme/default/skin/identica/images/icons/twotone/green/clock.gif diff --git a/theme/identica/images/icons/twotone/green/closed-folder.gif b/theme/default/skin/identica/images/icons/twotone/green/closed-folder.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/closed-folder.gif rename to theme/default/skin/identica/images/icons/twotone/green/closed-folder.gif diff --git a/theme/identica/images/icons/twotone/green/database.gif b/theme/default/skin/identica/images/icons/twotone/green/database.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/database.gif rename to theme/default/skin/identica/images/icons/twotone/green/database.gif diff --git a/theme/identica/images/icons/twotone/green/disfavourite.gif b/theme/default/skin/identica/images/icons/twotone/green/disfavourite.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/disfavourite.gif rename to theme/default/skin/identica/images/icons/twotone/green/disfavourite.gif diff --git a/theme/identica/images/icons/twotone/green/diskette.gif b/theme/default/skin/identica/images/icons/twotone/green/diskette.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/diskette.gif rename to theme/default/skin/identica/images/icons/twotone/green/diskette.gif diff --git a/theme/identica/images/icons/twotone/green/document.gif b/theme/default/skin/identica/images/icons/twotone/green/document.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/document.gif rename to theme/default/skin/identica/images/icons/twotone/green/document.gif diff --git a/theme/identica/images/icons/twotone/green/double-arrow.gif b/theme/default/skin/identica/images/icons/twotone/green/double-arrow.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/double-arrow.gif rename to theme/default/skin/identica/images/icons/twotone/green/double-arrow.gif diff --git a/theme/default/skin/identica/images/icons/twotone/green/edit.gif b/theme/default/skin/identica/images/icons/twotone/green/edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..c746aca601dfce71bec63cc34bd2cea576a608c6 GIT binary patch literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%fFb# bLC#BkUBTx**BG_BS(!^$or-W`WUvMRPNf%3 literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/twotone/green/eject.gif b/theme/default/skin/identica/images/icons/twotone/green/eject.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/eject.gif rename to theme/default/skin/identica/images/icons/twotone/green/eject.gif diff --git a/theme/identica/images/icons/twotone/green/exclaim.gif b/theme/default/skin/identica/images/icons/twotone/green/exclaim.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/exclaim.gif rename to theme/default/skin/identica/images/icons/twotone/green/exclaim.gif diff --git a/theme/identica/images/icons/twotone/green/fastforward.gif b/theme/default/skin/identica/images/icons/twotone/green/fastforward.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/fastforward.gif rename to theme/default/skin/identica/images/icons/twotone/green/fastforward.gif diff --git a/theme/identica/images/icons/twotone/green/favourite.gif b/theme/default/skin/identica/images/icons/twotone/green/favourite.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/favourite.gif rename to theme/default/skin/identica/images/icons/twotone/green/favourite.gif diff --git a/theme/identica/images/icons/twotone/green/flag.gif b/theme/default/skin/identica/images/icons/twotone/green/flag.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/flag.gif rename to theme/default/skin/identica/images/icons/twotone/green/flag.gif diff --git a/theme/identica/images/icons/twotone/green/graph.gif b/theme/default/skin/identica/images/icons/twotone/green/graph.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/graph.gif rename to theme/default/skin/identica/images/icons/twotone/green/graph.gif diff --git a/theme/identica/images/icons/twotone/green/grow.gif b/theme/default/skin/identica/images/icons/twotone/green/grow.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/grow.gif rename to theme/default/skin/identica/images/icons/twotone/green/grow.gif diff --git a/theme/identica/images/icons/twotone/green/headphones.gif b/theme/default/skin/identica/images/icons/twotone/green/headphones.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/headphones.gif rename to theme/default/skin/identica/images/icons/twotone/green/headphones.gif diff --git a/theme/identica/images/icons/twotone/green/home.gif b/theme/default/skin/identica/images/icons/twotone/green/home.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/home.gif rename to theme/default/skin/identica/images/icons/twotone/green/home.gif diff --git a/theme/identica/images/icons/twotone/green/hourglass.gif b/theme/default/skin/identica/images/icons/twotone/green/hourglass.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/hourglass.gif rename to theme/default/skin/identica/images/icons/twotone/green/hourglass.gif diff --git a/theme/identica/images/icons/twotone/green/info.gif b/theme/default/skin/identica/images/icons/twotone/green/info.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/info.gif rename to theme/default/skin/identica/images/icons/twotone/green/info.gif diff --git a/theme/identica/images/icons/twotone/green/key.gif b/theme/default/skin/identica/images/icons/twotone/green/key.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/key.gif rename to theme/default/skin/identica/images/icons/twotone/green/key.gif diff --git a/theme/identica/images/icons/twotone/green/lock.gif b/theme/default/skin/identica/images/icons/twotone/green/lock.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/lock.gif rename to theme/default/skin/identica/images/icons/twotone/green/lock.gif diff --git a/theme/default/skin/identica/images/icons/twotone/green/mail.gif b/theme/default/skin/identica/images/icons/twotone/green/mail.gif new file mode 100644 index 0000000000000000000000000000000000000000..1084c862f62fd5490abc582fcfe7b577d450efff GIT binary patch literal 82 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=s`erVB%fEQa if?KZ~c0{bs%Z(FiQZABxslH78RN`eH|DIR|25SH{2phKm literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/twotone/green/move.gif b/theme/default/skin/identica/images/icons/twotone/green/move.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/move.gif rename to theme/default/skin/identica/images/icons/twotone/green/move.gif diff --git a/theme/identica/images/icons/twotone/green/music.gif b/theme/default/skin/identica/images/icons/twotone/green/music.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/music.gif rename to theme/default/skin/identica/images/icons/twotone/green/music.gif diff --git a/theme/default/skin/identica/images/icons/twotone/green/news.gif b/theme/default/skin/identica/images/icons/twotone/green/news.gif new file mode 100644 index 0000000000000000000000000000000000000000..712c685dc0b02b2bfd262e9007b7a8ce0f81e2e8 GIT binary patch literal 76 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F6`erVB%dgDh c(B`#%N#&>iH4Co$il+Z^fq{uZhXDvc@(fHGA$>EKz2#t<@&1gr k?6jS+w?iK-pOA3ERiJ7ef0ygV@3|(aU3`n#ofsLc0gB=r!2kdN literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/twotone/green/rewind.gif b/theme/default/skin/identica/images/icons/twotone/green/rewind.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/rewind.gif rename to theme/default/skin/identica/images/icons/twotone/green/rewind.gif diff --git a/theme/identica/images/icons/twotone/green/search.gif b/theme/default/skin/identica/images/icons/twotone/green/search.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/search.gif rename to theme/default/skin/identica/images/icons/twotone/green/search.gif diff --git a/theme/default/skin/identica/images/icons/twotone/green/shield.gif b/theme/default/skin/identica/images/icons/twotone/green/shield.gif new file mode 100644 index 0000000000000000000000000000000000000000..419d5ee4be0c57121049c616e8ef6bf6dc736e3e GIT binary patch literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%Xy&L m=u~<0*$KCf<=zp@TOe*ZbEQ(w>ZOy#&cDmB_R$kzum%90svYG3 literal 0 HcmV?d00001 diff --git a/theme/identica/images/icons/twotone/green/skip-back.gif b/theme/default/skin/identica/images/icons/twotone/green/skip-back.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/skip-back.gif rename to theme/default/skin/identica/images/icons/twotone/green/skip-back.gif diff --git a/theme/identica/images/icons/twotone/green/skip.gif b/theme/default/skin/identica/images/icons/twotone/green/skip.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/skip.gif rename to theme/default/skin/identica/images/icons/twotone/green/skip.gif diff --git a/theme/identica/images/icons/twotone/green/skull.gif b/theme/default/skin/identica/images/icons/twotone/green/skull.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/skull.gif rename to theme/default/skin/identica/images/icons/twotone/green/skull.gif diff --git a/theme/identica/images/icons/twotone/green/statusbar.gif b/theme/default/skin/identica/images/icons/twotone/green/statusbar.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/statusbar.gif rename to theme/default/skin/identica/images/icons/twotone/green/statusbar.gif diff --git a/theme/identica/images/icons/twotone/green/stop.gif b/theme/default/skin/identica/images/icons/twotone/green/stop.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/stop.gif rename to theme/default/skin/identica/images/icons/twotone/green/stop.gif diff --git a/theme/identica/images/icons/twotone/green/template.gif b/theme/default/skin/identica/images/icons/twotone/green/template.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/template.gif rename to theme/default/skin/identica/images/icons/twotone/green/template.gif diff --git a/theme/identica/images/icons/twotone/green/text-bigger.gif b/theme/default/skin/identica/images/icons/twotone/green/text-bigger.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/text-bigger.gif rename to theme/default/skin/identica/images/icons/twotone/green/text-bigger.gif diff --git a/theme/identica/images/icons/twotone/green/text-smaller.gif b/theme/default/skin/identica/images/icons/twotone/green/text-smaller.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/text-smaller.gif rename to theme/default/skin/identica/images/icons/twotone/green/text-smaller.gif diff --git a/theme/identica/images/icons/twotone/green/trash.gif b/theme/default/skin/identica/images/icons/twotone/green/trash.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/trash.gif rename to theme/default/skin/identica/images/icons/twotone/green/trash.gif diff --git a/theme/identica/images/icons/twotone/green/two-docs.gif b/theme/default/skin/identica/images/icons/twotone/green/two-docs.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/two-docs.gif rename to theme/default/skin/identica/images/icons/twotone/green/two-docs.gif diff --git a/theme/identica/images/icons/twotone/green/twotone.gif b/theme/default/skin/identica/images/icons/twotone/green/twotone.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/twotone.gif rename to theme/default/skin/identica/images/icons/twotone/green/twotone.gif diff --git a/theme/identica/images/icons/twotone/green/undo.gif b/theme/default/skin/identica/images/icons/twotone/green/undo.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/undo.gif rename to theme/default/skin/identica/images/icons/twotone/green/undo.gif diff --git a/theme/identica/images/icons/twotone/green/user.gif b/theme/default/skin/identica/images/icons/twotone/green/user.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/user.gif rename to theme/default/skin/identica/images/icons/twotone/green/user.gif diff --git a/theme/identica/images/icons/twotone/green/vegetable.gif b/theme/default/skin/identica/images/icons/twotone/green/vegetable.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/vegetable.gif rename to theme/default/skin/identica/images/icons/twotone/green/vegetable.gif diff --git a/theme/identica/images/icons/twotone/green/x.gif b/theme/default/skin/identica/images/icons/twotone/green/x.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/x.gif rename to theme/default/skin/identica/images/icons/twotone/green/x.gif diff --git a/theme/identica/images/icons/twotone/green/zoom-in.gif b/theme/default/skin/identica/images/icons/twotone/green/zoom-in.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/zoom-in.gif rename to theme/default/skin/identica/images/icons/twotone/green/zoom-in.gif diff --git a/theme/identica/images/icons/twotone/green/zoom-out.gif b/theme/default/skin/identica/images/icons/twotone/green/zoom-out.gif similarity index 100% rename from theme/identica/images/icons/twotone/green/zoom-out.gif rename to theme/default/skin/identica/images/icons/twotone/green/zoom-out.gif diff --git a/theme/identica/default-avatar-mini.png b/theme/identica/default-avatar-mini.png deleted file mode 100644 index 38b8692b4a2f71c8de3d6a12b715df33aada5f7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b diff --git a/theme/identica/default-avatar-profile.png b/theme/identica/default-avatar-profile.png deleted file mode 100644 index f8357d4fc296271b837b3d9911cfbc133918ef2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi From 6c7f5db9b3b70795fab790d55d488531a6a8141a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 12 Apr 2009 02:38:14 +0000 Subject: [PATCH 334/503] Removed unused images --- .../images/icons/twotone/green/against.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/arrow-down.gif | Bin 75 -> 0 bytes .../icons/twotone/green/arrow-downleft.gif | Bin 75 -> 0 bytes .../icons/twotone/green/arrow-downright.gif | Bin 75 -> 0 bytes .../images/icons/twotone/green/arrow-up.gif | Bin 74 -> 0 bytes .../images/icons/twotone/green/arrow-upleft.gif | Bin 75 -> 0 bytes .../images/icons/twotone/green/arrow-upright.gif | Bin 73 -> 0 bytes .../images/icons/twotone/green/back-forth.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/bookmark.gif | Bin 82 -> 0 bytes .../default/images/icons/twotone/green/bulb.gif | Bin 83 -> 0 bytes .../images/icons/twotone/green/calendar.gif | Bin 83 -> 0 bytes .../images/icons/twotone/green/calendar2.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/camera.gif | Bin 79 -> 0 bytes .../default/images/icons/twotone/green/cart.gif | Bin 86 -> 0 bytes .../images/icons/twotone/green/caution.gif | Bin 82 -> 0 bytes .../default/images/icons/twotone/green/chart.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/checkmark.gif | Bin 76 -> 0 bytes .../images/icons/twotone/green/clipboard.gif | Bin 80 -> 0 bytes .../default/images/icons/twotone/green/clock.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/closed-folder.gif | Bin 78 -> 0 bytes .../images/icons/twotone/green/database.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/diskette.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/document.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/double-arrow.gif | Bin 78 -> 0 bytes .../default/images/icons/twotone/green/eject.gif | Bin 73 -> 0 bytes .../images/icons/twotone/green/exclaim.gif | Bin 74 -> 0 bytes .../images/icons/twotone/green/fastforward.gif | Bin 77 -> 0 bytes .../default/images/icons/twotone/green/flag.gif | Bin 80 -> 0 bytes .../default/images/icons/twotone/green/graph.gif | Bin 82 -> 0 bytes .../default/images/icons/twotone/green/grow.gif | Bin 90 -> 0 bytes .../images/icons/twotone/green/headphones.gif | Bin 78 -> 0 bytes .../default/images/icons/twotone/green/home.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/hourglass.gif | Bin 85 -> 0 bytes .../default/images/icons/twotone/green/info.gif | Bin 73 -> 0 bytes .../default/images/icons/twotone/green/key.gif | Bin 76 -> 0 bytes .../default/images/icons/twotone/green/lock.gif | Bin 83 -> 0 bytes .../default/images/icons/twotone/green/move.gif | Bin 80 -> 0 bytes .../default/images/icons/twotone/green/music.gif | Bin 80 -> 0 bytes .../default/images/icons/twotone/green/note.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/open-folder.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/paper-clip.gif | Bin 78 -> 0 bytes .../images/icons/twotone/green/paper-clip2.gif | Bin 80 -> 0 bytes .../default/images/icons/twotone/green/pause.gif | Bin 75 -> 0 bytes .../default/images/icons/twotone/green/phone.gif | Bin 79 -> 0 bytes .../default/images/icons/twotone/green/play.gif | Bin 75 -> 0 bytes .../default/images/icons/twotone/green/plus.gif | Bin 74 -> 0 bytes .../default/images/icons/twotone/green/print.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/question-mark.gif | Bin 74 -> 0 bytes .../images/icons/twotone/green/refresh.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/repost.gif | Bin 87 -> 0 bytes .../images/icons/twotone/green/rewind.gif | Bin 77 -> 0 bytes .../images/icons/twotone/green/search.gif | Bin 76 -> 0 bytes .../images/icons/twotone/green/skip-back.gif | Bin 76 -> 0 bytes .../default/images/icons/twotone/green/skip.gif | Bin 78 -> 0 bytes .../default/images/icons/twotone/green/skull.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/statusbar.gif | Bin 82 -> 0 bytes .../default/images/icons/twotone/green/stop.gif | Bin 72 -> 0 bytes .../images/icons/twotone/green/template.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/text-bigger.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/text-smaller.gif | Bin 80 -> 0 bytes .../images/icons/twotone/green/two-docs.gif | Bin 83 -> 0 bytes .../images/icons/twotone/green/twotone.gif | Bin 2461 -> 0 bytes .../default/images/icons/twotone/green/undo.gif | Bin 79 -> 0 bytes .../default/images/icons/twotone/green/user.gif | Bin 77 -> 0 bytes .../images/icons/twotone/green/vegetable.gif | Bin 82 -> 0 bytes .../default/images/icons/twotone/green/x.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/zoom-in.gif | Bin 86 -> 0 bytes .../images/icons/twotone/green/zoom-out.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/against.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/arrow-down.gif | Bin 75 -> 0 bytes .../icons/twotone/green/arrow-downleft.gif | Bin 75 -> 0 bytes .../icons/twotone/green/arrow-downright.gif | Bin 75 -> 0 bytes .../images/icons/twotone/green/arrow-up.gif | Bin 74 -> 0 bytes .../images/icons/twotone/green/arrow-upleft.gif | Bin 75 -> 0 bytes .../images/icons/twotone/green/arrow-upright.gif | Bin 73 -> 0 bytes .../images/icons/twotone/green/back-forth.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/bookmark.gif | Bin 82 -> 0 bytes .../identica/images/icons/twotone/green/bulb.gif | Bin 83 -> 0 bytes .../images/icons/twotone/green/calendar.gif | Bin 83 -> 0 bytes .../images/icons/twotone/green/calendar2.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/camera.gif | Bin 79 -> 0 bytes .../identica/images/icons/twotone/green/cart.gif | Bin 86 -> 0 bytes .../images/icons/twotone/green/caution.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/chart.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/checkmark.gif | Bin 76 -> 0 bytes .../images/icons/twotone/green/clipboard.gif | Bin 80 -> 0 bytes .../images/icons/twotone/green/clock.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/closed-folder.gif | Bin 78 -> 0 bytes .../images/icons/twotone/green/database.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/diskette.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/document.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/double-arrow.gif | Bin 78 -> 0 bytes .../images/icons/twotone/green/eject.gif | Bin 73 -> 0 bytes .../images/icons/twotone/green/exclaim.gif | Bin 74 -> 0 bytes .../images/icons/twotone/green/fastforward.gif | Bin 77 -> 0 bytes .../identica/images/icons/twotone/green/flag.gif | Bin 80 -> 0 bytes .../images/icons/twotone/green/graph.gif | Bin 82 -> 0 bytes .../identica/images/icons/twotone/green/grow.gif | Bin 90 -> 0 bytes .../images/icons/twotone/green/headphones.gif | Bin 78 -> 0 bytes .../identica/images/icons/twotone/green/home.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/hourglass.gif | Bin 85 -> 0 bytes .../identica/images/icons/twotone/green/info.gif | Bin 73 -> 0 bytes .../identica/images/icons/twotone/green/key.gif | Bin 76 -> 0 bytes .../identica/images/icons/twotone/green/lock.gif | Bin 83 -> 0 bytes .../identica/images/icons/twotone/green/move.gif | Bin 80 -> 0 bytes .../images/icons/twotone/green/music.gif | Bin 80 -> 0 bytes .../identica/images/icons/twotone/green/note.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/open-folder.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/paper-clip.gif | Bin 78 -> 0 bytes .../images/icons/twotone/green/paper-clip2.gif | Bin 80 -> 0 bytes .../images/icons/twotone/green/pause.gif | Bin 75 -> 0 bytes .../images/icons/twotone/green/phone.gif | Bin 79 -> 0 bytes .../identica/images/icons/twotone/green/play.gif | Bin 75 -> 0 bytes .../identica/images/icons/twotone/green/plus.gif | Bin 74 -> 0 bytes .../images/icons/twotone/green/print.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/question-mark.gif | Bin 74 -> 0 bytes .../images/icons/twotone/green/refresh.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/repost.gif | Bin 87 -> 0 bytes .../images/icons/twotone/green/rewind.gif | Bin 77 -> 0 bytes .../images/icons/twotone/green/search.gif | Bin 76 -> 0 bytes .../images/icons/twotone/green/skip-back.gif | Bin 76 -> 0 bytes .../identica/images/icons/twotone/green/skip.gif | Bin 78 -> 0 bytes .../images/icons/twotone/green/skull.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/statusbar.gif | Bin 82 -> 0 bytes .../identica/images/icons/twotone/green/stop.gif | Bin 72 -> 0 bytes .../images/icons/twotone/green/template.gif | Bin 81 -> 0 bytes .../images/icons/twotone/green/text-bigger.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/text-smaller.gif | Bin 80 -> 0 bytes .../images/icons/twotone/green/two-docs.gif | Bin 83 -> 0 bytes .../images/icons/twotone/green/twotone.gif | Bin 2461 -> 0 bytes .../identica/images/icons/twotone/green/undo.gif | Bin 79 -> 0 bytes .../identica/images/icons/twotone/green/user.gif | Bin 77 -> 0 bytes .../images/icons/twotone/green/vegetable.gif | Bin 82 -> 0 bytes .../identica/images/icons/twotone/green/x.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/zoom-in.gif | Bin 86 -> 0 bytes .../images/icons/twotone/green/zoom-out.gif | Bin 85 -> 0 bytes 136 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 theme/default/skin/default/images/icons/twotone/green/against.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/arrow-down.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/arrow-downleft.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/arrow-downright.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/arrow-up.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/arrow-upleft.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/arrow-upright.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/back-forth.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/bookmark.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/bulb.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/calendar.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/calendar2.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/camera.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/cart.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/caution.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/chart.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/checkmark.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/clipboard.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/clock.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/closed-folder.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/database.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/diskette.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/document.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/double-arrow.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/eject.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/exclaim.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/fastforward.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/flag.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/graph.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/grow.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/headphones.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/home.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/hourglass.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/info.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/key.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/lock.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/move.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/music.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/note.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/open-folder.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/paper-clip.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/paper-clip2.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/pause.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/phone.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/play.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/plus.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/print.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/question-mark.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/refresh.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/repost.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/rewind.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/search.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/skip-back.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/skip.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/skull.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/statusbar.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/stop.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/template.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/text-bigger.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/text-smaller.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/two-docs.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/twotone.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/undo.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/user.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/vegetable.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/x.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/zoom-in.gif delete mode 100644 theme/default/skin/default/images/icons/twotone/green/zoom-out.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/against.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-down.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-downleft.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-downright.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-up.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-upleft.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-upright.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/back-forth.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/bookmark.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/bulb.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/calendar.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/calendar2.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/camera.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/cart.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/caution.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/chart.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/checkmark.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/clipboard.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/clock.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/closed-folder.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/database.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/diskette.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/document.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/double-arrow.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/eject.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/exclaim.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/fastforward.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/flag.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/graph.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/grow.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/headphones.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/home.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/hourglass.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/info.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/key.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/lock.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/move.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/music.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/note.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/open-folder.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/paper-clip.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/paper-clip2.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/pause.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/phone.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/play.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/plus.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/print.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/question-mark.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/refresh.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/repost.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/rewind.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/search.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/skip-back.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/skip.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/skull.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/statusbar.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/stop.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/template.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/text-bigger.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/text-smaller.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/two-docs.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/twotone.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/undo.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/user.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/vegetable.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/x.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/zoom-in.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/zoom-out.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/against.gif b/theme/default/skin/default/images/icons/twotone/green/against.gif deleted file mode 100644 index ca796c8a36ff26f41dcb0bacfd1e4e076c9c095f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%g;PR lXBVD&QyasQ6;Qb}>xhpNBZD;nc>)<7 diff --git a/theme/default/skin/default/images/icons/twotone/green/arrow-up.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-up.gif deleted file mode 100644 index d0f5fbeaa84564e38daa0f772acd229affc82e61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%dgDh ZAm^oetS~(`@?iSJ1s%(jk~vu!tN|tM6`cS8 diff --git a/theme/default/skin/default/images/icons/twotone/green/arrow-upleft.gif b/theme/default/skin/default/images/icons/twotone/green/arrow-upleft.gif deleted file mode 100644 index 1e9e6935bd9a3ddfed9b46a5c3f34aeefa2046c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%b(0V b k^F{6jZZmF8W=)*Y^I&C3XxFSYH=?w5UKI%DW@WGj09=(EL{8Fg%W&6v mLlkSu3C-WUMI9EUAsk73mQhpLRu{hBl$(B@!%dpTp i@LV_liI8i573MP+IhKSiS<#lZt9Qm9IUaQp25SH%`WtTm diff --git a/theme/default/skin/default/images/icons/twotone/green/diskette.gif b/theme/default/skin/default/images/icons/twotone/green/diskette.gif deleted file mode 100644 index e970b0a30c1881cf9a40679a435a9edd8a574587..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB`@dn% lmW$juVL^}2<#JlosU*#FZ|zFGwlY^>_k~_|A3YHUYXF>E9a{hZ diff --git a/theme/default/skin/default/images/icons/twotone/green/document.gif b/theme/default/skin/default/images/icons/twotone/green/document.gif deleted file mode 100644 index 9c08f4a3a91cba4925fbfded9759f2d1c5fe52e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=r`erVB%ilQ1 h;Ec3>snFYHwO-E|{XLq}Di`HO95p(0!ikZ=8UXm`8j%11 diff --git a/theme/default/skin/default/images/icons/twotone/green/double-arrow.gif b/theme/default/skin/default/images/icons/twotone/green/double-arrow.gif deleted file mode 100644 index 2e8648264d54f9a17eb030a5ec2f45c7282df6b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%fEOI e!yK;FytiK7*Hn0sI43gh_K|IRr+u6l8LR=iv>HGF diff --git a/theme/default/skin/default/images/icons/twotone/green/eject.gif b/theme/default/skin/default/images/icons/twotone/green/eject.gif deleted file mode 100644 index 7e0906cfe983cc8cd86af5fb84cd6faa05e7525b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b*`erVB%fEOI ZJ44pmGnPfZzV}6^J-cZzIe>w|8UQMM7X$zR diff --git a/theme/default/skin/default/images/icons/twotone/green/exclaim.gif b/theme/default/skin/default/images/icons/twotone/green/exclaim.gif deleted file mode 100644 index 588e28c26122f6eb76a68e44d5fdf796be4737ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%P+`a acvef3ue|(E=)-533p|(cHFL5uSOWkrdlpCl diff --git a/theme/default/skin/default/images/icons/twotone/green/fastforward.gif b/theme/default/skin/default/images/icons/twotone/green/fastforward.gif deleted file mode 100644 index 28e49510317e0f0814ed89e227337c2f0b2765ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7ym`erVB%fEOI dLyOkxqXGH9E5u)9B)1e^KDAB9n3I*k8UUVN8B72G diff --git a/theme/default/skin/default/images/icons/twotone/green/flag.gif b/theme/default/skin/default/images/icons/twotone/green/flag.gif deleted file mode 100644 index 68c8aee2598d4c470b1c60c36232fea6b52dbef6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%g@;0 g#a2CkYK(uMX`+Uoh*MBz%DnK`$BZ6xu`*Z#0Jqf`MF0Q* diff --git a/theme/default/skin/default/images/icons/twotone/green/graph.gif b/theme/default/skin/default/images/icons/twotone/green/graph.gif deleted file mode 100644 index 0c1794b4e7f35194cd5734cfc5de513c6283a4b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=s`erVB%P-4d ic(!ZZl9}eU4X0eIltb-SW-NSXe$>d#okvZC!5RPzJ{ji# diff --git a/theme/default/skin/default/images/icons/twotone/green/grow.gif b/theme/default/skin/default/images/icons/twotone/green/grow.gif deleted file mode 100644 index c4118d53bdc16883409cf7276480cffb5d4b3291..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J611`erV>%dohG r(<0@g?ab9LGUKnYF6~@)=SyhLQ!m|bU8{L62k$lYsTUAoV6X-NHqIaP diff --git a/theme/default/skin/default/images/icons/twotone/green/headphones.gif b/theme/default/skin/default/images/icons/twotone/green/headphones.gif deleted file mode 100644 index 5be6c67ddf1a3d7ced982417295971bcf5da2cd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%m0{J e#G`w|<;Y(LWEWZl^{!m-^5@pPBNa}J4Aua|3L8WK diff --git a/theme/default/skin/default/images/icons/twotone/green/home.gif b/theme/default/skin/default/images/icons/twotone/green/home.gif deleted file mode 100644 index d2a3421efe8e1f15d2c8f8de2ba5dd90e6f7245a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=r`erVB%P+_f h=qL5QHEQ?0T7_#pOCGUap1f|+>#(AuC!81=tN{eA95w&| diff --git a/theme/default/skin/default/images/icons/twotone/green/hourglass.gif b/theme/default/skin/default/images/icons/twotone/green/hourglass.gif deleted file mode 100644 index b62b9480cbb0d8706a7d224020d253166eee5609..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%ebf~ l|J*GGx2X4zZ3Q%nQY8B#W~r^66*)!u{L{mC8Uq*@tO0)l9drNy diff --git a/theme/default/skin/default/images/icons/twotone/green/info.gif b/theme/default/skin/default/images/icons/twotone/green/info.gif deleted file mode 100644 index 86ef1f8b4a7ba4171b2c27e4a0dbd2374cbbe3b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b*`erVB%dgDh Zpp;d-=xR}K>U{C6XDQ9DWR2z}AKSEW_cpG{oU9Di0P08@NdN!< diff --git a/theme/default/skin/default/images/icons/twotone/green/music.gif b/theme/default/skin/default/images/icons/twotone/green/music.gif deleted file mode 100644 index 64b51d4e100420e2fca737504aaf22bbea0ecffd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%m0{p g3sZ)6Sox>9B@eF#Hg-g`-fZ5aPvz?l804#xaT`=`5tW%25SJKSQoGW diff --git a/theme/default/skin/default/images/icons/twotone/green/paper-clip.gif b/theme/default/skin/default/images/icons/twotone/green/paper-clip.gif deleted file mode 100644 index 1d45f1d1eef9831bc859c5e643387f3d9d593599..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%dgB5 e!q!l5B&N(Z_K{lC`Si?X>9N_n4>&P0SOWl)+8CSw diff --git a/theme/default/skin/default/images/icons/twotone/green/paper-clip2.gif b/theme/default/skin/default/images/icons/twotone/green/paper-clip2.gif deleted file mode 100644 index a8c7805bef4ca86c713bfb88a424952eb3fc14f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%P%_P gBST5zHmiXDF-kXjRV9-`x4Fi%9_L`@W@WGj0MNP^3;+NC diff --git a/theme/default/skin/default/images/icons/twotone/green/pause.gif b/theme/default/skin/default/images/icons/twotone/green/pause.gif deleted file mode 100644 index ced0b6440c8fe67e6d530103d8ac1aa4b70453ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%fEOI b!yKu?3;xB=BLil1-fvm9>WGgMBZD;nY2_H} diff --git a/theme/default/skin/default/images/icons/twotone/green/phone.gif b/theme/default/skin/default/images/icons/twotone/green/phone.gif deleted file mode 100644 index 69359f7648c04ec6d70f9dea5d3d2cf68c61f1b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TA`erVB%lW7| f@LW{-0f+q8srRn;CUq=ad2Hr`7Y2(17#OSp`+Xe# diff --git a/theme/default/skin/default/images/icons/twotone/green/play.gif b/theme/default/skin/default/images/icons/twotone/green/play.gif deleted file mode 100644 index 794ec85b6ac815e0ca134bbc0e81872ded44cc8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%fFa8 bL@rA8T*2p;t_wRNm$oj;IuPN+$Y2csUhNo3 diff --git a/theme/default/skin/default/images/icons/twotone/green/plus.gif b/theme/default/skin/default/images/icons/twotone/green/plus.gif deleted file mode 100644 index 4407d0b2d5e65816a16edb6989936e37dbfc45d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%dgDh app?bmx8?iu%1dbzlcz3Sb#wzOgEas@*ce~{ diff --git a/theme/default/skin/default/images/icons/twotone/green/print.gif b/theme/default/skin/default/images/icons/twotone/green/print.gif deleted file mode 100644 index 17727d5d7d78a79ac3b4222d642f852d38a90b65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%g;PR lLC#9|+yTPFXZxyDMdl)|PDDpNb+3)&N?q8{z-} diff --git a/theme/default/skin/default/images/icons/twotone/green/question-mark.gif b/theme/default/skin/default/images/icons/twotone/green/question-mark.gif deleted file mode 100644 index 1689efcd0293bfd8c25b47f5a1c0ddfc43d1b722..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%m0{J a{-@AH?kQ2!UTT#^eskIhQ=KKiN0U}FFSgEasbdmDKG diff --git a/theme/default/skin/default/images/icons/twotone/green/repost.gif b/theme/default/skin/default/images/icons/twotone/green/repost.gif deleted file mode 100644 index 1fab5dcc7fe1dfd3a75d9dc886df5f38d4000dea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87 zcmZ?wbhEHb6krfwSjfom|NsB^DFP6r_>+Z^fq{uZhXDvc@(fHGA$>EKz2#t<@&1gr k?6jS+w?iK-pOA3ERiJ7ef0ygV@3|(aU3`n#ofsLc0gB=r!2kdN diff --git a/theme/default/skin/default/images/icons/twotone/green/rewind.gif b/theme/default/skin/default/images/icons/twotone/green/rewind.gif deleted file mode 100644 index aca3ee35b8aca2e3025e8c51064b6905a6673468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7ym`erVB%fEOI dV?))#qc?MR+saGy&aG&@a%!7^F()g7H2|NL86N-u diff --git a/theme/default/skin/default/images/icons/twotone/green/search.gif b/theme/default/skin/default/images/icons/twotone/green/search.gif deleted file mode 100644 index c36463d0d9843feb92b597f68e902f1bad26b7d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F6`erVB%b&~= c!q)KNOwfJL(147IOVgLWk}{YUz`$S)0CD;l9RL6T diff --git a/theme/default/skin/default/images/icons/twotone/green/skip-back.gif b/theme/default/skin/default/images/icons/twotone/green/skip-back.gif deleted file mode 100644 index adca7aa3ee2c0cc939c8b7a3ee6ea5eafd52e657..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F6`erVB%fEOI cLnGJ6qwDkDRYWg|UBc@3>Xg?R6%ht&0E-nFl>h($ diff --git a/theme/default/skin/default/images/icons/twotone/green/skip.gif b/theme/default/skin/default/images/icons/twotone/green/skip.gif deleted file mode 100644 index ae5417f2f816c60245db5bba38a4a875f047c679..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%fEOI eg95kqG5_dy6^u7B*jI*JKeBDzX&)y>25SJI+8Iay diff --git a/theme/default/skin/default/images/icons/twotone/green/skull.gif b/theme/default/skin/default/images/icons/twotone/green/skull.gif deleted file mode 100644 index 033506732767418de878eb41beffb4164c41a1ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%g;PR m`O^Ut$#-2(ib%^N~T@nKF;x(iALD=M%Y@Pq-|#(urgQ!0B6D;9RL6T diff --git a/theme/default/skin/default/images/icons/twotone/green/twotone.gif b/theme/default/skin/default/images/icons/twotone/green/twotone.gif deleted file mode 100644 index 45aad25c4c49c27a500a05daa7b606df4d52f268..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2461 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 b4*0+ee(;1Zyx|Xz_{1xI@r+M=0RR9ydkW?< diff --git a/theme/default/skin/default/images/icons/twotone/green/undo.gif b/theme/default/skin/default/images/icons/twotone/green/undo.gif deleted file mode 100644 index 6869b30501187a85f8bcf2fd105aba5707f9f42e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TA`erVB%g^7z f=_9pfTfzIf)P=%DGb$GKr>~3WvgT0}VXy`Owage$ diff --git a/theme/default/skin/default/images/icons/twotone/green/user.gif b/theme/default/skin/default/images/icons/twotone/green/user.gif deleted file mode 100644 index c85460fcd5c48dc10a37be719df04a141b87d29b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7ym`erVB%P+_f d=oh7bZg-V+q12LIze?MTA6xk!bFwm60|0b<7m5G? diff --git a/theme/default/skin/default/images/icons/twotone/green/vegetable.gif b/theme/default/skin/default/images/icons/twotone/green/vegetable.gif deleted file mode 100644 index 4d421c1bbd4d3359c91d724dd3c86fb14513f873..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=s`erVB%P;6* i>=z(<@AlIRt_tae5-Icif0-_`*ruUlv>||j!5RPr6&c?E diff --git a/theme/default/skin/default/images/icons/twotone/green/x.gif b/theme/default/skin/default/images/icons/twotone/green/x.gif deleted file mode 100644 index ffb2efea00c78ee8fd74913cce781c2d08c9ed80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TA`erVB%fFbp f)2@MkTk-Q3o{k(mJ$4OTU(?l0#1$&+62)?5co~QeWubG>b!5RQ|VjD*Q diff --git a/theme/default/skin/default/images/icons/twotone/green/zoom-out.gif b/theme/default/skin/default/images/icons/twotone/green/zoom-out.gif deleted file mode 100644 index c61f999fd009be1c7bcb21d9f1b1d61b6d021977..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%a~Nd luJQWA**%e#nVlUILZ8P5vo(dh+&4ibJWbYMYXAd-H2{749CrW! diff --git a/theme/default/skin/identica/images/icons/twotone/green/against.gif b/theme/default/skin/identica/images/icons/twotone/green/against.gif deleted file mode 100644 index ca796c8a36ff26f41dcb0bacfd1e4e076c9c095f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%g;PR lXBVD&QyasQ6;Qb}>xhpNBZD;nc>)<7 diff --git a/theme/default/skin/identica/images/icons/twotone/green/arrow-up.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-up.gif deleted file mode 100644 index d0f5fbeaa84564e38daa0f772acd229affc82e61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%dgDh ZAm^oetS~(`@?iSJ1s%(jk~vu!tN|tM6`cS8 diff --git a/theme/default/skin/identica/images/icons/twotone/green/arrow-upleft.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-upleft.gif deleted file mode 100644 index 1e9e6935bd9a3ddfed9b46a5c3f34aeefa2046c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%b(0V b k^F{6jZZmF8W=)*Y^I&C3XxFSYH=?w5UKI%DW@WGj09=(EL{8Fg%W&6v mLlkSu3C-WUMI9EUAsk73mQhpLRu{hBl$(B@!%dpTp i@LV_liI8i573MP+IhKSiS<#lZt9Qm9IUaQp25SH%`WtTm diff --git a/theme/default/skin/identica/images/icons/twotone/green/diskette.gif b/theme/default/skin/identica/images/icons/twotone/green/diskette.gif deleted file mode 100644 index e970b0a30c1881cf9a40679a435a9edd8a574587..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB`@dn% lmW$juVL^}2<#JlosU*#FZ|zFGwlY^>_k~_|A3YHUYXF>E9a{hZ diff --git a/theme/default/skin/identica/images/icons/twotone/green/document.gif b/theme/default/skin/identica/images/icons/twotone/green/document.gif deleted file mode 100644 index 9c08f4a3a91cba4925fbfded9759f2d1c5fe52e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=r`erVB%ilQ1 h;Ec3>snFYHwO-E|{XLq}Di`HO95p(0!ikZ=8UXm`8j%11 diff --git a/theme/default/skin/identica/images/icons/twotone/green/double-arrow.gif b/theme/default/skin/identica/images/icons/twotone/green/double-arrow.gif deleted file mode 100644 index 2e8648264d54f9a17eb030a5ec2f45c7282df6b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%fEOI e!yK;FytiK7*Hn0sI43gh_K|IRr+u6l8LR=iv>HGF diff --git a/theme/default/skin/identica/images/icons/twotone/green/eject.gif b/theme/default/skin/identica/images/icons/twotone/green/eject.gif deleted file mode 100644 index 7e0906cfe983cc8cd86af5fb84cd6faa05e7525b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b*`erVB%fEOI ZJ44pmGnPfZzV}6^J-cZzIe>w|8UQMM7X$zR diff --git a/theme/default/skin/identica/images/icons/twotone/green/exclaim.gif b/theme/default/skin/identica/images/icons/twotone/green/exclaim.gif deleted file mode 100644 index 588e28c26122f6eb76a68e44d5fdf796be4737ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%P+`a acvef3ue|(E=)-533p|(cHFL5uSOWkrdlpCl diff --git a/theme/default/skin/identica/images/icons/twotone/green/fastforward.gif b/theme/default/skin/identica/images/icons/twotone/green/fastforward.gif deleted file mode 100644 index 28e49510317e0f0814ed89e227337c2f0b2765ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7ym`erVB%fEOI dLyOkxqXGH9E5u)9B)1e^KDAB9n3I*k8UUVN8B72G diff --git a/theme/default/skin/identica/images/icons/twotone/green/flag.gif b/theme/default/skin/identica/images/icons/twotone/green/flag.gif deleted file mode 100644 index 68c8aee2598d4c470b1c60c36232fea6b52dbef6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%g@;0 g#a2CkYK(uMX`+Uoh*MBz%DnK`$BZ6xu`*Z#0Jqf`MF0Q* diff --git a/theme/default/skin/identica/images/icons/twotone/green/graph.gif b/theme/default/skin/identica/images/icons/twotone/green/graph.gif deleted file mode 100644 index 0c1794b4e7f35194cd5734cfc5de513c6283a4b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=s`erVB%P-4d ic(!ZZl9}eU4X0eIltb-SW-NSXe$>d#okvZC!5RPzJ{ji# diff --git a/theme/default/skin/identica/images/icons/twotone/green/grow.gif b/theme/default/skin/identica/images/icons/twotone/green/grow.gif deleted file mode 100644 index c4118d53bdc16883409cf7276480cffb5d4b3291..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J611`erV>%dohG r(<0@g?ab9LGUKnYF6~@)=SyhLQ!m|bU8{L62k$lYsTUAoV6X-NHqIaP diff --git a/theme/default/skin/identica/images/icons/twotone/green/headphones.gif b/theme/default/skin/identica/images/icons/twotone/green/headphones.gif deleted file mode 100644 index 5be6c67ddf1a3d7ced982417295971bcf5da2cd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%m0{J e#G`w|<;Y(LWEWZl^{!m-^5@pPBNa}J4Aua|3L8WK diff --git a/theme/default/skin/identica/images/icons/twotone/green/home.gif b/theme/default/skin/identica/images/icons/twotone/green/home.gif deleted file mode 100644 index d2a3421efe8e1f15d2c8f8de2ba5dd90e6f7245a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=r`erVB%P+_f h=qL5QHEQ?0T7_#pOCGUap1f|+>#(AuC!81=tN{eA95w&| diff --git a/theme/default/skin/identica/images/icons/twotone/green/hourglass.gif b/theme/default/skin/identica/images/icons/twotone/green/hourglass.gif deleted file mode 100644 index b62b9480cbb0d8706a7d224020d253166eee5609..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%ebf~ l|J*GGx2X4zZ3Q%nQY8B#W~r^66*)!u{L{mC8Uq*@tO0)l9drNy diff --git a/theme/default/skin/identica/images/icons/twotone/green/info.gif b/theme/default/skin/identica/images/icons/twotone/green/info.gif deleted file mode 100644 index 86ef1f8b4a7ba4171b2c27e4a0dbd2374cbbe3b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b*`erVB%dgDh Zpp;d-=xR}K>U{C6XDQ9DWR2z}AKSEW_cpG{oU9Di0P08@NdN!< diff --git a/theme/default/skin/identica/images/icons/twotone/green/music.gif b/theme/default/skin/identica/images/icons/twotone/green/music.gif deleted file mode 100644 index 64b51d4e100420e2fca737504aaf22bbea0ecffd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%m0{p g3sZ)6Sox>9B@eF#Hg-g`-fZ5aPvz?l804#xaT`=`5tW%25SJKSQoGW diff --git a/theme/default/skin/identica/images/icons/twotone/green/paper-clip.gif b/theme/default/skin/identica/images/icons/twotone/green/paper-clip.gif deleted file mode 100644 index 1d45f1d1eef9831bc859c5e643387f3d9d593599..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%dgB5 e!q!l5B&N(Z_K{lC`Si?X>9N_n4>&P0SOWl)+8CSw diff --git a/theme/default/skin/identica/images/icons/twotone/green/paper-clip2.gif b/theme/default/skin/identica/images/icons/twotone/green/paper-clip2.gif deleted file mode 100644 index a8c7805bef4ca86c713bfb88a424952eb3fc14f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TB`erVB%P%_P gBST5zHmiXDF-kXjRV9-`x4Fi%9_L`@W@WGj0MNP^3;+NC diff --git a/theme/default/skin/identica/images/icons/twotone/green/pause.gif b/theme/default/skin/identica/images/icons/twotone/green/pause.gif deleted file mode 100644 index ced0b6440c8fe67e6d530103d8ac1aa4b70453ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%fEOI b!yKu?3;xB=BLil1-fvm9>WGgMBZD;nY2_H} diff --git a/theme/default/skin/identica/images/icons/twotone/green/phone.gif b/theme/default/skin/identica/images/icons/twotone/green/phone.gif deleted file mode 100644 index 69359f7648c04ec6d70f9dea5d3d2cf68c61f1b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TA`erVB%lW7| f@LW{-0f+q8srRn;CUq=ad2Hr`7Y2(17#OSp`+Xe# diff --git a/theme/default/skin/identica/images/icons/twotone/green/play.gif b/theme/default/skin/identica/images/icons/twotone/green/play.gif deleted file mode 100644 index 794ec85b6ac815e0ca134bbc0e81872ded44cc8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%fFa8 bL@rA8T*2p;t_wRNm$oj;IuPN+$Y2csUhNo3 diff --git a/theme/default/skin/identica/images/icons/twotone/green/plus.gif b/theme/default/skin/identica/images/icons/twotone/green/plus.gif deleted file mode 100644 index 4407d0b2d5e65816a16edb6989936e37dbfc45d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%dgDh app?bmx8?iu%1dbzlcz3Sb#wzOgEas@*ce~{ diff --git a/theme/default/skin/identica/images/icons/twotone/green/print.gif b/theme/default/skin/identica/images/icons/twotone/green/print.gif deleted file mode 100644 index 17727d5d7d78a79ac3b4222d642f852d38a90b65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%g;PR lLC#9|+yTPFXZxyDMdl)|PDDpNb+3)&N?q8{z-} diff --git a/theme/default/skin/identica/images/icons/twotone/green/question-mark.gif b/theme/default/skin/identica/images/icons/twotone/green/question-mark.gif deleted file mode 100644 index 1689efcd0293bfd8c25b47f5a1c0ddfc43d1b722..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%m0{J a{-@AH?kQ2!UTT#^eskIhQ=KKiN0U}FFSgEasbdmDKG diff --git a/theme/default/skin/identica/images/icons/twotone/green/repost.gif b/theme/default/skin/identica/images/icons/twotone/green/repost.gif deleted file mode 100644 index 1fab5dcc7fe1dfd3a75d9dc886df5f38d4000dea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87 zcmZ?wbhEHb6krfwSjfom|NsB^DFP6r_>+Z^fq{uZhXDvc@(fHGA$>EKz2#t<@&1gr k?6jS+w?iK-pOA3ERiJ7ef0ygV@3|(aU3`n#ofsLc0gB=r!2kdN diff --git a/theme/default/skin/identica/images/icons/twotone/green/rewind.gif b/theme/default/skin/identica/images/icons/twotone/green/rewind.gif deleted file mode 100644 index aca3ee35b8aca2e3025e8c51064b6905a6673468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7ym`erVB%fEOI dV?))#qc?MR+saGy&aG&@a%!7^F()g7H2|NL86N-u diff --git a/theme/default/skin/identica/images/icons/twotone/green/search.gif b/theme/default/skin/identica/images/icons/twotone/green/search.gif deleted file mode 100644 index c36463d0d9843feb92b597f68e902f1bad26b7d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F6`erVB%b&~= c!q)KNOwfJL(147IOVgLWk}{YUz`$S)0CD;l9RL6T diff --git a/theme/default/skin/identica/images/icons/twotone/green/skip-back.gif b/theme/default/skin/identica/images/icons/twotone/green/skip-back.gif deleted file mode 100644 index adca7aa3ee2c0cc939c8b7a3ee6ea5eafd52e657..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F6`erVB%fEOI cLnGJ6qwDkDRYWg|UBc@3>Xg?R6%ht&0E-nFl>h($ diff --git a/theme/default/skin/identica/images/icons/twotone/green/skip.gif b/theme/default/skin/identica/images/icons/twotone/green/skip.gif deleted file mode 100644 index ae5417f2f816c60245db5bba38a4a875f047c679..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7yn`erVB%fEOI eg95kqG5_dy6^u7B*jI*JKeBDzX&)y>25SJI+8Iay diff --git a/theme/default/skin/identica/images/icons/twotone/green/skull.gif b/theme/default/skin/identica/images/icons/twotone/green/skull.gif deleted file mode 100644 index 033506732767418de878eb41beffb4164c41a1ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%g;PR m`O^Ut$#-2(ib%^N~T@nKF;x(iALD=M%Y@Pq-|#(urgQ!0B6D;9RL6T diff --git a/theme/default/skin/identica/images/icons/twotone/green/twotone.gif b/theme/default/skin/identica/images/icons/twotone/green/twotone.gif deleted file mode 100644 index 45aad25c4c49c27a500a05daa7b606df4d52f268..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2461 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 b4*0+ee(;1Zyx|Xz_{1xI@r+M=0RR9ydkW?< diff --git a/theme/default/skin/identica/images/icons/twotone/green/undo.gif b/theme/default/skin/identica/images/icons/twotone/green/undo.gif deleted file mode 100644 index 6869b30501187a85f8bcf2fd105aba5707f9f42e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TA`erVB%g^7z f=_9pfTfzIf)P=%DGb$GKr>~3WvgT0}VXy`Owage$ diff --git a/theme/default/skin/identica/images/icons/twotone/green/user.gif b/theme/default/skin/identica/images/icons/twotone/green/user.gif deleted file mode 100644 index c85460fcd5c48dc10a37be719df04a141b87d29b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7ym`erVB%P+_f d=oh7bZg-V+q12LIze?MTA6xk!bFwm60|0b<7m5G? diff --git a/theme/default/skin/identica/images/icons/twotone/green/vegetable.gif b/theme/default/skin/identica/images/icons/twotone/green/vegetable.gif deleted file mode 100644 index 4d421c1bbd4d3359c91d724dd3c86fb14513f873..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=s`erVB%P;6* i>=z(<@AlIRt_tae5-Icif0-_`*ruUlv>||j!5RPr6&c?E diff --git a/theme/default/skin/identica/images/icons/twotone/green/x.gif b/theme/default/skin/identica/images/icons/twotone/green/x.gif deleted file mode 100644 index ffb2efea00c78ee8fd74913cce781c2d08c9ed80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J0TA`erVB%fFbp f)2@MkTk-Q3o{k(mJ$4OTU(?l0#1$&+62)?5co~QeWubG>b!5RQ|VjD*Q diff --git a/theme/default/skin/identica/images/icons/twotone/green/zoom-out.gif b/theme/default/skin/identica/images/icons/twotone/green/zoom-out.gif deleted file mode 100644 index c61f999fd009be1c7bcb21d9f1b1d61b6d021977..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7CW`erVB%a~Nd luJQWA**%e#nVlUILZ8P5vo(dh+&4ibJWbYMYXAd-H2{749CrW! From 5033c057f8544f0d4a1139908a1d5fe59905716e Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 12 Apr 2009 18:33:56 +0000 Subject: [PATCH 335/503] =?UTF-8?q?Updated=20Polish=20translations=20made?= =?UTF-8?q?=20by=20Piotr=20Dr=C4=85g.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locale/pl_PL/LC_MESSAGES/laconica.mo | Bin 32614 -> 100014 bytes locale/pl_PL/LC_MESSAGES/laconica.po | 3239 ++++++++++++++++---------- 2 files changed, 2006 insertions(+), 1233 deletions(-) diff --git a/locale/pl_PL/LC_MESSAGES/laconica.mo b/locale/pl_PL/LC_MESSAGES/laconica.mo index faf549054a60598a97fd0c12e9e7fef0a804d69d..9a9cdccf3265c0269c00564a40b4453d073b730c 100644 GIT binary patch literal 100014 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 a>HdhL-(asTy#43@7(XB{FnPC$OaCvzWY-@6 literal 32614 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 z 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 diff --git a/locale/pl_PL/LC_MESSAGES/laconica.po b/locale/pl_PL/LC_MESSAGES/laconica.po index 9a61ada6bd..8da9dd59b3 100644 --- a/locale/pl_PL/LC_MESSAGES/laconica.po +++ b/locale/pl_PL/LC_MESSAGES/laconica.po @@ -1,41 +1,33 @@ -# #-#-#-#-# laconica.pot (PACKAGE VERSION) #-#-#-#-# -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. +# translation of pl.po to Polish # Paweł Wilk , 2008. +# Piotr Drąg , 2009. # -# #-#-#-#-# laconica.new.pot (PACKAGE VERSION) #-#-#-#-# -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. +# Polish language has 3 plural forms. +# Special case is used for one and some numbers ending in 2, 3, or 4. +# Example: +# 1 WINDOW -> 1 OKNO +# x2 to x4 WINDOWS -> x2 do x4 OKNA (x != 1) +# 5 or more WINDOWS -> 5 lub więcej OKIEN # msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: pl\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-01-25 16:24+0000\n" -"PO-Revision-Date: 2009-02-28 17:14+0000\n" -"Last-Translator: Ryba \n" -"Language-Team: LANGUAGE \n" +"POT-Creation-Date: 2009-03-11 09:33+0000\n" +"PO-Revision-Date: 2009-04-10 00:39+0200\n" +"Last-Translator: Piotr Drąg \n" +"Language-Team: Polish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2);\n" -"X-Generator: Pootle 1.1.0\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%" +"100<10 || n%100>=20) ? 1 : 2);\n" -# Polish language has 3 plural forms. -# Special case is used for one and some numbers ending in 2, 3, or 4. -# Example: -# 1 WINDOW -> 1 OKNO -# x2 to x4 WINDOWS -> x2 do x4 OKNA (x != 1) -# 5 or more WINDOWS -> 5 lub więcej OKIEN #: ../actions/noticesearchrss.php:64 actions/noticesearchrss.php:68 #: actions/noticesearchrss.php:88 #, php-format msgid " Search Stream for \"%s\"" -msgstr "Szukaj strumienia dla \"%s\"" +msgstr " Znajdź strumień dla \"%s\"" #: ../actions/finishopenidlogin.php:82 ../actions/register.php:191 #: actions/finishopenidlogin.php:88 actions/register.php:205 @@ -43,26 +35,27 @@ msgstr "Szukaj strumienia dla \"%s\"" msgid "" " except this private data: password, email address, IM address, phone number." msgstr "" -"z wyłączeniem tych prywatnych danych: e-maila, identyfikatora IM, numeru " +" poza tymi prywatnymi danymi: hasło, adres e-mail, adres komunikatora, numer " "telefonu." #: ../actions/showstream.php:400 ../lib/stream.php:109 #: actions/showstream.php:418 lib/mailbox.php:164 lib/stream.php:76 msgid " from " -msgstr "" +msgstr " od " #: ../actions/twitapistatuses.php:478 actions/twitapistatuses.php:412 -#: actions/twitapistatuses.php:347 +#: actions/twitapistatuses.php:347 actions/twitapistatuses.php:363 #, php-format msgid "%1$s / Updates replying to %2$s" -msgstr "" +msgstr "%1$s/aktualizacje odpowiadające na %2$s" #: ../actions/invite.php:168 actions/invite.php:176 actions/invite.php:211 +#: actions/invite.php:218 #, php-format msgid "%1$s has invited you to join them on %2$s" -msgstr "%1$s zapraszają Cię byś dołączył do nich w %2$s" +msgstr "%1$s zapraszają Cię, abyś dołączył do nich w %2$s" -#: ../actions/invite.php:170 +#: ../actions/invite.php:170 actions/invite.php:220 #, php-format msgid "" "%1$s has invited you to join them on %2$s (%3$s).\n" @@ -92,11 +85,38 @@ msgid "" "\n" "Sincerely, %2$s\n" msgstr "" +"Użytkownik %1$s zapraszają Cię, abyś dołączył do nich w %2$s (%3$s).\n" +"\n" +"%2$s jest usługą mikroblogowania, która umożliwia pozostawanie w kontakcie z " +"osobami, których znasz i z tymi, którzy Cię interesują.\n" +"\n" +"Możesz także dzielić się w sieci nowinkami o sobie, swoimi przemyśleniami, " +"lub swoim życiem z osobami, którzy Cię znają. To także wspaniały sposób na " +"poznawanie nowych osób, którzy dzielą Twoje zainteresowania.\n" +"\n" +"Użytkownik %1$s powiedział:\n" +"\n" +"%4$s\n" +"\n" +"Możesz zobaczyć stronę profilu %1$s na %2$s tutaj:\n" +"\n" +"%5$s\n" +"\n" +"Jeśli chcesz wypróbować usługę, naciśnij na poniższy odnośnik, aby " +"zaakceptować zaproszenie.\n" +"\n" +"%6$s\n" +"\n" +"Jeśli nie, możesz zignorować tę wiadomość. Dziękujemy za Twoją cierpliwość i " +"czas.\n" +"\n" +"Z poważaniem, %2$s\n" #: ../lib/mail.php:124 lib/mail.php:124 lib/mail.php:126 lib/mail.php:241 +#: lib/mail.php:236 #, php-format msgid "%1$s is now listening to your notices on %2$s." -msgstr "%1$s obserwuje teraz Twoje wpisy na %2$s." +msgstr "Użytkownik %1$s obserwuje teraz Twoje wpisy na %2$s." #: ../lib/mail.php:126 #, php-format @@ -108,16 +128,18 @@ msgid "" "Faithfully yours,\n" "%4$s.\n" msgstr "" -"%1$s obserwuje teraz Twoje wpisy na %2$s.\n" +"Użytkownik %1$s obserwuje teraz Twoje wpisy na %2$s.\n" "\n" -"Kłaniam się,\n" +"\t%3$s\n" +"\n" +"Z poważaniem,\n" "%4$s.\n" #: ../actions/twitapistatuses.php:482 actions/twitapistatuses.php:415 -#: actions/twitapistatuses.php:350 +#: actions/twitapistatuses.php:350 actions/twitapistatuses.php:367 #, php-format msgid "%1$s updates that reply to updates from %2$s / %3$s." -msgstr "" +msgstr "%1$s aktualizuje tę odpowiedź na aktualizacje od %2$s/%3$s." #: ../actions/shownotice.php:45 actions/shownotice.php:45 #: actions/shownotice.php:161 @@ -129,7 +151,7 @@ msgstr "Status użytkownika %1$s na %2$s" #: actions/invite.php:99 actions/invite.php:123 actions/invite.php:131 #, php-format msgid "%s (%s)" -msgstr "" +msgstr "%s (%s)" #: ../actions/publicrss.php:62 actions/publicrss.php:48 #: actions/publicrss.php:90 @@ -142,68 +164,74 @@ msgstr "Publiczny strumień %s" #: actions/allrss.php:60 actions/twitapistatuses.php:155 lib/personal.php:51 #: actions/all.php:65 actions/allrss.php:103 actions/facebookhome.php:164 #: actions/twitapistatuses.php:126 lib/personalgroupnav.php:99 +#: actions/all.php:68 actions/all.php:114 actions/allrss.php:106 +#: actions/facebookhome.php:163 actions/twitapistatuses.php:130 #, php-format msgid "%s and friends" msgstr "%s i przyjaciele" #: ../actions/twitapistatuses.php:49 actions/twitapistatuses.php:49 -#: actions/twitapistatuses.php:33 +#: actions/twitapistatuses.php:33 actions/twitapistatuses.php:32 #, php-format msgid "%s public timeline" msgstr "Publiczna oś czasu %s" -#: ../lib/mail.php:206 lib/mail.php:212 lib/mail.php:411 +#: ../lib/mail.php:206 lib/mail.php:212 lib/mail.php:411 lib/mail.php:412 #, php-format msgid "%s status" -msgstr "status %s" +msgstr "Status %s" #: ../actions/twitapistatuses.php:338 actions/twitapistatuses.php:265 -#: actions/twitapistatuses.php:199 +#: actions/twitapistatuses.php:199 actions/twitapistatuses.php:209 #, php-format msgid "%s timeline" -msgstr "oś czasu %s" +msgstr "Oś czasu %s" #: ../actions/twitapistatuses.php:52 actions/twitapistatuses.php:52 -#: actions/twitapistatuses.php:36 +#: actions/twitapistatuses.php:36 actions/twitapistatuses.php:38 #, php-format msgid "%s updates from everyone!" -msgstr "" +msgstr "%s aktualizuje od każdego!" -#: ../actions/register.php:213 +#: ../actions/register.php:213 actions/register.php:497 msgid "" "(You should receive a message by email momentarily, with instructions on how " "to confirm your email address.)" msgstr "" +"(Powinieneś właśnie otrzymać wiadomość e-mail, zawierającą instrukcje " +"potwierdzenia adresu e-mail)" -#: ../lib/util.php:257 lib/util.php:273 lib/action.php:605 +#: ../lib/util.php:257 lib/util.php:273 lib/action.php:605 lib/action.php:702 #, php-format msgid "" "**%%site.name%%** is a microblogging service brought to you by [%%site." "broughtby%%](%%site.broughtbyurl%%). " msgstr "" -"**%%site.name%%** to serwis z mikroblogami prowadzony przez [%%site.broughtby" -"%%](%%site.broughtbyurl%%)." +"**%%site.name%%** jest usługą mikroblogowania prowadzony przez [%%site." +"broughtby%%](%%site.broughtbyurl%%). " -#: ../lib/util.php:259 lib/util.php:275 lib/action.php:607 +#: ../lib/util.php:259 lib/util.php:275 lib/action.php:607 lib/action.php:704 #, php-format msgid "**%%site.name%%** is a microblogging service. " -msgstr "**%%site.name%%** to serwis do mikroblogowania." +msgstr "**%%site.name%%** jest usługą mikroblogowania. " #: ../lib/util.php:274 lib/util.php:290 msgid ". Contributors should be attributed by full name or nickname." msgstr "" -". Współpracownicy powinni być wymienieni z imienia i nazwiska lub pseudonimu." +". Współtwórcy powinni być wymienieni z imienia i nazwiska lub pseudonimu." #: ../actions/finishopenidlogin.php:73 ../actions/profilesettings.php:43 #: actions/finishopenidlogin.php:79 actions/profilesettings.php:76 #: actions/finishopenidlogin.php:101 actions/profilesettings.php:100 #: lib/groupeditform.php:139 msgid "1-64 lowercase letters or numbers, no punctuation or spaces" -msgstr "Max. 64 znaki alfanumeryczne, bez spacji i znaków przestankowych" +msgstr "1-64 małe litery lub liczby, bez spacji i znaków przestankowych" #: ../actions/register.php:152 actions/register.php:166 +#: actions/register.php:368 msgid "1-64 lowercase letters or numbers, no punctuation or spaces. Required." msgstr "" +"1-64 małe litery lub liczby, bez spacji i znaków przestankowych. Wymagane." #: ../actions/password.php:42 actions/profilesettings.php:181 #: actions/passwordsettings.php:102 @@ -213,39 +241,41 @@ msgstr "6 lub więcej znaków" #: ../actions/recoverpassword.php:180 actions/recoverpassword.php:186 #: actions/recoverpassword.php:220 msgid "6 or more characters, and don't forget it!" -msgstr "6 lub więcej znaków – nie zapomnij go!" +msgstr "6 lub więcej znaków, i nie zapomnij go!" #: ../actions/register.php:154 actions/register.php:168 #: actions/register.php:373 msgid "6 or more characters. Required." -msgstr "" +msgstr "6 lub więcej znaków. Wymagane." #: ../actions/imsettings.php:197 actions/imsettings.php:205 +#: actions/imsettings.php:321 #, php-format msgid "" "A confirmation code was sent to the IM address you added. You must approve %" "s for sending messages to you." msgstr "" -"Na Twój adres komunikatora został wysłany kod potwierdzający. Musisz " +"Kod potwierdzający został wysłany na dodany adres komunikatora. Musisz " "zaakceptować otrzymywanie wiadomości od %s." #: ../actions/emailsettings.php:213 actions/emailsettings.php:231 +#: actions/emailsettings.php:350 msgid "" "A confirmation code was sent to the email address you added. Check your " "inbox (and spam box!) for the code and instructions on how to use it." msgstr "" -"Kod potwierdzający został wysłany na podany przez Ciebie adres e-mail. " -"Sprawdź w swojej skrzynce odbiorczej (także w folderze SPAM) czy otrzymałeś " -"kod i instrukcje dotyczące jego użycia. " +"Kod potwierdzający został wysłany na dodany adres e-mail. Sprawdź w swojej " +"skrzynce odbiorczej (także w wiadomościach niechcianych!), czy otrzymałeś " +"kod i instrukcje dotyczące jego użycia." #: ../actions/smssettings.php:216 actions/smssettings.php:224 msgid "" "A confirmation code was sent to the phone number you added. Check your inbox " "(and spam box!) for the code and instructions on how to use it." msgstr "" -"Kod potwierdzający został wysłany na podany przez Ciebie numer telefonu. " -"Sprawdź w swojej skrzynce odbiorczej (także w folderze SPAM) czy otrzymałeś " -"kod i instrukcje dotyczące jego użycia. " +"Kod potwierdzający został wysłany na dodany numer telefonu. Sprawdź w swojej " +"skrzynce odbiorczej (także w wiadomościach niechcianych!), czy otrzymałeś " +"kod i instrukcje dotyczące jego użycia." #: ../actions/twitapiaccount.php:49 ../actions/twitapihelp.php:45 #: ../actions/twitapistatuses.php:88 ../actions/twitapistatuses.php:259 @@ -265,9 +295,14 @@ msgstr "" #: actions/twitapistatuses.php:147 actions/twitapistatuses.php:228 #: actions/twitapistatuses.php:239 actions/twitapistatuses.php:392 #: actions/twitapistatuses.php:402 actions/twitapistatuses.php:429 -#: actions/twitapiusers.php:32 +#: actions/twitapiusers.php:32 actions/twitapidirect_messages.php:120 +#: actions/twitapifavorites.php:91 actions/twitapifavorites.php:108 +#: actions/twitapistatuses.php:82 actions/twitapistatuses.php:159 +#: actions/twitapistatuses.php:246 actions/twitapistatuses.php:257 +#: actions/twitapistatuses.php:416 actions/twitapistatuses.php:426 +#: actions/twitapistatuses.php:453 msgid "API method not found!" -msgstr "metoda API nie znaleziona!" +msgstr "Nie znaleziono metody API!" #: ../actions/twitapiaccount.php:57 ../actions/twitapiaccount.php:113 #: ../actions/twitapiaccount.php:119 ../actions/twitapiblocks.php:28 @@ -288,18 +323,21 @@ msgstr "metoda API nie znaleziona!" #: actions/twitapidirect_messages.php:184 actions/twitapifavorites.php:143 #: actions/twitapihelp.php:52 actions/twitapilaconica.php:172 #: actions/twitapinotifications.php:31 actions/twitapinotifications.php:37 -#: actions/twitapistatuses.php:562 +#: actions/twitapistatuses.php:562 actions/twitapiaccount.php:46 +#: actions/twitapiaccount.php:98 actions/twitapiaccount.php:104 +#: actions/twitapidirect_messages.php:193 actions/twitapifavorites.php:149 +#: actions/twitapistatuses.php:625 actions/twitapitrends.php:87 msgid "API method under construction." -msgstr "metoda API w trakcie powstawania." +msgstr "Metoda API jest w trakcie tworzenia." -#: ../lib/util.php:324 lib/util.php:340 lib/action.php:568 +#: ../lib/util.php:324 lib/util.php:340 lib/action.php:568 lib/action.php:661 msgid "About" -msgstr "O serwisie" +msgstr "O usłudze" #: ../actions/userauthorization.php:119 actions/userauthorization.php:126 #: actions/userauthorization.php:143 msgid "Accept" -msgstr "Akceptuj" +msgstr "Zaakceptuj" #: ../actions/emailsettings.php:62 ../actions/imsettings.php:63 #: ../actions/openidsettings.php:57 ../actions/smssettings.php:71 @@ -308,6 +346,7 @@ msgstr "Akceptuj" #: actions/twittersettings.php:85 actions/emailsettings.php:120 #: actions/imsettings.php:127 actions/openidsettings.php:111 #: actions/smssettings.php:133 actions/twittersettings.php:163 +#: actions/twittersettings.php:166 msgid "Add" msgstr "Dodaj" @@ -330,13 +369,14 @@ msgid "Address" msgstr "Adres" #: ../actions/invite.php:131 actions/invite.php:139 actions/invite.php:176 +#: actions/invite.php:181 msgid "Addresses of friends to invite (one per line)" -msgstr "Adresy subskrybentów, których zapraszasz (jeden w każdej linii)" +msgstr "Adresy przyjaciół, których zapraszasz (jeden na wiersz)" #: ../actions/showstream.php:273 actions/showstream.php:288 #: actions/showstream.php:422 msgid "All subscriptions" -msgstr "Wszyscy obserwowani" +msgstr "Wszystkie subskrypcje" #: ../actions/publicrss.php:64 actions/publicrss.php:50 #: actions/publicrss.php:92 @@ -348,7 +388,7 @@ msgstr "Wszystkie aktualizacje od %s" #: actions/noticesearchrss.php:90 #, php-format msgid "All updates matching search term \"%s\"" -msgstr "Wszystkie aktualizacje pasujące do wzorca wyszukiwania \"%s\"" +msgstr "Wszystkie aktualizacje pasujące do wyszukiwanego terminu \"%s\"" #: ../actions/finishopenidlogin.php:29 ../actions/login.php:31 #: ../actions/openidlogin.php:29 ../actions/register.php:30 @@ -361,68 +401,72 @@ msgstr "Jesteś już zalogowany." #: ../lib/subs.php:42 lib/subs.php:42 lib/subs.php:49 msgid "Already subscribed!." -msgstr "Już obserwujesz!" +msgstr "Już subskrybowane!" #: ../actions/deletenotice.php:54 actions/deletenotice.php:55 -#: actions/deletenotice.php:113 +#: actions/deletenotice.php:113 actions/deletenotice.php:114 msgid "Are you sure you want to delete this notice?" msgstr "Jesteś pewien, że chcesz usunąć ten wpis?" #: ../actions/userauthorization.php:77 actions/userauthorization.php:83 #: actions/userauthorization.php:81 msgid "Authorize subscription" -msgstr "Pozwól na obserwację" +msgstr "Upoważnij subskrypcję" #: ../actions/login.php:104 ../actions/register.php:178 -#: actions/register.php:192 +#: actions/register.php:192 actions/login.php:218 actions/openidlogin.php:117 +#: actions/register.php:416 msgid "Automatically login in the future; not for shared computers!" msgstr "" -"Automatycznie loguj mnie na konto. Nie używać w przypadku współdzielonych " -"komputerów!" +"Automatyczne logowanie. Nie użyj na komputerach używanych przez wiele osób!" #: ../actions/profilesettings.php:65 actions/profilesettings.php:98 +#: actions/profilesettings.php:144 msgid "" "Automatically subscribe to whoever subscribes to me (best for non-humans)" msgstr "" -"Automatycznie zasubskrybuj każdego kto mnie zasubskrybuje (najlepsze dla " +"Automatycznie zasubskrybuj każdego, kto mnie zasubskrybuje (najlepsze dla " "botów)" #: ../actions/avatar.php:32 ../lib/settingsaction.php:90 #: actions/profilesettings.php:34 actions/avatarsettings.php:65 #: actions/showgroup.php:209 lib/accountsettingsaction.php:107 +#: actions/avatarsettings.php:67 actions/showgroup.php:211 msgid "Avatar" msgstr "Awatar" #: ../actions/avatar.php:113 actions/profilesettings.php:350 -#: actions/avatarsettings.php:395 +#: actions/avatarsettings.php:395 actions/avatarsettings.php:346 msgid "Avatar updated." -msgstr "Awatar załadowany." +msgstr "Zaktualizowano awatar." #: ../actions/imsettings.php:55 actions/imsettings.php:56 +#: actions/imsettings.php:108 #, php-format msgid "" "Awaiting confirmation on this address. Check your Jabber/GTalk account for a " "message with further instructions. (Did you add %s to your buddy list?)" msgstr "" -"Oczekiwanie na potwierdzenie dla tego adresu. Sprawdź czy na Twoje konto " -"Jabbera/GTalka przyszła wiadomość z dalszymi instrukcjami. (Nie zapomnij " -"dodać %s do listy znajomych.)" +"Oczekiwanie na potwierdzenie tego adresu. Sprawdź swoje konto Jabbera/GTalk, " +"czy otrzymałeś wiadomość z dalszymi instrukcjami (dodałeś %s do listy " +"znajomych?)." #: ../actions/emailsettings.php:54 actions/emailsettings.php:55 +#: actions/emailsettings.php:107 msgid "" "Awaiting confirmation on this address. Check your inbox (and spam box!) for " "a message with further instructions." msgstr "" -"Ten adres oczekuje potwierdzenia. Sprawdź swoją skrzynkę odbiorczą (także " -"folder SPAM!) czy dostałeś wiadomość z dalszymi instrukcjami. " +"Oczekiwanie na potwierdzenie tego adresu. Sprawdź swoją skrzynkę odbiorczą " +"(także w wiadomościach niechcianych!), czy otrzymałeś wiadomość z dalszymi " +"instrukcjami." #: ../actions/smssettings.php:58 actions/smssettings.php:58 #: actions/smssettings.php:111 msgid "Awaiting confirmation on this phone number." -msgstr "Oczekiwanie na potwierdzenie dla tego numeru telefonu." +msgstr "Oczekiwanie na potwierdzenie tego numeru telefonu." #: ../lib/util.php:1318 lib/util.php:1452 -#, fuzzy msgid "Before »" msgstr "Wcześniej »" @@ -436,23 +480,24 @@ msgstr "O mnie" #: ../actions/updateprofile.php:103 actions/profilesettings.php:216 #: actions/register.php:89 actions/updateprofile.php:104 #: actions/profilesettings.php:205 actions/register.php:174 -#: actions/updateprofile.php:107 +#: actions/updateprofile.php:107 actions/updateprofile.php:109 msgid "Bio is too long (max 140 chars)." -msgstr "Wpis \"O mnie\" jest za długi (maks. 140 znaków)" +msgstr "Wpis \"O mnie\" jest za długi (maksymalnie 140 znaków)." #: ../lib/deleteaction.php:41 lib/deleteaction.php:41 lib/deleteaction.php:69 msgid "Can't delete this notice." -msgstr "Nie można usunąć tego wpisu. " +msgstr "Nie można usunąć tego wpisu." #: ../actions/updateprofile.php:119 actions/updateprofile.php:120 -#: actions/updateprofile.php:123 +#: actions/updateprofile.php:123 actions/updateprofile.php:125 #, php-format msgid "Can't read avatar URL '%s'" -msgstr "Nie można odczytać URL-a awatara '%s'" +msgstr "Nie można odczytać adresu URL awatara \"%s\"" #: ../actions/password.php:85 ../actions/recoverpassword.php:300 #: actions/profilesettings.php:404 actions/recoverpassword.php:313 #: actions/passwordsettings.php:169 actions/recoverpassword.php:347 +#: actions/passwordsettings.php:174 msgid "Can't save new password." msgstr "Nie można zapisać nowego hasła." @@ -465,8 +510,9 @@ msgid "Cancel" msgstr "Anuluj" #: ../lib/openid.php:121 lib/openid.php:121 lib/openid.php:130 +#: lib/openid.php:133 msgid "Cannot instantiate OpenID consumer object." -msgstr "Nie można stworzyć instancji obiektu OpenID." +msgstr "Nie można utworzyć instancji obiektu klienta OpenID." #: ../actions/imsettings.php:163 actions/imsettings.php:171 #: actions/imsettings.php:286 @@ -474,9 +520,9 @@ msgid "Cannot normalize that Jabber ID" msgstr "Nie można znormalizować tego identyfikatora Jabbera" #: ../actions/emailsettings.php:181 actions/emailsettings.php:199 -#: actions/emailsettings.php:311 +#: actions/emailsettings.php:311 actions/emailsettings.php:318 msgid "Cannot normalize that email address" -msgstr "" +msgstr "Nie można znormalizować tego adresu e-mail" #: ../actions/password.php:45 actions/profilesettings.php:184 #: actions/passwordsettings.php:110 @@ -486,7 +532,7 @@ msgstr "Zmień" #: ../lib/settingsaction.php:88 lib/settingsaction.php:88 #: lib/accountsettingsaction.php:114 msgid "Change email handling" -msgstr "" +msgstr "Zmień obsługę adresu e-mail" #: ../actions/password.php:32 actions/profilesettings.php:36 #: actions/passwordsettings.php:58 @@ -495,12 +541,12 @@ msgstr "Zmień hasło" #: ../lib/settingsaction.php:94 lib/accountsettingsaction.php:111 msgid "Change your password" -msgstr "" +msgstr "Zmień hasło" #: ../lib/settingsaction.php:85 lib/settingsaction.php:85 #: lib/accountsettingsaction.php:105 msgid "Change your profile settings" -msgstr "" +msgstr "Zmień ustawienia profilu" #: ../actions/password.php:43 ../actions/recoverpassword.php:181 #: ../actions/register.php:155 ../actions/smssettings.php:65 @@ -520,21 +566,21 @@ msgstr "Potwierdź adres" #: ../actions/smssettings.php:245 actions/emailsettings.php:256 #: actions/imsettings.php:230 actions/smssettings.php:253 #: actions/emailsettings.php:379 actions/imsettings.php:361 -#: actions/smssettings.php:374 +#: actions/smssettings.php:374 actions/emailsettings.php:386 msgid "Confirmation cancelled." msgstr "Anulowano potwierdzenie." #: ../actions/smssettings.php:63 actions/smssettings.php:63 #: actions/smssettings.php:118 msgid "Confirmation code" -msgstr "" +msgstr "Kod potwierdzający" #: ../actions/confirmaddress.php:38 actions/confirmaddress.php:38 #: actions/confirmaddress.php:80 msgid "Confirmation code not found." msgstr "Nie znaleziono kodu potwierdzającego." -#: ../actions/register.php:202 +#: ../actions/register.php:202 actions/register.php:473 #, php-format msgid "" "Congratulations, %s! And welcome to %%%%site.name%%%%. From here, you may " @@ -552,9 +598,24 @@ msgid "" "\n" "Thanks for signing up and we hope you enjoy using this service." msgstr "" +"Gratulacje, %s! Witaj na %%%%site.name%%%%. Stąd możesz chcieć...\n" +"\n" +"* Przejść do [swojego profilu](%s) i wysłać swoją pierwszą wiadomość.\n" +"* Dodać [adres Jabbera/GTalk](%%%%action.imsettings%%%%), abyś mógł wysyłać " +"wpisy przez komunikatora.\n" +"* [Poszukać osób](%%%%action.peoplesearch%%%%), których możesz znać lub " +"którzy dzielą Twoje zainteresowania. \n" +"* Zaktualizować swoje [ustawienia profilu](%%%%action.profilesettings%%%%), " +"aby powiedzieć innym więcej o sobie. \n" +"* Przeczytać [dokumentację w sieci](%%%%doc.help%%%%), aby dowiedzieć się o " +"funkcjach, które mogłeś pominąć. \n" +"\n" +"Dziękujemy za zarejestrowanie się i mamy nadzieję, że używanie tej usługi " +"sprawi Ci przyjemność." #: ../actions/finishopenidlogin.php:91 actions/finishopenidlogin.php:97 -#: actions/finishopenidlogin.php:119 lib/action.php:330 +#: actions/finishopenidlogin.php:119 lib/action.php:330 lib/action.php:403 +#: lib/action.php:406 msgid "Connect" msgstr "Połącz" @@ -563,11 +624,12 @@ msgstr "Połącz" msgid "Connect existing account" msgstr "Połącz z istniejącym kontem" -#: ../lib/util.php:332 lib/util.php:348 lib/action.php:576 +#: ../lib/util.php:332 lib/util.php:348 lib/action.php:576 lib/action.php:669 msgid "Contact" msgstr "Kontakt" #: ../lib/openid.php:178 lib/openid.php:178 lib/openid.php:187 +#: lib/openid.php:190 #, php-format msgid "Could not create OpenID form: %s" msgstr "Nie można utworzyć formularza OpenID: %s" @@ -577,45 +639,46 @@ msgstr "Nie można utworzyć formularza OpenID: %s" #: actions/twitapifriendships.php:48 actions/twitapifriendships.php:64 #, php-format msgid "Could not follow user: %s is already on your list." -msgstr "" +msgstr "Nie można obserwować użytkownika: %s jest już na Twojej liście." #: ../actions/twitapifriendships.php:53 actions/twitapifriendships.php:53 #: actions/twitapifriendships.php:41 msgid "Could not follow user: User not found." -msgstr "" +msgstr "Nie można obserwować użytkownika: nie znaleziono użytkownika." #: ../lib/openid.php:160 lib/openid.php:160 lib/openid.php:169 +#: lib/openid.php:172 #, php-format msgid "Could not redirect to server: %s" msgstr "Nie można przekierować do serwera: %s" #: ../actions/updateprofile.php:162 actions/updateprofile.php:163 -#: actions/updateprofile.php:166 +#: actions/updateprofile.php:166 actions/updateprofile.php:176 msgid "Could not save avatar info" msgstr "Nie można zapisać informacji o awatarze" #: ../actions/updateprofile.php:155 actions/updateprofile.php:156 -#: actions/updateprofile.php:159 +#: actions/updateprofile.php:159 actions/updateprofile.php:163 msgid "Could not save new profile info" msgstr "Nie można zapisać informacji o nowym profilu" #: ../lib/subs.php:54 lib/subs.php:61 lib/subs.php:72 msgid "Could not subscribe other to you." -msgstr "" +msgstr "Nie można zasubskrybować innych do Ciebie." #: ../lib/subs.php:46 lib/subs.php:46 lib/subs.php:57 msgid "Could not subscribe." -msgstr "" +msgstr "Nie można zasubskrybować." #: ../actions/recoverpassword.php:102 actions/recoverpassword.php:105 #: actions/recoverpassword.php:111 msgid "Could not update user with confirmed email address." -msgstr "" +msgstr "Nie można zaktualizować użytkownika z potwierdzonym adresem e-mail." #: ../actions/finishremotesubscribe.php:99 #: actions/finishremotesubscribe.php:101 actions/finishremotesubscribe.php:114 msgid "Couldn't convert request tokens to access tokens." -msgstr "Nie można przekształcić tokenów z żądaniami na tokeny dostępu." +msgstr "Nie można przekonwertować tokenów żądań na tokeny dostępu." #: ../actions/confirmaddress.php:84 ../actions/emailsettings.php:234 #: ../actions/imsettings.php:218 ../actions/smssettings.php:241 @@ -623,52 +686,56 @@ msgstr "Nie można przekształcić tokenów z żądaniami na tokeny dostępu." #: actions/imsettings.php:226 actions/smssettings.php:249 #: actions/confirmaddress.php:126 actions/emailsettings.php:375 #: actions/imsettings.php:357 actions/smssettings.php:370 +#: actions/emailsettings.php:382 msgid "Couldn't delete email confirmation." -msgstr "Nie można skasować potwierdzenia adresu e-mail." +msgstr "Nie można usunąć potwierdzenia adresu e-mail." #: ../lib/subs.php:103 lib/subs.php:116 lib/subs.php:134 msgid "Couldn't delete subscription." -msgstr "Nie można usunąć obserwacji." +msgstr "Nie można usunąć subskrypcji." #: ../actions/twitapistatuses.php:93 actions/twitapistatuses.php:98 -#: actions/twitapistatuses.php:84 +#: actions/twitapistatuses.php:84 actions/twitapistatuses.php:87 msgid "Couldn't find any statuses." -msgstr "" +msgstr "Nie można znaleźć żadnych statusów." #: ../actions/remotesubscribe.php:127 actions/remotesubscribe.php:136 #: actions/remotesubscribe.php:178 msgid "Couldn't get a request token." -msgstr "Nie można uzyskać tokena z żądaniem." +msgstr "Nie można uzyskać tokenu żądana." #: ../actions/emailsettings.php:205 ../actions/imsettings.php:187 #: ../actions/smssettings.php:206 actions/emailsettings.php:223 #: actions/imsettings.php:195 actions/smssettings.php:214 #: actions/emailsettings.php:337 actions/imsettings.php:311 -#: actions/smssettings.php:325 +#: actions/smssettings.php:325 actions/emailsettings.php:344 msgid "Couldn't insert confirmation code." msgstr "Nie można wprowadzić kodu potwierdzającego." #: ../actions/finishremotesubscribe.php:180 #: actions/finishremotesubscribe.php:182 actions/finishremotesubscribe.php:218 msgid "Couldn't insert new subscription." -msgstr "Nie można wprowadzić nowej obserwacji." +msgstr "Nie można wprowadzić nowej subskrypcji." #: ../actions/profilesettings.php:184 ../actions/twitapiaccount.php:96 #: actions/profilesettings.php:299 actions/twitapiaccount.php:94 #: actions/profilesettings.php:302 actions/twitapiaccount.php:81 +#: actions/twitapiaccount.php:82 msgid "Couldn't save profile." msgstr "Nie można zapisać profilu." #: ../actions/profilesettings.php:161 actions/profilesettings.php:276 #: actions/profilesettings.php:279 msgid "Couldn't update user for autosubscribe." -msgstr "" +msgstr "Nie można zaktualizować użytkownika do automatycznej subskrypcji." #: ../actions/emailsettings.php:280 ../actions/emailsettings.php:294 #: actions/emailsettings.php:298 actions/emailsettings.php:312 #: actions/emailsettings.php:440 actions/emailsettings.php:462 +#: actions/emailsettings.php:447 actions/emailsettings.php:469 +#: actions/smssettings.php:515 actions/smssettings.php:539 msgid "Couldn't update user record." -msgstr "" +msgstr "Nie można zaktualizować wpisu użytkownika." #: ../actions/confirmaddress.php:72 ../actions/emailsettings.php:156 #: ../actions/emailsettings.php:259 ../actions/imsettings.php:138 @@ -682,7 +749,8 @@ msgstr "" #: actions/emailsettings.php:411 actions/imsettings.php:252 #: actions/imsettings.php:395 actions/othersettings.php:162 #: actions/profilesettings.php:259 actions/smssettings.php:266 -#: actions/smssettings.php:408 +#: actions/smssettings.php:408 actions/emailsettings.php:287 +#: actions/emailsettings.php:418 msgid "Couldn't update user." msgstr "Nie można zaktualizować użytkownika." @@ -694,57 +762,61 @@ msgstr "Utwórz" #: ../actions/finishopenidlogin.php:70 actions/finishopenidlogin.php:76 #: actions/finishopenidlogin.php:98 msgid "Create a new user with this nickname." -msgstr "Załóż użytkownika o tym pseudonimie." +msgstr "Utwórz nowego użytkownika o tym pseudonimie." #: ../actions/finishopenidlogin.php:68 actions/finishopenidlogin.php:74 #: actions/finishopenidlogin.php:96 msgid "Create new account" -msgstr "Załóż nowe konto" +msgstr "Utwórz nowe konto" #: ../actions/finishopenidlogin.php:191 actions/finishopenidlogin.php:197 #: actions/finishopenidlogin.php:231 msgid "Creating new account for OpenID that already has a user." -msgstr "Tworzenie nowego konta użytkownika na podstawie identyfikatora OpenID." +msgstr "" +"Tworzenie nowego konta dla identyfikatora OpenID, który posiada już " +"użytkownika." #: ../actions/imsettings.php:45 actions/imsettings.php:46 #: actions/imsettings.php:100 msgid "Current confirmed Jabber/GTalk address." -msgstr "Potwierdzone adresy Jabbera/GTalka" +msgstr "Obecnie potwierdzone adresy Jabbera/GTalk." #: ../actions/smssettings.php:46 actions/smssettings.php:46 #: actions/smssettings.php:100 msgid "Current confirmed SMS-enabled phone number." -msgstr "" +msgstr "Obecnie potwierdzone numery telefonów z włączoną usługą SMS." #: ../actions/emailsettings.php:44 actions/emailsettings.php:45 #: actions/emailsettings.php:99 msgid "Current confirmed email address." -msgstr "" +msgstr "Obecnie potwierdzone adresy e-mail." #: ../actions/showstream.php:356 actions/showstream.php:367 msgid "Currently" msgstr "Obecnie" #: ../classes/Notice.php:72 classes/Notice.php:86 classes/Notice.php:91 +#: classes/Notice.php:114 #, php-format msgid "DB error inserting hashtag: %s" -msgstr "" +msgstr "Błąd bazy danych podczas wprowadzania znacznika hasha: %s" #: ../lib/util.php:1061 lib/util.php:1110 classes/Notice.php:698 +#: classes/Notice.php:757 #, php-format msgid "DB error inserting reply: %s" -msgstr "Błąd przy dodawaniu do bazy danych: %s" +msgstr "Błąd bazy danych podczas wprowadzania odpowiedzi: %s" #: ../actions/deletenotice.php:41 actions/deletenotice.php:41 -#: actions/deletenotice.php:79 +#: actions/deletenotice.php:79 actions/deletenotice.php:111 msgid "Delete notice" -msgstr "" +msgstr "Usuń wpis" #: ../actions/profilesettings.php:51 ../actions/register.php:172 #: actions/profilesettings.php:84 actions/register.php:186 -#: actions/profilesettings.php:114 +#: actions/profilesettings.php:114 actions/register.php:404 msgid "Describe yourself and your interests in 140 chars" -msgstr "Opisz się w 140 znakach" +msgstr "Opisz się i swoje zainteresowania w 140 znakach" #: ../actions/register.php:158 ../actions/register.php:161 #: ../lib/settingsaction.php:87 actions/register.php:172 @@ -756,59 +828,60 @@ msgstr "E-mail" #: ../actions/emailsettings.php:59 actions/emailsettings.php:60 #: actions/emailsettings.php:115 msgid "Email Address" -msgstr "" +msgstr "Adres e-mail" #: ../actions/emailsettings.php:32 actions/emailsettings.php:32 #: actions/emailsettings.php:60 msgid "Email Settings" -msgstr "" +msgstr "Ustawienia adresu e-mail" #: ../actions/register.php:73 actions/register.php:80 actions/register.php:163 msgid "Email address already exists." -msgstr "Taki e-mail już istnieje" +msgstr "Adres e-mail już istnieje." #: ../lib/mail.php:90 lib/mail.php:90 lib/mail.php:173 msgid "Email address confirmation" -msgstr "Potwierdzenie adresu e-mailowego" +msgstr "Potwierdzenie adresu e-mail" #: ../actions/emailsettings.php:61 actions/emailsettings.php:62 #: actions/emailsettings.php:117 msgid "Email address, like \"UserName@example.org\"" -msgstr "" +msgstr "Adres e-mail, taki jak \"NazwaUżytkownika@przykład.org\"" #: ../actions/invite.php:129 actions/invite.php:137 actions/invite.php:174 +#: actions/invite.php:179 msgid "Email addresses" -msgstr "" +msgstr "Adresy e-mail" #: ../actions/recoverpassword.php:191 actions/recoverpassword.php:197 #: actions/recoverpassword.php:231 msgid "Enter a nickname or email address." -msgstr "Podaj pseudonim lub adres e-mailowy" +msgstr "Podaj pseudonim lub adres e-mail." #: ../actions/smssettings.php:64 actions/smssettings.php:64 #: actions/smssettings.php:119 msgid "Enter the code you received on your phone." -msgstr "" +msgstr "Podaj kod, który otrzymałeś na telefonie." #: ../actions/userauthorization.php:137 actions/userauthorization.php:144 #: actions/userauthorization.php:161 msgid "Error authorizing token" -msgstr "Błąd podczas autoryzacji tokena" +msgstr "Błąd podczas upoważniania tokena" #: ../actions/finishopenidlogin.php:253 actions/finishopenidlogin.php:259 -#: actions/finishopenidlogin.php:297 +#: actions/finishopenidlogin.php:297 actions/finishopenidlogin.php:302 msgid "Error connecting user to OpenID." -msgstr "Błąd w podłączaniu użytkownika do OpenID." +msgstr "Błąd podczas łączenia użytkownika z OpenID." #: ../actions/finishaddopenid.php:78 actions/finishaddopenid.php:78 #: actions/finishaddopenid.php:126 msgid "Error connecting user." -msgstr "Błąd w podłączaniu użytkownika." +msgstr "Błąd podczas łączenia użytkownika." #: ../actions/finishremotesubscribe.php:151 #: actions/finishremotesubscribe.php:153 actions/finishremotesubscribe.php:166 msgid "Error inserting avatar" -msgstr "Błąd we wstawianiu awatara" +msgstr "Błąd podczas wprowadzania awatara" #: ../actions/finishremotesubscribe.php:143 #: actions/finishremotesubscribe.php:145 actions/finishremotesubscribe.php:158 @@ -823,33 +896,36 @@ msgstr "Błąd podczas wprowadzania zdalnego profilu" #: ../actions/recoverpassword.php:240 actions/recoverpassword.php:246 #: actions/recoverpassword.php:280 msgid "Error saving address confirmation." -msgstr "Błąd w zapisie potwierdzenia adresu." +msgstr "Błąd podczas zapisywania potwierdzenia adresu." #: ../actions/userauthorization.php:140 actions/userauthorization.php:147 #: actions/userauthorization.php:164 msgid "Error saving remote profile" -msgstr "Błąd w zapisie zdalnego profilu." +msgstr "Błąd podczas zapisie zdalnego profilu" #: ../lib/openid.php:226 lib/openid.php:226 lib/openid.php:235 +#: lib/openid.php:238 msgid "Error saving the profile." -msgstr "Błąd w zapisie profilu." +msgstr "Błąd podczas zapisywania profilu." #: ../lib/openid.php:237 lib/openid.php:237 lib/openid.php:246 +#: lib/openid.php:249 msgid "Error saving the user." -msgstr "Błąd w zapisie użytkownika." +msgstr "Błąd podczas zapisywanie użytkownika." #: ../actions/password.php:80 actions/profilesettings.php:399 -#: actions/passwordsettings.php:164 +#: actions/passwordsettings.php:164 actions/passwordsettings.php:169 msgid "Error saving user; invalid." -msgstr "Błąd podczas zapisywania użytkownika; niepoprawne dane." +msgstr "Błąd podczas zapisywania użytkownika; nieprawidłowy." #: ../actions/login.php:47 ../actions/login.php:73 #: ../actions/recoverpassword.php:307 ../actions/register.php:98 #: actions/login.php:47 actions/login.php:73 actions/recoverpassword.php:320 #: actions/register.php:108 actions/login.php:112 actions/login.php:138 #: actions/recoverpassword.php:354 actions/register.php:198 +#: actions/login.php:120 msgid "Error setting user." -msgstr "Błąd w ustawianiu danych użytkownika." +msgstr "Błąd podczas ustawiania użytkownika." #: ../actions/finishaddopenid.php:83 actions/finishaddopenid.php:83 #: actions/finishaddopenid.php:131 @@ -869,78 +945,83 @@ msgstr "Błąd kodu potwierdzającego." #: ../actions/finishopenidlogin.php:89 actions/finishopenidlogin.php:95 #: actions/finishopenidlogin.php:117 msgid "Existing nickname" -msgstr "Dotychczasowy pseudonim" +msgstr "Istniejący pseudonim" -#: ../lib/util.php:326 lib/util.php:342 lib/action.php:570 +#: ../lib/util.php:326 lib/util.php:342 lib/action.php:570 lib/action.php:663 msgid "FAQ" msgstr "FAQ" #: ../actions/avatar.php:115 actions/profilesettings.php:352 -#: actions/avatarsettings.php:397 +#: actions/avatarsettings.php:397 actions/avatarsettings.php:349 msgid "Failed updating avatar." -msgstr "Uaktualnianie awatara nie powiodło się." +msgstr "Zaktualizowanie awatara nie powiodło się." #: ../actions/all.php:61 ../actions/allrss.php:64 actions/all.php:61 #: actions/allrss.php:64 actions/all.php:75 actions/allrss.php:107 +#: actions/allrss.php:110 #, php-format msgid "Feed for friends of %s" msgstr "Kanał dla znajomych użytkownika %s" #: ../actions/replies.php:65 ../actions/repliesrss.php:80 #: actions/replies.php:65 actions/repliesrss.php:66 actions/replies.php:134 -#: actions/repliesrss.php:71 +#: actions/repliesrss.php:71 actions/replies.php:136 #, php-format msgid "Feed for replies to %s" msgstr "Kanał dla odpowiedzi do użytkownika %s" #: ../actions/tag.php:55 actions/tag.php:55 actions/tag.php:61 +#: actions/tag.php:68 #, php-format msgid "Feed for tag %s" -msgstr "" +msgstr "Kanał dla znaczników %s" #: ../lib/searchaction.php:105 lib/searchaction.php:105 #: lib/searchgroupnav.php:83 msgid "Find content of notices" -msgstr "" +msgstr "Przeszukaj zawartość wpisów" #: ../lib/searchaction.php:101 lib/searchaction.php:101 #: lib/searchgroupnav.php:81 msgid "Find people on this site" -msgstr "" +msgstr "Znajdź osoby na tej stronie" -#: ../actions/login.php:122 +#: ../actions/login.php:122 actions/login.php:247 msgid "" "For security reasons, please re-enter your user name and password before " "changing your settings." msgstr "" -"Z powodów bezpieczeństwa wprowadź proszę ponownie nazwę użytkownika i hasło " -"przed zmianą swoich ustawień." +"Z powodów bezpieczeństwa ponownie podaj nazwę użytkownika i hasło przed " +"zmienianiem ustawień." #: ../actions/profilesettings.php:44 ../actions/register.php:164 #: actions/profilesettings.php:77 actions/register.php:178 #: actions/profilesettings.php:103 actions/register.php:391 #: actions/showgroup.php:235 actions/showstream.php:262 #: actions/tagother.php:105 lib/groupeditform.php:142 +#: actions/showgroup.php:237 actions/showstream.php:255 +#: actions/tagother.php:104 msgid "Full name" -msgstr "Pełna nazwa" +msgstr "Imię i nazwisko" #: ../actions/profilesettings.php:98 ../actions/register.php:79 #: ../actions/updateprofile.php:93 actions/profilesettings.php:213 #: actions/register.php:86 actions/updateprofile.php:94 #: actions/editgroup.php:195 actions/newgroup.php:146 #: actions/profilesettings.php:202 actions/register.php:171 -#: actions/updateprofile.php:97 +#: actions/updateprofile.php:97 actions/updateprofile.php:99 msgid "Full name is too long (max 255 chars)." -msgstr "Pełna nazwa jest zbyt długa (max. 255 znaków)." +msgstr "Imię i nazwisko jest za długie (maksymalnie 255 znaków)." #: ../lib/util.php:322 lib/util.php:338 lib/action.php:344 lib/action.php:566 +#: lib/action.php:421 lib/action.php:659 msgid "Help" msgstr "Pomoc" #: ../lib/util.php:298 lib/util.php:314 lib/action.php:322 -#: lib/facebookaction.php:200 +#: lib/facebookaction.php:200 lib/action.php:393 lib/facebookaction.php:213 msgid "Home" -msgstr "Początek" +msgstr "Strona główna" #: ../actions/profilesettings.php:46 ../actions/register.php:167 #: actions/profilesettings.php:79 actions/register.php:181 @@ -954,17 +1035,17 @@ msgstr "Strona domowa" #: actions/editgroup.php:192 actions/newgroup.php:143 #: actions/profilesettings.php:199 actions/register.php:168 msgid "Homepage is not a valid URL." -msgstr "Adres strony domowej nie jest poprawnym URL-em." +msgstr "Strona domowa nie jest prawidłowym adresem URL." #: ../actions/emailsettings.php:91 actions/emailsettings.php:98 -#: actions/emailsettings.php:173 +#: actions/emailsettings.php:173 actions/emailsettings.php:178 msgid "I want to post notices by email." -msgstr "" +msgstr "Chcę wysyłać wpisy przez e-mail." #: ../lib/settingsaction.php:102 lib/settingsaction.php:96 #: lib/connectsettingsaction.php:104 msgid "IM" -msgstr "" +msgstr "Komunikator" #: ../actions/imsettings.php:60 actions/imsettings.php:61 #: actions/imsettings.php:118 @@ -982,146 +1063,149 @@ msgid "" "If you already have an account, login with your username and password to " "connect it to your OpenID." msgstr "" -"Jeśli już masz konto, zaloguj się używając nazwy użytkownika i hasła, aby " +"Jeśli już masz konto, zaloguj się za pomocą nazwy użytkownika i hasła, aby " "połączyć je ze swoim identyfikatorem OpenID." -#: ../actions/openidsettings.php:45 +#: ../actions/openidsettings.php:45 actions/openidsettings.php:96 msgid "" "If you want to add an OpenID to your account, enter it in the box below and " "click \"Add\"." msgstr "" -"Jeśli chcesz skojarzyć konto OpenID ze swoim lokalnym kontem, wprowadź " -"identyfikator w poniższe pole i kliknij \"Dodaj\"." +"Jeśli chcesz dodać identyfikator OpenID do swojego konta, podaj go w " +"poniższym polu i naciśnij \"Dodaj\"." -#: ../actions/recoverpassword.php:137 +#: ../actions/recoverpassword.php:137 actions/recoverpassword.php:152 msgid "" "If you've forgotten or lost your password, you can get a new one sent to the " "email address you have stored in your account." msgstr "" +"Jeśli zapomniałeś lub zgubiłeś swoje hasło, możesz dostać nowe na adres e-" +"mail, który podałeś." #: ../actions/emailsettings.php:67 ../actions/smssettings.php:76 #: actions/emailsettings.php:68 actions/smssettings.php:76 #: actions/emailsettings.php:127 actions/smssettings.php:140 msgid "Incoming email" -msgstr "" +msgstr "Wiadomości przychodzące" #: ../actions/emailsettings.php:283 actions/emailsettings.php:301 -#: actions/emailsettings.php:443 +#: actions/emailsettings.php:443 actions/emailsettings.php:450 +#: actions/smssettings.php:518 msgid "Incoming email address removed." -msgstr "" +msgstr "Usunięto przychodzący adres e-mail." #: ../actions/password.php:69 actions/profilesettings.php:388 -#: actions/passwordsettings.php:153 +#: actions/passwordsettings.php:153 actions/passwordsettings.php:158 msgid "Incorrect old password" -msgstr "Stare hasło jest niepoprawne" +msgstr "Niepoprawne stare hasło" #: ../actions/login.php:67 actions/login.php:67 actions/facebookhome.php:131 -#: actions/login.php:132 +#: actions/login.php:132 actions/facebookhome.php:130 actions/login.php:114 msgid "Incorrect username or password." -msgstr "Błędna nazwa użytkownika lub hasło." +msgstr "Niepoprawna nazwa użytkownika lub hasło." -#: ../actions/recoverpassword.php:265 +#: ../actions/recoverpassword.php:265 actions/recoverpassword.php:304 msgid "" "Instructions for recovering your password have been sent to the email " "address registered to your account." msgstr "" -"Instrukcje dotyczące przywrócenia hasła zostały wysłane na adres e-mailowy " -"skojarzony z Twoim kontem." +"Instrukcje przywracania hasła zostały wysłane na adres e-mail zarejestrowany " +"z Twoim kontem." #: ../actions/updateprofile.php:114 actions/updateprofile.php:115 -#: actions/updateprofile.php:118 +#: actions/updateprofile.php:118 actions/updateprofile.php:120 #, php-format msgid "Invalid avatar URL '%s'" -msgstr "Błędny URL awatara '%s'" +msgstr "Nieprawidłowy adres URL awatara \"%s\"" #: ../actions/invite.php:55 actions/invite.php:62 actions/invite.php:70 #, php-format msgid "Invalid email address: %s" -msgstr "" +msgstr "Nieprawidłowy adres e-mail: %s" #: ../actions/updateprofile.php:98 actions/updateprofile.php:99 -#: actions/updateprofile.php:102 +#: actions/updateprofile.php:102 actions/updateprofile.php:104 #, php-format msgid "Invalid homepage '%s'" -msgstr "Błędna strona domowa '%s'" +msgstr "Nieprawidłowa strona domowa \"%s\"" #: ../actions/updateprofile.php:82 actions/updateprofile.php:83 -#: actions/updateprofile.php:86 +#: actions/updateprofile.php:86 actions/updateprofile.php:88 #, php-format msgid "Invalid license URL '%s'" -msgstr "Błędny URL licencji '%s'" +msgstr "Nieprawidłowy adres URL licencji \"%s\"" #: ../actions/postnotice.php:61 actions/postnotice.php:62 #: actions/postnotice.php:66 msgid "Invalid notice content" -msgstr "Błędna zawartość wpisu" +msgstr "Nieprawidłowa zawartość wpisu" #: ../actions/postnotice.php:67 actions/postnotice.php:68 #: actions/postnotice.php:72 msgid "Invalid notice uri" -msgstr "Błędny URI wpisu" +msgstr "Nieprawidłowy adres URI wpisu" #: ../actions/postnotice.php:72 actions/postnotice.php:73 #: actions/postnotice.php:77 msgid "Invalid notice url" -msgstr "Błędny URL wpisu" +msgstr "Nieprawidłowy adres URL wpisu" #: ../actions/updateprofile.php:87 actions/updateprofile.php:88 -#: actions/updateprofile.php:91 +#: actions/updateprofile.php:91 actions/updateprofile.php:93 #, php-format msgid "Invalid profile URL '%s'." -msgstr "Błędny URL profilu '%s'." +msgstr "Nieprawidłowy adres URL profilu \"%s\"." #: ../actions/remotesubscribe.php:96 actions/remotesubscribe.php:105 #: actions/remotesubscribe.php:135 msgid "Invalid profile URL (bad format)" -msgstr "Błędny URL profilu (zły format)" +msgstr "Nieprawidłowy adres URL profilu (błędny format)" #: ../actions/finishremotesubscribe.php:77 #: actions/finishremotesubscribe.php:79 actions/finishremotesubscribe.php:80 msgid "Invalid profile URL returned by server." -msgstr "Błędny URL profilu zwrócony przez serwer." +msgstr "Nieprawidłowy adres URL profilu zwrócony przez serwer." #: ../actions/avatarbynickname.php:37 actions/avatarbynickname.php:37 #: actions/avatarbynickname.php:69 msgid "Invalid size." -msgstr "Niepoprawny rozmiar." +msgstr "Nieprawidłowy rozmiar." #: ../actions/finishopenidlogin.php:235 ../actions/register.php:93 #: ../actions/register.php:111 actions/finishopenidlogin.php:241 #: actions/register.php:103 actions/register.php:121 #: actions/finishopenidlogin.php:279 actions/register.php:193 -#: actions/register.php:211 +#: actions/register.php:211 actions/finishopenidlogin.php:284 msgid "Invalid username or password." -msgstr "Błędna nazwa użytkownika lub hasło." +msgstr "Nieprawidłowa nazwa użytkownika lub hasło." #: ../actions/invite.php:79 actions/invite.php:86 actions/invite.php:102 msgid "Invitation(s) sent" -msgstr "" +msgstr "Wysłano zaproszenia" #: ../actions/invite.php:97 actions/invite.php:104 actions/invite.php:136 msgid "Invitation(s) sent to the following people:" -msgstr "" +msgstr "Wysłano zaproszenia do następujących osób:" #: ../lib/util.php:306 lib/util.php:322 lib/facebookaction.php:207 -#: lib/subgroupnav.php:103 +#: lib/subgroupnav.php:103 lib/facebookaction.php:220 msgid "Invite" -msgstr "" +msgstr "Zaproś" #: ../actions/invite.php:123 actions/invite.php:130 actions/invite.php:104 msgid "Invite new users" -msgstr "" +msgstr "Zaproś nowych użytkowników" -#: ../lib/util.php:261 lib/util.php:277 lib/action.php:609 +#: ../lib/util.php:261 lib/util.php:277 lib/action.php:609 lib/action.php:706 #, php-format msgid "" "It runs the [Laconica](http://laconi.ca/) microblogging software, version %" "s, available under the [GNU Affero General Public License](http://www.fsf." "org/licensing/licenses/agpl-3.0.html)." msgstr "" -"Działa pod kontrolą oprogramowania [Laconica](http://laconi.ca/) służącego " -"do prowadzenia mikroblogów, w wersji %s, dostępnego na licencji [GNU Affero " -"General Public License](http://www.fsf.org/licensing/licenses/agpl-3.0.html)." +"Działa pod kontrolą oprogramowania do mikroblogowania [Laconica](http://" +"laconi.ca/) w wersji %s, dostępnego na [Powszechnej Licencji Publicznej GNU " +"Affero](http://www.fsf.org/licensing/licenses/agpl-3.0.html)." #: ../actions/imsettings.php:173 actions/imsettings.php:181 #: actions/imsettings.php:296 @@ -1129,132 +1213,143 @@ msgid "Jabber ID already belongs to another user." msgstr "Identyfikator Jabbera należy już do innego użytkownika." #: ../actions/imsettings.php:62 actions/imsettings.php:63 +#: actions/imsettings.php:120 #, php-format msgid "" "Jabber or GTalk address, like \"UserName@example.org\". First, make sure to " "add %s to your buddy list in your IM client or on GTalk." msgstr "" -"Adres Jabbera lub GTalka w postaci \"Użytkownik@przykladowadomena.org\". Nie " -"zapomnij dodać %s do listy znajomych w swoim komunikatorze lub panelu GTalka." +"Adres Jabbera lub GTalk, taki jak \"NazwaUżytkownika@przykład.org\". " +"Najpierw upewnij się, że dodałeś %s do listy znajomych w komunikatorze lub " +"na GTalk." #: ../actions/profilesettings.php:57 actions/profilesettings.php:90 #: actions/profilesettings.php:128 msgid "Language" -msgstr "" +msgstr "Język" #: ../actions/profilesettings.php:113 actions/profilesettings.php:228 #: actions/profilesettings.php:217 msgid "Language is too long (max 50 chars)." -msgstr "" +msgstr "Język jest za długi (maksymalnie 50 znaków)." #: ../actions/profilesettings.php:52 ../actions/register.php:173 #: actions/profilesettings.php:85 actions/register.php:187 #: actions/profilesettings.php:117 actions/register.php:408 #: actions/showgroup.php:244 actions/showstream.php:271 #: actions/tagother.php:113 lib/groupeditform.php:156 lib/grouplist.php:126 -#: lib/profilelist.php:125 +#: lib/profilelist.php:125 actions/showgroup.php:246 +#: actions/showstream.php:264 actions/tagother.php:112 lib/profilelist.php:123 msgid "Location" -msgstr "Lokalizacja" +msgstr "Położenie" #: ../actions/profilesettings.php:104 ../actions/register.php:85 #: ../actions/updateprofile.php:108 actions/profilesettings.php:219 #: actions/register.php:92 actions/updateprofile.php:109 #: actions/editgroup.php:201 actions/newgroup.php:152 #: actions/profilesettings.php:208 actions/register.php:177 -#: actions/updateprofile.php:112 +#: actions/updateprofile.php:112 actions/updateprofile.php:114 msgid "Location is too long (max 255 chars)." -msgstr "Lokalizacja jest za długa (max. 255 znaków)." +msgstr "Położenie jest za długie (maksymalnie 255 znaków)." #: ../actions/login.php:97 ../actions/login.php:106 #: ../actions/openidlogin.php:68 ../lib/util.php:310 actions/login.php:97 #: actions/login.php:106 actions/openidlogin.php:77 lib/util.php:326 #: actions/facebooklogin.php:93 actions/login.php:186 actions/login.php:239 #: actions/openidlogin.php:112 lib/action.php:335 lib/facebookaction.php:288 -#: lib/facebookaction.php:315 lib/logingroupnav.php:75 +#: lib/facebookaction.php:315 lib/logingroupnav.php:75 actions/login.php:169 +#: actions/login.php:222 actions/openidlogin.php:121 lib/action.php:412 +#: lib/facebookaction.php:293 lib/facebookaction.php:319 #, php-format msgid "Login" -msgstr "Login" +msgstr "Zaloguj się" #: ../actions/openidlogin.php:44 actions/openidlogin.php:52 -#: actions/openidlogin.php:62 +#: actions/openidlogin.php:62 actions/openidlogin.php:70 #, php-format msgid "Login with an [OpenID](%%doc.openid%%) account." -msgstr "Zaloguj się używając konta [OpenID](%%doc.openid%%)." +msgstr "Zaloguj się za pomocą konta [OpenID](%%doc.openid%%)." -#: ../actions/login.php:126 +#: ../actions/login.php:126 actions/login.php:251 #, php-format msgid "" "Login with your username and password. Don't have a username yet? [Register]" "(%%action.register%%) a new account, or try [OpenID](%%action.openidlogin%" "%). " msgstr "" -"Zaloguj się używając nazwy użytkownika i hasła. Nie masz ich jeszcze? " -"[Zarejestruj się](%%action.register%%) i utwórz konto, albo użyj swojego " -"[OpenID](%%action.openidlogin%%)." +"Zaloguj się za pomocą nazwy użytkownika i hasła. Nie masz ich jeszcze? " +"[Zarejestruj](%%action.register%%) nowe konto lub wypróbuj [OpenID](%%action." +"openidlogin%%). " -#: ../lib/util.php:308 lib/util.php:324 lib/action.php:332 +#: ../lib/util.php:308 lib/util.php:324 lib/action.php:332 lib/action.php:409 msgid "Logout" -msgstr "Wyloguj" +msgstr "Wyloguj się" #: ../actions/register.php:166 actions/register.php:180 #: actions/register.php:393 msgid "Longer name, preferably your \"real\" name" -msgstr "" +msgstr "Dłuższa nazwa, najlepiej twoje \"prawdziwe\" nazwisko" #: ../actions/login.php:110 actions/login.php:110 actions/login.php:245 -#: lib/facebookaction.php:320 +#: lib/facebookaction.php:320 actions/login.php:228 lib/facebookaction.php:325 msgid "Lost or forgotten password?" -msgstr "Zgubione hasło?" +msgstr "Zgubione lub zapomniane hasło?" #: ../actions/emailsettings.php:80 ../actions/smssettings.php:89 #: actions/emailsettings.php:81 actions/smssettings.php:89 +#: actions/emailsettings.php:139 actions/smssettings.php:150 msgid "Make a new email address for posting to; cancels the old one." -msgstr "" +msgstr "Używaj nowego adresu e-mail do wysyłania; anuluj stary." #: ../actions/emailsettings.php:27 actions/emailsettings.php:27 #: actions/emailsettings.php:71 #, php-format msgid "Manage how you get email from %%site.name%%." -msgstr "" +msgstr "Zarządzaj, jak otrzymywać wiadomości e-mail od %%site.name%%." #: ../actions/showstream.php:300 actions/showstream.php:315 #: actions/showstream.php:480 msgid "Member since" -msgstr "W serwisie od" +msgstr "Członek od" #: ../actions/userrss.php:70 actions/userrss.php:67 actions/userrss.php:72 #, php-format msgid "Microblog by %s" -msgstr "%s – mikroblog" +msgstr "Mikroblog użytkownika %s" -#: ../actions/smssettings.php:304 +#: ../actions/smssettings.php:304 actions/smssettings.php:464 #, php-format msgid "" "Mobile carrier for your phone. If you know a carrier that accepts SMS over " "email but isn't listed here, send email to let us know at %s." msgstr "" +"Operator komórkowy Twojego telefonu. Jeśli znasz operatora, który akceptuje " +"wiadomości SMS przez e-mail, a nie znajduje się na liście, wyślij wiadomość " +"e-mail na %s (w języku angielskim), aby nam o tym powiedzieć." #: ../actions/finishopenidlogin.php:79 ../actions/register.php:188 #: actions/finishopenidlogin.php:85 actions/register.php:202 #: actions/finishopenidlogin.php:107 actions/register.php:429 +#: actions/register.php:430 msgid "My text and files are available under " -msgstr "Moje teksty i pliki są widoczne pod" +msgstr "Moje teksty i pliki są dostępne na " #: ../actions/emailsettings.php:82 ../actions/smssettings.php:91 #: actions/emailsettings.php:83 actions/smssettings.php:91 #: actions/emailsettings.php:142 actions/smssettings.php:152 msgid "New" -msgstr "" +msgstr "Nowe" #: ../lib/mail.php:144 lib/mail.php:144 lib/mail.php:286 #, php-format msgid "New email address for posting to %s" -msgstr "" +msgstr "Nowy adres e-mail do wysyłania do %s" #: ../actions/emailsettings.php:297 actions/emailsettings.php:315 -#: actions/emailsettings.php:465 +#: actions/emailsettings.php:465 actions/emailsettings.php:472 +#: actions/smssettings.php:542 msgid "New incoming email address added." -msgstr "" +msgstr "Dodano nowy przychodzący adres e-mail." #: ../actions/finishopenidlogin.php:71 actions/finishopenidlogin.php:77 #: actions/finishopenidlogin.php:99 @@ -1272,9 +1367,9 @@ msgstr "Nowy wpis" msgid "New password" msgstr "Nowe hasło" -#: ../actions/recoverpassword.php:314 +#: ../actions/recoverpassword.php:314 actions/recoverpassword.php:361 msgid "New password successfully saved. You are now logged in." -msgstr "Nowe hasło zapisano pomyślnie. Możesz się zalogować." +msgstr "Pomyślnie zapisano nowe hasło. Jesteś teraz zalogowany." #: ../actions/login.php:101 ../actions/profilesettings.php:41 #: ../actions/register.php:151 actions/login.php:101 @@ -1282,7 +1377,9 @@ msgstr "Nowe hasło zapisano pomyślnie. Możesz się zalogować." #: actions/login.php:228 actions/profilesettings.php:98 #: actions/register.php:367 actions/showgroup.php:224 #: actions/showstream.php:251 actions/tagother.php:95 -#: lib/facebookaction.php:308 lib/groupeditform.php:137 +#: lib/facebookaction.php:308 lib/groupeditform.php:137 actions/login.php:211 +#: actions/showgroup.php:226 actions/showstream.php:244 +#: actions/tagother.php:94 lib/facebookaction.php:312 msgid "Nickname" msgstr "Pseudonim" @@ -1293,21 +1390,23 @@ msgstr "Pseudonim" #: actions/newgroup.php:134 actions/profilesettings.php:214 #: actions/register.php:159 msgid "Nickname already in use. Try another one." -msgstr "Ten pseudonim jest już w użyciu. Wybierz inny." +msgstr "Pseudonim jest już używany. Spróbuj innego." #: ../actions/finishopenidlogin.php:165 ../actions/profilesettings.php:88 #: ../actions/register.php:67 ../actions/updateprofile.php:77 #: actions/finishopenidlogin.php:171 actions/profilesettings.php:203 #: actions/register.php:74 actions/updateprofile.php:78 #: actions/finishopenidlogin.php:205 actions/profilesettings.php:192 -#: actions/updateprofile.php:81 +#: actions/updateprofile.php:81 actions/editgroup.php:179 +#: actions/newgroup.php:130 actions/register.php:156 +#: actions/updateprofile.php:83 msgid "Nickname must have only lowercase letters and numbers and no spaces." -msgstr "Pseudonim musi zawierać tylko małe litery i cyfry, bez znaków spacji." +msgstr "Pseudonim może zawierać tylko małe litery i cyfry, bez spacji." #: ../actions/finishopenidlogin.php:170 actions/finishopenidlogin.php:176 #: actions/finishopenidlogin.php:210 msgid "Nickname not allowed." -msgstr "Pseudonim niedozwolony." +msgstr "Niedozwolony pseudonim." #: ../actions/remotesubscribe.php:72 actions/remotesubscribe.php:81 #: actions/remotesubscribe.php:106 @@ -1317,12 +1416,13 @@ msgstr "Pseudonim użytkownika którego chcesz obserwować" #: ../actions/recoverpassword.php:162 actions/recoverpassword.php:167 #: actions/recoverpassword.php:186 msgid "Nickname or email" -msgstr "Pseudonim lub e-mail" +msgstr "Pseudonim lub adres e-mail" #: ../actions/deletenotice.php:59 actions/deletenotice.php:60 #: actions/block.php:147 actions/deletenotice.php:118 +#: actions/deletenotice.php:116 msgid "No" -msgstr "" +msgstr "Nie" #: ../actions/imsettings.php:156 actions/imsettings.php:164 #: actions/imsettings.php:279 @@ -1332,17 +1432,17 @@ msgstr "Brak identyfikatora Jabbera." #: ../actions/userauthorization.php:129 actions/userauthorization.php:136 #: actions/userauthorization.php:153 msgid "No authorization request!" -msgstr "Brak żądania autoryzacji!" +msgstr "Brak żądania upoważnienia!" #: ../actions/smssettings.php:181 actions/smssettings.php:189 #: actions/smssettings.php:299 msgid "No carrier selected." -msgstr "" +msgstr "Nie wybrano operatora." #: ../actions/smssettings.php:316 actions/smssettings.php:324 #: actions/smssettings.php:486 msgid "No code entered" -msgstr "" +msgstr "Nie podano kodu" #: ../actions/confirmaddress.php:33 actions/confirmaddress.php:33 #: actions/confirmaddress.php:75 @@ -1352,27 +1452,29 @@ msgstr "Brak kodu potwierdzającego." #: ../actions/newnotice.php:44 actions/newmessage.php:53 #: actions/newnotice.php:44 classes/Command.php:197 actions/newmessage.php:109 #: actions/newnotice.php:126 classes/Command.php:223 +#: actions/newmessage.php:142 actions/newnotice.php:131 lib/command.php:223 msgid "No content!" msgstr "Brak zawartości!" #: ../actions/emailsettings.php:174 actions/emailsettings.php:192 -#: actions/emailsettings.php:304 +#: actions/emailsettings.php:304 actions/emailsettings.php:311 msgid "No email address." -msgstr "" +msgstr "Brak adresu e-mail." #: ../actions/userbyid.php:32 actions/userbyid.php:32 actions/userbyid.php:70 msgid "No id." msgstr "Brak identyfikatora." #: ../actions/emailsettings.php:271 actions/emailsettings.php:289 -#: actions/emailsettings.php:430 +#: actions/emailsettings.php:430 actions/emailsettings.php:437 +#: actions/smssettings.php:505 msgid "No incoming email address." -msgstr "" +msgstr "Brak przychodzącego adresu e-mail." #: ../actions/finishremotesubscribe.php:65 #: actions/finishremotesubscribe.php:67 actions/finishremotesubscribe.php:68 msgid "No nickname provided by remote server." -msgstr "Zdalny serwer nie wysłał pseudonimu." +msgstr "Zdalny serwer nie dostarczył pseudonimu." #: ../actions/avatarbynickname.php:27 actions/avatarbynickname.php:27 #: actions/avatarbynickname.php:59 actions/leavegroup.php:81 @@ -1383,24 +1485,24 @@ msgstr "Brak pseudonimu." #: ../actions/smssettings.php:229 actions/emailsettings.php:240 #: actions/imsettings.php:214 actions/smssettings.php:237 #: actions/emailsettings.php:363 actions/imsettings.php:345 -#: actions/smssettings.php:358 +#: actions/smssettings.php:358 actions/emailsettings.php:370 msgid "No pending confirmation to cancel." msgstr "Brak oczekujących potwierdzeń do anulowania." #: ../actions/smssettings.php:176 actions/smssettings.php:184 #: actions/smssettings.php:294 msgid "No phone number." -msgstr "" +msgstr "Brak numeru telefonu." #: ../actions/finishremotesubscribe.php:72 #: actions/finishremotesubscribe.php:74 actions/finishremotesubscribe.php:75 msgid "No profile URL returned by server." -msgstr "Serwer nie zwrócił żadnego URL-a." +msgstr "Serwer nie zwrócił adresu URL profilu." #: ../actions/recoverpassword.php:226 actions/recoverpassword.php:232 #: actions/recoverpassword.php:266 msgid "No registered email address for that user." -msgstr "Brak zarejestrowanych adresów e-mailowych dla tego użytkownika." +msgstr "Brak zarejestrowanych adresów e-mail dla tego użytkownika." #: ../actions/userauthorization.php:49 actions/userauthorization.php:55 #: actions/userauthorization.php:57 @@ -1410,51 +1512,52 @@ msgstr "Nie znaleziono żądania!" #: ../actions/noticesearch.php:64 ../actions/peoplesearch.php:64 #: actions/noticesearch.php:69 actions/peoplesearch.php:69 #: actions/groupsearch.php:81 actions/noticesearch.php:104 -#: actions/peoplesearch.php:85 +#: actions/peoplesearch.php:85 actions/noticesearch.php:117 msgid "No results" msgstr "Brak wyników" #: ../actions/avatarbynickname.php:32 actions/avatarbynickname.php:32 #: actions/avatarbynickname.php:64 msgid "No size." -msgstr "Zerowy rozmiar." +msgstr "Brak rozmiaru." #: ../actions/twitapistatuses.php:595 actions/twitapifavorites.php:136 #: actions/twitapistatuses.php:520 actions/twitapifavorites.php:112 -#: actions/twitapistatuses.php:446 +#: actions/twitapistatuses.php:446 actions/twitapifavorites.php:118 +#: actions/twitapistatuses.php:470 msgid "No status found with that ID." -msgstr "" +msgstr "Nie znaleziono statusów z tym identyfikatorem." #: ../actions/twitapistatuses.php:555 actions/twitapistatuses.php:478 -#: actions/twitapistatuses.php:418 +#: actions/twitapistatuses.php:418 actions/twitapistatuses.php:442 msgid "No status with that ID found." -msgstr "" +msgstr "Nie znaleziono statusów z tym identyfikatorem." #: ../actions/openidsettings.php:135 actions/openidsettings.php:144 #: actions/openidsettings.php:222 msgid "No such OpenID." -msgstr "Brak takiego identyfikatora OpenID." +msgstr "Nie ma takiego identyfikatora OpenID." #: ../actions/doc.php:29 actions/doc.php:29 actions/doc.php:64 msgid "No such document." -msgstr "Brak takiego dokumentu." +msgstr "Nie ma takiego dokumentu." #: ../actions/shownotice.php:32 ../actions/shownotice.php:83 #: ../lib/deleteaction.php:30 actions/shownotice.php:32 #: actions/shownotice.php:83 lib/deleteaction.php:30 actions/shownotice.php:87 #: lib/deleteaction.php:51 msgid "No such notice." -msgstr "Brak takiego wpisu." +msgstr "Nie ma takiego wpisu." #: ../actions/recoverpassword.php:56 actions/recoverpassword.php:56 #: actions/recoverpassword.php:62 msgid "No such recovery code." -msgstr "Brak takiego kodu przywracania." +msgstr "Nie ma takiego kodu przywracania." #: ../actions/postnotice.php:56 actions/postnotice.php:57 #: actions/postnotice.php:60 msgid "No such subscription" -msgstr "Nie ma takiej obserwacji" +msgstr "Nie ma takiej subskrypcji" #: ../actions/all.php:34 ../actions/allrss.php:35 #: ../actions/avatarbynickname.php:43 ../actions/foaf.php:40 @@ -1480,14 +1583,16 @@ msgstr "Nie ma takiej obserwacji" #: actions/usergroups.php:92 actions/userrss.php:38 actions/xrds.php:73 #: classes/Command.php:140 classes/Command.php:185 classes/Command.php:234 #: classes/Command.php:271 lib/galleryaction.php:60 lib/mailbox.php:82 -#: lib/subs.php:34 lib/subs.php:109 +#: lib/subs.php:34 lib/subs.php:109 actions/all.php:56 actions/allrss.php:68 +#: actions/favoritesrss.php:74 lib/command.php:140 lib/command.php:185 +#: lib/command.php:234 lib/command.php:271 lib/mailbox.php:84 msgid "No such user." msgstr "Brak takiego użytkownika." #: ../actions/recoverpassword.php:211 actions/recoverpassword.php:217 #: actions/recoverpassword.php:251 msgid "No user with that email address or username." -msgstr "" +msgstr "Brak użytkownika z tym adresem e-mail lub nazwą użytkownika." #: ../lib/gallery.php:80 lib/gallery.php:85 msgid "Nobody to show!" @@ -1501,64 +1606,66 @@ msgstr "To nie jest kod przywracania." #: ../scripts/maildaemon.php:50 scripts/maildaemon.php:50 #: scripts/maildaemon.php:53 msgid "Not a registered user." -msgstr "" +msgstr "To nie jest zarejestrowany użytkownik." #: ../lib/twitterapi.php:226 ../lib/twitterapi.php:247 #: ../lib/twitterapi.php:332 lib/twitterapi.php:391 lib/twitterapi.php:418 #: lib/twitterapi.php:502 lib/twitterapi.php:448 lib/twitterapi.php:476 -#: lib/twitterapi.php:566 +#: lib/twitterapi.php:566 lib/twitterapi.php:483 lib/twitterapi.php:511 +#: lib/twitterapi.php:601 msgid "Not a supported data format." -msgstr "" +msgstr "To nie jest obsługiwany format danych." #: ../actions/imsettings.php:167 actions/imsettings.php:175 #: actions/imsettings.php:290 msgid "Not a valid Jabber ID" -msgstr "Niepoprawny identyfikator Jabbera" +msgstr "To nie jest prawidłowy identyfikator Jabbera" #: ../lib/openid.php:131 lib/openid.php:131 lib/openid.php:140 +#: lib/openid.php:143 msgid "Not a valid OpenID." -msgstr "Niepoprawny identyfikator OpenID." +msgstr "To nie jest prawidłowy identyfikator OpenID." #: ../actions/emailsettings.php:185 actions/emailsettings.php:203 -#: actions/emailsettings.php:315 +#: actions/emailsettings.php:315 actions/emailsettings.php:322 msgid "Not a valid email address" -msgstr "" +msgstr "To nie jest prawidłowy adres e-mail" #: ../actions/register.php:63 actions/register.php:70 actions/register.php:152 msgid "Not a valid email address." -msgstr "Niewłaściwy adres e-mailowy." +msgstr "To nie jest prawidłowy adres e-mail." #: ../actions/profilesettings.php:91 ../actions/register.php:71 #: actions/profilesettings.php:206 actions/register.php:78 #: actions/editgroup.php:186 actions/newgroup.php:137 #: actions/profilesettings.php:195 actions/register.php:161 msgid "Not a valid nickname." -msgstr "Niewłaściwy pseudonim." +msgstr "To nie jest prawidłowy pseudonim." #: ../actions/remotesubscribe.php:120 actions/remotesubscribe.php:129 #: actions/remotesubscribe.php:159 msgid "Not a valid profile URL (incorrect services)." -msgstr "Błędny URL profilu (niepoprawne usługi)" +msgstr "To nie jest prawidłowy adres URL profilu (niepoprawne usługi)." #: ../actions/remotesubscribe.php:113 actions/remotesubscribe.php:122 #: actions/remotesubscribe.php:152 msgid "Not a valid profile URL (no XRDS defined)." -msgstr "Błędny URL profilu (nie zdefiniowany XRDS)" +msgstr "To nie jest prawidłowy adres URL profilu (nie podano XRDS)." #: ../actions/remotesubscribe.php:104 actions/remotesubscribe.php:113 #: actions/remotesubscribe.php:143 msgid "Not a valid profile URL (no YADIS document)." -msgstr "Błędny URL profilu (brak dokumentu YADIS)" +msgstr "To nie jest prawidłowy adres URL profilu (brak dokumentu YADIS)." #: ../actions/avatar.php:95 actions/profilesettings.php:332 -#: lib/imagefile.php:87 +#: lib/imagefile.php:87 lib/imagefile.php:90 msgid "Not an image or corrupt file." -msgstr "Brak obrazka lub plik uszkodzony." +msgstr "To nie jest obraz lub lub plik jest uszkodzony." #: ../actions/finishremotesubscribe.php:51 #: actions/finishremotesubscribe.php:53 actions/finishremotesubscribe.php:54 msgid "Not authorized." -msgstr "Brak autoryzacji." +msgstr "Brak upoważnienia." #: ../actions/finishremotesubscribe.php:38 #: actions/finishremotesubscribe.php:38 actions/finishremotesubscribe.php:40 @@ -1566,9 +1673,9 @@ msgid "Not expecting this response!" msgstr "Nieoczekiwana odpowiedź!" #: ../actions/twitapistatuses.php:422 actions/twitapistatuses.php:361 -#: actions/twitapistatuses.php:309 +#: actions/twitapistatuses.php:309 actions/twitapistatuses.php:327 msgid "Not found" -msgstr "" +msgstr "Nie znaleziono" #: ../actions/finishaddopenid.php:29 ../actions/logout.php:33 #: ../actions/newnotice.php:29 ../actions/subscribe.php:28 @@ -1582,18 +1689,18 @@ msgstr "" #: actions/newmessage.php:83 actions/newnotice.php:90 actions/nudge.php:63 #: actions/subedit.php:31 actions/subscribe.php:30 actions/unblock.php:60 #: actions/unsubscribe.php:27 lib/deleteaction.php:66 -#: lib/settingsaction.php:72 +#: lib/settingsaction.php:72 actions/newmessage.php:87 msgid "Not logged in." msgstr "Niezalogowany." #: ../lib/subs.php:91 lib/subs.php:104 lib/subs.php:122 msgid "Not subscribed!." -msgstr "Nie obserwujesz!." +msgstr "Nie zasubskrybowane!" #: ../actions/opensearch.php:35 actions/opensearch.php:35 #: actions/opensearch.php:67 msgid "Notice Search" -msgstr "" +msgstr "Wyszukiwanie wpisów" #: ../actions/showstream.php:82 actions/showstream.php:82 #: actions/showstream.php:180 actions/showstream.php:187 @@ -1605,19 +1712,19 @@ msgstr "Kanał wpisów dla %s" #: ../actions/shownotice.php:39 actions/shownotice.php:39 #: actions/shownotice.php:94 msgid "Notice has no profile" -msgstr "Wpis nie ma przypisanego profilu" +msgstr "Wpis nie posiada profilu" #: ../actions/showstream.php:316 actions/showstream.php:331 #: actions/showstream.php:504 lib/facebookaction.php:477 lib/mailbox.php:116 -#: lib/noticelist.php:87 +#: lib/noticelist.php:87 lib/facebookaction.php:581 lib/mailbox.php:118 msgid "Notices" msgstr "Wpisy" #: ../actions/tag.php:35 ../actions/tag.php:81 actions/tag.php:35 -#: actions/tag.php:81 actions/tag.php:41 +#: actions/tag.php:81 actions/tag.php:41 actions/tag.php:49 #, php-format msgid "Notices tagged with %s" -msgstr "" +msgstr "Wpisy ze znacznikiem %s" #: ../actions/password.php:39 actions/profilesettings.php:178 #: actions/passwordsettings.php:97 @@ -1626,7 +1733,7 @@ msgstr "Stare hasło" #: ../lib/settingsaction.php:96 ../lib/util.php:314 lib/settingsaction.php:90 #: lib/util.php:330 lib/accountsettingsaction.php:116 lib/action.php:341 -#: lib/logingroupnav.php:81 +#: lib/logingroupnav.php:81 lib/action.php:418 msgid "OpenID" msgstr "OpenID" @@ -1636,39 +1743,43 @@ msgid "OpenID Account Setup" msgstr "Ustawienia konta OpenID" #: ../lib/openid.php:180 lib/openid.php:180 lib/openid.php:266 +#: lib/openid.php:269 msgid "OpenID Auto-Submit" -msgstr "Automatyczne zatwierdzanie OpenID" +msgstr "Automatyczne wysłanie OpenID" #: ../actions/finishaddopenid.php:99 ../actions/finishopenidlogin.php:140 #: ../actions/openidlogin.php:60 actions/finishaddopenid.php:99 #: actions/finishopenidlogin.php:146 actions/openidlogin.php:68 #: actions/finishaddopenid.php:170 actions/openidlogin.php:80 +#: actions/openidlogin.php:89 msgid "OpenID Login" -msgstr "Użytkownik OpenID" +msgstr "Login OpenID" #: ../actions/openidlogin.php:65 ../actions/openidsettings.php:49 #: actions/openidlogin.php:74 actions/openidsettings.php:50 #: actions/openidlogin.php:102 actions/openidsettings.php:101 +#: actions/openidlogin.php:111 msgid "OpenID URL" -msgstr "URL usługi OpenID" +msgstr "Adres URL identyfikatora OpenID" #: ../actions/finishaddopenid.php:42 ../actions/finishopenidlogin.php:103 #: actions/finishaddopenid.php:42 actions/finishopenidlogin.php:109 #: actions/finishaddopenid.php:88 actions/finishopenidlogin.php:130 msgid "OpenID authentication cancelled." -msgstr "Uwiarygadnianie OpenID przerwane." +msgstr "Anulowano uwierzytelnienie OpenID." #: ../actions/finishaddopenid.php:46 ../actions/finishopenidlogin.php:107 #: actions/finishaddopenid.php:46 actions/finishopenidlogin.php:113 #: actions/finishaddopenid.php:92 actions/finishopenidlogin.php:134 #, php-format msgid "OpenID authentication failed: %s" -msgstr "Uwiarygadnianie OpenID nie powiodło się: %s" +msgstr "Uwierzytelnienie OpenID nie powiodło się: %s" #: ../lib/openid.php:133 lib/openid.php:133 lib/openid.php:142 +#: lib/openid.php:145 #, php-format msgid "OpenID failure: %s" -msgstr "Awaria OpenID: %s" +msgstr "Niepowodzenie OpenID: %s" #: ../actions/openidsettings.php:144 actions/openidsettings.php:153 #: actions/openidsettings.php:231 @@ -1681,13 +1792,14 @@ msgid "OpenID settings" msgstr "Ustawienia OpenID" #: ../actions/invite.php:135 actions/invite.php:143 actions/invite.php:180 +#: actions/invite.php:186 msgid "Optionally add a personal message to the invitation." -msgstr "" +msgstr "Opcjonalnie dodaj osobistą wiadomość do zaproszenia." #: ../actions/avatar.php:84 actions/profilesettings.php:321 -#: lib/imagefile.php:75 +#: lib/imagefile.php:75 lib/imagefile.php:79 msgid "Partial upload." -msgstr "Częściowa wysyłka." +msgstr "Częściowo wysłano." #: ../actions/finishopenidlogin.php:90 ../actions/login.php:102 #: ../actions/register.php:153 ../lib/settingsaction.php:93 @@ -1695,63 +1807,68 @@ msgstr "Częściowa wysyłka." #: actions/register.php:167 actions/finishopenidlogin.php:118 #: actions/login.php:231 actions/register.php:372 #: lib/accountsettingsaction.php:110 lib/facebookaction.php:311 +#: actions/login.php:214 lib/facebookaction.php:315 msgid "Password" msgstr "Hasło" #: ../actions/recoverpassword.php:288 actions/recoverpassword.php:301 #: actions/recoverpassword.php:335 msgid "Password and confirmation do not match." -msgstr "Hasło i jego potwierdzenie nie pasują do siebie." +msgstr "Hasło i potwierdzenie nie pasują do siebie." #: ../actions/recoverpassword.php:284 actions/recoverpassword.php:297 #: actions/recoverpassword.php:331 msgid "Password must be 6 chars or more." -msgstr "Hasło musi mieć 6 lub więcej znaków." +msgstr "Hasło musi mieć sześć lub więcej znaków." #: ../actions/recoverpassword.php:261 ../actions/recoverpassword.php:263 #: actions/recoverpassword.php:267 actions/recoverpassword.php:269 #: actions/recoverpassword.php:199 actions/recoverpassword.php:301 msgid "Password recovery requested" -msgstr "Zażądano odzyskania hasła" +msgstr "Zażądano przywracania hasła" #: ../actions/password.php:89 ../actions/recoverpassword.php:313 #: actions/profilesettings.php:408 actions/recoverpassword.php:326 #: actions/passwordsettings.php:173 actions/recoverpassword.php:200 +#: actions/passwordsettings.php:178 msgid "Password saved." -msgstr "Hasło zostało zapisane." +msgstr "Zapisano hasło." #: ../actions/password.php:61 ../actions/register.php:88 #: actions/profilesettings.php:380 actions/register.php:98 #: actions/passwordsettings.php:145 actions/register.php:183 +#: actions/passwordsettings.php:150 msgid "Passwords don't match." -msgstr "Podane hasła nie pasują do siebie." +msgstr "Hasła nie pasują do siebie." #: ../lib/searchaction.php:100 lib/searchaction.php:100 #: lib/searchgroupnav.php:80 msgid "People" -msgstr "" +msgstr "Osoby" #: ../actions/opensearch.php:33 actions/opensearch.php:33 #: actions/opensearch.php:64 msgid "People Search" -msgstr "" +msgstr "Wyszukiwanie osób" #: ../actions/peoplesearch.php:33 actions/peoplesearch.php:33 #: actions/peoplesearch.php:58 msgid "People search" -msgstr "Szukaj ludzi" +msgstr "Wyszukiwanie osób" #: ../lib/stream.php:50 lib/personal.php:50 lib/personalgroupnav.php:98 msgid "Personal" msgstr "Osobiste" #: ../actions/invite.php:133 actions/invite.php:141 actions/invite.php:178 +#: actions/invite.php:184 msgid "Personal message" -msgstr "" +msgstr "Osobista wiadomość" #: ../actions/smssettings.php:69 actions/smssettings.php:69 +#: actions/smssettings.php:128 msgid "Phone number, no punctuation or spaces, with area code" -msgstr "" +msgstr "Numer telefonu, bez znaków przestankowych i spacji, z kodem państwa" #: ../actions/userauthorization.php:78 msgid "" @@ -1759,21 +1876,20 @@ msgid "" "user's notices. If you didn't just ask to subscribe to someone's notices, " "click \"Cancel\"." msgstr "" -"Sprawdź proszę poniższe informacje, aby upewnić się czy na pewno chcesz " -"obserwować wpisy tego użytkownika. Jeżeli to pomyłka lub chodziło o kogoś " -"innego kliknij \"Anuluj\"." +"Sprawdź te szczegóły, aby upewnić się, czy chcesz subskrybować wpisy tego " +"użytkownika. Jeśli nie chcesz, po prostu naciśnij \"Anuluj\"." #: ../actions/imsettings.php:73 actions/imsettings.php:74 #: actions/imsettings.php:142 msgid "Post a notice when my Jabber/GTalk status changes." -msgstr "Utwórz wpis kiedy zmieni się status na komunikatorze." +msgstr "Wyślij wpis, kiedy zmieni się mój status na Jabberze/GTalk." #: ../actions/emailsettings.php:85 ../actions/imsettings.php:67 #: ../actions/smssettings.php:94 actions/emailsettings.php:86 #: actions/imsettings.php:68 actions/smssettings.php:94 #: actions/twittersettings.php:70 actions/emailsettings.php:147 #: actions/imsettings.php:133 actions/smssettings.php:157 -#: actions/twittersettings.php:134 +#: actions/twittersettings.php:134 actions/twittersettings.php:137 msgid "Preferences" msgstr "Preferencje" @@ -1782,22 +1898,24 @@ msgstr "Preferencje" #: actions/imsettings.php:152 actions/smssettings.php:171 #: actions/emailsettings.php:286 actions/imsettings.php:258 #: actions/othersettings.php:168 actions/smssettings.php:272 +#: actions/emailsettings.php:293 msgid "Preferences saved." -msgstr "Preferencje zostały zapisane." +msgstr "Zapisano preferencje." #: ../actions/profilesettings.php:57 actions/profilesettings.php:90 #: actions/profilesettings.php:129 msgid "Preferred language" -msgstr "" +msgstr "Preferowany język" -#: ../lib/util.php:328 lib/util.php:344 lib/action.php:572 +#: ../lib/util.php:328 lib/util.php:344 lib/action.php:572 lib/action.php:665 msgid "Privacy" msgstr "Prywatność" #: ../classes/Notice.php:95 ../classes/Notice.php:106 classes/Notice.php:109 #: classes/Notice.php:119 classes/Notice.php:145 classes/Notice.php:155 +#: classes/Notice.php:178 classes/Notice.php:188 msgid "Problem saving notice." -msgstr "Problem z zachowywaniem wpisu." +msgstr "Problem podczas zapisywania wpisu." #: ../lib/settingsaction.php:84 ../lib/stream.php:60 lib/personal.php:60 #: lib/settingsaction.php:84 lib/accountsettingsaction.php:104 @@ -1808,7 +1926,7 @@ msgstr "Profil" #: ../actions/remotesubscribe.php:73 actions/remotesubscribe.php:82 #: actions/remotesubscribe.php:109 msgid "Profile URL" -msgstr "URL profilu" +msgstr "Adres URL profilu" #: ../actions/profilesettings.php:34 actions/profilesettings.php:32 #: actions/profilesettings.php:58 @@ -1818,32 +1936,33 @@ msgstr "Ustawienia profilu" #: ../actions/postnotice.php:51 ../actions/updateprofile.php:52 #: actions/postnotice.php:52 actions/updateprofile.php:53 #: actions/postnotice.php:55 actions/updateprofile.php:56 +#: actions/updateprofile.php:58 msgid "Profile unknown" msgstr "Nieznany profil" #: ../actions/public.php:54 actions/public.php:54 actions/public.php:124 msgid "Public Stream Feed" -msgstr "Publiczny Kanał Strumieni" +msgstr "Kanał publicznego strumienia" #: ../actions/public.php:33 actions/public.php:33 actions/public.php:109 -#: lib/publicgroupnav.php:77 +#: lib/publicgroupnav.php:77 actions/public.php:112 lib/publicgroupnav.php:79 msgid "Public timeline" msgstr "Publiczna oś czasu" #: ../actions/imsettings.php:79 actions/imsettings.php:80 #: actions/imsettings.php:153 msgid "Publish a MicroID for my Jabber/GTalk address." -msgstr "" +msgstr "Opublikuj MicroID adresu Jabbera/GTalk." #: ../actions/emailsettings.php:94 actions/emailsettings.php:101 -#: actions/emailsettings.php:178 +#: actions/emailsettings.php:178 actions/emailsettings.php:183 msgid "Publish a MicroID for my email address." -msgstr "" +msgstr "Opublikuj MicroID adresu e-mail." #: ../actions/tag.php:75 ../actions/tag.php:76 actions/tag.php:75 #: actions/tag.php:76 msgid "Recent Tags" -msgstr "" +msgstr "Ostatnie znaczniki" #: ../actions/recoverpassword.php:166 actions/recoverpassword.php:171 #: actions/recoverpassword.php:190 @@ -1853,29 +1972,30 @@ msgstr "Przywróć" #: ../actions/recoverpassword.php:156 actions/recoverpassword.php:161 #: actions/recoverpassword.php:198 msgid "Recover password" -msgstr "Odzyskiwanie hasła" +msgstr "Przywróć hasło" #: ../actions/recoverpassword.php:67 actions/recoverpassword.php:67 #: actions/recoverpassword.php:73 msgid "Recovery code for unknown user." -msgstr "Kod przywracający dla nieznanego użytkownika." +msgstr "Kod przywracania dla nieznanego użytkownika." #: ../actions/register.php:142 ../actions/register.php:193 ../lib/util.php:312 #: actions/register.php:152 actions/register.php:207 lib/util.php:328 #: actions/register.php:69 actions/register.php:436 lib/action.php:338 #: lib/facebookaction.php:277 lib/logingroupnav.php:78 +#: actions/register.php:438 lib/action.php:415 lib/facebookaction.php:279 msgid "Register" -msgstr "Zarejestruj" +msgstr "Zarejestruj się" #: ../actions/register.php:28 actions/register.php:28 #: actions/finishopenidlogin.php:196 actions/register.php:90 msgid "Registration not allowed." -msgstr "" +msgstr "Rejestracja nie jest dozwolona." #: ../actions/register.php:200 actions/register.php:214 #: actions/register.php:67 msgid "Registration successful" -msgstr "" +msgstr "Rejestracja powiodła się" #: ../actions/userauthorization.php:120 actions/userauthorization.php:127 #: actions/userauthorization.php:144 @@ -1884,19 +2004,19 @@ msgstr "Odrzuć" #: ../actions/login.php:103 ../actions/register.php:176 actions/login.php:103 #: actions/register.php:190 actions/login.php:234 actions/openidlogin.php:107 -#: actions/register.php:414 +#: actions/register.php:414 actions/login.php:217 actions/openidlogin.php:116 msgid "Remember me" -msgstr "Pamiętaj mnie" +msgstr "Zapamiętaj mnie" #: ../actions/updateprofile.php:70 actions/updateprofile.php:71 -#: actions/updateprofile.php:74 +#: actions/updateprofile.php:74 actions/updateprofile.php:76 msgid "Remote profile with no matching profile" -msgstr "Zdalny profil bez odpowiadającego profilu lokalnego" +msgstr "Zdalny profil bez odpowiadającego profilu" #: ../actions/remotesubscribe.php:65 actions/remotesubscribe.php:73 #: actions/remotesubscribe.php:88 msgid "Remote subscribe" -msgstr "Zdalna subskrypcja" +msgstr "Zasubskrybuj zdalnie" #: ../actions/emailsettings.php:47 ../actions/emailsettings.php:75 #: ../actions/imsettings.php:48 ../actions/openidsettings.php:106 @@ -1908,21 +2028,22 @@ msgstr "Zdalna subskrypcja" #: actions/emailsettings.php:134 actions/imsettings.php:102 #: actions/openidsettings.php:166 actions/smssettings.php:103 #: actions/smssettings.php:146 actions/twittersettings.php:115 +#: actions/twittersettings.php:118 msgid "Remove" msgstr "Usuń" #: ../actions/openidsettings.php:68 actions/openidsettings.php:69 #: actions/openidsettings.php:123 msgid "Remove OpenID" -msgstr "Usuń konto OpenID" +msgstr "Usuń identyfikator OpenID" -#: ../actions/openidsettings.php:73 +#: ../actions/openidsettings.php:73 actions/openidsettings.php:128 msgid "" "Removing your only OpenID would make it impossible to log in! If you need to " "remove it, add another OpenID first." msgstr "" -"Usunięcie jedynego konta OpenID uniemożliwi dalsze logowanie! Jeśli musisz " -"je usunąć dodaj wcześniej jakieś inne." +"Usunięcie jedynego identyfikatora OpenID uniemożliwi zalogowanie się! Jeśli " +"musisz je usunąć, dodaj najpierw inne." #: ../lib/stream.php:55 lib/personal.php:55 lib/personalgroupnav.php:103 msgid "Replies" @@ -1931,7 +2052,7 @@ msgstr "Odpowiedzi" #: ../actions/replies.php:47 ../actions/repliesrss.php:76 ../lib/stream.php:56 #: actions/replies.php:47 actions/repliesrss.php:62 lib/personal.php:56 #: actions/replies.php:116 actions/repliesrss.php:67 -#: lib/personalgroupnav.php:104 +#: lib/personalgroupnav.php:104 actions/replies.php:118 #, php-format msgid "Replies to %s" msgstr "Odpowiedzi na %s" @@ -1939,41 +2060,42 @@ msgstr "Odpowiedzi na %s" #: ../actions/recoverpassword.php:183 actions/recoverpassword.php:189 #: actions/recoverpassword.php:223 msgid "Reset" -msgstr "Wyzeruj" +msgstr "Przywróć" #: ../actions/recoverpassword.php:173 actions/recoverpassword.php:178 #: actions/recoverpassword.php:197 msgid "Reset password" -msgstr "Ustaw ponownie hasło" +msgstr "Przywróć hasło" #: ../lib/settingsaction.php:99 lib/settingsaction.php:93 #: actions/subscriptions.php:123 lib/connectsettingsaction.php:107 +#: actions/subscriptions.php:125 msgid "SMS" -msgstr "" +msgstr "SMS" #: ../actions/smssettings.php:67 actions/smssettings.php:67 #: actions/smssettings.php:126 msgid "SMS Phone number" -msgstr "" +msgstr "Numer telefonu SMS" #: ../actions/smssettings.php:33 actions/smssettings.php:33 #: actions/smssettings.php:58 msgid "SMS Settings" -msgstr "" +msgstr "Ustawienia SMS" -#: ../lib/mail.php:219 lib/mail.php:225 lib/mail.php:437 +#: ../lib/mail.php:219 lib/mail.php:225 lib/mail.php:437 lib/mail.php:438 msgid "SMS confirmation" -msgstr "" +msgstr "Potwierdzenie SMS" #: ../actions/recoverpassword.php:182 actions/recoverpassword.php:188 #: actions/recoverpassword.php:222 msgid "Same as password above" -msgstr "Takie samo jak hasło wprowadzone powyżej" +msgstr "Takie samo jak powyższe hasło" #: ../actions/register.php:156 actions/register.php:170 #: actions/register.php:377 msgid "Same as password above. Required." -msgstr "" +msgstr "Takie samo jak powyższe hasło. Wymagane." #: ../actions/emailsettings.php:97 ../actions/imsettings.php:81 #: ../actions/profilesettings.php:67 ../actions/smssettings.php:100 @@ -1984,48 +2106,51 @@ msgstr "" #: actions/othersettings.php:117 actions/profilesettings.php:150 #: actions/smssettings.php:169 actions/subscriptions.php:124 #: actions/tagother.php:152 actions/twittersettings.php:161 -#: lib/groupeditform.php:171 +#: lib/groupeditform.php:171 actions/emailsettings.php:187 +#: actions/subscriptions.php:126 actions/tagother.php:154 +#: actions/twittersettings.php:164 msgid "Save" msgstr "Zapisz" #: ../lib/searchaction.php:84 ../lib/util.php:300 lib/searchaction.php:84 -#: lib/util.php:316 lib/action.php:325 +#: lib/util.php:316 lib/action.php:325 lib/action.php:396 msgid "Search" -msgstr "Szukaj" +msgstr "Znajdź" #: ../actions/noticesearch.php:80 actions/noticesearch.php:85 #: actions/noticesearch.php:127 msgid "Search Stream Feed" -msgstr "Szukaj Kanału Strumieni" +msgstr "Znajdź kanał strumienia" #: ../actions/noticesearch.php:30 actions/noticesearch.php:30 -#: actions/noticesearch.php:57 +#: actions/noticesearch.php:57 actions/noticesearch.php:68 #, php-format msgid "" "Search for notices on %%site.name%% by their contents. Separate search terms " "by spaces; they must be 3 characters or more." msgstr "" -"Wyszukiwanie w treści wpisów w serwisie %%site.name%%. Użyj spacji aby " -"oddzielić elementy wyszukiwania. Słowa muszą mieć minimum 3 znaki." +"Znajdź wpisy na %%site.name%% według ich zawartości. Oddziel wyszukiwane " +"terminy spacjami. Terminy muszą mieć trzy znaki lub więcej." -#: ../actions/peoplesearch.php:28 +#: ../actions/peoplesearch.php:28 actions/peoplesearch.php:52 #, php-format msgid "" "Search for people on %%site.name%% by their name, location, or interests. " "Separate the terms by spaces; they must be 3 characters or more." msgstr "" -"Szukaj ludzi w serwisie %%site.name%%. Kryteriami mogą być imiona i " -"nazwiska, miejscowości lub zainteresowania. Użyj spacji aby oddzielić " -"elementy wyszukiwania. Słowa muszą mieć minimum 3 znaki." +"Znajdź osoby na %%site.name%% według ich nazwiska, położenia lub " +"zainteresowań. Oddziel wyszukiwane terminy spacjami. Terminy muszą mieć trzy " +"znaki lub więcej." #: ../actions/smssettings.php:296 actions/smssettings.php:304 #: actions/smssettings.php:457 msgid "Select a carrier" -msgstr "" +msgstr "Wybierz operatora" #: ../actions/invite.php:137 ../lib/util.php:1172 actions/invite.php:145 #: lib/util.php:1306 lib/util.php:1731 actions/invite.php:182 -#: lib/messageform.php:167 lib/noticeform.php:177 +#: lib/messageform.php:167 lib/noticeform.php:177 actions/invite.php:189 +#: lib/messageform.php:165 msgid "Send" msgstr "Wyślij" @@ -2033,45 +2158,51 @@ msgstr "Wyślij" #: actions/emailsettings.php:74 actions/smssettings.php:82 #: actions/emailsettings.php:132 actions/smssettings.php:145 msgid "Send email to this address to post new notices." -msgstr "" +msgstr "Wyślij wiadomość e-mail na ten adres, aby wysyłać nowe wpisy." #: ../actions/emailsettings.php:88 actions/emailsettings.php:89 #: actions/emailsettings.php:152 msgid "Send me notices of new subscriptions through email." -msgstr "" +msgstr "Wyślij mi wpisy nowych subskrypcji przez e-mail." #: ../actions/imsettings.php:70 actions/imsettings.php:71 #: actions/imsettings.php:137 msgid "Send me notices through Jabber/GTalk." -msgstr "Wysyłaj mi wpisy przez Jabbera/GTalka" +msgstr "Wyślij mi wpisy przez Jabbera/GTalk." #: ../actions/smssettings.php:97 actions/smssettings.php:97 +#: actions/smssettings.php:162 msgid "" "Send me notices through SMS; I understand I may incur exorbitant charges " "from my carrier." msgstr "" +"Wyślij mi wpisy przez SMS. Rozumiem, że mogę otrzymywać większe rachunki od " +"swojego operatora." #: ../actions/imsettings.php:76 actions/imsettings.php:77 +#: actions/imsettings.php:147 msgid "Send me replies through Jabber/GTalk from people I'm not subscribed to." msgstr "" +"Wyślij mi odpowiedzi przez Jabbera/GTalk od osób, których nie subskrybuję." #: ../lib/util.php:304 lib/util.php:320 lib/facebookaction.php:215 +#: lib/facebookaction.php:228 msgid "Settings" msgstr "Ustawienia" #: ../actions/profilesettings.php:192 actions/profilesettings.php:307 #: actions/profilesettings.php:319 msgid "Settings saved." -msgstr "Ustawienia zostały zapisane." +msgstr "Zapisano ustawienia." #: ../actions/tag.php:60 actions/tag.php:60 msgid "Showing most popular tags from the last week" -msgstr "" +msgstr "Wyświetlanie najpopularniejszych znaczników od ostatniego tygodnia" #: ../actions/finishaddopenid.php:66 actions/finishaddopenid.php:66 #: actions/finishaddopenid.php:114 msgid "Someone else already has this OpenID." -msgstr "Ktoś inny posługuje się już tym identyfikatorem OpenID." +msgstr "Ktoś inny już posiada ten identyfikator OpenID." #: ../actions/finishopenidlogin.php:42 ../actions/openidsettings.php:126 #: actions/finishopenidlogin.php:47 actions/openidsettings.php:135 @@ -2082,27 +2213,28 @@ msgstr "Stało się coś dziwnego." #: ../scripts/maildaemon.php:58 scripts/maildaemon.php:58 #: scripts/maildaemon.php:61 msgid "Sorry, no incoming email allowed." -msgstr "" +msgstr "Przepraszamy, przychodzący e-mail nie jest dozwolony." #: ../scripts/maildaemon.php:54 scripts/maildaemon.php:54 #: scripts/maildaemon.php:57 msgid "Sorry, that is not your incoming email address." -msgstr "" +msgstr "Przepraszamy, to nie jest twój przychodzący adres e-mail." -#: ../lib/util.php:330 lib/util.php:346 lib/action.php:574 +#: ../lib/util.php:330 lib/util.php:346 lib/action.php:574 lib/action.php:667 msgid "Source" msgstr "Kod źródłowy" #: ../actions/showstream.php:296 actions/showstream.php:311 -#: actions/showstream.php:476 +#: actions/showstream.php:476 actions/showgroup.php:375 msgid "Statistics" msgstr "Statystyki" #: ../actions/finishopenidlogin.php:182 ../actions/finishopenidlogin.php:246 #: actions/finishopenidlogin.php:188 actions/finishopenidlogin.php:252 #: actions/finishopenidlogin.php:222 actions/finishopenidlogin.php:290 +#: actions/finishopenidlogin.php:295 msgid "Stored OpenID not found." -msgstr "Nie znaleziono zapisanego konta OpenID." +msgstr "Nie znaleziono przechowywanego identyfikatora OpenID." #: ../actions/remotesubscribe.php:75 ../actions/showstream.php:188 #: ../actions/showstream.php:197 actions/remotesubscribe.php:84 @@ -2110,7 +2242,7 @@ msgstr "Nie znaleziono zapisanego konta OpenID." #: actions/remotesubscribe.php:113 actions/showstream.php:376 #: lib/subscribeform.php:139 msgid "Subscribe" -msgstr "Subskrybuj" +msgstr "Zasubskrybuj" #: ../actions/showstream.php:313 ../actions/subscribers.php:27 #: actions/showstream.php:328 actions/subscribers.php:27 @@ -2120,14 +2252,14 @@ msgid "Subscribers" msgstr "Subskrybenci" #: ../actions/userauthorization.php:310 actions/userauthorization.php:322 -#: actions/userauthorization.php:338 +#: actions/userauthorization.php:338 actions/userauthorization.php:344 msgid "Subscription authorized" -msgstr "Subskrypcja uwierzytelniona" +msgstr "Upoważniono subskrypcję" #: ../actions/userauthorization.php:320 actions/userauthorization.php:332 -#: actions/userauthorization.php:349 +#: actions/userauthorization.php:349 actions/userauthorization.php:355 msgid "Subscription rejected" -msgstr "Subskrypcja odrzucona" +msgstr "Odrzucono subskrypcję" #: ../actions/showstream.php:230 ../actions/showstream.php:307 #: ../actions/subscriptions.php:27 actions/showstream.php:240 @@ -2138,25 +2270,26 @@ msgid "Subscriptions" msgstr "Subskrypcje" #: ../actions/avatar.php:87 actions/profilesettings.php:324 -#: lib/imagefile.php:78 +#: lib/imagefile.php:78 lib/imagefile.php:82 msgid "System error uploading file." -msgstr "Błąd systemowy podczas wysyłania pliku." +msgstr "Błąd systemu podczas wysyłania pliku." #: ../actions/tag.php:41 ../lib/util.php:301 actions/tag.php:41 #: lib/util.php:317 actions/profilesettings.php:122 actions/showstream.php:297 #: actions/tagother.php:147 actions/tagother.php:207 lib/profilelist.php:162 -#: lib/profilelist.php:164 +#: lib/profilelist.php:164 actions/showstream.php:290 actions/tagother.php:149 +#: actions/tagother.php:209 lib/profilelist.php:160 msgid "Tags" -msgstr "" +msgstr "Znaczniki" #: ../lib/searchaction.php:104 lib/searchaction.php:104 msgid "Text" -msgstr "" +msgstr "Tekst" #: ../actions/noticesearch.php:34 actions/noticesearch.php:34 -#: actions/noticesearch.php:67 +#: actions/noticesearch.php:67 actions/noticesearch.php:78 msgid "Text search" -msgstr "Szukaj tekstu" +msgstr "Znajdź tekst" #: ../actions/openidsettings.php:140 actions/openidsettings.php:149 #: actions/openidsettings.php:227 @@ -2166,7 +2299,7 @@ msgstr "Ten identyfikator OpenID nie należy do Ciebie." #: ../actions/confirmaddress.php:52 actions/confirmaddress.php:52 #: actions/confirmaddress.php:94 msgid "That address has already been confirmed." -msgstr "Ten adres został już potwierdzony" +msgstr "Ten adres został już potwierdzony." #: ../actions/confirmaddress.php:43 actions/confirmaddress.php:43 #: actions/confirmaddress.php:85 @@ -2174,8 +2307,9 @@ msgid "That confirmation code is not for you!" msgstr "Ten kod potwierdzający nie jest przeznaczony dla Ciebie!" #: ../actions/emailsettings.php:191 actions/emailsettings.php:209 +#: actions/emailsettings.php:328 msgid "That email address already belongs to another user." -msgstr "" +msgstr "Ten adres e-mail należy już do innego użytkownika." #: ../actions/avatar.php:80 actions/profilesettings.php:317 #: lib/imagefile.php:71 @@ -2185,17 +2319,17 @@ msgstr "Ten plik jest za duży." #: ../actions/imsettings.php:170 actions/imsettings.php:178 #: actions/imsettings.php:293 msgid "That is already your Jabber ID." -msgstr "Ten identyfikator Jabbera jest już do Ciebie przypisany." +msgstr "Ten identyfikator Jabbera jest już Twój." #: ../actions/emailsettings.php:188 actions/emailsettings.php:206 -#: actions/emailsettings.php:318 +#: actions/emailsettings.php:318 actions/emailsettings.php:325 msgid "That is already your email address." -msgstr "" +msgstr "Ten adres e-mail jest już Twój." #: ../actions/smssettings.php:188 actions/smssettings.php:196 #: actions/smssettings.php:306 msgid "That is already your phone number." -msgstr "" +msgstr "Ten numer telefonu jest już Twój." #: ../actions/imsettings.php:233 actions/imsettings.php:241 #: actions/imsettings.php:381 @@ -2203,109 +2337,117 @@ msgid "That is not your Jabber ID." msgstr "To nie jest Twój identyfikator Jabbera." #: ../actions/emailsettings.php:249 actions/emailsettings.php:267 -#: actions/emailsettings.php:397 +#: actions/emailsettings.php:397 actions/emailsettings.php:404 msgid "That is not your email address." -msgstr "" +msgstr "To nie jest Twój adres e-mail." #: ../actions/smssettings.php:257 actions/smssettings.php:265 #: actions/smssettings.php:393 msgid "That is not your phone number." -msgstr "" +msgstr "To nie jest Twój numer telefonu." #: ../actions/emailsettings.php:226 ../actions/imsettings.php:210 #: actions/emailsettings.php:244 actions/imsettings.php:218 #: actions/emailsettings.php:367 actions/imsettings.php:349 +#: actions/emailsettings.php:374 msgid "That is the wrong IM address." msgstr "To jest błędny adres komunikatora." #: ../actions/smssettings.php:233 actions/smssettings.php:241 #: actions/smssettings.php:362 msgid "That is the wrong confirmation number." -msgstr "" +msgstr "To jest błędny numer potwierdzenia." #: ../actions/smssettings.php:191 actions/smssettings.php:199 #: actions/smssettings.php:309 msgid "That phone number already belongs to another user." -msgstr "" +msgstr "Ten numer telefonu należy już do innego użytkownika." #: ../actions/newnotice.php:49 ../actions/twitapistatuses.php:408 #: actions/newnotice.php:49 actions/twitapistatuses.php:330 #: actions/facebookhome.php:243 actions/twitapistatuses.php:276 +#: actions/newnotice.php:136 actions/twitapistatuses.php:294 +#: lib/facebookaction.php:485 msgid "That's too long. Max notice size is 140 chars." -msgstr "Wpis za długi. Maksymalna długość to 140 znaków." +msgstr "Wpis jest za długi. Maksymalna długość to 140 znaków." #: ../actions/twitapiaccount.php:74 actions/twitapiaccount.php:72 -#: actions/twitapiaccount.php:62 +#: actions/twitapiaccount.php:62 actions/twitapiaccount.php:63 msgid "That's too long. Max notice size is 255 chars." -msgstr "" +msgstr "Wpis jest za długi. Maksymalna długość to 255 znaków." #: ../actions/confirmaddress.php:92 actions/confirmaddress.php:92 +#: actions/confirmaddress.php:159 #, php-format msgid "The address \"%s\" has been confirmed for your account." -msgstr "Skojarzony z Twoim kontem adres \"%s\" został potwierdzony." +msgstr "Adres \"%s\" został potwierdzony dla Twojego konta." #: ../actions/emailsettings.php:264 ../actions/imsettings.php:250 #: ../actions/smssettings.php:274 actions/emailsettings.php:282 #: actions/imsettings.php:258 actions/smssettings.php:282 #: actions/emailsettings.php:416 actions/imsettings.php:402 -#: actions/smssettings.php:413 +#: actions/smssettings.php:413 actions/emailsettings.php:423 msgid "The address was removed." msgstr "Adres został usunięty." -#: ../actions/userauthorization.php:312 +#: ../actions/userauthorization.php:312 actions/userauthorization.php:346 msgid "" "The subscription has been authorized, but no callback URL was passed. Check " "with the site's instructions for details on how to authorize the " "subscription. Your subscription token is:" msgstr "" -"Twoje żądanie obserwacji zostało odrzucone, ale nie przekazano żadnego URL-a " -"do zwrotnego komunikatu. Sprawdź w instrukcjach serwisu w jaki sposób " -"dokładnie odbywa się odrzucanie subskrypcji. Twój token subskrypcji to:" +"Subskrypcja została upoważniona, ale nie przekazano zwrotnego adresu URL. " +"Sprawdź w instrukcjach strony, jak upoważnić subskrypcję. Token subskrypcji:" -#: ../actions/userauthorization.php:322 +#: ../actions/userauthorization.php:322 actions/userauthorization.php:357 msgid "" "The subscription has been rejected, but no callback URL was passed. Check " "with the site's instructions for details on how to fully reject the " "subscription." msgstr "" -"Twoje żądanie obserwacji zostało odrzucone, ale nie przekazano żadnego URL-a " -"do zwrotnego komunikatu. Sprawdź w instrukcjach serwisu w jaki sposób " -"dokładnie odbywa się odrzucanie subskrypcji." +"Subskrypcja została odrzucona, ale nie przekazano zwrotnego adresu URL. " +"Sprawdź w instrukcjach strony, jak w pełni odrzucić subskrypcję." #: ../actions/subscribers.php:35 actions/subscribers.php:35 +#: actions/subscribers.php:67 #, php-format msgid "These are the people who listen to %s's notices." -msgstr "Ludzie obserwujący wpisy użytkownika %s." +msgstr "Osoby obserwujące wpisy użytkownika %s." #: ../actions/subscribers.php:33 actions/subscribers.php:33 +#: actions/subscribers.php:63 msgid "These are the people who listen to your notices." -msgstr "Ludzie obserwujący Twoje wpisy." +msgstr "Osoby obserwujący Twoje wpisy." #: ../actions/subscriptions.php:35 actions/subscriptions.php:35 +#: actions/subscriptions.php:69 #, php-format msgid "These are the people whose notices %s listens to." -msgstr "Ludzie, których wpisy obserwuje użytkownik %s." +msgstr "Osoby, których wpisy obserwuje użytkownik %s." #: ../actions/subscriptions.php:33 actions/subscriptions.php:33 +#: actions/subscriptions.php:65 msgid "These are the people whose notices you listen to." -msgstr "Ludzie których wpisy obserwujesz." +msgstr "Osoby, których wpisy obserwujesz." #: ../actions/invite.php:89 actions/invite.php:96 actions/invite.php:128 msgid "" "These people are already users and you were automatically subscribed to them:" msgstr "" +"Te osoby są już użytkownikami i zostałeś do nich automatycznie " +"zasubskrybowany:" -#: ../actions/recoverpassword.php:88 +#: ../actions/recoverpassword.php:88 actions/recoverpassword.php:97 msgid "This confirmation code is too old. Please start again." -msgstr "Kod potwierdzający jest przeterminowany. Zacznij jeszcze raz." +msgstr "Kod potwierdzający jest za stary. Rozpocznij ponownie." -#: ../lib/openid.php:195 +#: ../lib/openid.php:195 lib/openid.php:206 msgid "" "This form should automatically submit itself. If not, click the submit " "button to go to your OpenID provider." msgstr "" -"Ten formularz powinien wysłać się automatycznie. Jeśli tak się nie stanie " -"kliknij Wyślij, aby przejść do Twojego dostawcy OpenID." +"Ten formularz powinien wysłać się automatycznie. Jeśli tak się nie stanie, " +"naciśnij przycisk Wyślij, aby przejść do dostawcy OpenID." #: ../actions/finishopenidlogin.php:56 actions/finishopenidlogin.php:61 #: actions/finishopenidlogin.php:67 @@ -2315,66 +2457,69 @@ msgid "" "to a local account. You can either create a new account, or connect with " "your existing account, if you have one." msgstr "" -"Jeżeli logujesz się po raz pierwszy do %s to twoje konto OpenID musi zostać " -"skojarzone z kontem lokalnym. Możesz więc albo utworzyć nowe konto, albo " -"połączyć je z posiadanym istniejącym." +"Jeżeli logujesz się do %s po raz pierwszy, musimy połączyć identyfikator " +"OpenID z lokalnym kontem. Można utworzyć nowe konto lub połączyć z " +"istniejącym, jeśli je posiadasz." #: ../actions/twitapifriendships.php:108 ../actions/twitapistatuses.php:586 #: actions/twitapifavorites.php:127 actions/twitapifriendships.php:108 #: actions/twitapistatuses.php:511 actions/twitapifavorites.php:97 #: actions/twitapifriendships.php:85 actions/twitapistatuses.php:436 +#: actions/twitapifavorites.php:103 actions/twitapistatuses.php:460 msgid "This method requires a POST or DELETE." -msgstr "" +msgstr "Ta metoda wymaga POST lub DELETE." #: ../actions/twitapiaccount.php:65 ../actions/twitapifriendships.php:44 #: ../actions/twitapistatuses.php:381 actions/twitapiaccount.php:63 #: actions/twitapidirect_messages.php:114 actions/twitapifriendships.php:44 #: actions/twitapistatuses.php:303 actions/twitapiaccount.php:53 #: actions/twitapidirect_messages.php:122 actions/twitapifriendships.php:32 -#: actions/twitapistatuses.php:244 +#: actions/twitapistatuses.php:244 actions/twitapiaccount.php:54 +#: actions/twitapidirect_messages.php:131 actions/twitapistatuses.php:262 msgid "This method requires a POST." -msgstr "" +msgstr "Ta metoda wymaga POST." -#: ../lib/util.php:164 lib/util.php:246 +#: ../lib/util.php:164 lib/util.php:246 lib/htmloutputter.php:104 msgid "This page is not available in a media type you accept" -msgstr "Ta strona nie jest dostępna dla medium, którego typ akceptujesz" +msgstr "Ta strona jest niedostępna dla akceptowanego typu medium" #: ../actions/profilesettings.php:63 actions/profilesettings.php:96 #: actions/profilesettings.php:138 msgid "Timezone" -msgstr "" +msgstr "Strefa czasowa" #: ../actions/profilesettings.php:107 actions/profilesettings.php:222 #: actions/profilesettings.php:211 msgid "Timezone not selected." -msgstr "" +msgstr "Nie wybrano strefy czasowej." -#: ../actions/remotesubscribe.php:43 +#: ../actions/remotesubscribe.php:43 actions/remotesubscribe.php:74 #, php-format msgid "" "To subscribe, you can [login](%%action.login%%), or [register](%%action." "register%%) a new account. If you already have an account on a [compatible " "microblogging site](%%doc.openmublog%%), enter your profile URL below." msgstr "" -"Aby się zapisać możesz się [zalogować](%%action.login%%) lub [zarejestrować]" -"(%%action.register%%). Jeśli już posiadasz konto w [kompatybilnym serwisie](%" -"%doc.openmublog%%) wprowadź poniżej identyfikator URL." +"Aby zasubskrybować, można [zalogować się](%%action.login%%) lub " +"[zarejestrować](%%action.register%%) nowe konto. Jeśli już posiadasz konto " +"na [zgodnej stronie mikroblogowania](%%doc.openmublog%%), podaj poniżej " +"adres URL profilu." #: ../actions/twitapifriendships.php:163 actions/twitapifriendships.php:167 #: actions/twitapifriendships.php:132 msgid "Two user ids or screen_names must be supplied." -msgstr "" +msgstr "Należy dostarczyć dwa identyfikatory lub nazwy użytkowników." #: ../actions/profilesettings.php:48 ../actions/register.php:169 #: actions/profilesettings.php:81 actions/register.php:183 -#: actions/profilesettings.php:109 +#: actions/profilesettings.php:109 actions/register.php:398 msgid "URL of your homepage, blog, or profile on another site" -msgstr "URL Twojej strony domowej, bloga, lub profilu na innej stronie" +msgstr "Adres URL strony domowej, bloga lub profilu na innej stronie" #: ../actions/remotesubscribe.php:74 actions/remotesubscribe.php:83 #: actions/remotesubscribe.php:110 msgid "URL of your profile on another compatible microblogging service" -msgstr "URL Twojego profilu na kompatybilnym serwisie do mikroblogów" +msgstr "Adres URL profilu na innej, zgodnej usłudze mikroblogowania" #: ../actions/emailsettings.php:130 ../actions/imsettings.php:110 #: ../actions/recoverpassword.php:39 ../actions/smssettings.php:135 @@ -2384,17 +2529,19 @@ msgstr "URL Twojego profilu na kompatybilnym serwisie do mikroblogów" #: actions/emailsettings.php:242 actions/grouplogo.php:317 #: actions/imsettings.php:214 actions/recoverpassword.php:44 #: actions/smssettings.php:236 actions/twittersettings.php:302 +#: actions/avatarsettings.php:263 actions/emailsettings.php:247 +#: actions/grouplogo.php:324 actions/twittersettings.php:306 msgid "Unexpected form submission." -msgstr "Nieoczekiwane przesłanie formularza." +msgstr "Nieoczekiwane wysłanie formularza." #: ../actions/recoverpassword.php:276 actions/recoverpassword.php:289 #: actions/recoverpassword.php:323 msgid "Unexpected password reset." -msgstr "Nieoczekiwane wyzerowanie hasła." +msgstr "Nieoczekiwane przywrócenie hasła." #: ../index.php:57 index.php:57 actions/recoverpassword.php:202 msgid "Unknown action" -msgstr "" +msgstr "Nieznane działanie" #: ../actions/finishremotesubscribe.php:58 #: actions/finishremotesubscribe.php:60 actions/finishremotesubscribe.php:61 @@ -2406,8 +2553,8 @@ msgid "" "Unless otherwise specified, contents of this site are copyright by the " "contributors and available under the " msgstr "" -"Prawo do kopiowania zawartości tej strony, chyba że zaznaczono inaczej, " -"należy do tworzących jej treści i uwarunkowane zasadami" +"Jeśli nie podano inaczej, prawa autorskie do zawartości tej strony należy do " +"współtwórców i jest dostępna na warunkach licencji " #: ../actions/confirmaddress.php:48 actions/confirmaddress.php:48 #: actions/confirmaddress.php:90 @@ -2423,38 +2570,40 @@ msgstr "Zrezygnuj z subskrypcji" #: ../actions/postnotice.php:44 ../actions/updateprofile.php:45 #: actions/postnotice.php:45 actions/updateprofile.php:46 #: actions/postnotice.php:48 actions/updateprofile.php:49 +#: actions/updateprofile.php:51 msgid "Unsupported OMB version" msgstr "Nieobsługiwana wersja OMB" #: ../actions/avatar.php:105 actions/profilesettings.php:342 -#: lib/imagefile.php:102 +#: lib/imagefile.php:102 lib/imagefile.php:99 msgid "Unsupported image file format." msgstr "Nieobsługiwany format pliku obrazu." #: ../lib/settingsaction.php:100 lib/settingsaction.php:94 #: lib/connectsettingsaction.php:108 msgid "Updates by SMS" -msgstr "" +msgstr "Aktualizacje przez wiadomości SMS" #: ../lib/settingsaction.php:103 lib/settingsaction.php:97 #: lib/connectsettingsaction.php:105 msgid "Updates by instant messenger (IM)" -msgstr "" +msgstr "Aktualizacje przez komunikator" #: ../actions/twitapistatuses.php:241 actions/twitapistatuses.php:158 -#: actions/twitapistatuses.php:129 +#: actions/twitapistatuses.php:129 actions/twitapistatuses.php:134 #, php-format msgid "Updates from %1$s and friends on %2$s!" -msgstr "" +msgstr "Aktualizacje od %1$s i przyjaciół na %2$s!" #: ../actions/twitapistatuses.php:341 actions/twitapistatuses.php:268 -#: actions/twitapistatuses.php:202 +#: actions/twitapistatuses.php:202 actions/twitapistatuses.php:213 #, php-format msgid "Updates from %1$s on %2$s!" -msgstr "" +msgstr "Aktualizacje od %1$s na %2$s!" #: ../actions/avatar.php:68 actions/profilesettings.php:161 #: actions/avatarsettings.php:162 actions/grouplogo.php:232 +#: actions/avatarsettings.php:165 actions/grouplogo.php:238 msgid "Upload" msgstr "Wyślij" @@ -2465,23 +2614,25 @@ msgid "" "site license, also. Use a picture that belongs to you and that you want to " "share." msgstr "" -"Tu możesz wysłać nowego \"awatara\" (wizerunek użytkownika). Nie da się " -"edytować obrazu po jego umieszczeniu w serwisie, więc upewnij się, że jest w " -"miarę kwadratowy. Wysyłając go zgadzasz się na jego publikację na warunkach " -"podanych w licencji strony. Użyj grafiki, która należy do Ciebie i którą " -"możesz dzielić się z innymi." +"Tu można wysłać nowego \"awatara\" (obraz użytkownika). Nie można " +"modyfikować obrazu po jego wysłaniu, więc upewnij się, że jest w miarę " +"kwadratowy. Musi być także na licencji strony. Użyj obrazu, który należy do " +"Ciebie, i którym chcesz się dzielić." #: ../lib/settingsaction.php:91 msgid "Upload a new profile image" -msgstr "" +msgstr "Wyślij nowy obraz profilu" #: ../actions/invite.php:114 actions/invite.php:121 actions/invite.php:154 msgid "" "Use this form to invite your friends and colleagues to use this service." msgstr "" +"Użyj tego formularza, aby zaprosić przyjaciół i kolegów do używania tej " +"usługi." #: ../actions/register.php:159 ../actions/register.php:162 -#: actions/register.php:173 actions/register.php:176 +#: actions/register.php:173 actions/register.php:176 actions/register.php:382 +#: actions/register.php:386 msgid "Used only for updates, announcements, and password recovery" msgstr "Używane tylko do aktualizacji, ogłoszeń i przywracania hasła" @@ -2505,8 +2656,10 @@ msgstr "Obserwowany użytkownik nie istnieje." #: actions/twitapifavorites.php:42 actions/twitapistatuses.php:167 #: actions/twitapistatuses.php:503 actions/twitapiusers.php:55 #: actions/usergroups.php:99 lib/galleryaction.php:67 lib/twitterapi.php:626 +#: actions/twitapiaccount.php:71 actions/twitapistatuses.php:179 +#: actions/twitapistatuses.php:535 actions/twitapiusers.php:59 msgid "User has no profile." -msgstr "Użytkownik nie ma profilu." +msgstr "Użytkownik nie posiada profilu." #: ../actions/remotesubscribe.php:71 actions/remotesubscribe.php:80 #: actions/remotesubscribe.php:105 @@ -2515,12 +2668,12 @@ msgstr "Pseudonim użytkownika" #: ../actions/twitapiusers.php:75 actions/twitapiusers.php:80 msgid "User not found." -msgstr "" +msgstr "Nie znaleziono użytkownika." #: ../actions/profilesettings.php:63 actions/profilesettings.php:96 #: actions/profilesettings.php:139 msgid "What timezone are you normally in?" -msgstr "" +msgstr "W jakiej strefie czasowej zwykle się znajdujesz?" #: ../lib/util.php:1159 lib/util.php:1293 lib/noticeform.php:141 #, php-format @@ -2529,111 +2682,115 @@ msgstr "Co słychać, %s?" #: ../actions/profilesettings.php:54 ../actions/register.php:175 #: actions/profilesettings.php:87 actions/register.php:189 -#: actions/profilesettings.php:119 +#: actions/profilesettings.php:119 actions/register.php:410 msgid "Where you are, like \"City, State (or Region), Country\"" -msgstr "Gdzie jesteś? (np. \"miasto, region, kraj\")" +msgstr "Gdzie jesteś, np. \"miasto, województwo (lub region), kraj\"" #: ../actions/updateprofile.php:128 actions/updateprofile.php:129 -#: actions/updateprofile.php:132 +#: actions/updateprofile.php:132 actions/updateprofile.php:134 #, php-format msgid "Wrong image type for '%s'" -msgstr "Nieprawidłowy typ obrazu dla '%s'" +msgstr "Błędny typ obrazu dla \"%s\"" #: ../actions/updateprofile.php:123 actions/updateprofile.php:124 -#: actions/updateprofile.php:127 +#: actions/updateprofile.php:127 actions/updateprofile.php:129 #, php-format msgid "Wrong size image at '%s'" -msgstr "Nieprawidłowy rozmiar obrazu dla '%s'" +msgstr "Błędny rozmiar obrazu \"%s\"" #: ../actions/deletenotice.php:63 ../actions/deletenotice.php:72 #: actions/deletenotice.php:64 actions/deletenotice.php:79 #: actions/block.php:148 actions/deletenotice.php:122 -#: actions/deletenotice.php:141 +#: actions/deletenotice.php:141 actions/deletenotice.php:115 msgid "Yes" -msgstr "" +msgstr "Tak" #: ../actions/finishaddopenid.php:64 actions/finishaddopenid.php:64 #: actions/finishaddopenid.php:112 msgid "You already have this OpenID!" -msgstr "Już masz ten identyfikator OpenID!" +msgstr "Już posiadasz ten identyfikator OpenID!" #: ../actions/deletenotice.php:37 actions/deletenotice.php:37 msgid "" "You are about to permanently delete a notice. Once this is done, it cannot " "be undone." msgstr "" +"Wpis zostanie za chwilę trwale usunięty. Kiedy to się stanie, to już się nie " +"odstanie." #: ../actions/recoverpassword.php:31 actions/recoverpassword.php:31 #: actions/recoverpassword.php:36 msgid "You are already logged in!" -msgstr "Nie musisz ponownie się logować!" +msgstr "Jesteś już zalogowany!" #: ../actions/invite.php:81 actions/invite.php:88 actions/invite.php:120 msgid "You are already subscribed to these users:" -msgstr "" +msgstr "Jesteś już zasubskrybowany do tych użytkowników:" #: ../actions/twitapifriendships.php:128 actions/twitapifriendships.php:128 #: actions/twitapifriendships.php:105 msgid "You are not friends with the specified user." -msgstr "" +msgstr "Nie jesteś przyjacielem podanego użytkownika." #: ../actions/password.php:27 msgid "You can change your password here. Choose a good one!" -msgstr "Tu możesz zmienić hasło. Wybierz porządne!" +msgstr "Tutaj można zmienić hasło. Wybierz dobre!" #: ../actions/register.php:135 actions/register.php:145 msgid "You can create a new account to start posting notices." -msgstr "Możesz utworzyć nowe konto, aby rozpocząć wysyłanie wpisów." +msgstr "Można utworzyć nowe konto, aby rozpocząć wysyłanie wpisów." #: ../actions/smssettings.php:28 actions/smssettings.php:28 #: actions/smssettings.php:69 #, php-format msgid "You can receive SMS messages through email from %%site.name%%." -msgstr "" +msgstr "Można otrzymywać wiadomości SMS przez e-mail od %%site.name%%." -#: ../actions/openidsettings.php:86 +#: ../actions/openidsettings.php:86 actions/openidsettings.php:143 msgid "" "You can remove an OpenID from your account by clicking the button marked " "\"Remove\"." msgstr "" -"Możesz usunąć łączność z serwerem OpenID ze swojego konta klikając \"Usuń\"." +"Można usunąć identyfikator OpenID ze swojego konta naciskając przycisk \"Usuń" +"\"." #: ../actions/imsettings.php:28 actions/imsettings.php:28 +#: actions/imsettings.php:70 #, php-format msgid "" "You can send and receive notices through Jabber/GTalk [instant messages](%%" "doc.im%%). Configure your address and settings below." msgstr "" -"Możesz wysyłać i odbierać wpisy przez komunikator Jabber/GTalk (%%doc.im%%). " -"Poniżej możesz skonfigurować swój adres i ustawienia IM." +"Można wysyłać i odbierać wpisy przez [komunikator](%%doc.im%%) Jabber/GTalk. " +"Skonfiguruj adres i ustawienia poniżej." -#: ../actions/profilesettings.php:27 +#: ../actions/profilesettings.php:27 actions/profilesettings.php:69 msgid "" "You can update your personal profile info here so people know more about you." msgstr "" -"W tym miejscu możesz zaktualizować informacje zawarte w Twoim osobistym " -"profilu, aby inni mogli lepiej Cię poznać." +"Tutaj można zaktualizować osobiste informacje w profilu, aby inni mogli " +"lepiej Cię poznać." #: ../actions/finishremotesubscribe.php:31 ../actions/remotesubscribe.php:31 #: actions/finishremotesubscribe.php:31 actions/remotesubscribe.php:31 #: actions/finishremotesubscribe.php:33 actions/finishremotesubscribe.php:85 #: actions/finishremotesubscribe.php:101 actions/remotesubscribe.php:35 msgid "You can use the local subscription!" -msgstr "Możesz skorzystać z lokalnej subskrypcji!" +msgstr "Można używać lokalnej subskrypcji!" #: ../actions/finishopenidlogin.php:33 ../actions/register.php:61 #: actions/finishopenidlogin.php:38 actions/register.php:68 -#: actions/finishopenidlogin.php:43 +#: actions/finishopenidlogin.php:43 actions/register.php:149 msgid "You can't register if you don't agree to the license." msgstr "" "Nie możesz się zarejestrować, jeśli nie zgadzasz się z warunkami licencji." #: ../actions/updateprofile.php:63 actions/updateprofile.php:64 -#: actions/updateprofile.php:67 +#: actions/updateprofile.php:67 actions/updateprofile.php:69 msgid "You did not send us that profile" -msgstr "Ten profil nie był wysłany przez Ciebie" +msgstr "Nie wysłałeś nam tego profilu" -#: ../lib/mail.php:147 +#: ../lib/mail.php:147 lib/mail.php:289 #, php-format msgid "" "You have a new posting address on %1$s.\n" @@ -2645,122 +2802,132 @@ msgid "" "Faithfully yours,\n" "%4$s" msgstr "" +"Posiadasz nowy adres wysyłania na %1$s.\n" +"\n" +"Wyślij wiadomość e-mail na %2$s, aby wysłać nowe wpisy.\n" +"\n" +"Więcej instrukcji dotyczących poczty e-mail można znaleźć na %3$s.\n" +"\n" +"Z poważaniem,\n" +"%4$s" #: ../actions/twitapistatuses.php:612 actions/twitapistatuses.php:537 -#: actions/twitapistatuses.php:463 +#: actions/twitapistatuses.php:463 actions/twitapistatuses.php:486 msgid "You may not delete another user's status." -msgstr "" +msgstr "Nie można usuwać statusów innych użytkowników." #: ../actions/invite.php:31 actions/invite.php:31 actions/invite.php:39 #, php-format msgid "You must be logged in to invite other users to use %s" msgstr "" +"Należy być zalogowanym, aby zapraszać innych użytkowników do używania %s" #: ../actions/invite.php:103 actions/invite.php:110 actions/invite.php:142 msgid "" "You will be notified when your invitees accept the invitation and register " "on the site. Thanks for growing the community!" msgstr "" +"Zostaniesz powiadomiony, kiedy ktoś zaakceptuje zaproszenie i zarejestruje " +"się na stronie. Dziękujemy za pomoc w zwiększaniu społeczności!" -#: ../actions/recoverpassword.php:149 +#: ../actions/recoverpassword.php:149 actions/recoverpassword.php:158 msgid "You've been identified. Enter a new password below. " -msgstr "Identyfikacja pomyślna. Wprowadź poniżej nowe hasło." +msgstr "Zostałeś zidentyfikowany. Podaj poniżej nowe hasło. " #: ../actions/openidlogin.php:67 actions/openidlogin.php:76 -#: actions/openidlogin.php:104 +#: actions/openidlogin.php:104 actions/openidlogin.php:113 msgid "Your OpenID URL" -msgstr "URL Twojej usługi OpenID" +msgstr "Twój adres URL OpenID" -#: ../actions/recoverpassword.php:164 +#: ../actions/recoverpassword.php:164 actions/recoverpassword.php:188 msgid "Your nickname on this server, or your registered email address." -msgstr "" -"Twój pseudonim na tym serwerze lub adres e-mailowy użyty podczas rejestracji." +msgstr "Twój pseudonim na tym serwerze lub zarejestrowany adres e-mail." -#: ../actions/openidsettings.php:28 +#: ../actions/openidsettings.php:28 actions/openidsettings.php:70 #, php-format msgid "" "[OpenID](%%doc.openid%%) lets you log into many sites with the same user " "account. Manage your associated OpenIDs from here." msgstr "" -"[OpenID](%%doc.openid%%) pozwala logować Ci się do wielu serwisów z " -"wykorzystaniem jednego konta użytkownika. Tu możesz zarządzać swoimi " +"[OpenID](%%doc.openid%%) umożliwia logowanie się do wielu stron za pomocą " +"tego samego konta użytkownika. Tu można zarządzać powiązanymi " "identyfikatorami OpenID." -#: ../lib/util.php:943 lib/util.php:992 lib/util.php:945 +#: ../lib/util.php:943 lib/util.php:992 lib/util.php:945 lib/util.php:756 msgid "a few seconds ago" msgstr "kilka sekund temu" -#: ../lib/util.php:955 lib/util.php:1004 lib/util.php:957 +#: ../lib/util.php:955 lib/util.php:1004 lib/util.php:957 lib/util.php:768 #, php-format msgid "about %d days ago" msgstr "około %d dni temu" -#: ../lib/util.php:951 lib/util.php:1000 lib/util.php:953 +#: ../lib/util.php:951 lib/util.php:1000 lib/util.php:953 lib/util.php:764 #, php-format msgid "about %d hours ago" msgstr "około %d godzin temu" -#: ../lib/util.php:947 lib/util.php:996 lib/util.php:949 +#: ../lib/util.php:947 lib/util.php:996 lib/util.php:949 lib/util.php:760 #, php-format msgid "about %d minutes ago" msgstr "około %d minut temu" -#: ../lib/util.php:959 lib/util.php:1008 lib/util.php:961 +#: ../lib/util.php:959 lib/util.php:1008 lib/util.php:961 lib/util.php:772 #, php-format msgid "about %d months ago" msgstr "około %d miesięcy temu" -#: ../lib/util.php:953 lib/util.php:1002 lib/util.php:955 +#: ../lib/util.php:953 lib/util.php:1002 lib/util.php:955 lib/util.php:766 msgid "about a day ago" msgstr "blisko dzień temu" -#: ../lib/util.php:945 lib/util.php:994 lib/util.php:947 +#: ../lib/util.php:945 lib/util.php:994 lib/util.php:947 lib/util.php:758 msgid "about a minute ago" -msgstr "blisko minutę temu" +msgstr "około minutę temu" -#: ../lib/util.php:957 lib/util.php:1006 lib/util.php:959 +#: ../lib/util.php:957 lib/util.php:1006 lib/util.php:959 lib/util.php:770 msgid "about a month ago" -msgstr "blisko miesiąc temu" +msgstr "około miesiąc temu" -#: ../lib/util.php:961 lib/util.php:1010 lib/util.php:963 +#: ../lib/util.php:961 lib/util.php:1010 lib/util.php:963 lib/util.php:774 msgid "about a year ago" -msgstr "blisko rok temu" +msgstr "około rok temu" -#: ../lib/util.php:949 lib/util.php:998 lib/util.php:951 +#: ../lib/util.php:949 lib/util.php:998 lib/util.php:951 lib/util.php:762 msgid "about an hour ago" -msgstr "blisko godzinę temu" +msgstr "około godzinę temu" #: ../actions/showstream.php:423 ../lib/stream.php:132 #: actions/showstream.php:441 lib/stream.php:99 msgid "delete" -msgstr "" +msgstr "usuń" #: ../actions/noticesearch.php:130 ../actions/showstream.php:408 #: ../lib/stream.php:117 actions/noticesearch.php:136 #: actions/showstream.php:426 lib/stream.php:84 actions/noticesearch.php:187 msgid "in reply to..." -msgstr "w odpowiedzi na…" +msgstr "w odpowiedzi na..." #: ../actions/noticesearch.php:137 ../actions/showstream.php:415 #: ../lib/stream.php:124 actions/noticesearch.php:143 #: actions/showstream.php:433 lib/stream.php:91 actions/noticesearch.php:194 msgid "reply" -msgstr "odpowiedź" +msgstr "odpowiedz" #: ../actions/password.php:44 actions/profilesettings.php:183 #: actions/passwordsettings.php:106 msgid "same as password above" -msgstr "takie samo hasło jak powyżej" +msgstr "takie samo jak hasło powyżej" #: ../actions/twitapistatuses.php:755 actions/twitapistatuses.php:678 -#: actions/twitapistatuses.php:555 +#: actions/twitapistatuses.php:555 actions/twitapistatuses.php:596 +#: actions/twitapistatuses.php:618 msgid "unsupported file type" -msgstr "" +msgstr "nieobsługiwany typ pliku" #: ../lib/util.php:1309 lib/util.php:1443 -#, fuzzy msgid "« After" -msgstr "« następne" +msgstr "« Następne" #: actions/deletenotice.php:74 actions/disfavor.php:43 #: actions/emailsettings.php:127 actions/favor.php:45 @@ -2775,68 +2942,80 @@ msgstr "« następne" #: actions/finishopenidlogin.php:38 actions/invite.php:54 actions/nudge.php:80 #: actions/openidlogin.php:37 actions/recoverpassword.php:316 #: actions/subscribe.php:46 actions/unblock.php:65 actions/unsubscribe.php:43 +#: actions/avatarsettings.php:251 actions/emailsettings.php:229 +#: actions/grouplogo.php:314 actions/imsettings.php:200 actions/login.php:103 +#: actions/newmessage.php:133 actions/newnotice.php:96 +#: actions/openidsettings.php:188 actions/othersettings.php:136 +#: actions/passwordsettings.php:131 actions/profilesettings.php:172 +#: actions/register.php:113 actions/remotesubscribe.php:53 +#: actions/smssettings.php:216 actions/subedit.php:38 actions/tagother.php:166 +#: actions/twittersettings.php:294 actions/userauthorization.php:39 msgid "There was a problem with your session token. Try again, please." -msgstr "" +msgstr "Wystąpił problem z tokenem sesji. Spróbuj ponownie." #: actions/disfavor.php:55 actions/disfavor.php:81 msgid "This notice is not a favorite!" -msgstr "" +msgstr "Ten wpis nie jest ulubiony!" #: actions/disfavor.php:63 actions/disfavor.php:87 msgid "Could not delete favorite." -msgstr "" +msgstr "Nie można usunąć ulubionego wpisu." #: actions/disfavor.php:72 lib/favorform.php:140 msgid "Favor" -msgstr "" +msgstr "Dodaj do ulubionych" -#: actions/emailsettings.php:92 +#: actions/emailsettings.php:92 actions/emailsettings.php:157 msgid "Send me email when someone adds my notice as a favorite." -msgstr "" +msgstr "Wyślij mi wiadomość e-mail, kiedy ktoś doda mój wpis jako ulubiony." #: actions/emailsettings.php:95 actions/emailsettings.php:163 msgid "Send me email when someone sends me a private message." -msgstr "" +msgstr "Wyślij mi wiadomość e-mail, kiedy ktoś wyśle mi prywatną wiadomość." #: actions/favor.php:53 actions/twitapifavorites.php:142 actions/favor.php:81 -#: actions/twitapifavorites.php:118 +#: actions/twitapifavorites.php:118 actions/twitapifavorites.php:124 msgid "This notice is already a favorite!" -msgstr "" +msgstr "Ten wpis jest już ulubiony!" #: actions/favor.php:60 actions/twitapifavorites.php:151 #: classes/Command.php:132 actions/favor.php:86 #: actions/twitapifavorites.php:125 classes/Command.php:152 +#: actions/twitapifavorites.php:131 lib/command.php:152 msgid "Could not create favorite." -msgstr "" +msgstr "Nie można utworzyć ulubionego wpisu." #: actions/favor.php:70 msgid "Disfavor" -msgstr "" +msgstr "Usuń wpis z ulubionych" #: actions/favoritesrss.php:60 actions/showfavorites.php:47 #: actions/favoritesrss.php:100 actions/showfavorites.php:77 +#: actions/favoritesrss.php:110 #, php-format msgid "%s favorite notices" -msgstr "" +msgstr "Ulubione wpisy użytkownika %s" #: actions/favoritesrss.php:64 actions/favoritesrss.php:104 +#: actions/favoritesrss.php:114 #, php-format msgid "Feed of favorite notices of %s" -msgstr "" +msgstr "Kanał ulubionych wpisów użytkownika %s" #: actions/inbox.php:28 actions/inbox.php:59 #, php-format msgid "Inbox for %s - page %d" -msgstr "" +msgstr "Odebrane wiadomości użytkownika %s - strona %d" #: actions/inbox.php:30 actions/inbox.php:62 #, php-format msgid "Inbox for %s" -msgstr "" +msgstr "Odebrane wiadomości użytkownika %s" #: actions/inbox.php:53 actions/inbox.php:115 msgid "This is your inbox, which lists your incoming private messages." msgstr "" +"To jest skrzynka odbiorcza, która wyświetla przychodzące wiadomości prywatne." #: actions/invite.php:178 actions/invite.php:213 #, php-format @@ -2844,234 +3023,260 @@ msgid "" "%1$s has invited you to join them on %2$s (%3$s).\n" "\n" msgstr "" +"%1$s zaprosił się do dołączenia do %2$s (%3$s).\n" +"\n" #: actions/login.php:104 actions/login.php:235 actions/openidlogin.php:108 #: actions/register.php:416 msgid "Automatically login in the future; " -msgstr "" +msgstr "Automatyczne logowanie; " #: actions/login.php:122 actions/login.php:264 msgid "For security reasons, please re-enter your " -msgstr "" +msgstr "Z powodów bezpieczeństwa ponownie podaj " #: actions/login.php:126 actions/login.php:268 msgid "Login with your username and password. " -msgstr "" +msgstr "Zaloguj się za pomocą nazwy użytkownika i hasła. " #: actions/newmessage.php:58 actions/twitapidirect_messages.php:130 -#: actions/twitapidirect_messages.php:141 +#: actions/twitapidirect_messages.php:141 actions/newmessage.php:148 +#: actions/twitapidirect_messages.php:150 msgid "That's too long. Max message size is 140 chars." -msgstr "" +msgstr "Wiadomość jest za długa. Maksymalna długość to 140 znaków." #: actions/newmessage.php:65 actions/newmessage.php:128 +#: actions/newmessage.php:155 msgid "No recipient specified." -msgstr "" +msgstr "Nie podano odbiorcy." #: actions/newmessage.php:68 actions/newmessage.php:113 #: classes/Command.php:206 actions/newmessage.php:131 #: actions/newmessage.php:168 classes/Command.php:237 +#: actions/newmessage.php:119 actions/newmessage.php:158 lib/command.php:237 msgid "You can't send a message to this user." -msgstr "" +msgstr "Nie można wysłać wiadomości do tego użytkownika." #: actions/newmessage.php:71 actions/twitapidirect_messages.php:146 #: classes/Command.php:209 actions/twitapidirect_messages.php:158 -#: classes/Command.php:240 +#: classes/Command.php:240 actions/newmessage.php:161 +#: actions/twitapidirect_messages.php:167 lib/command.php:240 msgid "" "Don't send a message to yourself; just say it to yourself quietly instead." -msgstr "" +msgstr "Nie wysyłaj wiadomości do siebie, po prostu powiedz to sobie po cichu." #: actions/newmessage.php:108 actions/microsummary.php:62 -#: actions/newmessage.php:163 +#: actions/newmessage.php:163 actions/newmessage.php:114 msgid "No such user" -msgstr "" +msgstr "Nie ma takiego użytkownika" #: actions/newmessage.php:117 actions/newmessage.php:67 +#: actions/newmessage.php:71 msgid "New message" -msgstr "" +msgstr "Nowa wiadomość" #: actions/noticesearch.php:95 actions/noticesearch.php:146 msgid "Notice without matching profile" -msgstr "" +msgstr "Wpis bez odpowiadającego profilu" #: actions/openidsettings.php:28 actions/openidsettings.php:70 #, php-format msgid "[OpenID](%%doc.openid%%) lets you log into many sites " -msgstr "" +msgstr "[OpenID](%%doc.openid%%) umożliwia logowanie się na wiele stron " #: actions/openidsettings.php:46 actions/openidsettings.php:96 msgid "If you want to add an OpenID to your account, " -msgstr "" +msgstr "Jeśli chcesz dodać identyfikator OpenID do konta, " #: actions/openidsettings.php:74 msgid "Removing your only OpenID would make it impossible to log in! " -msgstr "" +msgstr "Usunięcie jedynego identyfikatora OpenID uniemożliwi zalogowanie się! " #: actions/openidsettings.php:87 actions/openidsettings.php:143 msgid "You can remove an OpenID from your account " -msgstr "" +msgstr "Można usunąć identyfikator OpenID z konta " #: actions/outbox.php:28 actions/outbox.php:58 #, php-format msgid "Outbox for %s - page %d" -msgstr "" +msgstr "Wysłane wiadomości użytkownika %s - strona %d" #: actions/outbox.php:30 actions/outbox.php:61 #, php-format msgid "Outbox for %s" -msgstr "" +msgstr "Wysłane wiadomości użytkownika %s" #: actions/outbox.php:53 actions/outbox.php:116 msgid "This is your outbox, which lists private messages you have sent." -msgstr "" +msgstr "To są wiadomości wysłane, czyli prywatne wiadomości, które wysłałeś." #: actions/peoplesearch.php:28 actions/peoplesearch.php:52 #, php-format msgid "" "Search for people on %%site.name%% by their name, location, or interests. " msgstr "" +"Znajdź osoby na %%site.name%% według ich nazwiska, położenia lub " +"zainteresowań. " #: actions/profilesettings.php:27 actions/profilesettings.php:69 msgid "You can update your personal profile info here " -msgstr "" +msgstr "Można tutaj zaktualizować osobiste informacje profilu " #: actions/profilesettings.php:115 actions/remotesubscribe.php:320 #: actions/userauthorization.php:159 actions/userrss.php:76 #: actions/avatarsettings.php:104 actions/avatarsettings.php:179 #: actions/grouplogo.php:177 actions/remotesubscribe.php:367 #: actions/userauthorization.php:176 actions/userrss.php:82 +#: actions/avatarsettings.php:106 actions/avatarsettings.php:182 +#: actions/grouplogo.php:183 actions/remotesubscribe.php:366 msgid "User without matching profile" -msgstr "" +msgstr "Użytkownik bez odpowiadającego profilu" #: actions/recoverpassword.php:91 actions/recoverpassword.php:97 msgid "This confirmation code is too old. " -msgstr "" +msgstr "Ten kod potwierdzający jest za stary. " #: actions/recoverpassword.php:141 actions/recoverpassword.php:152 msgid "If you've forgotten or lost your" -msgstr "" +msgstr "Jeśli zapomniałeś lub zgubiłeś" #: actions/recoverpassword.php:154 actions/recoverpassword.php:158 msgid "You've been identified. Enter a " -msgstr "" +msgstr "Zostałeś zidentyfikowany. Podaj " #: actions/recoverpassword.php:169 actions/recoverpassword.php:188 msgid "Your nickname on this server, " -msgstr "" +msgstr "Pseudonim na tym serwerze, " #: actions/recoverpassword.php:271 actions/recoverpassword.php:304 msgid "Instructions for recovering your password " -msgstr "" +msgstr "Instrukcje przywracania hasła " #: actions/recoverpassword.php:327 actions/recoverpassword.php:361 msgid "New password successfully saved. " -msgstr "" +msgstr "Pomyślnie zapisano nowe hasło. " #: actions/register.php:95 actions/register.php:180 +#: actions/passwordsettings.php:147 msgid "Password must be 6 or more characters." -msgstr "" +msgstr "Hasło musi mieć sześć lub więcej znaków." #: actions/register.php:216 #, php-format msgid "" "Congratulations, %s! And welcome to %%%%site.name%%%%. From here, you may " "want to..." -msgstr "" +msgstr "Gratulacje, %s! Witaj na %%%%site.name%%%%. Stąd możesz chcieć..." #: actions/register.php:227 msgid "(You should receive a message by email momentarily, with " -msgstr "" +msgstr "(Powinieneś właśnie otrzymać wiadomość przez e-mail z " #: actions/remotesubscribe.php:51 actions/remotesubscribe.php:74 #, php-format msgid "To subscribe, you can [login](%%action.login%%)," -msgstr "" +msgstr "Aby zasubskrybować, można [zalogować się](%%action.login%%)," #: actions/showfavorites.php:61 actions/showfavorites.php:145 +#: actions/showfavorites.php:147 #, php-format msgid "Feed for favorites of %s" -msgstr "" +msgstr "Kanał ulubionych wpisów użytkownika %s" #: actions/showfavorites.php:84 actions/twitapifavorites.php:85 #: actions/showfavorites.php:202 actions/twitapifavorites.php:59 +#: actions/showfavorites.php:179 msgid "Could not retrieve favorite notices." -msgstr "" +msgstr "Nie można odebrać ulubionych wpisów." #: actions/showmessage.php:33 actions/showmessage.php:81 msgid "No such message." -msgstr "" +msgstr "Nie ma takiej wiadomości." -#: actions/showmessage.php:42 +#: actions/showmessage.php:42 actions/showmessage.php:98 msgid "Only the sender and recipient may read this message." -msgstr "" +msgstr "Tylko nadawca i odbiorca mogą przeczytać tę wiadomość." #: actions/showmessage.php:61 actions/showmessage.php:108 #, php-format msgid "Message to %1$s on %2$s" -msgstr "" +msgstr "Wiadomość do użytkownika %1$s na %2$s" #: actions/showmessage.php:66 actions/showmessage.php:113 #, php-format msgid "Message from %1$s on %2$s" -msgstr "" +msgstr "Wiadomość od użytkownika %1$s na %2$s" #: actions/showstream.php:154 msgid "Send a message" -msgstr "" +msgstr "Wyślij wiadomość" #: actions/smssettings.php:312 actions/smssettings.php:464 #, php-format msgid "Mobile carrier for your phone. " -msgstr "" +msgstr "Operator komórkowy Twojego telefonu. " #: actions/twitapidirect_messages.php:76 actions/twitapidirect_messages.php:68 +#: actions/twitapidirect_messages.php:67 #, php-format msgid "Direct messages to %s" -msgstr "" +msgstr "Bezpośrednia wiadomość do użytkownika %s" #: actions/twitapidirect_messages.php:77 actions/twitapidirect_messages.php:69 +#: actions/twitapidirect_messages.php:68 #, php-format msgid "All the direct messages sent to %s" -msgstr "" +msgstr "Wszystkie bezpośrednie wiadomości wysłane do użytkownika %s" #: actions/twitapidirect_messages.php:81 actions/twitapidirect_messages.php:73 +#: actions/twitapidirect_messages.php:72 msgid "Direct Messages You've Sent" -msgstr "" +msgstr "Wysłane bezpośrednie wiadomości" #: actions/twitapidirect_messages.php:82 actions/twitapidirect_messages.php:74 +#: actions/twitapidirect_messages.php:73 #, php-format msgid "All the direct messages sent from %s" -msgstr "" +msgstr "Wszystkie bezpośrednie wiadomości wysłane od użytkownika %s" #: actions/twitapidirect_messages.php:128 #: actions/twitapidirect_messages.php:137 +#: actions/twitapidirect_messages.php:146 msgid "No message text!" -msgstr "" +msgstr "Brak tekstu wiadomości!" #: actions/twitapidirect_messages.php:138 #: actions/twitapidirect_messages.php:150 +#: actions/twitapidirect_messages.php:159 msgid "Recipient user not found." -msgstr "" +msgstr "Nie znaleziono odbiorcy." #: actions/twitapidirect_messages.php:141 #: actions/twitapidirect_messages.php:153 +#: actions/twitapidirect_messages.php:162 msgid "Can't send direct messages to users who aren't your friend." msgstr "" +"Nie można wysłać bezpośredniej wiadomości do użytkowników, którzy nie są " +"Twoimi przyjaciółmi." #: actions/twitapifavorites.php:92 actions/twitapifavorites.php:66 +#: actions/twitapifavorites.php:64 #, php-format msgid "%s / Favorites from %s" -msgstr "" +msgstr "%s/ulubione wpisy od %s" #: actions/twitapifavorites.php:95 actions/twitapifavorites.php:69 +#: actions/twitapifavorites.php:68 #, php-format msgid "%s updates favorited by %s / %s." -msgstr "" +msgstr "Użytkownik %s aktualizuje ulubione według %s/%s." #: actions/twitapifavorites.php:187 lib/mail.php:275 #: actions/twitapifavorites.php:164 lib/mail.php:553 +#: actions/twitapifavorites.php:170 lib/mail.php:554 #, php-format msgid "%s added your notice as a favorite" -msgstr "" +msgstr "Użytkownik %s dodał Twój wpis jako ulubiony" #: actions/twitapifavorites.php:188 lib/mail.php:276 #: actions/twitapifavorites.php:165 @@ -3080,230 +3285,251 @@ msgid "" "%1$s just added your notice from %2$s as one of their favorites.\n" "\n" msgstr "" +"Użytkownik %1$s właśnie dodał Twój wpis od %2$s jako jeden z jego " +"ulubionych.\n" +"\n" #: actions/twittersettings.php:27 msgid "" "Add your Twitter account to automatically send your notices to Twitter, " msgstr "" +"Dodaj swoje konto Twittera, aby automatycznie wysyłać wpisy na Twittera, " #: actions/twittersettings.php:41 actions/twittersettings.php:60 +#: actions/twittersettings.php:61 msgid "Twitter settings" -msgstr "" +msgstr "Ustawienia Twittera" #: actions/twittersettings.php:48 actions/twittersettings.php:105 +#: actions/twittersettings.php:106 msgid "Twitter Account" -msgstr "" +msgstr "Konto Twittera" #: actions/twittersettings.php:56 actions/twittersettings.php:113 +#: actions/twittersettings.php:114 msgid "Current verified Twitter account." -msgstr "" +msgstr "Obecnie sprawdzone konto Twittera." #: actions/twittersettings.php:63 msgid "Twitter Username" -msgstr "" +msgstr "Nazwa użytkownika Twitter" #: actions/twittersettings.php:65 actions/twittersettings.php:123 +#: actions/twittersettings.php:126 msgid "No spaces, please." -msgstr "" +msgstr "Bez spacji." #: actions/twittersettings.php:67 msgid "Twitter Password" -msgstr "" +msgstr "Hasło Twittera" #: actions/twittersettings.php:72 actions/twittersettings.php:139 +#: actions/twittersettings.php:142 msgid "Automatically send my notices to Twitter." -msgstr "" +msgstr "Automatycznie wyślij moje wpisy na Twittera." #: actions/twittersettings.php:75 actions/twittersettings.php:146 +#: actions/twittersettings.php:149 msgid "Send local \"@\" replies to Twitter." -msgstr "" +msgstr "Wyślij lokalne odpowiedzi \"@\" na Twittera." #: actions/twittersettings.php:78 actions/twittersettings.php:153 +#: actions/twittersettings.php:156 msgid "Subscribe to my Twitter friends here." -msgstr "" +msgstr "Zasubskrybuj tutaj moich przyjaciół z Twittera." -#: actions/twittersettings.php:122 +#: actions/twittersettings.php:122 actions/twittersettings.php:331 msgid "" "Username must have only numbers, upper- and lowercase letters, and " "underscore (_). 15 chars max." msgstr "" +"Nazwa użytkownika może zawierać tylko liczby, małe i wielkie litery oraz " +"podkreślnik (_). Maksymalnie 15 znaków." #: actions/twittersettings.php:128 actions/twittersettings.php:334 +#: actions/twittersettings.php:338 msgid "Could not verify your Twitter credentials!" -msgstr "" +msgstr "Nie można sprawdzić danych uwierzytelniających Twittera!" #: actions/twittersettings.php:137 #, php-format msgid "Unable to retrieve account information for \"%s\" from Twitter." -msgstr "" +msgstr "Nie można pobrać informacji o koncie \"%s\" z Twittera." #: actions/twittersettings.php:151 actions/twittersettings.php:170 #: actions/twittersettings.php:348 actions/twittersettings.php:368 +#: actions/twittersettings.php:352 actions/twittersettings.php:372 msgid "Unable to save your Twitter settings!" -msgstr "" +msgstr "Nie można zapisać ustawień Twittera!" #: actions/twittersettings.php:174 actions/twittersettings.php:376 +#: actions/twittersettings.php:380 msgid "Twitter settings saved." -msgstr "" +msgstr "Zapisano ustawienia Twittera." #: actions/twittersettings.php:192 actions/twittersettings.php:395 +#: actions/twittersettings.php:399 msgid "That is not your Twitter account." -msgstr "" +msgstr "To nie jest Twoje konto Twittera." #: actions/twittersettings.php:200 actions/twittersettings.php:208 -#: actions/twittersettings.php:403 +#: actions/twittersettings.php:403 actions/twittersettings.php:407 msgid "Couldn't remove Twitter user." -msgstr "" +msgstr "Nie można usunąć użytkownika Twittera." #: actions/twittersettings.php:212 actions/twittersettings.php:407 +#: actions/twittersettings.php:411 msgid "Twitter account removed." -msgstr "" +msgstr "Usunięto użytkownika Twittera." #: actions/twittersettings.php:225 actions/twittersettings.php:239 #: actions/twittersettings.php:428 actions/twittersettings.php:439 -#: actions/twittersettings.php:453 +#: actions/twittersettings.php:453 actions/twittersettings.php:432 +#: actions/twittersettings.php:443 actions/twittersettings.php:457 msgid "Couldn't save Twitter preferences." -msgstr "" +msgstr "Nie można zapisać preferencji Twittera." #: actions/twittersettings.php:245 actions/twittersettings.php:461 +#: actions/twittersettings.php:465 msgid "Twitter preferences saved." -msgstr "" +msgstr "Zapisano preferencje Twittera." #: actions/userauthorization.php:84 actions/userauthorization.php:86 msgid "Please check these details to make sure " -msgstr "" +msgstr "Sprawdź te szczegóły, aby upewnić się " #: actions/userauthorization.php:324 actions/userauthorization.php:340 msgid "The subscription has been authorized, but no " -msgstr "" +msgstr "Subskrypcja została upoważniona, ale nie " #: actions/userauthorization.php:334 actions/userauthorization.php:351 msgid "The subscription has been rejected, but no " -msgstr "" +msgstr "Subskrypcja została odrzucona, ale nie " #: classes/Channel.php:113 classes/Channel.php:132 classes/Channel.php:151 +#: lib/channel.php:138 lib/channel.php:158 msgid "Command results" -msgstr "" +msgstr "Wyniki polecenia" -#: classes/Channel.php:148 classes/Channel.php:204 +#: classes/Channel.php:148 classes/Channel.php:204 lib/channel.php:210 msgid "Command complete" -msgstr "" +msgstr "Zakończono polecenie" -#: classes/Channel.php:158 classes/Channel.php:215 +#: classes/Channel.php:158 classes/Channel.php:215 lib/channel.php:221 msgid "Command failed" -msgstr "" +msgstr "Polecenie nie powiodło się" -#: classes/Command.php:39 classes/Command.php:44 +#: classes/Command.php:39 classes/Command.php:44 lib/command.php:44 msgid "Sorry, this command is not yet implemented." -msgstr "" +msgstr "Przepraszamy, te polecenie nie zostało jeszcze zaimplementowane." #: classes/Command.php:96 classes/Command.php:113 #, php-format msgid "Subscriptions: %1$s\n" -msgstr "" +msgstr "Subskrypcje: %1$s\n" #: classes/Command.php:125 classes/Command.php:242 classes/Command.php:145 -#: classes/Command.php:276 +#: classes/Command.php:276 lib/command.php:145 lib/command.php:276 msgid "User has no last notice" -msgstr "" +msgstr "Użytkownik nie posiada ostatniego wpisu" -#: classes/Command.php:146 classes/Command.php:166 +#: classes/Command.php:146 classes/Command.php:166 lib/command.php:166 msgid "Notice marked as fave." -msgstr "" +msgstr "Zaznaczono wpis jako ulubiony." -#: classes/Command.php:166 classes/Command.php:189 +#: classes/Command.php:166 classes/Command.php:189 lib/command.php:189 #, php-format msgid "%1$s (%2$s)" -msgstr "" +msgstr "%1$s (%2$s)" -#: classes/Command.php:169 classes/Command.php:192 +#: classes/Command.php:169 classes/Command.php:192 lib/command.php:192 #, php-format msgid "Fullname: %s" -msgstr "" +msgstr "Imię i nazwisko: %s" -#: classes/Command.php:172 classes/Command.php:195 +#: classes/Command.php:172 classes/Command.php:195 lib/command.php:195 #, php-format msgid "Location: %s" -msgstr "" +msgstr "Położenie: %s" -#: classes/Command.php:175 classes/Command.php:198 +#: classes/Command.php:175 classes/Command.php:198 lib/command.php:198 #, php-format msgid "Homepage: %s" -msgstr "" +msgstr "Strona domowa: %s" -#: classes/Command.php:178 classes/Command.php:201 +#: classes/Command.php:178 classes/Command.php:201 lib/command.php:201 #, php-format msgid "About: %s" -msgstr "" +msgstr "O mnie: %s" -#: classes/Command.php:200 classes/Command.php:228 +#: classes/Command.php:200 classes/Command.php:228 lib/command.php:228 #, php-format msgid "Message too long - maximum is 140 characters, you sent %d" -msgstr "" +msgstr "Wiadomość jest za długa - maksymalnie 140 znaków, wysłano %d" -#: classes/Command.php:214 classes/Command.php:245 +#: classes/Command.php:214 classes/Command.php:245 lib/command.php:245 #, php-format msgid "Direct message to %s sent" -msgstr "" +msgstr "Wysłano bezpośrednią wiadomość do użytkownika %s" -#: classes/Command.php:216 classes/Command.php:247 +#: classes/Command.php:216 classes/Command.php:247 lib/command.php:247 msgid "Error sending direct message." -msgstr "" +msgstr "Błąd podczas wysyłania bezpośredniej wiadomości." -#: classes/Command.php:263 classes/Command.php:300 +#: classes/Command.php:263 classes/Command.php:300 lib/command.php:300 msgid "Specify the name of the user to subscribe to" -msgstr "" +msgstr "Podaj nazwę użytkownika do zasubskrybowania" -#: classes/Command.php:270 classes/Command.php:307 +#: classes/Command.php:270 classes/Command.php:307 lib/command.php:307 #, php-format msgid "Subscribed to %s" -msgstr "" +msgstr "Zasubskrybowano użytkownika %s" -#: classes/Command.php:288 classes/Command.php:328 +#: classes/Command.php:288 classes/Command.php:328 lib/command.php:328 msgid "Specify the name of the user to unsubscribe from" -msgstr "" +msgstr "Podaj nazwę użytkownika do usunięcia subskrypcji" -#: classes/Command.php:295 classes/Command.php:335 +#: classes/Command.php:295 classes/Command.php:335 lib/command.php:335 #, php-format msgid "Unsubscribed from %s" -msgstr "" +msgstr "Usunięto subskrypcję użytkownika %s" #: classes/Command.php:310 classes/Command.php:330 classes/Command.php:353 -#: classes/Command.php:376 +#: classes/Command.php:376 lib/command.php:353 lib/command.php:376 msgid "Command not yet implemented." -msgstr "" +msgstr "Nie zaimplementowano polecenia." -#: classes/Command.php:313 classes/Command.php:356 +#: classes/Command.php:313 classes/Command.php:356 lib/command.php:356 msgid "Notification off." -msgstr "" +msgstr "Wyłączono powiadomienia." -#: classes/Command.php:315 classes/Command.php:358 +#: classes/Command.php:315 classes/Command.php:358 lib/command.php:358 msgid "Can't turn off notification." -msgstr "" +msgstr "Nie można wyłączyć powiadomień." -#: classes/Command.php:333 classes/Command.php:379 +#: classes/Command.php:333 classes/Command.php:379 lib/command.php:379 msgid "Notification on." -msgstr "" +msgstr "Włączono powiadomienia." -#: classes/Command.php:335 classes/Command.php:381 +#: classes/Command.php:335 classes/Command.php:381 lib/command.php:381 msgid "Can't turn on notification." -msgstr "" +msgstr "Nie można włączyć powiadomień." #: classes/Command.php:344 classes/Command.php:392 msgid "Commands:\n" -msgstr "" +msgstr "Polecenia:\n" #: classes/Message.php:53 classes/Message.php:56 msgid "Could not insert message." -msgstr "" +msgstr "Nie można wprowadzić wiadomości." #: classes/Message.php:63 classes/Message.php:66 msgid "Could not update message with new URI." -msgstr "" +msgstr "Nie można zaktualizować wiadomości za pomocą nowego adresu URL." #: lib/gallery.php:46 msgid "User without matching profile in system." -msgstr "" +msgstr "Użytkownik bez odpowiadającego profilu w systemie." #: lib/mail.php:147 lib/mail.php:289 #, php-format @@ -3311,11 +3537,13 @@ msgid "" "You have a new posting address on %1$s.\n" "\n" msgstr "" +"Posiadasz nowy adres wysyłania na %1$s.\n" +"\n" -#: lib/mail.php:249 lib/mail.php:508 +#: lib/mail.php:249 lib/mail.php:508 lib/mail.php:509 #, php-format msgid "New private message from %s" -msgstr "" +msgstr "Nowa prywatna wiadomość od użytkownika %s" #: lib/mail.php:253 lib/mail.php:512 #, php-format @@ -3323,88 +3551,97 @@ msgid "" "%1$s (%2$s) sent you a private message:\n" "\n" msgstr "" +"Użytkownik %1$s (%2$s) wysłał Ci prywatną wiadomość:\n" +"\n" -#: lib/mailbox.php:43 lib/mailbox.php:89 +#: lib/mailbox.php:43 lib/mailbox.php:89 lib/mailbox.php:91 msgid "Only the user can read their own mailboxes." -msgstr "" +msgstr "Tylko użytkownik może czytać swoje skrzynki pocztowe." #: lib/openid.php:195 lib/openid.php:203 msgid "This form should automatically submit itself. " -msgstr "" +msgstr "Ten formularz powinien automatycznie się wysłać. " #: lib/personal.php:65 lib/personalgroupnav.php:113 msgid "Favorites" -msgstr "" +msgstr "Ulubione" #: lib/personal.php:66 lib/personalgroupnav.php:114 #, php-format msgid "%s's favorite notices" -msgstr "" +msgstr "Ulubione wpisy użytkownika %s" #: lib/personal.php:66 lib/personalgroupnav.php:114 msgid "User" -msgstr "" +msgstr "Użytkownik" #: lib/personal.php:75 lib/personalgroupnav.php:123 msgid "Inbox" -msgstr "" +msgstr "Odebrane" #: lib/personal.php:76 lib/personalgroupnav.php:124 msgid "Your incoming messages" -msgstr "" +msgstr "Wiadomości przychodzące" #: lib/personal.php:80 lib/personalgroupnav.php:128 msgid "Outbox" -msgstr "" +msgstr "Wysłane" #: lib/personal.php:81 lib/personalgroupnav.php:129 msgid "Your sent messages" -msgstr "" +msgstr "Wysłane wiadomości" #: lib/settingsaction.php:99 lib/connectsettingsaction.php:110 msgid "Twitter" -msgstr "" +msgstr "Twitter" #: lib/settingsaction.php:100 lib/connectsettingsaction.php:111 msgid "Twitter integration options" -msgstr "" +msgstr "Opcje integracji z Twitterem" #: lib/util.php:1718 lib/messageform.php:139 lib/noticelist.php:422 +#: lib/messageform.php:137 lib/noticelist.php:425 msgid "To" -msgstr "" +msgstr "Do" #: scripts/maildaemon.php:45 scripts/maildaemon.php:48 msgid "Could not parse message." -msgstr "" +msgstr "Nie można przeanalizować wiadomości." -#: actions/all.php:63 actions/facebookhome.php:162 -#, fuzzy, php-format +#: actions/all.php:63 actions/facebookhome.php:162 actions/all.php:66 +#: actions/facebookhome.php:161 +#, php-format msgid "%s and friends, page %d" -msgstr "%s i przyjaciele" +msgstr "Użytkownik %s i przyjaciele, strona %d" #: actions/avatarsettings.php:76 msgid "You can upload your personal avatar." -msgstr "" +msgstr "Można wysłać osobisty awatar." #: actions/avatarsettings.php:117 actions/avatarsettings.php:191 -#: actions/grouplogo.php:250 -#, fuzzy +#: actions/grouplogo.php:250 actions/avatarsettings.php:119 +#: actions/avatarsettings.php:194 actions/grouplogo.php:256 msgid "Avatar settings" -msgstr "Ustawienia" +msgstr "Ustawienia awatara" #: actions/avatarsettings.php:124 actions/avatarsettings.php:199 #: actions/grouplogo.php:198 actions/grouplogo.php:258 +#: actions/avatarsettings.php:126 actions/avatarsettings.php:202 +#: actions/grouplogo.php:204 actions/grouplogo.php:264 msgid "Original" -msgstr "" +msgstr "Oryginał" #: actions/avatarsettings.php:139 actions/avatarsettings.php:211 #: actions/grouplogo.php:209 actions/grouplogo.php:270 +#: actions/avatarsettings.php:141 actions/avatarsettings.php:214 +#: actions/grouplogo.php:215 actions/grouplogo.php:276 msgid "Preview" -msgstr "" +msgstr "Podgląd" #: actions/avatarsettings.php:225 actions/grouplogo.php:284 +#: actions/avatarsettings.php:228 actions/grouplogo.php:291 msgid "Crop" -msgstr "" +msgstr "Przytnij" #: actions/avatarsettings.php:248 actions/deletenotice.php:133 #: actions/emailsettings.php:224 actions/grouplogo.php:307 @@ -3416,594 +3653,567 @@ msgstr "" #: actions/subedit.php:38 actions/twittersettings.php:290 #: actions/userauthorization.php:39 msgid "There was a problem with your session token. " -msgstr "" +msgstr "Wystąpił problem z tokenem sesji. " #: actions/avatarsettings.php:303 actions/grouplogo.php:360 +#: actions/avatarsettings.php:308 msgid "Pick a square area of the image to be your avatar" -msgstr "" +msgstr "Wybierz kwadratowy obszar obrazu do awatara" #: actions/avatarsettings.php:327 actions/grouplogo.php:384 +#: actions/avatarsettings.php:323 actions/grouplogo.php:382 msgid "Lost our file data." -msgstr "" +msgstr "Utracono dane pliku." #: actions/avatarsettings.php:334 actions/grouplogo.php:391 -#: classes/User_group.php:112 -#, fuzzy +#: classes/User_group.php:112 lib/imagefile.php:112 msgid "Lost our file." -msgstr "Brak takiego wpisu." +msgstr "Utracono plik." #: actions/avatarsettings.php:349 actions/avatarsettings.php:383 #: actions/grouplogo.php:406 actions/grouplogo.php:440 -#: classes/User_group.php:129 classes/User_group.php:161 +#: classes/User_group.php:129 classes/User_group.php:161 lib/imagefile.php:144 +#: lib/imagefile.php:191 msgid "Unknown file type" -msgstr "" +msgstr "Nieznany typ pliku" #: actions/block.php:69 actions/subedit.php:46 actions/unblock.php:70 msgid "No profile specified." -msgstr "" +msgstr "Nie podano profilu." #: actions/block.php:74 actions/subedit.php:53 actions/tagother.php:46 #: actions/unblock.php:75 msgid "No profile with that ID." -msgstr "" +msgstr "Brak profilu o tym identyfikatorze." #: actions/block.php:111 -#, fuzzy msgid "Block user" -msgstr "Brak takiego użytkownika." +msgstr "Zablokuj użytkownika" #: actions/block.php:129 msgid "Are you sure you want to block this user? " -msgstr "" +msgstr "Na pewno chcesz zablokować tego użytkownika? " #: actions/block.php:162 -#, fuzzy msgid "You have already blocked this user." -msgstr "Nie musisz ponownie się logować!" +msgstr "Ten użytkownik został już zablokowany." #: actions/block.php:167 msgid "Failed to save block information." -msgstr "" +msgstr "Zapisanie informacji o blokadzie nie powiodło się." #: actions/confirmaddress.php:159 -#, fuzzy, php-format +#, php-format msgid "The address \"%s\" has been " -msgstr "Adres został usunięty." +msgstr "Adres \"%s\" został " #: actions/deletenotice.php:73 msgid "You are about to permanently delete a notice. " -msgstr "" +msgstr "Za chwilę wpis zostanie trwale usunięty. " #: actions/disfavor.php:94 msgid "Add to favorites" -msgstr "" +msgstr "Dodaj do ulubionych" #: actions/editgroup.php:54 #, php-format msgid "Edit %s group" -msgstr "" +msgstr "Edytuj grupę %s" #: actions/editgroup.php:66 actions/groupbyid.php:72 actions/grouplogo.php:66 #: actions/joingroup.php:60 actions/newgroup.php:65 actions/showgroup.php:100 +#: actions/grouplogo.php:70 actions/grouprss.php:80 msgid "Inboxes must be enabled for groups to work" -msgstr "" +msgstr "Skrzynki odbiorcze grup muszą być włączone, aby działały" #: actions/editgroup.php:71 actions/grouplogo.php:71 actions/newgroup.php:70 +#: actions/grouplogo.php:75 msgid "You must be logged in to create a group." -msgstr "" +msgstr "Musisz być zalogowany, aby utworzyć grupę." #: actions/editgroup.php:87 actions/grouplogo.php:87 #: actions/groupmembers.php:76 actions/joingroup.php:81 -#: actions/showgroup.php:121 -#, fuzzy +#: actions/showgroup.php:121 actions/grouplogo.php:91 actions/grouprss.php:96 msgid "No nickname" -msgstr "Brak pseudonimu." +msgstr "Brak pseudonimu" #: actions/editgroup.php:99 actions/groupbyid.php:88 actions/grouplogo.php:100 #: actions/groupmembers.php:83 actions/joingroup.php:88 -#: actions/showgroup.php:128 -#, fuzzy +#: actions/showgroup.php:128 actions/grouplogo.php:104 +#: actions/grouprss.php:103 msgid "No such group" -msgstr "Brak takiego wpisu." +msgstr "Nie ma takiej grupy" #: actions/editgroup.php:106 actions/editgroup.php:165 -#: actions/grouplogo.php:107 +#: actions/grouplogo.php:107 actions/grouplogo.php:111 msgid "You must be an admin to edit the group" -msgstr "" +msgstr "Musisz być administratorem, aby zmodyfikować grupę" #: actions/editgroup.php:157 msgid "Use this form to edit the group." -msgstr "" +msgstr "Użyj tego formularza, aby zmodyfikować grupę." #: actions/editgroup.php:179 actions/newgroup.php:130 actions/register.php:156 -#, fuzzy msgid "Nickname must have only lowercase letters " -msgstr "Pseudonim musi zawierać tylko małe litery i cyfry, bez znaków spacji." +msgstr "Pseudonim może zawierać tylko małe litery " #: actions/editgroup.php:198 actions/newgroup.php:149 -#, fuzzy msgid "description is too long (max 140 chars)." -msgstr "Wpis \"O mnie\" jest za długi (maks. 140 znaków)" +msgstr "opis jest za długi (maksymalnie 140 znaków)." #: actions/editgroup.php:218 -#, fuzzy msgid "Could not update group." -msgstr "Nie można zaktualizować użytkownika." +msgstr "Nie można zaktualizować grupy." #: actions/editgroup.php:226 -#, fuzzy msgid "Options saved." -msgstr "Ustawienia zostały zapisane." +msgstr "Zapisano opcje." #: actions/emailsettings.php:107 actions/imsettings.php:108 -#, fuzzy, php-format +#, php-format msgid "Awaiting confirmation on this address. " -msgstr "Błąd kodu potwierdzającego." +msgstr "Oczekiwanie na potwierdzenie tego adresu. " #: actions/emailsettings.php:139 actions/smssettings.php:150 msgid "Make a new email address for posting to; " -msgstr "" +msgstr "Utwórz nowy adres e-mail do wysyłania; " #: actions/emailsettings.php:157 msgid "Send me email when someone " -msgstr "" +msgstr "Wyślij mi wiadomość e-mail, kiedy ktoś " -#: actions/emailsettings.php:168 +#: actions/emailsettings.php:168 actions/emailsettings.php:173 msgid "Allow friends to nudge me and send me an email." -msgstr "" +msgstr "Pozwól przyjaciołom na szturchanie mnie i wyślij mi wiadomość e-mail." #: actions/emailsettings.php:321 -#, fuzzy msgid "That email address already belongs " -msgstr "Taki e-mail już istnieje" +msgstr "Ten adres e-mail już należy " #: actions/emailsettings.php:343 -#, fuzzy msgid "A confirmation code was sent to the email address you added. " -msgstr "" -"Na Twój adres komunikatora został wysłany kod potwierdzający. Musisz " -"zaakceptować otrzymywanie wiadomości od %s." +msgstr "Kod potwierdzający został wysłany na dodany adres e-mail. " #: actions/facebookhome.php:110 msgid "Server error - couldn't get user!" -msgstr "" +msgstr "Błąd serwera - nie można uzyskać użytkownika!" #: actions/facebookhome.php:196 #, php-format msgid "If you would like the %s app to automatically update " -msgstr "" +msgstr "Jeśli chcesz, aby aplikacja %s automatycznie aktualizowała " #: actions/facebookhome.php:213 actions/facebooksettings.php:137 #, php-format msgid "Allow %s to update my Facebook status" -msgstr "" +msgstr "Pozwól %s na aktualizowanie mojego statusu na Facebook" -#: actions/facebookhome.php:218 +#: actions/facebookhome.php:218 actions/facebookhome.php:223 msgid "Skip" -msgstr "" +msgstr "Pomiń" -#: actions/facebookhome.php:235 -#, fuzzy +#: actions/facebookhome.php:235 lib/facebookaction.php:479 msgid "No notice content!" -msgstr "Brak zawartości!" +msgstr "Brak zawartości wpisu!" #: actions/facebookhome.php:295 lib/action.php:870 lib/facebookaction.php:399 +#: actions/facebookhome.php:253 lib/action.php:973 lib/facebookaction.php:433 msgid "Pagination" -msgstr "" +msgstr "Paginacja" #: actions/facebookhome.php:304 lib/action.php:879 lib/facebookaction.php:408 -#, fuzzy +#: actions/facebookhome.php:262 lib/action.php:982 lib/facebookaction.php:442 msgid "After" -msgstr "« następne" +msgstr "Następne" #: actions/facebookhome.php:312 lib/action.php:887 lib/facebookaction.php:416 -#, fuzzy +#: actions/facebookhome.php:270 lib/action.php:990 lib/facebookaction.php:450 msgid "Before" -msgstr "Wcześniej »" +msgstr "Wcześniej" #: actions/facebookinvite.php:70 #, php-format msgid "Thanks for inviting your friends to use %s" -msgstr "" +msgstr "Dziękujemy za zaproszenie przyjaciół do używania %s" #: actions/facebookinvite.php:72 msgid "Invitations have been sent to the following users:" -msgstr "" +msgstr "Zaproszenia zostały wysłane do następujących użytkowników:" -#: actions/facebookinvite.php:96 +#: actions/facebookinvite.php:96 actions/facebookinvite.php:102 #, php-format msgid "You have been invited to %s" -msgstr "" +msgstr "Zostałeś zaproszony do %s" -#: actions/facebookinvite.php:105 -#, fuzzy, php-format +#: actions/facebookinvite.php:105 actions/facebookinvite.php:111 +#, php-format msgid "Invite your friends to use %s" -msgstr "Kanał dla znajomych użytkownika %s" +msgstr "Zaproś przyjaciół do używania %s" -#: actions/facebookinvite.php:113 +#: actions/facebookinvite.php:113 actions/facebookinvite.php:126 #, php-format msgid "Friends already using %s:" -msgstr "" +msgstr "Przyjaciele już używający %s:" -#: actions/facebookinvite.php:130 +#: actions/facebookinvite.php:130 actions/facebookinvite.php:143 #, php-format msgid "Send invitations" -msgstr "" +msgstr "Wyślij zaproszenia" #: actions/facebookremove.php:56 -#, fuzzy msgid "Couldn't remove Facebook user." -msgstr "Nie można zaktualizować użytkownika." +msgstr "Nie można usunąć użytkownika Facebook." #: actions/facebooksettings.php:65 msgid "There was a problem saving your sync preferences!" -msgstr "" +msgstr "Wystąpił problem podczas zapisywania preferencji synchronizacji!" #: actions/facebooksettings.php:67 -#, fuzzy msgid "Sync preferences saved." -msgstr "Preferencje zostały zapisane." +msgstr "Zapisano preferencje synchronizacji." #: actions/facebooksettings.php:90 msgid "Automatically update my Facebook status with my notices." -msgstr "" +msgstr "Automatycznie aktualizuj status na Facebook moimi wpisami." #: actions/facebooksettings.php:97 msgid "Send \"@\" replies to Facebook." -msgstr "" +msgstr "Wyślij odpowiedzi \"@\" do Facebook." #: actions/facebooksettings.php:106 -#, fuzzy msgid "Prefix" -msgstr "Profil" +msgstr "Przedrostek" #: actions/facebooksettings.php:108 msgid "A string to prefix notices with." -msgstr "" +msgstr "Tekst do poprzedzenia wpisów." #: actions/facebooksettings.php:124 #, php-format msgid "If you would like %s to automatically update " -msgstr "" +msgstr "Jeśli chcesz, aby %s automatycznie aktualizowało " #: actions/facebooksettings.php:147 -#, fuzzy msgid "Sync preferences" -msgstr "Preferencje" +msgstr "Zsynchronizuj preferencje" #: actions/favor.php:94 lib/disfavorform.php:140 msgid "Disfavor favorite" -msgstr "" +msgstr "Usuń wpis z ulubionych" #: actions/favorited.php:65 lib/popularnoticesection.php:76 -#: lib/publicgroupnav.php:91 -#, fuzzy +#: lib/publicgroupnav.php:91 lib/popularnoticesection.php:82 +#: lib/publicgroupnav.php:93 msgid "Popular notices" -msgstr "Brak takiego wpisu." +msgstr "Popularne wpisy" #: actions/favorited.php:67 -#, fuzzy, php-format +#, php-format msgid "Popular notices, page %d" -msgstr "Brak takiego wpisu." +msgstr "Popularne wpisy, strona %d" #: actions/favorited.php:79 msgid "The most popular notices on the site right now." -msgstr "" +msgstr "Najpopularniejsze wpisy na stronie w te chwili." #: actions/featured.php:69 lib/featureduserssection.php:82 -#: lib/publicgroupnav.php:87 +#: lib/publicgroupnav.php:87 lib/publicgroupnav.php:89 msgid "Featured users" -msgstr "" +msgstr "Znani użytkownicy" #: actions/featured.php:71 #, php-format msgid "Featured users, page %d" -msgstr "" +msgstr "Znani użytkownicy, strona %d" #: actions/featured.php:99 #, php-format msgid "A selection of some of the great users on %s" -msgstr "" +msgstr "Wybór znanych użytkowników na %s" #: actions/finishremotesubscribe.php:188 msgid "That user has blocked you from subscribing." -msgstr "" +msgstr "Ten użytkownik zablokował Cię z subskrypcji." #: actions/groupbyid.php:79 msgid "No ID" -msgstr "" +msgstr "Brak identyfikatora" #: actions/grouplogo.php:138 actions/grouplogo.php:191 +#: actions/grouplogo.php:144 actions/grouplogo.php:197 msgid "Group logo" -msgstr "" +msgstr "Logo grupy" #: actions/grouplogo.php:149 msgid "You can upload a logo image for your group." -msgstr "" +msgstr "Można wysłać obraz logo dla grupy." -#: actions/grouplogo.php:448 -#, fuzzy +#: actions/grouplogo.php:448 actions/grouplogo.php:401 msgid "Logo updated." -msgstr "Awatar załadowany." +msgstr "Zaktualizowano logo." -#: actions/grouplogo.php:450 -#, fuzzy +#: actions/grouplogo.php:450 actions/grouplogo.php:403 msgid "Failed updating logo." -msgstr "Uaktualnianie awatara nie powiodło się." +msgstr "Zaktualizowanie logo nie powiodło się." #: actions/groupmembers.php:93 lib/groupnav.php:91 #, php-format msgid "%s group members" -msgstr "" +msgstr "Członkowie grupy %s" #: actions/groupmembers.php:96 #, php-format msgid "%s group members, page %d" -msgstr "" +msgstr "Członkowie grupy %s, strona %d" #: actions/groupmembers.php:111 msgid "A list of the users in this group." -msgstr "" +msgstr "Lista użytkowników znajdujących się w tej grupie." #: actions/groups.php:62 actions/showstream.php:518 lib/publicgroupnav.php:79 -#: lib/subgroupnav.php:96 +#: lib/subgroupnav.php:96 lib/publicgroupnav.php:81 msgid "Groups" -msgstr "" +msgstr "Grupy" #: actions/groups.php:64 #, php-format msgid "Groups, page %d" -msgstr "" +msgstr "Grupy, strona %d" #: actions/groups.php:90 #, php-format msgid "%%%%site.name%%%% groups let you find and talk with " -msgstr "" +msgstr "Grupy %%%%site.name%%%% pozwalają na szukanie i rozmawianie z " #: actions/groups.php:106 actions/usergroups.php:124 lib/groupeditform.php:123 -#, fuzzy +#: actions/usergroups.php:125 msgid "Create a new group" -msgstr "Załóż nowe konto" +msgstr "Utwórz nową grupę" #: actions/groupsearch.php:57 -#, fuzzy, php-format +#, php-format msgid "" "Search for groups on %%site.name%% by their name, location, or description. " -msgstr "" -"Szukaj ludzi w serwisie %%site.name%%. Kryteriami mogą być imiona i " -"nazwiska, miejscowości lub zainteresowania. Użyj spacji aby oddzielić " -"elementy wyszukiwania. Słowa muszą mieć minimum 3 znaki." +msgstr "Znajdź grupy na %%site.name%% według ich nazw, położenia lub opisu. " #: actions/groupsearch.php:63 -#, fuzzy msgid "Group search" -msgstr "Szukaj ludzi" +msgstr "Znajdź grupę" #: actions/imsettings.php:70 msgid "You can send and receive notices through " -msgstr "" +msgstr "Można wysyłać i otrzymywać wpisy przez " #: actions/imsettings.php:120 #, php-format msgid "Jabber or GTalk address, " -msgstr "" +msgstr "adres Jabbera lub GTalk, " #: actions/imsettings.php:147 -#, fuzzy msgid "Send me replies through Jabber/GTalk " -msgstr "Wysyłaj mi wpisy przez Jabbera/GTalka" +msgstr "Wyślij mi odpowiedzi przez Jabbera/GTalk " #: actions/imsettings.php:321 -#, fuzzy, php-format +#, php-format msgid "A confirmation code was sent " -msgstr "Brak kodu potwierdzającego." +msgstr "Kod potwierdzający został wysłany " #: actions/joingroup.php:65 msgid "You must be logged in to join a group." -msgstr "" +msgstr "Musisz być zalogowany, aby dołączyć do grupy." #: actions/joingroup.php:95 -#, fuzzy msgid "You are already a member of that group" -msgstr "Nie musisz ponownie się logować!" +msgstr "Jesteś już członkiem tej grupy" #: actions/joingroup.php:128 -#, fuzzy, php-format +#, php-format msgid "Could not join user %s to group %s" -msgstr "Nie można przekierować do serwera: %s" +msgstr "Nie można dołączyć użytkownika %s do grupy %s" #: actions/joingroup.php:135 #, php-format msgid "%s joined group %s" -msgstr "" +msgstr "Użytkownik %s dołączył do grupy %s" #: actions/leavegroup.php:60 msgid "Inboxes must be enabled for groups to work." -msgstr "" +msgstr "Skrzynki odbiorcze dla grup muszą być włączone, aby działały." #: actions/leavegroup.php:65 msgid "You must be logged in to leave a group." -msgstr "" +msgstr "Musisz być zalogowany, aby opuścić grupę." #: actions/leavegroup.php:88 -#, fuzzy msgid "No such group." -msgstr "Brak takiego wpisu." +msgstr "Nie ma takiej grupy." #: actions/leavegroup.php:95 -#, fuzzy msgid "You are not a member of that group." -msgstr "Ten profil nie był wysłany przez Ciebie" +msgstr "Nie jesteś członkiem tej grupy." #: actions/leavegroup.php:100 msgid "You may not leave a group while you are its administrator." -msgstr "" +msgstr "Nie możesz opuścić grupy, kiedy jesteś jej administratorem." -#: actions/leavegroup.php:130 +#: actions/leavegroup.php:130 actions/leavegroup.php:124 msgid "Could not find membership record." -msgstr "" +msgstr "Nie można znaleźć wpisu członkostwa." -#: actions/leavegroup.php:138 -#, fuzzy, php-format +#: actions/leavegroup.php:138 actions/leavegroup.php:132 +#, php-format msgid "Could not remove user %s to group %s" -msgstr "Nie można utworzyć formularza OpenID: %s" +msgstr "Nie można usunąć użytkownika %s z grupy %s" -#: actions/leavegroup.php:145 +#: actions/leavegroup.php:145 actions/leavegroup.php:139 #, php-format msgid "%s left group %s" -msgstr "" +msgstr "Użytkownik %s opuścił grupę %s" -#: actions/login.php:225 lib/facebookaction.php:304 +#: actions/login.php:225 lib/facebookaction.php:304 actions/login.php:208 msgid "Login to site" -msgstr "" +msgstr "Zaloguj się na stronie" #: actions/microsummary.php:69 msgid "No current status" -msgstr "" +msgstr "Brak obecnego statusu" #: actions/newgroup.php:53 msgid "New group" -msgstr "" +msgstr "Nowa grupa" #: actions/newgroup.php:115 msgid "Use this form to create a new group." -msgstr "" +msgstr "Użyj tego formularza, aby utworzyć nową grupę." #: actions/newgroup.php:177 -#, fuzzy msgid "Could not create group." -msgstr "Nie można zapisać informacji o awatarze" +msgstr "Nie można utworzyć grupy." #: actions/newgroup.php:191 -#, fuzzy msgid "Could not set group membership." -msgstr "Nie można obserwować." +msgstr "Nie można ustawić członkostwa w grupie." #: actions/newmessage.php:119 actions/newnotice.php:132 -#, fuzzy msgid "That's too long. " -msgstr "Ten plik jest za duży." +msgstr "Wiadomość jest za długa. " #: actions/newmessage.php:134 msgid "Don't send a message to yourself; " -msgstr "" +msgstr "Nie wysyłaj wiadomości do siebie; " -#: actions/newnotice.php:166 -#, fuzzy +#: actions/newnotice.php:166 actions/newnotice.php:174 msgid "Notice posted" -msgstr "Wpisy" +msgstr "Wysłano wpis" -#: actions/newnotice.php:200 classes/Channel.php:163 +#: actions/newnotice.php:200 classes/Channel.php:163 actions/newnotice.php:208 +#: lib/channel.php:170 msgid "Ajax Error" -msgstr "" +msgstr "Błąd AJAX" #: actions/nudge.php:85 msgid "" "This user doesn't allow nudges or hasn't confirmed or set his email yet." msgstr "" +"Ten użytkownik nie pozwala na szturchnięcia lub nie potwierdził lub nie " +"ustawił jeszcze swojego adresu e-mail." #: actions/nudge.php:94 msgid "Nudge sent" -msgstr "" +msgstr "Wysłano szturchnięcie" #: actions/nudge.php:97 msgid "Nudge sent!" -msgstr "" +msgstr "Wysłano szturchnięcie!" -#: actions/openidlogin.php:97 -#, fuzzy +#: actions/openidlogin.php:97 actions/openidlogin.php:106 msgid "OpenID login" -msgstr "Użytkownik OpenID" +msgstr "Login OpenID" #: actions/openidsettings.php:128 -#, fuzzy msgid "Removing your only OpenID " -msgstr "Usuń konto OpenID" +msgstr "Usuwanie jedynego identyfikatora OpenID " #: actions/othersettings.php:60 -#, fuzzy msgid "Other Settings" -msgstr "Ustawienia" +msgstr "Inne ustawienia" #: actions/othersettings.php:71 msgid "Manage various other options." -msgstr "" +msgstr "Zarządzaj różnymi innymi opcjami." #: actions/othersettings.php:93 msgid "URL Auto-shortening" -msgstr "" +msgstr "Automatyczne skracanie adresów URL" #: actions/othersettings.php:112 -#, fuzzy msgid "Service" -msgstr "Szukaj" +msgstr "Usługa" #: actions/othersettings.php:113 msgid "Automatic shortening service to use." -msgstr "" +msgstr "Używana automatyczna usługa skracania." #: actions/othersettings.php:144 -#, fuzzy msgid "URL shortening service is too long (max 50 chars)." -msgstr "Lokalizacja jest za długa (max. 255 znaków)." +msgstr "Adres URL usługi skracania jest za długi (maksymalnie 50 znaków)." #: actions/passwordsettings.php:69 -#, fuzzy msgid "Change your password." -msgstr "Zmień hasło" +msgstr "Zmień hasło." #: actions/passwordsettings.php:89 -#, fuzzy msgid "Password change" -msgstr "Hasło zostało zapisane." +msgstr "Zmiana hasła" -#: actions/peopletag.php:35 -#, fuzzy, php-format +#: actions/peopletag.php:35 actions/peopletag.php:70 +#, php-format msgid "Not a valid people tag: %s" -msgstr "Niewłaściwy adres e-mailowy." +msgstr "Nieprawidłowy znacznik osób: %s" -#: actions/peopletag.php:47 +#: actions/peopletag.php:47 actions/peopletag.php:144 #, php-format msgid "Users self-tagged with %s - page %d" -msgstr "" +msgstr "Użytkownicy używający znacznika %s - strona %d" #: actions/peopletag.php:91 #, php-format msgid "These are users who have tagged themselves \"%s\" " -msgstr "" +msgstr "To są użytkownicy którzy nadali sobie znacznik \"%s\" " #: actions/profilesettings.php:91 -#, fuzzy msgid "Profile information" -msgstr "Nieznany profil" +msgstr "Informacje o profilu" #: actions/profilesettings.php:124 msgid "" "Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated" msgstr "" +"Znaczniki dla siebie (litery, liczby, -, . i _), oddzielone przecinkami lub " +"spacjami" #: actions/profilesettings.php:144 msgid "Automatically subscribe to whoever " -msgstr "" +msgstr "Automatycznie zasubskrybuj do każdego " #: actions/profilesettings.php:229 actions/tagother.php:176 -#, fuzzy, php-format +#: actions/tagother.php:178 +#, php-format msgid "Invalid tag: \"%s\"" -msgstr "Błędna strona domowa '%s'" +msgstr "Nieprawidłowy znacznik: \"%s\"" #: actions/profilesettings.php:311 -#, fuzzy msgid "Couldn't save tags." -msgstr "Nie można zapisać profilu." +msgstr "Nie można zapisać znaczników." -#: actions/public.php:107 -#, fuzzy, php-format +#: actions/public.php:107 actions/public.php:110 +#, php-format msgid "Public timeline, page %d" -msgstr "Publiczna oś czasu" +msgstr "Publiczna oś czasu, strona %d" -#: actions/public.php:173 +#: actions/public.php:173 actions/public.php:184 msgid "Could not retrieve public stream." -msgstr "" +msgstr "Nie można pobrać publicznego strumienia." #: actions/public.php:220 #, php-format @@ -4011,139 +4221,132 @@ msgid "" "This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" "blogging) service " msgstr "" +"To jest %%site.name%%, usługa [mikroblogowania](http://en.wikipedia.org/wiki/" +"Micro-blogging) " #: actions/publictagcloud.php:57 -#, fuzzy msgid "Public tag cloud" -msgstr "Publiczny Kanał Strumieni" +msgstr "Publiczna chmura znaczników" #: actions/publictagcloud.php:63 #, php-format msgid "These are most popular recent tags on %s " -msgstr "" +msgstr "To są najpopularniejsze ostatnie znaczniki na %s " #: actions/publictagcloud.php:119 msgid "Tag cloud" -msgstr "" +msgstr "Chmura znaczników" #: actions/register.php:139 actions/register.php:349 msgid "Sorry, only invited people can register." -msgstr "" +msgstr "Przepraszamy, tylko zaproszone osoby mogą się rejestrować." #: actions/register.php:149 -#, fuzzy msgid "You can't register if you don't " -msgstr "" -"Nie możesz się zarejestrować, jeśli nie zgadzasz się z warunkami licencji." +msgstr "Nie możesz się zarejestrować, jeśli nie " #: actions/register.php:286 msgid "With this form you can create " -msgstr "" +msgstr "Za pomocą tego formularza można utworzyć " #: actions/register.php:368 -#, fuzzy msgid "1-64 lowercase letters or numbers, " -msgstr "Max. 64 znaki alfanumeryczne, bez spacji i znaków przestankowych" +msgstr "1-64 małe litery lub liczby, " #: actions/register.php:382 actions/register.php:386 -#, fuzzy msgid "Used only for updates, announcements, " -msgstr "Używane tylko do aktualizacji, ogłoszeń i przywracania hasła" +msgstr "Używane tylko do aktualizacji, ogłoszeń, " #: actions/register.php:398 -#, fuzzy msgid "URL of your homepage, blog, " -msgstr "URL Twojej strony domowej, bloga, lub profilu na innej stronie" +msgstr "Adres URL strony domowej, bloga, " #: actions/register.php:404 -#, fuzzy msgid "Describe yourself and your " -msgstr "Opisz się w 140 znakach" +msgstr "Opisz się i swoje " #: actions/register.php:410 -#, fuzzy msgid "Where you are, like \"City, " -msgstr "Gdzie jesteś? (np. \"miasto, region, kraj\")" +msgstr "Gdzie jesteś, np. \"miasto, " #: actions/register.php:432 -#, fuzzy msgid " except this private data: password, " -msgstr "" -"z wyłączeniem tych prywatnych danych: e-maila, identyfikatora IM, numeru " -"telefonu." +msgstr " poza tymi prywatnymi danymi: hasło, " #: actions/register.php:471 #, php-format msgid "Congratulations, %s! And welcome to %%%%site.name%%%%. " -msgstr "" +msgstr "Gratulacje, %s! Witaj na %%%%site.name%%%%. " #: actions/register.php:495 msgid "(You should receive a message by email " -msgstr "" +msgstr "(Powinieneś otrzymać wiadomość przez e-mail " #: actions/remotesubscribe.php:166 actions/remotesubscribe.php:171 msgid "That's a local profile! Login to subscribe." -msgstr "" +msgstr "To jest profil lokalny! Zaloguj się, aby zasubskrybować." -#: actions/replies.php:118 -#, fuzzy, php-format +#: actions/replies.php:118 actions/replies.php:120 +#, php-format msgid "Replies to %s, page %d" -msgstr "Odpowiedzi na %s" +msgstr "Odpowiedzi na %s, strona %d" #: actions/showfavorites.php:79 #, php-format msgid "%s favorite notices, page %d" -msgstr "" +msgstr "Ulubione wpisy użytkownika %s, strona %d" #: actions/showgroup.php:77 lib/groupnav.php:85 #, php-format msgid "%s group" -msgstr "" +msgstr "Grupa %s" #: actions/showgroup.php:79 #, php-format msgid "%s group, page %d" -msgstr "" +msgstr "Grupa %s, strona %d" -#: actions/showgroup.php:206 -#, fuzzy +#: actions/showgroup.php:206 actions/showgroup.php:208 msgid "Group profile" -msgstr "Brak takiego wpisu." +msgstr "Profil grupy" #: actions/showgroup.php:251 actions/showstream.php:278 #: actions/tagother.php:119 lib/grouplist.php:134 lib/profilelist.php:133 +#: actions/showgroup.php:253 actions/showstream.php:271 +#: actions/tagother.php:118 lib/profilelist.php:131 msgid "URL" -msgstr "" +msgstr "Adres URL" #: actions/showgroup.php:262 actions/showstream.php:289 #: actions/tagother.php:129 lib/grouplist.php:145 lib/profilelist.php:144 -#, fuzzy +#: actions/showgroup.php:264 actions/showstream.php:282 +#: actions/tagother.php:128 lib/profilelist.php:142 msgid "Note" -msgstr "Wpisy" +msgstr "Wpis" -#: actions/showgroup.php:270 +#: actions/showgroup.php:270 actions/showgroup.php:272 msgid "Group actions" -msgstr "" +msgstr "Działania grupy" -#: actions/showgroup.php:323 -#, fuzzy, php-format +#: actions/showgroup.php:323 actions/showgroup.php:304 +#, php-format msgid "Notice feed for %s group" -msgstr "Kanał wpisów dla %s" +msgstr "Kanał wpisów dla grupy %s" -#: actions/showgroup.php:357 lib/groupnav.php:90 -#, fuzzy +#: actions/showgroup.php:357 lib/groupnav.php:90 actions/showgroup.php:339 +#: actions/showgroup.php:384 msgid "Members" -msgstr "W serwisie od" +msgstr "Członkowie" #: actions/showgroup.php:363 actions/showstream.php:413 #: actions/showstream.php:442 actions/showstream.php:524 lib/section.php:95 -#: lib/tagcloudsection.php:71 +#: lib/tagcloudsection.php:71 actions/showgroup.php:344 msgid "(None)" -msgstr "" +msgstr "(Brak)" -#: actions/showgroup.php:370 +#: actions/showgroup.php:370 actions/showgroup.php:350 msgid "All members" -msgstr "" +msgstr "Wszyscy członkowie" #: actions/showgroup.php:378 #, php-format @@ -4151,50 +4354,51 @@ msgid "" "**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." "wikipedia.org/wiki/Micro-blogging) service " msgstr "" +"**%s** jest grupą użytkowników na %%%%site.name%%%%, usłudze " +"[mikroblogowania](http://en.wikipedia.org/wiki/Micro-blogging) " #: actions/showmessage.php:98 msgid "Only the sender and recipient " -msgstr "" +msgstr "Tylko nadawca i odbiorca " #: actions/showstream.php:73 #, php-format msgid "%s, page %d" -msgstr "" +msgstr "%s, strona %d" #: actions/showstream.php:143 -#, fuzzy msgid "'s profile" -msgstr "Profil" +msgstr " - profil" #: actions/showstream.php:236 actions/tagother.php:77 -#, fuzzy +#: actions/showstream.php:220 msgid "User profile" -msgstr "Użytkownik nie ma profilu." +msgstr "Profil użytkownika" #: actions/showstream.php:240 actions/tagother.php:81 +#: actions/showstream.php:224 msgid "Photo" -msgstr "" +msgstr "Zdjęcie" -#: actions/showstream.php:317 +#: actions/showstream.php:317 actions/showstream.php:309 msgid "User actions" -msgstr "" +msgstr "Działania użytkownika" #: actions/showstream.php:342 msgid "Send a direct message to this user" -msgstr "" +msgstr "Wyślij bezpośrednią wiadomość do tego użytkownika" #: actions/showstream.php:343 msgid "Message" -msgstr "" +msgstr "Wiadomość" #: actions/showstream.php:451 -#, fuzzy msgid "All subscribers" -msgstr "Subskrybenci" +msgstr "Wszyscy subskrybenci" #: actions/showstream.php:533 msgid "All groups" -msgstr "" +msgstr "Wszystkie grupy" #: actions/showstream.php:542 #, php-format @@ -4202,480 +4406,449 @@ msgid "" "**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." "wikipedia.org/wiki/Micro-blogging) service " msgstr "" +"**%s** posiada konto na %%%%site.name%%%%, usłudze [mikroblogowania](http://" +"en.wikipedia.org/wiki/Micro-blogging) " #: actions/smssettings.php:128 -#, fuzzy msgid "Phone number, no punctuation or spaces, " -msgstr "Max. 64 znaki alfanumeryczne, bez spacji i znaków przestankowych" +msgstr "Numer telefonu, bez znaków przestankowych i spacji, " #: actions/smssettings.php:162 -#, fuzzy msgid "Send me notices through SMS; " -msgstr "Wysyłaj mi wpisy przez Jabbera/GTalka" +msgstr "Wyślij mi wpisy przez SMS; " #: actions/smssettings.php:335 -#, fuzzy msgid "A confirmation code was sent to the phone number you added. " -msgstr "Ten kod potwierdzający nie jest przeznaczony dla Ciebie!" +msgstr "Kod potwierdzający został wysłany na dodany numer telefonu. " #: actions/smssettings.php:453 msgid "Mobile carrier" -msgstr "" +msgstr "Operator komórkowy" #: actions/subedit.php:70 -#, fuzzy msgid "You are not subscribed to that profile." -msgstr "Ten profil nie był wysłany przez Ciebie" +msgstr "Nie jesteś zasubskrybowany do tego profilu." #: actions/subedit.php:83 -#, fuzzy msgid "Could not save subscription." -msgstr "Nie można obserwować." +msgstr "Nie można zapisać subskrypcji." #: actions/subscribe.php:55 -#, fuzzy msgid "Not a local user." -msgstr "Brak takiego użytkownika." +msgstr "Nie jest lokalnym użytkownikiem." #: actions/subscribe.php:69 -#, fuzzy msgid "Subscribed" -msgstr "Subskrybuj" +msgstr "Zasubskrybowano" #: actions/subscribers.php:50 -#, fuzzy, php-format +#, php-format msgid "%s subscribers" -msgstr "Subskrybenci" +msgstr "Subskrybenci %s" #: actions/subscribers.php:52 #, php-format msgid "%s subscribers, page %d" -msgstr "" +msgstr "Subskrybenci %s, strona %d" #: actions/subscribers.php:63 -#, fuzzy msgid "These are the people who listen to " -msgstr "Ludzie obserwujący wpisy użytkownika %s." +msgstr "Osoby obserwujące " #: actions/subscribers.php:67 -#, fuzzy, php-format +#, php-format msgid "These are the people who " -msgstr "Ludzie obserwujący wpisy użytkownika %s." +msgstr "Osoby, które " #: actions/subscriptions.php:52 -#, fuzzy, php-format +#, php-format msgid "%s subscriptions" -msgstr "Wszyscy obserwowani" +msgstr "Subskrypcje %s" #: actions/subscriptions.php:54 -#, fuzzy, php-format +#, php-format msgid "%s subscriptions, page %d" -msgstr "Wszyscy obserwowani" +msgstr "Subskrypcje %s, strona %d" #: actions/subscriptions.php:65 -#, fuzzy msgid "These are the people whose notices " -msgstr "Ludzie, których wpisy obserwuje użytkownik %s." +msgstr "Osoby, których wpisy " #: actions/subscriptions.php:69 -#, fuzzy, php-format +#, php-format msgid "These are the people whose " -msgstr "Ludzie obserwujący wpisy użytkownika %s." +msgstr "Osoby, których " -#: actions/subscriptions.php:122 -#, fuzzy +#: actions/subscriptions.php:122 actions/subscriptions.php:124 msgid "Jabber" -msgstr "Brak identyfikatora Jabbera." +msgstr "Jabber" -#: actions/tag.php:43 -#, fuzzy, php-format +#: actions/tag.php:43 actions/tag.php:51 +#, php-format msgid "Notices tagged with %s, page %d" -msgstr "%s – mikroblog" +msgstr "Wpisy ze znacznikiem %s, strona %d" -#: actions/tag.php:66 +#: actions/tag.php:66 actions/tag.php:73 #, php-format msgid "Messages tagged \"%s\", most recent first" -msgstr "" +msgstr "Wiadomości ze znacznikiem \"%s\", najpierw najnowsze" #: actions/tagother.php:33 -#, fuzzy msgid "Not logged in" -msgstr "Niezalogowany." +msgstr "Nie zalogowano" #: actions/tagother.php:39 -#, fuzzy msgid "No id argument." -msgstr "Brak takiego dokumentu." +msgstr "Brak parametru identyfikatora." #: actions/tagother.php:65 #, php-format msgid "Tag %s" -msgstr "" +msgstr "Znacznik %s" #: actions/tagother.php:141 msgid "Tag user" -msgstr "" +msgstr "Znacznik użytkownika" -#: actions/tagother.php:149 +#: actions/tagother.php:149 actions/tagother.php:151 msgid "" "Tags for this user (letters, numbers, -, ., and _), comma- or space- " "separated" msgstr "" +"Znaczniki dla tego użytkownika (litery, liczby, -, . i _), oddzielone " +"przecinkami lub spacjami" #: actions/tagother.php:164 msgid "There was a problem with your session token." -msgstr "" +msgstr "Wystąpił problem z tokenem sesji." -#: actions/tagother.php:191 +#: actions/tagother.php:191 actions/tagother.php:193 msgid "" "You can only tag people you are subscribed to or who are subscribed to you." msgstr "" +"Można nadawać znaczniki tylko osobom, których subskrybujesz lub którzy " +"subskrybują Ciebie." -#: actions/tagother.php:198 -#, fuzzy +#: actions/tagother.php:198 actions/tagother.php:200 msgid "Could not save tags." -msgstr "Nie można zapisać informacji o awatarze" +msgstr "Nie można zapisać znaczników." -#: actions/tagother.php:233 +#: actions/tagother.php:233 actions/tagother.php:235 msgid "Use this form to add tags to your subscribers or subscriptions." msgstr "" +"Użyj tego formularza, aby dodać znaczniki subskrybentom lub subskrypcjom." #: actions/tagrss.php:35 -#, fuzzy msgid "No such tag." -msgstr "Brak takiego wpisu." +msgstr "Nie ma takiego znacznika." -#: actions/tagrss.php:66 -#, fuzzy, php-format +#: actions/tagrss.php:66 actions/tagrss.php:64 +#, php-format msgid "Microblog tagged with %s" -msgstr "%s – mikroblog" +msgstr "Mikroblogi ze znacznikiem %s" #: actions/twitapiblocks.php:47 msgid "Block user failed." -msgstr "" +msgstr "Zablokowanie użytkownika nie powiodło się." #: actions/twitapiblocks.php:69 msgid "Unblock user failed." -msgstr "" +msgstr "Odblokowanie użytkownika nie powiodło się." -#: actions/twitapiusers.php:48 -#, fuzzy +#: actions/twitapiusers.php:48 actions/twitapiusers.php:52 msgid "Not found." -msgstr "Nie znaleziono żądania!" +msgstr "Nie znaleziono." #: actions/twittersettings.php:71 msgid "Add your Twitter account to automatically send " -msgstr "" +msgstr "Dodaj konto Twittera, aby automatycznie wysyłać " -#: actions/twittersettings.php:119 +#: actions/twittersettings.php:119 actions/twittersettings.php:122 msgid "Twitter user name" -msgstr "" +msgstr "Nazwa użytkownika Twittera" -#: actions/twittersettings.php:126 -#, fuzzy +#: actions/twittersettings.php:126 actions/twittersettings.php:129 msgid "Twitter password" -msgstr "Nowe hasło" +msgstr "Hasło Twittera" -#: actions/twittersettings.php:228 +#: actions/twittersettings.php:228 actions/twittersettings.php:232 msgid "Twitter Friends" -msgstr "" +msgstr "Przyjaciele z Twittera" #: actions/twittersettings.php:327 msgid "Username must have only numbers, " -msgstr "" +msgstr "Nazwa użytkownika może zawierać tylko liczby, " #: actions/twittersettings.php:341 -#, fuzzy, php-format +#, php-format msgid "Unable to retrieve account information " -msgstr "Nie można skasować potwierdzenia adresu e-mail." +msgstr "Nie można pobrać informacji o koncie " #: actions/unblock.php:108 -#, fuzzy msgid "Error removing the block." -msgstr "Błąd w zapisie użytkownika." +msgstr "Błąd podczas usuwania blokady." #: actions/unsubscribe.php:50 -#, fuzzy msgid "No profile id in request." -msgstr "Serwer nie zwrócił żadnego URL-a." +msgstr "Brak identyfikatora profilu w żądaniu." #: actions/unsubscribe.php:57 -#, fuzzy msgid "No profile with that id." -msgstr "Zdalny profil bez odpowiadającego profilu lokalnego" +msgstr "Brak profilu z tym identyfikatorem." #: actions/unsubscribe.php:71 -#, fuzzy msgid "Unsubscribed" -msgstr "Zrezygnuj z subskrypcji" +msgstr "Zrezygnowano z subskrypcji" #: actions/usergroups.php:63 #, php-format msgid "%s groups" -msgstr "" +msgstr "Grupy %s" #: actions/usergroups.php:65 #, php-format msgid "%s groups, page %d" -msgstr "" +msgstr "Grupy %s, strona %d" -#: classes/Notice.php:104 -#, fuzzy +#: classes/Notice.php:104 classes/Notice.php:128 msgid "Problem saving notice. Unknown user." -msgstr "Problem z zachowywaniem wpisu." +msgstr "Problem podczas zapisywania wpisu. Nieznany użytkownik." -#: classes/Notice.php:109 +#: classes/Notice.php:109 classes/Notice.php:133 msgid "" "Too many notices too fast; take a breather and post again in a few minutes." msgstr "" +"Za dużo wpisów w za krótkim czasie, weź głęboki oddech i wyślij ponownie za " +"kilka minut." -#: classes/Notice.php:116 +#: classes/Notice.php:116 classes/Notice.php:145 msgid "You are banned from posting notices on this site." -msgstr "" +msgstr "Zabroniono Ci wysyłania wpisów na tej stronie." #: lib/accountsettingsaction.php:108 -#, fuzzy msgid "Upload an avatar" -msgstr "Uaktualnianie awatara nie powiodło się." +msgstr "Wyślij awatar" #: lib/accountsettingsaction.php:119 msgid "Other" -msgstr "" +msgstr "Inne" #: lib/accountsettingsaction.php:120 msgid "Other options" -msgstr "" +msgstr "Inne opcje" -#: lib/action.php:130 +#: lib/action.php:130 lib/action.php:132 #, php-format msgid "%s - %s" -msgstr "" +msgstr "%s - %s" -#: lib/action.php:145 +#: lib/action.php:145 lib/action.php:147 msgid "Untitled page" -msgstr "" +msgstr "Strona bez nazwy" -#: lib/action.php:316 +#: lib/action.php:316 lib/action.php:387 msgid "Primary site navigation" -msgstr "" +msgstr "Główna nawigacja strony" -#: lib/action.php:322 +#: lib/action.php:322 lib/action.php:393 msgid "Personal profile and friends timeline" -msgstr "" +msgstr "Profil osobisty i oś czasu przyjaciół" -#: lib/action.php:325 +#: lib/action.php:325 lib/action.php:396 msgid "Search for people or text" -msgstr "" +msgstr "Znajdź osoby lub tekst" -#: lib/action.php:328 -#, fuzzy +#: lib/action.php:328 lib/action.php:399 msgid "Account" -msgstr "O serwisie" +msgstr "Konto" -#: lib/action.php:328 +#: lib/action.php:328 lib/action.php:399 msgid "Change your email, avatar, password, profile" -msgstr "" +msgstr "Zmień adres e-mail, awatar, hasło, profil" -#: lib/action.php:330 +#: lib/action.php:330 lib/action.php:403 msgid "Connect to IM, SMS, Twitter" -msgstr "" +msgstr "Połącz z komunikatorem, SMS, Twitterem" -#: lib/action.php:332 +#: lib/action.php:332 lib/action.php:409 msgid "Logout from the site" -msgstr "" +msgstr "Wyloguj się ze strony" -#: lib/action.php:335 +#: lib/action.php:335 lib/action.php:412 msgid "Login to the site" -msgstr "" +msgstr "Zaloguj się na stronę" -#: lib/action.php:338 -#, fuzzy +#: lib/action.php:338 lib/action.php:415 msgid "Create an account" -msgstr "Załóż nowe konto" +msgstr "Utwórz konto" -#: lib/action.php:341 -#, fuzzy +#: lib/action.php:341 lib/action.php:418 msgid "Login with OpenID" -msgstr "Brak takiego identyfikatora OpenID." +msgstr "Zaloguj się za pomocą OpenID" -#: lib/action.php:344 -#, fuzzy +#: lib/action.php:344 lib/action.php:421 msgid "Help me!" -msgstr "Pomoc" +msgstr "Pomóż mi!" -#: lib/action.php:362 -#, fuzzy +#: lib/action.php:362 lib/action.php:441 msgid "Site notice" -msgstr "Nowy wpis" +msgstr "Wpis strony" -#: lib/action.php:417 +#: lib/action.php:417 lib/action.php:504 msgid "Local views" -msgstr "" +msgstr "Lokalne widoki" -#: lib/action.php:472 -#, fuzzy +#: lib/action.php:472 lib/action.php:559 msgid "Page notice" -msgstr "Nowy wpis" +msgstr "Wpis strony" -#: lib/action.php:562 -#, fuzzy +#: lib/action.php:562 lib/action.php:654 msgid "Secondary site navigation" -msgstr "Subskrypcje" +msgstr "Druga nawigacja strony" -#: lib/action.php:602 lib/action.php:623 +#: lib/action.php:602 lib/action.php:623 lib/action.php:699 lib/action.php:720 msgid "Laconica software license" -msgstr "" +msgstr "Licencja oprogramowania Laconica" -#: lib/action.php:630 +#: lib/action.php:630 lib/action.php:727 msgid "All " -msgstr "" +msgstr "Wszystko " -#: lib/action.php:635 +#: lib/action.php:635 lib/action.php:732 msgid "license." -msgstr "" +msgstr "licencja." #: lib/blockform.php:123 lib/blockform.php:153 -#, fuzzy msgid "Block this user" -msgstr "Brak takiego użytkownika." +msgstr "Zablokuj tego użytkownika" #: lib/blockform.php:153 msgid "Block" -msgstr "" +msgstr "Zablokuj" #: lib/disfavorform.php:114 lib/disfavorform.php:140 msgid "Disfavor this notice" -msgstr "" +msgstr "Usuń ten wpis z ulubionych" #: lib/facebookaction.php:268 #, php-format msgid "To use the %s Facebook Application you need to login " -msgstr "" +msgstr "Aby używać aplikacji Facebook %s, musisz się zalogować " -#: lib/facebookaction.php:271 -#, fuzzy +#: lib/facebookaction.php:271 lib/facebookaction.php:273 msgid " a new account." -msgstr "Załóż nowe konto" +msgstr " nowe konto." #: lib/facebookaction.php:557 lib/mailbox.php:214 lib/noticelist.php:354 -#, fuzzy +#: lib/facebookaction.php:675 lib/mailbox.php:216 lib/noticelist.php:357 msgid "Published" -msgstr "Publiczny" +msgstr "Opublikowano" #: lib/favorform.php:114 lib/favorform.php:140 -#, fuzzy msgid "Favor this notice" -msgstr "Brak takiego wpisu." +msgstr "Dodaj ten wpis do ulubionych" #: lib/feedlist.php:64 msgid "Export data" -msgstr "" +msgstr "Wyeksportuj dane" #: lib/galleryaction.php:121 msgid "Filter tags" -msgstr "" +msgstr "Filtruj znaczniki" #: lib/galleryaction.php:131 msgid "All" -msgstr "" +msgstr "Wszystko" #: lib/galleryaction.php:137 msgid "Tag" -msgstr "" +msgstr "Znacznik" #: lib/galleryaction.php:138 msgid "Choose a tag to narrow list" -msgstr "" +msgstr "Wybierz znacznik do ograniczonej listy" #: lib/galleryaction.php:139 msgid "Go" -msgstr "" +msgstr "Przejdź" #: lib/groupeditform.php:148 -#, fuzzy msgid "URL of the homepage or blog of the group or topic" -msgstr "URL Twojej strony domowej, bloga, lub profilu na innej stronie" +msgstr "Adres URL strony domowej lub bloga grupy, albo temat" #: lib/groupeditform.php:151 -#, fuzzy msgid "Description" -msgstr "Subskrypcje" +msgstr "Opis" #: lib/groupeditform.php:153 -#, fuzzy msgid "Describe the group or topic in 140 chars" -msgstr "Opisz się w 140 znakach" +msgstr "Opisz grupę lub temat w 140 znakach" #: lib/groupeditform.php:158 -#, fuzzy msgid "" "Location for the group, if any, like \"City, State (or Region), Country\"" -msgstr "Gdzie jesteś? (np. \"miasto, region, kraj\")" +msgstr "" +"Położenie grupy, jeśli istnieje, np. \"miasto, województwo (lub region), kraj" +"\"" #: lib/groupnav.php:84 lib/searchgroupnav.php:84 msgid "Group" -msgstr "" +msgstr "Grupa" #: lib/groupnav.php:100 msgid "Admin" -msgstr "" +msgstr "Administrator" #: lib/groupnav.php:101 #, php-format msgid "Edit %s group properties" -msgstr "" +msgstr "Edytuj właściwości grupy %s" #: lib/groupnav.php:106 -#, fuzzy msgid "Logo" -msgstr "Wyloguj" +msgstr "Logo" #: lib/groupnav.php:107 #, php-format msgid "Add or edit %s logo" -msgstr "" +msgstr "Dodaj lub edytuj logo grupy %s" #: lib/groupsbymemberssection.php:71 msgid "Groups with most members" -msgstr "" +msgstr "Grupy z największą liczbą członków" #: lib/groupsbypostssection.php:71 msgid "Groups with most posts" -msgstr "" +msgstr "Grupy z największą ilością wpisów" #: lib/grouptagcloudsection.php:56 #, php-format msgid "Tags in %s group's notices" -msgstr "" +msgstr "Znaczniki we wpisach grupy %s" #: lib/htmloutputter.php:104 -#, fuzzy msgid "This page is not available in a " -msgstr "Ta strona nie jest dostępna dla medium, którego typ akceptujesz" +msgstr "Ta strona nie jest dostępna w " #: lib/joinform.php:114 -#, fuzzy msgid "Join" -msgstr "Login" +msgstr "Dołącz" #: lib/leaveform.php:114 -#, fuzzy msgid "Leave" -msgstr "Zapisz" +msgstr "Opuść" #: lib/logingroupnav.php:76 -#, fuzzy msgid "Login with a username and password" -msgstr "Błędna nazwa użytkownika lub hasło." +msgstr "Zaloguj się za pomocą nazwy użytkownika i hasła" #: lib/logingroupnav.php:79 -#, fuzzy msgid "Sign up for a new account" msgstr "Załóż nowe konto" #: lib/logingroupnav.php:82 msgid "Login or register with OpenID" -msgstr "" +msgstr "Zaloguj się lub zarejestruj za pomocą OpenID" #: lib/mail.php:175 #, php-format @@ -4683,21 +4856,23 @@ msgid "" "Hey, %s.\n" "\n" msgstr "" +"Cześć, %s.\n" +"\n" #: lib/mail.php:236 -#, fuzzy, php-format +#, php-format msgid "%1$s is now listening to " -msgstr "%1$s obserwuje teraz Twoje wpisy na %2$s." +msgstr "%1$s obserwuje teraz " #: lib/mail.php:254 -#, fuzzy, php-format +#, php-format msgid "Location: %s\n" -msgstr "Lokalizacja" +msgstr "Położenie: %s\n" #: lib/mail.php:256 -#, fuzzy, php-format +#, php-format msgid "Homepage: %s\n" -msgstr "Strona domowa" +msgstr "Strona domowa: %s\n" #: lib/mail.php:258 #, php-format @@ -4705,185 +4880,783 @@ msgid "" "Bio: %s\n" "\n" msgstr "" +"O mnie: %s\n" +"\n" -#: lib/mail.php:461 +#: lib/mail.php:461 lib/mail.php:462 #, php-format msgid "You've been nudged by %s" -msgstr "" +msgstr "Zostałeś szturchnięty przez %s" #: lib/mail.php:465 #, php-format msgid "%1$s (%2$s) is wondering what you are up to " -msgstr "" +msgstr "%1$s (%2$s) zastanawia się, co zamierzasz " #: lib/mail.php:555 -#, fuzzy, php-format +#, php-format msgid "%1$s just added your notice from %2$s" -msgstr "%1$s obserwuje teraz Twoje wpisy na %2$s." +msgstr "%1$s właśnie dodał Twój wpis z %2$s" -#: lib/mailbox.php:229 lib/noticelist.php:380 +#: lib/mailbox.php:229 lib/noticelist.php:380 lib/mailbox.php:231 +#: lib/noticelist.php:383 msgid "From" -msgstr "" +msgstr "Od" -#: lib/messageform.php:110 +#: lib/messageform.php:110 lib/messageform.php:109 msgid "Send a direct notice" -msgstr "" +msgstr "Wyślij bezpośredni wpis" #: lib/noticeform.php:125 -#, fuzzy msgid "Send a notice" -msgstr "Nowy wpis" +msgstr "Wyślij wpis" #: lib/noticeform.php:152 -#, fuzzy msgid "Available characters" -msgstr "6 lub więcej znaków" +msgstr "Dostępne znaki" -#: lib/noticelist.php:426 -#, fuzzy +#: lib/noticelist.php:426 lib/noticelist.php:429 msgid "in reply to" -msgstr "w odpowiedzi na…" +msgstr "w odpowiedzi na" -#: lib/noticelist.php:447 lib/noticelist.php:450 +#: lib/noticelist.php:447 lib/noticelist.php:450 lib/noticelist.php:451 +#: lib/noticelist.php:454 msgid "Reply to this notice" -msgstr "" +msgstr "Odpowiedz na ten wpis" -#: lib/noticelist.php:451 -#, fuzzy +#: lib/noticelist.php:451 lib/noticelist.php:455 msgid "Reply" -msgstr "odpowiedź" +msgstr "Odpowiedz" -#: lib/noticelist.php:471 lib/noticelist.php:474 +#: lib/noticelist.php:471 lib/noticelist.php:474 lib/noticelist.php:476 +#: lib/noticelist.php:479 msgid "Delete this notice" -msgstr "" +msgstr "Usuń ten wpis" -#: lib/noticelist.php:474 +#: lib/noticelist.php:474 actions/avatarsettings.php:148 +#: lib/noticelist.php:479 msgid "Delete" -msgstr "" +msgstr "Usuń" #: lib/nudgeform.php:116 msgid "Nudge this user" -msgstr "" +msgstr "Szturchnij tego użytkownika" #: lib/nudgeform.php:128 msgid "Nudge" -msgstr "" +msgstr "Szturchnij" #: lib/nudgeform.php:128 msgid "Send a nudge to this user" -msgstr "" +msgstr "Wyślij szturchnięcie do tego użytkownika" #: lib/personaltagcloudsection.php:56 #, php-format msgid "Tags in %s's notices" -msgstr "" +msgstr "Znaczniki we wpisach użytkownika %s" -#: lib/profilelist.php:182 +#: lib/profilelist.php:182 lib/profilelist.php:180 msgid "(none)" -msgstr "" +msgstr "(brak)" -#: lib/publicgroupnav.php:76 +#: lib/publicgroupnav.php:76 lib/publicgroupnav.php:78 msgid "Public" msgstr "Publiczny" -#: lib/publicgroupnav.php:80 +#: lib/publicgroupnav.php:80 lib/publicgroupnav.php:82 msgid "User groups" -msgstr "" +msgstr "Grupy użytkowników" #: lib/publicgroupnav.php:82 lib/publicgroupnav.php:83 +#: lib/publicgroupnav.php:84 lib/publicgroupnav.php:85 msgid "Recent tags" -msgstr "" +msgstr "Ostatnie znaczniki" -#: lib/publicgroupnav.php:86 +#: lib/publicgroupnav.php:86 lib/publicgroupnav.php:88 msgid "Featured" -msgstr "" +msgstr "Znane" -#: lib/publicgroupnav.php:90 -#, fuzzy +#: lib/publicgroupnav.php:90 lib/publicgroupnav.php:92 msgid "Popular" -msgstr "Szukaj ludzi" +msgstr "Popularne" #: lib/searchgroupnav.php:82 -#, fuzzy msgid "Notice" -msgstr "Wpisy" +msgstr "Wpis" #: lib/searchgroupnav.php:85 msgid "Find groups on this site" -msgstr "" +msgstr "Znajdź grupy na tej stronie" #: lib/section.php:89 msgid "Untitled section" -msgstr "" +msgstr "Sekcja bez nazwy" #: lib/subgroupnav.php:81 -#, fuzzy, php-format +#, php-format msgid "People %s subscribes to" -msgstr "Zdalna subskrypcja" +msgstr "Osoby %s zasubskrybowane do" #: lib/subgroupnav.php:89 -#, fuzzy, php-format +#, php-format msgid "People subscribed to %s" -msgstr "Zdalna subskrypcja" +msgstr "Osoby zasubskrybowane do %s" #: lib/subgroupnav.php:97 #, php-format msgid "Groups %s is a member of" -msgstr "" +msgstr "Grupy %s są członkiem" #: lib/subgroupnav.php:104 #, php-format msgid "Invite friends and colleagues to join you on %s" -msgstr "" +msgstr "Zaproś przyjaciół i kolegów do dołączenia do Ciebie na %s" #: lib/subs.php:53 -#, fuzzy msgid "User has blocked you." -msgstr "Użytkownik nie ma profilu." +msgstr "Użytkownik zablokował Cię." #: lib/subscribeform.php:115 lib/subscribeform.php:139 -#, fuzzy msgid "Subscribe to this user" -msgstr "Subskrypcja uwierzytelniona" +msgstr "Zasubskrybuj tego użytkownika" #: lib/tagcloudsection.php:56 msgid "None" -msgstr "" +msgstr "Brak" #: lib/topposterssection.php:74 msgid "Top posters" -msgstr "" +msgstr "Najczęściej wysyłający wpisy" #: lib/unblockform.php:120 lib/unblockform.php:150 -#, fuzzy msgid "Unblock this user" -msgstr "Brak takiego użytkownika." +msgstr "Odblokuj tego użytkownika" #: lib/unblockform.php:150 msgid "Unblock" -msgstr "" +msgstr "Odblokuj" #: lib/unsubscribeform.php:113 lib/unsubscribeform.php:137 msgid "Unsubscribe from this user" +msgstr "Zrezygnuj z subskrypcji tego użytkownika" + +#: actions/all.php:77 +#, php-format +msgid "Feed for friends of %s (RSS 1.0)" +msgstr "Kanał dla znajomych użytkownika %s (RSS 1.0)" + +#: actions/all.php:82 +#, php-format +msgid "Feed for friends of %s (RSS 2.0)" +msgstr "Kanał dla znajomych użytkownika %s (RSS 2.0)" + +#: actions/all.php:87 +#, php-format +msgid "Feed for friends of %s (Atom)" +msgstr "Kanał dla znajomych użytkownika %s (Atom)" + +#: actions/all.php:112 +msgid "You and friends" +msgstr "Ty i przyjaciele" + +#: actions/avatarsettings.php:78 +#, php-format +msgid "You can upload your personal avatar. The maximum file size is %s." +msgstr "Można wysłać swój osobisty awatar. Maksymalny rozmiar pliku to %s." + +#: actions/avatarsettings.php:373 +msgid "Avatar deleted." +msgstr "Usunięto awatar." + +#: actions/block.php:129 +msgid "" +"Are you sure you want to block this user? Afterwards, they will be " +"unsubscribed from you, unable to subscribe to you in the future, and you " +"will not be notified of any @-replies from them." msgstr "" +"Jesteś pewny, że chcesz zablokować tego użytkownika. Po tym jego subskrypcja " +"do Ciebie zostanie usunięta, nie będzie mógł Cię zasubskrybować w " +"przyszłości i nie będziesz powiadamiany o żadnych odpowiedziach @ od niego." -#, fuzzy -#~ msgid "Delete my account" -#~ msgstr "Załóż nowe konto" +#: actions/deletenotice.php:73 +msgid "" +"You are about to permanently delete a notice. Once this is done, it cannot " +"be undone." +msgstr "" +"Za chwilę wpis zostanie trwale usunięty. Kiedy to się stanie, to już się nie " +"odstanie." -#~ msgid "Couldn't confirm email." -#~ msgstr "Nie można potwierdzić e-maila." +#: actions/deletenotice.php:127 +msgid "There was a problem with your session token. Try again, please." +msgstr "Wystąpił problem z tokenem sesji. Spróbuj ponownie." -#~ msgid "Email address" -#~ msgstr "Adres e-mailowy" +#: actions/emailsettings.php:168 +msgid "Send me email when someone sends me an \"@-reply\"." +msgstr "Wyślij mi wiadomość e-mail, kiedy ktoś wyśle mi odpowiedź \"@\"." -#~ msgid "Error inserting notice" -#~ msgstr "Błąd przy wprowadzaniu wpisu" +#: actions/facebookhome.php:193 +#, php-format +msgid "" +"If you would like the %s app to automatically update your Facebook status " +"with your latest notice, you need to give it permission." +msgstr "" +"Jeśli chcesz, aby aplikacja %s automatycznie aktualizowała status na " +"Facebook najnowszym wpisem, musisz dać jej pozwolenie." -#~ msgid "" -#~ "If you've forgotten or lost your password, you can get a new one sent " -#~ "the email address you have stored in your account." -#~ msgstr "" -#~ "Jeśli Twoje hasło gdzieś się zapodziało lub zostało zapomniane to możesz " -#~ "wygenerować nowe. Zostanie ono wysłane na adres e-mailowy skojarzony z " -#~ "Twoim kontem." +#: actions/facebookhome.php:217 +#, php-format +msgid "Okay, do it!" +msgstr "OK, zrób to!" + +#: actions/facebooksettings.php:124 +#, php-format +msgid "" +"If you would like %s to automatically update your Facebook status with your " +"latest notice, you need to give it permission." +msgstr "" +"Jeśli chcesz, aby %s automatycznie aktualizowało status na Facebook " +"najnowszym wpisem, musisz dać mu pozwolenie." + +#: actions/grouplogo.php:155 +#, php-format +msgid "" +"You can upload a logo image for your group. The maximum file size is %s." +msgstr "Można wysłać obraz logo grupy. Maksymalny rozmiar pliku to %s." + +#: actions/grouplogo.php:367 +msgid "Pick a square area of the image to be the logo." +msgstr "Wybierz kwadratowy obszar obrazu, który będzie logo." + +#: actions/grouprss.php:136 +#, php-format +msgid "Microblog by %s group" +msgstr "Mikroblog grupy %s" + +#: actions/groupsearch.php:57 +#, php-format +msgid "" +"Search for groups on %%site.name%% by their name, location, or description. " +"Separate the terms by spaces; they must be 3 characters or more." +msgstr "" +"Znajdź grupy na %%site.name%% według ich nazwy, położenia lub opisu. Oddziel " +"terminy spacjami; muszą mieć trzy znaki lub więcej." + +#: actions/groups.php:90 +#, php-format +msgid "" +"%%%%site.name%%%% groups let you find and talk with people of similar " +"interests. After you join a group you can send messages to all other members " +"using the syntax \"!groupname\". Don't see a group you like? Try [searching " +"for one](%%%%action.groupsearch%%%%) or [start your own!](%%%%action.newgroup" +"%%%%)" +msgstr "" +"Grupy %%%%site.name%%%% umożliwiają znalezienie i rozmawianie z osobami o " +"podobnych zainteresowaniach. Po dołączeniu do grupy można wysyłać wiadomości " +"do wszystkich członków używając składni \"!nazwagrupy\". Nie widzisz grupy, " +"która Cię interesuje? Spróbuj ją [znaleźć](%%%%action.groupsearch%%%%) lub " +"[założyć własną!](%%%%action.newgroup%%%%)" + +#: actions/newmessage.php:102 +msgid "Only logged-in users can send direct messages." +msgstr "Tylko zalogowani użytkownicy mogą wysyłać bezpośrednie wiadomości." + +#: actions/noticesearch.php:91 +#, php-format +msgid "Search results for \"%s\" on %s" +msgstr "Wyniki wyszukiwania dla \"%s\" na %s" + +#: actions/openidlogin.php:66 +#, php-format +msgid "" +"For security reasons, please re-login with your [OpenID](%%doc.openid%%) " +"before changing your settings." +msgstr "" +"Z powodów bezpieczeństwa przed zmienianiem ustawień zaloguj się ponownie za " +"pomocą identyfikatora [OpenID](%%doc.openid%%)." + +#: actions/public.php:125 +msgid "Public Stream Feed (RSS 1.0)" +msgstr "Kanał publicznego strumienia (RSS 1.0)" + +#: actions/public.php:130 +msgid "Public Stream Feed (RSS 2.0)" +msgstr "Kanał publicznego strumienia (RSS 2.0)" + +#: actions/public.php:135 +msgid "Public Stream Feed (Atom)" +msgstr "Kanał publicznego strumienia (Atom)" + +#: actions/public.php:210 +#, php-format +msgid "" +"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" +"blogging) service based on the Free Software [Laconica](http://laconi.ca/) " +"tool. [Join now](%%action.register%%) to share notices about yourself with " +"friends, family, and colleagues! ([Read more](%%doc.help%%))" +msgstr "" +"To jest %%site.name%%, usługa [mikroblogowania](http://en.wikipedia.org/wiki/" +"Micro-blogging) oparta na wolnym narzędziu [Laconica](http://laconi.ca/). " +"[Dołącz teraz](%%action.register%%), aby dzielić się wpisami o sobie z " +"przyjaciółmi, rodziną i kolegami! ([Przeczytaj więcej](%%doc.help%%))" + +#: actions/register.php:286 +#, php-format +msgid "" +"With this form you can create a new account. You can then post notices and " +"link up to friends and colleagues. (Have an [OpenID](http://openid.net/)? " +"Try our [OpenID registration](%%action.openidlogin%%)!)" +msgstr "" +"Za pomocą tego formularza można utworzyć nowe konto. Można wtedy wysyłać " +"wpisy i połączyć się z przyjaciółmi i kolegami. (Posiadasz identyfikator " +"[OpenID](http://openid.net/)? Wypróbuj [rejestracji OpenID](%%action." +"openidlogin%%)!)" + +#: actions/register.php:432 +msgid "Creative Commons Attribution 3.0" +msgstr "Creative Commons Uznanie Autorstwa 3.0" + +#: actions/register.php:433 +msgid "" +" except this private data: password, email address, IM address, and phone " +"number." +msgstr "" +" poza tymi prywatnymi danymi: hasło, adres e-mail, adres komunikatora i " +"numer telefonu." + +#: actions/showgroup.php:378 +msgid "Created" +msgstr "Utworzono" + +#: actions/showgroup.php:393 +#, php-format +msgid "" +"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[Laconica](http://laconi.ca/) tool. Its members share short messages about " +"their life and interests. [Join now](%%%%action.register%%%%) to become part " +"of this group and many more! ([Read more](%%%%doc.help%%%%))" +msgstr "" +"**%s** jest grupą użytkowników na %%%%site.name%%%%, usłudze " +"[mikroblogowania](http://en.wikipedia.org/wiki/Micro-blogging) opartej na " +"wolnym narzędziu [Laconica](http://laconi.ca/). Jej członkowie dzielą się " +"krótkimi wiadomościami o swoim życiu i zainteresowaniach. [Dołącz teraz](%%%%" +"action.register%%%%), aby stać się częścią tej grupy i wiele więcej! " +"([Przeczytaj więcej](%%%%doc.help%%%%))" + +#: actions/showstream.php:147 +msgid "Your profile" +msgstr "Twój profil" + +#: actions/showstream.php:149 +#, php-format +msgid "%s's profile" +msgstr "Profil użytkownika %s" + +#: actions/showstream.php:163 +#, php-format +msgid "Notice feed for %s (RSS 1.0)" +msgstr "Kanał wpisów dla %s (RSS 1.0)" + +#: actions/showstream.php:170 +#, php-format +msgid "Notice feed for %s (RSS 2.0)" +msgstr "Kanał wpisów dla %s (RSS 2.0)" + +#: actions/showstream.php:177 +#, php-format +msgid "Notice feed for %s (Atom)" +msgstr "Kanał wpisów dla %s (Atom)" + +#: actions/showstream.php:182 +#, php-format +msgid "FOAF for %s" +msgstr "FOAF dla %s" + +#: actions/showstream.php:237 +msgid "Edit Avatar" +msgstr "Edytuj awatar" + +#: actions/showstream.php:316 +msgid "Edit profile settings" +msgstr "Edytuj ustawienia profilu" + +#: actions/showstream.php:317 +msgid "Edit" +msgstr "Edytuj" + +#: actions/showstream.php:542 +#, php-format +msgid "" +"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[Laconica](http://laconi.ca/) tool. [Join now](%%%%action.register%%%%) to " +"follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))" +msgstr "" +"**%s** posiada konto na %%%%site.name%%%%, usłudze [mikroblogowania](http://" +"en.wikipedia.org/wiki/Micro-blogging) opartej na wolnym narzędziu [Laconica]" +"(http://laconi.ca/). [Dołącz teraz](%%%%action.register%%%%), aby obserwować " +"wpisy użytkownika **%s** i wiele więcej! ([Przeczytaj więcej](%%%%doc.help%%%" +"%))" + +#: actions/smssettings.php:335 +msgid "" +"A confirmation code was sent to the phone number you added. Check your phone " +"for the code and instructions on how to use it." +msgstr "" +"Kod potwierdzający został wysłany na dodany numer telefonu. Sprawdź telefon, " +"czy otrzymałeś kod i instrukcje jak go użyć." + +#: actions/twitapifavorites.php:171 lib/mail.php:556 +#, php-format +msgid "" +"%1$s just added your notice from %2$s as one of their favorites.\n" +"\n" +"In case you forgot, you can see the text of your notice here:\n" +"\n" +"%3$s\n" +"\n" +"You can see the list of %1$s's favorites here:\n" +"\n" +"%4$s\n" +"\n" +"Faithfully yours,\n" +"%5$s\n" +msgstr "" +"%1$s właśnie dodał Twój wpis z %2$s jako jeden ze swoich ulubionych.\n" +"\n" +"Jeśli go zapomniałeś, tutaj możesz zobaczyć tekst wpisu:\n" +"\n" +"%3$s\n" +"\n" +"Tutaj możesz zobaczyć listę ulubionych wpisów użytkownika %1$s:\n" +"\n" +"%4$s\n" +"\n" +"Z poważaniem,\n" +"%5$s\n" + +#: actions/twitapistatuses.php:124 +msgid "No such user!" +msgstr "Nie ma takiego użytkownika!" + +#: actions/twittersettings.php:72 +msgid "" +"Add your Twitter account to automatically send your notices to Twitter, and " +"subscribe to Twitter friends already here." +msgstr "" +"Dodaj konto Twittera, aby automatycznie wysyłać wpisy do Twittera i " +"zasubskrybować przyjaciół z Twittera, którzy już tu są." + +#: actions/twittersettings.php:345 +#, php-format +msgid "Unable to retrieve account information For \"%s\" from Twitter." +msgstr "Nie można pobrać informacji o koncie dla \"%s\" z Twittera." + +#: actions/userauthorization.php:86 +msgid "" +"Please check these details to make sure that you want to subscribe to this " +"user's notices. If you didn't just ask to subscribe to someone's notices, " +"click \"Reject\"." +msgstr "" +"Sprawdź te szczegóły, aby upewnić się, czy na pewno chcesz zasubskrybować " +"wpisy tego użytkownika. Jeżeli nie prosiłeś o subskrypcję czyichś wpisów, " +"naciśnij \"Odrzuć\"." + +#: actions/usergroups.php:131 +msgid "Search for more groups" +msgstr "Znajdź więcej grup" + +#: classes/Notice.php:138 +msgid "" +"Too many duplicate messages too quickly; take a breather and post again in a " +"few minutes." +msgstr "" +"Za dużo takich samych wiadomości w za krótkim czasie, weź głęboki oddech i " +"wyślij ponownie za kilka minut." + +#: lib/action.php:406 +msgid "Connect to SMS, Twitter" +msgstr "Połącz z SMS, Twitterem" + +#: lib/action.php:671 +msgid "Badge" +msgstr "Odznaka" + +#: lib/command.php:113 +#, php-format +msgid "" +"Subscriptions: %1$s\n" +"Subscribers: %2$s\n" +"Notices: %3$s" +msgstr "" +"Subskrypcje: %1$s\n" +"Subskrybenci: %2$s\n" +"Wpisy: %3$s" + +#: lib/command.php:392 +msgid "" +"Commands:\n" +"on - turn on notifications\n" +"off - turn off notifications\n" +"help - show this help\n" +"follow - subscribe to user\n" +"leave - unsubscribe from user\n" +"d - direct message to user\n" +"get - get last notice from user\n" +"whois - get profile info on user\n" +"fav - add user's last notice as a 'fave'\n" +"stats - get your stats\n" +"stop - same as 'off'\n" +"quit - same as 'off'\n" +"sub - same as 'follow'\n" +"unsub - same as 'leave'\n" +"last - same as 'get'\n" +"on - not yet implemented.\n" +"off - not yet implemented.\n" +"nudge - not yet implemented.\n" +"invite - not yet implemented.\n" +"track - not yet implemented.\n" +"untrack - not yet implemented.\n" +"track off - not yet implemented.\n" +"untrack all - not yet implemented.\n" +"tracks - not yet implemented.\n" +"tracking - not yet implemented.\n" +msgstr "" +"Polecenia:\n" +"on - włącza powiadomienia\n" +"off - wyłącza powiadomienia\n" +"help - wyświetla tę pomoc\n" +"follow - subskrybuje użytkownika\n" +"leave - rezygnuje z subskrypcji użytkownika\n" +"d - bezpośrednia wiadomość do użytkownika\n" +"get - uzyskuje ostatni wpis użytkownika\n" +"whois - uzyskuje informacje o profilu użytkownika\n" +"fav - dodaje ostatni wpis użytkownika jako \"ulubiony\"\n" +"stats - uzyskuje Twoje statystyki\n" +"stop - to samo co \"off\"\n" +"quit - to samo co \"off\"\n" +"sub - to samo co \"follow\"\n" +"unsub - to samo co \"leave\"\n" +"last - to samo co \"get\"\n" +"on - jeszcze nie zaimplementowano.\n" +"off - jeszcze nie zaimplementowano.\n" +"nudge - jeszcze nie zaimplementowano.\n" +"invite - jeszcze nie zaimplementowano.\n" +"track - jeszcze nie zaimplementowano.\n" +"untrack - jeszcze nie zaimplementowano.\n" +"track off - jeszcze nie zaimplementowano.\n" +"untrack all - jeszcze nie zaimplementowano.\n" +"tracks - jeszcze nie zaimplementowano.\n" +"tracking - jeszcze nie zaimplementowano.\n" + +#: lib/dberroraction.php:60 +msgid "Database error" +msgstr "Błąd bazy danych" + +#: lib/facebookaction.php:271 +#, php-format +msgid "" +"To use the %s Facebook Application you need to login with your username and " +"password. Don't have a username yet? " +msgstr "" +"Aby użyć aplikacji Facebook %s, musisz się zalogować za pomocą nazwy " +"użytkownika i hasła. Nie masz jeszcze nazwy użytkownika? " + +#: lib/feed.php:85 +msgid "RSS 1.0" +msgstr "RSS 1.0" + +#: lib/feed.php:87 +msgid "RSS 2.0" +msgstr "RSS 2.0" + +#: lib/feed.php:89 +msgid "Atom" +msgstr "Atom" + +#: lib/feed.php:91 +msgid "FOAF" +msgstr "FOAF" + +#: lib/imagefile.php:75 +#, php-format +msgid "That file is too big. The maximum file size is %d." +msgstr "Ten plik jest za duży. Maksymalny rozmiar pliku to %d." + +#: lib/mail.php:175 +#, php-format +msgid "" +"Hey, %s.\n" +"\n" +"Someone just entered this email address on %s.\n" +"\n" +"If it was you, and you want to confirm your entry, use the URL below:\n" +"\n" +"\t%s\n" +"\n" +"If not, just ignore this message.\n" +"\n" +"Thanks for your time, \n" +"%s\n" +msgstr "" +"Cześć, %s.\n" +"\n" +"Ktoś właśnie podał ten adres e-mail na %s.\n" +"\n" +"Jeśli to byłeś Ty, i chcesz potwierdzić swoje wejście, użyj poniższego " +"adresu URL:\n" +"\n" +"\t%s\n" +"\n" +"Jeśli to nie ty, po prostu zignoruj tę wiadomość.\n" +"\n" +"Dziękujemy za Twój czas, \n" +"%s\n" + +#: lib/mail.php:241 +#, php-format +msgid "" +"%1$s is now listening to your notices on %2$s.\n" +"\n" +"\t%3$s\n" +"\n" +"%4$s%5$s%6$s\n" +"Faithfully yours,\n" +"%7$s.\n" +"\n" +"----\n" +"Change your email address or notification options at %8$s\n" +msgstr "" +"Użytkownik %1$s obserwuje teraz Twoje wpisy na %2$s.\n" +"\n" +"\t%3$s\n" +"\n" +"%4$s%5$s%6$s\n" +"Z poważaniem,\n" +"%7$s.\n" +"\n" +"----\n" +"Zmień adres e-mail lub opcje powiadamiania na %8$s\n" + +#: lib/mail.php:466 +#, php-format +msgid "" +"%1$s (%2$s) is wondering what you are up to these days and is inviting you " +"to post some news.\n" +"\n" +"So let's hear from you :)\n" +"\n" +"%3$s\n" +"\n" +"Don't reply to this email; it won't get to them.\n" +"\n" +"With kind regards,\n" +"%4$s\n" +msgstr "" +"Użytkownik %1$s (%2$s) zastanawia się, co się z Tobą dzieje w ostatnich " +"dniach i zaprasza Cię do wysłania jakichś aktualności.\n" +"\n" +"Tak więc do usłyszenia. :)\n" +"\n" +"%3$s\n" +"\n" +"Nie odpowiadaj na tę wiadomość e-mail, nie dotrze ona do nich.\n" +"\n" +"Z poważaniem,\n" +"%4$s\n" + +#: lib/mail.php:513 +#, php-format +msgid "" +"%1$s (%2$s) sent you a private message:\n" +"\n" +"------------------------------------------------------\n" +"%3$s\n" +"------------------------------------------------------\n" +"\n" +"You can reply to their message here:\n" +"\n" +"%4$s\n" +"\n" +"Don't reply to this email; it won't get to them.\n" +"\n" +"With kind regards,\n" +"%5$s\n" +msgstr "" +"Użytkownik %1$s (%2$s) wysłał Ci prywatną wiadomość:\n" +"\n" +"------------------------------------------------------\n" +"%3$s\n" +"------------------------------------------------------\n" +"\n" +"Tutaj możesz na nią odpowiedzieć:\n" +"\n" +"%4$s\n" +"\n" +"Nie odpowiadaj na tę wiadomość e-mail, nie dotrze ona do nich.\n" +"\n" +"Z poważaniem,\n" +"%5$s\n" + +#: lib/mail.php:598 +#, php-format +msgid "%s sent a notice to your attention" +msgstr "Użytkownik %s wysłał wpis wymagający Twojej uwagi" + +#: lib/mail.php:600 +#, php-format +msgid "" +"%1$s just sent a notice to your attention (an '@-reply') on %2$s.\n" +"\n" +"The notice is here:\n" +"\n" +"\t%3$s\n" +"\n" +"It reads:\n" +"\n" +"\t%4$s\n" +"\n" +"You can reply back here:\n" +"\n" +"\t%5$s\n" +"\n" +"The list of all @-replies for you here:\n" +"\n" +"%6$s\n" +"\n" +"Faithfully yours,\n" +"%2$s\n" +"\n" +"P.S. You can turn off these email notifications here: %7$s\n" +msgstr "" +"Użytkownik %1$s właśnie wysłał wpis wymagający Twojej uwagi (odpowiedź \"@" +"\") na %2$s.\n" +"\n" +"Twój wpis znajduje się tutaj:\n" +"\n" +"\t%3$s\n" +"\n" +"Zawiera tekst:\n" +"\n" +"\t%4$s\n" +"\n" +"Tutaj możesz odpowiedzieć:\n" +"\n" +"\t%5$s\n" +"\n" +"Lista wszystkich odpowiedzi \"@\" do Ciebie znajduje się tutaj:\n" +"\n" +"%6$s\n" +"\n" +"Z poważaniem,\n" +"%2$s\n" +"\n" +"PS Tutaj możesz wyłączyć te powiadomienia przez e-mail: %7$s\n" + +#: lib/searchaction.php:122 +msgid "Search site" +msgstr "Znajdź stronę" + +#: lib/section.php:106 +msgid "More..." +msgstr "Więcej..." From f934cf2ac0cab8be26e5108c51fe0dcbef5b8517 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 12 Apr 2009 15:34:38 -0400 Subject: [PATCH 336/503] Update XML generation and list of actions in public XRDS Updated the XML generation calls and list of actions in the public XRDS document. --- actions/publicxrds.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actions/publicxrds.php b/actions/publicxrds.php index aad59d779e..2c52f12468 100644 --- a/actions/publicxrds.php +++ b/actions/publicxrds.php @@ -51,7 +51,7 @@ class PublicxrdsAction extends Action { /** * Is read only? - * + * * @return boolean true */ function isReadOnly() @@ -61,7 +61,7 @@ class PublicxrdsAction extends Action /** * Class handler. - * + * * @param array $args array of arguments * * @return nothing @@ -70,24 +70,24 @@ class PublicxrdsAction extends Action { parent::handle($args); header('Content-Type: application/xrds+xml'); - common_start_xml(); + $this->startXML(); $this->elementStart('XRDS', array('xmlns' => 'xri://$xrds')); $this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', 'xmlns:simple' => 'http://xrds-simple.net/core/1.0', 'version' => '2.0')); $this->element('Type', null, 'xri://$xrds*simple'); - foreach (array('finishopenidlogin', 'finishaddopenid', 'finishimmediate') as $finish) { + foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) { $this->showService(Auth_OpenID_RP_RETURN_TO_URL_TYPE, common_local_url($finish)); } $this->elementEnd('XRD'); $this->elementEnd('XRDS'); - common_end_xml(); + $this->endXML(); } /** * Show service. - * + * * @param string $type XRDS type * @param string $uri URI * @param array $params type parameters, null by default From a9461356b809cb27bd5e509678830791608f5e5b Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 12 Apr 2009 20:30:14 +0000 Subject: [PATCH 337/503] Created Design page for users to customize the way their profile pages look by changing the background image and picking a colour palette for text. --- actions/designsettings.php | 172 ++++++++++++++++++++++++++++++++++ lib/accountsettingsaction.php | 3 + lib/router.php | 2 +- 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 actions/designsettings.php diff --git a/actions/designsettings.php b/actions/designsettings.php new file mode 100644 index 0000000000..87afdac8ad --- /dev/null +++ b/actions/designsettings.php @@ -0,0 +1,172 @@ +. + * + * @category Settings + * @package Laconica + * @author Sarven Capadisli + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/accountsettingsaction.php'; + + + +class DesignsettingsAction extends AccountSettingsAction +{ + /** + * Title of the page + * + * @return string Title of the page + */ + + function title() + { + return _('Profile design'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + + function getInstructions() + { + return _('Customize the way your profile looks with a background image and a colour palette of your choice.'); + } + + /** + * Content area of the page + * + * Shows a form for changing the password + * + * @return void + */ + + function showContent() + { + $user = common_current_user(); + $this->elementStart('form', array('method' => 'POST', + 'id' => 'form_settings_design', + 'class' => 'form_settings', + 'action' => + common_local_url('designsettings'))); + $this->elementStart('fieldset'); +// $this->element('legend', null, _('Design settings')); + $this->hidden('token', common_session_token()); + + $this->elementStart('fieldset', array('id' => 'settings_design_background-image')); + $this->element('legend', null, _('Change background image')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->element('p', null, _('Upload background image')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->elementStart('fieldset', array('id' => 'settings_design_colour')); + $this->element('legend', null, _('Change colours')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->element('p', null, _('Edit text colours')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + + $this->submit('save', _('Save')); + + $this->elementEnd('fieldset'); + $this->elementEnd('form'); + } + + /** + * Handle a post + * + * Validate input and save changes. Reload the form with a success + * or error message. + * + * @return void + */ + + function handlePost() + { + /* + // CSRF protection + + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->showForm(_('There was a problem with your session token. '. + 'Try again, please.')); + return; + } + + $user = common_current_user(); + assert(!is_null($user)); // should already be checked + + // FIXME: scrub input + + $newpassword = $this->arg('newpassword'); + $confirm = $this->arg('confirm'); + + # Some validation + + if (strlen($newpassword) < 6) { + $this->showForm(_('Password must be 6 or more characters.')); + return; + } else if (0 != strcmp($newpassword, $confirm)) { + $this->showForm(_('Passwords don\'t match.')); + return; + } + + if ($user->password) { + $oldpassword = $this->arg('oldpassword'); + + if (!common_check_user($user->nickname, $oldpassword)) { + $this->showForm(_('Incorrect old password')); + return; + } + } + + $original = clone($user); + + $user->password = common_munge_password($newpassword, $user->id); + + $val = $user->validate(); + if ($val !== true) { + $this->showForm(_('Error saving user; invalid.')); + return; + } + + if (!$user->update($original)) { + $this->serverError(_('Can\'t save new password.')); + return; + } + + $this->showForm(_('Password saved.'), true); + */ + } +} diff --git a/lib/accountsettingsaction.php b/lib/accountsettingsaction.php index 46090b8c19..86800d2a36 100644 --- a/lib/accountsettingsaction.php +++ b/lib/accountsettingsaction.php @@ -115,6 +115,9 @@ class AccountSettingsNav extends Widget 'openidsettings' => array(_('OpenID'), _('Add or remove OpenIDs')), + 'designsettings' => + array(_('Design'), + _('Design your profile')), 'othersettings' => array(_('Other'), _('Other options'))); diff --git a/lib/router.php b/lib/router.php index 060253eb54..5e16f34191 100644 --- a/lib/router.php +++ b/lib/router.php @@ -131,7 +131,7 @@ class Router // settings foreach (array('profile', 'avatar', 'password', 'openid', 'im', - 'email', 'sms', 'twitter', 'other') as $s) { + 'email', 'sms', 'twitter', 'design', 'other') as $s) { $m->connect('settings/'.$s, array('action' => $s.'settings')); } From e9e7671d5fbb6e3e66c8629ac78246cd9a47ceda Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 12 Apr 2009 21:40:29 +0000 Subject: [PATCH 338/503] Updated markup for entity_profile on Authorize subscription page. --- actions/userauthorization.php | 87 ++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/actions/userauthorization.php b/actions/userauthorization.php index 8723848c7b..c8c679dcd0 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -97,47 +97,90 @@ class UserauthorizationAction extends Action $location = $params['omb_listenee_location']; $avatar = $params['omb_listenee_avatar']; - $this->elementStart('div', 'profile'); + $this->elementStart('div', array('class' => 'profile')); + $this->elementStart('div', 'entity_profile vcard'); + $this->elementStart('a', array('href' => $profile, + 'class' => 'url')); if ($avatar) { $this->element('img', array('src' => $avatar, - 'class' => 'avatar', + 'class' => 'photo avatar', 'width' => AVATAR_PROFILE_SIZE, 'height' => AVATAR_PROFILE_SIZE, 'alt' => $nickname)); } - $this->element('a', array('href' => $profile, - 'class' => 'external profile nickname'), - $nickname); + $hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname'; + $this->elementStart('span', $hasFN); + $this->raw($nickname); + $this->elementEnd('span'); + $this->elementEnd('a'); + if (!is_null($fullname)) { - $this->elementStart('div', 'fullname'); - if (!is_null($homepage)) { - $this->element('a', array('href' => $homepage), - $fullname); - } else { - $this->text($fullname); - } - $this->elementEnd('div'); + $this->elementStart('dl', 'entity_fn'); + $this->elementStart('dd'); + $this->elementStart('span', 'fn'); + $this->raw($fullname); + $this->elementEnd('span'); + $this->elementEnd('dd'); + $this->elementEnd('dl'); } if (!is_null($location)) { - $this->element('div', 'location', $location); + $this->elementStart('dl', 'entity_location'); + $this->element('dt', null, _('Location')); + $this->elementStart('dd', 'label'); + $this->raw($location); + $this->elementEnd('dd'); + $this->elementEnd('dl'); } + + if (!is_null($homepage)) { + $this->elementStart('dl', 'entity_url'); + $this->element('dt', null, _('URL')); + $this->elementStart('dd'); + $this->elementStart('a', array('href' => $homepage, + 'class' => 'url')); + $this->raw($homepage); + $this->elementEnd('a'); + $this->elementEnd('dd'); + $this->elementEnd('dl'); + } + if (!is_null($bio)) { - $this->element('div', 'bio', $bio); + $this->elementStart('dl', 'entity_note'); + $this->element('dt', null, _('Note')); + $this->elementStart('dd', 'note'); + $this->raw($bio); + $this->elementEnd('dd'); + $this->elementEnd('dl'); + } + + if (!is_null($license)) { + $this->elementStart('dl', 'entity_license'); + $this->element('dt', null, _('License')); + $this->elementStart('dd', 'license'); + $this->element('a', array('href' => $license, + 'class' => 'license'), + $license); + $this->elementEnd('dd'); + $this->elementEnd('dl'); } - $this->elementStart('div', 'license'); - $this->element('a', array('href' => $license, - 'class' => 'license'), - $license); - $this->elementEnd('div'); $this->elementEnd('div'); + + $this->elementStart('div', 'entity_actions'); + $this->elementStart('ul'); + $this->elementStart('li', 'entity_subscribe'); $this->elementStart('form', array('method' => 'post', 'id' => 'userauthorization', 'name' => 'userauthorization', 'action' => common_local_url('userauthorization'))); $this->hidden('token', common_session_token()); - $this->submit('accept', _('Accept')); - $this->submit('reject', _('Reject')); + + $this->submit('accept', _('Accept'), 'submit accept', null, _('Subscribe to this user')); + $this->submit('reject', _('Reject'), 'submit reject', null, _('Reject this subscription')); $this->elementEnd('form'); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->elementEnd('div'); + $this->elementEnd('div'); } function sendAuthorization() From 7a00dc749da9bcc003aad5f90b0346ba164680df Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 12 Apr 2009 21:50:14 +0000 Subject: [PATCH 339/503] Updated styles for the Authrization subscription form inputs --- actions/userauthorization.php | 1 + theme/base/css/display.css | 6 ++++-- theme/default/css/display.css | 3 ++- theme/identica/css/display.css | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/actions/userauthorization.php b/actions/userauthorization.php index c8c679dcd0..1680191495 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -170,6 +170,7 @@ class UserauthorizationAction extends Action $this->elementStart('li', 'entity_subscribe'); $this->elementStart('form', array('method' => 'post', 'id' => 'userauthorization', + 'class' => 'form_user_authorization', 'name' => 'userauthorization', 'action' => common_local_url('userauthorization'))); $this->hidden('token', common_session_token()); diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 3b4a2a4b30..9c0980ec6d 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -607,7 +607,9 @@ border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; } - +.entity_actions .accept { +margin-bottom:18px; +} .entity_tags ul { list-style-type:none; @@ -1158,4 +1160,4 @@ display:none; } .guide { clear:both; -} \ No newline at end of file +} diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 42e29374f1..5523a331e2 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -164,7 +164,8 @@ background-color:#A9BF4F; color:#fff; } .form_user_unsubscribe input.submit, -.form_group_leave input.submit { +.form_group_leave input.submit, +.form_user_authorization input.reject { background-color:#97BFD1; } diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 8edb005a68..e4f582b6c1 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -164,7 +164,8 @@ background-color:#9BB43E; color:#fff; } .form_user_unsubscribe input.submit, -.form_group_leave input.submit { +.form_group_leave input.submit, +.form_user_authorization input.reject { background-color:#87B4C8; } From d62f69e5928e94e1ca15a469ba31cdfef6a80016 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 03:05:00 +0000 Subject: [PATCH 340/503] Removing h1 from display in Profile page due to duplicate visibility of fn and nickname. --- theme/base/css/display.css | 1 + 1 file changed, 1 insertion(+) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 9c0980ec6d..00f7c0e8fe 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -29,6 +29,7 @@ h1 { font-size:1.4em; margin-bottom:18px; } +#showstream h1 { display:none; } h2 { font-size:1.3em; } h3 { font-size:1.2em; } h4 { font-size:1.1em; } From 765ea6966775271f90eb74c0adcb1b03d4dc7776 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 03:10:05 +0000 Subject: [PATCH 341/503] Updated Cloudy theme's base style for Authorize subscription input accept --- theme/cloudy/base/css/display.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/theme/cloudy/base/css/display.css b/theme/cloudy/base/css/display.css index 8d34e8442b..2f78e9729e 100644 --- a/theme/cloudy/base/css/display.css +++ b/theme/cloudy/base/css/display.css @@ -30,6 +30,7 @@ h1 { font-size:1.4em; margin-bottom:18px; } +#showstream h1 { display:none; } h2 { font-size:1.3em; } h3 { font-size:1.2em; } h4 { font-size:1.1em; } @@ -630,7 +631,9 @@ border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; } - +.entity_actions .accept { +margin-bottom:18px; +} .entity_tags ul { list-style-type:none; From 4a8c23fe32cf0f3c556dfa062dcffedd77fd5857 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 03:49:37 +0000 Subject: [PATCH 342/503] Updated path for jCrop --- actions/avatarsettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/avatarsettings.php b/actions/avatarsettings.php index c2bb35a395..60f69b6850 100644 --- a/actions/avatarsettings.php +++ b/actions/avatarsettings.php @@ -383,7 +383,7 @@ class AvatarsettingsAction extends AccountSettingsAction { parent::showStylesheets(); $jcropStyle = - common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION); + common_path('theme/default/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION); $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', From ed3d68435f042ff6bc212022058310255db0e1bd Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 05:39:23 +0000 Subject: [PATCH 343/503] Using farbtastic jQuery plugin to select design colours. --- actions/designsettings.php | 61 +++++- js/farbtastic/LICENSE.txt | 341 +++++++++++++++++++++++++++++ js/farbtastic/farbtastic.go.js | 10 + js/farbtastic/farbtastic.js | 329 ++++++++++++++++++++++++++++ js/farbtastic/marker.png | Bin 0 -> 652 bytes js/farbtastic/mask.png | Bin 0 -> 2020 bytes js/farbtastic/wheel.png | Bin 0 -> 11733 bytes theme/default/base/css/display.css | 9 + 8 files changed, 747 insertions(+), 3 deletions(-) create mode 100644 js/farbtastic/LICENSE.txt create mode 100644 js/farbtastic/farbtastic.go.js create mode 100644 js/farbtastic/farbtastic.js create mode 100755 js/farbtastic/marker.png create mode 100644 js/farbtastic/mask.png create mode 100644 js/farbtastic/wheel.png diff --git a/actions/designsettings.php b/actions/designsettings.php index 87afdac8ad..05293f7126 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -88,19 +88,34 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementEnd('ul'); $this->elementEnd('fieldset'); - $this->elementStart('fieldset', array('id' => 'settings_design_colour')); + $this->elementStart('fieldset', array('id' => 'settings_design_color')); $this->element('legend', null, _('Change colours')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); - $this->element('p', null, _('Edit text colours')); + $this->input('color-1', _('Background color'), '#F0F2F5', null); $this->elementEnd('li'); - $this->elementEnd('ul'); + $this->elementStart('li'); + $this->input('color-2', _('Content background color'), '#FFFFFF', null); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('color-3', _('Sidebar background color'), '#CEE1E9', null); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('color-4', _('Text color'), '#000000', null); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('color-5', _('Link color'), '#002E6E', null); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->element('div', array('id' => 'color-picker')); $this->elementEnd('fieldset'); + $this->submit('save', _('Save')); $this->elementEnd('fieldset'); $this->elementEnd('form'); + } /** @@ -169,4 +184,44 @@ class DesignsettingsAction extends AccountSettingsAction $this->showForm(_('Password saved.'), true); */ } + + + /** + * Add the jCrop stylesheet + * + * @return void + */ + + function showStylesheets() + { + parent::showStylesheets(); + $farbtasticStyle = + common_path('theme/default/base/css/farbtastic.css?version='.LACONICA_VERSION); + + $this->element('link', array('rel' => 'stylesheet', + 'type' => 'text/css', + 'href' => $farbtasticStyle, + 'media' => 'screen, projection, tv')); + } + + /** + * Add the jCrop scripts + * + * @return void + */ + + function showScripts() + { + parent::showScripts(); + +// if ($this->mode == 'crop') { + $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); + $farbtasticGo = common_path('js/farbtastic/farbtastic.go.js'); + + $this->element('script', array('type' => 'text/javascript', + 'src' => $farbtasticPack)); + $this->element('script', array('type' => 'text/javascript', + 'src' => $farbtasticGo)); +// } + } } diff --git a/js/farbtastic/LICENSE.txt b/js/farbtastic/LICENSE.txt new file mode 100644 index 0000000000..5a3cc209ad --- /dev/null +++ b/js/farbtastic/LICENSE.txt @@ -0,0 +1,341 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js new file mode 100644 index 0000000000..21a1530bca --- /dev/null +++ b/js/farbtastic/farbtastic.go.js @@ -0,0 +1,10 @@ +$(document).ready(function() { + var f = $.farbtastic('#color-picker'); + var colors = $('#settings_design_color input'); + + colors + .each(function () { f.linkTo(this); }) + .focus(function() { + f.linkTo(this); + }); +}); diff --git a/js/farbtastic/farbtastic.js b/js/farbtastic/farbtastic.js new file mode 100644 index 0000000000..24a377803c --- /dev/null +++ b/js/farbtastic/farbtastic.js @@ -0,0 +1,329 @@ +// $Id: farbtastic.js,v 1.2 2007/01/08 22:53:01 unconed Exp $ +// Farbtastic 1.2 + +jQuery.fn.farbtastic = function (callback) { + $.farbtastic(this, callback); + return this; +}; + +jQuery.farbtastic = function (container, callback) { + var container = $(container).get(0); + return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback)); +} + +jQuery._farbtastic = function (container, callback) { + // Store farbtastic object + var fb = this; + + // Insert markup + $(container).html('

'); + var e = $('.farbtastic', container); + fb.wheel = $('.wheel', container).get(0); + // Dimensions + fb.radius = 84; + fb.square = 100; + fb.width = 194; + + // Fix background PNGs in IE6 + if (navigator.appVersion.match(/MSIE [0-6]\./)) { + $('*', e).each(function () { + if (this.currentStyle.backgroundImage != 'none') { + var image = this.currentStyle.backgroundImage; + image = this.currentStyle.backgroundImage.substring(5, image.length - 2); + $(this).css({ + 'backgroundImage': 'none', + 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')" + }); + } + }); + } + + /** + * Link to the given element(s) or callback. + */ + fb.linkTo = function (callback) { + // Unbind previous nodes + if (typeof fb.callback == 'object') { + $(fb.callback).unbind('keyup', fb.updateValue); + } + + // Reset color + fb.color = null; + + // Bind callback or elements + if (typeof callback == 'function') { + fb.callback = callback; + } + else if (typeof callback == 'object' || typeof callback == 'string') { + fb.callback = $(callback); + fb.callback.bind('keyup', fb.updateValue); + if (fb.callback.get(0).value) { + fb.setColor(fb.callback.get(0).value); + } + } + return this; + } + fb.updateValue = function (event) { + if (this.value && this.value != fb.color) { + fb.setColor(this.value); + } + } + + /** + * Change color with HTML syntax #123456 + */ + fb.setColor = function (color) { + var unpack = fb.unpack(color); + if (fb.color != color && unpack) { + fb.color = color; + fb.rgb = unpack; + fb.hsl = fb.RGBToHSL(fb.rgb); + fb.updateDisplay(); + } + return this; + } + + /** + * Change color with HSL triplet [0..1, 0..1, 0..1] + */ + fb.setHSL = function (hsl) { + fb.hsl = hsl; + fb.rgb = fb.HSLToRGB(hsl); + fb.color = fb.pack(fb.rgb); + fb.updateDisplay(); + return this; + } + + ///////////////////////////////////////////////////// + + /** + * Retrieve the coordinates of the given event relative to the center + * of the widget. + */ + fb.widgetCoords = function (event) { + var x, y; + var el = event.target || event.srcElement; + var reference = fb.wheel; + + if (typeof event.offsetX != 'undefined') { + // Use offset coordinates and find common offsetParent + var pos = { x: event.offsetX, y: event.offsetY }; + + // Send the coordinates upwards through the offsetParent chain. + var e = el; + while (e) { + e.mouseX = pos.x; + e.mouseY = pos.y; + pos.x += e.offsetLeft; + pos.y += e.offsetTop; + e = e.offsetParent; + } + + // Look for the coordinates starting from the wheel widget. + var e = reference; + var offset = { x: 0, y: 0 } + while (e) { + if (typeof e.mouseX != 'undefined') { + x = e.mouseX - offset.x; + y = e.mouseY - offset.y; + break; + } + offset.x += e.offsetLeft; + offset.y += e.offsetTop; + e = e.offsetParent; + } + + // Reset stored coordinates + e = el; + while (e) { + e.mouseX = undefined; + e.mouseY = undefined; + e = e.offsetParent; + } + } + else { + // Use absolute coordinates + var pos = fb.absolutePosition(reference); + x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x; + y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y; + } + // Subtract distance to middle + return { x: x - fb.width / 2, y: y - fb.width / 2 }; + } + + /** + * Mousedown handler + */ + fb.mousedown = function (event) { + // Capture mouse + if (!document.dragging) { + $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup); + document.dragging = true; + } + + // Check which area is being dragged + var pos = fb.widgetCoords(event); + fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square; + + // Process + fb.mousemove(event); + return false; + } + + /** + * Mousemove handler + */ + fb.mousemove = function (event) { + // Get coordinates relative to color picker center + var pos = fb.widgetCoords(event); + + // Set new HSL parameters + if (fb.circleDrag) { + var hue = Math.atan2(pos.x, -pos.y) / 6.28; + if (hue < 0) hue += 1; + fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]); + } + else { + var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5)); + var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5)); + fb.setHSL([fb.hsl[0], sat, lum]); + } + return false; + } + + /** + * Mouseup handler + */ + fb.mouseup = function () { + // Uncapture mouse + $(document).unbind('mousemove', fb.mousemove); + $(document).unbind('mouseup', fb.mouseup); + document.dragging = false; + } + + /** + * Update the markers and styles + */ + fb.updateDisplay = function () { + // Markers + var angle = fb.hsl[0] * 6.28; + $('.h-marker', e).css({ + left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px', + top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px' + }); + + $('.sl-marker', e).css({ + left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px', + top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px' + }); + + // Saturation/Luminance gradient + $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5]))); + + // Linked elements or callback + if (typeof fb.callback == 'object') { + // Set background/foreground color + $(fb.callback).css({ + backgroundColor: fb.color, + color: fb.hsl[2] > 0.5 ? '#000' : '#fff' + }); + + // Change linked value + $(fb.callback).each(function() { + if (this.value && this.value != fb.color) { + this.value = fb.color; + } + }); + } + else if (typeof fb.callback == 'function') { + fb.callback.call(fb, fb.color); + } + } + + /** + * Get absolute position of element + */ + fb.absolutePosition = function (el) { + var r = { x: el.offsetLeft, y: el.offsetTop }; + // Resolve relative to offsetParent + if (el.offsetParent) { + var tmp = fb.absolutePosition(el.offsetParent); + r.x += tmp.x; + r.y += tmp.y; + } + return r; + }; + + /* Various color utility functions */ + fb.pack = function (rgb) { + var r = Math.round(rgb[0] * 255); + var g = Math.round(rgb[1] * 255); + var b = Math.round(rgb[2] * 255); + return '#' + (r < 16 ? '0' : '') + r.toString(16) + + (g < 16 ? '0' : '') + g.toString(16) + + (b < 16 ? '0' : '') + b.toString(16); + } + + fb.unpack = function (color) { + if (color.length == 7) { + return [parseInt('0x' + color.substring(1, 3)) / 255, + parseInt('0x' + color.substring(3, 5)) / 255, + parseInt('0x' + color.substring(5, 7)) / 255]; + } + else if (color.length == 4) { + return [parseInt('0x' + color.substring(1, 2)) / 15, + parseInt('0x' + color.substring(2, 3)) / 15, + parseInt('0x' + color.substring(3, 4)) / 15]; + } + } + + fb.HSLToRGB = function (hsl) { + var m1, m2, r, g, b; + var h = hsl[0], s = hsl[1], l = hsl[2]; + m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s; + m1 = l * 2 - m2; + return [this.hueToRGB(m1, m2, h+0.33333), + this.hueToRGB(m1, m2, h), + this.hueToRGB(m1, m2, h-0.33333)]; + } + + fb.hueToRGB = function (m1, m2, h) { + h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + if (h * 2 < 1) return m2; + if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6; + return m1; + } + + fb.RGBToHSL = function (rgb) { + var min, max, delta, h, s, l; + var r = rgb[0], g = rgb[1], b = rgb[2]; + min = Math.min(r, Math.min(g, b)); + max = Math.max(r, Math.max(g, b)); + delta = max - min; + l = (min + max) / 2; + s = 0; + if (l > 0 && l < 1) { + s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l)); + } + h = 0; + if (delta > 0) { + if (max == r && max != g) h += (g - b) / delta; + if (max == g && max != b) h += (2 + (b - r) / delta); + if (max == b && max != r) h += (4 + (r - g) / delta); + h /= 6; + } + return [h, s, l]; + } + + // Install mousedown handler (the others are set on the document on-demand) + $('*', e).mousedown(fb.mousedown); + + // Init color + fb.setColor('#000000'); + + // Set linked elements/callback + if (callback) { + fb.linkTo(callback); + } +} \ No newline at end of file diff --git a/js/farbtastic/marker.png b/js/farbtastic/marker.png new file mode 100755 index 0000000000000000000000000000000000000000..3929bbb51dd950802bb9bf12a397d1ac1e140610 GIT binary patch literal 652 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 literal 0 HcmV?d00001 diff --git a/theme/default/base/css/display.css b/theme/default/base/css/display.css index d8c7badb35..6c7ae20ea9 100644 --- a/theme/default/base/css/display.css +++ b/theme/default/base/css/display.css @@ -1149,6 +1149,15 @@ clear:both; margin-bottom:0; } +#form_settings_design #settings_design_color .form_data, +#form_settings_design #color-picker { +float:left; +} +#form_settings_design #settings_design_color .form_data { +width:400px; +margin-right:28px; +} + .instructions ul { list-style-position:inside; } From ffa00073509a275df2605ca39d110c0c3fcf2dee Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 16:40:51 +0000 Subject: [PATCH 344/503] Ticket 1419. Added config option to set site to private. --- config.php.sample | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.php.sample b/config.php.sample index 0a01552fec..e70d9ab46e 100644 --- a/config.php.sample +++ b/config.php.sample @@ -30,6 +30,8 @@ $config['site']['path'] = 'laconica'; #$config['site']['closed'] = true; #Only allow registration for people invited by another user #$config['site']['inviteonly'] = true; +#Make the site invisible to non-logged-in users +#$config['site']['private'] = true; # If you want logging sent to a file instead of syslog #$config['site']['logfile'] = '/tmp/laconica.log'; From d4f9f2c69bb9cba7aa2ff67a2b75d106f1bd1607 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 17:26:12 +0000 Subject: [PATCH 345/503] Moved layout styles to base stylesheet. --- theme/base/css/display.css | 4 ++++ theme/default/css/display.css | 4 ---- theme/identica/css/display.css | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 00f7c0e8fe..2fb1c007fc 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -921,6 +921,10 @@ padding:0; } +#usergroups #new_group { +float: left; +margin-right: 2em; +} #new_group, #group_search { margin-bottom:18px; } diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 5523a331e2..c5d6946108 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -232,10 +232,6 @@ background-color:#fcfcfc; #new_group a { background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; } -#usergroups #new_group { -float: left; -margin-right: 2em; -} .pagination .nav_prev a, .pagination .nav_next a { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index e4f582b6c1..c32b6269d0 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -232,10 +232,6 @@ background-color:#fcfcfc; #new_group a { background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; } -#usergroups #new_group { -float: left; -margin-right: 2em; -} .pagination .nav_prev a, .pagination .nav_next a { From d4291f1f9b5e01d670d8bce599df936b9513b262 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 17:29:15 +0000 Subject: [PATCH 346/503] Moved Cloudy's layout styles in skin to theme. --- theme/cloudy/base/css/display.css | 4 ++++ theme/cloudy/skin/default/css/display.css | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/theme/cloudy/base/css/display.css b/theme/cloudy/base/css/display.css index 2f78e9729e..c71a59ef2c 100644 --- a/theme/cloudy/base/css/display.css +++ b/theme/cloudy/base/css/display.css @@ -957,6 +957,10 @@ padding:0; } +#usergroups #new_group { +float: left; +margin-right: 2em; +} #new_group, #group_search { margin-bottom:18px; } diff --git a/theme/cloudy/skin/default/css/display.css b/theme/cloudy/skin/default/css/display.css index 055e4fca20..b30ca9d0da 100644 --- a/theme/cloudy/skin/default/css/display.css +++ b/theme/cloudy/skin/default/css/display.css @@ -233,10 +233,6 @@ background-color:#fcfcfc; #new_group a { background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; } -#usergroups #new_group { -float: left; -margin-right: 2em; -} .pagination .nav_prev a, .pagination .nav_next a { From 4f966709e680048fa4c2631c33250bbaaff6cc71 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 13 Apr 2009 17:30:25 +0000 Subject: [PATCH 347/503] Added farbtastic's default stylesheet --- theme/default/base/css/farbtastic.css | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 theme/default/base/css/farbtastic.css diff --git a/theme/default/base/css/farbtastic.css b/theme/default/base/css/farbtastic.css new file mode 100644 index 0000000000..3b8fec58f8 --- /dev/null +++ b/theme/default/base/css/farbtastic.css @@ -0,0 +1,32 @@ +.farbtastic { + position: relative; +} +.farbtastic * { + position: absolute; + cursor: crosshair; +} +.farbtastic, .farbtastic .wheel { + width: 195px; + height: 195px; +} +.farbtastic .color, .farbtastic .overlay { + top: 47px; + left: 47px; + width: 101px; + height: 101px; +} +.farbtastic .wheel { + background: url(../../../../js/farbtastic/wheel.png) no-repeat; + width: 195px; + height: 195px; +} +.farbtastic .overlay { + background: url(../../../../js/farbtastic/mask.png) no-repeat; +} +.farbtastic .marker { + width: 17px; + height: 17px; + margin: -8px 0 0 -8px; + overflow: hidden; + background: url(../../../../js/farbtastic/marker.png) no-repeat; +} From e9e75fc9d5f44b2ffe10602a3bd183cccb7da4ec Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 13 Apr 2009 15:49:26 -0400 Subject: [PATCH 348/503] isReadOnly() now takes arguments Add an array of arguments to isReadOnly() method of actions, to let them change their results depending on what actions are called. Primarily used by the 'api' action. Ideally in the future that will be multiple actions. But this might still be useful. --- actions/all.php | 2 +- actions/api.php | 13 ++++++------- actions/avatarbynickname.php | 2 +- actions/doc.php | 2 +- actions/favorited.php | 2 +- actions/featured.php | 2 +- actions/foaf.php | 2 +- actions/groupbyid.php | 2 +- actions/groupmembers.php | 2 +- actions/grouprss.php | 2 +- actions/groups.php | 2 +- actions/invite.php | 2 +- actions/login.php | 2 +- actions/logout.php | 2 +- actions/microsummary.php | 2 +- actions/noticesearchrss.php | 2 +- actions/nudge.php | 2 +- actions/opensearch.php | 2 +- actions/public.php | 2 +- actions/publicrss.php | 2 +- actions/publictagcloud.php | 2 +- actions/publicxrds.php | 2 +- actions/replies.php | 2 +- actions/repliesrss.php | 2 +- actions/requesttoken.php | 2 +- actions/showfavorites.php | 2 +- actions/showgroup.php | 2 +- actions/showmessage.php | 2 +- actions/shownotice.php | 2 +- actions/showstream.php | 2 +- actions/subscribers.php | 2 +- actions/sup.php | 2 +- actions/tag.php | 2 +- actions/tagrss.php | 2 +- actions/twitapisearchjson.php | 2 +- actions/userbyid.php | 2 +- actions/usergroups.php | 2 +- actions/userrss.php | 2 +- actions/xrds.php | 2 +- index.php | 2 +- lib/action.php | 5 ++++- lib/error.php | 2 +- lib/galleryaction.php | 2 +- lib/peoplesearchresults.php | 2 +- lib/personal.php | 2 +- lib/searchaction.php | 2 +- 46 files changed, 54 insertions(+), 52 deletions(-) diff --git a/actions/all.php b/actions/all.php index f5bbfe2e39..69890a70ca 100644 --- a/actions/all.php +++ b/actions/all.php @@ -25,7 +25,7 @@ require_once INSTALLDIR.'/lib/feedlist.php'; class AllAction extends ProfileAction { - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/api.php b/actions/api.php index c18d551b6d..e40a187987 100644 --- a/actions/api.php +++ b/actions/api.php @@ -134,8 +134,8 @@ class ApiAction extends Action 'favorites/favorites'); $fullname = "$this->api_action/$this->api_method"; - - // If the site is "private", all API methods except laconica/config + + // If the site is "private", all API methods except laconica/config // need authentication if (common_config('site', 'private')) { return $fullname != 'laconica/config' || false; @@ -180,11 +180,11 @@ class ApiAction extends Action } } - function isReadOnly() + function isReadOnly($args)($args) { - # NOTE: before handle(), can't use $this->arg - $apiaction = $_REQUEST['apiaction']; - $method = $_REQUEST['method']; + $apiaction = $args['apiaction']; + $method = $args['method']; + list($cmdtext, $fmt) = explode('.', $method); static $write_methods = array( @@ -207,5 +207,4 @@ class ApiAction extends Action return false; } - } diff --git a/actions/avatarbynickname.php b/actions/avatarbynickname.php index ca58c96537..e92a993722 100644 --- a/actions/avatarbynickname.php +++ b/actions/avatarbynickname.php @@ -98,7 +98,7 @@ class AvatarbynicknameAction extends Action common_redirect($url, 302); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/doc.php b/actions/doc.php index ebffb7c154..e6508030b6 100644 --- a/actions/doc.php +++ b/actions/doc.php @@ -108,7 +108,7 @@ class DocAction extends Action return ucfirst($this->title); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/favorited.php b/actions/favorited.php index 09ab1216a6..c902d80f53 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -85,7 +85,7 @@ class FavoritedAction extends Action * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/featured.php b/actions/featured.php index 86fd3f374a..79eba2aa67 100644 --- a/actions/featured.php +++ b/actions/featured.php @@ -50,7 +50,7 @@ class FeaturedAction extends Action { var $page = null; - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/foaf.php b/actions/foaf.php index 416935b1b7..2d5b78d123 100644 --- a/actions/foaf.php +++ b/actions/foaf.php @@ -25,7 +25,7 @@ define('BOTH', 0); class FoafAction extends Action { - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/groupbyid.php b/actions/groupbyid.php index 678119a945..7d327d56cc 100644 --- a/actions/groupbyid.php +++ b/actions/groupbyid.php @@ -59,7 +59,7 @@ class GroupbyidAction extends Action * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 00f43a9f55..a90108e4d4 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -48,7 +48,7 @@ class GroupmembersAction extends Action { var $page = null; - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/grouprss.php b/actions/grouprss.php index de76a59600..a9a2eef877 100644 --- a/actions/grouprss.php +++ b/actions/grouprss.php @@ -57,7 +57,7 @@ class groupRssAction extends Rss10Action * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/groups.php b/actions/groups.php index 39dc2232bc..26b52a5fcd 100644 --- a/actions/groups.php +++ b/actions/groups.php @@ -51,7 +51,7 @@ class GroupsAction extends Action var $page = null; var $profile = null; - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/invite.php b/actions/invite.php index df6e3b7147..7e52cdbcc6 100644 --- a/actions/invite.php +++ b/actions/invite.php @@ -27,7 +27,7 @@ class InviteAction extends Action var $subbed = null; var $sent = null; - function isReadOnly() + function isReadOnly($args) { return false; } diff --git a/actions/login.php b/actions/login.php index 59c6b4874b..50de83f6fb 100644 --- a/actions/login.php +++ b/actions/login.php @@ -55,7 +55,7 @@ class LoginAction extends Action * @return boolean false */ - function isReadOnly() + function isReadOnly($args) { return false; } diff --git a/actions/logout.php b/actions/logout.php index b7681be382..9f3bfe2470 100644 --- a/actions/logout.php +++ b/actions/logout.php @@ -52,7 +52,7 @@ class LogoutAction extends Action * * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return false; } diff --git a/actions/microsummary.php b/actions/microsummary.php index 065a2e0eba..0b408ec953 100644 --- a/actions/microsummary.php +++ b/actions/microsummary.php @@ -74,7 +74,7 @@ class MicrosummaryAction extends Action print $user->nickname . ': ' . $notice->content; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/noticesearchrss.php b/actions/noticesearchrss.php index ba5276d06e..f6da969ee4 100644 --- a/actions/noticesearchrss.php +++ b/actions/noticesearchrss.php @@ -92,7 +92,7 @@ class NoticesearchrssAction extends Rss10Action return null; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/nudge.php b/actions/nudge.php index b4e5e01dd8..c23d3e6435 100644 --- a/actions/nudge.php +++ b/actions/nudge.php @@ -124,7 +124,7 @@ class NudgeAction extends Action } } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/opensearch.php b/actions/opensearch.php index 2eb8183066..d1f4895ce4 100644 --- a/actions/opensearch.php +++ b/actions/opensearch.php @@ -84,7 +84,7 @@ class OpensearchAction extends Action $this->endXML(); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/public.php b/actions/public.php index 5a380de9a8..27153f1315 100644 --- a/actions/public.php +++ b/actions/public.php @@ -56,7 +56,7 @@ class PublicAction extends Action var $page = null; - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/publicrss.php b/actions/publicrss.php index 77e26e0f4c..bc52f29522 100644 --- a/actions/publicrss.php +++ b/actions/publicrss.php @@ -102,7 +102,7 @@ class PublicrssAction extends Rss10Action // nop } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index 855cfed9b5..e9f33d58b6 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -47,7 +47,7 @@ define('TAGS_PER_PAGE', 100); class PublictagcloudAction extends Action { - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/publicxrds.php b/actions/publicxrds.php index 2c52f12468..283a932ca5 100644 --- a/actions/publicxrds.php +++ b/actions/publicxrds.php @@ -54,7 +54,7 @@ class PublicxrdsAction extends Action * * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/replies.php b/actions/replies.php index 2769cb4227..eac4d0a3ae 100644 --- a/actions/replies.php +++ b/actions/replies.php @@ -196,7 +196,7 @@ class RepliesAction extends Action $this->elementEnd('div'); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/repliesrss.php b/actions/repliesrss.php index 985318bf16..2017c43094 100644 --- a/actions/repliesrss.php +++ b/actions/repliesrss.php @@ -83,7 +83,7 @@ class RepliesrssAction extends Rss10Action return ($avatar) ? $avatar->url : null; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/requesttoken.php b/actions/requesttoken.php index ca253b97aa..fb577fdd57 100644 --- a/actions/requesttoken.php +++ b/actions/requesttoken.php @@ -52,7 +52,7 @@ class RequesttokenAction extends Action * * @return boolean false */ - function isReadOnly() + function isReadOnly($args) { return false; } diff --git a/actions/showfavorites.php b/actions/showfavorites.php index 4d43495054..e8cf1cb01c 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -58,7 +58,7 @@ class ShowfavoritesAction extends Action * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/showgroup.php b/actions/showgroup.php index 79445851f9..7e86a79f15 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -60,7 +60,7 @@ class ShowgroupAction extends Action * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/showmessage.php b/actions/showmessage.php index 572a71739a..4fcaadbe83 100644 --- a/actions/showmessage.php +++ b/actions/showmessage.php @@ -177,7 +177,7 @@ class ShowmessageAction extends MailboxAction return ''; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/shownotice.php b/actions/shownotice.php index ccae49bb3e..2c469c9dee 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -106,7 +106,7 @@ class ShownoticeAction extends Action * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/showstream.php b/actions/showstream.php index ce237dae22..c1a2c337a0 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -56,7 +56,7 @@ require_once INSTALLDIR.'/lib/feedlist.php'; class ShowstreamAction extends ProfileAction { - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/subscribers.php b/actions/subscribers.php index 7ebb54d33d..d91a7d4fd3 100644 --- a/actions/subscribers.php +++ b/actions/subscribers.php @@ -130,7 +130,7 @@ class SubscribersList extends ProfileList $bf->show(); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/sup.php b/actions/sup.php index 246b3299d3..691153d6a3 100644 --- a/actions/sup.php +++ b/actions/sup.php @@ -79,7 +79,7 @@ class SupAction extends Action return $updates; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/tag.php b/actions/tag.php index c413bf8c34..7f82c2a581 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -87,7 +87,7 @@ class TagAction extends Action $this->page, 'tag', array('tag' => $this->tag)); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/tagrss.php b/actions/tagrss.php index a77fa12c98..83cf3afe2f 100644 --- a/actions/tagrss.php +++ b/actions/tagrss.php @@ -65,7 +65,7 @@ class TagrssAction extends Rss10Action return $c; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/twitapisearchjson.php b/actions/twitapisearchjson.php index 0f9f523a14..b0e3be687c 100644 --- a/actions/twitapisearchjson.php +++ b/actions/twitapisearchjson.php @@ -142,7 +142,7 @@ class TwitapisearchjsonAction extends TwitterapiAction * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/userbyid.php b/actions/userbyid.php index 1e30d1aac3..4a985fcd72 100644 --- a/actions/userbyid.php +++ b/actions/userbyid.php @@ -50,7 +50,7 @@ class UserbyidAction extends Action * * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/usergroups.php b/actions/usergroups.php index 06b2334bf5..e3088dcbd8 100644 --- a/actions/usergroups.php +++ b/actions/usergroups.php @@ -52,7 +52,7 @@ class UsergroupsAction extends Action var $page = null; var $profile = null; - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/userrss.php b/actions/userrss.php index d3bf352d8d..5861d9ee36 100644 --- a/actions/userrss.php +++ b/actions/userrss.php @@ -96,7 +96,7 @@ class UserrssAction extends Rss10Action parent::initRss($limit); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/actions/xrds.php b/actions/xrds.php index 0758318037..1335b6b806 100644 --- a/actions/xrds.php +++ b/actions/xrds.php @@ -52,7 +52,7 @@ class XrdsAction extends Action * * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/index.php b/index.php index e83d08c13e..e24bde9179 100644 --- a/index.php +++ b/index.php @@ -128,7 +128,7 @@ function main() // XXX: find somewhere for this little block to live - if (common_config('db', 'mirror') && $action_obj->isReadOnly()) { + if (common_config('db', 'mirror') && $action_obj->isReadOnly($args)) { if (is_array(common_config('db', 'mirror'))) { // "load balancing", ha ha $arr = common_config('db', 'mirror'); diff --git a/lib/action.php b/lib/action.php index cc98d4445a..6735492467 100644 --- a/lib/action.php +++ b/lib/action.php @@ -791,9 +791,12 @@ class Action extends HTMLOutputter // lawsuit * * MAY override * + * @param array $args other arguments + * * @return boolean is read only action? */ - function isReadOnly() + + function isReadOnly($args)($args) { return false; } diff --git a/lib/error.php b/lib/error.php index 526d9f81be..282682133a 100644 --- a/lib/error.php +++ b/lib/error.php @@ -93,7 +93,7 @@ class ErrorAction extends Action return $this->message; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 8e21d7393b..0484918ce2 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -76,7 +76,7 @@ class GalleryAction extends Action return true; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/peoplesearchresults.php b/lib/peoplesearchresults.php index f8ab7cf3b6..d3f8408525 100644 --- a/lib/peoplesearchresults.php +++ b/lib/peoplesearchresults.php @@ -67,7 +67,7 @@ class PeopleSearchResults extends ProfileList return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/personal.php b/lib/personal.php index e46350c630..f92732375b 100644 --- a/lib/personal.php +++ b/lib/personal.php @@ -47,7 +47,7 @@ class PersonalAction extends Action var $user = null; - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/searchaction.php b/lib/searchaction.php index e7ad4affda..e74450e11f 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -51,7 +51,7 @@ class SearchAction extends Action * * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } From 4c9be4d566c4d4b6e846935cbabd951f5d59259d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 13 Apr 2009 15:52:15 -0400 Subject: [PATCH 349/503] typo in api.php --- actions/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/api.php b/actions/api.php index e40a187987..d2f0a2eff0 100644 --- a/actions/api.php +++ b/actions/api.php @@ -180,7 +180,7 @@ class ApiAction extends Action } } - function isReadOnly($args)($args) + function isReadOnly($args) { $apiaction = $args['apiaction']; $method = $args['method']; From 4684d34713a8057387750bc52802d0c0475ec926 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 13 Apr 2009 15:54:16 -0400 Subject: [PATCH 350/503] typo in lib action --- lib/action.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/action.php b/lib/action.php index 6735492467..1ba062812a 100644 --- a/lib/action.php +++ b/lib/action.php @@ -796,7 +796,7 @@ class Action extends HTMLOutputter // lawsuit * @return boolean is read only action? */ - function isReadOnly($args)($args) + function isReadOnly($args) { return false; } From 01695dc3465c8198123c254816f9a93a35b6c773 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 13 Apr 2009 15:03:34 -0700 Subject: [PATCH 351/503] Fix bad dates in API's JSON search results --- lib/jsonsearchresultslist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jsonsearchresultslist.php b/lib/jsonsearchresultslist.php index 0cdcf0c516..f786c20a80 100644 --- a/lib/jsonsearchresultslist.php +++ b/lib/jsonsearchresultslist.php @@ -232,7 +232,7 @@ class ResultItem $this->profile_image_url = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE); - $this->created_at = date('r', $this->notice->created); + $this->created_at = common_date_rfc2822($this->notice->created); } /** From ad5dd9030bf919dba95e1ca066acef71a2d3e6bd Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 13 Apr 2009 19:19:26 -0700 Subject: [PATCH 352/503] Add option to Twitter settings for importing Friends Timeline --- actions/twittersettings.php | 21 +++++++++++++++------ classes/Foreign_link.php | 10 ++++++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/actions/twittersettings.php b/actions/twittersettings.php index 45725d3ff4..580d9ecf76 100644 --- a/actions/twittersettings.php +++ b/actions/twittersettings.php @@ -138,7 +138,7 @@ class TwittersettingsAction extends ConnectSettingsAction $this->elementStart('ul', 'form_data'); $this->elementStart('li'); - $this->checkbox('noticesync', + $this->checkbox('noticesend', _('Automatically send my notices to Twitter.'), ($flink) ? ($flink->noticesync & FOREIGN_NOTICE_SEND) : @@ -158,6 +158,13 @@ class TwittersettingsAction extends ConnectSettingsAction ($flink->friendsync & FOREIGN_FRIEND_RECV) : false); $this->elementEnd('li'); + $this->elementStart('li'); + $this->checkbox('noticerecv', + _('Import my Friends Timeline.'), + ($flink) ? + ($flink->noticesync & FOREIGN_NOTICE_RECV) : + false); + $this->elementEnd('li'); $this->elementEnd('ul'); if ($flink) { @@ -261,7 +268,7 @@ class TwittersettingsAction extends ConnectSettingsAction 'alt' => ($other->fullname) ? $other->fullname : $other->nickname)); - + $this->element('span', 'fn nickname', $other->nickname); $this->elementEnd('a'); $this->elementEnd('li'); @@ -320,7 +327,8 @@ class TwittersettingsAction extends ConnectSettingsAction { $screen_name = $this->trimmed('twitter_username'); $password = $this->trimmed('twitter_password'); - $noticesync = $this->boolean('noticesync'); + $noticesend = $this->boolean('noticesend'); + $noticerecv = $this->boolean('noticerecv'); $replysync = $this->boolean('replysync'); $friendsync = $this->boolean('friendsync'); @@ -363,7 +371,7 @@ class TwittersettingsAction extends ConnectSettingsAction $flink->credentials = $password; $flink->created = common_sql_now(); - $flink->set_flags($noticesync, $replysync, $friendsync); + $flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync); $flink_id = $flink->insert(); @@ -419,7 +427,8 @@ class TwittersettingsAction extends ConnectSettingsAction function savePreferences() { - $noticesync = $this->boolean('noticesync'); + $noticesend = $this->boolean('noticesend'); + $noticerecv = $this->boolean('noticerecv'); $friendsync = $this->boolean('friendsync'); $replysync = $this->boolean('replysync'); @@ -448,7 +457,7 @@ class TwittersettingsAction extends ConnectSettingsAction $original = clone($flink); - $flink->set_flags($noticesync, $replysync, $friendsync); + $flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync); $result = $flink->update($original); diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php index afc0e21804..5d9c82a85a 100644 --- a/classes/Foreign_link.php +++ b/classes/Foreign_link.php @@ -57,13 +57,19 @@ class Foreign_link extends Memcached_DataObject return null; } - function set_flags($noticesync, $replysync, $friendsync) + function set_flags($noticesend, $noticerecv, $replysync, $friendsync) { - if ($noticesync) { + if ($noticesend) { $this->noticesync |= FOREIGN_NOTICE_SEND; } else { $this->noticesync &= ~FOREIGN_NOTICE_SEND; } + + if ($noticerecv) { + $this->noticesync |= FOREIGN_NOTICE_RECV; + } else { + $this->noticesync &= ~FOREIGN_NOTICE_RECV; + } if ($replysync) { $this->noticesync |= FOREIGN_NOTICE_SEND_REPLY; From 9f2e2e4b2c1b428a1892c57c7194fbc5ede5b125 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 14 Apr 2009 11:50:59 -0700 Subject: [PATCH 353/503] Notice sources: Fixed Nambu, added Tricklepost and sorted the list. --- db/notice_source.sql | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/db/notice_source.sql b/db/notice_source.sql index ac23f14aa1..d5124e223a 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -1,29 +1,28 @@ INSERT INTO notice_source (code, name, url, created) VALUES - ('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()), - ('Facebook','Facebook','http://apps.facebook.com/identica/', now()), - ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()), - ('HelloTxt','HelloTxt','http://hellotxt.com/', now()), - ('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()), - ('LaTwit','LaTwit','http://latwit.mac65.com/', now()), - ('Nambu','Nambu','http://www.nambu.com/', now()), - ('Pikchur','Pikchur','http://www.pikchur.com/', now()), - ('Ping.fm','Ping.fm','http://ping.fm/', now()), - ('Twidge','Twidge','http://software.complete.org/twidge', now()), - ('Updating.Me','Updating.Me','http://updating.me/', now()), + ('adium', 'Adium', 'http://www.adiumx.com/', now()), ('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()), ('bti','bti','http://gregkh.github.com/bti/', now()), ('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()), ('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()), + ('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()), + ('Facebook','Facebook','http://apps.facebook.com/identica/', now()), + ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()), + ('HelloTxt','HelloTxt','http://hellotxt.com/', now()), ('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()), ('identichat','identichat','http://identichat.prosody.im/', now()), + ('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()), ('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()), + ('LaTwit','LaTwit','http://latwit.mac65.com/', now()), ('maisha', 'Maisha', 'http://maisha.grango.org/', now()), ('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()), ('Mobidentica', 'Mobidentica', 'http://www.substanceofcode.com/software/mobidentica/', now()), ('moconica','Moconica','http://moconica.com/', now()), + ('nambu','Nambu','http://www.nambu.com/', now()), ('peoplebrowsr', 'PeopleBrowsr', 'http://www.peoplebrowsr.com/', now()), + ('Pikchur','Pikchur','http://www.pikchur.com/', now()), + ('Ping.fm','Ping.fm','http://ping.fm/', now()), ('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()), ('posty','Posty','http://spreadingfunkyness.com/posty/', now()), ('royalewithcheese','Royale With Cheese','http://p.hellyeah.org/', now()), @@ -35,9 +34,11 @@ VALUES ('tarpipe','tarpipe','http://tarpipe.com/', now()), ('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()), ('tr.im','tr.im','http://tr.im/', now()), + ('triklepost', 'Tricklepost', 'http://github.com/zcopley/tricklepost/tree/master', now()), ('tweenky','Tweenky','http://beta.tweenky.com/', now()), ('twhirl','Twhirl','http://www.twhirl.org/', now()), ('twibble','twibble','http://www.twibble.de/', now()), + ('Twidge','Twidge','http://software.complete.org/twidge', now()), ('twidge','Twidge','http://software.complete.org/twidge', now()), ('twidroid','twidroid','http://www.twidroid.com/', now()), ('twittelator','Twittelator','http://www.stone.com/iPhone/Twittelator/', now()), @@ -47,6 +48,6 @@ VALUES ('twittertools','Twitter Tools','http://wordpress.org/extend/plugins/twitter-tools/', now()), ('twitux','Twitux','http://live.gnome.org/DanielMorales/Twitux', now()), ('twitvim','TwitVim','http://vim.sourceforge.net/scripts/script.php?script_id=2204', now()), + ('Updating.Me','Updating.Me','http://updating.me/', now()), ('urfastr','urfastr','http://urfastr.net/', now()), - ('adium', 'Adium', 'http://www.adiumx.com/', now()), ('yatca','Yatca','http://www.yatca.com/', now()); From b1940bcb7b028b993b26cd3c36f4fdbbc79c96e6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 14 Apr 2009 16:01:02 -0400 Subject: [PATCH 354/503] escape slash in regexp --- plugins/LinkbackPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 56a26176b1..881ead99ec 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -99,7 +99,7 @@ class LinkbackPlugin extends Plugin if (array_key_exists('X-Pingback', $result->headers)) { $pb = $result->headers['X-Pingback']; - } else if (preg_match('//', + } else if (preg_match('//', $result->body, $match)) { $pb = $match[1]; From b142c260108f43636b69adb90d5a27ffa44f0f74 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 14 Apr 2009 16:02:09 -0400 Subject: [PATCH 355/503] Make stuff work with no base --- lib/action.php | 4 ---- theme/default/css/display.css | 10 ++-------- theme/identica/css/display.css | 10 ++-------- theme/iphone/display.css | 16 +++++++--------- 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/lib/action.php b/lib/action.php index 1ba062812a..b02f525f0b 100644 --- a/lib/action.php +++ b/lib/action.php @@ -192,10 +192,6 @@ class Action extends HTMLOutputter // lawsuit { if (Event::handle('StartShowStyles', array($this))) { if (Event::handle('StartShowLaconicaStyles', array($this))) { - $this->element('link', array('rel' => 'stylesheet', - 'type' => 'text/css', - 'href' => theme_path('css/display.css', 'base') . '?version=' . LACONICA_VERSION, - 'media' => 'screen, projection, tv')); $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', 'href' => theme_path('css/display.css', null) . '?version=' . LACONICA_VERSION, diff --git a/theme/default/css/display.css b/theme/default/css/display.css index c5d6946108..69a600cc28 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -7,6 +7,8 @@ * @link http://laconi.ca/ */ +@import url(../../base/css/display.css); + html, body, a:active { @@ -70,7 +72,6 @@ border-top-color:#D1D9E4; border-top-color:#97BFD1; } - #content .notice p.entry-content a:visited { background-color:#fcfcfc; } @@ -82,7 +83,6 @@ background-color:#fcfffc; background-color:#CEE1E9; } - #notice_text-count { color:#333; } @@ -112,7 +112,6 @@ background-color:rgba(255, 255, 255, 0.2); background-color:rgba(255, 255, 255, 0.7); } - .error { background-color:#F7E8E8; } @@ -120,7 +119,6 @@ background-color:#F7E8E8; background-color:#EFF3DC; } - #anon_notice { background-color:#97BFD1; color:#fff; @@ -131,7 +129,6 @@ border-color:#fff; background-color:#A9BF4F; } - #export_data li a { background-repeat:no-repeat; background-position:0 45%; @@ -184,8 +181,6 @@ background-image:url(../images/icons/twotone/green/mail.gif); background-image:url(../images/icons/twotone/green/shield.gif); } - - /* NOTICES */ .notices li.over { background-color:#fcfcfc; @@ -228,7 +223,6 @@ background-color:#fcfcfc; } /*END: NOTICES */ - #new_group a { background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; } diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index c32b6269d0..d05578d439 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -7,6 +7,8 @@ * @link http://laconi.ca/ */ +@import url(../../base/css/display.css); + html, body, a:active { @@ -70,7 +72,6 @@ border-top-color:#CEE1E9; border-top-color:#87B4C8; } - #content .notice p.entry-content a:visited { background-color:#fcfcfc; } @@ -82,7 +83,6 @@ background-color:#fcfffc; background-color:#CEE1E9; } - #notice_text-count { color:#333; } @@ -112,7 +112,6 @@ background-color:rgba(135, 180, 200, 0.3); background-color:rgba(255, 255, 255, 0.7); } - .error { background-color:#F7E8E8; } @@ -120,7 +119,6 @@ background-color:#F7E8E8; background-color:#EFF3DC; } - #anon_notice { background-color:#87B4C8; color:#fff; @@ -131,7 +129,6 @@ border-color:#fff; background-color:#9BB43E; } - #export_data li a { background-repeat:no-repeat; background-position:0 45%; @@ -184,8 +181,6 @@ background-image:url(../images/icons/twotone/green/mail.gif); background-image:url(../images/icons/twotone/green/shield.gif); } - - /* NOTICES */ .notices li.over { background-color:#fcfcfc; @@ -228,7 +223,6 @@ background-color:#fcfcfc; } /*END: NOTICES */ - #new_group a { background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; } diff --git a/theme/iphone/display.css b/theme/iphone/display.css index 6ac471c1e8..1838a8e86e 100644 --- a/theme/iphone/display.css +++ b/theme/iphone/display.css @@ -2,6 +2,8 @@ /* Design & CSS by Marie-Claude Doyon http://www.marieclaudedoyon.com */ /* Simplified for mobile by Ken Sheppardson http://identi.ca/kshep */ +@import url(../../base/css/display.css); + html {} body { width: 100%; @@ -28,7 +30,6 @@ h1 { font-size: 1.2em; } - #wrap { margin: 0; } @@ -196,7 +197,7 @@ p#branding a { } .instructions a:hover, .success a:hover, .error a:hover { color: #FCFFF5; -} +} .success { clear: both; float: left; @@ -210,7 +211,6 @@ p#branding a { background-color: #ce3728; } - /* ----- Stream -----*/ #notices { @@ -273,7 +273,7 @@ p.time { p.time a { color: #91AA9D; } - + /* ----- Profile -----*/ #profile { clear: both; @@ -356,7 +356,7 @@ dl.statistics { clear: left; float: left; width: 200px; -} +} .statistics dd { float: left; } @@ -402,8 +402,6 @@ ul.subscriptions li, ul.subscribers li { } /* ----- End Subscriptions & Subscribers -----*/ - - #pagination { margin: 18px auto; } @@ -488,7 +486,7 @@ input#submit:hover, input.submit:hover { input.checkbox { width: auto; border: 0; -} +} textarea, input { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 1em; @@ -629,7 +627,7 @@ input#openid_url { #profiles a:hover { text-decoration: underline; } - + .profile_single { clear: both; display: block; From 20394664957a202cc86cc48ee2d115032e82c58a Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 14 Apr 2009 23:03:19 +0000 Subject: [PATCH 356/503] trac#1223 Show most popular notices per tag in the tag page sidebar. --- actions/tag.php | 7 +++++++ lib/popularnoticesection.php | 25 +++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/actions/tag.php b/actions/tag.php index d15f64498d..cb6572b962 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -45,6 +45,13 @@ class TagAction extends Action return true; } + function showSections() + { + $pop = new PopularNoticeSection($this); + $pop->show(); + } + + function title() { if ($this->page == 1) { diff --git a/lib/popularnoticesection.php b/lib/popularnoticesection.php index 0505f0fa9a..a8d47ef542 100644 --- a/lib/popularnoticesection.php +++ b/lib/popularnoticesection.php @@ -50,17 +50,26 @@ class PopularNoticeSection extends NoticeSection { if (common_config('db', 'type') == 'pgsql') { $weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))'; + if (!empty($this->out->tag)) { + $tag = pg_escape_string($this->tag); + } } else { $weightexpr='sum(exp(-(now() - fave.modified) / %s))'; + if (!empty($this->out->tag)) { + $tag = mysql_escape_string($this->out->tag); + } } - - $qry = 'SELECT notice.*, '. - $weightexpr . ' as weight ' . - 'FROM notice JOIN fave ON notice.id = fave.notice_id ' . - 'GROUP BY notice.id,notice.profile_id,notice.content,notice.uri,' . - 'notice.rendered,notice.url,notice.created,notice.modified,' . - 'notice.reply_to,notice.is_local,notice.source ' . - 'ORDER BY weight DESC'; + $qry = "SELECT notice.*, $weightexpr as weight "; + if(isset($tag)) { + $qry .= 'FROM notice_tag, notice JOIN fave ON notice.id = fave.notice_id ' . + "WHERE notice.id = notice_tag.notice_id and '$tag' = notice_tag.tag"; + } else { + $qry .= 'FROM notice JOIN fave ON notice.id = fave.notice_id'; + } + $qry .= ' GROUP BY notice.id,notice.profile_id,notice.content,notice.uri,' . + 'notice.rendered,notice.url,notice.created,notice.modified,' . + 'notice.reply_to,notice.is_local,notice.source ' . + 'ORDER BY weight DESC'; $offset = 0; $limit = NOTICES_PER_SECTION + 1; From 7095c93f66fa2fc4fdae57276ca66ad777788afd Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 14 Apr 2009 23:13:02 +0000 Subject: [PATCH 357/503] Simpler separation of themes. New themes can either make use of the default styles or make their own. --- lib/action.php | 18 +- theme/{default => }/base/css/display.css | 0 theme/{cloudy => }/base/css/facebookapp.css | 0 theme/{default => }/base/css/farbtastic.css | 0 theme/{cloudy => }/base/css/ie.css | 0 theme/{cloudy => }/base/css/ie6.css | 0 theme/{cloudy => }/base/css/jquery.Jcrop.css | 0 theme/{cloudy => }/base/css/mobile.css | 0 theme/{cloudy => }/base/css/print.css | 0 theme/{cloudy => }/base/css/thickbox.css | 0 theme/base/default-avatar-mini.png | Bin 0 -> 646 bytes theme/base/default-avatar-profile.png | Bin 0 -> 2853 bytes theme/base/default-avatar-stream.png | Bin 0 -> 1487 bytes .../base/images/icons/icon_atom.png | Bin .../base/images/icons/icon_foaf.gif | Bin .../base/images/icons/icon_rss.png | Bin .../base/images/icons/icon_vcard.gif | Bin .../images/icons/twotone/green/arrow-left.gif | Bin .../icons/twotone/green/arrow-right.gif | Bin .../icons/twotone/green/disfavourite.gif | Bin .../images/icons/twotone/green/edit.gif | Bin .../images/icons/twotone/green/favourite.gif | Bin .../images/icons/twotone/green/mail.gif | Bin .../images/icons/twotone/green/news.gif | Bin .../images/icons/twotone/green/quote.gif | Bin .../images/icons/twotone/green/reply.gif | Bin .../images/icons/twotone/green/shield.gif | Bin .../images/icons/twotone/green/trash.gif | Bin .../base/images/illustrations/illu_jcrop.gif | Bin .../illu_progress_loading-01.gif | Bin theme/{default => base}/logo.png | Bin theme/cloudy/{base => }/css/display.css | 308 +++++++++++++++++ theme/cloudy/{skin/default => }/css/ie.css | 0 .../images/icons/icon_atom.png | Bin .../images/icons/icon_disfavourite.gif | Bin .../images/icons/icon_favourite.gif | Bin .../default => }/images/icons/icon_foaf.gif | Bin .../images/icons/icon_processing.gif | Bin .../default => }/images/icons/icon_reply.gif | Bin .../base => cloudy}/images/icons/icon_rss.png | Bin .../default => }/images/icons/icon_trash.gif | Bin .../default => }/images/icons/icon_vcard.gif | Bin .../images/icons/twotone/green/arrow-left.gif | Bin .../icons/twotone/green/arrow-right.gif | Bin .../images/icons/twotone/green/edit.gif | Bin .../images/icons/twotone/green/mail.gif | Bin .../images/icons/twotone/green/news.gif | Bin .../images/icons/twotone/green/quote.gif | Bin .../images/icons/twotone/green/shield.gif | Bin .../images/illustrations/illu_arrow-up-01.gif | Bin .../images/illustrations/illu_clouds-01.gif | Bin .../images/illustrations/illu_jcrop.gif | Bin .../illu_progress_loading-01.gif | Bin .../images/illustrations/illu_unicorn-01.png | Bin theme/cloudy/skin/default/css/display.css | 314 ------------------ .../skin/default/images/icons/icon_atom.jpg | Bin 1117 -> 0 bytes .../skin/default/images/icons/icon_rss.jpg | Bin 1166 -> 0 bytes theme/default/base/css/facebookapp.css | 100 ------ theme/default/base/css/ie.css | 32 -- theme/default/base/css/ie6.css | 30 -- theme/default/base/css/jquery.Jcrop.css | 45 --- theme/default/base/css/mobile.css | 150 --------- theme/default/base/css/print.css | 36 -- theme/default/base/css/thickbox.css | 163 --------- theme/default/base/images/icons/icon_foaf.gif | Bin 1144 -> 0 bytes .../base/images/icons/icon_processing.gif | Bin 673 -> 0 bytes .../default/base/images/icons/icon_vcard.gif | Bin 331 -> 0 bytes .../{skin/default => }/css/display.css | 32 +- theme/default/{skin/default => }/css/ie.css | 0 .../skin/default/images/icons/icon_atom.jpg | Bin 1117 -> 0 bytes .../skin/default/images/icons/icon_foaf.gif | Bin 1144 -> 0 bytes .../skin/default/images/icons/icon_rss.jpg | Bin 1166 -> 0 bytes .../skin/default/images/icons/icon_vcard.gif | Bin 331 -> 0 bytes .../skin/identica/images/icons/icon_atom.jpg | Bin 1117 -> 0 bytes .../skin/identica/images/icons/icon_foaf.gif | Bin 1144 -> 0 bytes .../skin/identica/images/icons/icon_rss.jpg | Bin 1166 -> 0 bytes .../skin/identica/images/icons/icon_vcard.gif | Bin 331 -> 0 bytes .../images/icons/twotone/green/arrow-left.gif | Bin 73 -> 0 bytes .../icons/twotone/green/arrow-right.gif | Bin 74 -> 0 bytes .../icons/twotone/green/disfavourite.gif | Bin 88 -> 0 bytes .../images/icons/twotone/green/edit.gif | Bin 75 -> 0 bytes .../images/icons/twotone/green/favourite.gif | Bin 73 -> 0 bytes .../images/icons/twotone/green/mail.gif | Bin 82 -> 0 bytes .../images/icons/twotone/green/news.gif | Bin 76 -> 0 bytes .../images/icons/twotone/green/quote.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/reply.gif | Bin 79 -> 0 bytes .../images/icons/twotone/green/shield.gif | Bin 85 -> 0 bytes .../images/icons/twotone/green/trash.gif | Bin 77 -> 0 bytes .../skin => }/identica/css/display.css | 32 +- theme/{default/skin => }/identica/css/ie.css | 0 theme/identica/default-avatar-mini.png | Bin 0 -> 646 bytes theme/identica/default-avatar-profile.png | Bin 0 -> 2853 bytes theme/identica/default-avatar-stream.png | Bin 0 -> 1487 bytes theme/identica/logo.png | Bin 0 -> 4988 bytes 94 files changed, 349 insertions(+), 911 deletions(-) rename theme/{default => }/base/css/display.css (100%) rename theme/{cloudy => }/base/css/facebookapp.css (100%) rename theme/{default => }/base/css/farbtastic.css (100%) rename theme/{cloudy => }/base/css/ie.css (100%) rename theme/{cloudy => }/base/css/ie6.css (100%) rename theme/{cloudy => }/base/css/jquery.Jcrop.css (100%) rename theme/{cloudy => }/base/css/mobile.css (100%) rename theme/{cloudy => }/base/css/print.css (100%) rename theme/{cloudy => }/base/css/thickbox.css (100%) create mode 100644 theme/base/default-avatar-mini.png create mode 100644 theme/base/default-avatar-profile.png create mode 100644 theme/base/default-avatar-stream.png rename theme/{cloudy => }/base/images/icons/icon_atom.png (100%) rename theme/{cloudy => }/base/images/icons/icon_foaf.gif (100%) rename theme/{cloudy => }/base/images/icons/icon_rss.png (100%) rename theme/{cloudy => }/base/images/icons/icon_vcard.gif (100%) rename theme/{cloudy/skin/default => base}/images/icons/twotone/green/arrow-left.gif (100%) rename theme/{cloudy/skin/default => base}/images/icons/twotone/green/arrow-right.gif (100%) rename theme/{default/skin/default => base}/images/icons/twotone/green/disfavourite.gif (100%) rename theme/{cloudy/skin/default => base}/images/icons/twotone/green/edit.gif (100%) rename theme/{default/skin/default => base}/images/icons/twotone/green/favourite.gif (100%) rename theme/{cloudy/skin/default => base}/images/icons/twotone/green/mail.gif (100%) rename theme/{cloudy/skin/default => base}/images/icons/twotone/green/news.gif (100%) rename theme/{cloudy/skin/default => base}/images/icons/twotone/green/quote.gif (100%) rename theme/{default/skin/default => base}/images/icons/twotone/green/reply.gif (100%) rename theme/{cloudy/skin/default => base}/images/icons/twotone/green/shield.gif (100%) rename theme/{default/skin/default => base}/images/icons/twotone/green/trash.gif (100%) rename theme/{cloudy => }/base/images/illustrations/illu_jcrop.gif (100%) rename theme/{cloudy => }/base/images/illustrations/illu_progress_loading-01.gif (100%) rename theme/{default => base}/logo.png (100%) rename theme/cloudy/{base => }/css/display.css (75%) rename theme/cloudy/{skin/default => }/css/ie.css (100%) rename theme/{default/base => cloudy}/images/icons/icon_atom.png (100%) rename theme/cloudy/{skin/default => }/images/icons/icon_disfavourite.gif (100%) rename theme/cloudy/{skin/default => }/images/icons/icon_favourite.gif (100%) rename theme/cloudy/{skin/default => }/images/icons/icon_foaf.gif (100%) rename theme/cloudy/{base => }/images/icons/icon_processing.gif (100%) rename theme/cloudy/{skin/default => }/images/icons/icon_reply.gif (100%) rename theme/{default/base => cloudy}/images/icons/icon_rss.png (100%) rename theme/cloudy/{skin/default => }/images/icons/icon_trash.gif (100%) rename theme/cloudy/{skin/default => }/images/icons/icon_vcard.gif (100%) rename theme/{default/skin/default => cloudy}/images/icons/twotone/green/arrow-left.gif (100%) rename theme/{default/skin/default => cloudy}/images/icons/twotone/green/arrow-right.gif (100%) rename theme/{default/skin/default => cloudy}/images/icons/twotone/green/edit.gif (100%) rename theme/{default/skin/default => cloudy}/images/icons/twotone/green/mail.gif (100%) rename theme/{default/skin/default => cloudy}/images/icons/twotone/green/news.gif (100%) rename theme/{default/skin/default => cloudy}/images/icons/twotone/green/quote.gif (100%) rename theme/{default/skin/default => cloudy}/images/icons/twotone/green/shield.gif (100%) rename theme/cloudy/{skin/default => }/images/illustrations/illu_arrow-up-01.gif (100%) rename theme/cloudy/{skin/default => }/images/illustrations/illu_clouds-01.gif (100%) rename theme/{default/base => cloudy}/images/illustrations/illu_jcrop.gif (100%) rename theme/{default/base => cloudy}/images/illustrations/illu_progress_loading-01.gif (100%) rename theme/cloudy/{skin/default => }/images/illustrations/illu_unicorn-01.png (100%) delete mode 100644 theme/cloudy/skin/default/css/display.css delete mode 100644 theme/cloudy/skin/default/images/icons/icon_atom.jpg delete mode 100644 theme/cloudy/skin/default/images/icons/icon_rss.jpg delete mode 100644 theme/default/base/css/facebookapp.css delete mode 100644 theme/default/base/css/ie.css delete mode 100644 theme/default/base/css/ie6.css delete mode 100644 theme/default/base/css/jquery.Jcrop.css delete mode 100644 theme/default/base/css/mobile.css delete mode 100644 theme/default/base/css/print.css delete mode 100644 theme/default/base/css/thickbox.css delete mode 100644 theme/default/base/images/icons/icon_foaf.gif delete mode 100644 theme/default/base/images/icons/icon_processing.gif delete mode 100644 theme/default/base/images/icons/icon_vcard.gif rename theme/default/{skin/default => }/css/display.css (76%) rename theme/default/{skin/default => }/css/ie.css (100%) delete mode 100644 theme/default/skin/default/images/icons/icon_atom.jpg delete mode 100644 theme/default/skin/default/images/icons/icon_foaf.gif delete mode 100644 theme/default/skin/default/images/icons/icon_rss.jpg delete mode 100644 theme/default/skin/default/images/icons/icon_vcard.gif delete mode 100644 theme/default/skin/identica/images/icons/icon_atom.jpg delete mode 100644 theme/default/skin/identica/images/icons/icon_foaf.gif delete mode 100644 theme/default/skin/identica/images/icons/icon_rss.jpg delete mode 100644 theme/default/skin/identica/images/icons/icon_vcard.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-left.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/arrow-right.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/disfavourite.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/edit.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/favourite.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/mail.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/news.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/quote.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/reply.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/shield.gif delete mode 100644 theme/default/skin/identica/images/icons/twotone/green/trash.gif rename theme/{default/skin => }/identica/css/display.css (76%) rename theme/{default/skin => }/identica/css/ie.css (100%) create mode 100644 theme/identica/default-avatar-mini.png create mode 100644 theme/identica/default-avatar-profile.png create mode 100644 theme/identica/default-avatar-stream.png create mode 100644 theme/identica/logo.png diff --git a/lib/action.php b/lib/action.php index 0a628bfdfe..ff75ee8554 100644 --- a/lib/action.php +++ b/lib/action.php @@ -194,37 +194,33 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowLaconicaStyles', array($this))) { $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', - 'href' => theme_path('base/css/display.css') . '?version=' . LACONICA_VERSION, - 'media' => 'screen, projection, tv')); - $this->element('link', array('rel' => 'stylesheet', - 'type' => 'text/css', - 'href' => skin_path('css/display.css') . '?version=' . LACONICA_VERSION, + 'href' => theme_path('css/display.css', null) . '?version=' . LACONICA_VERSION, 'media' => 'screen, projection, tv')); if (common_config('site', 'mobile')) { $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', - 'href' => theme_path('base/css/mobile.css') . '?version=' . LACONICA_VERSION, + 'href' => theme_path('css/mobile.css', 'base') . '?version=' . LACONICA_VERSION, // TODO: "handheld" CSS for other mobile devices 'media' => 'only screen and (max-device-width: 480px)')); // Mobile WebKit } $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', - 'href' => theme_path('base/css/print.css') . '?version=' . LACONICA_VERSION, + 'href' => theme_path('css/print.css', 'base') . '?version=' . LACONICA_VERSION, 'media' => 'print')); Event::handle('EndShowLaconicaStyles', array($this)); } if (Event::handle('StartShowUAStyles', array($this))) { $this->comment('[if IE]>comment('[if lte IE '.$ver.']>comment('[if IE]>t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b literal 0 HcmV?d00001 diff --git a/theme/base/default-avatar-profile.png b/theme/base/default-avatar-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..f8357d4fc296271b837b3d9911cfbc133918ef2f GIT binary patch literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi literal 0 HcmV?d00001 diff --git a/theme/cloudy/base/images/icons/icon_atom.png b/theme/base/images/icons/icon_atom.png similarity index 100% rename from theme/cloudy/base/images/icons/icon_atom.png rename to theme/base/images/icons/icon_atom.png diff --git a/theme/cloudy/base/images/icons/icon_foaf.gif b/theme/base/images/icons/icon_foaf.gif similarity index 100% rename from theme/cloudy/base/images/icons/icon_foaf.gif rename to theme/base/images/icons/icon_foaf.gif diff --git a/theme/cloudy/base/images/icons/icon_rss.png b/theme/base/images/icons/icon_rss.png similarity index 100% rename from theme/cloudy/base/images/icons/icon_rss.png rename to theme/base/images/icons/icon_rss.png diff --git a/theme/cloudy/base/images/icons/icon_vcard.gif b/theme/base/images/icons/icon_vcard.gif similarity index 100% rename from theme/cloudy/base/images/icons/icon_vcard.gif rename to theme/base/images/icons/icon_vcard.gif diff --git a/theme/cloudy/skin/default/images/icons/twotone/green/arrow-left.gif b/theme/base/images/icons/twotone/green/arrow-left.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/twotone/green/arrow-left.gif rename to theme/base/images/icons/twotone/green/arrow-left.gif diff --git a/theme/cloudy/skin/default/images/icons/twotone/green/arrow-right.gif b/theme/base/images/icons/twotone/green/arrow-right.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/twotone/green/arrow-right.gif rename to theme/base/images/icons/twotone/green/arrow-right.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/disfavourite.gif b/theme/base/images/icons/twotone/green/disfavourite.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/disfavourite.gif rename to theme/base/images/icons/twotone/green/disfavourite.gif diff --git a/theme/cloudy/skin/default/images/icons/twotone/green/edit.gif b/theme/base/images/icons/twotone/green/edit.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/twotone/green/edit.gif rename to theme/base/images/icons/twotone/green/edit.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/favourite.gif b/theme/base/images/icons/twotone/green/favourite.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/favourite.gif rename to theme/base/images/icons/twotone/green/favourite.gif diff --git a/theme/cloudy/skin/default/images/icons/twotone/green/mail.gif b/theme/base/images/icons/twotone/green/mail.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/twotone/green/mail.gif rename to theme/base/images/icons/twotone/green/mail.gif diff --git a/theme/cloudy/skin/default/images/icons/twotone/green/news.gif b/theme/base/images/icons/twotone/green/news.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/twotone/green/news.gif rename to theme/base/images/icons/twotone/green/news.gif diff --git a/theme/cloudy/skin/default/images/icons/twotone/green/quote.gif b/theme/base/images/icons/twotone/green/quote.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/twotone/green/quote.gif rename to theme/base/images/icons/twotone/green/quote.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/reply.gif b/theme/base/images/icons/twotone/green/reply.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/reply.gif rename to theme/base/images/icons/twotone/green/reply.gif diff --git a/theme/cloudy/skin/default/images/icons/twotone/green/shield.gif b/theme/base/images/icons/twotone/green/shield.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/twotone/green/shield.gif rename to theme/base/images/icons/twotone/green/shield.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/trash.gif b/theme/base/images/icons/twotone/green/trash.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/trash.gif rename to theme/base/images/icons/twotone/green/trash.gif diff --git a/theme/cloudy/base/images/illustrations/illu_jcrop.gif b/theme/base/images/illustrations/illu_jcrop.gif similarity index 100% rename from theme/cloudy/base/images/illustrations/illu_jcrop.gif rename to theme/base/images/illustrations/illu_jcrop.gif diff --git a/theme/cloudy/base/images/illustrations/illu_progress_loading-01.gif b/theme/base/images/illustrations/illu_progress_loading-01.gif similarity index 100% rename from theme/cloudy/base/images/illustrations/illu_progress_loading-01.gif rename to theme/base/images/illustrations/illu_progress_loading-01.gif diff --git a/theme/default/logo.png b/theme/base/logo.png similarity index 100% rename from theme/default/logo.png rename to theme/base/logo.png diff --git a/theme/cloudy/base/css/display.css b/theme/cloudy/css/display.css similarity index 75% rename from theme/cloudy/base/css/display.css rename to theme/cloudy/css/display.css index c71a59ef2c..151758b489 100644 --- a/theme/cloudy/base/css/display.css +++ b/theme/cloudy/css/display.css @@ -1240,3 +1240,311 @@ padding-top:160px; #tag #form_notice { display:none; } + + +html, +body, +a:active { +background-color:#9AE4E8; +} +body { +font-family:'Lucida Grande',sans-serif; +background:#9AE4E8 url(../images/illustrations/illu_clouds-01.gif) 0 0 no-repeat; +color:#333333; +} +#core { +background:url(../images/illustrations/illu_arrow-up-01.gif) no-repeat 25px 0; +} + +input, textarea, select, option { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +} +input, textarea, select, +.entity_remote_subscribe { +border-color:#aaa; +} +#filter_tags ul li { +border-color:#ddd; +} + +.form_settings input.form_action-secondary { +background:none; +} + +input.submit, +#form_notice.warning #notice_text-count, +#nav_register a, +.form_settings .form_note, +.entity_remote_subscribe { +background-color:#9BB43E; +} + +input:focus, textarea:focus, select:focus, +#form_notice.warning #notice_data-text { +border-color:#9BB43E; +} +input.submit, +#nav_register a, +.entity_remote_subscribe { +color:#fff; +} + +a, +div.notice-options input, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.form_user_nudge input.submit, +.entity_nudge p, +.form_settings input.form_action-secondary { +color:#0084B4; +} + +.notice, +.profile { +border-top-color:#DDFFCC; +} +.section .profile { +border-top-color:#87B4C8; +} + + +#content .notice p.entry-content a:visited { +background-color:#fcfcfc; +} +#content .notice p.entry-content .vcard a { +background-color:#fcfffc; +} + +#aside_primary { +background-color:#DDFFCC; +} + + +#notice_text-count { +color:#333; +} +#form_notice.warning #notice_text-count { +color:#000; +} +#form_notice.processing #notice_action-submit { +background:#fff url(../../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +cursor:wait; +text-indent:-9999px; +} + +#content, +#site_nav_local_views a, +#aside_primary { +border-color:#fff; +} +#content, +#site_nav_local_views .current a { +background-color:#fff; +} + +#site_nav_local_views a { +background-color:rgba(135, 180, 200, 0.3); +} +#site_nav_local_views a:hover { +background-color:rgba(255, 255, 255, 0.7); +} + + +.error { +background-color:#F7E8E8; +} +.success { +background-color:#EFF3DC; +} + + +#anon_notice { +background-color:#FEFFDF; +color:#333; +border-color:#fff; +} + +#showstream #anon_notice { +background-color:#FEFFDF; +} + + +#export_data li a { +background-repeat:no-repeat; +background-position:0 45%; +} +#export_data li a.rss { +background-image:url(../../base/images/icons/icon_rss.png); +} +#export_data li a.atom { +background-image:url(../../base/images/icons/icon_atom.png); +} +#export_data li a.foaf { +background-image:url(../../base/images/icons/icon_foaf.gif); +} + +.entity_edit a, +.entity_send-a-message a, +.form_user_nudge input.submit, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_nudge p { +background-position: 0 40%; +background-repeat: no-repeat; +background-color:transparent; +} +.form_group_join input.submit, +.form_group_leave input.submit +.form_user_subscribe input.submit, +.form_user_unsubscribe input.submit { +background-color:#9BB43E; +color:#fff; +} +.form_user_unsubscribe input.submit, +.form_group_leave input.submit { +background-color:#87B4C8; +} + +.entity_edit a { +background-image:url(../images/icons/twotone/green/edit.gif); +} +.entity_send-a-message a { +background-image:url(../images/icons/twotone/green/quote.gif); +} +.entity_nudge p, +.form_user_nudge input.submit { +background-image:url(../images/icons/twotone/green/mail.gif); +} +.form_user_block input.submit, +.form_user_unblock input.submit { +background-image:url(../images/icons/twotone/green/shield.gif); +} + + + +/* NOTICES */ +.notices li.over { +background-color:#fcfcfc; +} + +.notice-options .notice_reply a, +.notice-options form input.submit { +background-color:transparent; +} +.notice-options .notice_reply a { +background:transparent url(../images/icons/icon_reply.gif) no-repeat 0 45%; +} +.notice-options form.form_favor input.submit { +background:transparent url(../images/icons/icon_favourite.gif) no-repeat 0 45%; +} +.notice-options form.form_disfavor input.submit { +background:transparent url(../images/icons/icon_disfavourite.gif) no-repeat 0 45%; +} +.notice-options .notice_delete a { +background:transparent url(../images/icons/icon_trash.gif) no-repeat 0 45%; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:0.4; +} +.notices li.hover div.entry-content, +.notices li.hover div.notice-options { +opacity:1; +} +div.entry-content { +color:#333; +} +div.notice-options a, +div.notice-options input { +font-family:sans-serif; +} +.notices li.hover { +background-color:#fcfcfc; +} +/*END: NOTICES */ + + +#new_group a { +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; +} + +.pagination .nav_prev a, +.pagination .nav_next a { +background-repeat:no-repeat; +border-color:#DDFFCC; +} +.pagination .nav_prev a { +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); +background-position:10% 45%; +} +.pagination .nav_next a { +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); +background-position:90% 45%; +} + + +/*--------------------------------------*/ + +#anon_notice { +background:url(../images/illustrations/illu_unicorn-01.png) no-repeat 0 0; +} +#showstream #anon_notice, +#content .notice p.entry-content a:visited, +content .notice p.entry-content .vcard a { +background-color:transparent; +} + +#anon_notice p { +background-color:#FEFFDF; +border-color:#FFFF00; +} + + +#form_notice .form_note { +color:#CCC; +} +input.submit { +background-color:#eee; +color:#666; +} + +.notices li.hover { +background-color:#F7F7F7; +} + + +.notice div.entry-content, +.notice div.entry-content a { +color:#999; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:1; +} + +#site_nav_local_views { +background-color:#DDFFCC; +} +#site_nav_local_views li, +#aside_primary { +border-color:#BDDCAD; +} +#site_nav_local_views a, +.aside .section h2 { +background-color:transparent; +border-color:transparent; +color:#4C4C4C; +} +#site_nav_local_views .current { +border-left-color:#fff; +} + +#site_nav_local_views .current a, +#site_nav_global_primary, +#footer { +background-color:#fff; +} + diff --git a/theme/cloudy/skin/default/css/ie.css b/theme/cloudy/css/ie.css similarity index 100% rename from theme/cloudy/skin/default/css/ie.css rename to theme/cloudy/css/ie.css diff --git a/theme/default/base/images/icons/icon_atom.png b/theme/cloudy/images/icons/icon_atom.png similarity index 100% rename from theme/default/base/images/icons/icon_atom.png rename to theme/cloudy/images/icons/icon_atom.png diff --git a/theme/cloudy/skin/default/images/icons/icon_disfavourite.gif b/theme/cloudy/images/icons/icon_disfavourite.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/icon_disfavourite.gif rename to theme/cloudy/images/icons/icon_disfavourite.gif diff --git a/theme/cloudy/skin/default/images/icons/icon_favourite.gif b/theme/cloudy/images/icons/icon_favourite.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/icon_favourite.gif rename to theme/cloudy/images/icons/icon_favourite.gif diff --git a/theme/cloudy/skin/default/images/icons/icon_foaf.gif b/theme/cloudy/images/icons/icon_foaf.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/icon_foaf.gif rename to theme/cloudy/images/icons/icon_foaf.gif diff --git a/theme/cloudy/base/images/icons/icon_processing.gif b/theme/cloudy/images/icons/icon_processing.gif similarity index 100% rename from theme/cloudy/base/images/icons/icon_processing.gif rename to theme/cloudy/images/icons/icon_processing.gif diff --git a/theme/cloudy/skin/default/images/icons/icon_reply.gif b/theme/cloudy/images/icons/icon_reply.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/icon_reply.gif rename to theme/cloudy/images/icons/icon_reply.gif diff --git a/theme/default/base/images/icons/icon_rss.png b/theme/cloudy/images/icons/icon_rss.png similarity index 100% rename from theme/default/base/images/icons/icon_rss.png rename to theme/cloudy/images/icons/icon_rss.png diff --git a/theme/cloudy/skin/default/images/icons/icon_trash.gif b/theme/cloudy/images/icons/icon_trash.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/icon_trash.gif rename to theme/cloudy/images/icons/icon_trash.gif diff --git a/theme/cloudy/skin/default/images/icons/icon_vcard.gif b/theme/cloudy/images/icons/icon_vcard.gif similarity index 100% rename from theme/cloudy/skin/default/images/icons/icon_vcard.gif rename to theme/cloudy/images/icons/icon_vcard.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/arrow-left.gif b/theme/cloudy/images/icons/twotone/green/arrow-left.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/arrow-left.gif rename to theme/cloudy/images/icons/twotone/green/arrow-left.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/arrow-right.gif b/theme/cloudy/images/icons/twotone/green/arrow-right.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/arrow-right.gif rename to theme/cloudy/images/icons/twotone/green/arrow-right.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/edit.gif b/theme/cloudy/images/icons/twotone/green/edit.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/edit.gif rename to theme/cloudy/images/icons/twotone/green/edit.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/mail.gif b/theme/cloudy/images/icons/twotone/green/mail.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/mail.gif rename to theme/cloudy/images/icons/twotone/green/mail.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/news.gif b/theme/cloudy/images/icons/twotone/green/news.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/news.gif rename to theme/cloudy/images/icons/twotone/green/news.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/quote.gif b/theme/cloudy/images/icons/twotone/green/quote.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/quote.gif rename to theme/cloudy/images/icons/twotone/green/quote.gif diff --git a/theme/default/skin/default/images/icons/twotone/green/shield.gif b/theme/cloudy/images/icons/twotone/green/shield.gif similarity index 100% rename from theme/default/skin/default/images/icons/twotone/green/shield.gif rename to theme/cloudy/images/icons/twotone/green/shield.gif diff --git a/theme/cloudy/skin/default/images/illustrations/illu_arrow-up-01.gif b/theme/cloudy/images/illustrations/illu_arrow-up-01.gif similarity index 100% rename from theme/cloudy/skin/default/images/illustrations/illu_arrow-up-01.gif rename to theme/cloudy/images/illustrations/illu_arrow-up-01.gif diff --git a/theme/cloudy/skin/default/images/illustrations/illu_clouds-01.gif b/theme/cloudy/images/illustrations/illu_clouds-01.gif similarity index 100% rename from theme/cloudy/skin/default/images/illustrations/illu_clouds-01.gif rename to theme/cloudy/images/illustrations/illu_clouds-01.gif diff --git a/theme/default/base/images/illustrations/illu_jcrop.gif b/theme/cloudy/images/illustrations/illu_jcrop.gif similarity index 100% rename from theme/default/base/images/illustrations/illu_jcrop.gif rename to theme/cloudy/images/illustrations/illu_jcrop.gif diff --git a/theme/default/base/images/illustrations/illu_progress_loading-01.gif b/theme/cloudy/images/illustrations/illu_progress_loading-01.gif similarity index 100% rename from theme/default/base/images/illustrations/illu_progress_loading-01.gif rename to theme/cloudy/images/illustrations/illu_progress_loading-01.gif diff --git a/theme/cloudy/skin/default/images/illustrations/illu_unicorn-01.png b/theme/cloudy/images/illustrations/illu_unicorn-01.png similarity index 100% rename from theme/cloudy/skin/default/images/illustrations/illu_unicorn-01.png rename to theme/cloudy/images/illustrations/illu_unicorn-01.png diff --git a/theme/cloudy/skin/default/css/display.css b/theme/cloudy/skin/default/css/display.css deleted file mode 100644 index b30ca9d0da..0000000000 --- a/theme/cloudy/skin/default/css/display.css +++ /dev/null @@ -1,314 +0,0 @@ -/** theme: twitter - * - * @package Laconica - * @author Sarven Capadisli - * @copyright 2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ -html, -body, -a:active { -background-color:#9AE4E8; -} -body { -font-family:'Lucida Grande',sans-serif; -background:#9AE4E8 url(../images/illustrations/illu_clouds-01.gif) 0 0 no-repeat; -color:#333333; -} -#core { -background:url(../images/illustrations/illu_arrow-up-01.gif) no-repeat 25px 0; -} - -input, textarea, select, option { -font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; -} -input, textarea, select, -.entity_remote_subscribe { -border-color:#aaa; -} -#filter_tags ul li { -border-color:#ddd; -} - -.form_settings input.form_action-secondary { -background:none; -} - -input.submit, -#form_notice.warning #notice_text-count, -#nav_register a, -.form_settings .form_note, -.entity_remote_subscribe { -background-color:#9BB43E; -} - -input:focus, textarea:focus, select:focus, -#form_notice.warning #notice_data-text { -border-color:#9BB43E; -} -input.submit, -#nav_register a, -.entity_remote_subscribe { -color:#fff; -} - -a, -div.notice-options input, -.form_user_block input.submit, -.form_user_unblock input.submit, -.entity_send-a-message a, -.form_user_nudge input.submit, -.entity_nudge p, -.form_settings input.form_action-secondary { -color:#0084B4; -} - -.notice, -.profile { -border-top-color:#DDFFCC; -} -.section .profile { -border-top-color:#87B4C8; -} - - -#content .notice p.entry-content a:visited { -background-color:#fcfcfc; -} -#content .notice p.entry-content .vcard a { -background-color:#fcfffc; -} - -#aside_primary { -background-color:#DDFFCC; -} - - -#notice_text-count { -color:#333; -} -#form_notice.warning #notice_text-count { -color:#000; -} -#form_notice.processing #notice_action-submit { -background:#fff url(../../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; -cursor:wait; -text-indent:-9999px; -} - -#content, -#site_nav_local_views a, -#aside_primary { -border-color:#fff; -} -#content, -#site_nav_local_views .current a { -background-color:#fff; -} - -#site_nav_local_views a { -background-color:rgba(135, 180, 200, 0.3); -} -#site_nav_local_views a:hover { -background-color:rgba(255, 255, 255, 0.7); -} - - -.error { -background-color:#F7E8E8; -} -.success { -background-color:#EFF3DC; -} - - -#anon_notice { -background-color:#FEFFDF; -color:#333; -border-color:#fff; -} - -#showstream #anon_notice { -background-color:#FEFFDF; -} - - -#export_data li a { -background-repeat:no-repeat; -background-position:0 45%; -} -#export_data li a.rss { -background-image:url(../../../base/images/icons/icon_rss.png); -} -#export_data li a.atom { -background-image:url(../../../base/images/icons/icon_atom.png); -} -#export_data li a.foaf { -background-image:url(../../../base/images/icons/icon_foaf.gif); -} - -.entity_edit a, -.entity_send-a-message a, -.form_user_nudge input.submit, -.form_user_block input.submit, -.form_user_unblock input.submit, -.entity_nudge p { -background-position: 0 40%; -background-repeat: no-repeat; -background-color:transparent; -} -.form_group_join input.submit, -.form_group_leave input.submit -.form_user_subscribe input.submit, -.form_user_unsubscribe input.submit { -background-color:#9BB43E; -color:#fff; -} -.form_user_unsubscribe input.submit, -.form_group_leave input.submit { -background-color:#87B4C8; -} - -.entity_edit a { -background-image:url(../images/icons/twotone/green/edit.gif); -} -.entity_send-a-message a { -background-image:url(../images/icons/twotone/green/quote.gif); -} -.entity_nudge p, -.form_user_nudge input.submit { -background-image:url(../images/icons/twotone/green/mail.gif); -} -.form_user_block input.submit, -.form_user_unblock input.submit { -background-image:url(../images/icons/twotone/green/shield.gif); -} - - - -/* NOTICES */ -.notices li.over { -background-color:#fcfcfc; -} - -.notice-options .notice_reply a, -.notice-options form input.submit { -background-color:transparent; -} -.notice-options .notice_reply a { -background:transparent url(../images/icons/icon_reply.gif) no-repeat 0 45%; -} -.notice-options form.form_favor input.submit { -background:transparent url(../images/icons/icon_favourite.gif) no-repeat 0 45%; -} -.notice-options form.form_disfavor input.submit { -background:transparent url(../images/icons/icon_disfavourite.gif) no-repeat 0 45%; -} -.notice-options .notice_delete a { -background:transparent url(../images/icons/icon_trash.gif) no-repeat 0 45%; -} - -.notices div.entry-content, -.notices div.notice-options { -opacity:0.4; -} -.notices li.hover div.entry-content, -.notices li.hover div.notice-options { -opacity:1; -} -div.entry-content { -color:#333; -} -div.notice-options a, -div.notice-options input { -font-family:sans-serif; -} -.notices li.hover { -background-color:#fcfcfc; -} -/*END: NOTICES */ - - -#new_group a { -background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; -} - -.pagination .nav_prev a, -.pagination .nav_next a { -background-repeat:no-repeat; -border-color:#DDFFCC; -} -.pagination .nav_prev a { -background-image:url(../images/icons/twotone/green/arrow-left.gif); -background-position:10% 45%; -} -.pagination .nav_next a { -background-image:url(../images/icons/twotone/green/arrow-right.gif); -background-position:90% 45%; -} - - -/*--------------------------------------*/ - -#anon_notice { -background:url(../images/illustrations/illu_unicorn-01.png) no-repeat 0 0; -} -#showstream #anon_notice, -#content .notice p.entry-content a:visited, -content .notice p.entry-content .vcard a { -background-color:transparent; -} - -#anon_notice p { -background-color:#FEFFDF; -border-color:#FFFF00; -} - - -#form_notice .form_note { -color:#CCC; -} -input.submit { -background-color:#eee; -color:#666; -} - -.notices li.hover { -background-color:#F7F7F7; -} - - -.notice div.entry-content, -.notice div.entry-content a { -color:#999; -} - -.notices div.entry-content, -.notices div.notice-options { -opacity:1; -} - -#site_nav_local_views { -background-color:#DDFFCC; -} -#site_nav_local_views li, -#aside_primary { -border-color:#BDDCAD; -} -#site_nav_local_views a, -.aside .section h2 { -background-color:transparent; -border-color:transparent; -color:#4C4C4C; -} -#site_nav_local_views .current { -border-left-color:#fff; -} - -#site_nav_local_views .current a, -#site_nav_global_primary, -#footer { -background-color:#fff; -} - diff --git a/theme/cloudy/skin/default/images/icons/icon_atom.jpg b/theme/cloudy/skin/default/images/icons/icon_atom.jpg deleted file mode 100644 index 22853edc43ff04778001d28e5e14e64b32693f05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1117 zcmex=xE0R}-11_1^EW=25anV3L`8Hkvf zSy(w(Sy@>Qk2+yV?tKuefdm_beh zs;mXdF|Y`-3Mm>ovIz$!vMUve7&T5@$f4}C@t|nX#SbdRNkvVZTw>x9l2WQ_>Kd9_ zCZ=ZQ7M51dF0O9w9-dyoA)#U65s^{JDXD4c8JStdC8cHM6_r)ZEv;?s9i3g1CQq3< zZTgIvvlcC0vUJ(<6)RV5+Pr1!w(UE1?mBe%$kAiRPnGGAU*RJ2VdF$b$$4{O< zd;a3(tB;>PfBE|D`;VW$7#Wx$-T{&r{s9I*BNGb?GYdP&Ka5P}K+G)2!m4P(ZXWYowZ;xuvL#)F*7#z7xMlZq~KiK&=8RQ(9@64*z?d8mmjAHh8Y_s{=Z3_Q$? zz+}TL$Y9U#^*!s4{C`4kQ@{F)F8#NE<^7nNX{$BEX7;OWE|d3v8oxYgwT`W+-_*q- z+uzjLw=VzM)weYJobTH^U)E+Hs>*NOQoXkN(6;Tf#Fj2Ov+-`EuiCfmW$ej|9|&k>x-`dJy*iwaIS@snEOaP0Pi8o%z1YZ)MKM zRh|Np+Y=60roJjLZm^p5YSuI*^Cmyt+P{5LF*_nZUCA@@&Al93&$PVvpTfaM*5M!4 zAAY>*^{;80%VnnTYCTgO_i(zRpnz~I%X9Ugp$`rGx_=#0x)>OxdU^ku>!Q7(i@)aR QKG!^Hc0cZ<-tqr80k4%pzW@LL diff --git a/theme/cloudy/skin/default/images/icons/icon_rss.jpg b/theme/cloudy/skin/default/images/icons/icon_rss.jpg deleted file mode 100644 index da23422d0616d0d2925545214c2591b78dd1d6cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1166 zcmex=Qa5@J#!Vq&6< zKy9o*9jvTeqI^7je4?a+|3?@XF)%Q)GJ*jxbisg;3FsI$b`DN1ZUF`+pe0N!%pj)$ zRn`LK7+3^Zg%k}P*@OcV*_8@Kj2b5{ECr+Nabot8FYu9hwy!G(W<0ns_ zJ%91?)yGetzkL1n{m0K=j10^W?*K^*{{VxZk%@(cnS~wXA4aBfAZ8Y1VO2C_6LJh> zPb?HxGHT=yahkYr<3Ubk6e=l{~ZV&R(P($<#Tc_eT}|Zsr;?yuxz;gdKo>o08iH_ez(7J*Xx$0_w2DP{4nd=rPuyD z`a)(@-l|)kedxsE9m)%3QmU^v_nh7s>82){>G!efn0MO#wHIGL{c+0jtmNgD(xyum zefR%$bCwl<_gg!Wm##8d)9z_*-yNvB?~T)ip1kmw&vVT4op{R=4C8OwoLuR)CoA_` zOx3bo_v7ZyN>|fo)OqB&T-^0={g$N{mw&I*Tx@-;&iYcF!b_?4mOt{Tt77hWuXV3n z?EbBWV{xfmmW=#VXK{s+mvPsWMca>EoX5{A_C9zP*X`J>JyYMgG3%|L9@=Its - * @author Sarven Capadisli - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -body { -font-size:2.5em; -} - -#wrap { -width:95%; -} - -#header, -#header address, -#anon_notice, -#site_nav_local_views .nav, -#form_notice, -#form_notice .form_data li, -#core, -#content_inner, -#notices_primary, -.notice, -.notice .entry-title, -.notice div.entry-content, -.notice-options, -.notice .notice-options a, -.pagination, -.pagination .nav, -.aside .section { -float:none; -} - -.notice-options .notice_reply, -.notice-options .notice_delete, -.notice-options .form_favor, -.notice-options .form_disfavor { -position:static; -} - -#form_notice, -#anon_notice, -#footer, -#form_notice .form_actions input.submit { -width:auto; -} - -.form_settings label { -width:25%; -} -.form_settings .form_data p.form_guide { -margin-left:26%; -} - -#site_nav_global_primary { -width:75%; -} - -.entity_profile { -width:65%; -} -.entity_actions { -margin-left:0; -} - -#form_notice, -#anon_notice { -clear:both; -} - -#content, -#aside_primary { -width:96%; -padding-left:2%; -padding-right:2%; -} - -#site_notice { -position:static; -float:right; -clear:right; -width:75%; -margin-right:0; -margin-bottom:11px; -} - -.notices { -font-size:1.5em; -} - -#form_notice textarea { -width:80%; -height:5em; -} -#form_notice .form_note { -right:20%; -top:6em; -} - - -.vcard .photo, -.section .vcard .photo { -margin-right:18px; -} -.notice, -.profile { -margin-bottom:18px; -} - -.notices .entry-title, -.notices div.entry-content { -width:90%; -} -.notice div.entry-content { -margin-left:0; -} - -.notice .author .photo { -height:4.5em; -width:4.5em; -} -.notice-options { -position:absolute; -top:0; -right:0; -padding-left:7%; -width:3%; -} - -.notice-options .notice_delete a { -float:left; -} -.pagination .nav { -overflow:auto; -} - -#export_data { -display:none; -} - -#site_nav_local_views li { -margin-right:4px; -} -#site_nav_local_views a { -padding:18px 11px; -} diff --git a/theme/default/base/css/print.css b/theme/default/base/css/print.css deleted file mode 100644 index d76dd608c4..0000000000 --- a/theme/default/base/css/print.css +++ /dev/null @@ -1,36 +0,0 @@ -/** theme: base - * - * @package Laconica - * @author Sarven Capadisli - * @copyright 2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -a:after { background-color:#fff; } -a:not([href^="#"]):after { content:" ( "attr(href)" ) "; } - -img { border:none; } -p { orphans: 2; widows: 1; } - -#site_nav_global_primary, -#site_nav_local_views, -#form_notice, -.pagination, -#site_nav_global_secondary, -.entity_actions, -.notice-options, -#aside_primary, -.form_subscription_edit .submit { -display:none; -} - -.timestamp dt, .timestamp dd, -.device dt, .device dd { -display:inline; -} - -.profiles li, -.notices li { -margin-bottom:18px; -} diff --git a/theme/default/base/css/thickbox.css b/theme/default/base/css/thickbox.css deleted file mode 100644 index d24b9bedff..0000000000 --- a/theme/default/base/css/thickbox.css +++ /dev/null @@ -1,163 +0,0 @@ -/* ----------------------------------------------------------------------------------------------------------------*/ -/* ---------->>> global settings needed for thickbox <<<-----------------------------------------------------------*/ -/* ----------------------------------------------------------------------------------------------------------------*/ -*{padding: 0; margin: 0;} - -/* ----------------------------------------------------------------------------------------------------------------*/ -/* ---------->>> thickbox specific link and font settings <<<------------------------------------------------------*/ -/* ----------------------------------------------------------------------------------------------------------------*/ -#TB_window { - font: 12px Arial, Helvetica, sans-serif; - color: #333333; -} - -#TB_secondLine { - font: 10px Arial, Helvetica, sans-serif; - color:#666666; -} - -#TB_window a:link {color: #666666;} -#TB_window a:visited {color: #666666;} -#TB_window a:hover {color: #000;} -#TB_window a:active {color: #666666;} -#TB_window a:focus{color: #666666;} - -/* ----------------------------------------------------------------------------------------------------------------*/ -/* ---------->>> thickbox settings <<<-----------------------------------------------------------------------------*/ -/* ----------------------------------------------------------------------------------------------------------------*/ -#TB_overlay { - position: fixed; - z-index:100; - top: 0px; - left: 0px; - height:100%; - width:100%; -} - -.TB_overlayMacFFBGHack {background: url(macFFBgHack.png) repeat;} -.TB_overlayBG { - background-color:#000; - filter:alpha(opacity=75); - -moz-opacity: 0.75; - opacity: 0.75; -} - -* html #TB_overlay { /* ie6 hack */ - position: absolute; - height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); -} - -#TB_window { - position: fixed; - background: #ffffff; - z-index: 102; - color:#000000; - display:none; - border: 4px solid #525252; - text-align:left; - top:50%; - left:50%; -} - -* html #TB_window { /* ie6 hack */ -position: absolute; -margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px'); -} - -#TB_window img#TB_Image { - display:block; - margin: 15px 0 0 15px; - border-right: 1px solid #ccc; - border-bottom: 1px solid #ccc; - border-top: 1px solid #666; - border-left: 1px solid #666; -} - -#TB_caption{ - height:25px; - padding:7px 30px 10px 25px; - float:left; -} - -#TB_closeWindow{ - height:25px; - padding:11px 25px 10px 0; - float:right; -} - -#TB_closeAjaxWindow{ - padding:7px 10px 5px 0; - margin-bottom:1px; - text-align:right; - float:right; -} - -#TB_ajaxWindowTitle{ - float:left; - padding:7px 0 5px 10px; - margin-bottom:1px; -} - -#TB_title{ - background-color:#e8e8e8; - height:27px; -} - -#TB_ajaxContent{ - clear:both; - padding:2px 15px 15px 15px; - overflow:auto; - text-align:left; - line-height:1.4em; -} - -#TB_ajaxContent.TB_modal{ - padding:15px; -} - -#TB_ajaxContent p{ - padding:5px 0px 5px 0px; -} - -#TB_load{ - position: fixed; - display:none; - height:13px; - width:208px; - z-index:103; - top: 50%; - left: 50%; - margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */ -} - -* html #TB_load { /* ie6 hack */ -position: absolute; -margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px'); -} - -#TB_HideSelect{ - z-index:99; - position:fixed; - top: 0; - left: 0; - background-color:#fff; - border:none; - filter:alpha(opacity=0); - -moz-opacity: 0; - opacity: 0; - height:100%; - width:100%; -} - -* html #TB_HideSelect { /* ie6 hack */ - position: absolute; - height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); -} - -#TB_iframeContent{ - clear:both; - border:none; - margin-bottom:-1px; - margin-top:1px; - _margin-bottom:1px; -} diff --git a/theme/default/base/images/icons/icon_foaf.gif b/theme/default/base/images/icons/icon_foaf.gif deleted file mode 100644 index f8f78442355bf0d0b509536bca7c57b4eedab04a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1144 zcmd^;?N1ta0Dyn!iB*(>T3&i*JrF8R7w1whHElM8C<3ml?j+W9-3dwyO`2L|HqDkn z5%F#4%5=zqhahRU8WmVVw{A%ro6Wr`PE6ceVj2??L*}%}w$5a?_V3v9;raf2cvR|! zleHa30UP`^2O^P(TCHAKSg=~He14Hqsif%uZ8F&hVl+)kq!MMLzPTBX#bWfui_Upx zD&?A({APN6nl_tVpScF^4um#Ch!`OgWH@Z1X>XUc>*oB;p^^I*kHugxqzIz#MkuV+ z27e0fbavY2Z0Yob-EJpWNrkE-kx0z`GV7<3B)Q`M(a*|fwO?ze5|oczl~rJTgzvcP zz!1czQbk)^OUg=ic0LdYc>Kb`Zg=9odT3ob5qn5U- zZT@vXO;3k^3m?hNp^{WgtIf?~Vi*>WTf)DFYicA*OYfDHpIEwZfu=*Xwa2whum5W{ zlO!obgc%u(w8@kv2n>cj-+78r7)Id$weIzL7Z!R>!0^-*v5e!F&8~w3Z(YM%0)Y@I zE{Nm!F$q#$j-}IMH89-M7w}AdKk~&$^8EQ0k%;<%3Q);-{B4CovDekr^qO&h-@R)# zADB!U?U`h6#s5A^?%aeE|u=?euQDt>S{El*K_kZ{mxHA zKZiIhc5pN3^BG3p|I*eU;lW3AS9DcXD27Q~_gwCYuVpe!2=hknj|h-5S$U0@T;=iD z)k0w^HAb$Gi#YE0tpNaNntta0C!(hi1AsYD`8@ym6W|aH&PB`*h_CXP`B1cFukIl$ zs|1(%WPd!$fVg5p|HQsAS^bi1b0#pP6%J=GW{H{G^{kf%TYUG<8ipXeV7Bse-~cv| zbFQln4K0m}iaXIuv5tC2w(J<*7GbcULq^Pkw5D#|;fUDp4ksPTyrZ@I+X3#gFQA-x zk0&Fbfm(V`Kb^8?Lhb_Ijq8^l&o~_g;dlNH1SJ|q-7P$;xu;vu8g;$-KF`Z%EK&)8HeT>g)Y#vUAp}MLgmL1PV~(!a7HD+ zI?Nr*lXC$Eu30nL$d)62zg!{*uVkS>^T@WwmwfEeqXVc$01lsS6Nu{>3~=f{5zlh9 diff --git a/theme/default/base/images/icons/icon_processing.gif b/theme/default/base/images/icons/icon_processing.gif deleted file mode 100644 index d0bce1542342e912da81a2c260562df172f30d73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nnmm28Kh24mmkF0U1e2Nli^nlO|14{Lk&@8WQa67~pE8 zXTZz|lvDgC+Z`3#dv5h=E26FfcG1 zbL_hF&)}42ws10s6^G;;cE1^EoUR)U5A70}d2pLv!jVIT7j&Z~EblI3x0K*v_sV|m z0kj3v921Z^em#l`(k(o@H$3ZdDRc@9NidXDNbqrumReCGv$gd8+e8WW28HVqkJ_9i zH>s*<31KtHjANIPvi2#*6BEu%3Dak5O_t&NBI)H?V$TxT}#l{vOTn5naXTfF^&~Hhq+NX@#Ccc>y7T?;vjI&jdhsDsPJyAw*m0Qz>i}K7# zL9w50Ng{fT}A5JUe8lRK1h7_Y2;BWJDd=c6f&i?Wv5(5q?6|P zQw{>maxZP<537OA37Uk}7@%_$4o$EWe_Zl>&#id|lE-BpDC#+Fn|msJ%_2h{Hg1vP z#N8WAzfWasG}yq|xqE)DrWaOofX=z|?*pgc%{ig5vl!pqDlC|q&~Z0$&Rvsft&VO- z4MZj+%-+Vx%W}v;V76hyp=;+R;x+~t^Q%*xuFTQAF2})fSfTHDAs>sO!OBw`)&)o$ c0!CNZt))x~rAZP^^P&YOFfdqy5)K#u0POD40{{R3 diff --git a/theme/default/base/images/icons/icon_vcard.gif b/theme/default/base/images/icons/icon_vcard.gif deleted file mode 100644 index 6d52947f3e96c0f74f00a80b430f99695e110e5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmV-R0kr-{Nk%w1VHW@n0K^{vi^LV;@6MUi1^D~(*6OmW*GsnCZu9x+db$Rr+7rg( zj*Y_!l*MRc(@bU8V@GBo706UV+d;tIe diff --git a/theme/default/skin/default/css/display.css b/theme/default/css/display.css similarity index 76% rename from theme/default/skin/default/css/display.css rename to theme/default/css/display.css index e290c208b0..2f41a9843c 100644 --- a/theme/default/skin/default/css/display.css +++ b/theme/default/css/display.css @@ -7,6 +7,8 @@ * @link http://laconi.ca/ */ +@import url(../../base/css/display.css); + html, body, a:active { @@ -90,7 +92,7 @@ color:#333; color:#000; } #form_notice.processing #notice_action-submit { -background:#fff url(../../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; cursor:wait; text-indent:-9999px; } @@ -137,13 +139,13 @@ background-repeat:no-repeat; background-position:0 45%; } #export_data li a.rss { -background-image:url(../../../base/images/icons/icon_rss.png); +background-image:url(../../base/images/icons/icon_rss.png); } #export_data li a.atom { -background-image:url(../../../base/images/icons/icon_atom.png); +background-image:url(../../base/images/icons/icon_atom.png); } #export_data li a.foaf { -background-image:url(../../../base/images/icons/icon_foaf.gif); +background-image:url(../../base/images/icons/icon_foaf.gif); } .entity_edit a, @@ -170,18 +172,18 @@ background-color:#97BFD1; } .entity_edit a { -background-image:url(../images/icons/twotone/green/edit.gif); +background-image:url(../../base/images/icons/twotone/green/edit.gif); } .entity_send-a-message a { -background-image:url(../images/icons/twotone/green/quote.gif); +background-image:url(../../base/images/icons/twotone/green/quote.gif); } .entity_nudge p, .form_user_nudge input.submit { -background-image:url(../images/icons/twotone/green/mail.gif); +background-image:url(../../base/images/icons/twotone/green/mail.gif); } .form_user_block input.submit, .form_user_unblock input.submit { -background-image:url(../images/icons/twotone/green/shield.gif); +background-image:url(../../base/images/icons/twotone/green/shield.gif); } @@ -196,16 +198,16 @@ background-color:#fcfcfc; background-color:transparent; } .notice-options .notice_reply a { -background:transparent url(../images/icons/twotone/green/reply.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; } .notice-options form.form_favor input.submit { -background:transparent url(../images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; } .notice-options form.form_disfavor input.submit { -background:transparent url(../images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; } .notice-options .notice_delete a { -background:transparent url(../images/icons/twotone/green/trash.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; } .notices div.entry-content, @@ -230,7 +232,7 @@ background-color:#fcfcfc; #new_group a { -background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; } .pagination .nav_prev a, @@ -239,10 +241,10 @@ background-repeat:no-repeat; border-color:#D1D9E4; } .pagination .nav_prev a { -background-image:url(../images/icons/twotone/green/arrow-left.gif); +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); background-position:10% 45%; } .pagination .nav_next a { -background-image:url(../images/icons/twotone/green/arrow-right.gif); +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); background-position:90% 45%; } diff --git a/theme/default/skin/default/css/ie.css b/theme/default/css/ie.css similarity index 100% rename from theme/default/skin/default/css/ie.css rename to theme/default/css/ie.css diff --git a/theme/default/skin/default/images/icons/icon_atom.jpg b/theme/default/skin/default/images/icons/icon_atom.jpg deleted file mode 100644 index 22853edc43ff04778001d28e5e14e64b32693f05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1117 zcmex=xE0R}-11_1^EW=25anV3L`8Hkvf zSy(w(Sy@>Qk2+yV?tKuefdm_beh zs;mXdF|Y`-3Mm>ovIz$!vMUve7&T5@$f4}C@t|nX#SbdRNkvVZTw>x9l2WQ_>Kd9_ zCZ=ZQ7M51dF0O9w9-dyoA)#U65s^{JDXD4c8JStdC8cHM6_r)ZEv;?s9i3g1CQq3< zZTgIvvlcC0vUJ(<6)RV5+Pr1!w(UE1?mBe%$kAiRPnGGAU*RJ2VdF$b$$4{O< zd;a3(tB;>PfBE|D`;VW$7#Wx$-T{&r{s9I*BNGb?GYdP&Ka5P}K+G)2!m4P(ZXWYowZ;xuvL#)F*7#z7xMlZq~KiK&=8RQ(9@64*z?d8mmjAHh8Y_s{=Z3_Q$? zz+}TL$Y9U#^*!s4{C`4kQ@{F)F8#NE<^7nNX{$BEX7;OWE|d3v8oxYgwT`W+-_*q- z+uzjLw=VzM)weYJobTH^U)E+Hs>*NOQoXkN(6;Tf#Fj2Ov+-`EuiCfmW$ej|9|&k>x-`dJy*iwaIS@snEOaP0Pi8o%z1YZ)MKM zRh|Np+Y=60roJjLZm^p5YSuI*^Cmyt+P{5LF*_nZUCA@@&Al93&$PVvpTfaM*5M!4 zAAY>*^{;80%VnnTYCTgO_i(zRpnz~I%X9Ugp$`rGx_=#0x)>OxdU^ku>!Q7(i@)aR QKG!^Hc0cZ<-tqr80k4%pzW@LL diff --git a/theme/default/skin/default/images/icons/icon_foaf.gif b/theme/default/skin/default/images/icons/icon_foaf.gif deleted file mode 100644 index f8f78442355bf0d0b509536bca7c57b4eedab04a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1144 zcmd^;?N1ta0Dyn!iB*(>T3&i*JrF8R7w1whHElM8C<3ml?j+W9-3dwyO`2L|HqDkn z5%F#4%5=zqhahRU8WmVVw{A%ro6Wr`PE6ceVj2??L*}%}w$5a?_V3v9;raf2cvR|! zleHa30UP`^2O^P(TCHAKSg=~He14Hqsif%uZ8F&hVl+)kq!MMLzPTBX#bWfui_Upx zD&?A({APN6nl_tVpScF^4um#Ch!`OgWH@Z1X>XUc>*oB;p^^I*kHugxqzIz#MkuV+ z27e0fbavY2Z0Yob-EJpWNrkE-kx0z`GV7<3B)Q`M(a*|fwO?ze5|oczl~rJTgzvcP zz!1czQbk)^OUg=ic0LdYc>Kb`Zg=9odT3ob5qn5U- zZT@vXO;3k^3m?hNp^{WgtIf?~Vi*>WTf)DFYicA*OYfDHpIEwZfu=*Xwa2whum5W{ zlO!obgc%u(w8@kv2n>cj-+78r7)Id$weIzL7Z!R>!0^-*v5e!F&8~w3Z(YM%0)Y@I zE{Nm!F$q#$j-}IMH89-M7w}AdKk~&$^8EQ0k%;<%3Q);-{B4CovDekr^qO&h-@R)# zADB!U?U`h6#s5A^?%aeE|u=?euQDt>S{El*K_kZ{mxHA zKZiIhc5pN3^BG3p|I*eU;lW3AS9DcXD27Q~_gwCYuVpe!2=hknj|h-5S$U0@T;=iD z)k0w^HAb$Gi#YE0tpNaNntta0C!(hi1AsYD`8@ym6W|aH&PB`*h_CXP`B1cFukIl$ zs|1(%WPd!$fVg5p|HQsAS^bi1b0#pP6%J=GW{H{G^{kf%TYUG<8ipXeV7Bse-~cv| zbFQln4K0m}iaXIuv5tC2w(J<*7GbcULq^Pkw5D#|;fUDp4ksPTyrZ@I+X3#gFQA-x zk0&Fbfm(V`Kb^8?Lhb_Ijq8^l&o~_g;dlNH1SJ|q-7P$;xu;vu8g;$-KF`Z%EK&)8HeT>g)Y#vUAp}MLgmL1PV~(!a7HD+ zI?Nr*lXC$Eu30nL$d)62zg!{*uVkS>^T@WwmwfEeqXVc$01lsS6Nu{>3~=f{5zlh9 diff --git a/theme/default/skin/default/images/icons/icon_rss.jpg b/theme/default/skin/default/images/icons/icon_rss.jpg deleted file mode 100644 index da23422d0616d0d2925545214c2591b78dd1d6cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1166 zcmex=Qa5@J#!Vq&6< zKy9o*9jvTeqI^7je4?a+|3?@XF)%Q)GJ*jxbisg;3FsI$b`DN1ZUF`+pe0N!%pj)$ zRn`LK7+3^Zg%k}P*@OcV*_8@Kj2b5{ECr+Nabot8FYu9hwy!G(W<0ns_ zJ%91?)yGetzkL1n{m0K=j10^W?*K^*{{VxZk%@(cnS~wXA4aBfAZ8Y1VO2C_6LJh> zPb?HxGHT=yahkYr<3Ubk6e=l{~ZV&R(P($<#Tc_eT}|Zsr;?yuxz;gdKo>o08iH_ez(7J*Xx$0_w2DP{4nd=rPuyD z`a)(@-l|)kedxsE9m)%3QmU^v_nh7s>82){>G!efn0MO#wHIGL{c+0jtmNgD(xyum zefR%$bCwl<_gg!Wm##8d)9z_*-yNvB?~T)ip1kmw&vVT4op{R=4C8OwoLuR)CoA_` zOx3bo_v7ZyN>|fo)OqB&T-^0={g$N{mw&I*Tx@-;&iYcF!b_?4mOt{Tt77hWuXV3n z?EbBWV{xfmmW=#VXK{s+mvPsWMca>EoX5{A_C9zP*X`J>JyYMgG3%|L9@=ItsMRc(@bU8V@GBo706UV+d;tIe diff --git a/theme/default/skin/identica/images/icons/icon_atom.jpg b/theme/default/skin/identica/images/icons/icon_atom.jpg deleted file mode 100644 index 22853edc43ff04778001d28e5e14e64b32693f05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1117 zcmex=xE0R}-11_1^EW=25anV3L`8Hkvf zSy(w(Sy@>Qk2+yV?tKuefdm_beh zs;mXdF|Y`-3Mm>ovIz$!vMUve7&T5@$f4}C@t|nX#SbdRNkvVZTw>x9l2WQ_>Kd9_ zCZ=ZQ7M51dF0O9w9-dyoA)#U65s^{JDXD4c8JStdC8cHM6_r)ZEv;?s9i3g1CQq3< zZTgIvvlcC0vUJ(<6)RV5+Pr1!w(UE1?mBe%$kAiRPnGGAU*RJ2VdF$b$$4{O< zd;a3(tB;>PfBE|D`;VW$7#Wx$-T{&r{s9I*BNGb?GYdP&Ka5P}K+G)2!m4P(ZXWYowZ;xuvL#)F*7#z7xMlZq~KiK&=8RQ(9@64*z?d8mmjAHh8Y_s{=Z3_Q$? zz+}TL$Y9U#^*!s4{C`4kQ@{F)F8#NE<^7nNX{$BEX7;OWE|d3v8oxYgwT`W+-_*q- z+uzjLw=VzM)weYJobTH^U)E+Hs>*NOQoXkN(6;Tf#Fj2Ov+-`EuiCfmW$ej|9|&k>x-`dJy*iwaIS@snEOaP0Pi8o%z1YZ)MKM zRh|Np+Y=60roJjLZm^p5YSuI*^Cmyt+P{5LF*_nZUCA@@&Al93&$PVvpTfaM*5M!4 zAAY>*^{;80%VnnTYCTgO_i(zRpnz~I%X9Ugp$`rGx_=#0x)>OxdU^ku>!Q7(i@)aR QKG!^Hc0cZ<-tqr80k4%pzW@LL diff --git a/theme/default/skin/identica/images/icons/icon_foaf.gif b/theme/default/skin/identica/images/icons/icon_foaf.gif deleted file mode 100644 index f8f78442355bf0d0b509536bca7c57b4eedab04a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1144 zcmd^;?N1ta0Dyn!iB*(>T3&i*JrF8R7w1whHElM8C<3ml?j+W9-3dwyO`2L|HqDkn z5%F#4%5=zqhahRU8WmVVw{A%ro6Wr`PE6ceVj2??L*}%}w$5a?_V3v9;raf2cvR|! zleHa30UP`^2O^P(TCHAKSg=~He14Hqsif%uZ8F&hVl+)kq!MMLzPTBX#bWfui_Upx zD&?A({APN6nl_tVpScF^4um#Ch!`OgWH@Z1X>XUc>*oB;p^^I*kHugxqzIz#MkuV+ z27e0fbavY2Z0Yob-EJpWNrkE-kx0z`GV7<3B)Q`M(a*|fwO?ze5|oczl~rJTgzvcP zz!1czQbk)^OUg=ic0LdYc>Kb`Zg=9odT3ob5qn5U- zZT@vXO;3k^3m?hNp^{WgtIf?~Vi*>WTf)DFYicA*OYfDHpIEwZfu=*Xwa2whum5W{ zlO!obgc%u(w8@kv2n>cj-+78r7)Id$weIzL7Z!R>!0^-*v5e!F&8~w3Z(YM%0)Y@I zE{Nm!F$q#$j-}IMH89-M7w}AdKk~&$^8EQ0k%;<%3Q);-{B4CovDekr^qO&h-@R)# zADB!U?U`h6#s5A^?%aeE|u=?euQDt>S{El*K_kZ{mxHA zKZiIhc5pN3^BG3p|I*eU;lW3AS9DcXD27Q~_gwCYuVpe!2=hknj|h-5S$U0@T;=iD z)k0w^HAb$Gi#YE0tpNaNntta0C!(hi1AsYD`8@ym6W|aH&PB`*h_CXP`B1cFukIl$ zs|1(%WPd!$fVg5p|HQsAS^bi1b0#pP6%J=GW{H{G^{kf%TYUG<8ipXeV7Bse-~cv| zbFQln4K0m}iaXIuv5tC2w(J<*7GbcULq^Pkw5D#|;fUDp4ksPTyrZ@I+X3#gFQA-x zk0&Fbfm(V`Kb^8?Lhb_Ijq8^l&o~_g;dlNH1SJ|q-7P$;xu;vu8g;$-KF`Z%EK&)8HeT>g)Y#vUAp}MLgmL1PV~(!a7HD+ zI?Nr*lXC$Eu30nL$d)62zg!{*uVkS>^T@WwmwfEeqXVc$01lsS6Nu{>3~=f{5zlh9 diff --git a/theme/default/skin/identica/images/icons/icon_rss.jpg b/theme/default/skin/identica/images/icons/icon_rss.jpg deleted file mode 100644 index da23422d0616d0d2925545214c2591b78dd1d6cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1166 zcmex=Qa5@J#!Vq&6< zKy9o*9jvTeqI^7je4?a+|3?@XF)%Q)GJ*jxbisg;3FsI$b`DN1ZUF`+pe0N!%pj)$ zRn`LK7+3^Zg%k}P*@OcV*_8@Kj2b5{ECr+Nabot8FYu9hwy!G(W<0ns_ zJ%91?)yGetzkL1n{m0K=j10^W?*K^*{{VxZk%@(cnS~wXA4aBfAZ8Y1VO2C_6LJh> zPb?HxGHT=yahkYr<3Ubk6e=l{~ZV&R(P($<#Tc_eT}|Zsr;?yuxz;gdKo>o08iH_ez(7J*Xx$0_w2DP{4nd=rPuyD z`a)(@-l|)kedxsE9m)%3QmU^v_nh7s>82){>G!efn0MO#wHIGL{c+0jtmNgD(xyum zefR%$bCwl<_gg!Wm##8d)9z_*-yNvB?~T)ip1kmw&vVT4op{R=4C8OwoLuR)CoA_` zOx3bo_v7ZyN>|fo)OqB&T-^0={g$N{mw&I*Tx@-;&iYcF!b_?4mOt{Tt77hWuXV3n z?EbBWV{xfmmW=#VXK{s+mvPsWMca>EoX5{A_C9zP*X`J>JyYMgG3%|L9@=ItsMRc(@bU8V@GBo706UV+d;tIe diff --git a/theme/default/skin/identica/images/icons/twotone/green/arrow-left.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-left.gif deleted file mode 100644 index afed190841f8b88f930d0dfe7030339f8aea296c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b*`erVB%fEOI ZBSY5uGcnueIVwI2eAel8Mn#0d8UQdZ7iIte diff --git a/theme/default/skin/identica/images/icons/twotone/green/arrow-right.gif b/theme/default/skin/identica/images/icons/twotone/green/arrow-right.gif deleted file mode 100644 index ee1707ed96a315d287e778dd7650fdad9f5ccc55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b+`erVB%fEOI a2ZPj`+FkFTWlpxJyV1Ff%b1gu!5RQfjTe{z diff --git a/theme/default/skin/identica/images/icons/twotone/green/disfavourite.gif b/theme/default/skin/identica/images/icons/twotone/green/disfavourite.gif deleted file mode 100644 index 3946869ae070474df5622c56ba6d0984bb06af5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88 zcmZ?wbhEHb6krfwSjfQe|NsB^DFQ$e2o!&^FfuSOG3YP=0Z5*KNi(ExCfnQpd~^IR nW#;qjPMx6XakMgtb5Z7{-1x4Q%h>kLs(l!eFlSK!1A{dHn&}~% diff --git a/theme/default/skin/identica/images/icons/twotone/green/edit.gif b/theme/default/skin/identica/images/icons/twotone/green/edit.gif deleted file mode 100644 index c746aca601dfce71bec63cc34bd2cea576a608c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F5`erVB%fFb# bLC#BkUBTx**BG_BS(!^$or-W`WUvMRPNf%3 diff --git a/theme/default/skin/identica/images/icons/twotone/green/favourite.gif b/theme/default/skin/identica/images/icons/twotone/green/favourite.gif deleted file mode 100644 index d93515e3790aa4672656512f416edf2c5c30f2f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J5b*`erVB%fEOI Z!yK;F*Ye-L@sv;Xeb%|`jEV?@H2^xX7##or diff --git a/theme/default/skin/identica/images/icons/twotone/green/mail.gif b/theme/default/skin/identica/images/icons/twotone/green/mail.gif deleted file mode 100644 index 1084c862f62fd5490abc582fcfe7b577d450efff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J4=s`erVB%fEQa if?KZ~c0{bs%Z(FiQZABxslH78RN`eH|DIR|25SH{2phKm diff --git a/theme/default/skin/identica/images/icons/twotone/green/news.gif b/theme/default/skin/identica/images/icons/twotone/green/news.gif deleted file mode 100644 index 712c685dc0b02b2bfd262e9007b7a8ce0f81e2e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J3F6`erVB%dgDh c(B`#%N#&>iH4Co$ilZOy#&cDmB_R$kzum%90svYG3 diff --git a/theme/default/skin/identica/images/icons/twotone/green/trash.gif b/theme/default/skin/identica/images/icons/twotone/green/trash.gif deleted file mode 100644 index 78dd64a3d8a2ee60d4696de96c0e5b2945cafe98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmZ?wbhEHb6krfwn8?KN|NsB^DFQ%}fq_BsCkrD30~3P|kPVa-0J7ym`erVB%g;YU d;ZpSCX%+k4SteZTk*_G5uxqQ-W=>WHYXF^I8F2sr diff --git a/theme/default/skin/identica/css/display.css b/theme/identica/css/display.css similarity index 76% rename from theme/default/skin/identica/css/display.css rename to theme/identica/css/display.css index a44b8cdd70..a961188979 100644 --- a/theme/default/skin/identica/css/display.css +++ b/theme/identica/css/display.css @@ -7,6 +7,8 @@ * @link http://laconi.ca/ */ +@import url(../../base/css/display.css); + html, body, a:active { @@ -90,7 +92,7 @@ color:#333; color:#000; } #form_notice.processing #notice_action-submit { -background:#fff url(../../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; cursor:wait; text-indent:-9999px; } @@ -137,13 +139,13 @@ background-repeat:no-repeat; background-position:0 45%; } #export_data li a.rss { -background-image:url(../../../base/images/icons/icon_rss.png); +background-image:url(../../base/images/icons/icon_rss.png); } #export_data li a.atom { -background-image:url(../../../base/images/icons/icon_atom.png); +background-image:url(../../base/images/icons/icon_atom.png); } #export_data li a.foaf { -background-image:url(../../../base/images/icons/icon_foaf.gif); +background-image:url(../../base/images/icons/icon_foaf.gif); } .entity_edit a, @@ -170,18 +172,18 @@ background-color:#87B4C8; } .entity_edit a { -background-image:url(../images/icons/twotone/green/edit.gif); +background-image:url(../../base/images/icons/twotone/green/edit.gif); } .entity_send-a-message a { -background-image:url(../images/icons/twotone/green/quote.gif); +background-image:url(../../base/images/icons/twotone/green/quote.gif); } .entity_nudge p, .form_user_nudge input.submit { -background-image:url(../images/icons/twotone/green/mail.gif); +background-image:url(../../base/images/icons/twotone/green/mail.gif); } .form_user_block input.submit, .form_user_unblock input.submit { -background-image:url(../images/icons/twotone/green/shield.gif); +background-image:url(../../base/images/icons/twotone/green/shield.gif); } @@ -196,16 +198,16 @@ background-color:#fcfcfc; background-color:transparent; } .notice-options .notice_reply a { -background:transparent url(../images/icons/twotone/green/reply.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; } .notice-options form.form_favor input.submit { -background:transparent url(../images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; } .notice-options form.form_disfavor input.submit { -background:transparent url(../images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; } .notice-options .notice_delete a { -background:transparent url(../images/icons/twotone/green/trash.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; } .notices div.entry-content, @@ -230,7 +232,7 @@ background-color:#fcfcfc; #new_group a { -background:transparent url(../images/icons/twotone/green/news.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; } .pagination .nav_prev a, @@ -239,10 +241,10 @@ background-repeat:no-repeat; border-color:#CEE1E9; } .pagination .nav_prev a { -background-image:url(../images/icons/twotone/green/arrow-left.gif); +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); background-position:10% 45%; } .pagination .nav_next a { -background-image:url(../images/icons/twotone/green/arrow-right.gif); +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); background-position:90% 45%; } diff --git a/theme/default/skin/identica/css/ie.css b/theme/identica/css/ie.css similarity index 100% rename from theme/default/skin/identica/css/ie.css rename to theme/identica/css/ie.css diff --git a/theme/identica/default-avatar-mini.png b/theme/identica/default-avatar-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..38b8692b4a2f71c8de3d6a12b715df33aada5f7c GIT binary patch literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b literal 0 HcmV?d00001 diff --git a/theme/identica/default-avatar-profile.png b/theme/identica/default-avatar-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..f8357d4fc296271b837b3d9911cfbc133918ef2f GIT binary patch literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi literal 0 HcmV?d00001 diff --git a/theme/identica/logo.png b/theme/identica/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7c68b34f61008753d12394806c3cf46f7b04effd GIT binary patch literal 4988 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 Date: Tue, 14 Apr 2009 23:17:25 +0000 Subject: [PATCH 358/503] Removed skin config option --- config.php.sample | 1 - 1 file changed, 1 deletion(-) diff --git a/config.php.sample b/config.php.sample index 4c4c9f08bc..b8ed45fa83 100644 --- a/config.php.sample +++ b/config.php.sample @@ -18,7 +18,6 @@ $config['site']['server'] = 'localhost'; $config['site']['path'] = 'laconica'; #$config['site']['fancy'] = false; #$config['site']['theme'] = 'default'; -#$config['site']['skin'] = 'default'; #To enable the built-in mobile style sheet, defaults to false. #$config['site']['mobile'] = true; #For contact email, defaults to $_SERVER["SERVER_ADMIN"] From 64e4b8a20f5ec3fb4f1a4c68337ae40b1b0b0dcf Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 14 Apr 2009 23:32:09 +0000 Subject: [PATCH 359/503] Updated remaining files and styles for style separation for themes --- actions/avatarsettings.php | 2 +- actions/designsettings.php | 2 +- theme/base/css/farbtastic.css | 6 +++--- theme/base/images/icons/icon_processing.gif | Bin 0 -> 673 bytes theme/cloudy/css/display.css | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 theme/base/images/icons/icon_processing.gif diff --git a/actions/avatarsettings.php b/actions/avatarsettings.php index 60f69b6850..c2bb35a395 100644 --- a/actions/avatarsettings.php +++ b/actions/avatarsettings.php @@ -383,7 +383,7 @@ class AvatarsettingsAction extends AccountSettingsAction { parent::showStylesheets(); $jcropStyle = - common_path('theme/default/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION); + common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION); $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', diff --git a/actions/designsettings.php b/actions/designsettings.php index 05293f7126..cdd950e78c 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -196,7 +196,7 @@ class DesignsettingsAction extends AccountSettingsAction { parent::showStylesheets(); $farbtasticStyle = - common_path('theme/default/base/css/farbtastic.css?version='.LACONICA_VERSION); + common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION); $this->element('link', array('rel' => 'stylesheet', 'type' => 'text/css', diff --git a/theme/base/css/farbtastic.css b/theme/base/css/farbtastic.css index 3b8fec58f8..7efcc73c3b 100644 --- a/theme/base/css/farbtastic.css +++ b/theme/base/css/farbtastic.css @@ -16,17 +16,17 @@ height: 101px; } .farbtastic .wheel { - background: url(../../../../js/farbtastic/wheel.png) no-repeat; + background: url(../../../js/farbtastic/wheel.png) no-repeat; width: 195px; height: 195px; } .farbtastic .overlay { - background: url(../../../../js/farbtastic/mask.png) no-repeat; + background: url(../../../js/farbtastic/mask.png) no-repeat; } .farbtastic .marker { width: 17px; height: 17px; margin: -8px 0 0 -8px; overflow: hidden; - background: url(../../../../js/farbtastic/marker.png) no-repeat; + background: url(../../../js/farbtastic/marker.png) no-repeat; } diff --git a/theme/base/images/icons/icon_processing.gif b/theme/base/images/icons/icon_processing.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0bce1542342e912da81a2c260562df172f30d73 GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nnmm28Kh24mmkF0U1e2Nli^nlO|14{Lk&@8WQa67~pE8 zXTZz|lvDgC+Z`3#dv5h=E26FfcG1 zbL_hF&)}42ws10s6^G;;cE1^EoUR)U5A70}d2pLv!jVIT7j&Z~EblI3x0K*v_sV|m z0kj3v921Z^em#l`(k(o@H$3ZdDRc@9NidXDNbqrumReCGv$gd8+e8WW28HVqkJ_9i zH>s*<31KtHjANIPvi2#*6BEu%3Dak5O_t&NBI)H?V$TxT}#l{vOTn5naXTfF^&~Hhq+NX@#Ccc>y7T?;vjI&jdhsDsPJyAw*m0Qz>i}K7# zL9w50Ng{fT}A5JUe8lRK1h7_Y2;BWJDd=c6f&i?Wv5(5q?6|P zQw{>maxZP<537OA37Uk}7@%_$4o$EWe_Zl>&#id|lE-BpDC#+Fn|msJ%_2h{Hg1vP z#N8WAzfWasG}yq|xqE)DrWaOofX=z|?*pgc%{ig5vl!pqDlC|q&~Z0$&Rvsft&VO- z4MZj+%-+Vx%W}v;V76hyp=;+R;x+~t^Q%*xuFTQAF2})fSfTHDAs>sO!OBw`)&)o$ c0!CNZt))x~rAZP^^P&YOFfdqy5)K#u0POD40{{R3 literal 0 HcmV?d00001 diff --git a/theme/cloudy/css/display.css b/theme/cloudy/css/display.css index 151758b489..b87722eec1 100644 --- a/theme/cloudy/css/display.css +++ b/theme/cloudy/css/display.css @@ -1328,7 +1328,7 @@ color:#333; color:#000; } #form_notice.processing #notice_action-submit { -background:#fff url(../../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; cursor:wait; text-indent:-9999px; } From e876b74e8ba7e80edcb9a13bff15deff4aa6ff15 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Wed, 15 Apr 2009 08:38:05 +0200 Subject: [PATCH 360/503] Add license notice to install.php, replace short and asp style tags by more portable long tag form. --- install.php | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/install.php b/install.php index 0240349bb1..87a99a6508 100644 --- a/install.php +++ b/install.php @@ -1,4 +1,22 @@ -. + */ + define('INSTALLDIR', dirname(__FILE__)); function main() @@ -19,12 +37,12 @@ function checkPrereqs() { if (file_exists(INSTALLDIR.'/config.php')) { ?>

Config file "config.php" already exists.

-

Require PHP version 5 or greater.

Require PHP version 5 or greater.

Cannot load required extension "".

Cannot load required extension "".

Cannot write config file to "".

+ ?>

Cannot write config file to "".

On your server, try this command:

-
chmod a+w
- chmod a+w +

Cannot write avatar directory "/avatar/".

+ ?>

Cannot write avatar directory "/avatar/".

On your server, try this command:

-
chmod a+w /avatar/
+
chmod a+w /avatar/

Install Laconica

- +
- \ No newline at end of file + From e8fc34e75c4c9684b8c7e03d471a905e08446618 Mon Sep 17 00:00:00 2001 From: Fil Date: Wed, 15 Apr 2009 10:35:15 +0200 Subject: [PATCH 361/503] Use preg_quote to fix http://laconi.ca/trac/ticket/1342 --- actions/noticesearch.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/noticesearch.php b/actions/noticesearch.php index 095d0a454a..0828e47d77 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -184,11 +184,11 @@ class SearchNoticeListItem extends NoticeListItem { function highlight($text, $terms) { /* Highligh search terms */ - $pattern = '/('.implode('|', array_map('htmlspecialchars', $terms)).')/i'; + $pattern = '/('.implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms))).')/i'; $result = preg_replace($pattern, '\\1', $text); /* Remove highlighting from inside links, loop incase multiple highlights in links */ - $pattern = '/(href="[^"]*)('.implode('|', array_map('htmlspecialchars', $terms)).')<\/strong>([^"]*")/iU'; + $pattern = '/(href="[^"]*)('.implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms))).')<\/strong>([^"]*")/iU'; do { $result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count); } while ($count); From 8439477201cd59a6c0dba84ddf48eb86a6154199 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Wed, 15 Apr 2009 13:29:52 +0200 Subject: [PATCH 362/503] Add escaping of /. --- actions/noticesearch.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/actions/noticesearch.php b/actions/noticesearch.php index 0828e47d77..d996998fc6 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -184,11 +184,13 @@ class SearchNoticeListItem extends NoticeListItem { function highlight($text, $terms) { /* Highligh search terms */ - $pattern = '/('.implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms))).')/i'; + $options = implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms), + array_fill(0, sizeof($terms), '/'))); + $pattern = "/($options)/i"; $result = preg_replace($pattern, '\\1', $text); /* Remove highlighting from inside links, loop incase multiple highlights in links */ - $pattern = '/(href="[^"]*)('.implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms))).')<\/strong>([^"]*")/iU'; + $pattern = '/(href="[^"]*)('.$options.')<\/strong>([^"]*")/iU'; do { $result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count); } while ($count); From 8da76e0810342a90ac006f67cfd73500972f883a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 15 Apr 2009 10:05:16 -0400 Subject: [PATCH 363/503] add user id to statistics --- lib/profileaction.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/profileaction.php b/lib/profileaction.php index c81924e316..1f2e309945 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -179,6 +179,11 @@ class ProfileAction extends Action $this->element('h2', null, _('Statistics')); // Other stats...? + $this->elementStart('dl', 'entity_user-id'); + $this->element('dt', null, _('User ID')); + $this->element('dd', null, $this->profile->id); + $this->elementEnd('dl'); + $this->elementStart('dl', 'entity_member-since'); $this->element('dt', null, _('Member since')); $this->element('dd', null, date('j M Y', From 7ba3f8aeb3277bec52eee896f0c6807c7121104c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 15 Apr 2009 11:30:33 -0400 Subject: [PATCH 364/503] script to trim very old notices from inboxes --- scripts/triminboxes.php | 83 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 scripts/triminboxes.php diff --git a/scripts/triminboxes.php b/scripts/triminboxes.php new file mode 100644 index 0000000000..0d2eaeaf09 --- /dev/null +++ b/scripts/triminboxes.php @@ -0,0 +1,83 @@ +#!/usr/bin/env php +. + */ + +# Abort if called from a web server +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(1); +} + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +$user = new User(); +if ($argc > 1) { + $user->whereAdd('id > ' . $argv[1]); +} +$cnt = $user->find(); + +while ($user->fetch()) { + + $inbox_entry = new Notice_inbox(); + $inbox_entry->user_id = $user->id; + $inbox_entry->orderBy('created DESC'); + $inbox_entry->limit(1000, 1); + + $id = null; + + if ($inbox_entry->find(true)) { + $id = $inbox_entry->notice_id; + } + + $inbox_entry->free(); + unset($inbox_entry); + + if (is_null($id)) { + continue; + } + + $start = microtime(true); + + $old_inbox = new Notice_inbox(); + $cnt = $old_inbox->query('DELETE from notice_inbox WHERE user_id = ' . $user->id . ' AND notice_id < ' . $id); + $old_inbox->free(); + unset($old_inbox); + + print "Deleted $cnt notices for $user->nickname ($user->id).\n"; + + $finish = microtime(true); + + $delay = 3.0 * ($finish - $start); + + print "Delaying $delay seconds..."; + + // Wait to let slaves catch up + + usleep($delay * 1000000); + + print "DONE.\n"; +} From 3081b2e31708520e6ed83041ce3ba04329d3ec90 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 16 Apr 2009 08:44:48 -0400 Subject: [PATCH 365/503] start of querybyid --- classes/User.php | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/classes/User.php b/classes/User.php index 3b9b5cd839..098381f738 100644 --- a/classes/User.php +++ b/classes/User.php @@ -444,21 +444,42 @@ class User extends Memcached_DataObject 'SELECT notice.* ' . 'FROM notice JOIN subscription ON notice.profile_id = subscription.subscribed ' . 'WHERE subscription.subscriber = %d '; - $order = null; + return Notice::getStream(sprintf($qry, $this->id), + 'user:notices_with_friends:' . $this->id, + $offset, $limit, $since_id, $before_id, + $order, $since); } else if ($enabled === true || ($enabled == 'transitional' && $this->inboxed == 1)) { - $qry = - 'SELECT notice.* ' . - 'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' . - 'WHERE notice_inbox.user_id = %d '; - // NOTE: we override ORDER - $order = null; + $cache = common_memcache(); + + if (!empty($cache)) { + + # Get the notices out of the cache + + $notices = $cache->get(common_cache_key($cachekey)); + + # On a cache hit, return a DB-object-like wrapper + + if ($notices !== false) { + $wrapper = new ArrayWrapper(array_slice($notices, $offset, $limit)); + return $wrapper; + } + } + + $inbox = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since); + + $ids = array(); + + while ($inbox->fetch()) { + $ids[] = $inbox->notice_id; + } + + $inbox->free(); + unset($inbox); + + return Notice::getStreamByIds($ids, 'user:notices_with_friends:' . $this->id); } - return Notice::getStream(sprintf($qry, $this->id), - 'user:notices_with_friends:' . $this->id, - $offset, $limit, $since_id, $before_id, - $order, $since); } function blowFavesCache() From 3e3fec39ffd2d8e82c493809967ac22723e2365c Mon Sep 17 00:00:00 2001 From: CiaranG Date: Thu, 16 Apr 2009 17:21:06 +0100 Subject: [PATCH 366/503] Clarification in README regarding welcome/default users, as it has tripped a couple of people up --- README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README b/README index 09d9d301c5..7b2dcacc50 100644 --- a/README +++ b/README @@ -1129,6 +1129,9 @@ welcome: nickname of a user account that sends welcome messages to new busy servers it may be a good idea to keep that one just for 'urgent' messages. Default is null; no message. +If either of these special user accounts are specified, the users should +be created before the configuration is updated. + Troubleshooting =============== From 362cac0a96a48a0568454b6d60306ae10e2175e6 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Thu, 16 Apr 2009 17:34:19 +0000 Subject: [PATCH 367/503] Add a few events (hooks): RegistrationTry, RegistrationForData, ProfileFormData and ProfileSaveForm. --- actions/profilesettings.php | 369 ++++++++++++++++++------------------ actions/register.php | 336 ++++++++++++++++---------------- 2 files changed, 357 insertions(+), 348 deletions(-) diff --git a/actions/profilesettings.php b/actions/profilesettings.php index 60f7c0796e..fb847680b9 100644 --- a/actions/profilesettings.php +++ b/actions/profilesettings.php @@ -91,67 +91,68 @@ class ProfilesettingsAction extends AccountSettingsAction $this->element('legend', null, _('Profile information')); $this->hidden('token', common_session_token()); - # too much common patterns here... abstractable? - + // too much common patterns here... abstractable? $this->elementStart('ul', 'form_data'); - $this->elementStart('li'); - $this->input('nickname', _('Nickname'), - ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname, - _('1-64 lowercase letters or numbers, no punctuation or spaces')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('fullname', _('Full name'), - ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('homepage', _('Homepage'), - ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage, - _('URL of your homepage, blog, or profile on another site')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->textarea('bio', _('Bio'), - ($this->arg('bio')) ? $this->arg('bio') : $profile->bio, - _('Describe yourself and your interests in 140 chars')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('location', _('Location'), - ($this->arg('location')) ? $this->arg('location') : $profile->location, - _('Where you are, like "City, State (or Region), Country"')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('tags', _('Tags'), - ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()), - _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated')); - $this->elementEnd('li'); - $this->elementStart('li'); - $language = common_language(); - $this->dropdown('language', _('Language'), - get_nice_language_list(), _('Preferred language'), - true, $language); - $this->elementEnd('li'); - $timezone = common_timezone(); - $timezones = array(); - foreach(DateTimeZone::listIdentifiers() as $k => $v) { - $timezones[$v] = $v; + if (Event::handle('StartProfileFormData', array($this))) { + $this->elementStart('li'); + $this->input('nickname', _('Nickname'), + ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname, + _('1-64 lowercase letters or numbers, no punctuation or spaces')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('fullname', _('Full name'), + ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('homepage', _('Homepage'), + ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage, + _('URL of your homepage, blog, or profile on another site')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->textarea('bio', _('Bio'), + ($this->arg('bio')) ? $this->arg('bio') : $profile->bio, + _('Describe yourself and your interests in 140 chars')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('location', _('Location'), + ($this->arg('location')) ? $this->arg('location') : $profile->location, + _('Where you are, like "City, State (or Region), Country"')); + $this->elementEnd('li'); + Event::handle('EndProfileFormData', array($this)); + $this->elementStart('li'); + $this->input('tags', _('Tags'), + ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()), + _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated')); + $this->elementEnd('li'); + $this->elementStart('li'); + $language = common_language(); + $this->dropdown('language', _('Language'), + get_nice_language_list(), _('Preferred language'), + false, $language); + $this->elementEnd('li'); + $timezone = common_timezone(); + $timezones = array(); + foreach(DateTimeZone::listIdentifiers() as $k => $v) { + $timezones[$v] = $v; + } + $this->elementStart('li'); + $this->dropdown('timezone', _('Timezone'), + $timezones, _('What timezone are you normally in?'), + true, $timezone); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->checkbox('autosubscribe', + _('Automatically subscribe to whoever '. + 'subscribes to me (best for non-humans)'), + ($this->arg('autosubscribe')) ? + $this->boolean('autosubscribe') : $user->autosubscribe); + $this->elementEnd('li'); } - $this->elementStart('li'); - $this->dropdown('timezone', _('Timezone'), - $timezones, _('What timezone are you normally in?'), - true, $timezone); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->checkbox('autosubscribe', - _('Automatically subscribe to whoever '. - 'subscribes to me (best for non-humans)'), - ($this->arg('autosubscribe')) ? - $this->boolean('autosubscribe') : $user->autosubscribe); - $this->elementEnd('li'); $this->elementEnd('ul'); $this->submit('save', _('Save')); $this->elementEnd('fieldset'); $this->elementEnd('form'); - } /** @@ -165,158 +166,158 @@ class ProfilesettingsAction extends AccountSettingsAction function handlePost() { - # CSRF protection - + // CSRF protection $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { $this->showForm(_('There was a problem with your session token. '. - 'Try again, please.')); + 'Try again, please.')); return; } - $nickname = $this->trimmed('nickname'); - $fullname = $this->trimmed('fullname'); - $homepage = $this->trimmed('homepage'); - $bio = $this->trimmed('bio'); - $location = $this->trimmed('location'); - $autosubscribe = $this->boolean('autosubscribe'); - $language = $this->trimmed('language'); - $timezone = $this->trimmed('timezone'); - $tagstring = $this->trimmed('tags'); + if (Event::handle('StartProfileSaveForm', array($this))) { - # Some validation + $nickname = $this->trimmed('nickname'); + $fullname = $this->trimmed('fullname'); + $homepage = $this->trimmed('homepage'); + $bio = $this->trimmed('bio'); + $location = $this->trimmed('location'); + $autosubscribe = $this->boolean('autosubscribe'); + $language = $this->trimmed('language'); + $timezone = $this->trimmed('timezone'); + $tagstring = $this->trimmed('tags'); - if (!Validate::string($nickname, array('min_length' => 1, - 'max_length' => 64, - 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) { - $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.')); - return; - } else if (!User::allowed_nickname($nickname)) { - $this->showForm(_('Not a valid nickname.')); - return; - } else if (!is_null($homepage) && (strlen($homepage) > 0) && - !Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) { - $this->showForm(_('Homepage is not a valid URL.')); - return; - } else if (!is_null($fullname) && mb_strlen($fullname) > 255) { - $this->showForm(_('Full name is too long (max 255 chars).')); - return; - } else if (!is_null($bio) && mb_strlen($bio) > 140) { - $this->showForm(_('Bio is too long (max 140 chars).')); - return; - } else if (!is_null($location) && mb_strlen($location) > 255) { - $this->showForm(_('Location is too long (max 255 chars).')); - return; - } else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) { - $this->showForm(_('Timezone not selected.')); - return; - } else if ($this->nicknameExists($nickname)) { - $this->showForm(_('Nickname already in use. Try another one.')); - return; - } else if (!is_null($language) && strlen($language) > 50) { - $this->showForm(_('Language is too long (max 50 chars).')); - return; - } - - if ($tagstring) { - $tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring)); - } else { - $tags = array(); - } - - foreach ($tags as $tag) { - if (!common_valid_profile_tag($tag)) { - $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag)); + // Some validation + if (!Validate::string($nickname, array('min_length' => 1, + 'max_length' => 64, + 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) { + $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.')); + return; + } else if (!User::allowed_nickname($nickname)) { + $this->showForm(_('Not a valid nickname.')); + return; + } else if (!is_null($homepage) && (strlen($homepage) > 0) && + !Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) { + $this->showForm(_('Homepage is not a valid URL.')); + return; + } else if (!is_null($fullname) && mb_strlen($fullname) > 255) { + $this->showForm(_('Full name is too long (max 255 chars).')); + return; + } else if (!is_null($bio) && mb_strlen($bio) > 140) { + $this->showForm(_('Bio is too long (max 140 chars).')); + return; + } else if (!is_null($location) && mb_strlen($location) > 255) { + $this->showForm(_('Location is too long (max 255 chars).')); + return; + } else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) { + $this->showForm(_('Timezone not selected.')); + return; + } else if ($this->nicknameExists($nickname)) { + $this->showForm(_('Nickname already in use. Try another one.')); + return; + } else if (!is_null($language) && strlen($language) > 50) { + $this->showForm(_('Language is too long (max 50 chars).')); return; } - } - $user = common_current_user(); - - $user->query('BEGIN'); - - if ($user->nickname != $nickname || - $user->language != $language || - $user->timezone != $timezone) { - - common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname, - __FILE__); - common_debug('Updating user language from ' . $user->language . ' to ' . $language, - __FILE__); - common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone, - __FILE__); - - $original = clone($user); - - $user->nickname = $nickname; - $user->language = $language; - $user->timezone = $timezone; - - $result = $user->updateKeys($original); - - if ($result === false) { - common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_('Couldn\'t update user.')); - return; + if ($tagstring) { + $tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring)); } else { - # Re-initialize language environment if it changed - common_init_language(); + $tags = array(); } - } - # XXX: XOR + foreach ($tags as $tag) { + if (!common_valid_profile_tag($tag)) { + $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag)); + return; + } + } - if ($user->autosubscribe ^ $autosubscribe) { + $user = common_current_user(); - $original = clone($user); + $user->query('BEGIN'); - $user->autosubscribe = $autosubscribe; + if ($user->nickname != $nickname || + $user->language != $language || + $user->timezone != $timezone) { - $result = $user->update($original); + common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname, + __FILE__); + common_debug('Updating user language from ' . $user->language . ' to ' . $language, + __FILE__); + common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone, + __FILE__); - if ($result === false) { - common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_('Couldn\'t update user for autosubscribe.')); + $original = clone($user); + + $user->nickname = $nickname; + $user->language = $language; + $user->timezone = $timezone; + + $result = $user->updateKeys($original); + + if ($result === false) { + common_log_db_error($user, 'UPDATE', __FILE__); + $this->serverError(_('Couldn\'t update user.')); + return; + } else { + // Re-initialize language environment if it changed + common_init_language(); + } + } + +// XXX: XOR + if ($user->autosubscribe ^ $autosubscribe) { + + $original = clone($user); + + $user->autosubscribe = $autosubscribe; + + $result = $user->update($original); + + if ($result === false) { + common_log_db_error($user, 'UPDATE', __FILE__); + $this->serverError(_('Couldn\'t update user for autosubscribe.')); + return; + } + } + + $profile = $user->getProfile(); + + $orig_profile = clone($profile); + + $profile->nickname = $user->nickname; + $profile->fullname = $fullname; + $profile->homepage = $homepage; + $profile->bio = $bio; + $profile->location = $location; + $profile->profileurl = common_profile_url($nickname); + + common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__); + common_debug('New profile: ' . common_log_objstring($profile), __FILE__); + + $result = $profile->update($orig_profile); + + if (!$result) { + common_log_db_error($profile, 'UPDATE', __FILE__); + $this->serverError(_('Couldn\'t save profile.')); return; } + + // Set the user tags + $result = $user->setSelfTags($tags); + + if (!$result) { + $this->serverError(_('Couldn\'t save tags.')); + return; + } + + $user->query('COMMIT'); + Event::handle('EndProfileSaveForm', array($this)); + common_broadcast_profile($profile); + + $this->showForm(_('Settings saved.'), true); + } - - $profile = $user->getProfile(); - - $orig_profile = clone($profile); - - $profile->nickname = $user->nickname; - $profile->fullname = $fullname; - $profile->homepage = $homepage; - $profile->bio = $bio; - $profile->location = $location; - $profile->profileurl = common_profile_url($nickname); - - common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__); - common_debug('New profile: ' . common_log_objstring($profile), __FILE__); - - $result = $profile->update($orig_profile); - - if (!$result) { - common_log_db_error($profile, 'UPDATE', __FILE__); - $this->serverError(_('Couldn\'t save profile.')); - return; - } - - # Set the user tags - - $result = $user->setSelfTags($tags); - - if (!$result) { - $this->serverError(_('Couldn\'t save tags.')); - return; - } - - $user->query('COMMIT'); - - common_broadcast_profile($profile); - - $this->showForm(_('Settings saved.'), true); } function nicknameExists($nickname) diff --git a/actions/register.php b/actions/register.php index 5d7a8ce690..ab49ad3fdc 100644 --- a/actions/register.php +++ b/actions/register.php @@ -108,107 +108,109 @@ class RegisterAction extends Action function tryRegister() { - $token = $this->trimmed('token'); - if (!$token || $token != common_session_token()) { - $this->showForm(_('There was a problem with your session token. '. - 'Try again, please.')); - return; - } + if (Event::handle('StartRegistrationTry', array($this))) { + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->showForm(_('There was a problem with your session token. '. + 'Try again, please.')); + return; + } - $nickname = $this->trimmed('nickname'); - $email = $this->trimmed('email'); - $fullname = $this->trimmed('fullname'); - $homepage = $this->trimmed('homepage'); - $bio = $this->trimmed('bio'); - $location = $this->trimmed('location'); + $nickname = $this->trimmed('nickname'); + $email = $this->trimmed('email'); + $fullname = $this->trimmed('fullname'); + $homepage = $this->trimmed('homepage'); + $bio = $this->trimmed('bio'); + $location = $this->trimmed('location'); - // We don't trim these... whitespace is OK in a password! + // We don't trim these... whitespace is OK in a password! + $password = $this->arg('password'); + $confirm = $this->arg('confirm'); - $password = $this->arg('password'); - $confirm = $this->arg('confirm'); + // invitation code, if any + $code = $this->trimmed('code'); - // invitation code, if any + if ($code) { + $invite = Invitation::staticGet($code); + } - $code = $this->trimmed('code'); + if (common_config('site', 'inviteonly') && !($code && $invite)) { + $this->clientError(_('Sorry, only invited people can register.')); + return; + } - if ($code) { - $invite = Invitation::staticGet($code); - } + // Input scrubbing + $nickname = common_canonical_nickname($nickname); + $email = common_canonical_email($email); - if (common_config('site', 'inviteonly') && !($code && $invite)) { - $this->clientError(_('Sorry, only invited people can register.')); - return; - } + if (!$this->boolean('license')) { + $this->showForm(_('You can\'t register if you don\'t '. + 'agree to the license.')); + } else if ($email && !Validate::email($email, true)) { + $this->showForm(_('Not a valid email address.')); + } else if (!Validate::string($nickname, array('min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { + $this->showForm(_('Nickname must have only lowercase letters '. + 'and numbers and no spaces.')); + } else if ($this->nicknameExists($nickname)) { + $this->showForm(_('Nickname already in use. Try another one.')); + } else if (!User::allowed_nickname($nickname)) { + $this->showForm(_('Not a valid nickname.')); + } else if ($this->emailExists($email)) { + $this->showForm(_('Email address already exists.')); + } else if (!is_null($homepage) && (strlen($homepage) > 0) && + !Validate::uri($homepage, + array('allowed_schemes' => + array('http', 'https')))) { + $this->showForm(_('Homepage is not a valid URL.')); + return; + } else if (!is_null($fullname) && mb_strlen($fullname) > 255) { + $this->showForm(_('Full name is too long (max 255 chars).')); + return; + } else if (!is_null($bio) && mb_strlen($bio) > 140) { + $this->showForm(_('Bio is too long (max 140 chars).')); + return; + } else if (!is_null($location) && mb_strlen($location) > 255) { + $this->showForm(_('Location is too long (max 255 chars).')); + return; + } else if (strlen($password) < 6) { + $this->showForm(_('Password must be 6 or more characters.')); + return; + } else if ($password != $confirm) { + $this->showForm(_('Passwords don\'t match.')); + } else if ($user = User::register(array('nickname' => $nickname, + 'password' => $password, + 'email' => $email, + 'fullname' => $fullname, + 'homepage' => $homepage, + 'bio' => $bio, + 'location' => $location, + 'code' => $code))) { + if (!$user) { + $this->showForm(_('Invalid username or password.')); + return; + } + // success! + if (!common_set_user($user)) { + $this->serverError(_('Error setting user.')); + return; + } + // this is a real login + common_real_login(true); + if ($this->boolean('rememberme')) { + common_debug('Adding rememberme cookie for ' . $nickname); + common_rememberme($user); + } - // Input scrubbing + Event::handle('EndRegistrationTry', array($this)); - $nickname = common_canonical_nickname($nickname); - $email = common_canonical_email($email); - - if (!$this->boolean('license')) { - $this->showForm(_('You can\'t register if you don\'t '. - 'agree to the license.')); - } else if ($email && !Validate::email($email, true)) { - $this->showForm(_('Not a valid email address.')); - } else if (!Validate::string($nickname, array('min_length' => 1, - 'max_length' => 64, - 'format' => NICKNAME_FMT))) { - $this->showForm(_('Nickname must have only lowercase letters '. - 'and numbers and no spaces.')); - } else if ($this->nicknameExists($nickname)) { - $this->showForm(_('Nickname already in use. Try another one.')); - } else if (!User::allowed_nickname($nickname)) { - $this->showForm(_('Not a valid nickname.')); - } else if ($this->emailExists($email)) { - $this->showForm(_('Email address already exists.')); - } else if (!is_null($homepage) && (strlen($homepage) > 0) && - !Validate::uri($homepage, - array('allowed_schemes' => - array('http', 'https')))) { - $this->showForm(_('Homepage is not a valid URL.')); - return; - } else if (!is_null($fullname) && mb_strlen($fullname) > 255) { - $this->showForm(_('Full name is too long (max 255 chars).')); - return; - } else if (!is_null($bio) && mb_strlen($bio) > 140) { - $this->showForm(_('Bio is too long (max 140 chars).')); - return; - } else if (!is_null($location) && mb_strlen($location) > 255) { - $this->showForm(_('Location is too long (max 255 chars).')); - return; - } else if (strlen($password) < 6) { - $this->showForm(_('Password must be 6 or more characters.')); - return; - } else if ($password != $confirm) { - $this->showForm(_('Passwords don\'t match.')); - } else if ($user = User::register(array('nickname' => $nickname, - 'password' => $password, - 'email' => $email, - 'fullname' => $fullname, - 'homepage' => $homepage, - 'bio' => $bio, - 'location' => $location, - 'code' => $code))) { - if (!$user) { + // Re-init language env in case it changed (not yet, but soon) + common_init_language(); + $this->showSuccess(); + } else { $this->showForm(_('Invalid username or password.')); - return; } - // success! - if (!common_set_user($user)) { - $this->serverError(_('Error setting user.')); - return; - } - // this is a real login - common_real_login(true); - if ($this->boolean('rememberme')) { - common_debug('Adding rememberme cookie for ' . $nickname); - common_rememberme($user); - } - // Re-init language env in case it changed (not yet, but soon) - common_init_language(); - $this->showSuccess(); - } else { - $this->showForm(_('Invalid username or password.')); } } @@ -250,7 +252,9 @@ class RegisterAction extends Action // overrrided to add entry-title class function showPageTitle() { - $this->element('h1', array('class' => 'entry-title'), $this->title()); + if (Event::handle('StartShowPageTitle', array($this))) { + $this->element('h1', array('class' => 'entry-title'), $this->title()); + } } // overrided to add hentry, and content-inner class @@ -351,9 +355,9 @@ class RegisterAction extends Action } $this->elementStart('form', array('method' => 'post', - 'id' => 'form_register', - 'class' => 'form_settings', - 'action' => common_local_url('register'))); + 'id' => 'form_register', + 'class' => 'form_settings', + 'action' => common_local_url('register'))); $this->elementStart('fieldset'); $this->element('legend', null, 'Account settings'); $this->hidden('token', common_session_token()); @@ -363,77 +367,80 @@ class RegisterAction extends Action } $this->elementStart('ul', 'form_data'); - $this->elementStart('li'); - $this->input('nickname', _('Nickname'), $this->trimmed('nickname'), - _('1-64 lowercase letters or numbers, '. - 'no punctuation or spaces. Required.')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->password('password', _('Password'), - _('6 or more characters. Required.')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->password('confirm', _('Confirm'), - _('Same as password above. Required.')); - $this->elementEnd('li'); - $this->elementStart('li'); - if ($invite && $invite->address_type == 'email') { - $this->input('email', _('Email'), $invite->address, - _('Used only for updates, announcements, '. - 'and password recovery')); - } else { - $this->input('email', _('Email'), $this->trimmed('email'), - _('Used only for updates, announcements, '. - 'and password recovery')); + if (Event::handle('StartRegistrationFormData', array($this))) { + $this->elementStart('li'); + $this->input('nickname', _('Nickname'), $this->trimmed('nickname'), + _('1-64 lowercase letters or numbers, '. + 'no punctuation or spaces. Required.')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->password('password', _('Password'), + _('6 or more characters. Required.')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->password('confirm', _('Confirm'), + _('Same as password above. Required.')); + $this->elementEnd('li'); + $this->elementStart('li'); + if ($invite && $invite->address_type == 'email') { + $this->input('email', _('Email'), $invite->address, + _('Used only for updates, announcements, '. + 'and password recovery')); + } else { + $this->input('email', _('Email'), $this->trimmed('email'), + _('Used only for updates, announcements, '. + 'and password recovery')); + } + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('fullname', _('Full name'), + $this->trimmed('fullname'), + _('Longer name, preferably your "real" name')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('homepage', _('Homepage'), + $this->trimmed('homepage'), + _('URL of your homepage, blog, '. + 'or profile on another site')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->textarea('bio', _('Bio'), + $this->trimmed('bio'), + _('Describe yourself and your '. + 'interests in 140 chars')); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->input('location', _('Location'), + $this->trimmed('location'), + _('Where you are, like "City, '. + 'State (or Region), Country"')); + $this->elementEnd('li'); + Event::handle('EndRegistrationFormData', array($this)); + $this->elementStart('li', array('id' => 'settings_rememberme')); + $this->checkbox('rememberme', _('Remember me'), + $this->boolean('rememberme'), + _('Automatically login in the future; '. + 'not for shared computers!')); + $this->elementEnd('li'); + $attrs = array('type' => 'checkbox', + 'id' => 'license', + 'class' => 'checkbox', + 'name' => 'license', + 'value' => 'true'); + if ($this->boolean('license')) { + $attrs['checked'] = 'checked'; + } + $this->elementStart('li'); + $this->element('input', $attrs); + $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license')); + $this->text(_('My text and files are available under ')); + $this->element('a', array('href' => common_config('license', 'url')), + common_config('license', 'title'), _("Creative Commons Attribution 3.0")); + $this->text(_(' except this private data: password, '. + 'email address, IM address, and phone number.')); + $this->elementEnd('label'); + $this->elementEnd('li'); } - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('fullname', _('Full name'), - $this->trimmed('fullname'), - _('Longer name, preferably your "real" name')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('homepage', _('Homepage'), - $this->trimmed('homepage'), - _('URL of your homepage, blog, '. - 'or profile on another site')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->textarea('bio', _('Bio'), - $this->trimmed('bio'), - _('Describe yourself and your '. - 'interests in 140 chars')); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('location', _('Location'), - $this->trimmed('location'), - _('Where you are, like "City, '. - 'State (or Region), Country"')); - $this->elementEnd('li'); - $this->elementStart('li', array('id' => 'settings_rememberme')); - $this->checkbox('rememberme', _('Remember me'), - $this->boolean('rememberme'), - _('Automatically login in the future; '. - 'not for shared computers!')); - $this->elementEnd('li'); - $attrs = array('type' => 'checkbox', - 'id' => 'license', - 'class' => 'checkbox', - 'name' => 'license', - 'value' => 'true'); - if ($this->boolean('license')) { - $attrs['checked'] = 'checked'; - } - $this->elementStart('li'); - $this->element('input', $attrs); - $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license')); - $this->text(_('My text and files are available under ')); - $this->element('a', array('href' => common_config('license', 'url')), - common_config('license', 'title'), _("Creative Commons Attribution 3.0")); - $this->text(_(' except this private data: password, '. - 'email address, IM address, and phone number.')); - $this->elementEnd('label'); - $this->elementEnd('li'); $this->elementEnd('ul'); $this->submit('submit', _('Register')); $this->elementEnd('fieldset'); @@ -515,3 +522,4 @@ class RegisterAction extends Action $nav->show(); } } + From ed0556971661de1b8748882f48c316afac20b8be Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Thu, 16 Apr 2009 17:58:52 +0000 Subject: [PATCH 368/503] Add an even (hook): StartPersonalGroupNav. --- lib/personalgroupnav.php | 68 +++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/lib/personalgroupnav.php b/lib/personalgroupnav.php index 63e6138df2..acc0336673 100644 --- a/lib/personalgroupnav.php +++ b/lib/personalgroupnav.php @@ -93,43 +93,45 @@ class PersonalGroupNav extends Widget $this->out->elementStart('ul', array('class' => 'nav')); - $this->out->menuItem(common_local_url('all', array('nickname' => - $nickname)), - _('Personal'), - sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), - $action == 'all', 'nav_timeline_personal'); - $this->out->menuItem(common_local_url('replies', array('nickname' => - $nickname)), - _('Replies'), - sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), - $action == 'replies', 'nav_timeline_replies'); - $this->out->menuItem(common_local_url('showstream', array('nickname' => - $nickname)), - _('Profile'), - ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname, - $action == 'showstream', 'nav_profile'); - $this->out->menuItem(common_local_url('showfavorites', array('nickname' => - $nickname)), - _('Favorites'), - sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')), - $action == 'showfavorites', 'nav_timeline_favorites'); + if (Event::handle('StartPersonalGroupNav', array($this))) { + $this->out->menuItem(common_local_url('all', array('nickname' => + $nickname)), + _('Personal'), + sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'all', 'nav_timeline_personal'); + $this->out->menuItem(common_local_url('replies', array('nickname' => + $nickname)), + _('Replies'), + sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'replies', 'nav_timeline_replies'); + $this->out->menuItem(common_local_url('showstream', array('nickname' => + $nickname)), + _('Profile'), + ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname, + $action == 'showstream', 'nav_profile'); + $this->out->menuItem(common_local_url('showfavorites', array('nickname' => + $nickname)), + _('Favorites'), + sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')), + $action == 'showfavorites', 'nav_timeline_favorites'); - $cur = common_current_user(); + $cur = common_current_user(); - if ($cur && $cur->id == $user->id) { + if ($cur && $cur->id == $user->id) { - $this->out->menuItem(common_local_url('inbox', array('nickname' => - $nickname)), - _('Inbox'), - _('Your incoming messages'), - $action == 'inbox'); - $this->out->menuItem(common_local_url('outbox', array('nickname' => - $nickname)), - _('Outbox'), - _('Your sent messages'), - $action == 'outbox'); + $this->out->menuItem(common_local_url('inbox', array('nickname' => + $nickname)), + _('Inbox'), + _('Your incoming messages'), + $action == 'inbox'); + $this->out->menuItem(common_local_url('outbox', array('nickname' => + $nickname)), + _('Outbox'), + _('Your sent messages'), + $action == 'outbox'); + } + Event::handle('EndPersonalGroupNav', array($this)); } - $this->out->elementEnd('ul'); } } From bac3ee95c96db10ed51a907f6f9b602a7c887c0f Mon Sep 17 00:00:00 2001 From: CiaranG Date: Thu, 16 Apr 2009 21:07:59 +0100 Subject: [PATCH 369/503] Abort the xmpp-related daemons immediately if xmpp is disabled in the config, otherwise they chew up *lots* of CPU doing nothing --- scripts/jabberqueuehandler.php | 9 ++++++++- scripts/publicqueuehandler.php | 7 +++++++ scripts/xmppconfirmhandler.php | 7 +++++++ scripts/xmppdaemon.php | 7 +++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php index 924fc45453..8b6e974c0a 100755 --- a/scripts/jabberqueuehandler.php +++ b/scripts/jabberqueuehandler.php @@ -54,6 +54,13 @@ class JabberQueueHandler extends XmppQueueHandler } } +// Abort immediately if xmpp is not enabled, otherwise the daemon chews up +// lots of CPU trying to connect to unconfigured servers +if (common_config('xmpp','enabled')==false) { + print "Aborting daemon - xmpp is disabled\n"; + exit(); +} + ini_set("max_execution_time", "0"); ini_set("max_input_time", "0"); set_time_limit(0); @@ -63,4 +70,4 @@ $resource = ($argc > 1) ? $argv[1] : (common_config('xmpp','resource') . '-queue $handler = new JabberQueueHandler($resource); -$handler->runOnce(); \ No newline at end of file +$handler->runOnce(); diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php index 5075c12df5..b0fa22d438 100755 --- a/scripts/publicqueuehandler.php +++ b/scripts/publicqueuehandler.php @@ -52,6 +52,13 @@ class PublicQueueHandler extends XmppQueueHandler } } +// Abort immediately if xmpp is not enabled, otherwise the daemon chews up +// lots of CPU trying to connect to unconfigured servers +if (common_config('xmpp','enabled')==false) { + print "Aborting daemon - xmpp is disabled\n"; + exit(); +} + ini_set("max_execution_time", "0"); ini_set("max_input_time", "0"); set_time_limit(0); diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php index 2b8b085ce8..7f39235fed 100755 --- a/scripts/xmppconfirmhandler.php +++ b/scripts/xmppconfirmhandler.php @@ -140,6 +140,13 @@ class XmppConfirmHandler extends XmppQueueHandler } } +// Abort immediately if xmpp is not enabled, otherwise the daemon chews up +// lots of CPU trying to connect to unconfigured servers +if (common_config('xmpp','enabled')==false) { + print "Aborting daemon - xmpp is disabled\n"; + exit(); +} + ini_set("max_execution_time", "0"); ini_set("max_input_time", "0"); set_time_limit(0); diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index ef3f8c63d8..0ce2f2a280 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -321,6 +321,13 @@ class XMPPDaemon extends Daemon } } +// Abort immediately if xmpp is not enabled, otherwise the daemon chews up +// lots of CPU trying to connect to unconfigured servers +if (common_config('xmpp','enabled')==false) { + print "Aborting daemon - xmpp is disabled\n"; + exit(); +} + ini_set("max_execution_time", "0"); ini_set("max_input_time", "0"); set_time_limit(0); From 4d0e4f733bdfa281487f370b70f5f7440a7ef931 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 16 Apr 2009 14:40:57 -0700 Subject: [PATCH 370/503] Make API dates more compatible with Twitter - ticket 1432 --- lib/twitterapi.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/twitterapi.php b/lib/twitterapi.php index b8357c6889..6a90b4e288 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -418,7 +418,7 @@ class TwitterapiAction extends Action function date_twitter($dt) { $t = strtotime($dt); - return date("D M d G:i:s O Y", $t); + return date("D M d H:i:s O Y", $t); } // XXX: Candidate for a general utility method somewhere? From c3a44d2ab982c42aaece2785316416a8ea780873 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 16 Apr 2009 21:57:42 +0000 Subject: [PATCH 371/503] form_notice textarea is cleared on successful direct message post. Disabled notice posting with XHR on Inbox and Outbox pages. This will be revisited in 0.8.x. --- js/util.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/js/util.js b/js/util.js index 81139744ff..38d2a9a424 100644 --- a/js/util.js +++ b/js/util.js @@ -166,28 +166,36 @@ $(document).ready(function(){ $("#notice_action-submit").addClass("disabled"); return true; }, - success: function(xml) { if ($("#error", xml).length > 0 || $("#command_result", xml).length > 0) { + success: function(xml) { if ($("#error", xml).length > 0) { var result = document._importNode($("p", xml).get(0), true); result = result.textContent || result.innerHTML; alert(result); } else { - $("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true)); + if ($("#command_result", xml).length > 0) { + var result = document._importNode($("p", xml).get(0), true); + result = result.textContent || result.innerHTML; + alert(result); + } + else { + $("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true)); + counter(); + $("#notices_primary .notice:first").css({display:"none"}); + $("#notices_primary .notice:first").fadeIn(2500); + NoticeHover(); + NoticeReply(); + } $("#notice_data-text").val(""); - counter(); - $("#notices_primary .notice:first").css({display:"none"}); - $("#notices_primary .notice:first").fadeIn(2500); - NoticeHover(); - NoticeReply(); } $("#form_notice").removeClass("processing"); $("#notice_action-submit").removeAttr("disabled"); $("#notice_action-submit").removeClass("disabled"); } }; - $("#form_notice").ajaxForm(PostNotice); - $("#form_notice").each(addAjaxHidden); - + if (document.body.id != 'inbox' && document.body.id != 'outbox') { + $("#form_notice").ajaxForm(PostNotice); + $("#form_notice").each(addAjaxHidden); + } NoticeHover(); NoticeReply(); }); From 34d904b180e5caa17eb945292a8a64656424d5d0 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 17 Apr 2009 01:11:38 +0000 Subject: [PATCH 372/503] Ticket 1404. Showing the link to the members list page. --- actions/grouprss.php | 2 +- actions/showgroup.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actions/grouprss.php b/actions/grouprss.php index a9a2eef877..0b7280a11c 100644 --- a/actions/grouprss.php +++ b/actions/grouprss.php @@ -34,7 +34,7 @@ if (!defined('LACONICA')) { require_once INSTALLDIR.'/lib/rssaction.php'; -define('MEMBERS_PER_SECTION', 81); +define('MEMBERS_PER_SECTION', 27); /** * Group RSS feed diff --git a/actions/showgroup.php b/actions/showgroup.php index 025f8383a2..a7df397273 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -35,7 +35,7 @@ if (!defined('LACONICA')) { require_once INSTALLDIR.'/lib/noticelist.php'; require_once INSTALLDIR.'/lib/feedlist.php'; -define('MEMBERS_PER_SECTION', 81); +define('MEMBERS_PER_SECTION', 27); /** * Group main page @@ -361,7 +361,7 @@ class ShowgroupAction extends Action $this->element('p', null, _('(None)')); } - if ($cnt == MEMBERS_PER_SECTION) { + if ($cnt > MEMBERS_PER_SECTION) { $this->element('a', array('href' => common_local_url('groupmembers', array('nickname' => $this->group->nickname))), _('All members')); From 21873b806d6c5cf3e55ea10e49959c944f708688 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 16:46:49 +0000 Subject: [PATCH 373/503] cosmetic fixes. --- lib/searchaction.php | 2 +- lib/tagcloudsection.php | 124 ---------------------------------------- lib/util.php | 3 +- 3 files changed, 3 insertions(+), 126 deletions(-) delete mode 100644 lib/tagcloudsection.php diff --git a/lib/searchaction.php b/lib/searchaction.php index e74450e11f..e7ad4affda 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -51,7 +51,7 @@ class SearchAction extends Action * * @return boolean true */ - function isReadOnly($args) + function isReadOnly() { return true; } diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php deleted file mode 100644 index ff2aca6d6e..0000000000 --- a/lib/tagcloudsection.php +++ /dev/null @@ -1,124 +0,0 @@ -. - * - * @category Widget - * @package Laconica - * @author Evan Prodromou - * @copyright 2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -if (!defined('LACONICA')) { - exit(1); -} - -define('TAGS_PER_SECTION', 20); - -/** - * Base class for sections - * - * These are the widgets that show interesting data about a person - * group, or site. - * - * @category Widget - * @package Laconica - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -class TagCloudSection extends Section -{ - function showContent() - { - $tags = $this->getTags(); - - if (!$tags) { - $this->out->element('p', null, _('None')); - return false; - } - - $cnt = 0; - - $tw = array(); - $sum = 0; - - while ($tags->fetch() && ++$cnt <= TAGS_PER_SECTION) { - $tw[$tags->tag] = $tags->weight; - $sum += $tags->weight; - } - - if ($cnt == 0) { - $this->out->element('p', null, _('(None)')); - return false; - } - - ksort($tw); - - $this->out->elementStart('ul', 'tags xoxo tag-cloud'); - foreach ($tw as $tag => $weight) { - $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); - } - $this->out->elementEnd('ul'); - - return ($cnt > TAGS_PER_SECTION); - } - - function getTags() - { - return null; - } - - function showTag($tag, $weight, $relative) - { - if ($relative > 0.1) { - $rel = 'tag-cloud-7'; - } else if ($relative > 0.05) { - $rel = 'tag-cloud-6'; - } else if ($relative > 0.02) { - $rel = 'tag-cloud-5'; - } else if ($relative > 0.01) { - $rel = 'tag-cloud-4'; - } else if ($relative > 0.005) { - $rel = 'tag-cloud-3'; - } else if ($relative > 0.002) { - $rel = 'tag-cloud-2'; - } else { - $rel = 'tag-cloud-1'; - } - - $this->out->elementStart('li', $rel); - $this->out->element('a', array('href' => $this->tagUrl($tag)), - $tag); - $this->out->elementEnd('li'); - } - - function tagUrl($tag) - { - return common_local_url('tag', array('tag' => $tag)); - } - - function divId() - { - return 'tagcloud'; - } -} diff --git a/lib/util.php b/lib/util.php index 675ff51f01..5d16e39b56 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1333,4 +1333,5 @@ function common_database_tablename($tablename) } //table prefixes could be added here later return $tablename; -} \ No newline at end of file +} + From c024ee935a638d2daf3d54374564a1956916857b Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:23:12 +0000 Subject: [PATCH 374/503] file was removed by mistake. --- lib/tagcloudsection.php | 142 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 lib/tagcloudsection.php diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php new file mode 100644 index 0000000000..f5c305c65f --- /dev/null +++ b/lib/tagcloudsection.php @@ -0,0 +1,142 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +define('TAGS_PER_SECTION', 20); + +/** + * Base class for sections + * + * These are the widgets that show interesting data about a person + * group, or site. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class TagCloudSection extends Section +{ + function showContent() + { + $tags = $this->getAllTags(); + + if (!$tags) { + $this->out->element('p', null, _('None')); + return false; + } + + $cnt = count($tags); + + if ($cnt == 0) { + $this->out->element('p', null, _('(None)')); + return false; + } + + ksort($tags); + + $this->out->elementStart('ul', 'tags xoxo tag-cloud'); + foreach ($tags as $tag => $weight) { + $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); + } + $this->out->elementEnd('ul'); + + return ($cnt > TAGS_PER_SECTION); + } + + function getTags($lst, $usr) + { + $profile_tag = new Profile_tag; + $profile_tag->selectAdd(); + $profile_tag->selectAdd('tag'); + $profile_tag->selectAdd('count(tag) as weight'); + $profile_tag->groupBy('tag'); + $profile_tag->orderBy('weight DESC'); + $cnt = $profile_tag->find(); + + $profile_tag->query(" +SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); + + $tags = array(); + while ($profile_tag->fetch()) { +// var_dump($profile_tag); + $tags[$profile_tag->tag] = $profile_tag->weight; + } + $profile_tag->free(); + if (0) { + echo 'tags:
';
+            var_dump($tags);
+            echo '
'; + } + return $tags; + } + + function getAllTags() { + return null; + } + + function showTag($tag, $weight, $relative) + { + if ($relative > 0.1) { + $rel = 'tag-cloud-7'; + } else if ($relative > 0.05) { + $rel = 'tag-cloud-6'; + } else if ($relative > 0.02) { + $rel = 'tag-cloud-5'; + } else if ($relative > 0.01) { + $rel = 'tag-cloud-4'; + } else if ($relative > 0.005) { + $rel = 'tag-cloud-3'; + } else if ($relative > 0.002) { + $rel = 'tag-cloud-2'; + } else { + $rel = 'tag-cloud-1'; + } + + $this->out->elementStart('li', $rel); + $this->out->element('a', array('href' => $this->tagUrl($tag)), + $tag); + $this->out->elementEnd('li'); + } + + function tagUrl($tag) + { + return common_local_url('tag', array('tag' => $tag)); + } + + function divId() + { + return 'tagcloud'; + } +} From 2e06d5a2cb0d05d944bd0f969dbf5a0b10a1d48e Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:24:41 +0000 Subject: [PATCH 375/503] file was removed by mistake. --- lib/tagcloudsection.php | 142 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 lib/tagcloudsection.php diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php new file mode 100644 index 0000000000..f5c305c65f --- /dev/null +++ b/lib/tagcloudsection.php @@ -0,0 +1,142 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +define('TAGS_PER_SECTION', 20); + +/** + * Base class for sections + * + * These are the widgets that show interesting data about a person + * group, or site. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class TagCloudSection extends Section +{ + function showContent() + { + $tags = $this->getAllTags(); + + if (!$tags) { + $this->out->element('p', null, _('None')); + return false; + } + + $cnt = count($tags); + + if ($cnt == 0) { + $this->out->element('p', null, _('(None)')); + return false; + } + + ksort($tags); + + $this->out->elementStart('ul', 'tags xoxo tag-cloud'); + foreach ($tags as $tag => $weight) { + $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); + } + $this->out->elementEnd('ul'); + + return ($cnt > TAGS_PER_SECTION); + } + + function getTags($lst, $usr) + { + $profile_tag = new Profile_tag; + $profile_tag->selectAdd(); + $profile_tag->selectAdd('tag'); + $profile_tag->selectAdd('count(tag) as weight'); + $profile_tag->groupBy('tag'); + $profile_tag->orderBy('weight DESC'); + $cnt = $profile_tag->find(); + + $profile_tag->query(" +SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); + + $tags = array(); + while ($profile_tag->fetch()) { +// var_dump($profile_tag); + $tags[$profile_tag->tag] = $profile_tag->weight; + } + $profile_tag->free(); + if (0) { + echo 'tags:
';
+            var_dump($tags);
+            echo '
'; + } + return $tags; + } + + function getAllTags() { + return null; + } + + function showTag($tag, $weight, $relative) + { + if ($relative > 0.1) { + $rel = 'tag-cloud-7'; + } else if ($relative > 0.05) { + $rel = 'tag-cloud-6'; + } else if ($relative > 0.02) { + $rel = 'tag-cloud-5'; + } else if ($relative > 0.01) { + $rel = 'tag-cloud-4'; + } else if ($relative > 0.005) { + $rel = 'tag-cloud-3'; + } else if ($relative > 0.002) { + $rel = 'tag-cloud-2'; + } else { + $rel = 'tag-cloud-1'; + } + + $this->out->elementStart('li', $rel); + $this->out->element('a', array('href' => $this->tagUrl($tag)), + $tag); + $this->out->elementEnd('li'); + } + + function tagUrl($tag) + { + return common_local_url('tag', array('tag' => $tag)); + } + + function divId() + { + return 'tagcloud'; + } +} From 2873940265611d6556eaee7a01dd53587d7ef446 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:31:22 +0000 Subject: [PATCH 376/503] Fixed file that was removed by mistake. --- lib/tagcloudsection.php | 44 ++++++++++++----------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php index f5c305c65f..ff2aca6d6e 100644 --- a/lib/tagcloudsection.php +++ b/lib/tagcloudsection.php @@ -50,24 +50,32 @@ class TagCloudSection extends Section { function showContent() { - $tags = $this->getAllTags(); + $tags = $this->getTags(); if (!$tags) { $this->out->element('p', null, _('None')); return false; } - $cnt = count($tags); + $cnt = 0; + + $tw = array(); + $sum = 0; + + while ($tags->fetch() && ++$cnt <= TAGS_PER_SECTION) { + $tw[$tags->tag] = $tags->weight; + $sum += $tags->weight; + } if ($cnt == 0) { $this->out->element('p', null, _('(None)')); return false; } - ksort($tags); + ksort($tw); $this->out->elementStart('ul', 'tags xoxo tag-cloud'); - foreach ($tags as $tag => $weight) { + foreach ($tw as $tag => $weight) { $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); } $this->out->elementEnd('ul'); @@ -75,34 +83,8 @@ class TagCloudSection extends Section return ($cnt > TAGS_PER_SECTION); } - function getTags($lst, $usr) + function getTags() { - $profile_tag = new Profile_tag; - $profile_tag->selectAdd(); - $profile_tag->selectAdd('tag'); - $profile_tag->selectAdd('count(tag) as weight'); - $profile_tag->groupBy('tag'); - $profile_tag->orderBy('weight DESC'); - $cnt = $profile_tag->find(); - - $profile_tag->query(" -SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); - - $tags = array(); - while ($profile_tag->fetch()) { -// var_dump($profile_tag); - $tags[$profile_tag->tag] = $profile_tag->weight; - } - $profile_tag->free(); - if (0) { - echo 'tags:
';
-            var_dump($tags);
-            echo '
'; - } - return $tags; - } - - function getAllTags() { return null; } From cb645558a511e0f4a03923a988bda78ceae5ff0d Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:35:51 +0000 Subject: [PATCH 377/503] Fixed file that was removed by mistake. --- lib/tagcloudsection.php | 44 ++++++++++++----------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php index f5c305c65f..ff2aca6d6e 100644 --- a/lib/tagcloudsection.php +++ b/lib/tagcloudsection.php @@ -50,24 +50,32 @@ class TagCloudSection extends Section { function showContent() { - $tags = $this->getAllTags(); + $tags = $this->getTags(); if (!$tags) { $this->out->element('p', null, _('None')); return false; } - $cnt = count($tags); + $cnt = 0; + + $tw = array(); + $sum = 0; + + while ($tags->fetch() && ++$cnt <= TAGS_PER_SECTION) { + $tw[$tags->tag] = $tags->weight; + $sum += $tags->weight; + } if ($cnt == 0) { $this->out->element('p', null, _('(None)')); return false; } - ksort($tags); + ksort($tw); $this->out->elementStart('ul', 'tags xoxo tag-cloud'); - foreach ($tags as $tag => $weight) { + foreach ($tw as $tag => $weight) { $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); } $this->out->elementEnd('ul'); @@ -75,34 +83,8 @@ class TagCloudSection extends Section return ($cnt > TAGS_PER_SECTION); } - function getTags($lst, $usr) + function getTags() { - $profile_tag = new Profile_tag; - $profile_tag->selectAdd(); - $profile_tag->selectAdd('tag'); - $profile_tag->selectAdd('count(tag) as weight'); - $profile_tag->groupBy('tag'); - $profile_tag->orderBy('weight DESC'); - $cnt = $profile_tag->find(); - - $profile_tag->query(" -SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); - - $tags = array(); - while ($profile_tag->fetch()) { -// var_dump($profile_tag); - $tags[$profile_tag->tag] = $profile_tag->weight; - } - $profile_tag->free(); - if (0) { - echo 'tags:
';
-            var_dump($tags);
-            echo '
'; - } - return $tags; - } - - function getAllTags() { return null; } From b22f446df2384c5bd3fa5cf428106ea0a62f1b7d Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 17 Apr 2009 19:51:20 +0000 Subject: [PATCH 378/503] Clear notice char counter for direct messages as well. --- js/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/util.js b/js/util.js index 38d2a9a424..3753bd9898 100644 --- a/js/util.js +++ b/js/util.js @@ -179,12 +179,12 @@ $(document).ready(function(){ } else { $("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true)); - counter(); $("#notices_primary .notice:first").css({display:"none"}); $("#notices_primary .notice:first").fadeIn(2500); NoticeHover(); NoticeReply(); } + counter(); $("#notice_data-text").val(""); } $("#form_notice").removeClass("processing"); From 231c61a7eb3bb79faed696945ccd6d831c80f0f2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 17 Apr 2009 12:52:26 -0700 Subject: [PATCH 379/503] store invite code in session so openidfinish can find it --- actions/finishopenidlogin.php | 33 ++++++- actions/register.php | 171 ++++++++++++++++++++-------------- 2 files changed, 127 insertions(+), 77 deletions(-) diff --git a/actions/finishopenidlogin.php b/actions/finishopenidlogin.php index 952185742f..b08b96df6c 100644 --- a/actions/finishopenidlogin.php +++ b/actions/finishopenidlogin.php @@ -191,11 +191,28 @@ class FinishopenidloginAction extends Action { # FIXME: save invite code before redirect, and check here - if (common_config('site', 'closed') || common_config('site', 'inviteonly')) { + if (common_config('site', 'closed')) { $this->clientError(_('Registration not allowed.')); return; } + $invite = null; + + if (common_config('site', 'inviteonly')) { + $code = $_SESSION['invitecode']; + if (empty($code)) { + $this->clientError(_('Registration not allowed.')); + return; + } + + $invite = Invitation::staticGet($code); + + if (empty($invite)) { + $this->clientError(_('Not a valid invitation code.')); + return; + } + } + $nickname = $this->trimmed('newname'); if (!Validate::string($nickname, array('min_length' => 1, @@ -257,10 +274,16 @@ class FinishopenidloginAction extends Action # XXX: add language # XXX: add timezone - $user = User::register(array('nickname' => $nickname, - 'email' => $email, - 'fullname' => $fullname, - 'location' => $location)); + $args = array('nickname' => $nickname, + 'email' => $email, + 'fullname' => $fullname, + 'location' => $location); + + if (!empty($invite)) { + $args['code'] = $invite->code; + } + + $user = User::register($args); $result = oid_link_user($user->id, $canonical, $display); diff --git a/actions/register.php b/actions/register.php index ab49ad3fdc..4ac7c349d7 100644 --- a/actions/register.php +++ b/actions/register.php @@ -55,6 +55,44 @@ class RegisterAction extends Action var $registered = false; + /** + * Prepare page to run + * + * + * @param $args + * @return string title + */ + + function prepare() + { + $this->code = $this->trimmed('code'); + + if (empty($this->code)) { + common_ensure_session(); + if (!empty($_SESSION['invitecode'])) { + $this->code = $_SESSION['invitecode']; + } + } + + if (common_config('site', 'inviteonly') && empty($this->code)) { + $this->clientError(_('Sorry, only invited people can register.')); + return false; + } + + if (!empty($this->code)) { + $this->invite = Invitation::staticGet($code); + if (empty($this->invite)) { + $this->clientError(_('Sorry, invalid invitation code.')); + return false; + } + // Store this in case we need it + common_ensure_session(); + $_SESSION['invitecode'] = $this->code; + } + + return true; + } + /** * Title of the page * @@ -112,7 +150,7 @@ class RegisterAction extends Action $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { $this->showForm(_('There was a problem with your session token. '. - 'Try again, please.')); + 'Try again, please.')); return; } @@ -145,14 +183,14 @@ class RegisterAction extends Action if (!$this->boolean('license')) { $this->showForm(_('You can\'t register if you don\'t '. - 'agree to the license.')); + 'agree to the license.')); } else if ($email && !Validate::email($email, true)) { $this->showForm(_('Not a valid email address.')); } else if (!Validate::string($nickname, array('min_length' => 1, - 'max_length' => 64, - 'format' => NICKNAME_FMT))) { + 'max_length' => 64, + 'format' => NICKNAME_FMT))) { $this->showForm(_('Nickname must have only lowercase letters '. - 'and numbers and no spaces.')); + 'and numbers and no spaces.')); } else if ($this->nicknameExists($nickname)) { $this->showForm(_('Nickname already in use. Try another one.')); } else if (!User::allowed_nickname($nickname)) { @@ -160,9 +198,9 @@ class RegisterAction extends Action } else if ($this->emailExists($email)) { $this->showForm(_('Email address already exists.')); } else if (!is_null($homepage) && (strlen($homepage) > 0) && - !Validate::uri($homepage, - array('allowed_schemes' => - array('http', 'https')))) { + !Validate::uri($homepage, + array('allowed_schemes' => + array('http', 'https')))) { $this->showForm(_('Homepage is not a valid URL.')); return; } else if (!is_null($fullname) && mb_strlen($fullname) > 255) { @@ -180,13 +218,13 @@ class RegisterAction extends Action } else if ($password != $confirm) { $this->showForm(_('Passwords don\'t match.')); } else if ($user = User::register(array('nickname' => $nickname, - 'password' => $password, - 'email' => $email, - 'fullname' => $fullname, - 'homepage' => $homepage, - 'bio' => $bio, - 'location' => $location, - 'code' => $code))) { + 'password' => $password, + 'email' => $email, + 'fullname' => $fullname, + 'homepage' => $homepage, + 'bio' => $bio, + 'location' => $location, + 'code' => $code))) { if (!$user) { $this->showForm(_('Invalid username or password.')); return; @@ -259,17 +297,17 @@ class RegisterAction extends Action // overrided to add hentry, and content-inner class function showContentBlock() - { - $this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); - $this->showPageTitle(); - $this->showPageNoticeBlock(); - $this->elementStart('div', array('id' => 'content_inner', - 'class' => 'entry-content')); - // show the actual content (forms, lists, whatever) - $this->showContent(); - $this->elementEnd('div'); - $this->elementEnd('div'); - } + { + $this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); + $this->showPageTitle(); + $this->showPageNoticeBlock(); + $this->elementStart('div', array('id' => 'content_inner', + 'class' => 'entry-content')); + // show the actual content (forms, lists, whatever) + $this->showContent(); + $this->elementEnd('div'); + $this->elementEnd('div'); + } /** * Instructions or a notice for the page @@ -343,90 +381,79 @@ class RegisterAction extends Action function showFormContent() { - $code = $this->trimmed('code'); - - if ($code) { - $invite = Invitation::staticGet($code); - } - - if (common_config('site', 'inviteonly') && !($code && $invite)) { - $this->clientError(_('Sorry, only invited people can register.')); - return; - } - $this->elementStart('form', array('method' => 'post', - 'id' => 'form_register', - 'class' => 'form_settings', - 'action' => common_local_url('register'))); + 'id' => 'form_register', + 'class' => 'form_settings', + 'action' => common_local_url('register'))); $this->elementStart('fieldset'); $this->element('legend', null, 'Account settings'); $this->hidden('token', common_session_token()); - if ($code) { - $this->hidden('code', $code); + if ($this->code) { + $this->hidden('code', $this->code); } $this->elementStart('ul', 'form_data'); if (Event::handle('StartRegistrationFormData', array($this))) { $this->elementStart('li'); $this->input('nickname', _('Nickname'), $this->trimmed('nickname'), - _('1-64 lowercase letters or numbers, '. - 'no punctuation or spaces. Required.')); + _('1-64 lowercase letters or numbers, '. + 'no punctuation or spaces. Required.')); $this->elementEnd('li'); $this->elementStart('li'); $this->password('password', _('Password'), - _('6 or more characters. Required.')); + _('6 or more characters. Required.')); $this->elementEnd('li'); $this->elementStart('li'); $this->password('confirm', _('Confirm'), - _('Same as password above. Required.')); + _('Same as password above. Required.')); $this->elementEnd('li'); $this->elementStart('li'); - if ($invite && $invite->address_type == 'email') { - $this->input('email', _('Email'), $invite->address, - _('Used only for updates, announcements, '. - 'and password recovery')); + if ($this->invite && $this->invite->address_type == 'email') { + $this->input('email', _('Email'), $this->invite->address, + _('Used only for updates, announcements, '. + 'and password recovery')); } else { $this->input('email', _('Email'), $this->trimmed('email'), - _('Used only for updates, announcements, '. - 'and password recovery')); + _('Used only for updates, announcements, '. + 'and password recovery')); } $this->elementEnd('li'); $this->elementStart('li'); $this->input('fullname', _('Full name'), - $this->trimmed('fullname'), - _('Longer name, preferably your "real" name')); + $this->trimmed('fullname'), + _('Longer name, preferably your "real" name')); $this->elementEnd('li'); $this->elementStart('li'); $this->input('homepage', _('Homepage'), - $this->trimmed('homepage'), - _('URL of your homepage, blog, '. - 'or profile on another site')); + $this->trimmed('homepage'), + _('URL of your homepage, blog, '. + 'or profile on another site')); $this->elementEnd('li'); $this->elementStart('li'); $this->textarea('bio', _('Bio'), - $this->trimmed('bio'), - _('Describe yourself and your '. - 'interests in 140 chars')); + $this->trimmed('bio'), + _('Describe yourself and your '. + 'interests in 140 chars')); $this->elementEnd('li'); $this->elementStart('li'); $this->input('location', _('Location'), - $this->trimmed('location'), - _('Where you are, like "City, '. - 'State (or Region), Country"')); + $this->trimmed('location'), + _('Where you are, like "City, '. + 'State (or Region), Country"')); $this->elementEnd('li'); Event::handle('EndRegistrationFormData', array($this)); $this->elementStart('li', array('id' => 'settings_rememberme')); $this->checkbox('rememberme', _('Remember me'), - $this->boolean('rememberme'), - _('Automatically login in the future; '. - 'not for shared computers!')); + $this->boolean('rememberme'), + _('Automatically login in the future; '. + 'not for shared computers!')); $this->elementEnd('li'); $attrs = array('type' => 'checkbox', - 'id' => 'license', - 'class' => 'checkbox', - 'name' => 'license', - 'value' => 'true'); + 'id' => 'license', + 'class' => 'checkbox', + 'name' => 'license', + 'value' => 'true'); if ($this->boolean('license')) { $attrs['checked'] = 'checked'; } @@ -435,9 +462,9 @@ class RegisterAction extends Action $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license')); $this->text(_('My text and files are available under ')); $this->element('a', array('href' => common_config('license', 'url')), - common_config('license', 'title'), _("Creative Commons Attribution 3.0")); + common_config('license', 'title'), _("Creative Commons Attribution 3.0")); $this->text(_(' except this private data: password, '. - 'email address, IM address, and phone number.')); + 'email address, IM address, and phone number.')); $this->elementEnd('label'); $this->elementEnd('li'); } From e8382b1292192d4c393f13ad7cd8da1be19211a8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 17 Apr 2009 13:03:33 -0700 Subject: [PATCH 380/503] incorrect variable access --- actions/register.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/actions/register.php b/actions/register.php index 4ac7c349d7..033cf557f8 100644 --- a/actions/register.php +++ b/actions/register.php @@ -63,13 +63,14 @@ class RegisterAction extends Action * @return string title */ - function prepare() + function prepare($args) { + parent::prepare($args); $this->code = $this->trimmed('code'); if (empty($this->code)) { common_ensure_session(); - if (!empty($_SESSION['invitecode'])) { + if (array_key_exists('invitecode', $_SESSION)) { $this->code = $_SESSION['invitecode']; } } @@ -80,7 +81,7 @@ class RegisterAction extends Action } if (!empty($this->code)) { - $this->invite = Invitation::staticGet($code); + $this->invite = Invitation::staticGet('code', $this->code); if (empty($this->invite)) { $this->clientError(_('Sorry, invalid invitation code.')); return false; From 81714c6c31569e35f6b068791870bdfec25d005c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 17 Apr 2009 20:14:06 +0000 Subject: [PATCH 381/503] counter() after val() reset to avoid (weird) bug. --- js/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/util.js b/js/util.js index 3753bd9898..53e6eb7923 100644 --- a/js/util.js +++ b/js/util.js @@ -184,8 +184,8 @@ $(document).ready(function(){ NoticeHover(); NoticeReply(); } - counter(); $("#notice_data-text").val(""); + counter(); } $("#form_notice").removeClass("processing"); $("#notice_action-submit").removeAttr("disabled"); From 7196410bb0398c15fbab767a9b7cedc513e6520b Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 18 Apr 2009 19:00:20 +0200 Subject: [PATCH 382/503] shortening links in notices from XMPP This patch enables shortening of links, that where send from XMPP. The problem was, that in util.php common_current_user() is not finding the user account from which is posted, so the service to shorten is not known, so no shortening at all... This patch cleans up the xmppdaemon a little bit and hard codes ur1.ca as shortening service _if_ the user is not set. Ugly but working. --- lib/util.php | 20 ++++++-------------- scripts/xmppdaemon.php | 17 +++++------------ 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/lib/util.php b/lib/util.php index 675ff51f01..ab5e99593e 100644 --- a/lib/util.php +++ b/lib/util.php @@ -519,11 +519,16 @@ function common_shorten_links($text) function common_shorten_link($url, $reverse = false) { + static $url_cache = array(); if ($reverse) return isset($url_cache[$url]) ? $url_cache[$url] : $url; $user = common_current_user(); - + if (!isset($user)) { + // common current user does not find a user when called from the XMPP daemon + // therefore we'll set one here fix, so that XMPP given URLs may be shortened + $user->urlshorteningservice = 'ur1.ca'; + } $curlh = curl_init(); curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); @@ -1321,16 +1326,3 @@ function common_compatible_license($from, $to) // XXX: better compatibility check needed here! return ($from == $to); } - -/** - * returns a quoted table name, if required according to config - */ -function common_database_tablename($tablename) -{ - - if(common_config('db','quote_identifiers')) { - $tablename = '"'. $tablename .'"'; - } - //table prefixes could be added here later - return $tablename; -} \ No newline at end of file diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index ef3f8c63d8..5711f715df 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -152,11 +152,6 @@ class XMPPDaemon extends Daemon $body = preg_replace('/d[\ ]*('. $to .')[\ ]*/', '', $pl['body']); $this->add_direct($user, $body, $to, $from); } else { - $len = mb_strlen($pl['body']); - if($len > 140) { - $this->from_site($from, 'Message too long - maximum is 140 characters, you sent ' . $len); - return; - } $this->add_notice($user, $pl); } @@ -255,15 +250,13 @@ class XMPPDaemon extends Daemon function add_notice(&$user, &$pl) { $body = trim($pl['body']); - $content_shortened = common_shorten_link($body); + $content_shortened = common_shorten_links($body); if (mb_strlen($content_shortened) > 140) { - $content = trim(mb_substr($body, 0, 140)); - $content_shortened = common_shorten_link($content); + $from = jabber_normalize_jid($pl['from']); + $this->from_site($from, "Message too long - maximum is 140 characters, you sent ".mb_strlen($content_shortened)); + return; } - else { - $content = $body; - } - $notice = Notice::saveNew($user->id, $content, 'xmpp'); + $notice = Notice::saveNew($user->id, $content_shortened, 'xmpp'); if (is_string($notice)) { $this->log(LOG_ERR, $notice); return; From 4b54a418f3f26b44defdb42b8168ae43f4d1c66c Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sat, 18 Apr 2009 19:08:33 +0000 Subject: [PATCH 383/503] trac#1215, 1216, 1217 and 1219: subscribers/subscriptions people tagclouds --- actions/subscribers.php | 10 +++ actions/subscriptions.php | 10 +++ lib/subpeopletagcloudsection.php | 76 +++++++++++++++++++ lib/subscriberspeopleselftagcloudsection.php | 54 +++++++++++++ lib/subscriberspeopletagcloudsection.php | 60 +++++++++++++++ ...subscriptionspeopleselftagcloudsection.php | 54 +++++++++++++ lib/subscriptionspeopletagcloudsection.php | 59 ++++++++++++++ 7 files changed, 323 insertions(+) create mode 100644 lib/subpeopletagcloudsection.php create mode 100644 lib/subscriberspeopleselftagcloudsection.php create mode 100644 lib/subscriberspeopletagcloudsection.php create mode 100644 lib/subscriptionspeopleselftagcloudsection.php create mode 100644 lib/subscriptionspeopletagcloudsection.php diff --git a/actions/subscribers.php b/actions/subscribers.php index d91a7d4fd3..4482de9a7c 100644 --- a/actions/subscribers.php +++ b/actions/subscribers.php @@ -118,6 +118,16 @@ class SubscribersAction extends GalleryAction $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } + + function showSections() + { + parent::showSections(); + $cloud = new SubscribersPeopleTagCloudSection($this); + $cloud->show(); + + $cloud2 = new SubscribersPeopleSelfTagCloudSection($this); + $cloud2->show(); + } } class SubscribersList extends ProfileList diff --git a/actions/subscriptions.php b/actions/subscriptions.php index e6f3c54db8..095b18ad87 100644 --- a/actions/subscriptions.php +++ b/actions/subscriptions.php @@ -125,6 +125,16 @@ class SubscriptionsAction extends GalleryAction $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } + + function showSections() + { + parent::showSections(); + $cloud = new SubscriptionsPeopleTagCloudSection($this); + $cloud->show(); + + $cloud2 = new SubscriptionsPeopleSelfTagCloudSection($this); + $cloud2->show(); + } } class SubscriptionsList extends ProfileList diff --git a/lib/subpeopletagcloudsection.php b/lib/subpeopletagcloudsection.php new file mode 100644 index 0000000000..d98f28afa7 --- /dev/null +++ b/lib/subpeopletagcloudsection.php @@ -0,0 +1,76 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubPeopleTagCloudSection extends TagCloudSection +{ + function getTags() + { + $qry = $this->query(); + $limit = TAGS_PER_SECTION; + $offset = 0; + + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + + $profile_tag = Memcached_DataObject::cachedQuery('Profile_tag', + sprintf($qry, + $this->out->user->id)); + return $profile_tag; + } + + function tagUrl($tag) { + return common_local_url('peopletag', array('tag' => $tag)); + } + + function showTag($tag, $weight, $relative) { + $rel = 'tag-cloud-'; + $rel .= 1+intval(7 * $relative * $weight - 0.01); + + $this->out->elementStart('li', $rel); + $this->out->element('a', array('href' => $this->tagUrl($tag)), $tag); + $this->out->elementEnd('li'); + } +} diff --git a/lib/subscriberspeopleselftagcloudsection.php b/lib/subscriberspeopleselftagcloudsection.php new file mode 100644 index 0000000000..b5a39c6de6 --- /dev/null +++ b/lib/subscriberspeopleselftagcloudsection.php @@ -0,0 +1,54 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as self-tagged'); + } + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; + } +} diff --git a/lib/subscriberspeopletagcloudsection.php b/lib/subscriberspeopletagcloudsection.php new file mode 100644 index 0000000000..23011efdd3 --- /dev/null +++ b/lib/subscriberspeopletagcloudsection.php @@ -0,0 +1,60 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as tagged'); + } + + function tagUrl($tag) { + $nickname = $this->out->profile->nickname; + return common_local_url('subscribers', array('nickname' => $nickname, 'tag' => $tag)); + } + + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; + } +} diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php new file mode 100644 index 0000000000..8ac65adb05 --- /dev/null +++ b/lib/subscriptionspeopleselftagcloudsection.php @@ -0,0 +1,54 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as self-tagged'); + } + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; + } +} diff --git a/lib/subscriptionspeopletagcloudsection.php b/lib/subscriptionspeopletagcloudsection.php new file mode 100644 index 0000000000..c3f7d1763e --- /dev/null +++ b/lib/subscriptionspeopletagcloudsection.php @@ -0,0 +1,59 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as tagged'); + } + + function tagUrl($tag) { + $nickname = $this->out->profile->nickname; + return common_local_url('subscriptions', array('nickname' => $nickname, 'tag' => $tag)); + } + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; + } +} From 90fb7be99a74689de0d0e2409230d8bd515ac5c3 Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sat, 18 Apr 2009 15:33:36 -0400 Subject: [PATCH 384/503] Bringing the presentation of boolean variables (favorited, truncated, profile_background_tile) and the result from friendships/exist in JSON results from the Twitter Compatible API in line with what the real Twitter API does. Currently, laconica returns text strings enclosed in quotes instead of bare Javascript booleans. This change fixes that. See http://laconi.ca/trac/ticket/1326 for one open issue related to this. --- actions/twitapifriendships.php | 6 +----- actions/twitapiusers.php | 2 +- lib/twitterapi.php | 29 ++++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/actions/twitapifriendships.php b/actions/twitapifriendships.php index c50c5e84a9..2f8250e0dc 100644 --- a/actions/twitapifriendships.php +++ b/actions/twitapifriendships.php @@ -133,11 +133,7 @@ class TwitapifriendshipsAction extends TwitterapiAction return; } - if ($user_a->isSubscribed($user_b)) { - $result = 'true'; - } else { - $result = 'false'; - } + $result = $user_a->isSubscribed($user_b); switch ($apidata['content-type']) { case 'xml': diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php index 2894b7486d..41d0d955b1 100644 --- a/actions/twitapiusers.php +++ b/actions/twitapiusers.php @@ -83,7 +83,7 @@ class TwitapiusersAction extends TwitterapiAction $twitter_user['profile_link_color'] = ''; $twitter_user['profile_sidebar_fill_color'] = ''; $twitter_user['profile_sidebar_border_color'] = ''; - $twitter_user['profile_background_tile'] = 'false'; + $twitter_user['profile_background_tile'] = false; $faves = DB_DataObject::factory('fave'); $faves->user_id = $user->id; diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 6a90b4e288..caf8c07163 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -51,6 +51,26 @@ class TwitterapiAction extends Action parent::handle($args); } + /** + * Overrides XMLOutputter::element to write booleans as strings (true|false). + * See that method's documentation for more info. + * + * @param string $tag Element type or tagname + * @param array $attrs Array of element attributes, as + * key-value pairs + * @param string $content string content of the element + * + * @return void + */ + function element($tag, $attrs=null, $content=null) + { + if (is_bool($content)) { + $content = ($content ? 'true' : 'false'); + } + + return parent::element($tag, $attrs, $content); + } + function twitter_user_array($profile, $get_notice=false) { @@ -66,7 +86,7 @@ class TwitterapiAction extends Action $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE); - $twitter_user['protected'] = 'false'; # not supported by Laconica yet + $twitter_user['protected'] = false; # not supported by Laconica yet $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null; if ($get_notice) { @@ -86,7 +106,7 @@ class TwitterapiAction extends Action $twitter_status = array(); $twitter_status['text'] = $notice->content; - $twitter_status['truncated'] = 'false'; # Not possible on Laconica + $twitter_status['truncated'] = false; # Not possible on Laconica $twitter_status['created_at'] = $this->date_twitter($notice->created); $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ? intval($notice->reply_to) : null; @@ -108,10 +128,9 @@ class TwitterapiAction extends Action ($replier_profile) ? $replier_profile->nickname : null; if (isset($this->auth_user)) { - $twitter_status['favorited'] = - ($this->auth_user->hasFave($notice)) ? 'true' : 'false'; + $twitter_status['favorited'] = $this->auth_user->hasFave($notice); } else { - $twitter_status['favorited'] = 'false'; + $twitter_status['favorited'] = false; } if ($include_user) { From b764c3be78aef4305b75b14d7f3e8c9f1c552f9e Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sat, 18 Apr 2009 15:42:44 -0400 Subject: [PATCH 385/503] This should change the JSON representation of the booleans 'following' and 'notifications', but unlike the previous change, I was unable to test this. --- actions/twitapiusers.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php index 41d0d955b1..92d67454cc 100644 --- a/actions/twitapiusers.php +++ b/actions/twitapiusers.php @@ -103,22 +103,14 @@ class TwitapiusersAction extends TwitterapiAction if (isset($apidata['user'])) { - if ($apidata['user']->isSubscribed($profile)) { - $twitter_user['following'] = 'true'; - } else { - $twitter_user['following'] = 'false'; - } + $twitter_user['following'] = $apidata['user']->isSubscribed($profile); // Notifications on? $sub = Subscription::pkeyGet(array('subscriber' => $apidata['user']->id, 'subscribed' => $profile->id)); if ($sub) { - if ($sub->jabber || $sub->sms) { - $twitter_user['notifications'] = 'true'; - } else { - $twitter_user['notifications'] = 'false'; - } + $twitter_user['notifications'] = ($sub->jabber || $sub->sms); } } From 48846c38057b20bb51814c22456d6907cc2a99e8 Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sat, 18 Apr 2009 15:54:23 -0400 Subject: [PATCH 386/503] Fixing spaces/tabs. --- actions/twitapiusers.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php index 92d67454cc..1542cfb33e 100644 --- a/actions/twitapiusers.php +++ b/actions/twitapiusers.php @@ -82,8 +82,8 @@ class TwitapiusersAction extends TwitterapiAction $twitter_user['profile_text_color'] = ''; $twitter_user['profile_link_color'] = ''; $twitter_user['profile_sidebar_fill_color'] = ''; - $twitter_user['profile_sidebar_border_color'] = ''; - $twitter_user['profile_background_tile'] = false; + $twitter_user['profile_sidebar_border_color'] = ''; + $twitter_user['profile_background_tile'] = false; $faves = DB_DataObject::factory('fave'); $faves->user_id = $user->id; @@ -103,16 +103,16 @@ class TwitapiusersAction extends TwitterapiAction if (isset($apidata['user'])) { - $twitter_user['following'] = $apidata['user']->isSubscribed($profile); + $twitter_user['following'] = $apidata['user']->isSubscribed($profile); - // Notifications on? - $sub = Subscription::pkeyGet(array('subscriber' => - $apidata['user']->id, 'subscribed' => $profile->id)); + // Notifications on? + $sub = Subscription::pkeyGet(array('subscriber' => + $apidata['user']->id, 'subscribed' => $profile->id)); - if ($sub) { - $twitter_user['notifications'] = ($sub->jabber || $sub->sms); - } - } + if ($sub) { + $twitter_user['notifications'] = ($sub->jabber || $sub->sms); + } + } if ($apidata['content-type'] == 'xml') { $this->init_document('xml'); From e9213043a820095cceeb6cacbfacf08bba9d3142 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 18 Apr 2009 19:36:25 -0700 Subject: [PATCH 387/503] add reply_to index to notice --- db/laconica.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/laconica.sql b/db/laconica.sql index a790a3fd27..5b57494d98 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -117,6 +117,7 @@ create table notice ( index notice_profile_id_idx (profile_id), index notice_created_idx (created), + index notice_replyto_idx (reply_to), FULLTEXT(content) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci; From 340cd553ec2e028e57f27b30e3a438c4d95584be Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 19 Apr 2009 23:40:37 +0000 Subject: [PATCH 388/503] otalk theme (preliminary) --- theme/otalk/css/base.css | 1201 +++++++++++++++++ theme/otalk/css/display.css | 295 ++++ theme/otalk/css/ie.css | 9 + theme/otalk/default-avatar-mini.png | Bin 0 -> 646 bytes theme/otalk/default-avatar-profile.png | Bin 0 -> 2853 bytes theme/otalk/default-avatar-stream.png | Bin 0 -> 1487 bytes .../illustrations/illu_arrow-left-01.gif | Bin 0 -> 75 bytes .../images/illustrations/illu_pattern-01.png | Bin 0 -> 3218 bytes theme/otalk/logo.png | Bin 0 -> 4988 bytes 9 files changed, 1505 insertions(+) create mode 100644 theme/otalk/css/base.css create mode 100644 theme/otalk/css/display.css create mode 100644 theme/otalk/css/ie.css create mode 100644 theme/otalk/default-avatar-mini.png create mode 100644 theme/otalk/default-avatar-profile.png create mode 100644 theme/otalk/default-avatar-stream.png create mode 100644 theme/otalk/images/illustrations/illu_arrow-left-01.gif create mode 100644 theme/otalk/images/illustrations/illu_pattern-01.png create mode 100644 theme/otalk/logo.png diff --git a/theme/otalk/css/base.css b/theme/otalk/css/base.css new file mode 100644 index 0000000000..c8737ea166 --- /dev/null +++ b/theme/otalk/css/base.css @@ -0,0 +1,1201 @@ +/** theme: italk base + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +* { margin:0; padding:0; } +img { display:block; border:0; } +a abbr { cursor: pointer; border-bottom:0; } +table { border-collapse:collapse; } +ol { list-style-position:inside; } +html { font-size: 87.5%; background-color:#fff; height:100%; } +body { +background-color:#fff; +color:#000; +font-family:sans-serif; +font-size:1em; +line-height:1.65; +position:relative; +} +h1,h2,h3,h4,h5,h6 { +margin-bottom:7px; +overflow:hidden; +} +h1 { +font-size:1.4em; +margin-bottom:18px; +} +#showstream h1 { display:none; } +h2 { font-size:1.3em; } +h3 { font-size:1.2em; } +h4 { font-size:1.1em; } +h5 { font-size:1em; } +h6 { font-size:0.9em; } + +caption { +font-weight:bold; +} +legend { +font-weight:bold; +font-size:1.3em; +} +input, textarea, select, option { +padding:4px; +font-family:sans-serif; +font-size:1em; +} +input, textarea, select { +border-width:2px; +border-style: solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +input.submit { +font-weight:bold; +cursor:pointer; +} +textarea { +overflow:auto; +} +option { +padding-bottom:0; +} +fieldset { +padding:0; +border:0; +} +form ul li { +list-style-type:none; +margin:0 0 18px 0; +} +form label { +font-weight:bold; +} +input.checkbox { +position:relative; +top:2px; +left:0; +border:0; +} + +.error, +.success { +padding:4px 7px; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +margin-bottom:18px; +} +form label.submit { +display:none; +} + +.form_settings { +clear:both; +} + +.form_settings fieldset { +margin-bottom:29px; +} +.form_settings input.remove { +margin-left:11px; +} +.form_settings .form_data li { +width:100%; +float:left; +} +.form_settings .form_data label { +float:left; +} +.form_settings .form_data textarea, +.form_settings .form_data select, +.form_settings .form_data input { +margin-left:11px; +float:left; +} +.form_settings .form_data input.submit { +margin-left:0; +} + +.form_settings label { +margin-top:2px; +width:152px; +} + +.form_actions label { +display:none; +} +.form_guide { +font-style:italic; +} + +.form_settings #settings_autosubscribe label { +display:inline; +font-weight:bold; +} + +#form_settings_profile legend, +#form_login legend, +#form_register legend, +#form_password legend, +#form_settings_avatar legend, +#newgroup legend, +#editgroup legend, +#form_tag_user legend, +#form_remote_subscribe legend, +#form_openid_login legend, +#form_search legend, +#form_invite legend, +#form_notice_delete legend, +#form_password_recover legend, +#form_password_change legend { +display:none; +} + +.form_settings .form_data p.form_guide { +clear:both; +margin-left:163px; +margin-bottom:0; +} + +.form_settings p { +margin-bottom:11px; +} + +.form_settings input.checkbox { +margin-top:3px; +margin-left:0; +} +.form_settings label.checkbox { +font-weight:normal; +margin-top:0; +margin-right:0; +margin-left:11px; +float:left; +width:90%; +} + + +#form_login p.form_guide, +#form_register #settings_rememberme p.form_guide, +#form_openid_login #settings_rememberme p.form_guide, +#settings_twitter_remove p.form_guide, +#form_search ul.form_data #q { +margin-left:0; +} + +.form_settings .form_note { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +padding:0 7px; +} + + +.form_settings input.form_action-secondary { +margin-left:29px; +padding:0; +} + +#form_search .submit { +margin-left:11px; +} + +address { +float:left; +margin-bottom:18px; +margin-left:18px; +} +address.vcard img.logo { +margin-right:0; +} +address .fn { +font-weight:bold; +} +address img + .fn { +display:none; +} + +#header { +width:100%; +position:relative; +float:left; +padding-top:18px; +margin-bottom:29px; +} + +#site_nav_global_primary { +float:right; +margin-right:18px; +margin-bottom:11px; +margin-left:18px; +} +#site_nav_global_primary ul li { +display:inline; +margin-left:11px; +} + +.system_notice dt { +font-weight:bold; +text-transform:uppercase; +display:none; +} + +#site_notice { +position:absolute; +top:65px; +right:18px; +width:250px; +width:24%; +} +#page_notice { +clear:both; +margin-bottom:18px; +} + + +#anon_notice { +float:left; +width:43.2%; +padding:1.1%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-width:2px; +border-style:solid; +line-height:1.5; +font-size:1.1em; +font-weight:bold; +} + + +#footer { +float:left; +width:64%; +padding:18px; +} + +#site_nav_local_views { +float:left; +} +#site_nav_local_views dt { +display:none; +} +#site_nav_local_views li { +float:left; +margin-right:18px; +list-style-type:none; +} +#site_nav_local_views a { +float:left; +text-decoration:none; +padding:4px 11px; +-moz-border-radius-topleft:4px; +-moz-border-radius-topright:4px; +-webkit-border-top-left-radius:4px; +-webkit-border-top-right-radius:4px; +border-width:0; +border-style:solid; +border-bottom:0; +text-shadow: 2px 2px 2px #ddd; +font-weight:bold; +} +#site_nav_local_views .nav { +float:left; +width:100%; +border-bottom-width:1px; +border-bottom-style:solid; +} + +#site_nav_global_primary dt, +#site_nav_global_secondary dt { +display:none; +} + +#site_nav_global_secondary { +margin-bottom:11px; +} + +#site_nav_global_secondary ul li { +display:inline; +margin-right:11px; +} +#export_data li a { +padding-left:20px; +} +#export_data li a.foaf { +padding-left:30px; +} +#export_data li a.export_vcard { +padding-left:28px; +} + +#export_data ul { +display:inline; +} +#export_data li { +list-style-type:none; +display:inline; +margin-left:11px; +} +#export_data li:first-child { +margin-left:0; +} + +#licenses { +font-size:0.9em; +} + +#licenses dt { +font-weight:bold; +display:none; +} +#licenses dd { +margin-bottom:11px; +line-height:1.5; +} + +#site_content_license_cc { +margin-bottom:0; +} +#site_content_license_cc img { +display:inline; +vertical-align:top; +margin-right:4px; +} + +#wrap { +margin:0 auto; +width:100%; +min-width:760px; +max-width:1003px; +overflow:hidden; +} + +#core { +position:relative; +width:100%; +float:left; +margin-bottom:1em; +} + +#content { +width:100%; +min-height:259px; +padding-top:1.795%; +padding-bottom:1.795%; + +float:left; +border-radius:7px; +-moz-border-radius:7px; +-moz-border-radius-topleft:0; +-webkit-border-radius:7px; +-webkit-border-top-left-radius:0; +border-style:solid; +border-width:0; +margin-bottom:18px; +} + +#content_inner { +position:relative; +width:100%; +float:left; +} + +#aside_primary { +width:96.3%; +min-height:259px; +float:left; +clear:both; +padding:1.795%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-width:1px; +border-style:solid; +} + +#form_notice { +width:45.664%; +float:left; +position:relative; +line-height:1; +} +#form_notice fieldset { +border:0; +padding:0; +} +#form_notice legend { +display:none; +} +#form_notice textarea { +float:left; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +width:80.789%; +height:67px; +line-height:1.5; +padding:7px 7px 16px 7px; +} +#form_notice label { +display:block; +float:left; +font-size:1.3em; +margin-bottom:7px; +} +#form_notice #notice_submit label { +display:none; +} +#form_notice .form_note { +position:absolute; +top:99px; +right:98px; +z-index:9; +} +#form_notice .form_note dt { +font-weight:bold; +display:none; +} +#notice_text-count { +font-weight:bold; +line-height:1.15; +padding:1px 2px; +} +#form_notice #notice_action-submit { +width:14%; +height:47px; +padding:0; +position:absolute; +bottom:0; +right:0; +} +#form_notice label[for=to] { +margin-top:7px; +} +#form_notice select[id=to] { +margin-bottom:7px; +margin-left:18px; +float:left; +} + + +/* entity_profile */ +.entity_profile { +position:relative; +width:521px; +min-height:123px; +float:left; +margin-bottom:18px; +margin-left:0; +overflow:hidden; +} +.entity_profile dt, +#entity_statistics dt { +font-weight:bold; +} +.entity_profile dd { +display:inline; +} + +.entity_profile .entity_depiction { +float:left; +width:96px; +margin-right:18px; +margin-bottom:18px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:113px; +margin-bottom:4px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname { +margin-left:11px; +display:inline; +font-weight:bold; +} +.entity_profile .entity_nickname { +margin-left:0; +} + +.entity_profile .entity_fn dd:before { +content: "("; +font-weight:normal; +} +.entity_profile .entity_fn dd:after { +content: ")"; +font-weight:normal; +} + +.entity_profile dt { +display:none; +} +.entity_profile h2 { +display:none; +} +/* entity_profile */ + + +/*entity_actions*/ +.entity_actions { +float:left; +margin-left:4.35%; +max-width:25%; +} +.entity_actions h2 { +display:none; +} +.entity_actions ul { +list-style-type:none; +} +.entity_actions li { +margin-bottom:4px; +} +.entity_actions li:first-child { +border-top:0; +} +.entity_actions fieldset { +border:0; +padding:0; +} +.entity_actions legend { +display:none; +} + +.entity_actions input.submit { +display:block; +text-align:left; +width:100%; +} +.entity_actions a, +.entity_nudge p, +.entity_remote_subscribe { +text-decoration:none; +font-weight:bold; +display:block; +} + +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.entity_edit a, +.form_user_nudge input.submit, +.entity_nudge p { +border:0; +padding-left:20px; +} + +.entity_edit a, +.entity_send-a-message a, +.entity_nudge p { +padding:4px 4px 4px 23px; +} + +.entity_remote_subscribe { +padding:4px; +border-width:2px; +border-style:solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.entity_actions .accept { +margin-bottom:18px; +} + +.entity_tags ul { +list-style-type:none; +display:inline; +} +.entity_tags li { +display:inline; +margin-right:4px; +} + +.aside .section { +margin-bottom:29px; +clear:both; +float:left; +width:100%; +} +.aside .section h2 { +text-transform:uppercase; +font-size:1em; +} + +#entity_statistics dt, +#entity_statistics dd { +display:inline; +} +#entity_statistics dt:after { +content: ":"; +} + +.section ul.entities { +float:left; +width:100%; +} +.section .entities li { +list-style-type:none; +float:left; +margin-right:7px; +margin-bottom:7px; +} +.section .entities li .photo { +margin-right:0; +margin-bottom:0; +} +.section .entities li .fn { +display:none; +} + +.aside .section p, +.aside .section .more { +clear:both; +} + +.profile .entity_profile { +margin-bottom:0; +min-height:60px; +} + + +.profile .form_group_join legend, +.profile .form_group_leave legend, +.profile .form_user_subscribe legend, +.profile .form_user_unsubscribe legend { +display:none; +} + +.profiles { +list-style-type:none; +} +.profile .entity_profile .entity_location { +width:auto; +clear:none; +margin-left:11px; +} +.profile .entity_profile dl, +.profile .entity_profile dd { +display:inline; +float:none; +} +.profile .entity_profile .entity_note, +.profile .entity_profile .entity_url, +.profile .entity_profile .entity_tags, +.profile .entity_profile .form_subscription_edit { +margin-left:59px; +clear:none; +display:block; +width:auto; +} +.profile .entity_profile .entity_tags dt { +display:inline; +margin-right:11px; +} + + +.profile .entity_profile .form_subscription_edit label { +font-weight:normal; +margin-right:11px; +} + + +/* NOTICE */ +.notice, +.profile { +position:relative; +clear:both; +float:left; +width:100%; +border-width:0; +border-style:solid; +margin-bottom:29px; +} +.notices li { +list-style-type:none; +} + +#content .notice { +width:25%; +margin-left:20px; +margin-bottom:47px; +clear:none; +overflow:hidden; +padding: 0 0 0 62px; +min-height:260px; +} + +/* NOTICES */ +#notices_primary { +float:left; +width:100%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +} +#notices_primary h2 { +display:none; +} +.notice-data a span { +display:block; +padding-left:28px; +} + +.notice .author { +margin-right:11px; +} + +#content .notice .author { +/*overflow:hidden;*/ +} + +.fn { +overflow:hidden; +} + +.notice .author .fn { +font-weight:bold; +} + +.notice .author .photo { +margin-bottom:0; +} + +#content .notice .author .photo { +margin-left:-80px; +padding-right:14px; +} + + +.vcard .photo { +display:inline; +margin-right:11px; +margin-bottom:11px; +float:left; +} +.vcard .url { +text-decoration:none; +} +.vcard .url:hover { +text-decoration:underline; +} + +.notice .entry-title { +float:left; +width:100%; +overflow:hidden; +} +#content .notice .entry-title { +overflow:visible; +margin-bottom:11px; +padding:18px; +width:83%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +min-height:165px; +} + +#shownotice .notice .entry-title { +font-size:2.2em; +} + +.notice p.entry-content { +display:inline; +} + +#content .notice p.entry-content +overflow:hidden; +} + +.notice p.entry-content .vcard a { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +.notice div.entry-content { +clear:left; +float:left; +font-size:0.95em; +} +#showstream .notice div.entry-content { +margin-left:0; +} + +.notice .notice-options a, +.notice .notice-options input { +float:left; +font-size:1.025em; +} + +.notice div.entry-content dl, +.notice div.entry-content dt, +.notice div.entry-content dd { +display:inline; +} + +.notice div.entry-content .timestamp dt, +.notice div.entry-content .response dt { +display:none; +} +.notice div.entry-content .timestamp a { +display:inline-block; +} +.notice div.entry-content .device dt { +text-transform:lowercase; +} + + + +.notice-data { +position:absolute; +top:18px; +right:0; +min-height:50px; +margin-bottom:4px; +} +.notice .entry-content .notice-data dt { +display:none; +} + +.notice-data a { +display:block; +outline:none; +} + +.notice-options { +position:absolute; +bottom:110px; +left:29px; +font-size:0.95em; +float:right; +} + +.notice-options a { +float:left; +} +.notice-options .notice_delete, +.notice-options .notice_reply, +.notice-options .form_favor, +.notice-options .form_disfavor { +position:absolute; +left:0; +} +.notice-options .form_favor, +.notice-options .form_disfavor { +top:0; +} +.notice-options .notice_reply { +top:29px; +} +.notice-options .notice_delete { +top:58px; +} +.notice-options .notice_reply dt { +display:none; +} + +.notice-options input, +.notice-options a { +text-indent:-9999px; +outline:none; +} + +.notice-options .notice_reply a, +.notice-options input.submit { +display:block; +border:0; +} +.notice-options .notice_reply a, +.notice-options .notice_delete a { +text-decoration:none; +padding-left:16px; +} + +.notice-options form input.submit { +width:16px; +padding:2px 0; +} + +.notice-options .notice_delete dt, +.notice-options .form_favor legend, +.notice-options .form_disfavor legend { +display:none; +} +.notice-options .notice_delete fieldset, +.notice-options .form_favor fieldset, +.notice-options .form_disfavor fieldset { +border:0; +padding:0; +} + + +#usergroups #new_group { +float: left; +margin-right: 2em; +} +#new_group, #group_search { +margin-bottom:18px; +} +#new_group a { +padding-left:20px; +} + + +#filter_tags { +margin-bottom:11px; +float:left; +} +#filter_tags dt { +display:none; +} +#filter_tags ul { +list-style-type:none; +} +#filter_tags ul li { +float:left; +margin-left:7px; +padding-left:7px; +border-left-width:1px; +border-left-style:solid; +} +#filter_tags ul li.child_1 { +margin-left:0; +border-left:0; +padding-left:0; +} +#filter_tags ul li#filter_tags_all a { +font-weight:bold; +margin-top:7px; +float:left; +} + +#filter_tags ul li#filter_tags_item label { +margin-right:7px; +} +#filter_tags ul li#filter_tags_item label, +#filter_tags ul li#filter_tags_item select { +display:inline; +} +#filter_tags ul li#filter_tags_item p { +float:left; +margin-left:38px; +} +#filter_tags ul li#filter_tags_item input { +position:relative; +top:3px; +left:3px; +} + + + +.pagination { +float:left; +clear:both; +width:100%; +margin-top:18px; +} + +.pagination dt { +font-weight:bold; +display:none; +} + +.pagination .nav { +float:left; +width:100%; +list-style-type:none; +} + +.pagination .nav_prev { +float:left; +} +.pagination .nav_next { +float:right; +} + +.pagination a { +display:block; +text-decoration:none; +font-weight:bold; +padding:7px; +border-width:1px; +border-style:solid; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-radius:7px; +} + +.pagination .nav_prev a { +padding-left:30px; +} +.pagination .nav_next a { +padding-right:30px; +} +/* END: NOTICE */ + + +.hentry .entry-content p { +margin-bottom:18px; +} +.hentry entry-content ol, +.hentry .entry-content ul { +list-style-position:inside; +} +.hentry .entry-content li { +margin-bottom:18px; +} +.hentry .entry-content li li { +margin-left:18px; +} + + + + +/* TOP_POSTERS */ +.section tbody td { +padding-right:11px; +padding-bottom:11px; +} +.section .vcard .photo { +margin-right:7px; +margin-bottom:0; +} + +.section .notice { +padding-top:7px; +padding-bottom:7px; +border-top:0; +} + +.section .notice:first-child { +padding-top:0; +} + +.section .notice .author { +margin-right:0; +} +.section .notice .author .fn { +display:none; +} + + +/* tagcloud */ +.tag-cloud { +list-style-type:none; +text-align:center; +} +.aside .tag-cloud { +font-size:0.8em; +} +.tag-cloud li { +display:inline; +margin-right:7px; +line-height:1.25; +} +.aside .tag-cloud li { +line-height:1.5; +} +.tag-cloud li a { +text-decoration:none; +} +#tagcloud.section dt { +text-transform:uppercase; +font-weight:bold; +} +.tag-cloud-1 { +font-size:1em; +} +.tag-cloud-2 { +font-size:1.25em; +} +.tag-cloud-3 { +font-size:1.75em; +} +.tag-cloud-4 { +font-size:2em; +} +.tag-cloud-5 { +font-size:2.25em; +} +.tag-cloud-6 { +font-size:2.75em; +} +.tag-cloud-7 { +font-size:3.25em; +} + +#publictagcloud #tagcloud.section dt { +display:none; +} + +#form_settings_photo .form_data { +clear:both; +} + +#form_settings_avatar li { +width:auto; +} +#form_settings_avatar input { +margin-left:0; +} +#avatar_original, +#avatar_preview { +float:left; +} +#avatar_preview { +margin-left:29px; +} +#avatar_preview_view { +height:96px; +width:96px; +margin-bottom:18px; +overflow:hidden; +} + +#settings_attach, +#form_settings_avatar .form_actions { +clear:both; +} + +#form_settings_avatar .form_actions { +margin-bottom:0; +} + +#form_settings_design #settings_design_color .form_data, +#form_settings_design #color-picker { +float:left; +} +#form_settings_design #settings_design_color .form_data { +width:400px; +margin-right:28px; +} + +.instructions ul { +list-style-position:inside; +} +.instructions p, +.instructions ul { +margin-bottom:18px; +} +.help dt { +display:none; +} +.guide { +clear:both; +} diff --git a/theme/otalk/css/display.css b/theme/otalk/css/display.css new file mode 100644 index 0000000000..54350fcc6a --- /dev/null +++ b/theme/otalk/css/display.css @@ -0,0 +1,295 @@ +/** theme: identica + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +@import url(base.css); + +html { +} + +html, +body, +a:active { +/*background-color:#F0F2F5;*/ +} +body { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +font-size:1em; +background:#ddd url(../images/illustrations/illu_pattern-01.png) repeat 0 0; +background-color:rgba(127, 127, 127, 0.1); +} +address { +margin-right:7.18%; +} + +input, textarea, select, option { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +} +input, textarea, select, +.entity_remote_subscribe { +border-color:#aaa; +} +#filter_tags ul li { +border-color:#ddd; +} + +.form_settings input.form_action-secondary { +background:none; +} + +input.submit, +#form_notice.warning #notice_text-count, +.form_settings .form_note, +.entity_remote_subscribe { +background-color:#9BB43E; +} + +input:focus, textarea:focus, select:focus, +#form_notice.warning #notice_data-text { +border-color:#9BB43E; +} +input.submit, +.entity_remote_subscribe { +color:#fff; +} + +a, +div.notice-options input, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.form_user_nudge input.submit, +.entity_nudge p, +.form_settings input.form_action-secondary { +color:#8F0000; +} + +.notice, +.profile { +border-color:#CEE1E9; +} +#content .notice .entry-title, +input, textarea, select, option { +background-color:rgba(255,255,255,0.8); +} + +#content .notices li.hover .entry-title { +background-color:rgba(255,255,255,0.9); +} + +#content .notice:nth-child(1) .entry-title { +background-color:rgba(255,255,255,0.95); +font-size:2em; +} +#content .notice:nth-child(2) .entry-title { +background-color:rgba(255,255,255,0.9); +font-size:1.9em; +} +#content .notice:nth-child(3) .entry-title { +background-color:rgba(255,255,255,0.8); +font-size:1.8em; +} +#content .notice:nth-child(4) .entry-title { +background-color:rgba(255,255,255,0.7); +font-size:1.7em; +} +#content .notice:nth-child(5) .entry-title { +background-color:rgba(255,255,255,0.6); +} +#content .notice:nth-child(6) .entry-title { +background-color:rgba(255,255,255,0.5); +} +#content .notice:nth-child(7) .entry-title { +background-color:rgba(255,255,255,0.4); +} +#content .notice:nth-child(8) .entry-title { +background-color:rgba(255,255,255,0.3); +} +#content .notice:nth-child(9) .entry-title { +background-color:rgba(255,255,255,0.2); +} +#content .notice:nth-child(10) { +background-color:rgba(255,255,255,0.1); +} + + +#content .notice .author .photo { +background:url(../images/illustrations/illu_arrow-left-01.gif) no-repeat 100% 0; +} + +.section .profile { +border-top-color:#87B4C8; +} + +#aside_primary { +background-color:rgba(206, 225, 233,0.5); +} + +#notice_text-count { +color:#333; +} +#form_notice.warning #notice_text-count { +color:#000; +} +#form_notice.processing #notice_action-submit { +background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +cursor:wait; +text-indent:-9999px; +} + +#content, +#site_nav_local_views .nav, +#site_nav_local_views a, +#aside_primary { +border-color:#fff; +} +#content, +#site_nav_local_views .current a { +background-color:transparent; +/*background-color:red;*/ +} + +#site_nav_local_views .current a { +background-color:transparent; +} + +#site_nav_local_views a { +background-color:rgba(127, 127, 127, 0.2); +} +#site_nav_local_views a:hover { +background-color:rgba(255, 255, 255, 0.8); +} + +.error { +background-color:#F7E8E8; +} +.success { +background-color:#EFF3DC; +} + +#anon_notice { +background-color:#87B4C8; +color:#fff; +border-color:#fff; +} + +#showstream #anon_notice { +background-color:#9BB43E; +} + +#export_data li a { +background-repeat:no-repeat; +background-position:0 45%; +} +#export_data li a.rss { +background-image:url(../../base/images/icons/icon_rss.png); +} +#export_data li a.atom { +background-image:url(../../base/images/icons/icon_atom.png); +} +#export_data li a.foaf { +background-image:url(../../base/images/icons/icon_foaf.gif); +} + +.entity_edit a, +.entity_send-a-message a, +.form_user_nudge input.submit, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_nudge p { +background-position: 0 40%; +background-repeat: no-repeat; +background-color:transparent; +} +.form_group_join input.submit, +.form_group_leave input.submit +.form_user_subscribe input.submit, +.form_user_unsubscribe input.submit { +background-color:#9BB43E; +color:#fff; +} +.form_user_unsubscribe input.submit, +.form_group_leave input.submit, +.form_user_authorization input.reject { +background-color:#87B4C8; +} + +.entity_edit a { +background-image:url(../../base/images/icons/twotone/green/edit.gif); +} +.entity_send-a-message a { +background-image:url(../../base/images/icons/twotone/green/quote.gif); +} +.entity_nudge p, +.form_user_nudge input.submit { +background-image:url(../../base/images/icons/twotone/green/mail.gif); +} +.form_user_block input.submit, +.form_user_unblock input.submit { +background-image:url(../../base/images/icons/twotone/green/shield.gif); +} + +/* NOTICES */ +.notices li.over { +background-color:#fcfcfc; +} + +.notice-options .notice_reply a, +.notice-options form input.submit { +background-color:transparent; +} +.notice-options .notice_reply a { +background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; +} +.notice-options form.form_favor input.submit { +background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +} +.notice-options form.form_disfavor input.submit { +background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +} +.notice-options .notice_delete a { +background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:0.4; +} +.notices li.hover div.entry-content, +.notices li.hover div.notice-options { +opacity:1; +} +div.entry-content { +color:#333; +} +div.notice-options a, +div.notice-options input { +font-family:sans-serif; +} +.notices li.hover { +/*background-color:#fcfcfc;*/ +} +/*END: NOTICES */ + +#new_group a { +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; +} + +.pagination .nav_prev a, +.pagination .nav_next a { +background-repeat:no-repeat; +border-color:#CEE1E9; +} +.pagination .nav_prev a { +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); +background-position:10% 45%; +} +.pagination .nav_next a { +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); +background-position:90% 45%; +} diff --git a/theme/otalk/css/ie.css b/theme/otalk/css/ie.css new file mode 100644 index 0000000000..2f463bb44d --- /dev/null +++ b/theme/otalk/css/ie.css @@ -0,0 +1,9 @@ +/* IE specific styles */ + +.notice-options input.submit { +color:#fff; +} + +#site_nav_local_views a { +background-color:#D0DFE7; +} diff --git a/theme/otalk/default-avatar-mini.png b/theme/otalk/default-avatar-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..38b8692b4a2f71c8de3d6a12b715df33aada5f7c GIT binary patch literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b literal 0 HcmV?d00001 diff --git a/theme/otalk/default-avatar-profile.png b/theme/otalk/default-avatar-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..f8357d4fc296271b837b3d9911cfbc133918ef2f GIT binary patch literal 2853 zcmb_ei8mD78y=G~k);$_B4nAeWf!uJb!=mwFxIgpYYNHGgi?(!!!%2>gg$GQDZ3$C zn6Z3Be3pqYcBbs~o9}=4-E-dioO|zk&w1~C&-1+RGdmkIZcbrN006*kVQvCrq1S%~ zI>VZOym_F-0`@2)3r7%ZJOcTpvDRn9&E29{{$u|cn~@yxA!}188sZx55QdC?;2r4? zc<|tXV$i*iC|~bzf5ouK0OGo?FaW@rZ((BS_>i>rHW4c7FWjxaVWi+;PI(&gUGbv) zCr`avoO2*wy=Ua~C1uC-v5*p$Q2JAp6N$SP)UT0fjP1Qa2BpIrR1SKnCEBZ}tIn-pzCOAL^VgF4S4C^PNcO*LaWpw=UvIUY^7m4i3h~MsaKF%sZz6N(33sl$Ce5KKlzn4d&swu~LH8q(F3rIK|9vBuDK&Xxv*&|}Nitk@B&1Xm=RlEy_1+0Kbz(#Fg+!DDI8Ugks(!DJ zlHJ;3R+WhBlF8(z-Rby$TN3V2k3L}|iG(&|fP@JrEjY`G;cjO~VGihvZ<#e~wwxS< z?5s_8_w=L@VjHpBh+e2V+cHXD?uusEbpJoL`sGe#%uBD|9!)k10S+Ja_ z0a9dwpwY!V*j{~oJ?mM4S5}&?NlQQ7-i{=fnyAsTpMdMw`HbWN(~h^wT&t3YhlkTj zf1=xucV`B;l$vspajqcy*&O=gGfkkfXiZZH#2ya66}Ix5?)N2y+t1(sZ~Tb_I*s72 z%yvZDdOl$agTdMb<{vHM19Bv;U$?{`i+J_Tx6cb@aL7mOst~EVTOIt~+~F;m1VV2L zx5x-I5q}f_Ls?s5+S`o^Dk|BCnqkh3i6<5y?-T_4Lnvcw_6cu_c5Tm9F!)*44VUXR zf^7Q$8HtWyl9EeNS*=g!bNn-9;AW(6oC-JmXa0?fm%o`2Ao1*s5cG_TyF6G&MPD zX&oKxPEJmQ?)+==z*;hSXmF5kq#<+6r#xIsRP?)B}1gBe9za%a;4x2G{S zR%T|YMZ3v;I3;4{bAauXR;mn{=sKJT}1XAVO%|mv1PPm}K#>vI?{ZlA$M&AI`#-iMpVKHn@jtv9? zF|d{=YJ^HkNf|R;v1n^Rc+Tm{<{ja50flYG=V%7ZGmas>-nh~7vGes`f3=+)A6i&h zF&Tm)B32O*H}8DD$9+eB9o>wf6VyXKl$FhQJmVi3nTxkm&EpfUiC|GlEszE5| zm5rrkes%Thxo!+|>cNcn=Sjxe8pP592D>1ldGDIOe&WO_Q!C{A%z(JKTRJhT;R={n zuT)f2l1G<^j@4G*P?0$aJ8om!RH7z>!DtI6FApy|;XFS@L_~CSb~36$cm?ELb7LnH zucCj8c`56q0B-q$a#jDYK-hiJcz;DePfrgdVPqqd$=tI$)M2QO4M9;>I7NE|VgRoi z(0b!+xiR#zy05(;guDP-o(Me;JHtDJ2!$U)c2n1q~pIBe~HLiIA@tHwJzNo9yij0bKYkjPT z$BPvt9GDbByOUZ1DFrGbQ1b9yjTMbHni)xk8W6=bAEx#>dUg z%*-AZqytz5EkE1iMq))f9`GKELxJZYmSCxhEQb&RflwDtPbPd-A1aO~dlwI{uoQ^! zN=(G!1qQ=BIV|BXd3>!fdMe5TXb#ptb=x_v_4l_s?yc)vWysl6U}+8>QM-_`#%Dha zT%1XL;k3Plc6#{7fB~_T)Mgt{aPI7Ql`rXb0-XA*0=r!u-*u7gJ$8-4_7greHMKg` zIJVJNDTQ|^wuv~}i%`$JGG5;ANVHNB-s9agE3Ba+=SE!+>I(u6-abCbUs8FQTis$V z5h(Gb84Ivpm*I}a+fdzbfjXBURU#Feon6f$;9x^UADn7w^lXS(2M|AoC8Y&D#^ z6k@a(P2%M$3A<8VT`dO&(<>U+Ib{}N+gN|fD&r#~BYO?HI4kgtCZS^D@S{t1Tpwsb z(&*W|RI&WJx;HFc&_N9@YDh^*Jv!N6e6-od(Q;rgb;k2A*gBJ}@D2z7NnAh`800Cn zc66Bh*R}NaN-8M4M5EEMH_v{+zNXW?4-OCamrE-HgMzlcH85ybKRQ{)1~;tP-Tl(sYl+ zS!I7?qkq$*l6##{qYBc%D6;rIMoURyO261pF_VNj@`K5~N77M-xR!a-8 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi literal 0 HcmV?d00001 diff --git a/theme/otalk/images/illustrations/illu_arrow-left-01.gif b/theme/otalk/images/illustrations/illu_arrow-left-01.gif new file mode 100644 index 0000000000000000000000000000000000000000..19777597655b4bc533abcc369e93c49e6e771d96 GIT binary patch literal 75 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 Date: Sun, 19 Apr 2009 23:45:03 +0000 Subject: [PATCH 389/503] Update to theme name in stylesheets. --- theme/otalk/css/base.css | 2 +- theme/otalk/css/display.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/otalk/css/base.css b/theme/otalk/css/base.css index c8737ea166..fc82798c8b 100644 --- a/theme/otalk/css/base.css +++ b/theme/otalk/css/base.css @@ -1,4 +1,4 @@ -/** theme: italk base +/** theme: otalk base * * @package Laconica * @author Sarven Capadisli diff --git a/theme/otalk/css/display.css b/theme/otalk/css/display.css index 54350fcc6a..b6ee9aaeaa 100644 --- a/theme/otalk/css/display.css +++ b/theme/otalk/css/display.css @@ -1,4 +1,4 @@ -/** theme: identica +/** theme: otalk * * @package Laconica * @author Sarven Capadisli From 802c1f121b58651cf2d68207781c09bd8958e546 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 20 Apr 2009 01:00:40 +0000 Subject: [PATCH 390/503] otalk theme update to overflows --- theme/otalk/css/base.css | 24 ++++++++++++++---------- theme/otalk/css/display.css | 8 +++----- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/theme/otalk/css/base.css b/theme/otalk/css/base.css index fc82798c8b..379590d30f 100644 --- a/theme/otalk/css/base.css +++ b/theme/otalk/css/base.css @@ -731,14 +731,19 @@ list-style-type:none; #content .notice { width:25%; -margin-left:20px; +margin-left:17px; margin-bottom:47px; clear:none; overflow:hidden; -padding: 0 0 0 62px; -min-height:260px; +padding: 0 0 0 65px; +min-height:235px; } +#aside_primary .notice { +margin-bottom:18px; +} + + /* NOTICES */ #notices_primary { float:left; @@ -776,8 +781,8 @@ margin-bottom:0; } #content .notice .author .photo { -margin-left:-80px; -padding-right:14px; +margin-left:-83px; +padding-right:17px; } @@ -803,11 +808,11 @@ overflow:hidden; overflow:visible; margin-bottom:11px; padding:18px; -width:83%; +width:85%; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; -min-height:165px; +min-height:161px; } #shownotice .notice .entry-title { @@ -880,10 +885,9 @@ outline:none; .notice-options { position:absolute; -bottom:110px; -left:29px; +top:120px; +left:30px; font-size:0.95em; -float:right; } .notice-options a { diff --git a/theme/otalk/css/display.css b/theme/otalk/css/display.css index b6ee9aaeaa..c039203393 100644 --- a/theme/otalk/css/display.css +++ b/theme/otalk/css/display.css @@ -74,7 +74,9 @@ color:#8F0000; border-color:#CEE1E9; } #content .notice .entry-title, -input, textarea, select, option { +input, textarea, select, option, +.pagination .nav_prev a, +.pagination .nav_next a { background-color:rgba(255,255,255,0.8); } @@ -84,19 +86,15 @@ background-color:rgba(255,255,255,0.9); #content .notice:nth-child(1) .entry-title { background-color:rgba(255,255,255,0.95); -font-size:2em; } #content .notice:nth-child(2) .entry-title { background-color:rgba(255,255,255,0.9); -font-size:1.9em; } #content .notice:nth-child(3) .entry-title { background-color:rgba(255,255,255,0.8); -font-size:1.8em; } #content .notice:nth-child(4) .entry-title { background-color:rgba(255,255,255,0.7); -font-size:1.7em; } #content .notice:nth-child(5) .entry-title { background-color:rgba(255,255,255,0.6); From 5d9862248bebf41bd1f97c03ec9f4f86fa206e82 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 20 Apr 2009 01:58:49 +0000 Subject: [PATCH 391/503] otalk theme: anon_notice background colour update --- theme/otalk/css/display.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/otalk/css/display.css b/theme/otalk/css/display.css index c039203393..22e0530ecc 100644 --- a/theme/otalk/css/display.css +++ b/theme/otalk/css/display.css @@ -171,13 +171,13 @@ background-color:#EFF3DC; } #anon_notice { -background-color:#87B4C8; +background-color:rgba(206, 225, 233, 0.7); color:#fff; border-color:#fff; } #showstream #anon_notice { -background-color:#9BB43E; +background-color:rgba(155, 180, 62, 0.7); } #export_data li a { From aadad4579fcdd3e62f5b8b8f2fcaa6cc282924f2 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 20 Apr 2009 04:37:13 +0000 Subject: [PATCH 392/503] earthy theme preliminary (colours only) --- theme/earthy/css/base.css | 1176 +++++++++++++++++++++++ theme/earthy/css/display.css | 245 +++++ theme/earthy/css/ie.css | 9 + theme/earthy/default-avatar-mini.png | Bin 0 -> 646 bytes theme/earthy/default-avatar-profile.png | Bin 0 -> 2853 bytes theme/earthy/default-avatar-stream.png | Bin 0 -> 1487 bytes theme/earthy/logo.png | Bin 0 -> 4988 bytes 7 files changed, 1430 insertions(+) create mode 100644 theme/earthy/css/base.css create mode 100644 theme/earthy/css/display.css create mode 100644 theme/earthy/css/ie.css create mode 100644 theme/earthy/default-avatar-mini.png create mode 100644 theme/earthy/default-avatar-profile.png create mode 100644 theme/earthy/default-avatar-stream.png create mode 100644 theme/earthy/logo.png diff --git a/theme/earthy/css/base.css b/theme/earthy/css/base.css new file mode 100644 index 0000000000..8ff65ad507 --- /dev/null +++ b/theme/earthy/css/base.css @@ -0,0 +1,1176 @@ +/** theme: earthy base + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +* { margin:0; padding:0; } +img { display:block; border:0; } +a abbr { cursor: pointer; border-bottom:0; } +table { border-collapse:collapse; } +ol { list-style-position:inside; } +html { background-color:#fff; height:100%; } +body { +background-color:#fff; +color:#000; +font-family:sans-serif; +font-size:1em; +line-height:1.65; +position:relative; +} +h1,h2,h3,h4,h5,h6 { +margin-bottom:7px; +overflow:hidden; +} +h1 { +font-size:1.4em; +margin-bottom:18px; +} +#showstream h1 { display:none; } +h2 { font-size:1.3em; } +h3 { font-size:1.2em; } +h4 { font-size:1.1em; } +h5 { font-size:1em; } +h6 { font-size:0.9em; } + +caption { +font-weight:bold; +} +legend { +font-weight:bold; +font-size:1.3em; +} +input, textarea, select, option { +padding:4px; +font-family:sans-serif; +font-size:1em; +} +input, textarea, select { +border-width:2px; +border-style: solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +input.submit { +font-weight:bold; +cursor:pointer; +} +textarea { +overflow:auto; +} +option { +padding-bottom:0; +} +fieldset { +padding:0; +border:0; +} +form ul li { +list-style-type:none; +margin:0 0 18px 0; +} +form label { +font-weight:bold; +} +input.checkbox { +position:relative; +top:2px; +left:0; +border:0; +} + +.error, +.success { +padding:4px 7px; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +margin-bottom:18px; +} +form label.submit { +display:none; +} + +.form_settings { +clear:both; +} + +.form_settings fieldset { +margin-bottom:29px; +} +.form_settings input.remove { +margin-left:11px; +} +.form_settings .form_data li { +width:100%; +float:left; +} +.form_settings .form_data label { +float:left; +} +.form_settings .form_data textarea, +.form_settings .form_data select, +.form_settings .form_data input { +margin-left:11px; +float:left; +} +.form_settings .form_data input.submit { +margin-left:0; +} + +.form_settings label { +margin-top:2px; +width:152px; +} + +.form_actions label { +display:none; +} +.form_guide { +font-style:italic; +} + +.form_settings #settings_autosubscribe label { +display:inline; +font-weight:bold; +} + +#form_settings_profile legend, +#form_login legend, +#form_register legend, +#form_password legend, +#form_settings_avatar legend, +#newgroup legend, +#editgroup legend, +#form_tag_user legend, +#form_remote_subscribe legend, +#form_openid_login legend, +#form_search legend, +#form_invite legend, +#form_notice_delete legend, +#form_password_recover legend, +#form_password_change legend { +display:none; +} + +.form_settings .form_data p.form_guide { +clear:both; +margin-left:163px; +margin-bottom:0; +} + +.form_settings p { +margin-bottom:11px; +} + +.form_settings input.checkbox { +margin-top:3px; +margin-left:0; +} +.form_settings label.checkbox { +font-weight:normal; +margin-top:0; +margin-right:0; +margin-left:11px; +float:left; +width:90%; +} + + +#form_login p.form_guide, +#form_register #settings_rememberme p.form_guide, +#form_openid_login #settings_rememberme p.form_guide, +#settings_twitter_remove p.form_guide, +#form_search ul.form_data #q { +margin-left:0; +} + +.form_settings .form_note { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +padding:0 7px; +} + + +.form_settings input.form_action-secondary { +margin-left:29px; +padding:0; +} + +#form_search .submit { +margin-left:11px; +} + +address { +float:left; +margin-bottom:18px; +margin-left:18px; +} +address.vcard img.logo { +margin-right:0; +} +address .fn { +font-weight:bold; +} +address img + .fn { +display:none; +} + +#header { +width:100%; +position:relative; +float:left; +padding-top:18px; +margin-bottom:29px; +} + +#site_nav_global_primary { +float:right; +margin-right:18px; +margin-bottom:11px; +margin-left:18px; +} +#site_nav_global_primary ul li { +display:inline; +margin-left:11px; +} + +.system_notice dt { +font-weight:bold; +text-transform:uppercase; +display:none; +} + +#site_notice { +position:absolute; +top:65px; +right:18px; +width:250px; +width:24%; +} +#page_notice { +clear:both; +margin-bottom:18px; +} + + +#anon_notice { +float:left; +width:43.2%; +padding:1.1%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-width:2px; +border-style:solid; +line-height:1.5; +font-size:1.1em; +font-weight:bold; +} + + +#footer { +float:left; +width:64%; +padding:18px; +} + +#site_nav_local_views { +float:right; +} +#site_nav_local_views dt { +display:none; +} +#site_nav_local_views li { +float:right; +margin-left:11px; +list-style-type:none; +} +#site_nav_local_views a { +float:left; +text-decoration:none; +padding:4px 11px; +-moz-border-radius-topleft:4px; +-moz-border-radius-topright:4px; +-webkit-border-top-left-radius:4px; +-webkit-border-top-right-radius:4px; +border-width:1px; +border-style:solid; +border-bottom:0; +text-shadow: 2px 2px 2px #ddd; +font-weight:bold; +} +#site_nav_local_views .nav { +float:left; +width:100%; +} + +#site_nav_global_primary dt, +#site_nav_global_secondary dt { +display:none; +} + +#site_nav_global_secondary { +margin-bottom:11px; +} + +#site_nav_global_secondary ul li { +display:inline; +margin-right:11px; +} +#export_data li a { +padding-left:20px; +} +#export_data li a.foaf { +padding-left:30px; +} +#export_data li a.export_vcard { +padding-left:28px; +} + +#export_data ul { +display:inline; +} +#export_data li { +list-style-type:none; +display:inline; +margin-left:11px; +} +#export_data li:first-child { +margin-left:0; +} + +#licenses { +font-size:0.9em; +} + +#licenses dt { +font-weight:bold; +display:none; +} +#licenses dd { +margin-bottom:11px; +line-height:1.5; +} + +#site_content_license_cc { +margin-bottom:0; +} +#site_content_license_cc img { +display:inline; +vertical-align:top; +margin-right:4px; +} + +#wrap { +margin:0 auto; +width:100%; +min-width:760px; +max-width:1003px; +overflow:hidden; +} + +#core { +position:relative; +width:100%; +float:left; +margin-bottom:1em; +} + +#content { +width:64.009%; +min-height:259px; +padding:1.795%; +float:right; +border-radius:7px; +-moz-border-radius:7px; +-moz-border-radius-topright:0; +-webkit-border-radius:7px; +-webkit-border-top-right-radius:0; +border-style:solid; +border-width:1px; +} + +#content_inner { +position:relative; +width:100%; +float:left; +} + +#aside_primary { +width:27.917%; +min-height:259px; +float:right; +margin-right:0.385%; +padding:1.795%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-width:1px; +border-style:solid; +} + +#form_notice { +width:45.664%; +float:left; +position:relative; +line-height:1; +} +#form_notice fieldset { +border:0; +padding:0; +} +#form_notice legend { +display:none; +} +#form_notice textarea { +float:left; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +width:80.789%; +height:67px; +line-height:1.5; +padding:7px 7px 16px 7px; +} +#form_notice label { +display:block; +float:left; +font-size:1.3em; +margin-bottom:7px; +} +#form_notice #notice_submit label { +display:none; +} +#form_notice .form_note { +position:absolute; +top:99px; +right:98px; +z-index:9; +} +#form_notice .form_note dt { +font-weight:bold; +display:none; +} +#notice_text-count { +font-weight:bold; +line-height:1.15; +padding:1px 2px; +} +#form_notice #notice_action-submit { +width:14%; +height:47px; +padding:0; +position:absolute; +bottom:0; +right:0; +} +#form_notice label[for=to] { +margin-top:7px; +} +#form_notice select[id=to] { +margin-bottom:7px; +margin-left:18px; +float:left; +} + + +/* entity_profile */ +.entity_profile { +position:relative; +width:67.702%; +min-height:123px; +float:left; +margin-bottom:18px; +margin-left:0; +overflow:hidden; +} +.entity_profile dt, +#entity_statistics dt { +font-weight:bold; +} +.entity_profile dd { +display:inline; +} + +.entity_profile .entity_depiction { +float:left; +width:96px; +margin-right:18px; +margin-bottom:18px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:113px; +margin-bottom:4px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname { +margin-left:11px; +display:inline; +font-weight:bold; +} +.entity_profile .entity_nickname { +margin-left:0; +} + +.entity_profile .entity_fn dd:before { +content: "("; +font-weight:normal; +} +.entity_profile .entity_fn dd:after { +content: ")"; +font-weight:normal; +} + +.entity_profile dt { +display:none; +} +.entity_profile h2 { +display:none; +} +/* entity_profile */ + + +/*entity_actions*/ +.entity_actions { +float:right; +margin-left:4.35%; +max-width:25%; +} +.entity_actions h2 { +display:none; +} +.entity_actions ul { +list-style-type:none; +} +.entity_actions li { +margin-bottom:4px; +} +.entity_actions li:first-child { +border-top:0; +} +.entity_actions fieldset { +border:0; +padding:0; +} +.entity_actions legend { +display:none; +} + +.entity_actions input.submit { +display:block; +text-align:left; +width:100%; +} +.entity_actions a, +.entity_nudge p, +.entity_remote_subscribe { +text-decoration:none; +font-weight:bold; +display:block; +} + +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.entity_edit a, +.form_user_nudge input.submit, +.entity_nudge p { +border:0; +padding-left:20px; +} + +.entity_edit a, +.entity_send-a-message a, +.entity_nudge p { +padding:4px 4px 4px 23px; +} + +.entity_remote_subscribe { +padding:4px; +border-width:2px; +border-style:solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.entity_actions .accept { +margin-bottom:18px; +} + +.entity_tags ul { +list-style-type:none; +display:inline; +} +.entity_tags li { +display:inline; +margin-right:4px; +} + +.aside .section { +margin-bottom:29px; +clear:both; +float:left; +width:100%; +} +.aside .section h2 { +text-transform:uppercase; +font-size:1em; +} + +#entity_statistics dt, +#entity_statistics dd { +display:inline; +} +#entity_statistics dt:after { +content: ":"; +} + +.section ul.entities { +float:left; +width:100%; +} +.section .entities li { +list-style-type:none; +float:left; +margin-right:7px; +margin-bottom:7px; +} +.section .entities li .photo { +margin-right:0; +margin-bottom:0; +} +.section .entities li .fn { +display:none; +} + +.aside .section p, +.aside .section .more { +clear:both; +} + +.profile .entity_profile { +margin-bottom:0; +min-height:60px; +} + + +.profile .form_group_join legend, +.profile .form_group_leave legend, +.profile .form_user_subscribe legend, +.profile .form_user_unsubscribe legend { +display:none; +} + +.profiles { +list-style-type:none; +} +.profile .entity_profile .entity_location { +width:auto; +clear:none; +margin-left:11px; +} +.profile .entity_profile dl, +.profile .entity_profile dd { +display:inline; +float:none; +} +.profile .entity_profile .entity_note, +.profile .entity_profile .entity_url, +.profile .entity_profile .entity_tags, +.profile .entity_profile .form_subscription_edit { +margin-left:59px; +clear:none; +display:block; +width:auto; +} +.profile .entity_profile .entity_tags dt { +display:inline; +margin-right:11px; +} + + +.profile .entity_profile .form_subscription_edit label { +font-weight:normal; +margin-right:11px; +} + + +/* NOTICE */ +.notice, +.profile { +position:relative; +padding-top:11px; +padding-bottom:11px; +clear:both; +float:left; +width:100%; +border-top-width:1px; +border-top-style:dotted; +} +.notices li { +list-style-type:none; +} +.notices li.hover { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +/* NOTICES */ +#notices_primary { +float:left; +width:100%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +} +#notices_primary h2 { +display:none; +} +.notice-data a span { +display:block; +padding-left:28px; +} + +.notice .author { +margin-right:11px; +} + +.fn { +overflow:hidden; +} + +.notice .author .fn { +font-weight:bold; +} + +.notice .author .photo { +margin-bottom:0; +} + +.vcard .photo { +display:inline; +margin-right:11px; +margin-bottom:11px; +float:left; +} +.vcard .url { +text-decoration:none; +} +.vcard .url:hover { +text-decoration:underline; +} + +.notice .entry-title { +float:left; +width:100%; +overflow:hidden; +} +#shownotice .notice .entry-title { +font-size:2.2em; +} + +.notice p.entry-content { +display:inline; +} + +#content .notice p.entry-content a:visited { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.notice p.entry-content .vcard a { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +.notice div.entry-content { +clear:left; +float:left; +font-size:0.95em; +margin-left:59px; +width:70%; +} +#showstream .notice div.entry-content { +margin-left:0; +} + +.notice .notice-options a, +.notice .notice-options input { +float:left; +font-size:1.025em; +} + +.notice div.entry-content dl, +.notice div.entry-content dt, +.notice div.entry-content dd { +display:inline; +} + +.notice div.entry-content .timestamp dt, +.notice div.entry-content .response dt { +display:none; +} +.notice div.entry-content .timestamp a { +display:inline-block; +} +.notice div.entry-content .device dt { +text-transform:lowercase; +} + + + +.notice-data { +position:absolute; +top:18px; +right:0; +min-height:50px; +margin-bottom:4px; +} +.notice .entry-content .notice-data dt { +display:none; +} + +.notice-data a { +display:block; +outline:none; +} + +.notice-options { +padding-left:2%; +float:left; +width:50%; +position:relative; +font-size:0.95em; +width:12.5%; +float:right; +} + +.notice-options a { +float:left; +} +.notice-options .notice_delete, +.notice-options .notice_reply, +.notice-options .form_favor, +.notice-options .form_disfavor { +position:absolute; +top:0; +} +.notice-options .form_favor, +.notice-options .form_disfavor { +left:0; +} +.notice-options .notice_reply { +left:29px; +} +.notice-options .notice_delete { +right:0; +} +.notice-options .notice_reply dt { +display:none; +} + +.notice-options input, +.notice-options a { +text-indent:-9999px; +outline:none; +} + +.notice-options .notice_reply a, +.notice-options input.submit { +display:block; +border:0; +} +.notice-options .notice_reply a, +.notice-options .notice_delete a { +text-decoration:none; +padding-left:16px; +} + +.notice-options form input.submit { +width:16px; +padding:2px 0; +} + +.notice-options .notice_delete dt, +.notice-options .form_favor legend, +.notice-options .form_disfavor legend { +display:none; +} +.notice-options .notice_delete fieldset, +.notice-options .form_favor fieldset, +.notice-options .form_disfavor fieldset { +border:0; +padding:0; +} + + +#usergroups #new_group { +float: left; +margin-right: 2em; +} +#new_group, #group_search { +margin-bottom:18px; +} +#new_group a { +padding-left:20px; +} + + +#filter_tags { +margin-bottom:11px; +float:left; +} +#filter_tags dt { +display:none; +} +#filter_tags ul { +list-style-type:none; +} +#filter_tags ul li { +float:left; +margin-left:7px; +padding-left:7px; +border-left-width:1px; +border-left-style:solid; +} +#filter_tags ul li.child_1 { +margin-left:0; +border-left:0; +padding-left:0; +} +#filter_tags ul li#filter_tags_all a { +font-weight:bold; +margin-top:7px; +float:left; +} + +#filter_tags ul li#filter_tags_item label { +margin-right:7px; +} +#filter_tags ul li#filter_tags_item label, +#filter_tags ul li#filter_tags_item select { +display:inline; +} +#filter_tags ul li#filter_tags_item p { +float:left; +margin-left:38px; +} +#filter_tags ul li#filter_tags_item input { +position:relative; +top:3px; +left:3px; +} + + + +.pagination { +float:left; +clear:both; +width:100%; +margin-top:18px; +} + +.pagination dt { +font-weight:bold; +display:none; +} + +.pagination .nav { +float:left; +width:100%; +list-style-type:none; +} + +.pagination .nav_prev { +float:left; +} +.pagination .nav_next { +float:right; +} + +.pagination a { +display:block; +text-decoration:none; +font-weight:bold; +padding:7px; +border-width:1px; +border-style:solid; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-radius:7px; +} + +.pagination .nav_prev a { +padding-left:30px; +} +.pagination .nav_next a { +padding-right:30px; +} +/* END: NOTICE */ + + +.hentry .entry-content p { +margin-bottom:18px; +} +.hentry entry-content ol, +.hentry .entry-content ul { +list-style-position:inside; +} +.hentry .entry-content li { +margin-bottom:18px; +} +.hentry .entry-content li li { +margin-left:18px; +} + + + + +/* TOP_POSTERS */ +.section tbody td { +padding-right:11px; +padding-bottom:11px; +} +.section .vcard .photo { +margin-right:7px; +margin-bottom:0; +} + +.section .notice { +padding-top:7px; +padding-bottom:7px; +border-top:0; +} + +.section .notice:first-child { +padding-top:0; +} + +.section .notice .author { +margin-right:0; +} +.section .notice .author .fn { +display:none; +} + + +/* tagcloud */ +.tag-cloud { +list-style-type:none; +text-align:center; +} +.aside .tag-cloud { +font-size:0.8em; +} +.tag-cloud li { +display:inline; +margin-right:7px; +line-height:1.25; +} +.aside .tag-cloud li { +line-height:1.5; +} +.tag-cloud li a { +text-decoration:none; +} +#tagcloud.section dt { +text-transform:uppercase; +font-weight:bold; +} +.tag-cloud-1 { +font-size:1em; +} +.tag-cloud-2 { +font-size:1.25em; +} +.tag-cloud-3 { +font-size:1.75em; +} +.tag-cloud-4 { +font-size:2em; +} +.tag-cloud-5 { +font-size:2.25em; +} +.tag-cloud-6 { +font-size:2.75em; +} +.tag-cloud-7 { +font-size:3.25em; +} + +#publictagcloud #tagcloud.section dt { +display:none; +} + +#form_settings_photo .form_data { +clear:both; +} + +#form_settings_avatar li { +width:auto; +} +#form_settings_avatar input { +margin-left:0; +} +#avatar_original, +#avatar_preview { +float:left; +} +#avatar_preview { +margin-left:29px; +} +#avatar_preview_view { +height:96px; +width:96px; +margin-bottom:18px; +overflow:hidden; +} + +#settings_attach, +#form_settings_avatar .form_actions { +clear:both; +} + +#form_settings_avatar .form_actions { +margin-bottom:0; +} + +#form_settings_design #settings_design_color .form_data, +#form_settings_design #color-picker { +float:left; +} +#form_settings_design #settings_design_color .form_data { +width:400px; +margin-right:28px; +} + +.instructions ul { +list-style-position:inside; +} +.instructions p, +.instructions ul { +margin-bottom:18px; +} +.help dt { +display:none; +} +.guide { +clear:both; +} diff --git a/theme/earthy/css/display.css b/theme/earthy/css/display.css new file mode 100644 index 0000000000..809ac8bc06 --- /dev/null +++ b/theme/earthy/css/display.css @@ -0,0 +1,245 @@ +/** theme: earthy + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +@import url(base.css); + +html, +body, +a:active { +background-color:#665500; +} +body { +font-family: Verdana, sans-serif; +font-size:1em; +} +address { +margin-right:7.18%; +} + +input, textarea, select, option { +font-family: Verdana, sans-serif; +} +input, textarea, select, +.entity_remote_subscribe { +border-color:#aaa; +} +#filter_tags ul li { +border-color:#ddd; +} + +.form_settings input.form_action-secondary { +background:none; +} + +input.submit, +#form_notice.warning #notice_text-count, +.form_settings .form_note, +.entity_remote_subscribe { +background-color:#9BB43E; +} + +input:focus, textarea:focus, select:focus, +#form_notice.warning #notice_data-text { +border-color:#9BB43E; +} +input.submit, +.entity_remote_subscribe { +color:#dddd33; +} + +a, +div.notice-options input, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.form_user_nudge input.submit, +.entity_nudge p, +.form_settings input.form_action-secondary { +color:#ee4400; +} + +.notice, +.profile { +border-top-color:#DDAA00; +} +.section .profile { +border-top-color:#aaaa66; +} + +#content .notice p.entry-content a:visited { +background-color:#fcfcfc; +} +#content .notice p.entry-content .vcard a { +background-color:#fcfffc; +} + +#aside_primary { +background-color:#DDAA00; +} + +#notice_text-count { +color:#333; +} +#form_notice.warning #notice_text-count { +color:#000; +} +#form_notice.processing #notice_action-submit { +background:#dddd33 url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +cursor:wait; +text-indent:-9999px; +} + +#content, +#site_nav_local_views a, +#aside_primary { +border-color:#dddd33; +} +#content, +#site_nav_local_views .current a { +background-color:#dddd33; +} +#site_nav_local_views .current a { +color:#EE4400; +} +#site_nav_local_views a { +background-color:rgba(135, 180, 200, 0.3); +color:#fff; +} +#site_nav_local_views a:hover { +background-color:rgba(255, 255, 255, 0.7); +} + +.error { +background-color:#F7E8E8; +} +.success { +background-color:#EFF3DC; +} + +#anon_notice { +background-color:#aaaa66; +color:#dddd33; +border-color:#dddd33; +} + +#showstream #anon_notice { +background-color:#9BB43E; +} + +#export_data li a { +background-repeat:no-repeat; +background-position:0 45%; +} +#export_data li a.rss { +background-image:url(../../base/images/icons/icon_rss.png); +} +#export_data li a.atom { +background-image:url(../../base/images/icons/icon_atom.png); +} +#export_data li a.foaf { +background-image:url(../../base/images/icons/icon_foaf.gif); +} + +.entity_edit a, +.entity_send-a-message a, +.form_user_nudge input.submit, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_nudge p { +background-position: 0 40%; +background-repeat: no-repeat; +background-color:transparent; +} +.form_group_join input.submit, +.form_group_leave input.submit +.form_user_subscribe input.submit, +.form_user_unsubscribe input.submit { +background-color:#9BB43E; +color:#dddd33; +} +.form_user_unsubscribe input.submit, +.form_group_leave input.submit, +.form_user_authorization input.reject { +background-color:#aaaa66; +} + +.entity_edit a { +background-image:url(../../base/images/icons/twotone/green/edit.gif); +} +.entity_send-a-message a { +background-image:url(../../base/images/icons/twotone/green/quote.gif); +} +.entity_nudge p, +.form_user_nudge input.submit { +background-image:url(../../base/images/icons/twotone/green/mail.gif); +} +.form_user_block input.submit, +.form_user_unblock input.submit { +background-image:url(../../base/images/icons/twotone/green/shield.gif); +} + +/* NOTICES */ +.notices li.over { +background-color:#fcfcfc; +} + +.notice-options .notice_reply a, +.notice-options form input.submit { +background-color:transparent; +} +.notice-options .notice_reply a { +background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; +} +.notice-options form.form_favor input.submit { +background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +} +.notice-options form.form_disfavor input.submit { +background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +} +.notice-options .notice_delete a { +background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:0.4; +} +.notices li.hover div.entry-content, +.notices li.hover div.notice-options { +opacity:1; +} +div.entry-content { +color:#333; +} +div.notice-options a, +div.notice-options input { +font-family:sans-serif; +} +.notices li.hover { +/*background-color:#fcfcfc;*/ +} +/*END: NOTICES */ + +#new_group a { +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; +} + +.pagination .nav_prev a, +.pagination .nav_next a { +background-repeat:no-repeat; +border-color:#DDAA00; +} +.pagination .nav_prev a { +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); +background-position:10% 45%; +} +.pagination .nav_next a { +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); +background-position:90% 45%; +} diff --git a/theme/earthy/css/ie.css b/theme/earthy/css/ie.css new file mode 100644 index 0000000000..2f463bb44d --- /dev/null +++ b/theme/earthy/css/ie.css @@ -0,0 +1,9 @@ +/* IE specific styles */ + +.notice-options input.submit { +color:#fff; +} + +#site_nav_local_views a { +background-color:#D0DFE7; +} diff --git a/theme/earthy/default-avatar-mini.png b/theme/earthy/default-avatar-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..38b8692b4a2f71c8de3d6a12b715df33aada5f7c GIT binary patch literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b literal 0 HcmV?d00001 diff --git a/theme/earthy/default-avatar-profile.png b/theme/earthy/default-avatar-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..f8357d4fc296271b837b3d9911cfbc133918ef2f GIT binary patch literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi literal 0 HcmV?d00001 diff --git a/theme/earthy/logo.png b/theme/earthy/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7c68b34f61008753d12394806c3cf46f7b04effd GIT binary patch literal 4988 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 Date: Mon, 20 Apr 2009 05:06:38 +0000 Subject: [PATCH 393/503] earthy theme: layout experiment --- theme/earthy/css/base.css | 36 ++++++++++++++++++++++++------------ theme/earthy/css/display.css | 14 ++++++++++---- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/theme/earthy/css/base.css b/theme/earthy/css/base.css index 8ff65ad507..6f46eef978 100644 --- a/theme/earthy/css/base.css +++ b/theme/earthy/css/base.css @@ -28,6 +28,7 @@ overflow:hidden; h1 { font-size:1.4em; margin-bottom:18px; +text-align:right; } #showstream h1 { display:none; } h2 { font-size:1.3em; } @@ -309,6 +310,8 @@ font-weight:bold; #site_nav_local_views .nav { float:left; width:100%; +border-bottom-width:1px; +border-bottom-style:solid; } #site_nav_global_primary dt, @@ -384,17 +387,15 @@ margin-bottom:1em; } #content { -width:64.009%; +width:63.009%; min-height:259px; -padding:1.795%; +padding-top:1.795%; +padding-bottom:1.795%; float:right; +clear:both; border-radius:7px; --moz-border-radius:7px; --moz-border-radius-topright:0; --webkit-border-radius:7px; --webkit-border-top-right-radius:0; border-style:solid; -border-width:1px; +border-width:0; } #content_inner { @@ -407,7 +408,8 @@ float:left; width:27.917%; min-height:259px; float:right; -margin-right:0.385%; +margin-right:4.385%; +margin-top:73px; padding:1.795%; border-radius:7px; -moz-border-radius:7px; @@ -713,14 +715,24 @@ margin-right:11px; .notice, .profile { position:relative; -padding-top:11px; -padding-bottom:11px; clear:both; float:left; width:100%; -border-top-width:1px; -border-top-style:dotted; +border-width:1px; +border-style:solid; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; } +#content .notice, +#content .profile { +padding:1.795%; +margin-bottom:44px; +} +#content .notice { +width:96.25%; +} + .notices li { list-style-type:none; } diff --git a/theme/earthy/css/display.css b/theme/earthy/css/display.css index 809ac8bc06..b67700f2d9 100644 --- a/theme/earthy/css/display.css +++ b/theme/earthy/css/display.css @@ -22,6 +22,10 @@ address { margin-right:7.18%; } +h1 { +color:#fff; +} + input, textarea, select, option { font-family: Verdana, sans-serif; } @@ -66,7 +70,7 @@ color:#ee4400; .notice, .profile { -border-top-color:#DDAA00; +border-color:#DDAA00; } .section .profile { border-top-color:#aaaa66; @@ -96,11 +100,13 @@ text-indent:-9999px; } #content, +#site_nav_local_views .nav, #site_nav_local_views a, #aside_primary { border-color:#dddd33; } -#content, +#content .notice, +#content .profile, #site_nav_local_views .current a { background-color:#dddd33; } @@ -108,11 +114,11 @@ background-color:#dddd33; color:#EE4400; } #site_nav_local_views a { -background-color:rgba(135, 180, 200, 0.3); +background-color:rgba(255, 255, 255, 0.2); color:#fff; } #site_nav_local_views a:hover { -background-color:rgba(255, 255, 255, 0.7); +background-color:rgba(255, 255, 255, 0.4); } .error { From 4cb0a929806869b09d4325c1464fc2ecb7b5a76e Mon Sep 17 00:00:00 2001 From: CiaranG Date: Tue, 21 Apr 2009 20:43:57 +0100 Subject: [PATCH 394/503] Add feed2omb to notice sources --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index d5124e223a..ce44f32354 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -8,6 +8,7 @@ VALUES ('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()), ('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()), ('Facebook','Facebook','http://apps.facebook.com/identica/', now()), + ('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()), ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()), ('HelloTxt','HelloTxt','http://hellotxt.com/', now()), ('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()), From ec5e06a542d6b06ea9b1d3de7cb309dd1088b4d4 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Tue, 21 Apr 2009 23:36:15 +0100 Subject: [PATCH 395/503] Suppress errors when checking for the existence of files that might be restricted by open_basedir - should resolve issue #1310 --- lib/common.php | 2 +- lib/util.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common.php b/lib/common.php index b3882d2079..f983c4d168 100644 --- a/lib/common.php +++ b/lib/common.php @@ -192,7 +192,7 @@ $_config_files[] = INSTALLDIR.'/config.php'; $_have_a_config = false; foreach ($_config_files as $_config_file) { - if (file_exists($_config_file)) { + if (@file_exists($_config_file)) { include_once($_config_file); $_have_a_config = true; } diff --git a/lib/util.php b/lib/util.php index e0eda0114b..e1dd238ba8 100644 --- a/lib/util.php +++ b/lib/util.php @@ -966,7 +966,7 @@ function common_root_url($ssl=false) function common_good_rand($bytes) { // XXX: use random.org...? - if (file_exists('/dev/urandom')) { + if (@file_exists('/dev/urandom')) { return common_urandom($bytes); } else { // FIXME: this is probably not good enough return common_mtrand($bytes); From 5f82ce18f012be4fe8d64a2ae79db99c2fd64670 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 21 Apr 2009 19:09:27 -0700 Subject: [PATCH 396/503] Script to import friends timelines from Twitter --- scripts/statusfetcher.php | 453 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 scripts/statusfetcher.php diff --git a/scripts/statusfetcher.php b/scripts/statusfetcher.php new file mode 100644 index 0000000000..d303a098c0 --- /dev/null +++ b/scripts/statusfetcher.php @@ -0,0 +1,453 @@ +#!/usr/bin/env php +. + */ + +// Abort if called from a web server +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +// Uncomment this to get useful console output +define('SCRIPT_DEBUG', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +$flink = new Foreign_link(); +$flink->service = 1; // Twitter +$cnt = $flink->find(); + +print "Updating Twitter friends subscriptions for $cnt users.\n"; + + +while ($flink->fetch()) { + + if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { + + $user = User::staticGet($flink->user_id); + + if (empty($user)) { + common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); + print "Unmatched user for ID $flink->user_id\n"; + continue; + } + + print 'Retrieving Friends Timeline for ' . $flink->user_id . "\n"; + + getTimeline($flink); + + if (defined('SCRIPT_DEBUG')) { + print "\nDONE\n"; + } + } +} + +function getTimeline($flink) +{ + + $fuser = $flink->getForeignUser(); + + if (empty($fuser)) { + common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); + if (defined('SCRIPT_DEBUG')) { + print "Unmatched user for ID $flink->user_id\n"; + } + continue; + } + + $screenname = $fuser->nickname; + + $url = 'http://twitter.com/statuses/friends_timeline.json'; + + $timeline_json = get_twitter_data($url, $fuser->nickname, + $flink->credentials); + + $timeline = json_decode($timeline_json); + + foreach ($timeline as $status) { + + // Hacktastic: filter out stuff coming from Laconica + $source = mb_strtolower(common_config('integration', 'source')); + + if (preg_match("/$source/", mb_strtolower($status->source))) { + continue; + } + + saveStatus($status, $flink); + } + +} + +function saveStatus($status, $flink) +{ + // Do we have a profile for this Twitter user? + + $id = ensureProfile($status->user); + $profile = Profile::staticGet($id); + + if (!$profile) { + common_log(LOG_ERR, 'Problem saving notice. No associated Profile.'); + if (defined('SCRIPT_DEBUG')) { + print "Problem saving notice. No associated Profile.\n"; + } + return null; + } + + $uri = 'http://twitter.com/' . $status->user->screen_name . + '/status/' . $status->id; + + // Skip save if notice source is Laconica or Identi.ca? + + $notice = Notice::staticGet('uri', $uri); + + // check to see if we've already imported the status + if (!$notice) { + + $notice = new Notice(); + + $notice->profile_id = $id; + + $notice->query('BEGIN'); + + // XXX: figure out reply_to + $notice->reply_to = null; + + // XXX: Should this be common_sql_now() instead of status create date? + + $notice->created = strftime('%Y-%m-%d %H:%M:%S', + strtotime($status->created_at)); + $notice->content = $status->text; + $notice->rendered = common_render_content($status->text, $notice); + $notice->source = 'twitter'; + $notice->is_local = 0; + $notice->uri = $uri; + + $notice_id = $notice->insert(); + + if (!$notice_id) { + common_log_db_error($notice, 'INSERT', __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Could not save notice!\n"; + } + } + + # XXX: do we need to change this for remote users? + + $notice->saveReplies(); + + // XXX: Do we want to polute our tag cloud with hashtags from Twitter? + $notice->saveTags(); + $notice->saveGroups(); + + $notice->query('COMMIT'); + + } + + if (!Notice_inbox::staticGet('notice_id', $notice->id)) { + + // Add to inbox + $inbox = new Notice_inbox(); + $inbox->user_id = $flink->user_id; + $inbox->notice_id = $notice->id; + $inbox->created = common_sql_now(); + + $inbox->insert(); + } + +} + +function ensureProfile($user) +{ + + // check to see if there's already a profile for this user + $profileurl = 'http://twitter.com/' . $user->screen_name; + + $profile = Profile::staticGet('profileurl', $profileurl); + + if ($profile) { + + common_debug("Profile for $profile->nickname found."); + + // Check to see if the user's Avatar has changed + checkAvatar($user, $profile); + return $profile->id; + + } else { + + $debugmsg = 'Adding profile and remote profile ' . + "for Twitter user: $profileurl\n"; + common_debug($debugmsg, __FILE__); + if (defined('SCRIPT_DEBUG')) { + print $debugmsg; + } + + $profile = new Profile(); + $profile->query("BEGIN"); + + $profile->nickname = $user->screen_name; + $profile->fullname = $user->name; + $profile->homepage = $user->url; + $profile->bio = $user->description; + $profile->location = $user->location; + $profile->profileurl = $profileurl; + $profile->created = common_sql_now(); + + $id = $profile->insert(); + + if (empty($id)) { + common_log_db_error($profile, 'INSERT', __FILE__); + if (defined('SCRIPT_DEBUG')) { + print 'Could not insert Profile: ' . + common_log_objstring($profile) . "\n"; + } + $profile->query("ROLLBACK"); + return false; + } + + // check for remote profile + $remote_pro = Remote_profile::staticGet('uri', $profileurl); + + if (!$remote_pro) { + + $remote_pro = new Remote_profile(); + + $remote_pro->id = $id; + $remote_pro->uri = $profileurl; + $remote_pro->created = common_sql_now(); + + $rid = $remote_pro->insert(); + + if (empty($rid)) { + common_log_db_error($profile, 'INSERT', __FILE__); + if (defined('SCRIPT_DEBUG')) { + print 'Could not insert Remote_profile: ' . + common_log_objstring($remote_pro) . "\n"; + } + $profile->query("ROLLBACK"); + return false; + } + } + + $profile->query("COMMIT"); + $profile->free(); + unset($profile); + + saveAvatars($user, $id); + + return $id; + } +} + +function checkAvatar($user, $profile) +{ + common_debug("in check avatar"); + + $path_parts = pathinfo($user->profile_image_url); + $newname = 'Twitter_' . $user->id . '_' . + $path_parts['basename']; + + $oldname = $profile->getAvatar(48)->filename; + + if ($newname != $oldname) { + + common_debug("Avatar for Twitter user $profile->nickname has changed."); + common_debug("old: $oldname new: $newname"); + + if (defined('SCRIPT_DEBUG')) { + print "Avatar for Twitter user $user->id has changed.\n"; + print "old: $oldname\n"; + print "new: $newname\n"; + } + + $img_root = substr($path_parts['basename'], 0, -11); + $ext = $path_parts['extension']; + $mediatype = getMediatype($ext); + + foreach (array('mini', 'normal', 'bigger') as $size) { + $url = $path_parts['dirname'] . '/' . + $img_root . '_' . $size . ".$ext"; + $filename = 'Twitter_' . $user->id . '_' . + $img_root . "_$size.$ext"; + + if (fetchAvatar($url, $filename)) { + updateAvatar($profile->id, $size, $mediatype, $filename); + } + } + } + +} + +function getMediatype($ext) +{ + $mediatype = null; + + switch (strtolower($ext)) { + case 'jpg': + $mediatype = 'image/jpg'; + break; + case 'gif': + $mediatype = 'image/gif'; + break; + default: + $mediatype = 'image/png'; + } + + return $mediatype; +} + + +function saveAvatars($user, $id) +{ + $path_parts = pathinfo($user->profile_image_url); + + // basename minus '_normal.ext' + + $ext = $path_parts['extension']; + $end = strlen('_normal' . $ext); + $img_root = substr($path_parts['basename'], 0, -($end+1)); + $mediatype = getMediatype($ext); + + foreach (array('mini', 'normal', 'bigger') as $size) { + $url = $path_parts['dirname'] . '/' . + $img_root . '_' . $size . ".$ext"; + $filename = 'Twitter_' . $user->id . '_' . + $img_root . "_$size.$ext"; + + if (fetchAvatar($url, $filename)) { + newAvatar($id, $size, $mediatype, $filename); + } else { + common_log(LOG_WARNING, "Problem fetching Avatar: $url", __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Problem fetching Avatar: $url\n"; + } + } + } +} + +function updateAvatar($profile_id, $size, $mediatype, $filename) { + + common_debug("updating avatar: $size"); + + $profile = Profile::staticGet($profile_id); + + if (!$profile) { + common_debug("Couldn't get profile: $profile_id!"); + if (defined('SCRIPT_DEBUG')) { + print "Couldn't get profile: $profile_id!\n"; + } + return; + } + + $sizes = array('mini' => 24, 'normal' => 48, 'bigger' => 73); + $avatar = $profile->getAvatar($sizes[$size]); + + if ($avatar) { + common_debug("Deleting $size avatar for $profile->nickname."); + @unlink(INSTALLDIR . '/avatar/' . $avatar->filename); + $avatar->delete(); + } + + newAvatar($profile->id, $size, $mediatype, $filename); +} + +function newAvatar($profile_id, $size, $mediatype, $filename) +{ + $avatar = new Avatar(); + $avatar->profile_id = $profile_id; + + switch($size) { + case 'mini': + $avatar->width = 24; + $avatar->height = 24; + break; + case 'normal': + $avatar->width = 48; + $avatar->height = 48; + break; + default: + + // Note: Twitter's big avatars are a different size than + // Laconica's (Laconica's = 96) + + $avatar->width = 73; + $avatar->height = 73; + } + + $avatar->original = 0; // we don't have the original + $avatar->mediatype = $mediatype; + $avatar->filename = $filename; + $avatar->url = Avatar::url($filename); + + common_debug("new filename: $avatar->url"); + + $avatar->created = common_sql_now(); + + $id = $avatar->insert(); + + if (!$id) { + common_log_db_error($avatar, 'INSERT', __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Could not insert avatar!\n"; + } + + return null; + } + + common_debug("Saved new $size avatar for $profile_id."); + + return $id; +} + +function fetchAvatar($url, $filename) +{ + $avatar_dir = INSTALLDIR . '/avatar/'; + + $avatarfile = $avatar_dir . $filename; + + $out = fopen($avatarfile, 'wb'); + if (!$out) { + common_log(LOG_WARNING, "Couldn't open file $filename", __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Couldn't open file! $filename\n"; + } + return false; + } + + common_debug("Fetching avatar: $url", __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Fetching avatar from Twitter: $url\n"; + } + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_FILE, $out); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + $result = curl_exec($ch); + curl_close($ch); + + fclose($out); + + return $result; +} + From fe3241183e3559442003b9b70435d59126e11b7e Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Thu, 23 Apr 2009 01:03:17 +0000 Subject: [PATCH 397/503] fix join a group link from user homepage when he hasn't posted anything yet --- actions/all.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/all.php b/actions/all.php index a92e554623..a53bbea07b 100644 --- a/actions/all.php +++ b/actions/all.php @@ -93,7 +93,7 @@ class AllAction extends ProfileAction if (common_logged_in()) { $current_user = common_current_user(); if ($this->user->id === $current_user->id) { - $message .= _('Try subscribing to more people, [join a group](%%action.groups) or post something yourself.'); + $message .= _('Try subscribing to more people, [join a group](%%action.groups%%) or post something yourself.'); } else { $message .= sprintf(_('You can try to [nudge %s](../%s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); } From c4941e904316ef98582290602f8cba1d220b873a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 23 Apr 2009 02:17:58 +0000 Subject: [PATCH 398/503] Added ajax responses --- actions/newmessage.php | 45 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/actions/newmessage.php b/actions/newmessage.php index 82276ff341..52d4899ba2 100644 --- a/actions/newmessage.php +++ b/actions/newmessage.php @@ -172,15 +172,54 @@ class NewmessageAction extends Action $this->notify($user, $this->other, $message); - $url = common_local_url('outbox', array('nickname' => $user->nickname)); + if ($this->boolean('ajax')) { + $this->startHTML('text/xml;charset=utf-8'); + $this->elementStart('head'); + $this->element('title', null, _('Message sent')); + $this->elementEnd('head'); + $this->elementStart('body'); + $this->element('p', array('id' => 'command_result'), + sprintf(_('Direct message to %s sent'), + $this->other->nickname)); + $this->elementEnd('body'); + $this->elementEnd('html'); + } else { + $url = common_local_url('outbox', + array('nickname' => $user->nickname)); + common_redirect($url, 303); + } + } - common_redirect($url, 303); + /** + * Show an Ajax-y error message + * + * Goes back to the browser, where it's shown in a popup. + * + * @param string $msg Message to show + * + * @return void + */ + + function ajaxErrorMsg($msg) + { + $this->startHTML('text/xml;charset=utf-8', true); + $this->elementStart('head'); + $this->element('title', null, _('Ajax Error')); + $this->elementEnd('head'); + $this->elementStart('body'); + $this->element('p', array('id' => 'error'), $msg); + $this->elementEnd('body'); + $this->elementEnd('html'); } function showForm($msg = null) { - $this->msg = $msg; + if ($msg && $this->boolean('ajax')) { + $this->ajaxErrorMsg($msg); + return; + } + $this->msg = $msg; $this->showPage(); } From 63c52784c7acc54b0b7b39ff3ca7763774e4ab9a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 23 Apr 2009 02:22:00 +0000 Subject: [PATCH 399/503] Allowing XHR for Inbox/Outbox pages. --- js/util.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/util.js b/js/util.js index 53e6eb7923..13036f7caf 100644 --- a/js/util.js +++ b/js/util.js @@ -192,10 +192,8 @@ $(document).ready(function(){ $("#notice_action-submit").removeClass("disabled"); } }; - if (document.body.id != 'inbox' && document.body.id != 'outbox') { - $("#form_notice").ajaxForm(PostNotice); - $("#form_notice").each(addAjaxHidden); - } + $("#form_notice").ajaxForm(PostNotice); + $("#form_notice").each(addAjaxHidden); NoticeHover(); NoticeReply(); }); From 640628de2d593933e810b4785dfe38923b979713 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 05:03:19 -0400 Subject: [PATCH 400/503] A queuehandler for blowing caches offline We add a queuehandler for blowing the memcached caches off-line. This should speed up the processing of new notices. --- classes/Notice.php | 25 ++++++++++++- lib/util.php | 14 ++++++-- scripts/memcachedqueuehandler.php | 58 +++++++++++++++++++++++++++++++ scripts/startdaemons.sh | 3 +- scripts/stopdaemons.sh | 2 +- 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 scripts/memcachedqueuehandler.php diff --git a/classes/Notice.php b/classes/Notice.php index 5fa0d79a16..fbfeb94899 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -207,7 +207,11 @@ class Notice extends Memcached_DataObject # XXX: someone clever could prepend instead of clearing the cache if (common_config('memcached', 'enabled')) { - $notice->blowCaches(); + if (common_config('queues', 'enabled')) { + $notice->blowAuthorCaches(); + } else { + $notice->blowCaches(); + } } return $notice; @@ -271,6 +275,25 @@ class Notice extends Memcached_DataObject $this->blowGroupCache($blowLast); } + function blowAuthorCaches($blowLast=false) + { + // Clear the user's cache + $cache = common_memcache(); + if ($cache) { + $user = User::staticGet($this->profile_id); + if (!empty($user)) { + $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); + if ($blowLast) { + $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last')); + } + } + $user->free(); + unset($user); + } + $this->blowNoticeCache($blowLast); + $this->blowPublicCache($blowLast); + } + function blowGroupCache($blowLast=false) { $cache = common_memcache(); diff --git a/lib/util.php b/lib/util.php index e0eda0114b..12797891cf 100644 --- a/lib/util.php +++ b/lib/util.php @@ -879,7 +879,17 @@ function common_broadcast_notice($notice, $remote=false) function common_enqueue_notice($notice) { - foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) { + $transports = array('omb', 'sms', 'twitter', 'facebook', 'ping'); + + if (common_config('xmpp', 'enabled')) { + $transports = array_merge($transports, array('jabber', 'public')); + } + + if (common_config('memcached', 'enabled')) { + $transports[] = 'memcached'; + } + + foreach ($transports as $transport) { $qi = new Queue_item(); $qi->notice_id = $notice->id; $qi->transport = $transport; @@ -1332,7 +1342,7 @@ function common_compatible_license($from, $to) */ function common_database_tablename($tablename) { - + if(common_config('db','quote_identifiers')) { $tablename = '"'. $tablename .'"'; } diff --git a/scripts/memcachedqueuehandler.php b/scripts/memcachedqueuehandler.php new file mode 100644 index 0000000000..3fcebcfc30 --- /dev/null +++ b/scripts/memcachedqueuehandler.php @@ -0,0 +1,58 @@ +#!/usr/bin/env php +. + */ + +// Abort if called from a web server + +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +set_error_handler('common_error_handler'); + +class MemcachedQueueHandler extends QueueHandler +{ + function transport() + { + return 'memcached'; + } + + function handle_notice($notice) + { + // XXX: fork here + common_log(LOG_INFO, "Blowing memcached for $notice->id\n"; + $notice->blowCaches(); + return true; + } +} + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +$handler = new MemcachedQueueHandler($resource); + +$handler->runOnce(); diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index c3729761d0..08de6d954a 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -24,7 +24,8 @@ DIR=`dirname $0` for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \ xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \ - twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php; do + twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php \ + memcachedqueuehandler.php; do echo -n "Starting $f..."; php $DIR/$f diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index 2bb8f9ecb2..e5a181cd12 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -24,7 +24,7 @@ SDIR=`dirname $0` DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ - xmppconfirmhandler xmppdaemon twitterhandler facebookhandler ; do + xmppconfirmhandler xmppdaemon twitterhandler facebookhandler memcachedhandler; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do From aee45ea91dcec4736d8b9befe17e030b873d9226 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 05:08:48 -0400 Subject: [PATCH 401/503] Add an inbox queue handler Handle distributing a notice to multiple inboxes in a queue handler rather than in the Web action. --- classes/Notice.php | 5 ++- lib/util.php | 4 +++ scripts/inboxqueuehandler.php | 57 +++++++++++++++++++++++++++++++++++ scripts/startdaemons.sh | 2 +- scripts/stopdaemons.sh | 3 +- 5 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 scripts/inboxqueuehandler.php diff --git a/classes/Notice.php b/classes/Notice.php index fbfeb94899..ff00f2a946 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -197,7 +197,10 @@ class Notice extends Memcached_DataObject $notice->saveTags(); $notice->saveGroups(); - $notice->addToInboxes(); + if (!common_config('queues', 'enabled')) { + $notice->addToInboxes(); + } + $notice->query('COMMIT'); Event::handle('EndNoticeSave', array($notice)); diff --git a/lib/util.php b/lib/util.php index 12797891cf..9b6d2941a0 100644 --- a/lib/util.php +++ b/lib/util.php @@ -889,6 +889,10 @@ function common_enqueue_notice($notice) $transports[] = 'memcached'; } + if (common_config('queues', 'enabled')) { + $transports[] = 'inbox'; + } + foreach ($transports as $transport) { $qi = new Queue_item(); $qi->notice_id = $notice->id; diff --git a/scripts/inboxqueuehandler.php b/scripts/inboxqueuehandler.php new file mode 100644 index 0000000000..16e334b83e --- /dev/null +++ b/scripts/inboxqueuehandler.php @@ -0,0 +1,57 @@ +#!/usr/bin/env php +. + */ + +// Abort if called from a web server + +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +set_error_handler('common_error_handler'); + +class InboxQueueHandler extends QueueHandler +{ + function transport() + { + return 'inbox'; + } + + function handle_notice($notice) + { + common_log(LOG_INFO, "Distributing notice to inboxes for $notice->id"); + $notice->addToInboxes(); + return true; + } +} + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +$handler = new InboxQueueHandler($resource); + +$handler->runOnce(); diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 08de6d954a..66f9ed4e0c 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -25,7 +25,7 @@ DIR=`dirname $0` for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \ xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \ twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php \ - memcachedqueuehandler.php; do + memcachedqueuehandler.php inboxqueuehandler.php; do echo -n "Starting $f..."; php $DIR/$f diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index e5a181cd12..196991de0f 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -24,7 +24,8 @@ SDIR=`dirname $0` DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ - xmppconfirmhandler xmppdaemon twitterhandler facebookhandler memcachedhandler; do + xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ + memcachedhandler inboxhandler; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do From 2053bdabef929f4a095d91fbdd3fa62646e9f332 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 05:23:59 -0400 Subject: [PATCH 402/503] fix parse error in memcachedqueuehandler --- scripts/memcachedqueuehandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/memcachedqueuehandler.php b/scripts/memcachedqueuehandler.php index 3fcebcfc30..43231fa2c6 100644 --- a/scripts/memcachedqueuehandler.php +++ b/scripts/memcachedqueuehandler.php @@ -42,7 +42,7 @@ class MemcachedQueueHandler extends QueueHandler function handle_notice($notice) { // XXX: fork here - common_log(LOG_INFO, "Blowing memcached for $notice->id\n"; + common_log(LOG_INFO, "Blowing memcached for $notice->id"); $notice->blowCaches(); return true; } From 31b04220bd9fbadbfac01b60276a9c14896b6a45 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 09:34:56 +0000 Subject: [PATCH 403/503] incorrect config setting for queues --- classes/Notice.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index ff00f2a946..ebed0b8af5 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -197,7 +197,7 @@ class Notice extends Memcached_DataObject $notice->saveTags(); $notice->saveGroups(); - if (!common_config('queues', 'enabled')) { + if (!common_config('queue', 'enabled')) { $notice->addToInboxes(); } @@ -210,7 +210,7 @@ class Notice extends Memcached_DataObject # XXX: someone clever could prepend instead of clearing the cache if (common_config('memcached', 'enabled')) { - if (common_config('queues', 'enabled')) { + if (common_config('queue', 'enabled')) { $notice->blowAuthorCaches(); } else { $notice->blowCaches(); From ece70bf326fa680ec7acdef00751e2bb71bceee1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 09:35:10 +0000 Subject: [PATCH 404/503] incorrect config setting for inboxes --- lib/util.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index af4db4f02d..d77039b747 100644 --- a/lib/util.php +++ b/lib/util.php @@ -889,7 +889,8 @@ function common_enqueue_notice($notice) $transports[] = 'memcached'; } - if (common_config('queues', 'enabled')) { + if (common_config('inboxes', 'enabled') === true || + common_config('inboxes', 'enabled') === 'transitional') { $transports[] = 'inbox'; } From a3e727823d01ed9fd5f440eeaf27449092309865 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 09:52:21 +0000 Subject: [PATCH 405/503] some basic fixes for inbox and memcached queue handlers --- scripts/inboxqueuehandler.php | 15 +++++++++++++-- scripts/memcachedqueuehandler.php | 16 ++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) mode change 100644 => 100755 scripts/inboxqueuehandler.php mode change 100644 => 100755 scripts/memcachedqueuehandler.php diff --git a/scripts/inboxqueuehandler.php b/scripts/inboxqueuehandler.php old mode 100644 new mode 100755 index 16e334b83e..c76b803898 --- a/scripts/inboxqueuehandler.php +++ b/scripts/inboxqueuehandler.php @@ -29,6 +29,7 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); require_once(INSTALLDIR . '/lib/common.php'); +require_once(INSTALLDIR . '/lib/queuehandler.php'); set_error_handler('common_error_handler'); @@ -39,12 +40,20 @@ class InboxQueueHandler extends QueueHandler return 'inbox'; } + function start() { + $this->log(LOG_INFO, "INITIALIZE"); + return true; + } + function handle_notice($notice) { - common_log(LOG_INFO, "Distributing notice to inboxes for $notice->id"); + $this->log(LOG_INFO, "Distributing notice to inboxes for $notice->id"); $notice->addToInboxes(); return true; } + + function finish() { + } } ini_set("max_execution_time", "0"); @@ -52,6 +61,8 @@ ini_set("max_input_time", "0"); set_time_limit(0); mb_internal_encoding('UTF-8'); -$handler = new InboxQueueHandler($resource); +$id = ($argc > 1) ? $argv[1] : null; + +$handler = new InboxQueueHandler($id); $handler->runOnce(); diff --git a/scripts/memcachedqueuehandler.php b/scripts/memcachedqueuehandler.php old mode 100644 new mode 100755 index 43231fa2c6..6e819b41f1 --- a/scripts/memcachedqueuehandler.php +++ b/scripts/memcachedqueuehandler.php @@ -29,6 +29,7 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); require_once(INSTALLDIR . '/lib/common.php'); +require_once(INSTALLDIR . '/lib/queuehandler.php'); set_error_handler('common_error_handler'); @@ -39,13 +40,22 @@ class MemcachedQueueHandler extends QueueHandler return 'memcached'; } + function start() { + $this->log(LOG_INFO, "INITIALIZE"); + return true; + } + function handle_notice($notice) { // XXX: fork here - common_log(LOG_INFO, "Blowing memcached for $notice->id"); + $this->log(LOG_INFO, "Blowing memcached for $notice->id"); $notice->blowCaches(); return true; } + + function finish() { + } + } ini_set("max_execution_time", "0"); @@ -53,6 +63,8 @@ ini_set("max_input_time", "0"); set_time_limit(0); mb_internal_encoding('UTF-8'); -$handler = new MemcachedQueueHandler($resource); +$id = ($argc > 1) ? $argv[1] : null; + +$handler = new MemcachedQueueHandler($id); $handler->runOnce(); From 7c383dc1d46cae8abc6d1e5c7eb93ad7cdd91f63 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 10:08:26 +0000 Subject: [PATCH 406/503] alert to what transport we're checking for --- lib/queuehandler.php | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/queuehandler.php b/lib/queuehandler.php index 9ce9e32b3b..fde650d9ed 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -36,7 +36,7 @@ class QueueHandler extends Daemon $this->set_id($id); } } - + function class_name() { return ucfirst($this->transport()) . 'Handler'; @@ -46,7 +46,7 @@ class QueueHandler extends Daemon { return strtolower($this->class_name().'.'.$this->get_id()); } - + function get_id() { return $this->_id; @@ -56,16 +56,16 @@ class QueueHandler extends Daemon { $this->_id = $id; } - + function transport() { return null; } - + function start() { } - + function finish() { } @@ -74,14 +74,14 @@ class QueueHandler extends Daemon { return true; } - + function run() { if (!$this->start()) { return false; } - $this->log(LOG_INFO, 'checking for queued notices'); $transport = $this->transport(); + $this->log(LOG_INFO, 'checking for queued notices for "' . $transport . '"'); do { $qi = Queue_item::top($transport); if ($qi) { @@ -113,7 +113,7 @@ class QueueHandler extends Daemon } else { $this->clear_old_claims(); $this->idle(5); - } + } } while (true); if (!$this->finish()) { return false; @@ -127,7 +127,7 @@ class QueueHandler extends Daemon sleep($timeout); } } - + function clear_old_claims() { $qi = new Queue_item(); @@ -137,10 +137,9 @@ class QueueHandler extends Daemon $qi->free(); unset($qi); } - + function log($level, $msg) { common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); } } - \ No newline at end of file From 290ae7888c4d8dbcb703920960b10bca635563ed Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 10:08:51 +0000 Subject: [PATCH 407/503] blow subs cache after updating inboxes --- scripts/inboxqueuehandler.php | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/inboxqueuehandler.php b/scripts/inboxqueuehandler.php index c76b803898..73d31e8542 100755 --- a/scripts/inboxqueuehandler.php +++ b/scripts/inboxqueuehandler.php @@ -49,6 +49,7 @@ class InboxQueueHandler extends QueueHandler { $this->log(LOG_INFO, "Distributing notice to inboxes for $notice->id"); $notice->addToInboxes(); + $notice->blowSubsCache(); return true; } From 1c0d82de3bb7f75649a017a7d5632a6e070876c2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 10:09:08 +0000 Subject: [PATCH 408/503] 8-char limit on transports --- lib/util.php | 3 ++- scripts/memcachedqueuehandler.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/util.php b/lib/util.php index d77039b747..f862d7fcc2 100644 --- a/lib/util.php +++ b/lib/util.php @@ -886,7 +886,8 @@ function common_enqueue_notice($notice) } if (common_config('memcached', 'enabled')) { - $transports[] = 'memcached'; + // Note: limited to 8 chars + $transports[] = 'memcache'; } if (common_config('inboxes', 'enabled') === true || diff --git a/scripts/memcachedqueuehandler.php b/scripts/memcachedqueuehandler.php index 6e819b41f1..185b781f75 100755 --- a/scripts/memcachedqueuehandler.php +++ b/scripts/memcachedqueuehandler.php @@ -37,7 +37,7 @@ class MemcachedQueueHandler extends QueueHandler { function transport() { - return 'memcached'; + return 'memcache'; } function start() { From a9df5eab100bce97da3e028851d224ea2e9fff80 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 10:38:51 +0000 Subject: [PATCH 409/503] insert into user's inbox at Web time --- classes/Notice.php | 76 +++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index ebed0b8af5..27b98de1cc 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -197,7 +197,9 @@ class Notice extends Memcached_DataObject $notice->saveTags(); $notice->saveGroups(); - if (!common_config('queue', 'enabled')) { + if (common_config('queue', 'enabled')) { + $notice->addToAuthorInbox(); + } else { $notice->addToInboxes(); } @@ -282,16 +284,8 @@ class Notice extends Memcached_DataObject { // Clear the user's cache $cache = common_memcache(); - if ($cache) { - $user = User::staticGet($this->profile_id); - if (!empty($user)) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); - if ($blowLast) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last')); - } - } - $user->free(); - unset($user); + if (!empty($cache)) { + $cache->delete(common_cache_key('user:notices_with_friends:' . $this->profile_id)); } $this->blowNoticeCache($blowLast); $this->blowPublicCache($blowLast); @@ -665,6 +659,33 @@ class Notice extends Memcached_DataObject return; } + function addToAuthorInbox() + { + $enabled = common_config('inboxes', 'enabled'); + + if ($enabled === true || $enabled === 'transitional') { + $user = User::staticGet('id', $this->profile_id); + if (empty($user)) { + return; + } + $inbox = new Notice_inbox(); + $UT = common_config('db','type')=='pgsql'?'"user"':'user'; + $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' . + "SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " . + "FROM $UT " . + "WHERE $UT.id = " . $this->profile_id . ' ' . + 'AND NOT EXISTS (SELECT user_id, notice_id ' . + 'FROM notice_inbox ' . + "WHERE user_id = " . $this->profile_id . ' '. + 'AND notice_id = ' . $this->id . ' )'; + if ($enabled === 'transitional') { + $qry .= " AND $UT.inboxed = 1"; + } + $inbox->query($qry); + } + return; + } + function saveGroups() { $enabled = common_config('inboxes', 'enabled'); @@ -717,24 +738,29 @@ class Notice extends Memcached_DataObject // FIXME: do this in an offline daemon - $inbox = new Notice_inbox(); - $UT = common_config('db','type')=='pgsql'?'"user"':'user'; - $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' . - "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " . - "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " . - 'WHERE group_member.group_id = ' . $group->id . ' ' . - 'AND NOT EXISTS (SELECT user_id, notice_id ' . - 'FROM notice_inbox ' . - "WHERE user_id = $UT.id " . - 'AND notice_id = ' . $this->id . ' )'; - if ($enabled === 'transitional') { - $qry .= " AND $UT.inboxed = 1"; - } - $result = $inbox->query($qry); + $this->addToGroupInboxes($group); } } } + function addToGroupInboxes($group) + { + $inbox = new Notice_inbox(); + $UT = common_config('db','type')=='pgsql'?'"user"':'user'; + $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' . + "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " . + "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " . + 'WHERE group_member.group_id = ' . $group->id . ' ' . + 'AND NOT EXISTS (SELECT user_id, notice_id ' . + 'FROM notice_inbox ' . + "WHERE user_id = $UT.id " . + 'AND notice_id = ' . $this->id . ' )'; + if ($enabled === 'transitional') { + $qry .= " AND $UT.inboxed = 1"; + } + $result = $inbox->query($qry); + } + function saveReplies() { // Alternative reply format From 2bdf192dabb9dfbbc889c3387bf5261a2d4166ce Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 23 Apr 2009 21:35:21 +0000 Subject: [PATCH 410/503] XHR alerts for server-side errors: 404, 502, 503, 504. There is also a 7 second timeout if the server doesn't get back with a response. --- js/util.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/js/util.js b/js/util.js index 13036f7caf..c7b1272c8d 100644 --- a/js/util.js +++ b/js/util.js @@ -166,6 +166,25 @@ $(document).ready(function(){ $("#notice_action-submit").addClass("disabled"); return true; }, + timeout: 1000, + error: function (xhr, textStatus, errorThrown) { $("#form_notice").removeClass("processing"); + $("#notice_action-submit").removeAttr("disabled"); + $("#notice_action-submit").removeClass("disabled"); + + if (textStatus == "timeout") { + alert ("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists"); + } + else { + switch(xhr.status) { + default: case 404: + alert("Sorry! We had trouble sending your notice. Please report the problem to the site administrator if this happens again."); + break; + case 502: case 503: case 504: + alert("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists."); + break; + } + } + }, success: function(xml) { if ($("#error", xml).length > 0) { var result = document._importNode($("p", xml).get(0), true); result = result.textContent || result.innerHTML; From 83ba1b0b5ef10dc1101ba35bcde4710fd13179cc Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 23 Apr 2009 21:51:49 +0000 Subject: [PATCH 411/503] The real 7 seconds (7000) timeout for XHR posting. --- js/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/util.js b/js/util.js index c7b1272c8d..16422df579 100644 --- a/js/util.js +++ b/js/util.js @@ -166,7 +166,7 @@ $(document).ready(function(){ $("#notice_action-submit").addClass("disabled"); return true; }, - timeout: 1000, + timeout: 7000, error: function (xhr, textStatus, errorThrown) { $("#form_notice").removeClass("processing"); $("#notice_action-submit").removeAttr("disabled"); $("#notice_action-submit").removeClass("disabled"); From 12867d114d8d40bf9a45b3e1eb9b0e50d736d333 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 24 Apr 2009 17:22:43 +0000 Subject: [PATCH 412/503] UI for server errors. --- js/util.js | 15 +++------------ theme/base/css/display.css | 11 +++++++++-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/js/util.js b/js/util.js index 16422df579..15a14625c7 100644 --- a/js/util.js +++ b/js/util.js @@ -166,23 +166,14 @@ $(document).ready(function(){ $("#notice_action-submit").addClass("disabled"); return true; }, - timeout: 7000, error: function (xhr, textStatus, errorThrown) { $("#form_notice").removeClass("processing"); $("#notice_action-submit").removeAttr("disabled"); $("#notice_action-submit").removeClass("disabled"); - - if (textStatus == "timeout") { - alert ("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists"); + if ($(".error", xhr.responseXML).length > 0) { + $('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true)); } else { - switch(xhr.status) { - default: case 404: - alert("Sorry! We had trouble sending your notice. Please report the problem to the site administrator if this happens again."); - break; - case 502: case 503: case 504: - alert("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists."); - break; - } + alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again."); } }, success: function(xml) { if ($("#error", xml).length > 0) { diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 2fb1c007fc..0bc2e68b65 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -86,7 +86,7 @@ border:0; .error, .success { -padding:4px 7px; +padding:4px 1.55%; border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; @@ -426,6 +426,7 @@ line-height:1; #form_notice fieldset { border:0; padding:0; +position:relative; } #form_notice legend { display:none; @@ -480,7 +481,13 @@ margin-bottom:7px; margin-left:18px; float:left; } - +#form_notice .error { +float:left; +clear:both; +width:96.9%; +margin-bottom:0; +line-height:1.618; +} /* entity_profile */ .entity_profile { From ecb09fb8646def7f6a7c5fc0fc2d4df6676edd06 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 24 Apr 2009 13:31:03 -0400 Subject: [PATCH 413/503] check for existence of xmlrpc extension in LinkbackPlugin --- plugins/LinkbackPlugin.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 881ead99ec..93a0294c4c 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -121,6 +121,12 @@ class LinkbackPlugin extends Plugin { $args = array($this->notice->uri, $url); + if (!extension_loaded('xmlrpc')) { + if (!dl('xmlrpc.so')) { + common_log(LOG_ERR, "Can't pingback; xmlrpc extension not available."); + } + } + $request = xmlrpc_encode_request('pingback.ping', $args); $context = stream_context_create(array('http' => array('method' => "POST", 'header' => @@ -141,7 +147,7 @@ class LinkbackPlugin extends Plugin } // Largely cadged from trackback_cls.php by - // Ran Aroussi , GPL2 + // Ran Aroussi , GPL2 or any later version // http://phptrackback.sourceforge.net/ function getTrackback($text, $url) From c008c0d4a56ec265ba6e10d208f9954510296f12 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 24 Apr 2009 20:01:03 +0000 Subject: [PATCH 414/503] fixed trac#1215, 1216, 1217 and 1219: subscribers/subscriptions people tagclouds. --- lib/subpeopletagcloudsection.php | 1 + lib/subscriberspeopleselftagcloudsection.php | 10 +++++++++- lib/subscriberspeopletagcloudsection.php | 5 +++-- lib/subscriptionspeopleselftagcloudsection.php | 9 ++++++++- lib/subscriptionspeopletagcloudsection.php | 4 +++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/subpeopletagcloudsection.php b/lib/subpeopletagcloudsection.php index d98f28afa7..9f6948dc92 100644 --- a/lib/subpeopletagcloudsection.php +++ b/lib/subpeopletagcloudsection.php @@ -74,3 +74,4 @@ class SubPeopleTagCloudSection extends TagCloudSection $this->out->elementEnd('li'); } } + diff --git a/lib/subscriberspeopleselftagcloudsection.php b/lib/subscriberspeopleselftagcloudsection.php index b5a39c6de6..115241a53f 100644 --- a/lib/subscriberspeopleselftagcloudsection.php +++ b/lib/subscriberspeopleselftagcloudsection.php @@ -49,6 +49,14 @@ class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; + + + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + + } } + diff --git a/lib/subscriberspeopletagcloudsection.php b/lib/subscriberspeopletagcloudsection.php index 23011efdd3..4dafbc1c7d 100644 --- a/lib/subscriberspeopletagcloudsection.php +++ b/lib/subscriberspeopletagcloudsection.php @@ -53,8 +53,9 @@ class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection return common_local_url('subscribers', array('nickname' => $nickname, 'tag' => $tag)); } - function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; } } + diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php index 8ac65adb05..3896294d28 100644 --- a/lib/subscriptionspeopleselftagcloudsection.php +++ b/lib/subscriptionspeopleselftagcloudsection.php @@ -49,6 +49,13 @@ class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; + + + + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; } } + diff --git a/lib/subscriptionspeopletagcloudsection.php b/lib/subscriptionspeopletagcloudsection.php index c3f7d1763e..f9c8672e36 100644 --- a/lib/subscriptionspeopletagcloudsection.php +++ b/lib/subscriptionspeopletagcloudsection.php @@ -54,6 +54,8 @@ class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; } } + From d71fbe9d9693cd5426be74807ff8f18fc6376c56 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 24 Apr 2009 20:28:39 +0000 Subject: [PATCH 415/503] fixed subscriptions dropdown action --- lib/galleryaction.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 0484918ce2..8fa11a7562 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -134,9 +134,11 @@ class GalleryAction extends Action $this->elementStart('li', array('id'=>'filter_tags_item')); $this->elementStart('form', array('name' => 'bytag', 'id' => 'bytag', + 'action' => common_path('?action=' . $this->trimmed('action')), 'method' => 'post')); $this->dropdown('tag', _('Tag'), $content, _('Choose a tag to narrow list'), false, $tag); + $this->hidden('nickname', $this->user->nickname); $this->submit('submit', _('Go')); $this->elementEnd('form'); $this->elementEnd('li'); @@ -169,4 +171,4 @@ class GalleryAction extends Action { return array(); } -} \ No newline at end of file +} From 6eb5a2566f5f29a4c129111e1cc86d85d641a3ad Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 24 Apr 2009 14:27:31 -0700 Subject: [PATCH 416/503] Some clean up -- this still doesn't work, yet. The processes all lose their database connections, including the parent process. --- scripts/statusfetcher.php | 324 +++++++++++++++++++++++--------------- 1 file changed, 198 insertions(+), 126 deletions(-) diff --git a/scripts/statusfetcher.php b/scripts/statusfetcher.php index d303a098c0..8f4b60cf74 100644 --- a/scripts/statusfetcher.php +++ b/scripts/statusfetcher.php @@ -32,38 +32,117 @@ define('SCRIPT_DEBUG', true); require_once(INSTALLDIR . '/lib/common.php'); -$flink = new Foreign_link(); -$flink->service = 1; // Twitter -$cnt = $flink->find(); +$children = array(); +$flink_ids = null; -print "Updating Twitter friends subscriptions for $cnt users.\n"; +$MAXCHILDREN = 5; +$POLL_INTERVAL = 10; // 10 seconds +do { -while ($flink->fetch()) { + $flink = new Foreign_link(); + $flink->service = 1; // Twitter + $cnt = $flink->find(); - if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { + if (defined('SCRIPT_DEBUG')) { + print "Updating Twitter friends subscriptions for $cnt users.\n"; + } - $user = User::staticGet($flink->user_id); + $flink_ids = array(); - if (empty($user)) { - common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); - print "Unmatched user for ID $flink->user_id\n"; - continue; + // XXX: This only reliably happens once. After the first interation of + // the do loop, the ->find() doesn't work ... lost DB connection? + + while ($flink->fetch()) { + + if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { + $flink_ids[] = $flink->foreign_id; } - - print 'Retrieving Friends Timeline for ' . $flink->user_id . "\n"; - - getTimeline($flink); - + } + + $flink->free(); + unset($flink); + + foreach ($flink_ids as $f){ + + $pid = pcntl_fork(); + + if ($pid == -1) { + die ("Couldn't fork!"); + } + + // Parent + if ($pid) { + if (defined('SCRIPT_DEBUG')) { + print "Parent: forked " . $pid . "\n"; + } + $children[] = $pid; + } else { + + // Child + + // XXX: Each child needs its own DB connection + + getTimeline($f); + exit(); + } + + // Remove child from ps list as it finishes + while(($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) { + if (defined('SCRIPT_DEBUG')) { + print "Child $c finished.\n"; + } + remove_ps($children, $c); + } + + // Wait if we have too many kids + if(sizeof($children) > $MAXCHILDREN) { + if (defined('SCRIPT_DEBUG')) { + print "Too many children. Waiting...\n"; + } + if( ($c = pcntl_wait($status, WUNTRACED) ) > 0){ + if (defined('SCRIPT_DEBUG')) { + print "Finished waiting for $c\n"; + } + remove_ps($children, $c); + } + } + } + + // Remove all children from the process list before restarting + while(($c = pcntl_wait($status, WUNTRACED)) > 0) { if (defined('SCRIPT_DEBUG')) { - print "\nDONE\n"; + print "Child $c finished.\n"; + } + remove_ps($children, $c); + } + + // Rest for a bit before we fetch more statuses + if (defined('SCRIPT_DEBUG')) { + print "Waiting $POLL_INTERVAL secs before hitting Twitter again.\n"; + } + + sleep($POLL_INTERVAL); + +} while (true); + + +function remove_ps(&$plist, $ps){ + for($i = 0; $i < sizeof($plist); $i++){ + if($plist[$i] == $ps){ + unset($plist[$i]); + $plist = array_values($plist); + break; } } } -function getTimeline($flink) +function getTimeline($fid) { + // XXX: Need to reconnect to the DB here? + + $flink = Foreign_link::getByForeignID($fid, 1); $fuser = $flink->getForeignUser(); if (empty($fuser)) { @@ -71,7 +150,6 @@ function getTimeline($flink) if (defined('SCRIPT_DEBUG')) { print "Unmatched user for ID $flink->user_id\n"; } - continue; } $screenname = $fuser->nickname; @@ -82,26 +160,34 @@ function getTimeline($flink) $flink->credentials); $timeline = json_decode($timeline_json); - + + if (empty($timeline)) { + common_log(LOG_WARNING, "Empty timeline."); + if (defined('SCRIPT_DEBUG')) { + print "Empty timeline!\n"; + } + return; + } + foreach ($timeline as $status) { - + // Hacktastic: filter out stuff coming from Laconica $source = mb_strtolower(common_config('integration', 'source')); - + if (preg_match("/$source/", mb_strtolower($status->source))) { continue; } - + saveStatus($status, $flink); } - + } function saveStatus($status, $flink) { - // Do we have a profile for this Twitter user? - - $id = ensureProfile($status->user); + // Do we have a profile for this Twitter user? + + $id = ensureProfile($status->user); $profile = Profile::staticGet($id); if (!$profile) { @@ -112,34 +198,33 @@ function saveStatus($status, $flink) return null; } - $uri = 'http://twitter.com/' . $status->user->screen_name . + $uri = 'http://twitter.com/' . $status->user->screen_name . '/status/' . $status->id; - - // Skip save if notice source is Laconica or Identi.ca? - - $notice = Notice::staticGet('uri', $uri); - + + // Skip save if notice source is Laconica or Identi.ca? + + $notice = Notice::staticGet('uri', $uri); + // check to see if we've already imported the status if (!$notice) { - - $notice = new Notice(); + $notice = new Notice(); $notice->profile_id = $id; - $notice->query('BEGIN'); + $notice->query('BEGIN'); // XXX: figure out reply_to - $notice->reply_to = null; - - // XXX: Should this be common_sql_now() instead of status create date? - - $notice->created = strftime('%Y-%m-%d %H:%M:%S', - strtotime($status->created_at)); - $notice->content = $status->text; - $notice->rendered = common_render_content($status->text, $notice); - $notice->source = 'twitter'; - $notice->is_local = 0; - $notice->uri = $uri; + $notice->reply_to = null; + + // XXX: Should this be common_sql_now() instead of status create date? + + $notice->created = strftime('%Y-%m-%d %H:%M:%S', + strtotime($status->created_at)); + $notice->content = $status->text; + $notice->rendered = common_render_content($status->text, $notice); + $notice->source = 'twitter'; + $notice->is_local = 0; + $notice->uri = $uri; $notice_id = $notice->insert(); @@ -150,59 +235,54 @@ function saveStatus($status, $flink) } } - # XXX: do we need to change this for remote users? - + // XXX: Figure out a better way to link replies? $notice->saveReplies(); - + // XXX: Do we want to polute our tag cloud with hashtags from Twitter? $notice->saveTags(); - $notice->saveGroups(); - + $notice->saveGroups(); + $notice->query('COMMIT'); - + } if (!Notice_inbox::staticGet('notice_id', $notice->id)) { - + // Add to inbox $inbox = new Notice_inbox(); $inbox->user_id = $flink->user_id; $inbox->notice_id = $notice->id; $inbox->created = common_sql_now(); - - $inbox->insert(); - } + $inbox->insert(); + } } -function ensureProfile($user) +function ensureProfile($user) { - + // check to see if there's already a profile for this user $profileurl = 'http://twitter.com/' . $user->screen_name; - $profile = Profile::staticGet('profileurl', $profileurl); - + if ($profile) { - common_debug("Profile for $profile->nickname found."); - + // Check to see if the user's Avatar has changed checkAvatar($user, $profile); return $profile->id; - + } else { - $debugmsg = 'Adding profile and remote profile ' . "for Twitter user: $profileurl\n"; common_debug($debugmsg, __FILE__); if (defined('SCRIPT_DEBUG')) { print $debugmsg; } - + $profile = new Profile(); $profile->query("BEGIN"); - + $profile->nickname = $user->screen_name; $profile->fullname = $user->name; $profile->homepage = $user->url; @@ -216,37 +296,37 @@ function ensureProfile($user) if (empty($id)) { common_log_db_error($profile, 'INSERT', __FILE__); if (defined('SCRIPT_DEBUG')) { - print 'Could not insert Profile: ' . + print 'Could not insert Profile: ' . common_log_objstring($profile) . "\n"; } $profile->query("ROLLBACK"); return false; - } - - // check for remote profile + } + + // check for remote profile $remote_pro = Remote_profile::staticGet('uri', $profileurl); - + if (!$remote_pro) { - + $remote_pro = new Remote_profile(); $remote_pro->id = $id; $remote_pro->uri = $profileurl; $remote_pro->created = common_sql_now(); - + $rid = $remote_pro->insert(); - - if (empty($rid)) { + + if (empty($rid)) { common_log_db_error($profile, 'INSERT', __FILE__); if (defined('SCRIPT_DEBUG')) { - print 'Could not insert Remote_profile: ' . + print 'Could not insert Remote_profile: ' . common_log_objstring($remote_pro) . "\n"; } $profile->query("ROLLBACK"); return false; - } + } } - + $profile->query("COMMIT"); $profile->free(); unset($profile); @@ -258,24 +338,22 @@ function ensureProfile($user) } function checkAvatar($user, $profile) -{ - common_debug("in check avatar"); - +{ $path_parts = pathinfo($user->profile_image_url); - $newname = 'Twitter_' . $user->id . '_' . + $newname = 'Twitter_' . $user->id . '_' . $path_parts['basename']; - + $oldname = $profile->getAvatar(48)->filename; if ($newname != $oldname) { - + common_debug("Avatar for Twitter user $profile->nickname has changed."); common_debug("old: $oldname new: $newname"); - + if (defined('SCRIPT_DEBUG')) { print "Avatar for Twitter user $user->id has changed.\n"; print "old: $oldname\n"; - print "new: $newname\n"; + print "new: $newname\n"; } $img_root = substr($path_parts['basename'], 0, -11); @@ -283,23 +361,22 @@ function checkAvatar($user, $profile) $mediatype = getMediatype($ext); foreach (array('mini', 'normal', 'bigger') as $size) { - $url = $path_parts['dirname'] . '/' . + $url = $path_parts['dirname'] . '/' . $img_root . '_' . $size . ".$ext"; - $filename = 'Twitter_' . $user->id . '_' . + $filename = 'Twitter_' . $user->id . '_' . $img_root . "_$size.$ext"; if (fetchAvatar($url, $filename)) { - updateAvatar($profile->id, $size, $mediatype, $filename); + updateAvatar($profile->id, $size, $mediatype, $filename); } } } - } -function getMediatype($ext) +function getMediatype($ext) { $mediatype = null; - + switch (strtolower($ext)) { case 'jpg': $mediatype = 'image/jpg'; @@ -310,26 +387,22 @@ function getMediatype($ext) default: $mediatype = 'image/png'; } - + return $mediatype; } - -function saveAvatars($user, $id) +function saveAvatars($user, $id) { $path_parts = pathinfo($user->profile_image_url); - - // basename minus '_normal.ext' - $ext = $path_parts['extension']; $end = strlen('_normal' . $ext); $img_root = substr($path_parts['basename'], 0, -($end+1)); $mediatype = getMediatype($ext); - + foreach (array('mini', 'normal', 'bigger') as $size) { - $url = $path_parts['dirname'] . '/' . + $url = $path_parts['dirname'] . '/' . $img_root . '_' . $size . ".$ext"; - $filename = 'Twitter_' . $user->id . '_' . + $filename = 'Twitter_' . $user->id . '_' . $img_root . "_$size.$ext"; if (fetchAvatar($url, $filename)) { @@ -348,7 +421,7 @@ function updateAvatar($profile_id, $size, $mediatype, $filename) { common_debug("updating avatar: $size"); $profile = Profile::staticGet($profile_id); - + if (!$profile) { common_debug("Couldn't get profile: $profile_id!"); if (defined('SCRIPT_DEBUG')) { @@ -356,17 +429,17 @@ function updateAvatar($profile_id, $size, $mediatype, $filename) { } return; } - + $sizes = array('mini' => 24, 'normal' => 48, 'bigger' => 73); $avatar = $profile->getAvatar($sizes[$size]); - + if ($avatar) { common_debug("Deleting $size avatar for $profile->nickname."); @unlink(INSTALLDIR . '/avatar/' . $avatar->filename); $avatar->delete(); } - - newAvatar($profile->id, $size, $mediatype, $filename); + + newAvatar($profile->id, $size, $mediatype, $filename); } function newAvatar($profile_id, $size, $mediatype, $filename) @@ -376,19 +449,19 @@ function newAvatar($profile_id, $size, $mediatype, $filename) switch($size) { case 'mini': - $avatar->width = 24; + $avatar->width = 24; $avatar->height = 24; break; case 'normal': - $avatar->width = 48; + $avatar->width = 48; $avatar->height = 48; break; default: - - // Note: Twitter's big avatars are a different size than + + // Note: Twitter's big avatars are a different size than // Laconica's (Laconica's = 96) - - $avatar->width = 73; + + $avatar->width = 73; $avatar->height = 73; } @@ -396,33 +469,33 @@ function newAvatar($profile_id, $size, $mediatype, $filename) $avatar->mediatype = $mediatype; $avatar->filename = $filename; $avatar->url = Avatar::url($filename); - + common_debug("new filename: $avatar->url"); - + $avatar->created = common_sql_now(); $id = $avatar->insert(); - if (!$id) { + if (!$id) { common_log_db_error($avatar, 'INSERT', __FILE__); if (defined('SCRIPT_DEBUG')) { print "Could not insert avatar!\n"; } - + return null; } - + common_debug("Saved new $size avatar for $profile_id."); - + return $id; } -function fetchAvatar($url, $filename) +function fetchAvatar($url, $filename) { $avatar_dir = INSTALLDIR . '/avatar/'; - + $avatarfile = $avatar_dir . $filename; - + $out = fopen($avatarfile, 'wb'); if (!$out) { common_log(LOG_WARNING, "Couldn't open file $filename", __FILE__); @@ -431,12 +504,12 @@ function fetchAvatar($url, $filename) } return false; } - + common_debug("Fetching avatar: $url", __FILE__); if (defined('SCRIPT_DEBUG')) { print "Fetching avatar from Twitter: $url\n"; } - + $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_FILE, $out); @@ -447,7 +520,6 @@ function fetchAvatar($url, $filename) curl_close($ch); fclose($out); - + return $result; } - From 5e6eb27f843a22b80ac114f382682fba0c37589e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 25 Apr 2009 14:20:24 -0400 Subject: [PATCH 417/503] first pass at Comet plugin; doesn't yet update --- plugins/Comet/CometPlugin.php | 138 +++++++++++ plugins/Comet/bayeux.class.inc.php | 129 ++++++++++ plugins/Comet/bayeux.class.inc.phps | 123 ++++++++++ plugins/Comet/jquery.comet.js | 363 ++++++++++++++++++++++++++++ plugins/Comet/updatetimeline.js | 3 + 5 files changed, 756 insertions(+) create mode 100644 plugins/Comet/CometPlugin.php create mode 100644 plugins/Comet/bayeux.class.inc.php create mode 100644 plugins/Comet/bayeux.class.inc.phps create mode 100644 plugins/Comet/jquery.comet.js create mode 100644 plugins/Comet/updatetimeline.js diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php new file mode 100644 index 0000000000..10f8c198c3 --- /dev/null +++ b/plugins/Comet/CometPlugin.php @@ -0,0 +1,138 @@ +. + * + * @category Plugin + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Plugin to do realtime updates using Comet + * + * @category Plugin + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class CometPlugin extends Plugin +{ + var $server = null; + + function __construct($server=null) + { + $this->server = $server; + + parent::__construct(); + } + + function onEndShowScripts($action) + { + $timeline = null; + + switch ($action->trimmed('action')) { + case 'public': + $timeline = '/timelines/public'; + break; + default: + return true; + } + + $action->element('script', array('type' => 'text/javascript', + 'src' => common_path('plugins/Comet/jquery.comet.js')), + ' '); + $action->elementStart('script', array('type' => 'text/javascript')); + $action->raw("var _timelineServer = \"$this->server\"; ". + "var _timeline = \"$timeline\";"); + $action->elementEnd('script'); + $action->element('script', array('type' => 'text/javascript', + 'src' => common_path('plugins/Comet/updatetimeline.js')), + ' '); + return true; + } + + function onEndNoticeSave($notice) + { + $this->log(LOG_INFO, "Called for save notice."); + + $timelines = array(); + + // XXX: Add other timelines; this is just for the public one + + if ($notice->is_local || + ($notice->is_local == 0 && !common_config('public', 'localonly'))) { + $timelines[] = '/timelines/public'; + } + + if (count($timelines) > 0) { + // Require this, since we need it + require_once(INSTALLDIR.'/plugins/Comet/bayeux.class.inc.php'); + + $json = $this->noticeAsJson($notice); + + $this->log(LOG_DEBUG, "JSON = '$json'"); + + // Bayeux? Comet? Huh? These terms confuse me + $bay = new Bayeux($this->server); + + foreach ($timelines as $timeline) { + $this->log(LOG_INFO, "Posting notice $notice->id to '$timeline'."); + $bay->publish($timeline, $json); + $this->log(LOG_DEBUG, "Done posting notice $notice->id to '$timeline'."); + } + + $bay = NULL; + } + + $this->log(LOG_DEBUG, "All done."); + return true; + } + + function noticeAsJson($notice) + { + // FIXME: this code should be abstracted to a neutral third + // party, like Notice::asJson(). I'm not sure of the ethics + // of refactoring from within a plugin, so I'm just abusing + // the TwitterApiAction method. Don't do this unless you're me! + + require_once(INSTALLDIR.'/lib/twitterapi.php'); + + $act = new TwitterApiAction('/dev/null'); + + $arr = $act->twitter_status_array($notice, true); + return $arr; + } + + // Push this up to Plugin + + function log($level, $msg) + { + common_log($level, get_class($this) . ': '.$msg); + } +} diff --git a/plugins/Comet/bayeux.class.inc.php b/plugins/Comet/bayeux.class.inc.php new file mode 100644 index 0000000000..602a7b6446 --- /dev/null +++ b/plugins/Comet/bayeux.class.inc.php @@ -0,0 +1,129 @@ + http://morglog.alleycatracing.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +class Bayeux +{ + private $oCurl = ''; + private $nNextId = 0; + + public $sUrl = ''; + + function __construct($sUrl) + { + $this->sUrl = $sUrl; + + $this->oCurl = curl_init(); + + $aHeaders = array(); + $aHeaders[] = 'Connection: Keep-Alive'; + + curl_setopt($this->oCurl, CURLOPT_URL, $sUrl); + curl_setopt($this->oCurl, CURLOPT_HTTPHEADER, $aHeaders); + curl_setopt($this->oCurl, CURLOPT_HEADER, 0); + curl_setopt($this->oCurl, CURLOPT_POST, 1); + curl_setopt($this->oCurl, CURLOPT_RETURNTRANSFER,1); + + $this->handShake(); + } + + function __destruct() + { + $this->disconnect(); + } + + function handShake() + { + $msgHandshake = array(); + $msgHandshake['channel'] = '/meta/handshake'; + $msgHandshake['version'] = "1.0"; + $msgHandshake['minimumVersion'] = "0.9"; + $msgHandshake['supportedConnectionTypes'] = array('long-polling'); + $msgHandshake['id'] = $this->nNextId++; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake))))); + + $data = curl_exec($this->oCurl); + + if(curl_errno($this->oCurl)) + die("Error: " . curl_error($this->oCurl)); + + $oReturn = json_decode($data); + + common_debug(print_r($oReturn, true)); + + if (is_array($oReturn)) { + $oReturn = $oReturn[0]; + } + + $bSuccessful = ($oReturn->successful) ? true : false; + + if($bSuccessful) + { + $this->clientId = $oReturn->clientId; + + $this->connect(); + } + } + + public function connect() + { + $aMsg['channel'] = '/meta/connect'; + $aMsg['id'] = $this->nNextId++; + $aMsg['clientId'] = $this->clientId; + $aMsg['connectionType'] = 'long-polling'; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg))))); + + $data = curl_exec($this->oCurl); + } + + function disconnect() + { + $msgHandshake = array(); + $msgHandshake['channel'] = '/meta/disconnect'; + $msgHandshake['id'] = $this->nNextId++; + $msgHandshake['clientId'] = $this->clientId; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake))))); + + curl_exec($this->oCurl); + } + + public function publish($sChannel, $oData) + { + if(!$sChannel || !$oData) + return; + + $aMsg = array(); + + $aMsg['channel'] = $sChannel; + $aMsg['id'] = $this->nNextId++; + $aMsg['data'] = $oData; + $aMsg['clientId'] = $this->clientId; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg))))); + + $data = curl_exec($this->oCurl); +// var_dump($data); + } +} diff --git a/plugins/Comet/bayeux.class.inc.phps b/plugins/Comet/bayeux.class.inc.phps new file mode 100644 index 0000000000..ea004a4532 --- /dev/null +++ b/plugins/Comet/bayeux.class.inc.phps @@ -0,0 +1,123 @@ + http://morglog.alleycatracing.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +class Bayeux + { + private $oCurl = ''; + private $nNextId = 0; + + public $sUrl = ''; + + function __construct($sUrl) + { + $this->sUrl = $sUrl; + + $this->oCurl = curl_init(); + + $aHeaders = array(); + $aHeaders[] = 'Connection: Keep-Alive'; + + curl_setopt($this->oCurl, CURLOPT_URL, $sUrl); + curl_setopt($this->oCurl, CURLOPT_HTTPHEADER, $aHeaders); + curl_setopt($this->oCurl, CURLOPT_HEADER, 0); + curl_setopt($this->oCurl, CURLOPT_POST, 1); + curl_setopt($this->oCurl, CURLOPT_RETURNTRANSFER,1); + + $this->handShake(); + } + + function __destruct() + { + $this->disconnect(); + } + + function handShake() + { + $msgHandshake = array(); + $msgHandshake['channel'] = '/meta/handshake'; + $msgHandshake['version'] = "1.0"; + $msgHandshake['minimumVersion'] = "0.9"; + $msgHandshake['id'] = $this->nNextId++; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake))))); + + $data = curl_exec($this->oCurl); + + if(curl_errno($this->oCurl)) + die("Error: " . curl_error($this->oCurl)); + + $oReturn = json_decode($data); + $oReturn = $oReturn[0]; + + $bSuccessful = ($oReturn->successful) ? true : false; + + if($bSuccessful) + { + $this->clientId = $oReturn->clientId; + + $this->connect(); + } + } + + public function connect() + { + $aMsg['channel'] = '/meta/connect'; + $aMsg['id'] = $this->nNextId++; + $aMsg['clientId'] = $this->clientId; + $aMsg['connectionType'] = 'long-polling'; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg))))); + + $data = curl_exec($this->oCurl); + } + + function disconnect() + { + $msgHandshake = array(); + $msgHandshake['channel'] = '/meta/disconnect'; + $msgHandshake['id'] = $this->nNextId++; + $msgHandshake['clientId'] = $this->clientId; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake))))); + + curl_exec($this->oCurl); + } + + public function publish($sChannel, $oData) + { + if(!$sChannel || !$oData) + return; + + $aMsg = array(); + + $aMsg['channel'] = $sChannel; + $aMsg['id'] = $this->nNextId++; + $aMsg['data'] = $oData; + $aMsg['clientId'] = $this->clientId; + + curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg))))); + + $data = curl_exec($this->oCurl); +// var_dump($data); + } + } diff --git a/plugins/Comet/jquery.comet.js b/plugins/Comet/jquery.comet.js new file mode 100644 index 0000000000..2124e882cb --- /dev/null +++ b/plugins/Comet/jquery.comet.js @@ -0,0 +1,363 @@ +(function($) +{ + var msgHandshake = + { + version: '1.0', + minimumVersion: '0.9', + channel: '/meta/handshake' + }; + + var oTransport = function() + { + this._bXD = + (($.comet._sUrl.substring(0,4) == 'http') && ($.comet._sUrl.substr(7,location.href.length).replace(/\/.*/, '') != location.host)) + ? + true + :false; + + this.connectionType = (this._bXD) ? 'callback-polling' : 'long-polling'; + + this.startup = function(oReturn) + { + if(this._comet._bConnected) return; + this.tunnelInit(); + }; + + this.tunnelInit = function() + { + var msgConnect = + { + channel: '/meta/connect', + clientId: $.comet.clientId, + id: String($.comet._nNextId++), + connectionType: $.comet._oTransport.connectionType + }; + + this.openTunnel(msgConnect); + }; + + this.openTunnel = function(oMsg) + { + $.comet._bPolling = true; + + this._send($.comet._sUrl, oMsg, function(sReturn) + { + var oReturn = (typeof sReturn != "object") ? (eval('(' + sReturn + ')')) : sReturn; + $.comet._bPolling = false; + $.comet.deliver(oReturn); + $.comet._oTransport.closeTunnel(); + }); + }; + + this.closeTunnel = function() + { + if(!$.comet._bInitialized) return; + + if($.comet._advice) + { + if($.comet._advice.reconnect == 'none') return; + + if($.comet._advice.interval > 0) + { + setTimeout($.comet._oTransport._connect, $.comet._advice.interval); + } + else + { + $.comet._oTransport._connect(); + } + } + else + { + $.comet._oTransport._connect(); + } + }; + + this._connect = function() + { + if(!$.comet._bInitialized) return; + + if($.comet._bPolling) return; + + if($.comet._advice && $.comet._advice.reconnect == 'handshake') + { + $.comet._bConnected = false; + $.comet.init($.comet._sUrl); + } + else if($.comet._bConnected) + { + var msgConnect = + { + //jsonp: 'test', + clientId: $.comet.clientId, + id: String($.comet._nNextId++), + channel: '/meta/connect', + connectionType: $.comet._oTransport.connectionType + }; + $.comet._oTransport.openTunnel(msgConnect); + } + }; + + this._send = function(sUrl, oMsg, fCallback) { + //default callback will check advice, deliver messages, and reconnect + var fCallback = (fCallback) ? fCallback : function(sReturn) + { + var oReturn = (typeof sReturn != "object") ? (eval('(' + sReturn + ')')) : sReturn; + + $.comet.deliver(oReturn); + + if($.comet._advice) + { + if($.comet._advice.reconnect == 'none') + return; + + if($.comet._advice.interval > 0) + { + setTimeout($.comet._oTransport._connect, $.comet._advice.interval); + } + else + { + $.comet._oTransport._connect(); + } + } + else + { + $.comet._oTransport._connect(); + } + }; + + //regular AJAX for same domain calls + if((!this._bXD) && (this.connectionType == 'long-polling')) + { + this._pollRequest = $.ajax({ + url: sUrl, + type: 'post', + beforeSend: function(oXhr) { oXhr.setRequestHeader('Connection', 'Keep-Alive'); }, + data: { message: JSON.stringify(oMsg) }, + success: fCallback + }); + } + else // JSONP callback for cross domain + { + this._pollRequest = $.ajax({ + url: sUrl, + dataType: 'jsonp', + jsonp: 'jsonp', + beforeSend: function(oXhr) { oXhr.setRequestHeader('Connection', 'Keep-Alive'); }, + data: + { + message: JSON.stringify($.extend(oMsg,{connectionType: 'callback-polling' })) + }, + success: fCallback + }); + } + } + }; + + $.comet = new function() + { + this.CONNECTED = 'CONNECTED'; + this.CONNECTING = 'CONNECTING'; + this.DISCONNECTED = 'DISCONNECTED'; + this.DISCONNECTING = 'DISCONNECTING'; + + this._aMessageQueue = []; + this._aSubscriptions = []; + this._aSubscriptionCallbacks = []; + this._bInitialized = false; + this._bConnected = false; + this._nBatch = 0; + this._nNextId = 0; + // just define the transport, do not assign it yet. + this._oTransport = ''; //oTransport; + this._sUrl = ''; + + this.supportedConectionTypes = [ 'long-polling', 'callback-polling' ]; + + this.clientId = ''; + + this._bTrigger = true; // this sends $.event.trigger(channel, data) + + this.init = function(sUrl) + { + this._sUrl = (sUrl) ? sUrl : '/cometd'; + + this._oTransport = new oTransport(); + + this._aMessageQueue = []; + this._aSubscriptions = []; + this._bInitialized = true; + this.startBatch(); + + var oMsg = $.extend(msgHandshake, {id: String(this._nNextId++)}); + + this._oTransport._send(this._sUrl, oMsg, $.comet._finishInit); + }; + + this._finishInit = function(sReturn) + { + var oReturn = (typeof sReturn != "object") ? (eval('(' + sReturn + ')')[0]) : sReturn[0]; + + if(oReturn.advice) + $.comet._advice = oReturn.advice; + + var bSuccess = (oReturn.successful) ? oReturn.successful : false; + // do version check + + if(bSuccess) + { + // pick transport ? + // ...... + + $.comet._oTransport._comet = $.comet; + $.comet._oTransport.version = $.comet.version; + + $.comet.clientId = oReturn.clientId; + $.comet._oTransport.startup(oReturn); + $.comet.endBatch(); + } + }; + + this._sendMessage = function(oMsg) + { + if($.comet._nBatch <= 0) + { + if(oMsg.length > 0) + for(var i in oMsg) + { + oMsg[i].clientId = String($.comet.clientId); + oMsg[i].id = String($.comet._nNextId++); + } + else + { + oMsg.clientId = String($.comet.clientId); + oMsg.id = String($.comet._nNextId++); + } + + $.comet._oTransport._send($.comet._sUrl, oMsg); + } + else + { + $.comet._aMessageQueue.push(oMsg); + } + }; + + + this.startBatch = function() { this._nBatch++ }; + this.endBatch = function() { + if(--this._nBatch <= 0) + { + this._nBatch = 0; + if(this._aMessageQueue.length > 0) + { + this._sendMessage(this._aMessageQueue); + this._aMessageQueue = []; + } + } + }; + + this.subscribe = function(sSubscription, fCallback) + { + // if this topic has not been subscribed to yet, send the message now + if(!this._aSubscriptions[sSubscription]) + { + this._aSubscriptions.push(sSubscription) + + if (fCallback) { + this._aSubscriptionCallbacks[sSubscription] = fCallback; + } + + this._sendMessage({ channel: '/meta/subscribe', subscription: sSubscription }); + } + + //$.event.add(window, sSubscription, fCallback); + }; + + this.unsubscribe = function(sSubscription) { + $.comet._sendMessage({ channel: '/meta/unsubscribe', subscription: sSubscription }); + }; + + this.publish = function(sChannel, oData) + { + $.comet._sendMessage({channel: sChannel, data: oData}); + }; + + this.deliver = function(sReturn) + { + var oReturn = sReturn;//eval(sReturn); + + $(oReturn).each(function() + { + $.comet._deliver(this); + }); + }; + + this.disconnect = function() + { + $($.comet._aSubscriptions).each(function(i) + { + $.comet.unsubscribe($.comet._aSubscriptions[i]); + }); + + $.comet._sendMessage({channel:'/meta/disconnect'}); + + $.comet._bInitialized = false; + } + + this._deliver = function(oMsg,oData) + { + if(oMsg.advice) + { + $.comet._advice = oMsg.advice; + } + + switch(oMsg.channel) + { + case '/meta/connect': + if(oMsg.successful && !$.comet._bConnected) + { + $.comet._bConnected = $.comet._bInitialized; + $.comet.endBatch(); + /* + $.comet._sendMessage(msgConnect); + */ + } + else + {} + //$.comet._bConnected = false; + break; + + // add in subscription handling stuff + case '/meta/subscribe': + if(!oMsg.successful) + { + $.comet._oTransport._cancelConnect(); + return; + } + break; + + case '/meta/unsubscribe': + if(!oMsg.successful) + { + $.comet._oTransport._cancelConnect(); + return; + } + break; + + } + + if(oMsg.data) + { + if($.comet._bTrigger) + { + $.event.trigger(oMsg.channel, [oMsg]); + } + + var cb = $.comet._aSubscriptionCallbacks[oMsg.channel]; + if (cb) { + cb(oMsg); + } + } + }; +}; + +})(jQuery); diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js new file mode 100644 index 0000000000..f4da1f47cd --- /dev/null +++ b/plugins/Comet/updatetimeline.js @@ -0,0 +1,3 @@ +// update the local timeline from a Comet server +// + From 056d0a2555bb6783a2bb4632d2c6ad9f52dde5ec Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 25 Apr 2009 14:20:57 -0400 Subject: [PATCH 418/503] remove unused duplicate file --- plugins/Comet/bayeux.class.inc.phps | 123 ---------------------------- 1 file changed, 123 deletions(-) delete mode 100644 plugins/Comet/bayeux.class.inc.phps diff --git a/plugins/Comet/bayeux.class.inc.phps b/plugins/Comet/bayeux.class.inc.phps deleted file mode 100644 index ea004a4532..0000000000 --- a/plugins/Comet/bayeux.class.inc.phps +++ /dev/null @@ -1,123 +0,0 @@ - http://morglog.alleycatracing.com - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -class Bayeux - { - private $oCurl = ''; - private $nNextId = 0; - - public $sUrl = ''; - - function __construct($sUrl) - { - $this->sUrl = $sUrl; - - $this->oCurl = curl_init(); - - $aHeaders = array(); - $aHeaders[] = 'Connection: Keep-Alive'; - - curl_setopt($this->oCurl, CURLOPT_URL, $sUrl); - curl_setopt($this->oCurl, CURLOPT_HTTPHEADER, $aHeaders); - curl_setopt($this->oCurl, CURLOPT_HEADER, 0); - curl_setopt($this->oCurl, CURLOPT_POST, 1); - curl_setopt($this->oCurl, CURLOPT_RETURNTRANSFER,1); - - $this->handShake(); - } - - function __destruct() - { - $this->disconnect(); - } - - function handShake() - { - $msgHandshake = array(); - $msgHandshake['channel'] = '/meta/handshake'; - $msgHandshake['version'] = "1.0"; - $msgHandshake['minimumVersion'] = "0.9"; - $msgHandshake['id'] = $this->nNextId++; - - curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake))))); - - $data = curl_exec($this->oCurl); - - if(curl_errno($this->oCurl)) - die("Error: " . curl_error($this->oCurl)); - - $oReturn = json_decode($data); - $oReturn = $oReturn[0]; - - $bSuccessful = ($oReturn->successful) ? true : false; - - if($bSuccessful) - { - $this->clientId = $oReturn->clientId; - - $this->connect(); - } - } - - public function connect() - { - $aMsg['channel'] = '/meta/connect'; - $aMsg['id'] = $this->nNextId++; - $aMsg['clientId'] = $this->clientId; - $aMsg['connectionType'] = 'long-polling'; - - curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg))))); - - $data = curl_exec($this->oCurl); - } - - function disconnect() - { - $msgHandshake = array(); - $msgHandshake['channel'] = '/meta/disconnect'; - $msgHandshake['id'] = $this->nNextId++; - $msgHandshake['clientId'] = $this->clientId; - - curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake))))); - - curl_exec($this->oCurl); - } - - public function publish($sChannel, $oData) - { - if(!$sChannel || !$oData) - return; - - $aMsg = array(); - - $aMsg['channel'] = $sChannel; - $aMsg['id'] = $this->nNextId++; - $aMsg['data'] = $oData; - $aMsg['clientId'] = $this->clientId; - - curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg))))); - - $data = curl_exec($this->oCurl); -// var_dump($data); - } - } From 262dbeac787ad3aecb28c470484eb3fc8d036d93 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 12:06:50 -0400 Subject: [PATCH 419/503] Some updates for testing Comet --- plugins/Comet/bayeux.class.inc.php | 2 - plugins/Comet/jquery.comet.js | 1814 ++++++++++++++++++++++------ plugins/Comet/updatetimeline.js | 27 + 3 files changed, 1478 insertions(+), 365 deletions(-) diff --git a/plugins/Comet/bayeux.class.inc.php b/plugins/Comet/bayeux.class.inc.php index 602a7b6446..785d3e3935 100644 --- a/plugins/Comet/bayeux.class.inc.php +++ b/plugins/Comet/bayeux.class.inc.php @@ -69,8 +69,6 @@ class Bayeux $oReturn = json_decode($data); - common_debug(print_r($oReturn, true)); - if (is_array($oReturn)) { $oReturn = $oReturn[0]; } diff --git a/plugins/Comet/jquery.comet.js b/plugins/Comet/jquery.comet.js index 2124e882cb..6de437fa8e 100644 --- a/plugins/Comet/jquery.comet.js +++ b/plugins/Comet/jquery.comet.js @@ -1,363 +1,1451 @@ -(function($) -{ - var msgHandshake = - { - version: '1.0', - minimumVersion: '0.9', - channel: '/meta/handshake' - }; - - var oTransport = function() - { - this._bXD = - (($.comet._sUrl.substring(0,4) == 'http') && ($.comet._sUrl.substr(7,location.href.length).replace(/\/.*/, '') != location.host)) - ? - true - :false; - - this.connectionType = (this._bXD) ? 'callback-polling' : 'long-polling'; - - this.startup = function(oReturn) - { - if(this._comet._bConnected) return; - this.tunnelInit(); - }; - - this.tunnelInit = function() - { - var msgConnect = - { - channel: '/meta/connect', - clientId: $.comet.clientId, - id: String($.comet._nNextId++), - connectionType: $.comet._oTransport.connectionType - }; - - this.openTunnel(msgConnect); - }; - - this.openTunnel = function(oMsg) - { - $.comet._bPolling = true; - - this._send($.comet._sUrl, oMsg, function(sReturn) - { - var oReturn = (typeof sReturn != "object") ? (eval('(' + sReturn + ')')) : sReturn; - $.comet._bPolling = false; - $.comet.deliver(oReturn); - $.comet._oTransport.closeTunnel(); - }); - }; - - this.closeTunnel = function() - { - if(!$.comet._bInitialized) return; - - if($.comet._advice) - { - if($.comet._advice.reconnect == 'none') return; - - if($.comet._advice.interval > 0) - { - setTimeout($.comet._oTransport._connect, $.comet._advice.interval); - } - else - { - $.comet._oTransport._connect(); - } - } - else - { - $.comet._oTransport._connect(); - } - }; - - this._connect = function() - { - if(!$.comet._bInitialized) return; - - if($.comet._bPolling) return; - - if($.comet._advice && $.comet._advice.reconnect == 'handshake') - { - $.comet._bConnected = false; - $.comet.init($.comet._sUrl); - } - else if($.comet._bConnected) - { - var msgConnect = - { - //jsonp: 'test', - clientId: $.comet.clientId, - id: String($.comet._nNextId++), - channel: '/meta/connect', - connectionType: $.comet._oTransport.connectionType - }; - $.comet._oTransport.openTunnel(msgConnect); - } - }; - - this._send = function(sUrl, oMsg, fCallback) { - //default callback will check advice, deliver messages, and reconnect - var fCallback = (fCallback) ? fCallback : function(sReturn) - { - var oReturn = (typeof sReturn != "object") ? (eval('(' + sReturn + ')')) : sReturn; - - $.comet.deliver(oReturn); - - if($.comet._advice) - { - if($.comet._advice.reconnect == 'none') - return; - - if($.comet._advice.interval > 0) - { - setTimeout($.comet._oTransport._connect, $.comet._advice.interval); - } - else - { - $.comet._oTransport._connect(); - } - } - else - { - $.comet._oTransport._connect(); - } - }; - - //regular AJAX for same domain calls - if((!this._bXD) && (this.connectionType == 'long-polling')) - { - this._pollRequest = $.ajax({ - url: sUrl, - type: 'post', - beforeSend: function(oXhr) { oXhr.setRequestHeader('Connection', 'Keep-Alive'); }, - data: { message: JSON.stringify(oMsg) }, - success: fCallback - }); - } - else // JSONP callback for cross domain - { - this._pollRequest = $.ajax({ - url: sUrl, - dataType: 'jsonp', - jsonp: 'jsonp', - beforeSend: function(oXhr) { oXhr.setRequestHeader('Connection', 'Keep-Alive'); }, - data: - { - message: JSON.stringify($.extend(oMsg,{connectionType: 'callback-polling' })) - }, - success: fCallback - }); - } - } - }; - - $.comet = new function() - { - this.CONNECTED = 'CONNECTED'; - this.CONNECTING = 'CONNECTING'; - this.DISCONNECTED = 'DISCONNECTED'; - this.DISCONNECTING = 'DISCONNECTING'; - - this._aMessageQueue = []; - this._aSubscriptions = []; - this._aSubscriptionCallbacks = []; - this._bInitialized = false; - this._bConnected = false; - this._nBatch = 0; - this._nNextId = 0; - // just define the transport, do not assign it yet. - this._oTransport = ''; //oTransport; - this._sUrl = ''; - - this.supportedConectionTypes = [ 'long-polling', 'callback-polling' ]; - - this.clientId = ''; - - this._bTrigger = true; // this sends $.event.trigger(channel, data) - - this.init = function(sUrl) - { - this._sUrl = (sUrl) ? sUrl : '/cometd'; - - this._oTransport = new oTransport(); - - this._aMessageQueue = []; - this._aSubscriptions = []; - this._bInitialized = true; - this.startBatch(); - - var oMsg = $.extend(msgHandshake, {id: String(this._nNextId++)}); - - this._oTransport._send(this._sUrl, oMsg, $.comet._finishInit); - }; - - this._finishInit = function(sReturn) - { - var oReturn = (typeof sReturn != "object") ? (eval('(' + sReturn + ')')[0]) : sReturn[0]; - - if(oReturn.advice) - $.comet._advice = oReturn.advice; - - var bSuccess = (oReturn.successful) ? oReturn.successful : false; - // do version check - - if(bSuccess) - { - // pick transport ? - // ...... - - $.comet._oTransport._comet = $.comet; - $.comet._oTransport.version = $.comet.version; - - $.comet.clientId = oReturn.clientId; - $.comet._oTransport.startup(oReturn); - $.comet.endBatch(); - } - }; - - this._sendMessage = function(oMsg) - { - if($.comet._nBatch <= 0) - { - if(oMsg.length > 0) - for(var i in oMsg) - { - oMsg[i].clientId = String($.comet.clientId); - oMsg[i].id = String($.comet._nNextId++); - } - else - { - oMsg.clientId = String($.comet.clientId); - oMsg.id = String($.comet._nNextId++); - } - - $.comet._oTransport._send($.comet._sUrl, oMsg); - } - else - { - $.comet._aMessageQueue.push(oMsg); - } - }; - - - this.startBatch = function() { this._nBatch++ }; - this.endBatch = function() { - if(--this._nBatch <= 0) - { - this._nBatch = 0; - if(this._aMessageQueue.length > 0) - { - this._sendMessage(this._aMessageQueue); - this._aMessageQueue = []; - } - } - }; - - this.subscribe = function(sSubscription, fCallback) - { - // if this topic has not been subscribed to yet, send the message now - if(!this._aSubscriptions[sSubscription]) - { - this._aSubscriptions.push(sSubscription) - - if (fCallback) { - this._aSubscriptionCallbacks[sSubscription] = fCallback; - } - - this._sendMessage({ channel: '/meta/subscribe', subscription: sSubscription }); - } - - //$.event.add(window, sSubscription, fCallback); - }; - - this.unsubscribe = function(sSubscription) { - $.comet._sendMessage({ channel: '/meta/unsubscribe', subscription: sSubscription }); - }; - - this.publish = function(sChannel, oData) - { - $.comet._sendMessage({channel: sChannel, data: oData}); - }; - - this.deliver = function(sReturn) - { - var oReturn = sReturn;//eval(sReturn); - - $(oReturn).each(function() - { - $.comet._deliver(this); - }); - }; - - this.disconnect = function() - { - $($.comet._aSubscriptions).each(function(i) - { - $.comet.unsubscribe($.comet._aSubscriptions[i]); - }); - - $.comet._sendMessage({channel:'/meta/disconnect'}); - - $.comet._bInitialized = false; - } - - this._deliver = function(oMsg,oData) - { - if(oMsg.advice) - { - $.comet._advice = oMsg.advice; - } - - switch(oMsg.channel) - { - case '/meta/connect': - if(oMsg.successful && !$.comet._bConnected) - { - $.comet._bConnected = $.comet._bInitialized; - $.comet.endBatch(); - /* - $.comet._sendMessage(msgConnect); - */ - } - else - {} - //$.comet._bConnected = false; - break; - - // add in subscription handling stuff - case '/meta/subscribe': - if(!oMsg.successful) - { - $.comet._oTransport._cancelConnect(); - return; - } - break; - - case '/meta/unsubscribe': - if(!oMsg.successful) - { - $.comet._oTransport._cancelConnect(); - return; - } - break; - - } - - if(oMsg.data) - { - if($.comet._bTrigger) - { - $.event.trigger(oMsg.channel, [oMsg]); - } - - var cb = $.comet._aSubscriptionCallbacks[oMsg.channel]; - if (cb) { - cb(oMsg); - } - } - }; -}; - -})(jQuery); +/** + * Copyright 2008 Mort Bay Consulting Pty. Ltd. + * Dual licensed under the Apache License 2.0 and the MIT license. + * ---------------------------------------------------------------------------- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http: *www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + * Licensed under the MIT license; + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ---------------------------------------------------------------------------- + * $Revision$ $Date$ + */ +(function($) +{ + /** + * The constructor for a Comet object. + * There is a default Comet instance already created at the variable $.cometd, + * and hence that can be used to start a comet conversation with a server. + * In the rare case a page needs more than one comet conversation, a new instance can be + * created via: + *

+     * var url2 = ...;
+     * var cometd2 = new $.Cometd();
+     * cometd2.init(url2);
+     * 
+ */ + $.Cometd = function(name) + { + var _name = name || 'default'; + var _logPriorities = { debug: 1, info: 2, warn: 3, error: 4 }; + var _logLevel = 'info'; + var _url; + var _xd = false; + var _transport; + var _status = 'disconnected'; + var _messageId = 0; + var _clientId = null; + var _batch = 0; + var _messageQueue = []; + var _listeners = {}; + var _backoff = 0; + var _backoffIncrement = 1000; + var _maxBackoff = 60000; + var _scheduledSend = null; + var _extensions = []; + var _advice = {}; + var _handshakeProps; + + /** + * Returns the name assigned to this Comet object, or the string 'default' + * if no name has been explicitely passed as parameter to the constructor. + */ + this.getName = function() + { + return _name; + }; + + /** + * Configures the initial comet communication with the comet server. + * @param cometURL the URL of the comet server + */ + this.configure = function(cometURL) + { + _configure(cometURL); + }; + + function _configure(cometURL) + { + _url = cometURL; + _debug('Initializing comet with url: {}', _url); + + // Check immediately if we're cross domain + // If cross domain, the handshake must not send the long polling transport type + var urlParts = /(^https?:)?(\/\/(([^:\/\?#]+)(:(\d+))?))?([^\?#]*)/.exec(cometURL); + if (urlParts[3]) _xd = urlParts[3] != location.host; + + // Temporary setup a transport to send the initial handshake + // The transport may be changed as a result of handshake + if (_xd) + _transport = newCallbackPollingTransport(); + else + _transport = newLongPollingTransport(); + _debug('Initial transport is {}', _transport.getType()); + }; + + /** + * Configures and establishes the comet communication with the comet server + * via a handshake and a subsequent connect. + * @param cometURL the URL of the comet server + * @param handshakeProps an object to be merged with the handshake message + * @see #configure(cometURL) + * @see #handshake(handshakeProps) + */ + this.init = function(cometURL, handshakeProps) + { + _configure(cometURL); + _handshake(handshakeProps); + }; + + /** + * Establishes the comet communication with the comet server + * via a handshake and a subsequent connect. + * @param handshakeProps an object to be merged with the handshake message + */ + this.handshake = function(handshakeProps) + { + _handshake(handshakeProps); + }; + + /** + * Disconnects from the comet server. + * @param disconnectProps an object to be merged with the disconnect message + */ + this.disconnect = function(disconnectProps) + { + var bayeuxMessage = { + channel: '/meta/disconnect' + }; + var message = $.extend({}, disconnectProps, bayeuxMessage); + // Deliver immediately + // The handshake and connect mechanism make use of startBatch(), and in case + // of a failed handshake the disconnect would not be delivered if using _send(). + _setStatus('disconnecting'); + _deliver([message], false); + }; + + /** + * Marks the start of a batch of application messages to be sent to the server + * in a single request, obtaining a single response containing (possibly) many + * application reply messages. + * Messages are held in a queue and not sent until {@link #endBatch()} is called. + * If startBatch() is called multiple times, then an equal number of endBatch() + * calls must be made to close and send the batch of messages. + * @see #endBatch() + */ + this.startBatch = function() + { + _startBatch(); + }; + + /** + * Marks the end of a batch of application messages to be sent to the server + * in a single request. + * @see #startBatch() + */ + this.endBatch = function() + { + _endBatch(true); + }; + + /** + * Subscribes to the given channel, performing the given callback in the given scope + * when a message for the channel arrives. + * @param channel the channel to subscribe to + * @param scope the scope of the callback + * @param callback the callback to call when a message is delivered to the channel + * @param subscribeProps an object to be merged with the subscribe message + * @return the subscription handle to be passed to {@link #unsubscribe(object)} + */ + this.subscribe = function(channel, scope, callback, subscribeProps) + { + var subscription = this.addListener(channel, scope, callback); + + // Send the subscription message after the subscription registration to avoid + // races where the server would deliver a message to the subscribers, but here + // on the client the subscription has not been added yet to the data structures + var bayeuxMessage = { + channel: '/meta/subscribe', + subscription: channel + }; + var message = $.extend({}, subscribeProps, bayeuxMessage); + _send(message); + + return subscription; + }; + + /** + * Unsubscribes the subscription obtained with a call to {@link #subscribe(string, object, function)}. + * @param subscription the subscription to unsubscribe. + */ + this.unsubscribe = function(subscription, unsubscribeProps) + { + // Remove the local listener before sending the message + // This ensures that if the server fails, this client does not get notifications + this.removeListener(subscription); + var bayeuxMessage = { + channel: '/meta/unsubscribe', + subscription: subscription[0] + }; + var message = $.extend({}, unsubscribeProps, bayeuxMessage); + _send(message); + }; + + /** + * Publishes a message on the given channel, containing the given content. + * @param channel the channel to publish the message to + * @param content the content of the message + * @param publishProps an object to be merged with the publish message + */ + this.publish = function(channel, content, publishProps) + { + var bayeuxMessage = { + channel: channel, + data: content + }; + var message = $.extend({}, publishProps, bayeuxMessage); + _send(message); + }; + + /** + * Adds a listener for bayeux messages, performing the given callback in the given scope + * when a message for the given channel arrives. + * @param channel the channel the listener is interested to + * @param scope the scope of the callback + * @param callback the callback to call when a message is delivered to the channel + * @returns the subscription handle to be passed to {@link #removeListener(object)} + * @see #removeListener(object) + */ + this.addListener = function(channel, scope, callback) + { + // The data structure is a map, where each subscription + // holds the callback to be called and its scope. + + // Normalize arguments + if (!callback) + { + callback = scope; + scope = undefined; + } + + var subscription = { + scope: scope, + callback: callback + }; + + var subscriptions = _listeners[channel]; + if (!subscriptions) + { + subscriptions = []; + _listeners[channel] = subscriptions; + } + // Pushing onto an array appends at the end and returns the id associated with the element increased by 1. + // Note that if: + // a.push('a'); var hb=a.push('b'); delete a[hb-1]; var hc=a.push('c'); + // then: + // hc==3, a.join()=='a',,'c', a.length==3 + var subscriptionIndex = subscriptions.push(subscription) - 1; + _debug('Added listener: channel \'{}\', callback \'{}\', index {}', channel, callback.name, subscriptionIndex); + + // The subscription to allow removal of the listener is made of the channel and the index + return [channel, subscriptionIndex]; + }; + + /** + * Removes the subscription obtained with a call to {@link #addListener(string, object, function)}. + * @param subscription the subscription to unsubscribe. + */ + this.removeListener = function(subscription) + { + var subscriptions = _listeners[subscription[0]]; + if (subscriptions) + { + delete subscriptions[subscription[1]]; + _debug('Removed listener: channel \'{}\', index {}', subscription[0], subscription[1]); + } + }; + + /** + * Removes all listeners registered with {@link #addListener(channel, scope, callback)} or + * {@link #subscribe(channel, scope, callback)}. + */ + this.clearListeners = function() + { + _listeners = {}; + }; + + /** + * Returns a string representing the status of the bayeux communication with the comet server. + */ + this.getStatus = function() + { + return _status; + }; + + /** + * Sets the backoff period used to increase the backoff time when retrying an unsuccessful or failed message. + * Default value is 1 second, which means if there is a persistent failure the retries will happen + * after 1 second, then after 2 seconds, then after 3 seconds, etc. So for example with 15 seconds of + * elapsed time, there will be 5 retries (at 1, 3, 6, 10 and 15 seconds elapsed). + * @param period the backoff period to set + * @see #getBackoffIncrement() + */ + this.setBackoffIncrement = function(period) + { + _backoffIncrement = period; + }; + + /** + * Returns the backoff period used to increase the backoff time when retrying an unsuccessful or failed message. + * @see #setBackoffIncrement(period) + */ + this.getBackoffIncrement = function() + { + return _backoffIncrement; + }; + + /** + * Returns the backoff period to wait before retrying an unsuccessful or failed message. + */ + this.getBackoffPeriod = function() + { + return _backoff; + }; + + /** + * Sets the log level for console logging. + * Valid values are the strings 'error', 'warn', 'info' and 'debug', from + * less verbose to more verbose. + * @param level the log level string + */ + this.setLogLevel = function(level) + { + _logLevel = level; + }; + + /** + * Registers an extension whose callbacks are called for every incoming message + * (that comes from the server to this client implementation) and for every + * outgoing message (that originates from this client implementation for the + * server). + * The format of the extension object is the following: + *
+         * {
+         *     incoming: function(message) { ... },
+         *     outgoing: function(message) { ... }
+         * }
+         * Both properties are optional, but if they are present they will be called
+         * respectively for each incoming message and for each outgoing message.
+         * 
+ * @param name the name of the extension + * @param extension the extension to register + * @return true if the extension was registered, false otherwise + * @see #unregisterExtension(name) + */ + this.registerExtension = function(name, extension) + { + var existing = false; + for (var i = 0; i < _extensions.length; ++i) + { + var existingExtension = _extensions[i]; + if (existingExtension.name == name) + { + existing = true; + return false; + } + } + if (!existing) + { + _extensions.push({ + name: name, + extension: extension + }); + _debug('Registered extension \'{}\'', name); + return true; + } + else + { + _info('Could not register extension with name \'{}\': another extension with the same name already exists'); + return false; + } + }; + + /** + * Unregister an extension previously registered with + * {@link #registerExtension(name, extension)}. + * @param name the name of the extension to unregister. + * @return true if the extension was unregistered, false otherwise + */ + this.unregisterExtension = function(name) + { + var unregistered = false; + $.each(_extensions, function(index, extension) + { + if (extension.name == name) + { + _extensions.splice(index, 1); + unregistered = true; + _debug('Unregistered extension \'{}\'', name); + return false; + } + }); + return unregistered; + }; + + /** + * Starts a the batch of messages to be sent in a single request. + * @see _endBatch(deliverMessages) + */ + function _startBatch() + { + ++_batch; + }; + + /** + * Ends the batch of messages to be sent in a single request, + * optionally delivering messages present in the message queue depending + * on the given argument. + * @param deliverMessages whether to deliver the messages in the queue or not + * @see _startBatch() + */ + function _endBatch(deliverMessages) + { + --_batch; + if (_batch < 0) _batch = 0; + if (deliverMessages && _batch == 0 && !_isDisconnected()) + { + var messages = _messageQueue; + _messageQueue = []; + if (messages.length > 0) _deliver(messages, false); + } + }; + + function _nextMessageId() + { + return ++_messageId; + }; + + /** + * Converts the given response into an array of bayeux messages + * @param response the response to convert + * @return an array of bayeux messages obtained by converting the response + */ + function _convertToMessages(response) + { + if (response === undefined) return []; + if (response instanceof Array) return response; + if (response instanceof String || typeof response == 'string') return eval('(' + response + ')'); + if (response instanceof Object) return [response]; + throw 'Conversion Error ' + response + ', typeof ' + (typeof response); + }; + + function _setStatus(newStatus) + { + _debug('{} -> {}', _status, newStatus); + _status = newStatus; + }; + + function _isDisconnected() + { + return _status == 'disconnecting' || _status == 'disconnected'; + }; + + /** + * Sends the initial handshake message + */ + function _handshake(handshakeProps) + { + _debug('Starting handshake'); + _clientId = null; + + // Start a batch. + // This is needed because handshake and connect are async. + // It may happen that the application calls init() then subscribe() + // and the subscribe message is sent before the connect message, if + // the subscribe message is not held until the connect message is sent. + // So here we start a batch to hold temporarly any message until + // the connection is fully established. + _batch = 0; + _startBatch(); + + // Save the original properties provided by the user + // Deep copy to avoid the user to be able to change them later + _handshakeProps = $.extend(true, {}, handshakeProps); + + var bayeuxMessage = { + version: '1.0', + minimumVersion: '0.9', + channel: '/meta/handshake', + supportedConnectionTypes: _xd ? ['callback-polling'] : ['long-polling', 'callback-polling'] + }; + // Do not allow the user to mess with the required properties, + // so merge first the user properties and *then* the bayeux message + var message = $.extend({}, handshakeProps, bayeuxMessage); + + // We started a batch to hold the application messages, + // so here we must bypass it and deliver immediately. + _setStatus('handshaking'); + _deliver([message], false); + }; + + function _findTransport(handshakeResponse) + { + var transportTypes = handshakeResponse.supportedConnectionTypes; + if (_xd) + { + // If we are cross domain, check if the server supports it, that's the only option + if ($.inArray('callback-polling', transportTypes) >= 0) return _transport; + } + else + { + // Check if we can keep long-polling + if ($.inArray('long-polling', transportTypes) >= 0) return _transport; + + // The server does not support long-polling + if ($.inArray('callback-polling', transportTypes) >= 0) return newCallbackPollingTransport(); + } + return null; + }; + + function _delayedHandshake() + { + _setStatus('handshaking'); + _delayedSend(function() + { + _handshake(_handshakeProps); + }); + }; + + function _delayedConnect() + { + _setStatus('connecting'); + _delayedSend(function() + { + _connect(); + }); + }; + + function _delayedSend(operation) + { + _cancelDelayedSend(); + var delay = _backoff; + _debug("Delayed send: backoff {}, interval {}", _backoff, _advice.interval); + if (_advice.interval && _advice.interval > 0) + delay += _advice.interval; + _scheduledSend = _setTimeout(operation, delay); + }; + + function _cancelDelayedSend() + { + if (_scheduledSend !== null) clearTimeout(_scheduledSend); + _scheduledSend = null; + }; + + function _setTimeout(funktion, delay) + { + return setTimeout(function() + { + try + { + funktion(); + } + catch (x) + { + _debug('Exception during scheduled execution of function \'{}\': {}', funktion.name, x); + } + }, delay); + }; + + /** + * Sends the connect message + */ + function _connect() + { + _debug('Starting connect'); + var message = { + channel: '/meta/connect', + connectionType: _transport.getType() + }; + _setStatus('connecting'); + _deliver([message], true); + _setStatus('connected'); + }; + + function _send(message) + { + if (_batch > 0) + _messageQueue.push(message); + else + _deliver([message], false); + }; + + /** + * Delivers the messages to the comet server + * @param messages the array of messages to send + */ + function _deliver(messages, comet) + { + // We must be sure that the messages have a clientId. + // This is not guaranteed since the handshake may take time to return + // (and hence the clientId is not known yet) and the application + // may create other messages. + $.each(messages, function(index, message) + { + message['id'] = _nextMessageId(); + if (_clientId) message['clientId'] = _clientId; + messages[index] = _applyOutgoingExtensions(message); + }); + + var self = this; + var envelope = { + url: _url, + messages: messages, + onSuccess: function(request, response) + { + try + { + _handleSuccess.call(self, request, response, comet); + } + catch (x) + { + _debug('Exception during execution of success callback: {}', x); + } + }, + onFailure: function(request, reason, exception) + { + try + { + _handleFailure.call(self, request, messages, reason, exception, comet); + } + catch (x) + { + _debug('Exception during execution of failure callback: {}', x); + } + } + }; + _debug('Sending request to {}, message(s): {}', envelope.url, JSON.stringify(envelope.messages)); + _transport.send(envelope, comet); + }; + + function _applyIncomingExtensions(message) + { + for (var i = 0; i < _extensions.length; ++i) + { + var extension = _extensions[i]; + var callback = extension.extension.incoming; + if (callback && typeof callback === 'function') + { + _debug('Calling incoming extension \'{}\', callback \'{}\'', extension.name, callback.name); + message = _applyExtension(extension.name, callback, message) || message; + } + } + return message; + }; + + function _applyOutgoingExtensions(message) + { + for (var i = 0; i < _extensions.length; ++i) + { + var extension = _extensions[i]; + var callback = extension.extension.outgoing; + if (callback && typeof callback === 'function') + { + _debug('Calling outgoing extension \'{}\', callback \'{}\'', extension.name, callback.name); + message = _applyExtension(extension.name, callback, message) || message; + } + } + return message; + }; + + function _applyExtension(name, callback, message) + { + try + { + return callback(message); + } + catch (x) + { + _debug('Exception during execution of extension \'{}\': {}', name, x); + return message; + } + }; + + function _handleSuccess(request, response, comet) + { + var messages = _convertToMessages(response); + _debug('Received response {}', JSON.stringify(messages)); + + // Signal the transport it can deliver other queued requests + _transport.complete(request, true, comet); + + for (var i = 0; i < messages.length; ++i) + { + var message = messages[i]; + message = _applyIncomingExtensions(message); + + if (message.advice) _advice = message.advice; + + var channel = message.channel; + switch (channel) + { + case '/meta/handshake': + _handshakeSuccess(message); + break; + case '/meta/connect': + _connectSuccess(message); + break; + case '/meta/disconnect': + _disconnectSuccess(message); + break; + case '/meta/subscribe': + _subscribeSuccess(message); + break; + case '/meta/unsubscribe': + _unsubscribeSuccess(message); + break; + default: + _messageSuccess(message); + break; + } + } + }; + + function _handleFailure(request, messages, reason, exception, comet) + { + var xhr = request.xhr; + _debug('Request failed, status: {}, reason: {}, exception: {}', xhr && xhr.status, reason, exception); + + // Signal the transport it can deliver other queued requests + _transport.complete(request, false, comet); + + for (var i = 0; i < messages.length; ++i) + { + var message = messages[i]; + var channel = message.channel; + switch (channel) + { + case '/meta/handshake': + _handshakeFailure(xhr, message); + break; + case '/meta/connect': + _connectFailure(xhr, message); + break; + case '/meta/disconnect': + _disconnectFailure(xhr, message); + break; + case '/meta/subscribe': + _subscribeFailure(xhr, message); + break; + case '/meta/unsubscribe': + _unsubscribeFailure(xhr, message); + break; + default: + _messageFailure(xhr, message); + break; + } + } + }; + + function _handshakeSuccess(message) + { + if (message.successful) + { + _debug('Handshake successful'); + // Save clientId, figure out transport, then follow the advice to connect + _clientId = message.clientId; + + var newTransport = _findTransport(message); + if (newTransport === null) + { + throw 'Could not agree on transport with server'; + } + else + { + if (_transport.getType() != newTransport.getType()) + { + _debug('Changing transport from {} to {}', _transport.getType(), newTransport.getType()); + _transport = newTransport; + } + } + + // Notify the listeners + // Here the new transport is in place, as well as the clientId, so + // the listener can perform a publish() if it wants, and the listeners + // are notified before the connect below. + _notifyListeners('/meta/handshake', message); + + var action = _advice.reconnect ? _advice.reconnect : 'retry'; + switch (action) + { + case 'retry': + _delayedConnect(); + break; + default: + break; + } + } + else + { + _debug('Handshake unsuccessful'); + + var retry = !_isDisconnected() && _advice.reconnect != 'none'; + if (!retry) _setStatus('disconnected'); + + _notifyListeners('/meta/handshake', message); + _notifyListeners('/meta/unsuccessful', message); + + // Only try again if we haven't been disconnected and + // the advice permits us to retry the handshake + if (retry) + { + _increaseBackoff(); + _debug('Handshake failure, backing off and retrying in {} ms', _backoff); + _delayedHandshake(); + } + } + }; + + function _handshakeFailure(xhr, message) + { + _debug('Handshake failure'); + + // Notify listeners + var failureMessage = { + successful: false, + failure: true, + channel: '/meta/handshake', + request: message, + xhr: xhr, + advice: { + action: 'retry', + interval: _backoff + } + }; + + var retry = !_isDisconnected() && _advice.reconnect != 'none'; + if (!retry) _setStatus('disconnected'); + + _notifyListeners('/meta/handshake', failureMessage); + _notifyListeners('/meta/unsuccessful', failureMessage); + + // Only try again if we haven't been disconnected and the + // advice permits us to try again + if (retry) + { + _increaseBackoff(); + _debug('Handshake failure, backing off and retrying in {} ms', _backoff); + _delayedHandshake(); + } + }; + + function _connectSuccess(message) + { + var action = _isDisconnected() ? 'none' : (_advice.reconnect ? _advice.reconnect : 'retry'); + if (!_isDisconnected()) _setStatus(action == 'retry' ? 'connecting' : 'disconnecting'); + + if (message.successful) + { + _debug('Connect successful'); + + // End the batch and allow held messages from the application + // to go to the server (see _handshake() where we start the batch). + // The batch is ended before notifying the listeners, so that + // listeners can batch other cometd operations + _endBatch(true); + + // Notify the listeners after the status change but before the next connect + _notifyListeners('/meta/connect', message); + + // Connect was successful. + // Normally, the advice will say "reconnect: 'retry', interval: 0" + // and the server will hold the request, so when a response returns + // we immediately call the server again (long polling) + switch (action) + { + case 'retry': + _resetBackoff(); + _delayedConnect(); + break; + default: + _resetBackoff(); + _setStatus('disconnected'); + break; + } + } + else + { + _debug('Connect unsuccessful'); + + // Notify the listeners after the status change but before the next action + _notifyListeners('/meta/connect', message); + _notifyListeners('/meta/unsuccessful', message); + + // Connect was not successful. + // This may happen when the server crashed, the current clientId + // will be invalid, and the server will ask to handshake again + switch (action) + { + case 'retry': + _increaseBackoff(); + _delayedConnect(); + break; + case 'handshake': + // End the batch but do not deliver the messages until we connect successfully + _endBatch(false); + _resetBackoff(); + _delayedHandshake(); + break; + case 'none': + _resetBackoff(); + _setStatus('disconnected'); + break; + } + } + }; + + function _connectFailure(xhr, message) + { + _debug('Connect failure'); + + // Notify listeners + var failureMessage = { + successful: false, + failure: true, + channel: '/meta/connect', + request: message, + xhr: xhr, + advice: { + action: 'retry', + interval: _backoff + } + }; + _notifyListeners('/meta/connect', failureMessage); + _notifyListeners('/meta/unsuccessful', failureMessage); + + if (!_isDisconnected()) + { + var action = _advice.reconnect ? _advice.reconnect : 'retry'; + switch (action) + { + case 'retry': + _increaseBackoff(); + _debug('Connect failure, backing off and retrying in {} ms', _backoff); + _delayedConnect(); + break; + case 'handshake': + _resetBackoff(); + _delayedHandshake(); + break; + case 'none': + _resetBackoff(); + break; + default: + _debug('Unrecognized reconnect value: {}', action); + break; + } + } + }; + + function _disconnectSuccess(message) + { + if (message.successful) + { + _debug('Disconnect successful'); + _disconnect(false); + _notifyListeners('/meta/disconnect', message); + } + else + { + _debug('Disconnect unsuccessful'); + _disconnect(true); + _notifyListeners('/meta/disconnect', message); + _notifyListeners('/meta/usuccessful', message); + } + }; + + function _disconnect(abort) + { + _cancelDelayedSend(); + if (abort) _transport.abort(); + _clientId = null; + _setStatus('disconnected'); + _batch = 0; + _messageQueue = []; + _resetBackoff(); + }; + + function _disconnectFailure(xhr, message) + { + _debug('Disconnect failure'); + _disconnect(true); + + var failureMessage = { + successful: false, + failure: true, + channel: '/meta/disconnect', + request: message, + xhr: xhr, + advice: { + action: 'none', + interval: 0 + } + }; + _notifyListeners('/meta/disconnect', failureMessage); + _notifyListeners('/meta/unsuccessful', failureMessage); + }; + + function _subscribeSuccess(message) + { + if (message.successful) + { + _debug('Subscribe successful'); + _notifyListeners('/meta/subscribe', message); + } + else + { + _debug('Subscribe unsuccessful'); + _notifyListeners('/meta/subscribe', message); + _notifyListeners('/meta/unsuccessful', message); + } + }; + + function _subscribeFailure(xhr, message) + { + _debug('Subscribe failure'); + + var failureMessage = { + successful: false, + failure: true, + channel: '/meta/subscribe', + request: message, + xhr: xhr, + advice: { + action: 'none', + interval: 0 + } + }; + _notifyListeners('/meta/subscribe', failureMessage); + _notifyListeners('/meta/unsuccessful', failureMessage); + }; + + function _unsubscribeSuccess(message) + { + if (message.successful) + { + _debug('Unsubscribe successful'); + _notifyListeners('/meta/unsubscribe', message); + } + else + { + _debug('Unsubscribe unsuccessful'); + _notifyListeners('/meta/unsubscribe', message); + _notifyListeners('/meta/unsuccessful', message); + } + }; + + function _unsubscribeFailure(xhr, message) + { + _debug('Unsubscribe failure'); + + var failureMessage = { + successful: false, + failure: true, + channel: '/meta/unsubscribe', + request: message, + xhr: xhr, + advice: { + action: 'none', + interval: 0 + } + }; + _notifyListeners('/meta/unsubscribe', failureMessage); + _notifyListeners('/meta/unsuccessful', failureMessage); + }; + + function _messageSuccess(message) + { + if (message.successful === undefined) + { + if (message.data) + { + // It is a plain message, and not a bayeux meta message + _notifyListeners(message.channel, message); + } + else + { + _debug('Unknown message {}', JSON.stringify(message)); + } + } + else + { + if (message.successful) + { + _debug('Publish successful'); + _notifyListeners('/meta/publish', message); + } + else + { + _debug('Publish unsuccessful'); + _notifyListeners('/meta/publish', message); + _notifyListeners('/meta/unsuccessful', message); + } + } + }; + + function _messageFailure(xhr, message) + { + _debug('Publish failure'); + + var failureMessage = { + successful: false, + failure: true, + channel: message.channel, + request: message, + xhr: xhr, + advice: { + action: 'none', + interval: 0 + } + }; + _notifyListeners('/meta/publish', failureMessage); + _notifyListeners('/meta/unsuccessful', failureMessage); + }; + + function _notifyListeners(channel, message) + { + // Notify direct listeners + _notify(channel, message); + + // Notify the globbing listeners + var channelParts = channel.split("/"); + var last = channelParts.length - 1; + for (var i = last; i > 0; --i) + { + var channelPart = channelParts.slice(0, i).join('/') + '/*'; + // We don't want to notify /foo/* if the channel is /foo/bar/baz, + // so we stop at the first non recursive globbing + if (i == last) _notify(channelPart, message); + // Add the recursive globber and notify + channelPart += '*'; + _notify(channelPart, message); + } + }; + + function _notify(channel, message) + { + var subscriptions = _listeners[channel]; + if (subscriptions && subscriptions.length > 0) + { + for (var i = 0; i < subscriptions.length; ++i) + { + var subscription = subscriptions[i]; + // Subscriptions may come and go, so the array may have 'holes' + if (subscription) + { + try + { + _debug('Notifying subscription: channel \'{}\', callback \'{}\'', channel, subscription.callback.name); + subscription.callback.call(subscription.scope, message); + } + catch (x) + { + // Ignore exceptions from callbacks + _warn('Exception during execution of callback \'{}\' on channel \'{}\' for message {}, exception: {}', subscription.callback.name, channel, JSON.stringify(message), x); + } + } + } + } + }; + + function _resetBackoff() + { + _backoff = 0; + }; + + function _increaseBackoff() + { + if (_backoff < _maxBackoff) _backoff += _backoffIncrement; + }; + + var _error = this._error = function(text, args) + { + _log('error', _format.apply(this, arguments)); + }; + + var _warn = this._warn = function(text, args) + { + _log('warn', _format.apply(this, arguments)); + }; + + var _info = this._info = function(text, args) + { + _log('info', _format.apply(this, arguments)); + }; + + var _debug = this._debug = function(text, args) + { + _log('debug', _format.apply(this, arguments)); + }; + + function _log(level, text) + { + var priority = _logPriorities[level]; + var configPriority = _logPriorities[_logLevel]; + if (!configPriority) configPriority = _logPriorities['info']; + if (priority >= configPriority) + { + if (window.console) window.console.log(text); + } + }; + + function _format(text) + { + var braces = /\{\}/g; + var result = ''; + var start = 0; + var count = 0; + while (braces.test(text)) + { + result += text.substr(start, braces.lastIndex - start - 2); + var arg = arguments[++count]; + result += arg !== undefined ? arg : '{}'; + start = braces.lastIndex; + } + result += text.substr(start, text.length - start); + return result; + }; + + function newLongPollingTransport() + { + return $.extend({}, new Transport('long-polling'), new LongPollingTransport()); + }; + + function newCallbackPollingTransport() + { + return $.extend({}, new Transport('callback-polling'), new CallbackPollingTransport()); + }; + + /** + * Base object with the common functionality for transports. + * The key responsibility is to allow at most 2 outstanding requests to the server, + * to avoid that requests are sent behind a long poll. + * To achieve this, we have one reserved request for the long poll, and all other + * requests are serialized one after the other. + */ + var Transport = function(type) + { + var _maxRequests = 2; + var _requestIds = 0; + var _cometRequest = null; + var _requests = []; + var _packets = []; + + this.getType = function() + { + return type; + }; + + this.send = function(packet, comet) + { + if (comet) + _cometSend(this, packet); + else + _send(this, packet); + }; + + function _cometSend(self, packet) + { + if (_cometRequest !== null) throw 'Concurrent comet requests not allowed, request ' + _cometRequest.id + ' not yet completed'; + + var requestId = ++_requestIds; + _debug('Beginning comet request {}', requestId); + + var request = {id: requestId}; + _debug('Delivering comet request {}', requestId); + self.deliver(packet, request); + _cometRequest = request; + }; + + function _send(self, packet) + { + var requestId = ++_requestIds; + _debug('Beginning request {}, {} other requests, {} queued requests', requestId, _requests.length, _packets.length); + + var request = {id: requestId}; + // Consider the comet request which should always be present + if (_requests.length < _maxRequests - 1) + { + _debug('Delivering request {}', requestId); + self.deliver(packet, request); + _requests.push(request); + } + else + { + _packets.push([packet, request]); + _debug('Queued request {}, {} queued requests', requestId, _packets.length); + } + }; + + this.complete = function(request, success, comet) + { + if (comet) + _cometComplete(request); + else + _complete(this, request, success); + }; + + function _cometComplete(request) + { + var requestId = request.id; + if (_cometRequest !== request) throw 'Comet request mismatch, completing request ' + requestId; + + // Reset comet request + _cometRequest = null; + _debug('Ended comet request {}', requestId); + }; + + function _complete(self, request, success) + { + var requestId = request.id; + var index = $.inArray(request, _requests); + // The index can be negative the request has been aborted + if (index >= 0) _requests.splice(index, 1); + _debug('Ended request {}, {} other requests, {} queued requests', requestId, _requests.length, _packets.length); + + if (_packets.length > 0) + { + var packet = _packets.shift(); + if (success) + { + _debug('Dequeueing and sending request {}, {} queued requests', packet[1].id, _packets.length); + _send(self, packet[0]); + } + else + { + _debug('Dequeueing and failing request {}, {} queued requests', packet[1].id, _packets.length); + // Keep the semantic of calling response callbacks asynchronously after the request + setTimeout(function() { packet[0].onFailure(packet[1], 'error'); }, 0); + } + } + }; + + this.abort = function() + { + for (var i = 0; i < _requests.length; ++i) + { + var request = _requests[i]; + _debug('Aborting request {}', request.id); + if (request.xhr) request.xhr.abort(); + } + if (_cometRequest) + { + _debug('Aborting comet request {}', _cometRequest.id); + if (_cometRequest.xhr) _cometRequest.xhr.abort(); + } + _cometRequest = null; + _requests = []; + _packets = []; + }; + }; + + var LongPollingTransport = function() + { + this.deliver = function(packet, request) + { + request.xhr = $.ajax({ + url: packet.url, + type: 'POST', + contentType: 'text/json;charset=UTF-8', + beforeSend: function(xhr) + { + xhr.setRequestHeader('Connection', 'Keep-Alive'); + return true; + }, + data: JSON.stringify(packet.messages), + success: function(response) { packet.onSuccess(request, response); }, + error: function(xhr, reason, exception) { packet.onFailure(request, reason, exception); } + }); + }; + }; + + var CallbackPollingTransport = function() + { + var _maxLength = 2000; + this.deliver = function(packet, request) + { + // Microsoft Internet Explorer has a 2083 URL max length + // We must ensure that we stay within that length + var messages = JSON.stringify(packet.messages); + // Encode the messages because all brackets, quotes, commas, colons, etc + // present in the JSON will be URL encoded, taking many more characters + var urlLength = packet.url.length + encodeURI(messages).length; + _debug('URL length: {}', urlLength); + // Let's stay on the safe side and use 2000 instead of 2083 + // also because we did not count few characters among which + // the parameter name 'message' and the parameter 'jsonp', + // which sum up to about 50 chars + if (urlLength > _maxLength) + { + var x = packet.messages.length > 1 ? + 'Too many bayeux messages in the same batch resulting in message too big ' + + '(' + urlLength + ' bytes, max is ' + _maxLength + ') for transport ' + this.getType() : + 'Bayeux message too big (' + urlLength + ' bytes, max is ' + _maxLength + ') ' + + 'for transport ' + this.getType(); + // Keep the semantic of calling response callbacks asynchronously after the request + _setTimeout(function() { packet.onFailure(request, 'error', x); }, 0); + } + else + { + $.ajax({ + url: packet.url, + type: 'GET', + dataType: 'jsonp', + jsonp: 'jsonp', + beforeSend: function(xhr) + { + xhr.setRequestHeader('Connection', 'Keep-Alive'); + return true; + }, + data: + { + // In callback-polling, the content must be sent via the 'message' parameter + message: messages + }, + success: function(response) { packet.onSuccess(request, response); }, + error: function(xhr, reason, exception) { packet.onFailure(request, reason, exception); } + }); + } + }; + }; + }; + + /** + * The JS object that exposes the comet API to applications + */ + $.cometd = new $.Cometd(); // The default instance + +})(jQuery); diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js index f4da1f47cd..6612b51168 100644 --- a/plugins/Comet/updatetimeline.js +++ b/plugins/Comet/updatetimeline.js @@ -1,3 +1,30 @@ // update the local timeline from a Comet server // +var updater = function() +{ + var _handshook = false; + var _connected = false; + var _cometd; + + return { + init: function() + { + _cometd = $.cometd; // Uses the default Comet object + _cometd.init(_timelineServer); + _cometd.subscribe(_timeline, this, receive); + $(window).unload(leave); + } + } + + function leave() + { + _cometd.disconnect(); + } + + function receive(message) + { + var noticeItem = makeNoticeItem(message.data); + var noticeList = $('ul.notices'); + } +}(); From 84072aa5cf6124d59a06a7f0a7945c00ee2836da Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 12:13:49 -0400 Subject: [PATCH 420/503] run 'set names' after each connection to deal with UTF8 correctly --- classes/Memcached_DataObject.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 5f71f716b3..877bbf2e0f 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -227,4 +227,20 @@ class Memcached_DataObject extends DB_DataObject $c->set($ckey, $cached, MEMCACHE_COMPRESSED, $expiry); return new ArrayWrapper($cached); } + + // We overload so that 'SET NAMES "utf8"' is called for + // each connection + + function _connect() + { + global $_DB_DATAOBJECT; + $exists = !empty($this->_database_dsn_md5) && + isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]); + $result = parent::_connect(); + if (!$exists) { + $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; + $DB->query('SET NAMES "utf8"'); + } + return $result; + } } From 068f6801cc59488bfc50ef399a2a4d22b1b7e9c2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 12:27:32 -0400 Subject: [PATCH 421/503] Revert "run 'set names' after each connection to deal with UTF8 correctly" This reverts commit 84072aa5cf6124d59a06a7f0a7945c00ee2836da. This commit caused grievous harm to old notices on identi.ca. Reverting until we figure out how to convert the old notices. --- classes/Memcached_DataObject.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 877bbf2e0f..5f71f716b3 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -227,20 +227,4 @@ class Memcached_DataObject extends DB_DataObject $c->set($ckey, $cached, MEMCACHE_COMPRESSED, $expiry); return new ArrayWrapper($cached); } - - // We overload so that 'SET NAMES "utf8"' is called for - // each connection - - function _connect() - { - global $_DB_DATAOBJECT; - $exists = !empty($this->_database_dsn_md5) && - isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]); - $result = parent::_connect(); - if (!$exists) { - $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; - $DB->query('SET NAMES "utf8"'); - } - return $result; - } } From ccf45d454c68f7f667d07e0db608569e049ec285 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 15:08:49 -0400 Subject: [PATCH 422/503] Lots of tweaking to make things work Did some tweaking and maneuvering to make things work. This version will now show a "notice received" alert box -- lots of progress! Had to test with Java server, not Python server. --- plugins/Comet/CometPlugin.php | 22 +- plugins/Comet/json2.js | 478 ++++++++++++++++++++++++++++++++ plugins/Comet/updatetimeline.js | 48 ++-- 3 files changed, 516 insertions(+), 32 deletions(-) create mode 100644 plugins/Comet/json2.js diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index 10f8c198c3..f60d400751 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -56,6 +56,8 @@ class CometPlugin extends Plugin { $timeline = null; + $this->log(LOG_DEBUG, 'got action ' . $action->trimmed('action')); + switch ($action->trimmed('action')) { case 'public': $timeline = '/timelines/public'; @@ -64,16 +66,18 @@ class CometPlugin extends Plugin return true; } - $action->element('script', array('type' => 'text/javascript', - 'src' => common_path('plugins/Comet/jquery.comet.js')), + $scripts = array('jquery.comet.js', 'json2.js', 'updatetimeline.js'); + + foreach ($scripts as $script) { + $action->element('script', array('type' => 'text/javascript', + 'src' => common_path('plugins/Comet/'.$script)), ' '); + } + $action->elementStart('script', array('type' => 'text/javascript')); - $action->raw("var _timelineServer = \"$this->server\"; ". - "var _timeline = \"$timeline\";"); + $action->raw("$(document).ready(function() { updater.init(\"$this->server\", \"$timeline\");});"); $action->elementEnd('script'); - $action->element('script', array('type' => 'text/javascript', - 'src' => common_path('plugins/Comet/updatetimeline.js')), - ' '); + return true; } @@ -96,21 +100,17 @@ class CometPlugin extends Plugin $json = $this->noticeAsJson($notice); - $this->log(LOG_DEBUG, "JSON = '$json'"); - // Bayeux? Comet? Huh? These terms confuse me $bay = new Bayeux($this->server); foreach ($timelines as $timeline) { $this->log(LOG_INFO, "Posting notice $notice->id to '$timeline'."); $bay->publish($timeline, $json); - $this->log(LOG_DEBUG, "Done posting notice $notice->id to '$timeline'."); } $bay = NULL; } - $this->log(LOG_DEBUG, "All done."); return true; } diff --git a/plugins/Comet/json2.js b/plugins/Comet/json2.js new file mode 100644 index 0000000000..7e27df5181 --- /dev/null +++ b/plugins/Comet/json2.js @@ -0,0 +1,478 @@ +/* + http://www.JSON.org/json2.js + 2009-04-16 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the object holding the key. + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. +*/ + +/*jslint evil: true */ + +/*global JSON */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + JSON = {}; +} +(function () { + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + 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 = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + 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) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/. +test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). +replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). +replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js index 6612b51168..7b22445e30 100644 --- a/plugins/Comet/updatetimeline.js +++ b/plugins/Comet/updatetimeline.js @@ -3,28 +3,34 @@ var updater = function() { - var _handshook = false; - var _connected = false; - var _cometd; + var _cometd; - return { - init: function() - { - _cometd = $.cometd; // Uses the default Comet object - _cometd.init(_timelineServer); - _cometd.subscribe(_timeline, this, receive); - $(window).unload(leave); - } - } + return { + init: function(server, timeline) + { + _cometd = $.cometd; // Uses the default Comet object + _cometd.setLogLevel('debug'); + _cometd.init(server); + _cometd.subscribe(timeline, receive); + $(window).unload(leave); + } + } - function leave() - { - _cometd.disconnect(); - } + function leave() + { + _cometd.disconnect(); + } - function receive(message) - { - var noticeItem = makeNoticeItem(message.data); - var noticeList = $('ul.notices'); - } + function receive(message) + { + alert("Received notice."); + var noticeItem = makeNoticeItem(message.data); + var noticeList = $('ul.notices'); + } + + function makeNoticeItem(data) + { + return ''; + } }(); + From 7dbb5fb8fdf7c4f82c212863a17793a50f887f58 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 15:37:00 -0400 Subject: [PATCH 423/503] Make notice auto-update Shows notices auto-updating --- plugins/Comet/CometPlugin.php | 5 +++++ plugins/Comet/updatetimeline.js | 37 ++++++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index f60d400751..a7a4f4b237 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -126,6 +126,11 @@ class CometPlugin extends Plugin $act = new TwitterApiAction('/dev/null'); $arr = $act->twitter_status_array($notice, true); + $arr['url'] = $notice->bestUrl(); + + $profile = $notice->getProfile(); + $arr['user']['profile_url'] = $profile->profileurl; + return $arr; } diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js index 7b22445e30..c6eefb4475 100644 --- a/plugins/Comet/updatetimeline.js +++ b/plugins/Comet/updatetimeline.js @@ -23,14 +23,45 @@ var updater = function() function receive(message) { - alert("Received notice."); var noticeItem = makeNoticeItem(message.data); - var noticeList = $('ul.notices'); + $("#notices_primary .notices").prepend(noticeItem, true); + $("#notices_primary .notice:first").css({display:"none"}); + $("#notices_primary .notice:first").fadeIn(2500); + NoticeHover(); + NoticeReply(); } function makeNoticeItem(data) { - return ''; + user = data['user']; + ni = "
  • "+ + "
    "+ + ""+ + ""+ + "\""+user['screen_name']+"\"/"+ + ""+user['screen_name']+""+ + ""+ + ""+ + "

    "+data['text']+"

    "+ + "
    "+ + "
    "+ + "
    "+ + "
    Published
    "+ + "
    "+ + ""+ + "a few seconds ago"+ + " "+ + "
    "+ + "
    "+ + "
    "+ + "
    From
    "+ + "
    "+data['source']+"
    "+ + "
    "+ + "
    "+ + "
    "+ + "
    "+ + "
  • "; + return ni; } }(); From 781341d91fd4c7406d8687e7828ab86f9696cf66 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 15:41:55 -0400 Subject: [PATCH 424/503] README for the comet plugin --- plugins/Comet/README | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 plugins/Comet/README diff --git a/plugins/Comet/README b/plugins/Comet/README new file mode 100644 index 0000000000..4abd40af7a --- /dev/null +++ b/plugins/Comet/README @@ -0,0 +1,26 @@ +This is a plugin to automatically load notices in the browser no +matter who creates them -- the kind of thing we see with +search.twitter.com, rejaw.com, or FriendFeed's "real time" news. + +NOTE: this is an insecure version; don't roll it out on a production +server. + +It requires a cometd server. I've only had the cometd-java server work +correctly; something's wiggy with the Twisted-based server. + +After you have a cometd server installed, just add this code to your +config.php: + + require_once(INSTALLDIR.'/plugins/Comet/CometPlugin.php'); + $cp = new CometPlugin('http://example.com:8080/cometd/'); + +Change 'example.com:8080' to the name and port of the server you +installed cometd on. + +TODO: + +* Needs to be tested with Ajax submission. Probably messes everything + up. +* Add more timelines: personal inbox and tags would be great. +* Add security. In particular, only let the PHP code publish notices + to the cometd server. Currently, it doesn't try to authenticate. From e438334c00ebe29c01bfc5b02aa64cffdb43cb46 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 18:00:06 -0400 Subject: [PATCH 425/503] add live updating for tag pages --- plugins/Comet/CometPlugin.php | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index a7a4f4b237..cff0d4c9d6 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -62,6 +62,14 @@ class CometPlugin extends Plugin case 'public': $timeline = '/timelines/public'; break; + case 'tag': + $tag = $action->trimmed('tag'); + if (!empty($tag)) { + $timeline = '/timelines/tag/'.$tag; + } else { + return true; + } + break; default: return true; } @@ -94,6 +102,14 @@ class CometPlugin extends Plugin $timelines[] = '/timelines/public'; } + $tags = $this->getNoticeTags($notice); + + if (!empty($tags)) { + foreach ($tags as $tag) { + $timelines[] = '/timelines/tag/' . $tag; + } + } + if (count($timelines) > 0) { // Require this, since we need it require_once(INSTALLDIR.'/plugins/Comet/bayeux.class.inc.php'); @@ -134,6 +150,26 @@ class CometPlugin extends Plugin return $arr; } + function getNoticeTags($notice) + { + $tags = null; + + $nt = new Notice_tag(); + $nt->notice_id = $notice->id; + + if ($nt->find()) { + $tags = array(); + while ($nt->fetch()) { + $tags[] = $nt->tag; + } + } + + $nt->free(); + $nt = null; + + return $tags; + } + // Push this up to Plugin function log($level, $msg) From db3b56a2fdf51e97e9859aa731674947571667aa Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 20:50:39 -0400 Subject: [PATCH 426/503] Display rendered HTML for a notice Display the rendered HTML for a notice --- plugins/Comet/CometPlugin.php | 1 + plugins/Comet/updatetimeline.js | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index cff0d4c9d6..2e0bb40a46 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -143,6 +143,7 @@ class CometPlugin extends Plugin $arr = $act->twitter_status_array($notice, true); $arr['url'] = $notice->bestUrl(); + $arr['html'] = htmlspecialchars($notice->rendered); $profile = $notice->getProfile(); $arr['user']['profile_url'] = $profile->profileurl; diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js index c6eefb4475..55511d35ff 100644 --- a/plugins/Comet/updatetimeline.js +++ b/plugins/Comet/updatetimeline.js @@ -34,6 +34,8 @@ var updater = function() function makeNoticeItem(data) { user = data['user']; + html = data['html'].replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + ni = "
  • "+ "
    "+ ""+ @@ -42,7 +44,7 @@ var updater = function() ""+user['screen_name']+""+ ""+ ""+ - "

    "+data['text']+"

    "+ + "

    "+html+"

    "+ "
    "+ "
    "+ "
    "+ From e97223b2ba3f9f1818ba12b707c53c0ebdcab144 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 21:15:11 -0400 Subject: [PATCH 427/503] Don't add a notice if it already exists on the page Try not to interfere with Ajax posting; don't show something if it's already on the page. --- plugins/Comet/updatetimeline.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js index 55511d35ff..de750baba3 100644 --- a/plugins/Comet/updatetimeline.js +++ b/plugins/Comet/updatetimeline.js @@ -23,6 +23,14 @@ var updater = function() function receive(message) { + id = message.data.id; + + // Don't add it if it already exists + + if ($("#notice-"+id).length > 0) { + return; + } + var noticeItem = makeNoticeItem(message.data); $("#notices_primary .notices").prepend(noticeItem, true); $("#notices_primary .notice:first").css({display:"none"}); From 7405d9dfa684975309150537069a1268a67ed6be Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 26 Apr 2009 21:16:09 -0400 Subject: [PATCH 428/503] Don't add a node if it's already there Try not to double-add a node on Ajax submit. Normally not a big deal, but may happen if the CometPlugin (or in the future Strophe or other auto-update plugins) is enabled. --- js/util.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/js/util.js b/js/util.js index 15a14625c7..f15c4f2bbf 100644 --- a/js/util.js +++ b/js/util.js @@ -188,11 +188,15 @@ $(document).ready(function(){ alert(result); } else { - $("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true)); - $("#notices_primary .notice:first").css({display:"none"}); - $("#notices_primary .notice:first").fadeIn(2500); - NoticeHover(); - NoticeReply(); + li = $("li", xml).get(0); + id = li.id; + if ($("#"+li.id).length == 0) { + $("#notices_primary .notices").prepend(document._importNode(li, true)); + $("#notices_primary .notice:first").css({display:"none"}); + $("#notices_primary .notice:first").fadeIn(2500); + NoticeHover(); + NoticeReply(); + } } $("#notice_data-text").val(""); counter(); From efe8c47d7d9e91eb8308845b8b0717e84e36e346 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 27 Apr 2009 20:07:22 +0000 Subject: [PATCH 429/503] Minor CSS order/cleanup. --- theme/base/css/display.css | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 0bc2e68b65..dc6b4bc29a 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -842,23 +842,6 @@ text-transform:lowercase; } - -.notice-data { -position:absolute; -top:18px; -right:0; -min-height:50px; -margin-bottom:4px; -} -.notice .entry-content .notice-data dt { -display:none; -} - -.notice-data a { -display:block; -outline:none; -} - .notice-options { padding-left:2%; float:left; @@ -1036,6 +1019,8 @@ padding-right:30px; .hentry .entry-content p { margin-bottom:18px; } +.system_notice ul, +.instructions ul, .hentry entry-content ol, .hentry .entry-content ul { list-style-position:inside; @@ -1160,9 +1145,6 @@ clear:both; margin-bottom:0; } -.instructions ul { -list-style-position:inside; -} .instructions p, .instructions ul { margin-bottom:18px; From 6a20ef71d3b2b325ce24318e2ba4483d6c8732ce Mon Sep 17 00:00:00 2001 From: CiaranG Date: Tue, 28 Apr 2009 13:05:48 +0100 Subject: [PATCH 430/503] Fixed typo in stopdaemons.sh - was not stopping the new memcached queue handler --- scripts/stopdaemons.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index 196991de0f..f6d71eddfb 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -25,7 +25,7 @@ DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ - memcachedhandler inboxhandler; do + memcachehandler inboxhandler; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do From 5b78f95e972f9f19ea46607e8b9544b8f7c4207a Mon Sep 17 00:00:00 2001 From: CiaranG Date: Tue, 28 Apr 2009 13:30:54 +0100 Subject: [PATCH 431/503] Only start daemons that are required, according to the site config. There is the potential to not start some more - see the checks in getvaliddaemons.php --- scripts/getvaliddaemons.php | 52 +++++++++++++++++++++++++++++++++++++ scripts/startdaemons.sh | 6 ++--- 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100755 scripts/getvaliddaemons.php diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php new file mode 100755 index 0000000000..482e63af70 --- /dev/null +++ b/scripts/getvaliddaemons.php @@ -0,0 +1,52 @@ +#!/usr/bin/env php +. + */ + +/** + * Utility script to get a list of daemons that should run, based on the + * current configuration. This is used by startdaemons.sh to determine what + * it should and shouldn't start up. The output is a list of space-separated + * daemon names. + */ + + +# Abort if called from a web server +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +if(common_config('xmpp','enabled')) { + echo "xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php "; + echo "xmppconfirmhandler.php "; +} +if(common_config('memcached','enabled')) { + echo "memcachedqueuehandler.php "; +} +echo "ombqueuehandler.php "; +echo "twitterqueuehandler.php "; +echo "facebookqueuehandler.php "; +echo "pingqueuehandler.php "; +echo "inboxqueuehandler.php "; +echo "smsqueuehandler.php "; diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 66f9ed4e0c..3869e95c4c 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -21,11 +21,9 @@ # Note that the 'maildaemon' needs to run as a mail filter. DIR=`dirname $0` +DAEMONS=`php $DIR/getvaliddaemons.php` -for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \ - xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \ - twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php \ - memcachedqueuehandler.php inboxqueuehandler.php; do +for f in $DAEMONS; do echo -n "Starting $f..."; php $DIR/$f From c7105c2af1ebe3cddd477265c6fea59a61d0c7e5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 28 Apr 2009 13:07:05 -0400 Subject: [PATCH 432/503] Change to avoid a join in notice inbox The join in notice_inbox is causing temp-table sorting on identi.ca, so I'm trying a finer-tuned approach. --- classes/Notice.php | 31 ++++++++++-- classes/Notice_inbox.php | 101 ++++++++++++++++++++++++++++++++++++++- classes/User.php | 29 +---------- 3 files changed, 127 insertions(+), 34 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 27b98de1cc..b087c94bc4 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -215,6 +215,7 @@ class Notice extends Memcached_DataObject if (common_config('queue', 'enabled')) { $notice->blowAuthorCaches(); } else { + common_debug("Blowing caches for new notice."); $notice->blowCaches(); } } @@ -285,7 +286,7 @@ class Notice extends Memcached_DataObject // Clear the user's cache $cache = common_memcache(); if (!empty($cache)) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $this->profile_id)); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$this->profile_id)); } $this->blowNoticeCache($blowLast); $this->blowPublicCache($blowLast); @@ -307,9 +308,9 @@ class Notice extends Memcached_DataObject $member->group_id = $group_inbox->group_id; if ($member->find()) { while ($member->fetch()) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $member->profile_id)); + $cache->delete(common_cache_key('notice_inbox:by_user:' . $member->profile_id)); if ($blowLast) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $member->profile_id . ';last')); + $cache->delete(common_cache_key('notice_inbox:by_user:' . $member->profile_id . ';last')); } } } @@ -352,9 +353,9 @@ class Notice extends Memcached_DataObject 'WHERE subscription.subscribed = ' . $this->profile_id); while ($user->fetch()) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id)); if ($blowLast) { - $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last')); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id.';last')); } } $user->free(); @@ -613,6 +614,26 @@ class Notice extends Memcached_DataObject return $wrapper; } + function getStreamByIds($ids) + { + $cache = common_memcache(); + + if (!empty($cache)) { + $notices = array(); + foreach ($ids as $id) { + $notices[] = Notice::staticGet('id', $id); + } + return new ArrayWrapper($notices); + } else { + $notice = new Notice(); + $notice->whereAdd('id in (' . implode(', ', $ids) . ')'); + $notice->orderBy('id DESC'); + + $notice->find(); + return $notice; + } + } + function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) { diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 81ddb45385..162da74fee 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -1,7 +1,7 @@ INBOX_CACHE_WINDOW) { + common_debug('Doing direct DB hit for notice_inbox since the params are screwy.'); + return Notice_inbox::_streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since); + } + + $idkey = common_cache_key('notice_inbox:by_user:'.$user_id); + + $idstr = $cache->get($idkey); + + if (!empty($idstr)) { + // Cache hit! Woohoo! + common_debug('Cache hit for notice_inbox.'); + $window = explode(',', $idstr); + $ids = array_slice($window, $offset, $limit); + return $ids; + } + + $laststr = common_cache_key($idkey.';last'); + + if (!empty($laststr)) { + common_debug('Cache hit for notice_inbox on last item.'); + + $window = explode(',', $laststr); + $last_id = $window[0]; + $new_ids = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, + $last_id, null, 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; + } + + $window = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, + null, null, null); + + $windowstr = implode(',', $new_window); + + $result = $cache->set($idkey, $windowstr); + $result = $cache->set($idkey . ';last', $windowstr); + + $ids = array_slice($window, $offset, $limit); + + return $ids; + } + + function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since) + { + $inbox = new Notice_inbox(); + + $inbox->user_id = $user_id; + + if ($since_id != 0) { + $inbox->whereAdd('notice_id > ' . $since_id); + } + + if ($before_id != 0) { + $inbox->whereAdd('notice_id < ' . $before_id); + } + + if (!is_null($since)) { + $inbox->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $inbox->orderBy('notice_id DESC'); + + if (!is_null($offset)) { + $inbox->limit($offset, $limit); + } + + $ids = array(); + + if ($inbox->find()) { + while ($inbox->fetch()) { + $ids[] = $inbox->notice_id; + } + } + + return $ids; + } } diff --git a/classes/User.php b/classes/User.php index 098381f738..ce7ea1464f 100644 --- a/classes/User.php +++ b/classes/User.php @@ -451,34 +451,9 @@ class User extends Memcached_DataObject } else if ($enabled === true || ($enabled == 'transitional' && $this->inboxed == 1)) { - $cache = common_memcache(); + $ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since); - if (!empty($cache)) { - - # Get the notices out of the cache - - $notices = $cache->get(common_cache_key($cachekey)); - - # On a cache hit, return a DB-object-like wrapper - - if ($notices !== false) { - $wrapper = new ArrayWrapper(array_slice($notices, $offset, $limit)); - return $wrapper; - } - } - - $inbox = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since); - - $ids = array(); - - while ($inbox->fetch()) { - $ids[] = $inbox->notice_id; - } - - $inbox->free(); - unset($inbox); - - return Notice::getStreamByIds($ids, 'user:notices_with_friends:' . $this->id); + return Notice::getStreamByIds($ids); } } From fe53e780be5db4ceb2831a1d69faec6130a10deb Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 28 Apr 2009 13:31:56 -0400 Subject: [PATCH 433/503] Remove some debug comments in query-by-id --- classes/Notice.php | 5 ++--- classes/Notice_inbox.php | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index b087c94bc4..49d0939c1a 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -215,7 +215,6 @@ class Notice extends Memcached_DataObject if (common_config('queue', 'enabled')) { $notice->blowAuthorCaches(); } else { - common_debug("Blowing caches for new notice."); $notice->blowCaches(); } } @@ -353,9 +352,9 @@ class Notice extends Memcached_DataObject 'WHERE subscription.subscribed = ' . $this->profile_id); while ($user->fetch()) { - $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id)); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id)); if ($blowLast) { - $cache->delete(common_cache_key('notice_inbox:by_user:'.$user_id.';last')); + $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id.';last')); } } $user->free(); diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 162da74fee..f321370380 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -50,7 +50,6 @@ class Notice_inbox extends Memcached_DataObject if (empty($cache) || $since_id != 0 || $before_id != 0 || !is_null($since) || ($offset + $limit) > INBOX_CACHE_WINDOW) { - common_debug('Doing direct DB hit for notice_inbox since the params are screwy.'); return Notice_inbox::_streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since); } @@ -60,7 +59,6 @@ class Notice_inbox extends Memcached_DataObject if (!empty($idstr)) { // Cache hit! Woohoo! - common_debug('Cache hit for notice_inbox.'); $window = explode(',', $idstr); $ids = array_slice($window, $offset, $limit); return $ids; @@ -69,8 +67,6 @@ class Notice_inbox extends Memcached_DataObject $laststr = common_cache_key($idkey.';last'); if (!empty($laststr)) { - common_debug('Cache hit for notice_inbox on last item.'); - $window = explode(',', $laststr); $last_id = $window[0]; $new_ids = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, From f798d1ea430d25c2f4a60179c65b39b1257a5340 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 28 Apr 2009 17:08:20 -0700 Subject: [PATCH 434/503] Added dirty dates to Foreign_link --- classes/Foreign_link.php | 2 ++ classes/laconica.ini | 2 ++ db/laconica.sql | 2 ++ 3 files changed, 6 insertions(+) diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php index 5d9c82a85a..6065609512 100644 --- a/classes/Foreign_link.php +++ b/classes/Foreign_link.php @@ -17,6 +17,8 @@ class Foreign_link extends Memcached_DataObject public $noticesync; // tinyint(1) not_null default_1 public $friendsync; // tinyint(1) not_null default_2 public $profilesync; // tinyint(1) not_null default_1 + public $last_noticesync; // datetime() + public $last_friendsync; // datetime() public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP diff --git a/classes/laconica.ini b/classes/laconica.ini index dd424bbdd3..5a905a4bbe 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -55,6 +55,8 @@ credentials = 2 noticesync = 145 friendsync = 145 profilesync = 145 +last_noticesync = 14 +last_friendsync = 14 created = 142 modified = 384 diff --git a/db/laconica.sql b/db/laconica.sql index 83d610f0d3..d9e21a7b51 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -291,6 +291,8 @@ create table foreign_link ( noticesync tinyint not null default 1 comment 'notice synchronization, bit 1 = sync outgoing, bit 2 = sync incoming, bit 3 = filter local replies', friendsync tinyint not null default 2 comment 'friend synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', profilesync tinyint not null default 1 comment 'profile synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', + last_noticesync datetime default null comment 'last time notices were imported', + last_friendsync datetime default null comment 'last time friends were imported', created datetime not null comment 'date this record was created', modified timestamp comment 'date this record was modified', From e85cddba45c2ce02d135f00acdcfa37cb9168130 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 28 Apr 2009 23:31:00 -0700 Subject: [PATCH 435/503] Ticket #1428 - Changed replies API method to "mentions". --- actions/twitapistatuses.php | 38 ++++++++++++++++++++----------------- lib/router.php | 4 ++-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 323c4f1f88..3abeba3672 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -144,10 +144,10 @@ class TwitapistatusesAction extends TwitterapiAction break; case 'atom': if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/friends_timeline/' . $apidata['api_arg'] . '.atom'; } else { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/friends_timeline.atom'; } $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri); @@ -231,10 +231,10 @@ class TwitapistatusesAction extends TwitterapiAction break; case 'atom': if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/user_timeline/' . $apidata['api_arg'] . '.atom'; } else { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/user_timeline.atom'; } $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink, $selfuri); @@ -344,7 +344,7 @@ class TwitapistatusesAction extends TwitterapiAction $this->show($args, $apidata); } - function replies($args, $apidata) + function mentions($args, $apidata) { parent::handle($args); @@ -360,11 +360,13 @@ class TwitapistatusesAction extends TwitterapiAction $profile = $user->getProfile(); $sitename = common_config('site', 'name'); - $title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname); + $title = sprintf(_('%1$s / Updates mentioning %2$s'), + $sitename, $user->nickname); $taguribase = common_config('integration', 'taguri'); - $id = "tag:$taguribase:Replies:".$user->id; + $id = "tag:$taguribase:Mentions:".$user->id; $link = common_local_url('replies', array('nickname' => $user->nickname)); - $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $user->nickname, $profile->getBestName()); + $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), + $sitename, $user->nickname, $profile->getBestName()); if (!$page) { $page = 1; @@ -385,7 +387,8 @@ class TwitapistatusesAction extends TwitterapiAction $since = strtotime($this->arg('since')); - $notice = $user->getReplies((($page-1)*20), $count, $since_id, $before_id, $since); + $notice = $user->getReplies((($page-1)*20), + $count, $since_id, $before_id, $since); $notices = array(); while ($notice->fetch()) { @@ -400,14 +403,10 @@ class TwitapistatusesAction extends TwitterapiAction $this->show_rss_timeline($notices, $title, $link, $subtitle); break; case 'atom': - if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . - 'api/statuses/replies/' . $apidata['api_arg'] . '.atom'; - } else { - $selfuri = $selfuri = common_root_url() . - 'api/statuses/replies.atom'; - } - $this->show_atom_timeline($notices, $title, $id, $link, $subtitle, null, $selfuri); + $selfuri = common_root_url() . + ltrim($_SERVER['QUERY_STRING'], 'p='); + $this->show_atom_timeline($notices, $title, $id, $link, $subtitle, + null, $selfuri); break; case 'json': $this->show_json_timeline($notices); @@ -418,6 +417,11 @@ class TwitapistatusesAction extends TwitterapiAction } + function replies($args, $apidata) + { + call_user_func(array($this, 'mentions'), $args, $apidata); + } + function show($args, $apidata) { parent::handle($args); diff --git a/lib/router.php b/lib/router.php index 6fb2f94872..12590b790d 100644 --- a/lib/router.php +++ b/lib/router.php @@ -231,12 +231,12 @@ class Router $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|mentions|friends|followers|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(user_timeline|friends_timeline|replies|show|destroy|friends|followers)')); + array('method' => '(user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); // users From 10ef8a2f7112a83188e9702d480abd3c6062c26c Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 29 Apr 2009 11:27:45 -0400 Subject: [PATCH 436/503] Move algorithm for caching to Notice class Moved the algorithm for notice stream caching to the Notice class. --- classes/Notice.php | 55 +++++++++++++++++++++++++++++++++++++++ classes/Notice_inbox.php | 56 ++++------------------------------------ 2 files changed, 60 insertions(+), 51 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 49d0939c1a..faabb1e140 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -967,4 +967,59 @@ class Notice extends Memcached_DataObject array('notice' => $this->id)); } } + + function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + { + $cache = common_memcache(); + + if (empty($cache) || + $since_id != 0 || $before_id != 0 || !is_null($since) || + ($offset + $limit) > NOTICE_CACHE_WINDOW) { + return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id, + $before_id, $since))); + } + + $idkey = common_cache_key($cachekey); + + $idstr = $cache->get($idkey); + + if (!empty($idstr)) { + // Cache hit! Woohoo! + $window = explode(',', $idstr); + $ids = array_slice($window, $offset, $limit); + return $ids; + } + + $laststr = common_cache_key($idkey.';last'); + + if (!empty($laststr)) { + $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; + } + + $window = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, + 0, 0, null))); + + $windowstr = implode(',', $new_window); + + $result = $cache->set($idkey, $windowstr); + $result = $cache->set($idkey . ';last', $windowstr); + + $ids = array_slice($window, $offset, $limit); + + return $ids; + } } diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index f321370380..dec14b0d18 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -43,58 +43,12 @@ class Notice_inbox extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function stream($user_id, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + function stream($user_id, $offset, $limit, $since_id, $before_id, $since) { - $cache = common_memcache(); - - if (empty($cache) || - $since_id != 0 || $before_id != 0 || !is_null($since) || - ($offset + $limit) > INBOX_CACHE_WINDOW) { - return Notice_inbox::_streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since); - } - - $idkey = common_cache_key('notice_inbox:by_user:'.$user_id); - - $idstr = $cache->get($idkey); - - if (!empty($idstr)) { - // Cache hit! Woohoo! - $window = explode(',', $idstr); - $ids = array_slice($window, $offset, $limit); - return $ids; - } - - $laststr = common_cache_key($idkey.';last'); - - if (!empty($laststr)) { - $window = explode(',', $laststr); - $last_id = $window[0]; - $new_ids = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, - $last_id, null, 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; - } - - $window = Notice_inbox::_streamDirect($user_id, 0, INBOX_CACHE_WINDOW, - null, null, null); - - $windowstr = implode(',', $new_window); - - $result = $cache->set($idkey, $windowstr); - $result = $cache->set($idkey . ';last', $windowstr); - - $ids = array_slice($window, $offset, $limit); - - return $ids; + return Notice::stream(array('Notice_inbox', '_streamDirect'), + array($user_id), + 'notice_inbox:by_user:'.$user_id, + $offset, $limit, $since_id, $before_id, $since); } function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since) From a4d959b8a2254d173bdf45f418f6add9f6f62cda Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 29 Apr 2009 12:05:31 -0400 Subject: [PATCH 437/503] Public stream uses IDs method Public stream now uses IDs method --- classes/Notice.php | 55 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index faabb1e140..6a7522bd32 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -635,25 +635,58 @@ class Notice extends Memcached_DataObject function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) { + $ids = Notice::stream(array('Notice', '_publicStreamDirect'), + array(), + 'public', + $offset, $limit, $since_id, $before_id, $since); - $parts = array(); + return Notice::getStreamByIds($ids); + } - $qry = 'SELECT * FROM notice '; + function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + { + $notice = new Notice(); + + $notice->selectAdd(); // clears it + $notice->selectAdd('id'); + + $notice->orderBy('id DESC'); + + if (!is_null($offset)) { + $notice->limit($offset, $limit); + } if (common_config('public', 'localonly')) { - $parts[] = 'is_local = 1'; + $notice->whereAdd('is_local = 1'); } else { # -1 == blacklisted - $parts[] = 'is_local != -1'; + $notice->whereAdd('is_local != -1'); } - if ($parts) { - $qry .= ' WHERE ' . implode(' AND ', $parts); + if ($since_id != 0) { + $notice->whereAdd('id > ' . $since_id); } - return Notice::getStream($qry, - 'public', - $offset, $limit, $since_id, $before_id, null, $since); + if ($before_id != 0) { + $notice->whereAdd('id < ' . $before_id); + } + + if (!is_null($since)) { + $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $ids = array(); + + if ($notice->find()) { + while ($notice->fetch()) { + $ids[] = $notice->id; + } + } + + $notice->free(); + $notice = NULL; + + return $ids; } function addToInboxes() @@ -990,7 +1023,7 @@ class Notice extends Memcached_DataObject return $ids; } - $laststr = common_cache_key($idkey.';last'); + $laststr = $cache->get($idkey.';last'); if (!empty($laststr)) { $window = explode(',', $laststr); @@ -1013,7 +1046,7 @@ class Notice extends Memcached_DataObject $window = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, 0, 0, null))); - $windowstr = implode(',', $new_window); + $windowstr = implode(',', $window); $result = $cache->set($idkey, $windowstr); $result = $cache->set($idkey . ';last', $windowstr); From 1e8ea1eb460b163176c4d7d1e7dffa500024ef91 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 29 Apr 2009 16:09:03 -0400 Subject: [PATCH 438/503] Make the tag stream use ID mechanism --- classes/Notice.php | 5 +--- classes/Notice_tag.php | 59 +++++++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 6a7522bd32..2bb466155a 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -328,10 +328,7 @@ class Notice extends Memcached_DataObject $tag->notice_id = $this->id; if ($tag->find()) { while ($tag->fetch()) { - $cache->delete(common_cache_key('notice_tag:notice_stream:' . $tag->tag)); - if ($blowLast) { - $cache->delete(common_cache_key('notice_tag:notice_stream:' . $tag->tag . ';last')); - } + $tag->blowCache($blowLast); } } $tag->free(); diff --git a/classes/Notice_tag.php b/classes/Notice_tag.php index f2247299a4..e5b7722430 100644 --- a/classes/Notice_tag.php +++ b/classes/Notice_tag.php @@ -37,21 +37,62 @@ class Notice_tag extends Memcached_DataObject ###END_AUTOCODE static function getStream($tag, $offset=0, $limit=20) { - $qry = - 'SELECT notice.* ' . - 'FROM notice JOIN notice_tag ON notice.id = notice_tag.notice_id ' . - "WHERE notice_tag.tag = '%s' "; - return Notice::getStream(sprintf($qry, $tag), - 'notice_tag:notice_stream:' . common_keyize($tag), - $offset, $limit); + $ids = Notice::stream(array('Notice_tag', '_streamDirect'), + array($tag), + 'notice_tag:notice_ids:' . common_keyize($tag), + $offset, $limit); + + return Notice::getStreamByIds($ids); } - function blowCache() + function _streamDirect($tag, $offset, $limit, $since_id, $before_id, $since) + { + $nt = new Notice_tag(); + + $nt->tag = $tag; + + $nt->selectAdd(); + $nt->selectAdd('notice_id'); + + if ($since_id != 0) { + $nt->whereAdd('notice_id > ' . $since_id); + } + + if ($before_id != 0) { + $nt->whereAdd('notice_id < ' . $before_id); + } + + if (!is_null($since)) { + $nt->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $nt->orderBy('notice_id DESC'); + + if (!is_null($offset)) { + $nt->limit($offset, $limit); + } + + $ids = array(); + + if ($nt->find()) { + while ($nt->fetch()) { + $ids[] = $nt->notice_id; + } + } + + return $ids; + } + + function blowCache($blowLast=false) { $cache = common_memcache(); if ($cache) { - $cache->delete(common_cache_key('notice_tag:notice_stream:' . $this->tag)); + $idkey = common_cache_key('notice_tag:notice_ids:' . common_keyize($this->tag)); + $cache->delete($idkey); + if ($blowLast) { + $cache->delete($idkey.';last'); + } } } From 8295402fb30a3854bae3b9d6c457c7c0e432c51a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 29 Apr 2009 13:16:52 -0700 Subject: [PATCH 439/503] Added 'mentions' the the list of API methods requiring bare auth --- actions/api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/actions/api.php b/actions/api.php index d2f0a2eff0..8762b4bcd3 100644 --- a/actions/api.php +++ b/actions/api.php @@ -130,6 +130,7 @@ class ApiAction extends Action 'statuses/friends_timeline', 'statuses/friends', 'statuses/replies', + 'statuses/mentions', 'statuses/followers', 'favorites/favorites'); From b79fef307481b36b4d04dbabb54e3f6d9edf6896 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Wed, 29 Apr 2009 23:43:42 +0100 Subject: [PATCH 440/503] Fixed remote subscription, broken in fc6cedd2227d9d560736e494f431e2b40b26b45c --- actions/accesstoken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/accesstoken.php b/actions/accesstoken.php index bb68d3314d..46b43c7021 100644 --- a/actions/accesstoken.php +++ b/actions/accesstoken.php @@ -59,7 +59,7 @@ class AccesstokenAction extends Action try { common_debug('getting request from env variables', __FILE__); common_remove_magic_from_request(); - $req = OAuthRequest::from_request('POST', common_locale_url('accesstoken')); + $req = OAuthRequest::from_request('POST', common_local_url('accesstoken')); common_debug('getting a server', __FILE__); $server = omb_oauth_server(); common_debug('fetching the access token', __FILE__); From aee641ee1e311fb0af0f9f6d75ca7fae2c7d8477 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 29 Apr 2009 20:45:33 -0400 Subject: [PATCH 441/503] make replies use new query format --- classes/Notice.php | 4 ++-- classes/Reply.php | 47 ++++++++++++++++++++++++++++++++++++++++++++-- classes/User.php | 10 +++------- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 2bb466155a..808631f4dc 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -380,9 +380,9 @@ class Notice extends Memcached_DataObject $reply->notice_id = $this->id; if ($reply->find()) { while ($reply->fetch()) { - $cache->delete(common_cache_key('user:replies:'.$reply->profile_id)); + $cache->delete(common_cache_key('reply:stream:'.$reply->profile_id)); if ($blowLast) { - $cache->delete(common_cache_key('user:replies:'.$reply->profile_id.';last')); + $cache->delete(common_cache_key('reply:stream:'.$reply->profile_id.';last')); } } } diff --git a/classes/Reply.php b/classes/Reply.php index af86aaf878..4439053b44 100644 --- a/classes/Reply.php +++ b/classes/Reply.php @@ -4,7 +4,7 @@ */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -class Reply extends Memcached_DataObject +class Reply extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -13,7 +13,7 @@ class Reply extends Memcached_DataObject public $notice_id; // int(4) primary_key not_null public $profile_id; // int(4) primary_key not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP - public $replied_id; // int(4) + public $replied_id; // int(4) /* Static get */ function staticGet($k,$v=null) @@ -21,4 +21,47 @@ class Reply extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + { + $ids = Notice::stream(array('Reply', '_streamDirect'), + array($user_id), + 'reply:stream:' . $user_id, + $offset, $limit, $since_id, $before_id, $since); + return $ids; + } + + function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + { + $reply = new Reply(); + $reply->profile_id = $user_id; + + if ($since_id != 0) { + $reply->whereAdd('notice_id > ' . $since_id); + } + + if ($before_id != 0) { + $reply->whereAdd('notice_id < ' . $before_id); + } + + if (!is_null($since)) { + $reply->whereAdd('modified > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $reply->orderBy('notice_id DESC'); + + if (!is_null($offset)) { + $reply->limit($offset, $limit); + } + + $ids = array(); + + if ($reply->find()) { + while ($reply->fetch()) { + $ids[] = $reply->notice_id; + } + } + + return $ids; + } } diff --git a/classes/User.php b/classes/User.php index ce7ea1464f..b76e45c330 100644 --- a/classes/User.php +++ b/classes/User.php @@ -401,13 +401,9 @@ class User extends Memcached_DataObject function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) { - $qry = - 'SELECT notice.* ' . - 'FROM notice JOIN reply ON notice.id = reply.notice_id ' . - 'WHERE reply.profile_id = %d '; - return Notice::getStream(sprintf($qry, $this->id), - 'user:replies:'.$this->id, - $offset, $limit, $since_id, $before_id, null, $since); + $ids = Reply::stream($this->id, $offset, $limit, $since_id, $before_id, $since); + common_debug("Ids = " . implode(',', $ids)); + return Notice::getStreamByIds($ids); } function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) From fb8340fb5429e632841b0be66d63dbdc512382ca Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 1 May 2009 03:50:24 +0000 Subject: [PATCH 442/503] Added laconica logo Updated installation page markup --- install.php | 161 ++++++++++++++++++++++++----------------- theme/default/logo.png | Bin 0 -> 2228 bytes 2 files changed, 93 insertions(+), 68 deletions(-) create mode 100644 theme/default/logo.png diff --git a/install.php b/install.php index 87a99a6508..66e8e87124 100644 --- a/install.php +++ b/install.php @@ -52,23 +52,21 @@ function checkPrereqs() foreach ($reqs as $req) { if (!checkExtension($req)) { - ?>

    Cannot load required extension "".

    Cannot load required extension:

    Cannot write config file to "".

    -

    On your server, try this command:

    -
    chmod a+w
    + ?>

    Cannot write config file to:

    +

    On your server, try this command: chmod a+w

    Cannot write avatar directory "/avatar/".

    -

    On your server, try this command:

    -
    chmod a+w /avatar/
    + ?>

    Cannot write avatar directory: /avatar/

    +

    On your server, try this command: chmod a+w /avatar/

    -

    Enter your database connection information below to initialize the database.

    - -
    -
      -
    • - - -

      The name of your site

      -
    • -
    • -
    • - - -

      Database hostname

      -
    • -
    • - - -

      Database name

      -
    • -
    • - - -

      Database username

      -
    • -
    • - - -

      Database password

      -
    • -
    - -
    + + +
    +
    +
    Page notice
    +
    +
    +

    Enter your database connection information below to initialize the database.

    +
    +
    +
    + +
    + Connection settings +
      +
    • + + +

      The name of your site

      +
    • +
    • +
    • + + +

      Database hostname

      +
    • +
    • + + +

      Database name

      +
    • +
    • + + +

      Database username

      +
    • +
    • + + +

      Database password

      +
    • +
    + +
    - -
  • - -
  • -> + + -
      - +
      +
      Page notice
      +
      +
        + -
      - - - - Install Laconica - - - - - -
      -
      -
      -

      Install Laconica

      + xml version="1.0" encoding="UTF-8" "; ?> + + + + Install Laconica + + + + + + + +
      + +
      +
      +

      Install Laconica

      -
      -
      -
      - +
      +
      +
      + diff --git a/theme/default/logo.png b/theme/default/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fdead6c4a0a23614552329ee68bb0860b0200a0c GIT binary patch literal 2228 zcmV;l2ut^gP)Px-Zb?KzRCwC$ojq^VNEpZe$?*ZqCphy7Zs}5i(^0Inn@_-|NO4u-G8MZ8O6kx- zv73fA8)=)94#lL}E=EX*D+s2b$Vn(ZiAVwRa)rmo#OIgs%h+S@^OvlMyR|(pzj@}F zXI{L7mg~jrfewJbc-ic)v(Y{BK*CZ>Agq`fYCJt#f)oT$DdJ`wVR0G05yJQd$`Td8s!2tM+d0!>>du}p1(x(x!NT6qM-0u-F6nzq(bB_Q6AF(Dw@E|-AFFPnfMAb2?~ z1mbnm60FolofoqQ$7o=5@8R{j0b#*E>!BGS z{C$D%FF)bOpQm}dlaUEb2#9zfIslHFU=hB*{DdC|pUd(y)=foxDCPEczL-7u2!+Gg z*C$_b@$?<8PcO=T^sWh*Wj$m8 zFlDINO?-R)p{mz)tPB=%XEyHu_=xN~T zWga5`9#|c~ArFO$Kq$3*{l~#)84jd~EGwa+SvOGxhCmvCefB)%HtHw^Ll9@ENr7Jw z3k=HJ9UnNO%2^1dx{L4S#2E@%%P1?sMiYaQ-?g0;m3L8#unXE&!uHGuMfXj&K^QF8?B_NdYAFfZ%l}U@mL9sKN z8#3Re1Q2Ygx^g27g;d#6epM`l0mW2P>>*BkG|^iGAlh^cfK+XFS7a`%@tSTS900rU zCxceu&*UwFTuINh?%GVG7^?fSvY58}<#03A+M^wG;C$H@L#jwfss@#kb-8hQ|`$F;xMGUQFU_2Enw* zhf3JJHfI5{v`Qs_2$t7L3RwplZFg6^T7lp`r}!VC01h^~M=JONuc5|*Umjvv=U>{} z-IZMcsM|v5%qiScZ4aagOf4VMy8Va)$=1OEuonEIRv;JzDsRx4qW*7nOe9)|DS&l; z8QmR_68qJfftZ+p#}=>jxfboQE-l#n;UuKBLP0dTP0U5WM42#9nbH2AB)^@?9@n!bNksR#%$D5~BXFfoDk zI`T^ALx_zy98_094ocj?l~un`b&Kf_z)2KV*M30)o_PD$BXxRhYj=>C5TD=i*6;+U*Gp-vNLu?-iZ?VpDlx1NHu@&)q{@PC|&<>aJ zsOvc4ek}w-)HP1Hpa0#EL7g=XQNJ&uaY}v$1#55CLKjSY64_RP`;Cn6Hv}s)sUT$np=C%*R0BE8aQ}Xm zgo*kPaebwY=tUsC7^=exb}pv{fui2;!QcDnWk_#S`X@0JCR3f5{MdrOH8PZCUj`6S zW@iNd*J?G=n+;rtKVg)2KZDDqUxn%D^@#FxA$AN>P?q;maMxFn z^C4`G>^$P{yI1`i2s(B zKS#EO2&j%D)4!&{hGnuqSC7k= z6O*4+);&HB+mlT1n~2B8iM`+0000 Date: Fri, 1 May 2009 04:39:49 +0000 Subject: [PATCH 443/503] Giving more contrast between the background colour and the laconica logo. --- theme/default/css/display.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 0c8fae166f..1fc99eff7d 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -12,7 +12,7 @@ html, body, a:active { -background-color:#97BFD1; +background-color:#C3D6DF; } body { font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; @@ -30,7 +30,7 @@ input, textarea, select, border-color:#aaa; } #filter_tags ul li { -border-color:#97BFD1; +border-color:#C3D6DF; } .form_settings input.form_action-secondary { @@ -69,7 +69,7 @@ color:#002E6E; border-top-color:#D1D9E4; } .section .profile { -border-top-color:#97BFD1; +border-top-color:#C3D6DF; } #content .notice p.entry-content a:visited { @@ -120,7 +120,7 @@ background-color:#EFF3DC; } #anon_notice { -background-color:#97BFD1; +background-color:#C3D6DF; color:#fff; border-color:#fff; } @@ -163,7 +163,7 @@ color:#fff; .form_user_unsubscribe input.submit, .form_group_leave input.submit, .form_user_authorization input.reject { -background-color:#97BFD1; +background-color:#C3D6DF; } .entity_edit a { From 8a142b272c87678268106df48497b90664be323a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 07:08:01 -0400 Subject: [PATCH 444/503] ignore Eclipse project files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 83a53dfa3f..da6947bfdc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ dataobject.ini *.rej .#* *.swp +.buildpath +.project +.settings From 9cac6413a342445a998773458b215d129c2be2d1 Mon Sep 17 00:00:00 2001 From: Ori Avtalion Date: Fri, 1 May 2009 07:11:28 -0400 Subject: [PATCH 445/503] Add s to user favorite notices --- actions/favoritesrss.php | 2 +- actions/showfavorites.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actions/favoritesrss.php b/actions/favoritesrss.php index f85bf1b190..6b46b8dec7 100644 --- a/actions/favoritesrss.php +++ b/actions/favoritesrss.php @@ -107,7 +107,7 @@ class FavoritesrssAction extends Rss10Action $c = array('url' => common_local_url('favoritesrss', array('nickname' => $user->nickname)), - 'title' => sprintf(_("%s favorite notices"), $user->nickname), + 'title' => sprintf(_("%s's favorite notices"), $user->nickname), 'link' => common_local_url('showfavorites', array('nickname' => $user->nickname)), diff --git a/actions/showfavorites.php b/actions/showfavorites.php index 6e011d5ca5..eed62a2ab3 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -74,9 +74,9 @@ class ShowfavoritesAction extends Action function title() { if ($this->page == 1) { - return sprintf(_("%s favorite notices"), $this->user->nickname); + return sprintf(_("%s's favorite notices"), $this->user->nickname); } else { - return sprintf(_("%s favorite notices, page %d"), + return sprintf(_("%s's favorite notices, page %d"), $this->user->nickname, $this->page); } From c5e72e248fa70b5e038c74b73b581884112706d5 Mon Sep 17 00:00:00 2001 From: Ori Avtalion Date: Fri, 1 May 2009 07:12:13 -0400 Subject: [PATCH 446/503] Several whitespace fixes --- actions/openidsettings.php | 4 ++-- actions/recoverpassword.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/openidsettings.php b/actions/openidsettings.php index 92469d20f8..5f59ebc014 100644 --- a/actions/openidsettings.php +++ b/actions/openidsettings.php @@ -67,8 +67,8 @@ class OpenidsettingsAction extends AccountSettingsAction function getInstructions() { - return _('[OpenID](%%doc.openid%%) lets you log into many sites ' . - ' with the same user account. '. + return _('[OpenID](%%doc.openid%%) lets you log into many sites' . + ' with the same user account.'. ' Manage your associated OpenIDs from here.'); } diff --git a/actions/recoverpassword.php b/actions/recoverpassword.php index 620fe7eb8e..82263fcd59 100644 --- a/actions/recoverpassword.php +++ b/actions/recoverpassword.php @@ -151,11 +151,11 @@ class RecoverpasswordAction extends Action $this->element('p', null, _('If you\'ve forgotten or lost your' . ' password, you can get a new one sent to' . - ' the email address you have stored ' . + ' the email address you have stored' . ' in your account.')); } else if ($this->mode == 'reset') { $this->element('p', null, - _('You\'ve been identified. Enter a ' . + _('You\'ve been identified. Enter a' . ' new password below. ')); } $this->elementEnd('div'); From 609ac4c22463af88c206968134ab16e75e500edd Mon Sep 17 00:00:00 2001 From: Ori Avtalion Date: Fri, 1 May 2009 07:12:37 -0400 Subject: [PATCH 447/503] Fix link to identi.ca in JavaScript badge --- js/identica-badge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/identica-badge.js b/js/identica-badge.js index 869230b7a4..ffa55ae93e 100644 --- a/js/identica-badge.js +++ b/js/identica-badge.js @@ -128,7 +128,7 @@ var a = document.createElement('A'); a.innerHTML = 'get this'; a.target = '_blank'; - a.href = 'http://identica/doc/badge'; + a.href = 'http://identi.ca/doc/badge'; $.s.f.appendChild(a); $.s.appendChild($.s.f); $.f.getUser(); From a86a0e91a5acb5ea894a3d066f9adf3b1ef305ae Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 08:00:37 -0700 Subject: [PATCH 448/503] add favor, reply, delete buttons for cometed notices --- plugins/Comet/CometPlugin.php | 16 ++++++- plugins/Comet/updatetimeline.js | 74 +++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index 2e0bb40a46..48ac9dcad6 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -82,8 +82,22 @@ class CometPlugin extends Plugin ' '); } + $user = common_current_user(); + + if (!empty($user->id)) { + $user_id = $user->id; + } else { + $user_id = 0; + } + + $replyurl = common_local_url('newnotice'); + $favorurl = common_local_url('favor'); + // FIXME: need to find a better way to pass this pattern in + $deleteurl = common_local_url('deletenotice', + array('notice' => '0000000000')); + $action->elementStart('script', array('type' => 'text/javascript')); - $action->raw("$(document).ready(function() { updater.init(\"$this->server\", \"$timeline\");});"); + $action->raw("$(document).ready(function() { updater.init(\"$this->server\", \"$timeline\", $user_id, \"$replyurl\", \"$favorurl\", \"$deleteurl\"); });"); $action->elementEnd('script'); return true; diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js index de750baba3..e89b3bddf7 100644 --- a/plugins/Comet/updatetimeline.js +++ b/plugins/Comet/updatetimeline.js @@ -3,14 +3,26 @@ var updater = function() { + var _server; + var _timeline; + var _userid; + var _replyurl; + var _favorurl; + var _deleteurl; var _cometd; return { - init: function(server, timeline) + init: function(server, timeline, userid, replyurl, favorurl, deleteurl) { _cometd = $.cometd; // Uses the default Comet object _cometd.setLogLevel('debug'); _cometd.init(server); + _server = server; + _timeline = timeline; + _userid = userid; + _favorurl = favorurl; + _replyurl = replyurl; + _deleteurl = deleteurl; _cometd.subscribe(timeline, receive); $(window).unload(leave); } @@ -34,7 +46,7 @@ var updater = function() var noticeItem = makeNoticeItem(message.data); $("#notices_primary .notices").prepend(noticeItem, true); $("#notices_primary .notice:first").css({display:"none"}); - $("#notices_primary .notice:first").fadeIn(2500); + $("#notices_primary .notice:first").fadeIn(1000); NoticeHover(); NoticeReply(); } @@ -68,10 +80,64 @@ var updater = function() "
      "+data['source']+"
      "+ "
      "+ ""+ - "
      "+ - "
      "+ + "
      "; + + if (_userid != 0) { + var input = $("form#form_notice fieldset input#token"); + var session_key = input.val(); + ni = ni+makeFavoriteForm(data['id'], session_key); + ni = ni+makeReplyLink(data['id'], data['user']['screen_name']); + if (_userid == data['user']['id']) { + ni = ni+makeDeleteLink(data['id']); + } + } + + ni = ni+"
      "+ ""; return ni; } + + function makeFavoriteForm(id, session_key) + { + var ff; + + ff = "
      "+ + "
      "+ + "Favor this notice"+ // XXX: i18n + ""+ + ""+ + ""+ + "
      "+ + "
      "; + return ff; + } + + function makeReplyLink(id, nickname) + { + var rl; + rl = "
      "+ + "
      Reply to this notice
      "+ + "
      "+ + "Reply "+id+""+ + ""+ + "
      "+ + "
      "; + return rl; + } + + function makeDeleteLink(id) + { + var dl, delurl; + delurl = _deleteurl.replace("0000000000", id); + + dl = "
      "+ + "
      Delete this notice
      "+ + "
      "+ + "Delete"+ + "
      "+ + "
      "; + + return dl; + } }(); From 5affe093aba97a0e4ac559b685a240d568929ffb Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 08:39:47 -0700 Subject: [PATCH 449/503] add in_reply_to link and make HTML in source work correctly --- plugins/Comet/CometPlugin.php | 9 +++++++++ plugins/Comet/updatetimeline.js | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index 48ac9dcad6..0f2fcd701d 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -158,6 +158,15 @@ class CometPlugin extends Plugin $arr = $act->twitter_status_array($notice, true); $arr['url'] = $notice->bestUrl(); $arr['html'] = htmlspecialchars($notice->rendered); + $arr['source'] = htmlspecialchars($arr['source']); + + if (!empty($notice->reply_to)) { + $reply_to = Notice::staticGet('id', $notice->reply_to); + if (!empty($reply_to)) { + $arr['in_reply_to_status_url'] = $reply_to->bestUrl(); + } + $reply_to = null; + } $profile = $notice->getProfile(); $arr['user']['profile_url'] = $profile->profileurl; diff --git a/plugins/Comet/updatetimeline.js b/plugins/Comet/updatetimeline.js index e89b3bddf7..170949e9ba 100644 --- a/plugins/Comet/updatetimeline.js +++ b/plugins/Comet/updatetimeline.js @@ -54,7 +54,8 @@ var updater = function() function makeNoticeItem(data) { user = data['user']; - html = data['html'].replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + html = data['html'].replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); + source = data['source'].replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); ni = "
    • "+ "
      "+ @@ -77,9 +78,19 @@ var updater = function() ""+ "
      "+ "
      From
      "+ - "
      "+data['source']+"
      "+ - "
      "+ - "
      "+ + "
      "+source+"
      "+ // may have a link, I think + ""; + + if (data['in_reply_to_status_id']) { + ni = ni+"
      "+ + "
      To
      "+ + "
      "+ + "in reply to"+ + "
      "+ + "
      "; + } + + ni = ni+""+ "
      "; if (_userid != 0) { From b12e72ae312488caf7cb1e1a396eb05dd38326a9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 09:42:38 -0700 Subject: [PATCH 450/503] optionally add a username/password on server side for Comet --- plugins/Comet/CometPlugin.php | 8 +++++--- plugins/Comet/bayeux.class.inc.php | 9 ++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/Comet/CometPlugin.php b/plugins/Comet/CometPlugin.php index 0f2fcd701d..45251c66f0 100644 --- a/plugins/Comet/CometPlugin.php +++ b/plugins/Comet/CometPlugin.php @@ -45,9 +45,11 @@ class CometPlugin extends Plugin { var $server = null; - function __construct($server=null) + function __construct($server=null, $username=null, $password=null) { - $this->server = $server; + $this->server = $server; + $this->username = $username; + $this->password = $password; parent::__construct(); } @@ -131,7 +133,7 @@ class CometPlugin extends Plugin $json = $this->noticeAsJson($notice); // Bayeux? Comet? Huh? These terms confuse me - $bay = new Bayeux($this->server); + $bay = new Bayeux($this->server, $this->user, $this->password); foreach ($timelines as $timeline) { $this->log(LOG_INFO, "Posting notice $notice->id to '$timeline'."); diff --git a/plugins/Comet/bayeux.class.inc.php b/plugins/Comet/bayeux.class.inc.php index 785d3e3935..39ad8a8fc6 100644 --- a/plugins/Comet/bayeux.class.inc.php +++ b/plugins/Comet/bayeux.class.inc.php @@ -26,9 +26,12 @@ class Bayeux private $oCurl = ''; private $nNextId = 0; + private $sUser = ''; + private $sPassword = ''; + public $sUrl = ''; - function __construct($sUrl) + function __construct($sUrl, $sUser='', $sPassword='') { $this->sUrl = $sUrl; @@ -43,6 +46,10 @@ class Bayeux curl_setopt($this->oCurl, CURLOPT_POST, 1); curl_setopt($this->oCurl, CURLOPT_RETURNTRANSFER,1); + if (!is_null($sUser) && mb_strlen($sUser) > 0) { + curl_setopt($this->oCurl, CURLOPT_USERPWD,"$sUser:$sPassword"); + } + $this->handShake(); } From deb07487bd0802fa6a89cfc8ddd56af93945eb4c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 1 May 2009 17:00:36 +0000 Subject: [PATCH 451/503] 60 seconds hard timeout for XHR notice posting. JavaScript throws an alert message to the client if the server doesn't respond back in any way. --- js/util.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/js/util.js b/js/util.js index f15c4f2bbf..3f14bc61c6 100644 --- a/js/util.js +++ b/js/util.js @@ -166,14 +166,20 @@ $(document).ready(function(){ $("#notice_action-submit").addClass("disabled"); return true; }, + timeout: '60000', error: function (xhr, textStatus, errorThrown) { $("#form_notice").removeClass("processing"); $("#notice_action-submit").removeAttr("disabled"); $("#notice_action-submit").removeClass("disabled"); - if ($(".error", xhr.responseXML).length > 0) { - $('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true)); + if (textStatus == "timeout") { + alert ("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists"); } else { - alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again."); + if ($(".error", xhr.responseXML).length > 0) { + $('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true)); + } + else { + alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again."); + } } }, success: function(xml) { if ($("#error", xml).length > 0) { @@ -189,7 +195,6 @@ $(document).ready(function(){ } else { li = $("li", xml).get(0); - id = li.id; if ($("#"+li.id).length == 0) { $("#notices_primary .notices").prepend(document._importNode(li, true)); $("#notices_primary .notice:first").css({display:"none"}); From 3328ec545c36fc2408cdb9d048effe24feafe218 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 11:27:57 -0700 Subject: [PATCH 452/503] make profile notice getting use ids --- classes/Notice.php | 6 +++--- classes/Profile.php | 51 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 808631f4dc..eceed325b0 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -363,10 +363,10 @@ class Notice extends Memcached_DataObject { if ($this->is_local) { $cache = common_memcache(); - if ($cache) { - $cache->delete(common_cache_key('profile:notices:'.$this->profile_id)); + if (!empty($cache)) { + $cache->delete(common_cache_key('profile:notice_ids:'.$this->profile_id)); if ($blowLast) { - $cache->delete(common_cache_key('profile:notices:'.$this->profile_id.';last')); + $cache->delete(common_cache_key('profile:notice_ids:'.$this->profile_id.';last')); } } } diff --git a/classes/Profile.php b/classes/Profile.php index f3bfe299cf..ae5641d79d 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -155,14 +155,51 @@ class Profile extends Memcached_DataObject function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) { - $qry = - 'SELECT * ' . - 'FROM notice ' . - 'WHERE profile_id = %d '; + // XXX: I'm not sure this is going to be any faster. It probably isn't. + $ids = Notice::stream(array($this, '_streamDirect'), + array(), + 'profile:notice_ids:' . $this->id, + $offset, $limit, $since_id, $before_id); - return Notice::getStream(sprintf($qry, $this->id), - 'profile:notices:'.$this->id, - $offset, $limit, $since_id, $before_id); + return Notice::getStreamByIds($ids); + } + + function _streamDirect($offset, $limit, $since_id, $before_id, $since) + { + $notice = new Notice(); + + $notice->profile_id = $this->id; + + $notice->selectAdd(); + $notice->selectAdd('id'); + + if ($since_id != 0) { + $notice->whereAdd('id > ' . $since_id); + } + + if ($before_id != 0) { + $notice->whereAdd('id < ' . $before_id); + } + + if (!is_null($since)) { + $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $notice->orderBy('id DESC'); + + if (!is_null($offset)) { + $notice->limit($offset, $limit); + } + + $ids = array(); + + if ($notice->find()) { + while ($notice->fetch()) { + $ids[] = $notice->id; + } + } + + return $ids; } function isMember($group) From 021b520a11d3449a1476182e1ad117582999d364 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 11:38:50 -0700 Subject: [PATCH 453/503] Make user group stream use IDs --- classes/Notice.php | 4 ++-- classes/User_group.php | 53 +++++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index eceed325b0..c036e6e9e5 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -299,9 +299,9 @@ class Notice extends Memcached_DataObject $group_inbox->notice_id = $this->id; if ($group_inbox->find()) { while ($group_inbox->fetch()) { - $cache->delete(common_cache_key('group:notices:'.$group_inbox->group_id)); + $cache->delete(common_cache_key('user_group:notice_ids:' . $group_inbox->group_id)); if ($blowLast) { - $cache->delete(common_cache_key('group:notices:'.$group_inbox->group_id.';last')); + $cache->delete(common_cache_key('user_group:notice_ids:' . $group_inbox->group_id.';last')); } $member = new Group_member(); $member->group_id = $group_inbox->group_id; diff --git a/classes/User_group.php b/classes/User_group.php index d152f9d567..7cc31e7026 100755 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -50,13 +50,50 @@ class User_group extends Memcached_DataObject function getNotices($offset, $limit) { - $qry = - 'SELECT notice.* ' . - 'FROM notice JOIN group_inbox ON notice.id = group_inbox.notice_id ' . - 'WHERE group_inbox.group_id = %d '; - return Notice::getStream(sprintf($qry, $this->id), - 'group:notices:'.$this->id, - $offset, $limit); + $ids = Notice::stream(array($this, '_streamDirect'), + array(), + 'user_group:notice_ids:' . $this->id, + $offset, $limit); + + return Notice::getStreamByIds($ids); + } + + function _streamDirect($offset, $limit, $since_id, $before_id, $since) + { + $inbox = new Group_inbox(); + + $inbox->group_id = $this->id; + + $inbox->selectAdd(); + $inbox->selectAdd('notice_id'); + + if ($since_id != 0) { + $inbox->whereAdd('notice_id > ' . $since_id); + } + + if ($before_id != 0) { + $inbox->whereAdd('notice_id < ' . $before_id); + } + + if (!is_null($since)) { + $inbox->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + $inbox->orderBy('notice_id DESC'); + + if (!is_null($offset)) { + $inbox->limit($offset, $limit); + } + + $ids = array(); + + if ($inbox->find()) { + while ($inbox->fetch()) { + $ids[] = $inbox->notice_id; + } + } + + return $ids; } function allowedNickname($nickname) @@ -91,7 +128,7 @@ class User_group extends Memcached_DataObject function setOriginal($filename) { $imagefile = new ImageFile($this->id, Avatar::path($filename)); - + $orig = clone($this); $this->original_logo = Avatar::url($filename); $this->homepage_logo = Avatar::url($imagefile->resize(AVATAR_PROFILE_SIZE)); From 5314d9b2cfaef3f2fd0ead262e18d1776fd99c8d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 1 May 2009 12:01:28 -0700 Subject: [PATCH 454/503] make faves work with ids --- classes/Fave.php | 53 ++++++++++++++++++++++++++++++++++++++++++++-- classes/Notice.php | 4 ++-- classes/User.php | 38 +++++++++++++++------------------ 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/classes/Fave.php b/classes/Fave.php index 24df5938c2..915b4572ff 100644 --- a/classes/Fave.php +++ b/classes/Fave.php @@ -4,7 +4,7 @@ */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -class Fave extends Memcached_DataObject +class Fave extends Memcached_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -31,9 +31,58 @@ class Fave extends Memcached_DataObject } return $fave; } - + function &pkeyGet($kv) { return Memcached_DataObject::pkeyGet('Fave', $kv); } + + function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE) + { + $ids = Notice::stream(array('Fave', '_streamDirect'), + array($user_id), + 'fave:ids_by_user:'.$user_id, + $offset, $limit); + return $ids; + } + + function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since) + { + $fav = new Fave(); + + $fav->user_id = $user_id; + + $fav->selectAdd(); + $fav->selectAdd('notice_id'); + + if ($since_id != 0) { + $fav->whereAdd('notice_id > ' . $since_id); + } + + if ($before_id != 0) { + $fav->whereAdd('notice_id < ' . $before_id); + } + + if (!is_null($since)) { + $fav->whereAdd('modified > \'' . date('Y-m-d H:i:s', $since) . '\''); + } + + // NOTE: we sort by fave time, not by notice time! + + $fav->orderBy('modified DESC'); + + if (!is_null($offset)) { + $fav->limit($offset, $limit); + } + + $ids = array(); + + if ($fav->find()) { + while ($fav->fetch()) { + $ids[] = $fav->notice_id; + } + } + + return $ids; + } } diff --git a/classes/Notice.php b/classes/Notice.php index c036e6e9e5..771a4e715f 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -412,9 +412,9 @@ class Notice extends Memcached_DataObject $fave->notice_id = $this->id; if ($fave->find()) { while ($fave->fetch()) { - $cache->delete(common_cache_key('user:faves:'.$fave->user_id)); + $cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id)); if ($blowLast) { - $cache->delete(common_cache_key('user:faves:'.$fave->user_id.';last')); + $cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id.';last')); } } } diff --git a/classes/User.php b/classes/User.php index b76e45c330..b5ac7b2206 100644 --- a/classes/User.php +++ b/classes/User.php @@ -349,30 +349,31 @@ class User extends Memcached_DataObject $cache = common_memcache(); // XXX: Kind of a hack. + if ($cache) { // This is the stream of favorite notices, in rev chron // order. This forces it into cache. - $faves = $this->favoriteNotices(0, NOTICE_CACHE_WINDOW); - $cnt = 0; - while ($faves->fetch()) { - if ($faves->id < $notice->id) { - // If we passed it, it's not a fave - return false; - } else if ($faves->id == $notice->id) { - // If it matches a cached notice, then it's a fave - return true; - } - $cnt++; + + $ids = Fave::stream($this->id, 0, NOTICE_CACHE_WINDOW); + + // If it's in the list, then it's a fave + + if (in_array($notice->id, $ids)) { + return true; } + // If we're not past the end of the cache window, // then the cache has all available faves, so this one // is not a fave. - if ($cnt < NOTICE_CACHE_WINDOW) { + + if (count($ids) < NOTICE_CACHE_WINDOW) { return false; } + // Otherwise, cache doesn't have all faves; // fall through to the default } + $fave = Fave::pkeyGet(array('user_id' => $this->id, 'notice_id' => $notice->id)); return ((is_null($fave)) ? false : true); @@ -418,13 +419,8 @@ class User extends Memcached_DataObject function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE) { - $qry = - 'SELECT notice.* ' . - 'FROM notice JOIN fave ON notice.id = fave.notice_id ' . - 'WHERE fave.user_id = %d '; - return Notice::getStream(sprintf($qry, $this->id), - 'user:faves:'.$this->id, - $offset, $limit); + $ids = Fave::stream($this->id, $offset, $limit); + return Notice::getStreamByIds($ids); } function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) @@ -459,8 +455,8 @@ class User extends Memcached_DataObject if ($cache) { // Faves don't happen chronologically, so we need to blow // ;last cache, too - $cache->delete(common_cache_key('user:faves:'.$this->id)); - $cache->delete(common_cache_key('user:faves:'.$this->id).';last'); + $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id)); + $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id.';last')); } } From 1fde80cf73c3cf43e3613f7f57fe213df688a1ec Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 1 May 2009 23:32:59 +0000 Subject: [PATCH 455/503] Minor CSS updates (No min-height on shownotice page, site_notice is floated instead of positioned absolutely, notice entry-content is aligned with the nickname on shownotice page) --- theme/base/css/display.css | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index efa5f4ac69..c242977a9f 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -248,10 +248,10 @@ display:none; } #site_notice { -position:absolute; -top:65px; -right:18px; -width:250px; +float:right; +clear:right; +margin-top:7px; +margin-right:18px; width:24%; } #page_notice { @@ -397,6 +397,9 @@ border-radius:7px; border-style:solid; border-width:1px; } +#shownotice #content { +min-height:0; +} #content_inner { position:relative; @@ -812,11 +815,14 @@ clear:left; float:left; font-size:0.95em; margin-left:59px; -width:70%; +width:65%; } #showstream .notice div.entry-content { margin-left:0; } +#shownotice .notice div.entry-content { +margin-left:108px; +} .notice .notice-options a, .notice .notice-options input { From 51377258a1660fee02a3f92436dc40ee40f2a88d Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sat, 2 May 2009 00:10:50 +0000 Subject: [PATCH 456/503] Aligned shownotice page's entry-content to left. Fixing vcard photo margin bottom value. --- theme/base/css/display.css | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index c242977a9f..10fc636385 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -769,16 +769,14 @@ overflow:hidden; font-weight:bold; } -.notice .author .photo { -margin-bottom:0; -} - .vcard .photo { display:inline; margin-right:11px; -margin-bottom:11px; float:left; } +#shownotice .vcard .photo { +margin-bottom:4px; +} .vcard .url { text-decoration:none; } @@ -817,11 +815,9 @@ font-size:0.95em; margin-left:59px; width:65%; } -#showstream .notice div.entry-content { -margin-left:0; -} +#showstream .notice div.entry-content, #shownotice .notice div.entry-content { -margin-left:108px; +margin-left:0; } .notice .notice-options a, From 6a12598695637e7ebdc613977c797413957cc464 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 3 May 2009 21:36:03 -0700 Subject: [PATCH 457/503] add pingvine notice source --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index ce44f32354..17720028dc 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -24,6 +24,7 @@ VALUES ('peoplebrowsr', 'PeopleBrowsr', 'http://www.peoplebrowsr.com/', now()), ('Pikchur','Pikchur','http://www.pikchur.com/', now()), ('Ping.fm','Ping.fm','http://ping.fm/', now()), + ('pingvine','PingVine','http://pingvine.com/', now()), ('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()), ('posty','Posty','http://spreadingfunkyness.com/posty/', now()), ('royalewithcheese','Royale With Cheese','http://p.hellyeah.org/', now()), From 7f417cfee023b372a281f5e45a7593c09e279233 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 5 May 2009 19:28:57 +0000 Subject: [PATCH 458/503] More work on 2-way Twitter sync. Works better now with lastest version of DB_DataObject that automatically reconnects to the DB, but forked processes still lose connections occassionally. --- scripts/statusfetcher.php | 135 +++++++++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 39 deletions(-) diff --git a/scripts/statusfetcher.php b/scripts/statusfetcher.php index 8f4b60cf74..8c3ee4330c 100644 --- a/scripts/statusfetcher.php +++ b/scripts/statusfetcher.php @@ -27,41 +27,20 @@ if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); +// Tune number of processes and how often to poll Twitter +define('MAXCHILDREN', 5); +define('POLL_INTERVAL', 60 * 5); // in seconds + // Uncomment this to get useful console output define('SCRIPT_DEBUG', true); require_once(INSTALLDIR . '/lib/common.php'); $children = array(); -$flink_ids = null; - -$MAXCHILDREN = 5; -$POLL_INTERVAL = 10; // 10 seconds do { - $flink = new Foreign_link(); - $flink->service = 1; // Twitter - $cnt = $flink->find(); - - if (defined('SCRIPT_DEBUG')) { - print "Updating Twitter friends subscriptions for $cnt users.\n"; - } - - $flink_ids = array(); - - // XXX: This only reliably happens once. After the first interation of - // the do loop, the ->find() doesn't work ... lost DB connection? - - while ($flink->fetch()) { - - if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { - $flink_ids[] = $flink->foreign_id; - } - } - - $flink->free(); - unset($flink); + $flink_ids = refreshFlinks(); foreach ($flink_ids as $f){ @@ -82,7 +61,6 @@ do { // Child // XXX: Each child needs its own DB connection - getTimeline($f); exit(); } @@ -96,11 +74,11 @@ do { } // Wait if we have too many kids - if(sizeof($children) > $MAXCHILDREN) { + if(sizeof($children) > MAXCHILDREN) { if (defined('SCRIPT_DEBUG')) { print "Too many children. Waiting...\n"; } - if( ($c = pcntl_wait($status, WUNTRACED) ) > 0){ + if(($c = pcntl_wait($status, WUNTRACED)) > 0){ if (defined('SCRIPT_DEBUG')) { print "Finished waiting for $c\n"; } @@ -119,14 +97,44 @@ do { // Rest for a bit before we fetch more statuses if (defined('SCRIPT_DEBUG')) { - print "Waiting $POLL_INTERVAL secs before hitting Twitter again.\n"; + print 'Waiting ' . POLL_INTERVAL . + " secs before hitting Twitter again.\n"; } - sleep($POLL_INTERVAL); + sleep(POLL_INTERVAL); } while (true); +function refreshFlinks() { + + global $config; + + $flink = new Foreign_link(); + $flink->service = 1; // Twitter + $flink->orderBy('last_noticesync'); + + $cnt = $flink->find(); + + if (defined('SCRIPT_DEBUG')) { + print "Updating Twitter friends subscriptions for $cnt users.\n"; + } + + $flinks = array(); + + while ($flink->fetch()) { + + if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { + $flinks[] = clone($flink); + } + } + + $flink->free(); + unset($flink); + + return $flinks; +} + function remove_ps(&$plist, $ps){ for($i = 0; $i < sizeof($plist); $i++){ if($plist[$i] == $ps){ @@ -137,22 +145,43 @@ function remove_ps(&$plist, $ps){ } } -function getTimeline($fid) +function getTimeline($flink) { - // XXX: Need to reconnect to the DB here? + global $config; + $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); + require_once(INSTALLDIR . '/lib/common.php'); - $flink = Foreign_link::getByForeignID($fid, 1); - $fuser = $flink->getForeignUser(); + if (defined('SCRIPT_DEBUG')) { + print "Trying to get timeline for $flink->foreign_id\n"; + } + + if (empty($flink)) { + common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); + if (defined('SCRIPT_DEBUG')) { + print "Can't retrieve Foreign_link for foreign ID $fid\n"; + } + return; + } + + $fuser = new Foreign_user(); + $fuser->service = 1; + $fuser->id = $flink->foreign_id; + $fuser->limit(1); + $fuser->find(true); if (empty($fuser)) { common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); if (defined('SCRIPT_DEBUG')) { print "Unmatched user for ID $flink->user_id\n"; } + return; } - $screenname = $fuser->nickname; + if (defined('SCRIPT_DEBUG')) { + // XXX: This is horrible and must be removed before releasing this + print 'username: ' . $fuser->nickname . ' password: ' . $flink->credentials . "\n"; + } $url = 'http://twitter.com/statuses/friends_timeline.json'; @@ -181,10 +210,19 @@ function getTimeline($fid) saveStatus($status, $flink); } + // Okay, record the time we synced with Twitter for posterity + + $flink->last_noticesync = common_sql_now(); + $flink->update(); } function saveStatus($status, $flink) { + + global $config; + $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); + require_once(INSTALLDIR . '/lib/common.php'); + // Do we have a profile for this Twitter user? $id = ensureProfile($status->user); @@ -244,6 +282,9 @@ function saveStatus($status, $flink) $notice->query('COMMIT'); + if (defined('SCRIPT_DEBUG')) { + print "Saved status $status->id as notice $notice->id.\n"; + } } if (!Notice_inbox::staticGet('notice_id', $notice->id)) { @@ -260,6 +301,7 @@ function saveStatus($status, $flink) function ensureProfile($user) { + global $config; // check to see if there's already a profile for this user $profileurl = 'http://twitter.com/' . $user->screen_name; @@ -328,8 +370,6 @@ function ensureProfile($user) } $profile->query("COMMIT"); - $profile->free(); - unset($profile); saveAvatars($user, $id); @@ -339,6 +379,8 @@ function ensureProfile($user) function checkAvatar($user, $profile) { + global $config; + $path_parts = pathinfo($user->profile_image_url); $newname = 'Twitter_' . $user->id . '_' . $path_parts['basename']; @@ -393,6 +435,8 @@ function getMediatype($ext) function saveAvatars($user, $id) { + global $config; + $path_parts = pathinfo($user->profile_image_url); $ext = $path_parts['extension']; $end = strlen('_normal' . $ext); @@ -418,7 +462,12 @@ function saveAvatars($user, $id) function updateAvatar($profile_id, $size, $mediatype, $filename) { - common_debug("updating avatar: $size"); + global $config; + + common_debug("Updating avatar: $size"); + if (defined('SCRIPT_DEBUG')) { + print "Updating avatar: $size\n"; + } $profile = Profile::staticGet($profile_id); @@ -444,6 +493,8 @@ function updateAvatar($profile_id, $size, $mediatype, $filename) { function newAvatar($profile_id, $size, $mediatype, $filename) { + global $config; + $avatar = new Avatar(); $avatar->profile_id = $profile_id; @@ -471,6 +522,9 @@ function newAvatar($profile_id, $size, $mediatype, $filename) $avatar->url = Avatar::url($filename); common_debug("new filename: $avatar->url"); + if (defined('SCRIPT_DEBUG')) { + print "New filename: $avatar->url\n"; + } $avatar->created = common_sql_now(); @@ -486,6 +540,9 @@ function newAvatar($profile_id, $size, $mediatype, $filename) } common_debug("Saved new $size avatar for $profile_id."); + if (defined('SCRIPT_DEBUG')) { + print "Saved new $size avatar for $profile_id.\n"; + } return $id; } From 99e8f3235f2718f46cc95966ae39e725ee31a7df Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 6 May 2009 01:12:26 +0000 Subject: [PATCH 459/503] This finally works (provided the newer version of DB_DataObject that auto-reconnects to the DB). --- scripts/statusfetcher.php | 87 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/scripts/statusfetcher.php b/scripts/statusfetcher.php index 8c3ee4330c..82ae5bfd43 100644 --- a/scripts/statusfetcher.php +++ b/scripts/statusfetcher.php @@ -29,7 +29,11 @@ define('LACONICA', true); // Tune number of processes and how often to poll Twitter define('MAXCHILDREN', 5); +<<<<<<< HEAD:scripts/statusfetcher.php +define('POLL_INTERVAL', 60 * 10); // in seconds +======= define('POLL_INTERVAL', 60 * 5); // in seconds +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php // Uncomment this to get useful console output define('SCRIPT_DEBUG', true); @@ -40,9 +44,20 @@ $children = array(); do { - $flink_ids = refreshFlinks(); +<<<<<<< HEAD:scripts/statusfetcher.php + $flinks = refreshFlinks(); - foreach ($flink_ids as $f){ + foreach ($flinks as $f){ + + // We have to disconnect from the DB before forking so + // each process will open its own connection and + // avoid stomping on each other +======= + $flink_ids = refreshFlinks(); +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php + + $conn = &$f->getDatabaseConnection(); + $conn->disconnect(); $pid = pcntl_fork(); @@ -50,38 +65,60 @@ do { die ("Couldn't fork!"); } - // Parent if ($pid) { + + // Parent + if (defined('SCRIPT_DEBUG')) { print "Parent: forked " . $pid . "\n"; } + $children[] = $pid; + } else { // Child +<<<<<<< HEAD:scripts/statusfetcher.php + getTimeline($f, $child_db_name); +======= // XXX: Each child needs its own DB connection getTimeline($f); +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php exit(); } // Remove child from ps list as it finishes while(($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) { + if (defined('SCRIPT_DEBUG')) { print "Child $c finished.\n"; } + remove_ps($children, $c); } // Wait if we have too many kids +<<<<<<< HEAD:scripts/statusfetcher.php + if (sizeof($children) > MAXCHILDREN) { + + if (defined('SCRIPT_DEBUG')) { + print "Too many children. Waiting...\n"; + } + + if (($c = pcntl_wait($status, WUNTRACED)) > 0){ + +======= if(sizeof($children) > MAXCHILDREN) { if (defined('SCRIPT_DEBUG')) { print "Too many children. Waiting...\n"; } if(($c = pcntl_wait($status, WUNTRACED)) > 0){ +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php if (defined('SCRIPT_DEBUG')) { print "Finished waiting for $c\n"; } + remove_ps($children, $c); } } @@ -89,13 +126,17 @@ do { // Remove all children from the process list before restarting while(($c = pcntl_wait($status, WUNTRACED)) > 0) { + if (defined('SCRIPT_DEBUG')) { print "Child $c finished.\n"; } + remove_ps($children, $c); } // Rest for a bit before we fetch more statuses + common_debug('Waiting ' . POLL_INTERVAL . + ' secs before hitting Twitter again.'); if (defined('SCRIPT_DEBUG')) { print 'Waiting ' . POLL_INTERVAL . " secs before hitting Twitter again.\n"; @@ -108,8 +149,11 @@ do { function refreshFlinks() { +<<<<<<< HEAD:scripts/statusfetcher.php +======= global $config; +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php $flink = new Foreign_link(); $flink->service = 1; // Twitter $flink->orderBy('last_noticesync'); @@ -136,8 +180,8 @@ function refreshFlinks() { } function remove_ps(&$plist, $ps){ - for($i = 0; $i < sizeof($plist); $i++){ - if($plist[$i] == $ps){ + for ($i = 0; $i < sizeof($plist); $i++) { + if ($plist[$i] == $ps) { unset($plist[$i]); $plist = array_values($plist); break; @@ -148,6 +192,17 @@ function remove_ps(&$plist, $ps){ function getTimeline($flink) { +<<<<<<< HEAD:scripts/statusfetcher.php + if (empty($flink)) { + common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); + if (defined('SCRIPT_DEBUG')) { + print "Can't retrieve Foreign_link for foreign ID $fid\n"; + } + return; + } + + $fuser = $flink->getForeignUser(); +======= global $config; $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); require_once(INSTALLDIR . '/lib/common.php'); @@ -169,6 +224,7 @@ function getTimeline($flink) $fuser->id = $flink->foreign_id; $fuser->limit(1); $fuser->find(true); +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php if (empty($fuser)) { common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); @@ -178,9 +234,17 @@ function getTimeline($flink) return; } +<<<<<<< HEAD:scripts/statusfetcher.php + common_debug('Trying to get timeline for Twitter user ' . + "$fuser->nickname ($flink->foreign_id)."); + if (defined('SCRIPT_DEBUG')) { + print 'Trying to get timeline for Twitter user ' . + "$fuser->nickname ($flink->foreign_id).\n"; +======= if (defined('SCRIPT_DEBUG')) { // XXX: This is horrible and must be removed before releasing this print 'username: ' . $fuser->nickname . ' password: ' . $flink->credentials . "\n"; +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php } $url = 'http://twitter.com/statuses/friends_timeline.json'; @@ -218,6 +282,8 @@ function getTimeline($flink) function saveStatus($status, $flink) { +<<<<<<< HEAD:scripts/statusfetcher.php +======= global $config; $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); @@ -225,6 +291,7 @@ function saveStatus($status, $flink) // Do we have a profile for this Twitter user? +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php $id = ensureProfile($status->user); $profile = Profile::staticGet($id); @@ -282,6 +349,10 @@ function saveStatus($status, $flink) $notice->query('COMMIT'); +<<<<<<< HEAD:scripts/statusfetcher.php + common_debug("Saved status $status->id as notice $notice->id."); +======= +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php if (defined('SCRIPT_DEBUG')) { print "Saved status $status->id as notice $notice->id.\n"; } @@ -301,8 +372,11 @@ function saveStatus($status, $flink) function ensureProfile($user) { +<<<<<<< HEAD:scripts/statusfetcher.php +======= global $config; +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php // check to see if there's already a profile for this user $profileurl = 'http://twitter.com/' . $user->screen_name; $profile = Profile::staticGet('profileurl', $profileurl); @@ -462,8 +536,11 @@ function saveAvatars($user, $id) function updateAvatar($profile_id, $size, $mediatype, $filename) { +<<<<<<< HEAD:scripts/statusfetcher.php +======= global $config; +>>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php common_debug("Updating avatar: $size"); if (defined('SCRIPT_DEBUG')) { print "Updating avatar: $size\n"; From b291cb8a1be0eb272e1663fbf6c6dea17bdb71db Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 6 May 2009 01:26:06 +0000 Subject: [PATCH 460/503] Fix for previous bad patch I pushed (had conflict markers) Sorry about that. --- scripts/statusfetcher.php | 80 --------------------------------------- 1 file changed, 80 deletions(-) diff --git a/scripts/statusfetcher.php b/scripts/statusfetcher.php index 82ae5bfd43..5518e3aa8c 100644 --- a/scripts/statusfetcher.php +++ b/scripts/statusfetcher.php @@ -29,11 +29,7 @@ define('LACONICA', true); // Tune number of processes and how often to poll Twitter define('MAXCHILDREN', 5); -<<<<<<< HEAD:scripts/statusfetcher.php define('POLL_INTERVAL', 60 * 10); // in seconds -======= -define('POLL_INTERVAL', 60 * 5); // in seconds ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php // Uncomment this to get useful console output define('SCRIPT_DEBUG', true); @@ -44,7 +40,6 @@ $children = array(); do { -<<<<<<< HEAD:scripts/statusfetcher.php $flinks = refreshFlinks(); foreach ($flinks as $f){ @@ -52,9 +47,6 @@ do { // We have to disconnect from the DB before forking so // each process will open its own connection and // avoid stomping on each other -======= - $flink_ids = refreshFlinks(); ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php $conn = &$f->getDatabaseConnection(); $conn->disconnect(); @@ -79,12 +71,7 @@ do { // Child -<<<<<<< HEAD:scripts/statusfetcher.php getTimeline($f, $child_db_name); -======= - // XXX: Each child needs its own DB connection - getTimeline($f); ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php exit(); } @@ -99,7 +86,6 @@ do { } // Wait if we have too many kids -<<<<<<< HEAD:scripts/statusfetcher.php if (sizeof($children) > MAXCHILDREN) { if (defined('SCRIPT_DEBUG')) { @@ -108,13 +94,6 @@ do { if (($c = pcntl_wait($status, WUNTRACED)) > 0){ -======= - if(sizeof($children) > MAXCHILDREN) { - if (defined('SCRIPT_DEBUG')) { - print "Too many children. Waiting...\n"; - } - if(($c = pcntl_wait($status, WUNTRACED)) > 0){ ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php if (defined('SCRIPT_DEBUG')) { print "Finished waiting for $c\n"; } @@ -149,11 +128,6 @@ do { function refreshFlinks() { -<<<<<<< HEAD:scripts/statusfetcher.php -======= - global $config; - ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php $flink = new Foreign_link(); $flink->service = 1; // Twitter $flink->orderBy('last_noticesync'); @@ -192,7 +166,6 @@ function remove_ps(&$plist, $ps){ function getTimeline($flink) { -<<<<<<< HEAD:scripts/statusfetcher.php if (empty($flink)) { common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); if (defined('SCRIPT_DEBUG')) { @@ -202,29 +175,6 @@ function getTimeline($flink) } $fuser = $flink->getForeignUser(); -======= - global $config; - $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); - require_once(INSTALLDIR . '/lib/common.php'); - - if (defined('SCRIPT_DEBUG')) { - print "Trying to get timeline for $flink->foreign_id\n"; - } - - if (empty($flink)) { - common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); - if (defined('SCRIPT_DEBUG')) { - print "Can't retrieve Foreign_link for foreign ID $fid\n"; - } - return; - } - - $fuser = new Foreign_user(); - $fuser->service = 1; - $fuser->id = $flink->foreign_id; - $fuser->limit(1); - $fuser->find(true); ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php if (empty($fuser)) { common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); @@ -234,17 +184,11 @@ function getTimeline($flink) return; } -<<<<<<< HEAD:scripts/statusfetcher.php common_debug('Trying to get timeline for Twitter user ' . "$fuser->nickname ($flink->foreign_id)."); if (defined('SCRIPT_DEBUG')) { print 'Trying to get timeline for Twitter user ' . "$fuser->nickname ($flink->foreign_id).\n"; -======= - if (defined('SCRIPT_DEBUG')) { - // XXX: This is horrible and must be removed before releasing this - print 'username: ' . $fuser->nickname . ' password: ' . $flink->credentials . "\n"; ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php } $url = 'http://twitter.com/statuses/friends_timeline.json'; @@ -282,16 +226,6 @@ function getTimeline($flink) function saveStatus($status, $flink) { -<<<<<<< HEAD:scripts/statusfetcher.php -======= - - global $config; - $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); - require_once(INSTALLDIR . '/lib/common.php'); - - // Do we have a profile for this Twitter user? - ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php $id = ensureProfile($status->user); $profile = Profile::staticGet($id); @@ -349,10 +283,6 @@ function saveStatus($status, $flink) $notice->query('COMMIT'); -<<<<<<< HEAD:scripts/statusfetcher.php - common_debug("Saved status $status->id as notice $notice->id."); -======= ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php if (defined('SCRIPT_DEBUG')) { print "Saved status $status->id as notice $notice->id.\n"; } @@ -372,11 +302,6 @@ function saveStatus($status, $flink) function ensureProfile($user) { -<<<<<<< HEAD:scripts/statusfetcher.php -======= - global $config; - ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php // check to see if there's already a profile for this user $profileurl = 'http://twitter.com/' . $user->screen_name; $profile = Profile::staticGet('profileurl', $profileurl); @@ -536,11 +461,6 @@ function saveAvatars($user, $id) function updateAvatar($profile_id, $size, $mediatype, $filename) { -<<<<<<< HEAD:scripts/statusfetcher.php -======= - global $config; - ->>>>>>> b8c700a7454db825b3867eadfa22afa1e5eb4f6c:scripts/statusfetcher.php common_debug("Updating avatar: $size"); if (defined('SCRIPT_DEBUG')) { print "Updating avatar: $size\n"; From 48226e0c48e9bb2a7d97dbfd8f048ae299fbb7bf Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 00:25:15 -0700 Subject: [PATCH 461/503] Properly daemonized 2-way Twitter bridge code --- scripts/statusfetcher.php | 929 ++++++++++++++++++++------------------ 1 file changed, 480 insertions(+), 449 deletions(-) diff --git a/scripts/statusfetcher.php b/scripts/statusfetcher.php index 5518e3aa8c..5275a45752 100644 --- a/scripts/statusfetcher.php +++ b/scripts/statusfetcher.php @@ -28,378 +28,439 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); define('LACONICA', true); // Tune number of processes and how often to poll Twitter -define('MAXCHILDREN', 5); -define('POLL_INTERVAL', 60 * 10); // in seconds +// XXX: Should these things be in config.php? +define('MAXCHILDREN', 2); +define('POLL_INTERVAL', 60); // in seconds // Uncomment this to get useful console output define('SCRIPT_DEBUG', true); require_once(INSTALLDIR . '/lib/common.php'); +require_once(INSTALLDIR . '/lib/daemon.php'); -$children = array(); +class TwitterStatusFetcher extends Daemon +{ -do { + private $children = array(); - $flinks = refreshFlinks(); + function name() + { + return 'twitterstatusfetcher'; + } - foreach ($flinks as $f){ + function run() + { + do { - // We have to disconnect from the DB before forking so - // each process will open its own connection and - // avoid stomping on each other + $flinks = $this->refreshFlinks(); - $conn = &$f->getDatabaseConnection(); - $conn->disconnect(); + foreach ($flinks as $f){ - $pid = pcntl_fork(); + // We have to disconnect from the DB before forking so + // each sub-process will open its own connection and + // avoid stomping on the others - if ($pid == -1) { - die ("Couldn't fork!"); - } + $conn = &$f->getDatabaseConnection(); + $conn->disconnect(); - if ($pid) { + $pid = pcntl_fork(); - // Parent - - if (defined('SCRIPT_DEBUG')) { - print "Parent: forked " . $pid . "\n"; - } - - $children[] = $pid; - - } else { - - // Child - - getTimeline($f, $child_db_name); - exit(); - } - - // Remove child from ps list as it finishes - while(($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) { - - if (defined('SCRIPT_DEBUG')) { - print "Child $c finished.\n"; - } - - remove_ps($children, $c); - } - - // Wait if we have too many kids - if (sizeof($children) > MAXCHILDREN) { - - if (defined('SCRIPT_DEBUG')) { - print "Too many children. Waiting...\n"; - } - - if (($c = pcntl_wait($status, WUNTRACED)) > 0){ - - if (defined('SCRIPT_DEBUG')) { - print "Finished waiting for $c\n"; + if ($pid == -1) { + die ("Couldn't fork!"); } - remove_ps($children, $c); + if ($pid) { + + // Parent + common_debug("Parent: forked new status fetcher process " . $pid); + + if (defined('SCRIPT_DEBUG')) { + print "Parent: forked fetcher process " . $pid . "\n"; + } + + $this->children[] = $pid; + + } else { + + // Child + $this->getTimeline($f); + exit(); + } + + // Remove child from ps list as it finishes + while(($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) { + + common_debug("Child $c finished."); + + if (defined('SCRIPT_DEBUG')) { + print "Child $c finished.\n"; + } + + $this->remove_ps($this->children, $c); + } + + // Wait! We have too many damn kids. + if (sizeof($this->children) > MAXCHILDREN) { + + common_debug('Too many children. Waiting...'); + + if (defined('SCRIPT_DEBUG')) { + print "Too many children. Waiting...\n"; + } + + if (($c = pcntl_wait($status, WUNTRACED)) > 0){ + + common_debug("Finished waiting for $c"); + + if (defined('SCRIPT_DEBUG')) { + print "Finished waiting for $c\n"; + } + + $this->remove_ps($this->children, $c); + } + } } - } - } - // Remove all children from the process list before restarting - while(($c = pcntl_wait($status, WUNTRACED)) > 0) { + // Remove all children from the process list before restarting + while(($c = pcntl_wait($status, WUNTRACED)) > 0) { - if (defined('SCRIPT_DEBUG')) { - print "Child $c finished.\n"; - } + common_debug("Child $c finished."); - remove_ps($children, $c); - } + if (defined('SCRIPT_DEBUG')) { + print "Child $c finished.\n"; + } - // Rest for a bit before we fetch more statuses - common_debug('Waiting ' . POLL_INTERVAL . - ' secs before hitting Twitter again.'); - if (defined('SCRIPT_DEBUG')) { - print 'Waiting ' . POLL_INTERVAL . - " secs before hitting Twitter again.\n"; - } + $this->remove_ps($this->children, $c); + } - sleep(POLL_INTERVAL); - -} while (true); - - -function refreshFlinks() { - - $flink = new Foreign_link(); - $flink->service = 1; // Twitter - $flink->orderBy('last_noticesync'); - - $cnt = $flink->find(); - - if (defined('SCRIPT_DEBUG')) { - print "Updating Twitter friends subscriptions for $cnt users.\n"; - } - - $flinks = array(); - - while ($flink->fetch()) { - - if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { - $flinks[] = clone($flink); - } - } - - $flink->free(); - unset($flink); - - return $flinks; -} - -function remove_ps(&$plist, $ps){ - for ($i = 0; $i < sizeof($plist); $i++) { - if ($plist[$i] == $ps) { - unset($plist[$i]); - $plist = array_values($plist); - break; - } - } -} - -function getTimeline($flink) -{ - - if (empty($flink)) { - common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); - if (defined('SCRIPT_DEBUG')) { - print "Can't retrieve Foreign_link for foreign ID $fid\n"; - } - return; - } - - $fuser = $flink->getForeignUser(); - - if (empty($fuser)) { - common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); - if (defined('SCRIPT_DEBUG')) { - print "Unmatched user for ID $flink->user_id\n"; - } - return; - } - - common_debug('Trying to get timeline for Twitter user ' . - "$fuser->nickname ($flink->foreign_id)."); - if (defined('SCRIPT_DEBUG')) { - print 'Trying to get timeline for Twitter user ' . - "$fuser->nickname ($flink->foreign_id).\n"; - } - - $url = 'http://twitter.com/statuses/friends_timeline.json'; - - $timeline_json = get_twitter_data($url, $fuser->nickname, - $flink->credentials); - - $timeline = json_decode($timeline_json); - - if (empty($timeline)) { - common_log(LOG_WARNING, "Empty timeline."); - if (defined('SCRIPT_DEBUG')) { - print "Empty timeline!\n"; - } - return; - } - - foreach ($timeline as $status) { - - // Hacktastic: filter out stuff coming from Laconica - $source = mb_strtolower(common_config('integration', 'source')); - - if (preg_match("/$source/", mb_strtolower($status->source))) { - continue; - } - - saveStatus($status, $flink); - } - - // Okay, record the time we synced with Twitter for posterity - - $flink->last_noticesync = common_sql_now(); - $flink->update(); -} - -function saveStatus($status, $flink) -{ - $id = ensureProfile($status->user); - $profile = Profile::staticGet($id); - - if (!$profile) { - common_log(LOG_ERR, 'Problem saving notice. No associated Profile.'); - if (defined('SCRIPT_DEBUG')) { - print "Problem saving notice. No associated Profile.\n"; - } - return null; - } - - $uri = 'http://twitter.com/' . $status->user->screen_name . - '/status/' . $status->id; - - // Skip save if notice source is Laconica or Identi.ca? - - $notice = Notice::staticGet('uri', $uri); - - // check to see if we've already imported the status - if (!$notice) { - - $notice = new Notice(); - $notice->profile_id = $id; - - $notice->query('BEGIN'); - - // XXX: figure out reply_to - $notice->reply_to = null; - - // XXX: Should this be common_sql_now() instead of status create date? - - $notice->created = strftime('%Y-%m-%d %H:%M:%S', - strtotime($status->created_at)); - $notice->content = $status->text; - $notice->rendered = common_render_content($status->text, $notice); - $notice->source = 'twitter'; - $notice->is_local = 0; - $notice->uri = $uri; - - $notice_id = $notice->insert(); - - if (!$notice_id) { - common_log_db_error($notice, 'INSERT', __FILE__); + // Rest for a bit before we fetch more statuses + common_debug('Waiting ' . POLL_INTERVAL . + ' secs before hitting Twitter again.'); if (defined('SCRIPT_DEBUG')) { - print "Could not save notice!\n"; + print 'Waiting ' . POLL_INTERVAL . + " secs before hitting Twitter again.\n"; + } + + sleep(POLL_INTERVAL); + + } while (true); + } + + function refreshFlinks() { + + $flink = new Foreign_link(); + $flink->service = 1; // Twitter + $flink->orderBy('last_noticesync'); + + $cnt = $flink->find(); + + if (defined('SCRIPT_DEBUG')) { + print "Updating Twitter friends subscriptions for $cnt users.\n"; + } + + $flinks = array(); + + while ($flink->fetch()) { + + if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { + $flinks[] = clone($flink); } } - // XXX: Figure out a better way to link replies? - $notice->saveReplies(); + $flink->free(); + unset($flink); - // XXX: Do we want to polute our tag cloud with hashtags from Twitter? - $notice->saveTags(); - $notice->saveGroups(); + return $flinks; + } - $notice->query('COMMIT'); - - if (defined('SCRIPT_DEBUG')) { - print "Saved status $status->id as notice $notice->id.\n"; + function remove_ps(&$plist, $ps){ + for ($i = 0; $i < sizeof($plist); $i++) { + if ($plist[$i] == $ps) { + unset($plist[$i]); + $plist = array_values($plist); + break; + } } } - if (!Notice_inbox::staticGet('notice_id', $notice->id)) { + function getTimeline($flink) + { - // Add to inbox - $inbox = new Notice_inbox(); - $inbox->user_id = $flink->user_id; - $inbox->notice_id = $notice->id; - $inbox->created = common_sql_now(); - - $inbox->insert(); - } -} - -function ensureProfile($user) -{ - // check to see if there's already a profile for this user - $profileurl = 'http://twitter.com/' . $user->screen_name; - $profile = Profile::staticGet('profileurl', $profileurl); - - if ($profile) { - common_debug("Profile for $profile->nickname found."); - - // Check to see if the user's Avatar has changed - checkAvatar($user, $profile); - return $profile->id; - - } else { - $debugmsg = 'Adding profile and remote profile ' . - "for Twitter user: $profileurl\n"; - common_debug($debugmsg, __FILE__); - if (defined('SCRIPT_DEBUG')) { - print $debugmsg; - } - - $profile = new Profile(); - $profile->query("BEGIN"); - - $profile->nickname = $user->screen_name; - $profile->fullname = $user->name; - $profile->homepage = $user->url; - $profile->bio = $user->description; - $profile->location = $user->location; - $profile->profileurl = $profileurl; - $profile->created = common_sql_now(); - - $id = $profile->insert(); - - if (empty($id)) { - common_log_db_error($profile, 'INSERT', __FILE__); + if (empty($flink)) { + common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); if (defined('SCRIPT_DEBUG')) { - print 'Could not insert Profile: ' . - common_log_objstring($profile) . "\n"; + print "Can't retrieve Foreign_link for foreign ID $fid\n"; } - $profile->query("ROLLBACK"); - return false; + return; } - // check for remote profile - $remote_pro = Remote_profile::staticGet('uri', $profileurl); + $fuser = $flink->getForeignUser(); - if (!$remote_pro) { + if (empty($fuser)) { + common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); + if (defined('SCRIPT_DEBUG')) { + print "Unmatched user for ID $flink->user_id\n"; + } + return; + } - $remote_pro = new Remote_profile(); + common_debug('Trying to get timeline for Twitter user ' . + "$fuser->nickname ($flink->foreign_id)."); + if (defined('SCRIPT_DEBUG')) { + print 'Trying to get timeline for Twitter user ' . + "$fuser->nickname ($flink->foreign_id).\n"; + } - $remote_pro->id = $id; - $remote_pro->uri = $profileurl; - $remote_pro->created = common_sql_now(); + $url = 'http://twitter.com/statuses/friends_timeline.json'; - $rid = $remote_pro->insert(); + $timeline_json = get_twitter_data($url, $fuser->nickname, + $flink->credentials); - if (empty($rid)) { + $timeline = json_decode($timeline_json); + + if (empty($timeline)) { + common_log(LOG_WARNING, "Empty timeline."); + if (defined('SCRIPT_DEBUG')) { + print "Empty timeline!\n"; + } + return; + } + + foreach ($timeline as $status) { + + // Hacktastic: filter out stuff coming from Laconica + $source = mb_strtolower(common_config('integration', 'source')); + + if (preg_match("/$source/", mb_strtolower($status->source))) { + continue; + } + + $this->saveStatus($status, $flink); + } + + // Okay, record the time we synced with Twitter for posterity + + $flink->last_noticesync = common_sql_now(); + $flink->update(); + } + + function saveStatus($status, $flink) + { + $id = $this->ensureProfile($status->user); + $profile = Profile::staticGet($id); + + if (!$profile) { + common_log(LOG_ERR, 'Problem saving notice. No associated Profile.'); + if (defined('SCRIPT_DEBUG')) { + print "Problem saving notice. No associated Profile.\n"; + } + return null; + } + + $uri = 'http://twitter.com/' . $status->user->screen_name . + '/status/' . $status->id; + + // Skip save if notice source is Laconica or Identi.ca? + + $notice = Notice::staticGet('uri', $uri); + + // check to see if we've already imported the status + if (!$notice) { + + $notice = new Notice(); + $notice->profile_id = $id; + + $notice->query('BEGIN'); + + // XXX: figure out reply_to + $notice->reply_to = null; + + // XXX: Should this be common_sql_now() instead of status create date? + + $notice->created = strftime('%Y-%m-%d %H:%M:%S', + strtotime($status->created_at)); + $notice->content = $status->text; + $notice->rendered = common_render_content($status->text, $notice); + $notice->source = 'twitter'; + $notice->is_local = 0; + $notice->uri = $uri; + + $notice_id = $notice->insert(); + + if (!$notice_id) { + common_log_db_error($notice, 'INSERT', __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Could not save notice!\n"; + } + } + + // XXX: Figure out a better way to link replies? + $notice->saveReplies(); + + // XXX: Do we want to polute our tag cloud with hashtags from Twitter? + $notice->saveTags(); + $notice->saveGroups(); + + $notice->query('COMMIT'); + + if (defined('SCRIPT_DEBUG')) { + print "Saved status $status->id as notice $notice->id.\n"; + } + } + + if (!Notice_inbox::staticGet('notice_id', $notice->id)) { + + // Add to inbox + $inbox = new Notice_inbox(); + $inbox->user_id = $flink->user_id; + $inbox->notice_id = $notice->id; + $inbox->created = common_sql_now(); + + $inbox->insert(); + } + } + + function ensureProfile($user) + { + // check to see if there's already a profile for this user + $profileurl = 'http://twitter.com/' . $user->screen_name; + $profile = Profile::staticGet('profileurl', $profileurl); + + if ($profile) { + common_debug("Profile for $profile->nickname found."); + + // Check to see if the user's Avatar has changed + $this->checkAvatar($user, $profile); + return $profile->id; + + } else { + $debugmsg = 'Adding profile and remote profile ' . + "for Twitter user: $profileurl\n"; + common_debug($debugmsg, __FILE__); + if (defined('SCRIPT_DEBUG')) { + print $debugmsg; + } + + $profile = new Profile(); + $profile->query("BEGIN"); + + $profile->nickname = $user->screen_name; + $profile->fullname = $user->name; + $profile->homepage = $user->url; + $profile->bio = $user->description; + $profile->location = $user->location; + $profile->profileurl = $profileurl; + $profile->created = common_sql_now(); + + $id = $profile->insert(); + + if (empty($id)) { common_log_db_error($profile, 'INSERT', __FILE__); if (defined('SCRIPT_DEBUG')) { - print 'Could not insert Remote_profile: ' . - common_log_objstring($remote_pro) . "\n"; + print 'Could not insert Profile: ' . + common_log_objstring($profile) . "\n"; } $profile->query("ROLLBACK"); return false; } + + // check for remote profile + $remote_pro = Remote_profile::staticGet('uri', $profileurl); + + if (!$remote_pro) { + + $remote_pro = new Remote_profile(); + + $remote_pro->id = $id; + $remote_pro->uri = $profileurl; + $remote_pro->created = common_sql_now(); + + $rid = $remote_pro->insert(); + + if (empty($rid)) { + common_log_db_error($profile, 'INSERT', __FILE__); + if (defined('SCRIPT_DEBUG')) { + print 'Could not insert Remote_profile: ' . + common_log_objstring($remote_pro) . "\n"; + } + $profile->query("ROLLBACK"); + return false; + } + } + + $profile->query("COMMIT"); + + $this->saveAvatars($user, $id); + + return $id; } - - $profile->query("COMMIT"); - - saveAvatars($user, $id); - - return $id; } -} -function checkAvatar($user, $profile) -{ - global $config; + function checkAvatar($user, $profile) + { + global $config; - $path_parts = pathinfo($user->profile_image_url); - $newname = 'Twitter_' . $user->id . '_' . - $path_parts['basename']; + $path_parts = pathinfo($user->profile_image_url); + $newname = 'Twitter_' . $user->id . '_' . + $path_parts['basename']; - $oldname = $profile->getAvatar(48)->filename; + $oldname = $profile->getAvatar(48)->filename; - if ($newname != $oldname) { + if ($newname != $oldname) { - common_debug("Avatar for Twitter user $profile->nickname has changed."); - common_debug("old: $oldname new: $newname"); + common_debug("Avatar for Twitter user $profile->nickname has changed."); + common_debug("old: $oldname new: $newname"); - if (defined('SCRIPT_DEBUG')) { - print "Avatar for Twitter user $user->id has changed.\n"; - print "old: $oldname\n"; - print "new: $newname\n"; + if (defined('SCRIPT_DEBUG')) { + print "Avatar for Twitter user $user->id has changed.\n"; + print "old: $oldname\n"; + print "new: $newname\n"; + } + + $img_root = substr($path_parts['basename'], 0, -11); + $ext = $path_parts['extension']; + $mediatype = $this->getMediatype($ext); + + foreach (array('mini', 'normal', 'bigger') as $size) { + $url = $path_parts['dirname'] . '/' . + $img_root . '_' . $size . ".$ext"; + $filename = 'Twitter_' . $user->id . '_' . + $img_root . "_$size.$ext"; + + if ($this->fetchAvatar($url, $filename)) { + $this->updateAvatar($profile->id, $size, $mediatype, $filename); + } + } + } + } + + function getMediatype($ext) + { + $mediatype = null; + + switch (strtolower($ext)) { + case 'jpg': + $mediatype = 'image/jpg'; + break; + case 'gif': + $mediatype = 'image/gif'; + break; + default: + $mediatype = 'image/png'; } - $img_root = substr($path_parts['basename'], 0, -11); + return $mediatype; + } + + function saveAvatars($user, $id) + { + global $config; + + $path_parts = pathinfo($user->profile_image_url); $ext = $path_parts['extension']; - $mediatype = getMediatype($ext); + $end = strlen('_normal' . $ext); + $img_root = substr($path_parts['basename'], 0, -($end+1)); + $mediatype = $this->getMediatype($ext); foreach (array('mini', 'normal', 'bigger') as $size) { $url = $path_parts['dirname'] . '/' . @@ -407,173 +468,143 @@ function checkAvatar($user, $profile) $filename = 'Twitter_' . $user->id . '_' . $img_root . "_$size.$ext"; - if (fetchAvatar($url, $filename)) { - updateAvatar($profile->id, $size, $mediatype, $filename); + if ($this->fetchAvatar($url, $filename)) { + $this->newAvatar($id, $size, $mediatype, $filename); + } else { + common_log(LOG_WARNING, "Problem fetching Avatar: $url", __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Problem fetching Avatar: $url\n"; + } } } } -} -function getMediatype($ext) -{ - $mediatype = null; + function updateAvatar($profile_id, $size, $mediatype, $filename) { - switch (strtolower($ext)) { - case 'jpg': - $mediatype = 'image/jpg'; - break; - case 'gif': - $mediatype = 'image/gif'; - break; - default: - $mediatype = 'image/png'; - } + common_debug("Updating avatar: $size"); + if (defined('SCRIPT_DEBUG')) { + print "Updating avatar: $size\n"; + } - return $mediatype; -} + $profile = Profile::staticGet($profile_id); -function saveAvatars($user, $id) -{ - global $config; - - $path_parts = pathinfo($user->profile_image_url); - $ext = $path_parts['extension']; - $end = strlen('_normal' . $ext); - $img_root = substr($path_parts['basename'], 0, -($end+1)); - $mediatype = getMediatype($ext); - - foreach (array('mini', 'normal', 'bigger') as $size) { - $url = $path_parts['dirname'] . '/' . - $img_root . '_' . $size . ".$ext"; - $filename = 'Twitter_' . $user->id . '_' . - $img_root . "_$size.$ext"; - - if (fetchAvatar($url, $filename)) { - newAvatar($id, $size, $mediatype, $filename); - } else { - common_log(LOG_WARNING, "Problem fetching Avatar: $url", __FILE__); + if (!$profile) { + common_debug("Couldn't get profile: $profile_id!"); if (defined('SCRIPT_DEBUG')) { - print "Problem fetching Avatar: $url\n"; + print "Couldn't get profile: $profile_id!\n"; } + return; } - } -} -function updateAvatar($profile_id, $size, $mediatype, $filename) { + $sizes = array('mini' => 24, 'normal' => 48, 'bigger' => 73); + $avatar = $profile->getAvatar($sizes[$size]); - common_debug("Updating avatar: $size"); - if (defined('SCRIPT_DEBUG')) { - print "Updating avatar: $size\n"; + if ($avatar) { + common_debug("Deleting $size avatar for $profile->nickname."); + @unlink(INSTALLDIR . '/avatar/' . $avatar->filename); + $avatar->delete(); + } + + $this->newAvatar($profile->id, $size, $mediatype, $filename); } - $profile = Profile::staticGet($profile_id); + function newAvatar($profile_id, $size, $mediatype, $filename) + { + global $config; - if (!$profile) { - common_debug("Couldn't get profile: $profile_id!"); + $avatar = new Avatar(); + $avatar->profile_id = $profile_id; + + switch($size) { + case 'mini': + $avatar->width = 24; + $avatar->height = 24; + break; + case 'normal': + $avatar->width = 48; + $avatar->height = 48; + break; + default: + + // Note: Twitter's big avatars are a different size than + // Laconica's (Laconica's = 96) + + $avatar->width = 73; + $avatar->height = 73; + } + + $avatar->original = 0; // we don't have the original + $avatar->mediatype = $mediatype; + $avatar->filename = $filename; + $avatar->url = Avatar::url($filename); + + common_debug("new filename: $avatar->url"); if (defined('SCRIPT_DEBUG')) { - print "Couldn't get profile: $profile_id!\n"; + print "New filename: $avatar->url\n"; } - return; - } - $sizes = array('mini' => 24, 'normal' => 48, 'bigger' => 73); - $avatar = $profile->getAvatar($sizes[$size]); + $avatar->created = common_sql_now(); - if ($avatar) { - common_debug("Deleting $size avatar for $profile->nickname."); - @unlink(INSTALLDIR . '/avatar/' . $avatar->filename); - $avatar->delete(); - } + $id = $avatar->insert(); - newAvatar($profile->id, $size, $mediatype, $filename); -} + if (!$id) { + common_log_db_error($avatar, 'INSERT', __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Could not insert avatar!\n"; + } -function newAvatar($profile_id, $size, $mediatype, $filename) -{ - global $config; + return null; + } - $avatar = new Avatar(); - $avatar->profile_id = $profile_id; - - switch($size) { - case 'mini': - $avatar->width = 24; - $avatar->height = 24; - break; - case 'normal': - $avatar->width = 48; - $avatar->height = 48; - break; - default: - - // Note: Twitter's big avatars are a different size than - // Laconica's (Laconica's = 96) - - $avatar->width = 73; - $avatar->height = 73; - } - - $avatar->original = 0; // we don't have the original - $avatar->mediatype = $mediatype; - $avatar->filename = $filename; - $avatar->url = Avatar::url($filename); - - common_debug("new filename: $avatar->url"); - if (defined('SCRIPT_DEBUG')) { - print "New filename: $avatar->url\n"; - } - - $avatar->created = common_sql_now(); - - $id = $avatar->insert(); - - if (!$id) { - common_log_db_error($avatar, 'INSERT', __FILE__); + common_debug("Saved new $size avatar for $profile_id."); if (defined('SCRIPT_DEBUG')) { - print "Could not insert avatar!\n"; + print "Saved new $size avatar for $profile_id.\n"; } - return null; + return $id; } - common_debug("Saved new $size avatar for $profile_id."); - if (defined('SCRIPT_DEBUG')) { - print "Saved new $size avatar for $profile_id.\n"; - } + function fetchAvatar($url, $filename) + { + $avatar_dir = INSTALLDIR . '/avatar/'; - return $id; -} + $avatarfile = $avatar_dir . $filename; -function fetchAvatar($url, $filename) -{ - $avatar_dir = INSTALLDIR . '/avatar/'; + $out = fopen($avatarfile, 'wb'); + if (!$out) { + common_log(LOG_WARNING, "Couldn't open file $filename", __FILE__); + if (defined('SCRIPT_DEBUG')) { + print "Couldn't open file! $filename\n"; + } + return false; + } - $avatarfile = $avatar_dir . $filename; - - $out = fopen($avatarfile, 'wb'); - if (!$out) { - common_log(LOG_WARNING, "Couldn't open file $filename", __FILE__); + common_debug("Fetching avatar: $url", __FILE__); if (defined('SCRIPT_DEBUG')) { - print "Couldn't open file! $filename\n"; + print "Fetching avatar from Twitter: $url\n"; } - return false; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_FILE, $out); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + $result = curl_exec($ch); + curl_close($ch); + + fclose($out); + + return $result; } - - common_debug("Fetching avatar: $url", __FILE__); - if (defined('SCRIPT_DEBUG')) { - print "Fetching avatar from Twitter: $url\n"; - } - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_FILE, $out); - curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); - $result = curl_exec($ch); - curl_close($ch); - - fclose($out); - - return $result; } + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); +declare(ticks = 1); + +$fetcher = new TwitterStatusFetcher(); +$fetcher->runOnce(); + From 2621a5471f9a3fa75d206ed5b3a4a91df1e28bdc Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 00:26:42 -0700 Subject: [PATCH 462/503] Better name --- scripts/{statusfetcher.php => twitterstatusfetcher.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{statusfetcher.php => twitterstatusfetcher.php} (100%) diff --git a/scripts/statusfetcher.php b/scripts/twitterstatusfetcher.php similarity index 100% rename from scripts/statusfetcher.php rename to scripts/twitterstatusfetcher.php From 856e05a08ff8d09fbd580ed35906e3dda0475a0a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 01:10:31 -0700 Subject: [PATCH 463/503] Less pychotic debugging statements --- scripts/twitterstatusfetcher.php | 140 ++++++++++++------------------- 1 file changed, 52 insertions(+), 88 deletions(-) mode change 100644 => 100755 scripts/twitterstatusfetcher.php diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php old mode 100644 new mode 100755 index 5275a45752..e8819f6651 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -72,10 +72,8 @@ class TwitterStatusFetcher extends Daemon if ($pid) { // Parent - common_debug("Parent: forked new status fetcher process " . $pid); - if (defined('SCRIPT_DEBUG')) { - print "Parent: forked fetcher process " . $pid . "\n"; + common_debug("Parent: forked new status fetcher process " . $pid); } $this->children[] = $pid; @@ -90,10 +88,8 @@ class TwitterStatusFetcher extends Daemon // Remove child from ps list as it finishes while(($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) { - common_debug("Child $c finished."); - if (defined('SCRIPT_DEBUG')) { - print "Child $c finished.\n"; + common_debug("Child $c finished."); } $this->remove_ps($this->children, $c); @@ -102,18 +98,14 @@ class TwitterStatusFetcher extends Daemon // Wait! We have too many damn kids. if (sizeof($this->children) > MAXCHILDREN) { - common_debug('Too many children. Waiting...'); - if (defined('SCRIPT_DEBUG')) { - print "Too many children. Waiting...\n"; + common_debug('Too many children. Waiting...'); } if (($c = pcntl_wait($status, WUNTRACED)) > 0){ - common_debug("Finished waiting for $c"); - if (defined('SCRIPT_DEBUG')) { - print "Finished waiting for $c\n"; + common_debug("Finished waiting for $c"); } $this->remove_ps($this->children, $c); @@ -124,21 +116,18 @@ class TwitterStatusFetcher extends Daemon // Remove all children from the process list before restarting while(($c = pcntl_wait($status, WUNTRACED)) > 0) { - common_debug("Child $c finished."); - if (defined('SCRIPT_DEBUG')) { - print "Child $c finished.\n"; + common_debug("Child $c finished."); } $this->remove_ps($this->children, $c); } // Rest for a bit before we fetch more statuses - common_debug('Waiting ' . POLL_INTERVAL . - ' secs before hitting Twitter again.'); + if (defined('SCRIPT_DEBUG')) { - print 'Waiting ' . POLL_INTERVAL . - " secs before hitting Twitter again.\n"; + common_debug('Waiting ' . POLL_INTERVAL . + ' secs before hitting Twitter again.'); } sleep(POLL_INTERVAL); @@ -155,14 +144,16 @@ class TwitterStatusFetcher extends Daemon $cnt = $flink->find(); if (defined('SCRIPT_DEBUG')) { - print "Updating Twitter friends subscriptions for $cnt users.\n"; + common_debug('Updating Twitter friends subscriptions' . + " for $cnt users."); } $flinks = array(); while ($flink->fetch()) { - if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { + if (($flink->noticesync & FOREIGN_NOTICE_RECV) == + FOREIGN_NOTICE_RECV) { $flinks[] = clone($flink); } } @@ -187,30 +178,28 @@ class TwitterStatusFetcher extends Daemon { if (empty($flink)) { - common_log(LOG_WARNING, "Can't retrieve Foreign_link for foreign ID $fid"); - if (defined('SCRIPT_DEBUG')) { - print "Can't retrieve Foreign_link for foreign ID $fid\n"; - } + common_log(LOG_WARNING, + "Can't retrieve Foreign_link for foreign ID $fid"); return; } $fuser = $flink->getForeignUser(); if (empty($fuser)) { - common_log(LOG_WARNING, "Unmatched user for ID " . $flink->user_id); - if (defined('SCRIPT_DEBUG')) { - print "Unmatched user for ID $flink->user_id\n"; - } + common_log(LOG_WARNING, "Unmatched user for ID " . + $flink->user_id); return; } - common_debug('Trying to get timeline for Twitter user ' . - "$fuser->nickname ($flink->foreign_id)."); if (defined('SCRIPT_DEBUG')) { - print 'Trying to get timeline for Twitter user ' . - "$fuser->nickname ($flink->foreign_id).\n"; + common_debug('Trying to get timeline for Twitter user ' . + "$fuser->nickname ($flink->foreign_id)."); } + // XXX: Biggest remaining issue - How do we know at which status + // to start importing? How many statuses? Right now I'm going + // with the default last 20. + $url = 'http://twitter.com/statuses/friends_timeline.json'; $timeline_json = get_twitter_data($url, $fuser->nickname, @@ -220,18 +209,19 @@ class TwitterStatusFetcher extends Daemon if (empty($timeline)) { common_log(LOG_WARNING, "Empty timeline."); - if (defined('SCRIPT_DEBUG')) { - print "Empty timeline!\n"; - } return; } foreach ($timeline as $status) { - // Hacktastic: filter out stuff coming from Laconica + // Hacktastic: filter out stuff coming from this Laconica $source = mb_strtolower(common_config('integration', 'source')); if (preg_match("/$source/", mb_strtolower($status->source))) { + if (defined('SCRIPT_DEBUG')) { + common_debug('Skipping import of status ' . $status->id . + ' with source ' . $source); + } continue; } @@ -239,7 +229,6 @@ class TwitterStatusFetcher extends Daemon } // Okay, record the time we synced with Twitter for posterity - $flink->last_noticesync = common_sql_now(); $flink->update(); } @@ -250,18 +239,14 @@ class TwitterStatusFetcher extends Daemon $profile = Profile::staticGet($id); if (!$profile) { - common_log(LOG_ERR, 'Problem saving notice. No associated Profile.'); - if (defined('SCRIPT_DEBUG')) { - print "Problem saving notice. No associated Profile.\n"; - } + common_log(LOG_ERR, + 'Problem saving notice. No associated Profile.'); return null; } $uri = 'http://twitter.com/' . $status->user->screen_name . '/status/' . $status->id; - // Skip save if notice source is Laconica or Identi.ca? - $notice = Notice::staticGet('uri', $uri); // check to see if we've already imported the status @@ -290,21 +275,23 @@ class TwitterStatusFetcher extends Daemon if (!$notice_id) { common_log_db_error($notice, 'INSERT', __FILE__); if (defined('SCRIPT_DEBUG')) { - print "Could not save notice!\n"; + common_debug('Could not save notice!'); } } - // XXX: Figure out a better way to link replies? + // XXX: Figure out a better way to link Twitter replies? $notice->saveReplies(); - // XXX: Do we want to polute our tag cloud with hashtags from Twitter? + // XXX: Do we want to polute our tag cloud with + // hashtags from Twitter? $notice->saveTags(); $notice->saveGroups(); $notice->query('COMMIT'); if (defined('SCRIPT_DEBUG')) { - print "Saved status $status->id as notice $notice->id.\n"; + common_debug("Saved status $status->id" . + " as notice $notice->id."); } } @@ -327,18 +314,19 @@ class TwitterStatusFetcher extends Daemon $profile = Profile::staticGet('profileurl', $profileurl); if ($profile) { - common_debug("Profile for $profile->nickname found."); + if (defined('SCRIPT_DEBUG')) { + common_debug("Profile for $profile->nickname found."); + } // Check to see if the user's Avatar has changed $this->checkAvatar($user, $profile); + return $profile->id; } else { - $debugmsg = 'Adding profile and remote profile ' . - "for Twitter user: $profileurl\n"; - common_debug($debugmsg, __FILE__); if (defined('SCRIPT_DEBUG')) { - print $debugmsg; + common_debug('Adding profile and remote profile ' . + "for Twitter user: $profileurl"); } $profile = new Profile(); @@ -356,10 +344,6 @@ class TwitterStatusFetcher extends Daemon if (empty($id)) { common_log_db_error($profile, 'INSERT', __FILE__); - if (defined('SCRIPT_DEBUG')) { - print 'Could not insert Profile: ' . - common_log_objstring($profile) . "\n"; - } $profile->query("ROLLBACK"); return false; } @@ -379,10 +363,6 @@ class TwitterStatusFetcher extends Daemon if (empty($rid)) { common_log_db_error($profile, 'INSERT', __FILE__); - if (defined('SCRIPT_DEBUG')) { - print 'Could not insert Remote_profile: ' . - common_log_objstring($remote_pro) . "\n"; - } $profile->query("ROLLBACK"); return false; } @@ -408,13 +388,10 @@ class TwitterStatusFetcher extends Daemon if ($newname != $oldname) { - common_debug("Avatar for Twitter user $profile->nickname has changed."); - common_debug("old: $oldname new: $newname"); - if (defined('SCRIPT_DEBUG')) { - print "Avatar for Twitter user $user->id has changed.\n"; - print "old: $oldname\n"; - print "new: $newname\n"; + common_debug('Avatar for Twitter user ' . + "$profile->nickname has changed."); + common_debug("old: $oldname new: $newname"); } $img_root = substr($path_parts['basename'], 0, -11); @@ -472,26 +449,21 @@ class TwitterStatusFetcher extends Daemon $this->newAvatar($id, $size, $mediatype, $filename); } else { common_log(LOG_WARNING, "Problem fetching Avatar: $url", __FILE__); - if (defined('SCRIPT_DEBUG')) { - print "Problem fetching Avatar: $url\n"; - } } } } function updateAvatar($profile_id, $size, $mediatype, $filename) { - common_debug("Updating avatar: $size"); if (defined('SCRIPT_DEBUG')) { - print "Updating avatar: $size\n"; + common_debug("Updating avatar: $size"); } $profile = Profile::staticGet($profile_id); if (!$profile) { - common_debug("Couldn't get profile: $profile_id!"); if (defined('SCRIPT_DEBUG')) { - print "Couldn't get profile: $profile_id!\n"; + common_debug("Couldn't get profile: $profile_id!"); } return; } @@ -500,7 +472,9 @@ class TwitterStatusFetcher extends Daemon $avatar = $profile->getAvatar($sizes[$size]); if ($avatar) { - common_debug("Deleting $size avatar for $profile->nickname."); + if (defined('SCRIPT_DEBUG')) { + common_debug("Deleting $size avatar for $profile->nickname."); + } @unlink(INSTALLDIR . '/avatar/' . $avatar->filename); $avatar->delete(); } @@ -538,9 +512,8 @@ class TwitterStatusFetcher extends Daemon $avatar->filename = $filename; $avatar->url = Avatar::url($filename); - common_debug("new filename: $avatar->url"); if (defined('SCRIPT_DEBUG')) { - print "New filename: $avatar->url\n"; + common_debug("new filename: $avatar->url"); } $avatar->created = common_sql_now(); @@ -549,16 +522,11 @@ class TwitterStatusFetcher extends Daemon if (!$id) { common_log_db_error($avatar, 'INSERT', __FILE__); - if (defined('SCRIPT_DEBUG')) { - print "Could not insert avatar!\n"; - } - return null; } - common_debug("Saved new $size avatar for $profile_id."); if (defined('SCRIPT_DEBUG')) { - print "Saved new $size avatar for $profile_id.\n"; + common_debug("Saved new $size avatar for $profile_id."); } return $id; @@ -573,15 +541,11 @@ class TwitterStatusFetcher extends Daemon $out = fopen($avatarfile, 'wb'); if (!$out) { common_log(LOG_WARNING, "Couldn't open file $filename", __FILE__); - if (defined('SCRIPT_DEBUG')) { - print "Couldn't open file! $filename\n"; - } return false; } - common_debug("Fetching avatar: $url", __FILE__); if (defined('SCRIPT_DEBUG')) { - print "Fetching avatar from Twitter: $url\n"; + common_debug("Fetching avatar: $url"); } $ch = curl_init(); From bc190595d1dfd56bf7e68597b3d574909eb27260 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 02:07:31 -0700 Subject: [PATCH 464/503] Added TwitterStatusFetcher into daemon startup and shutdown subsystem --- config.php.sample | 3 +++ lib/common.php | 2 ++ scripts/getvaliddaemons.php | 3 +++ scripts/stopdaemons.sh | 2 +- scripts/twitterstatusfetcher.php | 10 ++++++---- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/config.php.sample b/config.php.sample index b8ed45fa83..6d6a9b533a 100644 --- a/config.php.sample +++ b/config.php.sample @@ -150,6 +150,9 @@ $config['sphinx']['port'] = 3312; #$config['memcached']['server'] = 'localhost'; #$config['memcached']['port'] = 11211; +# Enable bidirectional Twitter bridge +#$config['twitterbridge']['enabled'] = true; + #Twitter integration source attribute. Note: default is Laconica #$config['integration']['source'] = 'Laconica'; diff --git a/lib/common.php b/lib/common.php index 00e5b0bc29..abdc22c0e3 100644 --- a/lib/common.php +++ b/lib/common.php @@ -143,6 +143,8 @@ $config = array('piddir' => '/var/run', 'user' => false, 'group' => false), + 'twitterbridge' => + array('enabled' => false), 'integration' => array('source' => 'Laconica', # source attribute for Twitter 'taguri' => $_server.',2009'), # base for tag URIs diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php index 482e63af70..a10233e69f 100755 --- a/scripts/getvaliddaemons.php +++ b/scripts/getvaliddaemons.php @@ -44,6 +44,9 @@ if(common_config('xmpp','enabled')) { if(common_config('memcached','enabled')) { echo "memcachedqueuehandler.php "; } +if(common_config('twitterbridge','enabled')) { + echo "twitterstatusfetcher.php "; +} echo "ombqueuehandler.php "; echo "twitterqueuehandler.php "; echo "facebookqueuehandler.php "; diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index f6d71eddfb..764037e8ff 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -25,7 +25,7 @@ DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ - memcachehandler inboxhandler; do + memcachehandler inboxhandler twitterstatusfetcher; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index e8819f6651..9dfadc7606 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -32,7 +32,7 @@ define('LACONICA', true); define('MAXCHILDREN', 2); define('POLL_INTERVAL', 60); // in seconds -// Uncomment this to get useful console output +// Uncomment this to get useful logging define('SCRIPT_DEBUG', true); require_once(INSTALLDIR . '/lib/common.php'); @@ -45,7 +45,7 @@ class TwitterStatusFetcher extends Daemon function name() { - return 'twitterstatusfetcher'; + return ('twitterstatusfetcher.generic'); } function run() @@ -130,7 +130,9 @@ class TwitterStatusFetcher extends Daemon ' secs before hitting Twitter again.'); } - sleep(POLL_INTERVAL); + if (POLL_INTERVAL > 0) { + sleep(POLL_INTERVAL); + } } while (true); } @@ -282,7 +284,7 @@ class TwitterStatusFetcher extends Daemon // XXX: Figure out a better way to link Twitter replies? $notice->saveReplies(); - // XXX: Do we want to polute our tag cloud with + // XXX: Do we want to pollute our tag cloud with // hashtags from Twitter? $notice->saveTags(); $notice->saveGroups(); From 5771f413bb28502540d3bc017bc58433e9b0abf9 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 02:08:49 -0700 Subject: [PATCH 465/503] Fil's Patch to DB_DataObject to make it reconnect to the DB if there's no connection. This patch has been added upstream and will be in the next release, but I need it now for the bidirectional bridge to work. --- extlib/DB/DataObject.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/extlib/DB/DataObject.php b/extlib/DB/DataObject.php index b1a1a4e218..0c6a13dc28 100644 --- a/extlib/DB/DataObject.php +++ b/extlib/DB/DataObject.php @@ -2357,6 +2357,8 @@ class DB_DataObject extends DB_DataObject_Overload $t= explode(' ',microtime()); $_DB_DATAOBJECT['QUERYENDTIME'] = $time = $t[0]+$t[1]; + + do { if ($_DB_driver == 'DB') { $result = $DB->query($string); @@ -2374,8 +2376,19 @@ class DB_DataObject extends DB_DataObject_Overload break; } } - - + + // try to reconnect, at most 3 times + $again = false; + if (is_a($result, 'PEAR_Error') + AND $result->getCode() == DB_ERROR_NODBSELECTED + AND $cpt++<3) { + $DB->disconnect(); + sleep(1); + $DB->connect($DB->dsn); + $again = true; + } + + } while ($again); if (is_a($result,'PEAR_Error')) { if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { From 4b0e5ff271d4ac0af3256b2716f1e1362ddb02d8 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 14:07:03 -0700 Subject: [PATCH 466/503] Added Twitter to notice sources --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index ce44f32354..e6e2180a57 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -43,6 +43,7 @@ VALUES ('twidge','Twidge','http://software.complete.org/twidge', now()), ('twidroid','twidroid','http://www.twidroid.com/', now()), ('twittelator','Twittelator','http://www.stone.com/iPhone/Twittelator/', now()), + ('twitter','Twitter','http://twitter.com/', now()), ('twitterfeed','twitterfeed','http://twitterfeed.com/', now()), ('twitterphoto','TwitterPhoto','http://richfish.org/twitterphoto/', now()), ('twitterpm','Net::Twitter','http://search.cpan.org/dist/Net-Twitter/', now()), From fbf23ae0ee4c8c63e80e3511aa7fce980b8d1ed5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 14:41:53 -0700 Subject: [PATCH 467/503] Only show import friends timeline option if bidirectional bridge enabled --- actions/twittersettings.php | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/actions/twittersettings.php b/actions/twittersettings.php index 580d9ecf76..1bce576951 100644 --- a/actions/twittersettings.php +++ b/actions/twittersettings.php @@ -158,13 +158,22 @@ class TwittersettingsAction extends ConnectSettingsAction ($flink->friendsync & FOREIGN_FRIEND_RECV) : false); $this->elementEnd('li'); - $this->elementStart('li'); - $this->checkbox('noticerecv', - _('Import my Friends Timeline.'), - ($flink) ? - ($flink->noticesync & FOREIGN_NOTICE_RECV) : - false); - $this->elementEnd('li'); + + if (common_config('twitterbridge','enabled')) { + $this->elementStart('li'); + $this->checkbox('noticerecv', + _('Import my Friends Timeline.'), + ($flink) ? + ($flink->noticesync & FOREIGN_NOTICE_RECV) : + false); + $this->elementEnd('li'); + } else { + // preserve setting even if bidrection bridge toggled off + if ($flink && ($flink->noticesync & FOREIGN_NOTICE_RECV)) { + $this->hidden('noticerecv', true, 'noticerecv'); + } + } + $this->elementEnd('ul'); if ($flink) { From 3e7b1e69e3e97ac007465376b62084f10bcf97ca Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 28 Apr 2009 17:08:20 -0700 Subject: [PATCH 468/503] Added dirty dates to Foreign_link --- classes/Foreign_link.php | 2 ++ classes/laconica.ini | 2 ++ db/laconica.sql | 2 ++ 3 files changed, 6 insertions(+) diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php index afc0e21804..af2b3f189d 100644 --- a/classes/Foreign_link.php +++ b/classes/Foreign_link.php @@ -17,6 +17,8 @@ class Foreign_link extends Memcached_DataObject public $noticesync; // tinyint(1) not_null default_1 public $friendsync; // tinyint(1) not_null default_2 public $profilesync; // tinyint(1) not_null default_1 + public $last_noticesync; // datetime() + public $last_friendsync; // datetime() public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP diff --git a/classes/laconica.ini b/classes/laconica.ini index 529454d99b..c054195884 100755 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -55,6 +55,8 @@ credentials = 2 noticesync = 145 friendsync = 145 profilesync = 145 +last_noticesync = 14 +last_friendsync = 14 created = 142 modified = 384 diff --git a/db/laconica.sql b/db/laconica.sql index 5b57494d98..c9730098e3 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -289,6 +289,8 @@ create table foreign_link ( noticesync tinyint not null default 1 comment 'notice synchronization, bit 1 = sync outgoing, bit 2 = sync incoming, bit 3 = filter local replies', friendsync tinyint not null default 2 comment 'friend synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', profilesync tinyint not null default 1 comment 'profile synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', + last_noticesync datetime default null comment 'last time notices were imported', + last_friendsync datetime default null comment 'last time friends were imported', created datetime not null comment 'date this record was created', modified timestamp comment 'date this record was modified', From 11e0db8c2cec18337fd960ccda055dd14d89f9d7 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 18:22:14 -0700 Subject: [PATCH 469/503] Twitter friends sync now does 25 users at a time and uses last_friendsync field to prioritize --- actions/twittersettings.php | 4 +++- scripts/synctwitterfriends.php | 38 ++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/actions/twittersettings.php b/actions/twittersettings.php index 45725d3ff4..0b98eef591 100644 --- a/actions/twittersettings.php +++ b/actions/twittersettings.php @@ -261,7 +261,7 @@ class TwittersettingsAction extends ConnectSettingsAction 'alt' => ($other->fullname) ? $other->fullname : $other->nickname)); - + $this->element('span', 'fn nickname', $other->nickname); $this->elementEnd('a'); $this->elementEnd('li'); @@ -375,6 +375,8 @@ class TwittersettingsAction extends ConnectSettingsAction if ($friendsync) { save_twitter_friends($user, $twit_user->id, $screen_name, $password); + $flink->last_friendsync = common_sql_now(); + $flink->update(); } $this->showForm(_('Twitter settings saved.'), true); diff --git a/scripts/synctwitterfriends.php b/scripts/synctwitterfriends.php index 794301f0f0..bd08ba58d6 100755 --- a/scripts/synctwitterfriends.php +++ b/scripts/synctwitterfriends.php @@ -32,8 +32,25 @@ define('LACONICA', true); require_once(INSTALLDIR . '/lib/common.php'); +// Make a lockfile +$lockfilename = lockFilename(); +if (!($lockfile = @fopen($lockfilename, "w"))) { + print "Already running... exiting.\n"; + exit(1); +} + +// Obtain an exlcusive lock on file (will fail if script is already going) +if (!@flock( $lockfile, LOCK_EX | LOCK_NB, &$wouldblock) || $wouldblock) { + // Script already running - abort + @fclose($lockfile); + print "Already running... exiting.\n"; + exit(1); +} + $flink = new Foreign_link(); $flink->service = 1; // Twitter +$flink->orderBy('last_friendsync'); +$flink->limit(25); // sync this many users during this run $cnt = $flink->find(); print "Updating Twitter friends subscriptions for $cnt users.\n"; @@ -60,8 +77,11 @@ while ($flink->fetch()) { continue; } - $result = save_twitter_friends($user, $fuser->id, - $fuser->nickname, $flink->credentials); + save_twitter_friends($user, $fuser->id, $fuser->nickname, $flink->credentials); + + $flink->last_friendsync = common_sql_now(); + $flink->update(); + if (defined('SCRIPT_DEBUG')) { print "\nDONE\n"; } else { @@ -70,4 +90,18 @@ while ($flink->fetch()) { } } +function lockFilename() +{ + $piddir = common_config('daemon', 'piddir'); + if (!$piddir) { + $piddir = '/var/run'; + } + + return $piddir . '/synctwitterfriends.lock'; +} + +// Cleanup +fclose($lockfile); +unlink($lockfilename); + exit(0); From 9a8095079dc602c7f2b74e48237445d682844de6 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Fri, 8 May 2009 08:14:50 +0100 Subject: [PATCH 470/503] PostgreSQL - added dirty dates to Foreign_link - see 3e7b1e69e3e97ac007465376b62084f10bcf97ca --- db/laconica_pg.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/laconica_pg.sql b/db/laconica_pg.sql index f879d7936f..a27a616f24 100644 --- a/db/laconica_pg.sql +++ b/db/laconica_pg.sql @@ -291,6 +291,8 @@ create table foreign_link ( noticesync int not null default 1 /* comment 'notice synchronisation, bit 1 = sync outgoing, bit 2 = sync incoming, bit 3 = filter local replies' */, friendsync int not null default 2 /* comment 'friend synchronisation, bit 1 = sync outgoing, bit 2 = sync incoming */, profilesync int not null default 1 /* comment 'profile synchronization, bit 1 = sync outgoing, bit 2 = sync incoming' */, + last_noticesync timestamp default null /* comment 'last time notices were imported' */, + last_friendsync timestamp default null /* comment 'last time friends were imported' */, created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */, modified timestamp /* comment 'date this record was modified' */, From 8fc8eaa1b6199d74f0e17197650c6316b4594203 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Sun, 10 May 2009 23:14:42 +0000 Subject: [PATCH 471/503] Init biz theme Design is similar (inspired) to http://drupal.org/project/acquia_marina Two of the background illustrations are reused. --- theme/biz/css/base.css | 1170 +++++++++++++++++ theme/biz/css/display.css | 252 ++++ theme/biz/css/ie.css | 9 + theme/biz/default-avatar-mini.png | Bin 0 -> 646 bytes theme/biz/default-avatar-profile.png | Bin 0 -> 2853 bytes theme/biz/default-avatar-stream.png | Bin 0 -> 1487 bytes .../images/illustrations/illu_pattern-01.png | Bin 0 -> 935 bytes .../images/illustrations/illu_pattern-02.png | Bin 0 -> 9498 bytes theme/biz/logo.png | Bin 0 -> 4988 bytes 9 files changed, 1431 insertions(+) create mode 100644 theme/biz/css/base.css create mode 100644 theme/biz/css/display.css create mode 100644 theme/biz/css/ie.css create mode 100644 theme/biz/default-avatar-mini.png create mode 100644 theme/biz/default-avatar-profile.png create mode 100644 theme/biz/default-avatar-stream.png create mode 100644 theme/biz/images/illustrations/illu_pattern-01.png create mode 100644 theme/biz/images/illustrations/illu_pattern-02.png create mode 100644 theme/biz/logo.png diff --git a/theme/biz/css/base.css b/theme/biz/css/base.css new file mode 100644 index 0000000000..22bbced08c --- /dev/null +++ b/theme/biz/css/base.css @@ -0,0 +1,1170 @@ +/** theme: biz base + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +* { margin:0; padding:0; } +img { display:block; border:0; } +a abbr { cursor: pointer; border-bottom:0; } +table { border-collapse:collapse; } +ol { list-style-position:inside; } +html { font-size: 87.5%; background-color:#fff; height:100%; } +body { +background-color:#fff; +color:#000; +font-family:sans-serif; +font-size:1em; +line-height:1.65; +position:relative; +} +h1,h2,h3,h4,h5,h6 { +margin-bottom:7px; +overflow:hidden; +} +h1 { +font-size:1.4em; +margin-bottom:18px; +} +#showstream h1 { display:none; } +h2 { font-size:1.3em; } +h3 { font-size:1.2em; } +h4 { font-size:1.1em; } +h5 { font-size:1em; } +h6 { font-size:0.9em; } + +caption { +font-weight:bold; +} +legend { +font-weight:bold; +font-size:1.3em; +} +input, textarea, select, option { +padding:4px; +font-family:sans-serif; +font-size:1em; +} +input, textarea, select { +border-width:2px; +border-style: solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +input.submit { +font-weight:bold; +cursor:pointer; +} +textarea { +overflow:auto; +} +option { +padding-bottom:0; +} +fieldset { +padding:0; +border:0; +} +form ul li { +list-style-type:none; +margin:0 0 18px 0; +} +form label { +font-weight:bold; +} +input.checkbox { +position:relative; +top:2px; +left:0; +border:0; +} + +.error, +.success { +padding:4px 1.55%; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +margin-bottom:18px; +} +form label.submit { +display:none; +} + +.form_settings { +clear:both; +} + +.form_settings fieldset { +margin-bottom:29px; +} +.form_settings input.remove { +margin-left:11px; +} +.form_settings .form_data li { +width:100%; +float:left; +} +.form_settings .form_data label { +float:left; +} +.form_settings .form_data textarea, +.form_settings .form_data select, +.form_settings .form_data input { +margin-left:11px; +float:left; +} +.form_settings .form_data input.submit { +margin-left:0; +} + +.form_settings label { +margin-top:2px; +width:113px; +} + +.form_actions label { +display:none; +} +.form_guide { +font-style:italic; +} + +.form_settings #settings_autosubscribe label { +display:inline; +font-weight:bold; +} + +#form_settings_profile legend, +#form_login legend, +#form_register legend, +#form_password legend, +#form_settings_avatar legend, +#newgroup legend, +#editgroup legend, +#form_tag_user legend, +#form_remote_subscribe legend, +#form_openid_login legend, +#form_search legend, +#form_invite legend, +#form_notice_delete legend, +#form_password_recover legend, +#form_password_change legend { +display:none; +} + +.form_settings .form_data p.form_guide { +clear:both; +margin-left:124px; +margin-bottom:0; +} + +.form_settings p { +margin-bottom:11px; +} + +.form_settings input.checkbox { +margin-top:3px; +margin-left:0; +} +.form_settings label.checkbox { +font-weight:normal; +margin-top:0; +margin-right:0; +margin-left:11px; +float:left; +width:90%; +} + + +#form_login p.form_guide, +#form_register #settings_rememberme p.form_guide, +#form_openid_login #settings_rememberme p.form_guide, +#settings_twitter_remove p.form_guide, +#form_search ul.form_data #q { +margin-left:0; +} + +.form_settings .form_note { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +padding:0 7px; +} + + +.form_settings input.form_action-secondary { +margin-left:29px; +padding:0; +} + +#form_search .submit { +margin-left:11px; +} + +address { +float:left; +margin-bottom:18px; +margin-left:18px; +} +address.vcard img.logo { +margin-right:0; +} +address .fn { +font-weight:bold; +} +address img + .fn { +display:none; +} + +#header { +width:100%; +position:relative; +float:left; +padding-top:18px; +margin-bottom:18px; +} + +#site_nav_global_primary { +float:left; +margin-right:18px; +margin-bottom:11px; +width:50%; +} +#site_nav_global_primary ul li { +display:inline; +margin-right:11px; +} + +.system_notice dt { +font-weight:bold; +text-transform:uppercase; +display:none; +} + +#site_notice { +float:right; +clear:right; +margin-top:7px; +margin-right:18px; +width:24%; +} +#page_notice { +clear:both; +margin-bottom:18px; +} + + +#anon_notice { +float:left; +width:45.4%; +/* +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-width:2px; +border-style:solid; +*/ +line-height:1.5; +font-size:1.1em; +font-weight:bold; +} + + +#footer { +float:left; +width:64%; +padding:18px; +} + +#site_nav_local_views { +width:14.5%; +float:left; +} +#site_nav_local_views dt { +display:none; +} +#site_nav_local_views li { +list-style-type:none; +} +#site_nav_local_views a { +display:block; +text-decoration:none; +padding:4px 11px; +-moz-border-radius-topleft:4px; +-moz-border-radius-bottomleft:4px; +-webkit-border-top-left-radius:4px; +-webkit-border-bottom-left-radius:4px; +border-width:1px; +border-style:solid; +border-right:0; +text-shadow: 2px 2px 2px #ddd; +font-weight:bold; +} +#site_nav_local_views .nav { +float:left; +width:100%; +} + +#site_nav_global_primary dt, +#site_nav_global_secondary dt { +display:none; +} + +#site_nav_global_secondary { +margin-bottom:11px; +} + +#site_nav_global_secondary ul li { +display:inline; +margin-right:11px; +} +#export_data li a { +padding-left:20px; +} +#export_data li a.foaf { +padding-left:30px; +} +#export_data li a.export_vcard { +padding-left:28px; +} + +#export_data ul { +display:inline; +} +#export_data li { +list-style-type:none; +display:inline; +margin-left:11px; +} +#export_data li:first-child { +margin-left:0; +} + +#licenses { +font-size:0.9em; +} + +#licenses dt { +font-weight:bold; +display:none; +} +#licenses dd { +margin-bottom:11px; +line-height:1.5; +} + +#site_content_license_cc { +margin-bottom:0; +} +#site_content_license_cc img { +display:inline; +vertical-align:top; +margin-right:4px; +} + +#wrap { +margin:0 auto; +width:100%; +min-width:760px; +max-width:1003px; +overflow:hidden; +} + +#core { +position:relative; +width:100%; +float:left; +margin-bottom:1em; +} + +#content { +width:51.009%; +min-height:259px; +padding:1.795%; +float:left; +border-radius:7px; +-moz-border-radius:7px; +-moz-border-radius-topleft:0; +-webkit-border-radius:7px; +-webkit-border-top-left-radius:0; +border-style:solid; +border-width:1px; +} +#shownotice #content { +min-height:0; +} + +#content_inner { +position:relative; +width:100%; +float:left; +} + +#aside_primary { +width:29.917%; +min-height:259px; +float:left; +margin-left:0.385%; +} + +#form_notice { +width:45.664%; +float:left; +position:relative; +line-height:1; +} +#form_notice fieldset { +border:0; +padding:0; +position:relative; +} +#form_notice legend { +display:none; +} +#form_notice textarea { +float:left; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +width:80.789%; +height:67px; +line-height:1.5; +padding:7px 7px 16px 7px; +} +#form_notice label { +display:block; +float:left; +font-size:1.3em; +margin-bottom:7px; +} +#form_notice #notice_submit label { +display:none; +} +#form_notice .form_note { +position:absolute; +top:99px; +right:98px; +z-index:9; +} +#form_notice .form_note dt { +font-weight:bold; +display:none; +} +#notice_text-count { +font-weight:bold; +line-height:1.15; +padding:1px 2px; +} +#form_notice #notice_action-submit { +width:14%; +height:47px; +padding:0; +position:absolute; +bottom:0; +right:0; +} +#form_notice label[for=to] { +margin-top:7px; +} +#form_notice select[id=to] { +margin-bottom:7px; +margin-left:18px; +float:left; +} +#form_notice .error { +float:left; +clear:both; +width:96.9%; +margin-bottom:0; +line-height:1.618; +} + +/* entity_profile */ +.entity_profile { +position:relative; +width:67.702%; +min-height:123px; +float:left; +margin-bottom:18px; +margin-left:0; +overflow:hidden; +} +.entity_profile dt, +#entity_statistics dt { +font-weight:bold; +} +.entity_profile dd { +display:inline; +} + +.entity_profile .entity_depiction { +float:left; +width:96px; +margin-right:18px; +margin-bottom:18px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:113px; +margin-bottom:4px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname { +margin-left:11px; +display:inline; +font-weight:bold; +} +.entity_profile .entity_nickname { +margin-left:0; +} + +.entity_profile .entity_fn dd:before { +content: "("; +font-weight:normal; +} +.entity_profile .entity_fn dd:after { +content: ")"; +font-weight:normal; +} + +.entity_profile dt { +display:none; +} +.entity_profile h2 { +display:none; +} +/* entity_profile */ + + +/*entity_actions*/ +.entity_actions { +float:right; +margin-left:4.35%; +max-width:25%; +} +.entity_actions h2 { +display:none; +} +.entity_actions ul { +list-style-type:none; +} +.entity_actions li { +margin-bottom:4px; +} +.entity_actions li:first-child { +border-top:0; +} +.entity_actions fieldset { +border:0; +padding:0; +} +.entity_actions legend { +display:none; +} + +.entity_actions input.submit { +display:block; +text-align:left; +width:100%; +} +.entity_actions a, +.entity_nudge p, +.entity_remote_subscribe { +text-decoration:none; +font-weight:bold; +display:block; +} + +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.entity_edit a, +.form_user_nudge input.submit, +.entity_nudge p { +border:0; +padding-left:20px; +} + +.entity_edit a, +.entity_send-a-message a, +.entity_nudge p { +padding:4px 4px 4px 23px; +} + +.entity_remote_subscribe { +padding:4px; +border-width:2px; +border-style:solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.entity_actions .accept { +margin-bottom:18px; +} + +.entity_tags ul { +list-style-type:none; +display:inline; +} +.entity_tags li { +display:inline; +margin-right:4px; +} + +.aside .section { +margin-bottom:18px; +clear:both; +float:left; +width:87.985%; +padding:6%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-width:1px; +border-style:solid; +} +.aside .section h2 { +text-transform:uppercase; +font-size:1em; +} + +#entity_statistics dt, +#entity_statistics dd { +display:inline; +} +#entity_statistics dt:after { +content: ":"; +} + +.section ul.entities { +float:left; +width:100%; +} +.section .entities li { +list-style-type:none; +float:left; +margin-right:7px; +margin-bottom:7px; +} +.section .entities li .photo { +margin-right:0; +margin-bottom:0; +} +.section .entities li .fn { +display:none; +} + +.aside .section p, +.aside .section .more { +clear:both; +} + +.profile .entity_profile { +margin-bottom:0; +min-height:60px; +} + + +.profile .form_group_join legend, +.profile .form_group_leave legend, +.profile .form_user_subscribe legend, +.profile .form_user_unsubscribe legend { +display:none; +} + +.profiles { +list-style-type:none; +} +.profile .entity_profile .entity_location { +width:auto; +clear:none; +margin-left:11px; +} +.profile .entity_profile dl, +.profile .entity_profile dd { +display:inline; +float:none; +} +.profile .entity_profile .entity_note, +.profile .entity_profile .entity_url, +.profile .entity_profile .entity_tags, +.profile .entity_profile .form_subscription_edit { +margin-left:59px; +clear:none; +display:block; +width:auto; +} +.profile .entity_profile .entity_tags dt { +display:inline; +margin-right:11px; +} + + +.profile .entity_profile .form_subscription_edit label { +font-weight:normal; +margin-right:11px; +} + + +/* NOTICE */ +.notice, +.profile { +position:relative; +padding-top:11px; +padding-bottom:11px; +clear:both; +float:left; +width:100%; +border-top-width:1px; +border-top-style:dotted; +} +.notices li { +list-style-type:none; +} +.notices li.hover { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +/* NOTICES */ +#notices_primary { +float:left; +width:100%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +} +#notices_primary h2 { +display:none; +} +.notice-data a span { +display:block; +padding-left:28px; +} + +.notice .author { +margin-right:11px; +} + +.fn { +overflow:hidden; +} + +.notice .author .fn { +font-weight:bold; +} + +.vcard .photo { +display:inline; +margin-right:11px; +float:left; +} +#shownotice .vcard .photo { +margin-bottom:4px; +} +.vcard .url { +text-decoration:none; +} +.vcard .url:hover { +text-decoration:underline; +} + +.notice .entry-title { +float:left; +width:100%; +overflow:hidden; +} +#shownotice .notice .entry-title { +font-size:2.2em; +} + +.notice p.entry-content { +display:inline; +} + +#content .notice p.entry-content a:visited { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.notice p.entry-content .vcard a { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +.notice div.entry-content { +clear:left; +float:left; +font-size:0.95em; +margin-left:59px; +width:65%; +} +#showstream .notice div.entry-content, +#shownotice .notice div.entry-content { +margin-left:0; +} + +.notice .notice-options a, +.notice .notice-options input { +float:left; +font-size:1.025em; +} + +.notice div.entry-content dl, +.notice div.entry-content dt, +.notice div.entry-content dd { +display:inline; +} + +.notice div.entry-content .timestamp dt, +.notice div.entry-content .response dt { +display:none; +} +.notice div.entry-content .timestamp a { +display:inline-block; +} +.notice div.entry-content .device dt { +text-transform:lowercase; +} + + +.notice-options { +padding-left:2%; +float:left; +width:50%; +position:relative; +font-size:0.95em; +width:12.5%; +float:right; +} + +.notice-options a { +float:left; +} +.notice-options .notice_delete, +.notice-options .notice_reply, +.notice-options .form_favor, +.notice-options .form_disfavor { +position:absolute; +top:0; +} +.notice-options .form_favor, +.notice-options .form_disfavor { +left:0; +} +.notice-options .notice_reply { +left:29px; +} +.notice-options .notice_delete { +right:0; +} +.notice-options .notice_reply dt { +display:none; +} + +.notice-options input, +.notice-options a { +text-indent:-9999px; +outline:none; +} + +.notice-options .notice_reply a, +.notice-options input.submit { +display:block; +border:0; +} +.notice-options .notice_reply a, +.notice-options .notice_delete a { +text-decoration:none; +padding-left:16px; +} + +.notice-options form input.submit { +width:16px; +padding:2px 0; +} + +.notice-options .notice_delete dt, +.notice-options .form_favor legend, +.notice-options .form_disfavor legend { +display:none; +} +.notice-options .notice_delete fieldset, +.notice-options .form_favor fieldset, +.notice-options .form_disfavor fieldset { +border:0; +padding:0; +} + + +#usergroups #new_group { +float: left; +margin-right: 2em; +} +#new_group, #group_search { +margin-bottom:18px; +} +#new_group a { +padding-left:20px; +} + + +#filter_tags { +margin-bottom:11px; +float:left; +} +#filter_tags dt { +display:none; +} +#filter_tags ul { +list-style-type:none; +} +#filter_tags ul li { +float:left; +margin-left:7px; +padding-left:7px; +border-left-width:1px; +border-left-style:solid; +} +#filter_tags ul li.child_1 { +margin-left:0; +border-left:0; +padding-left:0; +} +#filter_tags ul li#filter_tags_all a { +font-weight:bold; +margin-top:7px; +float:left; +} + +#filter_tags ul li#filter_tags_item label { +margin-right:7px; +} +#filter_tags ul li#filter_tags_item label, +#filter_tags ul li#filter_tags_item select { +display:inline; +} +#filter_tags ul li#filter_tags_item p { +float:left; +margin-left:38px; +} +#filter_tags ul li#filter_tags_item input { +position:relative; +top:3px; +left:3px; +} + + + +.pagination { +float:left; +clear:both; +width:100%; +margin-top:18px; +} + +.pagination dt { +font-weight:bold; +display:none; +} + +.pagination .nav { +float:left; +width:100%; +list-style-type:none; +} + +.pagination .nav_prev { +float:left; +} +.pagination .nav_next { +float:right; +} + +.pagination a { +display:block; +text-decoration:none; +font-weight:bold; +padding:7px; +border-width:1px; +border-style:solid; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-radius:7px; +} + +.pagination .nav_prev a { +padding-left:30px; +} +.pagination .nav_next a { +padding-right:30px; +} +/* END: NOTICE */ + + +.hentry .entry-content p { +margin-bottom:18px; +} +.system_notice ul, +.instructions ul, +.hentry entry-content ol, +.hentry .entry-content ul { +list-style-position:inside; +} +.hentry .entry-content li { +margin-bottom:18px; +} +.hentry .entry-content li li { +margin-left:18px; +} + + + + +/* TOP_POSTERS */ +.section tbody td { +padding-right:11px; +padding-bottom:11px; +} +.section .vcard .photo { +margin-right:7px; +margin-bottom:0; +} + +.section .notice { +padding-top:7px; +padding-bottom:7px; +border-top:0; +} + +.section .notice:first-child { +padding-top:0; +} + +.section .notice .author { +margin-right:0; +} +.section .notice .author .fn { +display:none; +} + + +/* tagcloud */ +.tag-cloud { +list-style-type:none; +text-align:center; +} +.aside .tag-cloud { +font-size:0.8em; +} +.tag-cloud li { +display:inline; +margin-right:7px; +line-height:1.25; +} +.aside .tag-cloud li { +line-height:1.5; +} +.tag-cloud li a { +text-decoration:none; +} +#tagcloud.section dt { +text-transform:uppercase; +font-weight:bold; +} +.tag-cloud-1 { +font-size:1em; +} +.tag-cloud-2 { +font-size:1.25em; +} +.tag-cloud-3 { +font-size:1.75em; +} +.tag-cloud-4 { +font-size:2em; +} +.tag-cloud-5 { +font-size:2.25em; +} +.tag-cloud-6 { +font-size:2.75em; +} +.tag-cloud-7 { +font-size:3.25em; +} + +#publictagcloud #tagcloud.section dt { +display:none; +} + +#form_settings_photo .form_data { +clear:both; +} + +#form_settings_avatar li { +width:auto; +} +#form_settings_avatar input { +margin-left:0; +} +#avatar_original, +#avatar_preview { +float:left; +} +#avatar_preview { +margin-left:29px; +} +#avatar_preview_view { +height:96px; +width:96px; +margin-bottom:18px; +overflow:hidden; +} + +#settings_attach, +#form_settings_avatar .form_actions { +clear:both; +} + +#form_settings_avatar .form_actions { +margin-bottom:0; +} + +#form_settings_design #settings_design_color .form_data, +#form_settings_design #color-picker { +float:left; +} +#form_settings_design #settings_design_color .form_data { +width:400px; +margin-right:28px; +} + +.instructions ul { +list-style-position:inside; +} +.instructions p, +.instructions ul { +margin-bottom:18px; +} +.help dt { +display:none; +} +.guide { +clear:both; +} diff --git a/theme/biz/css/display.css b/theme/biz/css/display.css new file mode 100644 index 0000000000..a7d360c532 --- /dev/null +++ b/theme/biz/css/display.css @@ -0,0 +1,252 @@ +/** theme: biz + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +@import url(base.css); + +html { +background-color:#144A6E; +} +a:active { +background-color:#F4F7E7; +} +body { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +font-size:1em; +background:#144A6E url(../images/illustrations/illu_pattern-01.png) repeat-x; +} + +address { +margin-right:7.18%; +} + +input, textarea, select, option { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +} +input, textarea, select, +.entity_remote_subscribe { +border-color:#aaa; +} +#filter_tags ul li { +border-color:#ddd; +} + +.form_settings input.form_action-secondary { +background:none; +} + +input.submit, +#form_notice.warning #notice_text-count, +.form_settings .form_note, +.entity_remote_subscribe { +background-color:#9BB43E; +} + +input:focus, textarea:focus, select:focus, +#form_notice.warning #notice_data-text { +border-color:#9BB43E; +} +input.submit, +.entity_remote_subscribe, +#site_nav_local_views a { +color:#fff; +} + +a, +#site_nav_local_views .current a, +div.notice-options input, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.form_user_nudge input.submit, +.entity_nudge p, +.form_settings input.form_action-secondary { +color:#002E6E; +} + +#header a, +#footer a { +color:#87B4C8; +} + +.notice, +.profile { +border-top-color:#CEE1E9; +} +.section .profile { +border-top-color:#87B4C8; +} + +#content .notice p.entry-content a:visited { +background-color:#fcfcfc; +} +#content .notice p.entry-content .vcard a { +background-color:#fcfffc; +} + +.aside .section { +background-color:#F1F5F8; +background-position:100% 0; +background-image:url(../images/illustrations/illu_pattern-02.png); +background-repeat:no-repeat; +} + +#notice_text-count { +color:#333; +} +#form_notice.warning #notice_text-count { +color:#000; +} +#form_notice.processing #notice_action-submit { +background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +cursor:wait; +text-indent:-9999px; +} + +#content, +#site_nav_local_views a, +.aside .section { +border-color:#fff; +} +#content, +#site_nav_local_views .current a { +background-color:#fff; +} + +#site_nav_local_views a { +background-color:rgba(135, 180, 200, 0.3); +} +#site_nav_local_views a:hover { +background-color:rgba(255, 255, 255, 0.7); +} + +.error { +background-color:#F7E8E8; +} +.success { +background-color:#EFF3DC; +} + +#anon_notice { +color:#fff; +} + +#showstream #anon_notice { +} + +#export_data li a { +background-repeat:no-repeat; +background-position:0 45%; +} +#export_data li a.rss { +background-image:url(../../base/images/icons/icon_rss.png); +} +#export_data li a.atom { +background-image:url(../../base/images/icons/icon_atom.png); +} +#export_data li a.foaf { +background-image:url(../../base/images/icons/icon_foaf.gif); +} + +.entity_edit a, +.entity_send-a-message a, +.form_user_nudge input.submit, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_nudge p { +background-position: 0 40%; +background-repeat: no-repeat; +background-color:transparent; +} +.form_group_join input.submit, +.form_group_leave input.submit +.form_user_subscribe input.submit, +.form_user_unsubscribe input.submit { +background-color:#9BB43E; +color:#fff; +} +.form_user_unsubscribe input.submit, +.form_group_leave input.submit, +.form_user_authorization input.reject { +background-color:#87B4C8; +} + +.entity_edit a { +background-image:url(../../base/images/icons/twotone/green/edit.gif); +} +.entity_send-a-message a { +background-image:url(../../base/images/icons/twotone/green/quote.gif); +} +.entity_nudge p, +.form_user_nudge input.submit { +background-image:url(../../base/images/icons/twotone/green/mail.gif); +} +.form_user_block input.submit, +.form_user_unblock input.submit { +background-image:url(../../base/images/icons/twotone/green/shield.gif); +} + +/* NOTICES */ +.notices li.over { +background-color:#fcfcfc; +} + +.notice-options .notice_reply a, +.notice-options form input.submit { +background-color:transparent; +} +.notice-options .notice_reply a { +background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; +} +.notice-options form.form_favor input.submit { +background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +} +.notice-options form.form_disfavor input.submit { +background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +} +.notice-options .notice_delete a { +background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:0.4; +} +.notices li.hover div.entry-content, +.notices li.hover div.notice-options { +opacity:1; +} +div.entry-content { +color:#333; +} +div.notice-options a, +div.notice-options input { +font-family:sans-serif; +} +.notices li.hover { +background-color:#fcfcfc; +} +/*END: NOTICES */ + +#new_group a { +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; +} + +.pagination .nav_prev a, +.pagination .nav_next a { +background-repeat:no-repeat; +border-color:#CEE1E9; +} +.pagination .nav_prev a { +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); +background-position:10% 45%; +} +.pagination .nav_next a { +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); +background-position:90% 45%; +} diff --git a/theme/biz/css/ie.css b/theme/biz/css/ie.css new file mode 100644 index 0000000000..2f463bb44d --- /dev/null +++ b/theme/biz/css/ie.css @@ -0,0 +1,9 @@ +/* IE specific styles */ + +.notice-options input.submit { +color:#fff; +} + +#site_nav_local_views a { +background-color:#D0DFE7; +} diff --git a/theme/biz/default-avatar-mini.png b/theme/biz/default-avatar-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..38b8692b4a2f71c8de3d6a12b715df33aada5f7c GIT binary patch literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b literal 0 HcmV?d00001 diff --git a/theme/biz/default-avatar-profile.png b/theme/biz/default-avatar-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..f8357d4fc296271b837b3d9911cfbc133918ef2f GIT binary patch literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi literal 0 HcmV?d00001 diff --git a/theme/biz/images/illustrations/illu_pattern-01.png b/theme/biz/images/illustrations/illu_pattern-01.png new file mode 100644 index 0000000000000000000000000000000000000000..79bb46b60e0e05846031e864251da9aa576eb266 GIT binary patch literal 935 zcmV;Y16cftP)p(}BpEOetIV~!wSiW*RN z8dQ7~OmZx6ofS`YFLtFDQh6w7l^RlcCTEi(VvQzckt1P@FLa_VaiAh#iY#!S8BcaA zZk#T4q$p~bC1j5oPjxPJr6ppHC}xu@Zk`xTb1re7C1{l(TZAfbohxymCTElvQg|a{ zk0M};CTW%zPnh literal 0 HcmV?d00001 diff --git a/theme/biz/images/illustrations/illu_pattern-02.png b/theme/biz/images/illustrations/illu_pattern-02.png new file mode 100644 index 0000000000000000000000000000000000000000..4438b751afbf45bd4a4da6b8aafcc78373871918 GIT binary patch literal 9498 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 Date: Mon, 11 May 2009 04:04:56 +0000 Subject: [PATCH 472/503] Init pigeon thoughts theme. Inspired by http://csarven.ca/labs/csszengarden.com/pigeon-thoughts/zengarden-sample.html --- theme/pigeonthoughts/css/base.css | 1153 +++++++++++++++++ theme/pigeonthoughts/css/display.css | 295 +++++ theme/pigeonthoughts/css/ie.css | 9 + theme/pigeonthoughts/default-avatar-mini.png | Bin 0 -> 646 bytes .../pigeonthoughts/default-avatar-profile.png | Bin 0 -> 2853 bytes .../pigeonthoughts/default-avatar-stream.png | Bin 0 -> 1487 bytes .../images/illustrations/illu_pigeons-01.png | Bin 0 -> 72649 bytes .../images/illustrations/illu_pigeons-02.png | Bin 0 -> 3538 bytes theme/pigeonthoughts/logo.png | Bin 0 -> 4988 bytes 9 files changed, 1457 insertions(+) create mode 100644 theme/pigeonthoughts/css/base.css create mode 100644 theme/pigeonthoughts/css/display.css create mode 100644 theme/pigeonthoughts/css/ie.css create mode 100644 theme/pigeonthoughts/default-avatar-mini.png create mode 100644 theme/pigeonthoughts/default-avatar-profile.png create mode 100644 theme/pigeonthoughts/default-avatar-stream.png create mode 100644 theme/pigeonthoughts/images/illustrations/illu_pigeons-01.png create mode 100644 theme/pigeonthoughts/images/illustrations/illu_pigeons-02.png create mode 100644 theme/pigeonthoughts/logo.png diff --git a/theme/pigeonthoughts/css/base.css b/theme/pigeonthoughts/css/base.css new file mode 100644 index 0000000000..1797198200 --- /dev/null +++ b/theme/pigeonthoughts/css/base.css @@ -0,0 +1,1153 @@ +/** theme: pigeonthoughts base + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +* { margin:0; padding:0; } +img { display:block; border:0; } +a abbr { cursor: pointer; border-bottom:0; } +table { border-collapse:collapse; } +ol { list-style-position:inside; } +html { font-size: 87.5%; background-color:#fff; } +body { +background-color:#fff; +color:#000; +font-family:sans-serif; +font-size:1em; +line-height:1.65; +position:relative; +margin-left:183px; +} +h1,h2,h3,h4,h5,h6 { +margin-bottom:7px; +overflow:hidden; +} +h1 { +font-size:1.4em; +margin-bottom:18px; +} +#showstream h1 { display:none; } +h2 { font-size:1.3em; } +h3 { font-size:1.2em; } +h4 { font-size:1.1em; } +h5 { font-size:1em; } +h6 { font-size:0.9em; } + +caption { +font-weight:bold; +} +legend { +font-weight:bold; +font-size:1.3em; +} +input, textarea, select, option { +padding:4px; +font-family:sans-serif; +font-size:1em; +} +input, textarea, select { +border-width:2px; +border-style: solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +input.submit { +font-weight:bold; +cursor:pointer; +} +textarea { +overflow:auto; +} +option { +padding-bottom:0; +} +fieldset { +padding:0; +border:0; +} +form ul li { +list-style-type:none; +margin:0 0 18px 0; +} +form label { +font-weight:bold; +} +input.checkbox { +position:relative; +top:2px; +left:0; +border:0; +} + +.error, +.success { +padding:4px 1.55%; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +margin-bottom:18px; +} +form label.submit { +display:none; +} + +.form_settings { +clear:both; +} + +.form_settings fieldset { +margin-bottom:29px; +} +.form_settings input.remove { +margin-left:11px; +} +.form_settings .form_data li { +width:100%; +float:left; +} +.form_settings .form_data label { +float:left; +} +.form_settings .form_data textarea, +.form_settings .form_data select, +.form_settings .form_data input { +margin-left:11px; +float:left; +} +.form_settings .form_data input.submit { +margin-left:0; +} + +.form_settings label { +margin-top:2px; +width:152px; +} + +.form_actions label { +display:none; +} +.form_guide { +font-style:italic; +} + +.form_settings #settings_autosubscribe label { +display:inline; +font-weight:bold; +} + +#form_settings_profile legend, +#form_login legend, +#form_register legend, +#form_password legend, +#form_settings_avatar legend, +#newgroup legend, +#editgroup legend, +#form_tag_user legend, +#form_remote_subscribe legend, +#form_openid_login legend, +#form_search legend, +#form_invite legend, +#form_notice_delete legend, +#form_password_recover legend, +#form_password_change legend { +display:none; +} + +.form_settings .form_data p.form_guide { +clear:both; +margin-left:163px; +margin-bottom:0; +} + +.form_settings p { +margin-bottom:11px; +} + +.form_settings input.checkbox { +margin-top:3px; +margin-left:0; +} +.form_settings label.checkbox { +font-weight:normal; +margin-top:0; +margin-right:0; +margin-left:11px; +float:left; +width:90%; +} + + +#form_login p.form_guide, +#form_register #settings_rememberme p.form_guide, +#form_openid_login #settings_rememberme p.form_guide, +#settings_twitter_remove p.form_guide, +#form_search ul.form_data #q { +margin-left:0; +} + +.form_settings .form_note { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +padding:0 7px; +} + + +.form_settings input.form_action-secondary { +margin-left:29px; +padding:0; +} + +#form_search .submit { +margin-left:11px; +} + +address { +float:right; +margin-bottom:18px; +margin-right:18px; +} +address.vcard img.logo { +margin-right:0; +} +address .fn { +font-weight:bold; +} +address img + .fn { +display:none; +} + +#header { +width:98.5%; +position:relative; +float:left; +padding-top:18px; +padding-left:18px; +margin-bottom:29px; +} + +#site_nav_global_primary { +float:left; +margin-right:18px; +margin-bottom:11px; +} +#site_nav_global_primary ul li { +display:inline; +margin-right:11px; +} + +.system_notice dt { +font-weight:bold; +text-transform:uppercase; +display:none; +} + +#site_notice { +float:right; +margin-top:7px; +margin-right:18px; +width:26%; +} +#page_notice { +clear:both; +margin-bottom:18px; +} + + +#anon_notice { +float:left; +width:50.2%; +line-height:1.5; +font-size:1.1em; +font-weight:bold; +} + + +#footer { +float:left; +width:64%; +padding:18px; +} + +#site_nav_local_views { +width:183px; +float:left; +margin-bottom:29px; +position:fixed; +top:179px; +left:0; +} +#site_nav_local_views dt { +display:none; +} +#site_nav_local_views li { +list-style-type:none; +} +#site_nav_local_views a { +text-decoration:none; +padding:4px 11px; +text-shadow: 1px 1px 1px #ddd; +font-weight:bold; +display:block; +} +#site_nav_local_views .nav { +float:left; +width:100%; +} + +#site_nav_global_primary dt, +#site_nav_global_secondary dt { +display:none; +} + +#site_nav_global_secondary { +margin-bottom:11px; +} + +#site_nav_global_secondary ul li { +display:inline; +margin-right:11px; +} +#export_data li a { +padding-left:20px; +} +#export_data li a.foaf { +padding-left:30px; +} +#export_data li a.export_vcard { +padding-left:28px; +} + +#export_data ul { +display:inline; +} +#export_data li { +list-style-type:none; +display:inline; +margin-left:11px; +} +#export_data li:first-child { +margin-left:0; +} + +#licenses { +font-size:0.9em; +} + +#licenses dt { +font-weight:bold; +display:none; +} +#licenses dd { +margin-bottom:11px; +line-height:1.5; +} + +#site_content_license_cc { +margin-bottom:0; +} +#site_content_license_cc img { +display:inline; +vertical-align:top; +margin-right:4px; +} + +#wrap { +width:100%; +min-width:760px; +max-width:1003px; +overflow:hidden; +} + +#core { +position:relative; +width:100%; +float:left; +margin-bottom:1em; +} + +#content { +width:50.009%; +min-height:259px; +float:left; +margin-left:18px; +} +#shownotice #content { +min-height:0; +} + +#content_inner { +position:relative; +width:100%; +float:left; +} + +#aside_primary { +width:45.917%; +min-height:259px; +float:left; +margin-left:1.385%; +padding-bottom:47px; +} + +#form_notice { +width:45.664%; +float:left; +position:relative; +line-height:1; +} +#form_notice fieldset { +border:0; +padding:0; +position:relative; +} +#form_notice legend { +display:none; +} +#form_notice textarea { +float:left; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +width:80.789%; +height:46px; +line-height:1.5; +padding:7px 7px 16px 7px; +} +#form_notice label { +display:block; +float:left; +font-size:1.3em; +margin-bottom:7px; +} +#form_notice #notice_submit label { +display:none; +} +#form_notice .form_note { +position:absolute; +top:76px; +right:98px; +z-index:9; +} +#form_notice .form_note dt { +font-weight:bold; +display:none; +} +#notice_text-count { +font-weight:bold; +line-height:1.15; +padding:1px 2px; +} +#form_notice #notice_action-submit { +width:14%; +height:47px; +padding:0; +position:absolute; +bottom:0; +right:0; +} +#form_notice label[for=to] { +margin-top:7px; +} +#form_notice select[id=to] { +margin-bottom:7px; +margin-left:18px; +float:left; +} +#form_notice .error { +float:left; +clear:both; +width:96.9%; +margin-bottom:0; +line-height:1.618; +} + +/* entity_profile */ +.entity_profile { +position:relative; +width:67.702%; +min-height:123px; +float:left; +margin-bottom:18px; +margin-left:0; +overflow:hidden; +} +.entity_profile dt, +#entity_statistics dt { +font-weight:bold; +} +.entity_profile dd { +display:inline; +} + +.entity_profile .entity_depiction { +float:left; +width:96px; +margin-right:18px; +margin-bottom:18px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:113px; +margin-bottom:4px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname { +margin-left:11px; +display:inline; +font-weight:bold; +} +.entity_profile .entity_nickname { +margin-left:0; +} + +.entity_profile .entity_fn dd:before { +content: "("; +font-weight:normal; +} +.entity_profile .entity_fn dd:after { +content: ")"; +font-weight:normal; +} + +.entity_profile dt { +display:none; +} +.entity_profile h2 { +display:none; +} +/* entity_profile */ + + +/*entity_actions*/ +.entity_actions { +float:right; +margin-left:4.35%; +max-width:25%; +} +.entity_actions h2 { +display:none; +} +.entity_actions ul { +list-style-type:none; +} +.entity_actions li { +margin-bottom:4px; +} +.entity_actions li:first-child { +border-top:0; +} +.entity_actions fieldset { +border:0; +padding:0; +} +.entity_actions legend { +display:none; +} + +.entity_actions input.submit { +display:block; +text-align:left; +width:100%; +} +.entity_actions a, +.entity_nudge p, +.entity_remote_subscribe { +text-decoration:none; +font-weight:bold; +display:block; +} + +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.entity_edit a, +.form_user_nudge input.submit, +.entity_nudge p { +border:0; +padding-left:20px; +} + +.entity_edit a, +.entity_send-a-message a, +.entity_nudge p { +padding:4px 4px 4px 23px; +} + +.entity_remote_subscribe { +padding:4px; +border-width:2px; +border-style:solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.entity_actions .accept { +margin-bottom:18px; +} + +.entity_tags ul { +list-style-type:none; +display:inline; +} +.entity_tags li { +display:inline; +margin-right:4px; +} + +.aside .section { +margin-bottom:29px; +float:right; +width:44%; +padding:1%; +border-width:1px; +border-style:solid; +margin-left:2.5%; +} +.aside .section h2 { +text-transform:uppercase; +font-size:1em; +} + +#entity_statistics dt, +#entity_statistics dd { +display:inline; +} +#entity_statistics dt:after { +content: ":"; +} + +.section ul.entities { +float:left; +width:100%; +} +.section .entities li { +list-style-type:none; +float:left; +margin-right:7px; +margin-bottom:7px; +} +.section .entities li .photo { +margin-right:0; +margin-bottom:0; +} +.section .entities li .fn { +display:none; +} + +.aside .section p, +.aside .section .more { +clear:both; +} + +.profile .entity_profile { +margin-bottom:0; +min-height:60px; +} + + +.profile .form_group_join legend, +.profile .form_group_leave legend, +.profile .form_user_subscribe legend, +.profile .form_user_unsubscribe legend { +display:none; +} + +.profiles { +list-style-type:none; +} +.profile .entity_profile .entity_location { +width:auto; +clear:none; +margin-left:11px; +} +.profile .entity_profile dl, +.profile .entity_profile dd { +display:inline; +float:none; +} +.profile .entity_profile .entity_note, +.profile .entity_profile .entity_url, +.profile .entity_profile .entity_tags, +.profile .entity_profile .form_subscription_edit { +margin-left:59px; +clear:none; +display:block; +width:auto; +} +.profile .entity_profile .entity_tags dt { +display:inline; +margin-right:11px; +} + + +.profile .entity_profile .form_subscription_edit label { +font-weight:normal; +margin-right:11px; +} + + +/* NOTICE */ +.notice, +.profile { +position:relative; +padding-top:11px; +padding-bottom:11px; +clear:both; +float:left; +width:96.41%; +border-width:1px; +border-style:solid; +padding:1.795%; +margin-bottom:11px; +} +.notices li { +list-style-type:none; +} + +#aside_primary .notice, +#aside_primary .profile { +border:0; +margin-bottom:11px; +} + +/* NOTICES */ +#notices_primary { +float:left; +width:100%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +} +#notices_primary h2 { +display:none; +} +.notice-data a span { +display:block; +padding-left:28px; +} + +.notice .author { +margin-right:11px; +} + +.fn { +overflow:hidden; +} + +.notice .author .fn { +font-weight:bold; +} + +.vcard .photo { +display:inline; +margin-right:11px; +float:left; +} +#shownotice .vcard .photo { +margin-bottom:4px; +} +.vcard .url { +text-decoration:none; +} +.vcard .url:hover { +text-decoration:underline; +} + +.notice .entry-title { +float:left; +width:100%; +overflow:hidden; +} +#shownotice .notice .entry-title { +font-size:2.2em; +} + +.notice p.entry-content { +display:inline; +} + +#content .notice p.entry-content a:visited { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.notice p.entry-content .vcard a { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +.notice div.entry-content { +clear:left; +float:left; +font-size:0.95em; +margin-left:59px; +width:65%; +} +#showstream .notice div.entry-content, +#shownotice .notice div.entry-content { +margin-left:0; +} + +.notice .notice-options a, +.notice .notice-options input { +float:left; +font-size:1.025em; +} + +.notice div.entry-content dl, +.notice div.entry-content dt, +.notice div.entry-content dd { +display:inline; +} + +.notice div.entry-content .timestamp dt, +.notice div.entry-content .response dt { +display:none; +} +.notice div.entry-content .timestamp a { +display:inline-block; +} +.notice div.entry-content .device dt { +text-transform:lowercase; +} + + +.notice-options { +padding-left:2%; +float:left; +width:50%; +position:relative; +font-size:0.95em; +width:12.5%; +float:right; +} + +.notice-options a { +float:left; +} +.notice-options .notice_delete, +.notice-options .notice_reply, +.notice-options .form_favor, +.notice-options .form_disfavor { +position:absolute; +top:0; +} +.notice-options .form_favor, +.notice-options .form_disfavor { +left:0; +} +.notice-options .notice_reply { +left:29px; +} +.notice-options .notice_delete { +right:0; +} +.notice-options .notice_reply dt { +display:none; +} + +.notice-options input, +.notice-options a { +text-indent:-9999px; +outline:none; +} + +.notice-options .notice_reply a, +.notice-options input.submit { +display:block; +border:0; +} +.notice-options .notice_reply a, +.notice-options .notice_delete a { +text-decoration:none; +padding-left:16px; +} + +.notice-options form input.submit { +width:16px; +padding:2px 0; +} + +.notice-options .notice_delete dt, +.notice-options .form_favor legend, +.notice-options .form_disfavor legend { +display:none; +} +.notice-options .notice_delete fieldset, +.notice-options .form_favor fieldset, +.notice-options .form_disfavor fieldset { +border:0; +padding:0; +} + + +#usergroups #new_group { +float: left; +margin-right: 2em; +} +#new_group, #group_search { +margin-bottom:18px; +} +#new_group a { +padding-left:20px; +} + + +#filter_tags { +margin-bottom:11px; +float:left; +} +#filter_tags dt { +display:none; +} +#filter_tags ul { +list-style-type:none; +} +#filter_tags ul li { +float:left; +margin-left:7px; +padding-left:7px; +border-left-width:1px; +border-left-style:solid; +} +#filter_tags ul li.child_1 { +margin-left:0; +border-left:0; +padding-left:0; +} +#filter_tags ul li#filter_tags_all a { +font-weight:bold; +margin-top:7px; +float:left; +} + +#filter_tags ul li#filter_tags_item label { +margin-right:7px; +} +#filter_tags ul li#filter_tags_item label, +#filter_tags ul li#filter_tags_item select { +display:inline; +} +#filter_tags ul li#filter_tags_item p { +float:left; +margin-left:38px; +} +#filter_tags ul li#filter_tags_item input { +position:relative; +top:3px; +left:3px; +} + + + +.pagination { +float:left; +clear:both; +width:100%; +margin-top:18px; +} + +.pagination dt { +font-weight:bold; +display:none; +} + +.pagination .nav { +float:left; +width:100%; +list-style-type:none; +} + +.pagination .nav_prev { +float:left; +} +.pagination .nav_next { +float:right; +} + +.pagination a { +display:block; +text-decoration:none; +font-weight:bold; +padding:7px; +border-width:1px; +border-style:solid; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-radius:7px; +} + +.pagination .nav_prev a { +padding-left:30px; +} +.pagination .nav_next a { +padding-right:30px; +} +/* END: NOTICE */ + + +.hentry .entry-content p { +margin-bottom:18px; +} +.system_notice ul, +.instructions ul, +.hentry entry-content ol, +.hentry .entry-content ul { +list-style-position:inside; +} +.hentry .entry-content li { +margin-bottom:18px; +} +.hentry .entry-content li li { +margin-left:18px; +} + + + + +/* TOP_POSTERS */ +.section tbody td { +padding-right:11px; +padding-bottom:11px; +} +.section .vcard .photo { +margin-right:7px; +margin-bottom:0; +} + +.section .notice { +padding-top:7px; +padding-bottom:7px; +border-top:0; +} + +.section .notice:first-child { +padding-top:0; +} + +.section .notice .author { +margin-right:0; +} +.section .notice .author .fn { +display:none; +} + + +/* tagcloud */ +.tag-cloud { +list-style-type:none; +text-align:center; +} +.aside .tag-cloud { +font-size:0.8em; +} +.tag-cloud li { +display:inline; +margin-right:7px; +line-height:1.25; +} +.aside .tag-cloud li { +line-height:1.5; +} +.tag-cloud li a { +text-decoration:none; +} +#tagcloud.section dt { +text-transform:uppercase; +font-weight:bold; +} +.tag-cloud-1 { +font-size:1em; +} +.tag-cloud-2 { +font-size:1.25em; +} +.tag-cloud-3 { +font-size:1.75em; +} +.tag-cloud-4 { +font-size:2em; +} +.tag-cloud-5 { +font-size:2.25em; +} +.tag-cloud-6 { +font-size:2.75em; +} +.tag-cloud-7 { +font-size:3.25em; +} + +#publictagcloud #tagcloud.section dt { +display:none; +} + +#form_settings_photo .form_data { +clear:both; +} + +#form_settings_avatar li { +width:auto; +} +#form_settings_avatar input { +margin-left:0; +} +#avatar_original, +#avatar_preview { +float:left; +} +#avatar_preview { +margin-left:29px; +} +#avatar_preview_view { +height:96px; +width:96px; +margin-bottom:18px; +overflow:hidden; +} + +#settings_attach, +#form_settings_avatar .form_actions { +clear:both; +} + +#form_settings_avatar .form_actions { +margin-bottom:0; +} + +#form_settings_design #settings_design_color .form_data, +#form_settings_design #color-picker { +float:left; +} +#form_settings_design #settings_design_color .form_data { +width:400px; +margin-right:28px; +} + +.instructions ul { +list-style-position:inside; +} +.instructions p, +.instructions ul { +margin-bottom:18px; +} +.help dt { +display:none; +} +.guide { +clear:both; +} diff --git a/theme/pigeonthoughts/css/display.css b/theme/pigeonthoughts/css/display.css new file mode 100644 index 0000000000..19341ef7f2 --- /dev/null +++ b/theme/pigeonthoughts/css/display.css @@ -0,0 +1,295 @@ +/** theme: pigeonthoughts + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +@import url(base.css); + +html { +background:#fff url(../images/illustrations/illu_pigeons-01.png) no-repeat 0 100%; +} + +body, +a:active { +background-color:#AEA187; +} +body { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +font-size:1em; +} +address { +margin-left:2%; +} + +input, textarea, select, option { +font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; +} +input, textarea, select, +.entity_remote_subscribe { +border-color:#aaa; +} +#filter_tags ul li { +border-color:#ddd; +} + +.form_settings input.form_action-secondary { +background:none; +} + +input.submit, +#form_notice.warning #notice_text-count, +.form_settings .form_note, +.entity_remote_subscribe { +background-color:#8F0000; +} + +input:focus, textarea:focus, select:focus, +#form_notice.warning #notice_data-text { +border-color:#8F0000; +} +input.submit, +.entity_remote_subscribe { +color:#fff; +} + +a, +div.notice-options input, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.form_user_nudge input.submit, +.entity_nudge p, +.form_settings input.form_action-secondary { +color:#000; +} + +.notice, +.profile { +border-color:#000; +} +.notice a, +.profile a { +color:#fff; +} + +.notice:nth-child(3n-1), +.profile:nth-child(3n-1) { +border-color:#fff; +} +.notice:nth-child(3n-1) a, +.profile:nth-child(3n-1) a { +color:#7F1114; +} +.notice:nth-child(3n), +.profile:nth-child(3n) { +border-color:#7F1114; +} +.notice:nth-child(3n) a, +.profile:nth-child(3n) a { +color:#000; +} + +.aside .section .notice, +.aside .section .profile, +.aside .section .notice:nth-child(3n-1), +.aside .section .profile:nth-child(3n-1), +.aside .section .notice:nth-child(3n), +.aside .section .profile:nth-child(3n) { +background-color:transparent; +color:#000; +} + + +.aside .section { +border-color:#fff; +background-color:#fff; +color:#000; +} + +.aside .section:nth-child(n) { +border-color:#000; +background-color:#000; +color:#fff; +} +.aside .section:nth-child(3n-1) { +border-color:#fff; +background-color:#fff; +color:#000; +} +.aside .section:nth-child(3n) { +background-color:#7F1114; +border-color:#7F1114; +color:#000; +} +.aside .section a { +color:#7F1114; +} +.aside .section:nth-child(3n-1) a { +color:#7F1114; +} +.aside .section:nth-child(3n) a { +color:#fff; +} + + +.section .profile { +border-top-color:#87B4C8; +} + +#aside_primary { +background:url(../images/illustrations/illu_pigeons-02.png) no-repeat 10% 100%; +} + +#notice_text-count { +color:#333; +} +#form_notice.warning #notice_text-count { +color:#000; +} +#form_notice.processing #notice_action-submit { +background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +cursor:wait; +text-indent:-9999px; +} + +#content, +#site_nav_local_views a { +border-color:#fff; +} +#site_nav_local_views .current a { +background-color:rgba(143, 0, 0, 0.8); +color:#fff; +} + +#site_nav_local_views a { +background-color:rgba(255, 255, 255, 0.3); +} +#site_nav_local_views a:hover { +background-color:#fff; +color:#8F0000; +} + +.error { +background-color:#F7E8E8; +} +.success { +background-color:#EFF3DC; +} + +#anon_notice { +color:#000; +} + + +#export_data li a { +background-repeat:no-repeat; +background-position:0 45%; +} +#export_data li a.rss { +background-image:url(../../base/images/icons/icon_rss.png); +} +#export_data li a.atom { +background-image:url(../../base/images/icons/icon_atom.png); +} +#export_data li a.foaf { +background-image:url(../../base/images/icons/icon_foaf.gif); +} + +.entity_edit a, +.entity_send-a-message a, +.form_user_nudge input.submit, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_nudge p { +background-position: 0 40%; +background-repeat: no-repeat; +background-color:transparent; +} +.form_group_join input.submit, +.form_group_leave input.submit +.form_user_subscribe input.submit, +.form_user_unsubscribe input.submit { +background-color:#8F0000; +color:#fff; +} +.form_user_unsubscribe input.submit, +.form_group_leave input.submit, +.form_user_authorization input.reject { +background-color:#87B4C8; +} + +.entity_edit a { +background-image:url(../../base/images/icons/twotone/green/edit.gif); +} +.entity_send-a-message a { +background-image:url(../../base/images/icons/twotone/green/quote.gif); +} +.entity_nudge p, +.form_user_nudge input.submit { +background-image:url(../../base/images/icons/twotone/green/mail.gif); +} +.form_user_block input.submit, +.form_user_unblock input.submit { +background-image:url(../../base/images/icons/twotone/green/shield.gif); +} + +/* NOTICES */ +.notices li.over { +background-color:#fcfcfc; +} + +.notice-options .notice_reply a, +.notice-options form input.submit { +background-color:transparent; +} +.notice-options .notice_reply a { +background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; +} +.notice-options form.form_favor input.submit { +background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +} +.notice-options form.form_disfavor input.submit { +background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +} +.notice-options .notice_delete a { +background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:0.4; +} +.notices li.hover div.entry-content, +.notices li.hover div.notice-options { +opacity:1; +} +div.entry-content { +color:#333; +} +div.notice-options a, +div.notice-options input { +font-family:sans-serif; +} +/*END: NOTICES */ + +#new_group a { +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; +} + +.pagination .nav_prev a, +.pagination .nav_next a { +background-repeat:no-repeat; +border-color:#000; +} +.pagination .nav_prev a { +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); +background-position:10% 45%; +} +.pagination .nav_next a { +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); +background-position:90% 45%; +} diff --git a/theme/pigeonthoughts/css/ie.css b/theme/pigeonthoughts/css/ie.css new file mode 100644 index 0000000000..2f463bb44d --- /dev/null +++ b/theme/pigeonthoughts/css/ie.css @@ -0,0 +1,9 @@ +/* IE specific styles */ + +.notice-options input.submit { +color:#fff; +} + +#site_nav_local_views a { +background-color:#D0DFE7; +} diff --git a/theme/pigeonthoughts/default-avatar-mini.png b/theme/pigeonthoughts/default-avatar-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..38b8692b4a2f71c8de3d6a12b715df33aada5f7c GIT binary patch literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b literal 0 HcmV?d00001 diff --git a/theme/pigeonthoughts/default-avatar-profile.png b/theme/pigeonthoughts/default-avatar-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..f8357d4fc296271b837b3d9911cfbc133918ef2f GIT binary patch literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi literal 0 HcmV?d00001 diff --git a/theme/pigeonthoughts/images/illustrations/illu_pigeons-01.png b/theme/pigeonthoughts/images/illustrations/illu_pigeons-01.png new file mode 100644 index 0000000000000000000000000000000000000000..4fdaaeb25b461d3300852feaa9252778ce2699ca GIT binary patch literal 72649 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 bBmS3@lgK4WNY0sm*&lscED%< literal 0 HcmV?d00001 diff --git a/theme/pigeonthoughts/images/illustrations/illu_pigeons-02.png b/theme/pigeonthoughts/images/illustrations/illu_pigeons-02.png new file mode 100644 index 0000000000000000000000000000000000000000..187c6c8a660390e37c9eace9e3bfa39d36676ef0 GIT binary patch literal 3538 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 Ju2!^+_z$X!Irjhn literal 0 HcmV?d00001 diff --git a/theme/pigeonthoughts/logo.png b/theme/pigeonthoughts/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7c68b34f61008753d12394806c3cf46f7b04effd GIT binary patch literal 4988 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 Date: Mon, 11 May 2009 13:45:00 -0400 Subject: [PATCH 473/503] db stuff for URLs: redirections, oembed, etc. --- actions/newnotice.php | 33 ++++++++++ classes/File.php | 47 +++++++++++++ classes/File_oembed.php | 53 +++++++++++++++ classes/File_redirection.php | 45 +++++++++++++ classes/File_thumbnail.php | 45 +++++++++++++ classes/File_to_post.php | 43 ++++++++++++ classes/laconica.ini | 123 +++++++++++++++++++++++++++++++++++ classes/laconica.links.ini | 71 ++++++++++++++++++++ lib/util.php | 8 ++- 9 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 classes/File.php create mode 100644 classes/File_oembed.php create mode 100644 classes/File_redirection.php create mode 100644 classes/File_thumbnail.php create mode 100644 classes/File_to_post.php mode change 100755 => 100644 classes/laconica.ini diff --git a/actions/newnotice.php b/actions/newnotice.php index cbd04c58b2..8b03abc62c 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -166,6 +166,8 @@ class NewnoticeAction extends Action return; } + $this->saveUrls($notice); + common_broadcast_notice($notice); if ($this->boolean('ajax')) { @@ -191,6 +193,37 @@ class NewnoticeAction extends Action } } + /** save all urls in the notice to the db + * + * follow redirects and save all available file information + * (mimetype, date, size, oembed, etc.) + * + * @param class $notice Notice to pull URLs from + * + * @return void + */ + function saveUrls($notice) { + common_debug("Saving all URLs"); + common_replace_urls_callback($notice->content, array($this, 'saveUrl'), $notice->id); + } + + function saveUrl($data) { + list($url, $notice_id) = $data; + common_debug("Saving $url for $notice_id"); + $file = File::staticGet('url', $url); + if (empty($file)) { + common_debug('unknown file/url'); + $file = new File; + $file->url = $url; + $file->insert(); + } + common_debug('File: ' . print_r($file, true)); + $f2p = new File_to_post; + $f2p->file_id = $file->id; + $f2p->post_id = $notice_id; + $f2p->insert(); + } + /** * Show an Ajax-y error message * diff --git a/classes/File.php b/classes/File.php new file mode 100644 index 0000000000..8dd017b79b --- /dev/null +++ b/classes/File.php @@ -0,0 +1,47 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file + */ + +class File extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file'; // table name + public $id; // int(11) not_null primary_key group_by + public $url; // varchar(255) unique_key + public $mimetype; // varchar(50) + public $size; // int(11) group_by + public $title; // varchar(255) + public $date; // int(11) group_by + public $protected; // int(1) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_oembed.php b/classes/File_oembed.php new file mode 100644 index 0000000000..33dd8200c2 --- /dev/null +++ b/classes/File_oembed.php @@ -0,0 +1,53 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_oembed + */ + +class File_oembed extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_oembed'; // table name + public $id; // int(11) not_null primary_key group_by + public $file_id; // int(11) unique_key group_by + public $version; // varchar(20) + public $type; // varchar(20) + public $provider; // varchar(50) + public $provider_url; // varchar(255) + public $width; // int(11) group_by + public $height; // int(11) group_by + public $html; // blob(65535) blob + public $title; // varchar(255) + public $author_name; // varchar(50) + public $author_url; // varchar(255) + public $url; // varchar(255) + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_oembed',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_redirection.php b/classes/File_redirection.php new file mode 100644 index 0000000000..e2d1e69c38 --- /dev/null +++ b/classes/File_redirection.php @@ -0,0 +1,45 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_redirection + */ + +class File_redirection extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_redirection'; // table name + public $id; // int(11) not_null primary_key group_by + public $url; // varchar(255) unique_key + public $file_id; // int(11) group_by + public $redirections; // int(11) group_by + public $httpcode; // int(11) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_redirection',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php new file mode 100644 index 0000000000..7b906a07ca --- /dev/null +++ b/classes/File_thumbnail.php @@ -0,0 +1,45 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_thumbnail + */ + +class File_thumbnail extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_thumbnail'; // table name + public $id; // int(11) not_null primary_key group_by + public $file_id; // int(11) unique_key group_by + public $url; // varchar(255) unique_key + public $width; // int(11) group_by + public $height; // int(11) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_thumbnail',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_to_post.php b/classes/File_to_post.php new file mode 100644 index 0000000000..bd0528d98f --- /dev/null +++ b/classes/File_to_post.php @@ -0,0 +1,43 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_to_post + */ + +class File_to_post extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_to_post'; // table name + public $id; // int(11) not_null primary_key group_by + public $file_id; // int(11) multiple_key group_by + public $post_id; // int(11) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_to_post',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/laconica.ini b/classes/laconica.ini old mode 100755 new mode 100644 index 5a905a4bbe..00a1b89365 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -1,4 +1,67 @@ +[file] +id = 129 +url = 2 +mimetype = 2 +size = 1 +title = 2 +date = 1 +protected = 17 + +[file__keys] +id = K +url = U + +[file_oembed] +id = 129 +file_id = 1 +version = 2 +type = 2 +provider = 2 +provider_url = 2 +width = 1 +height = 1 +html = 66 +title = 2 +author_name = 2 +author_url = 2 +url = 2 + +[file_oembed__keys] +id = K +file_id = U + +[file_redirection] +id = 129 +url = 2 +file_id = 1 +redirections = 1 +httpcode = 1 + +[file_redirection__keys] +id = K +url = U + +[file_thumbnail] +id = 129 +file_id = 1 +url = 2 +width = 1 +height = 1 + +[file_thumbnail__keys] +id = K +file_id = U +url = U + +[file_to_post] +id = 129 +file_id = 1 +post_id = 1 + +[file_to_post__keys] +id = K + [avatar] profile_id = 129 original = 17 @@ -393,3 +456,63 @@ modified = 384 [user_openid__keys] canonical = K display = U + +[file] +id = 129 +url = 2 +mimetype = 2 +size = 1 +title = 2 +date = 1 +protected = 1 + +[file__keys] +id = N + +[file_oembed] +id = 129 +file_id = 129 +version = 2 +type = 2 +provider = 2 +provider_url = 2 +width = 1 +height = 1 +html = 34 +title = 2 +author_name = 2 +author_url = 2 +url = 2 + +[file_oembed__keys] +id = N + +[file_redirection] +id = 129 +url = 2 +file_id = 129 +redirections = 1 +httpcode = 1 + +[file_redirection__keys] +id = N + +[file_thumbnail] +id = 129 +file_id = 129 +url = 2 +width = 1 +height = 1 + +[file_thumbnail__keys] +id = N + +[file_to_post] +id = 129 +file_id = 129 +post_id = 129 + +[file_to_post__keys] +id = N + + diff --git a/classes/laconica.links.ini b/classes/laconica.links.ini index 173b187267..bc52ce578e 100644 --- a/classes/laconica.links.ini +++ b/classes/laconica.links.ini @@ -41,3 +41,74 @@ subscribed = profile:id [fave] notice_id = notice:id user_id = user:id + +[file_oembed] +file_id = file:id + +[file_redirection] +file_id = file:id + +[file_thumbnail] +file_id = file:id + +[file_to_post] +file_id = file:id +post_id = post:id + +[avatar] +profile_id = profile:id + +[user] +id = profile:id +carrier = sms_carrier:id + +[remote_profile] +id = profile:id + +[notice] +profile_id = profile:id +reply_to = notice:id + +[reply] +notice_id = notice:id +profile_id = profile:id + +[token] +consumer_key = consumer:consumer_key + +[nonce] +consumer_key,token = token:consumer_key,token + +[user_openid] +user_id = user:id + +[confirm_address] +user_id = user:id + +[remember_me] +user_id = user:id + +[queue_item] +notice_id = notice:id + +[subscription] +subscriber = profile:id +subscribed = profile:id + +[fave] +notice_id = notice:id +user_id = user:id + +[file_oembed] +file_id = file:id + +[file_redirection] +file_id = file:id + +[file_thumbnail] +file_id = file:id + +[file_to_post] +file_id = file:id +post_id = post:id + diff --git a/lib/util.php b/lib/util.php index 1981853385..c4a63a4412 100644 --- a/lib/util.php +++ b/lib/util.php @@ -395,7 +395,7 @@ function common_render_text($text) return $r; } -function common_replace_urls_callback($text, $callback) { +function common_replace_urls_callback($text, $callback, $notice_id = null) { // Start off with a regex $regex = '#'. '(?:'. @@ -466,7 +466,11 @@ function common_replace_urls_callback($text, $callback) { $url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url); // Call user specified func - $modified_url = call_user_func($callback, $url); + if (isset($notice_id)) { + $modified_url = call_user_func($callback, array($url, $notice_id)); + } else { + $modified_url = call_user_func($callback, $url); + } // Replace it! $start = mb_strpos($text, $url, $offset); From 78e5572b38ee3f71c0a5cf8743141817cc81079e Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 13 May 2009 15:56:44 +0000 Subject: [PATCH 474/503] Init h4ck3r theme. Originally suggested by Zach ( http://identi.ca/user/25 ). Background image (aka matrix h4x0r animated chars) is copied from Google neonblade2 theme ( http://ur1.ca/49wv ). Original creator of the image is unknown at this time. --- theme/h4ck3r/css/base.css | 1136 +++++++++++++++++ theme/h4ck3r/css/display.css | 236 ++++ theme/h4ck3r/css/ie.css | 9 + theme/h4ck3r/default-avatar-mini.png | Bin 0 -> 646 bytes theme/h4ck3r/default-avatar-profile.png | Bin 0 -> 2853 bytes theme/h4ck3r/default-avatar-stream.png | Bin 0 -> 1487 bytes .../images/illustrations/illu_h4x0r1ng.gif | Bin 0 -> 432979 bytes theme/h4ck3r/logo.png | Bin 0 -> 4988 bytes 8 files changed, 1381 insertions(+) create mode 100644 theme/h4ck3r/css/base.css create mode 100644 theme/h4ck3r/css/display.css create mode 100644 theme/h4ck3r/css/ie.css create mode 100644 theme/h4ck3r/default-avatar-mini.png create mode 100644 theme/h4ck3r/default-avatar-profile.png create mode 100644 theme/h4ck3r/default-avatar-stream.png create mode 100644 theme/h4ck3r/images/illustrations/illu_h4x0r1ng.gif create mode 100644 theme/h4ck3r/logo.png diff --git a/theme/h4ck3r/css/base.css b/theme/h4ck3r/css/base.css new file mode 100644 index 0000000000..54763006bc --- /dev/null +++ b/theme/h4ck3r/css/base.css @@ -0,0 +1,1136 @@ +/** theme: h4ck3r base + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +* { margin:0; padding:0; } +img { display:block; border:0; } +a abbr { cursor: pointer; border-bottom:0; } +table { border-collapse:collapse; } +ol { list-style-position:inside; } +html { font-size: 100%; background-color:#fff; height:100%; } +body { +background-color:#fff; +color:#000; +font-family:sans-serif; +font-size:1em; +line-height:1.65; +position:relative; +} +h1,h2,h3,h4,h5,h6 { +margin-bottom:7px; +overflow:hidden; +} +h1 { +font-size:1.4em; +margin-bottom:18px; +} +#showstream h1 { display:none; } +h2 { font-size:1.3em; } +h3 { font-size:1.2em; } +h4 { font-size:1.1em; } +h5 { font-size:1em; } +h6 { font-size:0.9em; } + +caption { +font-weight:bold; +} +legend { +font-weight:bold; +font-size:1.3em; +} +input, textarea, select, option { +padding:4px; +font-family:sans-serif; +font-size:1em; +} +input, textarea, select { +border-width:2px; +border-style: solid; +} + +input.submit { +font-weight:bold; +cursor:pointer; +} +textarea { +overflow:auto; +} +option { +padding-bottom:0; +} +fieldset { +padding:0; +border:0; +} +form ul li { +list-style-type:none; +margin:0 0 18px 0; +} +form label { +font-weight:bold; +} +input.checkbox { +position:relative; +top:2px; +left:0; +border:0; +} + +.error, +.success { +padding:4px 1.55%; +margin-bottom:18px; +} +form label.submit { +display:none; +} + +.form_settings { +clear:both; +} + +.form_settings fieldset { +margin-bottom:29px; +} +.form_settings input.remove { +margin-left:11px; +} +.form_settings .form_data li { +width:100%; +float:left; +} +.form_settings .form_data label { +float:left; +} +.form_settings .form_data textarea, +.form_settings .form_data select, +.form_settings .form_data input { +margin-left:11px; +float:left; +} +.form_settings .form_data input.submit { +margin-left:0; +} + +.form_settings label { +margin-top:2px; +width:152px; +} + +.form_actions label { +display:none; +} +.form_guide { +font-style:italic; +} + +.form_settings #settings_autosubscribe label { +display:inline; +font-weight:bold; +} + +#form_settings_profile legend, +#form_login legend, +#form_register legend, +#form_password legend, +#form_settings_avatar legend, +#newgroup legend, +#editgroup legend, +#form_tag_user legend, +#form_remote_subscribe legend, +#form_openid_login legend, +#form_search legend, +#form_invite legend, +#form_notice_delete legend, +#form_password_recover legend, +#form_password_change legend { +display:none; +} + +.form_settings .form_data p.form_guide { +clear:both; +margin-left:163px; +margin-bottom:0; +} + +.form_settings p { +margin-bottom:11px; +} + +.form_settings input.checkbox { +margin-top:3px; +margin-left:0; +} +.form_settings label.checkbox { +font-weight:normal; +margin-top:0; +margin-right:0; +margin-left:11px; +float:left; +width:90%; +} + + +#form_login p.form_guide, +#form_register #settings_rememberme p.form_guide, +#form_openid_login #settings_rememberme p.form_guide, +#settings_twitter_remove p.form_guide, +#form_search ul.form_data #q { +margin-left:0; +} + +.form_settings .form_note { +padding:0 7px; +} + + +.form_settings input.form_action-secondary { +margin-left:29px; +padding:0; +} + +#form_search .submit { +margin-left:11px; +} + +address { +float:left; +margin-bottom:18px; +margin-left:18px; +} +address.vcard img.logo { +margin-right:0; +} +address .fn { +font-weight:bold; +} +address img + .fn { +display:none; +} + +#header { +width:100%; +position:relative; +float:left; +padding-top:18px; +margin-bottom:29px; +} + +#site_nav_global_primary { +float:right; +margin-right:18px; +margin-bottom:11px; +margin-left:18px; +} +#site_nav_global_primary ul li { +display:inline; +margin-left:11px; +} + +.system_notice dt { +font-weight:bold; +text-transform:uppercase; +display:none; +} + +#site_notice { +float:left; +clear:right; +margin-top:7px; +margin-right:18px; +width:31%; +} +#page_notice { +clear:both; +margin-bottom:18px; +} + + +#anon_notice { +float:right; +width:41.2%; +padding:1.1%; +border-width:2px; +border-style:dashed; +line-height:1.5; +font-size:1.1em; +font-weight:bold; +-moz-transform:skewX(-30deg) scale(0.85); +-webkit-transform:skewX(-30deg) scale(0.85); +} + + +#footer { +float:left; +width:64%; +padding:18px; +} + +#site_nav_local_views { +width:100%; +float:right; +} +#site_nav_local_views dt { +display:none; +} +#site_nav_local_views li { +float:right; +margin-left:11px; +list-style-type:none; +} +#site_nav_local_views a { +float:left; +text-decoration:none; +padding:4px 11px; +border-width:1px; +border-style:dashed; +border-bottom:0; +text-shadow: 2px 2px 2px #ddd; +font-weight:bold; +} +#site_nav_local_views .nav { +float:left; +width:100%; +} + +#site_nav_global_primary dt, +#site_nav_global_secondary dt { +display:none; +} + +#site_nav_global_secondary { +margin-bottom:11px; +} + +#site_nav_global_secondary ul li { +display:inline; +margin-right:11px; +} +#export_data li a { +padding-left:20px; +} +#export_data li a.foaf { +padding-left:30px; +} +#export_data li a.export_vcard { +padding-left:28px; +} + +#export_data ul { +display:inline; +} +#export_data li { +list-style-type:none; +display:inline; +margin-left:11px; +} +#export_data li:first-child { +margin-left:0; +} + +#licenses { +font-size:0.9em; +} + +#licenses dt { +font-weight:bold; +display:none; +} +#licenses dd { +margin-bottom:11px; +line-height:1.5; +} + +#site_content_license_cc { +margin-bottom:0; +} +#site_content_license_cc img { +display:inline; +vertical-align:top; +margin-right:4px; +} + +#wrap { +margin:0 auto; +width:100%; +min-width:760px; +max-width:1003px; +overflow:hidden; +} + +#core { +position:relative; +width:100%; +float:left; +margin-bottom:1em; +} + +#content { +width:60.009%; +min-height:259px; +padding:1.795%; +float:right; +border-style:dashed; +border-width:1px; +} +#shownotice #content { +min-height:0; +} + +#content_inner { +position:relative; +width:100%; +float:left; +} + +#aside_primary { +width:27.917%; +min-height:259px; +float:right; +margin-right:4.385%; +padding:1.795%; +border-width:1px; +border-style:dashed; +} + +#form_notice { +width:43.664%; +float:right; +position:relative; +line-height:1; +} +#form_notice fieldset { +border:0; +padding:0; +position:relative; +} +#form_notice legend { +display:none; +} +#form_notice textarea { +float:left; +width:80.789%; +height:67px; +line-height:1.5; +padding:7px 7px 16px 7px; +} +#form_notice label { +display:block; +float:left; +font-size:1.3em; +margin-bottom:7px; +} +#form_notice #notice_submit label { +display:none; +} +#form_notice .form_note { +position:absolute; +top:99px; +right:98px; +z-index:9; +} +#form_notice .form_note dt { +font-weight:bold; +display:none; +} +#notice_text-count { +font-weight:bold; +line-height:1.15; +padding:1px 2px; +} +#form_notice #notice_action-submit { +width:14%; +height:47px; +padding:0; +position:absolute; +bottom:0; +right:0; +} +#form_notice label[for=to] { +margin-top:7px; +} +#form_notice select[id=to] { +margin-bottom:7px; +margin-left:18px; +float:left; +} +#form_notice .error { +float:left; +clear:both; +width:96.9%; +margin-bottom:0; +line-height:1.618; +} + +/* entity_profile */ +.entity_profile { +position:relative; +width:67.702%; +min-height:123px; +float:left; +margin-bottom:18px; +margin-left:0; +overflow:hidden; +} +.entity_profile dt, +#entity_statistics dt { +font-weight:bold; +} +.entity_profile dd { +display:inline; +} + +.entity_profile .entity_depiction { +float:left; +width:96px; +margin-right:18px; +margin-bottom:18px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname, +.entity_profile .entity_location, +.entity_profile .entity_url, +.entity_profile .entity_note, +.entity_profile .entity_tags { +margin-left:113px; +margin-bottom:4px; +} + +.entity_profile .entity_fn, +.entity_profile .entity_nickname { +margin-left:11px; +display:inline; +font-weight:bold; +} +.entity_profile .entity_nickname { +margin-left:0; +} + +.entity_profile .entity_fn dd:before { +content: "("; +font-weight:normal; +} +.entity_profile .entity_fn dd:after { +content: ")"; +font-weight:normal; +} + +.entity_profile dt { +display:none; +} +.entity_profile h2 { +display:none; +} +/* entity_profile */ + + +/*entity_actions*/ +.entity_actions { +float:right; +margin-left:4.35%; +max-width:25%; +} +.entity_actions h2 { +display:none; +} +.entity_actions ul { +list-style-type:none; +} +.entity_actions li { +margin-bottom:4px; +} +.entity_actions li:first-child { +border-top:0; +} +.entity_actions fieldset { +border:0; +padding:0; +} +.entity_actions legend { +display:none; +} + +.entity_actions input.submit { +display:block; +text-align:left; +width:100%; +} +.entity_actions a, +.entity_nudge p, +.entity_remote_subscribe { +text-decoration:none; +font-weight:bold; +display:block; +} + +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.entity_edit a, +.form_user_nudge input.submit, +.entity_nudge p { +border:0; +padding-left:20px; +} + +.entity_edit a, +.entity_send-a-message a, +.entity_nudge p { +padding:4px 4px 4px 23px; +} + +.entity_remote_subscribe { +padding:4px; +border-width:2px; +border-style:solid; +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.entity_actions .accept { +margin-bottom:18px; +} + +.entity_tags ul { +list-style-type:none; +display:inline; +} +.entity_tags li { +display:inline; +margin-right:4px; +} + +.aside .section { +margin-bottom:29px; +clear:both; +float:left; +width:100%; +} +.aside .section h2 { +text-transform:uppercase; +font-size:1em; +} + +#entity_statistics dt, +#entity_statistics dd { +display:inline; +} +#entity_statistics dt:after { +content: ":"; +} + +.section ul.entities { +float:left; +width:100%; +} +.section .entities li { +list-style-type:none; +float:left; +margin-right:7px; +margin-bottom:7px; +} +.section .entities li .photo { +margin-right:0; +margin-bottom:0; +} +.section .entities li .fn { +display:none; +} + +.aside .section p, +.aside .section .more { +clear:both; +} + +.profile .entity_profile { +margin-bottom:0; +min-height:60px; +} + + +.profile .form_group_join legend, +.profile .form_group_leave legend, +.profile .form_user_subscribe legend, +.profile .form_user_unsubscribe legend { +display:none; +} + +.profiles { +list-style-type:none; +} +.profile .entity_profile .entity_location { +width:auto; +clear:none; +margin-left:11px; +} +.profile .entity_profile dl, +.profile .entity_profile dd { +display:inline; +float:none; +} +.profile .entity_profile .entity_note, +.profile .entity_profile .entity_url, +.profile .entity_profile .entity_tags, +.profile .entity_profile .form_subscription_edit { +margin-left:59px; +clear:none; +display:block; +width:auto; +} +.profile .entity_profile .entity_tags dt { +display:inline; +margin-right:11px; +} + + +.profile .entity_profile .form_subscription_edit label { +font-weight:normal; +margin-right:11px; +} + + +/* NOTICE */ +.notice, +.profile { +position:relative; +padding-top:11px; +padding-bottom:11px; +clear:both; +float:left; +width:100%; +border-top-width:1px; +border-top-style:dashed; +} +.notices li { +list-style-type:none; +} + + +/* NOTICES */ +#notices_primary { +float:left; +width:100%; +border-radius:7px; +-moz-border-radius:7px; +-webkit-border-radius:7px; +} +#notices_primary h2 { +display:none; +} +.notice-data a span { +display:block; +padding-left:28px; +} + +.notice .author { +margin-right:11px; +} + +.fn { +overflow:hidden; +} + +.notice .author .fn { +font-weight:bold; +} + +.vcard .photo { +display:inline; +margin-right:11px; +float:left; +} +#shownotice .vcard .photo { +margin-bottom:4px; +} +.vcard .url { +text-decoration:none; +} +.vcard .url:hover { +text-decoration:underline; +} + +.notice .entry-title { +display:inline; +width:100%; +overflow:hidden; +} +#shownotice .notice .entry-title { +font-size:2.2em; +} + +.notice p.entry-content { +display:inline; +} + +#content .notice p.entry-content a:visited { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} +.notice p.entry-content .vcard a { +border-radius:4px; +-moz-border-radius:4px; +-webkit-border-radius:4px; +} + +.notice div.entry-content { +float:left; +font-size:0.95em; +width:65%; +} + +.notice .notice-options a, +.notice .notice-options input { +float:left; +font-size:1.025em; +} + +.notice div.entry-content dl, +.notice div.entry-content dt, +.notice div.entry-content dd { +display:inline; +} + +.notice div.entry-content .timestamp dt, +.notice div.entry-content .response dt { +display:none; +} +.notice div.entry-content .timestamp a { +display:inline-block; +} +.notice div.entry-content .device dt { +text-transform:lowercase; +} + + +.notice-options { +padding-left:2%; +float:left; +width:50%; +position:relative; +font-size:0.95em; +width:12.5%; +float:right; +} + +.notice-options a { +float:left; +} +.notice-options .notice_delete, +.notice-options .notice_reply, +.notice-options .form_favor, +.notice-options .form_disfavor { +position:absolute; +top:0; +} +.notice-options .form_favor, +.notice-options .form_disfavor { +left:0; +} +.notice-options .notice_reply { +left:29px; +} +.notice-options .notice_delete { +right:0; +} +.notice-options .notice_reply dt { +display:none; +} + +.notice-options input, +.notice-options a { +text-indent:-9999px; +outline:none; +} + +.notice-options .notice_reply a, +.notice-options input.submit { +display:block; +border:0; +} +.notice-options .notice_reply a, +.notice-options .notice_delete a { +text-decoration:none; +padding-left:16px; +} + +.notice-options form input.submit { +width:16px; +padding:2px 0; +} + +.notice-options .notice_delete dt, +.notice-options .form_favor legend, +.notice-options .form_disfavor legend { +display:none; +} +.notice-options .notice_delete fieldset, +.notice-options .form_favor fieldset, +.notice-options .form_disfavor fieldset { +border:0; +padding:0; +} + + +#usergroups #new_group { +float: left; +margin-right: 2em; +} +#new_group, #group_search { +margin-bottom:18px; +} +#new_group a { +padding-left:20px; +} + + +#filter_tags { +margin-bottom:11px; +float:left; +} +#filter_tags dt { +display:none; +} +#filter_tags ul { +list-style-type:none; +} +#filter_tags ul li { +float:left; +margin-left:7px; +padding-left:7px; +border-left-width:1px; +border-left-style:solid; +} +#filter_tags ul li.child_1 { +margin-left:0; +border-left:0; +padding-left:0; +} +#filter_tags ul li#filter_tags_all a { +font-weight:bold; +margin-top:7px; +float:left; +} + +#filter_tags ul li#filter_tags_item label { +margin-right:7px; +} +#filter_tags ul li#filter_tags_item label, +#filter_tags ul li#filter_tags_item select { +display:inline; +} +#filter_tags ul li#filter_tags_item p { +float:left; +margin-left:38px; +} +#filter_tags ul li#filter_tags_item input { +position:relative; +top:3px; +left:3px; +} + + + +.pagination { +float:left; +clear:both; +width:100%; +margin-top:18px; +} + +.pagination dt { +font-weight:bold; +display:none; +} + +.pagination .nav { +float:left; +width:100%; +list-style-type:none; +} + +.pagination .nav_prev { +float:left; +} +.pagination .nav_next { +float:right; +} + +.pagination a { +display:block; +text-decoration:none; +font-weight:bold; +padding:7px; +border-width:1px; +border-style:solid; +-moz-border-radius:7px; +-webkit-border-radius:7px; +border-radius:7px; +} + +.pagination .nav_prev a { +padding-left:30px; +} +.pagination .nav_next a { +padding-right:30px; +} +/* END: NOTICE */ + + +.hentry .entry-content p { +margin-bottom:18px; +} +.system_notice ul, +.instructions ul, +.hentry entry-content ol, +.hentry .entry-content ul { +list-style-position:inside; +} +.hentry .entry-content li { +margin-bottom:18px; +} +.hentry .entry-content li li { +margin-left:18px; +} + + + + +/* TOP_POSTERS */ +.section tbody td { +padding-right:11px; +padding-bottom:11px; +} +.section .vcard .photo { +margin-right:7px; +margin-bottom:0; +} + +.section .notice { +padding-top:7px; +padding-bottom:7px; +border-top:0; +} + +.section .notice:first-child { +padding-top:0; +} + +.section .notice .author { +margin-right:0; +} +.section .notice .author .fn { +display:none; +} + + +/* tagcloud */ +.tag-cloud { +list-style-type:none; +text-align:center; +} +.aside .tag-cloud { +font-size:0.8em; +} +.tag-cloud li { +display:inline; +margin-right:7px; +line-height:1.25; +} +.aside .tag-cloud li { +line-height:1.5; +} +.tag-cloud li a { +text-decoration:none; +} +#tagcloud.section dt { +text-transform:uppercase; +font-weight:bold; +} +.tag-cloud-1 { +font-size:1em; +} +.tag-cloud-2 { +font-size:1.25em; +} +.tag-cloud-3 { +font-size:1.75em; +} +.tag-cloud-4 { +font-size:2em; +} +.tag-cloud-5 { +font-size:2.25em; +} +.tag-cloud-6 { +font-size:2.75em; +} +.tag-cloud-7 { +font-size:3.25em; +} + +#publictagcloud #tagcloud.section dt { +display:none; +} + +#form_settings_photo .form_data { +clear:both; +} + +#form_settings_avatar li { +width:auto; +} +#form_settings_avatar input { +margin-left:0; +} +#avatar_original, +#avatar_preview { +float:left; +} +#avatar_preview { +margin-left:29px; +} +#avatar_preview_view { +height:96px; +width:96px; +margin-bottom:18px; +overflow:hidden; +} + +#settings_attach, +#form_settings_avatar .form_actions { +clear:both; +} + +#form_settings_avatar .form_actions { +margin-bottom:0; +} + +#form_settings_design #settings_design_color .form_data, +#form_settings_design #color-picker { +float:left; +} +#form_settings_design #settings_design_color .form_data { +width:400px; +margin-right:28px; +} + +.instructions ul { +list-style-position:inside; +} +.instructions p, +.instructions ul { +margin-bottom:18px; +} +.help dt { +display:none; +} +.guide { +clear:both; +} diff --git a/theme/h4ck3r/css/display.css b/theme/h4ck3r/css/display.css new file mode 100644 index 0000000000..c7631a8ebd --- /dev/null +++ b/theme/h4ck3r/css/display.css @@ -0,0 +1,236 @@ +/** theme: h4ck3r + * + * @package Laconica + * @author Sarven Capadisli + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +@import url(base.css); + +html, +body, +a:active { +background-color:#000; +} + +body { +background-image:url(../images/illustrations/illu_h4x0r1ng.gif); +font-family: monospace; +font-size:1em; +color:#647819; +} +address { +margin-right:7.18%; +} + +input, textarea, select, option { +font-family: monospace; +} +input, textarea, select, +.entity_remote_subscribe { +border-color:#aaa; +background-color:#000; +color:#ccc; +} +#filter_tags ul li { +border-color:#ddd; +} + +.form_settings input.form_action-secondary { +background:none; +} + +input.submit, +#form_notice.warning #notice_text-count, +.form_settings .form_note, +.entity_remote_subscribe { +background-color:rgba(0, 255, 0, 0.5); +} + +input:focus, textarea:focus, select:focus, +#form_notice.warning #notice_data-text { +border-color:#9BB43E; +} +input.submit, +.entity_remote_subscribe { +color:#fff; +} + +a, +div.notice-options input, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_send-a-message a, +.form_user_nudge input.submit, +.entity_nudge p, +.form_settings input.form_action-secondary { +color:#0f0; +} + +.notice, +.profile { +border-top-color:#333; +} +.section .profile { +border-top-color:#87B4C8; +} + +#aside_primary { +background-color:rgba(0,128,0,0.3); +} + +#notice_text-count { +color:#0f0; +} +#form_notice.warning #notice_text-count { +color:#000; +} +#form_notice.processing #notice_action-submit { +background:#ccc url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; +cursor:wait; +text-indent:-9999px; +} + +#content, +#site_nav_local_views a, +#aside_primary { +border-color:#50964D; +} +#content, +#site_nav_local_views .current a { +background-color:rgba(0, 0, 0, 0.698); +} + +#site_nav_local_views a { +background-color:rgba(0, 200, 0, 0.3); +} +#site_nav_local_views a:hover { +background-color:rgba(255, 255, 255, 0.4); +} + +.error { +background-color:#F7E8E8; +} +.success { +background-color:#EFF3DC; +} + +#anon_notice { +color:#ccc; +border-color:#50964D; +} + +#showstream #anon_notice { +} + +#export_data li a { +background-repeat:no-repeat; +background-position:0 45%; +} +#export_data li a.rss { +background-image:url(../../base/images/icons/icon_rss.png); +} +#export_data li a.atom { +background-image:url(../../base/images/icons/icon_atom.png); +} +#export_data li a.foaf { +background-image:url(../../base/images/icons/icon_foaf.gif); +} + +.entity_edit a, +.entity_send-a-message a, +.form_user_nudge input.submit, +.form_user_block input.submit, +.form_user_unblock input.submit, +.entity_nudge p { +background-position: 0 40%; +background-repeat: no-repeat; +background-color:transparent; +} +.form_group_join input.submit, +.form_group_leave input.submit +.form_user_subscribe input.submit, +.form_user_unsubscribe input.submit { +background-color:#9BB43E; +color:#ccc; +} +.form_user_unsubscribe input.submit, +.form_group_leave input.submit, +.form_user_authorization input.reject { +background-color:#87B4C8; +} + +.entity_edit a { +background-image:url(../../base/images/icons/twotone/green/edit.gif); +} +.entity_send-a-message a { +background-image:url(../../base/images/icons/twotone/green/quote.gif); +} +.entity_nudge p, +.form_user_nudge input.submit { +background-image:url(../../base/images/icons/twotone/green/mail.gif); +} +.form_user_block input.submit, +.form_user_unblock input.submit { +background-image:url(../../base/images/icons/twotone/green/shield.gif); +} + +/* NOTICES */ +.notices li.over { +background-color:#fcfcfc; +} + +.notice-options .notice_reply a, +.notice-options form input.submit { +background-color:transparent; +} +.notice-options .notice_reply a { +background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; +} +.notice-options form.form_favor input.submit { +background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +} +.notice-options form.form_disfavor input.submit { +background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +} +.notice-options .notice_delete a { +background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; +} + +.notices div.entry-content, +.notices div.notice-options { +opacity:0.4; +} +.notices li.hover div.entry-content, +.notices li.hover div.notice-options { +opacity:1; +} +div.entry-content { +color:#ccc; +} +div.notice-options a, +div.notice-options input { +font-family:sans-serif; +} + +/*END: NOTICES */ + +#new_group a { +background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; +} + +.pagination .nav_prev a, +.pagination .nav_next a { +background-repeat:no-repeat; +border-color:#000; +} +.pagination .nav_prev a { +background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); +background-position:10% 45%; +} +.pagination .nav_next a { +background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); +background-position:90% 45%; +} diff --git a/theme/h4ck3r/css/ie.css b/theme/h4ck3r/css/ie.css new file mode 100644 index 0000000000..2f463bb44d --- /dev/null +++ b/theme/h4ck3r/css/ie.css @@ -0,0 +1,9 @@ +/* IE specific styles */ + +.notice-options input.submit { +color:#fff; +} + +#site_nav_local_views a { +background-color:#D0DFE7; +} diff --git a/theme/h4ck3r/default-avatar-mini.png b/theme/h4ck3r/default-avatar-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..38b8692b4a2f71c8de3d6a12b715df33aada5f7c GIT binary patch literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b literal 0 HcmV?d00001 diff --git a/theme/h4ck3r/default-avatar-profile.png b/theme/h4ck3r/default-avatar-profile.png new file mode 100644 index 0000000000000000000000000000000000000000..f8357d4fc296271b837b3d9911cfbc133918ef2f GIT binary patch literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi literal 0 HcmV?d00001 diff --git a/theme/h4ck3r/images/illustrations/illu_h4x0r1ng.gif b/theme/h4ck3r/images/illustrations/illu_h4x0r1ng.gif new file mode 100644 index 0000000000000000000000000000000000000000..c233af3912ffafe31d5dbd6d06db292b65c64a4f GIT binary patch literal 432979 zcmb5#S6CBW*f;u_WD+I`C4oTbCJ+J$YCw>Vp?3&K6_5Y|5y2-QDj;eIy&8&0Qxian zH6RwO0RaIK1EOM&*swhYY}j}zB}L2;xDIJCx7M_x1L@ zeDyN45`wNmP$C4iKy58;kS4S_ar5J+k4;yaLe&ry3e{HEj!%qhYii45<)Nog)W#^t z7J?=qXeR{qK)pS^89OuVZS5g61nq?&XDDZHj;p)t<%^dg8U$U0pg0IR3^gBahSZ?V zaho4Md`zWLp?eTi2|+#*7#tc5t%IO32ug>bQ_zW1Co1tD`4uUp9wRN@A zQ`6eI+VYC>!2j_<`48vs7QDg5iRos(nvMjQFQoi{FaVGanEsvQ?`;C)mbd^fFTbF$ zsJNuGtjOQ7oL^O4Q-tuxuxlHen*HUP1;Unm*xjnNvkTC0KS_x^)?Grf)lA&fQy3Go zAGnlHvI%uhXhp+-2}P{u#bfJ{`tI;Nrth~}bp)HtJS{Zh(T1LNr=WpI@L31%BhOW1 zzphOysLNYZ5bP=oes$~wIQR`kqUtZ^h}9SUAYetPnr|Z`wzwLNV$+FVTxKb2jB{$! z7N7$~sf*|XUJc$W8cD|Agr9R?KXLc>;8N*l{(Wtv;(yf>YdBIIz(dgHrIg|u)vee- zvPG>P!z#q&YLw1qw>lNT|J(F(qg=32Dp*ExjKwNUYAM|jc)%Ucgd)e5nvwGXw zl=C-#_$sN9%!Io_U-YL#m<{;7R&Te@J{Q>mu0Q`gvU`ga);H^~BCmDd@btVeM94u4 zs8n$t^eaXF9zP)%*H#g`Y6R=^P;fOUwnp!cU?18%)&JJWXL9a1Y4WTcW>|kkRqNKN zb#q@@KwprPx!q!D{Yo5ePspqIAE-K#|9urzajWnZAlte=gM51WPdV_4Nj3R>U5DEg z-hFemhNm(TWe0;z0qfaPO$tF<##2F;=z(jL_E12I6&zo%w@ENrpT=WSco<$3*?9|m ztmC?h2OEg0DE5?4^sUsNtL@kFo4b?k8nl$|1g$Bre_6wH*T7;{j(p9l4NvTPRo8eS zkf)wB*#D}2bKREL4ea)=*NrLX-o9?)3>&{`F4aye*p;3gyW-F?WL+HrQf|yw51Alq~ycmO9H&echwT8Rwo;EEVA-jZe$UhH3|x<0UrrAJ!r3~ zgUxaBgcqhBujU!YQ=MDg+Ai|ajpf3r)b13^ZkX&xA$*yV8huu)z8lIc)Y?{SV3bzq z-YB}1pfPuqh3dL~YAWQ|nkDTjXH}06w%*EbRrMI?0A|%Hqfx!;nYh5hUzoao*!}s~ zxS$qU{o4C%1+2l>M{5k}nHFS9WO*(i5Q_SnD1D%)sWwG=W=PB&prO<;rz6(#y52R9 zp}wQXX2`fstufSngosPpb=GQRcVHunh{bz2!0ND1`q{cP!%=tDFofv*Odi`Fi(tU4 zMLqyAhm|({2Ixk5Y(7_Y7bttaL(hB5peiM{%eVtzQ<|QL>$d%T`|5GU&vz%zR~Cc6 zF0TId;mnbyypY~Er+)o=`TM`WJ_%D}hkDtS!d%6aU|oZ=#ZfF18K*S6LdjpCeN@9T z%Ivg~tys?qTH5IB=XrynkG=E!F_e%x( z(XtM3;`V!{2HiIY4&s!)d% z0Y>^whdtYIa02RBnWC0lcL8*{yXY8w;P%UU*j9PeGdoIU#prY)KJz)-3oAxGUHX1i zMP3gv|Gv$tTqHEt4kT_LoKn1iM>?^+!L%{(_bhy6qjHM^hI!b!IPvDDp9=@Y^6m5@ zukkp|&-Ej|?dAs~^i`;2)Q^=n6x2q?p9uRgZgU=JMY~b8Hi}xI}+9ZRLSfa|) z8bj*&x!lVN&Kj>qDxI8Sp>;E#wP@i0fo@Yl$^ zRtj%c1@=z*^-=`uzoPNF3-+f00MyN7JIWE(Iup5Ir+`PeN?$5eLXe^GW_PFEwwRkn zA*x=2N#+&deyTm?sHOQ7UY?L2p3)D|nVpJB_1LCaVsqil$}s&{joub#AO@dn|17iO zt3Z4j;BBVNviySw6F~6;o=SOqNW|QZ)8+6=z{0Mg7w>%Pj%)zD=nN@%V&s##yksHW z)`=-Vbr~TMk^><3j}!%tI4P#9<0|5I8tHybUAePcgDmEDT)R7g(r$SC+V*>&q~cUY zhtHFD8^2$iNxc(cqjKp(_O4Y2YH*UO)<1M(LTTsaHY!|oC;_KSs)gG31sP-MuIIn!#GD* zh>VDsLhzA#d1*qXSl(<}N7eiD;9G5L(n77ctlI=oAgcCP1Z$OS=r6?GS-nPH`dn?ES30~mmjI)w)){V1jhw5_A)c+^E$3HXe-@LU@K`MpsejnUbNni3_J*! zCPx!L+=Mr)52b%`(K+ol0Q_UYI8kPtyN--Z%@>?o`S?wNd~n@G6W9k4uHx-IVf6&}9NXd(}m+nf7rb6S?UKEH%iT>9F8)-HFIF|)Nc zHYP#xH9(F2vNHAgG>@Bk&uOc#h3GlTXyg?cD=ugrFxwlpbaW8pZCh&(BJG;;l@2ej znteZP#NZw##PYPFmdF^!HA}NDPWpY+CfUGcvv&ifi^GPaP_XRM3&VgPV}@3+X+RBl z_z<;fP0KZJ!z>RuFA?6%{MAmEjJQX_M&NZLIN5TGmaonClrTXiKhL%vf#D-p ztK$yKWlPrjApl+rXD^C{RFDSTkvSBl8$DCYX`&-sGHGmacAcF4w#CA9>!OVCqMeyV zne|2egWIMBCdOiy>o4uIjj$R<;eQUozTt`lre?e-NBkwJD;HQV!Fn2CO#oy9v+x_u zE|Q$DL_uh_>x`N+uRInFVhRx1FZ)3dKd!EcE_$zV2-XS!QU~G?T|Mt!5cDS=-$(!Yqx|*v^c_WriVZT=$6@#lP>)Vc$^q>arS43FAZ8JWXE|5?=_I>b#jos}IW$Fku2ExdQ)3ZPv+jXyAp#k|EU$c19o4h^AR^Wp7(B$gkjOwpZs%yv}soqslU=`czF8_9Yb#!^5k2Ybf?)6tEJT8DS!D$^r(jIV7qS3v-I?2hwzR!MUa6=O2OjZcC^mVX*OrMz)Pr$iCQ@2HZ3$0=}QHnHpCu_xg19&xK>5H`%K-BKB?z(iY`ZPQJo6}8Edz;sv?>R!veMcLgVF&2Q!Z-o zobX%r>BYv=KQF4eN-}=gV#AV9CdR&w_yBMvhKDk3vNBxK&~cQ;-W}Z6%@;A%F(i(C znCMV}6jdwSM35HCKd(BCXzdR^q~g=FB|WF7+Qe3TxPYvDg^TFNVw-mwDICWvZ?#>? zpwV&IhJNPCi;_+`WQ+vua2yUMuNptoS_rHkl|lxe5ytn5t7KaMCR#g7LC+4ZGFE(f z0b|43m%!~j3zahX*_~3n$8mVF7i+1!uZUZhk9P*d+kC2PpNh`%M4nc57!A6fD{JY* zwYB;HAG(ai+&mkViNmZ=G2gsf#lC==kFd190mraVTTO7;IG~IwywqhhYwK&pS8mu1 zC%+GMe$nUHzaiZYUc)tK5HPONm2}q0XW|oFH5Z!X{Oj2*vuqy|K!3F1Tyqn)m$1%v ztCm@ixvK!F{2UCEo^~LS+@;56=$GabFI6*8F#u%3yjVmAFD6_OTcGu1s6CBvM;W&C zx^-pE;^v+ClMD;b1SK=-253Z}ejLV(f1* zUb|me-k0Z@j7^K`B!kFETX*`FJlP4Wg8bSbG?xdE&#dgigPWG57K!+af9fy@Y0q5( zZsSV~v&=xxsWkHo{?}k-3Lb>{$EI0`6@|Nx)nj$}y8pKOzU@Z++kt7aQ~Swm=>m~# zSuMZ-t|?;}qBUV3RM6W00NisP%~)45kplGg-5I=avyvu*=FPEBzNwO%s9*8BSoF3k z$+gM1D%VXw{g#Vmvhrgx$Ve)_(xxso>Vdh6y0Wv)0;OboJVU0GcH>mFh$r8lfjNuf zU55GE+Js*aj@)y+6WeG?Qn9JZm#EmO$f-y|gal*m_t8>OUswVYjv7`h!Ui{MKHP5R zt%`Q0V+j1SPi3f6^OR%Uo6e@bUd>nKZQ!NsrZM}TwZUsKjCmNx@B!wbkNEIgC$K%i zsyExlV`LW`rnb~wpJ>6?$}w*QEFeR;0Vr3DEdew?PNT7Is{FnU=tvL_5-3`7-u>z` z*`Scwb?hGccet%f3AtaZV=7-#L$<%$cEVjUoW2sfw?`3V-VR69+V6zaKi_ot&Y051 zc?l%X3@(%bcgD<5op3o(2Dt3*?tfr#r$C0vN&>D$8d_YjU3Um4pSOArkt69#ws(N7 z1WYTLq!G|@yFv>&MD@E87FBl_km`7^!USJgkq}<^jC1!GXWH}6-74|q^bXCak2*nq znAREF#AyA(vSfFuJX?CZkhNs}FXLzd3*~}>R{I+6s30>pCL0zYQgkqmdyGRRGo=iN zjlEOs0W@t7WOPfvI7M>!&jW$Z!xo2!ZBOjHM7WU@8fxmnQ61dQfxFGWV29)KiCo3P z&>6?vO(M~z1CKhdxk8~*`df1>g*%Hh#?bZZo!uMsyeiNA=Y-$-S|2` z*x)&m!hcvQLlJgf|1}Rqb|ZeMpyQYbtfW>bTi>H`$d!)9TVPazl|NsBIe}}|6~aHB zBwkm+(aGY1B_@POeVU7q!o1Cu#Mx7KRFhX>*xW}o zoKU;Y35^iABNpi?Mydf#0)crK8KFzgR^PTRM)bUt5B*7nSv$`P-n=-8)Rwym+lV!7 zS7{>f2$2qMI=td44dqM+wdq*D8by`E+#{KN8*eT zK3{S%h{rtf$A3)p2t16H9nRlqUM|LBiXLpHRVr*2AKc6+i!up9Ect7Q_0W>H<#<^O z8m~`A$MJ9FA(31B;lbE<wHxz-B}>cjFNMtciN@Zmqy#{-`$a^a=+n(!gv(nn93}IKQS=G?+{#=!!z&kP@tz{nz-UGS zMJgLKfQJoU-{}4K+Ry{M>pKk zKNGrjMmm~QHF2#LL?2FW_C~2QAx$1uHcshc9WUmT5LaOYdmp9;U0=gN5RSl23enBU z=szOVg7#=P-Yet&E6N<$tYH|RhNM2j_&Q*)$-!OtZNoNj*Iu|OcLj;H<)tE|X=3o4 z6L%>9cExAOB7R3yBiD%hH<2Ga?C)}SJp?j|oS+C+vgSno_j3X+@ZdjXMXVe4b> zFUsBtBRQQp+B(rb>Uw)B7E6C@$lNUdr|fuUpWBYyXzRJ+iNhm>?)5HjeLZ75pB!GV z5z9Wg;$+1XxCwz*zi#CdrH2_{WwMi4J{|jh9FEe1R#(&fi_L?6v*!v{Vy-gIVLgqV ztJYn+eA!y&eD4Gz%DYy~V}tVQi12gB+3VCxL=E%WQE7#8l~!=EcB%9ww}!NoA0$6N zR7N@y8X;_}?L9uzz4>ONLC9CrPBV9Av2*9TQ;+*Hx{sbLvpW6sO3qi5CqZyp+Mkcp zaxAy*o*gRJ`kWe{A9fYRaD@f$bFl}s-q4l;Ct2=2FD8?2OO?GzGA{cV2RJ3CqcSO_pmU7w3Q#JxR}C8J{oC?X<-4l0E0Bu+-bMkGmeqMS2;T{F(P zuDD)4ZBRMDH*H8oWxjn#^PnbARab75v#kgNEDR6h=UvWbIgWlZGZC{QDU4b$&rPGr zpeL5+p6+yM=~K|lz!;N!R*M{k8j)~w*gjWV@1++vBg$rl{b|Q8OdVJZsPjKi&0Xhx zuj0eH%q)TV-xNGrW`*~uOMrMbQzr1=Fh2MEWJM2<| zCuw_lPlgl>lA2@XHP*0iRf=iFW#hI5d^upw+NF3@JyG`lB{ec*SO3xOd42EM(vgXY zyL+DOAi3GXN58DRD4Wun>r#@tj-r?6jv8!kn*Xey_LC`00ARA!<@yW{JKJ-gLkjP) zJ-w@r|NP>QwRx@WyyY3qGJ7Va>z1nqr~RNEy_H0SrP@!eivBCn{W z%XU#rXF3GVv~tT15!jcVMy&Q(Yi$GM2lj(P|Ms#Fed(V)`ZUD6bN z9a;2i=+EKeA=ApT)Hb6cwQKM&+Y>+=6~`K3cOgNJS$RrItJX8vBd}bUmzEQx724S$ z`_0>$a6#h`lXdFChnM=fDX492;Rp4jo~L9AH%Jb@1Z7nSlwrC%Mz_vhyaRR zFxo(Akfxq>xVgUFDOSrWYkxXAo9Z?p0RXWOdhnsl|Dgz#s}bjfn|l~RWvp%d(^{C% z7|_H{f>u-&BBP-uWTyv=xL2?is5fvUw(zgiB3&-qDlJ?kd-X&O9GnAU7$7}AEBlyf z*py-PYWA&tPo3#8z(GR3C%mE;1TCt|04660`wk{3Rm{1@*w&fou;?C{PQkA`0-f!H z*F1lKSbgyAy0fOWdh6YIIBYjMYam0J5#H)JBjc|MC$7=>Q)Eq++`7t~sxFz~>Ao_b zW>Zy4|;|Xb_2=g6HB#+hDfpcHgbnfs*OBx(kcCWt2)$O`c9j}Gl;b%%fO zQ3vhCHza-in9$+UrMQynVul$_Uea*KKMp(wI4c&}WA!74Q1*0RXl~=t74#rtKxV9l z^W#F2KtnC2UY{_gRjN&ffz(AO=I4b+>pc*MZc}T`s3?0_J%iTDZKUc$)2h` z)q8YJ#arL^2B3O){d&vPay8BVfjO>uTzmGB-^RuW%7{~i$;Ui-SVPB`CV$LpL#2?D<>QfI4(FT$R78hWC#^ri{qx+;8#@6usa_^HcNj~k_aVdRBzP(d}bn{=6p)V9k`X?9}|+SvC_tmv+FcpIrXxJka_5vKq- z{i}>n-%g=&@{8_#cJ9lvG4;Ly;C??m?&CZh7_>8`I zdZ6^ho=-WSE0a;T+b|B>@~8#T`K&#|7xqD0}_ibP$bI3nx4Omn6iX& zw$-5>`(5v0`z?3Y=Gw-1_Luthq!KnuY;?%K!DGEB0tj1n#C$^6O<0#gq9ybM6}^ zc}oH5$QOnM5$dE+86ri7^yn;zH7bl}yCFOZljg7*f*tiNXe%0PC513d-Z>V+j~wGC z&Z{T0Yk=+S5o{$2{Ew9@DoQVh`qj;I} zZE?65Pgubk7a~HSC0njB3)o_1`e&7_Mc4D@YPIq5HY~J<43gsm1~t4^E|A=wcut04 z%MgitC9kUJ&C1y57rDEsh}7?HBuUW^I?7vyOZ9|}=o@bH^Qy>U*97wZB2=J}Wp)}! zU7KwxM)nn;xIdAK&UUKRvDMBKmr9ghfLmu2FGvAZo$ge1O$?VU{8-&rAa~1;{Xb#hHHi)lBW~{_q_Z2QxtO!&oC#OWbdB z^uqmWTfCnwv$g;)U&x5xk_E<)0h1+s!}jNUA3opvz=^D7f%A7>*Xt2dNk?z$f+Lyo z@pw1WSyY&Gl?I?yi{A>=AQLqrX)K1T;6R>G$6&+3jz!!pCw26jv??jGNze?46iqxa zsVpr6RI=VwGmql;faie~VUQba+9h~2j zfiJRHXGB`VH>8nEX$aH(s^(etd;sJ5UOroWdT+%{|8g{5aJo7?3SlUYCQ~ zIDDv_DO`+0ARA%Qn_a=o2s9b|Jwh@T9UKgYIX8=v5Dkwy-|0fp_*jt_)k!8jLcc#G;V);Z* z0+U;FLJE?oU`ev_(^2=|_tXtIyZd&*u~Ppj4vD|fSinKJ$&}XeBZV^5Zfmq@)sA{H zxQSj@{myt~E&3wXtlL)e@tZx;U9ck`#bWplb2lW`1HVTVM{G+n3lZy?hl`|OY^j2c z4C(pfD5e>$XgkQENz*R$axEE5h*kr9_08`*Oww^yT7$fu4omsDMo z3(<_DH|RhK4U78*Q!xO6OnGaAV+|apAx~5Wo(Aw}tjzxitkksDt_?y&tW>ZNx3@@K zf|EswOl^kj)FhAt&~sBQf-24O%;CHOJaPj^K9boH3OGCDQ3PVN!d9F%vs*|8w2$xe zV4^0lm|zzA<3qHZp!&E7rNK1{C~MD%-SI)z-9r8+Pchg;P|r9cdG@u3Z_tpkd}W-}a4*7?OgI zjLakq$j9pRhokUb6OyAO^?q^Na;nuNMY5TcRD6f>XH4)Cf9EO~MPwpOC4lG7@FG5< zBM|vX17pZR&{{wx#@RMLv@Hc0_;Ulb(63F zfo=4NC&*4;+z3UDW6&k1ftDb`Z_#1v{ z(>t1o0)1bMlDGkoU3A5k6J+=$U8!=)mun)`!8nSQl4s%evZxKF=U9EnDDlNe`Qcd8 z;h0D1tp}?4G8EcY-5~SC@Fnj6;zj?>XR5>(GA3hw$N?LDVJ$Jr0tc9iQCfT@HuHvZ z-i;l>BN_dk*(Wwk;LzpcSPlG*5MEJvC}F6 zBAdIVB$x#y)0U#j9}ih9@~~V*x~xGp?^@h(C`mf}K`;@JVHkg+u2bXqr4te*g-ODy z$=F^WyELJSpP9qw+ZpqaVuhO=^O9CDbmF3K(L?qB;>hkV&S3J;O}z$Tea; z-yHb4*=VFEyzRKz7jb{$e57R_jNpS5DN5n8Sx<&2W_Yv&D2o=Zp~>zfI+dL(E<@>H zTB-&@g=vn0T>%i}#@uv~BQLR53uTmquOi;dBtIxt_~xQM=w^7g8d2 zXjM)?uo?Qv3d)!g#V?HOACJREQSey18Huc9L)Jbm0{ZW%|L*bOInB(-ydzf;2UQV6 zON9Jbs!rJ|*C#0uy#kKsPD9~v0C|Q8Rs-bf4>CbyUQ6;kWHqft6DNnyBWx<@o0-sn zX!+ecv>TzX$LTx6co3aCWv6p(yRgQ-OLPXWy`f^VGvvvGRRz(bPuNCvn=y}{`8|D= z`n2uqP{;zba}Ryyij$LjMCTLim6<}oW22qw`M{&`NAAabomNd1&nUzrbpN257LL@r z!6uAbF})l1V*o3T^h^FfIoS$&bPIoKmmXIe{HWSDtu)q8d34fDJrOu49IIxlq6yM8 z%DT<*>ps%ai6zIPg$nVkSgH6aVMEr=>ko=p_ne(jBWGsQVr{fiac-N{{X->c`)4t) z@4FxE82p;{=)OR~<&>J?O+}LIAuVm4^}p^%cg^;Z)%=;Oj73w)!c*s#`)5x^_X7$f z@~j&2^$n(1LhP%gs@LbFPmA&J|6fiP{^hN_zeseMpDy#(W!pNqOgVf0BGF}gy39lW zs#axa*>Nsw*S{Dv=r2G0U(%ZXKiG6xg_>I|JJ)60xlCIBD$=XamxV9O4D>H5_5KTC zmtpI&YF&1v%RKb2e@#yLi&-_H5AQxK!_Z|!`@e=Y8(LPX%g}aNul_G@E&U&{+5#=h z+GVKv7m^PD)u?}M>oPxGRwJuxRWx2cT zUzgeLU(BleKmK*oUqQPJf0t$Ova(%fyUWUU+5Z0D^49;4Tm{SbFU!?pCTM9~)6m!i z>NXt_)WoDxJqx4#RD{P*Bcx z-JYsWFavP30+nMduRG6*{dg!7>4YN+2#b5o%G1wB!480?+wnL}UghgQK=_jQPo|TR zleSYT)>3#M>B`uCEt_1gT2fK5%4BEC!J&IjaHdV% z_JWw8O;)vFc-n`Qc9SLIYYlIsqu$QWp5V(JH+Ot$Mdn+}?uu&oN=b>ddgF`$yr$VJ zh7DG7-83fD2cEqAdu|M*6f2(-rhV_+GI6qzj?Y*i>=%1!Aw`$>-&d8OLh}+d*466M z9Yri>ot2*jw+2 zhkzc@nTv!hx6MCFa}Wl#?bsITzwDwTG&U?6&P{cg%~P;~WgCNtb4*>zn#Xtsa4Wy3 z5ci=^gr=wvoyzTmZIT%d(py=q5S=1rV2sTdkXrfVejfP_0pYF^JvgGmN;>rBg}%Nh zc8c%GTl!o`Ox3QU#;hlYsh|Qvx4b$KUKoT_a<%4!)UgVUU;n@4YF5H>%>IC&=JVLF z!-M=J%M(YiCr}B$b~xqpPiD+t7qW9keN=3xnaY%YSlPImt$oHhJK(7-*D&k@BcFOv zxW!Q4=mH4fZSLi}MY?$!kHntnO?2OS2Nu<6SP`A|fO@^YK~v3Xjsc$~?o86VJR|1owfnZV=0&pi11+gdUOrsAdpDt~mDg?$W02E;sU<{;jb;A#mv{lb3&ug_nr^Xaq)2!*6I>^Bkz= znnM1tQeNT>6JaiZ9;}wxdB&B6H2m8al4#}xDkbT4*W2BI@tTSseQqid{{)Sw>RZeU z>);g?k)59R1pCoA!yjZMYZRe}{3=6u*gB>3nM1<`JmTc`s`Ntg|({GlChx!$dUfnBD(_GPc zBu*=BFqT`&|Azqz!*v^v{suVxdpwg2mZ{Gk&)M9|Ge8^F>p8-xlS_T+cC@#`7<*@T zH7HkwSUTGRlU6#R*E=y>$Q)05BObb%%e_RwD7w=T+G-M_6SIp>^37HE=AT@yF98Rc zlhRf&_arqo_=tF5hq;`l$vgv&W-yeatf|&UEC5^YL^JiInSGgyMp0drkmSB3)^lf) zd6ZE$ORVy9&N7e;tL`Bp%zHs}7Y`!cupl_$C&Kc>!xOGrDQMqosR+wfK#iGstmqeD z*YXF{CM^&G>T?IKw(G@HOQPKRx2uTWyU}`wJd53ji}!wOqBdT{7Z@>8J&96=$%{;@ zb*$&8lNJW6Lh-;l!Sfh_Q7q*#`;=0-Z${i_!Z%L_;8n{-gwxx;wr_!9>rZ%;RNM0W z=&fzppPQue9o9FzCej-}H_!PRHss5?xnJWE?i&o}ZRc_`$Wrva@+vt;4)8RCNHk z9L8#~GbeP3tgvS=0EgBD{+O%AEBqd$%qXK-}Cpe+!HwA$gc3eRe`2%gOA z^$uBcfbxo*eF0VNjgZHOU-!ln3UVFw+X6P401qG1ZiatVk@u7Xj#(*q&;e+_K_%|Z z1rH{h0h75rN(<9nx$f?XLfL!n6qn~z`@AzH{ezVhgHj?aoB|kmnkwOAt!_J1vTSrI z7I+{4eb<}j*5&=VzWoAr_T)3Jal#=&fmS{$DI^x(1 z)$PZycNL4VN(G(G)!CE(Eb2L^-~sxpA8iER;%k7Sh%4tSMQAOGVSf>iG|pP0{vn^a z!->u_Oo3IJ`vU;$0gWC?v03wTp{h*D7gKKilUb6u8XzrMEShT;dM zTC7;46>Ck}Lk3!NTnf4B4*m(HR4TvkPz|8v`^3qY5Q9a%mlyk4edDFkUl?+#Zb4d1 zGH57tJGR6Zmb~`f@a8JTbiNi*8+fsQsAmDSsUN#Wg%aRxTCK;>j~%f zt`1MHC?@2iz+Weayn>vQnHI5|eGjdm@NeO){%ccZEFyrbc!V<(uy8ImJo~+Io!Rf5 zY+gO%ypuHXW8wOB z^F!C_pp;nssF?MxdqebqF*QJK{oIbcXxWRWKbKrKF=boY-`=Y}vUN7KAROHNZI$$L z*^9Bf5!+P=2KYLsryp1ITd!KAiLMQV*K>JzdIiga+TXYL(~at`Ls_An5J8iEUGu{+ zDTy`ku0UdM5_)87CI$f>*;ufl%dr>}ojZo~cT%X!_H)YQ;yV8nP8mx%wdbFJWLU#w z^`6od3<2iHY~SLIfTe|||9;N}T>E+d_FiYk;U))l7cGBD<*Pe;o0#}L3~fA~IDLurA=&vtTaOV7TTd=!Kg8c6dmZY++oS$0Cgj7fTQUy^S-xQw4 zqvPKAxvyQlM9yvGq_08dmT-`5Bs+&CGCG`#3X~~ttxJ{)HWS4_VS>Yd9iYY=d5{5F ziO?%M*B+5VitY%BP3{c_#1K zAfP#dWn017i}Is-vA!d)8$JI*9V#!|#ub7gXMiEmtXs7a`LOF-Q1-nXEMxlMMegn-(1LNA~v$`Z#{RduI zNaBE?ImRFz*6vIJt{2I>7ER-;Jus9VDq?YIOR;1^F<~P=6ke$;euwIgjY7 zygiUZ0Ay-q)5Mx1GBh%xrig3Z$TDxE?ZfUe{2U(n%?MT$L9=Tez4`%5S;7$;d%iKo zLrkTM5o+Hts8Rg`8mKr4$Nk4Rs6KYPCL%v%F=vGJ^;SR4KEjwEHv#68?$w~ zTYA>+U;T48!xsK*j3L+xPoF_wcUqU&*{alyax}KzDr?IDTLHdlAYaj0w6lnLWIJp} zTtt$&m6YyiwnYgzkBpQqmvoIiXPN?9z!avU`Wr&?nc^$Z;WrqZA187gb7arY4z6Y= z&$csvI^j%Mrb6t{rYyB%jvCV=6j~CTt_Xa z3L`WKU+P7H_!iZFrDdYwp?Qt|M>OoC_(b^ zU*{(%+FdgD48^`0g1do?i5uhrIzkjvR$pN)MqU@f^0?4huF&L#x{-I`dIiT#DyWA-?V z&0BT67B)1~DE-G0W*&_)7NMPuF^3xsI8DTMPux#5N_YeNXlj+odwof-{MuM`)etIQ z47`$xy!zV<$>(3-FElbCFQ)P3Y>n0`J>)U#J-f}pY3#qjN5jn9^2ojca_BYOgU`qp z_rk^}#3cY{S6B<$&xZW-1`ve990>N(*TNXJnjgPZ@9Yg<)WRT`Q0P`gvB@Q|7>gGZ z&T8tT@t33kT4w;;vg1M{*FqRMIpK6L6S9ZGW${0)uUfy!_<->T4X=u$~L{ zRZy7_O!#%y{)bZ@cU|a!l0H`(#d7>Af*f{l{XPkSCJKoF0s){j>@oUMgbE+}x2#-m zY4&Vqtk|9coejCt-!xDqwdU)iBbv0gGLe@HQEWRnZa30Ov@FLCeZ`~jbySNFwCXI= zdj9os47pn$Ik&s_Pe`O|%FxEkLs5^1?qpP&-bWTqUFM5dUp<4!tw$xCEj_e+!b3m1 zRC9vs^OJ)bFZ9p1i};Sgq?y7=y?PCi2FlM@rcNU5&co4CWC{Rov{i^Sk~eLJ)9h8N zr>^BhD3NS2d+fE&Rt+AUL?!Z1Z)NrsOA%L=_ZJ&+#(?H}8LmRhq?g|O>aE{NAy{`} z6h#I$XkhVHYM}`I)t?c+cEed~Ve=0W$H)MKAm;OH&jJX&4u7k)5lhc-V_#Vpn>hwF z`E^C&LcVnLwg{aFT-W5@Iyj2^&Gz3)1`LolPnczm`RxDU0o(Pj3FA+c025@=QD9&^ zCu-aBU)esU^`9PNe|}JVaR$swhso00fXXQOzUEl@KO5y(noOO4O>fXa+V7roWn^gm zWkuml;Y?+x!olL*KB6DTW)@T)}$gAaxz6aUw|}x2Ke=lD2VZ#;kdh_O!FZ zv}^RV`<`hx2T8}BDHx5&?J{JA*gqS^eG|uYviR<{EytPpK}B~0(ovR&F#QB`tE~nI zo$ac};Vrj%_L|yt{ia6vrEc|uDRN`mD^&C7-60Dov}6fwD&k1QBqDN+Y+<^Jb0038 zDbSsj{hldlZ^718|5<_YBkHTY#=^|`9F|zP$3R8WPoxR8 z$~Kz-pgtF!=8(JgInuX6GhU2PG(ep^N+#!_5~2+v%BSZJJ$-lO>4zsz|4p@%m*Vh$ zo<4Ooj5Ef#*NhelHrtBSP57!aX7QG z1#+IX=&bZQ)wC54tXK^PZSSvmDy|~0DgW@=QShP!AmvGgZ-PsNbmQX_w~WQDmzlH4 zm9v6Tr~9^tw|{;gZ2Zi!9JTa{g-*B%JG$e1#A#opX|HP$PUp+V)v-kBM_V0?Egpz} z4_yDCW-Qy|N4BvNf!60ylQ_)b4KEXTGhYsU`g!%!@28)ZmOe@8hwg59>w0o{@n89K z6B-n&hiR)0zuaP=V)+Rj3ZyptTf_e_1t8Wl#x~QTAUsk#@#Xu^@aJFD)o#P6VfhU& zyiaoH2|M8cCdX6UsrTQ$ju}DCD~ZlzfDdbDfi(EEXDrOsOJuy`OBZ%$!a=OGt}B=| z9KaQSuZDY|hTQUgqmr&{O-8{2a@eir6zmyLQY0NH=a&MkZ$kXRYI180>fL@xU8)yO zxuvOk=(f4CjF0%y;{bFo_WvY0JZu%=>BZR6C7bG=X_K&Z9qoJ)u5ddT~wP_SOon~LQy@5SS zFNJ-CZbp?Gz1B)4ut=Uy8ZrW03rTs&CyEuaJjTDlQy6aj$u+gk6NEWw{k9#~pw}L) zT3`Uc)Xu-C1Rnu-r5}PP2df?Y&YNS&454h+9WSIx)PSRJXb5@yketYsrQc=8To`yd z+F*oQ%c2&fD=HyjAvygkR)SjjZ87doM?5bM=jgA(oWY`<>PiWC{O>rd`ODj#A$>a^ zefYFi%ey|p(7?9m-J^cbk$2K|z2b#o&kDhl3%wtnPuJNVld-?D{A#WvGM^yjQ>CZ$ zCM*MLv0cWzsKtGVtPxwj`K(}jASaR&Swp+J&@*lXQ6FV&S) zV?-zPi8MLU!B;+m0^BBk7qp8gbKcoxFL@H{2+^y)w~iaEm^oa z8Bq6)kK>8~u5;E<1y@~PW76C)*pvqXs!M^9#}k^H$LEUJ%PdB+JAc4c-mWOANyf(b z)sT{B>zC>3!82SheW%eunz=%~!ZS1P)py!0T8wlkOg`*k6RwKQ0wd+uZVjYi2oLip zxorQ`B32BQ@FyoV8vAl^mQS6d@ijq`iW9K!8Y$hTxU}`uYuINCYcNn zQ&bDi5s}~PGx3>_%l7punY1Gjt9wQ|$gmy_1DWlZNM}lcv`Fflr<` zzv-2HeZ!xj9F>qK(-$UIBd9sRiFHm3jyKmUi}g?~`^FQ^@IQo_8AhF-hHjjdOXxP! zP^@xRSc)N_CSED_*p!lnfjWvA=oV_!9iU1AC%WB65 zeNy#v$uiHB@s{<-LtFi{(c3573imKS$;cma&3rz$Y@`sR^Zw1bL`WVMPt9oVux_WPf4&!hqCV)$GDN^+b)@}uvGmZnG%=jR<6f0|g z2*}V@7&zQQo|eV?!TMeaCOabQPAxW^VuWQN_SOki)%oDf-UQAkk-PL&GY4(M#JqtT z0lEer(XZVty}7qa;haRS#w8Y5%MH%-T5G{9Sp_9vka+k)rbTJyKBM`$^0=oRw>x+1 zT%f2c93NLRHf}gF6a)t9mB>GdVHJ0f<$!t}K<>;y(V3b^SHb}fCLSayG&`#=NJh>I zyi&jcQM!X=zu^D2xDeKvA`4hLoi~)SdL5sHK6PVx@p4estSd4CH_sexRNpKBz3Iwc zJsrbyU3h~v@VbnZS^|J*k%Ll>6NwO-;nSIo)FM(?dMrkqiu*j7&$6cyJ`$^(vx&r~ zpd+4cwP4n&Kg!Gwc6+v~uRRaPO69D#i;zBMF+~d;Z+22A6C3njYT;{3)}OJkLQ!D1PvkMW}Sc(u;SE{=uDe_}VUQN!u<=4`ip(B_cHe+_Q^xf6=`w3V zpwLjdBy-m{V%j4+q*ALD^wSJ#F!O)v7AL;QemB~{;lvuCv4FC1vbB!m7Hvx*GD-Kv z$tGB&FQ7YVsne8IMFYykiur#XF>F?mb2L|PQb+ctC~Vb5A>&0E+N(9w_3-zX4zL2m^pB*nrz+_9inK4Z+pwC?7&6*zI= z|B|a$(xe|8+N#pcV^Lxn@I!Jet1e%=dy_AuULD@5-c1AKVzg|XgNE>TKRj>-6xQml zbTZG40(i%lcpNPgn-*v7<#j-Z()N~FNweuJ9Kdd2IjC)QDpoBdDs85Z$*!bVKRF+b ziV-_wtwK1Q&ope;q64zI1g*-7AR9o``&cqSi1Me5`N>pHmm)3$4D9ZPu{t=n#3+8M zKyglbJK=7?Aumu1U=0DZTWn3|)dTWjgc7uT0WtrI37*~75#JpGA6e{K5A{ykvC!R) z&Q7Wcq`^#(73sm>-Tz6LxZjuNEeVzoHdUf3cY{%mKky)F^19+tK3eLyj&uv}e9BOP zV$17MlzMgiR&yHqe9XLBY4)p5>M3B-fjyu&x|s zIu99iDXnzQZg`)c)GFvQzPEadTszd?caJWL+B)i3uL}#nHNsChJU%#<^Q2|O4N4a< z_WR5!gI`+4u#e|<1@YV!a-L1|!;*pYc43ry-2nqKH8Nje5Za6F-Z7qxF-c))q+4Vjla8N1p%?6y7BcMjIIR&6jBvlR0x&Z6#C5s%v zy@MZD?Z>ilaZLy7MGqc2%Q=-_3_Nh>ZlUP>xvOvY7k_{F=EMb^$G@f6iM=W?sS1IF zAmG~1>+$2-mDi3Pub9nBH6T7Y(BFpoxGSUE>g(mNAJdPfcJI!Tor3TdXFsn!`v-Ov z1mcM=uB}fOB4y`U&u%AXAX04d6?u1ll#jpI5P1_$a)MJVB`UnF z`QN&z;4m3U7pG2jArK`5t?*Lg7q%v6u%r1d%tUDq0m9o zQr3lzFr|X2E7|cvX(IvJB8CF`?tiyMft3!Qc&=X9#@RAGQ%u%o^EGMHqp}cAu(tv@UeWA&{ zEgc3F=qF_e8`5tKWOmUZ8$L*8A}aR41J>A6caXaLqCEqvUSk2W+>#=mxR6av3k}4T zR2;f_>-cpLgjKLaDZogOku5@)Y)Q;rCISLwk?P}}qsOXQGlt&-)N+vOlaxz*FM^Q?*-Cg90OE;&dTO_1TjT(b5nfW6zRvO%Lmvbt(t{`}9R;#O#&KFuz=+%AUXe-`2D`xfSjdJU#Af8#K zGEkq*-KkN!^EDEX1?yj)!Yha>&o3ZoF26O1CD9^dn2)Tgf$KjNOS0x13Dw#p* z!SKkQBfldO)bdH_U|2I4PKMKdhBsZ217<16KhsY(F!OFI@c=p?a|myqeI{mcD)g#`K>%MV!eOv(U&@%9sHRMCv$XhTyM+1vL zT07h?w-cXiB-dLp5s~?r01@!!AbfNf9V4!Oco5@uUtNvclzqrzhFfd$@pwMAy~MD+ z%%i=+CSP#M*=|D3YX0DXyqd>7IHNq&(;e#U4{LTo0G@`dHN<(7wWAr89Csh(_L?a< z;6y&GN~e-pSsi8#zRT8g;IR(@y3y8cXMt=U0k4u+*eGn~P@%N&;+J0_H6G&773?}O z>_|Hn6qz(vl40jta?%&lxQv_lhEXHrJ{CiN#cr)%W*%q*i{tRRRHMq%Y&LZj3KE?y zC+IBRS1n=SZ=C|iy1 zAF3{Ud5xCVJ~;p+(!oUth$uqG*KEXCFius}c#@0U%&qkL>g{9m_Uxp`Xg3BW?%bU8slZeJ=v!3TOUV+eM&8zOwflCV+*0P3WquRSP+c zPn|y#J#{JJ&87Xgo;*7 zg3IgFXK=3msY)jzwu^E!D?y`d~5zYcc3?Ct9gWWBFc2Tj9FRZ!T z-f2fy^b~*thcOA}B}yR{#6a@QdlXX8mq$Qs6}D~D0u&hj&=#;n8!bzfO(Z}{!dm0y z`UW8)o(rjRai0LRDfvQBr1s1LDvKTvqJ#^i0|vq(w$K3Da$Gw~n#2YBZ%60yS}Q51 zQWg=rzhfbK8NJ;4fUSBsIW_-*|5tKM@h9!cU|1nuI#GoBJQc&?{?Rv#_Mr;8cvr$0 z1y)&T?ep%peFEI>W4jBmuV;o&oa20T8OtkQ!a68K!KD6W-`_b6tT;wD+^xAo!=>{I=Cj@-8!&M&UOZm z<&>V7z8&`VcK&J5KdWGuNj}87z2PZ%r|)P8^{jyq>2_T$hS2uby|LG7+I1GOiLPB3 z)ReeZ16AgCY9(%OMkJjDJYZgQErUu0Xx4U(>yC14D%yi7kP`y2(<<++i$9Sj?<_hRiYp{rC`gf$(Hu%hSV5paDe3>57mt8kf)@9r#N6g zKjvIRxiy0BLSB~CHa|-Y{XL7i z!rgwXXv3aJ(4Tpwks&#Mk=?Zs4$rg5DvHjbnXc(Z_grz75`p(7>Wl)^ZYXLbNt?=q z!XzQEor(=-2p^Nt2QODenbeX!7fNDkl(*K@-K*JiWM^jx<_ZzFYvkY`i%GRJ;sL3L8l<x)@)iYuE*w&}| zv%`jGO7s@ixC2}t=WWpf1$u&SU>EGYPwCK*)lnx|l<=N&BF<54cZT^y&&j8y^H~)Y zGT28g7Cny+w_%21?a42%WS}pCkXrK#-{we-P3_f)FNNXEkuRPP3|U0X{Uuv>+@>S;`nLx{w3_Tt(c5|*F#f)|E`DrzZlqm zLaG1Lz)GU2zZmTO|7Bo*q1XS-V1G$ciIbHWRV;G(^YX74?0*>8!C#fs|H)u~QQ7~& zV1Gf^|C@yUujZ-*;m-WZ&;F9C|BnXt+J72YNk#ToX7=$v<=B54*k9=Ne>2!$wD!iY zeyjw;{`mIe7vud813UUFVEaEA>@O<&KNzeeQTzW-!v2SWRs5HMWhk1t|1z+?s=o{@ zSzQVxxgw$bGO%Hr`LP-j1M3*N3Dmn-84(l)^|KhJX+s*gyx17iZg|nrUNB||x zrkr-f&xtsjGxt1Q==a?N1j8@$_7F1djXPW}0LMjcXcZuNKd#L^S^2p4CWnA-_z8Vn z9oT?;f+T9k*WT<8SS!N2WeNZ6lk+3m0gkZki4R_Zl}qX$Zqxe&#hd1TqxHu z#_^M%6mfMKZ{|G2($dQHcyK3zTU8?OnD!}64;$Dz< zpQZUuUn`ps2iSj;|9d!Lxk=k@HhYysyA6ZqFxa5NBgD+ZFF$|!o||2Z4hP8Tzpr`q z@}q-lnp%V~l;iiUAq5;kA_l*3)M7&4XU6#}E+Ep`g$)iUMKar4>ZBVd*G&JO6fD9wCy~{It0FDhsV@0JUqYnO<7m zo?YU#;nlOU^;d2Qu%SFDiGlr9Zw*a*^}Oo84J_I6M7v(}CZ^e+wQMq3zP^Aa8mhB* zZx~MAtX~po6i?IAhc9@~vSs(t7=hJ)3@cO012~BzHbI?KH-+mD#jXmu(;HheieWhf z;A?l^58$-O`GudMX}QUN@%{*HGfbC{t^iU*IhFSTDijX5?Wl}O!TLVduEdl+^92c~ zQE-Qh{M)r^=fhjh%{$Pe^!M=&Bvh4QON}e<_jB(mWR|nvk@rOPzO5d!QDI?CSpq>f zAoA4MlU*(F?XOw<-f{*Y9NCTVKEgEd+^y&V3qsP~PbKnJCp|;*J6>T+$*O2(sYLSb}S=8EpG7XwM+c45Vvi$s+=yMyZ}s zXs3Hdh`S{73tCqDgDxKL`0#L2<%g2@19GsjNwoVhBS|w{6h6 zq=l+}ZOfBdBKN+rFKigp*^M_F!LRN9G$6CuOPa|-U*LDeRC*Jid@2i#XZaJ=3g1L2 zX{2!3I+3)N+b2WL%e|p&Jtb#=cyxj=yFeVdBeUL5N2(vJ4O$n$K5LZfbSliA*`OZh^S;KnB!X_Zu zR(t!iFD3>$>r_AVBR5xNvub4=B2+d2EX6s|AalH!p#cjNx4Gg# zhoR&B+QWJ^&YQm%-SXP3?3;Lj{f{SBrcZ79GI8_hw~r?Q z={6cplmiqtRCJRDoRPsdb^Jxx*9=hk^PT3&^&*xxZOA3B2Cq5&1jT92NvXF4Eu%6J zxZN?%%_7BBFt2tajjS6B=8Sl~Q>X0q1<&&cCQ%FdhN)XnNU?O)DyKHPw?R)hpRGxk z1Ms{>%cQtf9qAuZ_^Cs_BsXf_I=76LsM9p5{BVB_t?h(6q3oy5SsXK=ue@puEA;t& z%MI{(_b;9@m4ytX`wzf?Pb#Cp+wZ9QaPw5d*@UA2O6!OaxxfB&~j%i!pDDIUl5j%R+Z;F@XLNcl?k138X4-Ol4nfkoJ-7STo)d82mo}B2AFy z!f{X~aMAbl4tNqp0(TRP4n?3v%!l^U-v+Ug-W?!dR?huz11nlZC+A7W%ub2by~5os zMc_{NA;iPhY{};wMsRyr);XvEx9x_M+L~;v7f^9(6~^r6t^>502yhlANpMStBOuEH!8TKjMt*nvN&~{@cALLCTGqL&yCa93$Z=Mfwt5cqq zB2TI%q+~PF@D7;PQAC7f+r@)c;+!XE`WK^)VF* zc|~u~=^WECHoUuIno*KVE-WkCmua-ZfYPK;W=F*k@B0n3w5GG-91R6U9aSU(=?iO1 zGK_O~5-5ic5uZRAXL};dfU!plbq;8OvZIWA%m6WP0DTJLO=Zph)L{vW?~=}98e924 zy8p<7`WeVQ@E@-W#cYS^rO!(_+0hO_%7-nD=r8M$c@>*hlb2~IA~T>X63|&jp>$vc z0s)|-qLs0cEKFtq{8<^ZQ*83RD#e(f?9FnRB`9bR(%OhpPC~ps0addHxl@cr)6f?$ zV)ci8$1LEDt9-D-1?R>D*@Od27gO&ZKxqosik2lwzev8o*=`&gd?4GSH`{AId+SOz zoy7LFW^YcSf13l;nHl+t2s1LvYYg=ajs4p}HJI!8ISTT8lC(fZ*$WZTy{W`DIMPi{ zfhZTtWquk4?b)e9DtZqOk{iuRw8l6EYw;}M=TDw(oax!=^6efmTt5e?S!p4N032q*bpV#0Q9jydB+`Tu8swe`$`t4x+ zSc<|kPCrXMcLk$LEj&f!Wb^mF0Sf!c>3a~Ve~@Ix7xGJ)xi@E#X`hV%I&#&w0w2Ga zLzhy_WC6Wy(zEF@!L%*?LlDT_n!Fh8!6>vHWG9cOkV+6_VACAn8!s%5=WYE>zu4cJ ziwxqT4|3reF7`4PpQoEXZ(AfKqd`DuI32h-Yxk0{OItZ2_z8L+b>~N&Jb=Hkc7`>< zO`}2w`zWbAUar}2ZmlGKu$}_B!+23-CWJbFM+Hzk)<7UStk@Y(U_13Awsn`4&@GK8 z3NL4cjh@;q5~7G;+)vALyPinbi5*#l*qRj1*+%Tpc=?qJ$(vNLHUR}+qg>h4Bu%im3WwQMqu@r-$psMpk>#w%Kbq8(BEm4*Z2#%DDF9Yi+&iSHKosTFBng}+P z!tDGQ=OF;sd@kpI1XcM6Rl=q$21-eccIA4_2>{e{w7UB?eo&DS7Zt-Yl3aKjixI1e zUiotIIXu*#p!Gv$mGmpy_m(GK96YgDbK>>o6HE6_$SCP&mY(2ll-|ZScqvx$Wk5<_ zYik%j?NTx^dD|$={5e6@NjkEX4m2Hr>CE5xgxbrLYQE$k%b?sooL9#r^gbszKesid zk&QPtbc*c<9i^`?b$Y>sIrFNXc=i79IR;Zt$C|zb%{7gcX^wJ zpebqq%PDE?%-nHwJ#0@t0kDvEG*sKDB1-UkF1gkJmfYW#&Hbzv{|hbSKFHThH0}_r zZdl5uqdi&mBaThsN*F~^*e=DL2?OYj0+iFpw#V)SmIu7w2Y;s;?UKB~mymJk6>l@p zz#${_MJL*yp6V92)69|lZ@WIZcl2E8=)d1_?OO-_YcoKHSi_(z$nHeoqo33Q6^&UG zS#>u>1~uT5+cuFDWz{-PvXnoNODKm&(M7LhP<+V#HjwUd!oZ~{p&|W|s=xiqh_Tz?v2npL5}}@IWnlR+J$*0 zhsFQW%qIh<1_n$W8C|^;06D3nyx8@rneTO9vS~(3GDx=B+eStecX%jLBp!^J(wBvm zsXde6q7Ly9%InWvr2t`M;3v$ze_GMC&a_4Vx!bZ)bjV1E#Iq{i9z6f<9=p2%?8J74 zKDfB^`$dN23kM5%>tf`Xhy5Es8>34$+8x6g)-_ZqL550G&55oSa0d!A{Y)-Y=`8z> z4q|3iH}&v|Jv`8;<06-;8Q7&@zgB-=h>e+N&ksxJ-c0vq$q6Wmm`y&HC9LHFE`Shq z{cDex_QimO&e``W-?M*veP2nE2ln=Bu!Fkg$8-oR)nT5lF&W)<*p}jFe$`X;T!AK= z-e4+3-kiWrypgmzWY2gi1`#fwlf=LI{hnt1F(am%L5v|)2I3vCFF67vp@{>)hBrD{ zQ??i7HUyp5*YJedhkHYCr_m6kg_GgWD10nX8GC^I(y{-Cvvm%lClErJ0cq&Rw90oDEi^@js%B*P|yfua$te~oQPBy6}g;Q8u`&U!U- zN26NjzdOsK0 z%^$1m)E%$f-CmDJKAGxZYIb$%+BKN&jtQAHBir*(tB%5nLSXu+@iah1Y+=T^4g!1B zhbrdeg9lO3t;n+mKwhXMjDJP`z54rmhW+9(mKQuykLMd-^>Dut+Gsl73!@n9V8Yn> zCkjNy^#cCb%kr&(5uo{6*z7K3WuNDnRP#Bs2a0#j8-0hhX-l0>*ji4Qnvq$Re5l=6DW^>ptU0?CsgyCk#G@wd%@_$SNM)K*zib4p%Z## zd*3j^+%COo{_E6o01!sM#}Va#WRy}E#Y2G7W21NWURJYs7$twhT;tJ<{iC_CM|XaE zH2?df68cFg7?Ut_e^vm%RMUo#Bp@^La$_Xe0(mpl|DXvAxM&r5rG_D8zUT&IGSNfW>s-n*x{|2^3&+6|u!~ zH6;bA_N?ZKBPdC;AN565$1S-mrV%Mk0FET^j1kQfEWoPvI=lT|9XHPB>b4Kke{u!r z_9FPmY3I$Q$}$<~L%*Fvdr<%0DD9~YP-Jwjqv!jEl*+Ed?&AI!d4#b59n`Pjwn-wP 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%0A-(I6CF;Ns|Kdc=6NlrK2L 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 z

      f_c_m9kIn$8N{Oj$qNNJR_^*W`v?{PKo&M7~$^XUExIobX9H*NYraVI$X$Wa;` z-`)|x(&cG^AFQuTzsHxRU6c9XXZ)d?nYr!Tq5bvVg!&b9{btIuc36p@X9zy9DZO8Q zPV93Oy)j{4rbu2pKW zmb#dp(h&-M`_BWBLudJU(PKD$-t1+`ObMYul|A^cfgM$lW-A5L0^RnGH%mt-VY*kV z#m^_Hcz3?!dWQT2EqlAXT|BGedk@Lqi0U5`7S*D2Os|1Jk4c9!6m}$0sH$a2VzkZ8V z{s~>G>%Y2`9=bp5YcmxRNLSKj{FjH$a90h=R?Q%LvKgaByf)+L8A6^Zyf<9)h3*2x^7eTHB=I zWocp>!a{#!v{V^qK#&`hm67G;=_U2WkRb%!grGU z6b?bBq1w~65CxJ3v85JUS6>%;1pO&R`$2`pg<~UQ(v-A+fd8Mq^vItqHq;KawYU9Y z;8qrp9P|fA=ln@wXXRvhd3y~?3)?0T)DJ;15Yz;nX*vU~f}}z0`MG&x6JzKFB&||Q z_4o10<5E%nzg3e40N}p?>Ye`q)IPNT1*mtr)fAeV{sGhopT-K%zq#Jp<9wEpsnNxF zt&80~S4;Rkb?3EYQ~(v3E4`<*?-Z1clsM-1_^euWUfXEs-jkV{>)kicj{&n!%ZIDX zC^g>mg^1uD(Rmn{e*g8~EdHtpQX?tC6lmYRnoD(b)4mTZCH3)&bv7o4tbx#ZCpNv5 zLr7R36^Z2YE!_I%4qaR3&d5`Usd)dMLVXzzsyVDi><6zL;jg{*Z4Q-c*WDXp2 zelVm5lS$4o@&D1+k#+5>^?lg?>n~{vtM^m|Fo9n-i#PS=gD~rb>$*GzJ7vv zyquurHxG<%^H-DK$tw>3_I7tD5P1jtJq%U)028yiFIw$kn*jy~3=-^HU(7xzr#l3@ zrYK^YtnaE<3Lg&MW4KMjP7L2Z*G)7_{aL%1zSUrSfXX#R(q1%5Wt)M6#i z8edi*5@m6DhX~pmIeD28UcNGqI+s4bKAApWbMwgN2OnRK*7@AJi5dAv3aB64y7k`y z_0tqqw&LQ_*>od#RmAP}{2K=XNdY~Pu95H%;3vE7NRwaIGCReSeQ}!y*3JQRH-Nk5m|8Dg#b(LUa{)sdrF5@;{-)_b4B?2rAM_}FTO&=Ke+klzmHLrW{ zM7QK8(+2QQ(ZccO<-poC0N>-Tylb=wjaFsm4l5cj_Mg=8X(2fm)$_&!HZ{*Toi(#} ztSG4Yw3|9c+uBCz+tyG`N9`EfJcqb$QM^2nK;10>0rnY@`bq)6L_Z+5>tybTqblpI_X}|OHa9&*x z^zO7`K?5zPk=WKL#FwA0Z_{xLOm`|fMU`X`4XBbB{$$Lq3wrvzbSXQJ>>na-Ro7}s z+@Vm4APnRux%U5KXBI!u{S3Ec(7NJ1R*ae5UO1`}5%V)2My94=6={M}p^A1%zaCa) z>|~NYF(i?WsJ|Ka`JTKFO z85pi!+E3h%PeNZ+8sm1EY&zKKs`ToR*gx%9e7cU_woUupuz$yuB1SSNFVi3I`uE0N ze99de%gKttQy#$P(-W>-{hu87c6S*b(sEUb(wmF`Wk>PT%rv4KNRDHB0(Q}o%qz>$ zM={v(;xaw079`7w>%N-N1Ml9|xhLy_d_Ph?Lufi+kdN(j>d-s4bK+el-}^TA$mhAt z6V307#pm?I{cNw1ZDlU^R;scH+C+(p_+P4#P%r)A)Vn}S;K^TpOa9M&w9#tm1>wMR zHI33+)Nr+6H40s-`e1f8>_mYWnRw1#Qh>4_saQgfpZuF>5Y1fOS(%|A*-WseKKmvs zL4H-?xi|&}zcOGVjC;fi8*Dgoe)MaZA%q>Tj4RpMa;V$ z=IE8H*taMGu_G)~f4x?^c}jigDe9>=U6wuS4Zyl-QnqP;(A`%=g>QG{0AE^g-lw%O z+I;Dv&_mo--B+bm(GwKDa{e4BP6|*Trvf-^-ziZhfYsCDacTO1%XTA!-e?7)!XRX1b43|8RhX6_+}HYM znueEoRZX~|<^dP9{SLVSxGaNZnGpcwGpILOXAO z8v&AXd(^fiUmez>LZCtVfy=1@3}(7hFxy1mi{tr^+c2fH;db=iHshADK z$2pzvo?3ULR>bsN24HOfVQNlT?Deb1AK2+a%x6AOC=BZ;=bkbNe8#QIr#>`)D>>@_ z90nsI!8gwlbw96X9CZgqb9lf!y$id2cH5p829Rx9?Gaw<`y)Dn^MbDJ6X4bjA5 z>}nJ3cC-JXc-IZit$Dt4-MopuHQ{gVVjv4Tu9a9q>oX1@%sF|X$B(;b)b$cfJP)7T z)=iTk#srQOB?lNP@vk^H4cd9$_0I&Bt!^eFo>zWLeGVMUhFm0&gWJ;$nDTWx^S`_v zT9vp2c-pr9OU@vj06?XUS%W^rglMEt=DtR~20=dJtjF|>n@rsSQJDG#O<}5n``#+zU<5=pN5Ju%?HAWT>RY>hnIoA0 zY8m{>(uoEpawR~Mt7Ld>+RBl4|4MJ1RQlfZJ>4~~ZGC-C>A~{Q`jsVKNt$`@H7q{a zu0W{25kV7SvX$l#Z#KvNbW6-s5(CJ*TPQ4xsRY`D-8;`q_LZfMRSWl#>LXn~{@w8j zDB7tY0}LY$*J03@IZVpxqQomSlBqjIiOzldL9^orQpr_vBu^M^wDg0iE9|}_K>XEB z<;?pu7`iNh9>2lK2NJiBITD6aJ3mu-OGE9ZlkTKPyu;5Qe_PZRAG#xLMC^kOQ#5fI znCFi%RiBXM<@f*|RD0XFQGnX94}9-z^s^L9xr8|O3g%nuY!ic9z8Y(fOJewKVhhy)39{U8Pt+o zPDj%?+9$Z~RdmZFCn#Fs$nR3*+0RJHM)*uha;*#?!$etkakGHK)GupPwGgU2V1p=* zpB`FHKh#V+@_H7m-?$NBa0tWGM2O>sGz|L z2%6Blp$aG(ilU$x6a{-|3J4k$5fL>YDk^HQV#6KR`kj6DI@dXGPX2!2I1DH%5fnzC-!TKKi!ly@4Haw! zV{Sn%2V6%j{nQ<3T_fEXnBR;Le{rP)=RiGHj-CU?;BtiqHc9dlUnAzGo0;@1s^Iv5 zZZtV6zsg^r`k3kMk1PRF%JNT{+*bOg91%8?hTdbSnQW-}juAAxh(Gw4XwS5M%qQg~ zRqIV-+Qhz3gb~t+WS18@CVG#N$nZ{iv&EVnx=+W>f58 zQpxmO{!(d#>a9cl?fcGs+Zqvk>`U_TiAk|gdYUK#&m3WS^aGW%0h_xnuI2ZvcMU1#S5$2)75$~ zV7N4)aeZ8Yq^f$DglYpQdfljWXU!-3kW?(UoC#Hly-4&};Ir3WHd zFwW;i|E!x_=qU)8x300rGttqk0m#s-mcjC zt%l$h9bcx}b_HqL5Z(6nO56Noo6>`WAGRJ(NwKeZxJv`$9EPgf+{z#5}j&1dr5!Ndp z_jtl*R_V&N65mv<=6Pt6?`ZDQfn9}XNKG5nuO2@;eO%g>t2iMm{ry}8V;AWO94a=_ zpf&cCX-rImg$JnYS{D`M zBBtghNf)-JUGC(1?=ymZuI5hiV*ZxaV0S|CmoQS2XKk?^JeZ@HC8v7puY9uZ%znmP0sAcWn`Tqx66osrQSz ze4~Cv1N}$_&oq$UZn(GIW3~VN25DWA;^%{O53bh+&qA#&1 zeiziFfjU3REPaGwazEh33Ef1P{i#n!N#0Q%>&`s!(+*Zx53j!}=W}&H+|c3{quVln zFPD5jgXM6E*RnPoX3v~mb>V)qsIHO(R%F`57G5eYBow6KY@S{UmR`MT1`}?oq*r$T zwf1-;eY}FXbm?^peBjqu5%W$aaGSZ05V8*>#}Z+hQ2L6>>PJGOMDqQ2$Lb_6`gw4b z+HetYcja%mq?mvMXr$5cEQx~$BVG;Tu*~KzJ~U)VaB6zA;CprWn(^IrLrd*fI}?iq z#@DVdo9bCJ)wdqENx|}H;_;5^Gr4+h$HUcC8JH8_00oa>D={Z!4L+l?DCd>?U*9up zTDG;lU)^CUlRNIY!5^x&LL$m8Wn{`r`mPMohl>kfNQz z9M9(J_I~&3ET75~p#zEueZ!f7{NDMEn_fA>?wHNqq{+Ds=>UcyBz`t-pcX1@TrJi$ zTta&8qsD*vMuxXb4?9of91d*^gK-QrArl18*1vrrEMZ~s2XL}?Gs$;nGFa1w&C_c; zrHjxnGGBvk{4u2jl1>*M)ihIr0J5SHDQYxw7yk7Wry@|)ywNrv3QMt|TU=-?9k0{( zqL>5*5taJC+Ck!hY$1lm0;(SpU0J9zC{f>ar;;9*btS_t&hgo8*Vcb=&Qj957e2++ zcvJQazHlGA{aC>IVwaa&Ej()?h5I!e!=Nw*B+VjuUOp3kVATi!Hrxn5aX`H*<20H3 zJeQFZ!v*GSt7qrUHi`A6OyI}8kFIcyl?$MkBXFZs%^Ld^Sk{{y0d{G161K96V9bAG zh{E4knB(~Z0vTXxIjlej1M)GZ?6J!{Ji<9?$Zt8!T@w}k0iS5UT9{Tbjq=*#M%s(6 zn4W)R?#x4^9iJ*EmaeH7MV(Ty^Q1{OYx#V$fd?MG%%ESYL;B7w!CP_02JWx{kKCcq z6waKVIofaCN46)4kB_F?19sAMl#+1cZSKNhWTA$;rs_JZ%!lF-tOj5$#akJIdRfA> zr83|5zy6pzS+RDzI>8Fk5kSFgFZ?~R^v7^M14q8`D2v1>p)1?-F+DNU)dKq+PvN8+ z7H+->fr5@gV;Ikg+;U!Xz4T4Daj)rcZaL^Iy95NXSL-n+5Ah*(n;8LE=^?B7SaC30 z0Br^UBHw3-kI@6r7hcpNZEuHoSOyo%;QwII>`J)&3@!^e0^ztQuQzDTa4e1gt_nbB zuQlT@L!D9&tU2JqS^K8z_J6HuLQ?+(d#d#aSAGk?MBisajQQ67WVk!Q7>_VBb zS@H_q78>v9pL_wwDo;`~v74G}ijOp(qb^uE{|>XNT||+9e2B=j#D*K#E3k{y0f2Z>3Ha@7~@)H&6(}) z_*j+W`1e+f7!){l73w%~EOmH~q>Xh$C(WnPv(UDzJ{`j2)=>pT{oXGBiczJSglHPq zLWE(XW7i%rx{~yktE}MK7qsPtWvezKIdQS_n9ER>qhF#&l1@738-_@&$#>9mC7!(G zSDBJA4O_3E?(FzOu;Polvj}STMON)I{Y7fF2Z+|^X9p{cLvIvWUwAcg)OP7_C0lTT zs-mzK6KufPZGf23K=4Q({)h!IX%*aT6GUDWLk{97n||k6ZKua1(S_A4hFtlqdc})D zr0Py$yPU;bk&Kf=tF4~}8)1Dc(Sm4emkmI`*x*$gXgtAE-e=OTX&ttcW-|EnumpxI z&kmY)@O%H`dp<6lM|aW9Mwncw`@Z9@`z{7m+)IY_v^cO2Y=r=u7FnVkt`6u7dtg@Q zW$QtrVfxVZ=PR z#dX|VmdfhE%msBTK-R*QcXa(3NnjA+^pCVH-CkXg!zh@q&}B?NG}> zazzEkrdAL?`;3n7zMPA>x+FyHL-JL2XRgNuAhn&*f@;sIsI0qkF@XTwAYRme8DVTC z*NqQ&)wm-99?0%V&0Y6vPEoJIH>W3aKDqhAg@min-sduoF7bJ1#m-otiO1f{^WQf< z>#5kvlvc#Cl>IJs!1R9U$RIlg95Bnw%3R6`<_P56D6=Kj1@E2OsYKh5*T@sa$OqES z&;7)=ikFr4o&2$`c)~t%f*^B(4mI_dS%SQkYz3IvAMcd^0jNLJ$p%%hvCdwZ-tIEHWM824 zRP}QzwZa7~wtRu=5GV!kg`gI>tJtQq(<$l;M#p&PV0v7%BiXS~XD}XjtdAq>*^W5` zXTEoy1y2_&eY`=p z3~L-qabMW93FyIxOq?<$epFda;s9v@GICS1jp$AJpD1SlmNc;TREDsG-nDe6 z`##AS>HTpnPv_PmLR6@6OuCgs>*_<&3z;K^X$S{-m1z??SISKTGLJB~SC1yUbHe<3 zdtirsnQ+AFCbI%l6)i0S>9ymj3(!`G?hd#^Uku_(Y6rdKHt}^mmTD+gb{o{?Rb7nL zsIr_&=QwM4g1UIwX9OpruFlBPJ4JKb+t+7i&v4i>LA|FcH;tt#y6ul-l{hjL8mm5Q zSW8W#5|{T8V&b=irttuW%i1S$xB}>sz_0bI#ojDQ8SK8Hb((a!kL-1rnAW1m)6&;; zHbs}qbdIE8J|Ce0@0tQw*)2PZNWIQLB9S>By89K^e3PT^Z)kapN8+LdH zctT?9KHajU3Af~WqqUs3%qcd;zTR1CRys)U#l>Xwyc9!Mi74p*K=^CQRvD}nm} z%(j>sbGCf)Fb}eLiVkpxun&hG&|ZRB$<%aXz&HMR$5|a>pz-56AwK9`1;H8FNm4h| zy7C>CXS~Gy)Nu!fSXmTxpnjetq+-gSQvYO2MKx=%Y^0%katWU>!Gj+szonB^D2 zD;5KC*SJxkLP_#PV?f%dJ!(M5T5~mh`>fp@3M8e-{hG*-m8@6XrZRn%VBI@*(oRO! zYC_6-#F8VrMANi3`dP#JEfxyH{uy72eX;%M z8zju&vT0xp0MsOMZLRDTxtqT{%1t-k_)KNrULl*lu5^0IUU?vZsII;?>gw!uEw*~h(eE!q^14U!==AwXMvha{ zFTXg!h%8AZ6Jy7@dWeDSFB+Lo5{*1Ab{J^OE6ozD@i_@KPo;Iz5<9KlTt7sa_L*dJ z^7i!tt7+XT>UI=k%5-Jl{;V8-JF%As0K=zhVWZK9%a-(>6Gp+|hlSm`7=SA1w8aS z@cHP+Yp-$rkdk0;%2N8$ZB%}cUG!UHIUSZEFYPf!_m|AUEkhq2DRj~!hYt_ z-O2Zl<*5tU-@V~|_I&!j<$dw${_c(=X$ipPJl+>&9A{|yJ8S4WF0gq^*@I~FTnH2< z=L4t-s=Ka(thE~vqFZ7GD-&7dJ8onu3k#BfT&b0WFX>!5`-nw)mIy;QWgf9hPV!H5 zxfL`|a*c3CYXSCEZZd1xihAtCi)PET7hx)(x+^1-i~cPIOf#}(Nu2j2*Nrd0 zI0RTq3?xVMXtjZ`<0B^s#$knN)Fkw1ptW1|3Wd%LFPH-$oL)L7lgY_uuMVY!ps7j# zA6nxMr!K;(@XGUtp^JwNJ3Fyg^sQdW$3D9SgIwqh7j?^#?Bgy|i-em7`fHF;KElwD zQ7l!6F>>FNI-7m+u%cw8^~t=DJ1=sZ1`5v36`X?$+YJgo_+qDMg`MuY)zKI#$u^n< z7Q`pg0MuGu_R&$Sloast^T8agwEST~HT(%f4rRtXo3<v(h5ar zI<(czxxAosx7Y2mOkVMNPE<7ez?M@vm&Dsy6Prcuu%3!F>NRRYjDtvtkLK3;rch#D zFSkCeIQq)xkhql0ujKL}MKUUqiKbRUD*yuL@*({i7$)t_L!ce6(d|`mZB~$Q4<#!X z*B6N%2(oXjmJR2kyaAM)xHwOU{X?nhimz>6%C9|ry0&$&_UxP5a~|58I=IIn(D1a9 zt`I0c<#DZnvRbs}hPBM0ph%xLn#*Uv<%1MM0Cg+{;>~4c(GGSnA){02#08rVZbWUf z143SEmT&GMP<^8k@n;PB_gCB(00Xf6E^^V4!tjTeNg7r7tr@akIYpyn zp>A#I@n0#@R9~zhkf7+Qb6f~?{UBoLXeHEfLj9(@DFhk`>I;UY*reCxfyE2Q*Vfku zq*Uf}LCwj?6|Tp*blH0b#89D!oTMD2T-%EfPE-`G{|ZBFTq0d5>^#NLpPfTTQ-0!H zbE1tx;8V#28GLm=3*fR&Va#|g{P97~A>px5Y~v5a zyA4CC=bvd<37ml9P+IsjGy{S+f$8oLSD#|EZ8N6aNS($$%V?s%5FZmixricO^ zybrqxv4#w6(G|s{7D@^JbXf~*DAIS5YdV{nCc;PhPnpjuhaniG;UbH14-?O#0 zE&>j2ZAbaBq!G{|QccyE-o9-P?#xB0s}Sp+NE1XltNHo7cQP8ZZL7~0 zjj!q~0y-7VBpvNF#e$t#z{vtm5g_EQH#?cl$5;cGFAA;-nHue}fEN8qAA+Sr+q>DD z=S5p??mmVn;6p_hLpacRK5#V%zQw}QNGvvpQD9@x-0N9%tR53x^s79p9yj=_nvp{A zc_nkFa1X#lx$|U+>H%xrVX?4cpC?J3Z4fWU>MXiyOu^6hOA74?UtSABL{2q1>pXy279CPOf98dF(xI@19IazQQrDg7j@ zh)nq#3akOFpmIC- z*p8j(Kw3jD3AGrivh#ez<@zqkv>L~i4(CEwj>rz`729*c)4zykrd4;@-s)wan-sKm z3Oj3Z;D<4p?O~LAVerPejUT3@wT&Ww2$$67kHWXt5&Qd1pZ+4gwxi@g=r%v9zUS`F6?x^xKTDBYeuA7E&zkkoVJ6kYPK*zck0tD9J z2Ri*mB>EHgVC75dCsn+)DUm!jJTH7eT#$}P_kAg#NbM%5(6Jg!$?Em7_jEe?3%Zha zy_=~$+5E7ZA2zjfv|jv>KphVsOe$cEyO9a{o-J51GXNxJ*#vnZGW0v;#12g#kml>)byvmc9yI53fJKKOSM-KPYI)K^1r5*4<0BiZmNr z5w5PiJ(Se)=Q_z1F@_m;C(C3DRH5W~cP-j}IUY4uhyr++d;9gH1w?z%jt2`kC4=P_xKQCux4P~3x#)&JCOa(Ga~asnad~QaSW86UtI+#a7>9H2dPzeZ6I5QW*&Z`yx9yNM_XUBDJsMPJvR1LvM>Cw zdn0xFO=-RQ(DXN*Bs4w4H}XKcoQlfY*LWAkD=DD z^ULIas9EB6|FK`cf6Dkjc=>;3p#O!T@&Dz8B~JMyT4IO)#h^X^k!J~EmiT3fAeLC* zf6{qt!augG`p^IV@A~uqOZvIszhH91f63ze=zn==2^qfi&mI5c!&vk`ZY&|vIa$uG z&JxAkcdPFo!H)fBjU_nxpI=t`hniyyO$z@TGW)H90eF?)m3rU*hRi2B z>8kdv+dMBxAamWd(Wj07fy`?+)x4O^k-!;Yv-f{N=4_t55!48IBmQXw#qG;(IQdpM zZ!zoP7MrLgm>8lXot(U|3tRH`yY|1LrQpOCq_SQe&?$|l*IiV>}WoyS%79x!9Of=;|?p0->c^|-PYhx;tzf?YB< ztC7;_iF382Yp5DFv2%2j?5LZgf>@C=CEtfLy_9B8^FSrO$^-?~lfUH0miGqgBMln?1$_i%M2Zk@g15O&tI3!(b$=A+Rrmdxk6UR|&}$%`WlGB6@O4AWn+F{S8G zqxc8DQcPvl%DJ5B!KyjG&&(k=XPcu*zGJyw$5LO-#2Fku2F0eWBK4ryaf^EkuyJR) z9~xBzqNF*!Jp~Lh?tu()qSP!A0d4(a_V1?3t*@gD@Y#Gx5n<4VEEw&ylp9*>suQzlR zeq7~5ySiez=iK5)(`{X=_~!CxF-qD{-EOEdIPx7|H(|+Sv>V&yeP-d7`o8&v+nVpH z98Ve8lO??=&KWa|ZtjfZoumCPHDFJJdSl)9Usv{EgNIL=uOr80WZ&%jK|8tsemv{7 zmbK3wS0(xuu1oLQz`8-S|IIk>p>oSQ51dEIOvZXAO4P+DUB-hA6E#Gt0klbK?gX-2 zo$u1$Tr}!{N|jUmu4@FV;m-i1{d=jzzK4)xcj!;%$*3Z#J6^pga(*^+agF+Pj;6*D z#D2=I-~~3ecHZcx=hseMVzhdJ!YW1PrPtX8a^o?b+)bh>DN)&#SFOYar||~6WnafS zG-ohMUQrFUoCuPSPnoC5^iN&g_|tvZZRao8=q`DyuNk_#W<#|d5Lc9R-Qb?=Db6Cm z_w55$<*DH@%j_(*?4SGW{P?3&xPJNMYNSTRU_}^;mtwxF&?4T0Lu#tS7m1+mJw1u8 z6sLTxfo_>paVA2nhh3=VWyK`DFE&N81Hv5n*$;{zQ5?Y2p^VG`>?V0NBi<9RXf`IH z(*St#vjIZ8b97@2Pym<33A7Vx8g}MQ$T#or<+rC~J5kB|M8?YJXNdum*!IpZ3SQ*3o)O5UYD>v8|^UTt#$GReKQ zQD-~){|Vss&I(&IUH-PbrCyW@`m5-1O*jDa@d_ zEmv{qzJ?aCs~1l|Qq~2j2Go+nJiz?sOcog~fQCT2s+~e^{Lg;Eg9zX^$=AbSou7hg zGEcT`apn6Y*^Eu@qCZ$FJ3Yh^HK*!rEY&XSSlyi+!xtEb1Qr{lIRb2xEVYC5yI$@b zX?r73S{RJ`{pL{SCT z7!yVN){O23+1Q3%Map5_t^ksW(n9c>MKNf6I6Bn0JICT^L=7u3Cjy^UY{9%B&sKDf zbt=s`;lGPic%pBmfq*S-)GHa#Hv8)z!I_7FxE1kEq@1WixxNj`+qoR%882s}vjgxd z$~j)Y-iLFljJ!(3*;)CnO>UhVs^8)DyB zKYlNf z_lm0N3VH%pahWx76JV}=iH|w>hAkEQA#2a~F9kTd5#E=yE^@(Qi(3Z-5E&haC34x! z7*v1^K4~R8!Eg~pzHY;-{v%W8X3EXw^a|?DFL<>PHoQK1 z#B_Li!Z8RXSxokIf0anv((VVzGzgUm^5(6T9r30>h8+Hfr2WUnm z&R6c%m)i~)Oh3FLL)vqC8)C?yqnubhSDfTNt+R``BzJuE4MXSmMe+@z{O(1nR-)L6 z?nX)oy4k4=l}ROItGYiUwAnyqb$?i(0B%X7%@%Hqmr3k>CF= z+vop=%sbFL)B1%I8i8tRbK$dbFP|(M6NHU0K(#J1W)=U7!iyiCc*LV(NG-0HycLHC=k0Kh_eG)(Z^l4Hka9+3gAuRy z27*So)P1k~yVqpNhVjvAY1L%Iped?eLzdK>fNn{9gk^5l&<^@5cXywRs^l)n^aUTB zwrKCQ*RU#6`K}9mqglh1zS2;%uY?(z5wT`%tk$41@RTsf>YH6Ee3Jv7YY`~IY^~+ zJX=@yBIcEAQuQr=Zw#QvLNO57orTilYbcNae!bsLcf z;P42IA#;jbz|E{{FZ$Ub-EtB22LUvb;p49IIBWIHHyVC)-L*W_wLow+J&3ahWsKmL z2{3c#(P6C08vdq95;npN`khSr_!(z{tIFe{WSRK@2}^J|Tt_`RT!xY5R<+HU`TRI~ ze-PeoUN@dnC-njol%cy-UlXokmVZ~2%imJ16h4u1Y%Ull^ewLzm@CL3#$%3$8F5<> z^gKQP8xO7YCf}wU^U6cUWH&02xqF0OKD!YW+ew`~Ra@YP`3aR^jQ zC8`R*zgskfua8dB>Q8-=Y1)g-8)`;JyT)7Mns0GrmJAzmxNKh54wV){6u;(G1XCAm zY!nAfB*WW3d*`ri9kePlXzRECfV;;_s|4wqF1T&tBbQkK;;9a?8mL#KWw4dmJj<8$ z>E)#Lc0b`n=B8sD+@+W0lLC~s5OjkzH}N0~zwNdyC!TW%_j>8S<<`5~;J30cu{Jn| z_#oP7JV3%cysSYlgJLl9QK@cmUmJ_Wc0r8BS7tu3UrrS>fmc=R0*8`DE=IQ@<%0t% zuoTl#L#VCAVMJ=1gmsy@FoK+T0-QX=@&&lQ=lCr_A@C*^cRDUP%?zF2q7lbK?Jvz) zB=JzSPHEZAc}&|rYIBtYhhA)5IxNiXlR80SAAKT%>=@`=g97weYs)9B@fB%a?Xfx$ zJy#ypk&3GtYHMISs5+lptUdSh$~oYC$?w#H=oG8u{)3;+ry2HR`z{B(uh?5bDorUhxwNp1<)2chAg6nUe(43a4@%} zkd*0e3mdlbVy-S}j5mP0XD?+U7jta!0SKBZh|Cz&R^XwTUO4aMJl}=RZznroynX%? z*c;eWSJ*`>ZDa9UA_pb?Xw=4^@U~NSmi#&!d`5?Y;W?7^BpZ7T0Ij`nlY_cXA7ACC z5~BG~`$~)fqPcmCR@pB+?g%d8$2nvJ)cQ{O9^tzBXH?DVtfLWImTkTM?ALXX+6_q> zx+J&Imv*i%0u{y!+cD{2NV=BG$L{Ij#OmVhE0nkXw0Y$gzLY8{mIJVH(;*~v2Ws^Y zGwGq1dPl}74S#L}|L{voSeMpz$`Nkgk1KA-E_rb6%!SJzOHG<=5IZ6GQCz})jMG+h zBQ6Oq51Ya7Y{>H8&S#qu8?lu)s8KzL(Si-G`?Y3=mH}2vJ2Z{xaY8O@cLWV0LHB> zgcxpu?>5prUdD;C)qDm4y7az_4x6(8(@{}R#ILgQ!pI;4`01}(KTdbPbTB3gjxUaG ziU@=Mpn<>6zUtSuW~g^(Fd&U0ePL~OId`yHc)q;{b6yJwVGb?IVWk8EiCACkDWsa|leZ-S)GP$AY9I|x(XhAR^ z9fI^fyf!j5HS+A5|HPBNMQAXpKXzn1A&`N*y%Wa&ecS5J(EW_P`(e$r1e_}u<5Lf* zA-!2FX&?CFuPI`?823IcHcJe(=ML!Z$59#sm5T`W=bdgMnqNgOemw2+-|%qbDmu4s zw%dI(0`K-h5Ig+f6KgNze5%WNP!BdSIbF#PoPN_s`wf@R;Z@$l1S6Qp6&&qOc$1*j z0fCbVFx%0}(H3@oa{rKd?-Rz@y3c*#jo^*a2gNkf3OmK3*$dc)eiz>Tc|Ca0xVtf6 zphU#CG{y@T;y}`&F8bXf#wf?KHQ+t&2fukExvoM4>1_qFI)&7YAY z`qzh-rA+Jx`u|Lgg+Conysleu>Ct;wyl$gSbX%7gn~3n{Oz>U|^qnS@I^FWoFgWnr ze`)Xj=qi^I8yGglV^21w>pu_Zf9!S9ZI9}G?Wef?MFX2Mu+N~!_!r<7< z)-^ltrFu;wCMLv<`PO)Q=Dut;W|{{cyB^@PA8#rEpVnzQJcFA!1DA<`v0{u2ZEuuR zL<0$M8UyV_@$a6>y^S&${jITFFuwemeuO|r>Bdv21K(9=w|Ub@>SRo%#tnIYhv-+B zEf=5iG~PBW!G-{O^6bVaey>dCaSi#cso6Jr>oG$YZ`dN5LHxOTA!NtDF|_fW%?K$k z!Kgt1oVX0S(w^4vAH+o|#7${-d@@|Bc(1(cnDpSzp8f9-|K)f~mYkt@vWAB~bJvU~ zu=8otIQGSm9gKD%sjL#BH?~P9wx0yp%QqHaq_rb0lN9V}*frYA%2|w+CWXf`x7u?b z9#}AROS+NC!X~A`t8~_(--({^`fq$7YSt?}221>V4eY`kLX%Iu^M~vcV7Dyns@-_m73+S7O|(4A z5iP>n3{6Rjxx?&DA=hk+H%|KRis9wR-S4~fKWpt-j&GK)+e3w8j%VZIQU2O?k9lZ* z$%-JF(#K~igZ&sMYdBu8Wa7=3*5&$RCM2p47Z5C(~wQpX? zkGGQ((u_tn^04&bdGvpmpt}sR-A4_qJ%YESsp6-~|mz6O`V`0(@}ul5F+H7=S1;=O&w zPbO4a_D|Hu#9x2+WcWbdv$o$82M!&2Q*o;7zxAgwA92n9z*Ng{|98=zeKd@m>X^KI$~dJbMfs%15CW` zo>|Y=nq&*km$*Y;+i>)T#k~YJm;o39$q}tjR5LYgR#AS`8?>CtKH5&d=id05 zruUOYY3V-wt7{w0W*B(2(S5!?_KvUjetsrboeR)CL|M{zafpy%M3fS%7f*aMusf(8pR+v0mjy)LchgHly%I%Iu*y1ABAFM}I zy=~4^AZG?d*s|*5?giv+?$oEg_dV|OC|?HiWQ*wm_w!}n7&;P_On)y%>wy}6)$Ba= z#{-0XgDo1aOI9@}biQXhyrj}8rLPQDEh$I|NRQI)3k! zuIIM1m!1`DYrFDcXxq6POZWtSu0eY@Ima)kpRULxJw{7gk~Gfxe!*mM3M%LhN_m)8 zPHO+Dja&3j090-1 zRjw#g%c=c&l|}P+TBR=<_MA$6UJ{^jw8(#tKK!FRh8K zzl``%6GG0=_VG2USN<%|=u=3%#)k&0teC)H^c1Pb{hq7Wp3isJ%BFw0@8gsHb$s)o z^ly_p?ycc^iG@E@v-WNtq(p_jctWbXKAuMaCrIq3D^-9#l&~Cfem!fPk^OtTh}%hZ zA2I*M>uYBzF3BCmxyboGm{`)|U|(Hq#N-O;vnDUH$yVLC`OrRa#~xye3FP{d&`%PT zWvF3{39nmotS#x?BML0CX2(N2OY^Ld3YvU}6`GS3b8;`S-b#OVn5bBKM0I?t#=5~N z>fXHkEB&M(hXg5oOZL?}>Sl6N5h(s{nzBiJG||IBW<`^MiBe7$sNAuxTcJDW7!wnu zjpWEhKGKW+LIN=H%lKMBa+=Qd*_A388__&_XJ&W00utRu5}?#N#8x}9`r!~7s2g1x zSop<_GSky0)wZ?#n)z`9m(y9l>ULIMS9MUJ4Gskjk>w{E*rtj3w}apAJbZ2brPdX_ z$|bTp!y;m$2iz?huv{jUaLNyjk*FreMRPe%7KBDbw@(}Rn%i5kov(2(?&TM)pwEeP z$QMr=7R>6XvJkELJ$afsJ8Q?UWJg|7saaW}pY=XDcZJ{!>FAbb1AX6~S6x{!RGT% zDCRqGs`jqXFGCALYq_9bnb@q?Jhj0HVl>9B5{@3&8YvwlaP)qZ51%Nute1cKJUt=A zpnB&n6zZ!~fJ%gn=CHi(%ajvZS7tLcJIn&z+yU(hA^Tip524?qJ4D~V4!abed(v~H zFa4G(8EzsZRHnUpvWn)vDZNMzT0CSi4uAsB6D@G&W&jd!(#~*Js3xLqlB!0wI7Sic zbhE?$m}Ly+@4c8O)?DFeTuF_uy!a0??l8T-&cH2XXiac|$F(=VXN7e|NvJ&-j?;_Bf zNBJCmR04A>5y1Uqt->?qR_8Oj(b^O!SEbt=4%)?5G|P}V4{%fibBKvu-3m+H9SpXJ z*MFkYLrwb4UD)P+#Yv)c0bk^~E%m|C54*pGow*(gP}|E%&)0mMf8%oW40h}ZT`FS% zrBQUxD(#r_l9E$&OAITMgj{g1p0$f*XWgxjN7~K?3KXh$)olYEm1d>pUr|N$2!pb7 zAiXE*wM%&~=4)JR*UN&i&m>Y1Q>$V9MFmFVQt4=S2GF-HUmXGpmVz9Q7@NBo#+_tG z2v=Jw5&d^>7%2?uk|s?=Z}z&D^XvzkF4y+HNFl2p@MK%X2t{b^MKx8+$Tqlj^;Uhm zi;)12rXt6@b=G~Sgyr|ZfO2g*E7AA`mi$v zukH<6Cz!diha)|s{{7m!^p9zWG@w|!5d~-PVZ$lM=TQ}(og%tn1#zJ6xW6wQt;bnIuO|9MidoP6+*35q>dRO*Po#mH#4aD3))(^)KUcA$W9V5B@P z7XjW%S?sk4wju#m?0qi2fT?)r?!&TCJVhq~iy$Ta_fZIHBXDcq8Vp5!>h(Ijf#S#8 zI}K^z{Z0zZP;2Xl^>6Qqn@#0Q0q6DE)B)H+0sHI{Jj4rGWM_m1Z{$iYgc;UA`9h<=tzsWL>uv^E|roW}Se7`Pg) zP&kk)rSglt|GG}{7yaCnQ@Q&Ga?|H>4^m8QgwAaDyeiS2rO^=$Bf-M{g1Wp{&4hZEc957AMNg zM=;gZve5$cW;sxXnXUUmZA}+^0#@+_@^!`RN`8)?ApV*#yW)QlcAs%c_Wk4kkAvj_ zI6%bQ;@*bls?@-}Qd~JJoM~ENmLnU8xV3O^#XYh@Q`3f_nOSLJOS5sJEn8<;on_1O zPuF!`zyJ09eQ*4@!#!^B03HuMpXdAarXh}v0aCmz=HtLKbMXsE;hB(Xmdv*yX!#Z5 z_%#I!q5Rp{gb);w|7zXwd1!^3e~WO??;2dU68gaf|D1vzFT!r?t`X@JKnNhek&@(6 z?I%_hmf&DyE_(b+=%$tfqTu2p9IEPGAZkEoAy0Crnf#hy|N2e{LMwV_qi*Y?OJ&)F zm-4%~Ckja=&#!3Pb79YI(7qJ?8eLg=8uDX>OpmskMm}_Kn0SLrtKuEk*;U%iMF^1y zMA7tjPF+pjj#aAF@bj2J;gH;B@wi^&lX|O~QJdqP1 zZa^l^7iGs)rRGX@Qk>X-7ncVVC7)@>$v>hM5vN6AZ&W-lmhC_z>c zfiPjtd$LTJh$71`M#r%t(MlKBDLtnb9kQU8taU@@0oC|myI3BKF3JL!2P#Cre@kZv z*fiPNdf&QpHOP^N&@YmIw+)80ZGR09Zp*BGLXgm)gC=tMg!`a2D$R1FuHLNSDy^ZI z6F0?-^5sTVbFo43b_yIYR)hsOo;}sj-YTe`ku$oe*m7M#VX-lv2H1>XJ%&)pP|K(K8u+6rzxsZtsmJ40qR>?5~hsg+EAh{UqzGl!}wb;D3 z&tmi0qJ!x^d7Q3FCSbXt?Qb3qz8v(W8FCEJYsD!3$}hYiiZ$PqZ#r@)ouz2N)$-OM zy;*IQc4+WlK}IeDe*lO11^T{B=Xz>yL0^wczhVOu5Z?<}KjXAT`1yxQU3w$=mFkf= zp{RkuUiVn5x!D7~c+*=w3$w8V9kWZ@BmBH?oWv|jnoR&Ix^8m%#8pG$$xYxvoxb#0 z*f2e3cF`w$L2)|@AQ=%qE=U>x>y89iHywzn#Wy8sC`t*^Jw@p?ypYT{3K0~l77&(v zy{L0>*CyV{H98Ijb~q;txE2n$pB(VKIZ%m5%JEvJa8+%ytruy&AzXOtswC=ab|)U0 zNP+u5Qjp@+J9aA|nLRz3$TRbj7W9rX%8`@^c)Fq0!N{|fNvJzq#LpWFqAH{(A6y>B z8l=nIQ9@Z%3^gb9H3Me|zOwh?&;ttP?Pe%Yc5n?iX0rhm>WN`*rsi>ib#K;ItTltm zdYGz|;2N^bPd3`6OVN-^7$1}D7mtiEd0)jLNgk@E5S249Tr3>%@AJbM5tF~l6#q!F z?nIL)7prT#`v4%3iL45fav`ZhT;$R^m3u}TtHyw=Zbf_A;1uIRDW~2UaH$0ltwxG3 z#?<>oevg&4@;M>itA?*1Nsbv2uiR9OVDw&OUX0eq^e-#^dDB^ZJFO9 zLyHfWMgtK8N|^6PvbuGhCsr;r(?*LqBQdciYGaB@{=hUD^{#H64oO{yHdIEwl*a`@ z$%|zr!wqII!y?Hl`K_Thpd_)iSwzBks02#c*FadD09O1;e$9YuCi%|KSpedA@EvoY zEpFE)J{Y(Wqfl@3?4+j_A9X9$$mi|Vt%Z~Ey^{&klY4$@D*-TX+NtX+=YaE25E+Na zM3XpqU1lg{+(elJ+=3x%$^%(%WiGrt9w!>Q%~y_?yV&(mG7i8P@`v(8?e>hg8Uedz zWh`DZ^KaPI_q1HoA2NS{lVyySDNeZc)JQ1>kOvO*P_KOUb&8_o{*9G77<{ht-6xyX@!=1#*kCTv1<-T-DRXfezzLD(!!>dl z8dJO*7e%Et9KUM8^}?hsfMWm%w+wnIT2HKD#a9tHl1f;T(`Gm*SAL{6TdUg;^XejY zg)&_w5HH-kRe+Zi&jkt+4;{aNE$@w{@MqQ-POb<97%6yWtTQ8;ZKJ@Gn?Vjnyf9JF z0M7a+Z|jb@eSry_i9|^4x%IUgD!mD)J(5gdNv0U<{~}A);t(zLyRmQYoYR=C#XFdY z##?EyLg*f0Ai_CuLhdYelP#ucP=Dznl!E~C%4H0Bh?hBN+kEsDa=o(Z$1ugGX%Jrun7lb`KRAxxv`^FQ8ug*S0e$QuAMPyxE$QcLgs?>NIyq5z zZA9vaEL{oGSqU!Q+B|LWm%?5WJXeHr%76+J;QPvuneSvY>s*O_k8?#C)C<_nLac|7 zAK3wuB$d_AD2Ohcu$~7?lDB;CQ^bmP_~0zw7enovM*Hj(UH53wX4j=Yg1*`1sOQSa z&nU(T0P(fz{cd=6XkWwPHkT_D{tCO;@%BYNuqS8njnN&u7@E2%|0^F*^AJ=-2#feA zoMU1`Gir@a2lsKI`v;*jdlvm8^pet_$!iSiFdvytJ!?CKmZY5{F}f?wo(J?(F2Az2 zpHNhy!|Hk=-M7juN8)R@Bff9Fq167seeA&n{$d$U-Gy>!m2yOYU;avgpX+L54k<=G zjgZtwno{t=0E`&FtDz6}Ax257SkZ%DDJ*z>_tUxz)A=17YhPwc!Japr$KQ0He)Bg6 zcHco*)C>+y+}%43STTU)1T{&%t`hy}hY1C5j+!^0)evDY6fkmj09CbAna_o9!6Rd5 zw3u)3JIHTqX2l~D87Fs3eGxtDz)K=2ubN_yW6GhQ+FBpzXWACA!2sg+%)7>*2kB$q z-pkA%9s>uzF^`rPN&dx=(V!sKbAcc-691>9c)fy-2u=Y8&&((c%tAUMpRku$!EPnR ziuE!GRNBL%FepQ6lX4S?;Bmcdl!pW zeAb;nE6PZX6dRHjSJoKB8C?Dr+Q(Lo_E(Cu=Ve80XSgT}!tLC@Ja4gW|EEH;6@#Ap zw)>=D9nGeD6eNAnCG;IZ`^Zr(pL6-2Yx_V#l;6*Z^CgC(?Md%jc*xjeGjbIFFJ#2% zC5XUWr`pR@;>=zI;D`NCCU>M0K73u}q4IY>@Z{@W%HBfoR>}naF~-UNS1kFzjPZmx z46ON2a#(DP#lTq1jDPE5F*9!bm+bwQG5*bo&3|Wx2l@xZU1V`)SX@mOcaDDx-W&g- z#bO35_Qql){2ycd8yFk@lN=T^W3e$7OXJ@)WwA8w_y-&RR>YeS|Hj7R9J09I{O?|} zSUCUIymt^kzyJKLi2tW9{!NQ@{|PXQb+MQhi-GZPS1bm`Er{Q>=6~tp-;mhqcX3%9 zgce7U52PFrCzHi!`FD(2ERe;lTFi`(|EmN2FIxQD6`TGOffnmxF)bDYXVAO!&7kPLTVLF(xF`6#0ZI0sHxpa(F8CF)xA7DT{bLZ5R_S?X##RW6_n%8e~cd88*bd!JqQTLu`E3uRL?2DPa;(CcjIBe@1w^y(^ zv&I|&ah*LiK#(1N2*Lv=vf8)x>g!AZqsLnpxB?E#gHqlIc+s5=6}oa*HskdJMXoYs z*=Zy$C0Q1kuo=0P;&G!0EGBK(gD+qIT8FXkD3BIEh?7*%axcM=w`p}JZ@OSrForI{ z8Lv63jzN664vBy{AdL)I1SlY&c@=+8v`Vp77&_xuuyp`0sr44s*DHTY=m>Eq4qAll z3ApyDtG&l#1Rr#|pnVaE0{Zo#u2G8q`#4WY>RB{;Ibz5!G%v)h{3GxzpHtU51a-`G zIn+R`iSi`hLuDj|1a{$}`T_~OzOK>+J?*wEG$PJeI`WnG%BvO8v$x8M+eVK#qWYiw zJCrpM1|xh`+KsK!}e)H zYMF`>nj&9yupb85^EuD;wP~c6Wu84}Su%0nmIZ(b_nVGE^l?3@9NmCsB;*li#??_5 zRo_!mIu#M4PlYj6ykp)tw(A#G%I-R5BKcrk@#Rm{ZF!spIZhA7r?3<=QX=D91}zry zyIXB<>_o9`ghGr>!T1#nfvup}T~NvD(eL^5+8feo^JS1=mBM;feyXV8{-vVQ2emB!YC=(vmnlnyCH-GT9rBCG%@yiaR`0`UYz(@_j znYcwu)ttCn#ucG}Eec5oj7lnHQRh*{1WV15&?}B}&D9Yagt+o=x*8EY1{?`kuS5_k za1nZVftY{lhuJ6>^duG)yU9z;l;7x3sr7KOH=-G07TggR?*75U*r?F zd+-$SnE0|GdS$<^E;m6u$FuGZU`XzL>b@*HX$ZaUuHH+0Q>{P&@3;1HTXukMDi`*K z9F{&*qm5gihu#C{up3*r5i#%sI>?_oYa|=>8#5c%pP0hL%^%IEp(;CoSdVBykp4mO z9L;(1k$vd#myeb*|7_zoup_NB5V%a{ud}z6?p5V$KiAE~z57GHnu4$_cG#0x=ZmoZ z|BbQUbJH~&F8uphr^;x{%q3{i?oAvucGcP;PyZTIm)591&2cFA;y|}HP_1xGz88ce z_;9cPonqdu^?-bgB?8{LfJl_?)npc&A`x7YZD?#tbjX;H=K|Rh1u&F5bL^)>v$ct+ zI4g`yLO3|*AGRSA-Eqpvy5!A2K>(Yz%wOkOlD%Gm3m!0L%ZOtYegiY`*msB*##MaF zM18D9A_6J7rT~AP&(aswVEQ2qH)^>#b5KZ?9pySYwLRNaNaj}wI8&~xrmQ*(672JQ ze$Q&2oPE}9%-;U&^Y!~Bx_LqiU0;V_O&0oKmYra6Iu2om=c9I=}BQqG5deF zr13{M0jTplS$4B%iI5svAp7xiCq=4&Z#fBcnx@&o7 zK?c6&FhZ_p(Z73b91&Wbi#De_Bbqa%_B;cTyIq4ng>b%E?Z@KkYLL%1Xt7Z zdN(bJH?da-HD}5zQN2^U@K?8kLOow?s@72?C0cP7(8M)^jX$qCHt~ZR<*npA^g*Rt zOk`$dj=Tfu6-ibZqfdK}_U@f<47rha-LwTH&%-2xUA9WBJ~;Q;oS$n81aeUnFS&UY z9V^lhS-+eNF;Arh-|XIXnA=+}?9w`2i-sVI*Hf>nN{y7K$7KIH+pGXHs3GJKwKLJh ziykU2i&u>;D&>Z@ZjW9&LiKh^lK3eF@`oTk)suMB_{A|PIF>ITFwL!v@OBPg{zkc3d zolp{Sm7P8Dj@h@0h_-%|oLBH}!EfL(>Q*L=F?k?wI`Ki+}%@b04DLgg(#mNTR zUL(r8_0Fl|a64_oy;8{M&b?raJvUibWybhQk`jS5-xtvRImW3737Ex&eOIX{kUhYK z>*!}{C|o)Ncrm5y@;+UqN6$gq5$ z4~ZCm+=Sc?fIzT~kcx|=97_+x$_L0TES+Bm^uC8ul%bKSY*Y}hNcPpAG1zBn;YRlS zgzJ-kj{X_zR8wXBVQ;Fg!zfAb+bjGi@bZbPTS@WNM;X;YcGH=e0--0}H zmaxG#aIAb?sRNUbi2cSwSJxJ#=&mKclTjLGKYp5T7^jWRew3?Wstr-&wTjvbo@(B> zrO`>4oTw%p)}5!t`)OCA3x=_SFIe?wv>n8Oq>N)}wC9omC9)^ORZlAM;ODpKquyaC zmtSOAdB&*`h=){C^fXWtaxAn|+9EIX@j4I>`-t344K8IQ1GepEha$7Csz;~8f33}4 zxQvidIegeLGxGEC<>FIZAMR?r23&D?OsAiFftpiCLb5 zLWG(Q0)=-Hq{UazTo7a}0229Ol6Q`5(?HnqBMJrLIx^yfFY^S6nFX+lC@@>@2H98= zL=QVTpgBEhX7Le>UvpLTqU}Dx&#d61c2SaQm`Y)E*v^kx%MXAAl3M&{gf=(xS0?Pwi~o55CiCAur$O5=(YW2+mDO%T3G6-B+HQM+Uo7b1HerxFz^Pc9z=m<~kUoDv~r~#I7`ZWprpi<1yPgh|QC*+|->}I_MA%sFwn%QV?pC zBW-c$P#zp&z*V^g4J5!K0(GDo9iRij_*vu#z^4r1F;A;&MmDU|@Sj423V~}~3Tv)Z z#6V1;1J2c*S6In|j|qT)DM=|Dn`wiVqN!($smzzKh5(8!6D3E7{YWKwaG~wb)x8Ic zLlFRO1E-a~F-HO8vIKSpW5)ZCYIN~VFu7ZCc7F_eSi3Ikt3Sr1nzM> zUcuxnh&Ru1T?|HG-G8xFOA6l5Q8ia{(D|gVOZn{@Xikd%>*&&QW~qQ-WjQCgQ=~vf z;|sEE-iXvT0~le4w#q~G355|F27J*+sce^s%I#Y2{4q%96iBf#1@O-%z$r*NAl zG}IG>4bV2O^7#{|@U{-L@b6p%YK?{rB$qs+=DG9-p1{EXVG_Em?z2RZa)-ikup}nTRnR)$Ee+AF!X7}wpD>b<-a+Hd z$C=0t!)@amp~MA@_u0+BMp@4d=y0YrAV7p~!o)40WBKUf&&_!>wx|#FIS!IQ0_Y0N zk=^=LJe1E}V4b2gSzv_{R8055)CF)8Qq~C$Y8?sEAOo%By1|FB)1vKzU7S1ta3kFy za5rQT<6m?L?OM$)7a>jV5F@wFVqI4rGZ8*krIK8(s33_gbvYlO9st`35_nus1pK8wP*L8vWxt6wAcK8US9t z2yXyj2vEui+)9zod)%2B04ApUq0F9>rE-2W@Cg8H1Edx#pfDV-3fGq<;=weyWkSRr z(OLBbW<3w-uVF*L_QUGrB*-$hq{d%Kycs6^&=`_PLN0J*)NrR;sgP5Tg6msI`!8ey zSuuUr1v(EU1APEA+$5IJpTN1@sflL`Tfeyx68CQ@6z7M8f_r+r}4&K z;zck0m$L*gs|0RQw4s{jj_28`l84U;7~$<3p#`l=MS_X#zK4N+xHK8@u7?z<<$P|b zIg8{&XOFi~lyXnHU*Cpti5%C0fVjt!&m>5vOOa-jD<30(vzdVT4KG|`YHA|dyk^|D z?TV^l*RM@z`JY%TFXb_FZ4Yx>|9c}Jo*NTcB?fP<0ZdeVzJ9D1v>Y@w#F#2ysn|4# zQYCkz9bmXn48d~zJlH$SjWl0`<Jr$58qXUsmL~w{Z{&6ol4!6ihhraW~A1pNd<& z?pz^0Bg59$=f>z?BSpjJHjgIG!Pi2W$lFFU^Yt?e7iV^NU7DyTdwK;VeA#`bV?VxS zbd=b7JxRu%a-)R=e88N!B`K5Pg*M@%{F_ynj{!(Lg?mwDMud4Dc>BjnnTo?EZ3aIN z2R!*lIpmBm`UV7Wx=GJ9~KQQ;D_lO{LTOgfE1dCD4xF=onedOhZ6S+ui;CQw5u#$*qA(Tm90jNVzR zZCMPR&g^x@07ueE0k)~Cd!VGqj9~0kKVTmu~)gEKq&&Z1aXYd({7wGMDfnKIgPUcNl!E!TEXzLE+ z&a)}+pX%&jD(Bjq@@p?NS))SMU@X+nx${ZJ>MK7=$8d})yO}Wz{J&C zGk0mb7*8-u&x&|RleHz^zr+O@IKd1rp^Kq0Eeb;7n%ywVpPu6`PXEH!oU30lR9z&I z7jIs2+VP3H=ptO{vG;d+l`K{_KU?zaGG#*2~j}`86|9(iEoQB$-8J;*L&%;Zv zIXuMs=s@m*g(?BiGrE3^JB!~l)h^6C9ocKlhgtX{JvXb_k#FY;4bN%3$l_arI5p~4 zsC9>O-zSB}tasjT@cB#?BgWNYk|PsT;3uLV97hLCzdb{>6z_P9fGfW_3b9R1AD6su zJoh2o6T6u~9xNJuBQ%sa2FWJ93bKdh_rjj+_4~TlZr=9;n76{v(nmRAU|U4UooJo) zm~w=uknuK;X1wc`Wc5?>q_@KLKOy!m*f~5ruTk#yX{qvi?`j{v52aW-klwKqR+g5) zg~gBS|6V`x=YSUp9VUD^#NR0mM>^u*(G~?_#tSmHtsi|w0Fe{N(FKIH>!Bs$Ln_ z^%`BH)YE$d+Sk4|9bL_9S}nM|nmUYf^dYI`^!t9I<-IL=+kXaHheH*;>gEvDZ@o%0nD%4s}!2Ts8KI8NJ; zcS>8Exo&ZobpH-8dbj@B(XSe)Pb;9fyZqytwTbx-jJc{MQwS$RJm<8$>aO9b`Q>HE z(X8uvW|}-)bl}q}boJXt_h2z3+4PjtDE{y!igJ_syeCs~$(DCg6O>3nunEJRQv4VARpZdFK1RbbX4E+`a_d z%ZBWnx1Xp}tnDTVBcTd#zBXxu*hA;zAT!MtJrY7;zTZW2MAZ@Ibz>IpTO_@C`gtu* zOA@hfn8afUxm7OS1o~>)$7lyrLZJOBZK*^>67e%u$*#bn`%b%8-KHZL%bt7P0VhK* z6mklF-K(Qv zUJ9DZuF@cW|59%Pu2rH=zEK*_zCV^A@6~}@t1j1nz1~UpKux_#D?bmDV#b#AD2-S; zHQgeEMz1qF@cy8eZh-loZIkEpb0=kp7b9SDD;iYSsFM=P7FY z0Na5bd$!{Mrn1t{JA8t!w#}4d*7CKy6hN}iTRFG7`W_2cGe@%Qh*@!F4{GFwn+l}H za}w2$?w{1qF3nmZQPqgbaV9Nu%|$KSNl2+VZ8#HGfp@^=6;=z>0o}*W-kAuc)$2-X z<9dZ9u6}2;(J=AG?Y$QwxGqwoYm`h108$nuH3+MWTaB**&cU%bX7iHOmIGfK48l|@ zu`r|Z)Y#v#WVagGZ_e=@wR>;GcQziy?Cxqg?yXNAQw|~{VA zX!C;%BE#Vw%Z<3EbMF--qu$H8DsjHxE)y_WWejv7N(B95>k~9?t^)}l1?M~FjfhH* zSiolulG{w4Krzo)T8V_T`F>37B=qww_RMh59qvw1hit_S~_i~*9#F;BD z@Lr5oRrT^T-6J)31M7x2S#|-q{*( zil!m|Q0-rHlaoC+Rv)ln?g1$o)01-KP1cvfdpJ|pp6<5hO^gjQ;i=-8<2k_c zL}h_nE%1Oh-6l6{XiH;R92Q>O)AbH*UGv9F?Jn(Cl*OcJTSQ+P&(kd(iCXp_-_+ZT z3HLzSNL9BaD~Wnir4|8L^9lcsnhIj@US(1J+_oV%b_dAc4-ec%eAg!phsG>Dnw))1dLLgEay734`hT5_kSUy> zFihzy(oshba5B~62Ko-P>xT}Iq)zTRajIg<0kyj62K*gG$vutIJQNW^s|HaU4c_^& z((Ke!P^euh?GlDp5Zz0fgH6G)aD*~Zb~z=$ySjRvHWPwJM-OMgGiB(w@$*NSQuYjD zP$Q{Odiaa{MLXvmma=f2#Grr=eN>z=2f_^qFBITpF2usXg8%??o$*jOL~;!~uue{U ze!bI%)tw*3+EkVJYcplKq290fs`|`)t$>LnO~=tojsFp3AuJ zFDCHuLfAS^M&9=rVd)?au-;VHX@0R4&MrAeE@#^8VE0dWOVUTFfM(Zq`1M z+;xgw)thwsY{Q45T_GL*hnEkJH~Ql}TPc~BXz7lnTaif2=e&$W@x5Op1D-WTX|BKd z!6t3G!e+qL5Jn%DK$4#4)yrq>T{;PF`w3w~LsgXj#3(+dRBYFd=*CAlNb2))03hYw zT$Dqj8~L&xq?qkB_IcX`Zg-yO-6Rfun{=2q8Gm3sns4yjsUJ7@{te^)BY{JIUH|o( zcabe_>BNS!E0@;NfHhtXV=H{k_ym*A@}*6w^m|hC#>~4n*QFg-2FM#IoNPNEOQ(eNk$kZL?d^SDY9Lr(g-NB zxQW){=LNWJ5CwjHP-v^sPo8_#~yA4+Uk zW5A!hKxzT@ok+N#4<_3M>C&>^auFmDu;ak}_4nS^B<|$I#gTIgMOjXi^g+s@LM}pP zQ97R{o>I)qCm(Vj*iN&SjyVwNGMn*JmuSY9eOv{RDeIt8tTvO79FfiDrmrMEcO9i<_jih z%1(*~%h1J^KZImo9)J6v<4}sLbbr3wWOpcp#%fqa9!iH05AB*1YZr1cdMWkK`Qp^I zggygtYs7a4*vJKtG}*W=TGS?kJQ1(G ztoX=?u@_VU6xh>i+f-bSJvob<%|T6-?gW{Yxg%xk$iELf`(6{3Zp2KCKp@ZLQ7PRu z9a=O{G7lk|-e?&jwGIZfZYaPccLZ-LXtnboLi85Z)p{waJ%x{0~s1vrB=suCMaU;>+JSuFm*}X(@TaTS_ zgeJv*OGN$_E~&GS(iu7n7`*^#F@;%_l4vu|V7{FA2%vW%=^4DUh}N|!l6Elw5?>j( zMxBTmqm^QS@*8&HW!(|o9eIN8Zbnzw3epIdIehkH^z2DDv+g#zlP|I`4jjq9uMsy@ zqlXjFRG!UL-L&OYmKrIN+kWZ zzcD<}hzIxNArpANoNB$Om6414MmdP<_uyx~OS(TR+7;1e#;l<=BY&34t!{+$XsC5C zz?Fv5V`8(bBX*hfz%u(fX-Iad8}^6sQ##6LLC#2kjmM-l3E-guP)!*d_DmZP!S8!O zYC zw@S1X@J4VuQuk$ndy2YnMoU5>y8|d3VoZj(JvX!@+Gn3y}9VtDgrk%Z?J%fu_zMOQZ38rt$uw_^qU{@%T661&;O7aKIPu9r7*UZF@oN4Sj8&4X5!boTRk}iz!Og{ZJG`0bkAwj4<$D`Abq#@vOowzpUckCJ6m+$uR1eBj36`m2wH#2dYp`M8?_i_?RAgam&5`NNP@KpsH9 zuswo?J2J*6eLJO?=T!bfz!bR+#XXa=9LMZ~H7t0RWOH1-2Q`DF{nHC0E}I-FpXF zVPWS>5o3uMX&%y=ff}iUjt#Hdp9j$Rcb4b}zkH&2(4%AZh)BU`lb}(3>CA`SdQaAh zbS0+dis@&~%@^1_c)}f^`yJF8hv~0C@}3Y&$qtQtc%b0w2E6uxXrMXCd4xHqdR00} zCkVcKVYgjVv@Ub|7(!j}c<433AFo|)HzrD)OWg`ZY{!N$0z2P#kBa8j>&(x)H$CSd z!vI)(5piI<DrRA#ECrCT`rC;A6u;N(a*am)x@>L@5el&4f?3I_@qL@rU&# zx9cLLv&4(Qy)S}}zX&mv=H`J>}`$6KrSMXB-}P8zZYDW%N&pmSSp^E3ll1l zxKrDcnt5&ao_s>s0hMQD?Ih+3GWxx$JBj&y3dO!uf%B82nwA5YV zi$(@2eaEyNQ@ooERs8Fv#^FGSgBQegHNPQ_kHNFfYmI+-KDi)wY5Lk>=S&APXmR^n z^~ke@I8=x%N|_>^e>d+Ir6Kw;bR}!?Sli(_%k`8tY z(lg=_P6>XS=oqtot>hgy=CW0kd=CdPw0faP4Sxi&G5Jcx)u&Lu5Io`~ttoDIQ$$ju z#22McYSadEzKazx5lY1vy_eg5lDsH*^o|0n$(nDX>8b&*&r!e-2Lxa)t>N>$Z-g@2 zfqW%a2QE0neZ>EReh&b~zbPsQ|-HNyPsh z7XFX>{dZgVxBfkfxHx)I?0&`i_uusQ_nZ9xdi)pq)%rL3r9uCo-pxrMM{o}(Ji1R$?n=qEy216~tWy@%jt{>5oU5r3qp18n!hseY zNHFSuNAd3g2ot*58YLPJIQnn4kykX_+@(!R+rPy5YD>+{BTuvUz>;X$+-l=HaFq+g zE6=8mHBc)rj(mD0C{8`@ed+vPZ|Bb@{Bi5jg|8okR|>7~J-a4DE;16S`W&Bm-?Ve^ zX7CA>0t`SXosSVbCK`tfxMi2=5jZdq;kl>NnRWda$xVXHn=7)MkGnFH8rTdw&Mw^u zQ6#G3OA&H3rY~L3fy77XN$KPMN{tm0rN2#?Z#zv;q~^FOl4S{a5AH6ichj5 z(AEw_>ESUfHG^??`8#e!G4uHqTv6KNOcsT4RnK`f5T^_y3m0__nZ6WRr@gW|QO>G? zFZ67dNN7F-2+eJJocE}-f{AlVtia(k^F;0KdvL9@*Zt1a4u?Y8flw? z;Jxo!{G0&$09?Yw)t4tfjQ;%cc3)CN%;yjM?N8r!jQOB#(Tv;ZFMgm@AWnS@wWiVQ zE)hBDT(5;&ProR9s)mVcsk;K>)!#TiZ|o*x z-x~i^rn$INOT#&Q?CQls(jTchCaXdhB|m+q4Z4Z<=HoQlKiaxUFpKGCy1NQGLJ{g)#9LJl5GCb!2Hxr8%^2)%0|7zS=aV!M4-nhK+cx^J#YOc8mEPS(chpa z{M>9eX}KT3k34_(7tajP4R6krVa1l_$k@A;Y_J>lF@N*nd3B@58{u`y#^AN5QTrYv zhQcB{R+l@~XJxjMr}Hse<`YkT|2((v?_aC0&iuW0N4KyZB^6w+XP?qwYS9eMJyZ9z z*Q%7yyG7X5wPWMF2oBLqrJn2_o17A%B)C^)ov(Py&>0)VUjrpoj!Nwqj7t zY1X(wN6Afq>{C6y4{WKD9#Z7>`%bFMt+r$%A|tJxmsRu%$d{`SG3@MMW#F?7ga!DR z-9RgKV#2_+i|f8!f2S7N_3{%79^tEgncgPh*Fg<4a?M#CDt|S1Pz)JU&NaWS=8x8M1{ZsTef&blm8KK;^tU< zo`wkBv6Mbrx8wUZ5VTtUBr7TBiH-_!s+>1=^qla+Dv5L)hR3lialMzcDWAxjWGm=g zwc2oF_V}UCtt6>#H&>54rL~`JzDzrTUUXJ|!{_!>yZzF=bMq8#^-0)GDR>>xDDrO` zlX_d^y^c~=Y+>wesj?cQtHjTG8lDNc-f(gWpsmf+vS3N>)l1%G_=*o`P4uC#Y28Bv zX&*9IYjG2MtMwRDcYuQ3|9H3I`C7D;h%5GRtS6G=1sl?QdTYsJ=XHf%6_}f{3HK4h zjDTyNt4ypC(|Db!;T)!`3(7cxkf|Q)>9mMIkkVx6o+ZXymS!IZKtgn`X4nm)N0xrH zR&C3@iZ%_jB(z7P_RhSA?N+RKKsR(|7Bq=FNH|fP7;SJN@O&(5$gkPOTB5ny`v4V) zSJ-iN! zp9g#Ldg{D>+)cI8WO@XTxg0aUw5(>>FGy4`7gX6B71(NkvA)SlyIy z!_m%YuQuA1P|695URM=xN`bI-RJQDh2D7L3K)_xnHcrz5war4K>-bc^R=0CTjf^XxKmar2f-_Cxr*Q=H*?xza!k+@n@pZe7fY;68 zGl;ekLMBx%hY&UYQo)KMgJ6Ov9G#h{-uK!iJc3(sD~M4xY`N04{NVK}3TC75uC)N-O+P&o+Ui`p~9~Ump(?CTWkKpsg37;Z* z(iF{=%KOHak>(=6qAwe7=k#eDI*hhpWZ3dYrHeP5UI`V^cW&W@Uk_5NlVLC=Hc>2Y z?(+Urd%1E%;E|0+Ncu-LM@nD$8GTVm`V_$5O3`>Uds`;@kn`rSw7RAY69*ty0X<(J2X|`JDIj>!cju7mY9SjRc zAsv+;5}`I%pz7C_P_Ges^%mltq40$Vu!sai4$t52I6j=v_MvVWSg>wR0qA!{-|hg} zuV3VA6#l?jlgH)!$nfs@U$Ub<7O%IQL0`W3ME0u06@AW$GmB*nVASen-5$#Ortm*x zYyL(|gujJ^J00N2TFNUk-=9>@mK^~SHtPLEE*-v)j`Y)j*PcVCeMO%P3<~+Uy9-zc z6TqOD%+$LukZjo-jrOB&v}YjIQz0}N?n07CG6T)YC=-f*7YBTQ4*mC(9g!A^%0!^JM*9FQKxiLRy+u;!7evPJ z@8_tSTb2ocAuvNdHp@tiAq9Y`8+tb#mBj>`P;i@OnCdc`Og0o(O5bT9zAmAX{!&$s zlMLtNCp8m%UBy2@z!o88e=ypEMhfLc)^d)pXh&EA7ZwTFvJ8ciHmNdVR2(+iF(?q_ z(5+^0xfyAxuV|cIkR!lG0n&YLXv5Cz6U@RjfLmBuBGovLmRnSF=N^4llCLUCTUar+ zc1t&4$6lf#Mi|9qB!kDP=-nJx79G`u0<>rV0T=x`WgC)~@hmeehp)Miruwd0rIh1P zFyZ=n6?!<2J`k7dMuWC97=t84f#}3LS$hu}k;d31nB`oXg(>?P|ImXBUIr)&ju(nR zTbijoAO3O~3M6~&6J@V`JzOpf0+{*lmi)4Ws5pMf6Aicr3GK&4+?Z$o?C1D}R8-@_ zx7AdHrdxlt)B<0r+H=E8|0)U#sf?{zZ^8s3hR`_1`V$JOfLuln8~XnUd+(?w+HhZc zW>T050TKwkC3FxaAOb2Sp$P~QngSw*B7y=&P(*AY^lB*5!O#U216Tl2LlqP?pduh@ zu%f7MP+z;eC-2_-+h?D3*80xhv*w?fSZxy(90A)z}J4<8-Ti;7mep!eg zuaGe~jL=k-*M6Z`eSv+Vjvj2Pd{pEiG!Mgg zC>6L@McTEqU_p?kny4DLyswmtHV~rh#g-O_nJtx}P23H3;xaXJ@a2!{;4g>_t@a;3 zz{#r8j7}fs)}CaP@8GR@G7e9^l|7J(n|HFGt=}{;i%48kH?lQC$Ow~tsuPs$RV?K2 zQ-i5c4EJ;%|8%FN-1=9ivxH!upXRkM6qQ`qgT))8pp3dJ_DhCY%`3qbzM(y{KAYN5 z#)AUtYj}Y3n;-&HTwefeDX^+pYeHdgrFWAXvE~-OZ1Sr{@ZbXWoeh#zSz%&g0<&U| z+_$N9my6|>9U5RX(Highpw(EIFInkc7aJd0fc}TeWO1L5eknK9I~4AxGYh8FMao$IYOJW&PZY36OJ>L&a5 zOBzG>*FrgakW*z8y&oHY{J<2=XjsrJv>Qk%hUL{BvUDe;_9yI*0UQVvhDc!p8M|Q! z{Njo<=UPkZ9S{#KLjW#kYbed3lmT?}0K()$>J6nUJT4ml8Pyn!)Et7l-=!zTz~KV$ zHSSy?&kiDx#4bA?pF+-#BUxoKk*ex$d$1(x`RP&_kPq#tLZ&j#^Tfo2KKUy@;aJhO z<`Q?QjmUGQ3)KK*&+rz%CEZH_DZC4#^$>j$qj(#Zu-Mwf4u?s80e9UA$m!~f=@LwOkXK1cpt3t;m%1<%V-s=< zW`EmttR_Z;)xHYLMZ;7EI;dn_U^{V#V1E`Hn~ejqZt=3jC_{^j=>RCjhg`_mRYFHD z4)agS70iAKd$(-^vvh>G(tLEVyG(TExXHG-!##(CO+!QnbAR=4)qB4uq7!s_MU%yM z!Z5C4?14wf&@g3VxrQ|oq|LoV8UkM6;3~zhfdmQ_y_N^~ zP%#b8IBgM1zq|IxXQwP4hTvhhbLi@%v~(F6DOym7WTW=6QBQ3=ZvNaMTTH=JBdOmU zIQ*h7G>ktP_9vhO1l#ee{U^n1I6Tjln{_v+T_s{{6cbcpvrCvkh4P2y7vUX1|I^Y@;7 z0dou|W62c&3@nL<-%q-nt?z1HI<%pte>f1PGq3;~y{I>w#~O7rO)g@QKq zU}VVL8wAja3DRk!XUJ$Z!AME{^>hG5I7a{Hlo;#8=A0D!!6ItzZx~Mny;wWH z{XMAIbJi>0zGi++%DG_U2+vVH%6gTNDIEym;bVYXWmg@xh_P5EdgarSw6E~W{@)W4 z=vN{Zb_z6YTeXI+;;Y83h#U16nfKj(G2vG2**1Y#7weAA*PtxzY2 zC6wC{(ZrIIKXAL1aPh$)YSC7!>@$klHKa_Wz9-nME$-;hMu4rZPx^3q#CXU>10#GC$VB!7! zvn*@lY2ZTTU0c5Go20{8tV@cT_i!KJf#1l(=);B5RjmzfPKqRVcJ)&Ym(*i(R^>hI zwdwi4X3uLr?y`Hlt8Mt=4nnFYRkLL70e$@S{8W_)t78OP@KA49cQy!w8mBh%@0gjD zkeY%tQ=F&6i_JCp>1KaVKh-fl`A1XX&oDRLLYL{cgE3;Ci_lS)6~ACt9m?DXNq?HJ zC;w#o$duumRSyWE8GKT(a6TWf%3%)Vm*F4vADzW3^khEFK8KGLD`I$~^AY;nS~emLeVm?aA6(f3k3KI_th~W zr{zGGY2YtSTk}x#(lO2F2OipfoZJnVemVA7yWu6H$boWv4rmWcynBcAz+Np$m-X@W z@s&5b-2o>m+FwVDKtA_F{=wJ8rw^8~iBzepH?_F)u;~QGR)EQ=(9i^4WeQr#wSp=` zW&fBk0*MVsU;-sUscpNN?D2BGbJh$12vAy#zfU2Y;&&r+mZS)61e zExvsT2T;Fo7_*J7U{AfUg3RFgK5G=u7b`N=wLM|W>+otV^#mS(;sHc!t(zYY&r;!w z7O*?xb+w_=N7>Orny^$bSg+M-Gz2h@VquZW=l;ucL}-^7yOvv2T!>?>RS!(>^N%Nd zvPVw%T__U}hzj@9sLr#^_(BckwM>i^6?35wH-9q>`{gP2<;S!+#6}j^KKL=4`#O`b z$}TQoZefwTvfRWvASok6h(3K`F5RLgr5uCn4@UcP&l@s% z=-&Mp>kn{CEkgf?r0R@F;x5}D{PttkfrGyUB6ptU^$GwpKK1^v{~8A4XE}AHf|tM+ z*OLH7^#2F_e$RG`9>WB+%|vF$^p4NI{V@(7gi*mbrsbEfN|&N=;?!y0@Cu4p>3`;B zRm-cCv61a(CO3N4EGB*Tsrh~%C2VZdSREJ4U<3-RK2$7(+Z+mS*GGi(^;K8~Gc=`a zdLERyl@yZPeC*zAfV6Peg<3RLkdA!EsfFmFu_VPZ=BQ&A=aZF{uRs6fs-*3zw4s>NNo!uH6|--zWIVZC$S|3CDLOq40X zm-G3z^rat~YueNwnT5{LS33k#0iZc&^ZDS*d?LU3ywz%hruTv?KC9(bl zZP#ux=RVVlo>p2(O+9?AXTQXtq!)#Q&Qb(Jb`kvSI(;VEazb_gr8i;bu@}iW)GyDQ zfRb^aud{-pTNp$gJkLYHwj`ATysha?ME&01Q^Q4?U*V{VaHXynPHhD_QB`|7#-pm^ zuOqu_5?1cI@2*XHnq#OZnI3b6a=;S8B%ePIeT0NVv;Gdq^~TMC1}zl;W5{F&`0SG4Tf8cEZkDLDKl3l3#k3T~sv zHS}HN?B<={>hHYf19wlT$vdlNstBdgUn$TkV0J_C0{z}rjw))_bgJ4XqNbjcGp-|l zZ>yiBwBTy)m{0pE@OMx);h8xh=$t1@K##*7lXj2QQG!OJ=Mw~*QO=^xc$5oifL*=> z2|KnvGhbS2MY8w&rCPLM4vc=Ba9d&EBy+2vY%Fqezph+U8=13BMGN8Zo=4ylUScJVnA)Y-yaaQPU9zt4H3 zgaWY9r_OOvf>&E2GBEp8_NVD@zgO<2u)(N)=-MelJ=#nymf35;y+!L;dVbRT_>b48 zPagmI?!vv}zdqi$FhSfT@V-%N&obA${3y8LR)Bg%ZK*-z2QS$mXElOo1&d~__VyA; z`ezw1^~-tUpYB_#8|u-rznAt+EecX!m#%j`N(~B$&buQ|LH8YK;4tSxEG3yfRv9pk zVZ_vNbu&HzustA9fL5euZdqXN^CbcT8wTXv!%&^5_k)#Fhip5g06)`ooa-ki7aQqS znhoM^0i z%a7(cHJ?n1XDU`Cbd|FdDp^r2wp6@L%{GeUNKbVef1Mvz&|$!O&I?)!D)QuK>8g@Y zX2(o&{t|?3$qWw173FEz7gHHF0UxBifX7pP<*jmJ?mF1b5ct>&*ZlOuG86q`d7>?a zYEX;xx?5-y?v`2u$F?c%;9u0aNkd;ZX%{0CzxG>ji`F1ym7GHY+!#)9*mhX)X`el# z&xy)|tX}52t@6oGwY-Ph!*5%)fdFKzd`<9Lnh&5nQ@y7$hcI(1fUP$^O?%kVPt&67 ztV~2{ss*WOTQwEXuV)oCefV89nvEf(s)yG3-Q7*A&&PP@%{^#Os&a&B!0(>92b{~R z;-hcF^1JO7NDG>7O9pCNg=KoNqJ~=)s{_N`?bAZz&F0^;bNX0;aVn2iIey<&>jCiP z^_B^{2^j}h6`|EQ_2;QE9K4ADOLxcM_s6hzBsy1`vlgx$XmFP5V$V80$m*|~@jbp1 z;<&E>yXeX?aY&Z~+2miV%C|#1=P(kwa##60A|GIz=6_qjdb} zDU06HL@oIq{lza=@S^_xCh15k81{rR%uQJ>r9U~~QxVjr+8`~64l;uW-yTVxGxp$F zdRr*J53fj4YTwfjt-|@bfwT^IF8(dKlXY<;*Sj) ze;G9_f_0Y$u;C|;9Cf9pYxqy6>CDWKdZ$M_r2BmuB0t`c`!OInRM54f*;4!inyMj! zR^ukJ0pa6_sm$GylWSj1x+6tSo`+wW&Gs64+`e`Cuk;u7o1J!g>~>b0C%kIeeC(b7 zg$)*08Hr~NIWL2)Gq8n!T4dR@ZPmg=29Ds}?NJXwey8yeH9OTJJJaqgZnL;FvvouG zqyxPTX(l`%S9=ftdP^Ux{q*<7hkS)7m0>)Eh@&zCsT+_m!#j;ZHfqPpJf&kXV!{J@~?K5cuV5#KSf!HX)Ah20xt7 zcHuRVzW#OgC?zxki8k#Z8;EFsm&B9K%c7tr27TJeC%bS{w&JUaM^9%t^B zwk|r&Iy-IsnY4{=#um&}TR1(3mw59FY6o8%0>FXH)h=wni*S%BuT%bleaIqx<%7az zN>h5PkKaqejtD4rNdfpQ2BQLCXBP0+kQ0-va=;H+%{uyxh0z273mQ7QG_EV1q$@}# zh|}{094}U~R6W?h!>nmRai;B+n=v-U83qQV#)a@tu7_+4Nd{uguUT+KiEHy#!V5;m zt3-!YH!(37poy7W#tMw#?XjZ(4FJZ^4Zky)#00=|pE9GJ*!BxKISlK+oI)@xtS;|R zE*ls~Jr-b*MW^JsO@fX9R4{WqOR|PU!C_xeTEf&rnI6X$9KFz6PhGE!Y)nt69Gxchk zeJ~f}qFS)G4aRjx^=;LT;G%O^W_2545EF4h3p?B-3c)~O&i-&!Z>2B8^?n8HWm%>5 z2K#U2lwGAYSbe5KN8vTH;c}ta8p&jV$q1kT5hH}U=s>f?y zYoxry`EA{`-gxW7ZCbA;wSCuP%m|o27wsK*RHJcrJ_Ce!yLghJ0d_z>)nU zbg;zS-Mc24P}>Tb^uk>N&zWYr1{pgfs=Ysqg$b2%3z@;(_*`1!m?ili;=Vk7<3v-C zm*}umr}9eBTX>r!wlLfC(z15kHr!?pd>9S-POZD00iT%RI+z=sABT7Fc4_@2d_$q-2!?Sg0XRVQ9rea=|P;O{Ue`p5*Oe>lWTB_zH>6T%Ne3DPPd+8zvLW4lk6K z>-#}6`&%-6@5NZ#Y8BI(B|LMDjo!*2I0}Gj3ajLnB5GZIE(q+avd?R8a-=|}qV?aY zTjv}z-&Pa`*Voz~IE_thn<%Aw@;zJFsU7Q1%7vj>Ou}xeu?fq$d-COC1S{wc z5Bu&Cj&@i>K9KVI%epcEa|a-V6rpDYfYSz&xiJRhp=56(U*BopSitf(*gJN&|HK04 z1CVBq!r)0XXMesu7@s2qSMxjSn4KC7v?f;~b4av#JeK zN?_O9-C4k~l)dmHb5%#iMQ}U&hA$$i?sPPRzQMTIvu=Ww2kTEOY;byo7~hr<|7EVJ zs_uLT{q3F`r_dvFuqM?gKB#AC2)(8f)t+ZR-fdgB3yuK16r9zJ4 zMh_o=EH(*`fce|uAr+F_FVKMspJX|lrAX3)uH16$*yaPQ>8gnc?@+3~zP#$j=gl|% z-h0Di5<8eB_i&)}pnT_zc347}qcn6EjV^}P>z&@CX266>nsVo=-~{2NEUHr^7FBVT zw8jG;_{J%62HrS@$~M}-47+FtRcBJc`6F@zTV=LRUf;gQarIf4Ds0OJ^1OTowGyyk z>a}YSLg(S?!V~MM0}hlJwOHJ2YSrlhWX1Zug4VDvlbVF89P*%FFcDyOUqynsGCTMR zK#kuJA$Du#dY9jOr8@I!Xt@|C#j5}S3#3*3Mm)@2PF5er0N7X_hI!580)HpBw@V4CVO4wqetT{g~q2^Y3<4CpOSixI1 zKi~0!#a3M=%Mrj(g?)};9t^g}cK`ypV+HJ%d@^vba~1C_sb};07#iWHPro9oe|)>5 zBmh$z09Q$Nw-DT|qboO>12CTw?j>S}u>|beEBCHcAi*2=8zE*rC_VyfetMkGN0awP$8GnXB69p{KXC9$KxcA>3QT3k@BZ^R35t z0npFlXMZ~pF4qWS4k$Zv=ZWzP%7qK69Sa9P;k|_8FMdYz58SsSLgVX|b`2aal$4Nt z_5lLyR|7?(+4?UUGMi|Su|yJS4(?UHkR`(IHiw)vNxQ^0HA3YRM3t2!OHvi^WJf(> z!k(s5%+`@lw@}chJ!MhNx7^I7TK6JV1FF}^s5EgfZQx}H3R>if)`j3cUpA3hfj=IS z8=3?pZN?4EIM0XRG;WU<18rI>dy_C8qIstxkS2(Bu9w4;-}Yw9DTtfm7v6X; zAve?F{HUHM#X4`46k$amYu$M&tb1Mp;JxOA*q4(X_JO&`^GgHe$G?_Y!m#?YCh{6)NFSvpaN>3CNSY(tU zP@;p*G$n;HX0r+Ke;Ii9|36{e%m2c-k>Qd53T<`t{!_pEFN`YzVgJLx>+kC?G4TE; zjQijEUG(UG$Zahw|8?)SqrZIp@;?o{{{`bpc-cK@iF@~7r>%+UzxrJXV*7uQxc}R| z+k*ZV!<8_&cmG9QC2a1$s@(t6!24e$Zr{HouEf17(fdjyy#J}+{nx`Q0f_&@!23T* z-2c|^O3+~m^(ztb{;S{Z_zx`j|0Z!I0C7B8qTiM1h9w@}e+|46&NviZQ&;mpN!=-LCDqNTF;TOVR~R|v8{?NM_Xe&L&lk-DD!ZBivxPSm z3c#J>s2=U8MVV+@H≥AERlnf0l&9glwYUVopwS>CYeAv&Zno2T!5#K_wUHptdPD zHe$@Dc)cV;*5!Ga;|OI<^qIr>abKYV{k5j1P#lM z`B(SP_??|T%b9-nh#zs=H7eoqhsQmMOHc1yz4F&HL7KF7{M+#o@@8VG{@tUD50AtB zL$#Kv@Qb?Js`T-JCqwE7+O}RwdHCDcPocN-rLC7NkVWiDgg@!%JzIPC{;l1t&(_EGVwB4YN$$$|g1}KEb>-;tFna2P5klJW zWfr5dXf&##RMb=8C$+$QC}Ch_v#i-$tFOz>lHT z9u>8lSeW_~FvPG9lcjSPr}r$K@6S-gb>sw!ozC^22Tcu3@xSJB)7u^v;b1~4;8%k-A(z;R5K%xm=AaxPYy~A~$z*mDP%U`B@HgylP`HePS z8ftc52qTG~T!}93E8lI$8L^ygk#}@$=oeD<6Nx=QlhYQaYW~bv}0QcYwZlAu+PTkIcR5e$DpSiWP9cQJf?n zBogZDXPzD%QU<=&d9Sr~HdA=R}Kcm~mpHg9G%(0xCLkX+5YsgQmM zksa>P#m^{W6tii^&Kn{ve(9*9upzH=^~QZ?=k=SCHsC`!npM>b#EllI%C@Nogb)os zYUo6tXTm`eSwKg#G6D$-D|*P3mYM8}=L-^d3L6Y&i0L<9E$`9*pJ^gKY&T&HL0=s$ z6;DNEor}~zM5HQft`ODE!fd3v1dT>->bYMD9r&_JR=Van%HE12&5l6&D=a}!MIKV& zPLh2ot$Mb!@_gRl=X0Apw~)Ik#yndr%Eu?7HhiuW=C@c*c862qcHb}XP29>Dn8-+EFn7K$Jodjy8 zD(#}zBl8S<(|53Gz6hiF(wPJa{OZ24s-nrlHY*?0hVT+YdjgUF+A&*0K*vfF)Nnt2 zSHO?29E+*~htRO4Yhe=UaP>?sLJS{C-C*0y)rwrOO=&I-Yi>=`I zHcMh|&UrzJ?o1;uqzcEj&L23RC8q!4tI6^Xb0o85ber;VHjYhDIC{-l{yJT^N!F2{ zK69(`I1|{77NMlu1Vpp_cVbfl2nt5V24uz-fZJV_$J4~R-BJMg%q%=#88Bf$11=P7 zkO~?XO8_M~D>5b7gXTM>)nV#o-4o3nNjaBFJLA7yz4CSdWFt>MRekGUycV#ncNv3b z9H=t=ZfKme7@(L>F3ZiP)@d0;nP{Bc79M?1ZSg8HE4!)u%oArCnx2m0NmjxN0OkWPo#9HNHjmQw zaw&52(e>*b6-_9?Z<`C>h|j587}CV^@;D z>2vrQT4>R|nu^=#qk!_-@1m};ns53k;ygfPr6F8{)~MpH|5WGntSsBnmd|@HRC{i- zuCZ;26rZCB58@xoy5BUUql+2~MhXSV`q}(RPq$x4y(m>xEB?&Zw&_P%V~7$JV0l(( z08wObHzDtgi@q*G+mznCnv(c8ow>G70JyQzeeI@9k|Xb5(r@=b(?c6%ilT=mgSryj zD>i5cTtQ3C-9@z&>%wFEe{dm2>h*0a%!*2(+2E_=X=?dAlx@sa-KQOhDPZ@pm}Ne0 zJn*2LMAk~#UBojdq6#1N+i)GSo~u*hJUtIy%Y~2WLcnRF<#vTrhR&~bhcjkZ=@=%S z{7K<*F%RA}UVcc1?kRU>E_FOraAtlt;+}U1{wes*3$IYAU`2ZLY$y0Ef{jx24AXhu zAYL^U5ehJid62Zy3FS8~=07}WB2=ICmE&T&>OHsrS^0kN#>%&Q|ExU2p{w7VkoK{! z5v^LzGA>aBr1(xDETH|SjDir{$i>vZKwY{SOJE+UT?@IhP!hvrH9Js12i7xD^F=5I z)$kM>JVr;)zLLZ6QO{R8QNjd$wVCyH1Y965zLLxtpscp&Ms5ngK@q$i2*R^B+oppd zLhN>S*sAX~JNa=tdGc<|B;?!Sa#7k3QM^4F8^<_SN7mi}NOrY!i9SU(6INkjAu7Yn z4N;+z7Ox;u1 zCuO&q0iuJG!=P<4VvZthpE_;_13#LwH2{e12Af_ClK|x<)SPNIXtfrKIC%I0=%wtG zlP}2lLC76uuGz!Rv;`7#s9THN4#syPbUrG701T33IVgFl@MMDxaQ)e`*L$R2ClsvY z0MPFNNCq7xCGeJF#}^V%?mP*a<|tz>S%2v3$5+3E(t zUoT~LWUJfqF`H%;V5WN^izPt}1C6q#vtjP3oUcYW#&@;nuJ*-DCctJE7-?*4Ra^Li zxhO;}f@^A6`4s>b$3>~JK>Go?8ll-}r;c`_x|d#g7Aq`^zfyXI2sn=`?4%}VveB>r zWlmLnZG&X4N2JLxO$Z%+>r*GP+?l9u;a}-m!A&6oQM{cJ3GHN{X#oLaCPF#0(Iv(R zrww^s98}G-u2`$?`4S;BP)#{Xajexv3926Zt>qq3v7_kjw{Sxc^7=Vyk{on65q=t> zzW1fpy>VDb&@fgO65*YdY6a=G zkFPim`V^Q5xEjl=okb|Y71)jzP#axhQ@ObYkXp?}$?k%8Qmq~yhBbiWZK<0VVvzSa z>ZSz14k-O|W&MwFot;dsa<5ug?uP5;8=6s#mcflyDUD9P2W&hVp+1w-FHsk+ zsHt$lvowtJ&xE>R%+O6QXbu&=%{V+$iM2H)Q$)xwt=N-C!;x+3i$)(J9^8(PtZ{lmofR~ zCp7a?79b-8+$G)yu@=D8$a}e;!*1!WkC23Qq!hKDBw(-Kgo^~A4+~|e*21CY4-*sy zdI`JVNfK{-1G3j%m{W%cs4Sl|l!Z2lx}>j<;6{^$#AmZb$q^gi>^b>Mw_u63J&=Ir z9c&ZSuQy;8AE<9$QDL>y1~7J`Nb8|<)cOkT7@0J7TROvaP3l_9ujoT()NyI($FoGQ zpG^nCu#=O>$RP@d+# zd4+85Yt(p!%4zHTeG_tKpVivfrMJCnIt?K1?&{eelah+I=3=z_lJg&_Lty6!yU_OG z;bKN^`ylW&NA|`G(%$TPeQ|d>ZA;9k(SAMT&vVpDLJaDS**^_(ujdpJd}|5?1w{Gc z)dR8+p`Amwt1r7j2dM`lHQ(y}t6#=(Bjf-9-5oWV;3dQo`uz<3qo*%U45Q<@V)ujfSv9%B8 zDjWUf6^eNlPC8(iDTa>RmNBol3!*~n7^pUBfPPRy{B-+TUMk^Zub-6*&Qep6Se&>$ ztMqY)0wJkW?bEk}r^Jk-%Ex;?%jI(+dk5*%(c=ZuskS8r43i0c( zhB7Rn4$`F;!T6eutNz)HQ})C^IIDeAc$x&A=zoq{-h(7Icg=qRw;V-X*oYV~!0iG7 ztN-TF`J2Z>jIqh8qKeLTP-=bw>zn{ba$C`@eCAJ5RSbLQLmDZYD6;rO}XQfN>^8p4>7YzGU=0xYq{*wal{)8nd zbN-~ATkCH=-mcvvc_B3e z_*MGd{2i`B7#|~NkB|-bGVcUI(dhypt#9HgHON5(0YXghFAIhU15hz)RHv8o@YH(J zn|TdW^qnzr&IqI5j&-4mO3{C%)_zOAascf+e>MNcTFzT1O1Y+ZpE+Hwf~8hrDiU^0UTY~=yZ z7U1lu1I3p^?qobF=5Fk;U4ff^%ST91#u#3tAfd};AbG@{4!u^_S;S;mr zZL4vI-XBr~?p-L2Qra`f>KC4UttC`KckJg?GS`mmFrK)UVK}CFVcph>W792SE6U?T zvNt0<6l(B->7@5hp6zgW{$aW%sEgl^JeS|&Y6(A|LP9@3%_E@g_~Vy}&weVS4Y(Ks zGFJQJAblX*M~MBsvTp9k_@yfLt$`v{b-P*Gg3U?Hi^mtMEkol^J6*TF{=)X@i`H(e z6ALIluSO=c#&Sg6Q*&*ds4~)MKjnEIqaWm=LDmE50Z=Uz)}_9(+x1GEiM`7q4pU37 zge70xsKKa9;V@M_&dWixh2m_zMK%^50Ho)TK;FyMhf&r%C?#G!rVe%wSH<18HX)+? z$)aK4X|3dz`o%N><_-kTztG`6g*R+bHW5HRT;d>cF%MWL+yJ-ibvgHvbnFRy#WX9R z@WLbTVIB`6@UgRAc+&~_I2w9C`ppIK-JUhqifEWB)W{0|-Gwu*1P#L7!Nqi@-*f%FnClp~J!q_Qdpklw_1ZFk{`>&OO$kJ;k>e1bt^>xG_yml~p%eW@R^ zc^^DdfuJ?GeNXSE3tuk@N7BjIN9F;;tS48Np$_WHcFJEFd_Q-96Mh{FF3JU7m&UNM z)_kKp=&_tLTK(%A`_}~;C*I~UmLxCnO6tq5=gSuYUf%ogV$DCFsM?<`96lS)VpW*a z-QkZjS;ww&H}+pA-Cp-B|D5{73)@=i#vrQ6!PfIW^xfXNq}n~B6J{xcn{tw#7+u8<1D2R0p@h-$GU6MQeD%U?fDg}-^J zL>yDwN7|Hl5s71=bOTV~MAW0y9~=QD_XKsy{O3-J@zo~?Xz@eC=XW~MokMjmxMCb` ze58npZ8TeoJ1z7Ud*fx)w}1*Wr{Pa1Ajm<&qfgpGrv?nEZ&n=SvR}!tXO6}!}EV}_#>mW#(qm^{Be7mF7!Yb>3|m3zfe$g zYj`3<>(27aGz@j{COUds0zotqHeRxB^E=`YCliLWP1#{aH$f$nHKnCb?kj&7*$8+y zysAj3-=?UDu~2b}a3!R<+_=oP-1R!bqSm_F&RCEZX^FX^2KUjkJ#til@KRovG)T$n z^JKg=UkEohci$sSAAJyUZ?|_ciGaJ~&WVV_UV73D4XW|_EBw&_UCSJ;Ms&+iVyfQj zyybCS_tm*he_6pj|NZ{MmO*<^O!fN|BnwD41yV;X z-*@oRR$fp2?ycAj@M>L%o>f8b$l29J>mgB-Ia=59qx=w!i?h5MIKRucv0^9v@#)G` zz&5!Hv3CUozDu)23idcR`8VJBK&UBA?BcYp{GptEG1|buRmR;Gl2QI#U=Yf|t*P*| zzil(dOqbu{7M7tDnjMy@7C#o2rF9$*&(LRs~L4Uj^kl+IzWUZ6Lq%jKC4l1d9 z5zAR&Dwu;ox>Y)CIZvTupo)Z@byNx?3=YZu!&(N-Y%dc1%>2*rJmuY@Cad*d+DR(2 z#<;E#hn?9`GDKUkX#QmLcS48~XJyRz4SDa(Wt5q{;O*w}u?I08djj$PIa?p`>LK|x zeLtdDniGhiG3yL_`x>A8HfhBGOF^3jyR29(I5VHdGpw2Jc2W8P4zYIxYK$%FAI&v1 zY~hG$E`@#0^&Az0#j3p1H;=w^-($jza>KjN1S4{a#7S zrUWs?-f~hEjEO?Kx%{NLJs0jIJ&wO2b7(%{p4Xu#Nsp2qJxS@-bOFfzzJj}L8aa0f zKjTr9$05`(NFgW9Ur0~440Dp*`cgEqCgk^rG(kGLv&%UB^yk$kIkE4)P&M$QR!ijC zQeVp1%FID*ADSU2wNoY>>(H4WA2u$4shy8ImYg0?x>3|LV&50)*oo75!5;GN9egpB z34>Aq3#N0{n6c&r;AQw9>Dm3-CkumbDRli_J+;{kmY>Y{h}7QfU#=o6^-s2b)^GIR zn@0FGQNN-xYJ)wV&L8}M1??OwvQp|Kr#@37_3#4}Bi47i&z3NwFF!c!J@?)FN4u(~ zzw9I2uI7ABpk(q`?BjnyB{W9;jfm0(G{73d+ehPs*?i@95$foMMrfemmCbl1=Y70O z=BmX8;KYl;7ueJrTV9G)ypq$TQUi0b{Sgp$BX)UiG<9SLQEw^c-VrQ){q0u(+z-%! zTY=eZg2w^idpY$04K(CTD&Pe)`OBgX=DGNN`R|AAWWVRB9^KEK3yjb;8_(B2{&iE<$sr)X2hJav-BG z8W&#vMm#reXr=w@uj5)VtPIB5& zf72kWe6O^uxV<(0C+FdGvo~OQ-^|(Qse?p(E%~C)N@?yf>7k~}t_%a`u96+`LN;J& zgKs8ph%k8o0K@T4n7_}VeGuuO&6Z`B9_xmSUaHMb>`Cgb`EYKxgLH5Ri3brCVxsAe zSfiRUg5sH*J?}>$gE1kxOmBjAsCV&mKyI3W=wd|Q8$@%%ujutz`-tg1@5c4Gt?kQ&u<2C zb2}2$N^)P>l^4hBF1UEv!hdlZz2yF|Or7)dA6#1ba4FVFkUu!PW9l4TprzHR&petx z&=4mR&cvv_|J7&~!U`P@u0giUC};qN-baV5KRQ(bxHRx=jnDeP2~bIhekSB$3w z#+~{X#+{Z@o8vG17mQo=L~Tyst{X*O|9Vcy&NP2411hozY7LC-{_J=)BPA)N+_RS# z?ylaSWAE};>D7GKER@WV10{gvGRD$&%TzQfHR%dp9e~N3q82UJJWY++6|JVRvp})p zyR@J0<5>7_K>$UCtF?ywBkWtm7yhLIFPUY%yM5PH&{VR-y|APe^Kt|oQJb%f7R}7K zC1oauKZ$yr5AKE8E;pzg<#V4_l-|9|I$I6C-T$D~?mbEt6hzFf}f6 z;-`Ae-D&9xLAse(54+qG@mMydK~|&+y?vXZ)ojk%#|&%l^zE$8@&PnX4&D3p>HEzz zdU?qqj`YQV-rGB6KUb6tl_}{IPuML#yVTk3*wCXQH!Vs_NOHV4$pCi}#G8Q%HVhto zd>0Ah;F#p_fww=d<4JigPEL{63>>E-&m}&Mn%CHR@*$k?G-vZB6x8fD@FG3`@?)hh zgb3>qwI0Bt(AFtP#!xbVCP)JgFz;L!gI6%%Qgr@A1Jhf5hqTWjKNh&zc1&ym>3)n$ z2T|^ZnGR?&JM8gE&dNmKQHm&j?WwNPk2fk5(@Rn_)yX34^dGEO(E@6MJTO?+^L6g; z473r7w;X-McJFqF>_>*E&##lunT3i7uhbi!SRchc@_O<2{h>SG)3T2?qA7nOs5dn3 z{*{57NW(lmq$3)o4o#NGzDCWDyE*8vdPa1t;vzx85?tAZqqA9LMvS(N z<2!WB){LY~vE~)uBfsQ9dFEP0F%(Wf)jrxZn`k|xh`u-goC-h&4P*-Va5xu3)RPV6 zVt29d7&dFgp3h0Ac}p+iB}iwWC~R3jI%RE$hDg^u8Xo+HZ1(Fdz{v93B%xD4(!J$#5-@H9(d2rlz;@S1;_w9}a}0 zxRyz}F*&|KWi&$I>KMF{-kdBOrveq6*$~CY#*CPy({e_bIZ2-YHf-IrbzkmuV8e{G zr=)zcC=)7#e53IN8JLQLS-?Qo5GDvr2M+ZXi9!R-~tPY_fzz8O0^SqE~_+6cgsPpuO( z(s$#1#E@?$diz_-zQZ^-UfvCwgJQW|)ZwxMKg22szKSXzAz;pDaFS*znTK(nRPA(Q z{1;t21Db*X_hi!jVn@TuG%~h{A8}7;%@Jbr$0?^*jN$qqoC1H-kxFR{;Yg}t;HiY- zbpWU;ii;^JN)yM>cSnhw(X|NPPNbtK&LDFDfpKLtfw}SPzMp|eR&UT0QhS|NTY0ed zVVm^6uQfFzwR1?_OaA(W9|?f~WWvNwW#Uw5M&huooTv>PM4oVTt!eTNL+ z`1O$VUKKBI0rY+w-d+G|kZazr-<%Rg>Wx8w+|BW=TU`THejmhzcVnc;krJWNp%?D1 zlLvZ%dI1A+BFhA+l-=hWUH@OKy@yv5>)XFOGbv0Ogc3RudY4cIK@0(;YXGIIp-5K) zHbitMp;to{5HVCiK!c)m4Mjw30W2t%Q0%%5>Q-#*ll}ev)>-d*%X!aQ=geO)Yt}Q* z%yZw@eSKQZ0`zMYEz&D^Kyb^tO&0nEh?3%cSe+lZb;O2S^qdKs)6d1wjyHJ8f#0L% z)PY6b2|;6KSIO#zDSdBj(nh}tu zprKXVa3T$^#}blDn2$=^3U2mRB=(&s=&Nq;i|Uf=YXYS7VL$hZid8N$G|FRtFL5|R zbNeLufoxKou-a+XYZ;ODQG38W)x=}q7$&7lK@R!G8gjcCvOE(C2*Bv|;2L+{l5jx2 z0s1I9xyug=F(o-+-rLDYLn^Qwuqn|4*^`L5c{BT@2;mIucbXl1%slJCDDM}52)}{G zM2v~bx+pS=!-N!==^TExVu7HRPaLq% zfrK6ySP~eh4PM-)v;i}Sc4Q%UlCKuu_qvS&ea8@*JcS#o%rMN}0ZM3K%{a79%gVO6^FwcLZ?Z zo=-QO$hd`P#OUM{p3A(Y^?H-{UZy>oivC#9|40r&$7{o}(nsEoODfR2=`wrA%Q!p` zD93w*6YfL$eLtwS88?=II6we>?nBv7$zIAN$4g;18Iv;t(449!48kW2XmvVD6T~v= zynzZTwIfmOp(nZ`%KonVwI(U)oqYP<$2gFW-Yo_b-q=uQF~-UYi-s5P3Q`J3*Mrnh zi;gZ-Rhc4?# zM2T<&+J5ZJ@YNULg5LMx{YldGGj~Z}hR6A96@TLssYu-ow>w!$8T{+b|CEFJ0pYDP zjJwTD;rArzom5gV>-HdXbWC_to;-NqfMX4xpviT3rntYvfuj5rWA&S|%9wedwO$0SQj}7-hn)FiV*1wqo@)N7zvsYOoad=4C^Ntd&r-8 z&ElD_GSH5~N4)4YE@vm?zQ}YcPM*2_xbwr~^MtvCQN$6;$EmkKyu0~h>Z21p>GvY( zLDujHTTdQ%@RB!sL@wUDHs%%?5lZ+eu<+XYsT^7}&)n;--jySC4J5x&2aL zFmQ&j(F&yhB%qiT<8%5OjuNb*aVAr8f(-|@Kf$MufMo{`jkmWgh|)aV{t@-&>`(1c zx-4J9Bny!24#`d1gtKz>3Ud_FFty8#JAbf>MvP0C+RzEbkLFwOl0N8 z#Swb*lP%V)clh&p%hXgIajA`XcvD@}0#!!&!?Rf)WU~f$WE%m_H(K1@k(6dKe;XIa zR65MYp8r(E5xkfu24x8K{g{f*jN!X1hk^eaVg28Ivj0L@n;M!V6zl(ruu8yA3B_t{ zX{{iq@Q+VcqF((M!uspSuYd5=d?eBfS(snw`d29uK$r@m0-6LkoAA1Si3KGOF&i$ysDt6@Q+V+ z68Ue66}j-=`DFh^u}ZL83CQ|yiuE6`_PQ+ zD~(mBlx=X@0BqQ^^dw6)p5vzaM*QYJ=ku7A#7nzr#!UXiU&Sn-R~F?tn30tUaBbqV z)POyA$O>c4o-%0SGv6n6XV(aVT+rJW%Ue9ltlz_I%qclRA@nT}PN!y{fv>sfQH z^MwG6x4xtPW3TXLpbn_ptl#Qc>LM8~8`zD=M_IZu$$V$f%6=6& z#dO*+vUp6ZmL-`KCks4rCbn-pw&krbAwT=%mR)*V9{1FdlNi@M;o_nj@QEB&mrLNz ziZ?HH4^F>oAm=x@gJ%d0np7B%wA-VY!)XvAO&)xx>EZ^|4q8 za5;UF-}WZDIEg4|1FQH``=)%?C1`KAPNvDbJbri$6Aur^>6>+bGv06&?Qrkh$et0P z>6-q#d}6+_H-?+^c;S8b`TcAG#%#&s!{sLj-+ky2d7-Ov=cQ9P_@@W!Kd^cpJ=_!O zS#=ND_hsAUZkbDpE2GL2lVA4);)AztmY;qQySERli_n97`qk!S0DajtNB6C2`|MQm zmmsZ;PcRKHE8WOqmrC{D-dpQ#8=uKMuV|t);)rjp^gI*7>MyzB^5Xl+VY8bLmkr16 zWPbM9IIEjG_Cw>zz9h{8x&1e~P>$PVkOo8h51Hdi-DKbSU#Nbd``mO6ORRGJnC`XH zOapC46?7>+&$++YsI8nAF-8QKr(KmHAwQb1Ms~I{@VK8!a8R z3ShU<ieCn6evU>$68BERB@O1k-_?|YcWs+ zEbY%{uy|F6^3F`1k+RAqFdzi=PXY&t7(_}Pj1jz7fUsr#G?>KhiFahm%dk&utY zzD{$g)->oJVSn4Djht$~t2{BxMqweOMx0>3hqC534Cm;{DovEh@}-5WA}71rJfbK& z?_4eWKow8*53HzaZLT>Ew zF=FbCSPl|3q|=D3(-@B8Ye+!yA>P=OnwLCBXURTUwKKjE@u`f5Z#H!Iob<2xRNi{; zo|Z)k(stRRg70(F_-|)vc-;TsBZvhY>)~OnrGO++;elSN6HS4N3+p{4<0J$&_0D4h zAr?M`csuXbv>e0$5R^mSZ~Vrc@i!o4sjOU$R{h<%jB-?8@@+3BV}m+*`?_kV!^guJ zv5}b}bFNA;gd$2xG|g1Z7fU)t4VXX?an=iZibCm6zpokgG~3Sfv0tnNNKN8<*HttU`yM=C-=-SsdrPOZxd*`Y(QJ>OCWoAU{TRG$B(LEk4UH(#?yp}HV@?sm?N-M&1f;aRW z8Drq%hKtSgj#WiR+z|Wr=Ro0FJuf|Ie8y@d<*mY*=zZ!=J`tnunE!` zSsyo6yiShuylL%7<7=93^*b}Eea%_LK!&zaGTK7H-U%jyU0=0e`xQT8{Dd5`oG%N% z*G+7oT54zVLy%42&{Hf3353Y6mpO>3ORnQ@p(9>T0m#Z<4Z6b7g(0k|7Ig-IP->p_7?|wz& za?j+Mt{Qed{Im@EuCo}cx9&V_IWb#po}A#nS|e`>4K?qA)}89#NjeEL3=+p>jBgbKR=XPG9&m z|Jb2+ujoESgW{io-mMl=G}htJ@XeU|#D=18if&iV70uLDtd}>Se!F50qLUl5UYF(e z8v67kZJMZ+Bhhn-u0@!W``$?rI+4SN`|@nr@zp+`( z9nX%X)oo5vC>Qt@^;)z>7HR54Vo2e&)#xy>{P{ z_BX$Nv3VohWs`ia&gQ@ihwp5;Klk|R*-|a&3>S@$6LwleE1>+UYp}Nq+PY~33KSyo z-D0*(yfeNwI1#8TM?aE&f%l3dm8H+_8}W434&giMXYZ^jVX$u3@Rhzl-&(Aw`&YoLnlA zZvzNw^wDx6fGt4<<}kAaQR-yFr$Kgp^=ljXmKXd$k7?~Jik!_jX3gpauu-6Ia0VV_ z$^krfnb@NHI&3NxYV0Si7iXtVJ~m>Yc7OlwRt8YH%mRp+HALv60>gd<=NNY=L!40{ zU`u3|o4O%SI>0<+r#qTe%s(dIm1+JOD>ZXCjH6HTfJ0uxPQ4fu_h^q0uxYaADF9*4 z(8pLzLM}1M1Kw+kkqXGoVWwF^ASuVlOQe07lwQn)RQcLfb_XI_T)n8y3?MZx0O>@@ z%~V#47olCIp&ots+BftMk{c)nT1$=FV##s65l8kF^eQF|t`rD*6SttYRVo*brxyO6 z*V444KCl1d8qGc{7L#Xz)h26(1%Og#)J-VntHoS|z0kmk8CF9^fIMW8E*Aa5mECO? zba{OvJ*Sk8KBA@el9_Q%gd7iw-$};$59ehF(4RjezV@;^8T5@zog?2&hWFvxV=>~_ z@IDdhsjTiBid-EFOti#s41M2o(W|qt%o|vr`%lVJlgqX{&>pQDxK4?mgkrB2i;;{1 z8VWEpdS-?IF!A>*8o`*{fJe1}#LUvk3)GEy85W0O6*BRH7Rp2zA~%8YF3HUY&=#(Y z6IDmz1pvX5JHVv;MJ&SF!=lR=hh^tz9C#l6RC#uT1C^8@603_0Y zHSB}MA6Kv*WYuQ2g+D#JfpvT@J>HpB_{$mUGsN8YIMs(@J$`iR+4oZ-mAYnR&I6sg zIq1Z%1auqCldVPyATS_(0Ttev}|PkCP7Ltsdh z)jW^dOGM?c^wy0;r06EBdTO5U+LOgawGi_qXxmG_;*aAf|5gVlAicyuQz{hRzye5g zUco9EN#@G^%FE5+qVg@kwf(TdA(*sY(@U}u@Iak3_!0u3XSxG#$z+yvm5Q2C0!-s0 z?DOH`DMSs4y9C5aN0CaF&r*rwJp{^>~z)Luq9KTZ;4UNSVFN@KdOYoj9~HN=O3&Kvar8JYSQ z!XAK#EQI$Y*^&wUSVHILLk}z#l#N|ueB2!zD)-*g`pwifg zp+`5F+kn|`nk(PJUUVRciMkUHtNyj)cKJEn0^*^n3P=Z?Sdn?;?mS{5Oefbixx|R5{YYabQ(*mc0kOd^v}Ad4`J=0d3C|dN=@jI*qtp z_F^#+=$!A$66kGj*HRqda0K9^IM|hVDU)c)jOi^FqO`7KPM&qa-6RlBUdjXz@9DrP zZ@2~r>=+<#m^-IRF=B|&-`B(2sYnd~ifD)T2qkg^MAc19EO35E);*I7?NgPh&p2O3 zL3^TtMz0~e8g#c~wg~izkR!@}%LXTO2&FnST2utN&oCX3xdO zY@qGNdupYmAWk00qTCrZ#YABNPr-S-#ld@#VW6-ngNJU=f)Et!r(5u!p@n7CIIjn1 zpVvya#KA#4ls$!;O}D*BGs)y38%SA3AK;pcSJs9*YMk;)bLl@e+=1>$oJyPN4eY$p zKI8OzhFTQ*wic6jqhOOr(p$NE^@6!oKSqfU%u%5ixyC~UuxY4CJQ?+U8cKeAuXGtR zu2hg5k5~A1`Dz0tN^5$KfwtyKTZ}rOp+ltcOfDvyB<6x6hFu%rLI? zFe;~0(6KEf!oA^#vwYa4Kzi?%*Riah#gw;gYBKQfwt;0A>1>bvU7!k`%Q!{4(sXgZMb*PZ&D+uzZq)%FuA`Mqj%l% zv>B`yq>7@0`aW;~nP3Cltzv?&j)ES$@jGtY?Gj*T=s-NxH(nImGY3B>8AWl!L(NpQ zxOX`Wl%g2Di4{=`JPHs)en9mA8R)AW>)QV;`}1?>)uRiBbqmH<7EGPe=t9trJP)Q+ zzH-o7JX+u->95fjQU3Ssg8jnj;7czBb>U1o8QC4<=W+$(b|;m>SZbuBD!!s^=$cdm zWT&kb<{6y8(KzO-K;b>8W#-6(pxIQQn#82fudD*^f9`_90my{>61}jPCp4G^ji&;Y z3`7XE+cHmB8jhb{W$?Xy0cYLrxe6Y7nhYxo?|gE$mB5>*3okijWe+QuNp0(op;W>uH%6 z9>t-=h>%IeEYaJiQ$TbLg7gl%y7U0W5NpIdg=caix*?!7+0Bg6zv2A9$w|>>rMaC!2W!FKT%&lUC864K>Z5fi7m6m7Ax! z6&;FU#GeidE0OqEA<~I#?h8Du01!_n(a&*!7UT7H>g#Gcs*U=h%k>>DWzlT2LhNC& z(eqFLMp$Rl`~^MMqnqJTTS86aJEzGmP3_^qpX>3r;qo$s+XF;6^Svr&&CDH)JlA6V z8O=c_IN&+KBL%Icu2%4xJZ^DKte!o|md)vNblGnvE_~QZ<)D{IRJ1va$+f3Hl5Md(7L|c*( zAs>6A){yT5&J?cZ=}7!FAF{=T0VxiR!=s(#2e;Ro?cr-bc+~r0&sq?8>%RrQ`poU? znr{jmR|$?q_;`TKG*)HV8!)VQ<#~{|d{puO_+>fKWuwQ-aI*Xc%{Xf~VgG*R`-r<} z_mAVh+-LCHu^aD~e}$%vD5Bp5Vn+?*cVF4lq1+dE$n(q=&uS4Ooak#Q1Rg$sKoO$+ z3d~|EYEwYQKR($iSZA9bc*)S-GbH|S9){?j2?S1+s-&f&w;878*PQL2eEjwYR?Wm= z)jRBeM_38sFN#^aO?4F^tw7=S`sAn6I;smdA8h~rwRn9OVsTQ-7StP0zBzRtf(qAO zfWj96<9o+-hmK90RQMQSXogoFT+d&)B^^!-RGutt;f;Bl%r2+cS^ABYSDqVNh=gBi zX@-si%8l3DP2k*nm%J8T(8?J-#PB}<%-OtbQ`yd>^%&Yn7)g5D?usR;ax15h1M_X3 zF`bH-8`1;)IK6vk=p-#WziplmLnv5Z=C^zowk9o9w&?J?Ct6(s;amT?^4(#sp@4#N z*_TS+ljmOA#=k(z<_dC=t5RWUDP0TKvYFhO5pkfrTtGK=v( z@ztkODc12?QU@o<({}?ar4_dm5~iEHQyw}!;ZKoY1eP?GWMJaz0j7tN z=U>bX{2{aP%CGNV-pyS-zVYhn?_WP>-a3z~8NH^_q`g>_hsLlLplD*ktRE(w+@|9S zfD;rA%UJG#>_4hsH&z%4%KgxQJ3}-nO|WLUA*8-EA(J*nKk$-?O8tU`+uo$03J9q! z`D(wp)DTPG)_v7E)vlJe)KmaUj_f(Z2oD4hd>FgrUkf(I>rRJ)26h8`~tmIrW`|!>BU_U&zK%ZY(cvMO^`v(^g?T9YZl0 z!W5j%MY5tyV7sl<(hlH;%Be1Dgq*%4>MPMS$p_F#9q^hqp(NY_ceOOYbMb)2705Z| zX(z|nEUNUTS6u~#NmE^7j)77Mdv2Oo#NdO+QC;v!l+vp}lYHV=-KiSmTaTxyJLRL5 za3xi`Y@k$EloBm7`KbWTZN`_4s44cQ<)clX9n4izogil^6!m>_k#&nZnSYvC8IMD( zsv1ri-?rR(2pY+=7P)NnHH4O7oz?<9+iNik8E7fy z@I|w~lQdQw6z1`QTN|v&k;bGiqr>&*$xhElF9{ec_bU#Krf6FsxX8IGI-V7AHhe0w zptp(%B!#F`ktTHNgxf-Ww}bcSSr@(g+UH~MU_&prM>fAdUpw^_Q(#_@|E9ac`@rM& zou324_igyw(Kv4EO1^^r1cO#`8OhtMXgN5x!WhWib18H&Y^Lfu>*Im0D7W$THmgHh zw;reFl#a}W&JVfeq7Gk(3;ml>mU+i>%)0sr?`65LGoW@@W8;dZzG5qm*daQ$GKy51 z0MWuF=s?iB;V09Tatq2*_D9~GRP1Kem;RlPO@u79t{;jMk zOnbfL? zwzYgz+~v_sGo0Gw`iqr?n$0!y;M#um^$jU2%T+IAAni@5vVzi4VoLO;K*RdIny&?G zCs>xA9cycH;_hk19l)W*DPfvFXC0P!EYMJZ&Id+tfC%Nk$(-F5cgu3O)>^k)RtjIr zQP7&cmg5o2s@jI5YB4ON+YZ6sK4k&HI6qq(_6SP*#a0JN9W`lwnuOD#thl)YRjR9cT@l6lfBfjyEAd; z&q5NJ2RCzeA7+x#b88nG0K3s$mlTa$zVJ}ByKk=lV`cOS`k)foLlwBdLhKGCq=&r& zmGOS8cbBD(?tF@pD%E9Gao*$CSJcP>moB^N)|=~FyDE=}n^d~N@JS+-D&V5MY+HO* zYBLpUSP1R7hl(_YltR}7WanlxhYh{7opR2QVd^Ehb-66{m!iye3vHG} zRZwGk$UV7HqOEXZQ!jJHH7-p7D8HRX8yA*}JMkxBmy znyTFt>h{+hWF&V4GtM)%{l!DEPGutSz*wYC z-?`uTSmGO><5Dvti-$;#Hrad3as|={O-iVW{vKKj@{&i$kDy2?FdE6Je5Pu|0<8{s%xsoh%4Dabw>j7;+^&YEW0i-(a zhWsm|YDP8k*#MR;bL{EPgR?|q`QY~^F%${w?CjO2{OKq$U`O`e04UfaTjhUY-j9F)!ySOg8!v!r;kCNy5!h)YP19b7P*rv4y62l{; zHgIVOyWdzt@lWN|FR>q-^=DmM*N~F<9x|@)B;U7m6$df6H5SY=eI50ERQ&2n-PO+W zbJpMZaRKn5`dwxPKUAzQp%i|M0OKx;Qljdk+QO@5Qzz2yrobP2aF25cb(gRVk^HO_ zp+0tR)3-lDbyzu+qi00NMp&$eJeDNUS7QV`j3k%r%k{l0`xBCaMD{~IlDij;J(21AI`bhD=`PM(DnYNt zyt2u)&RR-lhh=2-G0}R+)Q|~WSgXzUUf8W08=@7Cm9liA{PCL&$aB$;XF?7}+Hk(2 z<0S2J{?SVQ-Z3)5o@odRfj&iomH@SQ5U00{pa_!+#2FN7>Qy?ZCci#kgf7`;vn*J1 zG#JDDwjoE5A`~JFMCjin+*C?tsVHssue6_0Y{nu=no^*W12ZF}1FmBew1Dlz)E)}> z5Eb>58hiR77R53N@6wg1lDicP^7v4zp-rtFrp^OnTNOP*$^FQLKyp!+5Me?A%j_^i z(}jJ4jc#a!KD9W&rKprqRK`T7jb;xDQ8e<7J48s8mwTDJDzRwn=zOhwz6vKPAtNKW z<(Y?f!N7ZVb~_z-@D;J|1TKV&c>Wr{rxyp2GxRb`@_3YQ5AoT-Hi-bBZ}9Q8n~?WUFA*Ryc2&m0X4JCnqu}>zMo9pQW^}ZLVtJLfxD?IE;;FVCA_ry%H+V z3OydLIU5f@&cm!bQFK)l=0ptgC5A*+BecYJF$jbvy8MSb#+MbBZiKf46b-1^U)ZOG z!?n3WR5KmBH@K_-sO`AK!>Hm2XG4i^d7VH4+#gC>U$62*`e0+dMZ8wKA_NnUpT1u_ zBd*`Ke@D33?ynr|-_@ZEA?m9U!NAy^lPoQzgk6gbO)vzSY)ZYjoB{?kEN?3h$(NqN zu1~-nbHSGcH;hr-Ru%K%?3U9b3}VY6)WKleR}`hR2j%Md7_U%VIIC%h%!Q0(ccFo@ z@3?q!u04Otwx#51a!Wx(h0fHLKr8^n*~%<7`+m=zj>X3^3j3Inz4Od4v$>S1kfMq^ zV2n!=19fk3v0mHV(v(YYr&^b{V1k*{}kd~2$09`b7 zb-xN1*rsbLmq5y9Z5ZR8>y@lJi}QoR900?wEX9N~b@2d5jYJ|*o6bTB!jj{8d?%y> zUb+Oek>52eL>}A(9fc8|0OCYG`>!%}n^nip|Fcm=NYLLFc~&0X?wlCPTT#4&y62t=)gBf!vu(RnC+}Wkv6gkhh4@ z+s<@oxJ2o>%;evt)3U{g^!)CTU1#fwz1bpzpm~Ipz-f~Zt+y&?>x8hzK;Ut`=4|S@ z{)vmj+`XDpcs&O+od`4<=0`E)B!#s0cl`5|eU!G20m_l|E|aU+_G&@$(B$ClcY}9v zLsMaETt$uB$`Lx~T`+ern+Gb&0d_UGZB%@c5J{QPEE&-q>K!`pGvqD;@fAQl?|~EQ zdj`o6m9^&@&?8Pp?+pN6)r8(14O_DhOGz^t=U@Fe3@ibNhu2sq=#?gxr&1IEDIPLO z?D$lx#f*G)fH>I7aOp`wGl*CB;z)O~0G?Wvc*#QjYfk~AGSJE_n*~g|jowwp7OCMh zeUAPXpnnr-nD=Xmzqo7FEXG8{J8T2qGWMv^@RN8>4ds2XfGR1)Z0Kh>dhOi7MTc z4(qk{n}R4woMnXrIx5k1`eY`9*L@b-N`BWUbwt_U4OUeAWx za(Sl2AHBPxwwd=Z@7`Lybd_hw2)SCymrP`0J{Dr^L@v>$?l*6CQ7C9jYRLg*EQO^+ zr?lT7O9bqY8K52ooO<4eH?=wwIio(igpDT#RdvA2>b6^WKmieWxb0v)H?M(f0#G6T zFPwDp8b`nUIXu1&ymH}$?vVwo#9sQxe&kl3M>G>5Qs?(lA(?Q(EXU09N98TDVnHCr zb{K364aouSvJ@n*$Zqw4dzTs8bpgQyW2RJ4u7g>>;V4}E2vwdIAASm>|Jz29=pU%} z;ICTD9`U780k{|lWcB0YJ0(70>kpxAj(&Hl>FIx%VcU+}HUQe8-!7wJwjLBDnswFl zcE9Q>Q)LNTZz6|<#CkTVcP1ILxlFVZ0G2>?0!o+7Axy37ttDsa>*;d?x95gF%v~is zxxCB0?ZeHG-LXOMaHHXv=S1m65jLY1PK~qtQj66U5NXue8KC^2>rA&0sUg;RWF|`k zG_L^1#~XtwdRK;8F(}xu%|y$D6+=(2Zp+oMk3v17P58j6ZR%YC75NH}mfF zCXB!6;T_({HToGpNuZqA>^x7#^VT9Nj!(4$OW^J z5K;nmAZf@m2g``>C@|0@9d4=4LCnd|?v#`Qk| zu*k>%jl=bSqF?`kcK-*5>wlzQ|67Oaf1+O{gzP_0`2WTApEa(<$0b>5|JJxxI1+;4 z>eJafJW3eBEiuNtv+d>E2cINy5OE$UEr(I!^M}^j!gX z$M}iOCBYoB)cvR9j&w)Pd2Wzvnt#x?r3lM1r} z6)ly|P-`m4aUQRx8Xd6Km!nR3Uj@E6HnnK$o+uoA4|`R}B5e&ZmsFzXJxd~&D{DdV z#j}sxTnb32@16k7b=7!8kkUl+ZPM6lQ~T6mM4rRqM31R-lT2B9(8QnH3k}UI2>f&E zmtsB>@Aeg!I%&&U=|-Im%En+v8T2yb0-(%rZ+#y-?z~A09BelS?wsDFyQ5NWWb{ml zEmC<6Z!D2VNO`|Ve}S&IM(?pPQq=LZ2JSm(#ySprzKDeRx}Hb#hO3n}*G7|&^w(d% zi6so|)%@W@KUO}!dw%t(=HGt<=>NpPPMlUp5crYPN$XpTZ z#q>c1rrpfc8%TK;RYqM+ZWP3Qe%-L3;|XiC_NlSURPER8Sa9KZcvG33 zF3flS;z zmK8pqVduCadY-PF;log|UhCX2$r)r=l&+AlR!5zPY}UohxI^1xys5%_eSh}c!jyNu!9BL&RF z%S+{^6(FyfPQ_Zy&9SLS+1RDso+rGMA}pR~9}`g)3fKL)vdDE``+ccAXwUZ-RijBX zyzvS9(-=~E;ntU*mAxs5hP?*V$b|6q9x|c(we$L#{)qe`_w zlEh&rA#Uf_M_2F2yb|2DCVs#q-_FIwaXCmdqI?c4l&U+q_L3TD@frM3k(fJCl+835L>&uPcwJ?Ac<*byjQOpRax|-fm7*KZ>M-AK($v76es> zPp7$U6&<}ahr*?>#`ft^ikO9s>aRSmuYbH;oO-Kqs0u!>G*KAfm`hXpYsJhdQrl<{ zJFUk2XAI2Td4lMwo4558fcGQriepKaugW4!Uhk46!9bgjnEiQblxxxt&5EJ{%chK@ zWvZDd*(Ful6RLG&fa?>V!(MbI1KJ^SMjC9*RAo+BlvA96dvwrHDBf^M-4y{zvBLEu zajQmDZF!EDx0s4@HXJ3Z4MWJPncBE?g4DPev5v@fPVhKBNRef^u~}Ky^IFI|WaSgJ zIbg^XafK?I2{jpHZkq&D)iZs(6q3EZ7!~BCL_^Xm^0IYRvg}#`V$Cf}*%yum(DZi| zeLQ5)H7KPoHpsQybH;R61W7KK-{UqYz&X8+p^blsiyt61Zvh~HC3GHV0?55LTwM%g zSx=G4P82=lxG{Y-z)j48BWf|ovq5V%u378h7VP4u5&)bF9l_`z0L%T@JS@xzzUz2L z)qTCc8J>m+G@O95fjq0h5^l*v#L4g;jOVx02{84e z;{1G3YlPp+-(&ft`HVZiNYNiP*y-jLkXaxN6)ZMCT1kNdT42EApzD11azvK33vmFt zRxInsGOn%Pc^#z^n;}BHJj=PH6E8@;o026xVT%cUEs$O>c;G^uM_5#`oW5Or@kBau zqJrUan$#WpEBc`D7~1W?kPW*-|Ho8}77a+_J9vcsn64VvF*m7?rYA+rq#!|0lVP?( z@eex-5k-F!T&@yEL+MjuW2>>jc>f0IA;ozgdwRiyUv6?Ntw~m6NH%CSC=%0Xch(qd z<{q|Xq0FPVDde*0tZTZF;dl!Y&OVHZ(ewd+)4IP#MsPwlLXWrDdSCL2WVmislid(( zWpTk5gZtZ7o=*JMTPr$kl4P~j>u`u(E=703GW&7GN_2bBlnXs|fU)z>hjLT`X6iwR zoH}Dv3QK=+k(^HanB;nW7j3U+Qpe1frIS|(!<@#HlX5!Tq-{=Xls!z-=Bw=xLb-m%nn6c_-X1R%r={_^T*G6%bj`f&uIdX4+ec1b4X5{ zDj6{7UMIVe2`D|dlVwgFiFdZYq+7cIvo@xN(Xoa;{qfGXD?e9%e`LuFisqx|hpk$c zDm-V}jPtPN z7^twqQ>AbXju5_~*wq6i^;$abuBN-LyvHFu|Cc}OAYSwa16S0hgQ%ED4vLiOJW?8( zr>tuOPuE4=Jk+)QZ1hoxXg7K@Uwg=#pTEyt=^1i*Z!VS`0g(%T>lm|$(mp%nuu5YS zZ&n~pYrKNTXVvvexCL!Fzv&}Wqf z?X_wwloTCh{tfO(VONSFM+&%TgC{eTyc>Q?Z2qw85=hUIcbCNa~|aGS{m-A|muIY3Bb6PR)x zj%AS~^O;F>P7(dED)Vq!H*%^6`&3CGi~;2(=Pb#lEtFt%0F)ltbgUsOJ4e&O5JTkI zWz8Ns)stJil3S39*3R0@4bH2y(;~}hf0@>ZHK6cD4;(#^DUH&!;sCBIYvkn*=7>Q} zroj&Pq*7qLs?hDU@aQfUahKrO>&P9Q2&~tvBqc0)>o6ih$l{5?hFGl0^)UBxm2NFy z-0qKUv&tFV^jH4z>dai91@F}W1No2^7Y-lOpp4;pz+08kfAWz@v+&hfI9LpN^3>(^ zz0p>#l5~@^RK4@gNHrQNQ3y#gx!r{588*hP9txa*dsg5emfRl*U{`MuPfRqYD|(|S zU;o08_^EjU;Ob>%iS6_(M`b5p@*j>+9@(GIRLE?FoypO!Y}h-*5K#a;o`ApQ>X5AA zzhlgC-7HX0lFLmv-(_X4Yn)Y5UM(p7d`(6N$j+sdR+CEJd*CBKhhWEzI>r(9)v(=4 z!geDWB1LIqV>!Sp&7&)LaJl&a?Uo(;RK1ld1{=!P)p_CI;C>YP>@s+%kf?XyU90R? zyMRosRXFA_Mtd0H$*s`Zx5aD$e(_bhXac_AQBcK1C2^4>40spW1wHC!8H38XZQ&Qy zu%i%Cra8d?w1ZL~W6{tU2^sXu_UuDlpJ_zvG*dr?{ zH;cWcMw`mHvO3IqE>X&WiR1|Dw=P@ZDK*FGNInvaej9i_84*l98O-qY;G>)-jjA!Y zA!2GG2gI6<4enw7{R@za(eB{!+{LBH4;j)>M+Zpy5{+hF%R%5F<1j zK^2d<@5u(HQJgs~)OpXts1bE-B_5V|1qejO2?n%{hav;9*=dz= zHQCTLL_-#446#33fEdZuEUJ`Fo`%i3QLp-q20>`=JZDWCQ{L_Hu)R z6^l1iZ#1ruLpPx6M5u^L_@N}bmWA4=)&MM=#~s?b*nAxOaK?3Ph*Oy#)&5=$CLaNTp&lQ5CpN35kcmT${I*jZHfyvevxx}tCl@6l5{w`q= zCo<@I4cXO1K6XOinYfCc@r0d(pglRRnuxX+A~y3b6;XiQWTd?pY|KOlg~47+$kwgE zi6iR8L8uIGcr-0@``r0;i@lWsa4U8nXr+7Xk!{kXk-4~JfMVXX-hCwml^BN)<0D;J zwLNNsBMyUOCR+LKn(J)OBT`TVu4H@`Hr1DrjQos;%G?xkF4Fe-V?xW(t9KKH&x%a3y ztPxDm@kV;nyXrm#nfEI{We2{PftxE4&Sd_IYdXG^7V~RpYe^X>K>J~3c-*VU$=$X# z@TRCHF==>APz4%~0HRpmfW60#jrZi; z-#Onod#`o&+Vc-&%}Ul}e)n@d*S)+J${KU*``uj>el8)ld+gWlhQ`T#SG&(&n-r0! zhRw4&{IPv+wmJ%7j|6=$W~`1)VvHomj>+cXOWA|#urP=g=^?Zl^aEkdIzDVg z;s6TW3tg^*n6#MsXaIOs9ORpOk}E|3vhx75!({`Z-DL$*5zR{Ett9JY7X#~TiJrje zIl%+ovLtDXXszv&+)B~IahC(K(@nIrw_G&RM-^eEaDDz?7a98x<8_SKv5~aD+e|fUQ#06%u`)m5iG!VIh`o zT&oj44$%MQaF60G`t6%Zd9p^Qp#?qknPJ68?4Jf2$!N9&L4`!_|1hxq;1=uktt3-N zv}k5_#I5^+Pxkl^pI4xhZ=_k#78wKU1i^=Td^}8+C$CGb+u-sPz`9FSpn2gd2Iy0X zE@t3jRN35al*Cx_x^eFO$SIjT6FFK zjC@IVV1#q%eH1z}GXi0NVijcn8|8bWT-~OM;lso(L-P zZ`KKER{b;@&q?^$F$lM>3VBIOyMK@zmeHMBwVp=bP&({@ruj7<)dn_SHZco& zai%%);+{VkJ5s&Hcd=`;(6cbAJ8&Bkv%ToKp~D zL)1J<@=1OhQh~mw5;KGC@GstB=V^HuBhGTZCmaq|4YeCK@bd(k#|$*iki}I`aY_mX zbF}Hqgfk~d18=^Hr2_?yRdmGzUt_(~UOnRql?T@&YxC)|oy11m%uh4pE!@7|PM7%| zr{Sb}^6xzGv-@hO+wf~FUlsVMqN~2{cwZ062M&fO-pZL!##I_w3F+&RE?Lj9a!Fl7 zuu!&2(CD7`F{G)CpDF|{&){ zaL=8`Xh1n;Q0TU3Gkop*6u3DxZCrhok)xY0^;;&WVh3j+eZnqnEiU5GDoZR~!Ly*b zr_<>tT-nSV52__Ot;jGiTKBwFO;fk zWG`%`j-?KZ2>EP5r4vW29*$3mc7)*J2CaIgSF{*9x|sY}H_~s>r(uGhzYpfX@`AAf z;tG;sW|G8%d6Kq%*)t)>;Ky@Nx-N*u#N1X`(wUh+za3}qY%JMv?taSTj`NTA%cu0` z>}c)ke}3Y-hvtq6CO5{M0tDu7oY~;HcIVjM6ayk37U^l9nC&iiENfvC;I{5l8ujYbrM^IUEZjqW zpucV67EpKytLwSDsLa_cB#$=Q6LK7SDC{czn#sGJQ+f4vIQPc-xaxrGw4m-dxN2U@ zAXYh_B{HgPkr>;r$hfNjxMT&lpEvux6g)>+qyJHAQmbm+Z#Fka^pF)h{rP769x%Bz zR};1zea-3+FiKI22K>A<@A*wkXk^qCW7Qj26L0X4v!d zPcUnLjy{uoFER{SKx{2+HZ5cp;`ywED$|NhDO3*rAr0?q?tV*PGPVb|P;A>Y`bkfh zO~tlhQ**pv(hW}51o-CtrtXSq0*-&*)(ZFe8;G!=JdVngcDu%y%F4n*rK}Fd&HiE1 zst&T&V^5?x8!rEFJU>iGFY2YZQG$n*)P1>r5!ItwDyfs(N>g^Vev#KKwzVYG0!svvm z%vrWbp)b^H*W+h}KBXW*D7_g^IidXYj2vF9UhKoD#_5YWx+JOhR^i0PpT9zJ1>vKY zE-@i@eu9dS&vh8$CY@C=O|uNHPek8YWilDKvWu^+ee6_}fRhu=qfYi4{Dh z6ep5`viZK?IiC3;Ja;opg3-t_yt6-CL!TUbYzAipgfQ=ZUH)B0+!}*YI`NH@b|Vn^ z`^lsd7MF)>2JpH75EI-A`#TZFz?#TuDFtx|%104Ol2-xE09*%*mH+)jF2Q+kA!@s> zoR;vBErwRDR@Jv>ZzV?=1uIxdZj%RD+o>mpxY{OFIHYLII7>LRB8SrA^pW#!w6G9i zE9h-@5c!b!h-@|+S?5w$y8LOL&Wgn?1bAZ4p@A>H@CzC=ixsz#e|^$(bL2d`O5+x6 z%Fa;EW!>=0z9O)6G!IqtFk$Eo?1fYkb%7qMlC=02j{Bc~*E%(Jf5V?e)MJ-Sijsg~McoCH_#le~ut1hN3GM&git<6>(ndb)D-v?`8u6xymC)uXIajXpxhG z;#-?d)m{=0<-x>w-q7(GAUApFtAcS2UBUkNnF|{kNDEqPF<0uw;8UZ0$##8+jq*oe z42~Bk?%Gf9uJaha>AcbK?ZxZ4x>IQDp!W|k_ ztOMdi&rNf=azNQ=!Ie{;%nZu1R^Y@5=Tln8i&&bRFct^x9nQ8cr5!GEI3Jc0!%kk| zh8T!_hP{D&ONTV^k5FoFWmSBulxqp<+F*fWH__{t2&?d%2gKvS-B(6tpJRsQJ@$!g z1QYvCzkw+$f6jGQT10C7#VgN#yE$=f8%DL7q^d|s-{!q1q5j-ySIg$YmlI>6=Vk-b z?}A=*ro&D7wF7e}%fI%%NalUqHE^d$eu(5H4^z0}gvj?^1JOixYf9qu&Iv)H`Ow%t zUAKEj_an)(XfKk2}qoeq3JsX`-jyqUMTxf*w4|fjzF|kvv?!eD(xi4IP}?vcCb>bwwVE z1K=jjKZtuipMUi!Q$+B2%q7Pt zZ&F)De=qFj(#anH`{Kh_m+L-^48zk3WzaCC;E>M~gj}M+F}a;;)=0B0L76}zTdt6e z?qbVNu#I?t|6R6S+j{CjRlI}6tpb{giIO)fjmTiDCMuC$uF>d{DJ3ukYoTWemR8i9 z`=`LT4BsLtEY!{>;2gqNs=eD7O%yYtzQGzqa2;x5nl1q2hryqMffA(7yy{i~o=o*> zs>}sMhRaSQ^u_`#GLDlvgn$^Z_hYU+MtU0EUa!kaW)euOXMAu2tJX%f)0BLNc{7q| z00*YORHciOX9Vz#48U8=jSb2#62O@x%PvOVfCNP5=E)?`35lu@fXwg0$b5tPxQqrn zXpJpQ3zwY9Ev#bZeVb;QnJ8r$g{SKRE-YS#gLl~yP8J6n>z4cuhVfrow35&}6ESA2 zG;BJNEQQrTs^*DG5Ba=6S}Ch<@9AKpeuy(|Qa0;dHkVj-x3KKqOReYaWmD6LNs$j&W`#|vAmsmvKx+ixnv}c!*Cp%Y0C90ig zL2&Bc%vmhCi+EiuUlt4BAVv_G<@fbm?WEvZ0hDZ$-!4GuR1&h5utst~thAIAW}&4H z>ij_OLh3pN!8X3k!oy$>9c-cnu?0Y$#RM8Bjc%z`3S(hUfWW1C3+HQbu0CjeX^~PZ z_RLYEeTJ6t6mZ1AWrAVp)KDP{eBav^tEL@nVeE`aC5?Wr`J)e#(16$ta@@A6fPHXM zY_KRR$SShHInv&2w+THx-BW3bcb1@|^vJ>S;t9wxeixZ<% z1qVLxi_-Cj=qeG)`l}A)(>!SiS*4B2Cq;by0LpHP0ll?qYGNcnfp4Q2^H|MQ5@hSy##;b-8h>_>dstzg>)ssTBF>Sg7 zXgdvTUY6Q-bye3rcv=r+v$THMHnPS3BivAOI5ia>%szZpRn=mk&3>W1h{n+Yk;)^x z+L@cv?04JiW@pinK|;$_V%4B;8=PQ@9ZSvCtd8vKo%>#Q9>8?vnsv#|!h#VwWUmom)Bshk-4)oT!uX*`rudUt zt;N@5g!noqJYY8KS-=7eM}Sf%n~j9#k2K%z`_cDl4Ijj;r?tgDalrR1Bt?vK6z$Xk zO_FPs1r&$jpAj;}Xdu7I9tQW2@S43Eu`=;Sgc3|rLXjykh7dctLXDmt+kyaA42M7^m^y9AL<2+{1+%_eb6&dH;d#pYl z?+$_qBhXu^s!=qsxQBRaw9|JtvA{UVC||-9zfhy?&72sZ$?BK?5BsBiV-Dv^CxsdADU$ zaGZ^kGr!m8)rA4Uxv#8;3BblMBK$28(F}l+lYaxrL8@ezFs$J1Q`o z%{?5c1eYM(o+1*H)%aQO8Y1a<0dGfhhqmx8sw@8* zeY_qehjuf=dHRUXd1s;;CM_z8)wWg5y-$ekI9U?h^}g_ zF4;=;m>Vl#14I_eNHWd^jyio@Nu$6%2>O4o?>RMNkR0S$c^Vo1aczO4hx%KawMdvz zILy!{qXlTmJ_2}(EkCfFi&;27+NJCF6`(LweCjHu4f1`5c4M*Fp!>s*>>`229|&KT=zC zv_lxFAx6Nzt8L*E+%6V9W1v3%!s2LmWPN_&LS8sn*0 zJb#7SGkd6OFBH@|Xcc?y=oky(Er8ob-$_ckQ^;1@FCT2n1j`NelGRXGnBpUBAJS)q zEfS>2Tg?}bUPHR;4pjMT?HjctZ0wnKa)Sl3wXT$KocM{~j zdEURRscHXXVpOI~m5Eb90tg-kpFV#I&Vb;0u%@a8v<7d_+y>J?nKD)8OO;tu|D{X~ zSs(ImYwDM8{~a+Z^QFqHsh|eVeW;ZatHIrwyQJ=6)D#0Zc6q2ZCbgap7`e{_;}9)R0T&2&2( zIdeSj4r(0_l^ao}aB#}A&tHrvgr4XdfzxN6k>%oFemm$bGVi5L~>5KW_Wvz(1}m9*8bb;Ya+rII4T(92AM&B$k{)oTIEJL*+zuO=b> zX2@%0ki)5{;BL>^R&=ac_8uGfKDxL(ad;iUU)L?J;~-V@D*!TktO`2~rKp%nG|(R<~-3TM#t z#{d^sVSAtK*wVB zhT_W&mMa?xVa~|SIGAeHi2C|ODayvBdqQ8|)fe&9AQCQWp>J~X_6%J|vPR-`OX>cb znLDmMbKK%Z=x~U?js`#*48aia#4e6&j4ZA4X6`YXF|^5a8*ZZLmlpY`t#(_~DfMB) z^3lu*6)$fiYdYY-HTmmnHIrZHS6fDdF}y_ z*MpX!Pt+8%z}~)bg=7c1Khb=usaRPp`YN4xcOrRidqh@=d@F#v&Z3%0JI8oK%e|>b zGh_H$JTJ5i9b*|WAh*Pc6_zlVMixfzL2|jbgsWuhaw?ys5<*30mi(ODpj5U0caa^h z(Z0x?6F!t?n1LRq-zpiEt(I;FonmedXTME1Qra|QY;x8$ZTyBp@ZGT?P5C?^z{Q7!d8CIB&O9?rjLbU8(-88p%9btS> zg*rM+h;-Ok1X7k5>z^WX1^Hq@UCPf_U7aU>zV1E${^uLvRZ9gplYe=|LP;MRIAM9s zvNU?aTGA6|4i|%C>p=F%ba}|@U#23tDB=$2%rN4C?`a_4;O6I-)>F&<#@3T65z$E% zKd#)di0_M_*{fL=(&flk+`Tcm3rl~qx^pXR1sYS0HM^}--Ks&UNj1V z3Ba--<-wSbl$>I9Wpt{N0q?;5=21n6O>gnm)wn~|~NSRpXBW15fSh@M@dN^9HRl@>$XFN*3Ivv#S zdPkOHpb(U;*VZ}*;X;<=Egr2c4C$G1)P>C2bsCVI3qmVItKm6puHkOGH+?d?1u^pEIhJly;6{ zT^1gD;Npw{>@T0fONPB>v+<*)wMND%dx+^}QqEus_59v52tbQ==bNIZm~L{^);mk0 zpY?=uJ?HJg=kp>3B+fl1x7G7~bJ_ZuG`kpQj+{C5i3`XMc=yyHg7vfN>US{+r1{{mL+jw06 zzSS-(c`vnDjO@Gf1|lVg3^R5eqDqn#>>i*ut;D;XscNl93Kzx8BUE|s07LF^P<_-P z6csX#)PCirw+6&eDePUEf2KyTlyC#;31RI^(_Kt9VuB)o$$^0c4IIF>gu|%-7oEIY zQPG5(*c0>Cn7>|O-?_Zl;QMF||45)ZLGRRUbQtym4AA}}!5<>>lujg9bn#g5OQ|utD8^w3BCXK6j=@YI&&) zkY+}gK+C9p33|$pw?3{!5q+jGaUUX2p8Dy|QDu_hq>4v6-Rj;t3QTV5X|XDY(N6ad zM!GehECwmQ8T|swwQwXyjh?Sf6P#$>P`c?ZF65AyhwXGhDlt~0Vezr2SNFjcBfawg zTMF8NWvL$yAc&=+hS7UgQ84OVU-m+e{Pmq_<@1lNY}{|izjh0MeP9zBQza*s;9|j5jyG{kOBX*hAg77T*p8Cu3$!-2 ziBRViTD4lE7@+W6_HHk`hSw@t6Woqv!F9A0A5%rXL38 zuLgcQ)%53W;=0wPk-yQb!E$6$mXA!C@RbYF6>LW@ybWP;Zf#s1#D9s#sMt|4W`)1- zgo$C;o#4xRDS|>*$xp`+QCb)%dT}`lzQ%#M)8F8W%}vtK3sd~j>038bGLyS|>=j@( zwps+{#5x%G^HRYRJ?VFoFOc+gdfQTg9A0==ef!fw-j0*cMrZ)x?dI41^{v`u!3DkF zgPWXZWIKbBhT?!B?#=Ta@()#b%E}bT-r2&ZnF_^&QsSInT=L91-W7SptM6Oj-@l93 zA6FCunqMe8zs9XB_zWGz@Bb#;kI~C60S?qN;Xml8_j0Sl#&*>)_n5RE$P>72rJ>Pt z*{9thOc#XBLYs*ZZ`g?^zdPMptM2{+TH2~anpY}ZrUH&s^ntkC5k_c7J4%^^j%32^ zzi{z&(C)h3dqFtF*mzLNc|igG$WD_YxSdsq0&~?4CcwbKw~HaVEP@i5HoGMyeOLeZ z0&272ZGO2{yFP#WeEy#245hETQydC1CRAQkB6}qk1GB73R=Pl#>Nk|_$ImqFvn&XM zr~qPL96SlfDUg!Nyi@I7+Ki<;3nYcbLe7p@RDB&LiGe&K2F63tAYuza>}kp8RIrPR z+1%UfUFJ6A?*K7mppZYusS^{LaA}2dXrzFWKvATy^9x1AMPeXHpk3Bs{x-d+lLj8D zCscSr-U38~5Rt$}gi#8X3u(&UBAzSOIiD0;q|tI2=pI zjBlMVT?v?S>jV@sHLi?lO=g+Ad<9`(fZn6qq28kfd|_3g6jZ)|y$b?ZQ6+5mLFaoO7uo2{S&%NOF*~9s za}QSnMO$jnXX|0=ltCI?oAA{^A<7>5+d;GJYxwHvh5!lM|0AftB<1lvsIXdXy{38^7)7u6 z5{5RDRDYwwJ=nnUt_sxn)tZ55XRG+op3S_@MaH&?Qo*SI6q ziWKiqpk;2f=7jP+)3^v+OEF95?vo~+Z0J_o?xMxRjxT})eB_fvr5Kj=g9PZs!Hx5d z=m*zY0&-;%SS32^@WWU^t)#V)k2LBel5ya!4UkSkb)~qev>WfXYzud$36RBtdj2N5 z=x_yPi_wdWsoV%$nI)oWjCv6t%53^($C78AEl2n!Hb$s7T|r448u zJ{V-5=@g5?3H+PAA@|Vu1_pd126Mzj%g?AG>3nO-o?Qen=&aJYYfop^^@ile&MH>i z(<4+PJg~|KZCj(o=?F0r2jFn2C{m#zyF|4HX>EqiE7m&ggLac3!#<%5C}6n}g#QeQ zvvEvO?R8E?7o+=bYIn5=F%lNzPs>TRfo#9Sf2?l@^A+{jkcsk%DYTpC&~o0G7TGrIVF%A1YV1ZDoCGWbJ1JoPC^>oZAbRhr6$iD>I$98R7c4|?D{TWEh)kO`m22Pe?Fd(O5 zXjD|}SoZ(|w*|b9Bu{{v{fVnBE;u1WGO6wmj@m|ELhlr#I5;^Q2DFa@j%%#o^7}{d z6mRPBvF~g7^xjf2a#4)Hcz`2sI06bn^CAjn%c*6rC~<2Z%_cwHd!`r%D&<1z5*hS~ zsQ&4sO!KW^gR&M^swCw38|c0q#zq9Lni%BZK$%(C^_0m|)3~a=IG;HU$zI5ZrGs6j zp6NlT7i2^0Byd-tjA(wPQ-Z9R4;XzoZ&n^%s}-b{d0QX7j(LGD z1Xn$T%%>oegH?q>eHm~aZ#QgW1?Tpd=&XirBsS#~1mZ`UKU(wzjk%8CAR6a6^c|MOB+q-DLE)#fw z*l-}aVCw{VhsHoAs`IdOLV9FpYxMPwoa@`iN~WY^n|GJ(9bLJQUDVMeOWuGo(nZf6 z5Bk5aE+hQuD&F@TZFmz`AdEm;S3l*o;BGBoxLs_p|$4l_H^xbZOOSuar zXe14#FG)A~Y&|=vOs4WY@M1)Oct!4XdBmjNqpAAj?SHW6{Bl88(GdkEKj@*?J1#JM zuO1Q#3}mA&Mi{LYUB7CR@lUKDZgQAaTuJo{|8n|GDS{%*s!*?+m^s-MeJ5exoy0?T zk{;#9NMSCtJ5$r(n^zRpq5O%Ym=wb)O0Ww}K5Pj1lN z2P+f6dG7)ez99A2qkNC=RDFJM@eLvD4$!niDT#)PXY4Cy0&B$UhVk9>f zFHsNKP<5s_)j9QczsSwk=7vEn_=bt}p-!6Sg0HX15>P0aii*%|uVBF4afA`imc7CPEv0cpgI-%^xR1#W~g)CP<|1v9j|EA=j(N!oU4J#U}t-4u)FO?Alby{{i7>I9! z#GZZ7ay483$63^L0|hpdzf9HtK8r*@f)s`QSUy_qBw=2P@f`TT(?tK@N&7n24$a)E4 z3+Bk-C>B0~VsHTC?$J^`^ndceP?rlbrL&g0JY0iVcjK=B7WO~L$;nmIsJmPnpt)yP`6wz z^QdFPsc##c(ay&b&kw7_3pE@vmAsfh?k`j_|M;5~Ft@t?SBKH+orLi)+uI*qKO*LQ z?Ax->DKBNWGK%^$XmW zN28K{91@=Oeu%OH&Hy5XZ|ejG{_8)DJ^p#(@1H`QU#Hgmih{$38qDL_h{STlqZ9c1 z`eZmeKe?Q;%9X4yJXkM6IM8Ieus2*0qT$b`F3O!3G>=N0*WCKw2_wK&KhgN{uN8s^ zT$?|0L%_%yo%`!Fot9fU0%arFYK#mB5M5tr!BA*m0t48x2^}d^r|!&T0~81E@I)Cg z3gMn-D4+gz05R|t&ciF@+E zndF~ox+aFtqN0noH8=N;#i7I_J?8VP;5dVzDemo~ZY8utJr{4fw`CwYb>l0~{*L|S zzb!X4zy!lH#~wGeJbW79@aAE4+GoNx)B3_kl-*FtSTd95#SSqW_avUCsGF%5N(zn2N90yqHYiP8bb~X3DTS1m zZml&A(7MCzr%iJcZ?4*mrCrY^_RjakPZrBxn0sr4Q>g0t4`TEb_Qk)5(e&7qkokXz z(IK9^rfaE#%#6C(#+Ki6g53x(Ya17H#|uhguqMllECS;s2K1Q93Yiq;m6Vi5t+0Ml z>bWXX9S(XE1lq0I+A+9~NAtc~Qiq=n^=mPiD?sgQ(iImkw7+>(pn+2vSiz>eyDyh{ zZ+`RL!h4qk_1>nuJ%7J9bfcxE6>pEOCYQBq{b?;=*&RDP{VBG=)F@ukko`gMLS9`i zD9&vQK#_W|$5<4)nsajpNzq|qt+(^H297|N$xJL(3WX?aUK7b-UEy(a{CxxG#MrUY z$f6N0hR$!*D<~Rs-(+Q}7zZa@UXqR5z4^B>C5t9$rD~mmd_C_7W z6`ULiUQQ=p?H`~7t8%p zE<8V6k}|+uqOb?vC;b{z`SjkYPSp?B(^Zr8l|hbP(o-GNPoAJWSGiuwhedK2EShRW zJY$QA3S695`Gat0C07{-y>&cbmcWC_Okv|1n59IPbp%yDEhSTY1~!;wUFedblK14d)CiWv&R7lP)bX8JMWBa=hDUx zMy3&7Tx9GCpU|({4i+dB?r^)>>K_tx#s9Myk$q@8f(>H0q%Cx1N^bV^gY4;mPGlMX zdu&iI-F1i@`Ef{b_2|H4pvxcIn=o|;a;iy;c^`Av+$|e7g17xP^on{x#N_q-?#Fq{ zw7xTb+dqj8TW4&oK48e=%v%rr?H|M@1+lnfTQ8+kLawy%g$;E+SZ-b6uyPM8Z)Soh zzbUZ}x-_H~@RF_Y`g`R$(k*j!R+BUNX~}(Qxw$u6L`d=)!Y>K@0w5ia$5f|CgIole zRieujHW-un=AYdQRn~jTpHz2~cVQqlJnjQS!Q5PO#=1}(mrDT`BJ+f8n3{2Sot_cw z?CA)jXr{5s%V|XB{u6k)+M`(EIF??Hyko!$T zoMH}#vUOWq`;V&K>of`Immrduba#7Qzye|#G;vz}R=3IrFH75t887^H76<#xClorq z>t1)@{}7|EH#vLZ6suIyqsQvT5^=dIWRq8z zElyfC%9LX(Gc{@WkD=S7k^lnp2|A{YL|T3;KqQHZcFkk-Zgs&bn)zx$8VpX*eV%Us z1)-t5>lj;f8mBHDl3QF-v|e&=G|r$eE1nLLCG;Rq3Nr^Zi-V$9RkccTH9{Dn`-a^*&qI@JD@s@(V`lyU>JE{mSQ_}u6cx&V< zxl$Yg<3MPRyoP4q@y2Bbe0{TL+1wCZudDUw`gc|lhu=J*7~>|~EUl^ggiQSv+1LD2 zPF0VnOdGo!A2~yFQ`KP3GIDlt^;^kt1o@_INn=6w?KPJ6(uNF@^I&pyLPlF;Uo9*zmeBFr~?n#Nq)cYRSHzCRN{{f zD%Uzu8HFRO#bV!;>UuuTS!Z?O+p)&{iX69z(YIvl5~CcZwz=0`A#66EBN)c63WgDe zLyA7BK3&GPF4?HFV+w)r?dNAmUr|?%*V*&$;k-m}t6iytITbg!hh@Qm<-O&wr$9#` zZ3NN04^neD0(||7Yz<0WNt9Grxp|N1j!S^R4{($b!(F|*850nnHIi5BrHKXdaKhHv z!X@^gAuQiuo;lM#dcH=Uz*X*LUCE!f+j#Ex=f04=FMW0n%(f_g?eg14w4731)sccd zyi-_kf6@4k&GcbQ6*&-*5UVDy3+R~V#xy|TKNc6io($$7)Ru#5jULiZ=q%nUlxkh` zN7eOD#t>rqD^(Utc4JaDROd^6>E@u$m{fVnYusJ3)DXgm83NGR0)=(hmJc{AM=f_) zZ&);aIX##RXK`#MU5oo*e`!m!B1~p3`fe(mHI_C^hwL*7KdEYqqc1tU1s4R5Fz*MB z$&;LN-iOuy98X?MZ>@HY*!ZF3iH=DwnMJp4WPMjzCgP8*ljh*+mOmbuw6*NgYTlnLl4~MrB$w3m6(?{1UC|dFD%+yIndWJWJgZ8M*K=YLFy_K zQdC?N!2lZHrG~^Myq+MB39d_HAS`9@QS(+l? zrwbr`ppdN#%X6jTQW;Z~_1i6;yrdt6u2?J#Dr1x=UZph)NlOQ5ZRg7&Ydtxnu!6 zky>-x>foM_CjsTf)hVB8FvpxA2-K(g5;8BL(tKq718>-U#3`Xn;aM9);U8qDp z>?x0?$<#b&m7FgrKLc#WY$GN}jl$Y2^CBv5g(s}PT3ud*tK1e}W7_b60`o>?HZ;W7 zy=u5UZP;Sk*vJMJ=QA3Xf0Uy~0Uu$k+&t!sgIeH1aI6qzPf57*R9zOE{V~~R>VcdW zgK?&c(ThcU=o&Pn!*iPAqgrTJmZjaj{jF?_vVK`YEb7bJ19SL5Gnv?huDEa(ebZD? zM^LjT7H)O$U=_nKs0gC7mCGVB_j|y4}-&&kRx*!oxHK=DBTkq9ZS?kt#xzCnZfHv{Ft&Z|gj; zU5>b{%s-6J1+|1>K}M>U3H9N4mm`kkjhK#DvyRQa9b1w*w)UXiU$4(7P(JiS_4;>9 z3ac!Y4x;s;L_V^97SyDIpJs!v=4y89!OFv-nyc#~XowJ-zRqn(R9bjpWmJskCr7+x~59X0Hr!kdxd_8 z?hNRs+*m7daO~?!Xa(Fxz;nA4drA2tc5tlF#xB(*a|`nM5F$akqNv!d^}a&|s`Z>L zNtVYNb}54P3h8^G?-PelV}MPs3_^jdqpbsNYn)H%0jNih>XU-lNjoG5TzsI7cUbW+5IEM6hh8`?3uwwk{V8^< zhXajm!h61|-<(uQIL{~=;sxcz^yWrqoYkpFM|B1UF}zua3aU=J4HJOT_0YxphIL6@ z-9@-16*XDXdPN@$6e#vWutv_A8VJ5p7w{7bKe2>I?wz>abt=*9+-ARXTawRheG_u! z&gSz$Py?(*7}^L?j`YJ-*T$aqf3Z2mM*EJW@qKLLIyYF2fojw*w=cVbi$|PnFQOG| zi805pykC~T6E*vl50T^HvOXq)#IA9E+ldCh&9DnB-A-VcQls}kuaI#;`Alu2#)jrM z$Kn?H|A;lNG!k{Iz)x*p7|y`*sDsjiea9Zi7I9Iq`r>m)b$!(U@%BX?!|te6@&~ zpD+avVIH5sX;CCHFbU1^Qwi>hB;QOE^sM&fQu;N9EJ zgZ-}+FoDhqBx7%I2;1LByt369eRSLSmu=U_sPH(%Wd(Y%>BpWMH22=>hMg<$3e_;y zb=lpyno7XVm+O(tWrPo|pX8SP?$oVXMvGk~xPs{!gR55<0urQg0l*}r3;a2X#^Hn{ z^J!whw91ZYwX$jT`Ag0{tRY08KcpJFMON>$PGfq`3VPEN93WK)W2#e_a9O#kGW*W; zEks=aV8$q$xm`bZ^rjsQR`O6#_FJc!jg5~FVTuultqHrYHz!C=e-a^M%;&3mAwL%T zURo@&p$rG@0Th^sOA8@L3+UcRd%gg*^N%7`WB!xGt76sI#BF}+5ZuW^0dl&$0t~-* zWVC=e+9*LjO-JnUGMm~ycvb6;_z>Dl;jSwx{9p{>rwk#2>C`Hh!|Bntd1z<&2sR&XmeHL5fS#`4 zzgW+IgPy?u;QG&SXTGzobLl@i(1QQP*L!$1wZ3b+b0#xkCbS8mh2{)IIv9Et6PkdC zK|ldfLbae6ih_!oLJ8GSML`Wk1#AHuSVNN{Dj+EK02b^)T`p{_leK^Q`^G+djC1lA zWMs^d`99Bk-PgT=ZM?jyw(iK$W1@QAQZmwTvLS%Hj_mEE7*lcIeS#wQ*$2L%C$*Td&|eSlr~i#A3gphI}EMF@Q4GhGaT zNXvRcI**+TV|boOrJlc7s1U>ToIk54NM2c8v`_|p7{kqjsP6W7`MnRP2=r3U!f=R%i-ai2L7Aw81J(|Sxp(Q! z527ObJJ8=6dhVn0(+o#ASlrs2g%V?*5$xEUgn|`yyiLl#?RMc19!n2unhdt>>egB z`45g_?B);VFDE56Pvt$(?3&6)^US6N)ap&s1!gCjrwgqv%}y85Zkf##JAB_Mv3vn@ z)|KQZB9a3eGfXRNuFZEh=8>uvdU}>&Cw5Ye{sIACKE3Pf-O^P_uB2U2Ms~`o;ZheE zj$n&(*FWb#9RKxErr!IMKd=iCJ9<4&?+nMnFf> z6hw9q=HQhlGt4M>X5;`bj)OjSOdH+NvZEla{3L3Z75?t{QtDZ?*hkyq=-Mn7=pLi>pMT&#Co7}>n~R=tMnLNN;Z9vol7b50jd@>~!S zG5D~q*xqUoBiwp#0=2CH;-dI{Cox|U#-8M-%+kB=$I|l9!C(U-&U2p5xOhbQ%SNgf z9n3|j%ez5>pF_uGSs?kf*ZY}wu^xJ38N8DV- zvz^DhoGs>fxyD-9tG;UE#YGqgvjfM}JE>_P>T?rRmG-_mG}HdWl=Z>D#nj8^miMEw zVM&)t8Nmb4U!76kGu?8m+~@Y)^~yX|4El_4gvq3@lF?SKB7+<5NK_otbk z|NOlmJ=ouSNAU~h2twaHbKc|T9=8jMOphahK-#-+AHOVlukA8^)}^!wE*?7Q=~03wGT z@*&BYFY7uoxseeliB%bxWED2y07<~K5^qdnC2VGUK6?feiu7uf!-d+q)8UaKO=EfQ z%D&#NB};Zojs7L|sGluOnjU@_n$tE|(_N5*@Sv3(XCG>i`fnkYJe*}@ZN~%c1epF! zV{|TeYS(kKc(ZJYqK0`y`(8!&{=h9-bUN;dFWMPRefktT@i2b2kF+hRRUlsYY0%o6RxU z)LvJNAeibF9&lP}5Bql~)V!6WC|yM^p?q*GQmC0>tT@blW7^~*FsxGtYTR?|k3_cp zL@LpB5w(&I5uP@iS4NI&mWSbZWj^Cblv)n)d#0Il!pGwpzB#J1X`@^jU0IU`qS!p3 z+;Nq+QSK&%pwuz11a6sIH@Rv{l+X$eiBa`cVG^bmYJSqV3cl98`>LC44&Kn%Ri=Zv zUCkNXV&;P+8cY}}7l_^lo%B=!7;6X&43>#zy2rnB-YK+j_HkrwLCNMPujqRD1Sqds z4{57tTr~6mRyzEUfYmMMz9nLtkS|?IbV(#4h($vDd2}Uux9>csf@t6qmEQMY{Pn2= zVDg#djmZW!H6qT1J7-cdZ$Ekd^ZOnZWg(ZM?c4he>a% zc5#V1vw`>KaqG#6u|}-CygxA~{~E?&Xvbw_P-#$MgQFmID}`7P4#7bq z_leMiuE)F*;b_;`#gP&M5S>HPkZf3BSj}F~lTO;DGMfTA7-1f5|FCh@ug6aozIU7~c*|&O`~2~8G>g_HR*vWR ztN}iK_r}Q20o=&UxU=H7j14+3|MnH4K)`$m&|9Kt@^Vo5)IoxJ1IOkr|6J433{O*$ zYAqY){wYG&)S7og`SrBlay^i?KML4Tvq&%}BZ(gQeFhI)Cdihnt&0bg8bhAjY02$w z`WzgYxwU|~2ouYFC4rRaPEFdxXquV_ExQigvHI_z#QMxCn)AdI-na|vr=@au!55B0 z$QEd7vDEnKa^=TJG{D(^Lesk*m7mIZ6A)i4}eK)gC2 zD=)|&7B7ZFXo*QKaNwq`CKBqU@H})p6_DajYZ3djas4M(rpUz`YylR;c}g`R(zV9= z(R>6q^9Aqs+HVU7`=s5PTeAo57F3{1&-$->=Uj9tt7wv{6XO`#F*%To%Xy;{gRN;d)XWrdu10qYG*|o(m@Qpp&A4`LSiTdHHon{&0?5 zV}W~}3H!?2*NQikF~MD3#Jls#RL+&yFgMZK;mwaXY*r3E|oN` zRCRj!FTGHeFFh!b0B>`3%yA3AfyU}a1`Ly{_((>k4@IVKkXS2H-mqSYtfFEGnlT#a2 zpqL~o$p_`#8<=}NfG&sRjv{wl;V>4(fu1%u8@x`8`)j@^zaCTmh_JNf$b*bbsq4{~ zkw;(eIvR=DgN_x_{4g#;Xc2H2i1N_?dzMcdSCJQE$GqwSPU7cC!ZJ9OEJg#fI|w3e}$zzl45b=8}@Y& zaT%@Z$8-!#hx}kpZes9KdNoe1Aa66g^egK+cXyJoOhmUs+4UzS zM@cjF_2}^i1kkyn<;9L#mIPZ}!rEMFs2XWlLey|7ToR_6Ij%;G$Sutu1(T$B^WKEy zkoql>6M5iq_4E@*5mKKvF;a{xvpr$gmK4eIPm7WhqD-MT0p4QJ%R2Hy(-syrVK7Ak zBzp^r)nqL`BEyquSW#v(t_x>cDGX(ER56EoT}hJ z>qdax1S_x3mXkt%hqPo}BOplVNDA2gY^T$X9_)73$;BOwR^6hbVyrhyeIb$!DA4?Q z?CRVIgD2fCktD@#H{sBp29fxJA& zkrpDtOo2^>w519w2;4F6<2!Up{q+H%kedlybRjeq7Q7&)ZZ#n)%OaVg=1eD8N6{)y zLiS>x-TwnLA=H&i%#X$yC|#^+;K++~YU^k^9_($`1L2j<=icWV2ayvRjK$eJz=M(F zpa58}BedCBN_WF+t~OPu;l2@+D!!e|MULsNaK^|MF50mJ@xVH&1iM_(>i3%@Z}NeZ zJ;WxyRr(5jhz8b60C`*EcQOGZ#RN5AqM3WWf8l*3m&>IXdlrT&yHt+i15h<_97nAO zCt52iy?vz&u$lIA<$|%eie$#xkXsa28_#a?g-wz`_i}sE8e`cCGLt@!)_85 zA9R(luJF|O3`P^d`EV{((m|$Ns4#SWw)V!mt2e4f_B`%L1;1a*J<8b0gvfW?jVW1*kvjdKc$`B;SyZR(L;c*#2K=|?^};@xbb z(nug7#(mKMWk&|dQq_C0|42vi0@6(kJ8$!w8Y~M0*pSBQuAs3kMef*>P52L2x`oDw zK1VOzg%-kteBKj4DSo>Q99T|R|E7CYHgz>i1EBXEV{M4q18*@p{i2gseFcsi!EW_+ z#?!BNHsCYr@iDdFnKB$WMEE38B}N-L)mAXqr81>!mFPl|q?<>B^69PUh`MSIR+A=Q zTwm<%?%okZy0tO8WPEQeVrYCDm;IZt?}L55tnaQ76sgpmCm@!5Fw&wQsp}+|h*wFu z#6v;Mx;jhSmUeBOp_8;B>olB$)FDiaPyev$+2oNN8djk@=5#T!=PR%#U1B3CLX7bs z6Rfo))GtOB?&}jr1^BrWi-Un{%b3@wMnxa=?oNB$eHnfCb@pA`@{WhH!6OK`=Gw~1 zlPm3JBolJ_@h2gjMa~gnE*0GTFbwbVh{i~5Us`6Fc@cMww$(9jjvG6ulkYra0smwV ztv*i62!}zxd*tpB0q5lNucn#V%0y+w$1>IH*&9Defa%QuBk8K%^k})<#5;o3kc>Xi zFlUbePIvTPar#cu+9Q)-m5OwW?!7NpWGu_o?*~D}qCK=T2Pg)Fd%*Qv*-rP(Mu)$Q z7md(0E>j+#+`EK#pWS}nxI|f7nP?%6)%68;7-3UnU8HI2sJ-JpYn`G$7GYfwwi)qd z@&f!W{RW{OcT6q2L5k_`g8I^n;P1*CUA47M0MZ?Jr=R@hYh<(tt$A;3x)iqi19k}q zZ!XT8^?2O0{=apg@}Bq`qPxbt>m9XsZ|I2MI1sQCn0wNQmCy7Z=?z4l9}ZbbKB$aS zrknqum=>cBx9c2Z_&9bs_U~dNs)R^pKgtW?o2?^6u-AO@jd<$Tbnb&@l636Ep_+19 z?+YUsBb>B~!!HKa$jCEs7vLk_g)D{Tg~8|0)*=Zw_*?nW<1O_QF{42R)E7SQE*VH(=8)+H+`XCQrDPCBk^oSP$x@udXYdt!C{K@G45pd!U&G?gYO^VUk zGmmX68m}$irFc{c{4?9)5GzU9+*EjZMV=BY)+C~y4Od{_okFg`xFoIL+( z#{a#Plq7V#>_*Z+ZS-Ytza6@Kj9&215sK;8TN&=~rKczU$sy9_4+I$KseC-(5DP31 zRgC~1YQM+pT_$``A+Eo!rDF#3TFb58mg^dM7| z;XW-ZY{{YqewDP6*+OAfzONev2XAo^^rcwsxtRF|O`*RV_TFCjMSu08)P3;Qx7F;H z*3gdDO>KU)XGjY^q9eO~~i-R+6n^|d9Q0!&B_ZUT{3xphnM+pk|4^eLA1Py&7*l=zwK+MV`%IzKq zp6xNhkAVxj5axp z;?#;{wdlvmG0le`3}4Ci?b=I5 z>cdGikDL5#oqgTCka)}C2bTRcBkZlW&&%{#f}T13+M%$9oq3MwzpXlPC9WRZ%;LAM zY_=FUb0+{?48IP1v?IiP#$@)=hKN7bI{J%RVvWppuG)U4^9B6R9R=-mAz9g^IDiBC zFIX|qu;A5)&}so<=L@qWc}021v}Eqk1!1=?9^gPc=WVTYVN*h~P%)5^1xDBpPNT&F zmn(Z*2WC(q-S;m`3;)K8WD5Wq@LH93=$OA|F3E>$YHT-K9=xT$v~}(N1Faad`g=K^ z=MVa68DJHZ>ui68WzSAc^SibiG|&_EZsQ>JEo*Fck1b9;xTG>0w4^S!kyH5o8MNCV zSe?YNT`>5l>u-2ZN(t|*^fQ1ZrpzaR~0Ps|*E&8;`X!~1+sm*fygHU|&Zp0hRtAc`0h)+|2W9pDvW z6Iw%9f#=6>S@>xm!oX{u?jw-!EzlbckNvt3o7k zbg%wRukPjb_lDJKtcBYpP-iOJFNYsy>z`aFp!l1)76i$1UdR|MkeyUyDcIwJb@kw6a#%aqr-ilD`-?c z7V4}dbBt`^;BsFldD-eXqzI?saxU$qi;9tiksezhN!%D@BIwV_6~kbzQdyi`LfN+9 zid;g74?$4}p@Cf0E<>*z?x`Adjkj+GxEzdUa@SSw@>ELgRbLg9+NTv$oO(-l`*3Q% z;eI9C2=u^jnwE0iZ=0fF26L+0SZB3X>BIm$s_D~EZ*3Um#lwCN?{CiSmJdrx@r zTT;otmGXMtq{yU^K4?%^EOD^ZS!^1^{(BOiV-<2G;cLU$il5Ndj71VS%3pc$(FyJ}e81LyMeIgrB z)XzG)t6i2yr83gW#flrgVI1mlC{UVKr&|5;IOdbLJU;Z~huJ9Th){OTNx2jLdEOFX z>z;3Psl!NqUrr^E3Qwm<=9gJ^S0#oUZ(I1ej&O4|6w;H7G zr=YAk@?lRG0R-Fv?5NkKl>J3(Ori_03vnHsyxJP>NX`SH;qPRUe(&-ftCLDpWHgrz zsKmOh*$rZMWgoEBx1|Hu*49DQFU($An2!!`9AF*lc*{Foy@|JdTYYj)^N49nzm}sE z0A0`%jfcan>*ZE$JR7xG&Nj*e0}&N-@I*+4lM8WEjYd|0g{uck{YYge(!ow5eyL7s8w zzz|sgVm@T!G$0_Ct#Pj??0SwZvqRNYUECV|(Zb<*MZmej9j6nlPetAcK?%4)P#B;3Kz~L6x!8wcfdCuA8 zh87&3^QYlFURe|Di{jOS>Uoa|m{!2w+RAWxZA=)PX4AU?mDHFX-Wq`dxYkLanlB-oDjbv<>KAh~k4++dB)w$0q% z1jBDE9`Cfzem!J3u=23+0@dhvJ_&Fo#pCyYM#iOX#tR-8Ml{-)0HZbMPT4%LL7=>$Fh8`7PX{@raUKQ^8Vn{R*nGsv|cU zV4Y=v7UIasS>48nLPKxRleM7xXOm+PtJu4@u!ttiV?#?&cv?r-05K^<@UkQ=L5J@M zY`4T;$qgZIIhkwlwrmlhoMK*X98kVEK;MUzYO>idPFSMJhk9LhV%lKsO|~ZKcCI6( zgY{a32Kpbh0g0N z!@ZZ_tQoKx4PHqngtDyxQ~`@5b1A*whm@G)cHCaoQ+!ar5wAA7iDh1W z6U5x(=H{}&wIiGg8qh>eqMPmu!Qm`Js^S0~DBS9O0c(%oJ|B1Giz@p-Fd2(^!3Vdo zu+@^~t4DBdqVm5sAN#xD*pHTDzXp#rg7};V$3Qpu%2?Ln@X|#UxNsp9&M8g7>qGCt z10o4hteP+=GdLx$gc*hbDk?{DJ~Nb@OSSI?ifs;KZ))9BoLt(!{Lx-pJBrjvRhB z)0hO}!=+ViZMYK*49mqfuoYg!+;7Z>0ysDqnT-t{+RiE}M&mQqX8JOqNF6D84mBS?yib1y@2jh8BcJ5BCp|HEtIHUz<38~mycPhY z%OJU*f2M&i9~OgXJ27b59IZ~&hV>RXDzE`%#?C1e$eTo9p}ZlS6fQB8?(jXz#&Ood zk*+Q=yF`y=r;l`D$zttAw8nG7{T^Z@oGb7^7gi2_$KTzU0|1aZy;4l83?DsvBo;p= z1NTR{qEftta6ev%Lm&+$AIzt2l7|H9cRVK_u82%1V;4MYp~_$a%hqyP%yvo&;# z5(R2^gZtAA{29b72zb%r#|ZQxv2n{s@^eIHy+Rf$4o*rHAL&|E5$N`WMo>bH&i_z$ zwp8(Gqn!C^dz6j?YmE8y_FK*&oeXf1I?hs;aH6p#4~_pgjaRA-*Ji*0s0x#FLf2kt z8QN~rZ`DiVeiL3u>H@Shfnyd#EEJ;j5Y98Yc%MdnN}~#X;Wu(RuKzqW`DHJ_T=MtW z=@R*@{jmMRVLkcw_1D6GtzY$U7z_)D9?7*sv6s9+45!JTd$D2YJoV7YQ>|C8-oASM z{neXS*DRHuOGu2$K~z%YyG@Qwkh}7EJ-w>|c0KFX9F4~lV)5h61{HehCUmIfyWVov z*)=}RYhSwFJKvFm#3$L_Xc)yAy|<0{VOYIm--agqQW};eb-k8F_!+Bp(OuVx9p9vO zs?Vq*Y0C8LDc@+BK02cNAd9g1w%U6|-DMo`Y=}6VOC{4;x+6gL>hPoYC45eMzU<)E zshjnbz2{Q9{8J@yz9}V*24(}rTPaKI3%%LD343b(3WR?7GIcp_g^qVslok;UD(ftEd}} z;2qi>*IcnZs|eh;BOsD9&qM{jbC);tGP8RIL}gJ_$%!{}LfsVvvkR4vr3v2gaF7su z^1aiw^6K+=Aj|xEpDtT@&e0AT>X+hE7TeW_1kl5nfCzKb3L%8Shl{+;uTM*q_(nuR-9zRn_V$M;?HA z_cUDbYRM|>y%M0FJ{7GgywlGDTr29rV-EoI!75pg|LD+hD%M?+1|#@qL3T-U_v*;? z35w!0GF~|n6|Tn5#^9g!t3{&QpZ+z2nNV z;j;|Gq}2S(i%;VxHr?Uv%m=!D(V$0{prt{o$DWau#4kdWQ!xGjG8T6FM-+s{foE$A5`>z+Cb%~sGJb}pEl5c zRiJXnRSvC|LQpVNTv{9y93)3Y{{=?7|2Hiv_kI3fPV|2|LFJsNTnqXiC+Pn_Df+)4 zQBOn9|3IRYXkXmFkf_<}BlQi9IiVn>sihUr19EzzoFV3|2$^#(v;p3*5X3F6wQ@J27q<^|yfeI)^Oe6dlA&-O#qdql8 zMDe0?gG1z7FZL@`y$3zD)z-gi4BD4Vmos}dr;&c_WzNd&I!8E z2Q&zFSw-2sdj5E~qt&&QHtUlq<=wa&oA|&3zu?=`A`fV*GaLVkbeubL^W3m@KquN9 zSS7nc6#Z<7)(e?@?10k6cyv9B;2oH6aCUFkZelp<*I2S7)VPuYwoF;w-7Jc z#>-Ca=4+kJi=iy{=k_XjY;#!wgF%#FA0teDRAGfg%2h}f{|kve$P%bHy>6Z<_4qzJ zbAXOFe<}3Q+WfN2-(;cXWqFX(+m{vPS<)j;AR~Z4w4zgBbt{o*C7_v8;2Ze3jsa;p zWVymiZUFI#rN`=LysKstOyc#of{0IIPECCv4-mvoJ28Dwd5j*xtjg`b{JM%>j}MBtBvmHf}3u$*IgxKXjl_Cs%&2<&wa1x>e7EHb&Q*JGHyi zQz(YCm;57j9|8s85f|Nz&(Ifu_uvM9mw2Z%sOvqN)T^eTm>MAr)a7fbcdPorK#bWf zm1*rGLqj?(!r`$RWo7^9b^cdsgSa8Zxip|hL!%^)t6b20>u~bNcAf3Q&%wWHDf6q1 zBH*O3nZqr)yw;>=wJ_)lmdfL46@`n+Vz0rW1RF4ZR3z9elm z;Nm&{sRBFX6XH0j2f(5i)05kNITju0PFV-CsL7LorZ=5@x5MY>aeQ)p>RCOrPuYlhDR2VAOE2CToHcH0gEAoCg_g%mPvJ%<#XU55k`AJ zf_IZ~kzx^K>d#nIAB#`*r@y{1m&@r~$+l0!B6JsGhjknrJ=>kKPl)}t{*D5krm1n1 zqcSZl!FtB45gyn=0~Y}>bbf*wGyoe)xBAAAyrQ63j_&hqDUKN464`QC1pw{J(P^U& z7F2+?CD0^1?Gtn>#t1iWT1!3M?;4$>r70&WsIx_c``jhd zlLAN-n4Y2kBs%GDWWzuzQc$d>aO+^-%K1i2LBU}lVPOR09CX&mM&!*H*KsmS;V z)W!S4OBfnbM)JTBqnFNv{igx2HK<0bfsF~|rGY7_>p-V0ZfG^LBhd%e`do1>8F=b%K~T&g~6t(7Ds>=R7o8 zy8Bxrs@&pV#RFbm#AO?=d~3DO_Ij-_^eKtSDgeYj*eg)8SfUbP8q`rt8@;Vi6aVq!@nUPR$CY~iO$$E>03!0j2@&dq+ zWJb0WGM3*;#PB6g?~+T^D(P_R$SIUoP`7GcH4Wi7h&HKf3m@$|jbGP`qY@jgKh}2I6B3yKlmGy>%MTeTnyfi%@;hAECK51Sd9RFkSfR@ zZ>=OvT-4ne6Md#A(rEuSc`Ns)P-oHQ2jm}vCu8aB zNJgl7ug;L>ZwxZ|n&~_LIg`(}s8;M^R%FK#7vH_3Do-RoB6i>qq(|3C$&Zo48YpUAhi4RgZfD5@WL*{d&CEfwi4P=|Edsh zf)3a2oQ<++R2mHl+_S`B_OUwVVlsP&5qkd3aWEM9%NJ5{=*l%;oG`IAo@2iQ;yWzN z+gy{+fac1!Zo7+hH!DSW1C1kzK1x%7hmfIWWuWrMMbfoAct@!VEq8EG3fE&g*>{Fw(IEr8OGceY2uq9n=3%MyiPSx=;n3yEo0^pu%{)!(z#lTPo< z80YyHb@w}~C2xOMVraO);<kv^io(d_pUp} z*|^Yvd~hB9HDAVnE+mE@Z(=C8MRYZstKNb~{#w4)54vG*)3AhnSS?&)X>jR%h2{l- zbpx-5>?C1Q|M7oQM7tW9ZAh*=5Wep5P|GSQ3j*5alHW!1)zv>XW~MIuLbBHqpUh!0 z7-EKlVFXt_$osOxz~SX{g;&s{A1k^pAD00-oNA+)RN?)ViU&2vu8w# z^$Z{bm()`6dV-C0U#+}n(oyxTL#9;#lp;0 zaj@nHy~aZPfn9vW@YicnAPee_gR=4rtJG}e-1cuNcC9l}mT%}40;mnZnxWh)0Q6o0 z;(UoDDISO54tNt0beW}e&r~WH3joF=_#h*^mMIZja5Ao8z@8}9{X9}3M4`FNCjb=1 z+Te+B%B1){jl*de0KvbXpsJWD>cIMEWY|QZYX#mycAjtYI+v@i9M=J7tj@~^K>d0sMca@t zKxI+|g-HH&MxaGLyt9!#i~8(uhPnPkYy?L^$Iy(016a5%4b&7=O-Y_0*Qa^ z%MleeN#d7JV2b_W5D^!kfvbIpo6%I5wr@BU7bbV>iDOn6;m_DAiUrzV)*9u@Jl$wG z{y}`O4C|C`fA5X)#b&wvx3VPS^}gpirPF2!xBH@{E~T?IrNf{}tU5o@*ej%iKoh4l z(05HuajsAZN)kxEKRKdfXgw0I*^WP$1(RkhZyhXzGJ=<0AmUo!82W)JTV4eRXRn5f zsfPXNI&1`Zvq{;TzJe+{P%aae_|vZna#~sC0wmSE-MtD)>vvG$({Rn3lr5$CrE0iO z5#{YD7G9ly+kUxv;T{hEHth?5Su)PbgH&fB4k=`o+FZu~q z1+X~-^S#;0r?b3WgbOv*4H4mre6>|%WEWITF;vfFF(G$!|6?hBGYtxnfP_dwY$tqM zXTkBb{Cl$nwIi7C57S2_fQ_H!g)cUto7b&tMsis3I7*x+T_dKGz~5DVsUpbNTv181 zn*j26RBCD&!*l9s6m7!VLsiqL7jLAh1v#9kOPO^t5)3QSjJVw`I7zI@{TWbJ17C_LK?NCni#A()uS`Mng-5z?;Z|GT(!{1nPp&d1dEap zz$(hgG>}L^jH9H`Kb?fYk@}=I3S!jE7okzr=K8^ zF&p2J!U`MNKTq&D4f!;j`XfD0F@^+qee65gwU%e3-kdOVV%=icl5@OR0)kTA{fCho z@xHmT=2}1@rCM$A6^b1Kd^K%Kz=Ec%dQ;AkN*cs=0%1{&mVf?LZA0P3M7lrx9G@cm z={iy%GSaLcxN>^<@#(uiPXmv)jyxtP0aa(CoEBajI@L;B#4Kk!H53*9B@&exc}juK zoz9+2e8FQvHEwZUAi-s1x$>M*6LWD&OTN(<=JRgH6#A(nXzC{mm7ZxuHhQ+kKTj?- zjs23*AX9>Apr$ydN?iXl9>U*-lK}--)Yc;RZkCtnZG_zr(q;)RK}fU|8nA)lGUnpV zlJ>^Mibf_#ZU8Lrm`4H3`aq}k7x2llmO`5P7HwkJYPGUvjWwBYp>0LE6mKX!S1HAZ z2#e=iiAkA6Ff_}Ca>d*@(ek?3WCX;txywrr^huD}!u6biLg31-5{d<>)tAr3hbu+z% zg{4n8bX3sP)vpq?(@&G@*ET~~TU+94N7xP(m5Yi#rZ3;<2HG+4*5ZyL7A2Vm?Ym9z z6FZ(xuJ&VbTBMz=9GqK^z4M{n{0PW}1?h3H^sCw~64fXPlu4#u)!S|#dzE37oq2!n zeckObBbzj}Z@k`fLk@|S^7b0{fw6YkRcuVnRcg32cDR18Wavhr@ceHIb_1=Gc!+2S zT%Q-x!DypRGc= zcv3`jp<(Cuq3izkW=fLIa!z;4xGEsIAmPfZ!n^X(6LN^t^p}75SjFLWcxVb5t%V=D z5#s1-DkElx{GDjot)CUJi71wK3NG%~bTYzxwiOtJ>l2d2 zJsPHBj9E6fwAk=#+hD;15>KDlR#06fJ+Cjs)5W)tY)@97D{BR@<}@+qsb0LudVM)D z-BnTb(I&WW!1VOc@J^R~4!3d&wzeR*hr4=)*Ial&9n6))`vnqAg&N6d&qDYL;_nJv zJ(hFa&q-dP*S&&h>W54P5rZT+S9-duI%p+2-5|sHO2Gr})Mw2%zD3{ro_%k=?%vO> zo{^`O%viKj)t2tjKPh_~8R|!!)j!gc$fM8eb3VzzVgUItE9h0C>Y`m=gBNznyZ9uRX(ML3>Q0??}d|PSUVK&y0n2O z9b*`cH%YCO$I#_Phh~|#a=+fsk>QHeG36&=t7jHIC5F)}?&n22O-+yUnL43I;P7X9 zzb@~eW=}M*#>LaPfHQFBZ~wCnPTR{Ss%YUo_X+VI%{D3PZx$__YS=m!f4=>7&JfaR z76Y_bA&{jGe#6r-U!MB31RzPFqKgq~cO0U`t(xrndE)zQn$q?ourmjf%ECWQSZuKV zv3J^|Ur!&O{qtCC@T7g|lj|XXM0kxcwl`q!qksd zjq>gO$gyR1@|=Wqn>s;>T~xedYY=P5&?coTAo|$o*b+pS->iy%wvs272%ym=30QgHedWS{L6-S zUcMyczC(lN5IPLDsr0KE=p)O5zPO!DxUAQ{;_ia=@Ub4SOY}S+P{_DLIEsr>^;Epq zh|})^O|}|8u}*qA|5U*0UFoI2#iPu>W~5-mg0{TOb1|r zZD*pioS@ymjC-dh$f=Q0^vOFS$XYT}E5@uj3qS5#{~Y(KUA%N@B|goT`WbUGS7LJk z3gaP<-P15|1^!Wy;f{jh`a0Iy#)DOdD+npGL_)2 z{M}V7!g0JY-eT_?Jy0SY?Y%)=kbWeVmO9vfym#%$>SvdqKD_bq>3?;`KNcVO<035` zbH7(ta-(#SsT7yE^0?L^y&olp%X}`ipk4@@EnHs*I)FA-iuVW>e~ucPvLIrx@lF!g z&NU^x^LU(WZx`9{;Tao0Q`gy8;?%jOz;ag!XAK}>LSxrP^SLnv2qIp}e?mBT9 zokFF(R61|Wvb(vn#klB-z%)5l^`4!AVbV+}O$T?`q zw_;gf#lx=?l~JDG_x~mvW_;l;dh~6#_ua-JYV7)Nwytpfu+i=DATS1Ac_k5%+P@=A z4%b)CDK~4_K`a|%pCt>rt&?@!>2GA)0LJn=g~G2JBH`<2`$zVYd?<6CA%Mm`P=!6` zuKvBcUVJSY{%XG1v7D)>d9)tEP}pJn8E_muHlSF=lD6&mS>=E3LYrfZmx(|H5g4iR zKRV+NsHCtOtEAX4^si;pp;Q#FN&h67TN9`TXbltI+Puo=cczP>?Fe?!b;7IYuENq9 zP1;B6NHF8ZBM+lIk`lU9{PXSvVRRMzPlj_%GO!5%$U@*yv5KY$cXB^$D#8UnG?tGF zH2;W*0Y{xQ*1+T}%$YZHebgLIFZkC0`ly90-jy)pN)8y>obed89SEFHqyp#y>)Y|& zmab~kmy84i1xZ_K3t{FZbbnLf3fHde)>P?BN!VQWpU%NlE$Z6L>&4Gp%B=31xeHSE ztuS(ONjUW*z1>yKQRmfGog2YfFOIzhcnlbif#B9qypvQ#D-GNGfUpQqYyyQz0`Ju~ z@O?ehJOxwJT>no`W>t?jC8~rKuBdrSs3$9jM8zXs>z6qLSy!HptI^?=9)isS32DsL zUcZ5Nzjl=~S2Pc^;>wL6j?muGxjFP%+`4YIM!kFuOz|MAiV)=n@9)xS6ZsLiU{NW^c|Y7^IOt z)}T+(k4|Gx*{5xMb%pqyx9F~!{x3+B9kd7MZg_X_&TQ~beGpV)j=bl_AN;OgkXj* zZQu@9(tRL)4FmN4lWnVk^c`94$6%wZl@veb_=9w$_+o(mj`3K!X)?-=RqOy5W$L2! zCn1tT7K+`0KWyBkpL?Mm<8>%isAtmx(3mVhL-bfUFq%)$)M;jc=6;@}${jAVp#WLx zD&n)&&_O^i4WRcp|M^Xaw;%oOn^0TzQv0d4>4Nkm!C<*QqaSlrXYkmeq-(J!OqA*z z1K=1YB>!CL?c0iOQBa^|KVs&pstr)P8MKyNLzQ_hZJXFZtG)6uSTkCnsow+XBH(x$ zre}GLPZwA9|EcJ_ACg?(KmI)M01rxtGY1m5XW~lKObAzshLve*hGmv%9bBnp9aLPo za8#z&!PL^ML`zMrzTn8wkUqI>;Ho@k(XP)a&xh|HaQ}4O_Ye1Vy{^~$_9x>U^uar& z(?ytkG9PjX2Xn6Qg=s}s`RVYB#_~L_7t!9RHvbHyInUGtd?K@;!%1aNO#;OPi(S5a z8LDRThTJTalgGyB`e-P#bu{9|O%=s-F+J%?fL)*FCU)&M&Q83-vbDZ&dE41CF3<=4 z{xrTZLMq{8dSzx%)Pe2N+3g_n6vcAmrTl;*!2|_F; zRy*=2#RmfEdKaSY_yFkDYG)WAq7|rb|6R`n!sTK}Iz23loy*x!oH~ET=1J;8u{%C( zv21%l+S0jK+Nj#|f2`5ebyMd&Tc)QI1KURS=hAy>s+kVz_;;%-f%6*dj0gPNLI$e4 zC(%#$e0^=Vg;&k#z4D6mx&9hXb5u@h4Au6W7ONuS&idDR#x4{c1Q+qOz6RA}@yYS! zC$Ib2-?LVYd_wOax#^eg$&2G!Jj1UxUU4>$4Nv{Tuw#9!GbaRS#?W%quXn8Ff70(q zSmiN^m+LPs_$+ZP#ol9;jAE}i8>>#5-`bZ3Bc2&UpI)hLuQ3H{AQsbQr84rF-L&Z! z2m>{W6z%jj|5l@yCPl!2ugIv0mHn8%cVsJp@>0W_S=q0!ywx0m4RV;R=`@^AdAok= zb~zr{@LU~en<~*9npb|{I-pv4F@8#~*i=3?&rM;d? zV((L`+ll6Wbvlj`8{oRka~Gv|UH>x|6MhSwSec1-0K9h4z3eKw_P$T*)C#YsY#2^> z=A{JW+L6i*4TZhjE~G;in?Y7{bHlM3+u>xYSkQdC!RF5Hw<O+Z>R!xj7*p_KF?cnr@y&5d&)rWE*i0%Js2u0(9ZyvrzP4C@;Dv{7nQme7 z@%@Nu>rs^iUI?d59r|X)1T2Kl!UXS{i7YdY@}?*1WOCjVSptpO@sB1Xc3<;BAJJC} zEDucSdHy0Vy=LZx{7lN-MeCNd(Sny>uC1qa?6ENpkOhA~_5=f08l-GjWZ^DvydSxW zVS_xo<&p0$`+Ty#J~-LO`jVpWukQhhl`q*=DCjM-UdKWn%0@eb`bE@YF#-4woj^df zNPw8co_!P2XJo$71I1zIbi1s1V09zkr@p^U(@)CRu@;?EYgD%dh?P3`xm&pkTce>_ z2GYySI^ne5D~B$ovdt<6dzmlbaY7Hh03XynFEr^ zk4AG!1(rOAppORunk*5MXJ-s?U+kpHAZ^rWweehZ#Z<^E$Lc>39M2j6sZF1eo!$Mp>qn^L0^ znB*s~&6GF&zM)28M?$Z;kS-x!I^cmDm6;s5^CTXN5f)t`wk^-tapcl&<#!@UoGs{E4uHQ9W|uWuo{ zq@brf7uPb^izZ6aTkPlGe6mJU-H0Sznnfkp~#5fgn`+c&sb?s|#lA%+5*hbl* z%_f)D-&=MY{PiYyplQ%B%PM8JTEB_K#{YQ3D~SXy8zM;&dWsMECa}yjEhq!22zOt^ z5Mntt6duqR?EKx7#^>lN=q&`5|1;+hU%*|FrHCD}UbQNhi2lsm9lrL(V~x~_eMsQn z>h+wYM#ZEkp9uEzZ`AktdTLY{dPnMYKmu|hf+oSpOYR?KHs7P0MC^ud_-exU(S^8Hh_(NgRU7T%hYC5<@r^n?Qku@n2I2fj{7hAd-6?Rx>HR zGL_XrIkf^p5oTwa8uiFx6o$9|8eGt7R*+61-#T1yjSDgaX@7CD6$YoXxv8T(beItE z5ur+QlyB!^(^Cs%s(4Mp$zFD!Nm%ZF!f{(Mq( z%GY<9hM{S!cZ-Z&Pf;uoWdle zqrYE-zMRXV2s7tYK@SeNRbCiAjEz`^e+Bn@?NYbJS1(G!9qkeT3pUfVZ^h#Pji%bY-!TC@$A|;LFmV@6XLhpx(td0cpIe5U_xebXt9|PAVk(k`{w3veLA}vKX!iyK^ zcgML&4ANw!)-aNXC0Vi$3@awnVn~H&;w}fYzQe+=PP)9aeNHun0CEd>U~(6lHIE!^ zAQ5Fa1X%^cuNOn7%lN)?rw>fI)7Qvw#SEJb7l? z%dF&((cKuo5Vp&W4qRxf(}REveu)aRKAh)n33FIDIeI+21nldvFMqmY;@kh#S2`tA5e8z5$eVb zz1)r*8HRU?kt6_kyFru-87 zrp0U&UVu931(VNh#w5{IhZggT=&Bc=vBNEgdv8VW>6a=_iY+N9o8X6z0|$ z8bSt9I6+0!q_KmBH|c7ASM^OrryT`l@w~G~#prlC6on)-fdCb_SZD}8Itaa8_RBli zJX%{)L`QCyBQ9}~#tDQFF*MWVtS)p4pvH_DG3Q5Uu1#y$WB`rtCu1^hP z)tb?=A_3YPDiy$VBpqINlAk4OE_!xjJmzBg0-$RP-q@|SVhg#;>j82rpL;EffZicA z*Hvv3g^G#^=9B$^t{93SSPUg1EKleM04D(sI$n%W%f}|tA$$d52eo=itOz@BHuQBq z4>VQymhbRu4~lIME@C{&g94>x<^8)EF^iUUsaBYG~Bt^UB~@PxgFy_asLWYRm%h)mkaK6 z)hz%feU>p(>m(tg{U}<`6#lt2aj;G-Y~Q3)p+~d?aKt47lVIyV(xni0+-}#P%pd{? z!t;G7YaXioV0X4$#gg5EsqL1`p-DiaV$CH>fZpF@G+l+OLl{kZpw-#H|AoOZ>Ua4v z^nzVTlO@SohFWmJ^4soS?)7{x((qL)Dp$wiIJ?lF6@qF7TCNvzg7EfX*M^?@I~v8q zQA%903rw~Lf4P18N8iy0wi8~xD!uECxYtWDeVm411cD(v@v(ovK?-`$;Z28krk0s@ z>BZmemMAv7|4f=y5$T}{cJ)qvyr1#k_Qtf{u!274>wT_|`rOi;Yh5E$1-EtW`ber| z)mpu>CVkIB+FHOv|759ceU5U+0nw-k9ZRpB3j`c-ta#H1r$?}_u#PS1ugXYhwuev| zlwwZq>=Lw-iwH|ur!Ht(VLwO*b)>2t5~{E}-bM2y3n3?s#II9-M@T8uvXdzec30UN zyK|#4GSnW{UcIpn>~+07oFp@SR)SK9 zefz)a6J-N^fp{Ee2ovwpxq0s&;pjjDAhW<8_@%BGau~d6orr{dtrTTLhJ3qs`d!~r z?Qrhr(D6rAF>z2z{o_}-C$A|^-b8W_@yQ!2EKcZZn|t(RVfoO`yF-EK0#*dOeyuL6 zS*JA5gebq+Y!AMd+g~84{!1_Yk*>sf{;#(sfVp6+2kdQxzIPc4oK*?$ytIHqir%0(k(Sl+ zee3iQ&@X)hXV^H6ur1yrRP0JxO)O?_yIBWb8rrMMP}@l-|M;xWqC#6cd%A1S0vTh~ z0^AnC{S^_1EX4nE-YaCYjBkxhP+U)4)!+9*C3OMm8>MQ*9&ucSX;MoBd3@Fwsp%1V z)$ig3`LlG}C@<-F=F@Xo@^hHLKtOP6IO9KNf#|>bqXT)!o6itsYuXW(>;P*3ajTUV z8$UCiP=&7@jgw?d23F?oX}c=#a&d*JgweNgez$JS_Fk>JXI;>uQ_aLZA2|Aa@b_a_ z+?yV$a`GRdhBek{9Ir_qUEv7o7)gIOAZH!|9TSX^c68Bi+!ik4$f}we5;&1|a=ge| zQ|78E?6R5Tz!zCc#v0APQ=TY4#m_;beM7l!MD^ck#|HWE-!FwG1NQ-Fz(sS4I0Y z0TnvImViOO^mN51qN3+nF@B!v8Xa!zOk27G$B;GvYxEZ>(f5(h;af-LNLLaoIJ=~>=`1s=grKYa`1L?KN AQUCw| literal 0 HcmV?d00001 diff --git a/theme/h4ck3r/logo.png b/theme/h4ck3r/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7c68b34f61008753d12394806c3cf46f7b04effd GIT binary patch literal 4988 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 Date: Wed, 13 May 2009 16:06:52 +0000 Subject: [PATCH 475/503] Minor clearing. --- theme/h4ck3r/css/base.css | 1 + 1 file changed, 1 insertion(+) diff --git a/theme/h4ck3r/css/base.css b/theme/h4ck3r/css/base.css index 54763006bc..5060bbb8b7 100644 --- a/theme/h4ck3r/css/base.css +++ b/theme/h4ck3r/css/base.css @@ -253,6 +253,7 @@ margin-bottom:18px; #anon_notice { float:right; +clear:right; width:41.2%; padding:1.1%; border-width:2px; From d8e49a21745bfde9a18a6d6e1047decc3c7e356f Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 13 May 2009 17:29:13 +0000 Subject: [PATCH 476/503] otalk theme: Using two columns for notice list --- theme/otalk/css/base.css | 16 ++++++++++------ theme/otalk/css/display.css | 1 - 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/theme/otalk/css/base.css b/theme/otalk/css/base.css index 379590d30f..32e8891d21 100644 --- a/theme/otalk/css/base.css +++ b/theme/otalk/css/base.css @@ -12,7 +12,7 @@ img { display:block; border:0; } a abbr { cursor: pointer; border-bottom:0; } table { border-collapse:collapse; } ol { list-style-position:inside; } -html { font-size: 87.5%; background-color:#fff; height:100%; } +html { font-size: 87.5%; background-color:#fff; } body { background-color:#fff; color:#000; @@ -386,12 +386,12 @@ margin-bottom:1em; } #content { -width:100%; +width:67.9%; min-height:259px; padding-top:1.795%; padding-bottom:1.795%; - float:left; +clear:left; border-radius:7px; -moz-border-radius:7px; -moz-border-radius-topleft:0; @@ -409,11 +409,11 @@ float:left; } #aside_primary { -width:96.3%; +width:27.917%; min-height:259px; float:left; -clear:both; padding:1.795%; +margin-left:0.385%; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; @@ -730,7 +730,7 @@ list-style-type:none; } #content .notice { -width:25%; +width:37%; margin-left:17px; margin-bottom:47px; clear:none; @@ -743,6 +743,10 @@ min-height:235px; margin-bottom:18px; } +#shownotice #content .notice { +width:96%; +} + /* NOTICES */ #notices_primary { diff --git a/theme/otalk/css/display.css b/theme/otalk/css/display.css index 22e0530ecc..6c646791bf 100644 --- a/theme/otalk/css/display.css +++ b/theme/otalk/css/display.css @@ -15,7 +15,6 @@ html { html, body, a:active { -/*background-color:#F0F2F5;*/ } body { font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; From 3b7ee5a5f9a2cd3066aff8a7a12d09878be3b06c Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 13 May 2009 14:27:32 -0400 Subject: [PATCH 477/503] rewrote short url stuff to handle new file/url classes (redirections, oembed, mimetypes, etc.) --- actions/newnotice.php | 18 +-- classes/File.php | 65 ++++++++++ classes/File_oembed.php | 43 +++++++ classes/File_redirection.php | 231 +++++++++++++++++++++++++++++++++++ classes/File_to_post.php | 17 +++ classes/Notice.php | 6 +- classes/laconica.ini | 64 ---------- classes/laconica.links.ini | 59 +-------- lib/Shorturl_api.php | 3 +- lib/util.php | 114 +++-------------- 10 files changed, 383 insertions(+), 237 deletions(-) diff --git a/actions/newnotice.php b/actions/newnotice.php index 8b03abc62c..ae0ff96363 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -158,7 +158,8 @@ class NewnoticeAction extends Action $replyto = 'false'; } - $notice = Notice::saveNew($user->id, $content, 'web', 1, +// $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, + $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, ($replyto == 'false') ? null : $replyto); if (is_string($notice)) { @@ -203,25 +204,12 @@ class NewnoticeAction extends Action * @return void */ function saveUrls($notice) { - common_debug("Saving all URLs"); common_replace_urls_callback($notice->content, array($this, 'saveUrl'), $notice->id); } function saveUrl($data) { list($url, $notice_id) = $data; - common_debug("Saving $url for $notice_id"); - $file = File::staticGet('url', $url); - if (empty($file)) { - common_debug('unknown file/url'); - $file = new File; - $file->url = $url; - $file->insert(); - } - common_debug('File: ' . print_r($file, true)); - $f2p = new File_to_post; - $f2p->file_id = $file->id; - $f2p->post_id = $notice_id; - $f2p->insert(); + $zzz = File::processNew($url, $notice_id); } /** diff --git a/classes/File.php b/classes/File.php index 8dd017b79b..2ddc5deb8b 100644 --- a/classes/File.php +++ b/classes/File.php @@ -20,6 +20,11 @@ if (!defined('LACONICA')) { exit(1); } require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; +require_once INSTALLDIR.'/classes/File_redirection.php'; +require_once INSTALLDIR.'/classes/File_oembed.php'; +require_once INSTALLDIR.'/classes/File_thumbnail.php'; +require_once INSTALLDIR.'/classes/File_to_post.php'; +//require_once INSTALLDIR.'/classes/File_redirection.php'; /** * Table Definition for file @@ -44,4 +49,64 @@ class File extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function isProtected($url) { + return 'http://www.facebook.com/login.php' === $url; + } + + function saveNew($redir_data, $given_url) { + $x = new File; + $x->url = $given_url; + if (!empty($redir_data['protected'])) $x->protected = $redir_data['protected']; + if (!empty($redir_data['title'])) $x->title = $redir_data['title']; + if (!empty($redir_data['type'])) $x->mimetype = $redir_data['type']; + if (!empty($redir_data['size'])) $x->size = intval($redir_data['size']); + if (isset($redir_data['time']) && $redir_data['time'] > 0) $x->date = intval($redir_data['time']); + $file_id = $x->insert(); + + if (isset($redir_data['type']) + && ('text/html' === substr($redir_data['type'], 0, 9)) + && ($oembed_data = File_oembed::_getOembed($given_url)) + && isset($oembed_data['json'])) { + + File_oembed::saveNew($oembed_data['json'], $file_id); + } + return $x; + } + + function processNew($given_url, $notice_id) { + if (empty($given_url)) return -1; // error, no url to process + $given_url = File_redirection::_canonUrl($given_url); + if (empty($given_url)) return -1; // error, no url to process + $file = File::staticGet('url', $given_url); + if (empty($file->id)) { + $file_redir = File_redirection::staticGet('url', $given_url); + if (empty($file_redir->id)) { + $redir_data = File_redirection::where($given_url); + $redir_url = $redir_data['url']; + if ($redir_url === $given_url) { + $x = File::saveNew($redir_data, $given_url); + $file_id = $x->id; + + } else { + $x = File::processNew($redir_url, $notice_id); + $file_id = $x->id; + File_redirection::saveNew($redir_data, $file_id, $given_url); + } + } else { + $file_id = $file_redir->file_id; + } + } else { + $file_id = $file->id; + $x = $file; + } + + if (empty($x)) { + $x = File::staticGet($file_id); + if (empty($x)) die('Impossible!'); + } + + File_to_post::processNew($file_id, $notice_id); + return $x; + } } diff --git a/classes/File_oembed.php b/classes/File_oembed.php index 33dd8200c2..2846f49dbc 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -50,4 +50,47 @@ class File_oembed extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + + function _getOembed($url, $maxwidth = 500, $maxheight = 400, $format = 'json') { + $cmd = 'http://oohembed.com/oohembed/?url=' . urlencode($url); + if (is_int($maxwidth)) $cmd .= "&maxwidth=$maxwidth"; + if (is_int($maxheight)) $cmd .= "&maxheight=$maxheight"; + if (is_string($format)) $cmd .= "&format=$format"; + $oe = @file_get_contents($cmd); + if (false === $oe) return false; + return array($format => (('json' === $format) ? json_decode($oe, true) : $oe)); + } + + function saveNew($data, $file_id) { + $file_oembed = new File_oembed; + $file_oembed->file_id = $file_id; + $file_oembed->version = $data['version']; + $file_oembed->type = $data['type']; + if (!empty($data['provider_name'])) $file_oembed->provider = $data['provider_name']; + if (!isset($file_oembed->provider) && !empty($data['provide'])) $file_oembed->provider = $data['provider']; + if (!empty($data['provide_url'])) $file_oembed->provider_url = $data['provider_url']; + if (!empty($data['width'])) $file_oembed->width = intval($data['width']); + if (!empty($data['height'])) $file_oembed->height = intval($data['height']); + if (!empty($data['html'])) $file_oembed->html = $data['html']; + if (!empty($data['title'])) $file_oembed->title = $data['title']; + if (!empty($data['author_name'])) $file_oembed->author_name = $data['author_name']; + if (!empty($data['author_url'])) $file_oembed->author_url = $data['author_url']; + if (!empty($data['url'])) $file_oembed->url = $data['url']; + $file_oembed->insert(); + + if (!empty($data['thumbnail_url'])) { + $tn = new File_thumbnail; + $tn->file_id = $file_id; + $tn->url = $data['thumbnail_url']; + $tn->width = intval($data['thumbnail_width']); + $tn->height = intval($data['thumbnail_height']); + $tn->insert(); + } + + + + } } + + diff --git a/classes/File_redirection.php b/classes/File_redirection.php index e2d1e69c38..a71d1c0831 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -20,6 +20,11 @@ if (!defined('LACONICA')) { exit(1); } require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; +require_once INSTALLDIR.'/classes/File.php'; +require_once INSTALLDIR.'/classes/File_oembed.php'; + +define('USER_AGENT', 'Laconica user agent / file probe'); + /** * Table Definition for file_redirection @@ -42,4 +47,230 @@ class File_redirection extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + + + function _commonCurl($url, $redirs) { + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_URL, $url); + curl_setopt($curlh, CURLOPT_AUTOREFERER, true); // # setup referer header when folowing redirects + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 10); // # seconds to wait + curl_setopt($curlh, CURLOPT_MAXREDIRS, $redirs); // # max number of http redirections to follow + curl_setopt($curlh, CURLOPT_USERAGENT, USER_AGENT); + curl_setopt($curlh, CURLOPT_FOLLOWLOCATION, true); // Follow redirects + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curlh, CURLOPT_FILETIME, true); + curl_setopt($curlh, CURLOPT_HEADER, true); // Include header in output + return $curlh; + } + + function _redirectWhere_imp($short_url, $redirs = 10, $protected = false) { + if ($redirs < 0) return false; + + // let's see if we know this... + $a = File::staticGet('url', $short_url); + if (empty($a->id)) { + $b = File_redirection::staticGet('url', $short_url); + if (empty($b->id)) { + // we'll have to figure it out + } else { + // this is a redirect to $b->file_id + $a = File::staticGet($b->file_id); + $url = $a->url; + } + } else { + // this is a direct link to $a->url + $url = $a->url; + } + if (isset($url)) { + return $url; + } + + + + $curlh = File_redirection::_commonCurl($short_url, $redirs); + // Don't include body in output + curl_setopt($curlh, CURLOPT_NOBODY, true); + curl_exec($curlh); + $info = curl_getinfo($curlh); + curl_close($curlh); + + if (405 == $info['http_code']) { + $curlh = File_redirection::_commonCurl($short_url, $redirs); + curl_exec($curlh); + $info = curl_getinfo($curlh); + curl_close($curlh); + } + + if (!empty($info['redirect_count']) && File::isProtected($info['url'])) { + return File_redirection::_redirectWhere_imp($short_url, $info['redirect_count'] - 1, true); + } + + $ret = array('code' => $info['http_code'] + , 'redirects' => $info['redirect_count'] + , 'url' => $info['url']); + + if (!empty($info['content_type'])) $ret['type'] = $info['content_type']; + if ($protected) $ret['protected'] = true; + if (!empty($info['download_content_length'])) $ret['size'] = $info['download_content_length']; + if (isset($info['filetime']) && ($info['filetime'] > 0)) $ret['time'] = $info['filetime']; + return $ret; + } + + function where($in_url) { + $ret = File_redirection::_redirectWhere_imp($in_url); + return $ret; + } + + function makeShort($long_url) { + $long_url = File_redirection::_canonUrl($long_url); + // do we already know this long_url and have a short redirection for it? + $file = new File; + $file_redir = new File_redirection; + $file->url = $long_url; + $file->joinAdd($file_redir); + $file->selectAdd('length(file_redirection.url) as len'); + $file->limit(1); + $file->orderBy('len'); + $file->find(true); + if (!empty($file->id)) { + return $file->url; + } + + // if yet unknown, we must find a short url according to user settings + $short_url = File_redirection::_userMakeShort($long_url, common_current_user()); + return $short_url; + } + + function _userMakeShort($long_url, $user) { + if (empty($user)) { + // common current user does not find a user when called from the XMPP daemon + // therefore we'll set one here fix, so that XMPP given URLs may be shortened + $user->urlshorteningservice = 'ur1.ca'; + } + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait + curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + + switch($user->urlshorteningservice) { + case 'ur1.ca': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new LilUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case '2tu.us': + $short_url_service = new TightUrl; + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'ptiturl.com': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new PtitUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'bit.ly': + curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url)); + $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; + break; + + case 'is.gd': + curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'snipr.com': + curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'metamark.net': + curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'tinyurl.com': + curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + default: + $short_url = false; + } + + curl_close($curlh); + + if ($short_url) { + $short_url = (string)$short_url; +if(1) { + // store it + $file = File::staticGet('url', $long_url); + if (empty($file)) { + $redir_data = File_redirection::where($long_url); + $file = File::saveNew($redir_data, $long_url); + $file_id = $file->id; + if (!empty($redir_data['oembed']['json'])) { + File_oembed::saveNew($redir_data['oembed']['json'], $file_id); + } + } else { + $file_id = $file->id; + } + $file_redir = File_redirection::staticGet('url', $short_url); + if (empty($file_redir)) { + $file_redir = new File_redirection; + $file_redir->url = $short_url; + $file_redir->file_id = $file_id; + $file_redir->insert(); + } } + return $short_url; + } + return $long_url; + } + + function _canonUrl($in_url, $default_scheme = 'http://') { + if (empty($in_url)) return false; + $out_url = $in_url; + $p = parse_url($out_url); + if (empty($p['host']) || empty($p['scheme'])) { + list($scheme) = explode(':', $in_url, 2); + switch ($scheme) { + case 'fax': + case 'tel': + $out_url = str_replace('.-()', '', $out_url); + break; + + case 'mailto': + case 'aim': + case 'jabber': + case 'xmpp': + // don't touch anything + break; + + default: + $out_url = $default_scheme . ltrim($out_url, '/'); + $p = parse_url($out_url); + if (empty($p['scheme'])) return false; + break; + } + } + + if (('ftp' == $p['scheme']) || ('http' == $p['scheme']) || ('https' == $p['scheme'])) { + if (empty($p['host'])) return false; + if (empty($p['path'])) { + $out_url .= '/'; + } + } + + return $out_url; + } + + function saveNew($data, $file_id, $url) { + $file_redir = new File_redirection; + $file_redir->url = $url; + $file_redir->file_id = $file_id; + $file_redir->redirections = intval($data['redirects']); + $file_redir->httpcode = intval($data['code']); + $file_redir->insert(); + } +} + diff --git a/classes/File_to_post.php b/classes/File_to_post.php index bd0528d98f..00ddebe6b8 100644 --- a/classes/File_to_post.php +++ b/classes/File_to_post.php @@ -40,4 +40,21 @@ class File_to_post extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function processNew($file_id, $notice_id) { + static $seen = array(); + if (empty($seen[$notice_id]) || !in_array($file_id, $seen[$notice_id])) { + $f2p = new File_to_post; + $f2p->file_id = $file_id; + $f2p->post_id = $notice_id; + $f2p->insert(); + if (empty($seen[$notice_id])) { + $seen[$notice_id] = array($file_id); + } else { + $seen[$notice_id][] = $file_id; + } + } + + } } + diff --git a/classes/Notice.php b/classes/Notice.php index 382d160ab3..c2fa2d19e5 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -124,7 +124,7 @@ class Notice extends Memcached_DataObject $profile = Profile::staticGet($profile_id); - $final = common_shorten_links($content); +// $final = common_shorten_links($content); if (!$profile) { common_log(LOG_ERR, 'Problem saving notice. Unknown user.'); @@ -167,8 +167,8 @@ class Notice extends Memcached_DataObject $notice->reply_to = $reply_to; $notice->created = common_sql_now(); - $notice->content = $final; - $notice->rendered = common_render_content($final, $notice); + $notice->content = $content; + $notice->rendered = common_render_content($content, $notice); $notice->source = $source; $notice->uri = $uri; diff --git a/classes/laconica.ini b/classes/laconica.ini index 00a1b89365..316923af02 100644 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -1,67 +1,3 @@ - -[file] -id = 129 -url = 2 -mimetype = 2 -size = 1 -title = 2 -date = 1 -protected = 17 - -[file__keys] -id = K -url = U - -[file_oembed] -id = 129 -file_id = 1 -version = 2 -type = 2 -provider = 2 -provider_url = 2 -width = 1 -height = 1 -html = 66 -title = 2 -author_name = 2 -author_url = 2 -url = 2 - -[file_oembed__keys] -id = K -file_id = U - -[file_redirection] -id = 129 -url = 2 -file_id = 1 -redirections = 1 -httpcode = 1 - -[file_redirection__keys] -id = K -url = U - -[file_thumbnail] -id = 129 -file_id = 1 -url = 2 -width = 1 -height = 1 - -[file_thumbnail__keys] -id = K -file_id = U -url = U - -[file_to_post] -id = 129 -file_id = 1 -post_id = 1 - -[file_to_post__keys] -id = K - [avatar] profile_id = 129 original = 17 diff --git a/classes/laconica.links.ini b/classes/laconica.links.ini index bc52ce578e..95c63f3c09 100644 --- a/classes/laconica.links.ini +++ b/classes/laconica.links.ini @@ -53,62 +53,5 @@ file_id = file:id [file_to_post] file_id = file:id -post_id = post:id - -[avatar] -profile_id = profile:id - -[user] -id = profile:id -carrier = sms_carrier:id - -[remote_profile] -id = profile:id - -[notice] -profile_id = profile:id -reply_to = notice:id - -[reply] -notice_id = notice:id -profile_id = profile:id - -[token] -consumer_key = consumer:consumer_key - -[nonce] -consumer_key,token = token:consumer_key,token - -[user_openid] -user_id = user:id - -[confirm_address] -user_id = user:id - -[remember_me] -user_id = user:id - -[queue_item] -notice_id = notice:id - -[subscription] -subscriber = profile:id -subscribed = profile:id - -[fave] -notice_id = notice:id -user_id = user:id - -[file_oembed] -file_id = file:id - -[file_redirection] -file_id = file:id - -[file_thumbnail] -file_id = file:id - -[file_to_post] -file_id = file:id -post_id = post:id +post_id = notice:id diff --git a/lib/Shorturl_api.php b/lib/Shorturl_api.php index fe106cb837..924aa93a89 100644 --- a/lib/Shorturl_api.php +++ b/lib/Shorturl_api.php @@ -22,6 +22,7 @@ if (!defined('LACONICA')) { exit(1); } class ShortUrlApi { protected $service_url; + protected $long_limit = 27; function __construct($service_url) { @@ -39,7 +40,7 @@ class ShortUrlApi } private function is_long($url) { - return strlen($url) >= 30; + return strlen($url) >= $this->long_limit; } protected function http_post($data) { diff --git a/lib/util.php b/lib/util.php index c4a63a4412..25c0fb0a15 100644 --- a/lib/util.php +++ b/lib/util.php @@ -466,10 +466,10 @@ function common_replace_urls_callback($text, $callback, $notice_id = null) { $url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url); // Call user specified func - if (isset($notice_id)) { - $modified_url = call_user_func($callback, array($url, $notice_id)); - } else { + if (empty($notice_id)) { $modified_url = call_user_func($callback, $url); + } else { + $modified_url = call_user_func($callback, array($url, $notice_id)); } // Replace it! @@ -485,107 +485,29 @@ function common_linkify($url) { // It comes in special'd, so we unspecial it before passing to the stringifying // functions $url = htmlspecialchars_decode($url); - $display = $url; - $url = (!preg_match('#^([a-z]+://|(mailto|aim|tel):)#i', $url)) ? 'http://'.$url : $url; - - $attrs = array('href' => $url, 'rel' => 'external'); - - if ($longurl = common_longurl($url)) { - $attrs['title'] = $longurl; + $display = File_redirection::_canonUrl($url); + $longurl_data = File_redirection::where($url); + if (is_array($longurl_data)) { + $longurl = $longurl_data['url']; + } elseif (is_string($longurl_data)) { + $longurl = $longurl_data; + } else { + die('impossible to linkify'); } + $attrs = array('href' => $longurl, 'rel' => 'external'); +if(0){ + if ($longurl !== $url) { + $attrs['title'] = $longurl; + } +} return XMLStringer::estring('a', $attrs, $display); } -function common_longurl($short_url) -{ - $long_url = common_shorten_link($short_url, true); - if ($long_url === $short_url) return false; - return $long_url; -} - -function common_longurl2($uri) -{ - $uri_e = urlencode($uri); - $longurl = unserialize(file_get_contents("http://api.longurl.org/v1/expand?format=php&url=$uri_e")); - if (empty($longurl['long_url']) || $uri === $longurl['long_url']) return false; - return stripslashes($longurl['long_url']); -} - function common_shorten_links($text) { if (mb_strlen($text) <= 140) return $text; - static $cache = array(); - if (isset($cache[$text])) return $cache[$text]; - // \s = not a horizontal whitespace character (since PHP 5.2.4) - return $cache[$text] = common_replace_urls_callback($text, 'common_shorten_link');; -} - -function common_shorten_link($url, $reverse = false) -{ - - static $url_cache = array(); - if ($reverse) return isset($url_cache[$url]) ? $url_cache[$url] : $url; - - $user = common_current_user(); - if (!isset($user)) { - // common current user does not find a user when called from the XMPP daemon - // therefore we'll set one here fix, so that XMPP given URLs may be shortened - $user->urlshorteningservice = 'ur1.ca'; - } - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait - curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - - switch($user->urlshorteningservice) { - case 'ur1.ca': - $short_url_service = new LilUrl; - $short_url = $short_url_service->shorten($url); - break; - - case '2tu.us': - $short_url_service = new TightUrl; - $short_url = $short_url_service->shorten($url); - break; - - case 'ptiturl.com': - $short_url_service = new PtitUrl; - $short_url = $short_url_service->shorten($url); - break; - - case 'bit.ly': - curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($url)); - $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; - break; - - case 'is.gd': - curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - case 'snipr.com': - curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - case 'metamark.net': - curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - case 'tinyurl.com': - curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - default: - $short_url = false; - } - - curl_close($curlh); - - if ($short_url) { - $url_cache[(string)$short_url] = $url; - return (string)$short_url; - } - return $url; + return common_replace_urls_callback($text, array('File_redirection', 'makeShort')); } function common_xml_safe_str($str) From 4a8c993ed01ed338bb94ba74a48982e0be8c64d1 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 14 May 2009 20:22:04 +0000 Subject: [PATCH 478/503] Updated instructions for creating a theme. Removed earthy theme ~ which was too basic to be unique. --- theme/earthy/css/base.css | 1188 ----------------------- theme/earthy/css/display.css | 251 ----- theme/earthy/css/ie.css | 9 - theme/earthy/default-avatar-mini.png | Bin 646 -> 0 bytes theme/earthy/default-avatar-profile.png | Bin 2853 -> 0 bytes theme/earthy/default-avatar-stream.png | Bin 1487 -> 0 bytes theme/earthy/logo.png | Bin 4988 -> 0 bytes theme/readme.txt | 10 +- 8 files changed, 6 insertions(+), 1452 deletions(-) delete mode 100644 theme/earthy/css/base.css delete mode 100644 theme/earthy/css/display.css delete mode 100644 theme/earthy/css/ie.css delete mode 100644 theme/earthy/default-avatar-mini.png delete mode 100644 theme/earthy/default-avatar-profile.png delete mode 100644 theme/earthy/default-avatar-stream.png delete mode 100644 theme/earthy/logo.png diff --git a/theme/earthy/css/base.css b/theme/earthy/css/base.css deleted file mode 100644 index 6f46eef978..0000000000 --- a/theme/earthy/css/base.css +++ /dev/null @@ -1,1188 +0,0 @@ -/** theme: earthy base - * - * @package Laconica - * @author Sarven Capadisli - * @copyright 2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -* { margin:0; padding:0; } -img { display:block; border:0; } -a abbr { cursor: pointer; border-bottom:0; } -table { border-collapse:collapse; } -ol { list-style-position:inside; } -html { background-color:#fff; height:100%; } -body { -background-color:#fff; -color:#000; -font-family:sans-serif; -font-size:1em; -line-height:1.65; -position:relative; -} -h1,h2,h3,h4,h5,h6 { -margin-bottom:7px; -overflow:hidden; -} -h1 { -font-size:1.4em; -margin-bottom:18px; -text-align:right; -} -#showstream h1 { display:none; } -h2 { font-size:1.3em; } -h3 { font-size:1.2em; } -h4 { font-size:1.1em; } -h5 { font-size:1em; } -h6 { font-size:0.9em; } - -caption { -font-weight:bold; -} -legend { -font-weight:bold; -font-size:1.3em; -} -input, textarea, select, option { -padding:4px; -font-family:sans-serif; -font-size:1em; -} -input, textarea, select { -border-width:2px; -border-style: solid; -border-radius:4px; --moz-border-radius:4px; --webkit-border-radius:4px; -} - -input.submit { -font-weight:bold; -cursor:pointer; -} -textarea { -overflow:auto; -} -option { -padding-bottom:0; -} -fieldset { -padding:0; -border:0; -} -form ul li { -list-style-type:none; -margin:0 0 18px 0; -} -form label { -font-weight:bold; -} -input.checkbox { -position:relative; -top:2px; -left:0; -border:0; -} - -.error, -.success { -padding:4px 7px; -border-radius:4px; --moz-border-radius:4px; --webkit-border-radius:4px; -margin-bottom:18px; -} -form label.submit { -display:none; -} - -.form_settings { -clear:both; -} - -.form_settings fieldset { -margin-bottom:29px; -} -.form_settings input.remove { -margin-left:11px; -} -.form_settings .form_data li { -width:100%; -float:left; -} -.form_settings .form_data label { -float:left; -} -.form_settings .form_data textarea, -.form_settings .form_data select, -.form_settings .form_data input { -margin-left:11px; -float:left; -} -.form_settings .form_data input.submit { -margin-left:0; -} - -.form_settings label { -margin-top:2px; -width:152px; -} - -.form_actions label { -display:none; -} -.form_guide { -font-style:italic; -} - -.form_settings #settings_autosubscribe label { -display:inline; -font-weight:bold; -} - -#form_settings_profile legend, -#form_login legend, -#form_register legend, -#form_password legend, -#form_settings_avatar legend, -#newgroup legend, -#editgroup legend, -#form_tag_user legend, -#form_remote_subscribe legend, -#form_openid_login legend, -#form_search legend, -#form_invite legend, -#form_notice_delete legend, -#form_password_recover legend, -#form_password_change legend { -display:none; -} - -.form_settings .form_data p.form_guide { -clear:both; -margin-left:163px; -margin-bottom:0; -} - -.form_settings p { -margin-bottom:11px; -} - -.form_settings input.checkbox { -margin-top:3px; -margin-left:0; -} -.form_settings label.checkbox { -font-weight:normal; -margin-top:0; -margin-right:0; -margin-left:11px; -float:left; -width:90%; -} - - -#form_login p.form_guide, -#form_register #settings_rememberme p.form_guide, -#form_openid_login #settings_rememberme p.form_guide, -#settings_twitter_remove p.form_guide, -#form_search ul.form_data #q { -margin-left:0; -} - -.form_settings .form_note { -border-radius:4px; --moz-border-radius:4px; --webkit-border-radius:4px; -padding:0 7px; -} - - -.form_settings input.form_action-secondary { -margin-left:29px; -padding:0; -} - -#form_search .submit { -margin-left:11px; -} - -address { -float:left; -margin-bottom:18px; -margin-left:18px; -} -address.vcard img.logo { -margin-right:0; -} -address .fn { -font-weight:bold; -} -address img + .fn { -display:none; -} - -#header { -width:100%; -position:relative; -float:left; -padding-top:18px; -margin-bottom:29px; -} - -#site_nav_global_primary { -float:right; -margin-right:18px; -margin-bottom:11px; -margin-left:18px; -} -#site_nav_global_primary ul li { -display:inline; -margin-left:11px; -} - -.system_notice dt { -font-weight:bold; -text-transform:uppercase; -display:none; -} - -#site_notice { -position:absolute; -top:65px; -right:18px; -width:250px; -width:24%; -} -#page_notice { -clear:both; -margin-bottom:18px; -} - - -#anon_notice { -float:left; -width:43.2%; -padding:1.1%; -border-radius:7px; --moz-border-radius:7px; --webkit-border-radius:7px; -border-width:2px; -border-style:solid; -line-height:1.5; -font-size:1.1em; -font-weight:bold; -} - - -#footer { -float:left; -width:64%; -padding:18px; -} - -#site_nav_local_views { -float:right; -} -#site_nav_local_views dt { -display:none; -} -#site_nav_local_views li { -float:right; -margin-left:11px; -list-style-type:none; -} -#site_nav_local_views a { -float:left; -text-decoration:none; -padding:4px 11px; --moz-border-radius-topleft:4px; --moz-border-radius-topright:4px; --webkit-border-top-left-radius:4px; --webkit-border-top-right-radius:4px; -border-width:1px; -border-style:solid; -border-bottom:0; -text-shadow: 2px 2px 2px #ddd; -font-weight:bold; -} -#site_nav_local_views .nav { -float:left; -width:100%; -border-bottom-width:1px; -border-bottom-style:solid; -} - -#site_nav_global_primary dt, -#site_nav_global_secondary dt { -display:none; -} - -#site_nav_global_secondary { -margin-bottom:11px; -} - -#site_nav_global_secondary ul li { -display:inline; -margin-right:11px; -} -#export_data li a { -padding-left:20px; -} -#export_data li a.foaf { -padding-left:30px; -} -#export_data li a.export_vcard { -padding-left:28px; -} - -#export_data ul { -display:inline; -} -#export_data li { -list-style-type:none; -display:inline; -margin-left:11px; -} -#export_data li:first-child { -margin-left:0; -} - -#licenses { -font-size:0.9em; -} - -#licenses dt { -font-weight:bold; -display:none; -} -#licenses dd { -margin-bottom:11px; -line-height:1.5; -} - -#site_content_license_cc { -margin-bottom:0; -} -#site_content_license_cc img { -display:inline; -vertical-align:top; -margin-right:4px; -} - -#wrap { -margin:0 auto; -width:100%; -min-width:760px; -max-width:1003px; -overflow:hidden; -} - -#core { -position:relative; -width:100%; -float:left; -margin-bottom:1em; -} - -#content { -width:63.009%; -min-height:259px; -padding-top:1.795%; -padding-bottom:1.795%; -float:right; -clear:both; -border-radius:7px; -border-style:solid; -border-width:0; -} - -#content_inner { -position:relative; -width:100%; -float:left; -} - -#aside_primary { -width:27.917%; -min-height:259px; -float:right; -margin-right:4.385%; -margin-top:73px; -padding:1.795%; -border-radius:7px; --moz-border-radius:7px; --webkit-border-radius:7px; -border-width:1px; -border-style:solid; -} - -#form_notice { -width:45.664%; -float:left; -position:relative; -line-height:1; -} -#form_notice fieldset { -border:0; -padding:0; -} -#form_notice legend { -display:none; -} -#form_notice textarea { -float:left; -border-radius:7px; --moz-border-radius:7px; --webkit-border-radius:7px; -width:80.789%; -height:67px; -line-height:1.5; -padding:7px 7px 16px 7px; -} -#form_notice label { -display:block; -float:left; -font-size:1.3em; -margin-bottom:7px; -} -#form_notice #notice_submit label { -display:none; -} -#form_notice .form_note { -position:absolute; -top:99px; -right:98px; -z-index:9; -} -#form_notice .form_note dt { -font-weight:bold; -display:none; -} -#notice_text-count { -font-weight:bold; -line-height:1.15; -padding:1px 2px; -} -#form_notice #notice_action-submit { -width:14%; -height:47px; -padding:0; -position:absolute; -bottom:0; -right:0; -} -#form_notice label[for=to] { -margin-top:7px; -} -#form_notice select[id=to] { -margin-bottom:7px; -margin-left:18px; -float:left; -} - - -/* entity_profile */ -.entity_profile { -position:relative; -width:67.702%; -min-height:123px; -float:left; -margin-bottom:18px; -margin-left:0; -overflow:hidden; -} -.entity_profile dt, -#entity_statistics dt { -font-weight:bold; -} -.entity_profile dd { -display:inline; -} - -.entity_profile .entity_depiction { -float:left; -width:96px; -margin-right:18px; -margin-bottom:18px; -} - -.entity_profile .entity_fn, -.entity_profile .entity_nickname, -.entity_profile .entity_location, -.entity_profile .entity_url, -.entity_profile .entity_note, -.entity_profile .entity_tags { -margin-left:113px; -margin-bottom:4px; -} - -.entity_profile .entity_fn, -.entity_profile .entity_nickname { -margin-left:11px; -display:inline; -font-weight:bold; -} -.entity_profile .entity_nickname { -margin-left:0; -} - -.entity_profile .entity_fn dd:before { -content: "("; -font-weight:normal; -} -.entity_profile .entity_fn dd:after { -content: ")"; -font-weight:normal; -} - -.entity_profile dt { -display:none; -} -.entity_profile h2 { -display:none; -} -/* entity_profile */ - - -/*entity_actions*/ -.entity_actions { -float:right; -margin-left:4.35%; -max-width:25%; -} -.entity_actions h2 { -display:none; -} -.entity_actions ul { -list-style-type:none; -} -.entity_actions li { -margin-bottom:4px; -} -.entity_actions li:first-child { -border-top:0; -} -.entity_actions fieldset { -border:0; -padding:0; -} -.entity_actions legend { -display:none; -} - -.entity_actions input.submit { -display:block; -text-align:left; -width:100%; -} -.entity_actions a, -.entity_nudge p, -.entity_remote_subscribe { -text-decoration:none; -font-weight:bold; -display:block; -} - -.form_user_block input.submit, -.form_user_unblock input.submit, -.entity_send-a-message a, -.entity_edit a, -.form_user_nudge input.submit, -.entity_nudge p { -border:0; -padding-left:20px; -} - -.entity_edit a, -.entity_send-a-message a, -.entity_nudge p { -padding:4px 4px 4px 23px; -} - -.entity_remote_subscribe { -padding:4px; -border-width:2px; -border-style:solid; -border-radius:4px; --moz-border-radius:4px; --webkit-border-radius:4px; -} -.entity_actions .accept { -margin-bottom:18px; -} - -.entity_tags ul { -list-style-type:none; -display:inline; -} -.entity_tags li { -display:inline; -margin-right:4px; -} - -.aside .section { -margin-bottom:29px; -clear:both; -float:left; -width:100%; -} -.aside .section h2 { -text-transform:uppercase; -font-size:1em; -} - -#entity_statistics dt, -#entity_statistics dd { -display:inline; -} -#entity_statistics dt:after { -content: ":"; -} - -.section ul.entities { -float:left; -width:100%; -} -.section .entities li { -list-style-type:none; -float:left; -margin-right:7px; -margin-bottom:7px; -} -.section .entities li .photo { -margin-right:0; -margin-bottom:0; -} -.section .entities li .fn { -display:none; -} - -.aside .section p, -.aside .section .more { -clear:both; -} - -.profile .entity_profile { -margin-bottom:0; -min-height:60px; -} - - -.profile .form_group_join legend, -.profile .form_group_leave legend, -.profile .form_user_subscribe legend, -.profile .form_user_unsubscribe legend { -display:none; -} - -.profiles { -list-style-type:none; -} -.profile .entity_profile .entity_location { -width:auto; -clear:none; -margin-left:11px; -} -.profile .entity_profile dl, -.profile .entity_profile dd { -display:inline; -float:none; -} -.profile .entity_profile .entity_note, -.profile .entity_profile .entity_url, -.profile .entity_profile .entity_tags, -.profile .entity_profile .form_subscription_edit { -margin-left:59px; -clear:none; -display:block; -width:auto; -} -.profile .entity_profile .entity_tags dt { -display:inline; -margin-right:11px; -} - - -.profile .entity_profile .form_subscription_edit label { -font-weight:normal; -margin-right:11px; -} - - -/* NOTICE */ -.notice, -.profile { -position:relative; -clear:both; -float:left; -width:100%; -border-width:1px; -border-style:solid; -border-radius:7px; --moz-border-radius:7px; --webkit-border-radius:7px; -} -#content .notice, -#content .profile { -padding:1.795%; -margin-bottom:44px; -} -#content .notice { -width:96.25%; -} - -.notices li { -list-style-type:none; -} -.notices li.hover { -border-radius:4px; --moz-border-radius:4px; --webkit-border-radius:4px; -} - -/* NOTICES */ -#notices_primary { -float:left; -width:100%; -border-radius:7px; --moz-border-radius:7px; --webkit-border-radius:7px; -} -#notices_primary h2 { -display:none; -} -.notice-data a span { -display:block; -padding-left:28px; -} - -.notice .author { -margin-right:11px; -} - -.fn { -overflow:hidden; -} - -.notice .author .fn { -font-weight:bold; -} - -.notice .author .photo { -margin-bottom:0; -} - -.vcard .photo { -display:inline; -margin-right:11px; -margin-bottom:11px; -float:left; -} -.vcard .url { -text-decoration:none; -} -.vcard .url:hover { -text-decoration:underline; -} - -.notice .entry-title { -float:left; -width:100%; -overflow:hidden; -} -#shownotice .notice .entry-title { -font-size:2.2em; -} - -.notice p.entry-content { -display:inline; -} - -#content .notice p.entry-content a:visited { -border-radius:4px; --moz-border-radius:4px; --webkit-border-radius:4px; -} -.notice p.entry-content .vcard a { -border-radius:4px; --moz-border-radius:4px; --webkit-border-radius:4px; -} - -.notice div.entry-content { -clear:left; -float:left; -font-size:0.95em; -margin-left:59px; -width:70%; -} -#showstream .notice div.entry-content { -margin-left:0; -} - -.notice .notice-options a, -.notice .notice-options input { -float:left; -font-size:1.025em; -} - -.notice div.entry-content dl, -.notice div.entry-content dt, -.notice div.entry-content dd { -display:inline; -} - -.notice div.entry-content .timestamp dt, -.notice div.entry-content .response dt { -display:none; -} -.notice div.entry-content .timestamp a { -display:inline-block; -} -.notice div.entry-content .device dt { -text-transform:lowercase; -} - - - -.notice-data { -position:absolute; -top:18px; -right:0; -min-height:50px; -margin-bottom:4px; -} -.notice .entry-content .notice-data dt { -display:none; -} - -.notice-data a { -display:block; -outline:none; -} - -.notice-options { -padding-left:2%; -float:left; -width:50%; -position:relative; -font-size:0.95em; -width:12.5%; -float:right; -} - -.notice-options a { -float:left; -} -.notice-options .notice_delete, -.notice-options .notice_reply, -.notice-options .form_favor, -.notice-options .form_disfavor { -position:absolute; -top:0; -} -.notice-options .form_favor, -.notice-options .form_disfavor { -left:0; -} -.notice-options .notice_reply { -left:29px; -} -.notice-options .notice_delete { -right:0; -} -.notice-options .notice_reply dt { -display:none; -} - -.notice-options input, -.notice-options a { -text-indent:-9999px; -outline:none; -} - -.notice-options .notice_reply a, -.notice-options input.submit { -display:block; -border:0; -} -.notice-options .notice_reply a, -.notice-options .notice_delete a { -text-decoration:none; -padding-left:16px; -} - -.notice-options form input.submit { -width:16px; -padding:2px 0; -} - -.notice-options .notice_delete dt, -.notice-options .form_favor legend, -.notice-options .form_disfavor legend { -display:none; -} -.notice-options .notice_delete fieldset, -.notice-options .form_favor fieldset, -.notice-options .form_disfavor fieldset { -border:0; -padding:0; -} - - -#usergroups #new_group { -float: left; -margin-right: 2em; -} -#new_group, #group_search { -margin-bottom:18px; -} -#new_group a { -padding-left:20px; -} - - -#filter_tags { -margin-bottom:11px; -float:left; -} -#filter_tags dt { -display:none; -} -#filter_tags ul { -list-style-type:none; -} -#filter_tags ul li { -float:left; -margin-left:7px; -padding-left:7px; -border-left-width:1px; -border-left-style:solid; -} -#filter_tags ul li.child_1 { -margin-left:0; -border-left:0; -padding-left:0; -} -#filter_tags ul li#filter_tags_all a { -font-weight:bold; -margin-top:7px; -float:left; -} - -#filter_tags ul li#filter_tags_item label { -margin-right:7px; -} -#filter_tags ul li#filter_tags_item label, -#filter_tags ul li#filter_tags_item select { -display:inline; -} -#filter_tags ul li#filter_tags_item p { -float:left; -margin-left:38px; -} -#filter_tags ul li#filter_tags_item input { -position:relative; -top:3px; -left:3px; -} - - - -.pagination { -float:left; -clear:both; -width:100%; -margin-top:18px; -} - -.pagination dt { -font-weight:bold; -display:none; -} - -.pagination .nav { -float:left; -width:100%; -list-style-type:none; -} - -.pagination .nav_prev { -float:left; -} -.pagination .nav_next { -float:right; -} - -.pagination a { -display:block; -text-decoration:none; -font-weight:bold; -padding:7px; -border-width:1px; -border-style:solid; --moz-border-radius:7px; --webkit-border-radius:7px; -border-radius:7px; -} - -.pagination .nav_prev a { -padding-left:30px; -} -.pagination .nav_next a { -padding-right:30px; -} -/* END: NOTICE */ - - -.hentry .entry-content p { -margin-bottom:18px; -} -.hentry entry-content ol, -.hentry .entry-content ul { -list-style-position:inside; -} -.hentry .entry-content li { -margin-bottom:18px; -} -.hentry .entry-content li li { -margin-left:18px; -} - - - - -/* TOP_POSTERS */ -.section tbody td { -padding-right:11px; -padding-bottom:11px; -} -.section .vcard .photo { -margin-right:7px; -margin-bottom:0; -} - -.section .notice { -padding-top:7px; -padding-bottom:7px; -border-top:0; -} - -.section .notice:first-child { -padding-top:0; -} - -.section .notice .author { -margin-right:0; -} -.section .notice .author .fn { -display:none; -} - - -/* tagcloud */ -.tag-cloud { -list-style-type:none; -text-align:center; -} -.aside .tag-cloud { -font-size:0.8em; -} -.tag-cloud li { -display:inline; -margin-right:7px; -line-height:1.25; -} -.aside .tag-cloud li { -line-height:1.5; -} -.tag-cloud li a { -text-decoration:none; -} -#tagcloud.section dt { -text-transform:uppercase; -font-weight:bold; -} -.tag-cloud-1 { -font-size:1em; -} -.tag-cloud-2 { -font-size:1.25em; -} -.tag-cloud-3 { -font-size:1.75em; -} -.tag-cloud-4 { -font-size:2em; -} -.tag-cloud-5 { -font-size:2.25em; -} -.tag-cloud-6 { -font-size:2.75em; -} -.tag-cloud-7 { -font-size:3.25em; -} - -#publictagcloud #tagcloud.section dt { -display:none; -} - -#form_settings_photo .form_data { -clear:both; -} - -#form_settings_avatar li { -width:auto; -} -#form_settings_avatar input { -margin-left:0; -} -#avatar_original, -#avatar_preview { -float:left; -} -#avatar_preview { -margin-left:29px; -} -#avatar_preview_view { -height:96px; -width:96px; -margin-bottom:18px; -overflow:hidden; -} - -#settings_attach, -#form_settings_avatar .form_actions { -clear:both; -} - -#form_settings_avatar .form_actions { -margin-bottom:0; -} - -#form_settings_design #settings_design_color .form_data, -#form_settings_design #color-picker { -float:left; -} -#form_settings_design #settings_design_color .form_data { -width:400px; -margin-right:28px; -} - -.instructions ul { -list-style-position:inside; -} -.instructions p, -.instructions ul { -margin-bottom:18px; -} -.help dt { -display:none; -} -.guide { -clear:both; -} diff --git a/theme/earthy/css/display.css b/theme/earthy/css/display.css deleted file mode 100644 index b67700f2d9..0000000000 --- a/theme/earthy/css/display.css +++ /dev/null @@ -1,251 +0,0 @@ -/** theme: earthy - * - * @package Laconica - * @author Sarven Capadisli - * @copyright 2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -@import url(base.css); - -html, -body, -a:active { -background-color:#665500; -} -body { -font-family: Verdana, sans-serif; -font-size:1em; -} -address { -margin-right:7.18%; -} - -h1 { -color:#fff; -} - -input, textarea, select, option { -font-family: Verdana, sans-serif; -} -input, textarea, select, -.entity_remote_subscribe { -border-color:#aaa; -} -#filter_tags ul li { -border-color:#ddd; -} - -.form_settings input.form_action-secondary { -background:none; -} - -input.submit, -#form_notice.warning #notice_text-count, -.form_settings .form_note, -.entity_remote_subscribe { -background-color:#9BB43E; -} - -input:focus, textarea:focus, select:focus, -#form_notice.warning #notice_data-text { -border-color:#9BB43E; -} -input.submit, -.entity_remote_subscribe { -color:#dddd33; -} - -a, -div.notice-options input, -.form_user_block input.submit, -.form_user_unblock input.submit, -.entity_send-a-message a, -.form_user_nudge input.submit, -.entity_nudge p, -.form_settings input.form_action-secondary { -color:#ee4400; -} - -.notice, -.profile { -border-color:#DDAA00; -} -.section .profile { -border-top-color:#aaaa66; -} - -#content .notice p.entry-content a:visited { -background-color:#fcfcfc; -} -#content .notice p.entry-content .vcard a { -background-color:#fcfffc; -} - -#aside_primary { -background-color:#DDAA00; -} - -#notice_text-count { -color:#333; -} -#form_notice.warning #notice_text-count { -color:#000; -} -#form_notice.processing #notice_action-submit { -background:#dddd33 url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; -cursor:wait; -text-indent:-9999px; -} - -#content, -#site_nav_local_views .nav, -#site_nav_local_views a, -#aside_primary { -border-color:#dddd33; -} -#content .notice, -#content .profile, -#site_nav_local_views .current a { -background-color:#dddd33; -} -#site_nav_local_views .current a { -color:#EE4400; -} -#site_nav_local_views a { -background-color:rgba(255, 255, 255, 0.2); -color:#fff; -} -#site_nav_local_views a:hover { -background-color:rgba(255, 255, 255, 0.4); -} - -.error { -background-color:#F7E8E8; -} -.success { -background-color:#EFF3DC; -} - -#anon_notice { -background-color:#aaaa66; -color:#dddd33; -border-color:#dddd33; -} - -#showstream #anon_notice { -background-color:#9BB43E; -} - -#export_data li a { -background-repeat:no-repeat; -background-position:0 45%; -} -#export_data li a.rss { -background-image:url(../../base/images/icons/icon_rss.png); -} -#export_data li a.atom { -background-image:url(../../base/images/icons/icon_atom.png); -} -#export_data li a.foaf { -background-image:url(../../base/images/icons/icon_foaf.gif); -} - -.entity_edit a, -.entity_send-a-message a, -.form_user_nudge input.submit, -.form_user_block input.submit, -.form_user_unblock input.submit, -.entity_nudge p { -background-position: 0 40%; -background-repeat: no-repeat; -background-color:transparent; -} -.form_group_join input.submit, -.form_group_leave input.submit -.form_user_subscribe input.submit, -.form_user_unsubscribe input.submit { -background-color:#9BB43E; -color:#dddd33; -} -.form_user_unsubscribe input.submit, -.form_group_leave input.submit, -.form_user_authorization input.reject { -background-color:#aaaa66; -} - -.entity_edit a { -background-image:url(../../base/images/icons/twotone/green/edit.gif); -} -.entity_send-a-message a { -background-image:url(../../base/images/icons/twotone/green/quote.gif); -} -.entity_nudge p, -.form_user_nudge input.submit { -background-image:url(../../base/images/icons/twotone/green/mail.gif); -} -.form_user_block input.submit, -.form_user_unblock input.submit { -background-image:url(../../base/images/icons/twotone/green/shield.gif); -} - -/* NOTICES */ -.notices li.over { -background-color:#fcfcfc; -} - -.notice-options .notice_reply a, -.notice-options form input.submit { -background-color:transparent; -} -.notice-options .notice_reply a { -background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; -} -.notice-options form.form_favor input.submit { -background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; -} -.notice-options form.form_disfavor input.submit { -background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; -} -.notice-options .notice_delete a { -background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; -} - -.notices div.entry-content, -.notices div.notice-options { -opacity:0.4; -} -.notices li.hover div.entry-content, -.notices li.hover div.notice-options { -opacity:1; -} -div.entry-content { -color:#333; -} -div.notice-options a, -div.notice-options input { -font-family:sans-serif; -} -.notices li.hover { -/*background-color:#fcfcfc;*/ -} -/*END: NOTICES */ - -#new_group a { -background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; -} - -.pagination .nav_prev a, -.pagination .nav_next a { -background-repeat:no-repeat; -border-color:#DDAA00; -} -.pagination .nav_prev a { -background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); -background-position:10% 45%; -} -.pagination .nav_next a { -background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); -background-position:90% 45%; -} diff --git a/theme/earthy/css/ie.css b/theme/earthy/css/ie.css deleted file mode 100644 index 2f463bb44d..0000000000 --- a/theme/earthy/css/ie.css +++ /dev/null @@ -1,9 +0,0 @@ -/* IE specific styles */ - -.notice-options input.submit { -color:#fff; -} - -#site_nav_local_views a { -background-color:#D0DFE7; -} diff --git a/theme/earthy/default-avatar-mini.png b/theme/earthy/default-avatar-mini.png deleted file mode 100644 index 38b8692b4a2f71c8de3d6a12b715df33aada5f7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 646 zcmV;10(t$3P)t7_1ao1dG5H5=fedf?I_U zERrsbGN6ogMr}` z=geF#+zTQC5di=LaBdjJM@3P-0idfKA;f20*DnA(@I8qLjEKM(3u~J8S_pAFm&<9f zSPbEC7@TwLgOn1}=@gFRpkA-LjIlSH&E_!?ePIBYs;Zr6Ga4*xpF`v&- zEEdi`SF2Su6bfC-+-EQtpin4yM0AgV_}m^LaEH4M-{d zNe9pK002AF4@7iH=bR&(&2Ehsiv@`2laNxrAB{#2)9Ew=0L!vqS=K>6*rng^e_gNF z@3`x_^;WAT4=u}|=ytns97hAt;6zjd&?=Y9n`49wheK2$*>gXpP+!1HdC8#9K|%7P#8l;_13R g5kkBIaJK9D9f4f}@hqK`?*IS*07*qoM6N<$f=KKaB>(^b diff --git a/theme/earthy/default-avatar-profile.png b/theme/earthy/default-avatar-profile.png deleted file mode 100644 index f8357d4fc296271b837b3d9911cfbc133918ef2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2853 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 MfY_K+7Z|aDy3W6;R?}) zJJa7D+8b}%q`4{D>!4paaL(^{&bi<3xi|OxZhl9J2i|dE0WSwJ z;8&o3y8I|2|D^3LB6AAh1ik=tKx{650`H~bDI%!ZcR(rC1bhe718ACt%jLrDcH?%t zsjjXjCnqQSb+v$ri3#rCzt6pU_lQIyjE#+%-9G>yipXCx_?iVMr9J?@266xz8X9P8 zYooHV@|6(Ign@wpIy*awMx%!5Z{TeaxosGd0+dqgn0n^&moHz={{8#ev17+#bDo2E zJkFUjXSj6flJR)|25b=#9i{~+rE-CvflW@QlM^RS;BvWaq&*i`u3X{NsZ&PtOA+}5 zK$|uk1vUZf+qdtvBM;Eh(!%D=n~mm2N~yO1G^JDl@G*eb>t*N8oim5o3i!0z3_V#k~=FJ5Y5fL6fe8}a?ml+uuu{^G}w$|L-;$Zs6JIj$0x~_BN z$PvQfu<=TxwzihNd-u}N&|sOw;NTz~9UY91j{}gClY`Ia!|(S~US2-$*ouk@%F4=k z^5hA?CJiVBC@U+=c;T+DE(Qk&F>ij6NQ91#4&w2+CGxtibMoZLBzb^DBEi+GR|y0H zmgXoeElpOn`8t~M;K2hfUc8vn7mvree*L9I7=(9lp?pRVhKLLsY^fGh+wHa6mLq>rRmtXN@bp62G}dHpL_uCz)C z$U;C-QBm59mz0#SXU`r>^K9F;jl8_Pls=!&$NKf_tx^KA5CGu!`|*0cGi(lrgF}Z7 zQCwVXX^w(|0uCQOJm-#8R#tN0z=3S&OkF>l&Z}3iroFwLTeoh}-`~%M4I8MhueZE^ z7}&mjJ6pGIB^V5%>pEVqmztWI1w{c1`aJY_Ja{~wg$zw1H#hgC#9diELa!s11lWxw z0d`|afZbRUU^kWo*p2_a087E#=;$cdu3aM*i=mWCMvY1-G)+s^&Gy*^NZD7@v^nFJ zEn7xYQdM$J zqX0X|X9Eq00_G&b4EX*2SC)~P4@#-D`H9idQKK4l0DXYx?%lg7JJ;3K5eNhbg+e@g z_RO3|Lqw8y$ZVf&OJ_H1=J`Z~f`S5kJ|9(8Rde`^jEoSA#f)a3A>e((QCL_wXHZE= z$!n3V0hqPWeHv2&0JwAK&Y}~_7U6K%sE&!qkj7NbX&m76>C-%a{@gBZ8S(h>V}ik; z(d+@xMC4zlGc-d(L!3Kz&L(>EBaujO{P=NnT?d!|K7;AksEB+E`~+~}!UYBf2JGUQ z7H7|%B@&4k%}+%n3^UWLRlseaLen&M?b?Ok@5kwM+CtbsG#aI|v(vn&-M~9CO?-Bu zyA}8zCnAEEc#v$kH_im?j{fjm~#(*06q~({y(4Us6jRG4bWoPoK7ce z)~s37qXxsn!{)#96Tnx%=OQvQlalTb1>gt9u>Y{fFF>Q^!yaZRr3!&Jd2!sP5vT!P pRW4Qse&@wen|>f9B54D%{{RsfdHbSpK`#IR002ovPDHLkV1m@7$GHFi diff --git a/theme/earthy/logo.png b/theme/earthy/logo.png deleted file mode 100644 index 7c68b34f61008753d12394806c3cf46f7b04effd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4988 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 Date: Thu, 14 May 2009 20:27:08 +0000 Subject: [PATCH 479/503] Updated logos to use laconica as default. --- theme/biz/logo.png | Bin 4988 -> 2228 bytes theme/cloudy/logo.png | Bin 4988 -> 2228 bytes theme/h4ck3r/logo.png | Bin 4988 -> 2228 bytes theme/otalk/logo.png | Bin 4988 -> 2228 bytes theme/pigeonthoughts/logo.png | Bin 4988 -> 2228 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/theme/biz/logo.png b/theme/biz/logo.png index 7c68b34f61008753d12394806c3cf46f7b04effd..fdead6c4a0a23614552329ee68bb0860b0200a0c 100644 GIT binary patch literal 2228 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 Date: Thu, 14 May 2009 23:43:41 +0000 Subject: [PATCH 480/503] Updated Cloudy theme default avatars and minor CSS --- theme/cloudy/css/display.css | 4 ++-- theme/cloudy/default-avatar-mini.png | Bin 1006 -> 1349 bytes theme/cloudy/default-avatar-profile.png | Bin 9026 -> 9256 bytes theme/cloudy/default-avatar-stream.png | Bin 2963 -> 3829 bytes 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/cloudy/css/display.css b/theme/cloudy/css/display.css index b87722eec1..e978896856 100644 --- a/theme/cloudy/css/display.css +++ b/theme/cloudy/css/display.css @@ -12,7 +12,7 @@ img { display:block; border:0; } a abbr { cursor: pointer; border-bottom:0; } table { border-collapse:collapse; } ol { list-style-position:inside; } -html { font-size: 100%; background-color:#fff; height:100%; } +html { font-size: 100%; background-color:#fff; } body { background-color:#fff; color:#000; @@ -126,7 +126,7 @@ margin-left:0; .form_settings label { margin-top:2px; -width:145px; +width:143px; } .form_actions label { diff --git a/theme/cloudy/default-avatar-mini.png b/theme/cloudy/default-avatar-mini.png index c0f1d411fdffd351fe16295c611f52d37be4fdf3..4fd8bd9e1951099c121ca843ef2d53f413b2a72f 100644 GIT binary patch delta 1318 zcmV+>1=;%U2gM4IFnYfMyE6ouEmGr-6o5E!TmS~M*VDpNp_5p;^s z1fkZ~V5MSxRIN%a)&vOBXsy^e3W+cv1JS+cx@6PD1e|lo}{k%4(dWzaXdeQmh*JIx% z2Dmy6bk%2PKP@S)%Q>I;$%?Ll7fWJewOVb~(PNQ8!G8z0ZNK|xgVi#!(DiYDcizyD zDf8s@(C=>e8dlDq?(X9;nH(irpbf~*$Z%6TUns9I1I_In{ouNqn$FJ7)U>o|&d#$n zn%j@-^-FzIQWGCPY6=WFFn9T;kd5gxe7)xSc$zH?5WT9YEw8P)SzkZ==FQ>VyOU3! z+WF1icz>gjnZZnw1mMf`PM`WXB4V>K z-e=Y_#GAblTq)oR(SUazmHsIc#mY?FwD5PA6p)xZ2WFf=UL zuBhF*SbUM0SuiuR5JHIF-rn%=a2{Pk2!A2O*eigDgru@QE@%^lZCu!Hd!+TBt!FuW zwwaSgqbVyZlPUJ?OP4oeKZtwx?hQ88{FJ;~08HcEmd42CU@@48&YnH1RJl&o2G5w` zC#*s~T3T8PK(E)UUDOY6ln$7z#CFXlddn*V$j{63nI9RtAtfnkm!yy^7K@B??SI;} zy1Kf!*f@*DGB`Y9-zI5-1Pdamyu7@vy*+%#0ryD~0ISs+6B9#3QBhGrK|uzCq5I!% zi3LsUwlskR1Rymv)jw*@car6UbS+P$|)fs!D_W`-n3C7s%?LnSn|;H`jx$q z-IxKHh=`&ya-!nbO`EKK+0}ZzqJL89sJeUZi0Qwf$fSc)f(V!Z07*qoM6N<$f))mfR{#J2 delta 972 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 delta 2944 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 Date: Fri, 15 May 2009 14:18:04 -0400 Subject: [PATCH 481/503] reformat action.php --- lib/action.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/action.php b/lib/action.php index 2ec9329e05..4bd41c2266 100644 --- a/lib/action.php +++ b/lib/action.php @@ -98,15 +98,15 @@ class Action extends HTMLOutputter // lawsuit Event::handle('EndShowHTML', array($this)); } if (Event::handle('StartShowHead', array($this))) { - $this->showHead(); + $this->showHead(); Event::handle('EndShowHead', array($this)); } if (Event::handle('StartShowBody', array($this))) { - $this->showBody(); + $this->showBody(); Event::handle('EndShowBody', array($this)); } if (Event::handle('StartEndHTML', array($this))) { - $this->endHTML(); + $this->endHTML(); Event::handle('EndEndHTML', array($this)); } } @@ -347,7 +347,7 @@ class Action extends HTMLOutputter // lawsuit { $this->elementStart('body', (common_current_user()) ? array('id' => $this->trimmed('action'), 'class' => 'user_in') - : array('id' => $this->trimmed('action'))); + : array('id' => $this->trimmed('action'))); $this->elementStart('div', array('id' => 'wrap')); if (Event::handle('StartShowHeader', array($this))) { $this->showHeader(); @@ -431,10 +431,10 @@ class Action extends HTMLOutputter // lawsuit _('Connect'), _('Connect to SMS, Twitter'), false, 'nav_connect'); } $this->menuItem(common_local_url('invite'), - _('Invite'), - sprintf(_('Invite friends and colleagues to join you on %s'), - common_config('site', 'name')), - false, 'nav_invitecontact'); + _('Invite'), + sprintf(_('Invite friends and colleagues to join you on %s'), + common_config('site', 'name')), + false, 'nav_invitecontact'); $this->menuItem(common_local_url('logout'), _('Logout'), _('Logout from the site'), false, 'nav_logout'); } @@ -629,7 +629,7 @@ class Action extends HTMLOutputter // lawsuit $this->elementStart('div', array('id' => 'aside_primary', 'class' => 'aside')); if (Event::handle('StartShowExportData', array($this))) { - $this->showExportData(); + $this->showExportData(); Event::handle('EndShowExportData', array($this)); } if (Event::handle('StartShowSections', array($this))) { From 14662354dc501e811dd714aa72fd8001842ee672 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 15 May 2009 14:22:49 -0400 Subject: [PATCH 482/503] add hooks for subgroupnav showing --- EVENTS.txt | 6 ++++ lib/subgroupnav.php | 68 ++++++++++++++++++++++++--------------------- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/EVENTS.txt b/EVENTS.txt index 5edf59245a..07fc446c34 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -100,6 +100,12 @@ StartPublicGroupNav: Showing the public group nav menu EndPublicGroupNav: At the end of the public group nav menu - $action: the current action +StartSubGroupNav: Showing the subscriptions group nav menu +- $action: the current action + +EndSubGroupNav: At the end of the subscriptions group nav menu +- $action: the current action + RouterInitialized: After the router instance has been initialized - $m: the Net_URL_Mapper that has just been set up diff --git a/lib/subgroupnav.php b/lib/subgroupnav.php index 31c3ea0b56..4a9b36ae8f 100644 --- a/lib/subgroupnav.php +++ b/lib/subgroupnav.php @@ -74,38 +74,44 @@ class SubGroupNav extends Widget $this->out->elementStart('ul', array('class' => 'nav')); - $this->out->menuItem(common_local_url('subscriptions', - array('nickname' => - $this->user->nickname)), - _('Subscriptions'), - sprintf(_('People %s subscribes to'), - $this->user->nickname), - $action == 'subscriptions', - 'nav_subscriptions'); - $this->out->menuItem(common_local_url('subscribers', - array('nickname' => - $this->user->nickname)), - _('Subscribers'), - sprintf(_('People subscribed to %s'), - $this->user->nickname), - $action == 'subscribers', - 'nav_subscribers'); - $this->out->menuItem(common_local_url('usergroups', - array('nickname' => - $this->user->nickname)), - _('Groups'), - sprintf(_('Groups %s is a member of'), - $this->user->nickname), - $action == 'usergroups', - 'nav_usergroups'); - if (!is_null($cur) && $this->user->id === $cur->id) { - $this->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'); + if (Event::handle('StartSubGroupNav', array($this))) { + + $this->out->menuItem(common_local_url('subscriptions', + array('nickname' => + $this->user->nickname)), + _('Subscriptions'), + sprintf(_('People %s subscribes to'), + $this->user->nickname), + $action == 'subscriptions', + 'nav_subscriptions'); + $this->out->menuItem(common_local_url('subscribers', + array('nickname' => + $this->user->nickname)), + _('Subscribers'), + sprintf(_('People subscribed to %s'), + $this->user->nickname), + $action == 'subscribers', + 'nav_subscribers'); + $this->out->menuItem(common_local_url('usergroups', + array('nickname' => + $this->user->nickname)), + _('Groups'), + sprintf(_('Groups %s is a member of'), + $this->user->nickname), + $action == 'usergroups', + 'nav_usergroups'); + if (!is_null($cur) && $this->user->id === $cur->id) { + $this->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($this)); } + $this->out->elementEnd('ul'); } } From fecb8c706dadb790c3a8c219275b4ba88e00b8ea Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 15 May 2009 15:04:58 -0400 Subject: [PATCH 483/503] Attachments and their list now provide "ajax" view. Also added a few sidebars relating tags and attachments. --- actions/attachment.php | 250 ++++++++++++++++++++++ actions/attachment_ajax.php | 141 +++++++++++++ actions/attachments.php | 292 ++++++++++++++++++++++++++ actions/attachments_ajax.php | 115 ++++++++++ actions/tag.php | 12 +- classes/File.php | 11 + classes/File_oembed.php | 11 +- classes/File_thumbnail.php | 10 + classes/Notice.php | 12 +- js/jquery.joverlay.min.js | 6 + js/util.js | 4 + lib/action.php | 12 +- lib/attachmentlist.php | 300 +++++++++++++++++++++++++++ lib/noticelist.php | 71 ++++++- lib/router.php | 14 ++ theme/base/images/icons/clip-big.png | Bin 0 -> 11245 bytes theme/base/images/icons/clip.png | Bin 0 -> 2298 bytes 17 files changed, 1243 insertions(+), 18 deletions(-) create mode 100644 actions/attachment.php create mode 100644 actions/attachment_ajax.php create mode 100644 actions/attachments.php create mode 100644 actions/attachments_ajax.php create mode 100644 js/jquery.joverlay.min.js create mode 100644 lib/attachmentlist.php create mode 100644 theme/base/images/icons/clip-big.png create mode 100644 theme/base/images/icons/clip.png diff --git a/actions/attachment.php b/actions/attachment.php new file mode 100644 index 0000000000..981882a5bb --- /dev/null +++ b/actions/attachment.php @@ -0,0 +1,250 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +//require_once INSTALLDIR.'/lib/personalgroupnav.php'; +//require_once INSTALLDIR.'/lib/feedlist.php'; +require_once INSTALLDIR.'/lib/attachmentlist.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class AttachmentAction extends Action +{ + /** + * Attachment object to show + */ + + var $attachment = null; + + /** + * Profile of the notice object + */ + +// var $profile = null; + + /** + * Avatar of the profile of the notice object + */ + +// var $avatar = null; + + /** + * Load attributes based on database arguments + * + * Loads all the DB stuff + * + * @param array $args $_REQUEST array + * + * @return success flag + */ + + function prepare($args) + { + parent::prepare($args); + + $id = $this->arg('attachment'); + + $this->attachment = File::staticGet($id); + + if (!$this->attachment) { + $this->clientError(_('No such attachment.'), 404); + return false; + } + return true; + } + + /** + * Is this action read-only? + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } + + /** + * Title of the page + * + * @return string title of the page + */ + function title() + { + $a = new Attachment($this->attachment); + return $a->title(); + } + + + + /** + * Last-modified date for page + * + * When was the content of this page last modified? Based on notice, + * profile, avatar. + * + * @return int last-modified date as unix timestamp + */ +/* + function lastModified() + { + return max(strtotime($this->notice->created), + strtotime($this->profile->modified), + ($this->avatar) ? strtotime($this->avatar->modified) : 0); + } +*/ + + /** + * An entity tag for this page + * + * Shows the ETag for the page, based on the notice ID and timestamps + * for the notice, profile, and avatar. It's weak, since we change + * the date text "one hour ago", etc. + * + * @return string etag + */ +/* + function etag() + { + $avtime = ($this->avatar) ? + strtotime($this->avatar->modified) : 0; + + return 'W/"' . implode(':', array($this->arg('action'), + common_language(), + $this->notice->id, + strtotime($this->notice->created), + strtotime($this->profile->modified), + $avtime)) . '"'; + } +*/ + + + /** + * Handle input + * + * Only handles get, so just show the page. + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + $this->showPage(); + } + + /** + * Don't show local navigation + * + * @return void + */ + + function showLocalNavBlock() + { + } + + /** + * Fill the content area of the page + * + * Shows a single notice list item. + * + * @return void + */ + + function showContent() + { + $this->elementStart('ul', array('class' => 'attachments')); + $ali = new Attachment($this->attachment, $this); + $cnt = $ali->show(); + $this->elementEnd('ul'); + } + + /** + * Don't show page notice + * + * @return void + */ + + function showPageNoticeBlock() + { + } + + /** + * Show aside: this attachments appears in what notices + * + * @return void + */ + + function showAside() { + $notice = new Notice; + $f2p = new File_to_post; + $f2p->file_id = $this->attachment->id; + $notice->joinAdd($f2p); + $notice->orderBy('created desc'); + $x = $notice->find(); + $this->elementStart('ol'); + while($notice->fetch()) { + $this->elementStart('li'); + $profile = $notice->getProfile(); + $this->element('a', array('href' => $notice->uri), $profile->nickname . ' on ' . $notice->created); + $this->elementEnd('li'); + } + $this->elementEnd('ol'); + $notice->free(); + $f2p->free(); + + $notice_tag = new Notice_tag; + $attachment = new File; + + $query = 'select tag,count(tag) as c from notice_tag join file_to_post on (notice_tag.notice_id=post_id) join notice on notice_id = notice.id where file_id=' . $notice_tag->escape($this->attachment->id) . ' group by tag order by c desc'; + + $notice_tag->query($query); + $this->elementStart('ol'); + while($notice_tag->fetch()) { + $this->elementStart('li'); + $href = common_local_url('tag', array('tag' => $notice_tag->tag)); + $this->element('a', array('href' => $href), $notice_tag->tag . ' (' . $notice_tag->c . ')'); + $this->elementEnd('li'); + } + $this->elementEnd('ol'); + } +} diff --git a/actions/attachment_ajax.php b/actions/attachment_ajax.php new file mode 100644 index 0000000000..1620b27dda --- /dev/null +++ b/actions/attachment_ajax.php @@ -0,0 +1,141 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/actions/attachment.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class Attachment_ajaxAction extends AttachmentAction +{ + /** + * Load attributes based on database arguments + * + * Loads all the DB stuff + * + * @param array $args $_REQUEST array + * + * @return success flag + */ + + function prepare($args) + { + parent::prepare($args); + if (!$this->attachment) { + $this->clientError(_('No such attachment.'), 404); + return false; + } + return true; + } + + /** + * Show page, a template method. + * + * @return nothing + */ + function showPage() + { + if (Event::handle('StartShowBody', array($this))) { + $this->showCore(); + Event::handle('EndShowBody', array($this)); + } + } + + /** + * Show core. + * + * Shows local navigation, content block and aside. + * + * @return nothing + */ + function showCore() + { + $this->elementStart('div', array('id' => 'core')); + if (Event::handle('StartShowContentBlock', array($this))) { + $this->showContentBlock(); + Event::handle('EndShowContentBlock', array($this)); + } + $this->elementEnd('div'); + } + + + + /** + * Last-modified date for page + * + * When was the content of this page last modified? Based on notice, + * profile, avatar. + * + * @return int last-modified date as unix timestamp + */ +/* + function lastModified() + { + return max(strtotime($this->notice->created), + strtotime($this->profile->modified), + ($this->avatar) ? strtotime($this->avatar->modified) : 0); + } +*/ + + /** + * An entity tag for this page + * + * Shows the ETag for the page, based on the notice ID and timestamps + * for the notice, profile, and avatar. It's weak, since we change + * the date text "one hour ago", etc. + * + * @return string etag + */ +/* + function etag() + { + $avtime = ($this->avatar) ? + strtotime($this->avatar->modified) : 0; + + return 'W/"' . implode(':', array($this->arg('action'), + common_language(), + $this->notice->id, + strtotime($this->notice->created), + strtotime($this->profile->modified), + $avtime)) . '"'; + } +*/ +} + diff --git a/actions/attachments.php b/actions/attachments.php new file mode 100644 index 0000000000..6b31c839da --- /dev/null +++ b/actions/attachments.php @@ -0,0 +1,292 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +//require_once INSTALLDIR.'/lib/personalgroupnav.php'; +//require_once INSTALLDIR.'/lib/feedlist.php'; +require_once INSTALLDIR.'/lib/attachmentlist.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class AttachmentsAction extends Action +{ + /** + * Notice object to show + */ + + var $notice = null; + + /** + * Profile of the notice object + */ + + var $profile = null; + + /** + * Avatar of the profile of the notice object + */ + + var $avatar = null; + + /** + * Is this action read-only? + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } + + /** + * Last-modified date for page + * + * When was the content of this page last modified? Based on notice, + * profile, avatar. + * + * @return int last-modified date as unix timestamp + */ + + function lastModified() + { + return max(strtotime($this->notice->created), + strtotime($this->profile->modified), + ($this->avatar) ? strtotime($this->avatar->modified) : 0); + } + + /** + * An entity tag for this page + * + * Shows the ETag for the page, based on the notice ID and timestamps + * for the notice, profile, and avatar. It's weak, since we change + * the date text "one hour ago", etc. + * + * @return string etag + */ + + function etag() + { + $avtime = ($this->avatar) ? + strtotime($this->avatar->modified) : 0; + + return 'W/"' . implode(':', array($this->arg('action'), + common_language(), + $this->notice->id, + strtotime($this->notice->created), + strtotime($this->profile->modified), + $avtime)) . '"'; + } + + /** + * Title of the page + * + * @return string title of the page + */ + + function title() + { + return sprintf(_('%1$s\'s status on %2$s'), + $this->profile->nickname, + common_exact_date($this->notice->created)); + } + + + /** + * Load attributes based on database arguments + * + * Loads all the DB stuff + * + * @param array $args $_REQUEST array + * + * @return success flag + */ + + function prepare($args) + { + parent::prepare($args); + + $id = $this->arg('notice'); + + $this->notice = Notice::staticGet($id); + + if (!$this->notice) { + $this->clientError(_('No such notice.'), 404); + return false; + } + + +/* +// STOP if there are no attachments +// maybe even redirect if there's a single one +// RYM FIXME TODO + $this->clientError(_('No such attachment.'), 404); + return false; + +*/ + + + + + $this->profile = $this->notice->getProfile(); + + if (!$this->profile) { + $this->serverError(_('Notice has no profile'), 500); + return false; + } + + $this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE); + return true; + } + + + + /** + * Handle input + * + * Only handles get, so just show the page. + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + + if ($this->notice->is_local == 0) { + if (!empty($this->notice->url)) { + common_redirect($this->notice->url, 301); + } else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) { + common_redirect($this->notice->uri, 301); + } + } else { + $f2p = new File_to_post; + $f2p->post_id = $this->notice->id; + $file = new File; + $file->joinAdd($f2p); + $file->selectAdd(); + $file->selectAdd('file.id as id'); + $count = $file->find(true); + if (!$count) return; + if (1 === $count) { + common_redirect(common_local_url('attachment', array('attachment' => $file->id)), 301); + } else { + $this->showPage(); + } + } + } + + /** + * Don't show local navigation + * + * @return void + */ + + function showLocalNavBlock() + { + } + + /** + * Fill the content area of the page + * + * Shows a single notice list item. + * + * @return void + */ + + function showContent() + { + $al = new AttachmentList($this->notice, $this); + $cnt = $al->show(); + } + + /** + * Don't show page notice + * + * @return void + */ + + function showPageNoticeBlock() + { + } + + /** + * Don't show aside + * + * @return void + */ + + function showAside() { + } + + /** + * Extra content + * + * We show the microid(s) for the author, if any. + * + * @return void + */ + + function extraHead() + { + $user = User::staticGet($this->profile->id); + + if (!$user) { + return; + } + + if ($user->emailmicroid && $user->email && $this->notice->uri) { + $id = new Microid('mailto:'. $user->email, + $this->notice->uri); + $this->element('meta', array('name' => 'microid', + 'content' => $id->toString())); + } + + if ($user->jabbermicroid && $user->jabber && $this->notice->uri) { + $id = new Microid('xmpp:', $user->jabber, + $this->notice->uri); + $this->element('meta', array('name' => 'microid', + 'content' => $id->toString())); + } + } +} + diff --git a/actions/attachments_ajax.php b/actions/attachments_ajax.php new file mode 100644 index 0000000000..402d8b5e79 --- /dev/null +++ b/actions/attachments_ajax.php @@ -0,0 +1,115 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +//require_once INSTALLDIR.'/lib/personalgroupnav.php'; +//require_once INSTALLDIR.'/lib/feedlist.php'; +require_once INSTALLDIR.'/actions/attachments.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class Attachments_ajaxAction extends AttachmentsAction +{ + function showContent() + { + } + + /** + * Fill the content area of the page + * + * Shows a single notice list item. + * + * @return void + */ + + function showContentBlock() + { + $al = new AttachmentList($this->notice, $this); + $cnt = $al->show(); + } + + /** + * Extra content + * + * We show the microid(s) for the author, if any. + * + * @return void + */ + + function extraHead() + { + } + + + /** + * Show page, a template method. + * + * @return nothing + */ + function showPage() + { + if (Event::handle('StartShowBody', array($this))) { + $this->showCore(); + Event::handle('EndShowBody', array($this)); + } + } + + /** + * Show core. + * + * Shows local navigation, content block and aside. + * + * @return nothing + */ + function showCore() + { + $this->elementStart('div', array('id' => 'core')); + if (Event::handle('StartShowContentBlock', array($this))) { + $this->showContentBlock(); + Event::handle('EndShowContentBlock', array($this)); + } + $this->elementEnd('div'); + } + + + + +} + diff --git a/actions/tag.php b/actions/tag.php index 02f3e35225..2202f9bb07 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -49,8 +49,18 @@ class TagAction extends Action { $pop = new PopularNoticeSection($this); $pop->show(); - } + $notice_tag = new Notice_tag; + $query = 'select file_id, count(file_id) as c from notice_tag join file_to_post on post_id = notice_id where tag="' . $notice_tag->escape($this->tag) . '" group by file_id order by c desc'; + $notice_tag->query($query); + $this->elementStart('ol'); + while ($notice_tag->fetch()) { + $this->elementStart('li'); + $this->element('a', array('class' => 'attachment', 'href' => common_local_url('attachment', array('attachment' => $notice_tag->file_id))), "Attachment tagged {$notice_tag->c} times"); + $this->elementEnd('li'); + } + $this->elementEnd('ol'); + } function title() { diff --git a/classes/File.php b/classes/File.php index 2ddc5deb8b..e5913115b7 100644 --- a/classes/File.php +++ b/classes/File.php @@ -54,6 +54,17 @@ class File extends Memcached_DataObject return 'http://www.facebook.com/login.php' === $url; } + function getAttachments($post_id) { + $query = "select file.* from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $this->escape($post_id); + $this->query($query); + $att = array(); + while ($this->fetch()) { + $att[] = clone($this); + } + $this->free(); + return $att; + } + function saveNew($redir_data, $given_url) { $x = new File; $x->url = $given_url; diff --git a/classes/File_oembed.php b/classes/File_oembed.php index 2846f49dbc..f1b2cb13c0 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -78,18 +78,9 @@ class File_oembed extends Memcached_DataObject if (!empty($data['author_url'])) $file_oembed->author_url = $data['author_url']; if (!empty($data['url'])) $file_oembed->url = $data['url']; $file_oembed->insert(); - if (!empty($data['thumbnail_url'])) { - $tn = new File_thumbnail; - $tn->file_id = $file_id; - $tn->url = $data['thumbnail_url']; - $tn->width = intval($data['thumbnail_width']); - $tn->height = intval($data['thumbnail_height']); - $tn->insert(); + File_thumbnail::saveNew($data, $file_id); } - - - } } diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php index 7b906a07ca..1a65b92c90 100644 --- a/classes/File_thumbnail.php +++ b/classes/File_thumbnail.php @@ -42,4 +42,14 @@ class File_thumbnail extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function saveNew($data, $file_id) { + $tn = new File_thumbnail; + $tn->file_id = $file_id; + $tn->url = $data['thumbnail_url']; + $tn->width = intval($data['thumbnail_width']); + $tn->height = intval($data['thumbnail_height']); + $tn->insert(); + } } + diff --git a/classes/Notice.php b/classes/Notice.php index c2fa2d19e5..30508070e5 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -124,8 +124,6 @@ class Notice extends Memcached_DataObject $profile = Profile::staticGet($profile_id); -// $final = common_shorten_links($content); - if (!$profile) { common_log(LOG_ERR, 'Problem saving notice. Unknown user.'); return _('Problem saving notice. Unknown user.'); @@ -279,6 +277,16 @@ class Notice extends Memcached_DataObject return true; } + function hasAttachments() { + $post = clone($this); + $query = "select count(file_id) as n_attachments from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $post->escape($this->id); + $post->query($query); + $post->fetch(); + $n_attachments = intval($post->n_attachments); + $post->free(); + return $n_attachments; + } + function blowCaches($blowLast=false) { $this->blowSubsCache($blowLast); diff --git a/js/jquery.joverlay.min.js b/js/jquery.joverlay.min.js new file mode 100644 index 0000000000..c9168506a5 --- /dev/null +++ b/js/jquery.joverlay.min.js @@ -0,0 +1,6 @@ +/* Copyright (c) 2009 Alvaro A. Lima Jr http://alvarojunior.com/jquery/joverlay.html + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * Version: 0.6 (Abr 23, 2009) + * Requires: jQuery 1.3+ + */ +(function($){var f=$.browser.msie&&$.browser.version==6.0;var g=null;$.fn.jOverlay=function(b){var b=$.extend({},$.fn.jOverlay.options,b);if(g!=null){clearTimeout(g)}var c=this.is('*')?this:'#jOverlayContent';var d=f?'absolute':'fixed';var e=b.imgLoading?"":'';$('body').prepend(e+"

      "+"
    • ', + $logout_url, $title, $logout_url, $text); + + $action->raw($html); + + } + else { + if (!common_config('site', 'closed')) { + $action->menuItem(common_local_url('register'), + _('Register'), _('Create an account'), false, 'nav_register'); + } + $action->menuItem(common_local_url('openidlogin'), + _('OpenID'), _('Login with OpenID'), false, 'nav_openid'); + $action->menuItem(common_local_url('login'), + _('Login'), _('Login to the site'), false, 'nav_login'); + } + + $action->menuItem(common_local_url('doc', array('title' => 'help')), + _('Help'), _('Help me!'), false, 'nav_help'); + $action->menuItem(common_local_url('peoplesearch'), + _('Search'), _('Search for people or text'), false, 'nav_search'); + + // Tack on "Connect with Facebook" button + + // XXX: Maybe this looks bad and should not go here. Where should it go? + + if (!$user) { + $action->elementStart('li'); + $action->element('fb:login-button', array('onlogin' => 'refresh_page()', + 'length' => 'long')); + $action->elementEnd('li'); + } + + return false; + } + + function checkFacebookUser() { + + try { + + $facebook = getFacebook(); + $fbuid = $facebook->get_loggedin_user(); + $user = common_current_user(); + + // If you're a Facebook user and you're logged in do nothing + + // If you're a Facebook user and you're not logged in + // redirect to Facebook connect login page because that means you have clicked + // the 'connect with Facebook' button and have cookies + + if ($fbuid > 0) { + + if ($facebook->api_client->users_isAppUser($fbuid) || + $facebook->api_client->added) { + + // user should be connected... + + common_debug("Facebook user found: $fbuid"); + + if ($user) { + common_debug("Facebook user is logged in."); + return; + + } else { + common_debug("Facebook user is NOT logged in."); + common_redirect(common_local_url('fbconnectlogin'), 303); + } + + } else { + common_debug("No Facebook connect user found."); + } + } + + } catch (Exception $e) { + common_debug('Expired FB session.'); + } + + } + + function onStartLogout($action) + { + common_debug("onEndLogout()"); + + common_set_user(null); + common_real_login(false); // not logged in + common_forgetme(); // don't log back in! + + try { + + $facebook = getFacebook(); + $fbuid = $facebook->get_loggedin_user(); + + // XXX: ARGGGH this doesn't work right! + + if ($fbuid) { + $facebook->expire_session(); + $facebook->logout(common_local_url('public')); + } + + } catch (Exception $e) { + common_debug('Problem expiring FB session'); + } + + common_debug("logged out."); + + return false; + } + +} + + diff --git a/plugins/FBConnect/xd_receiver.htm b/plugins/FBConnect/xd_receiver.htm new file mode 100644 index 0000000000..43fb2c4e48 --- /dev/null +++ b/plugins/FBConnect/xd_receiver.htm @@ -0,0 +1,10 @@ + + + + cross domain receiver page + + + + + From f3ea79a12a7bdf0d4efcd7eb706d25ae81b7fad9 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sun, 17 May 2009 00:05:07 -0400 Subject: [PATCH 491/503] Added site path field to installer + fancy URL javascript auto-detection. --- index.php | 4 ++++ install.php | 31 ++++++++++++++++++++++++++----- js/install.js | 18 ++++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 js/install.js diff --git a/index.php b/index.php index e24bde9179..cfef211896 100644 --- a/index.php +++ b/index.php @@ -63,6 +63,10 @@ function handleError($error) function main() { + // quick check for fancy URL auto-detection support in installer. + if ('/check-fancy' === $_SERVER['REDIRECT_URL']) { + die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs."); + } global $user, $action, $config; if (!_have_config()) { diff --git a/install.php b/install.php index 66e8e87124..32915200b2 100644 --- a/install.php +++ b/install.php @@ -86,7 +86,8 @@ function checkExtension($name) function showForm() { -?> + $config_path = htmlentities(trim(dirname($_SERVER['REQUEST_URI']), '/')); + echo<< @@ -108,11 +109,21 @@ function showForm()

      The name of your site

    • + + enable
      + disable
      +

      Enable fancy (pretty) URLs. Auto-detection failed, it depends on Javascript.

      +
    • Database hostname

    • +
    • + + +

      Site path, following the "/" after the domain name in the URL. Empty is fine. Field should be filled automatically.

      +
    • @@ -132,7 +143,8 @@ function showForm() -
      Page notice
      @@ -225,29 +239,34 @@ function handlePost() } updateStatus("Writing config file..."); $sqlUrl = "mysqli://$username:$password@$host/$database"; - $res = writeConf($sitename, $sqlUrl); + $res = writeConf($sitename, $sqlUrl, $fancy, $path); if (!$res) { updateStatus("Can't write config file.", true); showForm(); return; } updateStatus("Done!"); + if ($path) $path .= '/'; + updateStatus("You can visit your new Laconica site + +
      diff --git a/js/install.js b/js/install.js new file mode 100644 index 0000000000..32a54111e2 --- /dev/null +++ b/js/install.js @@ -0,0 +1,18 @@ +$(document).ready(function(){ + $.ajax({url:'check-fancy', + type:'GET', + success:function(data, textStatus) { + $('#fancy-enable').attr('checked', true); + $('#fancy-disable').attr('checked', false); + $('#fancy-form_guide').text(data); + }, + error:function(XMLHttpRequest, textStatus, errorThrown) { + $('#fancy-enable').attr('checked', false); + $('#fancy-disable').attr('checked', true); + $('#fancy-enable').attr('disabled', true); + $('#fancy-disable').attr('disabled', true); + $('#fancy-form_guide').text("Fancy URL support detection failed, disabling this option. Make sure you renamed htaccess.sample to .htaccess."); + } + }); +}); + From 5897dfa4c37d6a44bcde5dc7569c8b0d30f21b84 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sun, 17 May 2009 22:06:08 -0400 Subject: [PATCH 492/503] Refactored new sections code to proper classes and added notice link to links in notice sections. --- actions/attachment.php | 53 +++----------------- actions/tag.php | 13 +---- classes/Notice.php | 6 +-- config.php.sample | 6 +++ index.php | 2 +- lib/attachmentnoticesection.php | 75 ++++++++++++++++++++++++++++ lib/attachmentsection.php | 80 +++++++++++++++++++++++++++++ lib/attachmenttagcloudsection.php | 83 +++++++++++++++++++++++++++++++ lib/frequentattachmentsection.php | 66 ++++++++++++++++++++++++ lib/noticesection.php | 35 +++++++++++-- lib/popularnoticesection.php | 2 +- 11 files changed, 354 insertions(+), 67 deletions(-) create mode 100644 lib/attachmentnoticesection.php create mode 100644 lib/attachmentsection.php create mode 100644 lib/attachmenttagcloudsection.php create mode 100644 lib/frequentattachmentsection.php diff --git a/actions/attachment.php b/actions/attachment.php index 981882a5bb..b9187ff081 100644 --- a/actions/attachment.php +++ b/actions/attachment.php @@ -53,18 +53,6 @@ class AttachmentAction extends Action var $attachment = null; - /** - * Profile of the notice object - */ - -// var $profile = null; - - /** - * Avatar of the profile of the notice object - */ - -// var $avatar = null; - /** * Load attributes based on database arguments * @@ -112,8 +100,6 @@ class AttachmentAction extends Action return $a->title(); } - - /** * Last-modified date for page * @@ -213,38 +199,11 @@ class AttachmentAction extends Action * * @return void */ - - function showAside() { - $notice = new Notice; - $f2p = new File_to_post; - $f2p->file_id = $this->attachment->id; - $notice->joinAdd($f2p); - $notice->orderBy('created desc'); - $x = $notice->find(); - $this->elementStart('ol'); - while($notice->fetch()) { - $this->elementStart('li'); - $profile = $notice->getProfile(); - $this->element('a', array('href' => $notice->uri), $profile->nickname . ' on ' . $notice->created); - $this->elementEnd('li'); - } - $this->elementEnd('ol'); - $notice->free(); - $f2p->free(); - - $notice_tag = new Notice_tag; - $attachment = new File; - - $query = 'select tag,count(tag) as c from notice_tag join file_to_post on (notice_tag.notice_id=post_id) join notice on notice_id = notice.id where file_id=' . $notice_tag->escape($this->attachment->id) . ' group by tag order by c desc'; - - $notice_tag->query($query); - $this->elementStart('ol'); - while($notice_tag->fetch()) { - $this->elementStart('li'); - $href = common_local_url('tag', array('tag' => $notice_tag->tag)); - $this->element('a', array('href' => $href), $notice_tag->tag . ' (' . $notice_tag->c . ')'); - $this->elementEnd('li'); - } - $this->elementEnd('ol'); + function showSections() { + $ns = new AttachmentNoticeSection($this); + $ns->show(); + $atcs = new AttachmentTagCloudSection($this); + $atcs->show(); } } + diff --git a/actions/tag.php b/actions/tag.php index 2202f9bb07..47420e4c33 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -49,17 +49,8 @@ class TagAction extends Action { $pop = new PopularNoticeSection($this); $pop->show(); - - $notice_tag = new Notice_tag; - $query = 'select file_id, count(file_id) as c from notice_tag join file_to_post on post_id = notice_id where tag="' . $notice_tag->escape($this->tag) . '" group by file_id order by c desc'; - $notice_tag->query($query); - $this->elementStart('ol'); - while ($notice_tag->fetch()) { - $this->elementStart('li'); - $this->element('a', array('class' => 'attachment', 'href' => common_local_url('attachment', array('attachment' => $notice_tag->file_id))), "Attachment tagged {$notice_tag->c} times"); - $this->elementEnd('li'); - } - $this->elementEnd('ol'); + $freqatt = new FrequentAttachmentSection($this); + $freqatt->show(); } function title() diff --git a/classes/Notice.php b/classes/Notice.php index 30508070e5..f6ac4f7802 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -134,7 +134,7 @@ class Notice extends Memcached_DataObject return _('Too many notices too fast; take a breather and post again in a few minutes.'); } - if (common_config('site', 'dupelimit') > 0 && !Notice::checkDupes($profile_id, $final)) { + if (common_config('site', 'dupelimit') > 0 && !Notice::checkDupes($profile_id, $content)) { common_log(LOG_WARNING, 'Dupe posting by profile #' . $profile_id . '; throttled.'); return _('Too many duplicate messages too quickly; take a breather and post again in a few minutes.'); } @@ -278,8 +278,8 @@ class Notice extends Memcached_DataObject } function hasAttachments() { - $post = clone($this); - $query = "select count(file_id) as n_attachments from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $post->escape($this->id); + $post = clone $this; + $query = "select count(file_id) as n_attachments from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $post->escape($post->id); $post->query($query); $post->fetch(); $n_attachments = intval($post->n_attachments); diff --git a/config.php.sample b/config.php.sample index 0e6bf0e5f6..826b086a3b 100644 --- a/config.php.sample +++ b/config.php.sample @@ -33,6 +33,12 @@ $config['site']['path'] = 'laconica'; #Make the site invisible to non-logged-in users #$config['site']['private'] = true; +# 'direct' for direct notice links in sections +# 'attachment' for notice attachment links in sections +# left undefined, no link is showed +#$config['site']['notice_link'] = 'attachment'; +#$config['site']['notice_link'] = 'direct'; + # If you want logging sent to a file instead of syslog #$config['site']['logfile'] = '/tmp/laconica.log'; diff --git a/index.php b/index.php index cfef211896..1b4fbf81ba 100644 --- a/index.php +++ b/index.php @@ -64,7 +64,7 @@ function handleError($error) function main() { // quick check for fancy URL auto-detection support in installer. - if ('/check-fancy' === $_SERVER['REDIRECT_URL']) { + if (isset($_SERVER['REDIRECT_URL']) && ('/check-fancy' === $_SERVER['REDIRECT_URL'])) { die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs."); } global $user, $action, $config; diff --git a/lib/attachmentnoticesection.php b/lib/attachmentnoticesection.php new file mode 100644 index 0000000000..eb31763764 --- /dev/null +++ b/lib/attachmentnoticesection.php @@ -0,0 +1,75 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * FIXME + * + * These are the widgets that show interesting data about a person * group, or site. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class AttachmentNoticeSection extends NoticeSection +{ + function showContent() { + parent::showContent(); + return false; + } + + function getNotices() + { + $notice = new Notice; + $f2p = new File_to_post; + $f2p->file_id = $this->out->attachment->id; + $notice->joinAdd($f2p); + $notice->orderBy('created desc'); + $notice->selectAdd('post_id as id'); + $notice->find(); + return $notice; + } + + function title() + { + return _('Notices where this attachment appears'); + } + + function divId() + { + return 'popular_notices'; + } +} + diff --git a/lib/attachmentsection.php b/lib/attachmentsection.php new file mode 100644 index 0000000000..20e620b9b6 --- /dev/null +++ b/lib/attachmentsection.php @@ -0,0 +1,80 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +define('ATTACHMENTS_PER_SECTION', 6); + +/** + * Base class for sections showing lists of attachments + * + * These are the widgets that show interesting data about a person + * group, or site. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class AttachmentSection extends Section +{ + function showContent() + { + $attachments = $this->getAttachments(); + + $cnt = 0; + + $this->out->elementStart('ul', 'attachments'); + + while ($attachments->fetch() && ++$cnt <= ATTACHMENTS_PER_SECTION) { + $this->showAttachment($attachments); + } + + $this->out->elementEnd('ul'); + + return ($cnt > ATTACHMENTS_PER_SECTION); + } + + function getAttachments() + { + return null; + } + + function showAttachment($attachment) + { + $this->out->elementStart('li'); + $this->out->element('a', array('class' => 'attachment', 'href' => common_local_url('attachment', array('attachment' => $attachment->file_id))), "Attachment tagged {$attachment->c} times"); + $this->out->elementEnd('li'); + } +} + diff --git a/lib/attachmenttagcloudsection.php b/lib/attachmenttagcloudsection.php new file mode 100644 index 0000000000..50bfceccb0 --- /dev/null +++ b/lib/attachmenttagcloudsection.php @@ -0,0 +1,83 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Attachment tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class AttachmentTagCloudSection extends TagCloudSection +{ + function title() + { + return _('Tags for this attachment'); + } + + function showTag($tag, $weight, $relative) + { + if ($relative > 0.5) { + $rel = 'tag-cloud-7'; + } else if ($relative > 0.4) { + $rel = 'tag-cloud-6'; + } else if ($relative > 0.3) { + $rel = 'tag-cloud-5'; + } else if ($relative > 0.2) { + $rel = 'tag-cloud-4'; + } else if ($relative > 0.1) { + $rel = 'tag-cloud-3'; + } else if ($relative > 0.05) { + $rel = 'tag-cloud-2'; + } else { + $rel = 'tag-cloud-1'; + } + + $this->out->elementStart('li', $rel); + $this->out->element('a', array('href' => $this->tagUrl($tag)), + $tag); + $this->out->elementEnd('li'); + } + + function getTags() + { + $notice_tag = new Notice_tag; + $query = 'select tag,count(tag) as weight from notice_tag join file_to_post on (notice_tag.notice_id=post_id) join notice on notice_id = notice.id where file_id=' . $notice_tag->escape($this->out->attachment->id) . ' group by tag order by weight desc'; + $notice_tag->query($query); + return $notice_tag; + } +} + diff --git a/lib/frequentattachmentsection.php b/lib/frequentattachmentsection.php new file mode 100644 index 0000000000..0ce0d18714 --- /dev/null +++ b/lib/frequentattachmentsection.php @@ -0,0 +1,66 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * FIXME + * + * These are the widgets that show interesting data about a person + * group, or site. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class FrequentAttachmentSection extends AttachmentSection +{ + function getAttachments() { + $notice_tag = new Notice_tag; + $query = 'select file_id, count(file_id) as c from notice_tag join file_to_post on post_id = notice_id where tag="' . $notice_tag->escape($this->out->tag) . '" group by file_id order by c desc'; + $notice_tag->query($query); + return $notice_tag; + } + + function title() + { + return sprintf(_('Attachments frequently tagged with %s'), $this->out->tag); + } + + function divId() + { + return 'frequent_attachments'; + } +} + diff --git a/lib/noticesection.php b/lib/noticesection.php index 94c2738efd..37aafdaf6c 100644 --- a/lib/noticesection.php +++ b/lib/noticesection.php @@ -51,17 +51,13 @@ class NoticeSection extends Section function showContent() { $notices = $this->getNotices(); - $cnt = 0; - $this->out->elementStart('ul', 'notices'); - while ($notices->fetch() && ++$cnt <= NOTICES_PER_SECTION) { $this->showNotice($notices); } $this->out->elementEnd('ul'); - return ($cnt > NOTICES_PER_SECTION); } @@ -100,6 +96,37 @@ 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'); if (!empty($notice->value)) { $this->out->elementStart('p'); diff --git a/lib/popularnoticesection.php b/lib/popularnoticesection.php index a8d47ef542..375d5538be 100644 --- a/lib/popularnoticesection.php +++ b/lib/popularnoticesection.php @@ -51,7 +51,7 @@ class PopularNoticeSection extends NoticeSection if (common_config('db', 'type') == 'pgsql') { $weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))'; if (!empty($this->out->tag)) { - $tag = pg_escape_string($this->tag); + $tag = pg_escape_string($this->out->tag); } } else { $weightexpr='sum(exp(-(now() - fave.modified) / %s))'; From 806200379d2e35a5cbf5ce4940474e1cbdd1f1a0 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 18 May 2009 20:10:46 +0000 Subject: [PATCH 493/503] Dynamic color updates to page elements when user picks a color. Using JSON to create swatches in HTML output. --- actions/designsettings.php | 73 ++++++++++++++++++++-------------- js/farbtastic/farbtastic.go.js | 69 +++++++++++++++++++++++++++++--- 2 files changed, 107 insertions(+), 35 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index cdd950e78c..0deb3f6847 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -76,7 +76,6 @@ class DesignsettingsAction extends AccountSettingsAction 'action' => common_local_url('designsettings'))); $this->elementStart('fieldset'); -// $this->element('legend', null, _('Design settings')); $this->hidden('token', common_session_token()); $this->elementStart('fieldset', array('id' => 'settings_design_background-image')); @@ -91,28 +90,46 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementStart('fieldset', array('id' => 'settings_design_color')); $this->element('legend', null, _('Change colours')); $this->elementStart('ul', 'form_data'); - $this->elementStart('li'); - $this->input('color-1', _('Background color'), '#F0F2F5', null); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('color-2', _('Content background color'), '#FFFFFF', null); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('color-3', _('Sidebar background color'), '#CEE1E9', null); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('color-4', _('Text color'), '#000000', null); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->input('color-5', _('Link color'), '#002E6E', null); - $this->elementEnd('li'); + + //This is a JSON object in the DB field. Here for testing. Remove later. + $userSwatch = '{"body":{"background-color":"#F0F2F5"}, + "#content":{"background-color":"#FFFFFF"}, + "#aside_primary":{"background-color":"#CEE1E9"}, + "html body":{"color":"#000000"}, + "a":{"color":"#002E6E"}}'; + + //Default theme swatch -- Where should this be stored? + $defaultSwatch = array('body' => array('background-color' => '#F0F2F5'), + '#content' => array('background-color' => '#FFFFFF'), + '#aside_primary' => array('background-color' => '#CEE1E9'), + 'html body' => array('color' => '#000000'), + 'a' => array('color' => '#002E6E')); + + $userSwatch = ($userSwatch) ? json_decode($userSwatch, true) : $defaultSwatch; + + $s = 0; + $labelSwatch = array('Background color', + 'Content background color', + 'Sidebar background color', + 'Text color', + 'Link color'); + foreach($userSwatch as $propertyvalue => $value) { + $foo = array_values($value); //Is this necessary? $value[0] doesn't work because of invalid key + $this->elementStart('li'); + $this->input("swatch-".$s, $labelSwatch[$s], $foo[0]); + $this->elementEnd('li'); + $s++; + } + $this->elementEnd('ul'); - $this->element('div', array('id' => 'color-picker')); $this->elementEnd('fieldset'); - $this->submit('save', _('Save')); - +/*TODO: Check submitted form values: +json_encode(form values) +if submitted Swatch == DefaultSwatch, don't store in DB. +else store in BD +*/ $this->elementEnd('fieldset'); $this->elementEnd('form'); @@ -187,7 +204,7 @@ class DesignsettingsAction extends AccountSettingsAction /** - * Add the jCrop stylesheet + * Add the Farbtastic stylesheet * * @return void */ @@ -205,7 +222,7 @@ class DesignsettingsAction extends AccountSettingsAction } /** - * Add the jCrop scripts + * Add the Farbtastic scripts * * @return void */ @@ -214,14 +231,12 @@ class DesignsettingsAction extends AccountSettingsAction { parent::showScripts(); -// if ($this->mode == 'crop') { - $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); - $farbtasticGo = common_path('js/farbtastic/farbtastic.go.js'); + $farbtasticPack = common_path('js/farbtastic/farbtastic.js'); + $farbtasticGo = common_path('js/farbtastic/farbtastic.go.js'); - $this->element('script', array('type' => 'text/javascript', - 'src' => $farbtasticPack)); - $this->element('script', array('type' => 'text/javascript', - 'src' => $farbtasticGo)); -// } + $this->element('script', array('type' => 'text/javascript', + 'src' => $farbtasticPack)); + $this->element('script', array('type' => 'text/javascript', + 'src' => $farbtasticGo)); } } diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js index 21a1530bca..64dd7db204 100644 --- a/js/farbtastic/farbtastic.go.js +++ b/js/farbtastic/farbtastic.go.js @@ -1,10 +1,67 @@ $(document).ready(function() { - var f = $.farbtastic('#color-picker'); - var colors = $('#settings_design_color input'); + function UpdateColors(e) { + var S = f.linked; + var C = f.color; - colors - .each(function () { f.linkTo(this); }) - .focus(function() { - f.linkTo(this); + if (S && S.value && S.value != C) { + UpdateSwatch(S); + + switch (parseInt(f.linked.id.slice(-1))) { + case 1: default: + $('body').css({'background-color':C}); + break; + case 2: + $('#content').css({'background-color':C}); + break; + case 3: + $('#aside_primary').css({'background-color':C}); + break; + case 4: + $('body').css({'color':C}); + break; + case 5: + $('a').css({'color':C}); + break; + } + S.value = C; + } + } + + function UpdateFarbtastic(e) { + f.linked = e; + f.setColor(e.value); + } + + function UpdateSwatch(e) { + $(e).css({ + "background-color": e.value, + "color": f.hsl[2] > 0.5 ? "#000": "#fff" }); + } + + $('#settings_design_color').append('
      '); + $('#color-picker').hide(); + + var f = $.farbtastic('#color-picker', UpdateColors); + var swatches = $('#settings_design_color input'); + + swatches + .each(UpdateColors) + + .blur(function() { + $(this).val($(this).val().toUpperCase()); + }) + + .focus(function() { + $('#color-picker').show(); + UpdateFarbtastic(this); + }) + + .change(function() { + UpdateFarbtastic(this); + UpdateSwatch(this); + }).change() + + ; + }); From 0271859c2425daff6fbaeac74aee6d6a9fcdce16 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 18 May 2009 17:18:57 -0400 Subject: [PATCH 494/503] Added personal tag page: http://example.com/MY_NICK/tag/A_TAG --- actions/showstream.php | 7 +++++- classes/Notice.php | 8 +++--- classes/Profile.php | 54 ++++++++++++++++++++++++++++++++++++++--- classes/User.php | 11 ++++++++- lib/profileaction.php | 13 +++++----- lib/router.php | 5 ++++ lib/tagcloudsection.php | 6 ++++- 7 files changed, 88 insertions(+), 16 deletions(-) diff --git a/actions/showstream.php b/actions/showstream.php index 82665e5b8b..1654f589c6 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -68,6 +68,9 @@ class ShowstreamAction extends ProfileAction } else { $base = $this->user->nickname; } + if (!empty($this->tag)) { + $base .= sprintf(_(' tagged %s'), $this->tag); + } if ($this->page == 1) { return $base; @@ -363,7 +366,9 @@ class ShowstreamAction extends ProfileAction function showNotices() { - $notice = $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); + $notice = empty($this->tag) + ? $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1) + : $this->user->getTaggedNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1, 0, 0, null, $this->tag); $pnl = new ProfileNoticeList($notice, $this); $cnt = $pnl->show(); diff --git a/classes/Notice.php b/classes/Notice.php index f6ac4f7802..1b5c0ab0a5 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1024,7 +1024,7 @@ class Notice extends Memcached_DataObject } } - function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null, $tag=null) { $cache = common_memcache(); @@ -1032,7 +1032,7 @@ class Notice extends Memcached_DataObject $since_id != 0 || $before_id != 0 || !is_null($since) || ($offset + $limit) > NOTICE_CACHE_WINDOW) { return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id, - $before_id, $since))); + $before_id, $since, $tag))); } $idkey = common_cache_key($cachekey); @@ -1052,7 +1052,7 @@ class Notice extends Memcached_DataObject $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))); + $last_id, 0, null, $tag))); $new_window = array_merge($new_ids, $window); @@ -1067,7 +1067,7 @@ class Notice extends Memcached_DataObject } $window = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW, - 0, 0, null))); + 0, 0, null, $tag))); $windowstr = implode(',', $window); diff --git a/classes/Profile.php b/classes/Profile.php index ae5641d79d..afc0ea4f74 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -153,18 +153,66 @@ class Profile extends Memcached_DataObject return null; } - function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) + function getTaggedNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null, $tag=null) + { + // XXX: I'm not sure this is going to be any faster. It probably isn't. + $ids = Notice::stream(array($this, '_streamTaggedDirect'), + array(), + 'profile:notice_ids:' . $this->id, + $offset, $limit, $since_id, $before_id, $since, $tag); + common_debug(print_r($ids, true)); + return Notice::getStreamByIds($ids); + } + + function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) { // XXX: I'm not sure this is going to be any faster. It probably isn't. $ids = Notice::stream(array($this, '_streamDirect'), array(), 'profile:notice_ids:' . $this->id, - $offset, $limit, $since_id, $before_id); + $offset, $limit, $since_id, $before_id, $since); return Notice::getStreamByIds($ids); } - function _streamDirect($offset, $limit, $since_id, $before_id, $since) + function _streamTaggedDirect($offset, $limit, $since_id, $before_id, $since=null, $tag=null) + { + common_debug('_streamTaggedDirect()'); + $notice = new Notice(); + $notice->profile_id = $this->id; + $query = "select id from notice join notice_tag on id=notice_id where tag='" . $notice->escape($tag) . "' and profile_id=" . $notice->escape($notice->profile_id); + if ($since_id != 0) { + $query .= " and id > $since_id"; + } + + if ($before_id != 0) { + $query .= " and id < $before_id"; + } + + if (!is_null($since)) { + $query .= " and created > '" . date('Y-m-d H:i:s', $since) . "'"; + } + + $query .= ' order by id DESC'; + + if (!is_null($offset)) { + $query .= " limit $offset, $limit"; + } + $notice->query($query); + $ids = array(); + + while ($notice->fetch()) { + common_debug(print_r($notice, true)); + $ids[] = $notice->id; + } + + return $ids; + } + + + + + function _streamDirect($offset, $limit, $since_id, $before_id, $since = null) { $notice = new Notice(); diff --git a/classes/User.php b/classes/User.php index b5ac7b2206..ea8ba40817 100644 --- a/classes/User.php +++ b/classes/User.php @@ -407,13 +407,22 @@ class User extends Memcached_DataObject return Notice::getStreamByIds($ids); } + function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) { + $profile = $this->getProfile(); + if (!$profile) { + return null; + } else { + return $profile->getTaggedNotices($tag, $offset, $limit, $since_id, $before_id, $since); + } + } + function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) { $profile = $this->getProfile(); if (!$profile) { return null; } else { - return $profile->getNotices($offset, $limit, $since_id, $before_id); + return $profile->getNotices($offset, $limit, $since_id, $before_id, $since); } } diff --git a/lib/profileaction.php b/lib/profileaction.php index 1f2e309945..a3437ff4dd 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -49,16 +49,17 @@ require_once INSTALLDIR.'/lib/groupminilist.php'; class ProfileAction extends Action { - var $user = null; - var $page = null; + var $user = null; + var $page = null; var $profile = null; + var $tag = null; function prepare($args) { parent::prepare($args); $nickname_arg = $this->arg('nickname'); - $nickname = common_canonical_nickname($nickname_arg); + $nickname = common_canonical_nickname($nickname_arg); // Permanent redirect on non-canonical nickname @@ -85,10 +86,9 @@ class ProfileAction extends Action return false; } + $this->tag = $this->trimmed('tag'); $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; - common_set_returnto($this->selfUrl()); - return true; } @@ -244,4 +244,5 @@ class ProfileAction extends Action $this->elementEnd('div'); } -} \ No newline at end of file +} + diff --git a/lib/router.php b/lib/router.php index 635e1d77e0..f07e593734 100644 --- a/lib/router.php +++ b/lib/router.php @@ -426,6 +426,11 @@ class Router array('size' => '(original|96|48|24)', 'nickname' => '[a-zA-Z0-9]{1,64}')); + $m->connect(':nickname/tag/:tag', + array('action' => 'showstream'), + array('nickname' => '[a-zA-Z0-9]{1,64}'), + array('tag' => '[a-zA-Z0-9]+')); + $m->connect(':nickname', array('action' => 'showstream'), array('nickname' => '[a-zA-Z0-9]{1,64}')); diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php index ff2aca6d6e..62f7d89612 100644 --- a/lib/tagcloudsection.php +++ b/lib/tagcloudsection.php @@ -114,7 +114,11 @@ class TagCloudSection extends Section function tagUrl($tag) { - return common_local_url('tag', array('tag' => $tag)); + if ('showstream' === $this->out->trimmed('action')) { + return common_local_url('showstream', array('nickname' => $this->out->profile->nickname, 'tag' => $tag)); + } else { + return common_local_url('tag', array('tag' => $tag)); + } } function divId() From f5606b6aa3868d777c6c697cf1bbc5348cb2ccc3 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 18 May 2009 18:18:08 -0400 Subject: [PATCH 495/503] Added RSS for personal tags --- actions/showstream.php | 9 +++++++++ actions/userrss.php | 24 ++++++++++++++++++++++-- lib/router.php | 5 +++++ lib/rssaction.php | 6 +++++- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/actions/showstream.php b/actions/showstream.php index 1654f589c6..678a3174c1 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -113,6 +113,15 @@ class ShowstreamAction extends ProfileAction function getFeeds() { + if (!empty($this->tag)) { + return array(new Feed(Feed::RSS1, + common_local_url('userrss', + array('nickname' => $this->user->nickname, + 'tag' => $this->tag)), + sprintf(_('Notice feed for %s tagged %s (RSS 1.0)'), + $this->user->nickname, $this->tag))); + } + return array(new Feed(Feed::RSS1, common_local_url('userrss', array('nickname' => $this->user->nickname)), diff --git a/actions/userrss.php b/actions/userrss.php index 5861d9ee36..2280509b22 100644 --- a/actions/userrss.php +++ b/actions/userrss.php @@ -25,14 +25,15 @@ require_once(INSTALLDIR.'/lib/rssaction.php'); class UserrssAction extends Rss10Action { - var $user = null; + var $tag = null; function prepare($args) { parent::prepare($args); - $nickname = $this->trimmed('nickname'); + $nickname = $this->trimmed('nickname'); $this->user = User::staticGet('nickname', $nickname); + $this->tag = $this->trimmed('tag'); if (!$this->user) { $this->clientError(_('No such user.')); @@ -42,6 +43,25 @@ class UserrssAction extends Rss10Action } } + function getTaggedNotices($tag = null, $limit=0) + { + $user = $this->user; + + if (is_null($user)) { + return null; + } + + $notice = $user->getTaggedNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit, 0, 0, null, $tag); + + $notices = array(); + while ($notice->fetch()) { + $notices[] = clone($notice); + } + + return $notices; + } + + function getNotices($limit=0) { diff --git a/lib/router.php b/lib/router.php index f07e593734..70ee0f3fb0 100644 --- a/lib/router.php +++ b/lib/router.php @@ -426,6 +426,11 @@ class Router array('size' => '(original|96|48|24)', 'nickname' => '[a-zA-Z0-9]{1,64}')); + $m->connect(':nickname/tag/:tag/rss', + array('action' => 'userrss'), + array('nickname' => '[a-zA-Z0-9]{1,64}'), + array('tag' => '[a-zA-Z0-9]+')); + $m->connect(':nickname/tag/:tag', array('action' => 'showstream'), array('nickname' => '[a-zA-Z0-9]{1,64}'), diff --git a/lib/rssaction.php b/lib/rssaction.php index ddba862dcf..2f25ed7e47 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -97,7 +97,11 @@ class Rss10Action extends Action // Parent handling, including cache check parent::handle($args); // Get the list of notices - $this->notices = $this->getNotices($this->limit); + if (empty($this->tag)) { + $this->notices = $this->getNotices($this->limit); + } else { + $this->notices = $this->getTaggedNotices($this->tag, $this->limit); + } $this->showRss(); } From dcd69eec9098fd6bc6340a233796d6b242953057 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 18 May 2009 23:23:00 +0000 Subject: [PATCH 496/503] Increase entity_profile fn, nickname font-size slightly. Gave entity_profile more width. --- theme/base/css/display.css | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index dc6b4bc29a..8029a5eee1 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -492,7 +492,7 @@ line-height:1.618; /* entity_profile */ .entity_profile { position:relative; -width:67.702%; +width:74.702%; min-height:123px; float:left; margin-bottom:18px; @@ -528,12 +528,15 @@ margin-bottom:4px; .entity_profile .entity_nickname { margin-left:11px; display:inline; -font-weight:bold; } .entity_profile .entity_nickname { margin-left:0; } - +.entity_profile .fn, +.entity_profile .nickname { +font-size:1.1em; +font-weight:bold; +} .entity_profile .entity_fn dd:before { content: "("; font-weight:normal; @@ -555,7 +558,7 @@ display:none; /*entity_actions*/ .entity_actions { float:right; -margin-left:4.35%; +margin-left:2.35%; max-width:25%; } .entity_actions h2 { From 9261e48ef039869fb3709d374b7e4346d8773a49 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 18 May 2009 19:23:18 -0400 Subject: [PATCH 497/503] Removed dead code. --- classes/File_redirection.php | 2 -- lib/noticelist.php | 4 ++-- lib/util.php | 5 ----- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/classes/File_redirection.php b/classes/File_redirection.php index a71d1c0831..0eae681783 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -201,7 +201,6 @@ class File_redirection extends Memcached_DataObject if ($short_url) { $short_url = (string)$short_url; -if(1) { // store it $file = File::staticGet('url', $long_url); if (empty($file)) { @@ -221,7 +220,6 @@ if(1) { $file_redir->file_id = $file_id; $file_redir->insert(); } -} return $short_url; } return $long_url; diff --git a/lib/noticelist.php b/lib/noticelist.php index 55dd902b4a..0049050562 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -187,7 +187,7 @@ class NoticeListItem extends Widget function showNotice() { -if (0) +if(0) $this->out->elementStart('entry-title'); else @@ -236,7 +236,7 @@ else $clip .= '.png'; $top = '20px'; } -if (0) +if(0) $this->out->elementStart('div', 'entry-attachments'); else $this->out->elementStart('p', array('class' => 'entry-attachments', 'style' => "float: right; width: $width_att; background: url($clip) no-repeat; text-align: right; height: $height;")); diff --git a/lib/util.php b/lib/util.php index 25c0fb0a15..fbef8764a7 100644 --- a/lib/util.php +++ b/lib/util.php @@ -496,11 +496,6 @@ function common_linkify($url) { } $attrs = array('href' => $longurl, 'rel' => 'external'); -if(0){ - if ($longurl !== $url) { - $attrs['title'] = $longurl; - } -} return XMLStringer::estring('a', $attrs, $display); } From da74a29e0385042e974dbe50c03acd160f982e18 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 18 May 2009 23:45:45 +0000 Subject: [PATCH 498/503] Using list-style-position:inside for lists so that bullets don't leak out of the container. Added more padding to groups with most posts table --- theme/base/css/display.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index 547752b510..eda04be77e 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -639,6 +639,7 @@ margin-bottom:29px; clear:both; float:left; width:100%; +list-style-position:inside; } .aside .section h2 { text-transform:uppercase; @@ -662,6 +663,7 @@ list-style-type:none; float:left; margin-right:7px; margin-bottom:7px; +display:inline; } .section .entities li .photo { margin-right:0; @@ -1042,7 +1044,7 @@ margin-left:18px; /* TOP_POSTERS */ .section tbody td { -padding-right:11px; +padding-right:18px; padding-bottom:11px; } .section .vcard .photo { From 8c5d1b63df63bdf73ef08f8b8c46699089939fc8 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 19 May 2009 00:09:06 +0000 Subject: [PATCH 499/503] Removed visited and vcard a background colors. --- theme/identica/css/display.css | 7 ------- 1 file changed, 7 deletions(-) diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index cc19da0f70..9d625848fc 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -72,13 +72,6 @@ border-top-color:#CEE1E9; border-top-color:#87B4C8; } -#content .notice p.entry-content a:visited { -background-color:#fcfcfc; -} -#content .notice p.entry-content .vcard a { -background-color:#fcfffc; -} - #aside_primary { background-color:#CEE1E9; } From 35b39342337fed5916e06876c8a37068d2052937 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 19 May 2009 01:07:45 +0000 Subject: [PATCH 500/503] Logout works properly now. --- plugins/FBConnect/FBConnectLogin.php | 9 +++-- plugins/FBConnect/FBConnectPlugin.php | 51 +++++++++------------------ 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/plugins/FBConnect/FBConnectLogin.php b/plugins/FBConnect/FBConnectLogin.php index a544352f32..c2a2885717 100644 --- a/plugins/FBConnect/FBConnectLogin.php +++ b/plugins/FBConnect/FBConnectLogin.php @@ -254,6 +254,8 @@ class FBConnectloginAction extends Action function tryLogin() { + common_debug("Trying Facebook Login..."); + $flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE); if ($flink) { @@ -261,7 +263,7 @@ class FBConnectloginAction extends Action if ($user) { - common_debug("Logged in Facebook user $flink->foreign_id as user $user->id"); + common_debug("Logged in Facebook user $flink->foreign_id as user $user->id ($user->nickname)"); common_set_user($user); common_real_login(true); @@ -284,6 +286,7 @@ class FBConnectloginAction extends Action array('nickname' => $nickname)); } + common_redirect($url, 303); } @@ -302,10 +305,6 @@ class FBConnectloginAction extends Action function bestNewNickname() { - - common_debug("bestNewNickname()"); - common_debug(print_r($this->fb_fields, true)); - if (!empty($this->fb_fields['name'])) { $nickname = $this->nicknamize($this->fb_fields['name']); if ($this->isNewNickname($nickname)) { diff --git a/plugins/FBConnect/FBConnectPlugin.php b/plugins/FBConnect/FBConnectPlugin.php index 30532e5ec4..342a624927 100644 --- a/plugins/FBConnect/FBConnectPlugin.php +++ b/plugins/FBConnect/FBConnectPlugin.php @@ -67,10 +67,8 @@ class FBConnectPlugin extends Plugin $name = get_class($action); - common_debug("action: $name"); - // Avoid a redirect loop - if ($name != 'FBConnectloginAction') { + if (!in_array($name, array('FBConnectloginAction', 'ClientErrorAction'))) { $this->checkFacebookUser($action); @@ -122,7 +120,14 @@ class FBConnectPlugin extends Plugin $apikey = common_config('facebook', 'apikey'); $plugin_path = common_path('plugins/FBConnect'); - $login_url = common_get_returnto() || common_local_url('public'); + $url = common_get_returnto(); + + if ($url) { + // We don't have to return to it again + common_set_returnto(null); + } else { + $url = common_local_url('public'); + } $html = sprintf('', $apikey, $plugin_path, $login_url); + ', $apikey, $plugin_path, $url); $action->raw($html); @@ -203,11 +208,16 @@ class FBConnectPlugin extends Plugin function checkFacebookUser() { + $user = common_current_user(); + + if ($user) { + return; + } + try { $facebook = getFacebook(); $fbuid = $facebook->get_loggedin_user(); - $user = common_current_user(); // If you're a Facebook user and you're logged in do nothing @@ -244,35 +254,6 @@ class FBConnectPlugin extends Plugin } - function onStartLogout($action) - { - common_debug("onEndLogout()"); - - common_set_user(null); - common_real_login(false); // not logged in - common_forgetme(); // don't log back in! - - try { - - $facebook = getFacebook(); - $fbuid = $facebook->get_loggedin_user(); - - // XXX: ARGGGH this doesn't work right! - - if ($fbuid) { - $facebook->expire_session(); - $facebook->logout(common_local_url('public')); - } - - } catch (Exception $e) { - common_debug('Problem expiring FB session'); - } - - common_debug("logged out."); - - return false; - } - } From 62d2229573f5191ed330dadb1637dfb12b62f590 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 19 May 2009 01:24:35 +0000 Subject: [PATCH 501/503] Removed visited and vcard background (matches identica theme) --- theme/default/css/display.css | 7 ------- 1 file changed, 7 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 1fc99eff7d..e4b57ef49c 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -72,13 +72,6 @@ border-top-color:#D1D9E4; border-top-color:#C3D6DF; } -#content .notice p.entry-content a:visited { -background-color:#fcfcfc; -} -#content .notice p.entry-content .vcard a { -background-color:#fcfffc; -} - #aside_primary { background-color:#CEE1E9; } From 0c442e459e42b5d5aa168f7e2d3a0ff9f6bb0cd5 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 19 May 2009 17:05:30 +0000 Subject: [PATCH 502/503] Added reset button Rearranged swatch layout Added background image upload input file --- actions/designsettings.php | 36 ++++++++++++++++++++++++++-------- js/farbtastic/farbtastic.go.js | 2 +- theme/base/css/display.css | 11 +++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/actions/designsettings.php b/actions/designsettings.php index 0deb3f6847..a85b36a254 100644 --- a/actions/designsettings.php +++ b/actions/designsettings.php @@ -82,7 +82,16 @@ class DesignsettingsAction extends AccountSettingsAction $this->element('legend', null, _('Change background image')); $this->elementStart('ul', 'form_data'); $this->elementStart('li'); - $this->element('p', null, _('Upload background image')); + $this->element('label', array('for' => 'design_ background-image_file'), + _('Upload file')); + $this->element('input', array('name' => 'design_background-image_file', + 'type' => 'file', + 'id' => 'design_background-image_file')); + $this->element('p', 'form_guide', _('You can upload your personal background image. The maximum file size is 2Mb.')); + $this->element('input', array('name' => 'MAX_FILE_SIZE', + 'type' => 'hidden', + 'id' => 'MAX_FILE_SIZE', + 'value' => ImageFile::maxFileSizeInt())); $this->elementEnd('li'); $this->elementEnd('ul'); $this->elementEnd('fieldset'); @@ -108,15 +117,22 @@ class DesignsettingsAction extends AccountSettingsAction $userSwatch = ($userSwatch) ? json_decode($userSwatch, true) : $defaultSwatch; $s = 0; - $labelSwatch = array('Background color', - 'Content background color', - 'Sidebar background color', - 'Text color', - 'Link color'); + $labelSwatch = array('Background', + 'Content', + 'Sidebar', + 'Text', + 'Links'); foreach($userSwatch as $propertyvalue => $value) { - $foo = array_values($value); //Is this necessary? $value[0] doesn't work because of invalid key + $foo = array_values($value); $this->elementStart('li'); - $this->input("swatch-".$s, $labelSwatch[$s], $foo[0]); + $this->element('label', array('for' => 'swatch-'.$s), _($labelSwatch[$s])); + $this->element('input', array('name' => 'swatch-'.$s, //prefer swatch[$s] ? + 'type' => 'text', + 'id' => 'swatch-'.$s, + 'class' => 'swatch', + 'maxlength' => '7', + 'size' => '7', + 'value' => $foo[0])); $this->elementEnd('li'); $s++; } @@ -125,6 +141,10 @@ class DesignsettingsAction extends AccountSettingsAction $this->elementEnd('fieldset'); $this->submit('save', _('Save')); + $this->element('input', array('type' => 'reset', + 'value' => 'Reset', + 'class' => 'form_action-secondary')); + /*TODO: Check submitted form values: json_encode(form values) if submitted Swatch == DefaultSwatch, don't store in DB. diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js index 64dd7db204..77e2135139 100644 --- a/js/farbtastic/farbtastic.go.js +++ b/js/farbtastic/farbtastic.go.js @@ -43,7 +43,7 @@ $(document).ready(function() { $('#color-picker').hide(); var f = $.farbtastic('#color-picker', UpdateColors); - var swatches = $('#settings_design_color input'); + var swatches = $('#settings_design_color .swatch'); swatches .each(UpdateColors) diff --git a/theme/base/css/display.css b/theme/base/css/display.css index eda04be77e..8bd0ae1c4f 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1161,6 +1161,17 @@ width:400px; margin-right:28px; } +#settings_design_color .form_data li { +width:33%; +} +#settings_design_color .form_data label { +float:none; +} +#settings_design_color .form_data .swatch { +padding:11px; +margin-left:0; +} + .instructions ul { list-style-position:inside; } From 09e95cc33fb2228066d524e399bcc549e85eb565 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 19 May 2009 17:31:43 +0000 Subject: [PATCH 503/503] Fixed array index --- js/farbtastic/farbtastic.go.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/farbtastic/farbtastic.go.js b/js/farbtastic/farbtastic.go.js index 77e2135139..e298c1dab0 100644 --- a/js/farbtastic/farbtastic.go.js +++ b/js/farbtastic/farbtastic.go.js @@ -7,19 +7,19 @@ $(document).ready(function() { UpdateSwatch(S); switch (parseInt(f.linked.id.slice(-1))) { - case 1: default: + case 0: default: $('body').css({'background-color':C}); break; - case 2: + case 1: $('#content').css({'background-color':C}); break; - case 3: + case 2: $('#aside_primary').css({'background-color':C}); break; - case 4: + case 3: $('body').css({'color':C}); break; - case 5: + case 4: $('a').css({'color':C}); break; }