From 7f9b07d8c9840944ea7ebf437f45e44584bcb5ee Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 24 Dec 2009 15:25:59 -0600 Subject: Move ssl settings from site admin panel to paths admin panel --- actions/pathsadminpanel.php | 34 ++++++++++++++++++++++++++++++++-- actions/siteadminpanel.php | 31 +------------------------------ 2 files changed, 33 insertions(+), 32 deletions(-) (limited to 'actions') diff --git a/actions/pathsadminpanel.php b/actions/pathsadminpanel.php index f1a2b1b8a..c6daa1734 100644 --- a/actions/pathsadminpanel.php +++ b/actions/pathsadminpanel.php @@ -92,7 +92,7 @@ class PathsadminpanelAction extends AdminPanelAction function saveSettings() { static $settings = array( - 'site' => array('path', 'locale_path'), + 'site' => array('path', 'locale_path', 'ssl', 'sslserver'), 'theme' => array('server', 'dir', 'path'), 'avatar' => array('server', 'dir', 'path'), 'background' => array('server', 'dir', 'path') @@ -160,6 +160,14 @@ class PathsadminpanelAction extends AdminPanelAction $this->clientError(sprintf(_("Locales directory not readable: %s"), $values['site']['locale_path'])); } + // Validate SSL setup + + if (in_array($values['site']['ssl'], array('sometimes', 'always'))) { + if (empty($values['site']['sslserver'])) { + $this->clientError(_("You must set an SSL server when enabling SSL.")); + } + } + } } @@ -283,6 +291,29 @@ class PathsAdminPanelForm extends AdminForm $this->out->elementEnd('ul'); $this->out->elementEnd('fieldset'); + + $this->out->elementStart('fieldset', array('id' => 'settings_admin_ssl')); + $this->out->element('legend', null, _('SSL')); + $this->out->elementStart('ul', 'form_data'); + $this->li(); + $ssl = array('never' => _('Never'), + 'sometimes' => _('Sometimes'), + 'always' => _('Always')); + + common_debug("site ssl = " . $this->value('site', 'ssl')); + + $this->out->dropdown('site-ssl', _('Use SSL'), + $ssl, _('When to use SSL'), + false, $this->value('ssl', 'site')); + $this->unli(); + + $this->li(); + $this->input('sslserver', _('SSL Server'), + _('Server to direct SSL requests to'), 'site'); + $this->unli(); + $this->out->elementEnd('ul'); + $this->out->elementEnd('fieldset'); + } /** @@ -297,7 +328,6 @@ class PathsAdminPanelForm extends AdminForm 'save', _('Save paths')); } - /** * Utility to simplify some of the duplicated code around * params and settings. Overriding the input() in the base class diff --git a/actions/siteadminpanel.php b/actions/siteadminpanel.php index b963336e6..f260a4476 100644 --- a/actions/siteadminpanel.php +++ b/actions/siteadminpanel.php @@ -92,8 +92,7 @@ class SiteadminpanelAction extends AdminPanelAction { static $settings = array('site' => array('name', 'broughtby', 'broughtbyurl', 'email', 'timezone', 'language', - 'ssl', 'sslserver', 'site', - 'textlimit', 'dupelimit'), + 'site', 'textlimit', 'dupelimit'), 'snapshot' => array('run', 'reporturl', 'frequency')); static $booleans = array('site' => array('private', 'inviteonly', 'closed', 'fancy')); @@ -192,14 +191,6 @@ class SiteadminpanelAction extends AdminPanelAction $this->clientError(_("Snapshot frequency must be a number.")); } - // Validate SSL setup - - if (in_array($values['site']['ssl'], array('sometimes', 'always'))) { - if (empty($values['site']['sslserver'])) { - $this->clientError(_("You must set an SSL server when enabling SSL.")); - } - } - if (mb_strlen($values['site']['sslserver']) > 255) { $this->clientError(_("Invalid SSL server. The maximum length is 255 characters.")); } @@ -376,26 +367,6 @@ class SiteAdminPanelForm extends AdminForm $this->out->elementEnd('ul'); $this->out->elementEnd('fieldset'); - $this->out->elementStart('fieldset', array('id' => 'settings_admin_ssl')); - $this->out->element('legend', null, _('SSL')); - $this->out->elementStart('ul', 'form_data'); - $this->li(); - $ssl = array('never' => _('Never'), - 'sometimes' => _('Sometimes'), - 'always' => _('Always')); - - $this->out->dropdown('ssl', _('Use SSL'), - $ssl, _('When to use SSL'), - false, $this->value('ssl', 'site')); - $this->unli(); - - $this->li(); - $this->input('sslserver', _('SSL Server'), - _('Server to direct SSL requests to')); - $this->unli(); - $this->out->elementEnd('ul'); - $this->out->elementEnd('fieldset'); - $this->out->elementStart('fieldset', array('id' => 'settings_admin_limits')); $this->out->element('legend', null, _('Limits')); $this->out->elementStart('ul', 'form_data'); -- cgit v1.2.3-54-g00ecf From 1a462b04d7594159e90b514538ddbe3f7effd7f8 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 24 Dec 2009 16:50:28 -0600 Subject: Paths admin panel should not insist on an ssl server being specified, ever. --- actions/pathsadminpanel.php | 7 ++----- actions/siteadminpanel.php | 4 ---- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'actions') diff --git a/actions/pathsadminpanel.php b/actions/pathsadminpanel.php index c6daa1734..d39c7c449 100644 --- a/actions/pathsadminpanel.php +++ b/actions/pathsadminpanel.php @@ -162,12 +162,9 @@ class PathsadminpanelAction extends AdminPanelAction // Validate SSL setup - if (in_array($values['site']['ssl'], array('sometimes', 'always'))) { - if (empty($values['site']['sslserver'])) { - $this->clientError(_("You must set an SSL server when enabling SSL.")); - } + if (mb_strlen($values['site']['sslserver']) > 255) { + $this->clientError(_("Invalid SSL server. The maximum length is 255 characters.")); } - } } diff --git a/actions/siteadminpanel.php b/actions/siteadminpanel.php index f260a4476..5e29f4c19 100644 --- a/actions/siteadminpanel.php +++ b/actions/siteadminpanel.php @@ -191,10 +191,6 @@ class SiteadminpanelAction extends AdminPanelAction $this->clientError(_("Snapshot frequency must be a number.")); } - if (mb_strlen($values['site']['sslserver']) > 255) { - $this->clientError(_("Invalid SSL server. The maximum length is 255 characters.")); - } - // Validate text limit if (!Validate::number($values['site']['textlimit'], array('min' => 140))) { -- cgit v1.2.3-54-g00ecf From c5de3262312f814bc44e596d9031c2df22420e27 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 10:42:55 -0800 Subject: events for blocking a user --- EVENTS.txt | 7 +++++++ actions/apiblockcreate.php | 13 ++++++++++--- actions/block.php | 8 ++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) (limited to 'actions') diff --git a/EVENTS.txt b/EVENTS.txt index 96250f64c..42aecfaf9 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -640,3 +640,10 @@ EndLog: After writing to the logs - $msg - $filename +StartBlockProfile: when we're about to block +- $user: the person doing the block +- $profile: the person getting blocked, can be remote + +EndBlockProfile: when a block has succeeded +- $user: the person doing the block +- $profile: the person blocked, can be remote diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php index e79dec32d..c26485f59 100644 --- a/actions/apiblockcreate.php +++ b/actions/apiblockcreate.php @@ -109,9 +109,16 @@ class ApiBlockCreateAction extends ApiAuthAction return; } - if ($this->user->hasBlocked($this->other) - || $this->user->block($this->other) - ) { + if (!$this->user->hasBlocked($this->other)) { + if (Event::handle('StartBlockProfile', array($this->user, $this->other))) { + $result = $this->user->block($this->other); + if ($result) { + Event::handle('EndBlockProfile', array($this->user, $this->other)); + } + } + } + + if ($this->user->hasBlocked($this->other)) { $this->initDocument($this->format); $this->showProfile($this->other, $this->format); $this->endDocument($this->format); diff --git a/actions/block.php b/actions/block.php index 71a34e087..5fae45dff 100644 --- a/actions/block.php +++ b/actions/block.php @@ -156,7 +156,12 @@ class BlockAction extends ProfileFormAction { $cur = common_current_user(); - $result = $cur->block($this->profile); + if (Event::handle('StartBlockProfile', array($cur, $this->profile))) { + $result = $cur->block($this->profile); + if ($result) { + Event::handle('EndBlockProfile', array($cur, $this->profile)); + } + } if (!$result) { $this->serverError(_('Failed to save block information.')); @@ -164,4 +169,3 @@ class BlockAction extends ProfileFormAction } } } - -- cgit v1.2.3-54-g00ecf From 2ae04bb6d598c74763aca79ab52172934158be46 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 10:50:12 -0800 Subject: add events for unblocking a profile --- EVENTS.txt | 8 ++++++++ actions/apiblockdestroy.php | 13 ++++++++++--- actions/unblock.php | 13 +++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) (limited to 'actions') diff --git a/EVENTS.txt b/EVENTS.txt index 42aecfaf9..64e345b69 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -647,3 +647,11 @@ StartBlockProfile: when we're about to block EndBlockProfile: when a block has succeeded - $user: the person doing the block - $profile: the person blocked, can be remote + +StartUnblockProfile: when we're about to unblock +- $user: the person doing the unblock +- $profile: the person getting unblocked, can be remote + +EndUnblockProfile: when an unblock has succeeded +- $user: the person doing the unblock +- $profile: the person unblocked, can be remote diff --git a/actions/apiblockdestroy.php b/actions/apiblockdestroy.php index 328f18ab0..666f308f4 100644 --- a/actions/apiblockdestroy.php +++ b/actions/apiblockdestroy.php @@ -97,9 +97,16 @@ class ApiBlockDestroyAction extends ApiAuthAction return; } - if (!$this->user->hasBlocked($this->other) - || $this->user->unblock($this->other) - ) { + if ($this->user->hasBlocked($this->other)) { + if (Event::handle('StartUnblockProfile', array($this->user, $this->other))) { + $result = $this->user->unblock($this->other); + if ($result) { + Event::handle('EndUnblockProfile', array($this->user, $this->other)); + } + } + } + + if (!$this->user->hasBlocked($this->other)) { $this->initDocument($this->format); $this->showProfile($this->other, $this->format); $this->endDocument($this->format); diff --git a/actions/unblock.php b/actions/unblock.php index c60458cd3..0f63e1dae 100644 --- a/actions/unblock.php +++ b/actions/unblock.php @@ -71,8 +71,17 @@ class UnblockAction extends ProfileFormAction function handlePost() { - $cur = common_current_user(); - $result = $cur->unblock($this->profile); + $cur = common_current_user(); + + $result = false; + + if (Event::handle('StartUnblockProfile', array($cur, $this->profile))) { + $result = $cur->unblock($this->profile); + if ($result) { + Event::handle('EndUnblockProfile', array($cur, $this->profile)); + } + } + if (!$result) { $this->serverError(_('Error removing the block.')); return; -- cgit v1.2.3-54-g00ecf From bb93d6b1c7c697891baca7082261ee694727f161 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 14:21:07 -0800 Subject: remove namespace setting from location; it's unused --- actions/newnotice.php | 43 ++++++++++++++++++++++++------------------- actions/profilesettings.php | 5 +++++ classes/User.php | 16 ++++++++++++++++ lib/default.php | 2 +- 4 files changed, 46 insertions(+), 20 deletions(-) (limited to 'actions') diff --git a/actions/newnotice.php b/actions/newnotice.php index c014f1781..8591522dc 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -164,19 +164,6 @@ class NewnoticeAction extends Action $replyto = 'false'; } - $lat = $this->trimmed('lat'); - $lon = $this->trimmed('lon'); - $location_id = $this->trimmed('location_id'); - $location_ns = $this->trimmed('location_ns'); - - if (!empty($lat) && !empty($lon) && empty($location_id)) { - $location = Location::fromLatLon($lat, $lon); - if (!empty($location)) { - $location_id = $location->location_id; - $location_ns = $location->location_ns; - } - } - $upload = null; $upload = MediaFile::fromUpload('attach'); @@ -195,12 +182,30 @@ class NewnoticeAction extends Action } } - $notice = Notice::saveNew($user->id, $content_shortened, 'web', - array('reply_to' => ($replyto == 'false') ? null : $replyto, - 'lat' => $lat, - 'lon' => $lon, - 'location_id' => $location_id, - 'location_ns' => $location_ns)); + $options = array('reply_to' => ($replyto == 'false') ? null : $replyto); + + if ($user->shareLocation()) { + + $lat = $this->trimmed('lat'); + $lon = $this->trimmed('lon'); + $location_id = $this->trimmed('location_id'); + $location_ns = $this->trimmed('location_ns'); + + if (!empty($lat) && !empty($lon) && empty($location_id)) { + $location = Location::fromLatLon($lat, $lon); + if (!empty($location)) { + $location_id = $location->location_id; + $location_ns = $location->location_ns; + } + } + + $options['lat'] = $lat; + $options['lon'] = $lon; + $options['location_id'] = $location_id; + $options['location_ns'] = $location_ns; + } + + $notice = Notice::saveNew($user->id, $content_shortened, 'web', $options); if (isset($upload)) { $upload->attachToNotice($notice); diff --git a/actions/profilesettings.php b/actions/profilesettings.php index 359664096..58bf838d7 100644 --- a/actions/profilesettings.php +++ b/actions/profilesettings.php @@ -133,6 +133,11 @@ class ProfilesettingsAction extends AccountSettingsAction ($this->arg('location')) ? $this->arg('location') : $profile->location, _('Where you are, like "City, State (or Region), Country"')); $this->elementEnd('li'); + $this->elementStart('li'); + $this->checkbox('sharelocation', _('Share my current location when posting notices'), + ($this->arg('sharelocation')) ? + $this->arg('sharelocation') : $user->shareLocation()); + $this->elementEnd('li'); Event::handle('EndProfileFormData', array($this)); $this->elementStart('li'); $this->input('tags', _('Tags'), diff --git a/classes/User.php b/classes/User.php index 6708d95b6..2bcb7c2a0 100644 --- a/classes/User.php +++ b/classes/User.php @@ -996,4 +996,20 @@ class User extends Memcached_DataObject return $ids; } + + function shareLocation() + { + $share = true; + + $prefs = User_location_prefs::staticGet('user_id', $this->id); + + if (empty($prefs)) { + $share = common_config('location', 'share'); + } else { + $share = $prefs->share_location; + $prefs->free(); + } + + return $share; + } } diff --git a/lib/default.php b/lib/default.php index 42d4623b1..b5eda7b2c 100644 --- a/lib/default.php +++ b/lib/default.php @@ -226,7 +226,7 @@ $default = 'message' => array('contentlimit' => null), 'location' => - array('namespace' => 1), // 1 = geonames, 2 = Yahoo Where on Earth + array(), 'omb' => array('timeout' => 5), // HTTP request timeout in seconds when contacting remote hosts for OMB updates 'logincommand' => -- cgit v1.2.3-54-g00ecf From e009f613d39d81e98d1438dbc182515b332a5ece Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 14:44:05 -0800 Subject: let users set location prefs from profile form --- actions/profilesettings.php | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'actions') diff --git a/actions/profilesettings.php b/actions/profilesettings.php index 58bf838d7..7db86a6c8 100644 --- a/actions/profilesettings.php +++ b/actions/profilesettings.php @@ -133,11 +133,13 @@ class ProfilesettingsAction extends AccountSettingsAction ($this->arg('location')) ? $this->arg('location') : $profile->location, _('Where you are, like "City, State (or Region), Country"')); $this->elementEnd('li'); - $this->elementStart('li'); - $this->checkbox('sharelocation', _('Share my current location when posting notices'), - ($this->arg('sharelocation')) ? - $this->arg('sharelocation') : $user->shareLocation()); - $this->elementEnd('li'); + if (common_config('location', 'share') == 'user') { + $this->elementStart('li'); + $this->checkbox('sharelocation', _('Share my current location when posting notices'), + ($this->arg('sharelocation')) ? + $this->arg('sharelocation') : $user->shareLocation()); + $this->elementEnd('li'); + } Event::handle('EndProfileFormData', array($this)); $this->elementStart('li'); $this->input('tags', _('Tags'), @@ -323,6 +325,37 @@ class ProfilesettingsAction extends AccountSettingsAction $profile->profileurl = common_profile_url($nickname); + if (common_config('location', 'share') == 'user') { + + $exists = false; + + $prefs = User_location_prefs::staticGet('user_id', $user->id); + + if (empty($prefs)) { + $prefs = new User_location_prefs(); + + $prefs->user_id = $user->id; + $prefs->created = common_sql_now(); + } else { + $exists = true; + $orig = clone($prefs); + } + + $prefs->share_location = $this->boolean('sharelocation'); + + if ($exists) { + $result = $prefs->update($orig); + } else { + $result = $prefs->insert(); + } + + if ($result === false) { + common_log_db_error($prefs, ($exists) ? 'UPDATE' : 'INSERT', __FILE__); + $this->serverError(_('Couldn\'t save location prefs.')); + return; + } + } + common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__); common_debug('New profile: ' . common_log_objstring($profile), __FILE__); -- cgit v1.2.3-54-g00ecf From ca6669538a16f36f92df918d679671b95b1859ac Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 15:13:15 -0800 Subject: Move location-argument-handling code into a single function Moved the important parts of the location-argument-handling stuff to a single function. Handles defaults and overrides correctly, and easy to use. Changed Web and API channels to use it. --- actions/apistatusesupdate.php | 20 +++++++-------- actions/newnotice.php | 22 +++++----------- classes/Notice.php | 59 +++++++++++++++++++++++++++++++++---------- 3 files changed, 61 insertions(+), 40 deletions(-) (limited to 'actions') diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php index dabbea92f..f594bbf39 100644 --- a/actions/apistatusesupdate.php +++ b/actions/apistatusesupdate.php @@ -203,12 +203,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction } } - $location = null; - - if (!empty($this->lat) && !empty($this->lon)) { - $location = Location::fromLatLon($this->lat, $this->lon); - } - $upload = null; try { @@ -235,11 +229,15 @@ class ApiStatusesUpdateAction extends ApiAuthAction $options = array('reply_to' => $reply_to); - if (!empty($location)) { - $options['lat'] = $location->lat; - $options['lon'] = $location->lon; - $options['location_id'] = $location->location_id; - $options['location_ns'] = $location->location_ns; + if ($this->user->shareLocation()) { + + $locOptions = Notice::locationOptions($this->lat, + $this->lon, + null, + null, + $this->user->getProfile()); + + $options = array_merge($options, $locOptions); } $this->notice = diff --git a/actions/newnotice.php b/actions/newnotice.php index 8591522dc..2d9f0ff79 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -186,23 +186,13 @@ class NewnoticeAction extends Action if ($user->shareLocation()) { - $lat = $this->trimmed('lat'); - $lon = $this->trimmed('lon'); - $location_id = $this->trimmed('location_id'); - $location_ns = $this->trimmed('location_ns'); - - if (!empty($lat) && !empty($lon) && empty($location_id)) { - $location = Location::fromLatLon($lat, $lon); - if (!empty($location)) { - $location_id = $location->location_id; - $location_ns = $location->location_ns; - } - } + $locOptions = Notice::locationOptions($this->trimmed('lat'), + $this->trimmed('lon'), + $this->trimmed('location_id'), + $this->trimmed('location_ns'), + $user->getProfile()); - $options['lat'] = $lat; - $options['lon'] = $lon; - $options['location_id'] = $location_id; - $options['location_ns'] = $location_ns; + $options = array_merge($options, $locOptions); } $notice = Notice::saveNew($user->id, $content_shortened, 'web', $options); diff --git a/classes/Notice.php b/classes/Notice.php index 7651d8bd5..9f68c5255 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -289,21 +289,11 @@ class Notice extends Memcached_DataObject if (!empty($lat) && !empty($lon)) { $notice->lat = $lat; $notice->lon = $lon; + } + + if (!empty($location_ns) && !empty($location_id)) { $notice->location_id = $location_id; $notice->location_ns = $location_ns; - } else if (!empty($location_ns) && !empty($location_id)) { - $location = Location::fromId($location_id, $location_ns); - if (!empty($location)) { - $notice->lat = $location->lat; - $notice->lon = $location->lon; - $notice->location_id = $location_id; - $notice->location_ns = $location_ns; - } - } else { - $notice->lat = $profile->lat; - $notice->lon = $profile->lon; - $notice->location_id = $profile->location_id; - $notice->location_ns = $profile->location_ns; } if (Event::handle('StartNoticeSave', array(&$notice))) { @@ -1429,4 +1419,47 @@ class Notice extends Memcached_DataObject return $ids; } + + function locationOptions($lat, $lon, $location_id, $location_ns, $profile = null) + { + $options = array(); + + if (!empty($location_id) && !empty($location_ns)) { + + $options['location_id'] = $location_id; + $options['location_ns'] = $location_ns; + + $location = Location::fromId($location_id, $location_ns); + + if (!empty($location)) { + $options['lat'] = $location->lat; + $options['lon'] = $location->lon; + } + + } else if (!empty($lat) && !empty($lon)) { + + $options['lat'] = $lat; + $options['lon'] = $lon; + + $location = Location::fromLatLon($lat, $lon); + + if (!empty($location)) { + $options['location_id'] = $location->location_id; + $options['location_ns'] = $location->location_ns; + } + } else if (!empty($profile)) { + + if (isset($profile->lat) && isset($profile->lon)) { + $options['lat'] = $profile->lat; + $options['lon'] = $profile->lon; + } + + if (isset($profile->location_id) && isset($profile->location_ns)) { + $options['location_id'] = $profile->location_id; + $options['location_ns'] = $profile->location_ns; + } + } + + return $options; + } } -- cgit v1.2.3-54-g00ecf From 98ce7daf5650ebd7e6f6bbaca6e57069ffccae55 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Tue, 29 Dec 2009 16:17:17 -0500 Subject: Implement user interface for user to preview what location they are sharing with a notice --- actions/geocode.php | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ actions/newnotice.php | 2 +- js/jquery.cookie.js | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ js/util.js | 46 +++++++++++++++++++++--- lib/action.php | 1 + lib/noticeform.php | 6 ++++ lib/router.php | 3 +- 7 files changed, 240 insertions(+), 7 deletions(-) create mode 100644 actions/geocode.php create mode 100644 js/jquery.cookie.js (limited to 'actions') diff --git a/actions/geocode.php b/actions/geocode.php new file mode 100644 index 000000000..7fd696baf --- /dev/null +++ b/actions/geocode.php @@ -0,0 +1,93 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2008, 2009, StatusNet, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Geocode action class + * + * @category Action + * @package StatusNet + * @author Craig Andrews + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ +class GeocodeAction extends Action +{ + function prepare($args) + { + parent::prepare($args); + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->clientError(_('There was a problem with your session token. '. + 'Try again, please.')); + } + $this->lat = $this->trimmed('lat'); + $this->lon = $this->trimmed('lon'); + $this->location = Location::fromLatLon($this->lat, $this->lon); + return true; + } + + /** + * Class handler + * + * @param array $args query arguments + * + * @return nothing + * + **/ + function handle($args) + { + header('Content-Type: application/json; charset=utf-8'); + $location_object = array(); + $location_object['lat']=$this->lat; + $location_object['lon']=$this->lon; + if($this->location) { + $location_object['location_id']=$this->location->location_id; + $location_object['location_ns']=$this->location->location_ns; + $location_object['name']=$this->location->getName(); + $location_object['url']=$this->location->getUrl(); + } + print(json_encode($location_object)); + } + + /** + * Is this action read-only? + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } +} +?> diff --git a/actions/newnotice.php b/actions/newnotice.php index 2d9f0ff79..8d89e9da0 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -184,7 +184,7 @@ class NewnoticeAction extends Action $options = array('reply_to' => ($replyto == 'false') ? null : $replyto); - if ($user->shareLocation()) { + if ($user->shareLocation() && $this->arg('notice_data-location_enabled')) { $locOptions = Notice::locationOptions($this->trimmed('lat'), $this->trimmed('lon'), diff --git a/js/jquery.cookie.js b/js/jquery.cookie.js new file mode 100644 index 000000000..6df1faca2 --- /dev/null +++ b/js/jquery.cookie.js @@ -0,0 +1,96 @@ +/** + * Cookie plugin + * + * Copyright (c) 2006 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +/** + * Create a cookie with the given name and value and other optional parameters. + * + * @example $.cookie('the_cookie', 'the_value'); + * @desc Set the value of a cookie. + * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); + * @desc Create a cookie with all available options. + * @example $.cookie('the_cookie', 'the_value'); + * @desc Create a session cookie. + * @example $.cookie('the_cookie', null); + * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain + * used when the cookie was set. + * + * @param String name The name of the cookie. + * @param String value The value of the cookie. + * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. + * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. + * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. + * If set to null or omitted, the cookie will be a session cookie and will not be retained + * when the the browser exits. + * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). + * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). + * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will + * require a secure protocol (like HTTPS). + * @type undefined + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ + +/** + * Get the value of a cookie with the given name. + * + * @example $.cookie('the_cookie'); + * @desc Get the value of a cookie. + * + * @param String name The name of the cookie. + * @return The value of the cookie. + * @type String + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ +jQuery.cookie = function(name, value, options) { + if (typeof value != 'undefined') { // name and value given, set cookie + options = options || {}; + if (value === null) { + value = ''; + options.expires = -1; + } + var expires = ''; + if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { + var date; + if (typeof options.expires == 'number') { + date = new Date(); + date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); + } else { + date = options.expires; + } + expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE + } + // CAUTION: Needed to parenthesize options.path and options.domain + // in the following expressions, otherwise they evaluate to undefined + // in the packed version for some reason... + var path = options.path ? '; path=' + (options.path) : ''; + var domain = options.domain ? '; domain=' + (options.domain) : ''; + var secure = options.secure ? '; secure' : ''; + document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); + } else { // only name given, get cookie + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } +}; \ No newline at end of file diff --git a/js/util.js b/js/util.js index 0987c6cc0..f52c70ba4 100644 --- a/js/util.js +++ b/js/util.js @@ -50,7 +50,9 @@ var SN = { // StatusNet NoticeLat: 'notice_data-lat', NoticeLon: 'notice_data-lon', NoticeLocationId: 'notice_data-location_id', - NoticeLocationNs: 'notice_data-location_ns' + NoticeLocationNs: 'notice_data-location_ns', + NoticeLocationName: 'notice_data-location_name', + NoticeLocationCookieName: 'location_enabled' } }, @@ -436,10 +438,44 @@ var SN = { // StatusNet }, NoticeLocationAttach: function() { - if(navigator.geolocation) navigator.geolocation.watchPosition(function(position) { - $('#'+SN.C.S.NoticeLat).val(position.coords.latitude); - $('#'+SN.C.S.NoticeLon).val(position.coords.longitude); - }); + if($('#notice_data-location_enabled').size()) { + if(navigator.geolocation) { + $('#notice_data-location_enabled').change(function() { + $.cookie(SN.C.S.NoticeLocationCookieName, $('#notice_data-location_enabled').attr('checked')); + if($('#notice_data-location_enabled').attr('checked')) { + $('#'+SN.C.S.NoticeLocationName).show(); + $('#'+SN.C.S.NoticeLocationName).addClass('processing'); + navigator.geolocation.getCurrentPosition(function(position) { + $('#'+SN.C.S.NoticeLat).val(position.coords.latitude); + $('#'+SN.C.S.NoticeLon).val(position.coords.longitude); + var data = {'lat': position.coords.latitude,'lon': position.coords.longitude, 'token': $('#token').val()}; + $.getJSON($('#notice_data-location_enabled_container').attr('data-geocode-url'), data,function(location) { + $('#'+SN.C.S.NoticeLocationName).removeClass('processing'); + if(typeof(location.location_ns)!="undefined") $('#'+SN.C.S.NoticeLocationNs).val(location.location_ns); + if(typeof(location.location_id)!="undefined") $('#'+SN.C.S.NoticeLocationId).val(location.location_id); + if(typeof(location.name)=="undefined") { + $('#'+SN.C.S.NoticeLocationName).text(position.coords.latitude + ' ' + position.coords.longitude); + } else { + $('#'+SN.C.S.NoticeLocationName).text(location.name); + $('#'+SN.C.S.NoticeLocationName).attr('href',location.url); + } + }); + }); + } else { + $('#'+SN.C.S.NoticeLocationName).hide(); + $('#'+SN.C.S.NoticeLat).val(""); + $('#'+SN.C.S.NoticeLon).val(""); + $('#'+SN.C.S.NoticeLocationNs).val(""); + $('#'+SN.C.S.NoticeLocationId).val(""); + } + }); + var cookieVal = $.cookie(SN.C.S.NoticeLocationCookieName); + $('#notice_data-location_enabled').attr('checked',(cookieVal == null || cookieVal == 'true')); + $('#notice_data-location_enabled').change(); + } else { + $('#notice_data-location_enabled_container').remove(); + } + } }, NewDirectMessage: function() { diff --git a/lib/action.php b/lib/action.php index dac0e2583..35df03566 100644 --- a/lib/action.php +++ b/lib/action.php @@ -252,6 +252,7 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowJQueryScripts', array($this))) { $this->script('js/jquery.min.js'); $this->script('js/jquery.form.js'); + $this->script('js/jquery.cookie.js'); $this->script('js/jquery.joverlay.min.js'); Event::handle('EndShowJQueryScripts', array($this)); } diff --git a/lib/noticeform.php b/lib/noticeform.php index 593a1e932..d85de9c22 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -220,5 +220,11 @@ class NoticeForm extends Form 'name' => 'status_submit', 'type' => 'submit', 'value' => _('Send'))); + if($this->user->shareLocation()) { + $this->out->elementStart('div',array('id' => 'notice_data-location_enabled_container', 'data-geocode-url' => common_local_url('geocode'))); + $this->out->checkbox('notice_data-location_enabled',_('Share your location ')); + $this->out->element('a', array('style' => 'display: none', 'target' => '_blank', 'id' => 'notice_data-location_name'), _('Finding your location...')); + $this->out->elementEnd('div'); + } } } diff --git a/lib/router.php b/lib/router.php index 474e05996..7ec962460 100644 --- a/lib/router.php +++ b/lib/router.php @@ -100,7 +100,8 @@ class Router 'sandbox', 'unsandbox', 'silence', 'unsilence', 'repeat', - 'deleteuser'); + 'deleteuser', + 'geocode'); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); -- cgit v1.2.3-54-g00ecf From 96ce2262f8083756ea846d8b2c59fcc87f94b54c Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 29 Dec 2009 14:30:15 -0800 Subject: If we got an identified location at ajax check time, renormalize lat/lon and naming. This'll match other displays of the names more consistently (Opera Plaza, San Francisco, CA, US instead of Opera Plaza, US) --- actions/geocode.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'actions') diff --git a/actions/geocode.php b/actions/geocode.php index 7fd696baf..9671d2c27 100644 --- a/actions/geocode.php +++ b/actions/geocode.php @@ -52,7 +52,12 @@ class GeocodeAction extends Action } $this->lat = $this->trimmed('lat'); $this->lon = $this->trimmed('lon'); - $this->location = Location::fromLatLon($this->lat, $this->lon); + $location = Location::fromLatLon($this->lat, $this->lon); + if ($location) { + $this->location = Location::fromId($location->location_id, $location->location_ns); + $this->lat = $this->location->lat; + $this->lon = $this->location->lon; + } return true; } -- cgit v1.2.3-54-g00ecf From 30f58bf15f9b7e8f2a58b998937b5fd1096ee930 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 4 Jan 2010 12:43:56 +0000 Subject: Updated element id for notice_data-geo --- actions/newnotice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actions') diff --git a/actions/newnotice.php b/actions/newnotice.php index 8d89e9da0..a4ed87bb6 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -184,7 +184,7 @@ class NewnoticeAction extends Action $options = array('reply_to' => ($replyto == 'false') ? null : $replyto); - if ($user->shareLocation() && $this->arg('notice_data-location_enabled')) { + if ($user->shareLocation() && $this->arg('notice_data-geo')) { $locOptions = Notice::locationOptions($this->trimmed('lat'), $this->trimmed('lon'), -- cgit v1.2.3-54-g00ecf From 11d7365a15bb8c8cb856bf0d545a0b550f3dbe26 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 4 Jan 2010 10:39:11 -0800 Subject: Don't spew notices when building tag cloud if there is no popularity sum to divide by. --- actions/publictagcloud.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'actions') diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index e7f6ee36c..5c7074029 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -136,7 +136,12 @@ class PublictagcloudAction extends Action $this->elementStart('dd'); $this->elementStart('ul', 'tags xoxo tag-cloud'); foreach ($tw as $tag => $weight) { - $this->showTag($tag, $weight, $weight/$sum); + if ($sum) { + $weightedSum = $weight/$sum; + } else { + $weightedSum = 1; + } + $this->showTag($tag, $weight, $weightedSum); } $this->elementEnd('ul'); $this->elementEnd('dd'); -- cgit v1.2.3-54-g00ecf From 6911e1c7972c3adec53d0fe04ebdd7da0fbd8b12 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 4 Jan 2010 11:55:27 -0800 Subject: Ticket 2141: bugs with weighted popularity lists across year boundary. Consolidated several separate implementations of the same weighting algorithm into common_sql_weight() and fixed some bugs... For MySQL, now using timestampdiff() instead of subtraction for the comparison, so we get sane results when the year doesn't match, and utc_timestamp() rather than now() so we don't get negative ages for recent items with local server timezone. Unknown whether the same problems affect PostgreSQL, but note that it lacks the timestampdiff() SQL function. --- actions/favorited.php | 8 ++------ actions/publictagcloud.php | 11 ++++------- lib/grouptagcloudsection.php | 7 +------ lib/personaltagcloudsection.php | 11 +++-------- lib/popularnoticesection.php | 6 +++--- lib/util.php | 20 ++++++++++++++++++++ 6 files changed, 33 insertions(+), 30 deletions(-) (limited to 'actions') diff --git a/actions/favorited.php b/actions/favorited.php index 150b67b0b..9ffa5b844 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -185,11 +185,7 @@ class FavoritedAction extends Action function showContent() { - if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))'; - } else { - $weightexpr='sum(exp(-(now() - fave.modified) / %s))'; - } + $weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff')); $qry = 'SELECT notice.*, '. $weightexpr . ' as weight ' . @@ -207,7 +203,7 @@ class FavoritedAction extends Action } $notice = Memcached_DataObject::cachedQuery('Notice', - sprintf($qry, common_config('popular', 'dropoff')), + $qry, 600); $nl = new NoticeList($notice, $this); diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index 5c7074029..b5b474f13 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -105,12 +105,8 @@ class PublictagcloudAction extends Action #Add the aggregated columns... $tags->selectAdd('max(notice_id) as last_notice_id'); - if(common_config('db','type')=='pgsql') { - $calc='sum(exp(-extract(epoch from (now()-created))/%s)) as weight'; - } else { - $calc='sum(exp(-(now() - created)/%s)) as weight'; - } - $tags->selectAdd(sprintf($calc, common_config('tag', 'dropoff'))); + $calc = common_sql_weight('created', common_config('tag', 'dropoff')); + $tags->selectAdd($calc . ' as weight'); $tags->groupBy('tag'); $tags->orderBy('weight DESC'); @@ -136,10 +132,11 @@ class PublictagcloudAction extends Action $this->elementStart('dd'); $this->elementStart('ul', 'tags xoxo tag-cloud'); foreach ($tw as $tag => $weight) { + common_log(LOG_DEBUG, "$weight/$sum"); if ($sum) { $weightedSum = $weight/$sum; } else { - $weightedSum = 1; + $weightedSum = 0.5; } $this->showTag($tag, $weight, $weightedSum); } diff --git a/lib/grouptagcloudsection.php b/lib/grouptagcloudsection.php index 091cf4845..14ceda085 100644 --- a/lib/grouptagcloudsection.php +++ b/lib/grouptagcloudsection.php @@ -58,11 +58,7 @@ class GroupTagCloudSection extends TagCloudSection function getTags() { - if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - notice_tag.created)) / %s))'; - } else { - $weightexpr='sum(exp(-(now() - notice_tag.created) / %s))'; - } + $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff')); $names = $this->group->getAliases(); @@ -99,7 +95,6 @@ class GroupTagCloudSection extends TagCloudSection $tag = Memcached_DataObject::cachedQuery('Notice_tag', sprintf($qry, - common_config('tag', 'dropoff'), $this->group->id, $namestring), 3600); diff --git a/lib/personaltagcloudsection.php b/lib/personaltagcloudsection.php index 0b29d58ca..091425f92 100644 --- a/lib/personaltagcloudsection.php +++ b/lib/personaltagcloudsection.php @@ -58,13 +58,9 @@ class PersonalTagCloudSection extends TagCloudSection function getTags() { - if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - notice_tag.created)) / %s))'; - } else { - $weightexpr='sum(exp(-(now() - notice_tag.created) / %s))'; - } - - $qry = 'SELECT notice_tag.tag, '. + $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff')); + + $qry = 'SELECT notice_tag.tag, '. $weightexpr . ' as weight ' . 'FROM notice_tag JOIN notice ' . 'ON notice_tag.notice_id = notice.id ' . @@ -83,7 +79,6 @@ class PersonalTagCloudSection extends TagCloudSection $tag = Memcached_DataObject::cachedQuery('Notice_tag', sprintf($qry, - common_config('tag', 'dropoff'), $this->user->id), 3600); return $tag; diff --git a/lib/popularnoticesection.php b/lib/popularnoticesection.php index 9fbc9d2dd..fbf9a60ab 100644 --- a/lib/popularnoticesection.php +++ b/lib/popularnoticesection.php @@ -48,17 +48,17 @@ class PopularNoticeSection extends NoticeSection { function getNotices() { + // @fixme there should be a common func for this if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))'; if (!empty($this->out->tag)) { $tag = pg_escape_string($this->out->tag); } } else { - $weightexpr='sum(exp(-(now() - fave.modified) / %s))'; if (!empty($this->out->tag)) { $tag = mysql_escape_string($this->out->tag); } } + $weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff')); $qry = "SELECT notice.*, $weightexpr as weight "; if(isset($tag)) { $qry .= 'FROM notice_tag, notice JOIN fave ON notice.id = fave.notice_id ' . @@ -78,7 +78,7 @@ class PopularNoticeSection extends NoticeSection $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; $notice = Memcached_DataObject::cachedQuery('Notice', - sprintf($qry, common_config('popular', 'dropoff')), + $qry, 1200); return $notice; } diff --git a/lib/util.php b/lib/util.php index 63656b604..50bd0e2ac 100644 --- a/lib/util.php +++ b/lib/util.php @@ -908,6 +908,26 @@ function common_sql_date($datetime) return strftime('%Y-%m-%d %H:%M:%S', $datetime); } +/** + * Return an SQL fragment to calculate an age-based weight from a given + * timestamp or datetime column. + * + * @param string $column name of field we're comparing against current time + * @param integer $dropoff divisor for age in seconds before exponentiation + * @return string SQL fragment + */ +function common_sql_weight($column, $dropoff) +{ + if (common_config('db', 'type') == 'pgsql') { + // PostgreSQL doesn't support timestampdiff function. + // @fixme will this use the right time zone? + // @fixme does this handle cross-year subtraction correctly? + return "sum(exp(-extract(epoch from (now() - $column)) / $dropoff))"; + } else { + return "sum(exp(timestampdiff(second, utc_timestamp(), $column) / $dropoff))"; + } +} + function common_redirect($url, $code=307) { static $status = array(301 => "Moved Permanently", -- cgit v1.2.3-54-g00ecf From af95005bc481d6f8f84a780bdc062426e22f3a03 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 4 Jan 2010 13:01:17 -0800 Subject: Ticket 2141: bugs with weighted popularity lists across year boundary. Consolidated several separate implementations of the same weighting algorithm into common_sql_weight() and fixed some bugs... For MySQL, now using timestampdiff() instead of subtraction for the comparison, so we get sane results when the year doesn't match, and utc_timestamp() rather than now() so we don't get negative ages for recent items with local server timezone. Unknown whether the same problems affect PostgreSQL, but note that it lacks the timestampdiff() SQL function. --- actions/favorited.php | 8 ++------ actions/publictagcloud.php | 15 ++++++++------- lib/grouptagcloudsection.php | 7 +------ lib/personaltagcloudsection.php | 11 +++-------- lib/popularnoticesection.php | 6 +++--- lib/util.php | 20 ++++++++++++++++++++ 6 files changed, 37 insertions(+), 30 deletions(-) (limited to 'actions') diff --git a/actions/favorited.php b/actions/favorited.php index 150b67b0b..9ffa5b844 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -185,11 +185,7 @@ class FavoritedAction extends Action function showContent() { - if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))'; - } else { - $weightexpr='sum(exp(-(now() - fave.modified) / %s))'; - } + $weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff')); $qry = 'SELECT notice.*, '. $weightexpr . ' as weight ' . @@ -207,7 +203,7 @@ class FavoritedAction extends Action } $notice = Memcached_DataObject::cachedQuery('Notice', - sprintf($qry, common_config('popular', 'dropoff')), + $qry, 600); $nl = new NoticeList($notice, $this); diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php index e7f6ee36c..9e4478dbb 100644 --- a/actions/publictagcloud.php +++ b/actions/publictagcloud.php @@ -105,12 +105,8 @@ class PublictagcloudAction extends Action #Add the aggregated columns... $tags->selectAdd('max(notice_id) as last_notice_id'); - if(common_config('db','type')=='pgsql') { - $calc='sum(exp(-extract(epoch from (now()-created))/%s)) as weight'; - } else { - $calc='sum(exp(-(now() - created)/%s)) as weight'; - } - $tags->selectAdd(sprintf($calc, common_config('tag', 'dropoff'))); + $calc = common_sql_weight('created', common_config('tag', 'dropoff')); + $tags->selectAdd($calc . ' as weight'); $tags->groupBy('tag'); $tags->orderBy('weight DESC'); @@ -136,7 +132,12 @@ class PublictagcloudAction extends Action $this->elementStart('dd'); $this->elementStart('ul', 'tags xoxo tag-cloud'); foreach ($tw as $tag => $weight) { - $this->showTag($tag, $weight, $weight/$sum); + if ($sum) { + $weightedSum = $weight/$sum; + } else { + $weightedSum = 0.5; + } + $this->showTag($tag, $weight, $weightedSum); } $this->elementEnd('ul'); $this->elementEnd('dd'); diff --git a/lib/grouptagcloudsection.php b/lib/grouptagcloudsection.php index 091cf4845..14ceda085 100644 --- a/lib/grouptagcloudsection.php +++ b/lib/grouptagcloudsection.php @@ -58,11 +58,7 @@ class GroupTagCloudSection extends TagCloudSection function getTags() { - if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - notice_tag.created)) / %s))'; - } else { - $weightexpr='sum(exp(-(now() - notice_tag.created) / %s))'; - } + $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff')); $names = $this->group->getAliases(); @@ -99,7 +95,6 @@ class GroupTagCloudSection extends TagCloudSection $tag = Memcached_DataObject::cachedQuery('Notice_tag', sprintf($qry, - common_config('tag', 'dropoff'), $this->group->id, $namestring), 3600); diff --git a/lib/personaltagcloudsection.php b/lib/personaltagcloudsection.php index 0b29d58ca..091425f92 100644 --- a/lib/personaltagcloudsection.php +++ b/lib/personaltagcloudsection.php @@ -58,13 +58,9 @@ class PersonalTagCloudSection extends TagCloudSection function getTags() { - if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - notice_tag.created)) / %s))'; - } else { - $weightexpr='sum(exp(-(now() - notice_tag.created) / %s))'; - } - - $qry = 'SELECT notice_tag.tag, '. + $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff')); + + $qry = 'SELECT notice_tag.tag, '. $weightexpr . ' as weight ' . 'FROM notice_tag JOIN notice ' . 'ON notice_tag.notice_id = notice.id ' . @@ -83,7 +79,6 @@ class PersonalTagCloudSection extends TagCloudSection $tag = Memcached_DataObject::cachedQuery('Notice_tag', sprintf($qry, - common_config('tag', 'dropoff'), $this->user->id), 3600); return $tag; diff --git a/lib/popularnoticesection.php b/lib/popularnoticesection.php index 9fbc9d2dd..fbf9a60ab 100644 --- a/lib/popularnoticesection.php +++ b/lib/popularnoticesection.php @@ -48,17 +48,17 @@ class PopularNoticeSection extends NoticeSection { function getNotices() { + // @fixme there should be a common func for this if (common_config('db', 'type') == 'pgsql') { - $weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))'; if (!empty($this->out->tag)) { $tag = pg_escape_string($this->out->tag); } } else { - $weightexpr='sum(exp(-(now() - fave.modified) / %s))'; if (!empty($this->out->tag)) { $tag = mysql_escape_string($this->out->tag); } } + $weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff')); $qry = "SELECT notice.*, $weightexpr as weight "; if(isset($tag)) { $qry .= 'FROM notice_tag, notice JOIN fave ON notice.id = fave.notice_id ' . @@ -78,7 +78,7 @@ class PopularNoticeSection extends NoticeSection $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; $notice = Memcached_DataObject::cachedQuery('Notice', - sprintf($qry, common_config('popular', 'dropoff')), + $qry, 1200); return $notice; } diff --git a/lib/util.php b/lib/util.php index ed81aeba1..fdcc87677 100644 --- a/lib/util.php +++ b/lib/util.php @@ -908,6 +908,26 @@ function common_sql_date($datetime) return strftime('%Y-%m-%d %H:%M:%S', $datetime); } +/** + * Return an SQL fragment to calculate an age-based weight from a given + * timestamp or datetime column. + * + * @param string $column name of field we're comparing against current time + * @param integer $dropoff divisor for age in seconds before exponentiation + * @return string SQL fragment + */ +function common_sql_weight($column, $dropoff) +{ + if (common_config('db', 'type') == 'pgsql') { + // PostgreSQL doesn't support timestampdiff function. + // @fixme will this use the right time zone? + // @fixme does this handle cross-year subtraction correctly? + return "sum(exp(-extract(epoch from (now() - $column)) / $dropoff))"; + } else { + return "sum(exp(timestampdiff(second, utc_timestamp(), $column) / $dropoff))"; + } +} + function common_redirect($url, $code=307) { static $status = array(301 => "Moved Permanently", -- cgit v1.2.3-54-g00ecf From 250bcfa8dc3ebf3c2c8458f363a62c529eb3a7f6 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Tue, 5 Jan 2010 17:47:37 -0500 Subject: Require users to login to view attachments on private sites Thank you jeff-themovie for this implementation! --- README | 20 ++++++++++++---- actions/getfile.php | 66 ++++++++++++++++++++++++++++++++++++++--------------- classes/File.php | 33 ++++++++++++++++----------- config.php.sample | 17 +++++++++++++- htaccess.sample | 8 ------- lib/default.php | 1 + 6 files changed, 100 insertions(+), 45 deletions(-) (limited to 'actions') diff --git a/README b/README index 6e39890cb..c26fe786e 100644 --- a/README +++ b/README @@ -710,11 +710,21 @@ private site, but users of the private site may be able to subscribe to users on a remote site. (Or not... it's not well tested.) The "proper behaviour" hasn't been defined here, so handle with care. -If fancy URLs is enabled, access to file attachments can also be -restricted to logged-in users only. Uncomment the appropriate rewrite -rule in .htaccess or your server's httpd.conf. (This most likely will -not work if you are using a virtual server for attachments, so consider -the performance/security tradeoff.) +Access to file attachments can also be restricted to logged-in users only. +1. Add a directory outside the web root where your file uploads will be + stored. Usually a command like this will work: + + mkdir /var/www/mublog-files + +2. Make the file uploads directory writeable by the web server. An + insecure way to do this is: + + chmod a+x /var/www/mublog-files + +3. Tell StatusNet to use this directory for file uploads. Add a line + like this to your config.php: + + $config['attachments']['dir'] = '/var/www/mublog-files'; Upgrading ========= diff --git a/actions/getfile.php b/actions/getfile.php index ecda34c0f..cd327e410 100644 --- a/actions/getfile.php +++ b/actions/getfile.php @@ -1,13 +1,13 @@ . * - * @category Personal + * @category PrivateAttachments * @package StatusNet * @author Jeffery To - * @copyright 2008-2009 StatusNet, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 * @link http://status.net/ */ -if (!defined('STATUSNET') && !defined('LACONICA')) { +if (!defined('STATUSNET')) { exit(1); } require_once 'MIME/Type.php'; /** - * Action for getting a file attachment + * An action for returning a requested file * - * @category Personal - * @package StatusNet - * @author Jeffery To - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ + * The StatusNet system will do an implicit user check if the site is + * private before allowing this to continue + * + * @category PrivateAttachments + * @package StatusNet + * @author Jeffery To + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ */ class GetfileAction extends Action @@ -68,7 +72,7 @@ class GetfileAction extends Action $path = null; if ($filename) { - $path = common_config('attachments', 'dir') . $filename; + $path = File::path($filename); } if (empty($path) or !file_exists($path)) { @@ -103,6 +107,10 @@ class GetfileAction extends Action function lastModified() { + if (common_config('site', 'use_x_sendfile')) { + return null; + } + return filemtime($this->path); } @@ -114,8 +122,24 @@ class GetfileAction extends Action * * @return string etag http header */ + function etag() { + if (common_config('site', 'use_x_sendfile')) { + return null; + } + + $cache = common_memcache(); + if($cache) { + $key = common_cache_key('attachments:etag:' . $this->path); + $etag = $cache->get($key); + if($etag === false) { + $etag = crc32(file_get_contents($this->path)); + $cache->set($key,$etag); + } + return $etag; + } + $stat = stat($this->path); return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"'; } @@ -133,13 +157,19 @@ class GetfileAction extends Action // undo headers set by PHP sessions $sec = session_cache_expire() * 60; header('Expires: ' . date(DATE_RFC1123, time() + $sec)); - header('Cache-Control: public, max-age=' . $sec); - header('Pragma: public'); + header('Cache-Control: max-age=' . $sec); parent::handle($args); $path = $this->path; + header('Content-Type: ' . MIME_Type::autoDetect($path)); - readfile($path); + + if (common_config('site', 'use_x_sendfile')) { + header('X-Sendfile: ' . $path); + } else { + header('Content-Length: ' . filesize($path)); + readfile($path); + } } } diff --git a/classes/File.php b/classes/File.php index e04a9d525..6173f31d6 100644 --- a/classes/File.php +++ b/classes/File.php @@ -182,25 +182,32 @@ class File extends Memcached_DataObject static function url($filename) { - $path = common_config('attachments', 'path'); + if(common_config('site','private')) { - if ($path[strlen($path)-1] != '/') { - $path .= '/'; - } + return common_local_url('getfile', + array('filename' => $filename)); - if ($path[0] != '/') { - $path = '/'.$path; - } + } else { + $path = common_config('attachments', 'path'); - $server = common_config('attachments', 'server'); + if ($path[strlen($path)-1] != '/') { + $path .= '/'; + } - if (empty($server)) { - $server = common_config('site', 'server'); - } + if ($path[0] != '/') { + $path = '/'.$path; + } + + $server = common_config('attachments', 'server'); - // XXX: protocol + if (empty($server)) { + $server = common_config('site', 'server'); + } - return 'http://'.$server.$path.$filename; + // XXX: protocol + + return 'http://'.$server.$path.$filename; + } } function getEnclosure(){ diff --git a/config.php.sample b/config.php.sample index 91e6614c0..b8852dc67 100644 --- a/config.php.sample +++ b/config.php.sample @@ -41,6 +41,20 @@ $config['site']['path'] = 'statusnet'; // Make the site invisible to non-logged-in users // $config['site']['private'] = true; +// If your web server supports X-Sendfile (Apache with mod_xsendfile, +// lighttpd, nginx), you can enable X-Sendfile support for better +// performance. Presently, only attachment serving when the site is +// in private mode will use X-Sendfile. +// $config['site']['X-Sendfile'] = false; +// You may also need to enable X-Sendfile support for your web server and +// allow it to access files outside of the web root. For Apache with +// mod_xsendfile, you can add these to your .htaccess or server config: +// +// XSendFile on +// XSendFileAllowAbove on +// +// See http://tn123.ath.cx/mod_xsendfile/ for mod_xsendfile. + // If you want logging sent to a file instead of syslog // $config['site']['logfile'] = '/tmp/statusnet.log'; @@ -265,6 +279,7 @@ $config['sphinx']['port'] = 3312; // $config['attachments']['user_quota'] = 50000000; // $config['attachments']['monthly_quota'] = 15000000; // $config['attachments']['uploads'] = true; -// $config['attachments']['path'] = "/file/"; +// $config['attachments']['path'] = "/file/"; //ignored if site is private +// $config['attachments']['dir'] = INSTALLDIR . '/file/'; // $config['oohembed']['endpoint'] = 'http://oohembed.com/oohembed/'; diff --git a/htaccess.sample b/htaccess.sample index 91ae9da9b..37eb8e01e 100644 --- a/htaccess.sample +++ b/htaccess.sample @@ -5,14 +5,6 @@ RewriteBase /mublog/ - # If your site is private and want to only allow logged-in users to - # be able to download file attachments, uncomment this rule. - # - # If you have a custom attachment path - # ($config['attachments']['path']), change "file/" to match. - # - #RewriteRule ^file/(.*) getfile/$1 - RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) index.php?p=$1 [L,QSA] diff --git a/lib/default.php b/lib/default.php index eea11eb2b..f2e577149 100644 --- a/lib/default.php +++ b/lib/default.php @@ -54,6 +54,7 @@ $default = 'dupelimit' => 60, # default for same person saying the same thing 'textlimit' => 140, 'indent' => true, + 'use_x_sendfile' => false, ), 'db' => array('database' => 'YOU HAVE TO SET THIS IN config.php', -- cgit v1.2.3-54-g00ecf From 013e6dfdd481470cc02994b6db58a387a95016ca Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 6 Jan 2010 13:40:28 -0800 Subject: Don't output notices from deleted users. --- actions/twitapisearchatom.php | 9 ++++++++- lib/jsonsearchresultslist.php | 10 ++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'actions') diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php index 1cb8d7efe..baed2a0c7 100644 --- a/actions/twitapisearchatom.php +++ b/actions/twitapisearchatom.php @@ -208,7 +208,14 @@ class TwitapisearchatomAction extends ApiAction $this->showFeed(); foreach ($notices as $n) { - $this->showEntry($n); + + $profile = $n->getProfile(); + + // Don't show notices from deleted users + + if (!empty($profile)) { + $this->showEntry($n); + } } $this->endAtom(); diff --git a/lib/jsonsearchresultslist.php b/lib/jsonsearchresultslist.php index 569bfa873..0d72ddf7a 100644 --- a/lib/jsonsearchresultslist.php +++ b/lib/jsonsearchresultslist.php @@ -105,8 +105,14 @@ class JSONSearchResultsList break; } - $item = new ResultItem($this->notice); - array_push($this->results, $item); + $profile = $this->notice->getProfile(); + + // Don't show notices from deleted users + + if (!empty($profile)) { + $item = new ResultItem($this->notice); + array_push($this->results, $item); + } } $time_end = microtime(true); -- cgit v1.2.3-54-g00ecf From a1c3a2d3a12c1667492e4107007b31ec3a1f9c7b Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 6 Jan 2010 16:21:29 -0800 Subject: Fix broken API method /api/statusnet/groups/leave/:id.:format --- actions/apigroupleave.php | 8 ++++---- actions/leavegroup.php | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'actions') diff --git a/actions/apigroupleave.php b/actions/apigroupleave.php index 514a3a557..5627bfc14 100644 --- a/actions/apigroupleave.php +++ b/actions/apigroupleave.php @@ -108,7 +108,7 @@ class ApiGroupLeaveAction extends ApiAuthAction $member = new Group_member(); $member->group_id = $this->group->id; - $member->profile_id = $this->auth->id; + $member->profile_id = $this->auth_user->id; if (!$member->find(true)) { $this->serverError(_('You are not a member of this group.')); @@ -118,12 +118,12 @@ class ApiGroupLeaveAction extends ApiAuthAction $result = $member->delete(); if (!$result) { - common_log_db_error($member, 'INSERT', __FILE__); + common_log_db_error($member, 'DELETE', __FILE__); $this->serverError( sprintf( - _('Could not remove user %s to group %s.'), + _('Could not remove user %s from group %s.'), $this->user->nickname, - $this->$group->nickname + $this->group->nickname ) ); return; diff --git a/actions/leavegroup.php b/actions/leavegroup.php index 08fce1509..90c85e1a4 100644 --- a/actions/leavegroup.php +++ b/actions/leavegroup.php @@ -123,8 +123,8 @@ class LeavegroupAction extends Action $result = $member->delete(); if (!$result) { - common_log_db_error($member, 'INSERT', __FILE__); - $this->serverError(sprintf(_('Could not remove user %s to group %s'), + common_log_db_error($member, 'DELETE', __FILE__); + $this->serverError(sprintf(_('Could not remove user %s from group %s'), $cur->nickname, $this->group->nickname)); } -- cgit v1.2.3-54-g00ecf From deeaafe71239597878cb3fd78aa66314745796a3 Mon Sep 17 00:00:00 2001 From: Ciaran Gultnieks Date: Thu, 7 Jan 2010 20:59:31 +0000 Subject: Fixes to bugs where non-local messages were being wrong put in the public timeline and public xmpp feed --- actions/shownotice.php | 2 +- classes/Notice.php | 2 +- lib/jabber.php | 2 +- lib/noticelist.php | 2 +- lib/ping.php | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'actions') diff --git a/actions/shownotice.php b/actions/shownotice.php index 5d16fdad9..d09100f67 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -103,7 +103,7 @@ class ShownoticeAction extends OwnerDesignAction $this->user = User::staticGet('id', $this->profile->id); - if (! $this->notice->is_local) { + if ($this->notice->is_local == Notice::REMOTE_OMB) { common_redirect($this->notice->uri); return false; } diff --git a/classes/Notice.php b/classes/Notice.php index 9fa022650..9bda47827 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -63,7 +63,7 @@ class Notice extends Memcached_DataObject public $created; // datetime multiple_key not_null default_0000-00-00%2000%3A00%3A00 public $modified; // timestamp not_null default_CURRENT_TIMESTAMP public $reply_to; // int(4) - public $is_local; // tinyint(1) + public $is_local; // int(4) public $source; // varchar(32) public $conversation; // int(4) public $lat; // decimal(10,7) diff --git a/lib/jabber.php b/lib/jabber.php index 01aed8ffa..6e094c207 100644 --- a/lib/jabber.php +++ b/lib/jabber.php @@ -440,7 +440,7 @@ function jabber_public_notice($notice) // XXX: should we send out non-local messages if public,localonly // = false? I think not - if ($public && $notice->is_local) { + if ($public && $notice->is_local == LOCAL_PUBLIC) { $profile = Profile::staticGet($notice->profile_id); if (!$profile) { diff --git a/lib/noticelist.php b/lib/noticelist.php index 5eb2633ac..78abf34a7 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -379,7 +379,7 @@ class NoticeListItem extends Widget function showNoticeLink() { - if($this->notice->is_local){ + if($this->notice->is_local == Notice::LOCAL_PUBLIC || $this->notice->is_local == Notice::LOCAL_NONPUBLIC){ $noticeurl = common_local_url('shownotice', array('notice' => $this->notice->id)); }else{ diff --git a/lib/ping.php b/lib/ping.php index 5698c4038..735af9ef1 100644 --- a/lib/ping.php +++ b/lib/ping.php @@ -21,7 +21,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } function ping_broadcast_notice($notice) { - if (!$notice->is_local) { + if ($notice->is_local != Notice::LOCAL_PUBLIC && $notice->is_local != Notice::LOCAL_NONPUBLIC) { return true; } @@ -115,4 +115,4 @@ function ping_notice_tags($notice) { return implode('|', $tags); } return NULL; -} \ No newline at end of file +} -- cgit v1.2.3-54-g00ecf From 6ae6fb7a35cb666fbb59218fa57717522af96f60 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 7 Jan 2010 15:59:07 -0800 Subject: clear profile location data if unparseable location string --- actions/profilesettings.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'actions') diff --git a/actions/profilesettings.php b/actions/profilesettings.php index ee236fe62..0d6777879 100644 --- a/actions/profilesettings.php +++ b/actions/profilesettings.php @@ -316,7 +316,12 @@ class ProfilesettingsAction extends AccountSettingsAction $loc = Location::fromName($location); - if (!empty($loc)) { + if (empty($loc)) { + $profile->lat = null; + $profile->lon = null; + $profile->location_id = null; + $profile->location_ns = null; + } else { $profile->lat = $loc->lat; $profile->lon = $loc->lon; $profile->location_id = $loc->location_id; -- cgit v1.2.3-54-g00ecf From 4a4ac7a1082405621ce8e578099ddb7be329bb38 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 7 Jan 2010 17:26:40 -0800 Subject: add a version action to give credit and list plugins --- actions/version.php | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/action.php | 2 + lib/router.php | 4 +- 3 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 actions/version.php (limited to 'actions') diff --git a/actions/version.php b/actions/version.php new file mode 100644 index 000000000..92a59ed47 --- /dev/null +++ b/actions/version.php @@ -0,0 +1,227 @@ +. + * + * @category Info + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Version info page + * + * A page that shows version information for this site. Helpful for + * debugging, for giving credit to authors, and for linking to more + * complete documentation for admins. + * + * @category Info + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 + * @link http://status.net/ + */ + +class VersionAction extends Action +{ + var $pluginVersions = array(); + + /** + * Return true since we're read-only. + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return true; + } + + /** + * Returns the page title + * + * @return string page title + */ + + function title() + { + return sprintf(_("StatusNet %s"), STATUSNET_VERSION); + } + + /** + * Prepare to run + * + * Fire off an event to let plugins report their + * versions. + * + * @param array $args array misc. arguments + * + * @return boolean true + */ + + function prepare($args) + { + parent::prepare($args); + + Event::handle('PluginVersion', array(&$this->pluginVersions)); + + return true; + } + + /** + * Execute the action + * + * Shows a page with the version information in the + * content area. + * + * @param array $args ignored. + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + $this->showPage(); + } + + /** + * Show version information + * + * @return void + */ + + function showContent() + { + $this->elementStart('p'); + + $this->raw(sprintf(_('This site is powered by %s version %s, '. + 'Copyright 2008-2010 StatusNet, Inc. '. + 'and contributors.'), + XMLStringer::estring('a', array('href' => 'http://status.net/'), + _('StatusNet')), + STATUSNET_VERSION)); + $this->elementEnd('p'); + + $this->element('h2', null, _('Contributors')); + + $this->element('p', null, implode(', ', $this->contributors)); + + $this->element('h2', null, _('License')); + + $this->element('p', null, + _('StatusNet is free software: you can redistribute it and/or modify '. + 'it under the terms of the GNU Affero General Public License as published by '. + 'the Free Software Foundation, either version 3 of the License, or '. + '(at your option) any later version. ')); + + $this->element('p', null, + _('This program is distributed in the hope that it will be useful, '. + 'but WITHOUT ANY WARRANTY; without even the implied warranty of '. + 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the '. + 'GNU Affero General Public License for more details. ')); + + $this->elementStart('p'); + $this->raw(sprintf(_('You should have received a copy of the GNU Affero General Public License '. + 'along with this program. If not, see %s.'), + XMLStringer::estring('a', array('href' => 'http://www.gnu.org/licenses/agpl.html'), + 'http://www.gnu.org/licenses/agpl.html'))); + $this->elementEnd('p'); + + // XXX: Theme information? + + if (count($this->pluginVersions)) { + $this->element('h2', null, _('Plugins')); + + foreach ($this->pluginVersions as $plugin) { + $this->elementStart('dl'); + $this->element('dt', null, _('Name')); + if (array_key_exists('homepage', $plugin)) { + $this->elementStart('dd'); + $this->element('a', array('href' => $plugin['homepage']), + $plugin['name']); + $this->elementEnd('dd'); + } else { + $this->element('dd', null, $plugin['name']); + } + $this->element('dt', null, _('Version')); + $this->element('dd', null, $plugin['version']); + if (array_key_exists('author', $plugin)) { + $this->element('dt', null, _('Author(s)')); + $this->element('dd', null, $plugin['author']); + } + if (array_key_exists('rawdescription', $plugin)) { + $this->element('dt', null, _('Description')); + $this->elementStart('dd'); + $this->raw($plugin['rawdescription']); + $this->elementEnd('dd'); + } else if (array_key_exists('description', $plugin)) { + $this->element('dt', null, _('Description')); + $this->element('dd', null, $plugin['description']); + } + $this->elementEnd('dl'); + } + } + + } + + var $contributors = array('Evan Prodromou (StatusNet)', + 'Zach Copley (StatusNet)', + 'Earle Martin (StatusNet)', + 'Marie-Claude Doyon (StatusNet)', + 'Sarven Capadisli (StatusNet)', + 'Robin Millette (StatusNet)', + 'Ciaran Gultnieks', + 'Michael Landers', + 'Ori Avtalion', + 'Garret Buell', + 'Mike Cochrane', + 'Matthew Gregg', + 'Florian Biree', + 'Erik Stambaugh', + 'drry', + 'Gina Haeussge', + 'Tryggvi Björgvinsson', + 'Adrian Lang', + 'Meitar Moscovitz', + 'Sean Murphy', + 'Leslie Michael Orchard', + 'Eric Helgeson', + 'Ken Sedgwick', + 'Brian Hendrickson', + 'Tobias Diekershoff', + 'Dan Moore', + 'Fil', + 'Jeff Mitchell', + 'Brenda Wallace', + 'Jeffery To', + 'Federico Marani', + 'Craig Andrews', + 'mEDI', + 'Brett Taylor'); +} diff --git a/lib/action.php b/lib/action.php index 35df03566..715072d1e 100644 --- a/lib/action.php +++ b/lib/action.php @@ -736,6 +736,8 @@ class Action extends HTMLOutputter // lawsuit _('Privacy')); $this->menuItem(common_local_url('doc', array('title' => 'source')), _('Source')); + $this->menuItem(common_local_url('version'), + _('Version')); $this->menuItem(common_local_url('doc', array('title' => 'contact')), _('Contact')); $this->menuItem(common_local_url('doc', array('title' => 'badge')), diff --git a/lib/router.php b/lib/router.php index 7ec962460..287d3c79f 100644 --- a/lib/router.php +++ b/lib/router.php @@ -101,7 +101,9 @@ class Router 'silence', 'unsilence', 'repeat', 'deleteuser', - 'geocode'); + 'geocode', + 'version', + ); foreach ($main as $a) { $m->connect('main/'.$a, array('action' => $a)); -- cgit v1.2.3-54-g00ecf From 9fc63a56a2280c69f55b747e4c1a78b45ea799a6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 7 Jan 2010 17:28:31 -0800 Subject: make a list of plugins --- actions/version.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'actions') diff --git a/actions/version.php b/actions/version.php index 92a59ed47..3d74560c7 100644 --- a/actions/version.php +++ b/actions/version.php @@ -158,7 +158,10 @@ class VersionAction extends Action if (count($this->pluginVersions)) { $this->element('h2', null, _('Plugins')); + $this->elementStart('ul'); + foreach ($this->pluginVersions as $plugin) { + $this->elementStart('li'); $this->elementStart('dl'); $this->element('dt', null, _('Name')); if (array_key_exists('homepage', $plugin)) { @@ -185,7 +188,9 @@ class VersionAction extends Action $this->element('dd', null, $plugin['description']); } $this->elementEnd('dl'); + $this->elementEnd('li'); } + $this->elementEnd('ul'); } } -- cgit v1.2.3-54-g00ecf From a7e73d318ab3e0f85ed86448d7250a65df435289 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 8 Jan 2010 10:20:51 +0000 Subject: Added Brigitte Schuster (http://brigitteschuster.com) as one of the contributors to StatusNet. She created the identi.ca, laconi.ca, and status.net logos. --- README | 1 + actions/version.php | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'actions') diff --git a/README b/README index c26fe786e..7457215a1 100644 --- a/README +++ b/README @@ -1622,6 +1622,7 @@ if anyone's been overlooked in error. * Craig Andrews * mEDI * Brett Taylor +* Brigitte Schuster Thanks also to the developers of our upstream library code and to the thousands of people who have tried out Identi.ca, installed StatusNet, diff --git a/actions/version.php b/actions/version.php index 3d74560c7..f8a17ced1 100644 --- a/actions/version.php +++ b/actions/version.php @@ -228,5 +228,6 @@ class VersionAction extends Action 'Federico Marani', 'Craig Andrews', 'mEDI', - 'Brett Taylor'); + 'Brett Taylor', + 'Brigitte Schuster'); } -- cgit v1.2.3-54-g00ecf From 5d04e4588691be6177f3475e61ba5b908a77280a Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 8 Jan 2010 11:41:12 +0000 Subject: Updated markup for versions page --- actions/version.php | 75 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 19 deletions(-) (limited to 'actions') diff --git a/actions/version.php b/actions/version.php index f8a17ced1..2cf914296 100644 --- a/actions/version.php +++ b/actions/version.php @@ -110,6 +110,36 @@ class VersionAction extends Action $this->showPage(); } + + /* + * Override to add hentry, and content-inner classes + * + * @return void + */ + function showContentBlock() + { + $this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); + $this->showPageTitle(); + $this->showPageNoticeBlock(); + $this->elementStart('div', array('id' => 'content_inner', + 'class' => 'entry-content')); + // show the actual content (forms, lists, whatever) + $this->showContent(); + $this->elementEnd('div'); + $this->elementEnd('div'); + } + + + /* + * Overrride to add entry-title class + * + * @return void + */ + function showPageTitle() { + $this->element('h1', array('class' => 'entry-title'), $this->title()); + } + + /** * Show version information * @@ -158,39 +188,46 @@ class VersionAction extends Action if (count($this->pluginVersions)) { $this->element('h2', null, _('Plugins')); - $this->elementStart('ul'); + $this->elementStart('table', array('id' => 'plugins_enabled')); + + $this->elementStart('thead'); + $this->elementStart('tr'); + $this->element('th', array('id' => 'plugin_name'), _('Name')); + $this->element('th', array('id' => 'plugin_version'), _('Version')); + $this->element('th', array('id' => 'plugin_authors'), _('Author(s)')); + $this->element('th', array('id' => 'plugin_description'), _('Description')); + $this->elementEnd('tr'); + $this->elementEnd('thead'); + $this->elementStart('tbody'); foreach ($this->pluginVersions as $plugin) { - $this->elementStart('li'); - $this->elementStart('dl'); - $this->element('dt', null, _('Name')); + $this->elementStart('tr'); if (array_key_exists('homepage', $plugin)) { - $this->elementStart('dd'); + $this->elementStart('th'); $this->element('a', array('href' => $plugin['homepage']), $plugin['name']); - $this->elementEnd('dd'); + $this->elementEnd('th'); } else { - $this->element('dd', null, $plugin['name']); + $this->element('th', null, $plugin['name']); } - $this->element('dt', null, _('Version')); - $this->element('dd', null, $plugin['version']); + + $this->element('td', null, $plugin['version']); + if (array_key_exists('author', $plugin)) { - $this->element('dt', null, _('Author(s)')); - $this->element('dd', null, $plugin['author']); + $this->element('td', null, $plugin['author']); } + if (array_key_exists('rawdescription', $plugin)) { - $this->element('dt', null, _('Description')); - $this->elementStart('dd'); + $this->elementStart('td'); $this->raw($plugin['rawdescription']); - $this->elementEnd('dd'); + $this->elementEnd('td'); } else if (array_key_exists('description', $plugin)) { - $this->element('dt', null, _('Description')); - $this->element('dd', null, $plugin['description']); + $this->element('td', null, $plugin['description']); } - $this->elementEnd('dl'); - $this->elementEnd('li'); + $this->elementEnd('tr'); } - $this->elementEnd('ul'); + $this->elementEnd('tbody'); + $this->elementEnd('table'); } } -- cgit v1.2.3-54-g00ecf