PluginProbe
NETSENSAI Shield / trunk
NETSENSAI Shield vtrunk
1.6.1 trunk 1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.6.0
← All changes | netsensai-shield.php +226 -61 1.2 → trunk View file →
@@ -4,9 +4,9 @@
4 4 *
5 5 * Plugin Name: NETSENSAI Shield
6 6 * Plugin URI: https://www.netsensai.pl/store/
7 7 * Description: NETSENSAI Shield is a security plugin designed to enhance WordPress site protection by offering essential security features based on best practice principles.
8 - * Version: 1.2
8 + * Version: 1.6.1
9 9 * Author: Rafał Gierlicki
10 10 * Author URI: https://www.netsensai.pl
11 11 * Text Domain: netsensai-shield
12 12 * Contributors: netsensai
@@ -18,8 +18,10 @@
18 18 if ( ! defined( 'ABSPATH' ) ) {
19 19 exit;
20 20 }
21 21
22 +define( 'NS_SHIELD_VERSION', '1.6.1' );
23 +
22 24 /**
23 25 * Filter admin title so it's never null.
24 26 *
25 27 * @param string $title Admin page title.
@@ -34,9 +36,12 @@
34 36 * Define tooltip function for login URL explanation.
35 37 */
36 38 if ( ! function_exists( 'ns_shield_get_login_url_tooltip' ) ) {
37 39 function ns_shield_get_login_url_tooltip() {
38 - return __( 'Changing the login URL helps protect your site from brute-force attacks aimed at the default wp-login.php endpoint. If the default URL remains unchanged, attackers could easily target it to attempt password cracking or credential stuffing attacks.', 'netsensai-shield' );
40 + return __(
41 + 'Changing the login URL helps protect your site from brute-force attacks aimed at the default wp-login.php endpoint. If the default URL remains unchanged, attackers could easily target it to attempt password cracking or credential stuffing attacks.',
42 + 'netsensai-shield'
43 + );
39 44 }
40 45 }
41 46
42 47 /**
@@ -43,33 +48,35 @@
43 48 * Include plugin function files.
44 49 */
45 50 require_once plugin_dir_path( __FILE__ ) . 'includes/login_url_functions.php';
46 51 require_once plugin_dir_path( __FILE__ ) . 'includes/disable_wp_api_json.php';
52 +require_once plugin_dir_path( __FILE__ ) . 'includes/disable_username_enumeration.php';
47 53 require_once plugin_dir_path( __FILE__ ) . 'includes/disable_xml_rpc.php';
48 54 require_once plugin_dir_path( __FILE__ ) . 'includes/disable_app_passwords.php';
49 55 require_once plugin_dir_path( __FILE__ ) . 'includes/disable_file_editor.php';
56 +require_once plugin_dir_path( __FILE__ ) . 'includes/apply_security_headers.php';
57 +require_once plugin_dir_path( __FILE__ ) . 'includes/disable_directory_indexing.php';
50 58 require_once plugin_dir_path( __FILE__ ) . 'includes/disable_default_admin.php';
59 +require_once plugin_dir_path( __FILE__ ) . 'includes/apply_hsts_header.php';
60 +//require_once plugin_dir_path( __FILE__ ) . 'includes/integrations/class-ns-shield-cache-integrator.php';
61 +// Wczytaj integracje
62 +function ns_shield_load_integrations() {
63 + $ns_shield_integration_dir = plugin_dir_path( __FILE__ ) . 'includes/integrations/';
51 64
52 -/**
53 - * Enqueue styles and scripts for the admin area.
54 - */
55 -function ns_shield_enqueue_styles_scripts() {
56 - wp_enqueue_style(
57 - 'ns_shield-style',
58 - plugin_dir_url( __FILE__ ) . 'assets/style.css',
59 - array(),
60 - filemtime( plugin_dir_path( __FILE__ ) . 'assets/style.css' )
61 - );
62 - wp_enqueue_script(
63 - 'ns_shield-script',
64 - plugin_dir_url( __FILE__ ) . 'assets/script.js',
65 - array(),
66 - '1.0',
67 - true
68 - );
65 + if ( is_dir( $ns_shield_integration_dir ) ) {
66 + foreach ( glob( $ns_shield_integration_dir . '*.php' ) as $ns_shield_integration_file ) {
67 + require_once $ns_shield_integration_file;
68 + }
69 + }
69 70 }
70 -add_action( 'admin_enqueue_scripts', 'ns_shield_enqueue_styles_scripts' );
71 +ns_shield_load_integrations();
71 72
73 +// Inicjalizacja integratora cache
74 +function ns_shield_init_cache_integrator() {
75 + new NS_Shield_Cache_Integrator();
76 +}
77 +add_action( 'plugins_loaded', 'ns_shield_init_cache_integrator' );
78 +
72 79 /**
73 80 * Add settings link on the plugins page.
74 81 *
75 82 * @param array $links Array of action links.
@@ -92,17 +99,47 @@
92 99 function ns_shield_secure_options_page() {
93 100 if ( ! current_user_can( 'manage_options' ) ) {
94 101 wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'netsensai-shield' ) );
95 102 }
96 - // Sprawdzamy metodę żądania i czy przesłano pole 'option_page'.
97 - if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] && isset( $_POST['option_page'] ) && 'ns_shield_options_group' === $_POST['option_page'] ) {
98 - // Nonce jest weryfikowany w options.php – poniższa funkcja uspokaja narzędzie analizy.
99 - check_admin_referer( 'ns_shield_options_group-options' );
100 - }
103 +
104 + // Ścieżka do logo
105 + $logo_url = plugin_dir_url( __FILE__ ) . 'assets/ns_logo.png';
106 +
107 + // Tworzymy treść dla popupu z możliwością tłumaczenia.
108 + // Używamy __() dla tekstu zawierającego znaczniki <a> aby linki były działające.
109 + $enable_html = sprintf(
110 + '<div class="ns-popup-logo-container">
111 + <img src="%1$s" alt="%2$s" class="ns-popup-logo" />
112 + </div>
113 + <div class="ns-popup-text">
114 + <p>%3$s</p>
115 + <p>%4$s</p>
116 + <p>%5$s</p>
117 + <p><strong>%6$s</strong> <a href="https://netsensai.pl/store" target="_blank">netsensai.pl/store</a></p>
118 + </div>
119 + <div class="ns-popup-button-container">
120 + <button id="ns-shield-modal-ok" class="ns-modal-ok-button">%7$s</button>
121 + </div>',
122 + esc_url( $logo_url ),
123 + esc_attr__( 'Netsensai Shield Logo', 'netsensai-shield' ),
124 + // Używamy __() zamiast esc_html__() dla akapitu ze znacznikami <a>
125 + __( 'Your website now achieves top scores in the most popular security scanners. (Check <a href="https://securityheaders.com" target="_blank">securityheaders.com</a> or <a href="https://observatory.mozilla.org" target="_blank">Mozilla Observatory</a>) Great job!', 'netsensai-shield' ),
126 + esc_html__( 'But in the PRO Club, we do even more: we detect, block, and support.', 'netsensai-shield' ),
127 + esc_html__( 'If an attack occurs, you get 3 months of assistance on us!', 'netsensai-shield' ),
128 + esc_html__( 'Check out:', 'netsensai-shield' ),
129 + esc_html__( 'OK', 'netsensai-shield' )
130 + );
131 +
132 + $disable_html = sprintf(
133 + '<h2 style="text-align:center; font-size:1.3em; margin-bottom:10px; color:#000;">%1$s</h2>
134 + <p style="font-size:1.1em; line-height:1.4; color:#000;">%2$s</p>',
135 + esc_html__( 'Oops...', 'netsensai-shield' ),
136 + esc_html__( 'The option has been disabled.', 'netsensai-shield' )
137 + );
101 138 ?>
102 139 <div id="netsensai-shield-plugin" class="wrap">
103 140
104 - <!-- Banner reklamowy wersji PRO -->
141 + <!-- PRO version banner -->
105 142 <div style="border: 1px solid #555; padding: 5px; margin: 5px 0; background-color: transparent; text-align: center; color: #fff;">
106 143 <p style="font-size: 1.2em; font-weight: bold; margin-bottom: 5px;">
107 144 <?php esc_html_e( 'Upgrade to NETSENSAI-SHIELD PRO for enhanced protection and advanced features.', 'netsensai-shield' ); ?>
108 145 </p>
@@ -115,9 +152,9 @@
115 152 </div>
116 153
117 154 <h2><?php echo esc_html__( 'Security Options', 'netsensai-shield' ); ?></h2>
118 155
119 - <!-- Wyświetlenie logotypów -->
156 + <!-- Logos display -->
120 157 <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 10px;">
121 158 <a href="https://www.netsensai.pl/store/" target="_blank" style="display: flex; align-items: center; gap: 20px;">
122 159 <img src="<?php echo esc_url( plugin_dir_url( __FILE__ ) . 'assets/ns_logo.png' ); ?>"
123 160 alt="<?php echo esc_attr__( 'Netsensai-Shield Logo', 'netsensai-shield' ); ?>"
@@ -127,21 +164,45 @@
127 164 style="width: 220px; height: auto; margin-bottom: -20px;">
128 165 </a>
129 166 </div>
130 167
131 - <!--
132 - Formularz przesyłany jest do options.php, gdzie nonce jest weryfikowany automatycznie,
133 - gdyż settings_fields() generuje odpowiednie pola ukryte.
134 - -->
168 + <!-- Konfiguracja modala -->
169 + <script type="text/javascript">
170 + window.nsShieldModalConfig = {
171 + modalShownFor: '',
172 + enableContentHTML: <?php echo wp_json_encode( $enable_html ); ?>,
173 + disableContentHTML: <?php echo wp_json_encode( $disable_html ); ?>
174 + };
175 + </script>
176 +
135 177 <form method="post" action="options.php">
136 - <?php
178 + <?php
137 179 settings_fields( 'ns_shield_options_group' );
138 180 do_settings_sections( 'secure-options' );
139 - submit_button();
140 181 ?>
182 + <div class="ns-shield-settings-actions">
183 + <?php
184 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Core function returns complete escaped button markup.
185 + echo get_submit_button( __( 'Save Changes', 'netsensai-shield' ), 'primary', 'submit', false );
186 + if ( function_exists( 'ns_shield_access_details_current_guide_button' ) ) {
187 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Helper returns fixed, internally escaped button markup.
188 + echo ns_shield_access_details_current_guide_button();
189 + }
190 + ?>
191 + </div>
192 + <?php
193 + ?>
141 194 </form>
142 195
143 - </div> <!-- .wrap -->
196 + <!-- Include modal popup file from includes/ -->
197 + <?php
198 +$modal_file = plugin_dir_path( __FILE__ ) . 'includes/modal_popup.php';
199 +if ( file_exists( $modal_file ) ) {
200 + include $modal_file;
201 +}
202 +// Jeśli plik nie zostanie znaleziony, nie rób nic – error_log() zostało usunięte.
203 +?>
204 + </div> <!-- End of wrap -->
144 205 <?php
145 206 }
146 207
147 208 /**
@@ -158,42 +219,52 @@
158 219 }
159 220 add_action( 'admin_menu', 'ns_shield_secure_options_menu' );
160 221
161 222 /**
162 - * Register settings and fields for Levels 1 and 2.
223 + * Register settings and fields.
163 224 */
164 225 function ns_shield_secure_options_settings() {
165 226 register_setting( 'ns_shield_options_group', 'ns_shield_login_url', 'sanitize_text_field' );
166 227 register_setting( 'ns_shield_options_group', 'ns_shield_login_url_enabled', 'sanitize_text_field' );
167 228 register_setting( 'ns_shield_options_group', 'ns_shield_wp_api_json', 'sanitize_text_field' );
229 + register_setting(
230 + 'ns_shield_options_group',
231 + 'ns_shield_username_protection',
232 + array(
233 + 'type' => 'boolean',
234 + 'sanitize_callback' => 'ns_shield_sanitize_username_protection',
235 + 'default' => false,
236 + )
237 + );
168 238 register_setting( 'ns_shield_options_group', 'ns_shield_xml_rpc', 'sanitize_text_field' );
169 239 register_setting( 'ns_shield_options_group', 'ns_shield_file_editor', 'sanitize_text_field' );
170 240 register_setting( 'ns_shield_options_group', 'ns_shield_app_passwords', 'absint' );
171 -
172 - // Level 1: Basic Security
241 + register_setting( 'ns_shield_options_group', 'ns_shield_security_headers', 'sanitize_text_field' );
242 + register_setting( 'ns_shield_options_group', 'ns_shield_directory_indexing', 'sanitize_text_field' );
243 + register_setting( 'ns_shield_options_group', 'ns_shield_default_admin', 'absint' );
244 + register_setting( 'ns_shield_options_group', 'ns_shield_new_admin_login', 'sanitize_text_field' );
245 + register_setting( 'ns_shield_options_group', 'ns_shield_debug', 'sanitize_text_field' );
246 + // Register new settings for CSP headers.
247 + register_setting( 'ns_shield_options_group', 'ns_shield_csp_header_light', 'intval' );
248 + register_setting( 'ns_shield_options_group', 'ns_shield_csp_header_hard', 'ns_shield_sanitize_csp_hard' );
249 +
250 + // Level 1: Basic Security (login URL options etc.)
173 251 add_settings_section( 'ns_shield_level_1', esc_html__( 'Level 1: Basic Security', 'netsensai-shield' ), null, 'secure-options' );
174 252 add_settings_field( 'ns_shield_login_url', esc_html__( 'Change Login URL', 'netsensai-shield' ), 'ns_shield_change_login_url', 'secure-options', 'ns_shield_level_1' );
175 253 add_settings_field( 'ns_shield_default_admin', esc_html__( 'Disable Default Admin', 'netsensai-shield' ), 'ns_shield_disable_default_admin', 'secure-options', 'ns_shield_level_1' );
176 254 add_settings_field( 'ns_shield_xml_rpc', esc_html__( 'Disable XML-RPC', 'netsensai-shield' ), 'ns_shield_field_xml_rpc', 'secure-options', 'ns_shield_level_1' );
177 -
255 +
178 256 // Level 2: Intermediate Security
179 257 add_settings_section( 'ns_shield_level_2', esc_html__( 'Level 2: Intermediate Security', 'netsensai-shield' ), null, 'secure-options' );
180 258 add_settings_field( 'ns_shield_wp_api_json', esc_html__( 'Disable WP API JSON', 'netsensai-shield' ), 'ns_shield_field_wp_api_json', 'secure-options', 'ns_shield_level_2' );
181 259 add_settings_field( 'ns_shield_file_editor', esc_html__( 'Disable File Editor', 'netsensai-shield' ), 'ns_shield_field_file_editor', 'secure-options', 'ns_shield_level_2' );
182 260 add_settings_field( 'ns_shield_app_passwords', esc_html__( 'Disable WordPress Application Passwords', 'netsensai-shield' ), 'ns_shield_field_app_passwords', 'secure-options', 'ns_shield_level_2' );
183 -
184 - // Przygotowanie fragmentów tekstu z tłumaczeniami.
185 - $white_text = '<span style="font-size:20px; color:#fff !important;">' . esc_html__( 'More features, more possibilities', 'netsensai-shield' ) . '</span>';
186 - $yellow_text = '<span style="font-size:20px; color:#E6DB00 !important;">&nbsp;– <a href="' . esc_url( 'https://netsensai.pl/store' ) . '" target="_blank" style="color:#E6DB00 !important; text-decoration:none;">' . esc_html__( 'purchase a lifetime PRO license', 'netsensai-shield' ) . '</a></span>';
187 -
188 - $level3_title = esc_html__( 'Level 3: Advanced Security', 'netsensai-shield' ) . '<br><br>' . $white_text . ' ' . $yellow_text;
189 -
190 - add_settings_section(
191 - 'ns_shield_level_3',
192 - wp_kses_post( $level3_title ),
193 - null,
194 - 'secure-options'
195 - );
261 +
262 + // Level 3: Advanced Security
263 + add_settings_section( 'ns_shield_level_3', esc_html__( 'Level 3: Advanced Security', 'netsensai-shield' ), null, 'secure-options' );
264 + add_settings_field( 'ns_shield_directory_indexing', esc_html__( 'Disable Directory Indexing', 'netsensai-shield' ), 'ns_shield_field_directory_indexing', 'secure-options', 'ns_shield_level_3' );
265 + add_settings_field( 'ns_shield_username_protection', esc_html__( 'Protect Usernames', 'netsensai-shield' ), 'ns_shield_field_username_protection', 'secure-options', 'ns_shield_level_3' );
266 + add_settings_field( 'ns_shield_security_headers', esc_html__( 'Apply Security Headers', 'netsensai-shield' ), 'ns_shield_field_security_headers', 'secure-options', 'ns_shield_level_3' );
196 267 }
197 268 add_action( 'admin_init', 'ns_shield_secure_options_settings' );
198 269
199 270 /* =====================
@@ -204,9 +275,14 @@
204 275 $checked = get_option( 'ns_shield_xml_rpc', 0 ) ? 'checked' : '';
205 276 echo '<label class="switch">';
206 277 echo '<input type="checkbox" name="ns_shield_xml_rpc" value="1" ' . esc_attr( $checked ) . '>';
207 278 echo '<span class="slider round"></span>';
208 - echo '<div class="tooltip">' . esc_html__( 'Disabling XML-RPC blocks unauthorized remote access attempts, which can enhance security. If XML-RPC remains enabled, hackers might attempt to perform DDoS attacks by sending multiple requests or brute-force password attacks to gain control over your site.', 'netsensai-shield' ) . '</div>';
279 + echo '<div class="tooltip">' .
280 + esc_html__(
281 + 'Disabling XML-RPC blocks unauthorized remote access attempts, which can enhance security. If XML-RPC remains enabled, hackers might attempt to perform DDoS attacks by sending multiple requests or brute-force password attacks to gain control over your site.',
282 + 'netsensai-shield'
283 + ) .
284 + '</div>';
209 285 echo '</label>';
210 286 }
211 287
212 288 function ns_shield_field_wp_api_json() {
@@ -213,9 +289,14 @@
213 289 $checked = get_option( 'ns_shield_wp_api_json', 0 ) ? 'checked' : '';
214 290 echo '<label class="switch">';
215 291 echo '<input type="checkbox" name="ns_shield_wp_api_json" value="1" ' . esc_attr( $checked ) . '>';
216 292 echo '<span class="slider round"></span>';
217 - echo '<div class="tooltip">' . esc_html__( 'Disabling WP API JSON can protect your site from unauthorized access to sensitive data through the API. If left enabled, hackers may exploit WP API JSON to gather information about your site’s structure or perform enumeration attacks on users, which can lead to brute-force attacks.', 'netsensai-shield' ) . '</div>';
293 + echo '<div class="tooltip">' .
294 + esc_html__(
295 + 'Disabling WP API JSON can protect your site from unauthorized access to sensitive data through the API. If left enabled, hackers may exploit WP API JSON to gather information about your site’s structure or perform enumeration attacks on users, which can lead to brute-force attacks.',
296 + 'netsensai-shield'
297 + ) .
298 + '</div>';
218 299 echo '</label>';
219 300 }
220 301
221 302 function ns_shield_field_file_editor() {
@@ -222,9 +303,14 @@
222 303 $checked = get_option( 'ns_shield_file_editor', 0 ) ? 'checked' : '';
223 304 echo '<label class="switch">';
224 305 echo '<input type="checkbox" name="ns_shield_file_editor" value="1" ' . esc_attr( $checked ) . '>';
225 306 echo '<span class="slider round"></span>';
226 - echo '<div class="tooltip">' . esc_html__( 'Disabling the file editor in the WP dashboard prevents unauthorized or accidental code changes. If left enabled, attackers who gain access to your admin panel could inject malicious code into your theme or plugin files, leading to a defacement of the site or the deployment of malware.', 'netsensai-shield' ) . '</div>';
307 + echo '<div class="tooltip">' .
308 + esc_html__(
309 + 'Disabling the file editor in the WP dashboard prevents unauthorized or accidental code changes. If left enabled, attackers who gain access to your admin panel could inject malicious code into your theme or plugin files, leading to a defacement of the site or the deployment of malware.',
310 + 'netsensai-shield'
311 + ) .
312 + '</div>';
227 313 echo '</label>';
228 314 }
229 315
230 316 function ns_shield_field_app_passwords() {
@@ -231,26 +317,69 @@
231 317 $checked = get_option( 'ns_shield_app_passwords', 0 ) ? 'checked' : '';
232 318 echo '<label class="switch">';
233 319 echo '<input type="checkbox" name="ns_shield_app_passwords" value="1" ' . esc_attr( $checked ) . '>';
234 320 echo '<span class="slider round"></span>';
235 - echo '<div class="tooltip">' . esc_html__( 'Disabling application passwords secures against creating unauthorized accesses to your site’s API. If left enabled, hackers may exploit application passwords to gain persistent access to your site, enabling them to execute unauthorized API requests or even escalate their privileges.', 'netsensai-shield' ) . '</div>';
321 + echo '<div class="tooltip">' .
322 + esc_html__(
323 + 'Disabling application passwords secures against creating unauthorized accesses to your site’s API. If left enabled, hackers may exploit application passwords to gain persistent access to your site, enabling them to execute unauthorized API requests or even escalate their privileges.',
324 + 'netsensai-shield'
325 + ) .
326 + '</div>';
236 327 echo '</label>';
237 328 }
238 329
330 +function ns_shield_field_security_headers() {
331 + $checked = get_option( 'ns_shield_security_headers', 0 ) ? 'checked' : '';
332 + echo '<label class="switch">';
333 + echo '<input type="checkbox" name="ns_shield_security_headers" id="ns-shield-preload-checkbox" value="1" ' . esc_attr( $checked ) . '>';
334 + echo '<span class="slider round"></span>';
335 + echo '<div class="tooltip">' .
336 + esc_html__(
337 + 'Applying security headers can protect your site from XSS attacks and other threats. On HTTPS pages, this also enables basic HSTS for the current domain only. Without these headers, your site could be vulnerable to cross-site scripting (XSS) attacks or clickjacking, allowing attackers to steal sensitive data or trick users into executing malicious actions.',
338 + 'netsensai-shield'
339 + ) .
340 + '</div>';
341 + echo '</label>';
342 +}
343 +
239 344 /**
240 - * Flush rewrite rules after settings update.
345 + * FIELD CALLBACK: Directory Indexing.
241 346 */
242 -function ns_shield_flush_rewrite_rules_on_settings_update() {
243 - if ( is_admin() && isset( $_GET['settings-updated'] ) && 'true' === $_GET['settings-updated'] ) {
244 - flush_rewrite_rules();
245 - }
347 +function ns_shield_field_directory_indexing() {
348 + $checked = get_option( 'ns_shield_directory_indexing', 0 ) ? 'checked' : '';
349 + echo '<label class="switch">';
350 + echo '<input type="checkbox" name="ns_shield_directory_indexing" value="1" ' . esc_attr( $checked ) . '>';
351 + echo '<span class="slider round"></span>';
352 + echo '<div class="tooltip">' .
353 + esc_html__(
354 + 'Directory indexing allows attackers to list and access files in directories that lack an index file, exposing sensitive files and configurations. If directory indexing is not disabled, attackers can execute Directory Traversal attacks, gaining access to configuration files, logs, or even databases.',
355 + 'netsensai-shield'
356 + ) .
357 + '</div>';
358 + echo '</label>';
246 359 }
247 -add_action( 'admin_init', 'ns_shield_flush_rewrite_rules_on_settings_update', 20 );
248 360
249 361 /**
362 + * FIELD CALLBACK: Username protection.
363 + *
364 + * @return void
365 + */
366 +function ns_shield_field_username_protection() {
367 + $checked = ns_shield_username_protection_is_enabled() ? 'checked' : '';
368 +
369 + echo '<label class="switch">';
370 + echo '<input type="checkbox" name="ns_shield_username_protection" value="1" ' . esc_attr( $checked ) . '>';
371 + echo '<span class="slider round"></span>';
372 + echo '<div class="tooltip">' . esc_html__( 'Makes it harder for unauthenticated visitors to discover account usernames and IDs through author archives and the REST API. It does not hide author names intentionally published on the website.', 'netsensai-shield' ) . '</div>';
373 + echo '</label>';
374 +}
375 +
376 +/**
250 377 * Flush rewrite rules on plugin activation.
251 378 */
252 379 function ns_shield_activation_flush() {
380 + ns_shield_migrate_legacy_hsts();
381 +
253 382 if ( function_exists( 'ns_shield_add_rewrite_rule' ) ) {
254 383 ns_shield_add_rewrite_rule();
255 384 }
256 385 flush_rewrite_rules();
@@ -263,5 +392,41 @@
263 392 function ns_shield_deactivation_flush() {
264 393 flush_rewrite_rules();
265 394 }
266 395 register_deactivation_hook( __FILE__, 'ns_shield_deactivation_flush' );
396 +
397 +
398 +// Wskazanie uruchomienia pliku script.js
399 +function ns_shield_admin_enqueue_assets( $hook_suffix ) {
400 + // tylko na /wp-admin/options-general.php?page=secure-options
401 + if ( 'settings_page_secure-options' !== $hook_suffix ) {
402 + return;
403 + }
404 +
405 + // a) Styl
406 + wp_enqueue_style(
407 + 'ns_shield-style',
408 + plugin_dir_url( __FILE__ ) . 'assets/style.css',
409 + [],
410 + filemtime( plugin_dir_path( __FILE__ ) . 'assets/style.css' )
411 + );
412 +
413 + // b) Skrypt z filemtime jako wersją
414 + $script_path = plugin_dir_path( __FILE__ ) . 'assets/script.js';
415 + $ver = file_exists( $script_path ) ? filemtime( $script_path ) : false;
416 + wp_enqueue_script(
417 + 'ns_shield-script',
418 + plugin_dir_url( __FILE__ ) . 'assets/script.js',
419 + ['jquery'],
420 + $ver,
421 + true
422 + );
423 +
424 + // c) Przekazanie ustawień do JS
425 + wp_localize_script( 'ns_shield-script', 'nsShieldSettings', [
426 + 'pageSlug' => 'secure-options',
427 + ] );
428 +}
429 +add_action( 'admin_enqueue_scripts', 'ns_shield_admin_enqueue_assets' );
430 +
431 +
267 432 ?>