plugin = $plugin; add_action('send_headers', [$this, 'add_security_headers']); add_action('admin_init', [$this, 'register_settings']); add_action('update_option_' . self::OPTION_NAME, [$this, 'sync_htaccess']); } public function sync_htaccess() { if (isset($this->plugin->htaccess_manager)) { $this->plugin->htaccess_manager->update_htaccess(); } } public function add_security_headers() { if (headers_sent() || is_admin()) { return; } $options = get_option(self::OPTION_NAME, $this->get_default_options()); if (!is_array($options)) { return; } foreach ($options as $key => $header) { if (!empty($header['enabled']) && !empty($header['name']) && !empty($header['value'])) { if ($key === 'hsts' && !is_ssl()) { continue; } header(trim($header['name']) . ': ' . trim($header['value']), true); } } } public function register_settings() { register_setting(self::OPTION_GROUP, self::OPTION_NAME, [ 'sanitize_callback' => [$this, 'sanitize_options'], 'default' => $this->get_default_options() ]); } public function get_default_options() { return [ 'referrer_policy' => ['name' => 'Referrer-Policy', 'value' => 'strict-origin-when-cross-origin', 'enabled' => true, 'description' => __('Controls referrer info sent to other sites.', 'advanced-ip-blocker')], 'permissions_policy' => ['name' => 'Permissions-Policy', 'value' => 'microphone=(), camera=(), geolocation=()', 'enabled' => true, 'description' => __('Controls which browser features can be used.', 'advanced-ip-blocker')], 'x_frame_options' => ['name' => 'X-Frame-Options', 'value' => 'SAMEORIGIN', 'enabled' => true, 'description' => __('Protects against clickjacking attacks.', 'advanced-ip-blocker')], 'x_content_type_options' => ['name' => 'X-Content-Type-Options', 'value' => 'nosniff', 'enabled' => true, 'description' => __('Prevents MIME-sniffing vulnerabilities.', 'advanced-ip-blocker')], 'hsts' => ['name' => 'Strict-Transport-Security', 'value' => 'max-age=31536000; includeSubDomains; preload', 'enabled' => true, 'description' => __('Warning: Only use if your site is fully on HTTPS.', 'advanced-ip-blocker')], 'csp' => ['name' => 'Content-Security-Policy', 'value' => "", 'enabled' => false, 'description' => __('Enforcing CSP. Build your policy using the Report-Only mode below first. Warning: Incorrect CSP can break your site.', 'advanced-ip-blocker')], 'csp_report_only' => ['name' => 'Content-Security-Policy-Report-Only', 'value' => "default-src 'self';", 'enabled' => false, 'description' => __('CSP Report-Only Mode. Use this to test your policy.', 'advanced-ip-blocker')], 'custom_1' => ['name' => '', 'value' => '', 'enabled' => false, 'description' => __('Define a custom header. Example: X-Forwarded-For', 'advanced-ip-blocker')], 'custom_2' => ['name' => '', 'value' => '', 'enabled' => false, 'description' => __('Define another custom header.', 'advanced-ip-blocker')], 'custom_3' => ['name' => '', 'value' => '', 'enabled' => false, 'description' => __('Define a third custom header.', 'advanced-ip-blocker')], ]; } public function sanitize_options($input) { $defaults = $this->get_default_options(); $output = []; foreach ($defaults as $key => $values) { $output[$key]['description'] = $values['description']; $output[$key]['enabled'] = !empty($input[$key]['enabled']) ? 1 : 0; $output[$key]['name'] = isset($input[$key]['name']) ? sanitize_text_field($input[$key]['name']) : $values['name']; if ($key === 'csp' || $key === 'csp_report_only') { $output[$key]['value'] = isset($input[$key]['value']) ? $this->sanitize_csp($input[$key]['value']) : ''; } else { $output[$key]['value'] = isset($input[$key]['value']) ? sanitize_text_field($input[$key]['value']) : ''; } } return $output; } private function sanitize_csp($value) { $value = wp_strip_all_tags($value); $value = str_replace(["\r", "\n"], ' ', $value); $value = str_replace('"', "'", $value); $value = preg_replace('/\s+/', ' ', $value); return trim($value); } public function display_settings_tab() { if (!current_user_can('advaipbl_manage_settings')) { return; } ?>

get_default_options()); $defaults = $this->get_default_options(); $db_options = is_array($options) ? $options : []; $options = []; foreach ($defaults as $k => $v) { $options[$k] = isset($db_options[$k]) ? $db_options[$k] : $v; } ?>
$header): ?>