PluginProbe
Patchstack – WordPress & Plugins Security / 2.2.2
Patchstack – WordPress & Plugins Security v2.2.2
2.3.7 trunk 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.17 2.1.18 2.1.19 2.1.2 2.1.20 2.1.21 2.1.22 2.1.23 2.1.24 2.1.25 2.1.3 2.1.4 2.1.5 2.1.6 All 49 releases
← All changes | includes/admin/options.php +602 -98 trunk2.2.2 View file →
@@ -18,8 +18,9 @@
18 18 * @return void
19 19 */
20 20 public function __construct( $core ) {
21 21 parent::__construct( $core );
22 + add_action( 'admin_init', [ $this, 'settings_init' ] );
22 23 }
23 24
24 25 /**
25 26 * All options and their default values.
@@ -27,114 +28,121 @@
27 28 * @var array
28 29 */
29 30 public $options = [
30 31 // Hardening options.
31 - 'patchstack_pluginedit' => ['default' => 1, 'autoload' => 'yes'],
32 - 'patchstack_userenum' => ['default' => 1, 'autoload' => 'yes'],
33 - 'patchstack_hidewpversion' => ['default' => 1, 'autoload' => 'yes'],
34 - 'patchstack_activity_log_is_enabled' => ['default' => 1, 'autoload' => 'yes'],
35 - 'patchstack_activity_log_failed_logins' => ['default' => 1, 'autoload' => 'no'],
36 - 'patchstack_activity_log_failed_logins_db' => ['default' => 0, 'autoload' => 'no'],
37 - 'patchstack_activity_log_posts' => ['default' => 0, 'autoload' => 'yes'],
38 - 'patchstack_activity_log_comments' => ['default' => 0, 'autoload' => 'yes'],
39 - 'patchstack_xmlrpc_is_disabled' => ['default' => 1, 'autoload' => 'yes'],
40 - 'patchstack_captcha_type' => ['default' => 'v2', 'autoload' => 'no'],
41 - 'patchstack_captcha_public_key_v3' => ['default' => '', 'autoload' => 'no'],
42 - 'patchstack_captcha_private_key_v3' => ['default' => '', 'autoload' => 'no'],
43 - 'patchstack_captcha_public_key_v3_new' => ['default' => '', 'autoload' => 'no'],
44 - 'patchstack_captcha_private_key_v3_new' => ['default' => '', 'autoload' => 'no'],
45 - 'patchstack_captcha_public_key_turnstile' => ['default' => '', 'autoload' => 'no'],
46 - 'patchstack_captcha_private_key_turnstile' => ['default' => '', 'autoload' => 'no'],
47 - 'patchstack_captcha_public_key' => ['default' => '', 'autoload' => 'no'],
48 - 'patchstack_captcha_private_key' => ['default' => '', 'autoload' => 'no'],
49 - 'patchstack_captcha_login_form' => ['default' => 0, 'autoload' => 'no'],
50 - 'patchstack_captcha_registration_form' => ['default' => 0, 'autoload' => 'no'],
51 - 'patchstack_captcha_reset_pwd_form' => ['default' => 0, 'autoload' => 'no'],
52 - 'patchstack_captcha_on_comments' => ['default' => 0, 'autoload' => 'yes'],
53 - 'patchstack_json_is_disabled' => ['default' => 0, 'autoload' => 'yes'],
54 - 'patchstack_auto_update' => ['default' => [], 'autoload' => 'yes'],
55 - 'patchstack_application_passwords_disabled' => ['default' => 1, 'autoload' => 'yes'],
32 + 'patchstack_pluginedit' => 1,
33 + 'patchstack_userenum' => 1,
34 + 'patchstack_basicscanblock' => 1,
35 + 'patchstack_hidewpcontent' => 1,
36 + 'patchstack_hidewpversion' => 1,
37 + 'patchstack_rm_readme' => 1,
38 + 'patchstack_activity_log_is_enabled' => 1,
39 + 'patchstack_activity_log_failed_logins' => 1,
40 + 'patchstack_activity_log_failed_logins_db' => 0,
41 + 'patchstack_xmlrpc_is_disabled' => 1,
42 + 'patchstack_captcha_type' => 'v2',
43 + 'patchstack_captcha_public_key_v3' => '',
44 + 'patchstack_captcha_private_key_v3' => '',
45 + 'patchstack_captcha_public_key_v3_new' => '',
46 + 'patchstack_captcha_private_key_v3_new' => '',
47 + 'patchstack_captcha_public_key' => '',
48 + 'patchstack_captcha_private_key' => '',
49 + 'patchstack_captcha_login_form' => 0,
50 + 'patchstack_captcha_registration_form' => 0,
51 + 'patchstack_captcha_reset_pwd_form' => 0,
52 + 'patchstack_captcha_on_comments' => 0,
53 + 'patchstack_prevent_default_file_access' => 1,
54 + 'patchstack_register_email_blacklist' => '',
55 + 'patchstack_json_is_disabled' => 0,
56 + 'patchstack_auto_update' => [],
57 + 'patchstack_application_passwords_disabled' => 1,
56 58
57 59 // The firewall and whitelist rules.
58 - 'patchstack_firewall_rules' => ['default' => '', 'autoload' => 'yes'],
59 - 'patchstack_firewall_rules_v3' => ['default' => '[]', 'autoload' => 'yes'],
60 - 'patchstack_firewall_rules_v3_ap' => ['default' => '[]', 'autoload' => 'yes'],
61 - 'patchstack_firewall_ap_error' => ['default' => '', 'autoload' => 'no'],
62 - 'patchstack_whitelist_rules' => ['default' => '', 'autoload' => 'yes'],
63 - 'patchstack_whitelist_rules_v3' => ['default' => '[]', 'autoload' => 'yes'],
64 - 'patchstack_whitelist_keys_rules' => ['default' => '', 'autoload' => 'yes'],
60 + 'patchstack_firewall_rules' => '',
61 + 'patchstack_firewall_rules_v3' => '[]',
62 + 'patchstack_whitelist_rules' => '',
63 + 'patchstack_whitelist_rules_v3' => '[]',
64 + 'patchstack_whitelist_keys_rules' => '',
65 65
66 66 // Firewall options.
67 - 'patchstack_basic_firewall' => ['default' => 1, 'autoload' => 'yes'],
68 - 'patchstack_basic_firewall_roles' => ['default' => [ 'administrator', 'editor', 'author', 'contributor' ], 'autoload' => 'yes'],
69 - 'patchstack_firewall_ip_header' => ['default' => '', 'autoload' => 'yes'],
70 - 'patchstack_ip_header_computed' => ['default' => 0, 'autoload' => 'no'],
71 - 'patchstack_ip_header_force_compute' => ['default' => 0, 'autoload' => 'no'],
72 - 'patchstack_disable_htaccess' => ['default' => 0, 'autoload' => 'yes'],
73 - 'patchstack_block_debug_log_access' => ['default' => 1, 'autoload' => 'no'],
74 - 'patchstack_block_fake_bots' => ['default' => 1, 'autoload' => 'no'],
75 - 'patchstack_index_views' => ['default' => 1, 'autoload' => 'no'],
76 - 'patchstack_proxy_comment_posting' => ['default' => 1, 'autoload' => 'no'],
77 - 'patchstack_image_hotlinking' => ['default' => 0, 'autoload' => 'no'],
78 - 'patchstack_prevent_default_file_access' => ['default' => 1, 'autoload' => 'no'],
79 - 'patchstack_basicscanblock' => ['default' => 1, 'autoload' => 'no'],
80 - 'patchstack_firewall_custom_rules' => ['default' => '', 'autoload' => 'no'],
81 - 'patchstack_firewall_custom_rules_loc' => ['default' => 'bottom', 'autoload' => 'no'],
82 - 'patchstack_add_security_headers' => ['default' => 1, 'autoload' => 'yes'],
83 - 'patchstack_ip_block_list' => ['default' => '', 'autoload' => 'yes'],
67 + 'patchstack_basic_firewall' => 1,
68 + 'patchstack_basic_firewall_roles' => [ 'administrator', 'editor', 'author', 'contributor' ],
69 + 'patchstack_firewall_ip_header' => '',
70 + 'patchstack_ip_header_computed' => 0,
71 + 'patchstack_disable_htaccess' => 0,
72 + 'patchstack_known_blacklist' => 0,
73 + 'patchstack_block_debug_log_access' => 1,
74 + 'patchstack_block_fake_bots' => 1,
75 + 'patchstack_index_views' => 1,
76 + 'patchstack_proxy_comment_posting' => 1,
77 + 'patchstack_bad_query_strings' => 0,
78 + 'patchstack_advanced_character_string_filter' => 0,
79 + 'patchstack_advanced_blacklist_firewall' => 0,
80 + 'patchstack_forbid_rfi' => 0,
81 + 'patchstack_image_hotlinking' => 0,
82 + 'patchstack_firewall_custom_rules' => '',
83 + 'patchstack_firewall_custom_rules_loc' => 'bottom',
84 + 'patchstack_add_security_headers' => 1,
85 + 'patchstack_blocked_attacks' => 0,
86 + 'patchstack_ip_block_list' => '',
87 + 'patchstack_geo_block_enabled' => 0,
88 + 'patchstack_geo_block_inverse' => 0,
89 + 'patchstack_geo_block_countries' => [],
84 90
91 + // Cookie notice options.
92 + 'patchstack_enable_cookie_notice_message' => 0,
93 + 'patchstack_cookie_notice_message' => 'We use cookies for various purposes including analytics and personalized marketing. By continuing to use the service, you agree to our use of cookies.',
94 + 'patchstack_cookie_notice_backgroundcolor' => '222222',
95 + 'patchstack_cookie_notice_textcolor' => 'ffffff',
96 + 'patchstack_cookie_notice_privacypolicy_enable' => 0,
97 + 'patchstack_cookie_notice_privacypolicy_text' => 'Cookie Policy',
98 + 'patchstack_cookie_notice_privacypolicy_link' => '#',
99 + 'patchstack_cookie_notice_cookie_expiration' => 'after_exit',
100 + 'patchstack_cookie_notice_opacity' => '100',
101 + 'patchstack_cookie_notice_accept_text' => 'I agree',
102 + 'patchstack_cookie_notice_credits' => 1,
103 +
85 104 // Login and firewall brute force options.
86 - 'patchstack_block_bruteforce_ips' => ['default' => 0, 'autoload' => 'no'],
87 - 'patchstack_anti_bruteforce_attempts' => ['default' => 10, 'autoload' => 'no'],
88 - 'patchstack_anti_bruteforce_minutes' => ['default' => 5, 'autoload' => 'no'],
89 - 'patchstack_anti_bruteforce_blocktime' => ['default' => 60, 'autoload' => 'no'],
90 - 'patchstack_autoblock_attempts' => ['default' => 60, 'autoload' => 'yes'],
91 - 'patchstack_autoblock_minutes' => ['default' => 1, 'autoload' => 'yes'],
92 - 'patchstack_autoblock_blocktime' => ['default' => 1, 'autoload' => 'yes'],
93 - 'patchstack_login_2fa' => ['default' => 0, 'autoload' => 'yes'],
94 - 'patchstack_login_whitelist' => ['default' => '', 'autoload' => 'no'],
105 + 'patchstack_block_bruteforce_ips' => 0,
106 + 'patchstack_anti_bruteforce_attempts' => 10,
107 + 'patchstack_anti_bruteforce_minutes' => 5,
108 + 'patchstack_anti_bruteforce_blocktime' => 60,
109 + 'patchstack_autoblock_attempts' => 10,
110 + 'patchstack_autoblock_minutes' => 30,
111 + 'patchstack_autoblock_blocktime' => 60,
112 + 'patchstack_login_time_block' => 0,
113 + 'patchstack_login_time_start' => '00:00',
114 + 'patchstack_login_time_end' => '23:59',
115 + 'patchstack_login_2fa' => 0,
116 + 'patchstack_login_whitelist' => '',
95 117
96 118 // General options.
97 - 'patchstack_environment_hash' => ['default' => '', 'autoload' => 'no'],
98 - 'patchstack_software_data_hash' => ['default' => '', 'autoload' => 'yes'],
99 - 'patchstack_software_upload_attempted' => ['default' => 0, 'autoload' => 'yes'],
100 - 'patchstack_license_expiry' => ['default' => '', 'autoload' => 'yes'],
101 - 'patchstack_clientid' => ['default' => '', 'autoload' => 'yes'],
102 - 'patchstack_secretkey' => ['default' => '', 'autoload' => 'no'],
103 - 'patchstack_secretkey_nonce' => ['default' => '', 'autoload' => 'no'],
104 - 'patchstack_license_free' => ['default' => 0, 'autoload' => 'yes'],
105 - 'patchstack_api_token' => ['default' => '', 'autoload' => 'yes'],
106 - 'patchstack_subscription_class' => ['default' => '', 'autoload' => 'no'],
107 - 'patchstack_last_license_check' => ['default' => 0, 'autoload' => 'no'],
108 - 'patchstack_last_sync' => ['default' => 0, 'autoload' => 'no'],
109 - 'patchstack_whitelist' => ['default' => '', 'autoload' => 'yes'],
110 - 'patchstack_show_settings' => ['default' => 0, 'autoload' => 'no'],
111 - 'patchstack_firewall_log_lastid' => ['default' => 0, 'autoload' => 'no'],
112 - 'patchstack_eventlog_lastid' => ['default' => 0, 'autoload' => 'no'],
113 - 'patchstack_ott_action' => ['default' => '', 'autoload' => 'no'],
114 - 'patchstack_managed' => ['default' => 0, 'autoload' => 'no'],
115 - 'patchstack_managed_text' => ['default' => '', 'autoload' => 'no'],
116 - 'patchstack_latest_vulnerable' => ['default' => [], 'autoload' => 'no'],
117 - 'patchstack_site_id' => ['default' => 0, 'autoload' => 'no'],
118 - 'patchstack_activation_secret' => ['default' => '', 'autoload' => 'no'],
119 - 'patchstack_activation_time' => ['default' => '', 'autoload' => 'no'],
120 - 'patchstack_firewall_ap_enabled' => ['default' => 0, 'autoload' => 'yes'],
121 - 'patchstack_firewall_log_processing' => ['default' => 0, 'autoload' => 'no'],
122 - 'patchstack_eventlog_processing' => ['default' => 0, 'autoload' => 'no'],
123 - 'patchstack_firewall_log_ap_processing' => ['default' => 0, 'autoload' => 'no'],
119 + 'patchstack_blackhole_log' => '',
120 + 'patchstack_software_data_hash' => '',
121 + 'patchstack_firewall_htaccess_hash' => '',
122 + 'patchstack_license_expiry' => '',
123 + 'patchstack_clientid' => false,
124 + 'patchstack_secretkey' => false,
125 + 'patchstack_secretkey_nonce' => '',
126 + 'patchstack_license_free' => 0,
127 + 'patchstack_api_token' => '',
128 + 'patchstack_subscription_class' => '',
129 + 'patchstack_last_license_check' => 0,
130 + 'patchstack_whitelist' => '',
131 + 'patchstack_show_settings' => 0,
132 + 'patchstack_firewall_log_lastid' => 0,
133 + 'patchstack_eventlog_lastid' => 0,
134 + 'patchstack_ott_action' => '',
135 + 'patchstack_enc_nonce' => '',
136 + 'patchstack_managed' => false,
137 + 'patchstack_managed_text' => '',
138 + 'patchstack_latest_vulnerable' => [],
139 + 'patchstack_site_id' => 0,
124 140
125 141 // Admin page rename options.
126 - 'patchstack_mv_wp_login' => ['default' => 0, 'autoload' => 'yes'],
127 - 'patchstack_rename_wp_login' => ['default' => 'swlogin', 'autoload' => 'yes'],
128 - 'patchstack_rename_wp_login_whitelist' => ['default' => [], 'autoload' => 'no'],
129 -
130 - // Statistics
131 - 'patchstack_vulns_present' => ['default' => '?', 'autoload' => 'no'],
132 - 'patchstack_fixes_present' => ['default' => '?', 'autoload' => 'no'],
133 - 'patchstack_vpatches_present' => ['default' => '?', 'autoload' => 'no'],
134 - 'patchstack_non_vpatches_present' => ['default' => '?', 'autoload' => 'no'],
135 - 'patchstack_hits_last_30' => ['default' => [], 'autoload' => 'no'],
136 - 'patchstack_hits_all_time' => ['default' => 0, 'autoload' => 'no'],
142 + 'patchstack_mv_wp_login' => 0,
143 + 'patchstack_rename_wp_login' => 'swlogin',
144 + 'patchstack_rename_wp_login_whitelist' => []
137 145 ];
138 146
139 147 /**
140 148 * Register all the options, if not set already.
@@ -141,15 +149,511 @@
141 149 *
142 150 * @return void
143 151 */
144 152 public function settings_init() {
153 +
145 154 // Add the options.
146 155 foreach ( $this->options as $name => $value ) {
147 - add_option( $name, $value['default'], '', $value['autoload'] );
156 + add_option( $name, $value );
148 157
149 158 // Clone settings for multisite so we can set defaults.
150 159 if ( is_multisite() ) {
151 - add_site_option( $name, $value['default'] );
160 + add_site_option( $name, $value );
152 161 }
153 162 }
163 +
164 + // Multisite options
165 + add_network_option( null, 'patchstack_multisite_installed', 0 );
166 +
167 + // Get the class value and convert.
168 + $class = get_option( 'patchstack_subscription_class', '' );
169 + $is_community = $class != '' && (int) $class === 0;
170 +
171 + // All (sub)sections that show up.
172 + add_settings_section( 'patchstack_settings_section_hardening', __( 'Security Configurations', 'patchstack' ), false, 'patchstack_hardening_settings' );
173 + add_settings_section( 'patchstack_settings_section_hardening_captcha', __( '<hr style="height:1px;border:none;background-color: rgba(170, 189, 215, 0.1);"><br /> reCAPTCHA<br /><span style="font-size: 13px; color: #d0d0d0;">It should be noted that the reCAPTCHA feature only applies to WordPress its core features at this time. Not custom forms or of third party plugins.</span>', 'patchstack' ), false, 'patchstack_hardening_settings' );
174 + add_settings_section( 'patchstack_settings_section_firewall', __( 'Firewall settings', 'patchstack' ), false, 'patchstack_firewall_settings' );
175 + if ( ( ! is_multisite() || ( isset( $_GET['page'] ) && $_GET['page'] == 'patchstack-multisite-settings' ) ) && ! $is_community ) {
176 + add_settings_section( 'patchstack_settings_section_firewall_htaccess', __( '.htaccess Features', 'patchstack' ), false, 'patchstack_firewall_settings' );
177 + }
178 +
179 + if (! $is_community ) {
180 + add_settings_section( 'patchstack_settings_section_firewall_geo', __( 'Country Blocking', 'patchstack' ), false, 'patchstack_firewall_settings' );
181 + }
182 +
183 + add_settings_section( 'patchstack_settings_section_firewall_wlbl', __( 'IP Whitelist &amp; Blacklist', 'patchstack' ), false, 'patchstack_firewall_settings' );
184 + add_settings_section( 'patchstack_settings_section_cookienotice', __( 'Cookie Notice Settings', 'patchstack' ), false, 'patchstack_cookienotice_settings' );
185 + add_settings_section( 'patchstack_settings_section_login', __( 'Login Protection', 'patchstack' ), false, 'patchstack_login_settings' );
186 + add_settings_section( 'patchstack_settings_section_login_2fa', __( '<hr style="height:1px;border:none;background-color: rgba(170, 189, 215, 0.1);"><br /> Two Factor Authentication', 'patchstack' ), false, 'patchstack_login_settings' );
187 + add_settings_section( 'patchstack_settings_section_login_blocked', __( '<hr style="height:1px;border:none;background-color: rgba(170, 189, 215, 0.1);"><br /> Currently Blocked IP Addresses', 'patchstack' ), false, 'patchstack_login_settings' );
188 + add_settings_section( 'patchstack_settings_section_login_whitelist', __( '<hr style="height:1px;border:none;background-color: rgba(170, 189, 215, 0.1);"><br /> Whitelisted IP Addresses', 'patchstack' ), false, 'patchstack_login_settings' );
189 +
190 + // Hardening.
191 + if ( ! is_multisite() || ( isset( $_GET['page'] ) && $_GET['page'] == 'patchstack-multisite-settings' ) ) {
192 + add_settings_field( 'patchstack_rm_readme', __( 'Remove readme.html', 'patchstack' ), [ $this, 'patchstack_rm_readme_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
193 + add_settings_field( 'patchstack_auto_update', __( 'Auto Update Software', 'patchstack' ), [ $this, 'patchstack_auto_update_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
194 + }
195 + add_settings_field( 'patchstack_basicscanblock', __( 'Stop readme.txt Scans', 'patchstack' ), [ $this, 'patchstack_basicscanblock_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
196 + add_settings_field( 'patchstack_pluginedit', __( 'Disable theme editor', 'patchstack' ), [ $this, 'patchstack_pluginedit_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
197 + add_settings_field( 'patchstack_userenum', __( 'Disable user enumeration', 'patchstack' ), [ $this, 'patchstack_userenum_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
198 + add_settings_field( 'patchstack_hidewpversion', __( 'Hide WordPress version', 'patchstack' ), [ $this, 'patchstack_hidewpversion_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
199 + add_settings_field( 'patchstack_activity_log_is_enabled', __( 'Enable activity log', 'patchstack' ), [ $this, 'patchstack_activity_log_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
200 + add_settings_field( 'patchstack_activity_log_failed_logins', __( 'Log failed logins', 'patchstack' ), [ $this, 'patchstack_activity_log_failed_logins_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
201 + add_settings_field( 'patchstack_activity_log_failed_logins_db', __( 'Upload failed logins to Patchstack', 'patchstack' ), [ $this, 'patchstack_activity_log_failed_logins_db_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
202 + add_settings_field( 'patchstack_application_passwords_disabled', __( 'Block Application Passwords', 'patchstack' ), [ $this, 'patchstack_application_passwords_disabled_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
203 + add_settings_field( 'patchstack_xmlrpc_is_disabled', __( 'Restrict XML-RPC Access', 'patchstack' ), [ $this, 'patchstack_xmlrpc_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
204 + add_settings_field( 'patchstack_json_is_disabled', __( 'Restrict WP REST API Access', 'patchstack' ), [ $this, 'patchstack_json_is_disabled_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
205 + add_settings_field( 'patchstack_register_email_blacklist', __( 'Registration Email Blacklist', 'patchstack' ), [ $this, 'patchstack_register_email_blacklist_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening' );
206 +
207 + // reCAPTCHA.
208 + add_settings_field( 'patchstack_captcha_on_comments', __( 'Post comments form', 'patchstack' ), [ $this, 'patchstack_captcha_on_comments_callback' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening_captcha' );
209 + add_settings_field( 'patchstack_captcha_login_form', __( 'Login form', 'patchstack' ), [ $this, 'patchstack_captcha_login_form_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening_captcha' );
210 + add_settings_field( 'patchstack_captcha_registration_form', __( 'Registration form', 'patchstack' ), [ $this, 'patchstack_captcha_registration_form_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening_captcha' );
211 + add_settings_field( 'patchstack_captcha_reset_pwd_form', __( 'Password reset form', 'patchstack' ), [ $this, 'patchstack_captcha_reset_pwd_form_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening_captcha' );
212 + add_settings_field( 'patchstack_captcha_type', __( 'reCAPTCHA version (invisible/normal)' ), [ $this, 'patchstack_captcha_type_callback' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening_captcha' );
213 + add_settings_field( 'patchstack_captcha_public_key', __( 'Site Key ', 'patchstack' ), [ $this, 'patchstack_captcha_public_key_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening_captcha' );
214 + add_settings_field( 'patchstack_captcha_private_key', __( 'Secret Key', 'patchstack' ), [ $this, 'patchstack_captcha_private_key_input' ], 'patchstack_hardening_settings', 'patchstack_settings_section_hardening_captcha' );
215 +
216 + // Firewall.
217 + add_settings_field( 'patchstack_basic_firewall', __( 'Enable firewall', 'patchstack' ), [ $this, 'patchstack_basic_firewall_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall' );
218 + add_settings_field( 'patchstack_basic_firewall_roles', __( 'Firewall user role whitelist', 'patchstack' ), [ $this, 'patchstack_basic_firewall_roles_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall' );
219 +
220 + if ( ! $is_community ) {
221 + add_settings_field( 'patchstack_basic_firewall_geo_enabled', __( 'Country Blocking Enabled', 'patchstack' ), [ $this, 'patchstack_basic_firewall_geo_enabled_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_geo' );
222 + add_settings_field( 'patchstack_basic_firewall_geo_inverse', __( 'Inversed Check', 'patchstack' ), [ $this, 'patchstack_basic_firewall_geo_inverse_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_geo' );
223 + add_settings_field( 'patchstack_basic_firewall_geo_countries', __( 'Countries To Block', 'patchstack' ), [ $this, 'patchstack_basic_firewall_geo_countries_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_geo' );
224 + }
225 +
226 + add_settings_field( 'patchstack_firewall_ip_header', __( 'IP Address Header Override', 'patchstack' ), [ $this, 'patchstack_firewall_ip_header_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall' );
227 +
228 + if ( ( ! is_multisite() || ( isset( $_GET['page'] ) && $_GET['page'] == 'patchstack-multisite-settings' ) ) && ! $is_community ) {
229 + add_settings_field( 'patchstack_disable_htaccess', __( 'Disable .htaccess features', 'patchstack' ), [ $this, 'patchstack_disable_htaccess_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
230 + add_settings_field( 'patchstack_add_security_headers', __( 'Add security headers', 'patchstack' ), [ $this, 'patchstack_add_security_headers_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
231 + add_settings_field( 'patchstack_prevent_default_file_access', __( 'Prevent default WordPress file access', 'patchstack' ), [ $this, 'patchstack_prevent_default_file_access_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
232 + add_settings_field( 'patchstack_block_debug_log_access', __( 'Block access to debug.log file', 'patchstack' ), [ $this, 'patchstack_block_debug_log_access_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
233 + add_settings_field( 'patchstack_index_views', __( 'Disable index views', 'patchstack' ), [ $this, 'patchstack_index_views_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
234 + add_settings_field( 'patchstack_proxy_comment_posting', __( 'Forbid proxy comment posting', 'patchstack' ), [ $this, 'patchstack_proxy_comment_posting_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
235 + add_settings_field( 'patchstack_image_hotlinking', __( 'Prevent image hotlinking', 'patchstack' ), [ $this, 'patchstack_image_hotlinking_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
236 + add_settings_field( 'patchstack_firewall_custom_rules', __( 'Add custom .htaccess rules here', 'patchstack' ), [ $this, 'patchstack_firewall_custom_rules_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
237 + add_settings_field( 'patchstack_firewall_custom_rules_loc', __( 'Custom .htaccess rules location', 'patchstack' ), [ $this, 'patchstack_firewall_custom_rules_loc_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_htaccess' );
238 + }
239 + add_settings_field( 'patchstack_blackhole_log', __( 'Block IP List', 'patchstack' ), [ $this, 'patchstack_blackhole_log_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_wlbl' );
240 + add_settings_field( 'patchstack_whitelist', __( 'Whitelist', 'patchstack' ), [ $this, 'patchstack_whitelist_input' ], 'patchstack_firewall_settings', 'patchstack_settings_section_firewall_wlbl' );
241 +
242 + // Login protection.
243 + if ( ( ! is_multisite() || ( isset( $_GET['page'] ) && $_GET['page'] == 'patchstack-multisite-settings' ) ) && floatval( substr( phpversion(), 0, 5 ) ) > 5.5 ) {
244 + add_settings_field( 'patchstack_mv_wp_login', __( 'Block access to wp-login.php', 'patchstack' ), [ $this, 'patchstack_hidewplogin_input' ], 'patchstack_login_settings', 'patchstack_settings_section_login' );
245 + add_settings_field( 'patchstack_rename_wp_login', '', [ $this, 'patchstack_hidewplogin_rename_input' ], 'patchstack_login_settings', 'patchstack_settings_section_login' );
246 + }
247 + add_settings_field( 'patchstack_block_bruteforce_ips', __( 'Automatic brute-force IP ban', 'patchstack' ), [ $this, 'patchstack_block_bruteforce_ips_input' ], 'patchstack_login_settings', 'patchstack_settings_section_login' );
248 + add_settings_field( 'patchstack_login_time_block', __( 'Logon hours', 'patchstack' ), [ $this, 'patchstack_login_time_block_input' ], 'patchstack_login_settings', 'patchstack_settings_section_login' );
249 + add_settings_field( 'patchstack_login_2fa', __( 'Two Factor Authentication', 'patchstack' ), [ $this, 'patchstack_login_2fa_input' ], 'patchstack_login_settings', 'patchstack_settings_section_login_2fa' );
250 + add_settings_field( 'patchstack_login_blocked', __( 'Blocked', 'patchstack' ), [ $this, 'patchstack_login_blocked_input' ], 'patchstack_login_settings', 'patchstack_settings_section_login_blocked' );
251 + add_settings_field( 'patchstack_login_whitelist', __( 'Whitelist', 'patchstack' ), [ $this, 'patchstack_login_whitelist_input' ], 'patchstack_login_settings', 'patchstack_settings_section_login_whitelist' );
252 +
253 + // Cookie notice.
254 + add_settings_field( 'patchstack_enable_cookie_notice_message', 'Enable Cookie Notice', [ $this, 'patchstack_enable_cookie_notice_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
255 + add_settings_field( 'patchstack_cookie_notice_message', 'Enter message for displaying', [ $this, 'patchstack_cookie_notice_message_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
256 + add_settings_field( 'patchstack_cookie_notice_accept_text', 'Cookie acceptance button text', [ $this, 'patchstack_cookie_notice_accept_text_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
257 + add_settings_field( 'patchstack_cookie_notice_backgroundcolor', 'Background color (HEX)', [ $this, 'patchstack_cookie_notice_backgroundcolor_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
258 + add_settings_field( 'patchstack_cookie_notice_textcolor', 'Text color (HEX)', [ $this, 'patchstack_cookie_notice_textcolor_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
259 + add_settings_field( 'patchstack_cookie_notice_privacypolicy_enable', 'Enable Policy Link', [ $this, 'patchstack_cookie_notice_privacypolicy_enable_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
260 + add_settings_field( 'patchstack_cookie_notice_privacypolicy_text', 'Enter Policy Text', [ $this, 'patchstack_cookie_notice_privacypolicy_text_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
261 + add_settings_field( 'patchstack_cookie_notice_privacypolicy_link', 'Enter Policy Link', [ $this, 'patchstack_cookie_notice_privacypolicy_link_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
262 + add_settings_field( 'patchstack_cookie_notice_cookie_expiration', 'When to ask user permission again', [ $this, 'patchstack_cookie_notice_cookie_expiration_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
263 + add_settings_field( 'patchstack_cookie_notice_opacity', 'Background opacity (in percentage)', [ $this, 'patchstack_cookie_notice_opacity_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
264 + add_settings_field( 'patchstack_cookie_notice_credits', 'Display Patchstack credits', [ $this, 'patchstack_cookie_notice_credits_callback' ], 'patchstack_cookienotice_settings', 'patchstack_settings_section_cookienotice' );
265 +
266 + // Register the group settings.
267 + $settings = [
268 + 'hardening' => [ 'patchstack_auto_update', 'patchstack_json_is_disabled', 'patchstack_register_email_blacklist', 'patchstack_pluginedit', 'patchstack_basicscanblock', 'patchstack_userenum', 'patchstack_rm_readme', 'patchstack_hidewpcontent', 'patchstack_hidewpversion', 'patchstack_activity_log_is_enabled', 'patchstack_activity_log_failed_logins', 'patchstack_activity_log_failed_logins_db', 'patchstack_movewpconfig', 'patchstack_captcha_on_comments', 'patchstack_captcha_login_form', 'patchstack_captcha_registration_form', 'patchstack_captcha_reset_pwd_form', 'patchstack_captcha_public_key', 'patchstack_captcha_private_key', 'patchstack_captcha_type', 'patchstack_captcha_public_key_v3', 'patchstack_captcha_private_key_v3', 'patchstack_captcha_public_key_v3_new', 'patchstack_captcha_private_key_v3_new', 'patchstack_xmlrpc_is_disabled', 'patchstack_application_passwords_disabled' ],
269 + 'firewall' => [ 'patchstack_geo_block_enabled', 'patchstack_geo_block_inverse', 'patchstack_basic_firewall_geo_countries', 'patchstack_ip_block_list', 'patchstack_prevent_default_file_access', 'patchstack_basic_firewall', 'patchstack_firewall_ip_header', 'patchstack_basic_firewall_roles', 'patchstack_disable_htaccess', 'patchstack_add_security_headers', 'patchstack_known_blacklist', 'patchstack_block_debug_log_access', 'patchstack_block_fake_bots', 'patchstack_index_views', 'patchstack_proxy_comment_posting', 'patchstack_bad_query_strings', 'patchstack_advanced_character_string_filter', 'patchstack_advanced_blacklist_firewall', 'patchstack_forbid_rfi', 'patchstack_image_hotlinking', 'patchstack_firewall_custom_rules', 'patchstack_firewall_custom_rules_loc', 'patchstack_blackhole_log', 'patchstack_whitelist', 'patchstack_autoblock_blocktime', 'patchstack_autoblock_attempts', 'patchstack_autoblock_minutes' ],
270 + 'cookienotice' => [ 'patchstack_enable_cookie_notice_message', 'patchstack_cookie_notice_message', 'patchstack_cookie_notice_backgroundcolor', 'patchstack_cookie_notice_textcolor', 'patchstack_cookie_notice_privacypolicy_enable', 'patchstack_cookie_notice_privacypolicy_text', 'patchstack_cookie_notice_privacypolicy_link', 'patchstack_cookie_notice_cookie_expiration', 'patchstack_cookie_notice_opacity', 'patchstack_cookie_notice_accept_text', 'patchstack_cookie_notice_credits' ],
271 + 'login' => [ 'patchstack_mv_wp_login', 'patchstack_rename_wp_login', 'patchstack_block_bruteforce_ips', 'patchstack_anti_bruteforce_attempts', 'patchstack_anti_bruteforce_minutes', 'patchstack_anti_bruteforce_blocktime', 'patchstack_login_time_block', 'patchstack_login_time_start', 'patchstack_login_time_end', 'patchstack_login_2fa', 'patchstack_login_blocked', 'patchstack_login_whitelist' ],
272 + ];
273 +
274 + foreach ( $settings as $key => $setting ) {
275 + foreach ( $setting as $option ) {
276 + register_setting( 'patchstack_' . $key . '_settings_group', $option );
277 + }
278 + }
279 + }
280 +
281 + public function patchstack_auto_update_input() {
282 + if ( defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED ) {
283 + echo wp_kses( '<p style="color: red;">The auto update feature cannot be enabled because a plugin or code change forces automatic updates to be disabled. (AUTOMATIC_UPDATER_DISABLED)</p>', $this->allowed_html );
284 + return;
285 + }
286 +
287 + $selected = get_site_option( 'patchstack_auto_update', [] );
288 + $selected = ! is_array( $selected ) ? [] : $selected;
289 + $options = [
290 + 'core' => 'WordPress Core',
291 + 'plugin' => 'Plugins',
292 + 'theme' => 'Themes',
293 + 'vulnerable' => 'Vulnerable Plugins',
294 + ];
295 + $out = '';
296 + foreach ( $options as $option => $text ) {
297 + $out .= '<input type="checkbox" id="patchstack_auto_update_' . $option . '" name="patchstack_auto_update[]" value="' . $option . '" ' . checked( 1, in_array( $option, $selected ), false ) . '/>'
298 + . '<label for="patchstack_auto_update_' . $option . '"><i>' . $text . '</i></label><br>';
299 + }
300 +
301 + $string1 = __( 'Select what needs to be automatically updated each time WordPress looks for updates in the background.<br />Keep in mind that if a plugin update contains a bug or a fatal error, it could break your site.', 'patchstack' );
302 + echo wp_kses( ( '<label for="patchstack_auto_update"><i>' . $string1 . '</i></label><br /><br />' . $out ), $this->allowed_html );
303 + }
304 +
305 + public function patchstack_basic_firewall_geo_enabled_input() {
306 + $string1 = __( 'If enabled and valid countries are specified to be blocked, will block these countries.', 'patchstack' );
307 + echo wp_kses( '<input type="checkbox" name="patchstack_geo_block_enabled" id="patchstack_geo_block_enabled" value="1" ' . checked( 1, $this->get_option( 'patchstack_geo_block_enabled' ), false ) . '/><label for="patchstack_geo_block_enabled"><i>' . $string1 . '</i></label>' , $this->allowed_html );
308 + }
309 +
310 + public function patchstack_basic_firewall_geo_inverse_input() {
311 + $string1 = __( 'If enabled, instead of checking if the country of the visitor is in the list, check if it is not in the list instead.', 'patchstack' );
312 + echo wp_kses( '<input type="checkbox" name="patchstack_geo_block_inverse" id="patchstack_geo_block_inverse" value="1" ' . checked( 1, $this->get_option( 'patchstack_geo_block_inverse' ), false ) . '/><label for="patchstack_geo_block_inverse"><i>' . $string1 . '</i></label>' , $this->allowed_html );
313 + }
314 +
315 + public function patchstack_basic_firewall_geo_countries_input() {
316 + $string1 = __( 'Specify which countries should be blocked.<br />Note that this will also block any type of (legitimate) bot traffic coming from this country. IP to country resolution might also not be 100% accurate.', 'patchstack' );
317 + $countries = $this->get_option( 'patchstack_geo_block_countries', [] );
318 + $country_list = '';
319 + if ( ! empty( $countries ) ) {
320 + foreach ( $countries as $country ) {
321 + $country_list .= esc_attr( $country ) . ",";
322 + }
323 + }
324 + echo wp_kses( '<select id="geo-countries" data-selected="' . substr( $country_list, 0, -1 ) . '" name="patchstack_geo_block_countries[]" placeholder="Select a country..."><option value="">Select a country...</option><option value="AF">Afghanistan</option> <option value="AX">&Aring;land Islands</option> <option value="AL">Albania</option> <option value="DZ">Algeria</option> <option value="AS">American Samoa</option> <option value="AD">Andorra</option> <option value="AO">Angola</option> <option value="AI">Anguilla</option> <option value="AQ">Antarctica</option> <option value="AG">Antigua and Barbuda</option> <option value="AR">Argentina</option> <option value="AM">Armenia</option> <option value="AW">Aruba</option> <option value="AU">Australia</option> <option value="AT">Austria</option> <option value="AZ">Azerbaijan</option> <option value="BS">Bahamas</option> <option value="BH">Bahrain</option> <option value="BD">Bangladesh</option> <option value="BB">Barbados</option> <option value="BY">Belarus</option> <option value="BE">Belgium</option> <option value="BZ">Belize</option> <option value="BJ">Benin</option> <option value="BM">Bermuda</option> <option value="BT">Bhutan</option> <option value="BO">Bolivia, Plurinational State of</option> <option value="BA">Bosnia and Herzegovina</option> <option value="BW">Botswana</option> <option value="BV">Bouvet Island</option> <option value="BR">Brazil</option> <option value="IO">British Indian Ocean Territory</option> <option value="BN">Brunei Darussalam</option> <option value="BG">Bulgaria</option> <option value="BF">Burkina Faso</option> <option value="BI">Burundi</option> <option value="KH">Cambodia</option> <option value="CM">Cameroon</option> <option value="CA">Canada</option> <option value="CV">Cape Verde</option> <option value="KY">Cayman Islands</option> <option value="CF">Central African Republic</option> <option value="TD">Chad</option> <option value="CL">Chile</option> <option value="CN">China</option> <option value="CX">Christmas Island</option> <option value="CC">Cocos (Keeling) Islands</option> <option value="CO">Colombia</option> <option value="KM">Comoros</option> <option value="CG">Congo</option> <option value="CD">Congo, the Democratic Republic of the</option> <option value="CK">Cook Islands</option> <option value="CR">Costa Rica</option> <option value="CI">C&ocirc;te d\'Ivoire</option> <option value="HR">Croatia</option> <option value="CU">Cuba</option> <option value="CY">Cyprus</option> <option value="CZ">Czech Republic</option> <option value="DK">Denmark</option> <option value="DJ">Djibouti</option> <option value="DM">Dominica</option> <option value="DO">Dominican Republic</option> <option value="EC">Ecuador</option> <option value="EG">Egypt</option> <option value="SV">El Salvador</option> <option value="GQ">Equatorial Guinea</option> <option value="ER">Eritrea</option> <option value="EE">Estonia</option> <option value="ET">Ethiopia</option> <option value="FK">Falkland Islands (Malvinas)</option> <option value="FO">Faroe Islands</option> <option value="FJ">Fiji</option> <option value="FI">Finland</option> <option value="FR">France</option> <option value="GF">French Guiana</option> <option value="PF">French Polynesia</option> <option value="TF">French Southern Territories</option> <option value="GA">Gabon</option> <option value="GM">Gambia</option> <option value="GE">Georgia</option> <option value="DE">Germany</option> <option value="GH">Ghana</option> <option value="GI">Gibraltar</option> <option value="GR">Greece</option> <option value="GL">Greenland</option> <option value="GD">Grenada</option> <option value="GP">Guadeloupe</option> <option value="GU">Guam</option> <option value="GT">Guatemala</option> <option value="GG">Guernsey</option> <option value="GN">Guinea</option> <option value="GW">Guinea-Bissau</option> <option value="GY">Guyana</option> <option value="HT">Haiti</option> <option value="HM">Heard Island and McDonald Islands</option> <option value="VA">Holy See (Vatican City State)</option> <option value="HN">Honduras</option> <option value="HK">Hong Kong</option> <option value="HU">Hungary</option> <option value="IS">Iceland</option> <option value="IN">India</option> <option value="ID">Indonesia</option> <option value="IR">Iran, Islamic Republic of</option> <option value="IQ">Iraq</option> <option value="IE">Ireland</option> <option value="IM">Isle of Man</option> <option value="IL">Israel</option> <option value="IT">Italy</option> <option value="JM">Jamaica</option> <option value="JP">Japan</option> <option value="JE">Jersey</option> <option value="JO">Jordan</option> <option value="KZ">Kazakhstan</option> <option value="KE">Kenya</option> <option value="KI">Kiribati</option> <option value="KP">Korea, Democratic People\'s Republic of</option> <option value="KR">Korea, Republic of</option> <option value="KW">Kuwait</option> <option value="KG">Kyrgyzstan</option> <option value="LA">Lao People\'s Democratic Republic</option> <option value="LV">Latvia</option> <option value="LB">Lebanon</option> <option value="LS">Lesotho</option> <option value="LR">Liberia</option> <option value="LY">Libyan Arab Jamahiriya</option> <option value="LI">Liechtenstein</option> <option value="LT">Lithuania</option> <option value="LU">Luxembourg</option> <option value="MO">Macao</option> <option value="MK">Macedonia, the former Yugoslav Republic of</option> <option value="MG">Madagascar</option> <option value="MW">Malawi</option> <option value="MY">Malaysia</option> <option value="MV">Maldives</option> <option value="ML">Mali</option> <option value="MT">Malta</option> <option value="MH">Marshall Islands</option> <option value="MQ">Martinique</option> <option value="MR">Mauritania</option> <option value="MU">Mauritius</option> <option value="YT">Mayotte</option> <option value="MX">Mexico</option> <option value="FM">Micronesia, Federated States of</option> <option value="MD">Moldova, Republic of</option> <option value="MC">Monaco</option> <option value="MN">Mongolia</option> <option value="ME">Montenegro</option> <option value="MS">Montserrat</option> <option value="MA">Morocco</option> <option value="MZ">Mozambique</option> <option value="MM">Myanmar</option> <option value="NA">Namibia</option> <option value="NR">Nauru</option> <option value="NP">Nepal</option> <option value="NL">Netherlands</option> <option value="AN">Netherlands Antilles</option> <option value="NC">New Caledonia</option> <option value="NZ">New Zealand</option> <option value="NI">Nicaragua</option> <option value="NE">Niger</option> <option value="NG">Nigeria</option> <option value="NU">Niue</option> <option value="NF">Norfolk Island</option> <option value="MP">Northern Mariana Islands</option> <option value="NO">Norway</option> <option value="OM">Oman</option> <option value="PK">Pakistan</option> <option value="PW">Palau</option> <option value="PS">Palestinian Territory, Occupied</option> <option value="PA">Panama</option> <option value="PG">Papua New Guinea</option> <option value="PY">Paraguay</option> <option value="PE">Peru</option> <option value="PH">Philippines</option> <option value="PN">Pitcairn</option> <option value="PL">Poland</option> <option value="PT">Portugal</option> <option value="PR">Puerto Rico</option> <option value="QA">Qatar</option> <option value="RE">R&eacute;union</option> <option value="RO">Romania</option> <option value="RU">Russian Federation</option> <option value="RW">Rwanda</option> <option value="BL">Saint Barth&eacute;lemy</option> <option value="SH">Saint Helena, Ascension and Tristan da Cunha</option> <option value="KN">Saint Kitts and Nevis</option> <option value="LC">Saint Lucia</option> <option value="MF">Saint Martin (French part)</option> <option value="PM">Saint Pierre and Miquelon</option> <option value="VC">Saint Vincent and the Grenadines</option> <option value="WS">Samoa</option> <option value="SM">San Marino</option> <option value="ST">Sao Tome and Principe</option> <option value="SA">Saudi Arabia</option> <option value="SN">Senegal</option> <option value="RS">Serbia</option> <option value="SC">Seychelles</option> <option value="SL">Sierra Leone</option> <option value="SG">Singapore</option> <option value="SK">Slovakia</option> <option value="SI">Slovenia</option> <option value="SB">Solomon Islands</option> <option value="SO">Somalia</option> <option value="ZA">South Africa</option> <option value="GS">South Georgia and the South Sandwich Islands</option> <option value="ES">Spain</option> <option value="LK">Sri Lanka</option> <option value="SD">Sudan</option> <option value="SR">Suriname</option> <option value="SJ">Svalbard and Jan Mayen</option> <option value="SZ">Swaziland</option> <option value="SE">Sweden</option> <option value="CH">Switzerland</option> <option value="SY">Syrian Arab Republic</option> <option value="TW">Taiwan, Province of China</option> <option value="TJ">Tajikistan</option> <option value="TZ">Tanzania, United Republic of</option> <option value="TH">Thailand</option> <option value="TL">Timor-Leste</option> <option value="TG">Togo</option> <option value="TK">Tokelau</option> <option value="TO">Tonga</option> <option value="TT">Trinidad and Tobago</option> <option value="TN">Tunisia</option> <option value="TR">Turkey</option> <option value="TM">Turkmenistan</option> <option value="TC">Turks and Caicos Islands</option> <option value="TV">Tuvalu</option> <option value="UG">Uganda</option> <option value="UA">Ukraine</option> <option value="AE">United Arab Emirates</option> <option value="GB">United Kingdom</option> <option value="US">United States</option> <option value="UM">United States Minor Outlying Islands</option> <option value="UY">Uruguay</option> <option value="UZ">Uzbekistan</option> <option value="VU">Vanuatu</option> <option value="VE">Venezuela, Bolivarian Republic of</option> <option value="VN">Viet Nam</option> <option value="VG">Virgin Islands, British</option> <option value="VI">Virgin Islands, U.S.</option> <option value="WF">Wallis and Futuna</option> <option value="EH">Western Sahara</option> <option value="YE">Yemen</option> <option value="ZM">Zambia</option> <option value="ZW">Zimbabwe</option></select>', $this->allowed_html );
325 + echo wp_kses( '<label for="patchstack_geo_block_enabled"><i>' . $string1 . '</i></label>' , $this->allowed_html );
326 + }
327 +
328 + public function patchstack_xmlrpc_input() {
329 + $string1 = __( 'Restrict access to xmlrpc.php by only allowing authenticated users to access it.', 'patchstack' );
330 + echo wp_kses( '<input type="checkbox" name="patchstack_xmlrpc_is_disabled" id="patchstack_xmlrpc_is_disabled" value="1" ' . checked( 1, $this->get_option( 'patchstack_xmlrpc_is_disabled' ), false ) . '/><label for="patchstack_xmlrpc_is_disabled"><i>' . $string1 . '</i></label>' , $this->allowed_html );
331 + }
332 +
333 + public function patchstack_application_passwords_disabled_input() {
334 + $string1 = __( 'Disables the application passwords feature introduced in WordPress 5.6.', 'patchstack' );
335 + echo wp_kses( '<input type="checkbox" name="patchstack_application_passwords_disabled" id="patchstack_application_passwords_disabled" value="1" ' . checked( 1, $this->get_option( 'patchstack_application_passwords_disabled' ), false ) . '/><label for="patchstack_application_passwords_disabled"><i>' . $string1 . '</i></label>' , $this->allowed_html );
336 + }
337 +
338 + public function patchstack_json_is_disabled_input() {
339 + $string1 = __( 'Restrict access to the WP Rest API by only allowing authenticated users to access it.', 'patchstack' );
340 + echo wp_kses( '<input type="checkbox" name="patchstack_json_is_disabled" id="patchstack_json_is_disabled" value="1" ' . checked( 1, $this->get_option( 'patchstack_json_is_disabled' ), false ) . '/><label for="patchstack_json_is_disabled"><i>' . $string1 . '</i></label>' , $this->allowed_html );
341 + }
342 +
343 + public function patchstack_register_email_blacklist_input() {
344 + $string1 = __( '<br /><br />Enter patterns here, seperated by commas, which email addresses we should block upon registration.<br />For example if you enter @badsite.com it will block all email addresses that contain @badsite.com.', 'patchstack' );
345 + echo wp_kses( '<input type="text" name="patchstack_register_email_blacklist" id="patchstack_register_email_blacklist" value="' . esc_attr( $this->get_option( 'patchstack_register_email_blacklist', '' ) ) . '"/><label for="patchstack_register_email_blacklist"><i>' . $string1 . '</i></label>' , $this->allowed_html );
346 + }
347 +
348 + public function patchstack_activity_log_input() {
349 + $string1 = __( 'If enabled, a large number of user related activities will be logged.', 'patchstack' );
350 + echo wp_kses( '<input type="checkbox" name="patchstack_activity_log_is_enabled" id="patchstack_activity_log_is_enabled" value="1" ' . checked( 1, $this->get_option( 'patchstack_activity_log_is_enabled' ), false ) . '/><label for="patchstack_activity_log_is_enabled"><i>' . $string1 . '</i></label>' , $this->allowed_html );
351 + }
352 +
353 + public function patchstack_activity_log_failed_logins_input() {
354 + $string1 = __( 'If this is checked along with the activity logs, we will also log failed login attempts.', 'patchstack' );
355 + echo wp_kses( '<input type="checkbox" name="patchstack_activity_log_failed_logins" id="patchstack_activity_log_failed_logins" value="1" ' . checked( 1, $this->get_option( 'patchstack_activity_log_failed_logins' ), false ) . '/><label for="patchstack_activity_log_failed_logins"><i>' . $string1 . '</i></label>' , $this->allowed_html );
356 + }
357 +
358 + public function patchstack_activity_log_failed_logins_db_input() {
359 + $string1 = __( 'If this is checked along with the failed login logger, we will also upload the failed login logs to Patchstack.', 'patchstack' );
360 + echo wp_kses( '<input type="checkbox" name="patchstack_activity_log_failed_logins_db" id="patchstack_activity_log_failed_logins_db" value="1" ' . checked( 1, $this->get_option( 'patchstack_activity_log_failed_logins_db' ), false ) . '/><label for="patchstack_activity_log_failed_logins_db"><i>' . $string1 . '</i></label>' , $this->allowed_html );
361 + }
362 +
363 + public function patchstack_captcha_on_comments_callback() {
364 + $string1 = __( 'Check this if you want to enable reCAPTCHA on post comments.', 'patchstack' );
365 + echo wp_kses( '<input type="checkbox" name="patchstack_captcha_on_comments" id="patchstack_captcha_on_comments" value="1" ' . checked( 1, $this->get_option( 'patchstack_captcha_on_comments' ), false ) . '/><label for="patchstack_captcha_on_comments"><i>' . $string1 . '</i></label>' , $this->allowed_html );
366 + }
367 +
368 + public function patchstack_cookie_notice_credits_callback() {
369 + $string1 = __( 'Check this if you want to display "Powered by Patchstack"', 'patchstack' );
370 + echo wp_kses( '<input type="checkbox" name="patchstack_cookie_notice_credits" id="patchstack_cookie_notice_credits" value="1" ' . checked( 1, $this->get_option( 'patchstack_cookie_notice_credits' ), false ) . '/><label for="patchstack_cookie_notice_credits"><i>' . $string1 . '</i></label>' , $this->allowed_html );
371 + }
372 +
373 + public function patchstack_enable_cookie_notice_callback() {
374 + $string1 = __( 'Check this if you want to enable cookie notice message.', 'patchstack' );
375 + echo wp_kses( '<input type="checkbox" name="patchstack_enable_cookie_notice_message" id="patchstack_enable_cookie_notice_message" value="1" ' . checked( 1, $this->get_option( 'patchstack_enable_cookie_notice_message' ), false ) . '/><label for="patchstack_index_views"><i>' . $string1 . '</i></label>' , $this->allowed_html );
376 + }
377 +
378 + public function patchstack_cookie_notice_message_callback() {
379 + echo wp_kses( '<textarea name="patchstack_cookie_notice_message" id="patchstack_cookie_notice_message" rows="20" cols="50">' . esc_textarea( $this->get_option( 'patchstack_cookie_notice_message' ) ) . '</textarea>', $this->allowed_html );
380 + }
381 +
382 + public function patchstack_cookie_notice_accept_text_callback() {
383 + echo wp_kses( "<input type='text' name='patchstack_cookie_notice_accept_text' id='patchstack_cookie_notice_accept_text' value='" . esc_attr( $this->get_option( 'patchstack_cookie_notice_accept_text' ) ) . "'>", $this->allowed_html );
384 + }
385 +
386 + public function patchstack_cookie_notice_backgroundcolor_callback() {
387 + echo wp_kses( "<input type='text' class='jscolor' name='patchstack_cookie_notice_backgroundcolor' id='patchstack_cookie_notice_backgroundcolor' value='" . esc_attr( $this->get_option( 'patchstack_cookie_notice_backgroundcolor' ) ) . "'>", $this->allowed_html );
388 + }
389 +
390 + public function patchstack_cookie_notice_textcolor_callback() {
391 + echo wp_kses( "<input type='text' class='jscolor' name='patchstack_cookie_notice_textcolor' id='patchstack_cookie_notice_textcolor' value='" . esc_attr( $this->get_option( 'patchstack_cookie_notice_textcolor' ) ) . "'>", $this->allowed_html );
392 + }
393 +
394 + public function patchstack_cookie_notice_privacypolicy_enable_callback() {
395 + $string1 = __( 'Check this if you want to enable policy link.', 'patchstack' );
396 + echo wp_kses( '<input type="checkbox" name="patchstack_cookie_notice_privacypolicy_enable" id="patchstack_cookie_notice_privacypolicy_enable" value="1" ' . checked( 1, $this->get_option( 'patchstack_cookie_notice_privacypolicy_enable' ), false ) . '/><label for="patchstack_index_views"><i>' . $string1 . '</i></label>' , $this->allowed_html );
397 + }
398 +
399 + public function patchstack_cookie_notice_privacypolicy_text_callback() {
400 + echo wp_kses( "<input type='text' name='patchstack_cookie_notice_privacypolicy_text' id='patchstack_cookie_notice_privacypolicy_text' value='" . esc_attr( $this->get_option( 'patchstack_cookie_notice_privacypolicy_text' ) ) . "'>", $this->allowed_html );
401 + }
402 +
403 + public function patchstack_cookie_notice_privacypolicy_link_callback() {
404 + echo wp_kses( "<input type='text' name='patchstack_cookie_notice_privacypolicy_link' id='patchstack_cookie_notice_privacypolicy_link' value='" . esc_attr( $this->get_option( 'patchstack_cookie_notice_privacypolicy_link' ) ) . "'>" , $this->allowed_html );
405 + echo wp_kses( '<br /><label for="patchstack_cookie_notice_privacypolicy_link"><i>Starting with http(s)://</i></label>', $this->allowed_html );
406 + }
407 +
408 + public function patchstack_cookie_notice_cookie_expiration_callback() {
409 + echo wp_kses ( '
410 + <select name="patchstack_cookie_notice_cookie_expiration" id="patchstack_cookie_notice_cookie_expiration">
411 + <option ' . ( $this->get_option( 'patchstack_cookie_notice_cookie_expiration' ) == 'after_exit' ? 'selected="selected"' : '' ) . ' value="after_exit">After user re-open browser</option>
412 + <option ' . ( $this->get_option( 'patchstack_cookie_notice_cookie_expiration' ) == '1week' ? 'selected="selected"' : '' ) . ' value="1week">After 1 week</option>
413 + <option ' . ( $this->get_option( 'patchstack_cookie_notice_cookie_expiration' ) == '1month' ? 'selected="selected"' : '' ) . ' value="1month">After 1 month</option>
414 + <option ' . ( $this->get_option( 'patchstack_cookie_notice_cookie_expiration' ) == '1year' ? 'selected="selected"' : '' ) . ' value="1year">After 1 year</option>
415 + </select>
416 + ', $this->allowed_html );
417 + }
418 +
419 + public function patchstack_cookie_notice_opacity_callback() {
420 + echo wp_kses( "<input min=1 max=100 type='number' name='patchstack_cookie_notice_opacity' id='patchstack_cookie_notice_opacity' value='" . esc_attr( $this->get_option( 'patchstack_cookie_notice_opacity' ) ) . "'>", $this->allowed_html );
421 + echo wp_kses( '<br /><label for="patchstack_cookie_notice_opacity"><i>min: 1 - max: 99 - no opacity: 100</i></label>', $this->allowed_html );
422 + }
423 +
424 + public function patchstack_hidewplogin_input() {
425 + $string1 = __( 'Block access to the default wp-login.php page. This will require you to visit the URL below which will whitelist your IP address for 10 minutes to login.', 'patchstack' );
426 + echo wp_kses( '<input type="checkbox" name="patchstack_mv_wp_login" id="patchstack_mv_wp_login" value="1" ' . checked( 1, $this->get_option( 'patchstack_mv_wp_login' ), false ) . '/><label for="patchstack_mv_wp_login"><i>' . $string1 . '</i></label>' , $this->allowed_html );
427 + }
428 +
429 + public function patchstack_hidewplogin_rename_input() {
430 + if ( $this->get_option( 'patchstack_mv_wp_login' ) == 0 && $this->get_option( 'patchstack_rename_wp_login' ) == 'swlogin' ) {
431 + update_site_option( 'patchstack_rename_wp_login', md5( wp_generate_password( 32, true, true ) ) );
432 + }
433 +
434 + echo wp_kses( '<label><i style="color:red;">This feature should not be used if you have renamed your login page already or when you make use of a system that allows regular users to login.</i></label><br /><br /><label style="font-weight: 300; color: #d0d0d0;"> ' . get_site_url() . '/ </label><input type="text" style="width: 350px;" name="patchstack_rename_wp_login" id="patchstack_rename_wp_login" value="' . esc_attr( $this->get_option( 'patchstack_rename_wp_login' ) ) . '" />' , $this->allowed_html );
435 + if ( $this->get_option( 'patchstack_mv_wp_login' ) && $this->get_option( 'patchstack_rename_wp_login' ) ) {
436 + echo wp_kses( '<br /><br /><div style="font-weight: 300; color: #d0d0d0;">Your login access page is here: <a href="' . get_site_url() . '/' . esc_attr( $this->get_option( 'patchstack_rename_wp_login' ) ) . '">' . get_site_url() . '/' . esc_attr( $this->get_option( 'patchstack_rename_wp_login' ) ) . '</div></a>', $this->allowed_html );
437 + echo wp_kses( '<br /><input type="submit" id="patchstack_send_mail_url" name="patchstack_send_mail_url" value="Send the link to your admin email." class="button-primary" />', $this->allowed_html );
438 + }
439 + }
440 +
441 + public function patchstack_pluginedit_input() {
442 + $string1 = __( 'Disable the theme editor. This could protect you from potential automated attacks that involve the theme editor.', 'patchstack' );
443 + echo wp_kses( '<input type="checkbox" name="patchstack_pluginedit" id="patchstack_pluginedit" value="1" ' . checked( 1, $this->get_option( 'patchstack_pluginedit' ), false ) . '/><label for="patchstack_pluginedit"><i>' . $string1 . '</i></label>' , $this->allowed_html );
444 + }
445 +
446 + public function patchstack_add_security_headers_input() {
447 + $string1 = __( 'Add security headers to the response by your webserver.', 'patchstack' );
448 + echo wp_kses( '<input type="checkbox" name="patchstack_add_security_headers" id="patchstack_add_security_headers" value="1" ' . checked( 1, $this->get_option( 'patchstack_add_security_headers' ), false ) . '/><label for="patchstack_add_security_headers"><i>' . $string1 . '</i></label>' , $this->allowed_html );
449 + }
450 +
451 + public function patchstack_basicscanblock_input() {
452 + $string1 = __( 'This will attempt to stop basic readme.txt scans. These scans are generally used to determine the version of installed plugins on the site.', 'patchstack' );
453 + echo wp_kses( '<input type="checkbox" name="patchstack_basicscanblock" id="patchstack_basicscanblock" value="1" ' . checked( 1, $this->get_option( 'patchstack_basicscanblock' ), false ) . '/><label for="patchstack_basicscanblock"><i>' . $string1 . '</i></label>' , $this->allowed_html );
454 + }
455 +
456 + public function patchstack_userenum_input() {
457 + $string1 = __( 'Make it harder for malicious people to find your WordPress username.', 'patchstack' );
458 + echo wp_kses( '<input type="checkbox" name="patchstack_userenum" id="patchstack_userenum" value="1" ' . checked( 1, $this->get_option( 'patchstack_userenum' ), false ) . '/><label for="patchstack_userenum"><i>' . $string1 . '</i></label>' , $this->allowed_html );
459 + }
460 +
461 + public function patchstack_hidewpversion_input() {
462 + $string1 = __( 'Removes the WordPress version in the meta tag in the HTML output.', 'patchstack' );
463 + echo wp_kses( '<input type="checkbox" name="patchstack_hidewpversion" id="patchstack_hidewpversion" value="1" ' . checked( 1, $this->get_option( 'patchstack_hidewpversion' ), false ) . '/><label for="patchstack_hidewpversion"><i>' . $string1 . '</i></label>' , $this->allowed_html );
464 + }
465 +
466 + public function patchstack_rm_readme_input() {
467 + $string1 = __( 'Removes the readme.html file from the WordPress root folder.', 'patchstack' );
468 + echo wp_kses( '<input type="checkbox" name="patchstack_rm_readme" id="patchstack_rm_readme" value="1" ' . checked( 1, $this->get_option( 'patchstack_rm_readme' ), false ) . '/><label for="patchstack_rm_readme"><i>' . $string1 . '</i></label>' , $this->allowed_html );
469 + }
470 +
471 + public function patchstack_prevent_default_file_access_input() {
472 + $string1 = __( 'Prevent direct access to files such as license.txt, readme.html and wp-config.php', 'patchstack' );
473 + echo wp_kses( '<input type="checkbox" name="patchstack_prevent_default_file_access" id="patchstack_prevent_default_file_access" value="1" ' . checked( 1, $this->get_option( 'patchstack_prevent_default_file_access' ), false ) . '/><label for="patchstack_prevent_default_file_access"><i>' . $string1 . '</i></label>' , $this->allowed_html );
474 + }
475 +
476 + public function patchstack_basic_firewall_input() {
477 + $string1 = __( 'Check this if you want to turn on the advanced firewall protection on your site.', 'patchstack' );
478 + echo wp_kses( '<input type="checkbox" name="patchstack_basic_firewall" id="patchstack_basic_firewall" value="1" ' . checked( 1, $this->get_option( 'patchstack_basic_firewall' ), false ) . '/><label for="patchstack_basic_firewall"><i>' . $string1 . '</i></label><br /><br /><i style="color:#d0d0d0">Block IP for <input style="width: 50px;" type="number" name="patchstack_autoblock_blocktime" value="' . esc_attr( $this->get_option( 'patchstack_autoblock_blocktime', 60 ) ) . '" id="patchstack_autoblock_blocktime"> minutes after <input style="width: 50px;" type="number" name="patchstack_autoblock_attempts" value="' . esc_attr( $this->get_option( 'patchstack_autoblock_attempts', 10 ) ) . '" id="patchstack_autoblock_attempts"> blocked requests over a period of <input style="width: 50px;" type="number" name="patchstack_autoblock_minutes" value="' . esc_attr( $this->get_option( 'patchstack_autoblock_minutes', 30 ) ) . '" id="patchstack_autoblock_minutes"> minutes</i>', $this->allowed_html);
479 + }
480 +
481 + public function patchstack_basic_firewall_roles_input() {
482 + $selected = $this->get_option( 'patchstack_basic_firewall_roles', [ 'administrator', 'editor', 'author' ] );
483 + $selected = ! is_array( $selected ) ? [] : $selected;
484 + $roles = wp_roles();
485 + $roles = $roles->get_names();
486 + $text = '';
487 + foreach ( $roles as $key => $val ) {
488 + $text .= '<input type="checkbox" id="patchstack_basic_firewall_roles-' . esc_attr( $key ) . '" name="patchstack_basic_firewall_roles[]" value="' . esc_attr( $key ) . '" ' . checked( 1, in_array( $key, $selected ), false ) . '/><label for="patchstack_basic_firewall_roles-' . esc_attr( $key ) . '"><i>' . esc_html( $val ) . '</i></label><br>';
489 + }
490 +
491 + $string1 = __( 'Against which user roles should the firewall not run against?<br />The firewall will always run against guests.<br />', 'patchstack' );
492 + echo wp_kses( ( '<label for="patchstack_basic_firewall_roles"><i>' . $string1 . '</i></label><br />' . $text ), $this->allowed_html );
493 + }
494 +
495 + public function patchstack_known_blacklist_input() {
496 + $string1 = __( 'Check this if you want to block known malicious connections.', 'patchstack' );
497 + echo wp_kses( '<input type="checkbox" name="patchstack_known_blacklist" id="patchstack_known_blacklist" value="1" ' . checked( 1, $this->get_option( 'patchstack_known_blacklist' ), false ) . '/><label for="patchstack_known_blacklist"><i>' . $string1 . '</i></label>' , $this->allowed_html );
498 + }
499 +
500 + public function patchstack_firewall_ip_header_input() {
501 + $string1 = __( 'If you would like to override the IP address header that we use to grab the IP address of the visitor, enter the value here. This must be a valid value in the $_SERVER array, for example HTTP_X_FORWARDED_FOR. If the $_SERVER value you enter does not exist, it will fallback to the Patchstack IP grab function so ask your hosting company if you are unsure. Leave this empty to use the Patchstack IP address grabbing function.', 'patchstack' );
502 + echo wp_kses( '<input type="text" name="patchstack_firewall_ip_header" id="patchstack_firewall_ip_header" value="' . esc_attr( $this->get_option( 'patchstack_firewall_ip_header' ) ) . '"/><br /><br /><label for="patchstack_firewall_ip_header"><i>' . $string1 . '</i></label>' , $this->allowed_html );
503 + }
504 +
505 + public function patchstack_disable_htaccess_input() {
506 + $string1 = __( 'Check this if you want to stop us from writing to your .htaccess file. Note that the current changes to the .htaccess file will remain.', 'patchstack' );
507 + echo wp_kses( '<input type="checkbox" name="patchstack_disable_htaccess" id="patchstack_disable_htaccess" value="1" ' . checked( 1, $this->get_option( 'patchstack_disable_htaccess' ), false ) . '/><label for="patchstack_disable_htaccess"><i>' . $string1 . '</i></label>' , $this->allowed_html );
508 + }
509 +
510 + public function patchstack_block_debug_log_access_input() {
511 + $string1 = __( 'Check this if you want to block access to the debug.log file that WordPress creates when debug logging is enabled.', 'patchstack' );
512 + echo wp_kses( '<input type="checkbox" name="patchstack_block_debug_log_access" id="patchstack_block_debug_log_access" value="1" ' . checked( 1, $this->get_option( 'patchstack_block_debug_log_access' ), false ) . '/><label for="patchstack_block_debug_log_access"><i>' . $string1 . '</i></label>' , $this->allowed_html );
513 + }
514 +
515 + public function patchstack_index_views_input() {
516 + $string1 = __( 'Check this if you want to disable directory and file listing.', 'patchstack' );
517 + echo wp_kses( '<input type="checkbox" name="patchstack_index_views" id="patchstack_index_views" value="1" ' . checked( 1, $this->get_option( 'patchstack_index_views' ), false ) . '/><label for="patchstack_index_views"><i>' . $string1 . '</i></label>' , $this->allowed_html );
518 + }
519 +
520 + public function patchstack_proxy_comment_posting_input() {
521 + $string1 = __( 'Check this if you want to forbid proxy comment posting.', 'patchstack' );
522 + echo wp_kses( '<input type="checkbox" name="patchstack_proxy_comment_posting" id="patchstack_proxy_comment_posting" value="1" ' . checked( 1, $this->get_option( 'patchstack_proxy_comment_posting' ), false ) . '/><label for="patchstack_proxy_comment_posting"><i>' . $string1 . '</i></label>' , $this->allowed_html );
523 + }
524 +
525 + public function patchstack_block_bruteforce_ips_input() {
526 + $string1 = __( 'Check this if you want to automatically ban IP addresses that fail to login multiple times in a short span of time.<br />For this feature to work, make sure that "Log failed logins" is turned on at the hardening settings page.', 'patchstack' );
527 + echo wp_kses( '<input type="checkbox" name="patchstack_block_bruteforce_ips" id="patchstack_block_bruteforce_ips" value="1" ' . checked( 1, $this->get_option( 'patchstack_block_bruteforce_ips' ), false ) . '/><label for="patchstack_block_bruteforce_ips"><i>' . $string1 . '</i></label><br /><br /><i style="color:#d0d0d0">Block IP for <input style="width: 50px;" type="number" name="patchstack_anti_bruteforce_blocktime" value="' . esc_attr( $this->get_option( 'patchstack_anti_bruteforce_blocktime', 60 ) ) . '" id="patchstack_anti_bruteforce_blocktime"> minutes after <input style="width: 50px;" type="number" name="patchstack_anti_bruteforce_attempts" value="' . esc_attr( $this->get_option( 'patchstack_anti_bruteforce_attempts', 10 ) ) . '" id="patchstack_anti_bruteforce_attempts"> failed login attempts over a period of <input style="width: 50px;" type="number" name="patchstack_anti_bruteforce_minutes" value="' . esc_attr( $this->get_option( 'patchstack_anti_bruteforce_minutes', 5 ) ) . '" id="patchstack_anti_bruteforce_minutes"> minutes</i>' , $this->allowed_html );
528 + }
529 +
530 + public function patchstack_login_time_block_input() {
531 + $string1 = __( 'Check this if you want to enforce specific logon hours.', 'patchstack' );
532 + echo wp_kses( '<input type="checkbox" name="patchstack_login_time_block" id="patchstack_login_time_block" value="1" ' . checked( 1, $this->get_option( 'patchstack_login_time_block' ), false ) . '/><label for="patchstack_login_time_block"><i>' . $string1 . '</i></label><br /><br /><i style="color:#d0d0d0">Allow login between <input style="width: 70px;" type="text" name="patchstack_login_time_start" value="' . esc_attr( $this->get_option( 'patchstack_login_time_start', '00:00' ) ) . '" id="patchstack_login_time_start" autocomplete="off"> and <input style="width: 70px;" type="text" name="patchstack_login_time_end" value="' . esc_attr( $this->get_option( 'patchstack_login_time_end', '23:59' ) ) . '" id="patchstack_login_time_end" autocomplete="off"><br />Times must be in the 24 hour clock format.<br />The logon hours are also based on the current time of your site: ' . current_time( 'H:i:s' ) . '</i>', $this->allowed_html );
533 + }
534 +
535 + public function patchstack_login_2fa_input() {
536 + $string1 = __( 'Check this if you want to make it possible for users to enable two factor authentication (2FA) on their account.', 'patchstack' );
537 + echo wp_kses( '<input type="checkbox" name="patchstack_login_2fa" id="patchstack_login_2fa" value="1" ' . checked( 1, $this->get_option( 'patchstack_login_2fa' ), false ) . '/><label for="patchstack_login_2fa"><i>' . $string1 . '<br />Once enabled, users can configure 2FA on the "Edit My Profile" page which is located <a href="' . admin_url( 'profile.php' ) . '">here</a>.</i></label><br />' , $this->allowed_html );
538 + }
539 +
540 + public function patchstack_login_blocked_input() {
541 + // Calculate block time.
542 + $minutes = (int) $this->get_option( 'patchstack_anti_bruteforce_minutes', 30 );
543 + $timeout = (int) $this->get_option( 'patchstack_anti_bruteforce_blocktime', 60 );
544 + if ( empty( $minutes ) || empty( $timeout ) ) {
545 + $time = 30 + 60;
546 + } else {
547 + $time = $minutes + $timeout;
548 + }
549 +
550 + // Check if X failed login attempts were made.
551 + global $wpdb;
552 + $results = $wpdb->get_results(
553 + $wpdb->prepare( 'SELECT id, ip, date FROM ' . $wpdb->prefix . "patchstack_event_log WHERE action = 'failed login' AND date >= ('" . current_time( 'mysql' ) . "' - INTERVAL %d MINUTE) GROUP BY ip HAVING COUNT(ip) >= %d ORDER BY date DESC", [ $time, $this->get_option( 'patchstack_anti_bruteforce_attempts', 10 ) ] ),
554 + OBJECT
555 + );
556 +
557 + // Render the rows.
558 + $rows = '';
559 + if ( count( $results ) == 0 ) {
560 + $rows = '<tr><td>No blocked IP addresses.</td><td></td><td></td><td></td></tr>';
561 + } else {
562 + $nonce = wp_create_nonce( 'patchstack-nonce-alter-ips' );
563 + foreach ( $results as $result ) {
564 + $rows .= '<tr><td>' . esc_html( $result->ip ) . '</td><td>' . ( isset( $result->log_date ) ? $result->log_date : $result->date ) . '</td><td><a href="' . esc_url( add_query_arg(
565 + [
566 + 'PatchstackNonce' => $nonce,
567 + 'action' => 'patchstack_unblock',
568 + 'id' => $result->id,
569 + ]
570 + ) ) . '">Unblock</a></td><td><a href="' . esc_url( add_query_arg(
571 + [
572 + 'PatchstackNonce' => $nonce,
573 + 'action' => 'patchstack_unblock_whitelist',
574 + 'id' => $result->id,
575 + ]
576 + ) ) . '">Unblock &amp; Whitelist</a></td></tr>';
577 + }
578 + }
579 +
580 + $string1 = __( 'These are the IP addresses that are currently blocked because of too many failed login attempts.<br />These are not the IP addresses banned by the firewall itself.<br /><br />', 'patchstack' );
581 + echo wp_kses( '<label><i>' . $string1 . '</i></label>', $this->allowed_html );
582 + echo wp_kses( '<div class="patchstack-content-inner-table"><table class="table dataTable patchstack-bi" style="margin: 0 !important;"><thead><tr><th>IP Address</th><th style="padding-left: 0 !important;">Last Attempt</th><th style="padding-left: 0 !important;">Unblock</th><th style="padding-left: 0 !important;">Unbock &amp; Whitelist</th></tr></thead><tbody>' . $rows . '</table></div>', $this->allowed_html );
583 + }
584 +
585 + public function patchstack_login_whitelist_input() {
586 + $ip_list = esc_textarea( rtrim( $this->get_option( 'patchstack_login_whitelist', '' ) ) );
587 + echo wp_kses( '<label><i>These IP addresses will never be blocked from logging in, no matter the amount of failed logins.</i></label><br /><br /><p><textarea rows="5" id="patchstack_login_whitelist" name="patchstack_login_whitelist">' . $ip_list . '</textarea>Each entry must be on its own line.<br />Your current IP address is: ' . esc_html( $this->get_ip() ) . '<br /><br /><strong>Following formats are accepted:</strong><p>127.0.0.1</p><p>127.0.0.*</p><p>127.0.0.0/24</p><p>127.0.0.0-127.0.0.255</p></p>', $this->allowed_html );
588 + }
589 +
590 + public function patchstack_image_hotlinking_input() {
591 + $string1 = __( 'Check this if you want to prevent hotlinking to images on your site.', 'patchstack' );
592 + echo wp_kses( '<input type="checkbox" name="patchstack_image_hotlinking" id="patchstack_image_hotlinking" value="1" ' . checked( 1, $this->get_option( 'patchstack_image_hotlinking' ), false ) . '/><label for="patchstack_image_hotlinking"><i>' . $string1 . '</i></label>' , $this->allowed_html );
593 + }
594 +
595 + public function patchstack_firewall_custom_rules_input() {
596 + $string1 = __( 'Add custom .htaccess rules here if you know what you are doing, otherwise you may break your site. So be careful.', 'patchstack' );
597 + echo wp_kses( '<textarea name="patchstack_firewall_custom_rules" id="patchstack_firewall_custom_rules" rows="20" cols="50" placeholder="' . $string1 . '">', $this->allowed_html );
598 + $rules = $this->get_option( 'patchstack_firewall_custom_rules' );
599 + if ( isset( $rules ) ) {
600 + if ( is_array( $rules ) ) {
601 + foreach ( $rules as $rule ) {
602 + echo wp_kses( esc_textarea( $rule ), $this->allowed_html );
603 + }
604 + } else {
605 + echo wp_kses( esc_textarea( $rules ), $this->allowed_html );
606 + }
607 + }
608 + echo wp_kses( '</textarea>', $this->allowed_html );
609 + echo wp_kses( '<p style="color:red;">If the custom .htaccess rules above cause an error, they will be removed automatically.</p>', $this->allowed_html );
610 + }
611 +
612 + public function patchstack_firewall_custom_rules_loc_input() {
613 + echo wp_kses( '<select name="patchstack_firewall_custom_rules_loc" id="patchstack_firewall_custom_rules_loc"><option ' . ( $this->get_option( 'patchstack_firewall_custom_rules_loc' ) == 'top' ? 'selected="selected"' : '' ) . ' value="top">Top - above Patchstack rules</option><option ' . ( $this->get_option( 'patchstack_firewall_custom_rules_loc' ) == 'bottom' ? 'selected="selected"' : '' ) . ' value="bottom">Bottom - under Patchstack rules</option></select>', $this->allowed_html );
614 + }
615 +
616 + public function patchstack_captcha_login_form_input() {
617 + $string1 = __( 'Check this if you want to enable reCAPTCHA on user login.', 'patchstack' );
618 + echo wp_kses( '<input type="checkbox" name="patchstack_captcha_login_form" id="patchstack_captcha_login_form" value="1" ' . checked( 1, $this->get_option( 'patchstack_captcha_login_form' ), false ) . '/><label for="patchstack_captcha_login_form"><i>' . $string1 . '</i></label>' , $this->allowed_html );
619 + }
620 +
621 + public function patchstack_captcha_registration_form_input() {
622 + $string1 = __( 'Check this if you want to enable reCAPTCHA on registration.', 'patchstack' );
623 + echo wp_kses( '<input type="checkbox" name="patchstack_captcha_registration_form" id="patchstack_captcha_registration_form" value="1" ' . checked( 1, $this->get_option( 'patchstack_captcha_registration_form' ), false ) . '/><label for="patchstack_captcha_registration_form"><i>' . $string1 . '</i></label>' , $this->allowed_html );
624 + }
625 +
626 + public function patchstack_captcha_reset_pwd_form_input() {
627 + $string1 = __( 'Check this if you want to enable reCAPTCHA on password reset.', 'patchstack' );
628 + echo wp_kses( '<input type="checkbox" name="patchstack_captcha_reset_pwd_form" id="patchstack_captcha_reset_pwd_form" value="1" ' . checked( 1, $this->get_option( 'patchstack_captcha_reset_pwd_form' ), false ) . '/><label for="patchstack_captcha_reset_pwd_form"><i>' . $string1 . '</i></label>' , $this->allowed_html );
629 + }
630 +
631 + public function patchstack_captcha_type_callback() {
632 + echo wp_kses( '
633 + <select name="patchstack_captcha_type" id="patchstack_captcha_type">
634 + <option ' . ( $this->get_option( 'patchstack_captcha_type' ) == 'v2' ? 'selected="selected"' : '' ) . ' value="v2">Checkbox (v2)</option>
635 + <option ' . ( $this->get_option( 'patchstack_captcha_type' ) == 'invisible' ? 'selected="selected"' : '' ) . ' value="invisible">Invisible (v2)</option>
636 + <option ' . ( $this->get_option( 'patchstack_captcha_type' ) == 'v3' ? 'selected="selected"' : '' ) . ' value="v3">Invisible (v3)</option>
637 + </select>', $this->allowed_html );
638 + }
639 +
640 + public function patchstack_captcha_public_key_input() {
641 + $string1 = __( '<br /><br />Enter the reCAPTCHA site key here.<br />Click <a href="https://docs.patchstack.com/discuss/62e286cf7040390013b73bf7" target="_blank">here</a> for a guide on how to get the site / secret key.', 'patchstack' );
642 + echo wp_kses( '<input style="display:none;" type="text" name="patchstack_captcha_public_key" id="patchstack_captcha_public_key" value="' . esc_attr( $this->get_option( 'patchstack_captcha_public_key', '' ) ) . '"/><input style="display:none;" type="text" name="patchstack_captcha_public_key_v3" id="patchstack_captcha_public_key_v3" value="' . esc_attr( $this->get_option( 'patchstack_captcha_public_key_v3', '' ) ) . '"/><input style="display:none;" type="text" name="patchstack_captcha_public_key_v3_new" id="patchstack_captcha_public_key_v3_new" value="' . esc_attr( $this->get_option( 'patchstack_captcha_public_key_v3_new', '' ) ) . '"/><label for="patchstack_captcha_public_key"><i>' . $string1 . '</i></label>' , $this->allowed_html );
643 + }
644 +
645 + public function patchstack_captcha_private_key_input() {
646 + $string1 = __( '<br /><br />Enter the reCAPTCHA secret key here.<br />Click <a href="https://docs.patchstack.com/discuss/62e286cf7040390013b73bf7" target="_blank">here</a> for a guide on how to get the site / secret key.', 'patchstack' );
647 + echo wp_kses( '<input style="display:none;" type="text" name="patchstack_captcha_private_key" id="patchstack_captcha_private_key" value="' . esc_attr( $this->get_option( 'patchstack_captcha_private_key', '' ) ) . '"/><input style="display:none;" type="text" name="patchstack_captcha_private_key_v3" id="patchstack_captcha_private_key_v3" value="' . esc_attr( $this->get_option( 'patchstack_captcha_private_key_v3', '' ) ) . '"/><input style="display:none;" type="text" name="patchstack_captcha_private_key_v3_new" id="patchstack_captcha_private_key_v3_new" value="' . esc_attr( $this->get_option( 'patchstack_captcha_private_key_v3_new', '' ) ) . '"/><label for="patchstack_captcha_private_key"><i>' . $string1 . '</i></label>' , $this->allowed_html );
648 + }
649 +
650 + public function patchstack_blackhole_log_input() {
651 + $ip_list = esc_textarea( rtrim( $this->get_option( 'patchstack_ip_block_list', '' ) ) );
652 + echo wp_kses( '<p><textarea rows="5" id="patchstack_ip_block_list" name="patchstack_ip_block_list">' . $ip_list . '</textarea>Each entry must be on its own line.<br /><br /><strong>Following formats are accepted:</strong><p>127.0.0.1</p><p>127.0.0.*</p><p>127.0.0.0/24</p><p>127.0.0.0-127.0.0.255</p>', $this->allowed_html );
653 + }
654 +
655 + public function patchstack_whitelist_input() {
656 + echo wp_kses( '<textarea name="patchstack_whitelist" id="patchstack_whitelist" rows="20" cols="50">' . esc_textarea( $this->get_option( 'patchstack_whitelist' ) ) . '</textarea>', $this->allowed_html );
657 + echo wp_kses( __( '<p>Each rule must be on a new line.<br /><br /><strong>The following keywords are accepted</strong><br />IP:IPADDRESS<br />PAYLOAD:someval<br />URL:/someurl<br /><br /><strong>Definitions</strong><br />IP = firewall will not run against the IP<br />PAYLOAD = if the entire payload contains the keyword, the firewall will not proceed<br />URL = if the URL contains given URL, firewall will not proceed<br /><br /><strong>Example</strong><br />IP:192.168.1.1<br />PAYLOAD:contact_form<br />URL:water<br />URL:/some-form<br /><br />In this scenario, the firewall will not run if the IP address is 192.168.1.1 or if the payload contains contact_form or if the URL contains water or if the URL contains /some-form.</p>', 'patchstack' ), $this->allowed_html );
154 658 }
155 659 }