PHP Classes

File: src/Module/SpamBotMod.php

Recommend this page to a friend!
  Classes of stefan   contao PHP Spambot Detection   src/Module/SpamBotMod.php   Download  
File: src/Module/SpamBotMod.php
Role: Class source
Content type: text/plain
Description: Class source
Class: contao PHP Spambot Detection
Detect and block spam bots from accessing sites
Author: By
Last change:
Date: 1 year ago
Size: 9,775 bytes
 

Contents

Class file image Download
<?php
declare(strict_types=1);

/*
 * sync*gw SpamBot Bundle
 *
 * @copyright https://syncgw.com, 2013 - 2022
 * @author Florian Daeumling, https://syncgw.com
 * @license http://opensource.org/licenses/lgpl-3.0.html
 */

namespace syncgw\SpamBotBundle\Module;

use
Contao\Validator;
use
Contao\Widget;

class
SpamBotMod extends SpamBot {

   
/*
     * @array
     */
   
protected $Fields = ['spambot_page' => 0, 'spambot_msg' => 0, 'spambot_mod' => 0,
                         
'spambot_internal_logspam' => 0, 'spambot_internal_logham' => 0, ];

   
/**
     * Wipe everything from template except our error message - called during FE template processing
     *
     * @param content
     * @param template name
     *
     * @return string content
     */
   
public function clearTemplate(string $strContent, string $strTemplate): string {

       
$str = [];
        if (
$GLOBALS['SpamBot']['Catch'] & (SpamBot::SPAM | SpamBot::BLACKL) && 'mod_article' === $strTemplate) {
           
preg_match('/(?<=<!-- SpamBot::start -->).*(?=<!-- SpamBot::end -->)/s', $strContent, $str);
           
// clear flag
           
unset($GLOBALS['SpamBot']['Catch']);
            return
$str[0];
        }

        return
$strContent;
    }

   
/**
     * Replace insert tags - called during processing of insert tags
     *
     * @param insert tag
     * @param $strTag
     *
     * @return string replacement
     */
   
public function replaceInsertTag(string $strTag) {

       
$parm = explode('::', $strTag);
       
// are we responsible?
       
if ('spambot' !== strtolower($parm[0]))
            return
FALSE;

       
// get information
       
if (!is_array($arr = deserialize(base64_decode($this->Input->cookie('SpamBot'), TRUE))))
           
$arr = [];

        return isset(
$arr[$parm[1]]) ? $arr[$parm[1]] : '';
    }

   
/**
     * Check special regular expression - called during processing of textfields in any forms
     *
     * @param rgxp name
     * @param e-mail
     * @param $obj
     *
     * @return bool
     */
   
public function checkMail(string $strRegexp, string $email, Widget $obj): bool {
        global
$objPage;

       
// are we responsible?
       
if ('rgxSpamBots' !== $strRegexp)
            return
FALSE;

       
// standard e-mail validation
       
if (!Validator::isEmail($email))
           
$obj->addError($GLOBALS['TL_LANG']['ERR']['email']);

       
// check for active module included in this page
       
$rc = $this->Db->prepare(
                   
'SELECT c.id FROM tl_article a LEFT JOIN tl_content b ON (b.pid=a.id) '.
                   
'LEFT JOIN tl_module c ON (c.id=b.module) WHERE '.
                   
'a.pid=? AND b.invisible<>1 AND c.type=?')
                    ->
execute($objPage->id, 'SpamBot-Mail');

       
// if not on page check layout
       
if (!$rc->numRows) {
           
// get list of SpamBot-Mail modules
           
$mods = $this->Db->prepare('SELECT id FROM tl_module WHERE type=?')->execute('SpamBot-Mail');
           
$mods = is_array($mods->id) ? $mods->id : [$mods->id];
           
// clear module ID
           
$this->modID = 0;
           
// check for modules included in page layout
           
$rc = $this->Db->prepare('SELECT modules FROM tl_layout WHERE id=?')->execute($objPage->layout);
            if (
$rc->modules) {
                foreach (
deserialize($rc->modules) as $v) {
                    foreach (
$mods as $mid) {
                        if (
$mid === $v['mod']) {
                           
$this->modID = $mid;
                            break;
                        }
                    }
                    if (
$this->modID)
                        break;
                }
            }
           
// not in page and not in layout :-(
           
if (!$this->modID)
                return
TRUE;
        } else
           
$this->modID = $rc->id;

        list(
$ptyp, , ) = self::_doCheck(SpamBot::TYP_MAIL, self::getIP(), $email);

       
// display user error message
       
if ($ptyp & (SpamBot::SPAM | SpamBot::BLACKL))
           
$obj->addError($GLOBALS['TL_LANG']['SpamBot']['SpamBot']['email']);

        return
TRUE;
    }

   
/**
     * Check IP address - called by ModuleSpamBotIP
     *
     * @param client IP
     *
     * @return array (SpamBot::Status, status message, execution time)
     */
   
public function checkIP(string $ip): array {
        return
self::_doCheck(SpamBot::TYP_IP, $ip, '');
    }

   
/**
     * Get IP address
     *
     * @return string
     */
   
public function getIP(): string {

       
$ip = [];
        foreach ([
'HTTP_CF_CONNECTING_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED',
                       
'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR', ] as $key) {
            if (
TRUE === array_key_exists($key, $_SERVER)) {
                foreach (
explode(',', $_SERVER[$key]) as $vip)
                   
$ip[] = str_replace(' ', '', $vip);
            }
        }
       
// if for some strange reason we don't get an IP we return imemdiately with 0.0.0.0
       
if (empty($ip))
           
$ip = '0.0.0.0';
        else {
           
$ip = array_values(array_unique($ip));
            foreach (
$ip as $v) {
                if (
filter_var($v, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                   
$ip = $v;
                    break;
                }
            }
        }

        return
is_array($ip) ? $ip[0] : $ip;
    }

   
/**
     * Perform check
     *
     * @param function to call
     * @param IP address
     * @param email address
     *
     * @return array (SpamBot::Status, status message, execution time)
     */
   
private function _doCheck(int $func, string $ip, string $mail): array {

       
// return value is undefined
       
$rc = NULL;

       
// check all engines
       
$en = deserialize(parent::callMods($func, $ip, $mail, intval($this->spambot_mod)));

       
// check for WHITE and BLACK list?
       
if (SpamBot::MOD_FIRST !== $this->spambot_mod) {
            foreach (
$en as $v) {
                if (
SpamBot::NOTFOUND === $v[0])
                    continue;

               
// check type
               
if ($v[0] & (SpamBot::BLACKL | SpamBot::WHITEL)) {
                   
$rc = $v;
                    break;
                }
            }
        }

       
// check all other returned values
       
if (!$rc) {
            foreach (
$en as $v) {
                if (
SpamBot::NOTFOUND === $v[0])
                    continue;

               
// check modus
               
switch ($this->spambot_mod) {
                case
SpamBot::MOD_FIRST:
                    if (!(
$v[0] & SpamBot::NOTFOUND))
                       
$rc = $v;
                    break;

                case
SpamBot::MOD_SPAM:
                    if (
$v[0] & SpamBot::SPAM)
                       
$rc = $v;
                    break;

                case
SpamBot::MOD_HAM:
                default:
                    if (
$v[0] & SpamBot::HAM)
                       
$rc = $v;
                    break;
                }

               
// anything found
               
if ($rc)
                    break;
            }
        }

       
// default to "Ham" (if not found)
       
if (!$rc || $rc[0] & SpamBot::NOTFOUND) {
           
$rc[0] = SpamBot::HAM;
           
$rc[1] = 'Default: Ham';
        }

       
// convert LOADED
       
if ($rc[0] & SpamBot::LOADED)
           
$rc[0] = SpamBot::SPAM;

       
// special Intern check
       
if (($rc[0] & (SpamBot::WHITEL | SpamBot::BLACKL)) ||
            ((
$rc[0] & SpamBot::HAM) && !$this->spambot_internal_logham) ||
            ((
$rc[0] & SpamBot::SPAM) && !$this->spambot_internal_logspam))
            return
$rc;

       
// clean status message
       
$rc[1] = strip_tags($rc[1]);

       
// update internal data base
       
$upd = time();
        if (
SpamBot::TYP_IP === $func) {
           
$rec = $this->Db->prepare('SELECT id FROM tl_spambot WHERE module=? AND ip=? AND typ<>?')
                                  ->
execute($this->modID, $ip, SpamBot::LOADED);
            if (
$rec->numRows)
               
$this->Db->prepare('UPDATE tl_spambot SET module=?, tstamp=?, browser=?, typ=?, status=? WHERE id=?')
                               ->
execute($this->modID, $upd, \Environment::get('httpUserAgent'), $rc[0], $rc[1], $rec->id);
            else
               
$this->Db->prepare('INSERT tl_spambot SET module=?, ip=?, created=?, tstamp=?, browser=?, typ=?, status=?')
                               ->
execute($this->modID, $ip, $upd, $upd, \Environment::get('httpUserAgent'), $rc[0], $rc[1]);
        } else {
           
$rec = $this->Db->prepare('SELECT id FROM tl_spambot WHERE module=? AND mail=? AND typ<>?')
                                  ->
execute($this->modID, $mail, SpamBot::LOADED);
            if (
$rec->numRows)
               
$this->Db->prepare('UPDATE tl_spambot SET module=?, tstamp=?, ip=?, browser=?, typ=?, status=? WHERE id=?')
                               ->
execute($this->modID, $upd, self::getIP(), \Environment::get('httpUserAgent'), $rc[0], $rc[1], $rec->id);
            else
               
$this->Db->prepare('INSERT tl_spambot SET module=?, ip=?, mail=?, created=?, tstamp=?, browser=?, typ=?, status=?')
                               ->
execute($this->modID, self::getIP(), $mail, $upd, $upd, \Environment::get('httpUserAgent'), $rc[0], $rc[1]);
        }

        return
$rc;
    }

}

?>