From 7160e11395168723f6692b140f35a943267731cd Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 24 Dec 2009 15:13:30 -0800 Subject: add setconfig.php script to set configuration options --- scripts/setconfig.php | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 scripts/setconfig.php diff --git a/scripts/setconfig.php b/scripts/setconfig.php new file mode 100644 index 000000000..b102f99b1 --- /dev/null +++ b/scripts/setconfig.php @@ -0,0 +1,98 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); + +$shortoptions = 'd'; +$longoptions = array('delete'); + +$helptext = << +With three args, set the setting to the value. +With two args, just show the setting. +With -d, delete the setting. + + [section] section to use (required) + [setting] setting to use (required) + value to set (optional) + + -d --delete delete the setting (no value) + +END_OF_SETCONFIG_HELP; + +require_once INSTALLDIR.'/scripts/commandline.inc'; + +if (count($args) < 2 || count($args) > 3) { + show_help(); + exit(1); +} + +$section = $args[0]; +$setting = $args[1]; + +if (count($args) == 3) { + $value = $args[2]; +} else { + $value = null; +} + +try { + + if (have_option('d', 'delete')) { // Delete + if (count($args) != 2) { + show_help(); + exit(1); + } + + if (have_option('v', 'verbose')) { + print "Deleting setting $section/$setting..."; + } + + $setting = Config::pkeyGet(array('section' => $section, + 'setting' => $setting)); + + if (empty($setting)) { + print "Not found.\n"; + } else { + $result = $setting->delete(); + if ($result) { + print "DONE.\n"; + } else { + print "ERROR.\n"; + } + } + } else if (count($args) == 2) { // show + if (have_option('v', 'verbose')) { + print "$section/$setting = "; + } + $value = common_config($section, $setting); + print "$value\n"; + } else { // set + if (have_option('v', 'verbose')) { + print "Setting $section/$setting..."; + } + Config::save($section, $setting, $value); + print "DONE.\n"; + } + +} catch (Exception $e) { + print $e->getMessage() . "\n"; + exit(1); +} -- cgit v1.2.3-54-g00ecf 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(-) 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(-) 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 5d6b6bfd3494a7829c8fdccfdf85278811db83c8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 27 Dec 2009 11:04:53 -0800 Subject: admin page checks for right to review flags --- plugins/UserFlag/UserFlagPlugin.php | 12 +++++++++- plugins/UserFlag/adminprofileflag.php | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index 75dcca4fc..b4f9bd783 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -43,6 +43,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { class UserFlagPlugin extends Plugin { + const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; + function onCheckSchema() { $schema = Schema::get(); @@ -138,7 +140,7 @@ class UserFlagPlugin extends Plugin function onEndShowStatusNetStyles($action) { - $action->cssLink(common_path('plugins/UserFlag/userflag.css'), + $action->cssLink(common_path('plugins/UserFlag/userflag.css'), null, 'screen, projection, tv'); return true; } @@ -148,4 +150,12 @@ class UserFlagPlugin extends Plugin $action->inlineScript('if ($(".form_entity_flag").length > 0) { SN.U.FormXHR($(".form_entity_flag")); }'); return true; } + + function onUserRightsCheck($user, $right, &$result) { + if ($right == self::REVIEWFLAGS) { + $result = $user->hasRole('moderator'); + return false; // done processing! + } + return true; // unchanged! + } } diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index 20b808637..5d6acf086 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -43,6 +43,8 @@ if (!defined('STATUSNET')) { class AdminprofileflagAction extends Action { + var $page = null; + /** * Take arguments for running * @@ -55,6 +57,47 @@ class AdminprofileflagAction extends Action { parent::prepare($args); + $user = common_current_user(); + + // User must be logged in. + + if (!common_logged_in()) { + $this->clientError(_('Not logged in.')); + return; + } + + $user = common_current_user(); + + // ...because they're logged in + + assert(!empty($user)); + + // It must be a "real" login, not saved cookie login + + if (!common_is_real_login()) { + // Cookie theft is too easy; we require automatic + // logins to re-authenticate before admining the site + common_set_returnto($this->selfUrl()); + if (Event::handle('RedirectToLogin', array($this, $user))) { + common_redirect(common_local_url('login'), 303); + } + } + + // User must have the right to review flags + + if (!$user->hasRight(UserFlagPlugin::REVIEWFLAGS)) { + $this->clientError(_('You cannot review profile flags.')); + return false; + } + + $page = $this->int('page'); + + if (empty($page)) { + $this->page = 1; + } else { + $this->page = $page; + } + return true; } -- cgit v1.2.3-54-g00ecf From 4b7835caa570a27f372935fdda799dd065ae8ea4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 27 Dec 2009 11:47:54 -0800 Subject: pagination works for flagged profiles --- plugins/UserFlag/adminprofileflag.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index 5d6acf086..b0888a31d 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -43,7 +43,8 @@ if (!defined('STATUSNET')) { class AdminprofileflagAction extends Action { - var $page = null; + var $page = null; + var $profiles = null; /** * Take arguments for running @@ -90,14 +91,14 @@ class AdminprofileflagAction extends Action return false; } - $page = $this->int('page'); + $this->page = $this->trimmed('page'); - if (empty($page)) { + if (empty($this->page)) { $this->page = 1; - } else { - $this->page = $page; } + $this->profiles = $this->getProfiles(); + return true; } @@ -128,11 +129,12 @@ class AdminprofileflagAction extends Action function showContent() { - $profile = $this->getProfiles(); + $pl = new FlaggedProfileList($this->profiles, $this); - $pl = new FlaggedProfileList($profile, $this); + $cnt = $pl->show(); - $pl->show(); + $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, + $this->page, 'adminprofileflag'); } function getProfiles() @@ -146,7 +148,12 @@ class AdminprofileflagAction extends Action $ufp->whereAdd('cleared is NULL'); $ufp->groupBy('profile_id'); - $ufp->orderBy('flag_count DESC'); + $ufp->orderBy('flag_count DESC, profile_id DESC'); + + $offset = ($this->page-1) * PROFILES_PER_PAGE; + $limit = PROFILES_PER_PAGE + 1; + + $ufp->limit($offset, $limit); $profiles = array(); -- cgit v1.2.3-54-g00ecf From 75fbec2fa336ac9b749fa273ac5a44c2fb211623 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 07:58:33 -0800 Subject: Add tools to clear flags Added a form to clear all flags for a profile, when showed on adminprofileflags list. Add an action to handle the form, and a right for the action. --- plugins/UserFlag/clearflag.php | 129 +++++++++++++++++++++++++++++++++++++ plugins/UserFlag/clearflagform.php | 92 ++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 plugins/UserFlag/clearflag.php create mode 100644 plugins/UserFlag/clearflagform.php diff --git a/plugins/UserFlag/clearflag.php b/plugins/UserFlag/clearflag.php new file mode 100644 index 000000000..58151d33c --- /dev/null +++ b/plugins/UserFlag/clearflag.php @@ -0,0 +1,129 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 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')) { + exit(1); +} + +/** + * Action to clear flags for a profile + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class ClearflagAction extends ProfileFormAction +{ + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + + function prepare($args) + { + if (!parent::prepare($args)) { + return false; + } + + $user = common_current_user(); + + assert(!empty($user)); // checked above + assert(!empty($this->profile)); // checked above + + return true; + } + + /** + * Handle request + * + * Overriding the base Action's handle() here to deal check + * for Ajax and return an HXR response if necessary + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ + + function handle($args) + { + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $this->handlePost(); + if (!$this->boolean('ajax')) { + $this->returnToArgs(); + } + } + } + + /** + * Handle POST + * + * @return void + */ + + function handlePost() + { + $ufp = new User_flag_profile(); + + $result = $ufp->query('UPDATE user_flag_profile ' . + 'SET cleared = now() ' . + 'WHERE cleared is null ' . + 'AND profile_id = ' . $this->profile->id); + + if ($result == false) { + throw new ServerException(sprintf(_("Couldn't clear flags for profile '%s'."), + $this->profile->nickname)); + } + + $ufp->free(); + + if ($this->boolean('ajax')) { + $this->ajaxResults(); + } + } + + function ajaxResults() { + header('Content-Type: text/xml;charset=utf-8'); + $this->xw->startDocument('1.0', 'UTF-8'); + $this->elementStart('html'); + $this->elementStart('head'); + $this->element('title', null, _('Flags cleared')); + $this->elementEnd('head'); + $this->elementStart('body'); + $this->element('p', 'cleared', _('Cleared')); + $this->elementEnd('body'); + $this->elementEnd('html'); + } +} + diff --git a/plugins/UserFlag/clearflagform.php b/plugins/UserFlag/clearflagform.php new file mode 100644 index 000000000..5ad6055d3 --- /dev/null +++ b/plugins/UserFlag/clearflagform.php @@ -0,0 +1,92 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/form.php'; + +/** + * Form for clearing profile flags + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ClearFlagForm extends ProfileActionForm +{ + /** + * class of the form + * Action this form provides + * + * @return string class of the form + */ + + function formClass() + { + return 'form_entity_clearflag'; + } + + /** + * Action this form provides + * + * @return string Name of the action, lowercased. + */ + + function target() + { + return 'clearflag'; + } + + /** + * Title of the form + * + * @return string Title of the form, internationalized + */ + + function title() + { + return _('Clear'); + } + + /** + * Description of the form + * + * @return string description of the form, internationalized + */ + + function description() + { + return _('Clear all flags'); + } +} -- cgit v1.2.3-54-g00ecf From 2c2a82fda0b78422802a9d0b23afc765c2f5f52b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:19:22 -0800 Subject: add stuff for clearing flags to UserFlagPlugin --- plugins/UserFlag/UserFlagPlugin.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index b4f9bd783..78979ace2 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -44,6 +44,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { class UserFlagPlugin extends Plugin { const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; + const CLEARFLAGS = 'UserFlagPlugin::clearflags'; function onCheckSchema() { @@ -72,6 +73,7 @@ class UserFlagPlugin extends Plugin function onRouterInitialized($m) { $m->connect('main/flag/profile', array('action' => 'flagprofile')); + $m->connect('main/flag/clear', array('action' => 'clearflag')); $m->connect('admin/profile/flag', array('action' => 'adminprofileflag')); return true; } @@ -82,9 +84,11 @@ class UserFlagPlugin extends Plugin { case 'FlagprofileAction': case 'AdminprofileflagAction': + case 'ClearflagAction': require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower(mb_substr($cls, 0, -6)) . '.php'); return false; case 'FlagProfileForm': + case 'ClearFlagForm': require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower($cls . '.php')); return false; case 'User_flag_profile': @@ -152,10 +156,13 @@ class UserFlagPlugin extends Plugin } function onUserRightsCheck($user, $right, &$result) { - if ($right == self::REVIEWFLAGS) { + switch ($right) { + case self::REVIEWFLAGS: + case self::CLEARFLAGS: $result = $user->hasRole('moderator'); return false; // done processing! } + return true; // unchanged! } } -- cgit v1.2.3-54-g00ecf From 85b8b35f53258a95989a8679455e0b2fd72bc5f5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:19:56 -0800 Subject: clear flags and show flaggers in adminflagprofile --- plugins/UserFlag/adminprofileflag.php | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index b0888a31d..ab1a86ac4 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -182,6 +182,8 @@ class FlaggedProfileList extends ProfileList { class FlaggedProfileListItem extends ProfileListItem { + const MAX_FLAGGERS = 5; + var $user = null; var $r2args = null; @@ -252,5 +254,70 @@ class FlaggedProfileListItem extends ProfileListItem function showClearButton() { + if ($this->user->hasRight(UserFlagPlugin::CLEARFLAGS)) { + $this->out->elementStart('li', 'entity_clear'); + $cf = new ClearFlagForm($this->out, $this->profile, $this->r2args); + $cf->show(); + $this->out->elementEnd('li'); + } + } + + function endProfile() + { + $this->showFlaggersList(); + parent::endProfile(); + } + + function showFlaggersList() + { + $flaggers = array(); + + $ufp = new User_flag_profile(); + + $ufp->selectAdd(); + $ufp->selectAdd('user_id'); + $ufp->profile_id = $this->profile->id; + $ufp->orderBy('created'); + + if ($ufp->find()) { // XXX: this should always happen + while ($ufp->fetch()) { + $user = User::staticGet('id', $ufp->user_id); + if (!empty($user)) { // XXX: this would also be unusual + $flaggers[] = clone($user); + } + } + } + + $cnt = count($flaggers); + $others = 0; + + if ($cnt > self::MAX_FLAGGERS) { + $flaggers = array_slice($flaggers, 0, self::MAX_FLAGGERS); + $others = $cnt - self::MAX_FLAGGERS; + } + + $lnks = array(); + + foreach ($flaggers as $flagger) { + + $url = common_local_url('showstream', + array('nickname' => $flagger->nickname)); + + $lnks[] = XMLStringer::estring('a', array('href' => $url, + 'class' => 'flagger'), + $flagger->nickname); + } + + if ($cnt > 0) { + $text = _('Flagged by '); + $text .= implode(', ', $lnks); + if ($others > 0) { + $text .= sprintf(_(' and %d others'), $others); + } + + $this->out->elementStart('p', array('class' => 'flaggers')); + $this->out->raw($text); + $this->out->elementEnd('p'); + } } } -- cgit v1.2.3-54-g00ecf From ea23111a5611a3634faf3828f3f5c67867a460e3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:37:30 -0800 Subject: PHPCS-clean UserFlagPlugin --- plugins/UserFlag/UserFlagPlugin.php | 100 ++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index 78979ace2..21af506a9 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -27,7 +27,7 @@ * @link http://status.net/ */ -if (!defined('STATUSNET') && !defined('LACONICA')) { +if (!defined('STATUSNET')) { exit(1); } @@ -46,6 +46,15 @@ class UserFlagPlugin extends Plugin const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; const CLEARFLAGS = 'UserFlagPlugin::clearflags'; + /** + * Hook for ensuring our tables are created + * + * Ensures that the user_flag_profile table exists + * and has the right columns. + * + * @return boolean hook return + */ + function onCheckSchema() { $schema = Schema::get(); @@ -65,40 +74,61 @@ class UserFlagPlugin extends Plugin return true; } - function onInitializePlugin() - { - // XXX: do something here? - return true; - } + /** + * Add our actions to the URL router + * + * @param Net_URL_Mapper $m URL mapper for this hit + * + * @return boolean hook return + */ - function onRouterInitialized($m) { + function onRouterInitialized($m) + { $m->connect('main/flag/profile', array('action' => 'flagprofile')); $m->connect('main/flag/clear', array('action' => 'clearflag')); $m->connect('admin/profile/flag', array('action' => 'adminprofileflag')); return true; } - function onAutoload($cls) + /** + * Auto-load our classes if called + * + * @param string $cls Class to load + * + * @return boolean hook return + */ + + function onAutoload($cls) { switch ($cls) { case 'FlagprofileAction': case 'AdminprofileflagAction': case 'ClearflagAction': - require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower(mb_substr($cls, 0, -6)) . '.php'); + include_once INSTALLDIR.'/plugins/UserFlag/' . + strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; case 'FlagProfileForm': case 'ClearFlagForm': - require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower($cls . '.php')); + include_once INSTALLDIR.'/plugins/UserFlag/' . strtolower($cls . '.php'); return false; case 'User_flag_profile': - require_once(INSTALLDIR.'/plugins/UserFlag/'.$cls.'.php'); + include_once INSTALLDIR.'/plugins/UserFlag/'.$cls.'.php'; return false; default: return true; } } + /** + * Add a 'flag' button to profile page + * + * @param Action &$action The action being called + * @param Profile $profile Profile being shown + * + * @return boolean hook result + */ + function onEndProfilePageActionsElements(&$action, $profile) { $user = common_current_user(); @@ -111,8 +141,8 @@ class UserFlagPlugin extends Plugin $action->element('p', 'flagged', _('Flagged')); } else { $form = new FlagProfileForm($action, $profile, - array('action' => 'showstream', - 'nickname' => $profile->nickname)); + array('action' => 'showstream', + 'nickname' => $profile->nickname)); $form->show(); } @@ -122,6 +152,14 @@ class UserFlagPlugin extends Plugin return true; } + /** + * Add a 'flag' button to profiles in a list + * + * @param ProfileListItem $item item being shown + * + * @return boolean hook result + */ + function onEndProfileListItemActionElements($item) { $user = common_current_user(); @@ -142,6 +180,14 @@ class UserFlagPlugin extends Plugin return true; } + /** + * Add our plugin's CSS to page output + * + * @param Action $action action being shown + * + * @return boolean hook result + */ + function onEndShowStatusNetStyles($action) { $action->cssLink(common_path('plugins/UserFlag/userflag.css'), @@ -149,13 +195,37 @@ class UserFlagPlugin extends Plugin return true; } + /** + * Initialize any flagging buttons on the page + * + * @param Action $action action being shown + * + * @return boolean hook result + */ + function onEndShowScripts($action) { - $action->inlineScript('if ($(".form_entity_flag").length > 0) { SN.U.FormXHR($(".form_entity_flag")); }'); + $action->inlineScript('if ($(".form_entity_flag").length > 0) { '. + 'SN.U.FormXHR($(".form_entity_flag")); '. + '}'); return true; } - function onUserRightsCheck($user, $right, &$result) { + /** + * Check whether a user has one of our defined rights + * + * We define extra rights; this function checks to see if a + * user has one of them. + * + * @param User $user User being checked + * @param string $right Right we're checking + * @param boolean &$result out, result of the check + * + * @return boolean hook result + */ + + function onUserRightsCheck($user, $right, &$result) + { switch ($right) { case self::REVIEWFLAGS: case self::CLEARFLAGS: -- cgit v1.2.3-54-g00ecf From c8fd5403e5bfc3b9110042eb1573904625f607e1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:45:21 -0800 Subject: PHPCS-clean adminprofileflags.php --- plugins/UserFlag/adminprofileflag.php | 99 ++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index ab1a86ac4..17374927b 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -117,7 +117,14 @@ class AdminprofileflagAction extends Action $this->showPage(); } - function title() { + /** + * Title of this page + * + * @return string Title of the page + */ + + function title() + { return _('Flagged profiles'); } @@ -137,6 +144,12 @@ class AdminprofileflagAction extends Action $this->page, 'adminprofileflag'); } + /** + * Retrieve this action's profiles + * + * @return Profile $profile Profile query results + */ + function getProfiles() { $ufp = new User_flag_profile(); @@ -151,7 +164,7 @@ class AdminprofileflagAction extends Action $ufp->orderBy('flag_count DESC, profile_id DESC'); $offset = ($this->page-1) * PROFILES_PER_PAGE; - $limit = PROFILES_PER_PAGE + 1; + $limit = PROFILES_PER_PAGE + 1; $ufp->limit($offset, $limit); @@ -172,7 +185,27 @@ class AdminprofileflagAction extends Action } } -class FlaggedProfileList extends ProfileList { +/** + * Specialization of ProfileList to show flagging information + * + * Most of the hard part is done in FlaggedProfileListItem. + * + * @category Widget + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class FlaggedProfileList extends ProfileList +{ + /** + * Factory method for creating new list items + * + * @param Profile $profile Profile to create an item for + * + * @return ProfileListItem newly-created item + */ function newListItem($profile) { @@ -180,13 +213,29 @@ class FlaggedProfileList extends ProfileList { } } +/** + * Specialization of ProfileListItem to show flagging information + * + * @category Widget + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + class FlaggedProfileListItem extends ProfileListItem { const MAX_FLAGGERS = 5; - var $user = null; + var $user = null; var $r2args = null; + /** + * Overload parent's action list with our own moderation-oriented buttons + * + * @return void + */ + function showActions() { $this->user = common_current_user(); @@ -211,6 +260,12 @@ class FlaggedProfileListItem extends ProfileListItem $this->endActions(); } + /** + * Show a button to sandbox the profile + * + * @return void + */ + function showSandboxButton() { if ($this->user->hasRight(Right::SANDBOXUSER)) { @@ -226,6 +281,12 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Show a button to silence the profile + * + * @return void + */ + function showSilenceButton() { if ($this->user->hasRight(Right::SILENCEUSER)) { @@ -241,6 +302,12 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Show a button to delete user and profile + * + * @return void + */ + function showDeleteButton() { @@ -252,6 +319,12 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Show a button to clear flags + * + * @return void + */ + function showClearButton() { if ($this->user->hasRight(UserFlagPlugin::CLEARFLAGS)) { @@ -262,12 +335,24 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Overload parent function to add flaggers list + * + * @return void + */ + function endProfile() { $this->showFlaggersList(); parent::endProfile(); } + /** + * Show a list of people who've flagged this profile + * + * @return void + */ + function showFlaggersList() { $flaggers = array(); @@ -288,12 +373,12 @@ class FlaggedProfileListItem extends ProfileListItem } } - $cnt = count($flaggers); + $cnt = count($flaggers); $others = 0; if ($cnt > self::MAX_FLAGGERS) { $flaggers = array_slice($flaggers, 0, self::MAX_FLAGGERS); - $others = $cnt - self::MAX_FLAGGERS; + $others = $cnt - self::MAX_FLAGGERS; } $lnks = array(); @@ -310,7 +395,9 @@ class FlaggedProfileListItem extends ProfileListItem if ($cnt > 0) { $text = _('Flagged by '); + $text .= implode(', ', $lnks); + if ($others > 0) { $text .= sprintf(_(' and %d others'), $others); } -- cgit v1.2.3-54-g00ecf From df98ddff0c6daa6a94c71be11b7db683f6181482 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 09:06:38 -0800 Subject: phpcs-clean clearflag.php --- plugins/UserFlag/clearflag.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/UserFlag/clearflag.php b/plugins/UserFlag/clearflag.php index 58151d33c..bd6732e2d 100644 --- a/plugins/UserFlag/clearflag.php +++ b/plugins/UserFlag/clearflag.php @@ -89,6 +89,8 @@ class ClearflagAction extends ProfileFormAction /** * Handle POST * + * Executes the actions; deletes all flags + * * @return void */ @@ -102,8 +104,9 @@ class ClearflagAction extends ProfileFormAction 'AND profile_id = ' . $this->profile->id); if ($result == false) { - throw new ServerException(sprintf(_("Couldn't clear flags for profile '%s'."), - $this->profile->nickname)); + $msg = sprintf(_("Couldn't clear flags for profile '%s'."), + $this->profile->nickname); + throw new ServerException($msg); } $ufp->free(); @@ -113,7 +116,14 @@ class ClearflagAction extends ProfileFormAction } } - function ajaxResults() { + /** + * Return results in ajax form + * + * @return void + */ + + function ajaxResults() + { header('Content-Type: text/xml;charset=utf-8'); $this->xw->startDocument('1.0', 'UTF-8'); $this->elementStart('html'); @@ -126,4 +136,3 @@ class ClearflagAction extends ProfileFormAction $this->elementEnd('html'); } } - -- cgit v1.2.3-54-g00ecf From 4a5bac43c33ef0006b85eb39eda10de55985d52d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 09:08:28 -0800 Subject: phpcs-clean flagprofile.php --- plugins/UserFlag/flagprofile.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/plugins/UserFlag/flagprofile.php b/plugins/UserFlag/flagprofile.php index 9bce7865b..55753f4e8 100644 --- a/plugins/UserFlag/flagprofile.php +++ b/plugins/UserFlag/flagprofile.php @@ -63,8 +63,7 @@ class FlagprofileAction extends ProfileFormAction assert(!empty($this->profile)); // checked above if (User_flag_profile::exists($this->profile->id, - $user->id)) - { + $user->id)) { $this->clientError(_('Flag already exists.')); return false; } @@ -72,7 +71,6 @@ class FlagprofileAction extends ProfileFormAction return true; } - /** * Handle request * @@ -114,8 +112,9 @@ class FlagprofileAction extends ProfileFormAction $ufp->created = common_sql_now(); if (!$ufp->insert()) { - throw new ServerException(sprintf(_("Couldn't flag profile '%s' for review."), - $this->profile->nickname)); + $msg = sprintf(_("Couldn't flag profile '%s' for review."), + $this->profile->nickname); + throw new ServerException($msg); } $ufp->free(); @@ -125,7 +124,14 @@ class FlagprofileAction extends ProfileFormAction } } - function ajaxResults() { + /** + * Return results as AJAX message + * + * @return void + */ + + function ajaxResults() + { header('Content-Type: text/xml;charset=utf-8'); $this->xw->startDocument('1.0', 'UTF-8'); $this->elementStart('html'); -- cgit v1.2.3-54-g00ecf From a80fa178726da3ff6d06272bd06f35afbfe2f757 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 09:15:07 -0800 Subject: phpcs-clean User_flag_profile as best as possible --- plugins/UserFlag/User_flag_profile.php | 59 ++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/plugins/UserFlag/User_flag_profile.php b/plugins/UserFlag/User_flag_profile.php index 30bd4ae68..b8f3f3fe1 100644 --- a/plugins/UserFlag/User_flag_profile.php +++ b/plugins/UserFlag/User_flag_profile.php @@ -1,5 +1,15 @@ + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * * StatusNet - the distributed open-source microblogging tool * Copyright (C) 2009, StatusNet, Inc. * @@ -23,6 +33,18 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; +/** + * Data class for profile flags + * + * A class representing a user flagging another profile for review. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + class User_flag_profile extends Memcached_DataObject { ###START_AUTOCODE @@ -40,7 +62,14 @@ class User_flag_profile extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function table() { + /** + * return table definition for DB_DataObject + * + * @return array array of column definitions + */ + + function table() + { return array( 'profile_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, 'user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, @@ -49,15 +78,39 @@ class User_flag_profile extends Memcached_DataObject ); } - function keys() { + /** + * return key definitions for DB_DataObject + * + * @return array key definitions + */ + + function keys() + { return array('profile_id' => 'N', 'user_id' => 'N'); } + /** + * Get a single object with multiple keys + * + * @param array $kv Map of key-value pairs + * + * @return User_flag_profile found object or null + */ + function &pkeyGet($kv) { return Memcached_DataObject::pkeyGet('User_flag_profile', $kv); } + /** + * Check if a flag exists for given profile and user + * + * @param integer $profile_id Profile to check for + * @param integer $user_id User to check for + * + * @return boolean true if exists, else false + */ + static function exists($profile_id, $user_id) { $ufp = User_flag_profile::pkeyGet(array('profile_id' => $profile_id, -- cgit v1.2.3-54-g00ecf From c07f22104094d26f7f6266c2b59f7999030fda1a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 10:42:31 -0800 Subject: check if other user exists before unsub --- classes/User.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/classes/User.php b/classes/User.php index 484dc8c82..6708d95b6 100644 --- a/classes/User.php +++ b/classes/User.php @@ -625,7 +625,11 @@ class User extends Memcached_DataObject // Cancel their subscription, if it exists - subs_unsubscribe_to($other->getUser(),$this->getProfile()); + $otherUser = User::staticGet('id', $other->id); + + if (!empty($otherUser)) { + subs_unsubscribe_to($otherUser, $this->getProfile()); + } $block->query('COMMIT'); -- 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(-) 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(-) 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 6d3e6b42849ad14b15cb4c41c4f8baac45e58df0 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 10:58:49 -0800 Subject: move flag creation to a method of data object --- plugins/UserFlag/User_flag_profile.php | 19 +++++++++++++++++++ plugins/UserFlag/flagprofile.php | 14 ++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/plugins/UserFlag/User_flag_profile.php b/plugins/UserFlag/User_flag_profile.php index b8f3f3fe1..658259452 100644 --- a/plugins/UserFlag/User_flag_profile.php +++ b/plugins/UserFlag/User_flag_profile.php @@ -118,4 +118,23 @@ class User_flag_profile extends Memcached_DataObject return !empty($ufp); } + + static function create($user_id, $profile_id) + { + $ufp = new User_flag_profile(); + + $ufp->profile_id = $profile_id; + $ufp->user_id = $user_id; + $ufp->created = common_sql_now(); + + if (!$ufp->insert()) { + $msg = sprintf(_("Couldn't flag profile '%d' for review."), + $profile_id); + throw new ServerException($msg); + } + + $ufp->free(); + + return true; + } } diff --git a/plugins/UserFlag/flagprofile.php b/plugins/UserFlag/flagprofile.php index 55753f4e8..2d0f0abb9 100644 --- a/plugins/UserFlag/flagprofile.php +++ b/plugins/UserFlag/flagprofile.php @@ -105,19 +105,9 @@ class FlagprofileAction extends ProfileFormAction assert(!empty($user)); assert(!empty($this->profile)); - $ufp = new User_flag_profile(); + // throws an exception on error - $ufp->profile_id = $this->profile->id; - $ufp->user_id = $user->id; - $ufp->created = common_sql_now(); - - if (!$ufp->insert()) { - $msg = sprintf(_("Couldn't flag profile '%s' for review."), - $this->profile->nickname); - throw new ServerException($msg); - } - - $ufp->free(); + User_flag_profile::create($user->id, $this->profile->id); if ($this->boolean('ajax')) { $this->ajaxResults(); -- cgit v1.2.3-54-g00ecf From d9efeb6ac3810ef2ed7da6a274c3fc5ef1cfd5d7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 11:02:44 -0800 Subject: optionally flag a profile for review when blocked --- plugins/UserFlag/UserFlagPlugin.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index 21af506a9..0fca5f9cf 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -46,6 +46,8 @@ class UserFlagPlugin extends Plugin const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; const CLEARFLAGS = 'UserFlagPlugin::clearflags'; + public $flagOnBlock = true; + /** * Hook for ensuring our tables are created * @@ -235,4 +237,23 @@ class UserFlagPlugin extends Plugin return true; // unchanged! } + + /** + * Optionally flag profile when a block happens + * + * We optionally add a flag when a profile has been blocked + * + * @param User $user User doing the block + * @param Profile $profile Profile being blocked + * + * @return boolean hook result + */ + + function onEndBlockProfile($user, $profile) + { + if ($this->flagOnBlock) { + User_flag_profile::create($user->id, $profile->id); + } + return true; + } } -- cgit v1.2.3-54-g00ecf From 749b8b5b8ca4d1c39d350879aadddbdb9d8b71d5 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 28 Dec 2009 12:27:28 -0800 Subject: Drop the Google Client API-based AJAX geolocation lookup shim -- it fails to ask for user permission, causing us quite a bit of difficulty. --- js/geometa.js | 123 +++------------------------------------------------------- 1 file changed, 5 insertions(+), 118 deletions(-) diff --git a/js/geometa.js b/js/geometa.js index 21deb1885..87e3c99a1 100644 --- a/js/geometa.js +++ b/js/geometa.js @@ -1,4 +1,4 @@ -// A shim to implement the W3C Geolocation API Specification using Gears or the Ajax API +// A shim to implement the W3C Geolocation API Specification using Gears if (typeof navigator.geolocation == "undefined" || navigator.geolocation.shim ) (function(){ // -- BEGIN GEARS_INIT @@ -96,122 +96,9 @@ var GearsGeoLocation = (function() { }; }); -var AjaxGeoLocation = (function() { - // -- PRIVATE - var loading = false; - var loadGoogleLoader = function() { - if (!hasGoogleLoader() && !loading) { - loading = true; - var s = document.createElement('script'); - s.src = (document.location.protocol == "https:"?"https://":"http://") + 'www.google.com/jsapi?callback=_google_loader_apiLoaded'; - s.type = "text/javascript"; - document.getElementsByTagName('body')[0].appendChild(s); - } - }; - - var queue = []; - var addLocationQueue = function(callback) { - queue.push(callback); - } - - var runLocationQueue = function() { - if (hasGoogleLoader()) { - while (queue.length > 0) { - var call = queue.pop(); - call(); - } - } - } - - window['_google_loader_apiLoaded'] = function() { - runLocationQueue(); - } - - var hasGoogleLoader = function() { - return (window['google'] && google['loader']); - } - - var checkGoogleLoader = function(callback) { - if (hasGoogleLoader()) return true; - - addLocationQueue(callback); - - loadGoogleLoader(); - - return false; - }; - - loadGoogleLoader(); // start to load as soon as possible just in case - - // -- PUBLIC - return { - shim: true, - - type: "ClientLocation", - - lastPosition: null, - - getCurrentPosition: function(successCallback, errorCallback, options) { - var self = this; - if (!checkGoogleLoader(function() { - self.getCurrentPosition(successCallback, errorCallback, options); - })) return; - - if (google.loader.ClientLocation) { - var cl = google.loader.ClientLocation; - - var position = { - coords: { - latitude: cl.latitude, - longitude: cl.longitude, - altitude: null, - accuracy: 43000, // same as Gears accuracy over wifi? - altitudeAccuracy: null, - heading: null, - speed: null, - }, - // extra info that is outside of the bounds of the core API - address: { - city: cl.address.city, - country: cl.address.country, - country_code: cl.address.country_code, - region: cl.address.region - }, - timestamp: new Date() - }; - - successCallback(position); - - this.lastPosition = position; - } else if (errorCallback === "function") { - errorCallback({ code: 3, message: "Using the Google ClientLocation API and it is not able to calculate a location."}); - } - }, - - watchPosition: function(successCallback, errorCallback, options) { - this.getCurrentPosition(successCallback, errorCallback, options); - - var self = this; - var watchId = setInterval(function() { - self.getCurrentPosition(successCallback, errorCallback, options); - }, 10000); - - return watchId; - }, - - clearWatch: function(watchId) { - clearInterval(watchId); - }, - - getPermission: function(siteName, imageUrl, extraMessage) { - // for now just say yes :) - return true; - } - - }; -}); - -// If you have Gears installed use that, else use Ajax ClientLocation -navigator.geolocation = (window.google && google.gears) ? GearsGeoLocation() : AjaxGeoLocation(); +// If you have Gears installed use that +if (window.google && google.gears) { + navigator.geolocation = GearsGeoLocation(); +} })(); -- cgit v1.2.3-54-g00ecf From dd0aaac70ec092edd38b53285ac74a4ad36e7c1e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 12:42:22 -0800 Subject: First version of blacklist plugin First version of blacklist plugin. Replaces custom code in identi.ca's config.php, which was getting scary and long. Also correctly handles changed nicknames or URLs in profile settings and using 'forbidden' URLs in notice text. --- plugins/Blacklist/BlacklistPlugin.php | 203 ++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 plugins/Blacklist/BlacklistPlugin.php diff --git a/plugins/Blacklist/BlacklistPlugin.php b/plugins/Blacklist/BlacklistPlugin.php new file mode 100644 index 000000000..655b0926b --- /dev/null +++ b/plugins/Blacklist/BlacklistPlugin.php @@ -0,0 +1,203 @@ +. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 StatusNet Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Plugin to prevent use of nicknames or URLs on a blacklist + * + * @category Plugin + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class BlacklistPlugin extends Plugin +{ + public $nicknames = array(); + public $urls = array(); + + /** + * Hook registration to prevent blacklisted homepages or nicknames + * + * Throws an exception if there's a blacklisted homepage or nickname. + * + * @param Action $action Action being called (usually register) + * + * @return boolean hook value + */ + + function onStartRegistrationTry($action) + { + $homepage = strtolower($action->trimmed('homepage')); + + if (!empty($homepage)) { + if (!$this->_checkUrl($homepage)) { + $msg = sprintf(_m("You may not register with homepage '%s'"), + $homepage); + throw new ClientException($msg); + } + } + + $nickname = strtolower($action->trimmed('nickname')); + + if (!empty($nickname)) { + if (!$this->_checkNickname($nickname)) { + $msg = sprintf(_m("You may not register with nickname '%s'"), + $nickname); + throw new ClientException($msg); + } + } + + return true; + } + + /** + * Hook profile update to prevent blacklisted homepages or nicknames + * + * Throws an exception if there's a blacklisted homepage or nickname. + * + * @param Action $action Action being called (usually register) + * + * @return boolean hook value + */ + + function onStartProfileSaveForm($action) + { + $homepage = strtolower($action->trimmed('homepage')); + + if (!empty($homepage)) { + if (!$this->_checkUrl($homepage)) { + $msg = sprintf(_m("You may not use homepage '%s'"), + $homepage); + throw new ClientException($msg); + } + } + + $nickname = strtolower($action->trimmed('nickname')); + + if (!empty($nickname)) { + if (!$this->_checkNickname($nickname)) { + $msg = sprintf(_m("You may not use nickname '%s'"), + $nickname); + throw new ClientException($msg); + } + } + + return true; + } + + /** + * Hook notice save to prevent blacklisted urls + * + * Throws an exception if there's a blacklisted url in the content. + * + * @param Notice &$notice Notice being saved + * + * @return boolean hook value + */ + + function onStartNoticeSave(&$notice) + { + common_replace_urls_callback($notice->content, + array($this, 'checkNoticeUrl')); + return true; + } + + /** + * Helper callback for notice save + * + * Throws an exception if there's a blacklisted url in the content. + * + * @param string $url URL in the notice content + * + * @return boolean hook value + */ + + function checkNoticeUrl($url) + { + // It comes in special'd, so we unspecial it + // before comparing against patterns + + $url = htmlspecialchars_decode($url); + + if (!$this->_checkUrl($url)) { + $msg = sprintf(_m("You may not use url '%s' in notices"), + $url); + throw new ClientException($msg); + } + + return $url; + } + + /** + * Helper for checking URLs + * + * Checks an URL against our patterns for a match. + * + * @param string $url URL to check + * + * @return boolean true means it's OK, false means it's bad + */ + + private function _checkUrl($url) + { + foreach ($this->urls as $pattern) { + if (preg_match("/$pattern/", $url)) { + return false; + } + } + + return true; + } + + /** + * Helper for checking nicknames + * + * Checks a nickname against our patterns for a match. + * + * @param string $nickname nickname to check + * + * @return boolean true means it's OK, false means it's bad + */ + + private function _checkNickname($nickname) + { + foreach ($this->nicknames as $pattern) { + if (preg_match("/$pattern/", $nickname)) { + return false; + } + } + + return true; + } +} -- cgit v1.2.3-54-g00ecf