Your IP : 216.73.216.44


Current Path : /home/krobertfnz/www/wp-content/plugins/wp-defender/src/component/
Upload File :
Current File : /home/krobertfnz/www/wp-content/plugins/wp-defender/src/component/blacklist-lockout.php

<?php

namespace WP_Defender\Component;

use Calotes\Helper\Array_Cache;
use WP_Defender\Component;
use WP_Defender\Integrations\MaxMind_Geolocation;
use WP_Defender\Model\Lockout_Log;
use WP_Defender\Model\Setting\Blacklist_Lockout as Model_Blacklist_Lockout;

class Blacklist_Lockout extends Component {
	use \WP_Defender\Traits\Country;
	use \WP_Defender\Traits\IP;

	/**
	 * Queue hooks when this class init.
	 */
	public function add_hooks() {
		add_filter( 'defender_ip_lockout_assets', array( &$this, 'output_scripts_data' ) );
	}

	/**
	 * @param array $data
	 *
	 * @return mixed
	 * @throws \MaxMind\Db\Reader\InvalidDatabaseException
	 */
	public function output_scripts_data( $data ) {
		$model       = new Model_Blacklist_Lockout();
		$user_ip     = $this->get_user_ip();
		$exist_geodb = $this->is_geodb_downloaded();
		// If MaxMind GeoIP DB is downloaded then display the required data.
		if ( $exist_geodb ) {
			$current_country     = $this->get_current_country( $user_ip );
			$current_country     = $current_country['iso'] ?? false;
			$country_list        = $this->countries_list();
			$blacklist_countries = array_merge( array( 'all' => __( 'Block all', 'wpdef' ) ), $country_list );
			$whitelist_countries = array_merge( array( 'all' => __( 'Allow all', 'wpdef' ) ), $country_list );
		} else {
			$current_country     = false;
			$blacklist_countries = array();
			$whitelist_countries = array();
		}
		$data['blacklist'] = array(
			'model'   => $model->export(),
			'summary' => array(
				'day' => 0,
			),
			'misc'    => array(
				'geo_db_downloaded'   => $exist_geodb,
				'current_country'     => $current_country,
				'blacklist_countries' => $blacklist_countries,
				'whitelist_countries' => $whitelist_countries,
				'user_ip'             => $user_ip,
			),
			'class'   => Model_Blacklist_Lockout::class,
		);

		return $data;
	}

	/**
	 * @param string $ip
	 *
	 * @return bool
	 */
	public function is_country_whitelist( $ip ) {
		// Check Firewall > IP Banning > Locations section is activated or not.
		$country = $this->get_current_country( $ip );
		if ( false === $country ) {
			return false;
		}
		$model     = new Model_Blacklist_Lockout();
		$whitelist = $model->get_country_whitelist();
		if ( empty( $whitelist ) ) {
			return false;
		}
		if ( ! empty( $country['iso'] ) && in_array( strtoupper( $country['iso'] ), $whitelist, true ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Return the default ips need to whitelisted, e.g. HUB ips.
	 *
	 * @return array
	 */
	private function get_default_ip_whitelisted() {
		$ips = array(
			'18.204.159.253',
			'54.227.51.40',
			'18.219.56.14',
			'45.55.78.242',
			'35.171.56.101',
			'192.241.140.159',
			'104.236.132.222',
			'192.241.148.185',
			'34.196.51.17',
			'35.157.144.199',
			'159.89.254.12',
			'127.0.0.1',
			array_key_exists( 'SERVER_ADDR', $_SERVER )
				? $_SERVER['SERVER_ADDR']
				: ( $_SERVER['LOCAL_ADDR'] ?? null ),
		);

		return apply_filters( 'ip_lockout_default_whitelist_ip', $ips );
	}

	/**
	 * Is IP on Whitelist?
	 *
	 * @param string $ip
	 *
	 * @return bool
	 */
	public function is_ip_whitelisted( $ip ) {
		if ( in_array( $ip, $this->get_default_ip_whitelisted(), true ) ) {
			return true;
		}

		$blacklist_settings = new Model_Blacklist_Lockout();

		return $this->is_ip_in_format( $ip, $blacklist_settings->get_list( 'allowlist' ) );
	}

	/**
	 * Is IP on Blocklist?
	 *
	 * @param string $ip
	 *
	 * @return bool
	 */
	public function is_blacklist( $ip ) {
		$blacklist_settings = new Model_Blacklist_Lockout();

		return $this->is_ip_in_format( $ip, $blacklist_settings->get_list( 'blocklist' ) );
	}

	/**
	 * Is country on Blacklist?
	 *
	 * @param string $ip
	 *
	 * @return bool
	 */
	public function is_country_blacklist( $ip ) {
		// Check Firewall > IP Banning > Locations section is activated or not.
		$country = $this->get_current_country( $ip );
		if ( false === $country ) {
			return false;
		}
		$blacklist_settings = new Model_Blacklist_Lockout();
		$blacklisted        = $blacklist_settings->get_country_blacklist();
		if ( empty( $blacklisted ) ) {
			return false;
		}
		if ( in_array( 'all', $blacklisted, true ) ) {
			return true;
		}
		if ( ! empty( $country['iso'] ) && in_array( strtoupper( $country['iso'] ), $blacklisted, true ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Validate import file is in right format and usable for IP Lockout.
	 *
	 * @param $file
	 *
	 * @return array|bool
	 */
	public function verify_import_file( $file ) {
		$fp   = fopen( $file, 'r' );
		$data = array();
		while ( ( $line = fgetcsv( $fp ) ) !== false ) { //phpcs:ignore
			if ( 2 !== count( $line ) ) {
				return false;
			}

			if ( ! in_array( $line[1], array( 'allowlist', 'blocklist' ), true ) ) {
				return false;
			}

			if ( false === $this->validate_ip( $line[0] ) ) {
				continue;
			}

			$data[] = $line;
		}
		fclose( $fp );

		return $data;
	}

	/**
	 * @param Model_Blacklist_Lockout $model
	 * @param string                  $country_iso
	 *
	 * @return object
	 * @since 2.8.0
	*/
	public function add_default_whitelisted_country( Model_Blacklist_Lockout $model, $country_iso ) {
		if ( empty( $model->country_whitelist ) ) {
			$model->country_whitelist[] = $country_iso;
		} elseif ( ! in_array( $country_iso, $model->country_whitelist, true ) ) {
			$model->country_whitelist[] = $country_iso;
		}

		return $model;
	}

	/**
	 * Like download_geodb.
	 */
	public function download_geo_ip() {
		$url = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz';
		if ( ! function_exists( 'download_url' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}
		$this->download_by_url( $url );
	}

	/**
	 * @param string $url
	 *
	 * @return bool
	 */
	public function download_by_url( $url ) {
		$tmp = download_url( $url );
		if ( ! is_wp_error( $tmp ) ) {
			$phar = new \PharData( $tmp );
			$path = $this->get_tmp_path() . DIRECTORY_SEPARATOR . 'maxmind';
			if ( ! is_dir( $path ) ) {
				wp_mkdir_p( $path );
			}
			$phar->extractTo( $path, null, true );
			$model             = new Model_Blacklist_Lockout();
			$service_geo       = wd_di()->get( MaxMind_Geolocation::class );
			$model->geodb_path = $path . DIRECTORY_SEPARATOR . $phar->current()->getFileName() . DIRECTORY_SEPARATOR . $service_geo->get_db_full_name();

			if ( file_exists( $tmp ) ) {
				unlink( $tmp );
			}

			if ( empty( $model->country_whitelist ) ) {
				$country = $this->get_current_country( $this->get_user_ip() );
				if ( false === $country ) {
					return false;
				}
				if ( ! empty( $country['iso'] ) ) {
					$model = $this->add_default_whitelisted_country( $model, $country['iso'] );
				}
			}
			$model->save();

			return true;
		}

		return false;
	}

	/**
	 * @param string $license_key
	 *
	 * @return bool|string|\WP_Error
	 */
	public function get_maxmind_downloaded_url( $license_key ) {
		$url = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=$license_key&suffix=tar.gz";
		if ( ! function_exists( 'download_url' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		return download_url( $url );
	}

	/**
	 * Check downloaded GeoDB.
	 *
	 * @return bool
	 */
	public function is_geodb_downloaded() {
		$model = new Model_Blacklist_Lockout();
		// Likely the case after the config import with existed MaxMind license key.
		if (
			! empty( $model->maxmind_license_key )
			&& ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) )
		) {
			$service_geo = wd_di()->get( MaxMind_Geolocation::class );
			$tmp         = $service_geo->get_downloaded_url( $model->maxmind_license_key );
			if ( ! is_wp_error( $tmp ) ) {
				$phar = new \PharData( $tmp );
				$path = $this->get_tmp_path() . DIRECTORY_SEPARATOR . 'maxmind';
				if ( ! is_dir( $path ) ) {
					wp_mkdir_p( $path );
				}
				$phar->extractTo( $path, null, true );
				$model->geodb_path = $path . DIRECTORY_SEPARATOR . $phar->current()->getFileName() . DIRECTORY_SEPARATOR . $service_geo->get_db_full_name();
				// Save because we'll check for a saved path.
				$model->save();

				if ( file_exists( $tmp ) ) {
					unlink( $tmp );
				}

				if ( empty( $model->country_whitelist ) ) {
					$country = $this->get_current_country( $this->get_user_ip() );
					if ( false === $country ) {
						return false;
					}
					if ( ! empty( $country['iso'] ) ) {
						$model = $this->add_default_whitelisted_country( $model, $country['iso'] );
					}
				}
				$model->save();
			}
		}

		// Check again.
		if ( is_null( $model->geodb_path ) || ! is_file( $model->geodb_path ) ) {
			return false;
		}

		// Check if the file exists on the site. The file can exist on the same server but for different sites.
		// For example, after config importing.
		$path_parts = pathinfo( $model->geodb_path );
		if ( preg_match( '/(\/wp-content\/.+)/', $path_parts['dirname'], $matches ) ) {
			$rel_path = $matches[1];
			$rel_path = ltrim( $rel_path, '/' );
			$abs_path = ABSPATH . $rel_path;
			if ( ! is_dir( $abs_path ) ) {
				wp_mkdir_p( $abs_path );
			}

			$rel_path = $abs_path . DIRECTORY_SEPARATOR . $path_parts['basename'];
			if ( file_exists( $rel_path ) ) {
				return true;
			} elseif ( ! empty( $model->geodb_path ) && file_exists( $model->geodb_path ) ) {
				// The case if ABSPATH was changed e.g. in wp-config.php.
				return true;
			}

			if ( move_uploaded_file( $model->geodb_path, $rel_path ) ) {
				$model->geodb_path = $rel_path;
				$model->save();
			} else {
				return false;
			}
		}

		return true;
	}

	/**
	 * For Country widget.
	 *
	 * @param int $limit
	 * @param int $max_age_days
	 *
	 * @return array
	 */
	public function get_top_countries_blocked( $limit = 10, $max_age_days = 7 ) {
		$result = Array_Cache::get( 'countries', 'ip_lockout', [] );
		if ( empty( $result ) ) {
			global $wpdb;
			$table = $wpdb->base_prefix . ( new Lockout_Log() )->get_table();
			$sql = $wpdb->prepare(
				"SELECT country_iso_code, COUNT(ip) AS ip_count FROM {$table}" .
				" WHERE (type = %s OR type = %s OR type = %s) AND date >= %d AND country_iso_code IS NOT NULL" .
				" GROUP BY country_iso_code" .
				" ORDER BY ip_count DESC LIMIT %d",
				Lockout_Log::LOCKOUT_404,
				Lockout_Log::AUTH_LOCK,
				Lockout_Log::LOCKOUT_UA,
				strtotime( '-' . $max_age_days . ' days', current_time( 'timestamp' ) ),
				$limit
			);

			$result = $wpdb->get_results( $sql, ARRAY_A );
			// Get data from cache.
			Array_Cache::set( 'countries', $result, 'ip_lockout' );
		}

		return ! empty( $result ) ? $result : [];
	}
}