From 24713499a9686b6c2f1e765bb29d7e93e7256cd0 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 7 Mar 2009 12:38:47 +0100 Subject: [PATCH 01/57] Fixes #827: Laconica expects full OAuth message for user auth request. When a user subscribes to a remote profile, he is redirected to his own service to confirm the request. This authorization request is specified in http://oauth.net/core/1.0#auth_step2. According to the standard, it does not have to pass consumer_key, nonce, timestamp or signature. The only specified parameters are oauth_token and oauth_callback, both optional. --- actions/userauthorization.php | 107 +++------------------------------- 1 file changed, 8 insertions(+), 99 deletions(-) diff --git a/actions/userauthorization.php b/actions/userauthorization.php index 6a76e3a4c2..d0041ca5ae 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -216,10 +216,8 @@ class UserauthorizationAction extends Action function authorizeToken(&$req) { - $consumer_key = $req->get_parameter('oauth_consumer_key'); $token_field = $req->get_parameter('oauth_token'); $rt = new Token(); - $rt->consumer_key = $consumer_key; $rt->tok = $token_field; $rt->type = 0; $rt->state = 0; @@ -390,15 +388,14 @@ class UserauthorizationAction extends Action function validateRequest(&$req) { - # OAuth stuff -- have to copy from OAuth.php since they're - # all private methods, and there's no user-authentication method - $this->checkVersion($req); - $datastore = omb_oauth_datastore(); - $consumer = $this->getConsumer($datastore, $req); - $token = $this->getToken($datastore, $req, $consumer); - $this->checkTimestamp($req); - $this->checkNonce($datastore, $req, $consumer, $token); - $this->checkSignature($req, $consumer, $token); + /* Find token. */ + $t = new Token(); + $t->tok = $req->get_parameter('oauth_token'); + $t->type = 0; + if (!$t->find(true)) { + throw new OAuthException("Invalid request token: " . $req->get_parameter('oauth_token')); + } + $this->validateOmb($req); return true; } @@ -515,92 +512,4 @@ class UserauthorizationAction extends Action throw new OAuthException("Callback URL '$callback' is for local site."); } } - - # Snagged from OAuthServer - - function checkVersion(&$req) - { - $version = $req->get_parameter("oauth_version"); - if (!$version) { - $version = 1.0; - } - if ($version != 1.0) { - throw new OAuthException("OAuth version '$version' not supported"); - } - return $version; - } - - # Snagged from OAuthServer - - function getConsumer($datastore, $req) - { - $consumer_key = @$req->get_parameter("oauth_consumer_key"); - if (!$consumer_key) { - throw new OAuthException("Invalid consumer key"); - } - - $consumer = $datastore->lookup_consumer($consumer_key); - if (!$consumer) { - throw new OAuthException("Invalid consumer"); - } - return $consumer; - } - - # Mostly cadged from OAuthServer - - function getToken($datastore, &$req, $consumer) - {/*{{{*/ - $token_field = @$req->get_parameter('oauth_token'); - $token = $datastore->lookup_token($consumer, 'request', $token_field); - if (!$token) { - throw new OAuthException("Invalid $token_type token: $token_field"); - } - return $token; - } - - function checkTimestamp(&$req) - { - $timestamp = @$req->get_parameter('oauth_timestamp'); - $now = time(); - if ($now - $timestamp > TIMESTAMP_THRESHOLD) { - throw new OAuthException("Expired timestamp, yours $timestamp, ours $now"); - } - } - - # NOTE: don't call twice on the same request; will fail! - function checkNonce(&$datastore, &$req, $consumer, $token) - { - $timestamp = @$req->get_parameter('oauth_timestamp'); - $nonce = @$req->get_parameter('oauth_nonce'); - $found = $datastore->lookup_nonce($consumer, $token, $nonce, $timestamp); - if ($found) { - throw new OAuthException("Nonce already used"); - } - return true; - } - - function checkSignature(&$req, $consumer, $token) - { - $signature_method = $this->getSignatureMethod($req); - $signature = $req->get_parameter('oauth_signature'); - $valid_sig = $signature_method->check_signature($req, - $consumer, - $token, - $signature); - if (!$valid_sig) { - throw new OAuthException("Invalid signature"); - } - } - - function getSignatureMethod(&$req) - { - $signature_method = @$req->get_parameter("oauth_signature_method"); - if (!$signature_method) { - $signature_method = "PLAINTEXT"; - } - if ($signature_method != 'HMAC-SHA1') { - throw new OAuthException("Signature method '$signature_method' not supported."); - } - return omb_hmac_sha1(); - } } From df7565ddcca1e75476f4ad9318e83751d79884ba Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sat, 7 Mar 2009 13:04:36 +0100 Subject: [PATCH 02/57] Remove second OAuth request validation. --- actions/userauthorization.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/actions/userauthorization.php b/actions/userauthorization.php index d0041ca5ae..28243deccc 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -56,7 +56,6 @@ class UserauthorizationAction extends Action if (!$req) { $this->clientError(_('No request found!')); } - # XXX: only validate new requests, since nonce is one-time use $this->validateRequest($req); $this->storeRequest($req); $this->showForm($req); @@ -307,14 +306,11 @@ class UserauthorizationAction extends Action } $user = common_current_user(); - $datastore = omb_oauth_datastore(); - $consumer = $this->getConsumer($datastore, $req); - $token = $this->getToken($datastore, $req, $consumer); $sub = new Subscription(); $sub->subscriber = $user->id; $sub->subscribed = $remote->id; - $sub->token = $token->key; # NOTE: request token, not valid for use! + $sub->token = $req->get_parameter('oauth_token'); # NOTE: request token, not valid for use! $sub->created = DB_DataObject_Cast::dateTime(); # current time if (!$sub->insert()) { @@ -388,7 +384,9 @@ class UserauthorizationAction extends Action function validateRequest(&$req) { - /* Find token. */ + /* Find token. + TODO: If no token is passed the user should get a prompt to enter it + according to OAuth Core 1.0 */ $t = new Token(); $t->tok = $req->get_parameter('oauth_token'); $t->type = 0; From 6367def2d80d725c560079b48153964959f740a9 Mon Sep 17 00:00:00 2001 From: Adrian Lang Date: Sun, 8 Mar 2009 09:28:34 +0100 Subject: [PATCH 03/57] Remove OAuthRequest as storage from userauthorization. Since we are not really handling a fullblown OAuth request (No signature, nonce, consumer) we should not use this class, rather store the plain param array in the session. --- actions/userauthorization.php | 159 ++++++++++++++++------------------ 1 file changed, 74 insertions(+), 85 deletions(-) diff --git a/actions/userauthorization.php b/actions/userauthorization.php index 28243deccc..8723848c7b 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -25,7 +25,7 @@ define('TIMESTAMP_THRESHOLD', 300); class UserauthorizationAction extends Action { var $error; - var $req; + var $params; function handle($args) { @@ -35,8 +35,8 @@ class UserauthorizationAction extends Action # CSRF protection $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { - $req = $this->getStoredRequest(); - $this->showForm($req, _('There was a problem with your session token. '. + $params = $this->getStoredParams(); + $this->showForm($params, _('There was a problem with your session token. '. 'Try again, please.')); return; } @@ -50,17 +50,13 @@ class UserauthorizationAction extends Action common_redirect(common_local_url('login')); return; } + try { - # this must be a new request - $req = $this->getNewRequest(); - if (!$req) { - $this->clientError(_('No request found!')); - } - $this->validateRequest($req); - $this->storeRequest($req); - $this->showForm($req); + $this->validateRequest(); + $this->storeParams($_GET); + $this->showForm($_GET); } catch (OAuthException $e) { - $this->clearRequest(); + $this->clearParams(); $this->clientError($e->getMessage()); return; } @@ -68,9 +64,9 @@ class UserauthorizationAction extends Action } } - function showForm($req, $error=null) + function showForm($params, $error=null) { - $this->req = $req; + $this->params = $params; $this->error = $error; $this->showPage(); } @@ -90,16 +86,16 @@ class UserauthorizationAction extends Action function showContent() { - $req = $this->req; + $params = $this->params; - $nickname = $req->get_parameter('omb_listenee_nickname'); - $profile = $req->get_parameter('omb_listenee_profile'); - $license = $req->get_parameter('omb_listenee_license'); - $fullname = $req->get_parameter('omb_listenee_fullname'); - $homepage = $req->get_parameter('omb_listenee_homepage'); - $bio = $req->get_parameter('omb_listenee_bio'); - $location = $req->get_parameter('omb_listenee_location'); - $avatar = $req->get_parameter('omb_listenee_avatar'); + $nickname = $params['omb_listenee_nickname']; + $profile = $params['omb_listenee_profile']; + $license = $params['omb_listenee_license']; + $fullname = $params['omb_listenee_fullname']; + $homepage = $params['omb_listenee_homepage']; + $bio = $params['omb_listenee_bio']; + $location = $params['omb_listenee_location']; + $avatar = $params['omb_listenee_avatar']; $this->elementStart('div', 'profile'); if ($avatar) { @@ -146,56 +142,56 @@ class UserauthorizationAction extends Action function sendAuthorization() { - $req = $this->getStoredRequest(); + $params = $this->getStoredParams(); - if (!$req) { + if (!$params) { $this->clientError(_('No authorization request!')); return; } - $callback = $req->get_parameter('oauth_callback'); + $callback = $params['oauth_callback']; if ($this->arg('accept')) { - if (!$this->authorizeToken($req)) { + if (!$this->authorizeToken($params)) { $this->clientError(_('Error authorizing token')); } - if (!$this->saveRemoteProfile($req)) { + if (!$this->saveRemoteProfile($params)) { $this->clientError(_('Error saving remote profile')); } if (!$callback) { - $this->showAcceptMessage($req->get_parameter('oauth_token')); + $this->showAcceptMessage($params['oauth_token']); } else { - $params = array(); - $params['oauth_token'] = $req->get_parameter('oauth_token'); - $params['omb_version'] = OMB_VERSION_01; - $user = User::staticGet('uri', $req->get_parameter('omb_listener')); + $newparams = array(); + $newparams['oauth_token'] = $params['oauth_token']; + $newparams['omb_version'] = OMB_VERSION_01; + $user = User::staticGet('uri', $params['omb_listener']); $profile = $user->getProfile(); if (!$profile) { common_log_db_error($user, 'SELECT', __FILE__); $this->serverError(_('User without matching profile')); return; } - $params['omb_listener_nickname'] = $user->nickname; - $params['omb_listener_profile'] = common_local_url('showstream', + $newparams['omb_listener_nickname'] = $user->nickname; + $newparams['omb_listener_profile'] = common_local_url('showstream', array('nickname' => $user->nickname)); if (!is_null($profile->fullname)) { - $params['omb_listener_fullname'] = $profile->fullname; + $newparams['omb_listener_fullname'] = $profile->fullname; } if (!is_null($profile->homepage)) { - $params['omb_listener_homepage'] = $profile->homepage; + $newparams['omb_listener_homepage'] = $profile->homepage; } if (!is_null($profile->bio)) { - $params['omb_listener_bio'] = $profile->bio; + $newparams['omb_listener_bio'] = $profile->bio; } if (!is_null($profile->location)) { - $params['omb_listener_location'] = $profile->location; + $newparams['omb_listener_location'] = $profile->location; } $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); if ($avatar) { - $params['omb_listener_avatar'] = $avatar->url; + $newparams['omb_listener_avatar'] = $avatar->url; } $parts = array(); - foreach ($params as $k => $v) { + foreach ($newparams as $k => $v) { $parts[] = $k . '=' . OAuthUtil::urlencode_rfc3986($v); } $query_string = implode('&', $parts); @@ -213,9 +209,9 @@ class UserauthorizationAction extends Action } } - function authorizeToken(&$req) + function authorizeToken(&$params) { - $token_field = $req->get_parameter('oauth_token'); + $token_field = $params['oauth_token']; $rt = new Token(); $rt->tok = $token_field; $rt->type = 0; @@ -232,21 +228,21 @@ class UserauthorizationAction extends Action # XXX: refactor with similar code in finishremotesubscribe.php - function saveRemoteProfile(&$req) + function saveRemoteProfile(&$params) { # FIXME: we should really do this when the consumer comes # back for an access token. If they never do, we've got stuff in a # weird state. - $nickname = $req->get_parameter('omb_listenee_nickname'); - $fullname = $req->get_parameter('omb_listenee_fullname'); - $profile_url = $req->get_parameter('omb_listenee_profile'); - $homepage = $req->get_parameter('omb_listenee_homepage'); - $bio = $req->get_parameter('omb_listenee_bio'); - $location = $req->get_parameter('omb_listenee_location'); - $avatar_url = $req->get_parameter('omb_listenee_avatar'); + $nickname = $params['omb_listenee_nickname']; + $fullname = $params['omb_listenee_fullname']; + $profile_url = $params['omb_listenee_profile']; + $homepage = $params['omb_listenee_homepage']; + $bio = $params['omb_listenee_bio']; + $location = $params['omb_listenee_location']; + $avatar_url = $params['omb_listenee_avatar']; - $listenee = $req->get_parameter('omb_listenee'); + $listenee = $params['omb_listenee']; $remote = Remote_profile::staticGet('uri', $listenee); if ($remote) { @@ -310,7 +306,7 @@ class UserauthorizationAction extends Action $sub = new Subscription(); $sub->subscriber = $user->id; $sub->subscribed = $remote->id; - $sub->token = $req->get_parameter('oauth_token'); # NOTE: request token, not valid for use! + $sub->token = $params['oauth_token']; # NOTE: request token, not valid for use! $sub->created = DB_DataObject_Cast::dateTime(); # current time if (!$sub->insert()) { @@ -354,66 +350,59 @@ class UserauthorizationAction extends Action common_show_footer(); } - function storeRequest($req) + function storeParams($params) { common_ensure_session(); - $_SESSION['userauthorizationrequest'] = $req; + $_SESSION['userauthorizationparams'] = $params; } - function clearRequest() + function clearParams() { common_ensure_session(); - unset($_SESSION['userauthorizationrequest']); + unset($_SESSION['userauthorizationparams']); } - function getStoredRequest() + function getStoredParams() { common_ensure_session(); - $req = $_SESSION['userauthorizationrequest']; - return $req; - } - - function getNewRequest() - { - common_remove_magic_from_request(); - $req = OAuthRequest::from_request(); - return $req; + $params = $_SESSION['userauthorizationparams']; + return $params; } # Throws an OAuthException if anything goes wrong - function validateRequest(&$req) + function validateRequest() { /* Find token. TODO: If no token is passed the user should get a prompt to enter it according to OAuth Core 1.0 */ $t = new Token(); - $t->tok = $req->get_parameter('oauth_token'); + $t->tok = $_GET['oauth_token']; $t->type = 0; if (!$t->find(true)) { - throw new OAuthException("Invalid request token: " . $req->get_parameter('oauth_token')); + throw new OAuthException("Invalid request token: " . $_GET['oauth_token']); } - $this->validateOmb($req); + $this->validateOmb(); return true; } - function validateOmb(&$req) + function validateOmb() { foreach (array('omb_version', 'omb_listener', 'omb_listenee', 'omb_listenee_profile', 'omb_listenee_nickname', 'omb_listenee_license') as $param) { - if (is_null($req->get_parameter($param))) { + if (!isset($_GET[$param]) || is_null($_GET[$param])) { throw new OAuthException("Required parameter '$param' not found"); } } # Now, OMB stuff - $version = $req->get_parameter('omb_version'); + $version = $_GET['omb_version']; if ($version != OMB_VERSION_01) { throw new OAuthException("OpenMicroBlogging version '$version' not supported"); } - $listener = $req->get_parameter('omb_listener'); + $listener = $_GET['omb_listener']; $user = User::staticGet('uri', $listener); if (!$user) { throw new OAuthException("Listener URI '$listener' not found here"); @@ -422,7 +411,7 @@ class UserauthorizationAction extends Action if ($cur->id != $user->id) { throw new OAuthException("Can't add for another user!"); } - $listenee = $req->get_parameter('omb_listenee'); + $listenee = $_GET['omb_listenee']; if (!Validate::uri($listenee) && !common_valid_tag($listenee)) { throw new OAuthException("Listenee URI '$listenee' not a recognizable URI"); @@ -445,13 +434,13 @@ class UserauthorizationAction extends Action throw new OAuthException("Already subscribed to user!"); } } - $nickname = $req->get_parameter('omb_listenee_nickname'); + $nickname = $_GET['omb_listenee_nickname']; if (!Validate::string($nickname, array('min_length' => 1, 'max_length' => 64, 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) { throw new OAuthException('Nickname must have only letters and numbers and no spaces.'); } - $profile = $req->get_parameter('omb_listenee_profile'); + $profile = $_GET['omb_listenee_profile']; if (!common_valid_http_url($profile)) { throw new OAuthException("Invalid profile URL '$profile'."); } @@ -460,7 +449,7 @@ class UserauthorizationAction extends Action throw new OAuthException("Profile URL '$profile' is for a local user."); } - $license = $req->get_parameter('omb_listenee_license'); + $license = $_GET['omb_listenee_license']; if (!common_valid_http_url($license)) { throw new OAuthException("Invalid license URL '$license'."); } @@ -469,23 +458,23 @@ class UserauthorizationAction extends Action throw new OAuthException("Listenee stream license '$license' not compatible with site license '$site_license'."); } # optional stuff - $fullname = $req->get_parameter('omb_listenee_fullname'); + $fullname = $_GET['omb_listenee_fullname']; if ($fullname && mb_strlen($fullname) > 255) { throw new OAuthException("Full name '$fullname' too long."); } - $homepage = $req->get_parameter('omb_listenee_homepage'); + $homepage = $_GET['omb_listenee_homepage']; if ($homepage && (!common_valid_http_url($homepage) || mb_strlen($homepage) > 255)) { throw new OAuthException("Invalid homepage '$homepage'"); } - $bio = $req->get_parameter('omb_listenee_bio'); + $bio = $_GET['omb_listenee_bio']; if ($bio && mb_strlen($bio) > 140) { throw new OAuthException("Bio too long '$bio'"); } - $location = $req->get_parameter('omb_listenee_location'); + $location = $_GET['omb_listenee_location']; if ($location && mb_strlen($location) > 255) { throw new OAuthException("Location too long '$location'"); } - $avatar = $req->get_parameter('omb_listenee_avatar'); + $avatar = $_GET['omb_listenee_avatar']; if ($avatar) { if (!common_valid_http_url($avatar) || strlen($avatar) > 255) { throw new OAuthException("Invalid avatar URL '$avatar'"); @@ -502,7 +491,7 @@ class UserauthorizationAction extends Action throw new OAuthException("Wrong image type for '$avatar'"); } } - $callback = $req->get_parameter('oauth_callback'); + $callback = $_GET['oauth_callback']; if ($callback && !common_valid_http_url($callback)) { throw new OAuthException("Invalid callback URL '$callback'"); } From 00d3d70a7db23851dcc0b8c0ec718d6a53c72337 Mon Sep 17 00:00:00 2001 From: "ken.sedgwick" Date: Fri, 13 Mar 2009 16:50:58 -0700 Subject: [PATCH 04/57] Fixed version issues in laconica RPM spec file. Fixed missing avatar directory in RPM packaging. --- scripts/laconica.spec | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/laconica.spec b/scripts/laconica.spec index 2df41c9323..502959fb1d 100644 --- a/scripts/laconica.spec +++ b/scripts/laconica.spec @@ -1,11 +1,14 @@ +# This version needs to match the tarball and unpacked directory name. +%define LACVER 0.7.2.1 + BuildRequires: php-pear BuildRequires: httpd-devel Name: laconica -Version: 0.7.1 +Version: %{LACVER} Release: 1%{?dist} License: GAGPL v3 or later -Source: laconica-0.7.1.tar.gz +Source: laconica-%{version}.tar.gz Group: Applications/Internet Summary: Laconica, the Open Source microblogging platform BuildArch: noarch @@ -49,6 +52,8 @@ cp -a * %{buildroot}%{wwwpath} mkdir -p %{buildroot}%{_datadir}/laconica cp -a db %{buildroot}%{_datadir}/laconica/db +mkdir -p %{buildroot}%{_datadir}/laconica/avatar + mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d cat > %{buildroot}%{_sysconfdir}/httpd/conf.d/laconica.conf <<"EOF" Alias /laconica/ "/var/www/laconica/" @@ -74,6 +79,12 @@ rm -rf %buildroot %config(noreplace) %{_sysconfdir}/httpd/conf.d/laconica.conf %changelog +* 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. + * Sat Feb 28 2009 Ken Sedgwick - 0.7.1-1 - Modified RPM for Fedora. From 214468d17ea7342a76868030bb0ef83d47276296 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 20 Mar 2009 05:59:03 -0700 Subject: [PATCH 05/57] added a few Laconica events --- lib/action.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/action.php b/lib/action.php index 975c2bfcb8..7998541770 100644 --- a/lib/action.php +++ b/lib/action.php @@ -97,9 +97,18 @@ class Action extends HTMLOutputter // lawsuit $this->startHTML(); Event::handle('EndShowHTML', array($this)); } + if (Event::handle('StartShowHead', array($this))) { $this->showHead(); + Event::handle('EndShowHead', array($this)); + } + if (Event::handle('StartShowBody', array($this))) { $this->showBody(); + Event::handle('EndShowBody', array($this)); + } + if (Event::handle('StartEndHTML', array($this))) { $this->endHTML(); + Event::handle('EndEndHTML', array($this)); + } } /** @@ -577,7 +586,10 @@ class Action extends HTMLOutputter // lawsuit { $this->elementStart('div', array('id' => 'aside_primary', 'class' => 'aside')); + if (Event::handle('StartShowExportData', array($this))) { $this->showExportData(); + Event::handle('EndShowExportData', array($this)); + } if (Event::handle('StartShowSections', array($this))) { $this->showSections(); Event::handle('EndShowSections', array($this)); From af887119ac43beb9c636b40fed0b95569ec05a8a Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 24 Mar 2009 12:41:03 -0700 Subject: [PATCH 06/57] TemplatePlugin.php 0.1 --- plugins/TemplatePlugin.php | 344 +++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 plugins/TemplatePlugin.php diff --git a/plugins/TemplatePlugin.php b/plugins/TemplatePlugin.php new file mode 100644 index 0000000000..03daf6219c --- /dev/null +++ b/plugins/TemplatePlugin.php @@ -0,0 +1,344 @@ + + * @copyright 2009 Megapump, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://megapump.com/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +define('TEMPLATEPLUGIN_VERSION', '0.1'); + +class TemplatePlugin extends Plugin { + + var $blocks = array(); + + function __construct() { + parent::__construct(); + } + + // capture the RouterInitialized event + // and connect a new API method + // for updating the template + function onRouterInitialized( &$m ) { + $m->connect( 'template/update', array( + 'action' => 'template', + )); + } + + + // <%styles%> + // <%scripts%> + // <%search%> + // <%feeds%> + // <%description%> + // <%head%> + function onStartShowHead( &$act ) { + $this->clear_xmlWriter($act); + $act->extraHead(); + $this->blocks['head'] = $act->xw->flush(); + $act->showStylesheets(); + $this->blocks['styles'] = $act->xw->flush(); + $act->showScripts(); + $this->blocks['scripts'] = $act->xw->flush(); + $act->showFeeds(); + $this->blocks['feeds'] = $act->xw->flush(); + $act->showOpenSearch(); + $this->blocks['search'] = $act->xw->flush(); + $act->showDescription(); + $this->blocks['description'] = $act->xw->flush(); + return false; + } + + // <%bodytext%> + function onStartShowContentBlock( &$act ) { + $this->clear_xmlWriter($act); + return true; + } + function onEndShowContentBlock( &$act ) { + $this->blocks['bodytext'] = $act->xw->flush(); + } + + // <%localnav%> + function onStartShowLocalNavBlock( &$act ) { + $this->clear_xmlWriter($act); + return true; + } + function onEndShowLocalNavBlock( &$act ) { + $this->blocks['localnav'] = $act->xw->flush(); + } + + // <%export%> + function onStartShowExportData( &$act ) { + $this->clear_xmlWriter($act); + return true; + } + function onEndShowExportData( &$act ) { + $this->blocks['export'] = $act->xw->flush(); + } + + // <%subscriptions%> + // <%subscribers%> + // <%groups%> + // <%statistics%> + // <%cloud%> + // <%groupmembers%> + // <%groupstatistics%> + // <%groupcloud%> + // <%popular%> + // <%groupsbyposts%> + // <%featuredusers%> + // <%groupsbymembers%> + function onStartShowSections( &$act ) { + global $action; + $this->clear_xmlWriter($act); + switch ($action) { + case "showstream": + $act->showSubscriptions(); + $this->blocks['subscriptions'] = $act->xw->flush(); + $act->showSubscribers(); + $this->blocks['subscribers'] = $act->xw->flush(); + $act->showGroups(); + $this->blocks['groups'] = $act->xw->flush(); + $act->showStatistics(); + $this->blocks['statistics'] = $act->xw->flush(); + $cloud = new PersonalTagCloudSection($act, $act->user); + $cloud->show(); + $this->blocks['cloud'] = $act->xw->flush(); + break; + case "showgroup": + $act->showMembers(); + $this->blocks['groupmembers'] = $act->xw->flush(); + $act->showStatistics(); + $this->blocks['groupstatistics'] = $act->xw->flush(); + $cloud = new GroupTagCloudSection($act, $act->group); + $cloud->show(); + $this->blocks['groupcloud'] = $act->xw->flush(); + break; + case "public": + $pop = new PopularNoticeSection($act); + $pop->show(); + $this->blocks['popular'] = $act->xw->flush(); + $gbp = new GroupsByPostsSection($act); + $gbp->show(); + $this->blocks['groupsbyposts'] = $act->xw->flush(); + $feat = new FeaturedUsersSection($act); + $feat->show(); + $this->blocks['featuredusers'] = $act->xw->flush(); + break; + case "groups": + $gbp = new GroupsByPostsSection($act); + $gbp->show(); + $this->blocks['groupsbyposts'] = $act->xw->flush(); + $gbm = new GroupsByMembersSection($act); + $gbm->show(); + $this->blocks['groupsbymembers'] = $act->xw->flush(); + break; + } + return false; + } + + // <%logo%> + // <%nav%> + // <%notice%> + // <%noticeform%> + function onStartShowHeader( &$act ) { + $this->clear_xmlWriter($act); + $act->showLogo(); + $this->blocks['logo'] = $act->xw->flush(); + $act->showPrimaryNav(); + $this->blocks['nav'] = $act->xw->flush(); + $act->showSiteNotice(); + $this->blocks['notice'] = $act->xw->flush(); + if (common_logged_in()) { + $act->showNoticeForm(); + } else { + $act->showAnonymousMessage(); + } + $this->blocks['noticeform'] = $act->xw->flush(); + return false; + } + + // <%secondarynav%> + // <%licenses%> + function onStartShowFooter( &$act ) { + $this->clear_xmlWriter($act); + $act->showSecondaryNav(); + $this->blocks['secondarynav'] = $act->xw->flush(); + $act->showLicenses(); + $this->blocks['licenses'] = $act->xw->flush(); + return false; + } + + // capture the EndHTML event + // and include the template + function onEndEndHTML($act) { + + global $action, $tags; + + // set the action and title values + $vars = array( + 'action'=>$action, + 'title'=>$act->title(). " - ". common_config('site', 'name') + ); + + // use the PHP template + // unless laconica config: + // $config['template']['mode'] = 'html'; + if (!(common_config('template', 'mode') == 'html')) { + $tpl_file = 'tpl/index.php'; + $tags = array_merge($vars,$this->blocks); + include $tpl_file; + return; + } + + $tpl_file = 'tpl/index.html'; + + // read the static template + $output = file_get_contents( $tpl_file ); + + $tags = array(); + + // get a list of the <%tags%> in the template + $pattern='/<%([a-z]+)%>/'; + + if ( 1 <= preg_match_all( $pattern, $output, $found )) + $tags[] = $found; + + // for each found tag, set its value from the rendered blocks + foreach( $tags[0][1] as $pos=>$tag ) { + if (isset($this->blocks[$tag])) + $vars[$tag] = $this->blocks[$tag]; + + // didn't find a block for the tag + elseif (!isset($vars[$tag])) + $vars[$tag] = ''; + } + + // replace the tags in the template + foreach( $vars as $key=>$val ) + $output = str_replace( '<%'.$key.'%>', $val, $output ); + + echo $output; + + return true; + + } + + // catching the StartShowHTML event to halt the rendering + function onStartShowHTML( &$act ) { + $this->clear_xmlWriter($act); + return true; + } + + // clear the xmlWriter + function clear_xmlWriter( &$act ) { + $act->xw->openMemory(); + $act->xw->setIndent(true); + } + +} + +/** + * Action for updating the template remotely + * + * "template/update" -- a POST method that requires a single + * parameter "template", containing the new template code + * + * @category Plugin + * @package Laconica + * @author Brian Hendrickson + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://megapump.com/ + * + */ + +class TemplateAction extends Action +{ + + function prepare($args) { + parent::prepare($args); + return true; + } + + function handle($args) { + + parent::handle($args); + + if (!isset($_SERVER['PHP_AUTH_USER'])) { + + // not authenticated, show login form + header('WWW-Authenticate: Basic realm="Laconica API"'); + + // cancelled the browser login form + $this->clientError(_('Authentication error!'), $code = 401); + + } else { + + $nick = $_SERVER['PHP_AUTH_USER']; + $pass = $_SERVER['PHP_AUTH_PW']; + + // check username and password + $user = common_check_user($nick,$pass); + + if ($user) { + + // verify that user is admin + if (!($user->id == 1)) + $this->clientError(_('only User #1 can update the template'), $code = 401); + + // open the old template + $tpl_file = 'tpl/index.html'; + $fp = fopen( $tpl_file, 'w+' ); + + // overwrite with the new template + fwrite($fp, $this->arg('template')); + fclose($fp); + + header('HTTP/1.1 200 OK'); + header('Content-type: text/plain'); + print "Template Updated!"; + + } else { + + // bad username and password + $this->clientError(_('Authentication error!'), $code = 401); + + } + + } + } +} + +/** + * Function for retrieving a laconica display section + * + * requires one parameter, the name of the section + * section names are listed in the comments of the TemplatePlugin class + * + * @category Plugin + * @package Laconica + * @author Brian Hendrickson + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://megapump.com/ + * + */ + +function section($tagname) { + global $tags; + if (isset($tags[$tagname])) + return $tags[$tagname]; +} + From c8343e75fc3a8e7e20abc240ed506eb7088ba71f Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 24 Mar 2009 12:42:42 -0700 Subject: [PATCH 07/57] tpl/index.php 0.1 --- tpl/index.php | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tpl/index.php diff --git a/tpl/index.php b/tpl/index.php new file mode 100644 index 0000000000..5f1ed84394 --- /dev/null +++ b/tpl/index.php @@ -0,0 +1,47 @@ + + + + <?php echo section('title'); ?> + + + + + + + + +
+ +
+ + +
+ + + + + + + + + + + + + +
+
+ +
+ + \ No newline at end of file From 03eb81d3b768fd595ae6c75cb7740cdab6595e52 Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 24 Mar 2009 12:45:26 -0700 Subject: [PATCH 08/57] how to configure templating --- config.php.sample | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config.php.sample b/config.php.sample index 529e86f15f..15236f9ee5 100644 --- a/config.php.sample +++ b/config.php.sample @@ -163,6 +163,10 @@ $config['sphinx']['port'] = 3312; # require_once('plugins/GoogleAnalyticsPlugin.php'); # $ga = new GoogleAnalyticsPlugin('your secret code'); +# Use Templating (template: /tpl/index.php) +# require_once('plugins/TemplatePlugin.php'); +# $tpl = new TemplatePlugin(); + #Don't allow saying the same thing more than once per hour #$config['site']['dupelimit'] = 3600; #Don't enforce the dupe limit From e3d5f965ae3241a9786cdcc3783af67029af57e9 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Wed, 1 Apr 2009 18:11:02 +0100 Subject: [PATCH 09/57] 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 5067939e9abaa7451faa26a7246460214aafb320 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Apr 2009 15:30:59 -0400 Subject: [PATCH 10/57] 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 890a1e1339001a82a78f766a1d13103271aadd09 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 1 Apr 2009 18:29:10 -0400 Subject: [PATCH 11/57] 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 dfce4c012f118c020305b7ce2f3e4fde26fab7b2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 12:51:43 -0400 Subject: [PATCH 12/57] 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 45d520550562691bebd17c3477eda1df049be0be Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 3 Apr 2009 14:00:52 -0400 Subject: [PATCH 13/57] 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 14/57] 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 61a08c91d5475a6eaedc56d999a8814b48a0fbb5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 3 Apr 2009 15:59:08 -0700 Subject: [PATCH 15/57] 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 16/57] 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 17/57] 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 18/57] 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 19/57] 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 20/57] 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 21/57] 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 22/57] 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 23/57] 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 24/57] 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 25/57] 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 26/57] 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 27/57] 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 28/57] 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 29/57] 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 30/57] 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 05b04b7970d1b0f1e35a64a5537ad61e2fb8db1c Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 7 Apr 2009 21:12:11 +0000 Subject: [PATCH 31/57] 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 32/57] 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 33/57] 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 34/57] 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 35/57] 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 36/57] 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 37/57] 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 38/57] 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 39/57] 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 40/57] 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 41/57] 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 42/57] 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 43/57] 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 44/57] 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 45/57] 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 46/57] 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 47/57] 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 48/57] 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 49/57] 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 50/57] 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 51/57] 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 52/57] 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 53/57] 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 54/57] 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 55/57] 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 56/57] 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 57/57] 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;