You are here

class SFW in Anti Spam by CleanTalk 8.4

Same name and namespace in other branches
  1. 9.1.x src/lib/Cleantalk/Common/Firewall/Modules/SFW.php \Cleantalk\Common\Firewall\Modules\SFW

Hierarchy

  • class \Cleantalk\Common\Firewall\FirewallModule
    • class \Cleantalk\Common\Firewall\Modules\SFW

Expanded class hierarchy of SFW

2 files declare their use of SFW
BootSubscriber.php in src/EventSubscriber/BootSubscriber.php
CleantalkFuncs.php in src/CleantalkFuncs.php

File

src/lib/Cleantalk/Common/Firewall/Modules/SFW.php, line 10

Namespace

Cleantalk\Common\Firewall\Modules
View source
class SFW extends FirewallModule {
  public $module_name = 'SFW';

  // Additional params
  private $sfw_counter = false;
  private $set_cookies = false;
  private $cookie_domain = false;

  /**
   * FireWall_module constructor.
   * Use this method to prepare any data for the module working.
   *
   * @param string $data_table
   * @param array $params
   */
  public function __construct($data_table, $params = array()) {
    $this->db_data_table_name = $data_table ?: null;
    foreach ($params as $param_name => $param) {
      $this->{$param_name} = isset($this->{$param_name}) ? $param : false;
    }
  }

  /**
   * Use this method to execute main logic of the module.
   *
   * @return array  Array of the check results
   */
  public function check() {
    $results = array();
    $status = 0;

    // Skip by cookie
    foreach ($this->ip_array as $current_ip) {
      if (substr(CleantalkFuncs::apbct_getcookie('ct_sfw_pass_key'), 0, 32) == md5($current_ip . $this->api_key)) {
        if (CleantalkFuncs::apbct_getcookie('ct_sfw_passed')) {
          if (!headers_sent()) {
            CleantalkFuncs::apbct_setcookie('ct_sfw_passed', '0');
          }
          else {
            $results[] = array(
              'ip' => $current_ip,
              'is_personal' => false,
              'status' => 'PASS_SFW__BY_COOKIE',
            );
          }

          // Do logging an one passed request
          $this
            ->update_log($current_ip, 'PASS_SFW');
          if ($this->sfw_counter) {

            // @ToDo have to implement the logic of incrementing and saving count of all handled requests.
          }
        }
        if (strlen(CleantalkFuncs::apbct_getcookie('ct_sfw_pass_key')) > 32) {
          $status = substr(CleantalkFuncs::apbct_getcookie('ct_sfw_pass_key'), -1);
        }
        if ($status) {
          $results[] = array(
            'ip' => $current_ip,
            'is_personal' => false,
            'status' => 'PASS_SFW__BY_WHITELIST',
          );
        }
        return $results;
      }
    }

    // Common check
    foreach ($this->ip_array as $origin => $current_ip) {
      $result_entry = array(
        'ip' => $current_ip,
      );
      $current_ip_v4 = sprintf("%u", ip2long($current_ip));
      for ($needles = array(), $m = 6; $m <= 32; $m++) {
        $mask = str_repeat('1', $m);
        $mask = str_pad($mask, 32, '0');
        $needles[] = sprintf("%u", bindec($mask & base_convert($current_ip_v4, 10, 2)));
      }
      $needles = array_unique($needles);
      $db_results = $this->db
        ->fetch_all("SELECT\n\t\t\t\tnetwork, mask, status, source\n\t\t\t\tFROM " . $this->db_data_table_name . "\n\t\t\t\tWHERE network IN (" . implode(',', $needles) . ")\n\t\t\t\tAND\tnetwork = " . $current_ip_v4 . " & mask\n\t\t\t\tAND " . rand(1, 100000) . " <> 0\n\t\t\t\tORDER BY status DESC");
      if (!empty($db_results)) {
        foreach ($db_results as $db_result) {
          $result_entry['network'] = Helper::ip__long2ip($db_result['network']) . '/' . Helper::ip__mask__long_to_number($db_result['mask']);
          $result_entry['is_personal'] = $db_result['source'];
          if ((int) $db_result['status'] === 1) {
            $result_entry['status'] = 'PASS_SFW__BY_WHITELIST';
            break;
          }
          if ((int) $db_result['status'] === 0) {
            $result_entry['status'] = 'DENY_SFW';
          }
        }
      }
      else {
        $result_entry['is_personal'] = null;
        $result_entry['status'] = 'PASS_SFW';
      }
      $results[] = $result_entry;
    }
    return $results;
  }

  /**
   * Add entry to SFW log.
   * Writes to database.
   *
   * @param string $ip
   * @param string $status
   * @param string $network
   * @param string $source
   */
  public function update_log($ip, $status, $network = null, $source = null) {
    $id = md5($ip . $this->module_name);
    $time = time();
    if (!$source) {
      $source = 'NULL';
    }
    if (!$network) {
      $network = 'NULL';
    }
    $query = "INSERT INTO `{$this->db_log_table_name}`\n\t\tSET\n\t\t\t`id` = '{$id}',\n\t\t\t`ip` = '{$ip}',\n\t\t\t`status` = '{$status}',\n\t\t\t`all_entries` = 1,\n\t\t\t`blocked_entries` = " . (strpos($status, 'DENY') !== false ? 1 : 0) . ",\n\t\t\t`entries_timestamp` = '{$time}',\n\t\t\t`ua_name` = '" . Server::get('HTTP_USER_AGENT') . "',\n\t\t\t`source` = {$source},\n\t\t\t`network` = '{$network}',\n      `first_url` = '" . substr(Server::get('HTTP_HOST') . Server::get('REQUEST_URI'), 0, 100) . "',\n      `last_url` = '" . substr(Server::get('HTTP_HOST') . Server::get('REQUEST_URI'), 0, 100) . "'\n\t\tON DUPLICATE KEY\n\t\tUPDATE\n\t\t\t`status` = '{$status}',\n\t\t\t`source` = {$source},\n\t\t\t`all_entries` = `all_entries` + 1,\n\t\t\t`blocked_entries` = `blocked_entries`" . (strpos($status, 'DENY') !== false ? ' + 1' : '') . ",\n\t\t\t`entries_timestamp` = '{$time}',\n\t\t\t`ua_name` = '" . Server::get('HTTP_USER_AGENT') . "',\n\t\t\t`network` = '{$network}',\n      `last_url` = '" . substr(Server::get('HTTP_HOST') . Server::get('REQUEST_URI'), 0, 100) . "'";
    $this->db
      ->execute(str_replace(';', '', $query));
  }

  /**
   * @inheritdoc
   */
  public function actionsForDenied($result) {
    if ($this->sfw_counter) {

      // @ToDo have to implement the logic of incrementing and saving count of blocked requests.
    }
  }

  /**
   * @inheritdoc
   */
  public function actionsForPassed($result) {
    if ($this->set_cookies && !headers_sent()) {
      $status = $result['status'] === 'PASS_SFW__BY_WHITELIST' ? '1' : '0';
      $cookie_val = md5($result['ip'] . $this->api_key) . $status;
      CleantalkFuncs::apbct_setcookie('ct_sfw_pass_key', $cookie_val);
    }
  }

  /**
   * @inheritdoc
   */
  public function _die($result) {
    parent::_die($result);

    // Statistics
    if (!empty($this->blocked_ips)) {
      reset($this->blocked_ips);

      // @ToDo have to implement the logic of saving last_sfw_block info.

      /*
      $this->apbct->stats['last_sfw_block']['time'] = time();
      $this->apbct->stats['last_sfw_block']['ip'] = $result['ip'];
      $this->apbct->save('stats');
      */
    }

    // File exists?
    if (file_exists(__DIR__ . "/die_page_sfw.html")) {
      $sfw_die_page = file_get_contents(__DIR__ . "/die_page_sfw.html");
      $net_count = $this->db
        ->fetch('SELECT COUNT(*) as net_count FROM ' . $this->db_data_table_name)['net_count'];
      $status = $result['status'] === 'PASS_SFW__BY_WHITELIST' ? '1' : '0';
      $cookie_val = md5($result['ip'] . $this->api_key) . $status;

      // Translation
      $replaces = array(
        '{SFW_DIE_NOTICE_IP}' => $this
          ->__('SpamFireWall is activated for your IP ', 'cleantalk-spam-protect'),
        '{SFW_DIE_MAKE_SURE_JS_ENABLED}' => $this
          ->__('To continue working with the web site, please make sure that you have enabled JavaScript.', 'cleantalk-spam-protect'),
        '{SFW_DIE_CLICK_TO_PASS}' => $this
          ->__('Please click the link below to pass the protection,', 'cleantalk-spam-protect'),
        '{SFW_DIE_YOU_WILL_BE_REDIRECTED}' => sprintf($this
          ->__('Or you will be automatically redirected to the requested page after %d seconds.', 'cleantalk-spam-protect'), 3),
        '{CLEANTALK_TITLE}' => $this->test ? $this
          ->__('This is the testing page for SpamFireWall', 'cleantalk-spam-protect') : '',
        '{REMOTE_ADDRESS}' => $result['ip'],
        '{SERVICE_ID}' => $net_count,
        '{HOST}' => '',
        '{GENERATED}' => '<p>The page was generated at&nbsp;' . date('D, d M Y H:i:s') . "</p>",
        '{REQUEST_URI}' => Server::get('REQUEST_URI'),
        '{USE_ALT_COOKIES}' => \Drupal::config('cleantalk.settings')
          ->get('cleantalk_alternative_cookies_session') ? 1 : 0,
        // Cookie
        '{COOKIE_PREFIX}' => '',
        '{COOKIE_DOMAIN}' => $this->cookie_domain,
        '{COOKIE_SFW}' => $this->test ? $this->test_ip : $cookie_val,
        // Test
        '{TEST_TITLE}' => '',
        '{REAL_IP__HEADER}' => '',
        '{TEST_IP__HEADER}' => '',
        '{TEST_IP}' => '',
        '{REAL_IP}' => '',
      );

      // Test
      if ($this->test) {
        $replaces['{TEST_TITLE}'] = $this
          ->__('This is the testing page for SpamFireWall', 'cleantalk-spam-protect');
        $replaces['{REAL_IP__HEADER}'] = 'Real IP:';
        $replaces['{TEST_IP__HEADER}'] = 'Test IP:';
        $replaces['{TEST_IP}'] = $this->test_ip;
        $replaces['{REAL_IP}'] = $this->real_ip;
      }

      // Debug
      if ($this->debug) {
        $debug = '<h1>Headers</h1>' . var_export(apache_request_headers(), true) . '<h1>REMOTE_ADDR</h1>' . Server::get('REMOTE_ADDR') . '<h1>SERVER_ADDR</h1>' . Server::get('REMOTE_ADDR') . '<h1>IP_ARRAY</h1>' . var_export($this->ip_array, true) . '<h1>ADDITIONAL</h1>' . var_export($this->debug_data, true);
      }
      $replaces['{DEBUG}'] = isset($debug) ? $debug : '';
      foreach ($replaces as $place_holder => $replace) {
        $sfw_die_page = str_replace($place_holder, $replace, $sfw_die_page);
      }
      die($sfw_die_page);
    }
    die("IP BLACKLISTED. Blocked by SFW " . $result['ip']);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FirewallModule::$api_key protected property
FirewallModule::$db protected property
FirewallModule::$db_data_table_name protected property
FirewallModule::$db_log_table_name protected property
FirewallModule::$debug protected property
FirewallModule::$debug_data protected property
FirewallModule::$helper protected property
FirewallModule::$ip_array protected property
FirewallModule::$real_ip protected property *
FirewallModule::$test protected property *
FirewallModule::$test_ip protected property *
FirewallModule::ipAppendAdditional public function Configure and set additional properties: real_ip, test_ip, test
FirewallModule::setApiKey public function Set API KEY
FirewallModule::setDb public function Set specify CMS based DB instance
FirewallModule::setHelper public function Set specify CMS based Helper instance
FirewallModule::setIpArray public function Set visitor's IP
FirewallModule::setIsDebug public function Set is debug property.
FirewallModule::setLogTableName public function Set Log Table name
FirewallModule::__ public function This is a placeholder for WP translation function. For compatibility with any CMS.
SFW::$cookie_domain private property
SFW::$module_name public property Overrides FirewallModule::$module_name
SFW::$set_cookies private property
SFW::$sfw_counter private property
SFW::actionsForDenied public function @inheritdoc Overrides FirewallModule::actionsForDenied
SFW::actionsForPassed public function @inheritdoc Overrides FirewallModule::actionsForPassed
SFW::check public function * Use this method to execute main logic of the module. * * Overrides FirewallModule::check
SFW::update_log public function * Add entry to SFW log. * Writes to database. * *
SFW::_die public function @inheritdoc Overrides FirewallModule::_die
SFW::__construct public function FireWall_module constructor. Use this method to prepare any data for the module working. Overrides FirewallModule::__construct