Changeset 3303789
- Timestamp:
- 05/30/2025 08:46:48 PM (10 months ago)
- Location:
- iron-security
- Files:
-
- 8 added
- 8 edited
- 46 copied
-
tags/2.3.4 (copied) (copied from iron-security/trunk)
-
tags/2.3.4/LICENSE.txt (copied) (copied from iron-security/trunk/LICENSE.txt)
-
tags/2.3.4/README.txt (copied) (copied from iron-security/trunk/README.txt) (2 diffs)
-
tags/2.3.4/admin (copied) (copied from iron-security/trunk/admin)
-
tags/2.3.4/admin/class-iron-security-admin.php (copied) (copied from iron-security/trunk/admin/class-iron-security-admin.php) (2 diffs)
-
tags/2.3.4/admin/classes/general-security.php (copied) (copied from iron-security/trunk/admin/classes/general-security.php)
-
tags/2.3.4/admin/classes/login-logout-functionality.php (copied) (copied from iron-security/trunk/admin/classes/login-logout-functionality.php) (25 diffs)
-
tags/2.3.4/admin/classes/tracking-access.php (copied) (copied from iron-security/trunk/admin/classes/tracking-access.php)
-
tags/2.3.4/admin/css/dashboard.css (copied) (copied from iron-security/trunk/admin/css/dashboard.css)
-
tags/2.3.4/admin/css/iron-security-admin.css (copied) (copied from iron-security/trunk/admin/css/iron-security-admin.css) (1 diff)
-
tags/2.3.4/admin/css/transitions.css (copied) (copied from iron-security/trunk/admin/css/transitions.css)
-
tags/2.3.4/admin/js/2fa.js (copied) (copied from iron-security/trunk/admin/js/2fa.js)
-
tags/2.3.4/admin/js/components/Dashboard.jsx (copied) (copied from iron-security/trunk/admin/js/components/Dashboard.jsx) (2 diffs)
-
tags/2.3.4/admin/js/components/FileDirectoryProectionSettings.jsx (copied) (copied from iron-security/trunk/admin/js/components/FileDirectoryProectionSettings.jsx)
-
tags/2.3.4/admin/js/components/GeneralSettings.jsx (copied) (copied from iron-security/trunk/admin/js/components/GeneralSettings.jsx)
-
tags/2.3.4/admin/js/components/HttpSecurityHeadersSettings.jsx (copied) (copied from iron-security/trunk/admin/js/components/HttpSecurityHeadersSettings.jsx)
-
tags/2.3.4/admin/js/components/LoginLogoutSettings.jsx (copied) (copied from iron-security/trunk/admin/js/components/LoginLogoutSettings.jsx)
-
tags/2.3.4/admin/js/components/SecurityLogs.jsx (copied) (copied from iron-security/trunk/admin/js/components/SecurityLogs.jsx)
-
tags/2.3.4/admin/js/dashboard.js (copied) (copied from iron-security/trunk/admin/js/dashboard.js)
-
tags/2.3.4/admin/js/dist/dashboard.409171eb914877d3afe7.js (copied) (copied from iron-security/trunk/admin/js/dist/dashboard.409171eb914877d3afe7.js)
-
tags/2.3.4/admin/js/dist/dashboard.6931e43c4d8629f63bd9.js (added)
-
tags/2.3.4/admin/js/dist/dashboard.6931e43c4d8629f63bd9.js.LICENSE.txt (added)
-
tags/2.3.4/admin/js/dist/dashboard.bundle.js (copied) (copied from iron-security/trunk/admin/js/dist/dashboard.bundle.js)
-
tags/2.3.4/admin/js/dist/dashboard.d4938437720f6eface82.js (copied) (copied from iron-security/trunk/admin/js/dist/dashboard.d4938437720f6eface82.js)
-
tags/2.3.4/admin/js/dist/manifest.json (copied) (copied from iron-security/trunk/admin/js/dist/manifest.json) (1 diff)
-
tags/2.3.4/admin/js/dist/vendors.6faccb462d3791bbb518.js (copied) (copied from iron-security/trunk/admin/js/dist/vendors.6faccb462d3791bbb518.js)
-
tags/2.3.4/admin/js/dist/vendors.6faccb462d3791bbb518.js.LICENSE.txt (copied) (copied from iron-security/trunk/admin/js/dist/vendors.6faccb462d3791bbb518.js.LICENSE.txt)
-
tags/2.3.4/admin/js/dist/vendors.91782840b9e9337a9a5f.js (copied) (copied from iron-security/trunk/admin/js/dist/vendors.91782840b9e9337a9a5f.js)
-
tags/2.3.4/admin/js/dist/vendors.91782840b9e9337a9a5f.js.LICENSE.txt (copied) (copied from iron-security/trunk/admin/js/dist/vendors.91782840b9e9337a9a5f.js.LICENSE.txt)
-
tags/2.3.4/admin/js/dist/vendors.b4116fd1b25e74ca1789.js (added)
-
tags/2.3.4/admin/js/dist/vendors.b4116fd1b25e74ca1789.js.LICENSE.txt (added)
-
tags/2.3.4/admin/js/iron-security-admin.js (copied) (copied from iron-security/trunk/admin/js/iron-security-admin.js)
-
tags/2.3.4/build (copied) (copied from iron-security/trunk/build)
-
tags/2.3.4/composer.json (copied) (copied from iron-security/trunk/composer.json)
-
tags/2.3.4/composer.lock (copied) (copied from iron-security/trunk/composer.lock)
-
tags/2.3.4/includes (copied) (copied from iron-security/trunk/includes)
-
tags/2.3.4/includes/class-iron-security-deactivator.php (copied) (copied from iron-security/trunk/includes/class-iron-security-deactivator.php)
-
tags/2.3.4/includes/class-iron-security-logger.php (copied) (copied from iron-security/trunk/includes/class-iron-security-logger.php)
-
tags/2.3.4/includes/class-iron-security.php (copied) (copied from iron-security/trunk/includes/class-iron-security.php) (2 diffs)
-
tags/2.3.4/includes/ss.json (copied) (copied from iron-security/trunk/includes/ss.json)
-
tags/2.3.4/index.php (copied) (copied from iron-security/trunk/index.php)
-
tags/2.3.4/iron-security.php (copied) (copied from iron-security/trunk/iron-security.php) (2 diffs)
-
tags/2.3.4/languages (copied) (copied from iron-security/trunk/languages)
-
tags/2.3.4/package.json (copied) (copied from iron-security/trunk/package.json)
-
tags/2.3.4/pnpm-lock.yaml (copied) (copied from iron-security/trunk/pnpm-lock.yaml)
-
tags/2.3.4/public (copied) (copied from iron-security/trunk/public)
-
tags/2.3.4/public/class-iron-security-public.php (copied) (copied from iron-security/trunk/public/class-iron-security-public.php)
-
tags/2.3.4/uninstall.php (copied) (copied from iron-security/trunk/uninstall.php)
-
tags/2.3.4/vendor (copied) (copied from iron-security/trunk/vendor)
-
tags/2.3.4/webpack.config.js (copied) (copied from iron-security/trunk/webpack.config.js)
-
trunk/README.txt (modified) (2 diffs)
-
trunk/admin/class-iron-security-admin.php (modified) (2 diffs)
-
trunk/admin/classes/login-logout-functionality.php (modified) (25 diffs)
-
trunk/admin/css/iron-security-admin.css (modified) (1 diff)
-
trunk/admin/js/components/Dashboard.jsx (modified) (2 diffs)
-
trunk/admin/js/dist/dashboard.6931e43c4d8629f63bd9.js (added)
-
trunk/admin/js/dist/dashboard.6931e43c4d8629f63bd9.js.LICENSE.txt (added)
-
trunk/admin/js/dist/manifest.json (modified) (1 diff)
-
trunk/admin/js/dist/vendors.b4116fd1b25e74ca1789.js (added)
-
trunk/admin/js/dist/vendors.b4116fd1b25e74ca1789.js.LICENSE.txt (added)
-
trunk/includes/class-iron-security.php (modified) (2 diffs)
-
trunk/iron-security.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
iron-security/tags/2.3.4/README.txt
r3300103 r3303789 5 5 Requires at least: 4.7 6 6 Tested up to: 6.8 7 Stable tag: 2.3. 37 Stable tag: 2.3.4 8 8 Requires PHP: 7.0 9 9 License: GPLv2 or later … … 142 142 == Changelog == 143 143 144 = 2.3.4 = 145 * Update plugin 146 144 147 = 2.3.3 = 145 148 * Add functionality to change default admin username -
iron-security/tags/2.3.4/admin/class-iron-security-admin.php
r3300103 r3303789 336 336 337 337 return $this->login_logout_functionality->wpironsecwp_block_locked_out_users( $user, $username, $password ); 338 } 339 340 public function wpironis_block_locked_out_ip_early() { 341 return $this->login_logout_functionality->wpironsecwp_block_locked_out_ip_early(); 338 342 } 339 343 … … 3608 3612 } 3609 3613 3614 public function handle_telegram_feedback() { 3615 check_ajax_referer('iron_security_nonce', 'nonce'); 3616 3617 if (!current_user_can('manage_options')) { 3618 wp_send_json_error('Insufficient permissions'); 3619 return; 3620 } 3621 3622 $name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : ''; 3623 $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; 3624 $message = isset($_POST['message']) ? sanitize_textarea_field($_POST['message']) : ''; 3625 3626 if (empty($name) || empty($email) || empty($message)) { 3627 wp_send_json_error('All fields are required'); 3628 return; 3629 } 3630 3631 $bot_token = '7891702745:AAE9NIFGYVZzgmIiLZ1xVKBVtG5Wn-E-66E'; 3632 $chat_id = '-1002293858145'; 3633 3634 $text = "*Iron Security Feedback* \n\n"; 3635 $text .= "*Name:* $name\n"; 3636 $text .= "*Email:* $email\n"; 3637 $text .= "*Message:*\n$message"; 3638 3639 $url = "https://api.telegram.org/bot$bot_token/sendMessage"; 3640 3641 $args = [ 3642 'body' => [ 3643 'chat_id' => $chat_id, 3644 'text' => $text, 3645 'parse_mode' => 'Markdown' 3646 ] 3647 ]; 3648 3649 $response = wp_remote_post($url, $args); 3650 3651 if (is_wp_error($response)) { 3652 error_log($response->get_error_message()); 3653 wp_send_json_error('Failed to send message: ' . $response->get_error_message()); 3654 return; 3655 } 3656 3657 $body = wp_remote_retrieve_body($response); 3658 $data = json_decode($body, true); 3659 3660 if (isset($data['ok']) && $data['ok'] === true) { 3661 wp_send_json_success('Feedback sent successfully'); 3662 } else { 3663 wp_send_json_error('Failed to send message'); 3664 } 3665 } 3666 3610 3667 private function get_hashed_filename( $base_name ) { 3611 3668 $manifest_path = plugin_dir_path( __FILE__ ) . 'js/dist/manifest.json'; -
iron-security/tags/2.3.4/admin/classes/login-logout-functionality.php
r3291538 r3303789 16 16 $this->version = '1.0.0'; 17 17 $this->tracking_access = new SafeWP_Setup_Tracking_Access(); 18 // $this->safe2fa = new safe_2fa_admin();19 18 } 20 19 … … 24 23 <p class="text-center"> 25 24 This section of the Iron Security Plugin offers several options to enhance the security of your 26 WordPress 27 site. These settings allow you to customize various aspects of the login and logout 25 WordPress site. These settings allow you to customize various aspects of the login and logout 28 26 process, reducing vulnerabilities and protecting against unauthorized access. 29 27 </p> 30 <?php 31 settings_errors( 'wpironis_messages' ); ?> 28 <?php settings_errors( 'wpironis_messages' ); ?> 32 29 <form method="post" action="options.php"> 33 30 <?php … … 49 46 <input type="checkbox" id="enable_session_timeout" 50 47 name="wpironis_plugin_settings_loginlogout[enable_session_timeout]" 51 value="1" <?php 52 checked( 1, $is_enabled, true ); ?>> 48 value="1" <?php checked( 1, $is_enabled, true ); ?>> 53 49 <span class="slider round"></span> 54 50 </label> … … 58 54 <input type="number" name="wpironis_plugin_settings_loginlogout[session_timeout_value]" 59 55 id="session_timeout_value" 60 value="<?php 61 echo esc_attr( $timeoutValue ); ?>" 56 value="<?php echo esc_attr( $timeoutValue ); ?>" 62 57 placeholder="Enter timeout in seconds (for example 3600 it will be 1hr)"> 63 58 </div> … … 77 72 <input type="checkbox" id="enable_slug_change" 78 73 name="wpironis_plugin_settings_loginlogout[enable_slug_change]" 79 value="1" <?php 80 checked( 1, $is_enabled, true ); ?>> 74 value="1" <?php checked( 1, $is_enabled, true ); ?>> 81 75 <span class="slider round"></span> 82 76 </label> … … 85 79 <input type="text" name="wpironis_plugin_settings_loginlogout[wpironis_custom_login_slug]" 86 80 id="wpironis_custom-admin-slug" 87 value="<?php 88 echo isset( $slug ) ? esc_attr( $slug ) : ''; ?>" 81 value="<?php echo isset( $slug ) ? esc_attr( $slug ) : ''; ?>" 89 82 placeholder="Enter custom login URL"> 90 83 </div> … … 94 87 automated attacks. This simple change adds an effective layer of protection to your website.</p> 95 88 </div> 96 97 89 <?php 98 90 } … … 105 97 <input type="checkbox" id="enable_limit_login_attempts" 106 98 name="wpironis_plugin_settings_loginlogout[enable_limit_login_attempts]" 107 value="1" <?php 108 checked( 1, $is_enabled, true ); ?>> 99 value="1" <?php checked( 1, $is_enabled, true ); ?>> 109 100 <span class="slider round"></span> 110 101 </label> … … 115 106 <input type="number" name="wpironis_plugin_settings_loginlogout[wpironis_limit_login_attempts]" 116 107 id="limit_login_attempts" 117 value="<?php 118 echo esc_attr( $attempts ); ?>" 108 value="<?php echo esc_attr( $attempts ); ?>" 119 109 placeholder="Enter the number of allowed attempts (for example: 5)"> 120 110 </div> … … 123 113 <input type="number" name="wpironis_plugin_settings_loginlogout[wpironis_lockout_duration]" 124 114 id="wpironis_lockout_duration" 125 value="<?php 126 echo esc_attr( $time ); ?>" placeholder="How long to keep user blocked? in seconds"> 115 value="<?php echo esc_attr( $time ); ?>" placeholder="How long to keep user blocked? in seconds"> 127 116 </div> 128 117 </div> … … 141 130 <input type="checkbox" id="enable_2fa" 142 131 name="wpironis_plugin_settings_loginlogout[enable_2fa]" 143 value="1" <?php 144 checked( 1, $is_enabled, true ); ?>> 132 value="1" <?php checked( 1, $is_enabled, true ); ?>> 145 133 <span class="slider round"></span> 146 134 </label> … … 154 142 <input type="checkbox" id="wpironis_2fa_google_auth_field" 155 143 name="wpironis_plugin_settings_loginlogout[wpironis_2fa_google_auth]" 156 value="1" <?php 157 checked( 1, $googleAuth, true ); ?>> 144 value="1" <?php checked( 1, $googleAuth, true ); ?>> 158 145 <span class="slider round"></span> 159 146 </label> … … 178 165 strtoupper( sanitize_text_field( $_SERVER['REQUEST_METHOD'] ) ) !== 'POST' 179 166 ) { 180 // Redirect to the home URL safely181 167 wp_redirect( esc_url( home_url() ) ); 182 168 exit; … … 184 170 } 185 171 186 187 172 public function customLoginUrl( $customUrl ) { 188 173 global $user_login, $error; 189 174 190 175 if ( strpos( $_SERVER['REQUEST_URI'], '/' . $customUrl ) !== false ) { 191 // Serve the login page if not logged in192 176 if ( ! is_user_logged_in() ) { 193 177 if ( ! isset( $user_login ) ) { … … 201 185 } 202 186 } 203 // If it's the default login URL, redirect to the custom URL204 187 if ( strpos( $_SERVER['REQUEST_URI'], 'wp-login.php' ) !== false && ! is_user_logged_in() ) { 205 188 wp_redirect( home_url( $customUrl ) ); … … 250 233 return admin_url(); 251 234 } 252 253 235 return home_url(); 254 236 } 255 256 237 return $redirect_to; 257 238 } … … 261 242 return (int) $timeout_value; 262 243 } 263 264 244 return $expireIn; 265 245 } … … 269 249 $attempts = get_transient( $ip_address . '_wpis_attempts' ) ?: 0; 270 250 $attempts ++; 251 271 252 set_transient( $ip_address . '_wpis_attempts', $attempts, $options['wpironis_lockout_duration'] ); 272 253 if ( $attempts >= $options['wpironis_limit_login_attempts'] ) { … … 289 270 290 271 public function wpironsecwp_block_locked_out_users( $user, $username, $password ) { 291 292 272 $ip_address = $this->get_user_ip(); 293 294 // Check if this IP is in lockout transient 273 295 274 if ( get_transient( $ip_address . '_wpis_lockout' ) ) { 296 297 // Optionally fetch how long until lockout ends:298 275 $lockout_duration = get_option( 'wpironis_plugin_settings_loginlogout' )['wpironis_lockout_duration']; 299 276 $lockout_time = get_transient( $ip_address . '_wpis_lockout_time' ); 300 277 $remaining_time = $lockout_duration - ( time() - $lockout_time ); 301 278 302 // Force all sessions for this IP to log out303 279 $this->wpisec_force_logout_by_ip( $ip_address ); 304 280 305 // -- 1) Immediately set a 403 status and kill on the login page --306 307 // Set 403 on "login_init"308 281 add_action( 'login_init', function() { 309 282 status_header( 403 ); 310 283 nocache_headers(); 311 // Stop execution so the login form never appears312 284 exit; 313 285 }); 314 286 315 // If WordPress tries to render the login form anyway, kill it316 287 add_action( 'login_form', function () { 317 288 exit; 318 289 }); 319 290 320 // -- 2) Also block access to the wp-admin area --321 322 291 add_action( 'admin_init', function() { 323 292 status_header( 403 ); 324 293 nocache_headers(); 325 // This prevents the admin panel from loading326 294 exit; 327 295 }); 328 329 // -- 3) Optionally add your own error message on the login page (if it were to load) --330 296 331 297 add_filter( 'login_message', function () use ( $remaining_time ) { … … 336 302 }); 337 303 338 // Return a WP_Error so WordPress sees this as a failed login339 304 return new WP_Error( 340 305 'locked_out', … … 343 308 } 344 309 345 // If not locked out, just return the user object346 310 return $user; 347 311 } 348 349 312 350 313 /** … … 352 315 */ 353 316 public function wpisec_force_logout_by_ip( $ip_address ) { 354 $users = get_users(); // Get all users317 $users = get_users(); 355 318 356 319 foreach ( $users as $user ) { 357 320 $sessions = WP_Session_Tokens::get_instance( $user->ID ); 358 $sessions->destroy_all(); // Log out all sessions for this user 359 } 360 361 // Destroy the current session if the locked user is logged in 321 $sessions->destroy_all(); 322 } 323 362 324 if ( is_user_logged_in() ) { 363 325 wp_destroy_current_session(); 364 326 wp_clear_auth_cookie(); 365 wp_redirect( home_url() ); // Redirect to home page327 wp_redirect( home_url() ); 366 328 exit; 367 329 } … … 392 354 } else { 393 355 error_log( '2FA code not entered' ); 394 395 356 return new WP_Error( 'missing_2fa_code', 396 357 '<strong>ERROR</strong>: Please enter your 2FA code.' ); … … 401 362 } else { 402 363 error_log( 'Nonce verification failed or nonce not set' ); 403 404 364 return new WP_Error( 'invalid_nonce', '<strong>ERROR</strong>: Nonce verification failed.' ); 405 365 } … … 415 375 } 416 376 417 418 377 public function get_user_ip() { 419 unset($_SERVER['HTTP_X_FORWARDED_FOR'], $_SERVER['CLIENT_IP']); 420 421 if (!empty($_SERVER['REMOTE_ADDR']) && self::validate_ip($_SERVER['REMOTE_ADDR'])) { 422 return $_SERVER['REMOTE_ADDR']; 423 } 424 } 425 426 private static function validate_ip($ip) { 427 return filter_var($ip, FILTER_VALIDATE_IP) !== false; 378 $remote_addr = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; 379 380 if (self::validate_ip($remote_addr)) { 381 return $remote_addr; 382 } 383 384 return '0.0.0.0'; 385 } 386 387 public static function validate_ip($ip) { 388 if (filter_var($ip, FILTER_VALIDATE_IP) === false) { 389 return false; 390 } 391 return true; 428 392 } 429 393 -
iron-security/tags/2.3.4/admin/css/iron-security-admin.css
r3288628 r3303789 224 224 color: #fff; 225 225 background: #0073aa; 226 } 227 228 /* Feedback Form */ 229 .iron-security-feedback-form { 230 background: #fff; 231 border: 1px solid #e2e4e7; 232 border-radius: 4px; 233 padding: 20px; 234 margin-top: 20px; 235 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); 236 } 237 238 .iron-security-feedback-form p { 239 margin-bottom: 15px; 240 color: #555; 241 } 242 243 .iron-security-form-field { 244 margin-bottom: 15px; 245 } 246 247 .iron-security-form-field label { 248 display: block; 249 margin-bottom: 5px; 250 font-weight: 500; 251 } 252 253 .iron-security-form-field input, 254 .iron-security-form-field textarea { 255 width: 100%; 256 padding: 8px 12px; 257 border-radius: 4px; 258 border: 1px solid #ddd; 259 font-size: 14px; 260 } 261 262 .iron-security-form-field textarea { 263 resize: vertical; 264 min-height: 80px; 265 } 266 267 .iron-security-feedback-status { 268 margin-bottom: 15px; 269 padding: 10px 15px; 270 border-radius: 4px; 271 font-size: 14px; 272 } 273 274 .iron-security-feedback-status.success { 275 background-color: #ecf9ec; 276 color: #1e7e34; 277 border: 1px solid #c3e6cb; 278 } 279 280 .iron-security-feedback-status.error { 281 background-color: #f8d7da; 282 color: #721c24; 283 border: 1px solid #f5c6cb; 284 } 285 286 .iron-security-feedback-form button { 287 margin-top: 5px; 226 288 } -
iron-security/tags/2.3.4/admin/js/components/Dashboard.jsx
r3300103 r3303789 7 7 import HttpSecurityHeadersSettings from "./HttpSecurityHeadersSettings"; 8 8 import Support from './Support'; 9 10 const FeedbackForm = ({ settings }) => { 11 const [name, setName] = useState(''); 12 const [email, setEmail] = useState(''); 13 const [message, setMessage] = useState(''); 14 const [isSending, setIsSending] = useState(false); 15 const [feedbackStatus, setFeedbackStatus] = useState(null); 16 17 const handleSubmit = async (e) => { 18 e.preventDefault(); 19 setIsSending(true); 20 setFeedbackStatus(null); 21 22 try { 23 const formData = new FormData(); 24 formData.append('action', 'iron_security_send_feedback'); 25 formData.append('name', name); 26 formData.append('email', email); 27 formData.append('message', message); 28 formData.append('nonce', settings.nonce); 29 30 const response = await fetch(settings.ajaxurl, { 31 method: 'POST', 32 body: formData, 33 credentials: 'same-origin' 34 }); 35 36 const data = await response.json(); 37 38 if (data.success) { 39 setFeedbackStatus({ type: 'success', message: 'Your feedback was sent successfully. Thank you!' }); 40 setName(''); 41 setEmail(''); 42 setMessage(''); 43 } else { 44 setFeedbackStatus({ type: 'error', message: data.data || 'Failed to send feedback. Please try again.' }); 45 } 46 } catch (error) { 47 console.error('Error sending feedback:', error); 48 setFeedbackStatus({ type: 'error', message: 'An error occurred while sending your feedback. Please try again.' }); 49 } finally { 50 setIsSending(false); 51 } 52 }; 53 54 return ( 55 <div className="iron-security-feedback-form iron-security-banner Standard"> 56 <div className="iron-security-banner-header">Send Us Your Feedback</div> 57 <p>We'd love to hear your thoughts about Iron Security. Please use this form to send us your feedback, suggestions, or questions.</p> 58 59 {feedbackStatus && ( 60 <div className={`iron-security-feedback-status ${feedbackStatus.type}`}> 61 {feedbackStatus.message} 62 </div> 63 )} 64 65 <form onSubmit={handleSubmit}> 66 <div className="iron-security-form-field"> 67 <label htmlFor="feedback-name">Your Name</label> 68 <br/> 69 <input 70 type="text" 71 id="feedback-name" 72 value={name} 73 onChange={(e) => setName(e.target.value)} 74 required 75 disabled={isSending} 76 style={{width:"100%"}} 77 /> 78 </div> 79 80 <div className="iron-security-form-field"> 81 <label htmlFor="feedback-email">Your Email</label> 82 <br/> 83 <input 84 type="email" 85 id="feedback-email" 86 value={email} 87 onChange={(e) => setEmail(e.target.value)} 88 required 89 disabled={isSending} 90 style={{width:"100%"}} 91 /> 92 </div> 93 94 <div className="iron-security-form-field"> 95 <label htmlFor="feedback-message">Your Message</label> 96 <br/> 97 <textarea 98 id="feedback-message" 99 value={message} 100 onChange={(e) => setMessage(e.target.value)} 101 required 102 disabled={isSending} 103 rows="4" 104 style={{width:"100%"}} 105 ></textarea> 106 </div> 107 108 <button 109 type="submit" 110 className="button button-primary" 111 disabled={isSending} 112 > 113 {isSending ? 'Sending...' : 'Send Feedback'} 114 </button> 115 </form> 116 </div> 117 ); 118 }; 9 119 10 120 const Dashboard = ({settings: initialSettings}) => { … … 202 312 <strong><a href='https://wordpress.org/plugins/quantity-discounts/' target='_blank'>Quantity Breaks</a></strong>`} 203 313 /> 314 <FeedbackForm settings={settings} /> 204 315 </div> 205 316 </div> -
iron-security/tags/2.3.4/admin/js/dist/manifest.json
r3300103 r3303789 1 1 { 2 "dashboard.js": "dashboard. 409171eb914877d3afe7.js",3 "vendors.js": "vendors. 91782840b9e9337a9a5f.js"2 "dashboard.js": "dashboard.6931e43c4d8629f63bd9.js", 3 "vendors.js": "vendors.b4116fd1b25e74ca1789.js" 4 4 } -
iron-security/tags/2.3.4/includes/class-iron-security.php
r3300103 r3303789 94 94 $this->loader->add_action( 'wp_login_failed', $plugin_admin, 'wpironis_handle_failed_login', 10, 3 ); 95 95 $this->loader->add_action( 'wp_login', $plugin_admin, 'log_successful_login', 10, 2 ); 96 $this->loader->add_action( 'init', $plugin_admin, 'wpironis_block_locked_out_ip_early', 1 ); 96 97 $this->loader->add_filter( 'authenticate', $plugin_admin, 'wpironis_block_locked_out_users', 10, 3 ); 97 98 $this->loader->add_filter( 'authenticate', $plugin_admin, 'wpironsecwp_block_verify_2fa', 20, 3 ); … … 295 296 $this->loader->add_action( 'wp_ajax_iron_security_get_settings', $plugin_admin, 'wpironis_get_settings' ); 296 297 $this->loader->add_action( 'wp_ajax_iron_security_toggle_ai_bot_blocking', $plugin_admin, 'wpironis_handle_ai_bot_blocking_toggle' ); 298 $this->loader->add_action( 'wp_ajax_iron_security_send_feedback', $plugin_admin, 'handle_telegram_feedback' ); 297 299 // $this->loader->add_action('wp_authenticate_user', $plugin_admin, 'wpironis_block_locked_out_users', 10, 4); 298 300 -
iron-security/tags/2.3.4/iron-security.php
r3300103 r3303789 17 17 * Plugin URI: https://wpiron.com 18 18 * Description: Iron Security is a powerful WordPress security plugin to protect your site from common threats. Lock down your site with login protection, file security, and HTTP headers — all in one lightweight plugin. 19 * Version: 2.3. 319 * Version: 2.3.4 20 20 * Author: wpiron 21 21 * Author URI: https://wpiron.com/ … … 31 31 } 32 32 33 define( 'IRON_SECURITY_VERSION', '2.3. 3' );33 define( 'IRON_SECURITY_VERSION', '2.3.4' ); 34 34 35 35 function wpiisec_activate_iron_security() { -
iron-security/trunk/README.txt
r3300103 r3303789 5 5 Requires at least: 4.7 6 6 Tested up to: 6.8 7 Stable tag: 2.3. 37 Stable tag: 2.3.4 8 8 Requires PHP: 7.0 9 9 License: GPLv2 or later … … 142 142 == Changelog == 143 143 144 = 2.3.4 = 145 * Update plugin 146 144 147 = 2.3.3 = 145 148 * Add functionality to change default admin username -
iron-security/trunk/admin/class-iron-security-admin.php
r3300103 r3303789 336 336 337 337 return $this->login_logout_functionality->wpironsecwp_block_locked_out_users( $user, $username, $password ); 338 } 339 340 public function wpironis_block_locked_out_ip_early() { 341 return $this->login_logout_functionality->wpironsecwp_block_locked_out_ip_early(); 338 342 } 339 343 … … 3608 3612 } 3609 3613 3614 public function handle_telegram_feedback() { 3615 check_ajax_referer('iron_security_nonce', 'nonce'); 3616 3617 if (!current_user_can('manage_options')) { 3618 wp_send_json_error('Insufficient permissions'); 3619 return; 3620 } 3621 3622 $name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : ''; 3623 $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; 3624 $message = isset($_POST['message']) ? sanitize_textarea_field($_POST['message']) : ''; 3625 3626 if (empty($name) || empty($email) || empty($message)) { 3627 wp_send_json_error('All fields are required'); 3628 return; 3629 } 3630 3631 $bot_token = '7891702745:AAE9NIFGYVZzgmIiLZ1xVKBVtG5Wn-E-66E'; 3632 $chat_id = '-1002293858145'; 3633 3634 $text = "*Iron Security Feedback* \n\n"; 3635 $text .= "*Name:* $name\n"; 3636 $text .= "*Email:* $email\n"; 3637 $text .= "*Message:*\n$message"; 3638 3639 $url = "https://api.telegram.org/bot$bot_token/sendMessage"; 3640 3641 $args = [ 3642 'body' => [ 3643 'chat_id' => $chat_id, 3644 'text' => $text, 3645 'parse_mode' => 'Markdown' 3646 ] 3647 ]; 3648 3649 $response = wp_remote_post($url, $args); 3650 3651 if (is_wp_error($response)) { 3652 error_log($response->get_error_message()); 3653 wp_send_json_error('Failed to send message: ' . $response->get_error_message()); 3654 return; 3655 } 3656 3657 $body = wp_remote_retrieve_body($response); 3658 $data = json_decode($body, true); 3659 3660 if (isset($data['ok']) && $data['ok'] === true) { 3661 wp_send_json_success('Feedback sent successfully'); 3662 } else { 3663 wp_send_json_error('Failed to send message'); 3664 } 3665 } 3666 3610 3667 private function get_hashed_filename( $base_name ) { 3611 3668 $manifest_path = plugin_dir_path( __FILE__ ) . 'js/dist/manifest.json'; -
iron-security/trunk/admin/classes/login-logout-functionality.php
r3291538 r3303789 16 16 $this->version = '1.0.0'; 17 17 $this->tracking_access = new SafeWP_Setup_Tracking_Access(); 18 // $this->safe2fa = new safe_2fa_admin();19 18 } 20 19 … … 24 23 <p class="text-center"> 25 24 This section of the Iron Security Plugin offers several options to enhance the security of your 26 WordPress 27 site. These settings allow you to customize various aspects of the login and logout 25 WordPress site. These settings allow you to customize various aspects of the login and logout 28 26 process, reducing vulnerabilities and protecting against unauthorized access. 29 27 </p> 30 <?php 31 settings_errors( 'wpironis_messages' ); ?> 28 <?php settings_errors( 'wpironis_messages' ); ?> 32 29 <form method="post" action="options.php"> 33 30 <?php … … 49 46 <input type="checkbox" id="enable_session_timeout" 50 47 name="wpironis_plugin_settings_loginlogout[enable_session_timeout]" 51 value="1" <?php 52 checked( 1, $is_enabled, true ); ?>> 48 value="1" <?php checked( 1, $is_enabled, true ); ?>> 53 49 <span class="slider round"></span> 54 50 </label> … … 58 54 <input type="number" name="wpironis_plugin_settings_loginlogout[session_timeout_value]" 59 55 id="session_timeout_value" 60 value="<?php 61 echo esc_attr( $timeoutValue ); ?>" 56 value="<?php echo esc_attr( $timeoutValue ); ?>" 62 57 placeholder="Enter timeout in seconds (for example 3600 it will be 1hr)"> 63 58 </div> … … 77 72 <input type="checkbox" id="enable_slug_change" 78 73 name="wpironis_plugin_settings_loginlogout[enable_slug_change]" 79 value="1" <?php 80 checked( 1, $is_enabled, true ); ?>> 74 value="1" <?php checked( 1, $is_enabled, true ); ?>> 81 75 <span class="slider round"></span> 82 76 </label> … … 85 79 <input type="text" name="wpironis_plugin_settings_loginlogout[wpironis_custom_login_slug]" 86 80 id="wpironis_custom-admin-slug" 87 value="<?php 88 echo isset( $slug ) ? esc_attr( $slug ) : ''; ?>" 81 value="<?php echo isset( $slug ) ? esc_attr( $slug ) : ''; ?>" 89 82 placeholder="Enter custom login URL"> 90 83 </div> … … 94 87 automated attacks. This simple change adds an effective layer of protection to your website.</p> 95 88 </div> 96 97 89 <?php 98 90 } … … 105 97 <input type="checkbox" id="enable_limit_login_attempts" 106 98 name="wpironis_plugin_settings_loginlogout[enable_limit_login_attempts]" 107 value="1" <?php 108 checked( 1, $is_enabled, true ); ?>> 99 value="1" <?php checked( 1, $is_enabled, true ); ?>> 109 100 <span class="slider round"></span> 110 101 </label> … … 115 106 <input type="number" name="wpironis_plugin_settings_loginlogout[wpironis_limit_login_attempts]" 116 107 id="limit_login_attempts" 117 value="<?php 118 echo esc_attr( $attempts ); ?>" 108 value="<?php echo esc_attr( $attempts ); ?>" 119 109 placeholder="Enter the number of allowed attempts (for example: 5)"> 120 110 </div> … … 123 113 <input type="number" name="wpironis_plugin_settings_loginlogout[wpironis_lockout_duration]" 124 114 id="wpironis_lockout_duration" 125 value="<?php 126 echo esc_attr( $time ); ?>" placeholder="How long to keep user blocked? in seconds"> 115 value="<?php echo esc_attr( $time ); ?>" placeholder="How long to keep user blocked? in seconds"> 127 116 </div> 128 117 </div> … … 141 130 <input type="checkbox" id="enable_2fa" 142 131 name="wpironis_plugin_settings_loginlogout[enable_2fa]" 143 value="1" <?php 144 checked( 1, $is_enabled, true ); ?>> 132 value="1" <?php checked( 1, $is_enabled, true ); ?>> 145 133 <span class="slider round"></span> 146 134 </label> … … 154 142 <input type="checkbox" id="wpironis_2fa_google_auth_field" 155 143 name="wpironis_plugin_settings_loginlogout[wpironis_2fa_google_auth]" 156 value="1" <?php 157 checked( 1, $googleAuth, true ); ?>> 144 value="1" <?php checked( 1, $googleAuth, true ); ?>> 158 145 <span class="slider round"></span> 159 146 </label> … … 178 165 strtoupper( sanitize_text_field( $_SERVER['REQUEST_METHOD'] ) ) !== 'POST' 179 166 ) { 180 // Redirect to the home URL safely181 167 wp_redirect( esc_url( home_url() ) ); 182 168 exit; … … 184 170 } 185 171 186 187 172 public function customLoginUrl( $customUrl ) { 188 173 global $user_login, $error; 189 174 190 175 if ( strpos( $_SERVER['REQUEST_URI'], '/' . $customUrl ) !== false ) { 191 // Serve the login page if not logged in192 176 if ( ! is_user_logged_in() ) { 193 177 if ( ! isset( $user_login ) ) { … … 201 185 } 202 186 } 203 // If it's the default login URL, redirect to the custom URL204 187 if ( strpos( $_SERVER['REQUEST_URI'], 'wp-login.php' ) !== false && ! is_user_logged_in() ) { 205 188 wp_redirect( home_url( $customUrl ) ); … … 250 233 return admin_url(); 251 234 } 252 253 235 return home_url(); 254 236 } 255 256 237 return $redirect_to; 257 238 } … … 261 242 return (int) $timeout_value; 262 243 } 263 264 244 return $expireIn; 265 245 } … … 269 249 $attempts = get_transient( $ip_address . '_wpis_attempts' ) ?: 0; 270 250 $attempts ++; 251 271 252 set_transient( $ip_address . '_wpis_attempts', $attempts, $options['wpironis_lockout_duration'] ); 272 253 if ( $attempts >= $options['wpironis_limit_login_attempts'] ) { … … 289 270 290 271 public function wpironsecwp_block_locked_out_users( $user, $username, $password ) { 291 292 272 $ip_address = $this->get_user_ip(); 293 294 // Check if this IP is in lockout transient 273 295 274 if ( get_transient( $ip_address . '_wpis_lockout' ) ) { 296 297 // Optionally fetch how long until lockout ends:298 275 $lockout_duration = get_option( 'wpironis_plugin_settings_loginlogout' )['wpironis_lockout_duration']; 299 276 $lockout_time = get_transient( $ip_address . '_wpis_lockout_time' ); 300 277 $remaining_time = $lockout_duration - ( time() - $lockout_time ); 301 278 302 // Force all sessions for this IP to log out303 279 $this->wpisec_force_logout_by_ip( $ip_address ); 304 280 305 // -- 1) Immediately set a 403 status and kill on the login page --306 307 // Set 403 on "login_init"308 281 add_action( 'login_init', function() { 309 282 status_header( 403 ); 310 283 nocache_headers(); 311 // Stop execution so the login form never appears312 284 exit; 313 285 }); 314 286 315 // If WordPress tries to render the login form anyway, kill it316 287 add_action( 'login_form', function () { 317 288 exit; 318 289 }); 319 290 320 // -- 2) Also block access to the wp-admin area --321 322 291 add_action( 'admin_init', function() { 323 292 status_header( 403 ); 324 293 nocache_headers(); 325 // This prevents the admin panel from loading326 294 exit; 327 295 }); 328 329 // -- 3) Optionally add your own error message on the login page (if it were to load) --330 296 331 297 add_filter( 'login_message', function () use ( $remaining_time ) { … … 336 302 }); 337 303 338 // Return a WP_Error so WordPress sees this as a failed login339 304 return new WP_Error( 340 305 'locked_out', … … 343 308 } 344 309 345 // If not locked out, just return the user object346 310 return $user; 347 311 } 348 349 312 350 313 /** … … 352 315 */ 353 316 public function wpisec_force_logout_by_ip( $ip_address ) { 354 $users = get_users(); // Get all users317 $users = get_users(); 355 318 356 319 foreach ( $users as $user ) { 357 320 $sessions = WP_Session_Tokens::get_instance( $user->ID ); 358 $sessions->destroy_all(); // Log out all sessions for this user 359 } 360 361 // Destroy the current session if the locked user is logged in 321 $sessions->destroy_all(); 322 } 323 362 324 if ( is_user_logged_in() ) { 363 325 wp_destroy_current_session(); 364 326 wp_clear_auth_cookie(); 365 wp_redirect( home_url() ); // Redirect to home page327 wp_redirect( home_url() ); 366 328 exit; 367 329 } … … 392 354 } else { 393 355 error_log( '2FA code not entered' ); 394 395 356 return new WP_Error( 'missing_2fa_code', 396 357 '<strong>ERROR</strong>: Please enter your 2FA code.' ); … … 401 362 } else { 402 363 error_log( 'Nonce verification failed or nonce not set' ); 403 404 364 return new WP_Error( 'invalid_nonce', '<strong>ERROR</strong>: Nonce verification failed.' ); 405 365 } … … 415 375 } 416 376 417 418 377 public function get_user_ip() { 419 unset($_SERVER['HTTP_X_FORWARDED_FOR'], $_SERVER['CLIENT_IP']); 420 421 if (!empty($_SERVER['REMOTE_ADDR']) && self::validate_ip($_SERVER['REMOTE_ADDR'])) { 422 return $_SERVER['REMOTE_ADDR']; 423 } 424 } 425 426 private static function validate_ip($ip) { 427 return filter_var($ip, FILTER_VALIDATE_IP) !== false; 378 $remote_addr = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; 379 380 if (self::validate_ip($remote_addr)) { 381 return $remote_addr; 382 } 383 384 return '0.0.0.0'; 385 } 386 387 public static function validate_ip($ip) { 388 if (filter_var($ip, FILTER_VALIDATE_IP) === false) { 389 return false; 390 } 391 return true; 428 392 } 429 393 -
iron-security/trunk/admin/css/iron-security-admin.css
r3288628 r3303789 224 224 color: #fff; 225 225 background: #0073aa; 226 } 227 228 /* Feedback Form */ 229 .iron-security-feedback-form { 230 background: #fff; 231 border: 1px solid #e2e4e7; 232 border-radius: 4px; 233 padding: 20px; 234 margin-top: 20px; 235 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); 236 } 237 238 .iron-security-feedback-form p { 239 margin-bottom: 15px; 240 color: #555; 241 } 242 243 .iron-security-form-field { 244 margin-bottom: 15px; 245 } 246 247 .iron-security-form-field label { 248 display: block; 249 margin-bottom: 5px; 250 font-weight: 500; 251 } 252 253 .iron-security-form-field input, 254 .iron-security-form-field textarea { 255 width: 100%; 256 padding: 8px 12px; 257 border-radius: 4px; 258 border: 1px solid #ddd; 259 font-size: 14px; 260 } 261 262 .iron-security-form-field textarea { 263 resize: vertical; 264 min-height: 80px; 265 } 266 267 .iron-security-feedback-status { 268 margin-bottom: 15px; 269 padding: 10px 15px; 270 border-radius: 4px; 271 font-size: 14px; 272 } 273 274 .iron-security-feedback-status.success { 275 background-color: #ecf9ec; 276 color: #1e7e34; 277 border: 1px solid #c3e6cb; 278 } 279 280 .iron-security-feedback-status.error { 281 background-color: #f8d7da; 282 color: #721c24; 283 border: 1px solid #f5c6cb; 284 } 285 286 .iron-security-feedback-form button { 287 margin-top: 5px; 226 288 } -
iron-security/trunk/admin/js/components/Dashboard.jsx
r3300103 r3303789 7 7 import HttpSecurityHeadersSettings from "./HttpSecurityHeadersSettings"; 8 8 import Support from './Support'; 9 10 const FeedbackForm = ({ settings }) => { 11 const [name, setName] = useState(''); 12 const [email, setEmail] = useState(''); 13 const [message, setMessage] = useState(''); 14 const [isSending, setIsSending] = useState(false); 15 const [feedbackStatus, setFeedbackStatus] = useState(null); 16 17 const handleSubmit = async (e) => { 18 e.preventDefault(); 19 setIsSending(true); 20 setFeedbackStatus(null); 21 22 try { 23 const formData = new FormData(); 24 formData.append('action', 'iron_security_send_feedback'); 25 formData.append('name', name); 26 formData.append('email', email); 27 formData.append('message', message); 28 formData.append('nonce', settings.nonce); 29 30 const response = await fetch(settings.ajaxurl, { 31 method: 'POST', 32 body: formData, 33 credentials: 'same-origin' 34 }); 35 36 const data = await response.json(); 37 38 if (data.success) { 39 setFeedbackStatus({ type: 'success', message: 'Your feedback was sent successfully. Thank you!' }); 40 setName(''); 41 setEmail(''); 42 setMessage(''); 43 } else { 44 setFeedbackStatus({ type: 'error', message: data.data || 'Failed to send feedback. Please try again.' }); 45 } 46 } catch (error) { 47 console.error('Error sending feedback:', error); 48 setFeedbackStatus({ type: 'error', message: 'An error occurred while sending your feedback. Please try again.' }); 49 } finally { 50 setIsSending(false); 51 } 52 }; 53 54 return ( 55 <div className="iron-security-feedback-form iron-security-banner Standard"> 56 <div className="iron-security-banner-header">Send Us Your Feedback</div> 57 <p>We'd love to hear your thoughts about Iron Security. Please use this form to send us your feedback, suggestions, or questions.</p> 58 59 {feedbackStatus && ( 60 <div className={`iron-security-feedback-status ${feedbackStatus.type}`}> 61 {feedbackStatus.message} 62 </div> 63 )} 64 65 <form onSubmit={handleSubmit}> 66 <div className="iron-security-form-field"> 67 <label htmlFor="feedback-name">Your Name</label> 68 <br/> 69 <input 70 type="text" 71 id="feedback-name" 72 value={name} 73 onChange={(e) => setName(e.target.value)} 74 required 75 disabled={isSending} 76 style={{width:"100%"}} 77 /> 78 </div> 79 80 <div className="iron-security-form-field"> 81 <label htmlFor="feedback-email">Your Email</label> 82 <br/> 83 <input 84 type="email" 85 id="feedback-email" 86 value={email} 87 onChange={(e) => setEmail(e.target.value)} 88 required 89 disabled={isSending} 90 style={{width:"100%"}} 91 /> 92 </div> 93 94 <div className="iron-security-form-field"> 95 <label htmlFor="feedback-message">Your Message</label> 96 <br/> 97 <textarea 98 id="feedback-message" 99 value={message} 100 onChange={(e) => setMessage(e.target.value)} 101 required 102 disabled={isSending} 103 rows="4" 104 style={{width:"100%"}} 105 ></textarea> 106 </div> 107 108 <button 109 type="submit" 110 className="button button-primary" 111 disabled={isSending} 112 > 113 {isSending ? 'Sending...' : 'Send Feedback'} 114 </button> 115 </form> 116 </div> 117 ); 118 }; 9 119 10 120 const Dashboard = ({settings: initialSettings}) => { … … 202 312 <strong><a href='https://wordpress.org/plugins/quantity-discounts/' target='_blank'>Quantity Breaks</a></strong>`} 203 313 /> 314 <FeedbackForm settings={settings} /> 204 315 </div> 205 316 </div> -
iron-security/trunk/admin/js/dist/manifest.json
r3300103 r3303789 1 1 { 2 "dashboard.js": "dashboard. 409171eb914877d3afe7.js",3 "vendors.js": "vendors. 91782840b9e9337a9a5f.js"2 "dashboard.js": "dashboard.6931e43c4d8629f63bd9.js", 3 "vendors.js": "vendors.b4116fd1b25e74ca1789.js" 4 4 } -
iron-security/trunk/includes/class-iron-security.php
r3300103 r3303789 94 94 $this->loader->add_action( 'wp_login_failed', $plugin_admin, 'wpironis_handle_failed_login', 10, 3 ); 95 95 $this->loader->add_action( 'wp_login', $plugin_admin, 'log_successful_login', 10, 2 ); 96 $this->loader->add_action( 'init', $plugin_admin, 'wpironis_block_locked_out_ip_early', 1 ); 96 97 $this->loader->add_filter( 'authenticate', $plugin_admin, 'wpironis_block_locked_out_users', 10, 3 ); 97 98 $this->loader->add_filter( 'authenticate', $plugin_admin, 'wpironsecwp_block_verify_2fa', 20, 3 ); … … 295 296 $this->loader->add_action( 'wp_ajax_iron_security_get_settings', $plugin_admin, 'wpironis_get_settings' ); 296 297 $this->loader->add_action( 'wp_ajax_iron_security_toggle_ai_bot_blocking', $plugin_admin, 'wpironis_handle_ai_bot_blocking_toggle' ); 298 $this->loader->add_action( 'wp_ajax_iron_security_send_feedback', $plugin_admin, 'handle_telegram_feedback' ); 297 299 // $this->loader->add_action('wp_authenticate_user', $plugin_admin, 'wpironis_block_locked_out_users', 10, 4); 298 300 -
iron-security/trunk/iron-security.php
r3300103 r3303789 17 17 * Plugin URI: https://wpiron.com 18 18 * Description: Iron Security is a powerful WordPress security plugin to protect your site from common threats. Lock down your site with login protection, file security, and HTTP headers — all in one lightweight plugin. 19 * Version: 2.3. 319 * Version: 2.3.4 20 20 * Author: wpiron 21 21 * Author URI: https://wpiron.com/ … … 31 31 } 32 32 33 define( 'IRON_SECURITY_VERSION', '2.3. 3' );33 define( 'IRON_SECURITY_VERSION', '2.3.4' ); 34 34 35 35 function wpiisec_activate_iron_security() {
Note: See TracChangeset
for help on using the changeset viewer.