| @@ -13,9 +13,9 @@ | ||
| 13 | 13 | use Calotes\Helper\Array_Cache; |
| 14 | 14 | use WP_Defender\Traits\Country; |
| 15 | 15 | use WP_Defender\Traits\Continent; |
| 16 | 16 | use WP_Defender\Model\Lockout_Log; |
| 17 | -use MaxMind\Db\Reader\InvalidDatabaseException; | |
| 17 | +use WP_DEFENDER_VENDOR\MaxMind\Db\Reader\InvalidDatabaseException; | |
| 18 | 18 | use WP_Defender\Integrations\MaxMind_Geolocation; |
| 19 | 19 | use WP_Defender\Model\Setting\Blacklist_Lockout as Model_Blacklist_Lockout; |
| 20 | 20 | use WP_Defender\Integrations\Main_Wp; |
| 21 | 21 | use WP_Filesystem_Base; |
| @@ -75,9 +75,9 @@ | ||
| 75 | 75 | return false; |
| 76 | 76 | } |
| 77 | 77 | $model = new Model_Blacklist_Lockout(); |
| 78 | 78 | $whitelist = $model->get_country_whitelist(); |
| 79 | - if ( ! is_array( $whitelist ) || array() === $whitelist ) { | |
| 79 | + if ( array() === $whitelist ) { | |
| 80 | 80 | return false; |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | if ( isset( $country['iso'] ) && '' !== $country['iso'] ) { |
| @@ -82,19 +82,11 @@ | ||
| 82 | 82 | |
| 83 | 83 | if ( isset( $country['iso'] ) && '' !== $country['iso'] ) { |
| 84 | 84 | $country_iso = strtoupper( $country['iso'] ); |
| 85 | 85 | |
| 86 | - // Check if the specific country is in the whitelist. | |
| 87 | - if ( in_array( $country_iso, $whitelist, true ) ) { | |
| 86 | + if ( $this->is_country_iso_in_list( $country_iso, $whitelist ) ) { | |
| 88 | 87 | return true; |
| 89 | 88 | } |
| 90 | - | |
| 91 | - // Check if any continent containing this country is in the whitelist. | |
| 92 | - foreach ( $whitelist as $allowed_code ) { | |
| 93 | - if ( $this->is_country_in_continent( $country_iso, $allowed_code ) ) { | |
| 94 | - return true; | |
| 95 | - } | |
| 96 | - } | |
| 97 | 89 | } |
| 98 | 90 | |
| 99 | 91 | return false; |
| 100 | 92 | } |
| @@ -109,9 +101,9 @@ | ||
| 109 | 101 | $remote_addr = defender_get_data_from_request( 'REMOTE_ADDR', 's' ); |
| 110 | 102 | $ips = array( |
| 111 | 103 | ...self::fetch_latest_ips(), |
| 112 | 104 | '127.0.0.1', |
| 113 | - isset( $server_addr ) ? $server_addr : $remote_addr, | |
| 105 | + $server_addr ?? $remote_addr, | |
| 114 | 106 | ); |
| 115 | 107 | |
| 116 | 108 | $whitelist_ips = apply_filters( 'ip_lockout_default_whitelist_ip', $ips ); |
| 117 | 109 | return is_array( $whitelist_ips ) ? $whitelist_ips : (array) $whitelist_ips; |
| @@ -235,19 +227,11 @@ | ||
| 235 | 227 | |
| 236 | 228 | if ( isset( $country['iso'] ) && '' !== $country['iso'] ) { |
| 237 | 229 | $country_iso = strtoupper( $country['iso'] ); |
| 238 | 230 | |
| 239 | - // Check if the specific country is in the blacklist. | |
| 240 | - if ( in_array( $country_iso, $blacklisted, true ) ) { | |
| 231 | + if ( $this->is_country_iso_in_list( $country_iso, $blacklisted ) ) { | |
| 241 | 232 | return true; |
| 242 | 233 | } |
| 243 | - | |
| 244 | - // Check if any continent containing this country is in the blacklist. | |
| 245 | - foreach ( $blacklisted as $blocked_code ) { | |
| 246 | - if ( $this->is_country_in_continent( $country_iso, $blocked_code ) ) { | |
| 247 | - return true; | |
| 248 | - } | |
| 249 | - } | |
| 250 | 234 | } |
| 251 | 235 | |
| 252 | 236 | return false; |
| 253 | 237 | } |
| @@ -312,9 +296,9 @@ | ||
| 312 | 296 | public function is_geodb_downloaded(): bool { |
| 313 | 297 | $model = new Model_Blacklist_Lockout(); |
| 314 | 298 | $license_key = $model->maxmind_license_key; |
| 315 | 299 | // Using Geo DB without a license key is not advisable. |
| 316 | - if ( '' === $license_key && is_file( $model->geodb_path ) ) { | |
| 300 | + if ( '' === $license_key && is_string( $model->geodb_path ) && is_file( $model->geodb_path ) ) { | |
| 317 | 301 | $service_geo = wd_di()->get( MaxMind_Geolocation::class ); |
| 318 | 302 | $service_geo->delete_database(); |
| 319 | 303 | $model->geodb_path = ''; |
| 320 | 304 | $model->save(); |
| @@ -324,9 +308,9 @@ | ||
| 324 | 308 | |
| 325 | 309 | // Likely the case after the config import with the existed MaxMind license key. |
| 326 | 310 | if ( |
| 327 | 311 | '' !== $license_key |
| 328 | - && ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) | |
| 312 | + && ( ! is_string( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) | |
| 329 | 313 | ) { |
| 330 | 314 | $service_geo = wd_di()->get( MaxMind_Geolocation::class ); |
| 331 | 315 | $tmp = $service_geo->get_downloaded_url( $license_key ); |
| 332 | 316 | if ( ! is_wp_error( $tmp ) ) { |
| @@ -363,9 +347,9 @@ | ||
| 363 | 347 | } |
| 364 | 348 | } |
| 365 | 349 | |
| 366 | 350 | // Check again. |
| 367 | - if ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) { | |
| 351 | + if ( ! is_string( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) { | |
| 368 | 352 | return false; |
| 369 | 353 | } |
| 370 | 354 | |
| 371 | 355 | // Check if the file exists on the site. The file can exist on the same server but for different sites. |
| @@ -381,9 +365,9 @@ | ||
| 381 | 365 | |
| 382 | 366 | $rel_path = $abs_path . DIRECTORY_SEPARATOR . $path_parts['basename']; |
| 383 | 367 | if ( file_exists( $rel_path ) ) { |
| 384 | 368 | return true; |
| 385 | - } elseif ( ! is_null( $model->geodb_path ) && '' !== $model->geodb_path && file_exists( $model->geodb_path ) ) { | |
| 369 | + } elseif ( '' !== $model->geodb_path && file_exists( $model->geodb_path ) ) { | |
| 386 | 370 | // The case if ABSPATH was changed e.g. in wp-config.php. |
| 387 | 371 | return true; |
| 388 | 372 | } |
| 389 | 373 | |
| @@ -517,6 +501,58 @@ | ||
| 517 | 501 | } |
| 518 | 502 | } |
| 519 | 503 | |
| 520 | 504 | return true; |
| 505 | + } | |
| 506 | + | |
| 507 | + /** | |
| 508 | + * Check whether a code identifies a continent without also identifying a country. | |
| 509 | + * | |
| 510 | + * @param string $code The code to check. | |
| 511 | + * @return bool True when the code identifies only a continent. | |
| 512 | + */ | |
| 513 | + private function is_continent_code( $code ): bool { | |
| 514 | + $countries_with_continents = $this->get_countries_with_continents(); | |
| 515 | + | |
| 516 | + if ( ! isset( $countries_with_continents[ $code ] ) ) { | |
| 517 | + return false; | |
| 518 | + } | |
| 519 | + | |
| 520 | + foreach ( $countries_with_continents as $continent ) { | |
| 521 | + if ( ! isset( $continent['area'] ) ) { | |
| 522 | + continue; | |
| 523 | + } | |
| 524 | + | |
| 525 | + foreach ( $continent['area'] as $area ) { | |
| 526 | + if ( isset( $area['countries'][ $code ] ) ) { | |
| 527 | + return false; | |
| 528 | + } | |
| 529 | + } | |
| 530 | + } | |
| 531 | + | |
| 532 | + return true; | |
| 533 | + } | |
| 534 | + | |
| 535 | + /** | |
| 536 | + * Checks whether a country ISO code (or any continent it belongs to) is present in the given list. | |
| 537 | + * | |
| 538 | + * @param string $country_iso The upcased two-letter ISO country code. | |
| 539 | + * @param array $iso_list The list of country/continent codes to check against. | |
| 540 | + * | |
| 541 | + * @return bool True if the country or one of its continents is found in the list. | |
| 542 | + */ | |
| 543 | + private function is_country_iso_in_list( string $country_iso, array $iso_list ): bool { | |
| 544 | + // Check if the specific country is in the list. | |
| 545 | + if ( in_array( $country_iso, $iso_list, true ) ) { | |
| 546 | + return true; | |
| 547 | + } | |
| 548 | + | |
| 549 | + // Check if any continent containing this country is in the list. | |
| 550 | + foreach ( $iso_list as $code ) { | |
| 551 | + if ( $this->is_continent_code( $code ) && $this->is_country_in_continent( $country_iso, $code ) ) { | |
| 552 | + return true; | |
| 553 | + } | |
| 554 | + } | |
| 555 | + | |
| 556 | + return false; | |
| 521 | 557 | } |
| 522 | 558 | } |