<?php

/** Proxy Definitions **/
define('PROXY_STRING', 'deflate');
define('PROXY_CONNECTION', 'close');
define('PROXY_REMOTE_HOST', '.');
define('PROXY_KEEP', 'keep-alive');

class Security
{
    public function _antiProxy()
    {
        $ProxyEncryption = $_SERVER['HTTP_ACCEPT_ENCODING'];
        $ProxyConnection = $_SERVER['HTTP_CONNECTION'];
        $ProxyIpLookup   = $_SERVER['REMOTE_ADDR'];
        $ProxyRemoteHost = $_SERVER['REMOTE_HOST'];

        if ($ProxyRemoteHost == PROXY_REMOTE_HOST) {
            $Firewalls = new Firewall;
            $Firewalls->DenyRequest('Proxy #2');
        } elseif (Security::GetHostByAddress($ProxyIpLookup) == ".") {
            $Firewalls = new Firewall;
            $Firewalls->DenyRequest('Proxy #3');
        } elseif (strpos($ProxyConnection, PROXY_CONNECTION) !== false) {
            $Firewalls = new Firewall;
            $Firewalls->DenyRequest('Proxy #4');
        } else {
            return false;
        }
    }

    public static function GetHostByAddress($Address)
    {
        return gethostbyaddr($Address);
    }
}

class Firewall
{
    private $Link;
    private $Address;
    private $Date;
    private $NoExpression;
    private $NoFunction;
    private $NullByteUrl;

    public function __construct()
    {
        $this->Link = 'verify.php';
        $this->Address = $_SERVER['REMOTE_ADDR'];
        $this->Date = date('m/d/Y h:i:s A');

        // Expression array();
        $this->NoExpression = ["'", "--", ";", "<", "[", "&lt;", ">", "&gt;", "&quot;", "&#x27;", "%", "&#x2F;", "../", "./", "/*"];

        // Function array();
        $this->NoFunction   = ["request", "select", "declare", "insert", "update", "drop", "exec(", "execute(", "cast(", "char", "nchar", "varchar", "nvarchar", "substring", "sysobject", "iframe", "syscolumns"];

        $this->NullByteUrl = $_SERVER['QUERY_STRING']; // Query_string -> explode the url and $_GET variables
    }

    public function DenyRequest($_log)
    {
        $this->AddLog('security_' . date('m-d') . '.log', $_log);
        $this->Redirect($this->Link);
    }

    private function AddLog($File, $_log)
    {
        $FilePath = 'Sdoc/bloqx/logs/' . $File;
        $Open = fopen($FilePath, "a+");
        if ($Open) {
            fwrite($Open, $_log . "\t // \n");
            fclose($Open);
        } else {
            // Handle error
            error_log("Failed to open log file: " . $FilePath);
        }
    }

    private function Redirect($Link)
    {
        exit('<meta HTTP-EQUIV="REFRESH" content="0; url=' . $Link . '">');
    }

    public function _antiInjection()
    {
        // $_GET Function
        foreach ($_GET as $key => $value) {
            foreach ($this->NoFunction as $forbiddenFunction) {
                if (stripos($value, $forbiddenFunction) !== false) {
                    $this->DenyRequest('IP [' . $_SERVER['REMOTE_ADDR'] . '] ($_GET) Sql Injection String: [' . htmlspecialchars($value, ENT_QUOTES) . ' ]');
                    return;
                }
            }
        }

        // $_GET expression
        foreach ($_GET as $key => $value) {
            foreach ($this->NoExpression as $forbiddenExpression) {
                if (stripos($value, $forbiddenExpression) !== false) {
                    $this->DenyRequest('IP [' . $_SERVER['REMOTE_ADDR'] . '] ($_GET) Sql Injection String: [' . htmlspecialchars($value) . ' ]');
                    return;
                }
            }
        }

        // NullByte
        if (strpos($this->NullByteUrl, "\0") !== false || strpos($this->NullByteUrl, '%00') !== false) {
            $this->DenyRequest('IP [' . $_SERVER['REMOTE_ADDR'] . '] (nByte) Injection String: [ %00 ]');
        }
        if (strlen($this->NullByteUrl) > 155) {
            $this->DenyRequest('IP [' . $_SERVER['REMOTE_ADDR'] . '] Query string too long... Request denied.' . $_SERVER['QUERY_STRING']);
        }
    }
}

class Guard
{
    public static function _startGuard()
    {
        $Firewall = new Firewall;
        $Firewall->_antiInjection();
    }
}

Guard::_startGuard();
