<?php
if (!defined('ABSPATH')) {
	exit; // Exit if accessed directly
}

class AIOWPSecurity_Firewall_Menu extends AIOWPSecurity_Admin_Menu {

	/**
	 * Firewall menu slug
	 *
	 * @var string
	 */
	protected $menu_page_slug = AIOWPSEC_FIREWALL_MENU_SLUG;

	/**
	 * Constructor adds menu for Firewall
	 */
	public function __construct() {
		parent::__construct(__('Firewall', 'all-in-one-wp-security-and-firewall'));
	}

	/**
	 * This function will setup the menus tabs by setting the array $menu_tabs
	 *
	 * @return void
	 */
	protected function setup_menu_tabs() {
		$menu_tabs = array(
			'basic-firewall' => array(
				'title' => __('Basic firewall rules', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_basic_firewall'),
			),
			'additional-firewall' => array(
				'title' => __('Additional firewall rules', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_additional_firewall'),
			),
			'6g-firewall' => array(
				'title' => __('6G Blacklist firewall rules', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_6g_firewall'),
			),
			'internet-bots' => array(
				'title' => __('Internet bots', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_internet_bots'),
			),
			'prevent-hotlinks' => array(
				'title' => __('Prevent hotlinks', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_prevent_hotlinks'),
			),
			'404-detection' => array(
				'title' => __('404 detection', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_404_detection'),
			),
			'custom-rules' => array(
				'title' => __('Custom rules', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_custom_rules'),
			),
			'advanced-settings' => array(
				'title' => __('Advanced settings', 'all-in-one-wp-security-and-firewall'),
				'render_callback' => array($this, 'render_advanced_settings'),
			),
		);

		$this->menu_tabs = array_filter($menu_tabs, array($this, 'should_display_tab'));
	}

	/**
	 * Renders the Basic Firewall tab
	 *
	 * @return void
	 */
	protected function render_basic_firewall() {
		global $aiowps_feature_mgr;
		global $aio_wp_security;
		global $aiowps_firewall_config;

		if (isset($_POST['aiowps_apply_basic_firewall_settings'])) { // Do form submission tasks
			$nonce = $_POST['_wpnonce'];
			if (!wp_verify_nonce($nonce, 'aiowpsec-enable-basic-firewall-nonce')) {
				$aio_wp_security->debug_logger->log_debug("Nonce check failed on enable basic firewall settings", 4);
				die("Nonce check failed on enable basic firewall settings");
			}

			// Max file upload size in basic rules
			$upload_size = absint($_POST['aiowps_max_file_upload_size']);

			$max_allowed = apply_filters('aiowps_max_allowed_upload_config', 250); // Set a filterable limit of 250MB
			$max_allowed = absint($max_allowed);

			if ($upload_size > $max_allowed) {
				$upload_size = $max_allowed;
			} elseif (empty($upload_size)) {
				$upload_size = AIOS_FIREWALL_MAX_FILE_UPLOAD_LIMIT_MB;
			}

			//Save settings
			$aio_wp_security->configs->set_value('aiowps_enable_basic_firewall', isset($_POST["aiowps_enable_basic_firewall"]) ? '1' : '');
			$aio_wp_security->configs->set_value('aiowps_max_file_upload_size', $upload_size);
			$aiowps_firewall_config->set_value('aiowps_enable_pingback_firewall', isset($_POST["aiowps_enable_pingback_firewall"]));
			$aio_wp_security->configs->set_value('aiowps_disable_xmlrpc_pingback_methods', isset($_POST["aiowps_disable_xmlrpc_pingback_methods"]) ? '1' : ''); //this disables only pingback methods of xmlrpc but leaves other methods so that Jetpack and other apps will still work
			$aio_wp_security->configs->set_value('aiowps_disable_rss_and_atom_feeds', isset($_POST['aiowps_disable_rss_and_atom_feeds']) ? '1' : '');
			$aio_wp_security->configs->set_value('aiowps_block_debug_log_file_access', isset($_POST["aiowps_block_debug_log_file_access"]) ? '1' : '');

			//Commit the config settings
			$aio_wp_security->configs->save_config();

			//Recalculate points after the feature status/options have been altered
			$aiowps_feature_mgr->check_feature_status_and_recalculate_points();

			//Now let's write the applicable rules to the .htaccess file
			$res = AIOWPSecurity_Utility_Htaccess::write_to_htaccess();

			if ($res) {
				$this->show_msg_updated(__('Settings were successfully saved', 'all-in-one-wp-security-and-firewall'));
			} else {
				$this->show_msg_error(__('Could not write to the .htaccess file. Please check the file permissions.', 'all-in-one-wp-security-and-firewall'));
			}
		}

		$aio_wp_security->include_template('wp-admin/firewall/basic-firewall.php');
		
	}

	/**
	 * Renders the Additional Firewall tab
	 *
	 * @return void
	 */
	protected function render_additional_firewall() {
		global $aio_wp_security;
		global $aiowps_feature_mgr;
		global $aiowps_firewall_config;

		$error = '';
		if(isset($_POST['aiowps_apply_additional_firewall_settings'])) { // Do advanced firewall submission tasks
			$nonce = $_POST['_wpnonce'];
			if (!wp_verify_nonce($nonce, 'aiowpsec-enable-additional-firewall-nonce')) {
				$aio_wp_security->debug_logger->log_debug("Nonce check failed on enable advanced firewall settings", 4);
				die("Nonce check failed on enable advanced firewall settings");
			}

			//Save settings
			if (isset($_POST['aiowps_disable_index_views'])) {
				$aio_wp_security->configs->set_value('aiowps_disable_index_views', '1');
			} else {
				$aio_wp_security->configs->set_value('aiowps_disable_index_views', '');
			}

			if (isset($_POST['aiowps_disable_trace_and_track'])) {
				$aio_wp_security->configs->set_value('aiowps_disable_trace_and_track', '1');
			} else {
				$aio_wp_security->configs->set_value('aiowps_disable_trace_and_track', '');
			}

			$aiowps_firewall_config->set_value('aiowps_forbid_proxy_comments', isset($_POST['aiowps_forbid_proxy_comments']));
			$aiowps_firewall_config->set_value('aiowps_deny_bad_query_strings', isset($_POST['aiowps_deny_bad_query_strings']));
			$aiowps_firewall_config->set_value('aiowps_advanced_char_string_filter', isset($_POST['aiowps_advanced_char_string_filter']));

			//Commit the config settings
			$aio_wp_security->configs->save_config();

			//Recalculate points after the feature status/options have been altered
			$aiowps_feature_mgr->check_feature_status_and_recalculate_points();

			//Now let's write the applicable rules to the .htaccess file
			$res = AIOWPSecurity_Utility_Htaccess::write_to_htaccess();

			if ($res) {
				$this->show_msg_updated(__('You have successfully saved the Additional Firewall Protection configuration', 'all-in-one-wp-security-and-firewall'));
			} else {
				$this->show_msg_error(__('Could not write to the .htaccess file. Please check the file permissions.', 'all-in-one-wp-security-and-firewall'));
			}

			if ($error) {
				$this->show_msg_error($error);
			}

		}
		
		$aio_wp_security->include_template('wp-admin/firewall/additional-firewall.php');
	}
	
	/**
	 * Renders the 6G Blacklist Firewall Rules tab
	 *
	 * @return void
	 */
	protected function render_6g_firewall() {
		global $aio_wp_security, $aiowps_feature_mgr, $aiowps_firewall_config;

		$block_request_methods = array_map('strtolower', AIOS_Abstracted_Ids::get_firewall_block_request_methods());

		//Other 6G settings form submission
		if (isset($_POST['aiowps_apply_6g_other_settings'])) {

			if (!wp_verify_nonce($_POST['_wpnonce'], 'aiowpsec-other-6g-settings-nonce')) {
				$aio_wp_security->debug_logger->log_debug('Nonce check failed for other 6G settings.');
				die("Nonce check failed");
			}
		
			$aiowps_firewall_config->set_value('aiowps_6g_block_query', (bool) isset($_POST['aiowps_block_query']));
			$aiowps_firewall_config->set_value('aiowps_6g_block_request', (bool) isset($_POST['aiowps_block_request']));
			$aiowps_firewall_config->set_value('aiowps_6g_block_referrers', (bool) isset($_POST['aiowps_block_refs']));
			$aiowps_firewall_config->set_value('aiowps_6g_block_agents', (bool) isset($_POST['aiowps_block_agents']));
		}

		//Block request methods form
		if (isset($_POST['aiowps_apply_6g_block_request_methods_settings'])) {

			if (!wp_verify_nonce($_POST['_wpnonce'], 'aiowpsec-6g-block-request-methods-nonce')) {
				$aio_wp_security->debug_logger->log_debug('Nonce check failed for blocking HTTP request methods');
				die("Nonce check failed");
			}
		
			$methods = array();

			foreach ($block_request_methods as $block_request_method) {
				if (isset($_POST['aiowps_block_request_method_'.$block_request_method])) {
					$methods[] = strtoupper($block_request_method);
				}
			}

			$aiowps_firewall_config->set_value('aiowps_6g_block_request_methods', $methods);
		}

		//Save 6G/5G
		if (isset($_POST['aiowps_apply_5g_6g_firewall_settings'])) {
			if (!wp_verify_nonce($_POST['_wpnonce'], 'aiowpsec-enable-5g-6g-firewall-nonce')) {
				$aio_wp_security->debug_logger->log_debug("Nonce check failed on enable 5G/6G firewall settings", 4);
				die("Nonce check failed on enable 5G/6G firewall settings");
			}

			// If the user has changed the 5G firewall checkbox settings, then there is a need yo write htaccess rules again.
			$is_5G_firewall_option_changed = ((isset($_POST['aiowps_enable_5g_firewall']) && '1' != $aio_wp_security->configs->get_value('aiowps_enable_5g_firewall')) || (!isset($_POST['aiowps_enable_5g_firewall']) && '1' == $aio_wp_security->configs->get_value('aiowps_enable_5g_firewall')));

			//Save settings
			if (isset($_POST['aiowps_enable_5g_firewall'])) {
				$aio_wp_security->configs->set_value('aiowps_enable_5g_firewall', '1');
			} else {
				$aio_wp_security->configs->set_value('aiowps_enable_5g_firewall', '');
			}

			if ($is_5G_firewall_option_changed) {
				$res = AIOWPSecurity_Utility_Htaccess::write_to_htaccess(); // let's write the applicable rules to the .htaccess file
			}

			if (isset($_POST['aiowps_enable_6g_firewall'])) {
				$aiowps_6g_block_request_methods = array_filter(AIOS_Abstracted_Ids::get_firewall_block_request_methods(), function($block_request_method) {
					return ('PUT' != $block_request_method);
				});

				$aiowps_firewall_config->set_value('aiowps_6g_block_request_methods', $aiowps_6g_block_request_methods);
				$aiowps_firewall_config->set_value('aiowps_6g_block_query', true);
				$aiowps_firewall_config->set_value('aiowps_6g_block_request', true);
				$aiowps_firewall_config->set_value('aiowps_6g_block_referrers', true);
				$aiowps_firewall_config->set_value('aiowps_6g_block_agents', true);
				$aio_wp_security->configs->set_value('aiowps_enable_6g_firewall', '1');
				$res = true; //shows the success notice
			} else {
		   		AIOWPSecurity_Configure_Settings::turn_off_all_6g_firewall_configs();
				$aio_wp_security->configs->set_value('aiowps_enable_6g_firewall', '');
				$res = true;
			}

			//Commit the config settings
			$aio_wp_security->configs->save_config();

			if ($res) {
				$this->show_msg_updated(__('You have successfully saved the 5G/6G Firewall Protection configuration', 'all-in-one-wp-security-and-firewall'));
				// Recalculate points after the feature status/options have been altered
				$aiowps_feature_mgr->check_feature_status_and_recalculate_points();
			} else {
				$this->show_msg_error(__('Could not write to the .htaccess file. Please check the file permissions.', 'all-in-one-wp-security-and-firewall'));
			}
		}

		 //Load required data from config
		 if (!empty($aiowps_firewall_config)) {
			// firewall config is available
			$methods = $aiowps_firewall_config->get_value('aiowps_6g_block_request_methods');
			if (empty($methods)) {
				$methods = array();
			}

			$blocked_query     = (bool) $aiowps_firewall_config->get_value('aiowps_6g_block_query');
			$blocked_request   = (bool) $aiowps_firewall_config->get_value('aiowps_6g_block_request');
			$blocked_referrers = (bool) $aiowps_firewall_config->get_value('aiowps_6g_block_referrers');
			$blocked_agents    = (bool) $aiowps_firewall_config->get_value('aiowps_6g_block_agents');
		} else {
			// firewall config is unavailable
			?>
				<div class="notice notice-error">
					<p><strong><?php _e('All in One WP Security and Firewall', 'all-in-one-wp-security-and-firewall'); ?></strong></p>
					<p><?php _e('We were unable to access the firewall\'s configuration file:', 'all-in-one-wp-security-and-firewall');?></p>
					<pre style="max-width: 100%;background-color: #f0f0f0;border: #ccc solid 1px;padding: 10px;white-space: pre-wrap;"><?php echo esc_html(AIOWPSecurity_Utility_Firewall::get_firewall_rules_path() . 'settings.php'); ?></pre>
					<p><?php _e('As a result, the firewall will be unavailable.', 'all-in-one-wp-security-and-firewall');?></p>
					<p><?php _e('Please check your PHP error log for further information.', 'all-in-one-wp-security-and-firewall');?></p>
					<p><?php _e('If you\'re unable to locate your PHP log file, please contact your web hosting company to ask them where it can be found on their setup.', 'all-in-one-wp-security-and-firewall');?></p>
				</div>
			<?php

			//set default variables
			$methods           = array();
			$blocked_query     = false;
			$blocked_request   = false;
			$blocked_referrers = false;
			$blocked_agents    = false;
		}

		$settings = array_merge(array('methods' => $methods), compact('blocked_query', 'blocked_request', 'blocked_referrers', 'blocked_agents', 'block_request_methods', 'aiowps_firewall_config'));
		$aio_wp_security->include_template('wp-admin/firewall/6g.php', false, $settings);
	}

	/**
	 * Renders the Internet Bots tab
	 *
	 * @return void
	 */
	protected function render_internet_bots() {
		global $aiowps_feature_mgr;
		global $aio_wp_security;
		if(isset($_POST['aiowps_save_internet_bot_settings'])) { // Do form submission tasks
			$nonce = $_POST['_wpnonce'];
			if (!wp_verify_nonce($nonce, 'aiowpsec-save-internet-bot-settings-nonce')) {
				$aio_wp_security->debug_logger->log_debug("Nonce check failed for save internet bot settings!", 4);
				die("Nonce check failed for save internet bot settings!");
			}

			//Save settings
			if (isset($_POST['aiowps_block_fake_googlebots'])) {
				$aio_wp_security->configs->set_value('aiowps_block_fake_googlebots', '1');
			} else {
				$aio_wp_security->configs->set_value('aiowps_block_fake_googlebots', '');
			}

			//Commit the config settings
			$aio_wp_security->configs->save_config();

			//Recalculate points after the feature status/options have been altered
			$aiowps_feature_mgr->check_feature_status_and_recalculate_points();

			$this->show_msg_updated(__('The Internet bot settings were successfully saved', 'all-in-one-wp-security-and-firewall'));
		}

		$aio_wp_security->include_template('wp-admin/firewall/internet-bots.php');
	}

	/**
	 * Renders the Prevent Hotlinks tab
	 *
	 * @return void
	 */
	protected function render_prevent_hotlinks() {
		global $aio_wp_security;
		$aio_wp_security->include_template('wp-admin/general/moved.php', false, array('key' => 'prevent-hotlinks'));
	}

	/**
	 * Renders the 404 Detection tab
	 *
	 * @return void
	 */
	protected function render_404_detection() {
		global $aio_wp_security, $aiowps_feature_mgr;

		if (isset($_POST['aiowps_delete_404_event_records'])) {
			$nonce = $_REQUEST['_wpnonce'];
			if (!wp_verify_nonce($nonce, 'aiowpsec-delete-404-event-records-nonce')) {
				$aio_wp_security->debug_logger->log_debug("Nonce check failed for delete all 404 event logs operation", 4);
				die(__('Nonce check failed for delete all 404 event logs operation!','all-in-one-wp-security-and-firewall'));
			}
			global $wpdb;
			$events_table_name = AIOWPSEC_TBL_EVENTS;
			//Delete all 404 records from the events table
			$where = array('event_type' => '404');
			$result = $wpdb->delete($events_table_name, $where);

			if ($result === FALSE) {
				$aio_wp_security->debug_logger->log_debug("404 Detection Feature - Delete all 404 event logs operation failed", 4);
				$this->show_msg_error(__('404 Detection Feature - Delete all 404 event logs operation failed!','all-in-one-wp-security-and-firewall'));
			} else {
				$this->show_msg_updated(__('All 404 event logs were deleted from the DB successfully!','all-in-one-wp-security-and-firewall'));
			}
		}

		include_once 'wp-security-list-404.php'; // For rendering the AIOWPSecurity_List_Table in basic-firewall tab
		$event_list_404 = new AIOWPSecurity_List_404(); // For rendering the AIOWPSecurity_List_Table in basic-firewall tab

		if (isset($_POST['aiowps_save_404_detect_options'])) { // Do form submission tasks
			$error = '';
			$nonce = $_POST['_wpnonce'];
			if (!wp_verify_nonce($nonce, 'aiowpsec-404-detection-nonce')) {
				$aio_wp_security->debug_logger->log_debug("Nonce check failed on 404 detection options save", 4);
				die("Nonce check failed on 404 detection options save");
			}

			$aio_wp_security->configs->set_value('aiowps_enable_404_logging',isset($_POST["aiowps_enable_404_IP_lockout"]) ? '1' : ''); //the "aiowps_enable_404_IP_lockout" checkbox currently controls both the 404 lockout and 404 logging
			$aio_wp_security->configs->set_value('aiowps_enable_404_IP_lockout',isset($_POST["aiowps_enable_404_IP_lockout"]) ? '1' : '');

			$lockout_time_length = isset($_POST['aiowps_404_lockout_time_length']) ? sanitize_text_field($_POST['aiowps_404_lockout_time_length']) : '';
			if (!is_numeric($lockout_time_length)) {
				$error .= '<br />'.__('You entered a non numeric value for the lockout time length field. It has been set to the default value.','all-in-one-wp-security-and-firewall');
				$lockout_time_length = '60';//Set it to the default value for this field
			}

			$redirect_url = isset($_POST['aiowps_404_lock_redirect_url']) ? trim($_POST['aiowps_404_lock_redirect_url']) : '';
			if ($redirect_url == '' || esc_url($redirect_url, array('http', 'https')) == '') {
				$error .= '<br />'.__('You entered an incorrect format for the "Redirect URL" field. It has been set to the default value.','all-in-one-wp-security-and-firewall');
				$redirect_url = 'http://127.0.0.1';
			}

			if ($error) {
				$this->show_msg_error(__('Attention:', 'all-in-one-wp-security-and-firewall').' '.$error);
			}

			$aio_wp_security->configs->set_value('aiowps_404_lockout_time_length', absint($lockout_time_length));
			$aio_wp_security->configs->set_value('aiowps_404_lock_redirect_url', $redirect_url);
			$aio_wp_security->configs->save_config();

			//Recalculate points after the feature status/options have been altered
			$aiowps_feature_mgr->check_feature_status_and_recalculate_points();

			$this->show_msg_settings_updated();
		}


		if (isset($_GET['action'])) { //Do list table form row action tasks
			if ('temp_block' == $_GET['action']) { // Temp Block link was clicked for a row in list table
				$event_list_404->block_ip(strip_tags($_GET['ip_address']));
			}

			if ('blacklist_ip' == $_GET['action']) { //Blacklist IP link was clicked for a row in list table
				$event_list_404->blacklist_ip_address(strip_tags($_GET['ip_address']));
			}

			if ('delete_event_log' == $_GET['action']) { //Unlock link was clicked for a row in list table
				$event_list_404->delete_404_event_records(strip_tags($_GET['id']));
			}
		}

		$page = $_REQUEST['page'];
		$tab = isset($_REQUEST["tab"]) ? $_REQUEST["tab"] : '';
		$aio_wp_security->include_template('wp-admin/firewall/404-detection.php', false, array('event_list_404' => $event_list_404, 'page' => $page, 'tab' => $tab));
	}

	/**
	 * Renders the Custom Rules tab
	 *
	 * @return void
	 */
	protected function render_custom_rules() {
		global $aio_wp_security;
		$aio_wp_security->include_template('wp-admin/general/moved.php', false, array('key' => 'custom-rules'));
	}

	/**
	 * Renders the Advanced settings tab.
	 *
	 * @return void
	 */
	protected function render_advanced_settings() {
		global $aio_wp_security;

		$allowlist = \AIOWPS\Firewall\Allow_List::get_ips();

		if (isset($_POST['aios_firewall_allowlist'])) {

			if (is_wp_error(AIOWPSecurity_Utility_Permissions::check_nonce_and_user_cap($_POST['_wpnonce'], 'aios-firewall-allowlist-nonce'))) {
					$aio_wp_security->debug_logger->log_debug("Nonce check failed for save firewall's allow list.", 4);
					die('Nonce check failed for firewall\'s allow list.');
			}

			$allowlist = $_POST['aios_firewall_allowlist'];
			$ips      = stripslashes($allowlist);
			$ips      = AIOWPSecurity_Utility_IP::create_ip_list_array_from_string_with_newline($ips);
			$validate = AIOWPSecurity_Utility_IP::validate_ip_list($ips, 'firewall_allowlist');
			$is_valid = (1 === $validate[0]);

			if ($is_valid) {
				\AIOWPS\Firewall\Allow_List::add_ips($validate[1]);
				$this->show_msg_settings_updated();
			} else {
				$messages = explode("\n", $validate[1][0]);
				foreach ($messages as $message) {
					if (empty(trim($message))) continue;
					$this->show_msg_error($message);
				}
			}
		}

		
		$aio_wp_security->include_template('wp-admin/firewall/advanced-settings.php', false, compact('allowlist'));
	}

} //end class
