Răsfoiți Sursa

#40 - Antispam module

Alex Trofimov 12 ani în urmă
părinte
comite
972964a668
36 a modificat fișierele cu 1700 adăugiri și 272 ștergeri
  1. 4 1
      inc/classes/BxDolCmts.php
  2. 1 1
      inc/classes/BxDolDb.php
  3. 7 4
      inc/classes/BxDolForm.php
  4. 2 6
      inc/params.inc.php
  5. 5 5
      inc/profiles.inc.php
  6. 4 159
      inc/utils.inc.php
  7. 0 8
      install/sql/system.sql
  8. 19 17
      modules/boonex/antispam/classes/BxAntispamAkismet.php
  9. 71 0
      modules/boonex/antispam/classes/BxAntispamConfig.php
  10. 34 32
      modules/boonex/antispam/classes/BxAntispamDNSBlacklists.php
  11. 30 25
      modules/boonex/antispam/classes/BxAntispamDNSURIBlacklists.php
  12. 22 0
      modules/boonex/antispam/classes/BxAntispamDb.php
  13. 105 0
      modules/boonex/antispam/classes/BxAntispamIP.php
  14. 234 0
      modules/boonex/antispam/classes/BxAntispamModule.php
  15. 103 0
      modules/boonex/antispam/classes/BxAntispamStopForumSpam.php
  16. 42 0
      modules/boonex/antispam/classes/BxAntispamStudioPage.php
  17. 22 0
      modules/boonex/antispam/classes/BxAntispamTemplate.php
  18. 128 2
      modules/boonex/antispam/data/three-level-tlds
  19. 300 2
      modules/boonex/antispam/data/two-level-tlds
  20. 152 0
      modules/boonex/antispam/install/config.php
  21. 22 0
      modules/boonex/antispam/install/installer.php
  22. 25 0
      modules/boonex/antispam/install/langs/en.xml
  23. 2 0
      modules/boonex/antispam/install/sql/disable.sql
  24. 25 0
      modules/boonex/antispam/install/sql/enable.sql
  25. 14 0
      modules/boonex/antispam/install/sql/install.sql
  26. 7 0
      modules/boonex/antispam/install/sql/uninstall.sql
  27. 17 0
      modules/boonex/antispam/request.php
  28. BIN
      modules/boonex/antispam/template/images/icons/std-mi.png
  29. BIN
      modules/boonex/antispam/template/images/icons/std-pi.png
  30. BIN
      modules/boonex/antispam/template/images/icons/std-si.png
  31. BIN
      modules/boonex/antispam/template/images/icons/std-wi.png
  32. 10 1
      modules/boonex/contact/classes/BxContactModule.php
  33. 0 8
      modules/boonex/english/data/langs/system.xml
  34. 1 1
      studio/classes/BxDolStudioIpBlockList.php
  35. 31 0
      tests/bootstrap.php
  36. 261 0
      tests/units/modules/boonex/antispam/classes/BxAntispamModuleTest.php

+ 4 - 1
inc/classes/BxDolCmts.php

@@ -868,7 +868,10 @@ class BxDolCmts extends BxDol
     }
 
     protected function _isSpam($s) {
-        return bx_is_spam($s);
+        // TODO: insert alert here, so other modules can be used instead of default one
+        if (!BxDolRequest::serviceExists('bx_antispam', 'is_spam'))
+            return false;
+        return BxDolService::call('bx_antispam', 'is_spam', array($s));
     }
 
 	/**

+ 1 - 1
inc/classes/BxDolDb.php

@@ -291,7 +291,7 @@ class BxDolDb extends BxDol implements iBxDolSingleton {
         else
             $this->error_message = '';
 
-        if (false === $res && !@mysql_ping($this->link)) { // if mysql connection is lost - reconnect and try again
+        if (!$res && !@mysql_ping($this->link)) { // if mysql connection is lost - reconnect and try again
             @mysql_close($this->link);
             $sErrorMessage = $this->connect();
             if ($sErrorMessage)

+ 7 - 4
inc/classes/BxDolForm.php

@@ -1123,7 +1123,8 @@ class BxDolFormChecker {
         }
 
         // check for spam
-        if (!$iErrors && ('on' == getParam('sys_uridnsbl_enable') || 'on' == getParam('sys_akismet_enable'))) {
+        // TODO: remake for bx_antispam module
+        if (!$iErrors && ('on' == getParam('bx_antispam_uridnsbl_enable') || 'on' == getParam('bx_antispam_akismet_enable'))) {
 
             foreach ($aInputs as $k => $a) {
 
@@ -1139,8 +1140,7 @@ class BxDolFormChecker {
                     continue;
 
                 ++$iErrors;
-                $aInputs[$k]['error'] = _t('_sys_spam_detected', BX_DOL_URL_ROOT . 'contact.php');
-
+                $aInputs[$k]['error'] = _t('_sys_spam_detected', BX_DOL_URL_ROOT . 'contact.php'); // TODO: remake to use contact module (see example in bx_antispam module)
             }
         }
 
@@ -1300,7 +1300,10 @@ class BxDolFormCheckerHelper {
         return $oCaptcha->check ();
     }
     function checkNoSpam($val) {
-        return !bx_is_spam($val);
+        // TODO: insert alert here, so other modules can be used instead of default one
+        if (!BxDolRequest::serviceExists('bx_antispam', 'is_spam'))
+            return true;
+        return !BxDolService::call('bx_antispam', 'is_spam', array($val));
     }
 
     // pass functions, prepare values to insert to database

+ 2 - 6
inc/params.inc.php

@@ -6,11 +6,7 @@
  */
 defined('BX_DOL') or die('hack attempt');
 
-if (defined('BX_PROFILER') && BX_PROFILER) require_once(BX_DIRECTORY_PATH_MODULES . 'boonex/profiler/classes/BxProfiler.php');
+if (defined('BX_PROFILER') && BX_PROFILER) 
+    require_once(BX_DIRECTORY_PATH_MODULES . 'boonex/profiler/classes/BxProfiler.php');
 
-// if IP is banned - total block
-if ((int)getParam('ipBlacklistMode') == 1 && bx_is_ip_blocked()) {
-    echo _t('_Sorry, your IP been banned');
-    exit;
-}
 

+ 5 - 5
inc/profiles.inc.php

@@ -39,6 +39,8 @@ if (!function_exists("isAdmin")) {
      * It checks if account is admin.
      */
     function isAdmin($iId = 0) {
+        if (!$iId && isset($GLOBALS['logged']['admin']) && $GLOBALS['logged']['admin']) // easier check for currently logged in user
+            return true;
         return isRole(BX_DOL_ROLE_ADMIN, $iId);
     }
 }
@@ -205,11 +207,9 @@ function bx_check_login($iID, $sPassword, $iRole = BX_DOL_ROLE_MEMBER) {
     if (isAdmin($aAccountInfo['id']))
         return '';
 
-    // If IP is banned
-    if ((2 == getParam('ipBlacklistMode') && bx_is_ip_blocked()) || ('on' == getParam('sys_dnsbl_enable') && bx_is_ip_dns_blacklisted('', 'login'))) {
-        bx_import('BxDolLanguages');
-        return _t('_Sorry, your IP been banned');
-    }
+    // Check if IP is banned
+    if (BxDolRequest::serviceExists('bx_antispam', 'check_login') && ($sErrorMsg = BxDolService::call('bx_antispam', 'check_login')))
+        return $sErrorMsg;
 
     // If account is banned
     if (isLoggedBanned($aAccountInfo['id'])) {

+ 4 - 159
inc/utils.inc.php

@@ -399,15 +399,14 @@ function extFileExists( $sFileSrc ) {
 
 function getVisitorIP() {
     $ip = "0.0.0.0";
-    if( ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) && ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) {
+    if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
         $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
-    } elseif( ( isset( $_SERVER['HTTP_CLIENT_IP'])) && (!empty($_SERVER['HTTP_CLIENT_IP'] ) ) ) {
+    } elseif (isset( $_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP'])) {
         $ip = explode(".",$_SERVER['HTTP_CLIENT_IP']);
         $ip = $ip[3].".".$ip[2].".".$ip[1].".".$ip[0];
-    } elseif((!isset( $_SERVER['HTTP_X_FORWARDED_FOR'])) || (empty($_SERVER['HTTP_X_FORWARDED_FOR']))) {
-        if ((!isset( $_SERVER['HTTP_CLIENT_IP'])) && (empty($_SERVER['HTTP_CLIENT_IP']))) {
+    } elseif (!isset( $_SERVER['HTTP_X_FORWARDED_FOR']) || empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+        if (!isset( $_SERVER['HTTP_CLIENT_IP']) && empty($_SERVER['HTTP_CLIENT_IP']) && isset($_SERVER['REMOTE_ADDR']))
             $ip = $_SERVER['REMOTE_ADDR'];
-        }
     }
     return $ip;
 }
@@ -537,160 +536,6 @@ function bx_mb_strpos ($s, $sReplacement, $iStart = 0) {
     return mb_strpos($s, $sReplacement, $iStart);
 }
 
-/**
- * Block user IP
- *
- * @param $sIP mixed
- * @param $iExpirationInSec integer
- * @param $sComment string
- * @return void
- */
-function bx_block_ip($mixedIP, $iExpirationInSec = 86400, $sComment = '') {
-
-    if (preg_match('/^[0-9]+$/', $mixedIP))
-        $iIP = $mixedIP;
-    else
-        $iIP = sprintf("%u", ip2long($sIP));
-
-    $iExpirationInSec = time() + (int)$iExpirationInSec;
-
-    $oDb = BxDolDb::getInstance();
-    $sQuery = $oDb->prepare("SELECT ID FROM `sys_ip_list` WHERE `From` = ? AND `To` = ? LIMIT 1", $iIP, $iIP);
-    if (!$oDb->getOne($sQuery)) {
-        $sQuery = $oDb->prepare("INSERT INTO `sys_ip_list` SET `From` = ?, `To` = ?, `Type` = 'deny', `LastDT` = ?, `Desc` = ?", $iIP, $iIP, $iExpirationInSec, $sComment);
-        return $oDb->res($sQuery);
-    }
-    return false;
-}
-
-function bx_is_ip_dns_blacklisted($sCurIP = '', $sType = '') {
-
-    if (defined('BX_DOL_CRON_EXECUTE'))
-        return false;
-
-    if (!$sCurIP)
-        $sCurIP = getVisitorIP();
-
-    if (bx_is_ip_whitelisted($sCurIP))
-        return false;
-
-    $o = bx_instance('BxDolDNSBlacklists');
-    if (BX_DOL_DNSBL_POSITIVE == $o->dnsbl_lookup_ip(BX_DOL_DNSBL_CHAIN_SPAMMERS, $sCurIP) && BX_DOL_DNSBL_POSITIVE != $o->dnsbl_lookup_ip(BX_DOL_DNSBL_CHAIN_WHITELIST, $sCurIP))
-    {
-        $o->onPositiveDetection ($sCurIP, $sType);
-        return true;
-    }
-
-    return false;
-}
-
-function bx_is_ip_whitelisted($sCurIP = '') {
-
-    if (defined('BX_DOL_CRON_EXECUTE'))
-        return true;
-
-    $iIPGlobalType = (int)getParam('ipListGlobalType');
-    if ($iIPGlobalType != 1 && $iIPGlobalType != 2) // 0 - disabled
-        return false;
-
-    if (!$sCurIP)
-        $sCurIP = getVisitorIP();
-    $iCurIP = sprintf("%u", ip2long($sCurIP));
-    $iCurrTume = time();
-
-    return db_value("SELECT `ID` FROM `sys_ip_list` WHERE `Type` = 'allow' AND `LastDT` > $iCurrTume AND `From` <= '$iCurIP' AND `To` >= '$iCurIP' LIMIT 1") ? true : false;
-}
-
-function bx_is_ip_blocked($sCurIP = '') {
-
-    if (defined('BX_DOL_CRON_EXECUTE'))
-        return false;
-
-    $iIPGlobalType = (int)getParam('ipListGlobalType');
-    if ($iIPGlobalType != 1 && $iIPGlobalType != 2) // 0 - disabled
-        return false;
-
-    if (!$sCurIP)
-        $sCurIP = getVisitorIP();
-    $iCurIP = sprintf("%u", ip2long($sCurIP));
-    $iCurrTume = time();
-
-    if (bx_is_ip_whitelisted($sCurIP))
-        return false;
-
-    $isBlocked = db_value("SELECT `ID` FROM `sys_ip_list` WHERE `Type` = 'deny' AND `LastDT` > $iCurrTume AND `From` <= '$iCurIP' AND `To` >= '$iCurIP' LIMIT 1");
-    if ($isBlocked)
-        return true;
-
-    // 1 - all allowed except listed
-    // 2 - all blocked except listed
-    return $iIPGlobalType == 2 ? true : false;
-}
-
-/**
- *  spam checking function
- *  @param $s content to check for spam
- *  @param $isStripSlashes slashes parameter:
- *          BX_SLASHES_AUTO - automatically detect magic_quotes_gpc setting
- *          BX_SLASHES_NO_ACTION - do not perform any action with slashes
- *  @return true if spam detected
- */
-function bx_is_spam ($val, $isStripSlashes = BX_SLASHES_AUTO) {
-
-    if (defined('BX_DOL_CRON_EXECUTE'))
-        return false;
-
-    if (isAdmin())
-        return false;
-
-    if (bx_is_ip_whitelisted())
-        return false;
-
-    if (get_magic_quotes_gpc() && $isStripSlashes == BX_SLASHES_AUTO)
-        $val = stripslashes($val);
-
-    $bRet = false;
-    if ('on' == getParam('sys_uridnsbl_enable')) {
-        $oBxDolDNSURIBlacklists = bx_instance('BxDolDNSURIBlacklists');
-        if ($oBxDolDNSURIBlacklists->isSpam($val)) {
-            $oBxDolDNSURIBlacklists->onPositiveDetection($val);
-            $bRet = true;
-        }
-    }
-
-    if ('on' == getParam('sys_akismet_enable')) {
-        $oBxDolAkismet = bx_instance('BxDolAkismet');
-        if ($oBxDolAkismet->isSpam($val)) {
-            $oBxDolAkismet->onPositiveDetection($val);
-            $bRet = true;
-        }
-    }
-
-    if ($bRet && 'on' == getParam('sys_antispam_report')) {
-
-        $iProfileId = getLoggedId();
-        $aPlus = array(
-            'SpammerUrl' => getProfileLink($iProfileId),
-            'SpammerNickName' => getNickName($iProfileId),
-            'Page' => htmlspecialchars_adv($_SERVER['PHP_SELF']),
-            'Get' => print_r($_GET, true),
-            'SpamContent' => htmlspecialchars_adv($val),
-        );
-
-        bx_import('BxDolEmailTemplates');
-        $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate('t_SpamReportAuto', $aPlus);
-        if (!$aTemplate)
-            trigger_error('Email template or translation missing: t_SpamReportAuto', E_USER_ERROR);
-
-        sendMail(getParam('site_email'), $aTemplate['Subject'], $aTemplate['Body']);
-    }
-
-    if ($bRet && 'on' == getParam('sys_antispam_block'))
-        return true;
-
-    return false;
-}
-
 /**
 ** @description : function will create cache file with all SQL queries ;
 ** @return        :

+ 0 - 8
install/sql/system.sql

@@ -411,18 +411,10 @@ SET @iCategoryId = LAST_INSERT_ID();
 
 INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
 (@iCategoryId, 'enable_member_store_ip', '_adm_stg_cpt_option_enable_member_store_ip', 'on', 'checkbox', '', '', '', 1),
-(@iCategoryId, 'ipBlacklistMode', '_adm_stg_cpt_option_ip_blacklist_mode', '2', 'digit', '', '', '', 2),
-(@iCategoryId, 'ipListGlobalType', '_adm_stg_cpt_option_ip_list_global_type', '0', 'digit', '', '', '', 3),
 (@iCategoryId, 'sys_security_impact_threshold_log', '_adm_stg_cpt_option_sys_security_impact_threshold_log', '-1', 'digit', '', '', '', 4),
 (@iCategoryId, 'sys_security_impact_threshold_block', '_adm_stg_cpt_option_sys_security_impact_threshold_block', '-1', 'digit', '', '', '', 5),
 (@iCategoryId, 'sys_security_form_token_enable', '_adm_stg_cpt_option_sys_security_form_token_enable', 'on', 'checkbox', '', '', '', 6),
 (@iCategoryId, 'sys_security_form_token_lifetime', '_adm_stg_cpt_option_sys_security_form_token_lifetime', '86400', 'digit', '', '', '', 7),
-(@iCategoryId, 'sys_dnsbl_enable', '_adm_stg_cpt_option_sys_dnsbl_enable', '', 'checkbox', '', '', '', 8),
-(@iCategoryId, 'sys_uridnsbl_enable', '_adm_stg_cpt_option_sys_uridnsbl_enable', '', 'checkbox', '', '', '', 9),
-(@iCategoryId, 'sys_akismet_enable', '_adm_stg_cpt_option_sys_akismet_enable', '', 'checkbox', '', '', '', 10),
-(@iCategoryId, 'sys_akismet_api_key', '_adm_stg_cpt_option_sys_akismet_api_key', '', 'digit', '', '', '', 11),
-(@iCategoryId, 'sys_antispam_block', '_adm_stg_cpt_option_sys_antispam_block', '', 'checkbox', '', '', '', 12),
-(@iCategoryId, 'sys_antispam_report', '_adm_stg_cpt_option_sys_antispam_report', 'on', 'checkbox', '', '', '', 13),
 (@iCategoryId, 'sys_recaptcha_key_public', '_adm_stg_cpt_option_sys_recaptcha_key_public', '', 'digit', '', '', '', 14),
 (@iCategoryId, 'sys_recaptcha_key_private', '_adm_stg_cpt_option_sys_recaptcha_key_private', '', 'digit', '', '', '', 15);
 

+ 19 - 17
inc/classes/BxDolAkismet.php → modules/boonex/antispam/classes/BxAntispamAkismet.php

@@ -1,25 +1,25 @@
-<?php
+<?php defined('BX_DOL') or die('hack attempt');
 /**
- * @package     Dolphin Core
- * @copyright   Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
- * @license     CC-BY - http://creativecommons.org/licenses/by/3.0/
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
  */
-defined('BX_DOL') or die('hack attempt');
 
 /**
- * Spam detection based on the message content and logged in user
+ * Spam detection based on the message content and logged in user info - http://akismet.com
  */
-class BxDolAkismet extends BxDol
+class BxAntispamAkismet extends BxDol
 {
-    var $oAkismet = null;
+    protected $oAkismet = null;
 
-    /**
-     * Constructor
-     */
-    public function BxDolAkismet($iProfileID = 0)
+    public function __construct($iProfileID = 0)
     {
-        parent::BxDol();
-        $sKey = getParam('sys_akismet_api_key');
+        parent::__construct();
+        $sKey = getParam('bx_antispam_akismet_api_key');
         if ($sKey) {
             require_once (BX_DIRECTORY_PATH_PLUGINS . 'akismet/Akismet.class.php');
             $this->oAkismet = new Akismet(BX_DOL_URL_ROOT, $sKey);
@@ -32,8 +32,8 @@ class BxDolAkismet extends BxDol
         }
     }
 
-    public function isSpam ($s, $sPermalink = false) {
-
+    public function isSpam ($s, $sPermalink = false)
+    {
         if (!$this->oAkismet)
             return false;
 
@@ -44,9 +44,11 @@ class BxDolAkismet extends BxDol
         return $this->oAkismet->isCommentSpam();
     }
 
-    public function onPositiveDetection ($sExtraData = '') {
+    public function onPositiveDetection ($sExtraData = '')
+    {
         $o = bx_instance('BxDolDNSBlacklists');
         $o->onPositiveDetection (getVisitorIP(), $sExtraData, 'akismet');
     }
 }
 
+/** @} */

+ 71 - 0
modules/boonex/antispam/classes/BxAntispamConfig.php

@@ -0,0 +1,71 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+bx_import('BxDolModuleConfig');
+
+class BxAntispamConfig extends BxDolModuleConfig 
+{
+    /**
+     * map system options to the local options names
+     */
+    protected $_aOptionsMap = array (
+        'antispam_block' => 'bx_antispam_block',
+        'antispam_report' => 'bx_antispam_report',
+        'dnsbl_enable' => 'bx_antispam_dnsbl_enable',
+        'uridnsbl_enable' => 'bx_antispam_uridnsbl_enable',
+        'dnsbl_behaviour' => 'bx_antispam_dnsbl_behaviour',
+        'akismet_enable' => 'bx_antispam_akismet_enable',
+    );
+    /**
+     * default local options, it is filled in with real system options in class contructor, @see restoreAntispamOptions
+     */
+    protected $_aOptions = array (
+        'antispam_block' => '',
+        'antispam_report' => '',
+        'dnsbl_enable' => '',
+        'uridnsbl_enable' => '',
+        'dnsbl_behaviour' => 'approval',
+        'akismet_enable' => '',
+    );
+
+	public function __construct($aModule) 
+    {
+	    parent::__construct($aModule);
+        $this->restoreAntispamOptions ();
+    }   
+
+    /**
+     * Set local option value, system value stays intact, useful for testing and debugging
+     */    
+    public function setAntispamOption ($sOption, $mixedVal) 
+    {
+        $this->_aOptions[$sOption] = $mixedVal;
+    }
+
+    /**
+     * Get an option, local value
+     */ 
+    public function getAntispamOption ($sOption) 
+    {
+        return $this->_aOptions[$sOption];
+    }
+
+    /**
+     * set local options values from system options
+     */
+    public function restoreAntispamOptions ()
+    {
+        foreach ($this->_aOptionsMap as $sNameLocal => $sNameParam)
+            $this->setAntispamOption($sNameLocal, getParam($sNameParam));
+    }
+}
+
+/** @} */

+ 34 - 32
inc/classes/BxDolDNSBlacklists.php → modules/boonex/antispam/classes/BxAntispamDNSBlacklists.php

@@ -1,10 +1,13 @@
-<?php
+<?php defined('BX_DOL') or die('hack attempt');
 /**
- * @package     Dolphin Core
- * @copyright   Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
- * @license     CC-BY - http://creativecommons.org/licenses/by/3.0/
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
  */
-defined('BX_DOL') or die('hack attempt');
 
 define('BX_DOL_DNSBL_NEGATIVE', 0);   // negative
 define('BX_DOL_DNSBL_POSITIVE', 1);   // positive match
@@ -27,28 +30,26 @@ define('BX_DOL_DNSBL_CHAIN_URIDNS', "uridns");
  *
  * Example of usage:
  *
- * \code
  *  if (DNSBL_POSITIVE == $o->dnsbl_lookup_ip(DNSBL_CHAIN_SPAMMERS, $sCurIP) && DNSBL_POSITIVE != $o->dnsbl_lookup_ip(DNSBL_CHAIN_WHITELIST, $sCurIP))
  *  {
  *    // positive detection - block this ip
  *  }
  *  // continue script execution
- * \endcode
+ *
  *
  *  There is more handy function available:
  *  @see bx_is_ip_dns_blacklisted
  */
-class BxDolDNSBlacklists extends BxDol
+class BxAntispamDNSBlacklists extends BxDol
 {
-
     private $aChains = array ();
 
     /**
      * Constructor
      */
-    public function BxDolDNSBlacklists()
+    public function __construct()
     {
-        parent::BxDol();
+        parent::__construct();
         $this->initChains();
     }
 
@@ -56,7 +57,7 @@ class BxDolDNSBlacklists extends BxDol
     {
         $lookupkey = $this->ipreverse($sIp);
         if (false === $lookupkey)
-            return BX_DOL_DNSBL_FAILURE;    // unable to prepare lookup string from address
+            return BX_DOL_DNSBL_FAILURE;	// unable to prepare lookup string from address
 
         if (is_array($mixedChain))
             $aChain = $mixedChain;
@@ -77,7 +78,8 @@ class BxDolDNSBlacklists extends BxDol
         return $this->dnsbl_lookup($aChain, $sUri, $querymode);
     }
 
-    public function onPositiveDetection ($sIP, $sExtraData = '', $sType = 'dnsbl') {
+    public function onPositiveDetection ($sIP, $sExtraData = '', $sType = 'dnsbl')
+    {
         $iIP = sprintf("%u", ip2long($sIP));
         $iMemberId = getLoggedId();
         $oDb = BxDolDb::getInstance();
@@ -85,7 +87,8 @@ class BxDolDNSBlacklists extends BxDol
         return $oDb->query($sQuery);
     }
 
-    public function clearCache () {
+    public function clearCache () 
+    {
         $oDb = BxDolDb::getInstance();
         $oDb->cleanCache('sys_dnsbl_'.BX_DOL_DNSBL_CHAIN_SPAMMERS);
         $oDb->cleanCache('sys_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST);
@@ -104,21 +107,22 @@ class BxDolDNSBlacklists extends BxDol
 
         if (($querymode!=BX_DOL_DNSBL_ANYPOSTV_RETFIRST) && ($querymode!=BX_DOL_DNSBL_ANYPOSTV_RETEVERY)
              && ($querymode!=BX_DOL_DNSBL_ALLPOSTV_RETEVERY))
-             return BX_DOL_DNSBL_FAILURE;    // invalid querymode
+             return BX_DOL_DNSBL_FAILURE;	// invalid querymode
 
-        foreach ($servers as $r)
-        {
+        foreach ($servers as $r) {
             $resultaddr = gethostbyname ($key . "." . $r['zonedomain']);
 
-            if ($resultaddr && $resultaddr != $key . "." . $r['zonedomain'])
-            {
+            if ($resultaddr && $resultaddr != $key . "." . $r['zonedomain']) {
                 // we got some result from the DNS query, not NXDOMAIN. should we consider 'positive'?
-                $postvresp = $r['postvresp'];    // check positive match criteria
-                if (BX_DOL_DNSBL_MATCH_ANY == $postvresp || $resultaddr == $postvresp)
-                {
+                $postvresp = $r['postvresp'];	// check positive match criteria
+                if (
+                    BX_DOL_DNSBL_MATCH_ANY == $postvresp || 
+                    (preg_match("/^\d+\.\d+\.\d+\.\d+$/", $postvresp) && $resultaddr == $postvresp) ||
+                    (is_numeric($postvresp) && (ip2long($resultaddr) & $postvresp))
+                ) {
                     $numpositive++;
                     if ($querymode == BX_DOL_DNSBL_ANYPOSTV_RETFIRST)
-                        return BX_DOL_DNSBL_POSITIVE;    // found one positive, returning single
+                        return BX_DOL_DNSBL_POSITIVE;	// found one positive, returning single
                 }
             }
         }
@@ -139,7 +143,8 @@ class BxDolDNSBlacklists extends BxDol
         return "{$m[4]}.{$m[3]}.{$m[2]}.{$m[1]}";
     }
 
-    private function initChains() {
+    private function initChains() 
+    {
 
         $oDb = BxDolDb::getInstance();
 
@@ -148,15 +153,11 @@ class BxDolDNSBlacklists extends BxDol
             $GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_SPAMMERS] = $GLOBALS['MySQL']->fromCache('sys_dnsbl_'.BX_DOL_DNSBL_CHAIN_SPAMMERS, 'getAll', $sQuery);
         }
 
-        if (!isset($GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST])) {
-            $sQuery = $oDb->prepare("SELECT `zonedomain`, `postvresp` FROM `sys_dnsbl_rules` WHERE `chain` = ? AND `active` = 1", BX_DOL_DNSBL_CHAIN_WHITELIST);
-            $GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST] = $GLOBALS['MySQL']->fromCache('sys_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST, 'getAll', $sQuery);
-        }
+        if (!isset($GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST]))
+            $GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST] = $GLOBALS['MySQL']->fromCache('sys_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST, 'getAll', "SELECT `zonedomain`, `postvresp` FROM `sys_dnsbl_rules` WHERE `chain` = '".BX_DOL_DNSBL_CHAIN_WHITELIST."' AND `active` = 1");
 
-        if (!isset($GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_URIDNS])) {
-            $sQuery = $oDb->prepare("SELECT `zonedomain`, `postvresp` FROM `sys_dnsbl_rules` WHERE `chain` = ? AND `active` = 1", BX_DOL_DNSBL_CHAIN_URIDNS);
-            $GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_URIDNS] = $GLOBALS['MySQL']->fromCache('sys_dnsbl_'.BX_DOL_DNSBL_CHAIN_URIDNS, 'getAll', $sQuery);
-        }
+        if (!isset($GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_URIDNS]))
+            $GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_URIDNS] = $GLOBALS['MySQL']->fromCache('sys_dnsbl_'.BX_DOL_DNSBL_CHAIN_URIDNS, 'getAll', "SELECT `zonedomain`, `postvresp` FROM `sys_dnsbl_rules` WHERE `chain` = '".BX_DOL_DNSBL_CHAIN_URIDNS."' AND `active` = 1");
 
         $this->aChains[BX_DOL_DNSBL_CHAIN_SPAMMERS] = &$GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_SPAMMERS];
         $this->aChains[BX_DOL_DNSBL_CHAIN_WHITELIST] = &$GLOBALS['bx_dol_dnsbl_'.BX_DOL_DNSBL_CHAIN_WHITELIST];
@@ -166,3 +167,4 @@ class BxDolDNSBlacklists extends BxDol
 
 }
 
+/** @} */

+ 30 - 25
inc/classes/BxDolDNSURIBlacklists.php → modules/boonex/antispam/classes/BxAntispamDNSURIBlacklists.php

@@ -1,41 +1,43 @@
-<?php
+<?php defined('BX_DOL') or die('hack attempt');
 /**
- * @package     Dolphin Core
- * @copyright   Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
- * @license     CC-BY - http://creativecommons.org/licenses/by/3.0/
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
  */
-defined('BX_DOL') or die('hack attempt');
-
 
 /**
  * Spam detection based on URIs in the message
  */
-class BxDolDNSURIBlacklists extends BxDol
+class BxAntispamDNSURIBlacklists extends BxDol
 {
-    var $aZonesUrls = array (
+    protected $aZonesUrls = array (
         2 => "http://www.surbl.org/tld/two-level-tlds",
         3 => "http://www.surbl.org/tld/three-level-tlds",
     );
 
-    var $oDb;
+    protected $oDb;
 
     /**
      * Constructor
      */
-    public function BxDolDNSURIBlacklists()
+    public function __construct()
     {
-        parent::BxDol();
+        parent::__construct();
         $this->aZonesUrls = array ( // for some reason original urls are restricted to fetch, so copies are created locally
-            2 => BX_DIRECTORY_PATH_ROOT . "two-level-tlds",
-            3 => BX_DIRECTORY_PATH_ROOT . "three-level-tlds",
+            2 => BX_DIRECTORY_PATH_MODULES . "boonex/antispam/data/two-level-tlds",
+            3 => BX_DIRECTORY_PATH_MODULES . "boonex/antispam/data/three-level-tlds",
         );
 
-        $this->oDb = BxDolDb::getInstance();
+        $this->oDb = &$GLOBALS['MySQL'];
         $this->initZones();
     }
 
-    public function isSpam ($s) {
-
+    public function isSpam ($s)
+    {
         $aURIs = $this->parseUrls ($s);
         if (!$aURIs)
             return false;
@@ -53,8 +55,8 @@ class BxDolDNSURIBlacklists extends BxDol
         return false;
     }
 
-    public function parseUrls (&$s) {
-
+    public function parseUrls (&$s)
+    {
         $aMatches = array ();
         if (!preg_match_all("!(https?|ftp|gopher|telnet|file|notes|ms-help):[/\\\\]+([\w\d\.]*)!", $s, $aMatches))
             return false;
@@ -72,8 +74,8 @@ class BxDolDNSURIBlacklists extends BxDol
         return $aUrlsUniq;
     }
 
-    public function validateUrls ($aUrlsUniq) {
-
+    public function validateUrls ($aUrlsUniq)
+    {
         $aUrls = array ();
         foreach ($aUrlsUniq as $sUrl) {
 
@@ -124,20 +126,22 @@ class BxDolDNSURIBlacklists extends BxDol
         return array_values($aUrlsUniq);
     }
 
-    public function onPositiveDetection ($sExtraData = '') {
+    public function onPositiveDetection ($sExtraData = '')
+    {
         $o = bx_instance('BxDolDNSBlacklists');
-        $o->onPositiveDetection (getVisitorIP(), $sExtraData, 'dnsbluri');
+        $o->onPositiveDetection (getVisitorIP(false), $sExtraData, 'dnsbluri');
     }
 
     /*************** private function ***************/
 
-    private function isDbZoneMatch ($iLevel, $sZone) {
+    private function isDbZoneMatch ($iLevel, $sZone) 
+    {
         $sQuery = $this->oDb->prepare("SELECT `level` FROM `sys_dnsbluri_zones` WHERE `level` = ? AND `zone` = ? LIMIT 1", $iLevel, $sZone);
         return $this->oDb->getOne($sQuery) ? true : false;
     }
 
-    private function initZones() {
-
+    private function initZones()
+    {
         if (0 == $this->oDb->getOne("SELECT COUNT(*) FROM `sys_dnsbluri_zones`")) {
 
             $this->oDb->query("TRUNCATE TABLE `sys_dnsbluri_zones`");
@@ -163,3 +167,4 @@ class BxDolDNSURIBlacklists extends BxDol
 
 }
 
+/** @} */

+ 22 - 0
modules/boonex/antispam/classes/BxAntispamDb.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+bx_import('BxDolModuleDb');
+
+class BxAntispamDb extends BxDolModuleDb
+{
+	function __construct(&$oConfig) 
+    {
+		parent::__construct($oConfig);	
+    }
+}
+
+/** @} */

+ 105 - 0
modules/boonex/antispam/classes/BxAntispamIP.php

@@ -0,0 +1,105 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+/**
+ * Blocking/whitelisting by IP using local database
+ */
+class BxAntispamIP extends BxDol
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Check if IP is directly whitelisted by IP address or by IP address range
+     *
+     * @param $sCurIP IP to check, or empty for current IP
+     * @return true - if IP is whitelisted or under cron execution; false - if IP is not whitelisted, or feature is not enabled
+     */
+    public function isIpWhitelisted ($sCurIP = '')
+    {
+        if (defined('BX_DOL_CRON_EXECUTE'))
+            return true;
+
+        $iIPGlobalType = (int)getParam('bx_antispam_ip_list_type');
+        if ($iIPGlobalType != 1 && $iIPGlobalType != 2) // 0 - disabled
+            return false;
+
+        if (!$sCurIP)
+            $sCurIP = getVisitorIP();
+        $iCurIP = sprintf("%u", ip2long($sCurIP));
+        $iCurrTime = time();
+
+        return db_value("SELECT `ID` FROM `sys_ip_list` WHERE `Type` = 'allow' AND `LastDT` > $iCurrTime AND `From` <= '$iCurIP' AND `To` >= '$iCurIP' LIMIT 1") ? true : false;
+    }
+
+    /**
+     * Check if IP is directly bloked by IP address or by IP address range
+     *
+     * @param $sCurIP IP to check, or empty for current IP
+     * @return true - if IP is blocked; false - if IP is not blocked, or feature is not enabled, or it is run under cron
+     */
+    public function isIpBlocked ($sCurIP = '')
+    {
+        if (defined('BX_DOL_CRON_EXECUTE'))
+            return false;
+
+        $iIPGlobalType = (int)getParam('bx_antispam_ip_list_type');
+        if ($iIPGlobalType != 1 && $iIPGlobalType != 2) // 0 - disabled
+            return false;
+
+        if (!$sCurIP)
+            $sCurIP = getVisitorIP();
+        $iCurIP = sprintf("%u", ip2long($sCurIP));
+        $iCurrTime = time();
+
+        if ($this->isIpWhitelisted($sCurIP))
+            return false;
+
+        $isBlocked = db_value("SELECT `ID` FROM `sys_ip_list` WHERE `Type` = 'deny' AND `LastDT` > $iCurrTime AND `From` <= '$iCurIP' AND `To` >= '$iCurIP' LIMIT 1");
+        if ($isBlocked)
+            return true;
+
+        // 1 - all allowed except listed
+        // 2 - all blocked except listed
+        return $iIPGlobalType == 2 ? true : false;
+    }
+
+
+    /**
+     * Add IP to blocklist
+     *
+     * @param $sIP IP as string or long integer
+     * @param $iExpirationInSec set expiration in seconds
+     * @param $sComment comment about blocking
+     * @return false on error, not false on success
+     */
+    public function blockIp($mixedIP, $iExpirationInSec = 86400, $sComment = '')
+    {
+        if (preg_match('/^[0-9]+$/', $mixedIP))
+            $iIP = $mixedIP;
+        else
+            $iIP = sprintf("%u", ip2long($sIP));
+
+        $iExpirationInSec = time() + (int)$iExpirationInSec;
+
+        $oDb = BxDolDb::getInstance();
+        $sQuery = $oDb->prepare("SELECT ID FROM `sys_ip_list` WHERE `From` = ? AND `To` = ? LIMIT 1", $iIP, $iIP);
+        if (!$oDb->getOne($sQuery)) {
+            $sQuery = $oDb->prepare("INSERT INTO `sys_ip_list` SET `From` = ?, `To` = ?, `Type` = 'deny', `LastDT` = ?, `Desc` = ?", $iIP, $iIP, $iExpirationInSec, $sComment);
+            return $oDb->res($sQuery);
+        }
+        return false;
+    }
+}
+
+/** @} */

+ 234 - 0
modules/boonex/antispam/classes/BxAntispamModule.php

@@ -0,0 +1,234 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+// TODO: add checking on join form
+
+bx_import('BxDolModule');
+
+class BxAntispamModule extends BxDolModule 
+{
+    function __construct(&$aModule) 
+    {
+        parent::__construct($aModule);
+    }
+
+    /**
+     * Check text for spam.
+     * First it check if IP is whitelisted(or under cron execution or user is admin) - for whitelisted IPs check for spam isn't performed,
+     * then it checks URLs found in text for DNSURI black lists (@see BxAntispamDNSURIBlacklists),
+     * then it checks text in Akismet service (@see BxAntispamAkismet).
+     * It can send report if spam is found or tries to inform caller to block the content (depending on configuration).
+     * 
+     * @param $sContent content to check for spam
+     * @param $sIp IP address of content poster
+     * @param $isStripSlashes slashes parameter:
+     *          BX_SLASHES_AUTO - automatically detect magic_quotes_gpc setting
+     *          BX_SLASHES_NO_ACTION - do not perform any action with slashes
+     * @return true if spam detected and content shouln't be recorded, false if content should be processed as usual.
+     */
+    function serviceIsSpam ($sContent, $sIp = '', $isStripSlashes = BX_SLASHES_AUTO) 
+    {
+        if (defined('BX_DOL_CRON_EXECUTE') || isAdmin())
+            return false;
+
+        if ($this->serviceIsIpWhitelisted($sIp))
+            return false;
+
+        if (get_magic_quotes_gpc() && $isStripSlashes == BX_SLASHES_AUTO)
+            $sContent = stripslashes($sContent);
+
+        $bRet = false;
+        if ('on' == $this->_oConfig->getAntispamOption('uridnsbl_enable')) {
+            $oDNSURIBlacklists = bx_instance('BxAntispamDNSURIBlacklists', array(), $this->_aModule);
+            if ($oDNSURIBlacklists->isSpam($sContent)) {
+                $oDNSURIBlacklists->onPositiveDetection($sContent);
+                $bRet = true;
+            }
+        }
+
+        if (!$bRet && 'on' == $this->_oConfig->getAntispamOption('akismet_enable')) {
+            $oAkismet = bx_instance('BxAntispamAkismet', array(), $this->_aModule);
+            if ($oAkismet->isSpam($sContent)) {
+                $oAkismet->onPositiveDetection($sContent);
+                $bRet = true;
+            }
+        }
+
+        bx_alert('bx_antispam', 'is_spam', bx_get_logged_profile_id(), 0, array('content' => $sContent, 'ip' => $sIp, 'result' => &$ret));
+
+        if ($bRet && 'on' == $this->_oConfig->getAntispamOption('antispam_report')) {
+
+            $iProfileId = getLoggedId();
+            $aPlus = array(
+                'SpammerUrl' => getProfileLink($iProfileId),
+                'SpammerNickName' => getNickName($iProfileId),
+                'Page' => htmlspecialchars_adv($_SERVER['PHP_SELF']),
+                'Get' => print_r($_GET, true),
+                'SpamContent' => htmlspecialchars_adv($sContent),
+            );
+
+            bx_import('BxDolEmailTemplates');
+            $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate('t_SpamReportAuto', $aPlus);
+            if (!$aTemplate)
+                trigger_error('Email template or translation missing: t_SpamReportAuto', E_USER_ERROR);
+
+            sendMail(getParam('site_email'), $aTemplate['Subject'], $aTemplate['Body']);
+        }
+
+        if ($bRet && 'on' == $this->_oConfig->getAntispamOption('antispam_block'))
+            return true;
+
+        return false;
+    }
+
+
+    /**
+     * Perform complex check if user is allowed to login.
+     * First it checks if IP is directly blocked (@see serviceIsIpBlocked), 
+     * then it checks in DNS black lists (@see serviceIsIpDnsBlacklisted).
+     *
+     * @param $sCurIP IP to check, or empty for current IP
+     * @param $sType [optional] place where checking is performed, for example 'join', 'login'
+     * @return empty string - if join should be allowed, error message - if join should be blocked
+     */
+    function serviceCheckLogin ($sIp = '')
+    {
+        $sErrorMsg = '';
+        $sType = 'login';
+
+        if (!$sIp)
+            $sIp = getVisitorIP();
+            
+        if (!$sErrorMsg && $this->serviceIsIpBlocked($sIp))
+            $sErrorMsg = $this->getErrorMessageIpBlocked();
+
+        if (!$sErrorMsg && 'on' == $this->_oConfig->getAntispamOption('dnsbl_enable') && 'block' == $this->_oConfig->getAntispamOption('dnsbl_behaviour') && $this->serviceIsIpDnsBlacklisted($sIp, $sType))
+            $sErrorMsg = $this->getErrorMessageSpam();
+        
+        bx_alert('bx_antispam', 'check_login', bx_get_logged_profile_id(), 0, array('ip' => $sIp, 'error_msg' => &$sErrorMsg));
+
+        return $sErrorMsg;
+    }
+
+    /**
+     * Perform complex check if user is allowed to join.
+     * First it checks if IP is directly blocked (@see serviceIsIpBlocked),
+     * then it checks in DNS black lists (@see serviceIsIpDnsBlacklisted),
+     * then it checks in StopForumSpam service (@see BxAntispamStopForumSpam).
+     *
+     * TODO: if dnsbl_behaviour == approval, inform caller to set account to approval status on positive detection
+     *
+     * @param $sCurIP IP to check, or empty for current IP
+     * @param $sType [optional] place where checking is performed, for example 'join', 'login'
+     * @return empty string - if join should be allowed, error message - if join should be blocked
+     */
+    function serviceCheckJoin ($sEmail, $sIp = '') 
+    {
+        $sErrorMsg = '';
+        $sType = 'join';
+
+        if (!$sIp)
+            $sIp = getVisitorIP();
+
+        if (!$sErrorMsg && $this->serviceIsIpBlocked($sIp))
+            $sErrorMsg = $this->getErrorMessageIpBlocked();
+
+        if (!$sErrorMsg && 'on' == $this->_oConfig->getAntispamOption('dnsbl_enable') && 'block' == $this->_oConfig->getAntispamOption('dnsbl_behaviour') && $this->serviceIsIpDnsBlacklisted($sIp, $sType))
+            $sErrorMsg = $this->getErrorMessageSpam();
+
+        
+        if (!$sErrorMsg) {
+            $oStopForumSpam = bx_instance('BxAntispamStopForumSpam', array(), $this->_aModule);
+            if ($oStopForumSpam->isSpammer(array('email' => $sEmail, 'ip' => $sIp), $sType))
+                $sErrorMsg = $this->getErrorMessageSpam();
+        }
+
+        bx_alert('bx_antispam', 'check_join', bx_get_logged_profile_id(), 0, array('email' => $sEmail, 'ip' => $sIp, 'error_msg' => &$sErrorMsg));
+
+        return $sErrorMsg;
+    }
+
+    /**
+     * Check if IP is blacklisted in some DNS chain (@see BxAntispamDNSBlacklists).
+     *
+     * @param $sCurIP IP to check, or empty for current IP
+     * @param $sType [optional] place where checking is performed, for example 'join', 'login'
+     * @return true if IP blacklisted and not whiteloisted, or false if under cron execution or if IP isn't blacklisted
+     */
+    function serviceIsIpDnsBlacklisted($sCurIP = '', $sType = '')
+    {
+        if (defined('BX_DOL_CRON_EXECUTE'))
+            return false;
+
+        if (!$sCurIP)
+            $sCurIP = getVisitorIP();
+
+        if ($this->serviceIsIpWhitelisted($sCurIP))
+            return false;
+
+        $o = bx_instance('BxAntispamDNSBlacklists', array(), $this->_aModule);
+
+        if (BX_DOL_DNSBL_POSITIVE == $o->dnsbl_lookup_ip(BX_DOL_DNSBL_CHAIN_SPAMMERS, $sCurIP) && BX_DOL_DNSBL_POSITIVE != $o->dnsbl_lookup_ip(BX_DOL_DNSBL_CHAIN_WHITELIST, $sCurIP)) {
+            $o->onPositiveDetection ($sCurIP, $sType);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * BxAntispamIP::isIpWhitelisted
+     */
+    function serviceIsIpWhitelisted($sIp = '')
+    {
+        $o = bx_instance('BxAntispamIP', array(), $this->_aModule);
+        return $o->isIpWhitelisted($sIp);
+    }
+
+    /**
+     * @see BxAntispamIP::isIpBlocked
+     */
+    function serviceIsIpBlocked($sIp = '')
+    {
+        $o = bx_instance('BxAntispamIP', array(), $this->_aModule);
+        return $o->isIpBlocked($sIp);
+    }
+
+    /**
+     * @see BxAntispamIP::blockIp
+     */
+    function serviceBlockIp($mixedIP, $iExpirationInSec = 86400, $sComment = '')
+    {
+        $o = bx_instance('BxAntispamIP', array(), $this->_aModule);
+        return $o->blockIp($mixedIP, $iExpirationInSec, $sComment);
+    }
+
+    protected function getErrorMessageIpBlocked () 
+    {
+        bx_import('BxDolLanguages');
+        return _t('_bx_antispam_ip_blocked', $this->getErrorMessageSubmitFalsePositiveReport());
+    }
+
+    protected function getErrorMessageSpam ()
+    {
+        bx_import('BxDolLanguages');
+        return _t('_bx_antispam_spam_detected', $this->getErrorMessageSubmitFalsePositiveReport());
+    }
+
+    protected function getErrorMessageSubmitFalsePositiveReport ()
+    {
+        if (BxDolRequest::serviceExists('bx_contact', 'get_contact_page_url') && ($sUrl = BxDolService::call('bx_contact', 'get_contact_page_url')))
+            return _t('_bx_antispam_submit_false_positive_report', $sUrl);
+        return '';
+    }
+}
+
+/** @} */

+ 103 - 0
modules/boonex/antispam/classes/BxAntispamStopForumSpam.php

@@ -0,0 +1,103 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+/**
+ * Spam detection based on email and ip powered by StopForumSpam service - http://www.stopforumspam.com/
+ */
+class BxAntispamStopForumSpam extends BxDol
+{
+    protected $_aKeys = array (
+        'ip' => 1, 
+        'email' => 1, 
+        'username' => 1,
+    );
+
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /** 
+     * Check if user is spammer
+     * @param $aValues - array with keys: ip, email, username
+     * @param $sDesc - desctiption, for example: join 
+     * @return true - on positive detection, false - on error or no spammer detection 
+     */ 
+    public function isSpammer ($aValues, $sDesc)
+    {        
+        if (!getParam('bx_antispam_stopforumspam_enable'))
+            return false;
+
+        if (!$aValues || !is_array($aValues))
+            return false;
+
+        $aRequestParams = array ('f' => 'json');
+        foreach ($this->_aKeys as $k => $b)  
+            if (isset($aValues[$k]))
+                $aRequestParams[$k] = rawurlencode($aValues[$k]);
+
+        $s = bx_file_get_contents('http://www.stopforumspam.com/api', $aRequestParams);
+        if (!$s)
+            return false;
+
+        $aResult = json_decode($s, true);
+        if (null === $aResult || !$aResult['success'])
+            return false;
+
+        foreach ($this->_aKeys as $k => $b) {
+            if (isset($aResult[$k]) && $aResult[$k]['appears']) {
+                $this->onPositiveDetection($sDesc);
+                return true;
+            }
+        }
+    
+        return false;
+    }
+
+    /** 
+     * Submit spammer
+     * @param @aValues - array with keys: ip, email, username
+     * @return false - on error, or true - on success
+     */ 
+    public function submitSpammer ($aValues, $sEvidences = false)
+    {
+        if (!getParam('bx_antispam_stopforumspam_enable'))
+            return false;
+
+        $sKey = getParam('bx_antispam_stopforumspam_api_key');
+        if (!$sKey)
+            return false;
+
+        $sData = 'api_key=' . $sKey . '&evidence=' . ($sEvidences ? rawurlencode($sEvidences) : 'spammer');
+        foreach ($this->_aKeys as $k => $b)
+            if (isset($aValues[$k]))
+                $sData .= '&' . ('ip' == $k ? 'ip_addr' : $k) . '=' . rawurlencode($aValues[$k]);
+
+        $fp = fsockopen("www.stopforumspam.com", 80);
+        fputs($fp, "POST /add.php HTTP/1.1\n" );
+        fputs($fp, "Host: www.stopforumspam.com\n" );
+        fputs($fp, "Content-type: application/x-www-form-urlencoded\n" );
+        fputs($fp, "Content-length: " . strlen($sData) . "\n" );
+        fputs($fp, "Connection: close\n\n" );
+        fputs($fp, $sData);
+        fclose($fp);
+        
+        return true;
+    }
+
+    public function onPositiveDetection ($sExtraData = '')
+    {
+        $o = bx_instance('BxDolDNSBlacklists');
+        $o->onPositiveDetection (getVisitorIP(false), $sExtraData, 'stopforumspam');
+    }
+}
+
+/** @} */

+ 42 - 0
modules/boonex/antispam/classes/BxAntispamStudioPage.php

@@ -0,0 +1,42 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+bx_import('BxTemplStudioModule');
+
+class BxAntispamStudioPage extends BxTemplStudioModule 
+{
+    protected $oModule;
+
+    function __construct($sModule = "", $sPage = "") 
+    {
+        parent::__construct($sModule, $sPage);
+
+        bx_import('BxDolModule');
+        $this->oModule = BxDolModule::getInstance('bx_antispam');
+
+        $this->aMenuItems = array(
+    	    array('name' => 'general', 'icon' => 'cogs', 'title' => '_adm_lmi_cpt_settings'),
+        );
+    }
+
+    function getHelp ()
+    {
+        return _t('_bx_antispam_help_text');
+    }
+
+    protected function getPageCaptionHelp() {
+        $oTemplate = BxDolStudioTemplate::getInstance();
+        $sContent = '<a href="' . BX_DOL_URL_STUDIO . 'module.php?name=bx_antispam&page=help">' . _t('_bx_antispam_help') . "</a>";
+        return $oTemplate->parseHtmlByName('page_caption_help.html', array('content' => $sContent));
+    }
+}
+
+/** @} */

+ 22 - 0
modules/boonex/antispam/classes/BxAntispamTemplate.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+bx_import ('BxDolModuleTemplate');
+
+class BxAntispamTemplate extends BxDolModuleTemplate 
+{    
+	function __construct(&$oConfig, &$oDb) 
+    {
+	    parent::__construct($oConfig, $oDb);
+    }    
+}
+
+/** @} */

+ 128 - 2
three-level-tlds → modules/boonex/antispam/data/three-level-tlds

@@ -1,10 +1,30 @@
 act.edu.au
 act.gov.au
+am.gov.br
 bay.livefilestore.com
+best.lt.ua
+best.volyn.ua
 blog.friendster.com
+blog33.fc2.com
+blogger.co.id
+blogger.co.il
+blogger.com.au
+blogger.com.co
+blogger.com.my
+blogger.com.pe
+blogger.com.ph
+blogspot.co.il
+blogspot.co.nz
+blogspot.co.uk
+blogspot.com.ar
+blogspot.com.au
+blogspot.com.br
+blogspot.com.es
+blogspot.com.tr
 blu.livefilestore.com
 bo.nordland.no
 bo.telemark.no
+ceeonline.co.in
 city.chiba.jp
 city.fukuoka.jp
 city.hiroshima.jp
@@ -27,12 +47,19 @@ co.at.pn
 co.at.tc
 co.uk.pn
 co.uk.tc
+co.uk.tt
 com.au.ms
 com.au.pn
 com.au.tc
+com.ne.kr
 com.sapo.pt
 do.sapo.pt
 docs.google.com
+dothome.co.kr
+elitesingles.co.uk
+en.alibaba.com
+ge.co.it
+go.gov.br
 groups.live.com
 gs.aa.no
 gs.ah.no
@@ -57,14 +84,75 @@ gs.va.no
 gs.vf.no
 heroy.more-og-romsdal.no
 heroy.nordland.no
+home.dyndns.org
 home.sapo.pt
 homepage.t-online.de
-lkd.co.im
+hop.clickbank.net
+hpu.edu.cn
+ig.com.br
+k12.ak.us
+k12.al.us
+k12.ar.us
+k12.as.us
+k12.az.us
+k12.ca.us
+k12.co.us
+k12.ct.us
+k12.dc.us
+k12.de.us
+k12.fl.us
+k12.ga.us
+k12.gu.us
+k12.ia.us
+k12.id.us
+k12.il.us
+k12.in.us
+k12.ks.us
+k12.ky.us
+k12.la.us
+k12.ma.us
+k12.md.us
+k12.me.us
+k12.mi.us
+k12.mn.us
+k12.mo.us
+k12.ms.us
+k12.mt.us
+k12.nc.us
+k12.nd.us
+k12.ne.us
+k12.nh.us
+k12.nj.us
+k12.nm.us
+k12.nv.us
+k12.ny.us
+k12.oh.us
+k12.ok.us
+k12.or.us
+k12.pa.us
+k12.pr.us
+k12.ri.us
+k12.sc.us
+k12.tn.us
+k12.tx.us
+k12.ut.us
+k12.va.us
+k12.vi.us
+k12.vt.us
+k12.wa.us
+k12.wi.us
+k12.wv.us
+k12.wy.us
+lima-city.de
 ltd.co.im
 me.uk.tc
 metro.tokyo.jp
+mg.gov.br
+mobile.web.tr
 nes.akershus.no
 nes.buskerud.no
+net.work.za
+no-ip.co.uk
 no.sapo.pt
 nsw.edu.au
 nsw.gov.au
@@ -76,6 +164,8 @@ os.hedmark.no
 os.hordaland.no
 pa.gov.pl
 paginas.sapo.pt
+perso.neuf.fr
+perso.sfr.fr
 plc.co.im
 po.gov.pl
 pref.aichi.jp
@@ -124,25 +214,53 @@ pref.wakayama.jp
 pref.yamagata.jp
 pref.yamaguchi.jp
 pref.yamanashi.jp
+privat.t-online.de
 profile.live.com
 qld.edu.au
 qld.gov.au
+qzone.qq.com
+rj.gov.br
+rr.gov.br
+s3-ap-northeast-1.amazonaws.com
+s3-ap-southeast-1.amazonaws.com
+s3-ap-southeast-2.amazonaws.com
+s3-eu-west-1.amazonaws.com
+s3-fips-us-gov-west-1.amazonaws.com
+s3-sa-east-1.amazonaws.com
+s3-us-gov-west-1.amazonaws.com
+s3-us-west-1.amazonaws.com
+s3-us-west-2.amazonaws.com
+s3-website-ap-northeast-1.amazonaws.com
+s3-website-ap-southeast-1.amazonaws.com
+s3-website-ap-southeast-2.amazonaws.com
+s3-website-eu-west-1.amazonaws.com
+s3-website-sa-east-1.amazonaws.com
+s3-website-us-east-1.amazonaws.com
+s3-website-us-gov-west-1.amazonaws.com
+s3-website-us-west-1.amazonaws.com
+s3-website-us-west-2.amazonaws.com
+s3.amazonaws.com
 sa.edu.au
 sa.gov.au
 sakura.ne.jp
 sande.more-og-romsdal.no
 sande.vestfold.no
+shop.conn.tw
 skydrive.live.com
 so.gov.pl
+sp.gov.br
 spaces.live.com
 spaces.msn.com
 sr.gov.pl
 starostwo.gov.pl
 tas.edu.au
 tas.gov.au
+uel.ac.uk
 ug.gov.pl
 um.gov.pl
 upow.gov.pl
+us3.list-manage2.com
+user.icpnet.pl
 uw.gov.pl
 valer.hedmark.no
 valer.ostfold.no
@@ -153,4 +271,12 @@ wa.gov.au
 web.aplus.net
 web.fc2.com
 web.officelive.com
-
+wimbp.lodz.pl
+win.iu.nl
+wozaonline.co.za
+xn--b-5ga.nordland.no
+xn--b-5ga.telemark.no
+xn--hery-ira.nordland.no
+xn--hery-ira.xn--mre-og-romsdal-qqb.no
+xn--vler-qoa.hedmark.no
+xn--vler-qoa.xn--stfold-9xa.no

Fișier diff suprimat deoarece este prea mare
+ 300 - 2
modules/boonex/antispam/data/two-level-tlds


+ 152 - 0
modules/boonex/antispam/install/config.php

@@ -0,0 +1,152 @@
+<?php 
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+	/**
+	 * Main Section.
+	 */
+	'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_antispam',
+	'title' => 'Antispam',
+    'note' => 'Antispam tools',
+	'version' => '1.0.6',
+	'vendor' => 'BoonEx',
+    'product_url' => 'http://www.boonex.com/products/{uri}',
+	'update_url' => '',
+	
+	'compatible_with' => array(
+        '8.0.x'
+    ),	
+
+    /**
+	 * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+	 */
+	'home_dir' => 'boonex/antispam/',
+	'home_uri' => 'antispam',
+	
+	'db_prefix' => 'bx_antispam_',
+	'class_prefix' => 'BxAntispam',
+	/**
+	 * Installation/Uninstallation Section.
+	 */
+	'install' => array(
+		'show_introduction' => 0,
+		'change_permissions' => 0,
+		'execute_sql' => 1,
+		'update_languages' => 1,
+		'recompile_main_menu' => 0,
+		'recompile_member_menu' => 0,
+        'recompile_site_stats' => 0,		
+		'recompile_page_builder' => 0,
+		'recompile_profile_fields' => 0,
+		'recompile_comments' => 0,
+		'recompile_member_actions' => 0,
+		'recompile_tags' => 0,
+		'recompile_votes' => 0,
+		'recompile_categories' => 0,
+		'recompile_search' => 0,
+		'recompile_injections' => 0,
+		'recompile_permalinks' => 0,
+		'recompile_alerts' => 0,
+        'clear_db_cache' => 0,
+		'show_conclusion' => 0,
+	),
+	'uninstall' => array (
+		'show_introduction' => 0,
+		'change_permissions' => 0,
+		'execute_sql' => 1,
+		'update_languages' => 1,
+		'recompile_main_menu' => 0,
+		'recompile_member_menu' => 0,
+		'recompile_site_stats' => 0,
+		'recompile_page_builder' => 0,
+		'recompile_profile_fields' => 0,
+		'recompile_comments' => 0,
+		'recompile_member_actions' => 0,
+		'recompile_tags' => 0,
+		'recompile_votes' => 0,
+		'recompile_categories' => 0,
+		'recompile_search' => 0,
+		'recompile_injections' => 0,
+		'recompile_permalinks' => 0,
+		'recompile_alerts' => 0,
+        'clear_db_cache' => 0,
+		'show_conclusion' => 0,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'recompile_global_paramaters' => 1,
+        'recompile_main_menu' => 0,
+        'recompile_member_menu' => 0,
+        'recompile_site_stats' => 0,
+        'recompile_page_builder' => 0,
+        'recompile_profile_fields' => 0,
+        'recompile_comments' => 0,
+        'recompile_member_actions' => 0,
+        'recompile_tags' => 0,
+        'recompile_votes' => 0,
+        'recompile_categories' => 0,
+        'recompile_injections' => 0,
+        'recompile_permalinks' => 0,
+        'recompile_alerts' => 0,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array(
+        'execute_sql' => 1,
+        'recompile_global_paramaters' => 1,
+        'recompile_main_menu' => 0,
+        'recompile_member_menu' => 0,
+        'recompile_site_stats' => 0,
+        'recompile_page_builder' => 0,
+        'recompile_profile_fields' => 0,
+        'recompile_comments' => 0,
+        'recompile_member_actions' => 0,
+        'recompile_tags' => 0,
+        'recompile_votes' => 0,
+        'recompile_categories' => 0,
+        'recompile_injections' => 0,
+        'recompile_permalinks' => 0,
+        'recompile_alerts' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+	 * Dependencies Section
+	 */
+	'dependencies' => array(
+    ),
+
+	/**
+	 * Category for language keys.
+	 */
+	'language_category' => 'Antispam',
+
+	/**
+	 * Permissions Section
+	 */
+    'install_permissions' => array(),
+    'uninstall_permissions' => array(),
+
+	/**
+	 * Introduction and Conclusion Section.
+	 */
+	'install_info' => array(
+		'introduction' => '',
+		'conclusion' => ''
+	),
+	'uninstall_info' => array(
+		'introduction' => '',
+		'conclusion' => ''
+	)
+);
+
+/** @} */
+

+ 22 - 0
modules/boonex/antispam/install/installer.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+bx_import('BxDolStudioInstaller');
+
+class BxAntispamInstaller extends BxDolStudioInstaller 
+{
+    function __construct($aConfig) 
+    {
+        parent::__construct($aConfig);
+    }    
+}
+
+/** @} */ 

+ 25 - 0
modules/boonex/antispam/install/langs/en.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+
+	<string name="_bx_antispam"><![CDATA[Antispam]]></string>
+    <string name="_bx_antispam_adm_stg_cpt_type"><![CDATA[Antispam]]></string>
+    <string name="_bx_antispam_adm_stg_cpt_category_general"><![CDATA[General]]></string>
+    <string name="_bx_antispam_help"><![CDATA[Help]]></string>
+    <string name="_bx_antispam_help_text"><![CDATA[TODO: help text here]]></string>
+    <string name="_bx_antispam_ip_blocked"><![CDATA[IP address is blocked. {0}]]></string>
+    <string name="_bx_antispam_spam_detected"><![CDATA[Spam detected. {0}]]></string>
+    <string name="_bx_antispam_submit_false_positive_report"><![CDATA[If you believe that this is a mistake, please submit a false positive report here: {0}]]></string>
+
+	<string name="_bx_antispam_option_block"><![CDATA[Total block all spam content]]></string>
+	<string name="_bx_antispam_option_report"><![CDATA[Send report to admin if spam content discovered]]></string>
+	<string name="_bx_antispam_option_ip_list_type"><![CDATA[IP List Type (1 - all allowed except listed, 2 - all blocked except listed, 0 - disabled)]]></string>
+	<string name="_bx_antispam_option_dnsbl_enable"><![CDATA[Enable DNS Block Lists]]></string>
+	<string name="_bx_antispam_option_dnsbl_behaviour"><![CDATA[User join behaviour if listed in DNS Block Lists]]></string>
+	<string name="_bx_antispam_option_uridnsbl_enable"><![CDATA[Enable URI DNS Block Lists]]></string>
+	<string name="_bx_antispam_option_akismet_enable"><![CDATA[Enable Akismet]]></string>
+	<string name="_bx_antispam_option_akismet_api_key"><![CDATA[Akismet API Key]]></string>
+	<string name="_bx_antispam_option_stopforumspam_enable"><![CDATA[Enable "Stop Forum Spam"]]></string>
+	<string name="_bx_antispam_option_stopforumspam_api_key"><![CDATA["Stop Forum Spam" API Key]]></string>
+
+</resources>
+

+ 2 - 0
modules/boonex/antispam/install/sql/disable.sql

@@ -0,0 +1,2 @@
+-- settings
+DELETE FROM `top`, `toc`, `to` USING `sys_options_types` AS `top` LEFT JOIN `sys_options_categories` AS `toc` ON `top`.`id`=`toc`.`type_id` LEFT JOIN `sys_options` AS `to` ON `toc`.`id`=`to`.`category_id` WHERE `top`.`name`='bx_antispam';

+ 25 - 0
modules/boonex/antispam/install/sql/enable.sql

@@ -0,0 +1,25 @@
+-- settings
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types` (`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_antispam', '_bx_antispam_adm_stg_cpt_type', 'bx_antispam@modules/boonex/antispam/|std-mi.png', IF(NOT ISNULL(@iTypeOrder), @iTypeOrder + 1, 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order` )  
+VALUES (@iTypeId, 'bx_antispam_general', '_bx_antispam_adm_stg_cpt_category_general', 1);
+SET @iCategoryId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+(@iCategoryId, 'bx_antispam_block', '_bx_antispam_option_block', '', 'checkbox', '', '', '', 10),
+(@iCategoryId, 'bx_antispam_report', '_bx_antispam_option_report', 'on', 'checkbox', '', '', '', 20),
+(@iCategoryId, 'bx_antispam_ip_list_type', '_bx_antispam_option_ip_list_type', '0', 'digit', '', '', '', 30),
+
+(@iCategoryId, 'bx_antispam_dnsbl_enable', '_bx_antispam_option_dnsbl_enable', '', 'checkbox', '', '', '', 40),
+(@iCategoryId, 'bx_antispam_dnsbl_behaviour', '_bx_antispam_option_dnsbl_behaviour', 'approval', 'select', 'block,approval', '', '', 41),
+(@iCategoryId, 'bx_antispam_uridnsbl_enable', '_bx_antispam_option_uridnsbl_enable', '', 'checkbox', '', '', '', 42),
+
+(@iCategoryId, 'bx_antispam_akismet_enable', '_bx_antispam_option_akismet_enable', '', 'checkbox', '', '', '', 50),
+(@iCategoryId, 'bx_antispam_akismet_api_key', '_bx_antispam_option_akismet_api_key', '', 'digit', '', '', '', 51),
+
+(@iCategoryId, 'bx_antispam_stopforumspam_enable', '_bx_antispam_option_stopforumspam_enable', 'on', 'checkbox', '', '', '', 60),
+(@iCategoryId, 'bx_antispam_stopforumspam_api_key', '_bx_antispam_option_stopforumspam_api_key', '', 'digit', '', '', '', 61);
+

+ 14 - 0
modules/boonex/antispam/install/sql/install.sql

@@ -0,0 +1,14 @@
+
+-- Studio page and widget
+
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_antispam', '_bx_antispam', '_bx_antispam', 'bx_antispam@modules/boonex/antispam/|std-pi.png');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_antispam', '{url_studio}module.php?name=bx_antispam', '', 'bx_antispam@modules/boonex/antispam/|std-wi.png', '_bx_antispam', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));
+

+ 7 - 0
modules/boonex/antispam/install/sql/uninstall.sql

@@ -0,0 +1,7 @@
+
+-- Studio page and widget
+
+DELETE FROM `tp`, `tw`, `tpw`
+USING `sys_std_pages` AS `tp`, `sys_std_widgets` AS `tw`, `sys_std_pages_widgets` AS `tpw`
+WHERE `tp`.`id` = `tw`.`page_id` AND `tw`.`id` = `tpw`.`widget_id` AND `tp`.`name` = 'bx_antispam';
+

+ 17 - 0
modules/boonex/antispam/request.php

@@ -0,0 +1,17 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ * 
+ * @defgroup    Antispam Antispam
+ * @ingroup     DolphinModules
+ *
+ * @{
+ */
+
+check_logged();
+
+bx_import('BxDolRequest');
+BxDolRequest::processAsAction($GLOBALS['aModule'], $GLOBALS['aRequest']);
+
+/** @} */

BIN
modules/boonex/antispam/template/images/icons/std-mi.png


BIN
modules/boonex/antispam/template/images/icons/std-pi.png


BIN
modules/boonex/antispam/template/images/icons/std-si.png


BIN
modules/boonex/antispam/template/images/icons/std-wi.png


+ 10 - 1
modules/boonex/contact/classes/BxContactModule.php

@@ -22,7 +22,7 @@ class BxContactModule extends BxDolModule
 
         $this->_oConfig->init($this->_oDb);
     }
-
+    
 	/**
      * SERVICE METHODS
      */
@@ -90,6 +90,15 @@ class BxContactModule extends BxDolModule
 	    );
 	}
 
+	public function serviceGetContactPageUrl()
+    {
+		//if (true !== $this->isAllowedContact())
+        //    return false;
+
+        bx_import('BxDolPermalinks');
+        return BxDolPermalinks::getInstance()->permalink('page.php?i=contact');
+    }
+
     /*
      * COMMON METHODS
      */

+ 0 - 8
modules/boonex/english/data/langs/system.xml

@@ -1103,8 +1103,6 @@
 	<string name="_adm_stg_cpt_option_enable_template"><![CDATA[Show Template Switcher]]></string>
 	<string name="_adm_stg_cpt_option_expire_notification_days"><![CDATA[Number of days before membership expiration to notify members ( -1 = after expiration )]]></string>
 	<string name="_adm_stg_cpt_option_expire_notify_once"><![CDATA[Notify members about membership expiration only once (every day otherwise)]]></string>
-	<string name="_adm_stg_cpt_option_ip_blacklist_mode"><![CDATA[IP Blacklist system mode (1 - total block, 2 - login block)]]></string>
-	<string name="_adm_stg_cpt_option_ip_list_global_type"><![CDATA[IP List Type (1 - all allowed except listed, 2 - all blocked except listed, 0 - disabled)]]></string>
 	<string name="_adm_stg_cpt_option_lang_default"><![CDATA[Default Language]]></string>
 	<string name="_adm_stg_cpt_option_msgs_per_start"><![CDATA[Send emails from queue, it happens every cron execution (5m-1h)]]></string>
 	<string name="_adm_stg_cpt_option_permalinks_modules"><![CDATA[Enable friendly permalinks for Modules]]></string>
@@ -1113,16 +1111,11 @@
 	<string name="_adm_stg_cpt_option_site_email_bug_report"><![CDATA[Site Email Bug Report]]></string>
 	<string name="_adm_stg_cpt_option_site_email_notify"><![CDATA[Site Email Notify]]></string>
 	<string name="_adm_stg_cpt_option_site_title"><![CDATA[Site Title]]></string>
-	<string name="_adm_stg_cpt_option_sys_akismet_api_key"><![CDATA[Akismet API Key]]></string>
-	<string name="_adm_stg_cpt_option_sys_akismet_enable"><![CDATA[Enable Akismet]]></string>
-	<string name="_adm_stg_cpt_option_sys_antispam_block"><![CDATA[Total block all spam content]]></string>
-	<string name="_adm_stg_cpt_option_sys_antispam_report"><![CDATA[Send report to admin if spam content discovered]]></string>
 	<string name="_adm_stg_cpt_option_sys_cache_memcache_host"><![CDATA[Memcached server host]]></string>
 	<string name="_adm_stg_cpt_option_sys_cache_memcache_port"><![CDATA[Memcached server port]]></string>
 	<string name="_adm_stg_cpt_option_sys_calendar_starts_sunday"><![CDATA[Does Calender start on Sunday?]]></string>
 	<string name="_adm_stg_cpt_option_sys_db_cache_enable"><![CDATA[Enable DB cache]]></string>
 	<string name="_adm_stg_cpt_option_sys_db_cache_engine"><![CDATA[DB cache engine (other than File option may require custom server setup)]]></string>
-	<string name="_adm_stg_cpt_option_sys_dnsbl_enable"><![CDATA[Enable DNS Block Lists]]></string>
 	<string name="_adm_stg_cpt_option_sys_format_date"><![CDATA[Date Format]]></string>
 	<string name="_adm_stg_cpt_option_sys_format_datetime"><![CDATA[Datetime Format]]></string>
 	<string name="_adm_stg_cpt_option_sys_format_time"><![CDATA[Time Format]]></string>
@@ -1155,7 +1148,6 @@
 	<string name="_adm_stg_cpt_option_sys_template_cache_js_enable"><![CDATA[Enable cache for JS files]]></string>
 	<string name="_adm_stg_cpt_option_sys_template_page_width_max"><![CDATA[Max page width(in pixels)]]></string>
 	<string name="_adm_stg_cpt_option_sys_template_page_width_min"><![CDATA[Min page width(in pixels)]]></string>
-	<string name="_adm_stg_cpt_option_sys_uridnsbl_enable"><![CDATA[Enable URI DNS Block Lists]]></string>
 	<string name="_adm_stg_cpt_option_tags_non_parsable"><![CDATA[Non-parsable tags (type all tags in lower case, delimit them by comma)]]></string>
 	<string name="_adm_stg_cpt_option_tags_perpage_browse"><![CDATA[Number of tags to show on browse pages]]></string>
 	<string name="_adm_stg_cpt_option_tags_show_limit"><![CDATA[Number of tags to show limit]]></string>

+ 1 - 1
studio/classes/BxDolStudioIpBlockList.php

@@ -110,7 +110,7 @@ EOF;
         $sType2C = _t('_adm_ipbl_Type2_desc');
         $sTitle = '';
 
-        $iIpListType = (int)getParam('ipListGlobalType');
+        $iIpListType = (int)getParam('bx_antispam_ip_list_type');
         switch ($iIpListType) {
             case 1:
                 $sTitle = '<h2>'.$sType1C.'</h2>';

+ 31 - 0
tests/bootstrap.php

@@ -9,3 +9,34 @@ if (!file_exists($sHeaderPath))
 
 require_once($sHeaderPath);
 
+
+class BxDolTestCase extends PHPUnit_Framework_TestCase
+{
+
+    function bxMockGet ($sClass, $aModule = array(), $bDisableContructor = false) 
+    {        
+        if ($aModule)
+            bx_import(bx_ltrim_str($sClass, $aModule['class_prefix']), $aModule);
+        else
+            bx_import($sClass);
+        
+        if ($bDisableContructor) {
+            $GLOBALS['bxDolClasses'][$sClass] = $this->getMockBuilder($sClass)
+                ->disableOriginalConstructor()
+                ->getMock();
+        } else {
+            $GLOBALS['bxDolClasses'][$sClass] = $this->getMock($sClass);
+        }
+
+        return $GLOBALS['bxDolClasses'][$sClass];
+    }
+
+    function bxMockFree (&$o) 
+    {
+        $sClassName = bx_ltrim_str(get_class($o), 'Mock_');
+        $sClassName = preg_replace('/_[A-Za-z0-9]+$/', '', $sClassName);
+        unset($GLOBALS['bxDolClasses'][$sClassName]);
+        unset($o);
+    }
+
+}

+ 261 - 0
tests/units/modules/boonex/antispam/classes/BxAntispamModuleTest.php

@@ -0,0 +1,261 @@
+<?php
+
+/**
+ * Test Antispam module
+ */
+class BxAntispamModuleTest extends BxDolTestCase
+{
+    protected $_sSampleEmail = 'some@example.com';
+    protected $_sSampleIP = '0.0.0.0';
+
+    protected $_oModule;
+
+    protected $_oMockIP;
+    protected $_oMockDNSBlacklists;
+    protected $_oMockDNSURIBlacklists;
+    protected $_oMockStopForumSpam;
+    protected $_oMockAkismet;
+
+    protected function setUp()
+    {
+        bx_import('BxDolModule');
+        $this->_oModule = BxDolModule::getInstance('bx_antispam');
+
+        $this->_oMockIP = $this->bxMockGet('BxAntispamIP', $this->_oModule->_aModule);
+        $this->_oMockDNSBlacklists = $this->bxMockGet('BxAntispamDNSBlacklists', $this->_oModule->_aModule, true);
+        $this->_oMockDNSURIBlacklists = $this->bxMockGet('BxAntispamDNSURIBlacklists', $this->_oModule->_aModule, true);
+        $this->_oMockStopForumSpam = $this->bxMockGet('BxAntispamStopForumSpam', $this->_oModule->_aModule);
+        $this->_oMockAkismet = $this->bxMockGet('BxAntispamAkismet', $this->_oModule->_aModule);
+    }
+
+    protected function tearDown()
+    {
+        // free all mock objects after each test call
+        $this->bxMockFree($this->_oMockIP);
+        $this->bxMockFree($this->_oMockDNSBlacklists);
+        $this->bxMockFree($this->_oMockDNSURIBlacklists);
+        $this->bxMockFree($this->_oMockStopForumSpam);
+        $this->bxMockFree($this->_oMockAkismet);
+
+        // restore options after each test call
+        $this->_oModule->_oConfig->restoreAntispamOptions();
+    }
+
+    public function providerForServiceIsSpam()
+    {
+        $any = $this->anything();
+        return array(
+            array(true, $any, $any, $any, $any, $any, $any, false), // no spam detection for admin account 
+            array(false, true, $any, $any, $any, $any, $any, false), // no spam detection for whitelisted IP
+
+            array(false, false, 'on', false, $any, $any, 'on', false), // no spam detection if not listed in URIDNSBL (in "blocking" mode)
+            array(false, false, 'on', true, $any, $any, 'on', true), // it is spam if listed in URIDNSBL (in "blocking" mode)
+
+            array(false, false, '', $any, 'on', false, 'on', false), // no spam detection if not listed in Akismet (in "blocking" mode)
+            array(false, false, '', $any, 'on', true, 'on', true), // it is spam if listed in Akismet (in "blocking" mode)
+
+            array(false, false, 'on', true, 'on', true, '', false), // no spam detection in URIDNSBL nor Akismet if not in "blocking" mode
+        );
+    }
+
+    /**
+     * @dataProvider providerForServiceIsSpam
+     */
+    public function testServiceIsSpam($isAdmin, $bIpWhitelisted, $sUriDnsblEnable, $bUriDnsblBlacklisted, $sAkismetlEnable, $bAkismetBlacklisted, $sBlock, $bRes)
+    {
+        $this->_oModule->_oConfig->setAntispamOption('antispam_report', ''); // turn off reporting during testing
+        $this->_oModule->_oConfig->setAntispamOption('uridnsbl_enable', $sUriDnsblEnable); 
+        $this->_oModule->_oConfig->setAntispamOption('akismet_enable', $sAkismetlEnable);
+        $this->_oModule->_oConfig->setAntispamOption('antispam_block', $sBlock);
+
+        $GLOBALS['logged']['admin'] = $isAdmin;
+
+        if ($isAdmin) { // if admin no futher call are performed
+            $this->_oMockIP->expects($this->never())->method('isIpWhitelisted');
+            $this->_oMockDNSURIBlacklists->expects($this->never())->method('isSpam');
+            $this->_oMockAkismet->expects($this->never())->method('isSpam');
+        } else { // if not admin then check for whitelisting
+            $this->_oMockIP->expects($this->once())->method('isIpWhitelisted')
+                ->will($this->returnValue($bIpWhitelisted));
+        }
+
+        if ('on' != $sUriDnsblEnable || $isAdmin || $bIpWhitelisted) { // don't check in DNDBL if anything is true
+            $this->_oMockDNSURIBlacklists->expects($this->never())->method('isSpam');
+        } else { // check in URIDNSBL if URIDNSBL is enabled, not admin and IP is not whitelisted
+            $this->_oMockDNSURIBlacklists->expects($this->once())->method('isSpam')
+                ->will($this->returnValue($bUriDnsblBlacklisted));
+        }
+
+        if ('on' != $sAkismetlEnable || $isAdmin || $bIpWhitelisted || ($bUriDnsblBlacklisted && $sUriDnsblEnable)) { // don't check in Akismet if anything is true
+            $this->_oMockAkismet->expects($this->never())->method('isSpam');
+        } else { // check in Akismet if Akismet is enabled, not admin, IP is not whitelisted and not previouslu detected in DNSBL
+            $this->_oMockAkismet->expects($this->once())->method('isSpam')
+                ->will($this->returnValue($bAkismetBlacklisted));
+        }
+
+        // check result boolean value
+        $this->assertEquals($bRes, $this->_oModule->serviceIsSpam($this->anything(), $this->_sSampleIP));
+    }
+
+    public function providerForServiceCheckJoin()
+    {
+        $any = $this->anything();
+        return array(
+            array(true, $any, $any, $any, $any, false), // join is NOT allowed for blocked IPs
+            array(false, '', $any, $any, false, true), // join is allowed if IP isn't blocked, DNSBL checking disabled, not listed in StopForumSpam
+            array(false, 'on', 'approval', false, false, true), // join is allowed if IP isn't blocked and DNSBL enabled in "approval" mode, but not listed
+            array(false, 'on', 'block', false, false, true), // join is allowed if IP isn't blocked and DNSBL enabled in "block", but not listed
+            array(false, 'on', 'approval', true, false, true), // join is allowed if IP isn't blocked and DNSBL enabled in "approval" and IP listed
+            array(false, 'on', 'block', true, $any, false), // join is NOT allowed if IP isn't blocked and DNSBL enabled in "block" and IP listed
+            array(false, '', $any, $any, true, false), // join is NOT allowed if IP isn't blocked but listed in StopForumSpam
+        );
+    }
+
+    /**
+     * @dataProvider providerForServiceCheckJoin
+     */
+    public function testServiceCheckJoin($bIpBlocked, $sDnsblEnable, $sDnsblBehaviour, $bDnsblIpBlacklisted, $bStopForumSpamSpammer, $bResultEmptyString)
+    {
+        // set different options
+        $this->_oModule->_oConfig->setAntispamOption('dnsbl_enable', $sDnsblEnable);
+        $this->_oModule->_oConfig->setAntispamOption('dnsbl_behaviour', $sDnsblBehaviour);
+
+        // first IP address block checking is called
+        $this->_oMockIP->expects($this->once())->method('isIpBlocked')
+            ->with($this->equalTo($this->_sSampleIP))
+            ->will($this->returnValue($bIpBlocked));
+
+        if ($bIpBlocked) { // if ip is blocked no other methods should be called
+
+            $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
+            $this->_oMockStopForumSpam->expects($this->never())->method('isSpammer');
+
+        } elseif (!$bIpBlocked) { // if ip is NOT blocked - perform further checks
+
+            if ('on' != $sDnsblEnable || 'block' != $sDnsblBehaviour) { // DNSBL shouldn't be called if it isn't enabled or set in 'approval' mode
+                $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
+            } elseif ('on' == $sDnsblEnable && 'block' == $sDnsblBehaviour) {
+                $this->_oMockDNSBlacklists->expects($this->at(0))->method('dnsbl_lookup_ip')
+                    ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_SPAMMERS), $this->equalTo($this->_sSampleIP))
+                    ->will($this->returnValue($bDnsblIpBlacklisted ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
+            }
+
+            if ('on' == $sDnsblEnable && $bDnsblIpBlacklisted && 'block' == $sDnsblBehaviour) { // StopForumSpam shouldn't be called if DNSBL detected spam
+                $this->_oMockStopForumSpam->expects($this->never())->method('isSpammer');
+            } else {
+                $this->_oMockStopForumSpam->expects($this->once())->method('isSpammer')
+                    ->will($this->returnValue($bStopForumSpamSpammer));
+            }
+        }
+
+        // empty string - no spam detected
+        $this->assertTrue($bResultEmptyString == ('' == $this->_oModule->serviceCheckJoin($this->_sSampleEmail, $this->_sSampleIP)));
+    }
+
+    public function providerForServiceCheckLogin()
+    {
+        return array(
+            array(true, false, 'approval', false, false),
+            array(false, false, 'approval', false, true),
+            array(false, true, 'approval', false, true),
+            array(false, true, 'block', false, true),
+            array(false, true, 'approval', true, true),
+            array(false, true, 'block', true, false),
+        );
+    }
+
+    /**
+     * @dataProvider providerForServiceCheckLogin
+     */
+    public function testServiceCheckLogin($bIpBlocked, $sDnsblEnable, $sDnsblBehaviour, $bDnsblIpBlacklisted, $bResultEmptyString)
+    {
+        // set different options
+        $this->_oModule->_oConfig->setAntispamOption('dnsbl_enable', $sDnsblEnable);
+        $this->_oModule->_oConfig->setAntispamOption('dnsbl_behaviour', $sDnsblBehaviour);
+
+        // first IP address block checking is called
+        $this->_oMockIP->expects($this->once())->method('isIpBlocked')
+            ->will($this->returnValue($bIpBlocked));
+
+        if ($bIpBlocked || 'on' != $sDnsblEnable || 'block' != $sDnsblBehaviour) { // if ip is blocked, or DNSBL isn't enabled, or set in 'approval' mode - DNSBL checking shouldn't be called
+
+            $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
+
+        } elseif (!$bIpBlocked && 'on' == $sDnsblEnable && 'block' == $sDnsblBehaviour) { // call DNSBL checking only if enabled, and set in 'block' mode, and IP isn;t already blocked
+
+            $this->_oMockDNSBlacklists->expects($this->at(0))->method('dnsbl_lookup_ip')
+                ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_SPAMMERS), $this->_sSampleIP)
+                ->will($this->returnValue($bDnsblIpBlacklisted ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
+
+        }
+
+        // empty string - no spam detected
+        $this->assertTrue($bResultEmptyString == ('' == $this->_oModule->serviceCheckLogin($this->_sSampleIP)));
+    }
+
+    public function providerForServiceIsIpDnsBlacklisted()
+    {
+        return array(
+            array(false, false, false),
+            array(true, false, true),
+            array(true, true, false),
+            array(false, true, false),
+        );
+    }
+
+    /**
+     * @dataProvider providerForServiceIsIpDnsBlacklisted
+     */
+    public function testServiceIsIpDnsBlacklisted($bDnsblSpammer, $bDnsblWhitelisted, $bRes)
+    {
+        // check of whitelisting should be called once
+        $this->_oMockIP->expects($this->once())->method('isIpWhitelisted')
+            ->with($this->equalTo($this->_sSampleIP))
+            ->will($this->returnValue(false));
+
+        // check in 'spammers' chain
+        $this->_oMockDNSBlacklists->expects($this->at(0))->method('dnsbl_lookup_ip')
+            ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_SPAMMERS), $this->equalTo($this->_sSampleIP))
+            ->will($this->returnValue($bDnsblSpammer ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
+
+        if ($bDnsblSpammer) { // if found in 'spammers' chain, then check if it is whitelisted in 'whitelist' chain
+            $this->_oMockDNSBlacklists->expects($this->at(1))->method('dnsbl_lookup_ip')
+                ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_WHITELIST), $this->equalTo($this->_sSampleIP))
+                ->will($this->returnValue($bDnsblWhitelisted ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
+        }
+
+        // check result boolean value
+        $this->assertEquals($bRes, $this->_oModule->serviceIsIpDnsBlacklisted($this->_sSampleIP));
+    }
+
+    public function testServiceIsIpDnsBlacklistedWhenIpIsWhiletisted()
+    {
+        $this->_oMockIP->expects($this->once())->method('isIpWhitelisted')
+            ->will($this->returnValue(true));
+        $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
+
+        $this->assertEquals(false, $this->_oModule->serviceIsIpDnsBlacklisted($this->_sSampleIP));
+    }
+
+    public function testServiceIsIpWhitelisted()
+    {
+        $this->_oMockIP->expects($this->once())->method('isIpWhitelisted');
+
+        $this->_oModule->serviceIsIpWhitelisted($this->_sSampleIP);
+    }
+
+    public function testServiceIsIpBlocked()
+    {
+        $this->_oMockIP->expects($this->once())->method('isIpBlocked');
+
+        $this->_oModule->serviceIsIpBlocked($this->_sSampleIP);
+    }
+
+    public function testServiceBlockIp()
+    {
+        $this->_oMockIP->expects($this->once())->method('blockIp');
+
+        $this->_oModule->serviceBlockIp($this->_sSampleIP);
+    }
+}
+

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff