Your IP : 216.73.217.11


Current Path : /home/poneycluc/www/plugins/system/bfnetwork/bfnetwork/
Upload File :
Current File : /home/poneycluc/www/plugins/system/bfnetwork/bfnetwork/bfAdmintools.php

<?php

/*
 * @package   bfNetwork
 * @copyright Copyright (C) 2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026 Blue Flame Digital Solutions Ltd. All rights reserved.
 * @license   GNU General Public License version 3 or later
 *
 * @see       https://mySites.guru/
 * @see       https://www.phil-taylor.com/
 *
 * @author    Phil Taylor / Blue Flame Digital Solutions Limited.
 *
 * bfNetwork is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * bfNetwork is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this package.  If not, see http://www.gnu.org/licenses/
 *
 * If you have any questions regarding this code, please contact phil@phil-taylor.com
 */

/*
 * Akeeba Admin Tools Professional integration: detect when Admin Tools' WAF has blocked the
 * mySites.guru worker/proxy IP, and clear that block so audits, snapshots, backups and updates
 * can reach the site again.
 *
 * Admin Tools auto-bans an IP after repeated "security exceptions". Because every mySites.guru
 * call to this site arrives from the same egress IP, the WAF can auto-ban us, after which every
 * remote call silently fails. This helper removes our IP from all of Admin Tools' block state and
 * adds it to the permanent allow-list so it is never auto-banned again.
 *
 * IP block state lives across these Admin Tools tables (real #__admintools_* tables, so the
 * connector's $db resolves #__ to the live prefix):
 *   ipblock          (id, ip, description)        - manual permanent block list
 *   ipautoban        (ip PK, reason, until)       - WAF auto-ban (the one that locks us out)
 *   ipautobanhistory (id, ip, reason, until)      - tally that drives re-banning
 *   ipallow          (id, ip, description)        - permanent allow-list (never auto-banned)
 *
 * Every query is wrapped so a missing/half-installed Admin Tools can never fatal the snapshot.
 *
 * If we have got here then we have already passed through decrypting the encrypted header and so
 * we are sure we are now secure and no one else can run the code below.
 */
final class bfAdmintools
{
    /**
     * Description stamped on the allow-list entry we add for the worker IP.
     */
    private const ALLOW_DESCRIPTION = 'mySites.guru management IP - auto allow-listed';

    /**
     * @var object
     */
    private $db;

    public function __construct($db)
    {
        $this->db = $db;
    }

    /**
     * Is the Admin Tools component installed and enabled on this site?
     */
    public function isInstalled(): bool
    {
        try {
            $this->db->setQuery(
                "SELECT COUNT(*) FROM #__extensions WHERE element = 'com_admintools' AND type = 'component' AND enabled = 1"
            );

            return (int) $this->db->loadResult() > 0;
        } catch (\Throwable $e) {
            return false;
        }
    }

    /**
     * Is the given IP currently blocked by Admin Tools? True if it appears in either the manual
     * block list or the WAF auto-ban list.
     */
    public function isIpBlocked(string $ip): bool
    {
        $ip = trim($ip);
        if ($ip === '') {
            return false;
        }

        $quoted = $this->db->quote($ip);

        foreach (['ipblock', 'ipautoban'] as $table) {
            try {
                $this->db->setQuery('SELECT COUNT(*) FROM #__admintools_' . $table . ' WHERE ip = ' . $quoted);
                if ((int) $this->db->loadResult() > 0) {
                    return true;
                }
            } catch (\Throwable $e) {
                // Table missing or unreadable - treat as not blocked for this table.
                continue;
            }
        }

        return false;
    }

    /**
     * Remove the given IP from every Admin Tools block table, then add it to the permanent
     * allow-list (idempotently) so it cannot be auto-banned again.
     *
     * @return array
     */
    public function unblockIp(string $ip): array
    {
        $ip = trim($ip);

        $result = [
            'ipblock'          => 0,
            'ipautoban'        => 0,
            'ipautobanhistory' => 0,
            'allowlisted'      => false,
            'ip'               => $ip,
        ];

        if ($ip === '') {
            return $result;
        }

        $quoted = $this->db->quote($ip);

        foreach (['ipblock', 'ipautoban', 'ipautobanhistory'] as $table) {
            try {
                $this->db->setQuery('DELETE FROM #__admintools_' . $table . ' WHERE ip = ' . $quoted);
                $this->db->execute();
                $result[$table] = (int) $this->db->getAffectedRows();
            } catch (\Throwable $e) {
                // Table missing - nothing to delete.
                continue;
            }
        }

        $result['allowlisted'] = $this->allowListIp($ip);

        return $result;
    }

    /**
     * Add the IP to the Admin Tools allow-list if it is not already there. Returns true when the
     * IP is present in the allow-list afterwards (whether we added it or it was already there).
     */
    private function allowListIp(string $ip): bool
    {
        $quoted = $this->db->quote($ip);

        try {
            $this->db->setQuery('SELECT COUNT(*) FROM #__admintools_ipallow WHERE ip = ' . $quoted);
            if ((int) $this->db->loadResult() > 0) {
                return true;
            }

            $this->db->setQuery(
                'INSERT INTO #__admintools_ipallow (ip, description) VALUES ('
                . $quoted . ', ' . $this->db->quote(self::ALLOW_DESCRIPTION) . ')'
            );
            $this->db->execute();

            return true;
        } catch (\Throwable $e) {
            return false;
        }
    }
}