WP Plugin

Plugin Structure

wp-content/plugins/wp-fort/

├── wp-fort.php # Main plugin file
├── readme.txt # WordPress.org description
├── uninstall.php # Clean uninstallation
├── LICENSE # GPL v2 or later

├── includes/
│ ├── class-wp-fort-core.php
│ ├── class-wp-fort-login-protection.php
│ ├── class-wp-fort-ip-manager.php
│ ├── class-wp-fort-security-logs.php
│ ├── class-wp-fort-firewall.php
│ ├── class-wp-fort-cloudflare.php
│ └── class-wp-fort-utilities.php

├── admin/
│ ├── class-wp-fort-admin.php
│ ├── css/
│ │ ├── admin.css
│ │ └── dashboard.css
│ ├── js/
│ │ ├── admin.js
│ │ └── charts.js
│ └── partials/
│ ├── dashboard.php
│ ├── login-security.php
│ ├── ip-restrictions.php
│ ├── firewall.php
│ ├── security-logs.php
│ ├── cloudflare.php
│ └── settings.php

├── assets/
│ ├── images/
│ │ ├── icon-128×128.png
│ │ ├── icon-256×256.png
│ │ └── banner-772×250.png
│ ├── css/
│ │ └── frontend.css
│ └── js/
│ └── frontend.js

├── templates/
│ ├── custom-login.php
│ └── security-lockout.php

└── languages/
├── wp-fort.pot
└── /[language-packs]/

Structural File Code

wp-fort/wp-fort.php

includes(); $this->init_components(); $this->register_hooks(); } private function includes() { require_once WP_FORT_PLUGIN_PATH . ‘includes/class-wp-fort-core.php’; require_once WP_FORT_PLUGIN_PATH . ‘includes/class-wp-fort-login-protection.php’; require_once WP_FORT_PLUGIN_PATH . ‘includes/class-wp-fort-ip-manager.php’; require_once WP_FORT_PLUGIN_PATH . ‘includes/class-wp-fort-security-logs.php’; require_once WP_FORT_PLUGIN_PATH . ‘includes/class-wp-fort-firewall.php’; require_once WP_FORT_PLUGIN_PATH . ‘includes/class-wp-fort-cloudflare.php’; require_once WP_FORT_PLUGIN_PATH . ‘includes/class-wp-fort-utilities.php’; if (is_admin()) { require_once WP_FORT_PLUGIN_PATH . ‘admin/class-wp-fort-admin.php’; } } private function init_components() { $this->core = new WP_Fort_Core(); $this->login_protection = new WP_Fort_Login_Protection(); $this->ip_manager = new WP_Fort_IP_Manager(); $this->security_logs = new WP_Fort_Security_Logs(); $this->firewall = new WP_Fort_Firewall(); $this->cloudflare = new WP_Fort_Cloudflare(); if (is_admin()) { $this->admin = new WP_Fort_Admin(); } } private function register_hooks() { register_activation_hook(__FILE__, array($this, ‘activate’)); register_deactivation_hook(__FILE__, array($this, ‘deactivate’)); add_action(‘plugins_loaded’, array($this, ‘load_textdomain’)); // Cloudflare AJAX handlers add_action(‘wp_ajax_wp_fort_test_cloudflare_connection’, array($this, ‘test_cloudflare_connection’)); add_action(‘wp_ajax_wp_fort_sync_cloudflare_rules’, array($this, ‘sync_cloudflare_rules’)); // Auto-sync blocked IPs to Cloudflare add_action(‘wp_fort_ip_blocked’, array($this, ‘sync_blocked_ip_to_cloudflare’), 10, 2); } public function activate() { // Initialize default options WP_Fort_Core::activate(); // Set default Cloudflare settings $default_settings = array( ‘cloudflare_enabled’ => 0, ‘cloudflare_email’ => ”, ‘cloudflare_api_key’ => ”, ‘cloudflare_zone_id’ => ”, ‘cloudflare_firewall_rules’ => 0, ‘cloudflare_threat_analytics’ => 0, ‘cloudflare_ddos_protection’ => 1 ); $current_settings = get_option(‘wp_fort_settings’, array()); $merged_settings = wp_parse_args($current_settings, $default_settings); update_option(‘wp_fort_settings’, $merged_settings); } public function deactivate() { // Cleanup temporary data WP_Fort_Core::deactivate(); // Clear any scheduled hooks wp_clear_scheduled_hook(‘wp_fort_cloudflare_sync’); } public function load_textdomain() { load_plugin_textdomain( ‘wp-fort’, false, dirname(plugin_basename(__FILE__)) . ‘/languages’ ); } /** * Test Cloudflare connection via AJAX */ public function test_cloudflare_connection() { // Verify nonce if (!wp_verify_nonce($_POST[‘nonce’], ‘wp_fort_cloudflare_test’)) { wp_send_json_error(‘Security check failed’); } // Check user capabilities if (!current_user_can(‘manage_options’)) { wp_send_json_error(‘Insufficient permissions’); } $result = $this->cloudflare->test_connection(); if ($result[‘success’]) { wp_send_json_success(array(‘message’ => $result[‘message’])); } else { wp_send_json_error($result[‘message’]); } } /** * Sync Cloudflare rules via AJAX */ public function sync_cloudflare_rules() { // Verify nonce if (!wp_verify_nonce($_POST[‘nonce’], ‘wp_fort_cloudflare_sync’)) { wp_send_json_error(‘Security check failed’); } // Check user capabilities if (!current_user_can(‘manage_options’)) { wp_send_json_error(‘Insufficient permissions’); } $result = $this->cloudflare->sync_existing_blocked_ips(); if ($result[‘success’]) { wp_send_json_success(array(‘message’ => $result[‘message’])); } else { wp_send_json_error($result[‘message’]); } } /** * Automatically sync blocked IPs to Cloudflare */ public function sync_blocked_ip_to_cloudflare($ip_address, $reason) { $options = get_option(‘wp_fort_settings’); if (isset($options[‘cloudflare_enabled’]) && $options[‘cloudflare_enabled’] && isset($options[‘cloudflare_firewall_rules’]) && $options[‘cloudflare_firewall_rules’]) { $this->cloudflare->create_firewall_rule($ip_address, ‘WP Fort Auto-block: ‘ . $reason); } } // Public access to components public function login_protection() { return $this->login_protection; } public function ip_manager() { return $this->ip_manager; } public function security_logs() { return $this->security_logs; } public function firewall() { return $this->firewall; } public function cloudflare() { return $this->cloudflare; } } // Initialize the plugin function wp_fort_init() { return WP_Fort_Plugin::get_instance(); } // Start the plugin add_action(‘plugins_loaded’, ‘wp_fort_init’); // Global helper functions if (!function_exists(‘wp_fort’)) { function wp_fort() { return WP_Fort_Plugin::get_instance(); } } /** * Cloudflare helper functions */ /** * Check if Cloudflare integration is enabled */ if (!function_exists(‘wp_fort_cloudflare_enabled’)) { function wp_fort_cloudflare_enabled() { $options = get_option(‘wp_fort_settings’); return isset($options[‘cloudflare_enabled’]) && $options[‘cloudflare_enabled’]; } } /** * Get Cloudflare instance */ if (!function_exists(‘wp_fort_cloudflare’)) { function wp_fort_cloudflare() { return wp_fort()->cloudflare(); } } /** * Test Cloudflare connection */ if (!function_exists(‘wp_fort_test_cloudflare_connection’)) { function wp_fort_test_cloudflare_connection() { return wp_fort()->cloudflare()->test_connection(); } } ?>

wp-fort/readme.txt

=== WP Fort ===
Contributors: brandanabia
Donate link: https://brandanabia.com
Tags: security, login protection, firewall, ip restriction, cloudflare, security logs, brute force protection
Requires at least: 5.8
Tested up to: 6.4
Stable tag: 1.0.0
Requires PHP: 7.4
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Ultimate WordPress security fortress with custom login protection, IP restrictions, security logging, and Cloudflare integration.

== Description ==

WP Fort is a comprehensive security solution that transforms your WordPress website into an impenetrable fortress. Developed by Brand Anabia, this plugin provides enterprise-level security features in an easy-to-use package.

= Key Features =

  • Custom Login URL Protection – Hide wp-login.php and use your own secret login URL
  • IP Address Restrictions – Allow only specific IP addresses to access admin area
  • Advanced Security Logging – Detailed logs of all login attempts with location data
  • Smart Firewall – Block suspicious requests and malicious traffic patterns
  • Cloudflare Integration – Enhanced security with Cloudflare firewall rules
  • Brute Force Protection – Automatic blocking after multiple failed attempts
  • Real-time Monitoring – Live security dashboard with threat alerts
  • Geo-location Tracking – See where login attempts are coming from worldwide

= Why WP Fort? =

  • Complete Security Suite – All security features in one plugin
  • Zero Performance Impact – Optimized code that doesn’t slow down your site
  • Easy Configuration – User-friendly dashboard with one-click setups
  • Regular Updates – Continuous security updates and feature enhancements
  • Professional Support – Backed by Brand Anabia development team

== Installation ==

  1. Upload wp-fort folder to the /wp-content/plugins/ directory
  2. Activate the plugin through the ‘Plugins’ menu in WordPress
  3. Go to WP Fort settings page to configure your security settings
  4. Set up your custom login URL and allowed IP addresses
  5. Enable additional security features as needed

== Frequently Asked Questions ==

= What makes WP Fort different from other security plugins? =

WP Fort provides a comprehensive approach with custom login URLs, IP restrictions, and Cloudflare integration in one package. Our focus is on prevention rather than just detection.

= Will this plugin slow down my website? =

No! WP Fort is optimized for performance and uses efficient coding practices to ensure zero impact on your site speed.

= Can I use WP Fort with other security plugins? =

While WP Fort is designed as a complete security solution, it can work alongside other plugins. We recommend testing compatibility.

== Changelog ==

= 1.0.0 =

  • Initial release
  • Custom login URL protection
  • IP address management
  • Security logging system
  • Basic firewall protection
  • Admin dashboard interface

== Upgrade Notice ==

= 1.0.0 =
Initial release of WP Fort security plugin.

== Screenshots ==

  1. Security Dashboard – Overview of security status and recent events
  2. Login Protection Settings – Configure custom login URL and IP restrictions
  3. Security Logs – Detailed view of all security events with filters
  4. Firewall Settings – Configure blocking rules and patterns
  5. Cloudflare Integration – Connect with Cloudflare for enhanced protection

== License ==

This plugin is licensed under the GPL v2 or later.

wp-fort/uninstall.php

<?php
/**

  • WP Fort Uninstaller
    • @package WP_Fort
  • @since 1.0.0
    */

// Prevent direct access
if (!defined(‘WP_UNINSTALL_PLUGIN’)) {
exit;
}

// Check if we should remove all data
$remove_data = get_option(‘wp_fort_remove_data_on_uninstall’, false);

if (!$remove_data) {
return;
}

global $wpdb;

// Remove options
delete_option(‘wp_fort_settings’);
delete_option(‘wp_fort_encryption_key’);
delete_option(‘wp_fort_remove_data_on_uninstall’);
delete_option(‘wp_fort_version’);

// Remove security logs table
$table_name = $wpdb->prefix . ‘wp_fort_security_logs’;
$wpdb->query(“DROP TABLE IF EXISTS $table_name”);

// Clear any scheduled events
wp_clear_scheduled_hook(‘wp_fort_cleanup_old_logs’);

// Remove transients
$wpdb->query(
“DELETE FROM $wpdb->options
WHERE option_name LIKE ‘%wp_fort_%’
OR option_name LIKE ‘%transient_wp_fort%’
OR option_name LIKE ‘%transient_timeout_wp_fort%'”
);

// Remove user meta if any
$wpdb->query(
“DELETE FROM $wpdb->usermeta
WHERE meta_key LIKE ‘wp_fort_%'”
);

wp-fort/LICENSE

GNU GENERAL PUBLIC LICENSE Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

                        Preamble

The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software–to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation’s software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.

We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

Also, for each author’s protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors’ reputations.

Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone’s free use or not licensed at all.

The precise terms and conditions for copying, distribution and
modification follow.

                GNU GENERAL PUBLIC LICENSE

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License applies to any program or other work which contains
    a notice placed by the copyright holder saying it may be distributed
    under the terms of this General Public License. The “Program”, below,
    refers to any such program or work, and a “work based on the Program”
    means either the Program or any derivative work under copyright law:
    that is to say, a work containing the Program or a portion of it,
    either verbatim or with modifications and/or translated into another
    language. (Hereinafter, translation is included without limitation in
    the term “modification”.) Each licensee is addressed as “you”.

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program’s
    source code as you receive it, in any medium, provided that you
    conspicuously and appropriately publish on each copy an appropriate
    copyright notice and disclaimer of warranty; keep intact all the
    notices that refer to this License and to the absence of any warranty;
    and give any other recipients of the Program a copy of this License
    along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  1. You may modify your copy or copies of the Program or any portion
    of it, thus forming a work based on the Program, and copy and
    distribute such modifications or work under the terms of Section 1
    above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License. c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License. (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  1. You may copy and distribute the Program (or a work based on it,
    under Section 2) in object code or executable form under the terms of
    Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing the source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or, c) Accompany it with the information you received as to the offer
    to distribute corresponding source code. (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  1. You may not copy, modify, sublicense, or distribute the Program
    except as expressly provided under this License. Any attempt
    otherwise to copy, modify, sublicense or distribute the Program is
    void, and will automatically terminate your rights under this License.
    However, parties who have received copies, or rights, from you under
    this License will not have their licenses terminated so long as such
    parties remain in full compliance.
  2. You are not required to accept this License, since you have not
    signed it. However, nothing else grants you permission to modify or
    distribute the Program or its derivative works. These actions are
    prohibited by law if you do not accept this License. Therefore, by
    modifying or distributing the Program (or any work based on the
    Program), you indicate your acceptance of this License to do so, and
    all its terms and conditions for copying, distributing or modifying
    the Program or works based on it.
  3. Each time you redistribute the Program (or any work based on the
    Program), the recipient automatically receives a license from the
    original licensor to copy, distribute or modify the Program subject to
    these terms and conditions. You may not impose any further
    restrictions on the recipients’ exercise of the rights granted herein.
    You are not responsible for enforcing compliance by third parties to
    this License.
  4. If, as a consequence of a court judgment or allegation of patent
    infringement or for any other reason (not limited to patent issues),
    conditions are imposed on you (whether by court order, agreement or
    otherwise) that contradict the conditions of this License, they do not
    excuse you from the conditions of this License. If you cannot
    distribute so as to satisfy simultaneously your obligations under this
    License and any other pertinent obligations, then as a consequence you
    may not distribute the Program at all. For example, if a patent
    license would not permit royalty-free redistribution of the Program by
    all those who receive copies directly or indirectly through you, then
    the only way you could satisfy both it and this License would be to
    refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  1. If the distribution and/or use of the Program is restricted in
    certain countries either by patents or by copyrighted interfaces, the
    original copyright holder who places the Program under this License
    may add an explicit geographical distribution limitation excluding
    those countries, so that distribution is permitted only in or among
    countries not thus excluded. In such case, this License incorporates
    the limitation as if written in the body of this License.
  2. The Free Software Foundation may publish revised and/or new versions
    of the General Public License from time to time. Such new versions will
    be similar in spirit to the present version, but may differ in detail to
    address new problems or concerns.

Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and “any
later version”, you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free
Software Foundation.

  1. If you wish to incorporate parts of the Program into other free
    programs whose distribution conditions are different, write to the author
    to ask for permission. For software which is copyrighted by the Free
    Software Foundation, write to the Free Software Foundation; we sometimes
    make exceptions for this. Our decision will be guided by the two goals
    of preserving the free status of all derivatives of our free software and
    of promoting the sharing and reuse of software generally. NO WARRANTY
  2. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
    PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
    REPAIR OR CORRECTION.
  3. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
    POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONSHow to Apply These Terms to Your New Programs</code></pre>If you develop a new program, and you want it to be of the greatest
    possible use to the public, the best way to achieve this is to make it
    free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest
    to attach them to the start of each source file to most effectively
    convey the exclusion of warranty; and each file should have at least
    the "copyright" line and a pointer to where the full notice is found.
    Copyright (C) This program 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 2 of the License, or
    (at your option) any later version. This program 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 program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

The hypothetical commands show w' andshow c’ should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than show w' andshow c’; they could even be
mouse-clicks or menu items–whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a “copyright disclaimer” for the program, if
necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision’ (which makes passes at compilers) written by James Hacker.

, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

wp-fort/ includes/

class-wp-fort-core.php

<?php
/**

  • WP Fort Core Security Class
    • @package WP_Fort
  • @since 1.0.0
    */

class WP_Fort_Core {

private static $instance = null;
private $options;

public function __construct() {
    $this->load_options();
    $this->init_hooks();
}

public static function get_instance() {
    if (null === self::$instance) {
        self::$instance = new self();
    }
    return self::$instance;
}

private function load_options() {
    $defaults = array(
        // Login Protection
        'login_protection_enabled' => true,
        'custom_login_slug' => 'secure-admin',
        'block_wp_login' => true,

        // IP Restrictions
        'ip_restriction_enabled' => false,
        'allowed_ips' => array(),
        'ip_whitelist' => array(),

        // Security Logging
        'logging_enabled' => true,
        'log_retention_days' => 30,
        'log_failed_logins' => true,
        'log_successful_logins' => true,

        // Firewall
        'firewall_enabled' => true,
        'block_suspicious_requests' => true,
        'prevent_php_execution' => true,

        // Brute Force Protection
        'brute_force_protection' => true,
        'max_login_attempts' => 5,
        'lockout_duration' => 30, // minutes

        // Cloudflare
        'cloudflare_enabled' => false,
        'cloudflare_api_key' => '',
        'cloudflare_email' => '',
        'cloudflare_zone_id' => '',

        // General Settings
        'disable_xmlrpc' => true,
        'hide_wp_version' => true,
        'disable_file_edit' => true,
    );

    $this->options = wp_parse_args(get_option('wp_fort_settings'), $defaults);
}

private function init_hooks() {
    add_action('init', array($this, 'security_headers'));
    add_action('wp_loaded', array($this, 'early_security_checks'));
    add_filter('rest_authentication_errors', array($this, 'rest_api_protection'));

    // WordPress hardening
    if ($this->options['disable_xmlrpc']) {
        add_filter('xmlrpc_enabled', '__return_false');
    }

    if ($this->options['hide_wp_version']) {
        remove_action('wp_head', 'wp_generator');
        add_filter('the_generator', '__return_empty_string');
    }

    // Only define DISALLOW_FILE_EDIT if not already defined and setting is enabled
    if ($this->options['disable_file_edit'] && !defined('DISALLOW_FILE_EDIT')) {
        define('DISALLOW_FILE_EDIT', true);
    }

    // Check if table exists and create if needed
    add_action('admin_init', array($this, 'check_table_exists'));
}

/**
 * Check if security logs table exists and create if needed
 */
public function check_table_exists() {
    global $wpdb;

    $table_name = $wpdb->prefix . 'wp_fort_security_logs';

    // Check if table exists
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        // Table doesn't exist, create it
        $this->create_logs_table();
    }
}

/**
 * Plugin activation
 */
public static function activate() {
    // Create default options
    if (!get_option('wp_fort_settings')) {
        $defaults = array(
            'login_protection_enabled' => true,
            'custom_login_slug' => 'secure-admin-' . wp_generate_password(8, false),
            'block_wp_login' => true,
            'logging_enabled' => true,
            'firewall_enabled' => true,
            'brute_force_protection' => true,
            'disable_xmlrpc' => true,
            'hide_wp_version' => true,
            'disable_file_edit' => true,
        );
        update_option('wp_fort_settings', $defaults);
    }

    // Create security logs table
    self::create_logs_table();

    // Add current IP to whitelist
    self::add_current_ip_to_whitelist();
}

/**
 * Plugin deactivation
 */
public static function deactivate() {
    // Clean up temporary data
    wp_clear_scheduled_hook('wp_fort_cleanup_old_logs');

    // Don't remove settings so configuration is preserved
}

/**
 * Create security logs table
 */
private static function create_logs_table() {
    global $wpdb;

    $table_name = $wpdb->prefix . 'wp_fort_security_logs';

    // Check if table already exists
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name) {
        return true;
    }

    $charset_collate = $wpdb->get_charset_collate();

    // Use a simpler SQL syntax that's more compatible
    $sql = "CREATE TABLE $table_name (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        timestamp datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
        event_type varchar(100) NOT NULL,
        ip_address varchar(45) NOT NULL,
        username varchar(255) DEFAULT '',
        user_agent text,
        request_url text,
        country varchar(100) DEFAULT '',
        region varchar(100) DEFAULT '',
        city varchar(100) DEFAULT '',
        details text,
        severity varchar(20) DEFAULT 'low',
        PRIMARY KEY (id),
        KEY event_type (event_type),
        KEY ip_address (ip_address),
        KEY timestamp (timestamp),
        KEY severity (severity)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

    $result = dbDelta($sql);

    // Check if table was created successfully
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        // Log error if table creation failed
        error_log('WP Fort: Failed to create security logs table');
        return false;
    }

    return true;
}

/**
 * Add current IP to whitelist during activation
 */
private static function add_current_ip_to_whitelist() {
    $current_ip = self::get_client_ip();
    $settings = get_option('wp_fort_settings', array());

    if (!isset($settings['allowed_ips'])) {
        $settings['allowed_ips'] = array();
    }

    if (!in_array($current_ip, $settings['allowed_ips'])) {
        $settings['allowed_ips'][] = $current_ip;
        update_option('wp_fort_settings', $settings);
    }
}

/**
 * Get client IP address
 */
public static function get_client_ip() {
    $ip_keys = array(
        'HTTP_X_REAL_IP',
        'HTTP_X_FORWARDED_FOR',
        'HTTP_CF_CONNECTING_IP', // Cloudflare
        'HTTP_CLIENT_IP',
        'REMOTE_ADDR'
    );

    foreach ($ip_keys as $key) {
        if (!empty($_SERVER[$key])) {
            $ip = trim($_SERVER[$key]);
            // Handle multiple IPs in X_FORWARDED_FOR
            if (strpos($ip, ',') !== false) {
                $ip_entries = explode(',', $ip);
                $ip = trim($ip_entries[0]);
            }
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $ip;
            }
        }
    }

    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

/**
 * Security headers
 */
public function security_headers() {
    if (!headers_sent()) {
        header('X-Content-Type-Options: nosniff');
        header('X-Frame-Options: SAMEORIGIN');
        header('X-XSS-Protection: 1; mode=block');

        // Strict Transport Security if SSL
        if (is_ssl()) {
            header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
        }

        // Referrer Policy
        header('Referrer-Policy: strict-origin-when-cross-origin');
    }
}

/**
 * Early security checks
 */
public function early_security_checks() {
    $this->block_suspicious_user_agents();
    $this->prevent_php_execution_in_uploads();
}

/**
 * Block suspicious user agents
 */
private function block_suspicious_user_agents() {
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
        return;
    }

    $user_agent = $_SERVER['HTTP_USER_AGENT'];
    $suspicious_patterns = array(
        'nmap', 'nikto', 'sqlmap', 'wpscan', 'acunetix', 
        'nessus', 'metasploit', 'havij', 'zap'
    );

    foreach ($suspicious_patterns as $pattern) {
        if (stripos($user_agent, $pattern) !== false) {
            $this->log_security_event('suspicious_user_agent', self::get_client_ip(), '', $user_agent);
            wp_die('Access denied.', 403);
        }
    }
}

/**
 * Prevent PHP execution in uploads
 */
private function prevent_php_execution_in_uploads() {
    // This will be handled by the firewall class
    // Keeping this as a placeholder for future implementation
}

/**
 * REST API protection
 */
public function rest_api_protection($result) {
    if (!is_user_logged_in() && $this->options['disable_xmlrpc']) {
        // Allow only specific public endpoints
        $allowed_endpoints = array(
            '/wp/v2/posts',
            '/wp/v2/pages',
            '/wp/v2/categories',
            '/wp/v2/tags'
        );

        $request_uri = $_SERVER['REQUEST_URI'] ?? '';
        $is_allowed = false;

        foreach ($allowed_endpoints as $endpoint) {
            if (strpos($request_uri, $endpoint) !== false) {
                $is_allowed = true;
                break;
            }
        }

        if (!$is_allowed) {
            return new WP_Error('rest_disabled', __('REST API access disabled.'), array('status' => 403));
        }
    }

    return $result;
}

/**
 * Log security events
 */
public function log_security_event($event_type, $ip_address, $username = '', $user_agent = '', $details = '') {
    if (!$this->options['logging_enabled']) {
        return;
    }

    global $wpdb;

    // Check if table exists before logging
    $table_name = $wpdb->prefix . 'wp_fort_security_logs';
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        return; // Table doesn't exist, skip logging
    }

    $geo_data = $this->get_geo_location($ip_address);

    $wpdb->insert(
        $table_name,
        array(
            'timestamp' => current_time('mysql'),
            'event_type' => $event_type,
            'ip_address' => $ip_address,
            'username' => $username,
            'user_agent' => $user_agent,
            'request_url' => $_SERVER['REQUEST_URI'] ?? '',
            'country' => $geo_data['country'] ?? '',
            'region' => $geo_data['region'] ?? '',
            'city' => $geo_data['city'] ?? '',
            'details' => is_array($details) ? json_encode($details) : $details,
            'severity' => $this->get_event_severity($event_type)
        ),
        array('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')
    );
}

/**
 * Get geo location data
 */
private function get_geo_location($ip_address) {
    // Simple IP geolocation - can be enhanced with paid services
    if ($ip_address === '127.0.0.1' || strpos($ip_address, '192.168.') === 0) {
        return array('country' => 'Local', 'region' => 'Internal', 'city' => 'Local Network');
    }

    // Free IP geolocation using ipapi.co
    $transient_key = 'wp_fort_geo_' . md5($ip_address);
    $geo_data = get_transient($transient_key);

    if ($geo_data === false) {
        $response = wp_remote_get('http://ipapi.co/' . $ip_address . '/json/');

        if (!is_wp_error($response) && $response['response']['code'] === 200) {
            $data = json_decode($response['body'], true);
            $geo_data = array(
                'country' => $data['country_name'] ?? 'Unknown',
                'region' => $data['region'] ?? 'Unknown',
                'city' => $data['city'] ?? 'Unknown'
            );
            set_transient($transient_key, $geo_data, WEEK_IN_SECONDS);
        } else {
            $geo_data = array('country' => 'Unknown', 'region' => 'Unknown', 'city' => 'Unknown');
        }
    }

    return $geo_data;
}

/**
 * Get event severity level
 */
private function get_event_severity($event_type) {
    $severity_map = array(
        'login_success' => 'low',
        'login_failed' => 'medium',
        'ip_blocked' => 'high',
        'brute_force_detected' => 'critical',
        'suspicious_request' => 'high',
        'file_change_detected' => 'high'
    );

    return $severity_map[$event_type] ?? 'low';
}

/**
 * Get plugin options
 */
public function get_options() {
    return $this->options;
}

/**
 * Update plugin options
 */
public function update_options($new_options) {
    $this->options = wp_parse_args($new_options, $this->options);
    update_option('wp_fort_settings', $this->options);
}

/**
 * Check if security logs table exists
 */
public function table_exists() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wp_fort_security_logs';
    return $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name;
}

}


class-wp-fort-login-protection.php

<?php
/**

  • WP Fort Login Protection Class
    • @package WP_Fort
  • @since 1.0.0
    */

class WP_Fort_Login_Protection {

private $core;
private $options;
private $login_attempts = array();

public function __construct() {
    $this->core = WP_Fort_Core::get_instance();
    $this->options = $this->core->get_options();

    $this->init_hooks();
}

private function init_hooks() {
    // Early hooks for login protection
    add_action('init', array($this, 'check_login_access'), 1);
    add_action('login_init', array($this, 'handle_custom_login'));

    // Login attempt tracking
    add_action('wp_login_failed', array($this, 'track_login_failure'));
    add_action('wp_login', array($this, 'track_login_success'), 10, 2);

    // Security headers on login page
    add_action('login_head', array($this, 'add_login_security_headers'));

    // Hide login errors
    add_filter('login_errors', array($this, 'hide_login_errors'));

    // Limit login attempts
    add_filter('authenticate', array($this, 'check_login_attempts'), 30, 3);
}

/**
 * Check login access and block wp-login.php if enabled
 */
public function check_login_access() {
    // Only proceed if we're accessing login-related URLs
    if (!$this->is_login_request()) {
        return;
    }

    $request_uri = $_SERVER['REQUEST_URI'] ?? '';
    $custom_slug = $this->options['custom_login_slug'] ?? '';

    // Block wp-login.php if custom URL is enabled and block setting is on
    if ($this->options['login_protection_enabled'] && 
        $this->options['block_wp_login'] && 
        strpos($request_uri, 'wp-login.php') !== false) {

        // Allow access only if it's our custom login URL
        if (empty($custom_slug) || strpos($request_uri, $custom_slug) === false) {
            $this->handle_blocked_login_access();
        }
    }
}

/**
 * Handle custom login URL
 */
public function handle_custom_login() {
    if (!$this->options['login_protection_enabled'] || empty($this->options['custom_login_slug'])) {
        return;
    }

    $request_uri = $_SERVER['REQUEST_URI'] ?? '';
    $custom_slug = $this->options['custom_login_slug'];

    // Check if we're accessing the custom login URL
    $is_custom_login = strpos($request_uri, $custom_slug) !== false;

    if (!$is_custom_login && $this->options['block_wp_login']) {
        $this->handle_blocked_login_access();
    }

    // If it's custom login, ensure proper handling
    if ($is_custom_login) {
        $this->custom_login_processing();
    }
}

/**
 * Process custom login URL access
 */
private function custom_login_processing() {
    // Add security checks for custom login
    $this->check_brute_force_protection();
    $this->check_ip_restrictions();
}

/**
 * Handle blocked login access
 */
private function handle_blocked_login_access() {
    $ip = WP_Fort_Core::get_client_ip();
    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';

    // Log the blocked attempt
    $this->core->log_security_event(
        'login_blocked', 
        $ip, 
        '', 
        $user_agent,
        array(
            'reason' => 'direct_wp_login_access',
            'request_uri' => $_SERVER['REQUEST_URI'] ?? ''
        )
    );

    // Show 404 or redirect
    if (wp_redirect(home_url('404'))) {
        exit;
    } else {
        status_header(404);
        nocache_headers();
        include get_404_template();
        exit;
    }
}

/**
 * Check if current request is login-related
 */
private function is_login_request() {
    $request_uri = $_SERVER['REQUEST_URI'] ?? '';

    return strpos($request_uri, 'wp-login.php') !== false ||
           strpos($request_uri, 'wp-signup.php') !== false ||
           strpos($request_uri, $this->options['custom_login_slug'] ?? '') !== false;
}

/**
 * Track failed login attempts
 */
public function track_login_failure($username) {
    if (!$this->options['log_failed_logins']) {
        return;
    }

    $ip = WP_Fort_Core::get_client_ip();
    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';

    $this->core->log_security_event(
        'login_failed',
        $ip,
        $username,
        $user_agent,
        array(
            'reason' => 'invalid_credentials',
            'timestamp' => current_time('mysql')
        )
    );

    $this->increment_login_attempts($ip);

    // Check if we should block this IP
    $this->check_brute_force_protection($ip);
}

/**
 * Track successful logins
 */
public function track_login_success($username, $user) {
    if (!$this->options['log_successful_logins']) {
        return;
    }

    // Only log admin/super admin logins
    if (!current_user_can('manage_options')) {
        return;
    }

    $ip = WP_Fort_Core::get_client_ip();
    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';

    $this->core->log_security_event(
        'login_success',
        $ip,
        $username,
        $user_agent,
        array(
            'user_id' => $user->ID,
            'roles' => $user->roles,
            'timestamp' => current_time('mysql')
        )
    );

    // Reset login attempts on successful login
    $this->reset_login_attempts($ip);
}

/**
 * Increment login attempts for IP
 */
private function increment_login_attempts($ip) {
    $transient_key = 'wp_fort_login_attempts_' . md5($ip);
    $attempts = get_transient($transient_key) ?: 0;
    $attempts++;

    set_transient($transient_key, $attempts, 15 * MINUTE_IN_SECONDS);
}

/**
 * Reset login attempts for IP
 */
private function reset_login_attempts($ip) {
    $transient_key = 'wp_fort_login_attempts_' . md5($ip);
    delete_transient($transient_key);
}

/**
 * Get login attempts for IP
 */
private function get_login_attempts($ip) {
    $transient_key = 'wp_fort_login_attempts_' . md5($ip);
    return get_transient($transient_key) ?: 0;
}

/**
 * Check brute force protection
 */
private function check_brute_force_protection($ip = null) {
    if (!$this->options['brute_force_protection']) {
        return;
    }

    $ip = $ip ?: WP_Fort_Core::get_client_ip();
    $attempts = $this->get_login_attempts($ip);
    $max_attempts = $this->options['max_login_attempts'] ?? 5;

    if ($attempts >= $max_attempts) {
        $this->handle_brute_force_detected($ip, $attempts);
    }
}

/**
 * Handle detected brute force attack
 */
private function handle_brute_force_detected($ip, $attempts) {
    // Log the brute force attempt
    $this->core->log_security_event(
        'brute_force_detected',
        $ip,
        '',
        $_SERVER['HTTP_USER_AGENT'] ?? '',
        array(
            'attempts' => $attempts,
            'max_attempts' => $this->options['max_login_attempts'] ?? 5,
            'timestamp' => current_time('mysql')
        )
    );

    // Block the IP temporarily
    $block_duration = ($this->options['lockout_duration'] ?? 30) * MINUTE_IN_SECONDS;
    $block_key = 'wp_fort_ip_blocked_' . md5($ip);
    set_transient($block_key, true, $block_duration);

    // Slow down responses
    sleep(min($attempts - $this->options['max_login_attempts'] + 1, 10));

    // Show error message
    wp_die(
        __('Too many login attempts. Please try again later.', 'wp-fort'),
        __('Login Blocked', 'wp-fort'),
        array('response' => 429)
    );
}

/**
 * Check login attempts during authentication
 */
public function check_login_attempts($user, $username, $password) {
    if (!$this->options['brute_force_protection']) {
        return $user;
    }

    $ip = WP_Fort_Core::get_client_ip();
    $block_key = 'wp_fort_ip_blocked_' . md5($ip);

    // Check if IP is temporarily blocked
    if (get_transient($block_key)) {
        return new WP_Error(
            'ip_blocked',
            __('Too many login attempts. Please try again later.', 'wp-fort')
        );
    }

    return $user;
}

/**
 * Check IP restrictions for login
 */
private function check_ip_restrictions() {
    if (!$this->options['ip_restriction_enabled'] || empty($this->options['allowed_ips'])) {
        return;
    }

    $current_ip = WP_Fort_Core::get_client_ip();
    $allowed_ips = $this->options['allowed_ips'];

    if (!in_array($current_ip, $allowed_ips)) {
        $this->handle_ip_restriction_violation($current_ip);
    }
}

/**
 * Handle IP restriction violation
 */
private function handle_ip_restriction_violation($ip) {
    $this->core->log_security_event(
        'ip_restriction_violation',
        $ip,
        '',
        $_SERVER['HTTP_USER_AGENT'] ?? '',
        array(
            'reason' => 'ip_not_in_whitelist',
            'allowed_ips' => $this->options['allowed_ips'],
            'timestamp' => current_time('mysql')
        )
    );

    wp_die(
        __('Access denied. Your IP address is not authorized to access this page.', 'wp-fort'),
        __('Access Denied', 'wp-fort'),
        array('response' => 403)
    );
}

/**
 * Add security headers to login page
 */
public function add_login_security_headers() {
    if (!headers_sent()) {
        header('X-Frame-Options: SAMEORIGIN');
        header('X-Content-Type-Options: nosniff');
        header('X-XSS-Protection: 1; mode=block');
    }
}

/**
 * Hide login errors to prevent username enumeration
 */
public function hide_login_errors($error) {
    if (in_array($error, array(
        __('<strong>Error</strong>: The username or password you entered is incorrect.'),
        __('<strong>Error</strong>: Invalid username.'),
        __('<strong>Error</strong>: The password you entered for the username %s is incorrect.')
    ), true)) {
        return __('<strong>Error</strong>: Invalid login credentials.');
    }

    return $error;
}

/**
 * Get custom login URL
 */
public function get_custom_login_url() {
    if (!$this->options['login_protection_enabled'] || empty($this->options['custom_login_slug'])) {
        return wp_login_url();
    }

    return home_url($this->options['custom_login_slug']);
}

/**
 * Validate custom login slug
 */
public function validate_custom_slug($slug) {
    // Check if slug is valid
    if (empty($slug) || !preg_match('/^[a-z0-9_-]+$/', $slug)) {
        return false;
    }

    // Check if slug conflicts with existing routes
    $reserved_slugs = array(
        'admin', 'wp-admin', 'wp-login', 'login', 'dashboard',
        'feed', 'comments', 'search', 'author', 'category'
    );

    if (in_array($slug, $reserved_slugs)) {
        return false;
    }

    return true;
}

}


class-wp-fort-ip-manager.php

<?php
/**

  • WP Fort IP Manager Class
    • @package WP_Fort
  • @since 1.0.0
    */

class WP_Fort_IP_Manager {

private $core;
private $options;

public function __construct() {
    $this->core = WP_Fort_Core::get_instance();
    $this->options = $this->core->get_options();

    $this->init_hooks();
}

private function init_hooks() {
    // IP restriction checks
    add_action('admin_init', array($this, 'check_admin_ip_restriction'));

    // REST API IP restrictions
    add_filter('rest_authentication_errors', array($this, 'check_rest_api_ip_restriction'));
}

/**
 * Check IP restrictions for admin area
 */
public function check_admin_ip_restriction() {
    // Skip for AJAX requests
    if (wp_doing_ajax()) {
        return;
    }

    // Skip if IP restriction is disabled
    if (!$this->options['ip_restriction_enabled'] || empty($this->options['allowed_ips'])) {
        return;
    }

    // Skip for users who can manage options (admins)
    if (current_user_can('manage_options')) {
        return;
    }

    $current_ip = WP_Fort_Core::get_client_ip();
    $allowed_ips = $this->options['allowed_ips'];

    if (!$this->is_ip_allowed($current_ip, $allowed_ips)) {
        $this->handle_admin_ip_restriction($current_ip);
    }
}

/**
 * Check IP restrictions for REST API
 */
public function check_rest_api_ip_restriction($result) {
    if (!$this->options['ip_restriction_enabled'] || empty($this->options['allowed_ips'])) {
        return $result;
    }

    // Skip if already authenticated
    if (is_user_logged_in()) {
        return $result;
    }

    $current_ip = WP_Fort_Core::get_client_ip();
    $allowed_ips = $this->options['allowed_ips'];

    if (!$this->is_ip_allowed($current_ip, $allowed_ips)) {
        return new WP_Error(
            'rest_ip_restricted',
            __('Access denied. Your IP address is not authorized.', 'wp-fort'),
            array('status' => 403)
        );
    }

    return $result;
}

/**
 * Check if IP is allowed
 */
public function is_ip_allowed($ip, $allowed_ips = null) {
    if ($allowed_ips === null) {
        $allowed_ips = $this->options['allowed_ips'] ?? array();
    }

    // Always allow localhost
    if ($ip === '127.0.0.1' || $ip === '::1') {
        return true;
    }

    foreach ($allowed_ips as $allowed_ip) {
        if ($this->check_ip_match($ip, $allowed_ip)) {
            return true;
        }
    }

    return false;
}

/**
 * Check if IP matches pattern (supports CIDR notation)
 */
private function check_ip_match($ip, $pattern) {
    // Exact match
    if ($ip === $pattern) {
        return true;
    }

    // CIDR notation match
    if (strpos($pattern, '/') !== false) {
        return $this->check_cidr_match($ip, $pattern);
    }

    // Wildcard match (e.g., 192.168.*)
    if (strpos($pattern, '*') !== false) {
        return $this->check_wildcard_match($ip, $pattern);
    }

    return false;
}

/**
 * Check CIDR notation match
 */
private function check_cidr_match($ip, $cidr) {
    list($subnet, $bits) = explode('/', $cidr);

    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
        return $this->check_ipv4_cidr($ip, $subnet, $bits);
    }

    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
        return $this->check_ipv6_cidr($ip, $subnet, $bits);
    }

    return false;
}

/**
 * Check IPv4 CIDR match
 */
private function check_ipv4_cidr($ip, $subnet, $bits) {
    $ip = ip2long($ip);
    $subnet = ip2long($subnet);
    $mask = -1 << (32 - $bits);

    return ($ip & $mask) === ($subnet & $mask);
}

/**
 * Check IPv6 CIDR match
 */
private function check_ipv6_cidr($ip, $subnet, $bits) {
    // Simplified IPv6 CIDR check
    $ip_bin = inet_pton($ip);
    $subnet_bin = inet_pton($subnet);

    // Compare the first $bits bits
    $bytes = intval($bits / 8);
    $bits_remain = $bits % 8;

    // Compare full bytes
    if (strncmp($ip_bin, $subnet_bin, $bytes) !== 0) {
        return false;
    }

    // Compare remaining bits
    if ($bits_remain > 0) {
        $ip_byte = ord($ip_bin[$bytes]);
        $subnet_byte = ord($subnet_bin[$bytes]);
        $mask = 0xFF << (8 - $bits_remain);

        return ($ip_byte & $mask) === ($subnet_byte & $mask);
    }

    return true;
}

/**
 * Check wildcard match
 */
private function check_wildcard_match($ip, $pattern) {
    $pattern = preg_quote($pattern, '/');
    $pattern = str_replace('\*', '.*', $pattern);
    $pattern = '/^' . $pattern . '$/';

    return preg_match($pattern, $ip) === 1;
}

/**
 * Handle admin IP restriction violation
 */
private function handle_admin_ip_restriction($ip) {
    $this->core->log_security_event(
        'admin_ip_restriction_violation',
        $ip,
        is_user_logged_in() ? wp_get_current_user()->user_login : '',
        $_SERVER['HTTP_USER_AGENT'] ?? '',
        array(
            'reason' => 'ip_not_in_admin_whitelist',
            'allowed_ips' => $this->options['allowed_ips'],
            'timestamp' => current_time('mysql')
        )
    );

    wp_die(
        __('Access denied. Your IP address is not authorized to access the admin area.', 'wp-fort'),
        __('Access Denied', 'wp-fort'),
        array('response' => 403)
    );
}

/**
 * Add IP to whitelist
 */
public function add_ip($ip) {
    if (!filter_var($ip, FILTER_VALIDATE_IP)) {
        return new WP_Error('invalid_ip', __('Invalid IP address.', 'wp-fort'));
    }

    $options = $this->core->get_options();

    if (!in_array($ip, $options['allowed_ips'])) {
        $options['allowed_ips'][] = $ip;
        $this->core->update_options($options);

        return true;
    }

    return new WP_Error('ip_exists', __('IP address already in whitelist.', 'wp-fort'));
}

/**
 * Remove IP from whitelist
 */
public function remove_ip($ip) {
    $options = $this->core->get_options();

    if (($key = array_search($ip, $options['allowed_ips'])) !== false) {
        unset($options['allowed_ips'][$key]);
        $options['allowed_ips'] = array_values($options['allowed_ips']);
        $this->core->update_options($options);

        return true;
    }

    return new WP_Error('ip_not_found', __('IP address not found in whitelist.', 'wp-fort'));
}

/**
 * Get all whitelisted IPs
 */
public function get_whitelisted_ips() {
    return $this->options['allowed_ips'] ?? array();
}

/**
 * Validate IP address
 */
public function validate_ip($ip) {
    return filter_var($ip, FILTER_VALIDATE_IP) !== false;
}

/**
 * Get IP information
 */
public function get_ip_info($ip) {
    $info = array(
        'ip' => $ip,
        'type' => filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 'IPv4' : 
                 (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? 'IPv6' : 'Invalid'),
        'is_private' => $this->is_private_ip($ip),
        'is_whitelisted' => $this->is_ip_allowed($ip)
    );

    return $info;
}

/**
 * Check if IP is private
 */
private function is_private_ip($ip) {
    $private_ranges = array(
        '10.0.0.0/8',
        '172.16.0.0/12', 
        '192.168.0.0/16',
        '127.0.0.0/8',
        '::1/128',
        'fc00::/7'
    );

    foreach ($private_ranges as $range) {
        if ($this->check_cidr_match($ip, $range)) {
            return true;
        }
    }

    return false;
}

/**
 * Get IP reputation (placeholder for future integration)
 */
public function get_ip_reputation($ip) {
    // This could integrate with services like AbuseIPDB, IPQualityScore, etc.
    return array(
        'score' => 0,
        'abuse_confidence' => 0,
        'is_malicious' => false,
        'threat_types' => array()
    );
}

}

class-wp-fort-security-logs.php

<?php
/**

  • WP Fort Security Logs Class
    • @package WP_Fort
  • @since 1.0.0
    */

class WP_Fort_Security_Logs {

private $core;
private $options;

public function __construct() {
    $this->core = WP_Fort_Core::get_instance();
    $this->options = $this->core->get_options();

    $this->init_hooks();
}

private function init_hooks() {
    // Schedule log cleanup
    add_action('wp_fort_cleanup_old_logs', array($this, 'cleanup_old_logs'));

    // Initialize scheduler
    add_action('init', array($this, 'init_scheduler'));
}

/**
 * Check if security logs table exists
 */
private function table_exists() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wp_fort_security_logs';
    return $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name;
}

/**
 * Initialize scheduler for log cleanup
 */
public function init_scheduler() {
    if (!wp_next_scheduled('wp_fort_cleanup_old_logs')) {
        wp_schedule_event(time(), 'daily', 'wp_fort_cleanup_old_logs');
    }
}

/**
 * Log security event
 */
public function log_event($event_type, $ip_address, $username = '', $user_agent = '', $details = '', $severity = 'low') {
    if (!$this->options['logging_enabled'] || !$this->table_exists()) {
        return false;
    }

    global $wpdb;

    $geo_data = $this->get_geo_location($ip_address);

    $result = $wpdb->insert(
        $wpdb->prefix . 'wp_fort_security_logs',
        array(
            'timestamp' => current_time('mysql'),
            'event_type' => $event_type,
            'ip_address' => $ip_address,
            'username' => $username,
            'user_agent' => $user_agent,
            'request_url' => $_SERVER['REQUEST_URI'] ?? '',
            'country' => $geo_data['country'] ?? '',
            'region' => $geo_data['region'] ?? '',
            'city' => $geo_data['city'] ?? '',
            'details' => is_array($details) ? wp_json_encode($details) : $details,
            'severity' => $severity
        ),
        array('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')
    );

    return $result !== false;
}

/**
 * Get security logs with pagination
 */
public function get_logs($args = array()) {
    global $wpdb;

    // Return empty results if table doesn't exist
    if (!$this->table_exists()) {
        return array(
            'logs' => array(),
            'total' => 0,
            'total_pages' => 0,
            'current_page' => $args['page'] ?? 1
        );
    }

    $defaults = array(
        'page' => 1,
        'per_page' => 20,
        'event_type' => '',
        'severity' => '',
        'ip_address' => '',
        'date_from' => '',
        'date_to' => '',
        'orderby' => 'timestamp',
        'order' => 'DESC'
    );

    $args = wp_parse_args($args, $defaults);

    $where = array();
    $prepare_args = array();

    // Build WHERE clause
    if (!empty($args['event_type'])) {
        $where[] = 'event_type = %s';
        $prepare_args[] = $args['event_type'];
    }

    if (!empty($args['severity'])) {
        $where[] = 'severity = %s';
        $prepare_args[] = $args['severity'];
    }

    if (!empty($args['ip_address'])) {
        $where[] = 'ip_address = %s';
        $prepare_args[] = $args['ip_address'];
    }

    if (!empty($args['date_from'])) {
        $where[] = 'timestamp >= %s';
        $prepare_args[] = $args['date_from'];
    }

    if (!empty($args['date_to'])) {
        $where[] = 'timestamp <= %s';
        $prepare_args[] = $args['date_to'];
    }

    $where_sql = '';
    if (!empty($where)) {
        $where_sql = 'WHERE ' . implode(' AND ', $where);
    }

    // Build ORDER BY clause
    $orderby = in_array($args['orderby'], array('timestamp', 'event_type', 'ip_address', 'severity')) ? 
               $args['orderby'] : 'timestamp';
    $order = strtoupper($args['order']) === 'ASC' ? 'ASC' : 'DESC';
    $order_sql = "ORDER BY {$orderby} {$order}";

    // Calculate offset
    $offset = ($args['page'] - 1) * $args['per_page'];

    // Get logs
    $logs = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}wp_fort_security_logs 
             {$where_sql} 
             {$order_sql} 
             LIMIT %d OFFSET %d",
            array_merge($prepare_args, array($args['per_page'], $offset))
        ),
        ARRAY_A
    );

    // Get total count
    $total = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}wp_fort_security_logs {$where_sql}",
            $prepare_args
        )
    );

    return array(
        'logs' => $logs,
        'total' => $total,
        'total_pages' => ceil($total / $args['per_page']),
        'current_page' => $args['page']
    );
}

/**
 * Get log statistics
 */
public function get_statistics($period = '30 days') {
    global $wpdb;

    // Return empty stats if table doesn't exist
    if (!$this->table_exists()) {
        return array(
            'total_events' => 0,
            'events_by_type' => array(),
            'events_by_severity' => array(),
            'top_ips' => array(),
            'events_timeline' => array()
        );
    }

    $date_cutoff = date('Y-m-d H:i:s', strtotime('-' . $period));

    $stats = array(
        'total_events' => 0,
        'events_by_type' => array(),
        'events_by_severity' => array(),
        'top_ips' => array(),
        'events_timeline' => array()
    );

    // Total events
    $stats['total_events'] = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE timestamp >= %s",
            $date_cutoff
        )
    );

    // Events by type
    $events_by_type = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT event_type, COUNT(*) as count 
             FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE timestamp >= %s 
             GROUP BY event_type 
             ORDER BY count DESC",
            $date_cutoff
        ),
        ARRAY_A
    );

    foreach ($events_by_type as $event) {
        $stats['events_by_type'][$event['event_type']] = $event['count'];
    }

    // Events by severity
    $events_by_severity = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT severity, COUNT(*) as count 
             FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE timestamp >= %s 
             GROUP BY severity",
            $date_cutoff
        ),
        ARRAY_A
    );

    foreach ($events_by_severity as $severity) {
        $stats['events_by_severity'][$severity['severity']] = $severity['count'];
    }

    // Top IPs
    $top_ips = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT ip_address, COUNT(*) as count 
             FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE timestamp >= %s 
             GROUP BY ip_address 
             ORDER BY count DESC 
             LIMIT 10",
            $date_cutoff
        ),
        ARRAY_A
    );

    foreach ($top_ips as $ip) {
        $stats['top_ips'][$ip['ip_address']] = $ip['count'];
    }

    // Events timeline (last 7 days)
    $timeline = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT DATE(timestamp) as date, COUNT(*) as count 
             FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE timestamp >= %s 
             GROUP BY DATE(timestamp) 
             ORDER BY date DESC 
             LIMIT 7",
            date('Y-m-d H:i:s', strtotime('-7 days'))
        ),
        ARRAY_A
    );

    foreach ($timeline as $day) {
        $stats['events_timeline'][$day['date']] = $day['count'];
    }

    return $stats;
}

/**
 * Cleanup old logs
 */
public function cleanup_old_logs() {
    global $wpdb;

    if (!$this->table_exists()) {
        return 0;
    }

    $retention_days = $this->options['log_retention_days'] ?? 30;
    $cutoff_date = date('Y-m-d H:i:s', strtotime('-' . $retention_days . ' days'));

    $deleted = $wpdb->query(
        $wpdb->prepare(
            "DELETE FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE timestamp < %s",
            $cutoff_date
        )
    );

    return $deleted;
}

/**
 * Clear all logs
 */
public function clear_all_logs() {
    global $wpdb;

    if (!$this->table_exists()) {
        return false;
    }

    $result = $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}wp_fort_security_logs");

    return $result !== false;
}

/**
 * Export logs to CSV
 */
public function export_logs($args = array()) {
    $logs_data = $this->get_logs(array_merge($args, array('per_page' => -1)));
    $logs = $logs_data['logs'];

    $filename = 'wp-fort-security-logs-' . date('Y-m-d-H-i-s') . '.csv';

    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="' . $filename . '"');

    $output = fopen('php://output', 'w');

    // Headers
    fputcsv($output, array(
        'Timestamp',
        'Event Type',
        'IP Address',
        'Username',
        'Country',
        'Region', 
        'City',
        'Severity',
        'User Agent',
        'Request URL',
        'Details'
    ));

    // Data
    foreach ($logs as $log) {
        fputcsv($output, array(
            $log['timestamp'],
            $log['event_type'],
            $log['ip_address'],
            $log['username'],
            $log['country'],
            $log['region'],
            $log['city'],
            $log['severity'],
            $log['user_agent'],
            $log['request_url'],
            $log['details']
        ));
    }

    fclose($output);
    exit;
}

/**
 * Get geo location for IP
 */
private function get_geo_location($ip_address) {
    // Use the core method
    return $this->core->get_geo_location($ip_address);
}

/**
 * Get event types
 */
public function get_event_types() {
    global $wpdb;

    if (!$this->table_exists()) {
        return array();
    }

    $event_types = $wpdb->get_col(
        "SELECT DISTINCT event_type FROM {$wpdb->prefix}wp_fort_security_logs ORDER BY event_type"
    );

    return $event_types;
}

/**
 * Get log count by severity
 */
public function get_severity_counts() {
    global $wpdb;

    if (!$this->table_exists()) {
        return array(
            'critical' => 0,
            'high' => 0,
            'medium' => 0,
            'low' => 0
        );
    }

    $counts = $wpdb->get_results(
        "SELECT severity, COUNT(*) as count 
         FROM {$wpdb->prefix}wp_fort_security_logs 
         GROUP BY severity",
        ARRAY_A
    );

    $result = array(
        'critical' => 0,
        'high' => 0,
        'medium' => 0,
        'low' => 0
    );

    foreach ($counts as $count) {
        $result[$count['severity']] = $count['count'];
    }

    return $result;
}

/**
 * Get recent security events
 */
public function get_recent_events($limit = 10) {
    global $wpdb;

    if (!$this->table_exists()) {
        return array();
    }

    $events = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}wp_fort_security_logs 
             ORDER BY timestamp DESC 
             LIMIT %d",
            $limit
        ),
        ARRAY_A
    );

    return $events;
}

/**
 * Get events count by type
 */
public function get_events_count_by_type($event_type) {
    global $wpdb;

    if (!$this->table_exists()) {
        return 0;
    }

    $count = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE event_type = %s",
            $event_type
        )
    );

    return $count ?: 0;
}

/**
 * Get today's events count
 */
public function get_todays_events_count() {
    global $wpdb;

    if (!$this->table_exists()) {
        return 0;
    }

    $count = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE DATE(timestamp) = %s",
            current_time('mysql')
        )
    );

    return $count ?: 0;
}

}

class-wp-fort-firewall.php

<?php
/**

  • WP Fort Firewall Class
    • @package WP_Fort
  • @since 1.0.0
    */

class WP_Fort_Firewall {

private $core;
private $options;
private $blocked_ips = array();

public function __construct() {
    $this->core = WP_Fort_Core::get_instance();
    $this->options = $this->core->get_options();

    $this->init_hooks();
    $this->load_blocked_ips();
}

private function init_hooks() {
    // Early firewall checks
    add_action('init', array($this, 'firewall_checks'), 1);

    // Block suspicious requests
    add_action('wp_loaded', array($this, 'check_suspicious_requests'));

    // REST API protection
    add_filter('rest_authentication_errors', array($this, 'rest_api_firewall'));

    // XML-RPC protection
    add_filter('xmlrpc_methods', array($this, 'disable_xmlrpc_methods'));
}

/**
 * Load blocked IPs from options
 */
private function load_blocked_ips() {
    $this->blocked_ips = $this->options['blocked_ips'] ?? array();
}

/**
 * Main firewall checks
 */
public function firewall_checks() {
    if (!$this->options['firewall_enabled']) {
        return;
    }

    $this->check_blocked_ips();
    $this->check_bad_bots();
    // Removed the undefined method call
}

/**
 * Check if current IP is blocked
 */
private function check_blocked_ips() {
    $current_ip = WP_Fort_Core::get_client_ip();

    foreach ($this->blocked_ips as $blocked_ip) {
        if ($this->check_ip_match($current_ip, $blocked_ip)) {
            $this->handle_blocked_ip_access($current_ip, $blocked_ip);
        }
    }

    // Check temporary blocks
    $temp_block_key = 'wp_fort_ip_blocked_' . md5($current_ip);
    if (get_transient($temp_block_key)) {
        $this->handle_blocked_ip_access($current_ip, 'temporary_block');
    }
}

/**
 * Check for bad bots and scanners
 */
private function check_bad_bots() {
    if (!isset($_SERVER['HTTP_USER_AGENT'])) {
        return;
    }

    $user_agent = $_SERVER['HTTP_USER_AGENT'];
    $bad_bots = $this->get_bad_bot_patterns();

    foreach ($bad_bots as $bot_pattern) {
        if (stripos($user_agent, $bot_pattern) !== false) {
            $this->handle_bad_bot_detected($user_agent, $bot_pattern);
        }
    }
}

/**
 * Check for malicious requests
 */
public function check_suspicious_requests() {
    if (!$this->options['block_suspicious_requests']) {
        return;
    }

    $this->check_sql_injection();
    $this->check_xss_attempts();
    $this->check_directory_traversal();
    $this->check_file_inclusion();
    $this->check_command_injection();
}

/**
 * Check for SQL injection attempts
 */
private function check_sql_injection() {
    $patterns = array(
        '/union\s+select/i',
        '/insert\s+into/i',
        '/drop\s+table/i',
        '/delete\s+from/i',
        '/update\s+.+set/i',
        '/or\s+1=1/i',
        '/and\s+1=1/i',
        '/exec(\s|\()+/i',
        '/eval(\s|\()+/i',
        '/benchmark\s*\(/i'
    );

    $this->scan_request_for_patterns($patterns, 'sql_injection');
}

/**
 * Check for XSS attempts
 */
private function check_xss_attempts() {
    $patterns = array(
        '/<script[^>]*>/i',
        '/javascript:/i',
        '/onload\s*=/i',
        '/onerror\s*=/i',
        '/onclick\s*=/i',
        '/onmouseover\s*=/i',
        '/alert\s*\(/i',
        '/document\.cookie/i',
        '/<iframe[^>]*>/i',
        '/<object[^>]*>/i'
    );

    $this->scan_request_for_patterns($patterns, 'xss_attempt');
}

/**
 * Check for directory traversal
 */
private function check_directory_traversal() {
    $patterns = array(
        '/\.\.\//',
        '/\.\.\\\/',
        '/\/etc\/passwd/',
        '/\/etc\/hosts/',
        '/\/proc\/self/',
        '/\/\.htaccess/',
        '/\/\.env/',
        '/\/wp-config\.php/'
    );

    $this->scan_request_for_patterns($patterns, 'directory_traversal');
}

/**
 * Check for file inclusion
 */
private function check_file_inclusion() {
    $patterns = array(
        '/include\s*\(/i',
        '/require\s*\(/i',
        '/include_once\s*\(/i',
        '/require_once\s*\(/i',
        '/file_get_contents\s*\(/i',
        '/file_put_contents\s*\(/i',
        '/fopen\s*\(/i',
        '/readfile\s*\(/i'
    );

    $this->scan_request_for_patterns($patterns, 'file_inclusion');
}

/**
 * Check for command injection
 */
private function check_command_injection() {
    $patterns = array(
        '/system\s*\(/i',
        '/exec\s*\(/i',
        '/shell_exec\s*\(/i',
        '/passthru\s*\(/i',
        '/popen\s*\(/i',
        '/proc_open\s*\(/i',
        '/`.*`/',
        '/\|\s*sh/',
        '/\|\s*bash/',
        '/\|\s*cmd/'
    );

    $this->scan_request_for_patterns($patterns, 'command_injection');
}

/**
 * Scan request data for malicious patterns
 */
private function scan_request_for_patterns($patterns, $attack_type) {
    $request_data = array_merge($_GET, $_POST, $_COOKIE);

    foreach ($request_data as $key => $value) {
        if (is_array($value)) {
            $value = implode(' ', $value);
        }

        foreach ($patterns as $pattern) {
            if (preg_match($pattern, $key) || preg_match($pattern, $value)) {
                $this->handle_malicious_request($attack_type, $key, $value, $pattern);
            }
        }
    }

    // Also check request URI
    $request_uri = $_SERVER['REQUEST_URI'] ?? '';
    foreach ($patterns as $pattern) {
        if (preg_match($pattern, $request_uri)) {
            $this->handle_malicious_request($attack_type, 'REQUEST_URI', $request_uri, $pattern);
        }
    }
}

/**
 * Handle malicious request detection
 */
private function handle_malicious_request($attack_type, $key, $value, $pattern) {
    $ip = WP_Fort_Core::get_client_ip();
    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';

    $this->core->log_security_event(
        'firewall_blocked',
        $ip,
        '',
        $user_agent,
        array(
            'attack_type' => $attack_type,
            'key' => $key,
            'value' => substr($value, 0, 100), // Limit value length
            'pattern' => $pattern,
            'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
            'timestamp' => current_time('mysql')
        ),
        'high'
    );

    // Block IP temporarily
    $this->block_ip_temporarily($ip, 30); // 30 minutes

    // Show access denied
    $this->show_access_denied($attack_type);
}

/**
 * Handle blocked IP access
 */
private function handle_blocked_ip_access($ip, $reason) {
    $this->core->log_security_event(
        'ip_blocked_by_firewall',
        $ip,
        '',
        $_SERVER['HTTP_USER_AGENT'] ?? '',
        array(
            'reason' => $reason,
            'timestamp' => current_time('mysql')
        ),
        'high'
    );

    $this->show_access_denied('ip_blocked');
}

/**
 * Handle bad bot detection
 */
private function handle_bad_bot_detected($user_agent, $bot_pattern) {
    $ip = WP_Fort_Core::get_client_ip();

    $this->core->log_security_event(
        'bad_bot_blocked',
        $ip,
        '',
        $user_agent,
        array(
            'bot_pattern' => $bot_pattern,
            'timestamp' => current_time('mysql')
        ),
        'medium'
    );

    $this->show_access_denied('bad_bot');
}

/**
 * Show access denied page
 */
private function show_access_denied($reason = '') {
    status_header(403);
    nocache_headers();

    $message = __('Access Denied', 'wp-fort');
    $details = __('Your request has been blocked by the security firewall.', 'wp-fort');

    switch ($reason) {
        case 'sql_injection':
            $details = __('SQL injection attempt detected and blocked.', 'wp-fort');
            break;
        case 'xss_attempt':
            $details = __('Cross-site scripting (XSS) attempt detected and blocked.', 'wp-fort');
            break;
        case 'directory_traversal':
            $details = __('Directory traversal attempt detected and blocked.', 'wp-fort');
            break;
        case 'file_inclusion':
            $details = __('File inclusion attempt detected and blocked.', 'wp-fort');
            break;
        case 'command_injection':
            $details = __('Command injection attempt detected and blocked.', 'wp-fort');
            break;
        case 'ip_blocked':
            $details = __('Your IP address has been blocked by the firewall.', 'wp-fort');
            break;
        case 'bad_bot':
            $details = __('Automated bot traffic detected and blocked.', 'wp-fort');
            break;
    }

    wp_die($details, $message, array('response' => 403));
}

/**
 * Block IP temporarily
 */
public function block_ip_temporarily($ip, $minutes = 30) {
    $transient_key = 'wp_fort_ip_blocked_' . md5($ip);
    set_transient($transient_key, true, $minutes * MINUTE_IN_SECONDS);

    return true;
}

/**
 * Block IP permanently
 */
public function block_ip_permanently($ip) {
    if (!in_array($ip, $this->blocked_ips)) {
        $this->blocked_ips[] = $ip;
        $this->save_blocked_ips();
    }

    return true;
}

/**
 * Unblock IP
 */
public function unblock_ip($ip) {
    if (($key = array_search($ip, $this->blocked_ips)) !== false) {
        unset($this->blocked_ips[$key]);
        $this->blocked_ips = array_values($this->blocked_ips);
        $this->save_blocked_ips();
    }

    // Also remove temporary block
    $transient_key = 'wp_fort_ip_blocked_' . md5($ip);
    delete_transient($transient_key);

    return true;
}

/**
 * Save blocked IPs to options
 */
private function save_blocked_ips() {
    $options = $this->core->get_options();
    $options['blocked_ips'] = $this->blocked_ips;
    $this->core->update_options($options);
}

/**
 * Get bad bot patterns
 */
private function get_bad_bot_patterns() {
    return array(
        'nmap', 'nikto', 'sqlmap', 'wpscan', 'acunetix',
        'nessus', 'metasploit', 'havij', 'zap', 'burp',
        'dirbuster', 'gobuster', 'wfuzz', 'skipfish',
        'arachni', 'vegile', 'morfeus', 'masscan',
        'netsparker', 'appscan', 'webinspect'
    );
}

/**
 * Check IP match (supports CIDR and wildcards)
 */
private function check_ip_match($ip, $pattern) {
    // Exact match
    if ($ip === $pattern) {
        return true;
    }

    // CIDR notation
    if (strpos($pattern, '/') !== false) {
        list($subnet, $bits) = explode('/', $pattern);
        return $this->check_cidr_match($ip, $subnet, $bits);
    }

    // Wildcard match
    if (strpos($pattern, '*') !== false) {
        $pattern = str_replace('*', '.*', preg_quote($pattern, '/'));
        return preg_match('/^' . $pattern . '$/', $ip) === 1;
    }

    return false;
}

/**
 * Check CIDR match
 */
private function check_cidr_match($ip, $subnet, $bits) {
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
        $ip = ip2long($ip);
        $subnet = ip2long($subnet);
        $mask = -1 << (32 - $bits);
        return ($ip & $mask) === ($subnet & $mask);
    }

    return false;
}

/**
 * REST API firewall protection
 */
public function rest_api_firewall($result) {
    if (!$this->options['firewall_enabled']) {
        return $result;
    }

    // Additional REST API security checks can be added here
    return $result;
}

/**
 * Disable dangerous XML-RPC methods
 */
public function disable_xmlrpc_methods($methods) {
    if (!$this->options['firewall_enabled']) {
        return $methods;
    }

    // Remove potentially dangerous methods
    $dangerous_methods = array(
        'pingback.ping',
        'pingback.extensions.getPingbacks',
        'wp.getUsersBlogs',
        'system.multicall',
        'system.listMethods'
    );

    foreach ($dangerous_methods as $method) {
        unset($methods[$method]);
    }

    return $methods;
}

/**
 * Get firewall statistics
 */
public function get_statistics() {
    global $wpdb;

    $stats = array(
        'total_blocks' => 0,
        'blocks_today' => 0,
        'top_attack_types' => array(),
        'blocked_ips_count' => count($this->blocked_ips)
    );

    // Total blocks
    $stats['total_blocks'] = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE event_type = %s",
            'firewall_blocked'
        )
    );

    // Today's blocks
    $stats['blocks_today'] = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE event_type = %s AND DATE(timestamp) = %s",
            'firewall_blocked',
            current_time('mysql')
        )
    );

    // Top attack types
    $attack_types = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT details->>'$.attack_type' as attack_type, COUNT(*) as count 
             FROM {$wpdb->prefix}wp_fort_security_logs 
             WHERE event_type = %s 
             GROUP BY details->>'$.attack_type' 
             ORDER BY count DESC 
             LIMIT 10",
            'firewall_blocked'
        ),
        ARRAY_A
    );

    foreach ($attack_types as $attack) {
        if (!empty($attack['attack_type'])) {
            $stats['top_attack_types'][$attack['attack_type']] = $attack['count'];
        }
    }

    return $stats;
}

}


class-wp-fort-cloudflare.php

<?php
/**

  • WP Fort Cloudflare Integration Class
    • @package WP_Fort
  • @since 1.0.0
    */

if (!defined(‘ABSPATH’)) {
exit;
}

class WP_Fort_Cloudflare {

private $core;
private $options;
private $api_base = 'https://api.cloudflare.com/client/v4/';

public function __construct($core = null) {
    if ($core) {
        $this->core = $core;
    } else {
        $this->core = WP_Fort_Core::get_instance();
    }
    $this->options = $this->core->get_options();

    $this->init_hooks();
}

private function init_hooks() {
    // Sync blocked IPs with Cloudflare
    add_action('wp_fort_ip_blocked', array($this, 'sync_blocked_ip_to_cloudflare'), 10, 2);

    // Sync security events
    add_action('wp_fort_security_event', array($this, 'sync_security_event_to_cloudflare'), 10, 2);

    // AJAX handler for connection test
    add_action('wp_ajax_wp_fort_test_cloudflare_connection', array($this, 'ajax_test_connection'));
}

/**
 * AJAX handler for testing Cloudflare connection
 */
public function ajax_test_connection() {
    // Verify nonce
    if (!check_ajax_referer('wp_fort_cloudflare_test', 'nonce', false)) {
        wp_send_json_error('Security check failed');
    }

    // Check user capabilities
    if (!current_user_can('manage_options')) {
        wp_send_json_error('Insufficient permissions');
    }

    $result = $this->test_connection();

    if (is_wp_error($result)) {
        wp_send_json_error($result->get_error_message());
    } else {
        wp_send_json_success(array(
            'message' => sprintf(
                __('Successfully connected to Cloudflare. Zone: %s (Status: %s, Plan: %s)', 'wp-fort'),
                $result['zone_name'],
                $result['status'],
                $result['plan']
            )
        ));
    }
}

/**
 * Test Cloudflare API connection
 */
public function test_connection() {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $response = $this->api_request('zones/' . $this->options['cloudflare_zone_id']);

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return array(
            'success' => true,
            'zone_name' => $response['result']['name'] ?? '',
            'status' => $response['result']['status'] ?? '',
            'plan' => $response['result']['plan']['name'] ?? ''
        );
    }

    // Extract error message from response
    $error_message = __('Cloudflare API returned an error.', 'wp-fort');
    if (isset($response['errors']) && is_array($response['errors'])) {
        $error_details = array();
        foreach ($response['errors'] as $error) {
            $error_details[] = $error['message'] ?? 'Unknown error';
        }
        $error_message .= ' ' . implode(', ', $error_details);
    }

    return new WP_Error('api_error', $error_message);
}

/**
 * Sync blocked IP to Cloudflare firewall
 */
public function sync_blocked_ip_to_cloudflare($ip, $reason = '') {
    if (!$this->is_configured() || !($this->options['cloudflare_firewall_rules'] ?? false)) {
        return false;
    }

    // Validate IP address
    if (!filter_var($ip, FILTER_VALIDATE_IP)) {
        error_log('WP Fort: Invalid IP address for Cloudflare sync: ' . $ip);
        return false;
    }

    // Check if IP is already blocked in Cloudflare
    $existing_rules = $this->get_firewall_rules();
    if (!is_wp_error($existing_rules)) {
        foreach ($existing_rules as $rule) {
            if (isset($rule['configuration']['value']) && $rule['configuration']['value'] === $ip) {
                return true; // Already blocked
            }
        }
    }

    // Create firewall rule
    $rule_data = array(
        'description' => 'WP Fort Blocked IP: ' . $ip . ' - ' . $reason,
        'mode' => 'block',
        'configuration' => array(
            'target' => 'ip',
            'value' => $ip
        ),
        'notes' => 'Blocked by WP Fort Security on ' . current_time('mysql')
    );

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/firewall/access_rules/rules',
        $rule_data,
        'POST'
    );

    $success = !is_wp_error($response) && isset($response['success']) && $response['success'];

    if ($success) {
        error_log('WP Fort: Successfully blocked IP in Cloudflare: ' . $ip);
    } else {
        error_log('WP Fort: Failed to block IP in Cloudflare: ' . $ip);
    }

    return $success;
}

/**
 * Sync existing blocked IPs to Cloudflare
 */
public function sync_existing_blocked_ips() {
    if (!$this->is_configured()) {
        return array(
            'success' => false,
            'message' => __('Cloudflare is not configured.', 'wp-fort')
        );
    }

    // Get blocked IPs from the IP manager
    $blocked_ips = array();

    // Try to get blocked IPs from various possible sources
    if (method_exists($this->core, 'get_blocked_ips')) {
        $blocked_ips = $this->core->get_blocked_ips();
    } elseif (class_exists('WP_Fort_IP_Manager')) {
        $ip_manager = new WP_Fort_IP_Manager();
        if (method_exists($ip_manager, 'get_blocked_ips')) {
            $blocked_ips = $ip_manager->get_blocked_ips();
        }
    } else {
        // Fallback to option
        $blocked_ips = get_option('wp_fort_blocked_ips', array());
    }

    $synced_count = 0;
    $failed_count = 0;

    foreach ($blocked_ips as $ip_data) {
        $ip = is_array($ip_data) ? ($ip_data['ip'] ?? '') : $ip_data;
        $reason = is_array($ip_data) ? ($ip_data['reason'] ?? 'Manual block') : 'Manual block';

        if ($ip && filter_var($ip, FILTER_VALIDATE_IP)) {
            if ($this->sync_blocked_ip_to_cloudflare($ip, $reason)) {
                $synced_count++;
            } else {
                $failed_count++;
            }
        }
    }

    $message = sprintf(
        __('Synced %d IP addresses to Cloudflare. %d failed.', 'wp-fort'),
        $synced_count,
        $failed_count
    );

    return array(
        'success' => $failed_count === 0,
        'message' => $message,
        'synced' => $synced_count,
        'failed' => $failed_count
    );
}

/**
 * Sync security event to Cloudflare
 */
public function sync_security_event_to_cloudflare($event_type, $event_data) {
    if (!$this->is_configured() || !($this->options['cloudflare_threat_analytics'] ?? false)) {
        return false;
    }

    // Log the event for now - in a real implementation, you'd send this to Cloudflare
    error_log(sprintf(
        'WP Fort: Security event sync to Cloudflare - Type: %s, Data: %s',
        $event_type,
        json_encode($event_data)
    ));

    return true;
}

/**
 * Get Cloudflare firewall rules
 */
public function get_firewall_rules() {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/firewall/access_rules/rules'
    );

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return $response['result'] ?? array();
    }

    return new WP_Error('api_error', __('Failed to fetch firewall rules.', 'wp-fort'));
}

/**
 * Create Cloudflare firewall rule
 */
public function create_firewall_rule($rule_data) {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/firewall/access_rules/rules',
        $rule_data,
        'POST'
    );

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return $response['result'];
    }

    return new WP_Error('api_error', __('Failed to create firewall rule.', 'wp-fort'));
}

/**
 * Delete Cloudflare firewall rule
 */
public function delete_firewall_rule($rule_id) {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/firewall/access_rules/rules/' . $rule_id,
        array(),
        'DELETE'
    );

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return true;
    }

    return new WP_Error('api_error', __('Failed to delete firewall rule.', 'wp-fort'));
}

/**
 * Get Cloudflare analytics
 */
public function get_analytics($time_range = '-7 days') {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $params = array(
        'since' => date('c', strtotime($time_range)),
        'until' => date('c'),
        'metrics' => 'threats,pageviews,requests,bandwidth'
    );

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/analytics/dashboard',
        $params
    );

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return $response['result'];
    }

    return new WP_Error('api_error', __('Failed to fetch analytics.', 'wp-fort'));
}

/**
 * Make Cloudflare API request
 */
private function api_request($endpoint, $data = array(), $method = 'GET') {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $url = $this->api_base . $endpoint;
    $args = array(
        'headers' => array(
            'X-Auth-Email' => $this->options['cloudflare_email'],
            'X-Auth-Key' => $this->options['cloudflare_api_key'],
            'Content-Type' => 'application/json'
        ),
        'timeout' => 30
    );

    if ($method === 'POST' || $method === 'PUT' || $method === 'PATCH') {
        $args['body'] = json_encode($data);
        $args['method'] = $method;
    } elseif ($method === 'GET' && !empty($data)) {
        $url .= '?' . http_build_query($data);
    } elseif ($method === 'DELETE') {
        $args['method'] = 'DELETE';
    }

    $response = wp_remote_request($url, $args);

    if (is_wp_error($response)) {
        return $response;
    }

    $response_code = wp_remote_retrieve_response_code($response);
    $body = wp_remote_retrieve_body($response);
    $decoded = json_decode($body, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        return new WP_Error('json_error', __('Invalid JSON response from Cloudflare.', 'wp-fort'));
    }

    // Log API errors for debugging
    if (isset($decoded['success']) && !$decoded['success']) {
        error_log('WP Fort Cloudflare API Error: ' . $body);
    }

    return $decoded;
}

/**
 * Check if Cloudflare is configured
 */
public function is_configured() {
    return isset($this->options['cloudflare_enabled']) && 
           $this->options['cloudflare_enabled'] &&
           !empty($this->options['cloudflare_email']) &&
           !empty($this->options['cloudflare_api_key']) &&
           !empty($this->options['cloudflare_zone_id']);
}

/**
 * Get Cloudflare zone settings
 */
public function get_zone_settings() {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/settings'
    );

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return $response['result'];
    }

    return new WP_Error('api_error', __('Failed to fetch zone settings.', 'wp-fort'));
}

/**
 * Update Cloudflare security level
 */
public function update_security_level($level = 'medium') {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $valid_levels = array('off', 'essentially_off', 'low', 'medium', 'high', 'under_attack');
    if (!in_array($level, $valid_levels)) {
        return new WP_Error('invalid_level', __('Invalid security level.', 'wp-fort'));
    }

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/settings/security_level',
        array('value' => $level),
        'PATCH'
    );

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return $response['result'];
    }

    return new WP_Error('api_error', __('Failed to update security level.', 'wp-fort'));
}

/**
 * Enable Cloudflare under attack mode
 */
public function enable_under_attack_mode($enable = true) {
    return $this->update_security_level($enable ? 'under_attack' : 'medium');
}

/**
 * Purge Cloudflare cache
 */
public function purge_cache($purge_everything = true) {
    if (!$this->is_configured()) {
        return new WP_Error('not_configured', __('Cloudflare API is not configured.', 'wp-fort'));
    }

    $data = $purge_everything ? array('purge_everything' => true) : array();

    $response = $this->api_request(
        'zones/' . $this->options['cloudflare_zone_id'] . '/purge_cache',
        $data,
        'POST'
    );

    if (is_wp_error($response)) {
        return $response;
    }

    if (isset($response['success']) && $response['success']) {
        return true;
    }

    return new WP_Error('api_error', __('Failed to purge cache.', 'wp-fort'));
}

/**
 * Get Cloudflare statistics
 */
public function get_statistics() {
    if (!$this->is_configured()) {
        return array(
            'configured' => false,
            'message' => 'Cloudflare not configured'
        );
    }

    $stats = array(
        'configured' => true,
        'zone_info' => array(),
        'threats_blocked' => 0,
        'bandwidth_saved' => 0,
        'requests_served' => 0
    );

    // Get zone info
    $zone_info = $this->test_connection();
    if (!is_wp_error($zone_info)) {
        $stats['zone_info'] = $zone_info;
    }

    // Get analytics for last 7 days
    $analytics = $this->get_analytics('-7 days');
    if (!is_wp_error($analytics)) {
        $stats['threats_blocked'] = $analytics['totals']['threats'] ?? 0;
        $stats['bandwidth_saved'] = $analytics['totals']['bandwidth']['cached'] ?? 0;
        $stats['requests_served'] = $analytics['totals']['requests']['cached'] ?? 0;
    }

    return $stats;
}

}


class-wp-fort-utilities.php

<?php
/**

  • WP Fort Utilities Class
    • @package WP_Fort
  • @since 1.0.0
    */

class WP_Fort_Utilities {

private static $instance = null;

public static function get_instance() {
    if (null === self::$instance) {
        self::$instance = new self();
    }
    return self::$instance;
}

/**
 * Generate random string
 */
public function generate_random_string($length = 32) {
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $string = '';

    for ($i = 0; $i < $length; $i++) {
        $string .= $chars[wp_rand(0, strlen($chars) - 1)];
    }

    return $string;
}

/**
 * Validate email address
 */
public function validate_email($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

/**
 * Validate IP address
 */
public function validate_ip($ip) {
    return filter_var($ip, FILTER_VALIDATE_IP) !== false;
}

/**
 * Validate URL
 */
public function validate_url($url) {
    return filter_var($url, FILTER_VALIDATE_URL) !== false;
}

/**
 * Sanitize input data
 */
public function sanitize_input($data) {
    if (is_array($data)) {
        return array_map(array($this, 'sanitize_input'), $data);
    }

    return sanitize_text_field($data);
}

/**
 * Encrypt data
 */
public function encrypt($data, $key = '') {
    if (empty($key)) {
        $key = $this->get_encryption_key();
    }

    $method = 'aes-256-cbc';
    $iv_length = openssl_cipher_iv_length($method);
    $iv = openssl_random_pseudo_bytes($iv_length);

    $encrypted = openssl_encrypt($data, $method, $key, 0, $iv);

    return base64_encode($iv . $encrypted);
}

/**
 * Decrypt data
 */
public function decrypt($data, $key = '') {
    if (empty($key)) {
        $key = $this->get_encryption_key();
    }

    $data = base64_decode($data);
    $method = 'aes-256-cbc';
    $iv_length = openssl_cipher_iv_length($method);

    $iv = substr($data, 0, $iv_length);
    $encrypted = substr($data, $iv_length);

    return openssl_decrypt($encrypted, $method, $key, 0, $iv);
}

/**
 * Get encryption key
 */
private function get_encryption_key() {
    $key = get_option('wp_fort_encryption_key');

    if (!$key) {
        $key = $this->generate_random_string(32);
        update_option('wp_fort_encryption_key', $key);
    }

    return $key;
}

/**
 * Hash data
 */
public function hash_data($data) {
    return hash('sha256', $data . $this->get_encryption_key());
}

/**
 * Verify hash
 */
public function verify_hash($data, $hash) {
    return hash_equals($this->hash_data($data), $hash);
}

/**
 * Get server information
 */
public function get_server_info() {
    return array(
        'php_version' => phpversion(),
        'mysql_version' => $this->get_mysql_version(),
        'web_server' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
        'wordpress_version' => get_bloginfo('version'),
        'wp_fort_version' => WP_FORT_VERSION,
        'server_os' => php_uname('s'),
        'server_arch' => php_uname('m'),
        'max_execution_time' => ini_get('max_execution_time'),
        'memory_limit' => ini_get('memory_limit'),
        'upload_max_filesize' => ini_get('upload_max_filesize'),
        'post_max_size' => ini_get('post_max_size')
    );
}

/**
 * Get MySQL version
 */
private function get_mysql_version() {
    global $wpdb;
    return $wpdb->db_version();
}

/**
 * Check if function exists and is enabled
 */
public function function_enabled($function_name) {
    return function_exists($function_name) && 
           !in_array($function_name, $this->get_disabled_functions());
}

/**
 * Get disabled PHP functions
 */
private function get_disabled_functions() {
    $disabled = ini_get('disable_functions');
    return $disabled ? explode(',', $disabled) : array();
}

/**
 * Get file permissions
 */
public function get_file_permissions($file_path) {
    if (!file_exists($file_path)) {
        return false;
    }

    $perms = fileperms($file_path);

    return array(
        'permissions' => substr(sprintf('%o', $perms), -4),
        'readable' => is_readable($file_path),
        'writable' => is_writable($file_path),
        'executable' => is_executable($file_path)
    );
}

/**
 * Check if site uses SSL
 */
public function is_ssl() {
    return is_ssl();
}

/**
 * Get current URL
 */
public function get_current_url() {
    $protocol = $this->is_ssl() ? 'https://' : 'http://';
    return $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}

/**
 * Get user agent info
 */
public function get_user_agent_info() {
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? '';

    return array(
        'user_agent' => $ua,
        'browser' => $this->get_browser_from_ua($ua),
        'platform' => $this->get_platform_from_ua($ua),
        'is_mobile' => wp_is_mobile(),
        'is_bot' => $this->is_bot($ua)
    );
}

/**
 * Get browser from user agent
 */
private function get_browser_from_ua($ua) {
    $browsers = array(
        'chrome' => 'Chrome',
        'firefox' => 'Firefox',
        'safari' => 'Safari',
        'opera' => 'Opera',
        'edge' => 'Edge',
        'ie' => 'Internet Explorer'
    );

    foreach ($browsers as $key => $browser) {
        if (stripos($ua, $key) !== false) {
            return $browser;
        }
    }

    return 'Unknown';
}

/**
 * Get platform from user agent
 */
private function get_platform_from_ua($ua) {
    $platforms = array(
        'windows' => 'Windows',
        'macintosh' => 'Mac',
        'linux' => 'Linux',
        'android' => 'Android',
        'iphone' => 'iPhone',
        'ipad' => 'iPad'
    );

    foreach ($platforms as $key => $platform) {
        if (stripos($ua, $key) !== false) {
            return $platform;
        }
    }

    return 'Unknown';
}

/**
 * Check if user agent is a bot
 */
private function is_bot($ua) {
    $bots = array(
        'bot', 'crawl', 'spider', 'slurp', 'search', 'archiver',
        'facebook', 'twitter', 'linkedin', 'google', 'bing'
    );

    foreach ($bots as $bot) {
        if (stripos($ua, $bot) !== false) {
            return true;
        }
    }

    return false;
}

/**
 * Format file size
 */
public function format_size($bytes) {
    $units = array('B', 'KB', 'MB', 'GB', 'TB');

    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);

    $bytes /= pow(1024, $pow);

    return round($bytes, 2) . ' ' . $units[$pow];
}

/**
 * Format time duration
 */
public function format_duration($seconds) {
    $units = array(
        'day' => 86400,
        'hour' => 3600,
        'minute' => 60,
        'second' => 1
    );

    $parts = array();

    foreach ($units as $name => $divisor) {
        $div = floor($seconds / $divisor);

        if ($div > 0) {
            $parts[] = $div . ' ' . $name . ($div > 1 ? 's' : '');
            $seconds %= $divisor;
        }
    }

    return implode(', ', $parts) ?: '0 seconds';
}

/**
 * Get directory size
 */
public function get_directory_size($path) {
    $total_size = 0;

    if (!is_dir($path)) {
        return 0;
    }

    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS)
    );

    foreach ($files as $file) {
        $total_size += $file->getSize();
    }

    return $total_size;
}

/**
 * Clean file path
 */
public function clean_path($path) {
    $path = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $path);
    $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
    $absolutes = array();

    foreach ($parts as $part) {
        if ('.' == $part) continue;
        if ('..' == $part) {
            array_pop($absolutes);
        } else {
            $absolutes[] = $part;
        }
    }

    return implode(DIRECTORY_SEPARATOR, $absolutes);
}

/**
 * Check if string is JSON
 */
public function is_json($string) {
    json_decode($string);
    return json_last_error() === JSON_ERROR_NONE;
}

/**
 * Safe JSON decode
 */
public function safe_json_decode($json, $assoc = true) {
    $decoded = json_decode($json, $assoc);

    if (json_last_error() !== JSON_ERROR_NONE) {
        return null;
    }

    return $decoded;
}

/**
 * Array to XML conversion
 */
public function array_to_xml($array, $root_element = 'root', $xml = null) {
    if ($xml === null) {
        $xml = new SimpleXMLElement('<' . $root_element . '/>');
    }

    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $this->array_to_xml($value, $key, $xml->addChild($key));
        } else {
            $xml->addChild($key, htmlspecialchars($value));
        }
    }

    return $xml->asXML();
}

/**
 * Send email notification
 */
public function send_notification($to, $subject, $message, $headers = '') {
    if (empty($headers)) {
        $headers = array(
            'Content-Type: text/html; charset=UTF-8',
            'From: WP Fort <noreply@' . $_SERVER['HTTP_HOST'] . '>'
        );
    }

    return wp_mail($to, $subject, $message, $headers);
}

/**
 * Log debug information
 */
public function log_debug($message, $data = null) {
    if (defined('WP_DEBUG') && WP_DEBUG) {
        error_log('WP Fort Debug: ' . $message);

        if ($data !== null) {
            error_log('WP Fort Data: ' . print_r($data, true));
        }
    }
}

/**
 * Get plugin settings as array
 */
public function get_settings_array() {
    $core = WP_Fort_Core::get_instance();
    return $core->get_options();
}

/**
 * Backup settings to file
 */
public function backup_settings($file_path = '') {
    $settings = $this->get_settings_array();
    $backup_data = array(
        'timestamp' => current_time('mysql'),
        'version' => WP_FORT_VERSION,
        'settings' => $settings
    );

    $json_data = json_encode($backup_data, JSON_PRETTY_PRINT);

    if (empty($file_path)) {
        $file_path = WP_CONTENT_DIR . '/wp-fort-backup-' . date('Y-m-d-H-i-s') . '.json';
    }

    return file_put_contents($file_path, $json_data) !== false;
}

/**
 * Restore settings from backup
 */
public function restore_settings($file_path) {
    if (!file_exists($file_path)) {
        return new WP_Error('file_not_found', __('Backup file not found.', 'wp-fort'));
    }

    $backup_data = file_get_contents($file_path);
    $backup = json_decode($backup_data, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        return new WP_Error('invalid_json', __('Invalid backup file format.', 'wp-fort'));
    }

    if (!isset($backup['settings'])) {
        return new WP_Error('invalid_backup', __('Invalid backup data.', 'wp-fort'));
    }

    $core = WP_Fort_Core::get_instance();
    $core->update_options($backup['settings']);

    return true;
}

}

wp-fort/admin/

class-wp-fort-admin.php

<?php
/**

  • WP Fort Admin Dashboard Class
    • @package WP_Fort
  • @since 1.0.0
    */

class WP_Fort_Admin {

private $core;
private $page_hook;

public function __construct() {
    $this->core = WP_Fort_Core::get_instance();
    $this->init_hooks();
}

private function init_hooks() {
    add_action('admin_menu', array($this, 'admin_menu'));
    add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
    add_action('admin_init', array($this, 'register_settings'));
    add_action('wp_ajax_wp_fort_get_logs', array($this, 'ajax_get_security_logs'));
    add_action('wp_ajax_wp_fort_clear_logs', array($this, 'ajax_clear_security_logs'));
    add_action('wp_ajax_wp_fort_export_logs', array($this, 'ajax_export_security_logs'));
    add_action('wp_ajax_wp_fort_add_ip', array($this, 'ajax_add_ip'));
    add_action('wp_ajax_wp_fort_remove_ip', array($this, 'ajax_remove_ip'));

    // Dashboard widgets
    add_action('wp_dashboard_setup', array($this, 'add_dashboard_widgets'));

    // Admin notices
    add_action('admin_notices', array($this, 'admin_notices'));
}

/**
 * Register settings with WordPress
 */
public function register_settings() {
    register_setting('wp_fort_options', 'wp_fort_options', array(
        'sanitize_callback' => array($this, 'sanitize_settings')
    ));
}

/**
 * Sanitize settings
 */
public function sanitize_settings($input) {
    if (!isset($input) || !is_array($input)) {
        return $this->core->get_options();
    }

    $current_settings = $this->core->get_options();
    $sanitized = array();

    // Login Protection
    $sanitized['login_protection_enabled'] = isset($input['login_protection_enabled']);
    $sanitized['custom_login_slug'] = sanitize_title($input['custom_login_slug'] ?? 'secure-admin');
    $sanitized['block_wp_login'] = isset($input['block_wp_login']);

    // IP Restrictions
    $sanitized['ip_restriction_enabled'] = isset($input['ip_restriction_enabled']);
    $sanitized['allowed_ips'] = $current_settings['allowed_ips']; // Keep existing IPs

    // Security Logging
    $sanitized['logging_enabled'] = isset($input['logging_enabled']);
    $sanitized['log_retention_days'] = absint($input['log_retention_days'] ?? 30);
    $sanitized['log_failed_logins'] = isset($input['log_failed_logins']);
    $sanitized['log_successful_logins'] = isset($input['log_successful_logins']);

    // Firewall
    $sanitized['firewall_enabled'] = isset($input['firewall_enabled']);
    $sanitized['block_suspicious_requests'] = isset($input['block_suspicious_requests']);
    $sanitized['prevent_php_execution'] = isset($input['prevent_php_execution']);

    // Brute Force Protection
    $sanitized['brute_force_protection'] = isset($input['brute_force_protection']);
    $sanitized['max_login_attempts'] = absint($input['max_login_attempts'] ?? 5);
    $sanitized['lockout_duration'] = absint($input['lockout_duration'] ?? 30);

    // Cloudflare
    $sanitized['cloudflare_enabled'] = isset($input['cloudflare_enabled']);
    $sanitized['cloudflare_api_key'] = sanitize_text_field($input['cloudflare_api_key'] ?? '');
    $sanitized['cloudflare_email'] = sanitize_email($input['cloudflare_email'] ?? '');
    $sanitized['cloudflare_zone_id'] = sanitize_text_field($input['cloudflare_zone_id'] ?? '');

    // General Settings
    $sanitized['disable_xmlrpc'] = isset($input['disable_xmlrpc']);
    $sanitized['hide_wp_version'] = isset($input['hide_wp_version']);
    $sanitized['disable_file_edit'] = isset($input['disable_file_edit']);

    return $sanitized;
}

/**
 * Add admin menu
 */
public function admin_menu() {
    $this->page_hook = add_menu_page(
        __('WP Fort Security', 'wp-fort'),
        __('WP Fort', 'wp-fort'),
        'manage_options',
        'wp-fort',
        array($this, 'admin_dashboard'),
        'dashicons-shield',
        100
    );

    // Submenus
    add_submenu_page(
        'wp-fort',
        __('Dashboard - WP Fort', 'wp-fort'),
        __('Dashboard', 'wp-fort'),
        'manage_options',
        'wp-fort',
        array($this, 'admin_dashboard')
    );

    add_submenu_page(
        'wp-fort',
        __('Login Protection - WP Fort', 'wp-fort'),
        __('Login Protection', 'wp-fort'),
        'manage_options',
        'wp-fort-login-protection',
        array($this, 'login_protection_page')
    );

    add_submenu_page(
        'wp-fort',
        __('IP Restrictions - WP Fort', 'wp-fort'),
        __('IP Restrictions', 'wp-fort'),
        'manage_options',
        'wp-fort-ip-restrictions',
        array($this, 'ip_restrictions_page')
    );

    add_submenu_page(
        'wp-fort',
        __('Security Logs - WP Fort', 'wp-fort'),
        __('Security Logs', 'wp-fort'),
        'manage_options',
        'wp-fort-security-logs',
        array($this, 'security_logs_page')
    );

    add_submenu_page(
        'wp-fort',
        __('Firewall - WP Fort', 'wp-fort'),
        __('Firewall', 'wp-fort'),
        'manage_options',
        'wp-fort-firewall',
        array($this, 'firewall_page')
    );

    add_submenu_page(
        'wp-fort',
        __('Cloudflare - WP Fort', 'wp-fort'),
        __('Cloudflare', 'wp-fort'),
        'manage_options',
        'wp-fort-cloudflare',
        array($this, 'cloudflare_page')
    );

    add_submenu_page(
        'wp-fort',
        __('Settings - WP Fort', 'wp-fort'),
        __('Settings', 'wp-fort'),
        'manage_options',
        'wp-fort-settings',
        array($this, 'settings_page')
    );
}

/**
 * Enqueue admin scripts and styles
 */
public function enqueue_admin_scripts($hook) {
    if (strpos($hook, 'wp-fort') === false) {
        return;
    }

    wp_enqueue_style(
        'wp-fort-admin',
        WP_FORT_PLUGIN_URL . 'admin/css/admin.css',
        array(),
        WP_FORT_VERSION
    );

    wp_enqueue_script(
        'wp-fort-admin',
        WP_FORT_PLUGIN_URL . 'admin/js/admin.js',
        array('jquery'),
        WP_FORT_VERSION,
        true
    );

    // Localize script for AJAX
    wp_localize_script('wp-fort-admin', 'wp_fort_ajax', array(
        'nonce' => wp_create_nonce('wp_fort_ajax_nonce'),
        'ajaxurl' => admin_url('admin-ajax.php')
    ));
}

/**
 * Main dashboard page
 */
public function admin_dashboard() {
    $options = $this->core->get_options();
    $stats = $this->get_security_stats();

    include WP_FORT_PLUGIN_PATH . 'admin/partials/dashboard.php';
}

/**
 * Login protection page
 */
public function login_protection_page() {
    $options = $this->core->get_options();

    // Show success message
    if (isset($_GET['settings-updated'])) {
        echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings saved successfully!', 'wp-fort') . '</p></div>';
    }

    include WP_FORT_PLUGIN_PATH . 'admin/partials/login-security.php';
}

/**
 * IP restrictions page
 */
public function ip_restrictions_page() {
    $options = $this->core->get_options();
    $current_ip = WP_Fort_Core::get_client_ip();

    include WP_FORT_PLUGIN_PATH . 'admin/partials/ip-restrictions.php';
}

/**
 * Security logs page
 */
public function security_logs_page() {
    $options = $this->core->get_options();

    include WP_FORT_PLUGIN_PATH . 'admin/partials/security-logs.php';
}

/**
 * Firewall page
 */
public function firewall_page() {
    $options = $this->core->get_options();

    // Show success message
    if (isset($_GET['settings-updated'])) {
        echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings saved successfully!', 'wp-fort') . '</p></div>';
    }

    include WP_FORT_PLUGIN_PATH . 'admin/partials/firewall.php';
}

/**
 * Cloudflare page
 */
public function cloudflare_page() {
    $options = $this->core->get_options();

    // Show success message
    if (isset($_GET['settings-updated'])) {
        echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings saved successfully!', 'wp-fort') . '</p></div>';
    }

    include WP_FORT_PLUGIN_PATH . 'admin/partials/cloudflare.php';
}

/**
 * Settings page
 */
public function settings_page() {
    $options = $this->core->get_options();

    // Show success message
    if (isset($_GET['settings-updated'])) {
        echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings saved successfully!', 'wp-fort') . '</p></div>';
    }

    include WP_FORT_PLUGIN_PATH . 'admin/partials/settings.php';
}

/**
 * Get security statistics
 */
private function get_security_stats() {
    global $wpdb;

    $table_name = $wpdb->prefix . 'wp_fort_security_logs';

    $stats = array(
        'total_events' => 0,
        'failed_logins' => 0,
        'blocked_ips' => 0,
        'suspicious_requests' => 0,
        'today_events' => 0,
        'events_by_severity' => array(
            'critical' => 0,
            'high' => 0,
            'medium' => 0,
            'low' => 0
        ),
        'recent_events' => array()
    );

    // Check if table exists
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        return $stats;
    }

    // Total events
    $stats['total_events'] = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");

    // Failed logins
    $stats['failed_logins'] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE event_type = %s", 'login_failed'));

    // Blocked IPs
    $stats['blocked_ips'] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE event_type = %s", 'ip_blocked'));

    // Suspicious requests
    $stats['suspicious_requests'] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE event_type = %s", 'suspicious_request'));

    // Today's events
    $stats['today_events'] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE DATE(timestamp) = %s", current_time('mysql')));

    // Events by severity
    $severity_counts = $wpdb->get_results("SELECT severity, COUNT(*) as count FROM $table_name GROUP BY severity", ARRAY_A);

    foreach ($severity_counts as $severity) {
        $stats['events_by_severity'][$severity['severity']] = $severity['count'];
    }

    // Recent events (last 10)
    $stats['recent_events'] = $wpdb->get_results("SELECT * FROM $table_name ORDER BY timestamp DESC LIMIT 10", ARRAY_A);

    return $stats;
}

/**
 * AJAX: Get security logs
 */
public function ajax_get_security_logs() {
    check_ajax_referer('wp_fort_ajax_nonce', 'nonce');

    if (!current_user_can('manage_options')) {
        wp_die(-1);
    }

    global $wpdb;

    $page = absint($_POST['page'] ?? 1);
    $per_page = 20;
    $offset = ($page - 1) * $per_page;

    $table_name = $wpdb->prefix . 'wp_fort_security_logs';

    // Check if table exists
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        wp_send_json_success(array(
            'logs' => array(),
            'total_pages' => 0,
            'current_page' => $page
        ));
    }

    $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name ORDER BY timestamp DESC LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A);

    $total_logs = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");

    wp_send_json_success(array(
        'logs' => $logs,
        'total_pages' => ceil($total_logs / $per_page),
        'current_page' => $page
    ));
}

/**
 * AJAX: Clear security logs
 */
public function ajax_clear_security_logs() {
    check_ajax_referer('wp_fort_ajax_nonce', 'nonce');

    if (!current_user_can('manage_options')) {
        wp_die(-1);
    }

    global $wpdb;

    $table_name = $wpdb->prefix . 'wp_fort_security_logs';

    // Check if table exists
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        wp_send_json_error(__('Security logs table does not exist.', 'wp-fort'));
    }

    $result = $wpdb->query("TRUNCATE TABLE $table_name");

    if ($result !== false) {
        wp_send_json_success(__('Security logs cleared successfully.', 'wp-fort'));
    } else {
        wp_send_json_error(__('Failed to clear security logs.', 'wp-fort'));
    }
}

/**
 * AJAX: Export security logs
 */
public function ajax_export_security_logs() {
    check_ajax_referer('wp_fort_ajax_nonce', 'nonce');

    if (!current_user_can('manage_options')) {
        wp_die(-1);
    }

    global $wpdb;

    $table_name = $wpdb->prefix . 'wp_fort_security_logs';

    // Check if table exists
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        wp_die('No security logs found.');
    }

    $logs = $wpdb->get_results("SELECT * FROM $table_name ORDER BY timestamp DESC", ARRAY_A);

    // Generate CSV
    $filename = 'wp-fort-security-logs-' . date('Y-m-d-H-i-s') . '.csv';

    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="' . $filename . '"');

    $output = fopen('php://output', 'w');

    // Headers
    fputcsv($output, array(
        'Timestamp',
        'Event Type',
        'IP Address',
        'Username',
        'Country',
        'Region',
        'City',
        'Severity',
        'Details'
    ));

    // Data
    foreach ($logs as $log) {
        fputcsv($output, array(
            $log['timestamp'],
            $log['event_type'],
            $log['ip_address'],
            $log['username'],
            $log['country'],
            $log['region'],
            $log['city'],
            $log['severity'],
            $log['details']
        ));
    }

    fclose($output);
    exit;
}

/**
 * AJAX: Add IP to whitelist
 */
public function ajax_add_ip() {
    check_ajax_referer('wp_fort_ajax_nonce', 'nonce');

    if (!current_user_can('manage_options')) {
        wp_die(-1);
    }

    $ip = sanitize_text_field($_POST['ip'] ?? '');

    if (!filter_var($ip, FILTER_VALIDATE_IP)) {
        wp_send_json_error(__('Invalid IP address.', 'wp-fort'));
    }

    $options = $this->core->get_options();

    if (!in_array($ip, $options['allowed_ips'])) {
        $options['allowed_ips'][] = $ip;
        $this->core->update_options($options);

        wp_send_json_success(__('IP address added to whitelist.', 'wp-fort'));
    } else {
        wp_send_json_error(__('IP address already in whitelist.', 'wp-fort'));
    }
}

/**
 * AJAX: Remove IP from whitelist
 */
public function ajax_remove_ip() {
    check_ajax_referer('wp_fort_ajax_nonce', 'nonce');

    if (!current_user_can('manage_options')) {
        wp_die(-1);
    }

    $ip = sanitize_text_field($_POST['ip'] ?? '');

    $options = $this->core->get_options();

    if (($key = array_search($ip, $options['allowed_ips'])) !== false) {
        unset($options['allowed_ips'][$key]);
        $options['allowed_ips'] = array_values($options['allowed_ips']);
        $this->core->update_options($options);

        wp_send_json_success(__('IP address removed from whitelist.', 'wp-fort'));
    } else {
        wp_send_json_error(__('IP address not found in whitelist.', 'wp-fort'));
    }
}

/**
 * Add dashboard widgets
 */
public function add_dashboard_widgets() {
    wp_add_dashboard_widget(
        'wp_fort_security_widget',
        __('WP Fort Security Overview', 'wp-fort'),
        array($this, 'dashboard_widget_content')
    );
}

/**
 * Dashboard widget content
 */
public function dashboard_widget_content() {
    $stats = $this->get_security_stats();
    $options = $this->core->get_options();

    echo '<div class="wp-fort-dashboard-widget">';
    echo '<div class="security-status ' . ($stats['today_events'] > 10 ? 'warning' : 'good') . '">';
    echo '<p><strong>' . __('Today\'s Events:', 'wp-fort') . '</strong> ' . $stats['today_events'] . '</p>';
    echo '</div>';

    echo '<div class="security-stats">';
    echo '<p><strong>' . __('Failed Logins:', 'wp-fort') . '</strong> ' . $stats['failed_logins'] . '</p>';
    echo '<p><strong>' . __('Blocked IPs:', 'wp-fort') . '</strong> ' . $stats['blocked_ips'] . '</p>';
    echo '</div>';

    echo '<div class="security-actions">';
    echo '<a href="' . admin_url('admin.php?page=wp-fort-security-logs') . '" class="button button-primary">' . __('View Security Logs', 'wp-fort') . '</a>';
    echo '</div>';
    echo '</div>';
}

/**
 * Admin notices
 */
public function admin_notices() {
    $options = $this->core->get_options();

    // Notice for first-time setup
    if ($options['login_protection_enabled'] && empty($options['custom_login_slug'])) {
        echo '<div class="notice notice-warning">';
        echo '<p>' . __('WP Fort: Please configure your custom login URL in the security settings.', 'wp-fort') . '</p>';
        echo '</div>';
    }

    // Notice if IP restriction is enabled but no IPs are whitelisted
    if ($options['ip_restriction_enabled'] && empty($options['allowed_ips'])) {
        echo '<div class="notice notice-error">';
        echo '<p>' . __('WP Fort: IP restriction is enabled but no IP addresses are whitelisted. You may lock yourself out!', 'wp-fort') . '</p>';
        echo '</div>';
    }
}

}



admin.css

/**

  • WP Fort Admin Styles
    • @package WP_Fort
  • @since 1.0.0
    */

/* Main Admin Container */
.wp-fort-admin {
max-width: 1200px;
margin: 20px 0;
}

.wp-fort-header {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
margin-bottom: 20px;
border-left: 4px solid #2271b1;
}

.wp-fort-header h1 {
margin: 0 0 10px 0;
color: #1d2327;
font-size: 28px;
}

.wp-fort-header p {
margin: 0;
color: #646970;
font-size: 16px;
}

/* Stats Grid */
.wp-fort-stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}

.wp-fort-stat-card {
background: #fff;
padding: 25px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
text-align: center;
border-top: 4px solid #2271b1;
transition: transform 0.2s ease;
}

.wp-fort-stat-card:hover {
transform: translateY(-2px);
}

.wp-fort-stat-card.critical {
border-top-color: #d63638;
}

.wp-fort-stat-card.high {
border-top-color: #dba617;
}

.wp-fort-stat-card.medium {
border-top-color: #00a32a;
}

.wp-fort-stat-card.low {
border-top-color: #2271b1;
}

.wp-fort-stat-number {
font-size: 36px;
font-weight: bold;
color: #1d2327;
display: block;
line-height: 1;
margin-bottom: 8px;
}

.wp-fort-stat-label {
font-size: 14px;
color: #646970;
text-transform: uppercase;
letter-spacing: 0.5px;
}

/* Tabs Navigation */
.wp-fort-tabs {
background: #fff;
border-radius: 8px 8px 0 0;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
margin-bottom: 0;
}

.wp-fort-tab-nav {
display: flex;
border-bottom: 1px solid #dcdcde;
margin: 0;
padding: 0;
}

.wp-fort-tab-nav li {
list-style: none;
margin: 0;
}

.wp-fort-tab-nav a {
display: block;
padding: 15px 25px;
text-decoration: none;
color: #646970;
border-bottom: 3px solid transparent;
transition: all 0.2s ease;
}

.wp-fort-tab-nav a:hover {
color: #2271b1;
background: #f6f7f7;
}

.wp-fort-tab-nav a.active {
color: #2271b1;
border-bottom-color: #2271b1;
background: #f6f7f7;
}

.wp-fort-tab-content {
background: #fff;
padding: 30px;
border-radius: 0 0 8px 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}

/* Forms */
.wp-fort-form-section {
background: #f6f7f7;
padding: 20px;
border-radius: 6px;
margin-bottom: 25px;
border-left: 4px solid #2271b1;
}

.wp-fort-form-section h3 {
margin-top: 0;
color: #1d2327;
}

.wp-fort-form-row {
margin-bottom: 20px;
}

.wp-fort-form-row label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #1d2327;
}

.wp-fort-form-row input[type=”text”],
.wp-fort-form-row input[type=”email”],
.wp-fort-form-row input[type=”password”],
.wp-fort-form-row input[type=”number”],
.wp-fort-form-row select,
.wp-fort-form-row textarea {
width: 100%;
max-width: 400px;
padding: 8px 12px;
border: 1px solid #dcdcde;
border-radius: 4px;
font-size: 14px;
}

.wp-fort-form-row input:focus,
.wp-fort-form-row select:focus,
.wp-fort-form-row textarea:focus {
border-color: #2271b1;
box-shadow: 0 0 0 1px #2271b1;
outline: none;
}

.wp-fort-form-help {
font-size: 13px;
color: #646970;
margin-top: 6px;
font-style: italic;
}

.wp-fort-form-help code {
background: #f0f0f1;
padding: 2px 6px;
border-radius: 3px;
font-family: monospace;
}

/* Toggle Switch */
.wp-fort-toggle {
position: relative;
display: inline-block;
width: 50px;
height: 24px;
}

.wp-fort-toggle input {
opacity: 0;
width: 0;
height: 0;
}

.wp-fort-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 24px;
}

.wp-fort-slider:before {
position: absolute;
content: “”;
height: 16px;
width: 16px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}

input:checked + .wp-fort-slider {
background-color: #2271b1;
}

input:checked + .wp-fort-slider:before {
transform: translateX(26px);
}

/* IP Management */
.wp-fort-ip-list {
background: #fff;
border: 1px solid #dcdcde;
border-radius: 4px;
max-height: 300px;
overflow-y: auto;
}

.wp-fort-ip-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 15px;
border-bottom: 1px solid #f0f0f1;
}

.wp-fort-ip-item:last-child {
border-bottom: none;
}

.wp-fort-ip-address {
font-family: monospace;
font-size: 14px;
}

.wp-fort-ip-current {
background: #f0f6fc;
border-left: 3px solid #2271b1;
}

.wp-fort-ip-actions {
display: flex;
gap: 10px;
}

/* Security Logs */
.wp-fort-logs-container {
background: #fff;
border: 1px solid #dcdcde;
border-radius: 4px;
overflow: hidden;
}

.wp-fort-logs-table {
width: 100%;
border-collapse: collapse;
}

.wp-fort-logs-table th,
.wp-fort-logs-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #f0f0f1;
}

.wp-fort-logs-table th {
background: #f6f7f7;
font-weight: 600;
color: #1d2327;
}

.wp-fort-logs-table tr:hover {
background: #f9f9f9;
}

.wp-fort-severity {
display: inline-block;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
}

.wp-fort-severity.critical {
background: #fcf0f1;
color: #d63638;
}

.wp-fort-severity.high {
background: #fcf9e8;
color: #dba617;
}

.wp-fort-severity.medium {
background: #edfaef;
color: #00a32a;
}

.wp-fort-severity.low {
background: #f0f6fc;
color: #2271b1;
}

/* Buttons */
.wp-fort-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
background: #2271b1;
color: #fff;
text-decoration: none;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s ease;
}

.wp-fort-btn:hover {
background: #135e96;
color: #fff;
}

.wp-fort-btn-danger {
background: #d63638;
}

.wp-fort-btn-danger:hover {
background: #b32d2e;
}

.wp-fort-btn-success {
background: #00a32a;
}

.wp-fort-btn-success:hover {
background: #008a20;
}

.wp-fort-btn-secondary {
background: #f6f7f7;
color: #3c434a;
border: 1px solid #dcdcde;
}

.wp-fort-btn-secondary:hover {
background: #f0f0f1;
color: #3c434a;
}

/* Loading States */
.wp-fort-loading {
opacity: 0.6;
pointer-events: none;
}

.wp-fort-spinner {
display: inline-block;
width: 16px;
height: 16px;
border: 2px solid #f3f3f3;
border-top: 2px solid #2271b1;
border-radius: 50%;
animation: wp-fort-spin 1s linear infinite;
}

@keyframes wp-fort-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

/* Dashboard Widget */
.wp-fort-dashboard-widget .security-status {
padding: 10px;
border-radius: 4px;
margin-bottom: 15px;
}

.wp-fort-dashboard-widget .security-status.good {
background: #edfaef;
border-left: 3px solid #00a32a;
}

.wp-fort-dashboard-widget .security-status.warning {
background: #fcf9e8;
border-left: 3px solid #dba617;
}

.wp-fort-dashboard-widget .security-stats {
margin-bottom: 15px;
}

.wp-fort-dashboard-widget .security-stats p {
margin: 5px 0;
}

.wp-fort-dashboard-widget .security-actions {
text-align: center;
}

/* Responsive */
@media (max-width: 768px) {
.wp-fort-stats-grid {
grid-template-columns: 1fr;
}

.wp-fort-tab-nav {
    flex-direction: column;
}

.wp-fort-tab-nav a {
    border-bottom: 1px solid #f0f0f1;
    border-left: 3px solid transparent;
}

.wp-fort-tab-nav a.active {
    border-left-color: #2271b1;
    border-bottom-color: #f0f0f1;
}

.wp-fort-logs-table {
    font-size: 12px;
}

.wp-fort-logs-table th,
.wp-fort-logs-table td {
    padding: 8px 10px;
}

}

/* Charts */
.wp-fort-chart-container {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
margin-bottom: 20px;
}

.wp-fort-chart {
height: 300px;
position: relative;
}


dashboard.css

Empty


js/
admin.js

/**

  • WP Fort Admin JavaScript
    • @package WP_Fort
  • @since 1.0.0
    */

(function($) {
‘use strict’;

class WPFortAdmin {
    constructor() {
        this.init();
    }

    init() {
        this.bindEvents();
        this.initTabs();
    }

    bindEvents() {
        // Add loading state to form submission
        $(document).on('submit', '.wp-fort-settings-form', this.handleFormSubmit.bind(this));

        // IP management
        $(document).on('click', '.wp-fort-add-ip', this.addIP.bind(this));
        $(document).on('click', '.wp-fort-remove-ip', this.removeIP.bind(this));
    }

    initTabs() {
        $('.wp-fort-tab-nav a').on('click', function(e) {
            e.preventDefault();

            const target = $(this).attr('href');

            // Update active tab
            $('.wp-fort-tab-nav a').removeClass('active');
            $(this).addClass('active');

            // Show target content
            $('.wp-fort-tab-content').hide();
            $(target).show();
        });

        // Show first tab by default
        $('.wp-fort-tab-nav a:first').click();
    }

    handleFormSubmit(e) {
        // Just add loading state, let the form submit normally
        const $submit = $(e.target).find('input[type="submit"], button[type="submit"]');
        const originalText = $submit.val() || $submit.text();

        $submit.prop('disabled', true);
        if ($submit.is('input')) {
            $submit.val('Saving...');
        } else {
            $submit.text('Saving...');
        }
    }

    addIP(e) {
        e.preventDefault();

        const $button = $(e.target).is('button') ? $(e.target) : $(e.target).closest('button');
        const $input = $('.wp-fort-ip-input');
        const ip = $input.val().trim();

        if (!this.validateIP(ip)) {
            alert('Please enter a valid IP address.');
            return;
        }

        $button.prop('disabled', true).text('Adding...');

        $.ajax({
            url: wp_fort_ajax.ajaxurl,
            type: 'POST',
            data: {
                action: 'wp_fort_add_ip',
                ip: ip,
                nonce: wp_fort_ajax.nonce
            },
            success: (response) => {
                if (response.success) {
                    $input.val('');
                    window.location.reload();
                } else {
                    alert(response.data);
                    $button.prop('disabled', false).text('Add IP');
                }
            },
            error: () => {
                alert('Error occurred. Please try again.');
                $button.prop('disabled', false).text('Add IP');
            }
        });
    }

    removeIP(e) {
        e.preventDefault();

        const $button = $(e.target).is('button') ? $(e.target) : $(e.target).closest('button');
        const ip = $button.data('ip');

        if (!confirm('Are you sure you want to remove this IP address?')) {
            return;
        }

        $button.prop('disabled', true).text('Removing...');

        $.ajax({
            url: wp_fort_ajax.ajaxurl,
            type: 'POST',
            data: {
                action: 'wp_fort_remove_ip',
                ip: ip,
                nonce: wp_fort_ajax.nonce
            },
            success: (response) => {
                if (response.success) {
                    window.location.reload();
                } else {
                    alert(response.data);
                    $button.prop('disabled', false).text('Remove');
                }
            },
            error: () => {
                alert('Error occurred. Please try again.');
                $button.prop('disabled', false).text('Remove');
            }
        });
    }

    validateIP(ip) {
        const ipPattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
        return ipPattern.test(ip);
    }
}

// Initialize when document is ready
$(document).ready(() => {
    new WPFortAdmin();
});

})(jQuery);


charts.js

/**

  • WP Fort Charts JavaScript
    • @package WP_Fort
  • @since 1.0.0
    */

(function($) {
‘use strict’;

class WPFortCharts {
    constructor() {
        this.charts = {};
        this.init();
    }

    init() {
        this.initSeverityChart();
        this.initEventsTimeline();
        this.initAttackTypesChart();
    }

    initSeverityChart() {
        const $chart = $('#severity-chart');
        if (!$chart.length) return;

        // Get data from the page (this would typically come from AJAX)
        const severityData = this.getSeverityData();

        // Create chart using Chart.js
        const ctx = $chart[0].getContext('2d');
        this.charts.severity = new Chart(ctx, {
            type: 'doughnut',
            data: {
                labels: [
                    'Critical',
                    'High', 
                    'Medium',
                    'Low'
                ],
                datasets: [{
                    data: [
                        severityData.critical,
                        severityData.high,
                        severityData.medium,
                        severityData.low
                    ],
                    backgroundColor: [
                        '#d63638', // Critical - Red
                        '#dba617', // High - Orange
                        '#00a32a', // Medium - Green
                        '#2271b1'  // Low - Blue
                    ],
                    borderWidth: 2,
                    borderColor: '#fff'
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: {
                        position: 'bottom',
                        labels: {
                            padding: 20,
                            usePointStyle: true
                        }
                    },
                    tooltip: {
                        callbacks: {
                            label: function(context) {
                                const label = context.label || '';
                                const value = context.parsed;
                                const total = context.dataset.data.reduce((a, b) => a + b, 0);
                                const percentage = total > 0 ? Math.round((value / total) * 100) : 0;
                                return `${label}: ${value} (${percentage}%)`;
                            }
                        }
                    }
                },
                cutout: '60%'
            }
        });
    }

    initEventsTimeline() {
        const $chart = $('#events-timeline-chart');
        if (!$chart.length) return;

        const timelineData = this.getTimelineData();

        const ctx = $chart[0].getContext('2d');
        this.charts.timeline = new Chart(ctx, {
            type: 'line',
            data: {
                labels: Object.keys(timelineData),
                datasets: [{
                    label: 'Security Events',
                    data: Object.values(timelineData),
                    borderColor: '#2271b1',
                    backgroundColor: 'rgba(34, 113, 177, 0.1)',
                    borderWidth: 3,
                    fill: true,
                    tension: 0.4,
                    pointBackgroundColor: '#2271b1',
                    pointBorderColor: '#fff',
                    pointBorderWidth: 2,
                    pointRadius: 5,
                    pointHoverRadius: 7
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: {
                        display: false
                    },
                    tooltip: {
                        mode: 'index',
                        intersect: false
                    }
                },
                scales: {
                    x: {
                        grid: {
                            display: false
                        },
                        ticks: {
                            maxRotation: 0
                        }
                    },
                    y: {
                        beginAtZero: true,
                        ticks: {
                            precision: 0
                        },
                        grid: {
                            borderDash: [3, 3]
                        }
                    }
                },
                interaction: {
                    intersect: false,
                    mode: 'nearest'
                }
            }
        });
    }

    initAttackTypesChart() {
        const $chart = $('#attack-types-chart');
        if (!$chart.length) return;

        const attackData = this.getAttackTypesData();

        const ctx = $chart[0].getContext('2d');
        this.charts.attackTypes = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: Object.keys(attackData),
                datasets: [{
                    label: 'Attack Attempts',
                    data: Object.values(attackData),
                    backgroundColor: [
                        '#d63638',
                        '#dba617', 
                        '#2271b1',
                        '#00a32a',
                        '#8c35e0'
                    ],
                    borderColor: '#fff',
                    borderWidth: 1,
                    borderRadius: 4,
                    borderSkipped: false
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    legend: {
                        display: false
                    }
                },
                scales: {
                    x: {
                        grid: {
                            display: false
                        }
                    },
                    y: {
                        beginAtZero: true,
                        ticks: {
                            precision: 0
                        },
                        grid: {
                            borderDash: [3, 3]
                        }
                    }
                },
                indexAxis: 'y' // Horizontal bars
            }
        });
    }

    getSeverityData() {
        // This data would typically come from AJAX
        // For now, using placeholder data
        return {
            critical: 12,
            high: 45,
            medium: 89,
            low: 156
        };
    }

    getTimelineData() {
        // Generate last 7 days data
        const data = {};
        for (let i = 6; i >= 0; i--) {
            const date = new Date();
            date.setDate(date.getDate() - i);
            const dateString = date.toISOString().split('T')[0];
            data[dateString] = Math.floor(Math.random() * 50) + 10;
        }
        return data;
    }

    getAttackTypesData() {
        return {
            'SQL Injection': 23,
            'XSS Attacks': 45,
            'Brute Force': 67,
            'Directory Traversal': 12,
            'File Inclusion': 8
        };
    }

    updateCharts() {
        // Method to refresh all charts with new data
        Object.values(this.charts).forEach(chart => {
            chart.destroy();
        });
        this.charts = {};
        this.init();
    }

    // Export chart as image
    exportChart(chartId, filename = 'chart.png') {
        const chart = this.charts[chartId];
        if (chart) {
            const link = document.createElement('a');
            link.download = filename;
            link.href = chart.toBase64Image();
            link.click();
        }
    }
}

// Initialize charts when document is ready
$(document).ready(() => {
    window.wpFortCharts = new WPFortCharts();
});

})(jQuery);


partials/
dashboard.php

<?php
/**
 * WP Fort Dashboard Template
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}
?>

<div class="wrap wp-fort-admin">
    <div class="wp-fort-header">
        <h1><?php _e('WP Fort Security Dashboard', 'wp-fort'); ?></h1>
        <p><?php _e('Comprehensive security protection for your WordPress website.', 'wp-fort'); ?></p>
    </div>

    <!-- Stats Grid -->
    <div class="wp-fort-stats-grid">
        <div class="wp-fort-stat-card">
            <span class="wp-fort-stat-number"><?php echo esc_html($stats['total_events']); ?></span>
            <span class="wp-fort-stat-label"><?php _e('Total Security Events', 'wp-fort'); ?></span>
        </div>
        
        <div class="wp-fort-stat-card critical">
            <span class="wp-fort-stat-number"><?php echo esc_html($stats['failed_logins']); ?></span>
            <span class="wp-fort-stat-label"><?php _e('Failed Logins', 'wp-fort'); ?></span>
        </div>
        
        <div class="wp-fort-stat-card high">
            <span class="wp-fort-stat-number"><?php echo esc_html($stats['blocked_ips']); ?></span>
            <span class="wp-fort-stat-label"><?php _e('Blocked IPs', 'wp-fort'); ?></span>
        </div>
        
        <div class="wp-fort-stat-card medium">
            <span class="wp-fort-stat-number"><?php echo esc_html($stats['today_events']); ?></span>
            <span class="wp-fort-stat-label"><?php _e("Today's Events", 'wp-fort'); ?></span>
        </div>
    </div>

    <!-- Quick Actions -->
    <div class="wp-fort-form-section">
        <h3><?php _e('Quick Actions', 'wp-fort'); ?></h3>
        <div style="display: flex; gap: 10px; flex-wrap: wrap;">
            <button class="wp-fort-btn wp-fort-quick-action" data-action="test_login_url">
                <?php _e('Test Login URL', 'wp-fort'); ?>
            </button>
            <button class="wp-fort-btn wp-fort-btn-secondary wp-fort-quick-action" data-action="scan_security">
                <?php _e('Security Scan', 'wp-fort'); ?>
            </button>
            <button class="wp-fort-btn wp-fort-btn-success wp-fort-quick-action" data-action="backup_settings">
                <?php _e('Backup Settings', 'wp-fort'); ?>
            </button>
        </div>
    </div>

    <!-- Tabs Navigation -->
    <div class="wp-fort-tabs">
        <ul class="wp-fort-tab-nav">
            <li><a href="#overview" class="active"><?php _e('Overview', 'wp-fort'); ?></a></li>
            <li><a href="#recent-events"><?php _e('Recent Events', 'wp-fort'); ?></a></li>
            <li><a href="#security-status"><?php _e('Security Status', 'wp-fort'); ?></a></li>
        </ul>
    </div>

    <!-- Tab Contents -->
    <div id="overview" class="wp-fort-tab-content">
        <h3><?php _e('Security Overview', 'wp-fort'); ?></h3>
        
        <div class="wp-fort-chart-container">
            <h4><?php _e('Events by Severity', 'wp-fort'); ?></h4>
            <div class="wp-fort-chart" id="severity-chart">
                <!-- Chart will be loaded via JavaScript -->
                <p style="text-align: center; padding: 60px 0;"><?php _e('Chart loading...', 'wp-fort'); ?></p>
            </div>
        </div>

        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
            <div class="wp-fort-form-section">
                <h4><?php _e('Security Features Status', 'wp-fort'); ?></h4>
                <ul style="list-style: none; padding: 0; margin: 0;">
                    <li style="padding: 8px 0; border-bottom: 1px solid #f0f0f1;">
                        <strong><?php _e('Login Protection:', 'wp-fort'); ?></strong>
                        <span style="color: <?php echo $options['login_protection_enabled'] ? '#00a32a' : '#d63638'; ?>;">
                            <?php echo $options['login_protection_enabled'] ? __('Enabled', 'wp-fort') : __('Disabled', 'wp-fort'); ?>
                        </span>
                    </li>
                    <li style="padding: 8px 0; border-bottom: 1px solid #f0f0f1;">
                        <strong><?php _e('IP Restrictions:', 'wp-fort'); ?></strong>
                        <span style="color: <?php echo $options['ip_restriction_enabled'] ? '#00a32a' : '#d63638'; ?>;">
                            <?php echo $options['ip_restriction_enabled'] ? __('Enabled', 'wp-fort') : __('Disabled', 'wp-fort'); ?>
                        </span>
                    </li>
                    <li style="padding: 8px 0; border-bottom: 1px solid #f0f0f1;">
                        <strong><?php _e('Firewall:', 'wp-fort'); ?></strong>
                        <span style="color: <?php echo $options['firewall_enabled'] ? '#00a32a' : '#d63638'; ?>;">
                            <?php echo $options['firewall_enabled'] ? __('Enabled', 'wp-fort') : __('Disabled', 'wp-fort'); ?>
                        </span>
                    </li>
                    <li style="padding: 8px 0;">
                        <strong><?php _e('Brute Force Protection:', 'wp-fort'); ?></strong>
                        <span style="color: <?php echo $options['brute_force_protection'] ? '#00a32a' : '#d63638'; ?>;">
                            <?php echo $options['brute_force_protection'] ? __('Enabled', 'wp-fort') : __('Disabled', 'wp-fort'); ?>
                        </span>
                    </li>
                </ul>
            </div>

            <div class="wp-fort-form-section">
                <h4><?php _e('System Information', 'wp-fort'); ?></h4>
                <ul style="list-style: none; padding: 0; margin: 0;">
                    <li style="padding: 8px 0; border-bottom: 1px solid #f0f0f1;">
                        <strong><?php _e('WordPress Version:', 'wp-fort'); ?></strong>
                        <?php echo esc_html(get_bloginfo('version')); ?>
                    </li>
                    <li style="padding: 8px 0; border-bottom: 1px solid #f0f0f1;">
                        <strong><?php _e('PHP Version:', 'wp-fort'); ?></strong>
                        <?php echo esc_html(phpversion()); ?>
                    </li>
                    <li style="padding: 8px 0; border-bottom: 1px solid #f0f0f1;">
                        <strong><?php _e('Your IP Address:', 'wp-fort'); ?></strong>
                        <code><?php echo esc_html(WP_Fort_Core::get_client_ip()); ?></code>
                    </li>
                    <li style="padding: 8px 0;">
                        <strong><?php _e('Custom Login URL:', 'wp-fort'); ?></strong>
                        <?php if ($options['login_protection_enabled'] && !empty($options['custom_login_slug'])): ?>
                            <code><?php echo esc_url(home_url($options['custom_login_slug'])); ?></code>
                        <?php else: ?>
                            <span style="color: #d63638;"><?php _e('Not configured', 'wp-fort'); ?></span>
                        <?php endif; ?>
                    </li>
                </ul>
            </div>
        </div>
    </div>

    <div id="recent-events" class="wp-fort-tab-content" style="display: none;">
        <h3><?php _e('Recent Security Events', 'wp-fort'); ?></h3>
        
        <div class="wp-fort-logs-container">
            <table class="wp-fort-logs-table">
                <thead>
                    <tr>
                        <th><?php _e('Timestamp', 'wp-fort'); ?></th>
                        <th><?php _e('Event Type', 'wp-fort'); ?></th>
                        <th><?php _e('IP Address', 'wp-fort'); ?></th>
                        <th><?php _e('Username', 'wp-fort'); ?></th>
                        <th><?php _e('Country', 'wp-fort'); ?></th>
                        <th><?php _e('Region', 'wp-fort'); ?></th>
                        <th><?php _e('City', 'wp-fort'); ?></th>
                        <th><?php _e('Severity', 'wp-fort'); ?></th>
                        <th><?php _e('Details', 'wp-fort'); ?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php if (empty($stats['recent_events'])): ?>
                        <tr>
                            <td colspan="9" style="text-align: center; padding: 40px;">
                                <?php _e('No security events recorded yet.', 'wp-fort'); ?>
                            </td>
                        </tr>
                    <?php else: ?>
                        <?php foreach ($stats['recent_events'] as $event): ?>
                            <tr>
                                <td><?php echo esc_html($event['timestamp']); ?></td>
                                <td><?php echo esc_html($event['event_type']); ?></td>
                                <td><code><?php echo esc_html($event['ip_address']); ?></code></td>
                                <td><?php echo esc_html($event['username'] ?: '—'); ?></td>
                                <td><?php echo esc_html($event['country'] ?: 'Unknown'); ?></td>
                                <td><?php echo esc_html($event['region'] ?: '—'); ?></td>
                                <td><?php echo esc_html($event['city'] ?: '—'); ?></td>
                                <td>
                                    <span class="wp-fort-severity <?php echo esc_attr($event['severity']); ?>">
                                        <?php echo esc_html($event['severity']); ?>
                                    </span>
                                </td>
                                <td><?php echo esc_html($event['details'] ?: '—'); ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </tbody>
            </table>
        </div>
        
        <div style="margin-top: 20px; text-align: center;">
            <a href="<?php echo admin_url('admin.php?page=wp-fort-security-logs'); ?>" class="wp-fort-btn">
                <?php _e('View All Security Logs', 'wp-fort'); ?>
            </a>
        </div>
    </div>

    <div id="security-status" class="wp-fort-tab-content" style="display: none;">
        <h3><?php _e('Security Status Check', 'wp-fort'); ?></h3>
        
        <div class="wp-fort-form-section">
            <h4><?php _e('Security Recommendations', 'wp-fort'); ?></h4>
            
            <?php
            $recommendations = array();
            
            if (!$options['login_protection_enabled']) {
                $recommendations[] = __('Enable login protection to hide wp-login.php', 'wp-fort');
            }
            
            if ($options['ip_restriction_enabled'] && empty($options['allowed_ips'])) {
                $recommendations[] = __('Add IP addresses to whitelist when IP restriction is enabled', 'wp-fort');
            }
            
            if (!$options['disable_xmlrpc']) {
                $recommendations[] = __('Disable XML-RPC to prevent brute force attacks', 'wp-fort');
            }
            
            if (empty($recommendations)): ?>
                <div style="background: #edfaef; padding: 15px; border-radius: 4px; border-left: 4px solid #00a32a;">
                    <p style="margin: 0; color: #00a32a;">
                        <strong><?php _e('Excellent!', 'wp-fort'); ?></strong>
                        <?php _e('All security recommendations are implemented.', 'wp-fort'); ?>
                    </p>
                </div>
            <?php else: ?>
                <ul style="list-style: disc; padding-left: 20px;">
                    <?php foreach ($recommendations as $recommendation): ?>
                        <li style="margin-bottom: 8px;"><?php echo esc_html($recommendation); ?></li>
                    <?php endforeach; ?>
                </ul>
            <?php endif; ?>
        </div>
        
        <div class="wp-fort-form-section">
            <h4><?php _e('Security Health Check', 'wp-fort'); ?></h4>
            
            <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
                <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                    <div style="font-size: 24px; font-weight: bold; color: #00a32a;">✓</div>
                    <div><?php _e('SSL Certificate', 'wp-fort'); ?></div>
                    <div style="font-size: 12px; color: #646970;">
                        <?php echo is_ssl() ? __('Active', 'wp-fort') : __('Not Active', 'wp-fort'); ?>
                    </div>
                </div>
                
                <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                    <div style="font-size: 24px; font-weight: bold; color: #00a32a;">✓</div>
                    <div><?php _e('File Permissions', 'wp-fort'); ?></div>
                    <div style="font-size: 12px; color: #646970;"><?php _e('Checking...', 'wp-fort'); ?></div>
                </div>
                
                <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                    <div style="font-size: 24px; font-weight: bold; color: #00a32a;">✓</div>
                    <div><?php _e('Database Security', 'wp-fort'); ?></div>
                    <div style="font-size: 12px; color: #646970;"><?php _e('Secure', 'wp-fort'); ?></div>
                </div>
                
                <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                    <div style="font-size: 24px; font-weight: bold; color: #00a32a;">✓</div>
                    <div><?php _e('WP Fort Active', 'wp-fort'); ?></div>
                    <div style="font-size: 12px; color: #646970;"><?php _e('Protected', 'wp-fort'); ?></div>
                </div>
            </div>
        </div>
    </div>
</div>


login-security.php

<?php
/**
 * WP Fort Login Protection Settings
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}
?>

<div class="wrap wp-fort-admin">
    <div class="wp-fort-header">
        <h1>Login Protection Settings</h1>
        <p>Secure your WordPress login with custom URLs and advanced protection.</p>
    </div>

    <?php if (isset($_GET['settings-updated'])): ?>
        <div class="notice notice-success is-dismissible">
            <p>Settings saved successfully!</p>
        </div>
    <?php endif; ?>

    <form method="post" action="options.php" class="wp-fort-settings-form">
        <?php 
        settings_fields('wp_fort_options');
        ?>
        
        <div class="wp-fort-form-section">
            <h3>Custom Login URL</h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[login_protection_enabled]" value="1" 
                        <?php checked($options['login_protection_enabled'], 1); ?>>
                    Enable Custom Login URL Protection
                </label>
                <p class="wp-fort-form-help">
                    Hide the default wp-login.php and use a custom URL for admin access.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="custom_login_slug">Custom Login Slug</label>
                <input type="text" id="custom_login_slug" name="wp_fort_settings[custom_login_slug]" 
                    value="<?php echo esc_attr($options['custom_login_slug']); ?>" 
                    class="regular-text" placeholder="secure-admin">
                <p class="wp-fort-form-help">
                    Choose a unique slug for your login page. Example: 
                    <code><?php echo esc_url(home_url('secure-admin')); ?></code>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[block_wp_login]" value="1" 
                        <?php checked($options['block_wp_login'], 1); ?>>
                    Block Access to wp-login.php
                </label>
                <p class="wp-fort-form-help">
                    Completely block access to the default WordPress login page.
                </p>
            </div>

            <?php if ($options['login_protection_enabled'] && !empty($options['custom_login_slug'])): ?>
            <div class="wp-fort-form-row" style="background: #edfaef; padding: 15px; border-radius: 4px; border-left: 4px solid #00a32a;">
                <strong>Your Custom Login URL:</strong><br>
                <code style="font-size: 16px; margin-top: 8px; display: inline-block;">
                    <?php echo esc_url(home_url($options['custom_login_slug'])); ?>
                </code>
                <p style="margin: 8px 0 0 0; color: #666;">
                    Bookmark this URL for future access.
                </p>
            </div>
            <?php endif; ?>
        </div>

        <div class="wp-fort-form-section">
            <h3>Brute Force Protection</h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[brute_force_protection]" value="1" 
                        <?php checked($options['brute_force_protection'], 1); ?>>
                    Enable Brute Force Protection
                </label>
                <p class="wp-fort-form-help">
                    Automatically block IP addresses after multiple failed login attempts.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="max_login_attempts">Maximum Login Attempts</label>
                <input type="number" id="max_login_attempts" name="wp_fort_settings[max_login_attempts]" 
                    value="<?php echo esc_attr($options['max_login_attempts']); ?>" 
                    min="1" max="20" class="small-text">
                <p class="wp-fort-form-help">
                    Number of failed login attempts before temporary lockout.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="lockout_duration">Lockout Duration (minutes)</label>
                <input type="number" id="lockout_duration" name="wp_fort_settings[lockout_duration]" 
                    value="<?php echo esc_attr($options['lockout_duration']); ?>" 
                    min="1" max="1440" class="small-text">
                <p class="wp-fort-form-help">
                    How long to block IP addresses after reaching maximum attempts.
                </p>
            </div>
        </div>

        <div class="wp-fort-form-section">
            <h3>Additional Login Security</h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[log_failed_logins]" value="1" 
                        <?php checked($options['log_failed_logins'], 1); ?>>
                    Log Failed Login Attempts
                </label>
                <p class="wp-fort-form-help">
                    Record all failed login attempts in security logs.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[log_successful_logins]" value="1" 
                        <?php checked($options['log_successful_logins'], 1); ?>>
                    Log Successful Logins
                </label>
                <p class="wp-fort-form-help">
                    Record successful admin logins for audit purposes.
                </p>
            </div>
        </div>

        <div class="wp-fort-form-row">
            <?php submit_button('Save Settings', 'primary', 'submit'); ?>
        </div>
    </form>

    <div class="wp-fort-form-section">
        <h3>Security Tips</h3>
        <ul style="list-style: disc; padding-left: 20px;">
            <li>Always use a strong, unique custom login slug</li>
            <li>Enable brute force protection to prevent automated attacks</li>
            <li>Combine with IP restrictions for maximum security</li>
            <li>Regularly monitor your security logs for suspicious activity</li>
        </ul>
    </div>
</div>


ip-restrictions.php

<?php
/**
 * WP Fort IP Restrictions Management
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}

$current_ip = WP_Fort_Core::get_client_ip();
?>

<div class="wrap wp-fort-admin">
    <div class="wp-fort-header">
        <h1>IP Restrictions Management</h1>
        <p>Control access to your WordPress admin by allowing specific IP addresses only.</p>
    </div>

    <?php if (isset($_GET['settings-updated'])): ?>
        <div class="notice notice-success is-dismissible">
            <p>Settings saved successfully!</p>
        </div>
    <?php endif; ?>

    <form method="post" action="options.php" class="wp-fort-settings-form">
        <?php settings_fields('wp_fort_options'); ?>
        
        <div class="wp-fort-form-section">
            <h3>IP Restriction Settings</h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[ip_restriction_enabled]" value="1" 
                        <?php checked($options['ip_restriction_enabled'], 1); ?>>
                    Enable IP Restriction
                </label>
                <p class="wp-fort-form-help">
                    Only allow access to admin area from specific IP addresses.
                    <strong style="color: #d63638;">
                        Warning: Make sure your IP is added below before enabling!
                    </strong>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <div style="background: #f0f6fc; padding: 15px; border-radius: 4px; border-left: 4px solid #2271b1;">
                    <strong>Your Current IP Address:</strong><br>
                    <code style="font-size: 16px; margin-top: 8px; display: inline-block;">
                        <?php echo esc_html($current_ip); ?>
                    </code>
                    <?php if (!in_array($current_ip, $options['allowed_ips'])): ?>
                        <p style="margin: 8px 0 0 0; color: #d63638;">
                            <strong>Warning:</strong>
                            Your current IP is not in the whitelist. You may get locked out!
                        </p>
                    <?php else: ?>
                        <p style="margin: 8px 0 0 0; color: #00a32a;">
                            Your IP is in the whitelist. You are safe.
                        </p>
                    <?php endif; ?>
                </div>
            </div>
        </div>

        <div class="wp-fort-form-row">
            <?php submit_button('Save Settings', 'primary', 'submit'); ?>
        </div>
    </form>

    <div class="wp-fort-form-section">
        <h3>IP Address Management</h3>
        
        <div class="wp-fort-form-row">
            <label for="new_ip_address">Add IP Address</label>
            <input type="text" id="new_ip_address" class="wp-fort-ip-input" 
                placeholder="192.168.1.1" style="width: 200px;">
            <button type="button" class="wp-fort-btn wp-fort-add-ip" style="margin-left: 10px;">
                Add IP
            </button>
            <p class="wp-fort-form-help">
                Enter a valid IP address to add to the whitelist.
            </p>
        </div>

        <div class="wp-fort-form-row">
            <label>Allowed IP Addresses</label>
            
            <?php if (empty($options['allowed_ips'])): ?>
                <div style="background: #fcf9e8; padding: 20px; text-align: center; border-radius: 4px;">
                    <p style="margin: 0; color: #dba617;">
                        <strong>No IP addresses in whitelist.</strong><br>
                        Add your IP address above to prevent getting locked out.
                    </p>
                </div>
            <?php else: ?>
                <div class="wp-fort-ip-list">
                    <?php foreach ($options['allowed_ips'] as $ip): ?>
                        <div class="wp-fort-ip-item <?php echo $ip === $current_ip ? 'wp-fort-ip-current' : ''; ?>">
                            <div class="wp-fort-ip-address">
                                <code><?php echo esc_html($ip); ?></code>
                                <?php if ($ip === $current_ip): ?>
                                    <span style="background: #2271b1; color: #fff; padding: 2px 6px; border-radius: 3px; font-size: 11px; margin-left: 8px;">
                                        Current
                                    </span>
                                <?php endif; ?>
                            </div>
                            <div class="wp-fort-ip-actions">
                                <button type="button" class="wp-fort-btn wp-fort-btn-danger wp-fort-remove-ip" 
                                    data-ip="<?php echo esc_attr($ip); ?>">
                                    Remove
                                </button>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php endif; ?>
        </div>
    </div>

    <div class="wp-fort-form-section">
        <h3>IP Management Tips</h3>
        <ul style="list-style: disc; padding-left: 20px;">
            <li>Always add your current IP address before enabling restrictions</li>
            <li>Consider adding your office IP range if you work from multiple locations</li>
            <li>Use CIDR notation for IP ranges (e.g., 192.168.1.0/24)</li>
            <li>Regularly review and update your IP whitelist</li>
        </ul>
        
        <h4>Common IP Ranges</h4>
        <table style="width: 100%; border-collapse: collapse;">
            <thead>
                <tr style="background: #f6f7f7;">
                    <th style="padding: 10px; text-align: left; border: 1px solid #dcdcde;">Description</th>
                    <th style="padding: 10px; text-align: left; border: 1px solid #dcdcde;">IP Range</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;">Local Network</td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>192.168.0.0/16</code></td>
                </tr>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;">Private Network</td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>10.0.0.0/8</code></td>
                </tr>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;">Localhost</td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>127.0.0.1</code></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>


firewall.php

<?php
/**
 * WP Fort Firewall Settings
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}
?>

<div class="wrap wp-fort-admin">
    <div class="wp-fort-header">
        <h1>Firewall Settings</h1>
        <p>Protect your website from malicious requests and attacks with advanced firewall rules.</p>
    </div>

    <?php if (isset($_GET['settings-updated'])): ?>
        <div class="notice notice-success is-dismissible">
            <p>Settings saved successfully!</p>
        </div>
    <?php endif; ?>

    <form method="post" action="options.php" class="wp-fort-settings-form">
        <?php settings_fields('wp_fort_options'); ?>
        
        <div class="wp-fort-form-section">
            <h3>Firewall Protection</h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[firewall_enabled]" value="1" 
                        <?php checked($options['firewall_enabled'], 1); ?>>
                    Enable Firewall Protection
                </label>
                <p class="wp-fort-form-help">
                    Block malicious requests and protect against common web attacks.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[block_suspicious_requests]" value="1" 
                        <?php checked($options['block_suspicious_requests'], 1); ?>>
                    Block Suspicious Requests
                </label>
                <p class="wp-fort-form-help">
                    Automatically block requests with suspicious patterns (SQL injection, XSS attempts, etc.).
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[prevent_php_execution]" value="1" 
                        <?php checked($options['prevent_php_execution'], 1); ?>>
                    Prevent PHP Execution in Uploads
                </label>
                <p class="wp-fort-form-help">
                    Block PHP file execution in the uploads directory to prevent malware attacks.
                </p>
            </div>
        </div>

        <div class="wp-fort-form-section">
            <h3>Advanced Firewall Rules</h3>
            
            <div class="wp-fort-form-row">
                <label for="blocked_user_agents">Blocked User Agents</label>
                <textarea id="blocked_user_agents" name="wp_fort_settings[blocked_user_agents]" 
                    rows="5" class="large-text" placeholder="nmap&#10;sqlmap&#10;wpscan&#10;acunetix"
                    style="font-family: monospace;"></textarea>
                <p class="wp-fort-form-help">
                    List of user agents to block (one per line). Common security scanners are blocked by default.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="blocked_ips">Permanently Blocked IPs</label>
                <textarea id="blocked_ips" name="wp_fort_settings[blocked_ips]" 
                    rows="5" class="large-text" placeholder="123.456.789.0&#10;192.168.1.100"
                    style="font-family: monospace;"></textarea>
                <p class="wp-fort-form-help">
                    IP addresses to permanently block (one per line).
                </p>
            </div>
        </div>

        <div class="wp-fort-form-row">
            <?php submit_button('Save Settings', 'primary', 'submit'); ?>
        </div>
    </form>

    <div class="wp-fort-form-section">
        <h3>Firewall Statistics</h3>
        
        <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 20px;">
            <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                <div style="font-size: 24px; font-weight: bold; color: #2271b1;">0</div>
                <div>Requests Blocked Today</div>
            </div>
            <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                <div style="font-size: 24px; font-weight: bold; color: #2271b1;">0</div>
                <div>Malicious IPs Blocked</div>
            </div>
            <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                <div style="font-size: 24px; font-weight: bold; color: #2271b1;">0</div>
                <div>SQL Injection Attempts</div>
            </div>
            <div style="text-align: center; padding: 20px; background: #f6f7f7; border-radius: 6px;">
                <div style="font-size: 24px; font-weight: bold; color: #2271b1;">0</div>
                <div>XSS Attack Attempts</div>
            </div>
        </div>
    </div>

    <div class="wp-fort-form-section">
        <h3>Common Attack Patterns Blocked</h3>
        
        <ul style="list-style: disc; padding-left: 20px;">
            <li><strong>SQL Injection:</strong> UNION SELECT, DROP TABLE, INSERT INTO</li>
            <li><strong>XSS Attacks:</strong> script tags, javascript protocols, event handlers</li>
            <li><strong>Directory Traversal:</strong> ../ sequences, absolute paths</li>
            <li><strong>File Inclusion:</strong> include(), require(), file_get_contents()</li>
            <li><strong>Command Injection:</strong> system(), exec(), shell_exec()</li>
        </ul>
        
        <p style="margin-top: 15px; padding: 10px; background: #f0f6fc; border-radius: 4px;">
            The firewall automatically detects and blocks these patterns without requiring manual configuration.
        </p>
    </div>
</div>


security-logs.php

<?php
/**
 * WP Fort Security Logs Interface
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}

// Handle form submission
if (isset($_POST['wp_fort_logs_submit'])) {
    if (wp_verify_nonce($_POST['wp_fort_logs_nonce'], 'wp_fort_logs_save')) {
        $current_settings = $this->core->get_options();
        $new_settings = array();
        
        // Logging Settings
        $new_settings['logging_enabled'] = isset($_POST['logging_enabled']);
        $new_settings['log_retention_days'] = absint($_POST['log_retention_days'] ?? 30);
        $new_settings['log_failed_logins'] = isset($_POST['log_failed_logins']);
        $new_settings['log_successful_logins'] = isset($_POST['log_successful_logins']);
        
        // Merge with existing settings to preserve other options
        $merged_settings = array_merge($current_settings, $new_settings);
        $this->core->update_options($merged_settings);
        
        echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings saved successfully!', 'wp-fort') . '</p></div>';
    }
}
?>

<div class="wrap wp-fort-admin">
    <div class="wp-fort-header">
        <h1><?php _e('Security Logs', 'wp-fort'); ?></h1>
        <p><?php _e('Monitor and analyze security events on your WordPress website.', 'wp-fort'); ?></p>
    </div>

    <form method="post" class="wp-fort-settings-form">
        <?php wp_nonce_field('wp_fort_logs_save', 'wp_fort_logs_nonce'); ?>
        
        <div class="wp-fort-form-section">
            <h3><?php _e('Logging Settings', 'wp-fort'); ?></h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="logging_enabled" value="1" 
                        <?php checked($options['logging_enabled'], 1); ?>>
                    <?php _e('Enable Security Logging', 'wp-fort'); ?>
                </label>
                <p class="wp-fort-form-help">
                    <?php _e('Record security events, login attempts, and suspicious activities.', 'wp-fort'); ?>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="log_retention_days"><?php _e('Log Retention Period (days)', 'wp-fort'); ?></label>
                <input type="number" id="log_retention_days" name="log_retention_days" 
                    value="<?php echo esc_attr($options['log_retention_days']); ?>" 
                    min="1" max="365" class="small-text">
                <p class="wp-fort-form-help">
                    <?php _e('How long to keep security logs before automatic cleanup.', 'wp-fort'); ?>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="log_failed_logins" value="1" 
                        <?php checked($options['log_failed_logins'], 1); ?>>
                    <?php _e('Log Failed Login Attempts', 'wp-fort'); ?>
                </label>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="log_successful_logins" value="1" 
                        <?php checked($options['log_successful_logins'], 1); ?>>
                    <?php _e('Log Successful Admin Logins', 'wp-fort'); ?>
                </label>
            </div>
        </div>

        <div class="wp-fort-form-row">
            <?php submit_button(__('Save Settings', 'wp-fort'), 'primary', 'wp_fort_logs_submit'); ?>
        </div>
    </form>

    <div class="wp-fort-form-section">
        <h3><?php _e('Security Logs Management', 'wp-fort'); ?></h3>
        
        <div style="display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap;">
            <button type="button" class="wp-fort-btn wp-fort-refresh-logs">
                <?php _e('Refresh Logs', 'wp-fort'); ?>
            </button>
            <button type="button" class="wp-fort-btn wp-fort-btn-secondary wp-fort-export-logs">
                <?php _e('Export Logs', 'wp-fort'); ?>
            </button>
            <button type="button" class="wp-fort-btn wp-fort-btn-danger wp-fort-clear-logs">
                <?php _e('Clear All Logs', 'wp-fort'); ?>
            </button>
        </div>

        <div class="wp-fort-logs-container">
            <table class="wp-fort-logs-table">
                <thead>
                    <tr>
                        <th><?php _e('Timestamp', 'wp-fort'); ?></th>
                        <th><?php _e('Event Type', 'wp-fort'); ?></th>
                        <th><?php _e('IP Address', 'wp-fort'); ?></th>
                        <th><?php _e('Username', 'wp-fort'); ?></th>
                        <th><?php _e('Country', 'wp-fort'); ?></th>
                        <th><?php _e('Region', 'wp-fort'); ?></th>
                        <th><?php _e('City', 'wp-fort'); ?></th>
                        <th><?php _e('Severity', 'wp-fort'); ?></th>
                        <th><?php _e('Details', 'wp-fort'); ?></th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td colspan="9" style="text-align: center; padding: 40px;">
                            <div class="wp-fort-spinner" style="margin: 0 auto 20px auto;"></div>
                            <?php _e('Loading security logs...', 'wp-fort'); ?>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>

        <div class="wp-fort-logs-pagination" style="margin-top: 20px; text-align: center;">
            <!-- Pagination will be loaded via AJAX -->
        </div>
    </div>

    <div class="wp-fort-form-section">
        <h3><?php _e('Log Event Types', 'wp-fort'); ?></h3>
        
        <table style="width: 100%; border-collapse: collapse;">
            <thead>
                <tr style="background: #f6f7f7;">
                    <th style="padding: 10px; text-align: left; border: 1px solid #dcdcde;"><?php _e('Event Type', 'wp-fort'); ?></th>
                    <th style="padding: 10px; text-align: left; border: 1px solid #dcdcde;"><?php _e('Description', 'wp-fort'); ?></th>
                    <th style="padding: 10px; text-align: left; border: 1px solid #dcdcde;"><?php _e('Severity', 'wp-fort'); ?></th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>login_success</code></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><?php _e('Successful admin login', 'wp-fort'); ?></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><span class="wp-fort-severity low"><?php _e('Low', 'wp-fort'); ?></span></td>
                </tr>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>login_failed</code></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><?php _e('Failed login attempt', 'wp-fort'); ?></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><span class="wp-fort-severity medium"><?php _e('Medium', 'wp-fort'); ?></span></td>
                </tr>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>ip_blocked</code></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><?php _e('IP address blocked by firewall', 'wp-fort'); ?></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><span class="wp-fort-severity high"><?php _e('High', 'wp-fort'); ?></span></td>
                </tr>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>brute_force_detected</code></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><?php _e('Brute force attack detected', 'wp-fort'); ?></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><span class="wp-fort-severity critical"><?php _e('Critical', 'wp-fort'); ?></span></td>
                </tr>
                <tr>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><code>suspicious_request</code></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><?php _e('Suspicious HTTP request detected', 'wp-fort'); ?></td>
                    <td style="padding: 10px; border: 1px solid #dcdcde;"><span class="wp-fort-severity high"><?php _e('High', 'wp-fort'); ?></span></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

<script>
jQuery(document).ready(function($) {
    var currentPage = 1;
    
    // Load logs on page load
    loadLogs(currentPage);
    
    // Refresh logs button
    $('.wp-fort-refresh-logs').on('click', function() {
        currentPage = 1;
        loadLogs(currentPage);
    });
    
    // Export logs button
    $('.wp-fort-export-logs').on('click', function() {
        window.location.href = ajaxurl + '?action=wp_fort_export_logs&nonce=' + wp_fort_ajax.nonce;
    });
    
    // Clear logs button
    $('.wp-fort-clear-logs').on('click', function() {
        if (confirm('<?php _e('Are you sure you want to clear all security logs? This action cannot be undone.', 'wp-fort'); ?>')) {
            $.ajax({
                url: wp_fort_ajax.ajaxurl,
                type: 'POST',
                data: {
                    action: 'wp_fort_clear_logs',
                    nonce: wp_fort_ajax.nonce
                },
                success: function(response) {
                    if (response.success) {
                        alert(response.data);
                        loadLogs(1);
                    } else {
                        alert('Error: ' + response.data);
                    }
                }
            });
        }
    });
    
    // Load logs function
    function loadLogs(page) {
        $('.wp-fort-logs-container').addClass('loading');
        
        $.ajax({
            url: wp_fort_ajax.ajaxurl,
            type: 'POST',
            data: {
                action: 'wp_fort_get_logs',
                page: page,
                nonce: wp_fort_ajax.nonce
            },
            success: function(response) {
                $('.wp-fort-logs-container').removeClass('loading');
                
                if (response.success) {
                    displayLogs(response.data.logs);
                    displayPagination(response.data.total_pages, response.data.current_page);
                } else {
                    $('.wp-fort-logs-table tbody').html('<tr><td colspan="9" style="text-align: center; padding: 40px;">Error loading logs</td></tr>');
                }
            },
            error: function() {
                $('.wp-fort-logs-container').removeClass('loading');
                $('.wp-fort-logs-table tbody').html('<tr><td colspan="9" style="text-align: center; padding: 40px;">Error loading logs</td></tr>');
            }
        });
    }
    
    // Display logs in table
    function displayLogs(logs) {
        var tbody = $('.wp-fort-logs-table tbody');
        
        if (logs.length === 0) {
            tbody.html('<tr><td colspan="9" style="text-align: center; padding: 40px;">No security logs found</td></tr>');
            return;
        }
        
        var html = '';
        logs.forEach(function(log) {
            html += '<tr>';
            html += '<td>' + log.timestamp + '</td>';
            html += '<td><code>' + log.event_type + '</code></td>';
            html += '<td>' + (log.ip_address || '-') + '</td>';
            html += '<td>' + (log.username || '-') + '</td>';
            html += '<td>' + (log.country || '-') + '</td>';
            html += '<td>' + (log.region || '-') + '</td>';
            html += '<td>' + (log.city || '-') + '</td>';
            html += '<td><span class="wp-fort-severity ' + log.severity + '">' + log.severity + '</span></td>';
            html += '<td>' + (log.details || '-') + '</td>';
            html += '</tr>';
        });
        
        tbody.html(html);
    }
    
    // Display pagination
    function displayPagination(totalPages, currentPage) {
        var pagination = $('.wp-fort-logs-pagination');
        
        if (totalPages <= 1) {
            pagination.html('');
            return;
        }
        
        var html = '';
        
        // Previous button
        if (currentPage > 1) {
            html += '<button class="button wp-fort-page-btn" data-page="' + (currentPage - 1) + '">« Previous</button> ';
        }
        
        // Page numbers
        for (var i = 1; i <= totalPages; i++) {
            if (i === currentPage) {
                html += '<span class="wp-fort-current-page">' + i + '</span> ';
            } else {
                html += '<button class="button wp-fort-page-btn" data-page="' + i + '">' + i + '</button> ';
            }
        }
        
        // Next button
        if (currentPage < totalPages) {
            html += '<button class="button wp-fort-page-btn" data-page="' + (currentPage + 1) + '">Next »</button>';
        }
        
        pagination.html(html);
        
        // Pagination button events
        $('.wp-fort-page-btn').on('click', function() {
            currentPage = parseInt($(this).data('page'));
            loadLogs(currentPage);
        });
    }
});
</script>

<style>
.wp-fort-severity {
    padding: 4px 8px;
    border-radius: 3px;
    font-size: 11px;
    font-weight: bold;
    text-transform: uppercase;
}

.wp-fort-severity.low {
    background: #e8f5e8;
    color: #2e7d32;
}

.wp-fort-severity.medium {
    background: #fff3e0;
    color: #ef6c00;
}

.wp-fort-severity.high {
    background: #ffebee;
    color: #c62828;
}

.wp-fort-severity.critical {
    background: #fce4ec;
    color: #880e4f;
}

.wp-fort-logs-table {
    width: 100%;
    border-collapse: collapse;
}

.wp-fort-logs-table th,
.wp-fort-logs-table td {
    padding: 8px 12px;
    border: 1px solid #dcdcde;
    text-align: left;
}

.wp-fort-logs-table th {
    background: #f6f7f7;
    font-weight: 600;
}

.wp-fort-current-page {
    padding: 4px 8px;
    background: #2271b1;
    color: white;
    border-radius: 3px;
}

.wp-fort-spinner {
    border: 3px solid #f3f3f3;
    border-top: 3px solid #2271b1;
    border-radius: 50%;
    width: 30px;
    height: 30px;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
</style>


cloudflare.php

<?php
/**
 * WP Fort Cloudflare Integration
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}
?>

<div class="wrap wp-fort-admin">
    <div class="wp-fort-header">
        <h1>Cloudflare Integration</h1>
        <p>Enhance your website security with Cloudflare firewall and DDoS protection.</p>
    </div>

    <?php if (isset($_GET['settings-updated'])): ?>
        <div class="notice notice-success is-dismissible">
            <p>Settings saved successfully!</p>
        </div>
    <?php endif; ?>

    <form method="post" action="options.php" class="wp-fort-settings-form">
        <?php settings_fields('wp_fort_options'); ?>
        
        <div class="wp-fort-form-section">
            <h3>Cloudflare API Configuration</h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[cloudflare_enabled]" value="1" 
                        <?php checked($options['cloudflare_enabled'], 1); ?>>
                    Enable Cloudflare Integration
                </label>
                <p class="wp-fort-form-help">
                    Connect to Cloudflare API for enhanced security features.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="cloudflare_email">Cloudflare Email</label>
                <input type="email" id="cloudflare_email" name="wp_fort_settings[cloudflare_email]" 
                    value="<?php echo esc_attr($options['cloudflare_email']); ?>" 
                    class="regular-text" placeholder="your-email@example.com">
                <p class="wp-fort-form-help">
                    The email address associated with your Cloudflare account.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="cloudflare_api_key">Cloudflare API Key</label>
                <input type="password" id="cloudflare_api_key" name="wp_fort_settings[cloudflare_api_key]" 
                    value="<?php echo esc_attr($options['cloudflare_api_key']); ?>" 
                    class="regular-text" placeholder="Your Cloudflare API Key">
                <p class="wp-fort-form-help">
                    Get your API key from 
                    <a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank">https://dash.cloudflare.com/profile/api-tokens</a>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="cloudflare_zone_id">Zone ID</label>
                <input type="text" id="cloudflare_zone_id" name="wp_fort_settings[cloudflare_zone_id]" 
                    value="<?php echo esc_attr($options['cloudflare_zone_id']); ?>" 
                    class="regular-text" placeholder="Your Cloudflare Zone ID">
                <p class="wp-fort-form-help">
                    The Zone ID for your domain in Cloudflare.
                </p>
            </div>

            <?php if (!empty($options['cloudflare_api_key']) && !empty($options['cloudflare_zone_id'])): ?>
            <div class="wp-fort-form-row">
                <button type="button" class="wp-fort-btn wp-fort-btn-secondary" id="test-cloudflare-connection">
                    Test Cloudflare Connection
                </button>
                <span id="cloudflare-test-result" style="margin-left: 10px;"></span>
            </div>
            <?php endif; ?>
        </div>

        <div class="wp-fort-form-section">
            <h3>Cloudflare Security Features</h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[cloudflare_firewall_rules]" value="1" 
                        <?php checked($options['cloudflare_firewall_rules'] ?? false, 1); ?>>
                    Automatically Create Firewall Rules
                </label>
                <p class="wp-fort-form-help">
                    Automatically create Cloudflare firewall rules for blocked IPs and suspicious activities.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[cloudflare_threat_analytics]" value="1" 
                        <?php checked($options['cloudflare_threat_analytics'] ?? false, 1); ?>>
                    Enable Threat Analytics
                </label>
                <p class="wp-fort-form-help">
                    Sync security events with Cloudflare threat analytics for better insights.
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="wp_fort_settings[cloudflare_ddos_protection]" value="1" 
                        <?php checked($options['cloudflare_ddos_protection'] ?? false, 1); ?>>
                    Enhanced DDoS Protection
                </label>
                <p class="wp-fort-form-help">
                    Leverage Cloudflare's DDoS protection for your WordPress site.
                </p>
            </div>
        </div>

        <div class="wp-fort-form-row">
            <?php submit_button('Save Settings', 'primary', 'submit'); ?>
        </div>
    </form>

    <div class="wp-fort-form-section">
        <h3>Cloudflare Benefits</h3>
        
        <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;">
            <div style="padding: 20px; background: #f0f6fc; border-radius: 6px; border-left: 4px solid #2271b1;">
                <h4 style="margin-top: 0;">DDoS Protection</h4>
                <p style="margin: 0;">Protect your site from distributed denial-of-service attacks with Cloudflare's global network.</p>
            </div>
            
            <div style="padding: 20px; background: #f0f6fc; border-radius: 6px; border-left: 4px solid #2271b1;">
                <h4 style="margin-top: 0;">Web Application Firewall</h4>
                <p style="margin: 0;">Advanced WAF rules to block SQL injection, XSS, and other common attacks.</p>
            </div>
            
            <div style="padding: 20px; background: #f0f6fc; border-radius: 6px; border-left: 4px solid #2271b1;">
                <h4 style="margin-top: 0;">Threat Intelligence</h4>
                <p style="margin: 0;">Leverage Cloudflare's global threat intelligence to block malicious traffic.</p>
            </div>
            
            <div style="padding: 20px; background: #f0f6fc; border-radius: 6px; border-left: 4px solid #2271b1;">
                <h4 style="margin-top: 0;">Performance Boost</h4>
                <p style="margin: 0;">Improved site performance through Cloudflare's CDN and optimization features.</p>
            </div>
        </div>
    </div>

    <div class="wp-fort-form-section">
        <h3>Setup Instructions</h3>
        
        <ol style="padding-left: 20px;">
            <li>Sign up for a Cloudflare account at <a href="https://cloudflare.com" target="_blank">cloudflare.com</a></li>
            <li>Add your website to Cloudflare and update your domain's nameservers</li>
            <li>Go to your Cloudflare dashboard and navigate to My Profile > API Tokens</li>
            <li>Create an API token with appropriate permissions (Zone:Read, Zone:Write)</li>
            <li>Find your Zone ID in the Cloudflare dashboard under your domain overview</li>
            <li>Enter your Cloudflare email, API key, and Zone ID in the form above</li>
            <li>Test the connection and enable desired security features</li>
        </ol>
    </div>
</div>

<script>
jQuery(document).ready(function($) {
    $('#test-cloudflare-connection').on('click', function() {
        const $button = $(this);
        const $result = $('#cloudflare-test-result');
        
        $button.prop('disabled', true).text('Testing...');
        $result.html('<span class="wp-fort-testing">Testing connection to Cloudflare...</span>');
        
        // AJAX call to test Cloudflare connection
        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'wp_fort_test_cloudflare_connection',
                nonce: '<?php echo wp_create_nonce("wp_fort_cloudflare_test"); ?>'
            },
            success: function(response) {
                if (response.success) {
                    $result.html('<span class="wp-fort-success" style="color: #46b450;">✓ ' + response.data.message + '</span>');
                } else {
                    $result.html('<span class="wp-fort-error" style="color: #dc3232;">✗ ' + response.data + '</span>');
                }
            },
            error: function() {
                $result.html('<span class="wp-fort-error" style="color: #dc3232;">✗ Connection test failed. Please check your settings.</span>');
            },
            complete: function() {
                $button.prop('disabled', false).text('Test Cloudflare Connection');
            }
        });
    });
});
</script>


settings.php

<?php
/**
 * WP Fort General Settings
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}

// Handle form submission
if (isset($_POST['wp_fort_settings_submit'])) {
    if (wp_verify_nonce($_POST['wp_fort_settings_nonce'], 'wp_fort_settings_save')) {
        $current_settings = $this->core->get_options();
        $new_settings = array();
        
        // WordPress Hardening
        $new_settings['disable_xmlrpc'] = isset($_POST['disable_xmlrpc']);
        $new_settings['hide_wp_version'] = isset($_POST['hide_wp_version']);
        $new_settings['disable_file_edit'] = isset($_POST['disable_file_edit']);
        
        // Security Headers
        $new_settings['security_headers'] = isset($_POST['security_headers']);
        
        // Database Security
        $new_settings['db_prefix_change'] = isset($_POST['db_prefix_change']);
        $new_settings['custom_db_prefix'] = sanitize_text_field($_POST['custom_db_prefix'] ?? 'wp_');
        
        // Maintenance & Cleanup
        $new_settings['auto_cleanup_days'] = absint($_POST['auto_cleanup_days'] ?? 30);
        $new_settings['enable_debug_log'] = isset($_POST['enable_debug_log']);
        
        // Merge with existing settings to preserve other options
        $merged_settings = array_merge($current_settings, $new_settings);
        $this->core->update_options($merged_settings);
        
        echo '<div class="notice notice-success is-dismissible"><p>' . __('Settings saved successfully!', 'wp-fort') . '</p></div>';
    }
}
?>

<div class="wrap wp-fort-admin">
    <div class="wp-fort-header">
        <h1><?php _e('General Settings', 'wp-fort'); ?></h1>
        <p><?php _e('Configure general security settings and WordPress hardening options.', 'wp-fort'); ?></p>
    </div>

    <form method="post" class="wp-fort-settings-form">
        <?php wp_nonce_field('wp_fort_settings_save', 'wp_fort_settings_nonce'); ?>
        
        <div class="wp-fort-form-section">
            <h3><?php _e('WordPress Hardening', 'wp-fort'); ?></h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="disable_xmlrpc" value="1" 
                        <?php checked($options['disable_xmlrpc'], 1); ?> 
                        class="wp-fort-toggle">
                    <?php _e('Disable XML-RPC', 'wp-fort'); ?>
                </label>
                <p class="wp-fort-form-help">
                    <?php _e('XML-RPC can be exploited for brute force attacks. Disable if not needed.', 'wp-fort'); ?>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="hide_wp_version" value="1" 
                        <?php checked($options['hide_wp_version'], 1); ?>>
                    <?php _e('Hide WordPress Version', 'wp-fort'); ?>
                </label>
                <p class="wp-fort-form-help">
                    <?php _e('Remove WordPress version number from source code and RSS feeds.', 'wp-fort'); ?>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="disable_file_edit" value="1" 
                        <?php checked($options['disable_file_edit'], 1); ?>>
                    <?php _e('Disable File Editor', 'wp-fort'); ?>
                </label>
                <p class="wp-fort-form-help">
                    <?php _e('Prevent users from editing theme and plugin files from the WordPress admin.', 'wp-fort'); ?>
                </p>
            </div>
        </div>

        <div class="wp-fort-form-section">
            <h3><?php _e('Security Headers', 'wp-fort'); ?></h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="security_headers" value="1" 
                        <?php checked($options['security_headers'] ?? true, 1); ?> 
                        class="wp-fort-toggle">
                    <?php _e('Enable Security Headers', 'wp-fort'); ?>
                </label>
                <p class="wp-fort-form-help">
                    <?php _e('Add security headers to protect against XSS, clickjacking, and other attacks.', 'wp-fort'); ?>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label><?php _e('Current Security Headers', 'wp-fort'); ?></label>
                <div style="background: #f6f7f7; padding: 15px; border-radius: 4px; font-family: monospace; font-size: 12px;">
                    X-Content-Type-Options: nosniff<br>
                    X-Frame-Options: SAMEORIGIN<br>
                    X-XSS-Protection: 1; mode=block<br>
                    Referrer-Policy: strict-origin-when-cross-origin<br>
                    <?php if (is_ssl()): ?>
                    Strict-Transport-Security: max-age=31536000; includeSubDomains
                    <?php endif; ?>
                </div>
            </div>
        </div>

        <div class="wp-fort-form-section">
            <h3><?php _e('Database Security', 'wp-fort'); ?></h3>
            
            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="db_prefix_change" value="1" 
                        <?php checked($options['db_prefix_change'] ?? false, 1); ?>>
                    <?php _e('Change Database Prefix', 'wp-fort'); ?>
                </label>
                <p class="wp-fort-form-help">
                    <?php _e('Change WordPress database table prefix from default wp_ to something unique.', 'wp-fort'); ?>
                    <strong style="color: #d63638;">
                        <?php _e('Backup your database before enabling this feature!', 'wp-fort'); ?>
                    </strong>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label for="custom_db_prefix"><?php _e('Custom Database Prefix', 'wp-fort'); ?></label>
                <input type="text" id="custom_db_prefix" name="custom_db_prefix" 
                    value="<?php echo esc_attr($options['custom_db_prefix'] ?? 'wp_'); ?>" 
                    class="regular-text" placeholder="wp_">
                <p class="wp-fort-form-help">
                    <?php _e('Use alphanumeric characters and underscores only. Must end with underscore.', 'wp-fort'); ?>
                </p>
            </div>
        </div>

        <div class="wp-fort-form-section">
            <h3><?php _e('Maintenance & Cleanup', 'wp-fort'); ?></h3>
            
            <div class="wp-fort-form-row">
                <label for="auto_cleanup_days"><?php _e('Auto Cleanup Logs (days)', 'wp-fort'); ?></label>
                <input type="number" id="auto_cleanup_days" name="auto_cleanup_days" 
                    value="<?php echo esc_attr($options['auto_cleanup_days'] ?? 30); ?>" 
                    min="1" max="365" class="small-text">
                <p class="wp-fort-form-help">
                    <?php _e('Automatically delete security logs older than specified days.', 'wp-fort'); ?>
                </p>
            </div>

            <div class="wp-fort-form-row">
                <label>
                    <input type="checkbox" name="enable_debug_log" value="1" 
                        <?php checked($options['enable_debug_log'] ?? false, 1); ?>>
                    <?php _e('Enable Debug Logging', 'wp-fort'); ?>
                </label>
                <p class="wp-fort-form-help">
                    <?php _e('Log debug information for troubleshooting purposes. Disable in production.', 'wp-fort'); ?>
                </p>
            </div>
        </div>

        <div class="wp-fort-form-row">
            <?php submit_button(__('Save Settings', 'wp-fort'), 'primary', 'wp_fort_settings_submit'); ?>
        </div>
    </form>

    <div class="wp-fort-form-section">
        <h3><?php _e('Plugin Information', 'wp-fort'); ?></h3>
        
        <table style="width: 100%; border-collapse: collapse;">
            <tr>
                <td style="padding: 10px; border: 1px solid #dcdcde; width: 200px; background: #f6f7f7;">
                    <strong><?php _e('Plugin Version', 'wp-fort'); ?></strong>
                </td>
                <td style="padding: 10px; border: 1px solid #dcdcde;">
                    <?php echo esc_html(WP_FORT_VERSION); ?>
                </td>
            </tr>
            <tr>
                <td style="padding: 10px; border: 1px solid #dcdcde; background: #f6f7f7;">
                    <strong><?php _e('WordPress Version', 'wp-fort'); ?></strong>
                </td>
                <td style="padding: 10px; border: 1px solid #dcdcde;">
                    <?php echo esc_html(get_bloginfo('version')); ?>
                </td>
            </tr>
            <tr>
                <td style="padding: 10px; border: 1px solid #dcdcde; background: #f6f7f7;">
                    <strong><?php _e('PHP Version', 'wp-fort'); ?></strong>
                </td>
                <td style="padding: 10px; border: 1px solid #dcdcde;">
                    <?php echo esc_html(phpversion()); ?>
                </td>
            </tr>
            <tr>
                <td style="padding: 10px; border: 1px solid #dcdcde; background: #f6f7f7;">
                    <strong><?php _e('Database Version', 'wp-fort'); ?></strong>
                </td>
                <td style="padding: 10px; border: 1px solid #dcdcde;">
                    <?php global $wpdb; echo esc_html($wpdb->db_version()); ?>
                </td>
            </tr>
            <tr>
                <td style="padding: 10px; border: 1px solid #dcdcde; background: #f6f7f7;">
                    <strong><?php _e('Security Logs Count', 'wp-fort'); ?></strong>
                </td>
                <td style="padding: 10px; border: 1px solid #dcdcde;">
                    <?php
                    global $wpdb;
                    $table_name = $wpdb->prefix . 'wp_fort_security_logs';
                    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name) {
                        $logs_count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
                        echo esc_html($logs_count);
                    } else {
                        echo '0';
                    }
                    ?>
                </td>
            </tr>
        </table>
    </div>

    <div class="wp-fort-form-section">
        <h3><?php _e('Quick Actions', 'wp-fort'); ?></h3>
        
        <div style="display: flex; gap: 10px; flex-wrap: wrap;">
            <button type="button" class="wp-fort-btn wp-fort-btn-danger" id="reset-settings">
                <?php _e('Reset All Settings', 'wp-fort'); ?>
            </button>
            <button type="button" class="wp-fort-btn wp-fort-btn-secondary" id="export-settings">
                <?php _e('Export Settings', 'wp-fort'); ?>
            </button>
            <button type="button" class="wp-fort-btn wp-fort-btn-secondary" id="import-settings">
                <?php _e('Import Settings', 'wp-fort'); ?>
            </button>
            <a href="<?php echo admin_url('admin.php?page=wp-fort&tab=debug'); ?>" class="wp-fort-btn wp-fort-btn-secondary">
                <?php _e('Debug Information', 'wp-fort'); ?>
            </a>
        </div>
    </div>
</div>

<script>
jQuery(document).ready(function($) {
    $('#reset-settings').on('click', function() {
        if (confirm('<?php _e('Are you sure you want to reset all WP Fort settings? This action cannot be undone.', 'wp-fort'); ?>')) {
            // AJAX call to reset settings
            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'wp_fort_reset_settings',
                    nonce: '<?php echo wp_create_nonce('wp_fort_ajax_nonce'); ?>'
                },
                success: function(response) {
                    if (response.success) {
                        alert(response.data);
                        location.reload();
                    } else {
                        alert('Error: ' + response.data);
                    }
                }
            });
        }
    });
    
    $('#export-settings').on('click', function() {
        alert('<?php _e('Settings export functionality would be implemented here.', 'wp-fort'); ?>');
    });
    
    $('#import-settings').on('click', function() {
        alert('<?php _e('Settings import functionality would be implemented here.', 'wp-fort'); ?>');
    });
});
</script>

wp-fort/assets/

images/
icon-128×128.png
icon-256×256.png
banner-772×250.png

css/

frontend.css

empty


js/

frontend.js

empty

wp-fort/templates/

custom-login.php

<?php
/**
 * WP Fort Custom Login Template
 * 
 * @package WP_Fort
 * @since 1.0.0
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

// Get WP Fort instance
$wp_fort = wp_fort();
$options = $wp_fort->core->get_options();

// Set up login URL
$login_url = site_url('wp-login.php', 'login');
if ($options['login_protection_enabled'] && !empty($options['custom_login_slug'])) {
    $login_url = home_url($options['custom_login_slug']);
}

// Handle login form submission
if (isset($_POST['wp-fort-login'])) {
    $this->handle_custom_login($_POST);
}

// Add security headers
header('X-Frame-Options: SAMEORIGIN');
header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block');

?><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login - <?php echo get_bloginfo('name'); ?></title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
        }

        .login-container {
            background: white;
            border-radius: 12px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            width: 100%;
            max-width: 400px;
            overflow: hidden;
        }

        .login-header {
            background: #2271b1;
            color: white;
            padding: 30px 20px;
            text-align: center;
        }

        .login-header h1 {
            font-size: 24px;
            font-weight: 600;
            margin-bottom: 8px;
        }

        .login-header p {
            opacity: 0.9;
            font-size: 14px;
        }

        .login-form {
            padding: 30px;
        }

        .form-group {
            margin-bottom: 20px;
        }

        .form-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: #2c3338;
            font-size: 14px;
        }

        .form-group input {
            width: 100%;
            padding: 12px 16px;
            border: 2px solid #dcdcde;
            border-radius: 6px;
            font-size: 16px;
            transition: all 0.3s ease;
        }

        .form-group input:focus {
            outline: none;
            border-color: #2271b1;
            box-shadow: 0 0 0 3px rgba(34, 113, 177, 0.1);
        }

        .login-button {
            width: 100%;
            background: #2271b1;
            color: white;
            border: none;
            padding: 14px 20px;
            border-radius: 6px;
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            transition: background 0.3s ease;
        }

        .login-button:hover {
            background: #135e96;
        }

        .login-button:disabled {
            background: #a7aaad;
            cursor: not-allowed;
        }

        .login-links {
            margin-top: 20px;
            text-align: center;
            font-size: 14px;
        }

        .login-links a {
            color: #2271b1;
            text-decoration: none;
        }

        .login-links a:hover {
            text-decoration: underline;
        }

        .security-notice {
            background: #f0f6fc;
            border: 1px solid #2271b1;
            border-radius: 6px;
            padding: 12px 16px;
            margin-bottom: 20px;
            font-size: 13px;
            color: #2271b1;
        }

        .error-message {
            background: #fcf0f1;
            border: 1px solid #d63638;
            border-radius: 6px;
            padding: 12px 16px;
            margin-bottom: 20px;
            font-size: 13px;
            color: #d63638;
        }

        .success-message {
            background: #edfaef;
            border: 1px solid #00a32a;
            border-radius: 6px;
            padding: 12px 16px;
            margin-bottom: 20px;
            font-size: 13px;
            color: #00a32a;
        }

        .loading-spinner {
            display: inline-block;
            width: 16px;
            height: 16px;
            border: 2px solid #ffffff;
            border-top: 2px solid transparent;
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin-right: 8px;
            vertical-align: middle;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        @media (max-width: 480px) {
            .login-container {
                margin: 0;
                border-radius: 0;
                min-height: 100vh;
            }
            
            body {
                padding: 0;
                background: white;
            }
        }
    </style>
</head>
<body>
    <div class="login-container">
        <div class="login-header">
            <h1>Secure Login</h1>
            <p><?php echo get_bloginfo('name'); ?></p>
        </div>

        <div class="login-form">
            <?php if (isset($_GET['loggedout']) && $_GET['loggedout'] == 'true'): ?>
                <div class="success-message">
                    You have been successfully logged out.
                </div>
            <?php endif; ?>

            <?php if (isset($_GET['login']) && $_GET['login'] == 'failed'): ?>
                <div class="error-message">
                    Invalid login credentials. Please try again.
                </div>
            <?php endif; ?>

            <?php if (isset($_GET['error']) && $_GET['error'] == 'empty_fields'): ?>
                <div class="error-message">
                    Please enter both username and password.
                </div>
            <?php endif; ?>

            <div class="security-notice">
                <strong>Security Protected:</strong> This login is secured by WP Fort.
            </div>

            <form method="post" action="<?php echo esc_url($login_url); ?>" id="wp-fort-login-form">
                <input type="hidden" name="wp-fort-login" value="1">
                
                <div class="form-group">
                    <label for="username">Username or Email</label>
                    <input type="text" id="username" name="log" required autocomplete="username">
                </div>

                <div class="form-group">
                    <label for="password">Password</label>
                    <input type="password" id="password" name="pwd" required autocomplete="current-password">
                </div>

                <div class="form-group">
                    <label>
                        <input type="checkbox" name="rememberme" value="forever">
                        Remember Me
                    </label>
                </div>

                <button type="submit" class="login-button" id="login-submit">
                    <span class="button-text">Log In</span>
                </button>
            </form>

            <div class="login-links">
                <?php if (get_option('users_can_register')): ?>
                    <p><a href="<?php echo esc_url(wp_registration_url()); ?>">Register</a></p>
                <?php endif; ?>
                <p><a href="<?php echo esc_url(wp_lostpassword_url()); ?>">Lost your password?</a></p>
                <p><a href="<?php echo esc_url(home_url()); ?>">← Back to site</a></p>
            </div>
        </div>
    </div>

    <script>
        document.getElementById('wp-fort-login-form').addEventListener('submit', function(e) {
            const submitButton = document.getElementById('login-submit');
            const buttonText = submitButton.querySelector('.button-text');
            
            // Disable button and show loading
            submitButton.disabled = true;
            buttonText.innerHTML = '<span class="loading-spinner"></span> Logging in...';
            
            // Basic client-side validation
            const username = document.getElementById('username').value.trim();
            const password = document.getElementById('password').value.trim();
            
            if (!username || !password) {
                e.preventDefault();
                alert('Please enter both username and password.');
                submitButton.disabled = false;
                buttonText.textContent = 'Log In';
                return false;
            }
        });

        // Add some security enhancements
        document.addEventListener('DOMContentLoaded', function() {
            // Prevent copy-paste on password field (optional)
            const passwordField = document.getElementById('password');
            passwordField.addEventListener('copy', function(e) {
                e.preventDefault();
            });
            passwordField.addEventListener('paste', function(e) {
                e.preventDefault();
            });

            // Auto-focus username field
            document.getElementById('username').focus();

            // Add input sanitization
            const inputs = document.querySelectorAll('input[type="text"], input[type="password"]');
            inputs.forEach(input => {
                input.addEventListener('input', function(e) {
                    // Remove potentially dangerous characters
                    this.value = this.value.replace(/[<>]/g, '');
                });
            });
        });

        // Protect against brute force by adding delay
        let loginAttempts = 0;
        const maxAttempts = 5;
        
        document.getElementById('wp-fort-login-form').addEventListener('submit', function(e) {
            loginAttempts++;
            
            if (loginAttempts > maxAttempts) {
                e.preventDefault();
                alert('Too many login attempts. Please wait a few minutes before trying again.');
                return false;
            }
            
            // Add increasing delay for multiple attempts
            if (loginAttempts > 2) {
                e.preventDefault();
                setTimeout(() => {
                    this.submit();
                }, (loginAttempts - 2) * 1000);
                return false;
            }
        });
    </script>
</body>
</html>


security-lockout.php

empty

wp-fort/languages/wp-fort.pot

/[language-packs]