| @@ -109,9 +109,9 @@ | ||
| 109 | 109 | is_multisite() ? 'manage_network_options' : 'manage_options', |
| 110 | 110 | $this->get_link( 'upsell', 'defender_new-submenu_upsell' ) |
| 111 | 111 | ); |
| 112 | 112 | global $submenu; |
| 113 | - if ( ! empty( $submenu['wp-defender'] ) ) { | |
| 113 | + if ( isset( $submenu['wp-defender'] ) && is_array( $submenu['wp-defender'] ) && array() !== $submenu['wp-defender'] ) { | |
| 114 | 114 | $last = array_key_last( $submenu['wp-defender'] ); |
| 115 | 115 | $submenu['wp-defender'][ $last ][4] = 'defender-menu-upsell'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited |
| 116 | 116 | } |
| 117 | 117 | } |
| @@ -173,14 +173,8 @@ | ||
| 173 | 173 | return $plugin_label . ' - '; |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 176 | /** |
| 177 | - * The method is a stub without content. | |
| 178 | - */ | |
| 179 | - private function menu_nope(): void { | |
| 180 | - } | |
| 181 | - | |
| 182 | - /** | |
| 183 | 177 | * Generates the submenu callout for the WP Defender plugin. |
| 184 | 178 | * |
| 185 | 179 | * @return void |
| 186 | 180 | */ |
| @@ -233,13 +227,9 @@ | ||
| 233 | 227 | |
| 234 | 228 | #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a, |
| 235 | 229 | #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a:hover, |
| 236 | 230 | #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a:active, |
| 237 | - #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a:focus, | |
| 238 | - #toplevel_page_wp-defender.wp-not-current-submenu > ul > li > a[href="admin.php?page=defender_cross_sell"], | |
| 239 | - #toplevel_page_wp-defender.wp-not-current-submenu > ul > li > a[href="admin.php?page=defender_cross_sell"]:hover, | |
| 240 | - #toplevel_page_wp-defender.wp-not-current-submenu > ul > li > a[href="admin.php?page=defender_cross_sell"]:active, | |
| 241 | - #toplevel_page_wp-defender.wp-not-current-submenu > ul > li > a[href="admin.php?page=defender_cross_sell"]:focus { | |
| 231 | + #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a:focus { | |
| 242 | 232 | margin-left: -4px; |
| 243 | 233 | } |
| 244 | 234 | </style> |
| 245 | 235 | <script type='text/javascript'> |
| @@ -612,15 +602,29 @@ | ||
| 612 | 602 | // Change model's data. |
| 613 | 603 | $model_firewall = wd_di()->get( Model\Setting\Firewall::class ); |
| 614 | 604 | $model_firewall->http_ip_header = 'HTTP_X_FORWARDED_FOR'; |
| 615 | 605 | $xff_ip = defender_get_data_from_request( 'HTTP_X_FORWARDED_FOR', 's' ); |
| 606 | + $xff_parts = preg_split( '/\s*,\s*/', $xff_ip ); | |
| 607 | + $xff_parts = is_array( $xff_parts ) ? $xff_parts : array(); | |
| 608 | + $xff_parts = array_map( 'trim', $xff_parts ); | |
| 609 | + $xff_parts = array_filter( | |
| 610 | + $xff_parts, | |
| 611 | + static function ( $ip ) { | |
| 612 | + return false !== filter_var( $ip, FILTER_VALIDATE_IP ); | |
| 613 | + } | |
| 614 | + ); | |
| 615 | + $separator = "\r\n"; | |
| 616 | + $xff_parts = array_unique( $xff_parts ); | |
| 617 | + $xff_ip = implode( $separator, $xff_parts ); | |
| 618 | + if ( '' === $xff_ip ) { | |
| 619 | + wp_send_json_error( | |
| 620 | + array( 'message' => esc_html__( 'Invalid trusted proxy IP(s) detected in X-Forwarded-For header.', 'defender-security' ) ) | |
| 621 | + ); | |
| 622 | + } | |
| 616 | 623 | if ( '' === $model_firewall->trusted_proxies_ip ) { |
| 617 | 624 | $model_firewall->trusted_proxies_ip = $xff_ip; |
| 618 | 625 | } else { |
| 619 | 626 | // Todo: improve the code using a separate method. This will be useful when the user switches between different proxy headeres (IP detection options). |
| 620 | - $separator = "\r\n"; | |
| 621 | - // Check if the XFF header contains multiple IPs. | |
| 622 | - $xff_ip = str_replace( array( ',', ' ,' ), $separator, $xff_ip ); | |
| 623 | 627 | $model_firewall->trusted_proxies_ip = $model_firewall->trusted_proxies_ip . $separator . $xff_ip; |
| 624 | 628 | } |
| 625 | 629 | $model_firewall->save(); |
| 626 | 630 | // Save Dismiss slug. |
| @@ -643,9 +647,14 @@ | ||
| 643 | 647 | } |
| 644 | 648 | |
| 645 | 649 | // Data to be passed to the template file. |
| 646 | 650 | $is_pro = wd_di()->get( WPMUDEV::class )->is_pro(); |
| 647 | - $docs_link = $this->get_link( 'support_with_utm', 'defender_deactivation_survey_help', '', $is_pro ? 'defender-pro' : 'defender' ); | |
| 651 | + $docs_link = $this->get_link( | |
| 652 | + 'support_with_utm', | |
| 653 | + 'defender_deactivation_survey_help', | |
| 654 | + '', | |
| 655 | + $is_pro ? 'defender-pro' : 'defender' | |
| 656 | + ); | |
| 648 | 657 | |
| 649 | 658 | ob_start(); |
| 650 | 659 | require_once $deactivation_survey_template_file; |
| 651 | 660 | // Everything escaped in all template files. |