3 * StatusNet, the distributed open-source microblogging tool
5 * Plugin to prevent use of nicknames or URLs on a blacklist
9 * LICENCE: This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * @author Evan Prodromou <evan@status.net>
25 * @copyright 2010 StatusNet Inc.
26 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
27 * @link http://status.net/
30 if (!defined('STATUSNET')) {
35 * Plugin to prevent use of nicknames or URLs on a blacklist
39 * @author Evan Prodromou <evan@status.net>
40 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
41 * @link http://status.net/
44 class BlacklistPlugin extends Plugin
46 const VERSION = STATUSNET_VERSION;
48 public $nicknames = array();
49 public $urls = array();
50 public $canAdmin = true;
52 private $_nicknamePatterns = array();
53 private $_urlPatterns = array();
56 * Initialize the plugin
63 $confNicknames = $this->_configArray('blacklist', 'nicknames')
65 $this->_nicknamePatterns = array_merge($this->nicknames,
68 $confURLs = $this->_configArray('blacklist', 'urls')
70 $this->_urlPatterns = array_merge($this->urls,
75 * Retrieve an array from configuration
77 * Carefully checks a section.
79 * @param string $section Configuration section
80 * @param string $setting Configuration setting
82 * @return array configuration values
85 function _configArray($section, $setting)
87 $config = common_config($section, $setting);
91 } else if (is_array($config)) {
93 } else if (is_string($config)) {
94 return explode("\r\n", $config);
96 throw new Exception("Unknown data type for config $section + $setting");
101 * Hook registration to prevent blacklisted homepages or nicknames
103 * Throws an exception if there's a blacklisted homepage or nickname.
105 * @param Action $action Action being called (usually register)
107 * @return boolean hook value
110 function onStartRegistrationTry($action)
112 $homepage = strtolower($action->trimmed('homepage'));
114 if (!empty($homepage)) {
115 if (!$this->_checkUrl($homepage)) {
116 $msg = sprintf(_m("You may not register with homepage '%s'"),
118 throw new ClientException($msg);
122 $nickname = strtolower($action->trimmed('nickname'));
124 if (!empty($nickname)) {
125 if (!$this->_checkNickname($nickname)) {
126 $msg = sprintf(_m("You may not register with nickname '%s'"),
128 throw new ClientException($msg);
136 * Hook profile update to prevent blacklisted homepages or nicknames
138 * Throws an exception if there's a blacklisted homepage or nickname.
140 * @param Action $action Action being called (usually register)
142 * @return boolean hook value
145 function onStartProfileSaveForm($action)
147 $homepage = strtolower($action->trimmed('homepage'));
149 if (!empty($homepage)) {
150 if (!$this->_checkUrl($homepage)) {
151 $msg = sprintf(_m("You may not use homepage '%s'"),
153 throw new ClientException($msg);
157 $nickname = strtolower($action->trimmed('nickname'));
159 if (!empty($nickname)) {
160 if (!$this->_checkNickname($nickname)) {
161 $msg = sprintf(_m("You may not use nickname '%s'"),
163 throw new ClientException($msg);
171 * Hook notice save to prevent blacklisted urls
173 * Throws an exception if there's a blacklisted url in the content.
175 * @param Notice &$notice Notice being saved
177 * @return boolean hook value
180 function onStartNoticeSave(&$notice)
182 common_replace_urls_callback($notice->content,
183 array($this, 'checkNoticeUrl'));
188 * Helper callback for notice save
190 * Throws an exception if there's a blacklisted url in the content.
192 * @param string $url URL in the notice content
194 * @return boolean hook value
197 function checkNoticeUrl($url)
199 // It comes in special'd, so we unspecial it
200 // before comparing against patterns
202 $url = htmlspecialchars_decode($url);
204 if (!$this->_checkUrl($url)) {
205 $msg = sprintf(_m("You may not use url '%s' in notices"),
207 throw new ClientException($msg);
214 * Helper for checking URLs
216 * Checks an URL against our patterns for a match.
218 * @param string $url URL to check
220 * @return boolean true means it's OK, false means it's bad
223 private function _checkUrl($url)
225 foreach ($this->_urlPatterns as $pattern) {
226 common_debug("Checking $url against $pattern");
227 if (preg_match("/$pattern/", $url)) {
236 * Helper for checking nicknames
238 * Checks a nickname against our patterns for a match.
240 * @param string $nickname nickname to check
242 * @return boolean true means it's OK, false means it's bad
245 private function _checkNickname($nickname)
247 foreach ($this->_nicknamePatterns as $pattern) {
248 common_debug("Checking $nickname against $pattern");
249 if (preg_match("/$pattern/", $nickname)) {
258 * Add our actions to the URL router
260 * @param Net_URL_Mapper $m URL mapper for this hit
262 * @return boolean hook return
265 function onRouterInitialized($m)
267 $m->connect('admin/blacklist', array('action' => 'blacklistadminpanel'));
272 * Auto-load our classes if called
274 * @param string $cls Class to load
276 * @return boolean hook return
279 function onAutoload($cls)
281 switch (strtolower($cls))
283 case 'blacklistadminpanelaction':
284 $base = strtolower(mb_substr($cls, 0, -6));
285 include_once INSTALLDIR.'/plugins/Blacklist/'.$base.'.php';
293 * Plugin version data
295 * @param array &$versions array of version blocks
297 * @return boolean hook value
300 function onPluginVersion(&$versions)
302 $versions[] = array('name' => 'Blacklist',
303 'version' => self::VERSION,
304 'author' => 'Evan Prodromou',
306 'http://status.net/wiki/Plugin:Blacklist',
308 _m('Keep a blacklist of forbidden nickname '.
309 'and URL patterns.'));
314 * Determines if our admin panel can be shown
316 * @param string $name name of the admin panel
317 * @param boolean &$isOK result
319 * @return boolean hook value
322 function onAdminPanelCheck($name, &$isOK)
324 if ($name == 'blacklist') {
325 $isOK = $this->canAdmin;
333 * Add our tab to the admin panel
335 * @param Widget $nav Admin panel nav
337 * @return boolean hook value
340 function onEndAdminPanelNav($nav)
342 if (AdminPanelAction::canAdmin('blacklist')) {
344 $action_name = $nav->action->trimmed('action');
346 $nav->out->menuItem(common_local_url('blacklistadminpanel'),
348 _('Blacklist configuration'),
349 $action_name == 'blacklistadminpanel',
350 'nav_blacklist_admin_panel');