]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/Blacklist/BlacklistPlugin.php
Merge branch 'master' into 1.0.x
[quix0rs-gnu-social.git] / plugins / Blacklist / BlacklistPlugin.php
index 84a2cb6168e7752d2ea2489917c06ec6c927cb4a..babf7031313e22565e0a0b366a009940834e585d 100644 (file)
@@ -22,7 +22,7 @@
  * @category  Action
  * @package   StatusNet
  * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet Inc.
+ * @copyright 2010 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/
  */
@@ -40,13 +40,97 @@ if (!defined('STATUSNET')) {
  * @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
 {
     const VERSION = STATUSNET_VERSION;
 
     public $nicknames = array();
     public $urls      = array();
+    public $canAdmin  = true;
+
+    function _getNicknamePatterns()
+    {
+        $confNicknames = $this->_configArray('blacklist', 'nicknames');
+
+        $dbNicknames = Nickname_blacklist::getPatterns();
+
+        return array_merge($this->nicknames,
+                           $confNicknames,
+                           $dbNicknames);
+    }
+
+    function _getUrlPatterns()
+    {
+        $confURLs = $this->_configArray('blacklist', 'urls');
+
+        $dbURLs = Homepage_blacklist::getPatterns();
+
+        return array_merge($this->urls,
+                           $confURLs,
+                           $dbURLs);
+    }
+
+    /**
+     * Database schema setup
+     *
+     * @return boolean hook value
+     */
+    function onCheckSchema()
+    {
+        $schema = Schema::get();
+
+        // For storing blacklist patterns for nicknames
+        $schema->ensureTable('nickname_blacklist',
+                             array(new ColumnDef('pattern',
+                                                 'varchar',
+                                                 255,
+                                                 false,
+                                                 'PRI'),
+                                   new ColumnDef('created',
+                                                 'datetime',
+                                                 null,
+                                                 false)));
+
+        $schema->ensureTable('homepage_blacklist',
+                             array(new ColumnDef('pattern',
+                                                 'varchar',
+                                                 255,
+                                                 false,
+                                                 'PRI'),
+                                   new ColumnDef('created',
+                                                 'datetime',
+                                                 null,
+                                                 false)));
+
+        return true;
+    }
+
+    /**
+     * Retrieve an array from configuration
+     *
+     * Carefully checks a section.
+     *
+     * @param string $section Configuration section
+     * @param string $setting Configuration setting
+     *
+     * @return array configuration values
+     */
+    function _configArray($section, $setting)
+    {
+        $config = common_config($section, $setting);
+
+        if (empty($config)) {
+            return array();
+        } else if (is_array($config)) {
+            return $config;
+        } else if (is_string($config)) {
+            return explode("\r\n", $config);
+        } else {
+            // TRANS: Exception thrown if the Blacklist plugin configuration is incorrect.
+            // TRANS: %1$s is a configuration section, %2$s is a configuration setting.
+            throw new Exception(sprintf(_m('Unknown data type for config %1$s + %2$s.'),$section, $setting));
+        }
+    }
 
     /**
      * Hook registration to prevent blacklisted homepages or nicknames
@@ -57,24 +141,25 @@ class BlacklistPlugin extends Plugin
      *
      * @return boolean hook value
      */
-
-    function onStartRegistrationTry($action)
+    function onStartRegisterUser(&$user, &$profile)
     {
-        $homepage = strtolower($action->trimmed('homepage'));
+        $homepage = strtolower($profile->homepage);
 
         if (!empty($homepage)) {
             if (!$this->_checkUrl($homepage)) {
-                $msg = sprintf(_m("You may not register with homepage '%s'"),
+                // TRANS: Validation failure for URL. %s is the URL.
+                $msg = sprintf(_m("You may not register with homepage \"%s\"."),
                                $homepage);
                 throw new ClientException($msg);
             }
         }
 
-        $nickname = strtolower($action->trimmed('nickname'));
+        $nickname = strtolower($profile->nickname);
 
         if (!empty($nickname)) {
             if (!$this->_checkNickname($nickname)) {
-                $msg = sprintf(_m("You may not register with nickname '%s'"),
+                // TRANS: Validation failure for nickname. %s is the nickname.
+                $msg = sprintf(_m("You may not register with nickname \"%s\"."),
                                $nickname);
                 throw new ClientException($msg);
             }
@@ -92,14 +177,14 @@ class BlacklistPlugin extends Plugin
      *
      * @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'"),
+                // TRANS: Validation failure for URL. %s is the URL.
+                $msg = sprintf(_m("You may not use homepage \"%s\"."),
                                $homepage);
                 throw new ClientException($msg);
             }
@@ -109,7 +194,8 @@ class BlacklistPlugin extends Plugin
 
         if (!empty($nickname)) {
             if (!$this->_checkNickname($nickname)) {
-                $msg = sprintf(_m("You may not use nickname '%s'"),
+                // TRANS: Validation failure for nickname. %s is the nickname.
+                $msg = sprintf(_m("You may not use nickname \"%s\"."),
                                $nickname);
                 throw new ClientException($msg);
             }
@@ -127,7 +213,6 @@ class BlacklistPlugin extends Plugin
      *
      * @return boolean hook value
      */
-
     function onStartNoticeSave(&$notice)
     {
         common_replace_urls_callback($notice->content,
@@ -144,7 +229,6 @@ class BlacklistPlugin extends Plugin
      *
      * @return boolean hook value
      */
-
     function checkNoticeUrl($url)
     {
         // It comes in special'd, so we unspecial it
@@ -153,7 +237,8 @@ class BlacklistPlugin extends Plugin
         $url = htmlspecialchars_decode($url);
 
         if (!$this->_checkUrl($url)) {
-            $msg = sprintf(_m("You may not use url '%s' in notices"),
+            // TRANS: Validation failure for URL. %s is the URL.
+            $msg = sprintf(_m("You may not use URL \"%s\" in notices."),
                            $url);
             throw new ClientException($msg);
         }
@@ -170,11 +255,12 @@ class BlacklistPlugin extends Plugin
      *
      * @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)) {
+        $patterns = $this->_getUrlPatterns();
+
+        foreach ($patterns as $pattern) {
+            if ($pattern != '' && preg_match("/$pattern/", $url)) {
                 return false;
             }
         }
@@ -191,11 +277,12 @@ class BlacklistPlugin extends Plugin
      *
      * @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)) {
+        $patterns = $this->_getNicknamePatterns();
+
+        foreach ($patterns as $pattern) {
+            if ($pattern != '' && preg_match("/$pattern/", $nickname)) {
                 return false;
             }
         }
@@ -203,14 +290,267 @@ class BlacklistPlugin extends Plugin
         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)
+    {
+        $m->connect('panel/blacklist', array('action' => 'blacklistadminpanel'));
+        return true;
+    }
+
+    /**
+     * Auto-load our classes if called
+     *
+     * @param string $cls Class to load
+     *
+     * @return boolean hook return
+     */
+    function onAutoload($cls)
+    {
+        switch (strtolower($cls))
+        {
+        case 'nickname_blacklist':
+        case 'homepage_blacklist':
+            include_once INSTALLDIR.'/plugins/Blacklist/'.ucfirst($cls).'.php';
+            return false;
+        case 'blacklistadminpanelaction':
+            $base = strtolower(mb_substr($cls, 0, -6));
+            include_once INSTALLDIR.'/plugins/Blacklist/'.$base.'.php';
+            return false;
+        default:
+            return true;
+        }
+    }
+
+    /**
+     * Plugin version data
+     *
+     * @param array &$versions array of version blocks
+     *
+     * @return boolean hook value
+     */
     function onPluginVersion(&$versions)
     {
         $versions[] = array('name' => 'Blacklist',
                             'version' => self::VERSION,
                             'author' => 'Evan Prodromou',
-                            'homepage' => 'http://status.net/wiki/Plugin:Blacklist',
+                            'homepage' =>
+                            'http://status.net/wiki/Plugin:Blacklist',
                             'description' =>
-                            _m('Keep a blacklist of forbidden nickname and URL patterns.'));
+                            // TRANS: Plugin description.
+                            _m('Keeps a blacklist of forbidden nickname '.
+                               'and URL patterns.'));
+        return true;
+    }
+
+    /**
+     * Determines if our admin panel can be shown
+     *
+     * @param string  $name  name of the admin panel
+     * @param boolean &$isOK result
+     *
+     * @return boolean hook value
+     */
+    function onAdminPanelCheck($name, &$isOK)
+    {
+        if ($name == 'blacklist') {
+            $isOK = $this->canAdmin;
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Add our tab to the admin panel
+     *
+     * @param Widget $nav Admin panel nav
+     *
+     * @return boolean hook value
+     */
+    function onEndAdminPanelNav($nav)
+    {
+        if (AdminPanelAction::canAdmin('blacklist')) {
+
+            $action_name = $nav->action->trimmed('action');
+
+            $nav->out->menuItem(common_local_url('blacklistadminpanel'),
+                                // TRANS: Menu item in admin panel.
+                                _m('MENU','Blacklist'),
+                                // TRANS: Tooltip for menu item in admin panel.
+                                _m('TOOLTIP','Blacklist configuration.'),
+                                $action_name == 'blacklistadminpanel',
+                                'nav_blacklist_admin_panel');
+        }
+
+        return true;
+    }
+
+    function onEndDeleteUserForm($action, $user)
+    {
+        $cur = common_current_user();
+
+        if (empty($cur) || !$cur->hasRight(Right::CONFIGURESITE)) {
+            return;
+        }
+
+        $profile = $user->getProfile();
+
+        if (empty($profile)) {
+            return;
+        }
+
+        $action->elementStart('ul', 'form_data');
+        $action->elementStart('li');
+        $this->checkboxAndText($action,
+                               'blacklistnickname',
+                               // TRANS: Checkbox label in the blacklist user form.
+                               _m('Add this nickname pattern to blacklist'),
+                               'blacklistnicknamepattern',
+                               $this->patternizeNickname($user->nickname));
+        $action->elementEnd('li');
+
+        if (!empty($profile->homepage)) {
+            $action->elementStart('li');
+            $this->checkboxAndText($action,
+                                   'blacklisthomepage',
+                                   // TRANS: Checkbox label in the blacklist user form.
+                                   _m('Add this homepage pattern to blacklist'),
+                                   'blacklisthomepagepattern',
+                                   $this->patternizeHomepage($profile->homepage));
+            $action->elementEnd('li');
+        }
+
+        $action->elementEnd('ul');
+    }
+
+    function onEndDeleteUser($action, $user)
+    {
+        if ($action->boolean('blacklisthomepage')) {
+            $pattern = $action->trimmed('blacklisthomepagepattern');
+            Homepage_blacklist::ensurePattern($pattern);
+        }
+
+        if ($action->boolean('blacklistnickname')) {
+            $pattern = $action->trimmed('blacklistnicknamepattern');
+            Nickname_blacklist::ensurePattern($pattern);
+        }
+
+        return true;
+    }
+
+    function checkboxAndText($action, $checkID, $label, $textID, $value)
+    {
+        $action->element('input', array('name' => $checkID,
+                                        'type' => 'checkbox',
+                                        'class' => 'checkbox',
+                                        'id' => $checkID));
+
+        $action->text(' ');
+
+        $action->element('label', array('class' => 'checkbox',
+                                        'for' => $checkID),
+                         $label);
+
+        $action->text(' ');
+
+        $action->element('input', array('name' => $textID,
+                                        'type' => 'text',
+                                        'id' => $textID,
+                                        'value' => $value));
+    }
+
+    function patternizeNickname($nickname)
+    {
+        return $nickname;
+    }
+
+    function patternizeHomepage($homepage)
+    {
+        $hostname = parse_url($homepage, PHP_URL_HOST);
+        return $hostname;
+    }
+
+    function onStartHandleFeedEntry($activity)
+    {
+        return $this->_checkActivity($activity);
+    }
+
+    function onStartHandleSalmon($activity)
+    {
+        return $this->_checkActivity($activity);
+    }
+
+    function _checkActivity($activity)
+    {
+        $actor = $activity->actor;
+
+        if (empty($actor)) {
+            return true;
+        }
+
+        $homepage = strtolower($actor->link);
+
+        if (!empty($homepage)) {
+            if (!$this->_checkUrl($homepage)) {
+                // TRANS: Exception thrown trying to post a notice while having set a blocked homepage URL. %s is the blocked URL.
+                $msg = sprintf(_m("Users from \"%s\" are blocked."),
+                               $homepage);
+                throw new ClientException($msg);
+            }
+        }
+
+        $nickname = strtolower($actor->poco->preferredUsername);
+
+        if (!empty($nickname)) {
+            if (!$this->_checkNickname($nickname)) {
+                // TRANS: Exception thrown trying to post a notice while having a blocked nickname. %s is the blocked nickname.
+                $msg = sprintf(_m("Notices from nickname \"%s\" disallowed."),
+                               $nickname);
+                throw new ClientException($msg);
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Check URLs and homepages for blacklisted users.
+     */
+    function onStartSubscribe($subscriber, $other)
+    {
+        foreach (array($other->profileurl, $other->homepage) as $url) {
+
+            if (empty($url)) {
+                continue;
+            }
+
+            $url = strtolower($url);
+
+            if (!$this->_checkUrl($url)) {
+                // TRANS: Client exception thrown trying to subscribe to a person with a blocked homepage or site URL. %s is the blocked URL.
+                $msg = sprintf(_m("Users from \"%s\" are blocked."),
+                               $url);
+                throw new ClientException($msg);
+            }
+        }
+
+        $nickname = $other->nickname;
+
+        if (!empty($nickname)) {
+            if (!$this->_checkNickname($nickname)) {
+                // TRANS: Client exception thrown trying to subscribe to a person with a blocked nickname. %s is the blocked nickname.
+                $msg = sprintf(_m("Cannot subscribe to nickname \"%s\"."),
+                               $nickname);
+                throw new ClientException($msg);
+            }
+        }
+
         return true;
     }
 }