/**
* IP Location Block - Admin class
*
* @package IP_Location_Block
* @author Darko Gjorgjijoski <dg@darkogcom>
* @license GPL-30
* @link https://iplocationblockcom/
* @copyright 2021 darkog
* @copyright 2013-2019 tokkonopapa
*/
class IP_Location_Block_Admin {
/**
* Constants for admin class
*
*/
const INTERVAL_LIVE_UPDATE = 5; // interval for live update [sec]
const TIMEOUT_LIVE_UPDATE = 60; // timeout of pausing live update [sec]
/**
* Globals in this class
*
*/
private static $instance = null;
private $is_network_admin = false;
private $admin_tab = 0;
/**
* Initialize the plugin by loading admin scripts & styles
* and adding a settings page and menu.
*/
private function __construct() {
// Control tab number
if ( isset( $_REQUEST['page'] ) && 'ip-location-block' === $_REQUEST['page'] ) {
$this->admin_tab = isset( $_REQUEST['tab'] ) ? intval( $_REQUEST['tab'] ) : 0;
} else {
$this->admin_tab = - 1;
}
// Load plugin text domain and add body class
add_action( 'init', array( $this, 'admin_init' ) );
// Add suggest text for inclusion in the site's privacy policy. @since 496
// add_action( 'admin_init', array( $this, 'add_privacy_policy' ) );
// Setup a nonce to validate authenticationadd_filter( 'wp_redirect', array( $this, 'add_redirect_nonce' ), 10, 2 ); // @since 0210
}
/**
* Return an instance of this class.
*
*/
public static function get_instance() {
return self::$instance ? self::$instance : ( self::$instance = new self );
}
/**
* Print admin notice welcome screen
* @return void
*/
public function show_intro_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
if ( ! isset( $settings['welcome'] ) || ! $settings['welcome'] ) {
ob_start();
echo '<div class="notice notice-info is-dismissible ip-location-block-notice-intro" data-notice="welcome">';
include( dirname( __FILE__ ) . '/includes/welcomephp' );
echo '</div>';
$message = ob_get_clean();
echo $message;
}
}
/**
* Print admin notice for API key upgrade requirement
* @return void
*/
public function show_api_key_upgrade_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
// Check if we've already marked this as completed (user upgraded or dismissed)
if ( isset( $settings['api_key_upgraded'] ) && $settings['api_key_upgraded'] ) {
return;
}
// Check if IP Location Block provider is being used
$providers = IP_Location_Block_Provider::get_valid_providers( $settings );
$uses_api = in_array( 'IP Location Block', $providers );
if ( ! $uses_api ) {
return;
}
// Get API key
$api_key = ! empty( $settings['providers']['IP Location Block'] ) ? $settings['providers']['IP Location Block'] : '';
if ( empty( $api_key ) ) {
return;
}
// Check quota to see if upgrade is required
$quota = IP_Location_Block_Provider::get_native_quota( $api_key );
// If API key needs upgrade, show the notice
if ( isset( $quota['name'] ) && $quota['name'] === 'requires-api-key-upgrade' ) {
$upgrade_url = 'https://appiplocationblockcom/upgrade-api-key?api_key=' . urlencode( $api_key );
ob_start();
<div class="notice notice-warning ip-location-block-notice-api-key-upgrade">
<p>
<strong>_e( 'IP Location Block: API Key Upgrade Required', 'ip-location-block' );</strong>
</p>
<p>
_e( 'Your API key needs to be upgraded due to security improvementsThis is a one-time process and will only take a moment.', 'ip-location-block' );
</p>
<p>
<a href="echo esc_url( $upgrade_url );" class="button button-primary" target="_blank">
_e( 'Upgrade API Key Now', 'ip-location-block' );
</a>
<a href="https://iplocationblockcom/api-platform-upgrade/" class="button button-secondary" target="_blank">
_e( 'Learn More', 'ip-location-block' );
</a>
</p>
</div>
echo ob_get_clean();
} elseif ( isset( $quota['name'] ) && $quota['name'] !== 'requires-api-key-upgrade' ) {
// API key is valid and doesn't need upgrade, mark as completed so we don't check again
$settings['api_key_upgraded'] = true;
IP_Location_Block::update_option( $settings );
}
}
/**
* Show admin notice when server-level caching conflicts with public page validation.
*/
public function show_cache_compat_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
if ( ! empty( $settings['cache_compat_dismissed'] ) ) {
return;
}
if ( ! ( 1 & $settings['validation']['public'] ) ) {
return;
}
// Detect hosting environment
if ( function_exists( 'is_wpe' ) && is_wpe() === '1' ) {
$host_name = 'WP Engine';
$article_url = 'https://iplocationblockcom/codex/compatibility-with-wpengine/';
} elseif ( isset( $_SERVER['KINSTA_CACHE_ZONE'] ) ) {
$host_name = 'Kinsta';
$article_url = 'https://iplocationblockcom/codex/compatibility-with-kinsta/';
} else {
return;
}
<div class="notice notice-warning ip-location-block-notice-cache-compat" data-notice="cache_compat">
<p><strong>_e( 'IP Location Block: Full-Page Cache Conflict', 'ip-location-block' );</strong></p>
<p>printf(
__( 'Your site is hosted on <strong>%1$s</strong>, which uses server-level page caching that runs before PHPWhen "Front-end target settings" validation is enabled, cached pages may be served to all visitors without geolocation checks. <a href="%2$s" target="_blank">Learn how to configure %1$s for compatibility</a>.', 'ip-location-block' ),
$host_name,
$article_url
);</p>
<p><a href="echo esc_url( $article_url );" target="_blank" class="button button-primary">_e( 'Read More', 'ip-location-block' );</a> <button type="button" class="button ip-location-block-cache-compat-dismiss">_e( 'I Understand', 'ip-location-block' );</button></p>
</div>
}
/**
* Load the plugin text domain for translation and add body class.
*
*/
public function admin_init() {
// include drop in for admin if it exists
$dropin_path = IP_Location_Block_Util::get_dropins_storage_dir( 'drop-in-adminphp' );
if ( file_exists( $dropin_path ) ) {
include_once $dropin_path;
}
// Add the options page and menu itemadd_action( 'admin_menu', array( $this, 'setup_admin_page' ) ); // @since: 250
add_action( 'admin_post_ip_location_block', array( $this, 'admin_ajax_callback' ) ); // @since: 260
add_action( 'wp_ajax_ip_location_block', array( $this, 'admin_ajax_callback' ) ); // @since: 210
add_filter( 'wp_prepare_revision_for_js', array( $this, 'add_revision_nonce' ), 10, 3 );
add_action( 'admin_enqueue_scripts', array($this, 'enqueue_admin_assets'), 15);
if ( IP_Location_Block_Util::is_user_logged_in() ) {
add_filter( 'ip-location-block-bypass-admins', array( $this, 'verify_request' ), 10, 2 );
}
if ( is_multisite() && is_plugin_active_for_network( IP_LOCATION_BLOCK_BASE ) ) { // @since: 300
$this->is_network_admin = current_user_can( 'manage_network_options' );
add_action( 'network_admin_menu', array( $this, 'setup_admin_page' ) ); // @since: 25
add_action( 'wpmu_new_blog', array( $this, 'create_blog' ), 10, 6 ); // on creating a new blog @since MU
add_action( 'delete_blog', array( $this, 'delete_blog' ), 10, 2 ); // on deleting an old blog @since 300
}
// loads a plugin’s translated stringsload_plugin_textdomain( IP_Location_Block::PLUGIN_NAME, false, dirname( IP_LOCATION_BLOCK_BASE ) . '/languages/' );
// add webview class into body tag.
// https://stackoverflowcom/questions/37591279/detect-if-user-is-using-webview-for-android-ios-or-a-regular-browser
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) &&
( strpos( $_SERVER['HTTP_USER_AGENT'], 'Mobile/' ) !== false ) &&
( strpos( $_SERVER['HTTP_USER_AGENT'], 'Safari/' ) === false ) ) {
add_filter( 'admin_body_class', array( $this, 'add_webview_class' ) );
} // for Android
elseif ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && $_SERVER['HTTP_X_REQUESTED_WITH'] === "comcompanyapp" ) {
add_filter( 'admin_body_class', array( $this, 'add_webview_class' ) );
}
}
/**
* Whether this plugin activated by network or not.
*
*/
public function is_network_admin() {
return $this->is_network_admin;
}
/**
* Add webview class into the body.
*
* @param $classes
*
* @return string
*/
public function add_webview_class( $classes ) {
return $classes . ( $classes ? ' ' : '' ) . 'webview';
}
/**
* Add nonce when redirect into wp-admin area.
*
* @param $location
* @param $status
*
* @return string
*/
public function add_redirect_nonce( $location, $status ) {
$status = true; // default is `retrieve` a nonce
$urls = array( wp_login_url() );
// avoid multiple redirection caused by WP hide 1491
if ( is_plugin_active( 'wp-hide-security-enhancer/wp-hidephp' ) ) {
$urls[] = 'options-permalinkphp';
}
foreach ( $urls as $url ) {
if ( false !== strpos( $location, $url ) ) {
$status = false; // do not `retieve` a nonce
break;
}
}
return IP_Location_Block_Util::rebuild_nonce( $location, $status );
}
/**
* Add nonce to revision @param $revisions_data
*
* @param $revision
* @param $post
*
* @return mixed
* @since 440
*/
public function add_revision_nonce( $revisions_data, $revision, $post ) {
$revisions_data['restoreUrl'] = add_query_arg(
$nonce = IP_Location_Block::get_auth_key(),
IP_Location_Block_Util::create_nonce( $nonce ),
$revisions_data['restoreUrl']
);
return $revisions_data;
}
/**
* Verify admin screen without action instead of validating nonce.
*
* @param $queries
* @param $settings
*
* @return mixed
*/
public function verify_request( $queries, $settings ) {
// the request that is intended to show the page without any action follows authentication of coreif ( 'GET' === IP_Location_Block_Util::get_request_method() && isset( $_GET['page'] ) ) {
foreach ( array( 'action', 'task' ) as $key ) {
if ( ! empty( $_GET[ $key ] ) ) {
return $queries;
}
}
$queries[] = $_GET['page'];
}
return $queries;
}
/**
* Do some procedures when a blog is created or deleted.
*
* @param $blog_id
* @param $user_id
* @param $domain
* @param $path
* @param $site_id
* @param $meta
*/
public function create_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
defined( 'IP_LOCATION_BLOCK_DEBUG' ) and IP_LOCATION_BLOCK_DEBUG and assert( is_main_site(), 'Not main blog.' );
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-actvphp';
// get options on main blog
$settings = IP_Location_Block::get_option();
// Switch to the new blog and initializeswitch_to_blog( $blog_id );
IP_Location_Block_Activate::activate_blog();
// Copy option from main blogif ( $this->is_network_admin && $settings['network_wide'] ) {
IP_Location_Block::update_option( $settings, false );
}
// Restore the main blogrestore_current_blog();
}
public function delete_blog( $blog_id, $drop ) {
// blog is already switched to the target in wpmu_delete_blog()
$drop and IP_Location_Block_Logs::delete_tables();
}
/**
* Get the action name of ajax for nonce
*
*/
private function get_ajax_action() {
return IP_Location_Block::PLUGIN_NAME . '-ajax-action';
}
/**
* Register and enqueue plugin-specific style sheet and JavaScript.
*/
public function enqueue_admin_assets() {
if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'manage_network_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
$release = ( ! defined( 'IP_LOCATION_BLOCK_DEBUG' ) || ! IP_LOCATION_BLOCK_DEBUG );
$footer = true;
$dependency = array( 'jquery' );
$version = $release ? IP_LOCATION_BLOCK_VERSION : max(
filemtime( IP_LOCATION_BLOCK_PATH . 'admin/css/admincss' ),
filemtime( IP_LOCATION_BLOCK_PATH . 'admin/js/adminjs' )
);
switch ( $this->admin_tab ) {
case 1:
case 4:
// css and js for DataTables
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-datatables-css',
plugins_url( 'datatables/css/datatables-allmincss', __FILE__ ),
array(), IP_LOCATION_BLOCK_VERSION
);
wp_enqueue_script( IP_Location_Block::PLUGIN_NAME . '-datatables-js',
plugins_url( 'datatables/js/datatables-allminjs', __FILE__ ),
$dependency, IP_LOCATION_BLOCK_VERSION, $footer
);
if ( 4 === $this->admin_tab ) {
break;
}
case 5:
// js for google charts
wp_register_script(
$addon = IP_Location_Block::PLUGIN_NAME . '-google-chart',
apply_filters( 'google-charts', 'https://wwwgstaticcom/charts/loaderjs' ), array(), null, $footer
);
wp_enqueue_script( $addon );
break;
case 2:
// Google Charts in China
$geo = IP_Location_Block::get_geolocation();
if ( isset( $geo['code'] ) && 'CN' === $geo['code'] ) {
add_filter( 'google-charts', array( $this, 'google_charts_cn' ) );
}
// Enqueue leafletjs
wp_enqueue_style(
IP_Location_Block::PLUGIN_NAME . '-leaflet',
plugins_url( 'vendor/leaflet/leafletcss', __FILE__ ),
array(),
IP_LOCATION_BLOCK_VERSION,
'all'
);
wp_enqueue_script(
IP_Location_Block::PLUGIN_NAME . '-leaflet',
plugins_url( 'vendor/leaflet/leafletjs', __FILE__ ),
array(),
IP_LOCATION_BLOCK_VERSION,
$footer
);
wp_enqueue_script( IP_Location_Block::PLUGIN_NAME . '-whois-js',
plugins_url( $release ? 'js/whoisminjs' : 'js/whoisjs', __FILE__ ),
$dependency, IP_LOCATION_BLOCK_VERSION, $footer
);
break;
}
// css for option page
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-admin-icons',
plugins_url( $release ? 'css/admin-iconsmincss' : 'css/admin-iconscss', __FILE__ ),
array(), IP_LOCATION_BLOCK_VERSION
);
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-admin-styles',
plugins_url( $release ? 'css/adminmincss' : 'css/admincss', __FILE__ ),
array(), $version
);
// js for IP Location Block admin page
wp_register_script(
$handle = IP_Location_Block::PLUGIN_NAME . '-admin',
plugins_url( $release ? 'js/adminminjs' : 'js/adminjs', __FILE__ ),
$dependency + ( isset( $addon ) ? array( $addon ) : array() ),
$version, $footer
);
wp_localize_script( $handle,
'IP_LOCATION_BLOCK',
array(
'action' => 'ip_location_block',
'tab' => isset($_GET['page']) && 'ip-location-block' === $_GET['page'] ? $this->admin_tab : -1,
'url' => admin_url( 'admin-ajaxphp' ),
'nonce' => IP_Location_Block_Util::create_nonce( $this->get_ajax_action() ),
'native' => (bool) IP_Location_Block_Provider::is_native( $settings ),
'msg' => array(
__( 'Are you sure ?', 'ip-location-block' ),
__( 'Open a new window', 'ip-location-block' ),
__( 'Generate new link', 'ip-location-block' ),
__( 'Delete current link', 'ip-location-block' ),
__( 'Please add the following link to favorites / bookmarks in your browser : ', 'ip-location-block' ),
__( 'ajax for logged-in user', 'ip-location-block' ),
__( 'ajax for non logged-in user', 'ip-location-block' ),
__( '[Found: %d]', 'ip-location-block' ),
__( 'Find and verify `%s` on “Logs” tab.', 'ip-location-block' ),
__( 'This feature is available with HTML5 compliant browsers.', 'ip-location-block' ),
__( 'The selected row cannot be found in the table.', 'ip-location-block' ),
__( 'An error occurred while executing the ajax command `%s`.', 'ip-location-block' ),
),
'i18n' => array(
'<div class="ip-location-block-loading"></div>',
__( 'No data available in table', 'ip-location-block' ),
__( 'No matching records found', 'ip-location-block' ),
__( 'IP address', 'ip-location-block' ),
__( 'Code', 'ip-location-block' ),
__( 'City', 'ip-location-block' ),
__( 'State', 'ip-location-block' ),
__( 'ASN', 'ip-location-block' ),
__( 'Host name', 'ip-location-block' ),
__( 'Target', 'ip-location-block' ),
__( 'Failure / Total', 'ip-location-block' ),
__( 'Elapsed[sec]', 'ip-location-block' ),
__( 'Time', 'ip-location-block' ),
__( 'Result', 'ip-location-block' ),
__( 'Request', 'ip-location-block' ),
__( 'User agent', 'ip-location-block' ),
__( 'HTTP headers', 'ip-location-block' ),
__( '$_POST data', 'ip-location-block' ),
),
'interval' => self::INTERVAL_LIVE_UPDATE, // interval for live update [sec]
'timeout' => self::TIMEOUT_LIVE_UPDATE, // timeout of pausing live update [sec]
)
);
IP_Location_Block::enqueue_nonce( null );
wp_enqueue_script( $handle );
}
/**
* Google Map in China
*
* @param $url
*
* @return string
*/
public function google_charts_cn( $url ) {
return 'https://wwwgstaticcn/charts/loaderjs';
}
/**
* Add plugin meta links
*
* @param $links
* @param $file
*
* @return mixed
*/
public function add_plugin_meta_links( $links, $file ) {
if ( $file === IP_LOCATION_BLOCK_BASE ) {
array_push(
$links,
'<a href="https://githubcom/gdarko/ip-location-block" title="IP Location Block on GitHub" target=_blank>' . __( 'Contribute on GitHub', 'ip-location-block' ) . '</a>'
);
}
return $links;
}
/**
* Add settings action link to the plugins page.
*
*/
public function add_action_links( $links ) {
$settings = IP_Location_Block::get_option();
return array_merge(
array( 'settings' => '<a href="' . esc_url( add_query_arg( array( 'page' => IP_Location_Block::PLUGIN_NAME ), $this->dashboard_url( $settings['network_wide'] ) ) ) . '">' . __( 'Settings' ) . '</a>' ),
$links
);
}
/**
* Add suggest text for inclusion in the site's privacy policy. @since 496
*
* /wp-admin/toolsphp?wp-privacy-policy-guide
* https://developerwordpressorg/plugins/privacy/privacy-related-options-hooks-and-capabilities/
*/
public function add_privacy_policy() {
if ( function_exists( 'wp_add_privacy_policy_content' ) ) {
wp_add_privacy_policy_content( 'IP Location Block', __( 'suggested text.', 'ip-location-block' ) );
}
}
/**
* Show global notice.
*
*/
public function show_admin_notices() {
$key = IP_Location_Block::PLUGIN_NAME . '-notice';
if ( false !== ( $notices = get_transient( $key ) ) ) {
foreach ( $notices as $msg => $type ) {
echo "\n", '<div class="notice is-dismissible ', esc_attr( $type ), '"><p>';
if ( 'updated' === $type ) {
echo '<strong>', IP_Location_Block_Util::kses( $msg ), '</strong>';
} else {
echo '<strong>IP Location Block:</strong> ', IP_Location_Block_Util::kses( $msg );
}
echo '</p></div>', "\n";
}
// delete all admin noties
delete_transient( $key );
}
}
/**
* Add global notice.
*
*/
public static function add_admin_notice( $type, $msg ) {
$key = IP_Location_Block::PLUGIN_NAME . '-notice';
if ( false === ( $notices = get_transient( $key ) ) ) {
$notices = array();
}
// can't overwrite the existent notice
if ( ! isset( $notices[ $msg ] ) ) {
$notices[ $msg ] = $type;
set_transient( $key, $notices, MINUTE_IN_SECONDS );
}
}
/**
* Get the admin url that depends on network multisite.
*
* @param bool $network_wide
*
* @return string|void
*/
public function dashboard_url( $network_wide = false ) {
return ( $network_wide ? $this->is_network_admin : $network_wide ) ? network_admin_url( 'adminphp' ) : admin_url( 'options-generalphp' );
}
/**
* Register the administration menu into the WordPress Dashboard menu.
*
* @param $settings
*/
private function add_plugin_admin_menu( $settings ) {
// Control tab number
if ( $admin_menu = ( 'admin_menu' === current_filter() ) ) {
if ( $this->is_network_admin && $settings['network_wide'] ) {
$this->admin_tab = min( 4, max( 1, $this->admin_tab ) );
} else {
$this->admin_tab = min( 4, max( 0, $this->admin_tab ) );
}
} else {
if ( $this->is_network_admin && $settings['network_wide'] ) {
$this->admin_tab = in_array( $this->admin_tab, array( 0, 5 ), true ) ? $this->admin_tab : 0;
} else {
$this->admin_tab = 5;
}
}
if ( $admin_menu ) {
// `options-generalphp` ==> `optionsphp` ==> `settings-updated` is added as query just after settings updatedif ( ! empty( $_REQUEST['page'] ) && IP_Location_Block::PLUGIN_NAME === $_REQUEST['page'] &&
! empty( $_REQUEST['settings-updated'] ) && $this->is_network_admin && $settings['network_wide'] ) {
$this->update_multisite_settings( $settings );
wp_safe_redirect( esc_url_raw( add_query_arg(
array( 'page' => IP_Location_Block::PLUGIN_NAME ),
$this->dashboard_url( true )
) ) );
exit;
}
// Add a settings page for this plugin to the Settings menu.
$hook = add_options_page(
__( 'IP Location Block', 'ip-location-block' ),
__( 'IP Location Block', 'ip-location-block' ),
'manage_options',
IP_Location_Block::PLUGIN_NAME,
array( $this, 'display_plugin_admin_page' )
);
} elseif ( $this->is_network_admin ) {
// Add a settings page for this plugin to the Settings menu.
$hook = add_menu_page(
__( 'IP Location Block', 'ip-location-block' ),
__( 'IP Location Block', 'ip-location-block' ),
'manage_network_options',
IP_Location_Block::PLUGIN_NAME,
array( $this, 'display_plugin_admin_page' )
//, 'dashicons-admin-site' // or 'data:image/svg+xml;base64...'
);
add_submenu_page(
IP_Location_Block::PLUGIN_NAME,
__( 'IP Location Block', 'ip-location-block' ),
__( 'Sites list', 'ip-location-block' ),
'manage_network_options',
IP_Location_Block::PLUGIN_NAME . '&tab=5',
array( $this, 'display_plugin_admin_page' )
);
if ( $settings['network_wide'] ) {
add_submenu_page(
IP_Location_Block::PLUGIN_NAME,
__( 'IP Location Block', 'ip-location-block' ),
__( 'Settings', 'ip-location-block' ),
'manage_network_options',
IP_Location_Block::PLUGIN_NAME,
array( $this, 'display_plugin_admin_page' )
);
}
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-admin-icons',
plugins_url( ! defined( 'IP_LOCATION_BLOCK_DEBUG' ) || ! IP_LOCATION_BLOCK_DEBUG ?
'css/admin-iconsmincss' : 'css/admin-iconscss', __FILE__
),
array(), IP_LOCATION_BLOCK_VERSION
);
}
// If successful, load admin assets only on this pageif ( ! empty( $hook ) ) // 'admin_enqueue_scripts'
{
//add_action( "load-$hook", array( $this, 'enqueue_admin_assets' ) );
}
}
/**
* Diagnosis of admin settings.
*
* @param $settings
*/
private function diagnose_admin_screen( $settings ) {
$updating = get_transient( IP_Location_Block::CRON_NAME );
$adminurl = $this->dashboard_url( false );
$network = $this->dashboard_url( $settings['network_wide'] );
// Check version and compatibility
if ( version_compare( get_bloginfo( 'version' ), '370' ) < 0 ) {
self::add_admin_notice( 'error', __( 'You need WordPress 37+.', 'ip-location-block' ) );
}
// Check providers
$providers = IP_Location_Block_Provider::get_valid_providers( $settings, false, false, true );
if ( empty( $providers ) ) {
$this->add_admin_notice( 'error', sprintf(
__( 'You should select at least one API at <a href="%s">Geolocation API settings</a>. Otherwise <strong>you\'ll be blocked</strong> after the cache expires.', 'ip-location-block' ),
esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 4
), $network ) ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-4'
) );
} else {
$providers = IP_Location_Block_Provider::get_addons( $settings['providers'] );
$is_core_api = ! empty( $settings['providers']['IP Location Block'] );
if ( empty( $providers ) && ! $is_core_api ) {
$this->add_admin_notice( 'error', sprintf(
__( 'You should select at least one API for local database at <a href="%s">Geolocation API settings</a>. Otherwise access to the external API may slow down the site.', 'ip-location-block' ),
esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 4
), $network ) ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-4'
) );
}
}
// Check consistency of matching rule
if ( - 1 === (int) $settings['matching_rule'] ) {
if ( false !== $updating ) {
self::add_admin_notice( 'notice-warning', sprintf(
__( 'Now downloading geolocation databases in backgroundAfter a little while, please check your country code and “<strong>Matching rule</strong>” at <a href="%s">Validation rules and behavior</a>.', 'ip-location-block' ),
esc_url( add_query_arg( array( 'page' => IP_Location_Block::PLUGIN_NAME ), $network ) )
) );
} else {
self::add_admin_notice( 'error', sprintf(
__( 'The “<strong>Matching rule</strong>” is not set properlyPlease confirm it at <a href="%s">Validation rules and behavior</a>.', 'ip-location-block' ),
esc_url( add_query_arg( array( 'page' => IP_Location_Block::PLUGIN_NAME ), $network ) )
) );
}
} // Check to finish updating matching rule
elseif ( 'done' === $updating ) {
delete_transient( IP_Location_Block::CRON_NAME );
self::add_admin_notice( 'updated ', __( 'Local database and matching rule have been updated.', 'ip-location-block' ) );
}
// Check the rule contents
if ( (int) $settings['matching_rule'] >= 0 ) {
$key = '';
if ( 0 === (int) $settings['matching_rule'] ) {
$key = 'white_list';
} else if ( 1 === (int) $settings['matching_rule'] ) {
$key = 'black_list';
}
if ( isset( $settings[ $key ] ) ) {
$feature = '';
if ( strpos( $settings[ $key ], ':City:' ) !== false ) {
$feature = 'city';
} elseif ( strpos( $settings[ $key ], ':State:' ) !== false ) {
$feature = 'state';
} elseif ( strpos( $settings[ $key ], ':' ) !== false ) {
$feature = 'city';
} elseif ( strpos( $settings[ $key ], 'AS' ) !== false ) {
$feature = 'asn';
}
if ( $feature ) {
$valid_providers = IP_Location_Block_Provider::get_valid_providers( $settings, false, false, true );
foreach ( $valid_providers as $valid_provider ) {
$provider = IP_Location_Block_API::get_instance( $valid_provider, $settings );
if ( $provider && ! $provider->supports( $feature ) ) {
self::add_admin_notice( 'error', sprintf(
__( 'Looks like you are trying to utilize <strong>%s</strong> level blocking, but the provider <strong>%s</strong> does not support thatIn this case you may get invalid resultsWe strongly advise you to disable the provider <strong>%s</strong> from the settings belowFor more details see <a target="_blank" href="%s">Supported Geo-Location Rule Formats</a>.', 'ip-location-block' ),
$feature,
$valid_provider,
$valid_provider,
'https://iplocationblockcom/codex/supported-geo-location-rule-formats/'
) );
}
}
}
}
}
// Check additional blacklist / whitelist rules
if ( ! empty( $settings['extra_ips'] ) && is_array( $settings['extra_ips'] ) ) {
$asn_use = [];
$invalid = [];
$lists = [
'white_list' => __( 'Whitelist of extra IP addresses prior to country code/pattern (CIDR, ASN)', 'ip-location-block' ),
'black_list' => __( 'Blacklist of extra IP addresses prior to country code/pattern (CIDR, ASN)', 'ip-location-block' ),
];
foreach ( $lists as $list_key => $list ) {
$invalid[ $list_key ] = [];
$asn_use[ $list_key ] = [];
if ( ! empty( $settings['extra_ips'][ $list_key ] ) ) {
$values = IP_Location_Block_Util::multiexplode( array( ",", "\n" ), $settings['extra_ips'][ $list_key ] );
foreach ( $values as $i ) {
"x" = isset( "x" ) ? min( 32, max( 0, (int) "x" ) ) : 32;
$is_asn = ( ! empty( $settings['use_asn'] ) && strpos( "e", 'AS' ) !== false );
$is_ip4 = filter_var( "e", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ); // Is valid ip4 subnet or ip4.
$is_ip6 = filter_var( "e", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ); // Is valid ip6 subnet or ip6
if ( ! ( $is_asn || $is_ip4 || $is_ip6 ) ) {
$invalid[ $list_key ][] = $i;
}
if ( $is_asn ) {
$asn_use[ $list_key ][] = $i;
}
}
}
}
// Display issues related to format & collect information abount asn usage.
$lists_with_asn = [];
foreach ( $lists as $list_key => $list_name ) {
if ( ! empty( $invalid[ $list_key ] ) ) {
self::add_admin_notice( 'error', sprintf(
__( 'The option <strong>"%s"</strong> is not properly configured, it contains invalid rules: <strong>%s</strong>. For more details please check <a target="_blank" href="%s">Validation rules and behavior</a>', 'ip-location-block' ),
$list_name,
implode( ', ', $invalid[ $list_key ] ),
esc_url( 'https://iplocationblockcom/codex/validation-rules-and-behavior/#whitelistblacklist-of-extra-ip-addresses-prior-to-country-code' )
) );
}
if ( ! empty( $asn_use[ $list_key ] ) ) {
$lists_with_asn[] = $list_name;
}
}
if ( ! empty( $lists_with_asn ) ) {
// FInd providers that doesn't support ASN and are active
$_unsupported_pr = [];
$valid_providers = IP_Location_Block_Provider::get_valid_providers( $settings, false, false, true );
foreach ( $valid_providers as $valid_provider ) {
$provider = IP_Location_Block_API::get_instance( $valid_provider, $settings );
if ( $provider && ! $provider->supports( 'asn' ) ) {
$_unsupported_pr[] = $valid_provider;
}
}
if ( ! empty( $_unsupported_pr ) ) {
$message = __( 'Looks like you want to block ASN by using the <strong>%s</strong> option(s) but your current geolocation provider(s) "<strong>%s</strong>" do not support itFor more details about the supported providers please scroll down to <strong>Geolocation API settings</strong> and check with the <strong>Compare</strong> button.', 'ip-location-block' );
self::add_admin_notice( 'error', sprintf(
$message,
implode( ', ', $lists_with_asn ),
implode( ', ', $_unsupported_pr ),
) );
}
}
}
// Check self blocking (skip during updating)
if ( false === $updating && 1 === (int) $settings['validation']['login'] ) {
$instance = IP_Location_Block::get_instance();
$validate = $instance->validate_ip( 'login', $settings, true, false ); // skip authentication check
if ( $validate && isset( $validate['result'] ) ) {
switch ( $validate['result'] ) {
case 'limited':
self::add_admin_notice( 'error',
__( 'Once you logout, you will be unable to login again because the number of login attempts reaches the limit.', 'ip-location-block' ) . ' ' .
sprintf(
__( 'Please remove your IP address in “%1$sStatistics in IP address cache%2$s” on “%3$sStatistics%4$s” tab to prevent locking yourself out.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 1,
'sec' => 2
), $adminurl ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-2' ) . '">', '</a></strong>',
'<strong>', '</strong>'
)
);
break;
case 'blocked':
case 'extra':
self::add_admin_notice( 'error',
( $settings['matching_rule'] ?
__( 'Once you logout, you will be unable to login again because your country code or IP address is in the blacklist.', 'ip-location-block' ) :
__( 'Once you logout, you will be unable to login again because your country code or IP address is not in the whitelist.', 'ip-location-block' )
) . ' ' .
( 'ZZ' !== $validate['code'] ?
sprintf(
__( 'Please check your “%sValidation rules and behavior%s”.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 0
), $network ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-0' ) . '">', '</a></strong>'
) :
sprintf(
__( 'Please confirm your local geolocation database files exist at “%sLocal database settings%s” section, or remove your IP address in cache at “%sStatistics in cache%s” section.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 5
), $network ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-5' ) . '">', '</a></strong>',
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 1,
'sec' => 2
), $adminurl ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-2' ) . '">', '</a></strong>'
)
)
);
break;
}
}
}
// Check consistency of emergency login link
if ( isset( $settings['login_link'] ) && $settings['login_link']['link'] && ! IP_Location_Block_Util::verify_link( $settings['login_link']['link'], $settings['login_link']['hash'] ) ) {
self::add_admin_notice( 'error',
sprintf(
__( 'Emergency login link is outdatedPlease delete it once and generate again at “%sPlugin settings%s” sectionAlso do not forget to update favorites / bookmarks in your browser.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 7
), $network ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-7' ) . '">', '</a></strong>'
)
);
}
// Check activation of IP Geo Allow
if ( $settings['validation']['timing'] && is_plugin_active( 'ip-geo-allow/indexphp' ) ) {
self::add_admin_notice( 'error',
__( '“mu-plugins” (ip-location-block-muphp) at “Validation timing” is imcompatible with <strong>IP Geo Allow</strong>. Please select “init” action hook.', 'ip-location-block' )
);
}
}
/**
* Setup menu and option page for this plugin
*
*/
public function setup_admin_page() {
$settings = IP_Location_Block::get_option();
// Register the administration menu.
$this->add_plugin_admin_menu( $settings );
// Avoid multiple validationif ( 'GET' === IP_Location_Block_Util::get_request_method() ) {
$this->diagnose_admin_screen( $settings );
}
// Register settings page only if it is neededif ( ( isset( $_GET ['page'] ) && IP_Location_Block::PLUGIN_NAME === $_GET ['page'] ) ||
( isset( $_POST['option_page'] ) && IP_Location_Block::PLUGIN_NAME === $_POST['option_page'] ) ) {
$this->register_settings_tab();
} // Add an action link pointing to the options page. @since 027
else {
add_filter( 'plugin_row_meta', array( $this, 'add_plugin_meta_links' ), 10, 2 );
add_filter( 'plugin_action_links_' . IP_LOCATION_BLOCK_BASE, array( $this, 'add_action_links' ), 10, 1 );
}
// Register scripts for adminadd_action( 'admin_enqueue_scripts', array( 'IP_Location_Block', 'enqueue_nonce' ), 0 );
// Show admin notices at the place where it should be. @since 0250
add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );
add_action( 'network_admin_notices', array( $this, 'show_admin_notices' ) );
// Welcome screen
add_action( 'admin_notices', array( $this, 'show_intro_notice' ) );
// API key upgrade notice
add_action( 'admin_notices', array( $this, 'show_api_key_upgrade_notice' ) );
// Cache compatibility notice
add_action( 'admin_notices', array( $this, 'show_cache_compat_notice' ) );
}
/**
* Get cookie that indicates open/close section
*
*/
public function get_cookie() {
static
if ( empty( $cookie ) && ! empty( $_COOKIE[ IP_Location_Block::PLUGIN_NAME ] ) ) {
foreach ( explode( '&', $_COOKIE[ IP_Location_Block::PLUGIN_NAME ] ) as $i => $v ) {
list( $i, $v ) = explode( '=', $v );
$cookie[ $i ] = str_split( $v );
}
}
return $cookie;
}
/**
* Prints out all settings sections added to a particular settings page
*
* wp-admin/includes/templatephp @since 0270
*/
private function do_settings_sections( $page, $tab ) {
global $wp_settings_sections, $wp_settings_fields;
// target section to be opened
$target = isset( $_GET['sec'] ) ? (int) $_GET['sec'] : - 1;
if ( isset( $wp_settings_sections[ $page ] ) ) {
$index = 0; // index of fieldset
foreach ( (array) $wp_settings_sections[ $page ] as $section ) {
// TRUE if open ('o') or FALSE if close ('x')
$stat = empty( $cookie[ $tab ][ $index ] ) || 'x' !== $cookie[ $tab ][ $index ] || $index === $target;
echo "\n", '<fieldset id="', IP_Location_Block::PLUGIN_NAME, '-section-', $index, '" class="', IP_Location_Block::PLUGIN_NAME, '-field panel panel-default" data-section="', $index, '">', "\n",
'<legend class="panel-heading"><h3 class="', IP_Location_Block::PLUGIN_NAME, ( $stat ? '-dropdown' : '-dropup' ), '">',
is_array( $section['title'] ) ? $section['title'][0] . '<span class="' . IP_Location_Block::PLUGIN_NAME . '-help-link">[ ' . $section['title'][1] . ' ]</span>' : $section['title'],
'</h3></legend>', "\n", '<div class="panel-body',
( $stat ? ' ' . IP_Location_Block::PLUGIN_NAME . '-border"' : '"' ),
( $stat || ( 4 === $tab && $index ) ? '>' : ' style="display:none">' ), "\n";
if ( $section['callback'] ) {
call_user_func( $section['callback'], $section );
}
if ( isset( $wp_settings_fields,
$wp_settings_fields[ $page ],
$wp_settings_fields[ $page ][ $section['id'] ] ) ) {
echo '<table class="form-table">';
do_settings_fields( $page, $section['id'] );
echo "</table>\n";
}
echo "</div>\n</fieldset>\n";
++ $index;
}
}
}
/**
* Render the settings page for this plugin.
*
*/
public function display_plugin_admin_page() {
$tab = $this->admin_tab;
$settings = IP_Location_Block::get_option();
$title = esc_html( get_admin_page_title() );
// Target page that depends on the network multisite or notif ( 'options-generalphp' === $GLOBALS['pagenow'] ) {
$action = 'optionsphp';
unset( "d" ); // Sites list
if ( $this->is_network_admin ) {
$title .= ' <span class="ip-location-block-menu-link"> [ ';
$title .= '<a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 5
), $this->dashboard_url( true ) ) ) . '" target="_self">' . __( 'Sites list', 'ip-location-block' ) . '</a>';
if ( $settings['network_wide'] ) {
unset( "e" ); // Settings
$title .= ' / <a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0
), $this->dashboard_url( true ) ) ) . '" target="_self">' . __( 'Settings', 'ip-location-block' ) . '</a>';
}
$title .= ' ]</span>';
}
} // '/wp-admin/network/adminphp'
else {
// `editphp` is an action handler for Multisite administration dashboard.
// `editphp` ==> do action `network_admin_edit_ip-location-block` ==> `validate_network_settings()`
$action = 'editphp?action=' . IP_Location_Block::PLUGIN_NAME;
if ( $this->is_network_admin ) {
unset( "x", "o", "p", "l" ); // Statistics, Logs, Search, Attribution
$title .= ' <span class="ip-location-block-menu-link"> [ ';
$title .= __( 'Sites list', 'ip-location-block' );
if ( $settings['network_wide'] ) {
$title .= ' / ' . __( 'Settings', 'ip-location-block' );
} else {
unset( "e" ); // Settings
}
$title .= ' ]</span>';
}
}
<div class="wrap ip-location-block-wrap">
<h2>echo $title;</h2>
include(IP_LOCATION_BLOCK_PATH.'admin/includes/statusphp');
<h2 class="nav-tab-wrapper">
foreach ( $tabs as $key => $val ) {
echo '<a href="?page=', IP_Location_Block::PLUGIN_NAME, '&tab=', $key, '" class="nav-tab', ( $tab === $key ? ' nav-tab-active' : '' ), '">', $val, '</a>';
}
</h2>
<p class="ip-location-block-navi-link">
<span class="ip-location-block-toggle-sections-wrap">[ <a id="ip-location-block-toggle-sections" href="#!">_e( 'Toggle all', 'ip-location-block' );</a> ]</span>
if ( 4 === $tab ) {
<input id="ip-location-block-live-update"
type="checkbox"checked( isset( "o"[1] ) && 'o' === "o"[1] );
disabled( $settings['validation']['reclogs'] && extension_loaded( 'pdo_sqlite' ), false ); />
<label for="ip-location-block-live-update">
<dfn title="_e( 'Independent of “Privacy and record settings”, you can see all the requests validated by this plugin in almost real time.', 'ip-location-block' );">_e( 'Live update', 'ip-location-block' );</dfn>
</label>
} elseif ( 5 === $tab ) {
<input id="ip-location-block-open-new"
type="checkbox"checked( isset( "d"[1] ) && 'o' === "d"[1] ); /><label
for="ip-location-block-open-new">
<dfn title="_e( 'Open a new window on clicking the link in the chart.', 'ip-location-block' );">_e( 'Open a new window', 'ip-location-block' );</dfn>
</label>
}</p>
<form method="post" action="echo $action;"
id="echo IP_Location_Block::PLUGIN_NAME, '-', $tab;"if ( $tab ) {
echo " class=\"", IP_Location_Block::PLUGIN_NAME, "-inhibit\"";
}>
settings_fields( IP_Location_Block::PLUGIN_NAME );
$this->do_settings_sections( IP_Location_Block::PLUGIN_NAME, $tab );
if ( 0 === $tab ) {
submit_button();
} // @since 31
</form>
if ( 2 === $tab ) {
<div id="ip-location-block-apis"></div>
<div id="ip-location-block-map"></div>
<div id="ip-location-block-whois"></div>
} elseif ( 3 === $tab ) {
// show attribution (higher priority order)
$tab = array();
foreach ( IP_Location_Block_Provider::get_addons() as $provider ) {
if ( $geo = IP_Location_Block_API::get_instance( $provider, $settings ) ) {
$tab[] = $geo->get_attribution();
}
}
echo '<p>', implode( '<br />', $tab ), "</p>\n";
echo '<p>', __( 'Thanks for providing these great services for free.', 'ip-location-block' ), "<br />\n";
echo __( '(Most browsers will redirect you to each site <a href="https://iplocationblockcom/referer-checker/" title="Referer Checker">without referrer when you click the link</a>.)', 'ip-location-block' ), "</p>\n";
}
if ( defined( 'IP_LOCATION_BLOCK_DEBUG' ) && IP_LOCATION_BLOCK_DEBUG ) {
echo '<p>', get_num_queries(), ' queries. ', timer_stop( 0 ), ' seconds. ', memory_get_usage(), " bytes.</p>\n";
}
<p id="ip-location-block-back-to-top">[ <a href="#">_e( 'Back to top', 'ip-location-block' );</a> ]
</p>
</div>
}
/**
* Initializes the options page by registering the Sections and Fields.
*
*/
private function register_settings_tab() {
$files = array(
0 => 'admin/includes/tab-settingsphp',
1 => 'admin/includes/tab-statisticsphp',
4 => 'admin/includes/tab-accesslogphp',
2 => 'admin/includes/tab-geolocationphp',
3 => 'admin/includes/tab-attributionphp',
5 => 'admin/includes/tab-networkphp',
);
require_once IP_LOCATION_BLOCK_PATH . $files[ $this->admin_tab ];
IP_Location_Block_Admin_Tab::tab_setup( $this, $this->admin_tab );
}
/**
* Function that fills the field with the desired inputs as part of the larger form.
* The 'id' and 'name' should match the $id given in the add_settings_field().
*
* @param array $args ['value'] must be sanitized because it comes from external.
*/
public function callback_field( $args ) {
if ( ! empty( $args['before'] ) ) {
echo $args['before'], "\n";
} // must be sanitized at caller
// field
$id = $name = '';
if ( ! empty( $args['field'] ) ) {
$id = sprintf( '%s_%s', $args['option'], $args['field'] );
$name = sprintf( '%s[%s]', $args['option'], $args['field'] );
}
// sub field
$sub_id = $sub_name = '';
if ( ! empty( $args['sub-field'] ) ) {
$sub_id = sprintf( '_%s', $args['sub-field'] );
$sub_name = sprintf( '[%s]', $args['sub-field'] );
}
switch ( $args['type'] ) {
case 'check-provider':
<div class="ip-location-block-providers ip-location-block-providers-compact">
<table class="wp-list-table widefat striped ip-location-block-services">
<thead>
<tr>
<th scope="col" class="manage-column">_e( 'Name', 'ip-location-block' );</th>
<th scope="col" class="manage-column">_e( 'API Key', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-requests">_e( 'Free Requests', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-ipv4">_e( 'IPv4 Lookups', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-ipv6">_e( 'IPv6 Lookups', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-asn">_e( 'ASN Blocking', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-asn">_e( 'City Blocking', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-asn">_e( 'State Blocking', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-limits">_e( 'Limitations', 'ip-location-block' );</th>
<th></th>
</tr>
</thead>
<tbody id="the-list">
foreach ( $args['providers'] as $key => $val ):
$id = sprintf( "%s_providers_%s", $args['option'], $key );
$name = sprintf( '%s[providers][%s]', $args['option'], $key );
$stat = ( null === $val && ! isset( $args['value'][ $key ] ) ) ||
( false === $val && ! empty( $args['value'][ $key ] ) ) ||
( is_string( $val ) && ! empty( $args['value'][ $key ] ) );
<tr class="format-standard hentry echo 'IP Location Block' === $key ? 'highlighted' : '';">
<td>
$checked = $stat && - 1 !== (int) $val ? 'checked' : '';
$disabled = - 1 === (int) $val ? 'disabled' : '';
$cssClass = isset( $args['local'] ) && $args['local'] ? 'API-local' : 'API-remote';
echo sprintf(
'<input %s %s id="%s" type="checkbox" name="%s" value="%s" class="%s"/> %s',
esc_attr( $checked ),
esc_attr( $disabled ),
esc_attr( $id ),
esc_attr( $name ),
esc_attr( $val ),
esc_attr( $cssClass ),
IP_Location_Block_Provider::format_provider_meta( $key, 'name' )
);
</td>
<td style="padding-left: 0;padding-right: 0;">
if ( ! is_null( $val ) ) {
$value = ! empty( $args['value'][ $key ] ) ? $args['value'][ $key ] : '';
echo sprintf( '<input type="text" class="code" name="%s" value="%s" placeholder="%s"/>', esc_attr( $name ), esc_attr( $value ), __( 'API Key', 'ip-location-block' ) );
}
</td>
<td class="meta-compare meta-requests">echo IP_Location_Block_Provider::format_provider_meta( $key, 'requests' );</td>
<td class="meta-compare meta-ipv4">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( $key, 'ipv4' ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-ipv6">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( $key, 'ipv6' ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-asn">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( $key, array(
'asn',
'asn_database'
) ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-city">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( $key, array( 'city' ) ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-state">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( $key, array( 'state' ) ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-limits">echo IP_Location_Block_Provider::format_provider_meta( $key, 'limits' );</td>
<td>echo IP_Location_Block_Provider::format_provider_meta( $key, 'signup-button' );</td>
</tr>
endforeach;
</tbody>
</table>
<div class="ip-location-block-providers-actions">
<a id="ip-location-block-providers-compare-toggle" href="#"
class="button-primary">_e( 'Compare', 'ip-location-block' );</a>
</div>
</div>
break;
case
'checkboxes':
echo "\n<ul class=\"ip-location-block-list\">\n";
foreach ( $args['list'] as $key => $val ) {
<li>
<input type="checkbox" id="echo $id, $sub_id, '_', $key;"
name="echo $name, $sub_name, '[', $key, ']';" value="echo $key;"checked( is_array( $args['value'] ) ? ! empty( $args['value'][ $key ] ) : ( $key & $args['value'] ? true : false ) ); /><label
for="echo $id, $sub_id, '_', $key;">if ( isset( $args['desc'][ $key ] ) ) {
echo '<dfn title="', $args['desc'][ $key ], '">', $val, '</dfn>';
} else {
echo $val;
}</label>
</li>
}
echo "</ul>\n";
break;
case 'checkbox':
<input type="checkbox" id="echo $id, $sub_id;" name="echo $name, $sub_name;"
value="1"checked( esc_attr( $args['value'] ) );
disabled( ! empty( $args['disabled'] ), true ); /><label for="echo $id, $sub_id;">if ( isset( $args['text'] ) ) {
echo esc_attr( $args['text'] );
} elseif ( isset( $args['html'] ) ) {
echo $args['html'];
} else {
_e( 'Enable', 'ip-location-block' );
}</label>
break;
case 'select':
case 'select-text':
$desc = '';
$field_id = sprintf( '%s%s', $id, $sub_id );
$field_name = sprintf( '%s%s', $name, $sub_name );
echo sprintf( '<select id="%s" name="%s" %s>%s', esc_attr( $field_id ), esc_attr( $field_name ), isset( $args['attr'] ) ? esc_attr( $args['attr'] ) : '', PHP_EOL );
foreach ( $args['list'] as $key => $val ) {
echo "\t<option value=\"$key\"", null === $val ? ' selected disabled' : ( is_array( $args['value'] ) ? selected( in_array( $key, $args['value'] ), true, false ) : selected( $args['value'], $key, false ) );
if ( isset( $args['desc'][ $key ] ) ) {
echo ' data-desc="', $args['desc'][ $key ], '"';
$key === $args['value'] and $desc = $args['desc'][ $key ];
}
echo '>', ( null === $val ? __( 'Select one', 'ip-location-block' ) : $val ), '</option>', "\n";
}
echo "</select>\n";
if ( isset( $args['desc'] ) ) {
echo '<p class="ip-location-block-desc">', $desc, "</p>\n";
}
if ( 'select' === $args['type'] ) {
break;
}
echo "<br />\n";
$sub_id = '_' . $args['txt-field']; // possible value of 'txt-field' is 'msg'
$sub_name = '[' . $args['txt-field'] . ']';
$args['value'] = $args['text']; // should be escaped because it can contain allowed tags
case 'text':
<input type="text" class="regular-text code" id="echo $id, $sub_id;"
name="echo $name, $sub_name;" value="echo esc_attr( $args['value'] );"disabled( ! empty( $args['disabled'] ) );
if ( isset( $args['placeholder'] ) ) {
echo ' placeholder="', esc_html( $args['placeholder'] ), '"';
} />
break; // disabled @since 30
case 'textarea':
<textarea class="regular-text code" id="echo $id, $sub_id;"
name="echo $name, $sub_name;"disabled( ! empty( $args['disabled'] ) );
if ( isset( $args['placeholder'] ) ) {
echo ' placeholder="', esc_html( $args['placeholder'] ), '"';
}>echo esc_html( $args['value'] );</textarea>
break;
case 'button':
<input type="button" class="button-secondary" id="echo $id;"
value="echo esc_attr( $args['value'] );"
disabled( ! empty( $args['disabled'] ) );/>
break;
case 'html':
echo "\n", $args['value'], "\n"; // must be sanitized at caller
break;
}
if ( ! empty( $args['after'] ) ) {
echo $args['after'], "\n";
} // must be sanitized at caller
}
/**
* Sanitize options before saving them into DB.
*
* @param array $input The values to be validated.
*
* @return mixed
* @link https://codexwordpressorg/Function_Reference/sanitize_option
* @link https://codexwordpressorg/Function_Reference/sanitize_text_field
* @link https://codexwordpressorg/Plugin_API/Filter_Reference/sanitize_option_$option
* @link https://coretracwordpressorg/browser/trunk/src/wp-includes/formattingphp
* @link https://codexwordpressorg/Validating_Sanitizing_and_Escaping_User_Data
*/
public function sanitize_options( $input ) {
// setup base options
$output = IP_Location_Block::get_option();
$default = IP_Location_Block::get_default();
// Integrate posted data into current settings because it can be a part of hole data
$input = $this->array_replace_recursive(
$output = $this->preprocess_options( $output, $default ), $input
);
// restore the 'signature' that might be transformed to avoid self blocking
if ( isset( $input['signature'] ) && false === strpos( $input['signature'], ',' ) ) {
$input['signature'] = str_rot13( base64_decode( $input['signature'] ) );
}
/**
* Sanitize a string from user input
*/
foreach ( $output as $key => $val ) {
$key = sanitize_text_field( $key ); // @since 300 can't use sanitize_key() because of capital letters.
// delete old key
if ( ! array_key_exists( $key, $default ) ) {
unset( $output[ $key ] );
continue;
}
switch ( $key ) {
case 'providers':
foreach ( IP_Location_Block_Provider::get_providers() as $provider => $api ) {
// need no key
if ( null === $api ) {
if ( isset( $input[ $key ][ $provider ] ) ) {
unset( $output[ $key ][ $provider ] );
} else {
$output['providers'][ $provider ] = '';
}
} // non-commercial
elseif ( false === $api ) {
if ( isset( $input[ $key ][ $provider ] ) ) {
$output['providers'][ $provider ] = '@';
} else {
unset( $output[ $key ][ $provider ] );
}
} // need key
else {
$output[ $key ][ $provider ] =
isset( $input[ $key ][ $provider ] ) ? sanitize_text_field( $input[ $key ][ $provider ] ) : '';
}
}
break;
case 'comment':
if ( isset( $input[ $key ]['pos'] ) ) {
$output[ $key ]['pos'] = (int) $input[ $key ]['pos'];
}
if ( isset( $input[ $key ]['msg'] ) ) {
$output[ $key ]['msg'] = IP_Location_Block_Util::kses( $input[ $key ]['msg'] );
}
break;
case 'white_list':
case 'black_list':
$input_value = isset( $input[ $key ] ) ? sanitize_text_field( $input[ $key ] ) : '';
$input_parts = self::sanitize_rules($input_value);
$output[ $key ] = implode( ',', $input_parts );
break;
case 'mimetype':
if ( isset( $input[ $key ]['white_list'] ) ) { // for json file before 303
foreach ( $input[ $key ]['white_list'] as $k => $v ) {
$output[ $key ]['white_list'][ sanitize_text_field( $k ) ] = sanitize_mime_type( $v ); // @since 313
}
}
if ( isset( $input[ $key ]['black_list'] ) ) { // for json file before 303
$output[ $key ]['black_list'] = sanitize_text_field( $input[ $key ]['black_list'] );
}
if ( isset( $input[ $key ]['capability'] ) ) {
$output[ $key ]['capability'] = array_map( 'sanitize_key', explode( ',', trim( $input[ $key ]['capability'], ',' ) ) ); // @since 300
}
break;
case 'metadata':
if ( isset( $input[ $key ] ) ) {
if ( is_string( $input[ $key ]['pre_update_option'] ) ) {
$output[ $key ]['pre_update_option'] = array_map( 'sanitize_key', explode( ',', trim( $input[ $key ]['pre_update_option'], ',' ) ) ); // @since 3017
}
if ( is_string( $input[ $key ]['pre_update_site_option'] ) ) {
$output[ $key ]['pre_update_site_option'] = array_map( 'sanitize_key', explode( ',', trim( $input[ $key ]['pre_update_site_option'], ',' ) ) ); // @since 3017
}
}
break;
default: // checkbox, select, text
// single field
if ( ! is_array( $default[ $key ] ) ) {
// for checkbox
if ( is_bool( $default[ $key ] ) ) {
$output[ $key ] = ! empty( $input[ $key ] );
} // for implicit data
elseif ( isset( $input[ $key ] ) ) {
$output[ $key ] = is_int( $default[ $key ] ) ?
(int) $input[ $key ] :
IP_Location_Block_Util::kses( trim( $input[ $key ] ), false );
} // otherwise keep as it is
else {
}
} // sub field
else {
foreach ( array_keys( (array) $val ) as $sub ) {
// delete old key
if ( ! array_key_exists( $sub, $default[ $key ] ) ) {
unset( $output[ $key ][ $sub ] );
} // for checkbox
elseif ( is_bool( $default[ $key ][ $sub ] ) ) {
$output[ $key ][ $sub ] = ! empty( $input[ $key ][ $sub ] );
} // for array
elseif ( is_array( $default[ $key ][ $sub ] ) ) {
$output[ $key ][ $sub ] = empty( $input[ $key ][ $sub ] ) ?
array() : $input[ $key ][ $sub ];
} // for implicit data
elseif ( isset( $input[ $key ][ $sub ] ) ) {
// for checkboxes
if ( is_array( $input[ $key ][ $sub ] ) ) {
foreach ( $input[ $key ][ $sub ] as $k => $v ) {
$output[ $key ][ $sub ] |= $v;
}
} else {
$output[ $key ][ $sub ] = ( is_int( $default[ $key ][ $sub ] ) ?
(int) $input[ $key ][ $sub ] :
IP_Location_Block_Util::kses( trim( $input[ $key ][ $sub ] ), false )
);
}
} // otherwise keep as it is
else {
}
}
}
if($key === 'public') {
foreach(['white_list', 'black_list'] as $prop) {
$input_value = isset( $input[ $key ][ $prop ] ) ? sanitize_text_field( $input[ $key ][ $prop ] ) : '';
$input_parts = self::sanitize_rules( $input_value );
$output[ $key ][ $prop ] = implode( ',', $input_parts );
}
}
}
}
// Check and format each setting data
return $this->postprocess_options( $output, $default );
}
/**
* Sanitizes the matching rule strings
* @param $input_value
*
* @return string[]
*/
public function sanitize_rules($input_value) {
$input_parts = explode( ',', $input_value );
foreach ( $input_parts as $index => $input_part ) {
if ( ! empty( "e" ) ) {
"e" = preg_replace( '/[^A-Z,]/', '', strtoupper( "e" ) );
}
if ( ! empty( "x" ) ) {
"x" = ucwords( strtolower( "x" ) );
}
if ( ! empty( "p" ) ) {
"p" = ucwords( strtolower( "p" ) );
}
$input_parts[ $index ] = implode( ':', $rule_parts );
}
return $input_parts;
}
// Initialize not on the form (mainly unchecked checkbox)
public function preprocess_options( $output, $default ) {
// initialize checkboxes not in the form (added after 200, just in case)
foreach (
array(
'providers',
'save_statistics',
'cache_hold',
'anonymize',
'restrict_api',
'network_wide',
'clean_uninstall',
'simulate',
'use_asn',
) as $key
) {
$output[ $key ] = is_array( $default[ $key ] ) ? array() : 0;
}
// initialize checkboxes not in the form
foreach ( array( 'comment', 'login', 'admin', 'ajax', 'plugins', 'themes', 'public', 'mimetype' ) as $key ) {
$output['validation'][ $key ] = 0;
}
// initialize checkboxes not in the form
$output['mimetype']['white_list'] = array();
// keep disabled checkboxes not in the form
foreach ( array( 'admin', 'plugins', 'themes' ) as $key ) {
$output['exception'][ $key ] = array();
}
// keep disabled checkboxes not in the form
foreach (
array(
'target_pages',
'target_posts',
'target_cates',
'target_tags',
'dnslkup',
'behavior'
) as $key
) {
$output['public'][ $key ] = is_array( $default['public'][ $key ] ) ? array() : false;
}
// disabled in case IP address cache is disabled
empty( $output['cache_hold'] ) and $output['login_fails'] = - 1;
// 305 Live update
$output['live_update']['in_memory'] = 0;
// 309 Fix for `login_action`
foreach ( array( 'login', 'register', 'resetpass', 'lostpassword', 'postpass' ) as $key ) {
$output['login_action'][ $key ] = false;
}
return $output;
}
// Check and format each setting data
private function postprocess_options( $output, $default ) {
// normalize escaped char
$output ['response_msg'] = preg_replace( '/\\\\/', '', $output ['response_msg'] );
$output['public']['response_msg'] = preg_replace( '/\\\\/', '', $output['public']['response_msg'] );
$output['comment']['msg'] = preg_replace( '/\\\\/', '', $output['comment']['msg'] );
// sanitize proxy
$output['validation']['proxy'] = implode( ',', $this->trim(
preg_replace( '/[^\w,]/', '', strtoupper( $output['validation']['proxy'] ) )
) );
// sanitize and format ip address (text area)
$key = array( '/[^\w\n\.\/,:]/', '/([\s,])+/', '/(?:^,|,$)/' );
$val = array( '', '$1', '' );
$output['extra_ips']['white_list'] = preg_replace( $key, $val, trim( $output['extra_ips']['white_list'] ) );
$output['extra_ips']['black_list'] = preg_replace( $key, $val, trim( $output['extra_ips']['black_list'] ) );
// format and reject invalid words which potentially blocks itself (text area)
array_shift( $key );
array_shift( $val );
$output['signature'] = preg_replace( $key, $val, trim( $output['signature'] ) );
$output['signature'] = implode( ',', $this->trim( $output['signature'] ) );
// 303 trim extra space and comma
$output['mimetype']['black_list'] = preg_replace( $key, $val, trim( $output['mimetype']['black_list'] ) );
$output['mimetype']['black_list'] = implode( ',', $this->trim( $output['mimetype']['black_list'] ) );
// 300 convert country code to upper case, remove redundant spaces
$output['public']['ua_list'] = preg_replace( $key, $val, trim( $output['public']['ua_list'] ) );
$output['public']['ua_list'] = preg_replace( '/([:#]) *([!]+) *([^ ]+) *([,\n]+)/', '$1$2$3$4', $output['public']['ua_list'] );
$output['public']['ua_list'] = preg_replace_callback( '/[:#]([\w:]+)/', array(
$this,
'strtoupper'
), $output['public']['ua_list'] );
// 300 public : convert country code to upper case
foreach ( array( 'white_list', 'black_list' ) as $key ) {
if( strpos($output['public'][ $key ], ':') === false ) {
$output['public'][ $key ] = strtoupper( preg_replace( '/\s/', '', $output['public'][ $key ] ) );
}
// 304 extra_ips : convert AS number to upper case
$output['extra_ips'][ $key ] = strtoupper( $output['extra_ips'][ $key ] );
}
// 225 exception : convert associative array to simple array
foreach ( array( 'plugins', 'themes' ) as $key ) {
$output['exception'][ $key ] = array_keys( $output['exception'][ $key ] );
}
// 300 - 303 exception : trim extra space and comma
foreach ( array( 'admin', 'public', 'includes', 'uploads', 'languages', 'restapi' ) as $key ) {
if ( empty( $output['exception'][ $key ] ) ) {
$output['exception'][ $key ] = $default['exception'][ $key ];
} else {
$output['exception'][ $key ] = ( is_array( $output['exception'][ $key ] ) ?
$output['exception'][ $key ] : $this->trim( $output['exception'][ $key ] ) );
}
}
if ( isset( $output['use_asn'] ) && (int) $output['use_asn'] > 0 ) {
// If provider supports asn database, then trigger downloading databases.
$supporting = 0;
$providers = IP_Location_Block_Provider::get_providers();
foreach ( $providers as $key => $provider ) {
if ( IP_Location_Block_Provider::supports( $key, 'asn_database' ) || IP_Location_Block_Provider::supports( $key, 'asn' ) ) {
$supporting ++;
}
}
if ( $supporting ) {
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-cronphp';
add_action( 'ip-location-block-settings-updated', array(
'IP_Location_Block_Cron',
'start_update_db'
), 10, 2 );
}
} else {
// If asn databases doesn't exist but path is specified, clear the pathrequire_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-filephp';
$filesystem = IP_Location_Block_FS::init( __FUNCTION__ );
$providers = IP_Location_Block_Provider::get_providers();
foreach ( $providers as $key => $provider ) {
if ( ! isset( $output[ $key ] ) ) {
continue;
}
if ( empty( $output[ $key ]['asn_path'] ) ) {
$output[ $key ]['asn_path'] = null;
} else {
if ( ! $filesystem->exists( $output[ $key ]['asn_path'] ) ) {
$output[ $key ]['asn_path'] = null;
}
}
}
}
// cron event
$key = wp_next_scheduled( IP_Location_Block::CRON_NAME, array( false ) );
if ( $output['update']['auto'] && ! $key ) {
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-cronphp';
IP_Location_Block_Cron::start_update_db( $output, false );
} elseif ( ! $output['update']['auto'] && $key ) {
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-cronphp';
IP_Location_Block_Cron::stop_update_db();
}
// expiration time [days]
$output['validation']['explogs'] = min( 365, max( 1, (int) $output['validation']['explogs'] ) );
return $output;
}
/**
* A fallback function of array_replace_recursive() before PHP 53.
*
* @link https://phpnet/manual/en/functionarray-replace-recursivephp#92574
* @link https://phpnet/manual/en/functionarray-replace-recursivephp#109390
*/
public function array_replace_recursive() {
if ( function_exists( 'array_replace_recursive' ) ) {
return call_user_func_array( 'array_replace_recursive', func_get_args() );
} else {
foreach ( array_slice( func_get_args(), 1 ) as $replacements ) {
$bref_stack = array( &$base );
$head_stack = array( $replacements );
do {
end( $bref_stack );
$bref = &$bref_stack[ key( $bref_stack ) ];
$head = array_pop( $head_stack );
unset( $bref_stack[ key( $bref_stack ) ] );
foreach ( array_keys( $head ) as $key ) {
if ( isset( $key, $bref, $bref[ $key ], $head[ $key ] ) && is_array( $bref[ $key ] ) && is_array( $head[ $key ] ) ) {
$bref_stack[] = &$bref[ $key ];
$head_stack[] = $head [ $key ];
} else {
$bref[ $key ] = $head [ $key ];
}
}
} while ( count( $head_stack ) );
}
return $base;
}
}
// Callback for preg_replace_callback()
public function strtoupper( $matches ) {
return filter_var( "x", FILTER_VALIDATE_IP ) ? "e" : strtoupper( "e" );
}
// Trim extra space and comma avoiding invalid signature which potentially blocks itself
private function trim( $text ) {
$path = IP_Location_Block::get_wp_path();
$ret = array();
foreach ( explode( ',', $text ) as $val ) {
$val = trim( $val );
if ( $val && false === stripos( $path['admin'], $val ) ) {
$ret[] = $val;
}
}
return $ret;
}
/**
* Check admin post
*
*/
private function check_admin_post( $ajax = false ) {
if ( $ajax ) {
$nonce = IP_Location_Block_Util::verify_nonce( IP_Location_Block_Util::retrieve_nonce( 'nonce' ), $this->get_ajax_action() );
} else {
$nonce = check_admin_referer( 'ip-location-block-options' );
} // a postfix '-options' is added at settings_fields().
$settings = IP_Location_Block::get_option();
if ( ( $ajax and $settings['validation']['ajax'] & 2 ) ||
( ! $ajax and $settings['validation']['admin'] & 2 ) ) {
$action = IP_Location_Block::get_auth_key();
$nonce &= IP_Location_Block_Util::verify_nonce( IP_Location_Block_Util::retrieve_nonce( $action ), $action );
}
if ( ! $nonce || ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'manage_network_options' ) ) ) {
status_header( 403 );
wp_die(
__( 'You do not have sufficient permissions to access this page.' ), '',
array( 'response' => 403, 'back_link' => true )
);
}
}
/**
* Validate settings and configure some features.
*
* @note: This function is triggered when update_option() is executed.
*/
public function validate_settings( $input = array() ) {
// must check that the user has the required capability
$this->check_admin_post( false );
// validate setting options
$options = $this->sanitize_options( $input );
// additional configuration
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-optsphp';
$file = IP_Location_Block_Opts::setup_validation_timing( $options );
if ( is_wp_error( $file ) ) {
$options['validation']['timing'] = 0;
self::add_admin_notice( 'error', $file->get_error_message() );
}
// Force to finish update matching rule
delete_transient( IP_Location_Block::CRON_NAME );
// start to update databases immediately
do_action( 'ip-location-block-settings-updated', $options, true );
return $options;
}
/**
* Validate settings and configure some features for network multisite.
*
* @see https://vedovininet/2015/10/using-the-wordpress-settings-api-with-network-admin-pages/
*/
public function validate_network_settings() {
// Must check that the user has the required capability
$this->check_admin_post( false );
// The list of registered options (IP_Location_Block::OPTION_NAME).
global $new_whitelist_options;
$options = $new_whitelist_options[ IP_Location_Block::PLUGIN_NAME ];
// Go through the posted data and save the targetted optionsforeach ( $options as $option ) {
if ( isset( $_POST[ $option ] ) ) {
$this->update_multisite_settings( $_POST[ $option ] );
}
}
// Register a settings error to be displayed to the user
self::add_admin_notice( 'updated', __( 'Settings saved.' ) );
// Redirect in order to back to the settings pagewp_redirect( esc_url_raw(
add_query_arg(
array( 'page' => IP_Location_Block::PLUGIN_NAME ),
$this->dashboard_url( ! empty( $_POST[ $option ]['network_wide'] ) )
)
) );
exit;
}
/**
* Update option in all blogs.
*
* @note: This function triggers `validate_settings()` on register_setting() in wp-include/optionphp.
*/
public function update_multisite_settings( $settings ) {
global $wpdb;
$blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" );
$ret = true;
foreach ( $blog_ids as $id ) {
switch_to_blog( $id );
$map = IP_Location_Block::get_option( false );
$ret &= IP_Location_Block::update_option( $settings, false );
restore_current_blog();
}
return $ret;
}
/**
* Analyze entries in "Validation logs"
*
* @param array $logs An array including each entry where:
* Array (
* [0 DB row number] => 154
* [1 Target ] => comment
* [2 Time ] => 1534580897
* [3 IP address ] => 102177147.***
* [4 Country code ] => ZA
* [5 Result ] => blocked
* [6 AS number ] => AS328239
* [7 Request ] => ",":/wp-comments-postphp
* [8 User agent ] => Mozilla/50 (Macintosh; Intel Mac OS X 10_13_6) ...
* [9 HTTP headers ] => HTTP_ORIGIN=http://localhost,HTTP_X_FORWARDED_FOR=102177147.***
* [10 $_POST data ] => comment=Hello.,author,email,url,comment_post_ID,comment_parent
* )
* And put a mark at "Target"
* ¹¹: Passed in Whitelist
* ¹²: Passed in Blacklist
* ¹³: Passed not in list
* ²¹: Blocked in Whitelist
* ²²: Blocked in Blacklist
* ²³: Blocked not in list
*
* @return array
*/
public function filter_logs( $logs ) {
$settings = IP_Location_Block::get_option();
// White/Black list for back-end
$white_backend = $settings['white_list'];
$black_backend = $settings['black_list'];
// White/Black list for front-end
if ( $settings['public']['matching_rule'] < 0 ) {
// Follow "Validation rule settings"
$white_frontend = $white_backend;
$black_frontend = $black_backend;
} else {
// Whitelist or Blacklist for "Public facing pages"
$white_frontend = $settings['public']['white_list'];
$black_frontend = $settings['public']['black_list'];
}
foreach ( $logs as $key => $log ) {
// Passed or Blocked
$mark = IP_Location_Block::is_passed( "d" ) ? '¹' : '²';
// Whitelisted, Blacklisted or N/A
if ( 'public' === "x" ) {
$mark .= IP_Location_Block::is_listed( "o", $white_frontend ) ? '¹' : (
IP_Location_Block::is_listed( "o", $black_frontend ) ? '²' : '³' );
} else {
$mark .= IP_Location_Block::is_listed( "o", $white_backend ) ? '¹' : (
IP_Location_Block::is_listed( "o", $black_backend ) ? '²' : '³' );
}
// Put a mark at "Target"
$logs[ $key ][1] .= $mark;
}
return $logs;
}
/**
* Register UI "Preset filters" at "Search in logs"
*
* @param array $filters An empty array by default.
*
* @return array $filters The array of paired with 'title' and 'value'.
*/
public function preset_filters( $filters = array() ) {
return array(
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-happy" > </span>' . __( '<span title="Show only passed entries whose country codes are in Whitelist.">Passed in Whitelist</span>', 'ip-location-block' ),
'value' => '¹¹'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-grin2" > </span>' . __( '<span title="Show only passed entries whose country codes are in Blacklist.">Passed in Blacklist</span>', 'ip-location-block' ),
'value' => '¹²'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-cool" > </span>' . __( '<span title="Show only passed entries whose country codes are not in either list.">Passed not in List</span>', 'ip-location-block' ),
'value' => '¹³'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-confused" > </span>' . __( '<span title="Show only blocked entries whose country codes are in Whitelist.">Blocked in Whitelist</span>', 'ip-location-block' ),
'value' => '²¹'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-confused2"> </span>' . __( '<span title="Show only blocked entries whose country codes are in Blacklist.">Blocked in Blacklist</span>', 'ip-location-block' ),
'value' => '²²'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-crying" > </span>' . __( '<span title="Show only blocked entries whose country codes are not in either list.">Blocked not in List</span>', 'ip-location-block' ),
'value' => '²³'
),
);
}
/**
* Ajax callback function
*
* @link https://codexwordpressorg/AJAX_in_Plugins
* @link https://codexwordpressorg/Function_Reference/check_ajax_referer
* @link https://coretracwordpressorg/browser/trunk/wp-admin/admin-ajaxphp
*/
public function admin_ajax_callback() {
require_once IP_LOCATION_BLOCK_PATH . 'admin/includes/class-admin-ajaxphp';
// Check request origin, nonce, capability.
$this->check_admin_post( true );
$services = array();
if ( ! empty( $_POST['which'] ) && is_array( $_POST['which'] ) ) {
foreach ( $_POST['which'] as $key => $value ) {
$services[ $key ] = sanitize_text_field( $value );
}
}
// `$which` and `$cmd` should be restricted by whitelist in each function
$settings = IP_Location_Block::get_option();
$which = isset( $_POST['which'] ) ? $services : array();
$cmd = isset( $_POST['cmd'] ) ? sanitize_text_field( $_POST['cmd'] ) : null;
switch ( $cmd ) {
case 'download':
$res = IP_Location_Block::get_instance();
$res = $res->exec_update_db();
break;
case 'search': // Get geolocation by IP
$res = array();
foreach ( (array) $which as $cmd ) {
$res[ $cmd ] = IP_Location_Block_Admin_Ajax::search_ip( $cmd );
}
break;
case 'scan-code': // Fetch providers to get country code
$res = IP_Location_Block_Admin_Ajax::scan_country( $which );
break;
case 'clear-statistics': // Set default values
IP_Location_Block_Logs::clear_stat();
$res = array(
'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME,
'tab' => 'tab=1'
);
break;
case 'clear-cache': // Delete cache of IP address
IP_Location_Block_API_Cache::clear_cache();
$res = array(
'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME,
'tab' => 'tab=1'
);
break;
case 'clear-logs': // Delete logs in MySQL DB
IP_Location_Block_Logs::clear_logs( $which );
$res = array(
'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME,
'tab' => 'tab=4'
);
break;
case 'export-logs':// Export logs from MySQL DB
IP_Location_Block_Admin_Ajax::export_logs( $which );
break;
case 'restore-logs': // Get logs from MySQL DB
has_filter( $cmd = 'ip-location-block-logs' ) or add_filter( $cmd, array(
$this,
'filter_logs'
) );
$res = IP_Location_Block_Admin_Ajax::restore_logs( $which );
break;
case 'live-start': // Restore live log
has_filter( $cmd = 'ip-location-block-logs' ) or add_filter( $cmd, array(
$this,
'filter_logs'
) );
if ( is_wp_error( $res = IP_Location_Block_Admin_Ajax::restore_live_log( $which, $settings ) ) ) {
$res = array( 'error' => $res->get_error_message() );
}
break;
case 'live-pause': // Pause live log
if ( ! is_wp_error( $res = IP_Location_Block_Admin_Ajax::catch_live_log() ) ) {
$res = array( 'data' => array() );
} else {
$res = array( 'error' => $res->get_error_message() );
}
break;
case 'live-stop': // Stop live log
if ( ! is_wp_error( $res = IP_Location_Block_Admin_Ajax::release_live_log() ) ) {
$res = array( 'data' => array() );
} else {
$res = array( 'error' => $res->get_error_message() );
}
break;
case 'reset-live': // Reset data source of live log
$res = IP_Location_Block_Admin_Ajax::reset_live_log();
break;
case 'validate': // Validate settings
IP_Location_Block_Admin_Ajax::validate_settings( $this );
break;
case 'import-default': // Import initial settings
$res = IP_Location_Block_Admin_Ajax::settings_to_json( IP_Location_Block::get_default() );
break;
case 'import-preferred': // Import preference
$res = IP_Location_Block_Admin_Ajax::preferred_to_json();
break;
case 'generate-link': // Generate new link
$res = array( 'link' => IP_Location_Block_Util::generate_link( $this ) );
break;
case 'delete-link': // Delete existing link
IP_Location_Block_Util::delete_link( $this );
$res = __( 'Done.' );
break;
case 'show-info': // Show system and debug information
$res = IP_Location_Block_Admin_Ajax::get_wp_info();
break;
case 'get-actions': // Get all the ajax/post actions
$res = IP_Location_Block_Util::get_registered_actions( true, $settings );
break;
case 'export-cache': // Restore cache from database and format for DataTables
IP_Location_Block_Admin_Ajax::export_cache( $settings['anonymize'] );
break;
case 'restore-cache': // Restore cache from database and format for DataTables
$res = IP_Location_Block_Admin_Ajax::restore_cache( $settings['anonymize'] );
break;
case 'bulk-action-remove': // Delete specified IP addresses from cache
$res = IP_Location_Block_Logs::delete_cache_entry( $which['IP'] );
break;
case 'bulk-action-ip-erase':
$res = IP_Location_Block_Logs::delete_logs_entry( $which['IP'] );
break;
case 'bulk-action-ip-white':
case 'bulk-action-ip-black':
case 'bulk-action-as-white':
case 'bulk-action-as-black':
// Bulk actions for registration of settings
$src = ( false !== strpos( $cmd, '-ip-' ) ? 'IP' : 'AS' );
$dst = ( false !== strpos( $cmd, '-white' ) ? 'white_list' : 'black_list' );
if ( empty( $which[ $src ] ) ) {
$res = array( 'error' => sprintf( __( 'An error occurred while executing the ajax command `%s`.', 'ip-location-block' ), $cmd ) );
break;
}
foreach ( array_unique( (array) $which[ $src ] ) as $val ) {
// replace anonymized IP address with CIDR (IPv4:256, IPv6:4096)
$val = preg_replace(
array( '/\.\*\*\*$/', '/:\w*\*\*\*$/', '/(::.*)::\/116$/' ),
array( '.0/24', '::/116', '$1/116' ),
trim( $val )
);
if ( ( filter_var( preg_replace( '/\/\d+$/', '', $val ), FILTER_VALIDATE_IP ) || preg_match( '/^AS\d+$/', $val ) ) &&
( false === strpos( $settings['extra_ips'][ $dst ], $val ) ) ) {
$settings['extra_ips'][ $dst ] .= "\n" . $val;
}
}
if ( $this->is_network_admin && $settings['network_wide'] ) {
$this->update_multisite_settings( $settings );
} else {
IP_Location_Block::update_option( $settings );
}
$res = array( 'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME );
break;
case 'restore-network': // Restore blocked per target in logs
$res = IP_Location_Block_Admin_Ajax::restore_network( $which, (int) $_POST['offset'], (int) $_POST['length'], false );
break;
case 'find-admin':
case 'find-plugins':
case 'find-themes':
// Get slug in blocked requests for exceptions
$res = IP_Location_Block_Admin_Ajax::find_exceptions( $cmd );
break;
case 'diag-tables': // Check database tables
IP_Location_Block_Logs::diag_tables() or IP_Location_Block_Logs::create_tables();
$res = array( 'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME );
break;
case 'migrate-from-legacy':
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-optsphp';
$settings = IP_Location_Block_Opts::get_legacy_settings();
if ( empty( $settings ) ) {
$res = array(
'success' => false,
'message' => __( 'No previous settings found.', 'ip-location-block' ),
);
} else {
$settings['version'] = IP_LOCATION_BLOCK_VERSION;
$settings['migrated_from_legacy'] = true;
IP_Location_Block::update_option( $settings );
$res = array(
'success' => true,
'message' => __( 'Migration successfulThis page will be reloaded now...', 'ip-location-block' ),
);
}
break;
case 'dismiss-notice':
$notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( $_POST['notice_id'] ) : '';
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-optsphp';
$settings = IP_Location_Block::get_option();
$dismissed = false;
if ( 'welcome' === $notice_id ) {
$settings['welcome'] = true;
$dismissed = true;
IP_Location_Block::update_option( $settings );
}
if ( 'cache_compat' === $notice_id ) {
$settings['cache_compat_dismissed'] = true;
$dismissed = true;
IP_Location_Block::update_option( $settings );
}
$res = array(
'success' => true,
'message' => $dismissed ? __( 'Notice dismissed.', 'ip-location-block' ) : __( 'Could not find notice to dismiss.', 'ip-location-block' ),
);
break;
}
if ( isset( $res ) ) // wp_send_json_{success,error}() @since 350
{
wp_send_json( $res );
} // @since 350
die(); // End of ajax
}
}
/**
* IP Location Block - Admin class
*
* @package IP_Location_Block
* @author Darko Gjorgjijoski <dg@darkogcom>
* @license GPL-30
* @link https://iplocationblockcom/
* @copyright 2021 darkog
* @copyright 2013-2019 tokkonopapa
*/
class IP_Location_Block_Admin {
/**
* Constants for admin class
*
*/
const INTERVAL_LIVE_UPDATE = 5; // interval for live update [sec]
const TIMEOUT_LIVE_UPDATE = 60; // timeout of pausing live update [sec]
/**
* Globals in this class
*
*/
private static $instance = null;
private $is_network_admin = false;
private $admin_tab = 0;
/**
* Initialize the plugin by loading admin scripts & styles
* and adding a settings page and menu.
*/
private function __construct() {
// Control tab number
if ( isset( $_REQUEST['page'] ) && 'ip-location-block' === $_REQUEST['page'] ) {
$this->admin_tab = isset( $_REQUEST['tab'] ) ? intval( $_REQUEST['tab'] ) : 0;
} else {
$this->admin_tab = - 1;
}
// Load plugin text domain and add body class
add_action( 'init', array( $this, 'admin_init' ) );
// Add suggest text for inclusion in the site's privacy policy. @since 496
// add_action( 'admin_init', array( $this, 'add_privacy_policy' ) );
// Setup a nonce to validate authenticationadd_filter( 'wp_redirect', array( $this, 'add_redirect_nonce' ), 10, 2 ); // @since 0210
}
/**
* Return an instance of this class.
*
*/
public static function get_instance() {
return self::$instance ? self::$instance : ( self::$instance = new self );
}
/**
* Print admin notice welcome screen
* @return void
*/
public function show_intro_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
if ( ! isset( $settings['welcome'] ) || ! $settings['welcome'] ) {
ob_start();
echo '<div class="notice notice-info is-dismissible ip-location-block-notice-intro" data-notice="welcome">';
include( dirname( __FILE__ ) . '/includes/welcomephp' );
echo '</div>';
$message = ob_get_clean();
echo $message;
}
}
/**
* Print admin notice for API key upgrade requirement
* @return void
*/
public function show_api_key_upgrade_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
// Check if we've already marked this as completed (user upgraded or dismissed)
if ( isset( $settings['api_key_upgraded'] ) && $settings['api_key_upgraded'] ) {
return;
}
// Check if IP Location Block provider is being used
$providers = IP_Location_Block_Provider::get_valid_providers( $settings );
$uses_api = in_array( 'IP Location Block', $providers );
if ( ! $uses_api ) {
return;
}
// Get API key
$api_key = ! empty( $settings['providers']['IP Location Block'] ) ? $settings['providers']['IP Location Block'] : '';
if ( empty( $api_key ) ) {
return;
}
// Check quota to see if upgrade is required
$quota = IP_Location_Block_Provider::get_native_quota( $api_key );
// If API key needs upgrade, show the notice
if ( isset( $quota['name'] ) && $quota['name'] === 'requires-api-key-upgrade' ) {
$upgrade_url = 'https://appiplocationblockcom/upgrade-api-key?api_key=' . urlencode( $api_key );
ob_start();
<div class="notice notice-warning ip-location-block-notice-api-key-upgrade">
<p>
<strong>_e( 'IP Location Block: API Key Upgrade Required', 'ip-location-block' );</strong>
</p>
<p>
_e( 'Your API key needs to be upgraded due to security improvementsThis is a one-time process and will only take a moment.', 'ip-location-block' );
</p>
<p>
<a href="echo esc_url( $upgrade_url );" class="button button-primary" target="_blank">
_e( 'Upgrade API Key Now', 'ip-location-block' );
</a>
<a href="https://iplocationblockcom/api-platform-upgrade/" class="button button-secondary" target="_blank">
_e( 'Learn More', 'ip-location-block' );
</a>
</p>
</div>
echo ob_get_clean();
} elseif ( isset( $quota['name'] ) && $quota['name'] !== 'requires-api-key-upgrade' ) {
// API key is valid and doesn't need upgrade, mark as completed so we don't check again
$settings['api_key_upgraded'] = true;
IP_Location_Block::update_option( $settings );
}
}
/**
* Show admin notice when server-level caching conflicts with public page validation.
*/
public function show_cache_compat_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
if ( ! empty( $settings['cache_compat_dismissed'] ) ) {
return;
}
if ( ! ( 1 & $settings['validation']['public'] ) ) {
return;
}
// Detect hosting environment
if ( function_exists( 'is_wpe' ) && is_wpe() === '1' ) {
'Kinsta' = 'WP Engine';
$article_url = 'https://iplocationblockcom/codex/compatibility-with-wpengine/';
} elseif ( isset( $_SERVER['KINSTA_CACHE_ZONE'] ) ) {
$article_url = 'https://iplocationblockcom/codex/compatibility-with-kinsta/';
} else {
return;
}
<div class="notice notice-warning ip-location-block-notice-cache-compat" data-notice="cache_compat">
<p><strong>_e( 'IP Location Block: Full-Page Cache Conflict', 'ip-location-block' );</strong></p>
<p>printf(
__( 'Your site is hosted on <strong>%1$s</strong>, which uses server-level page caching that runs before PHPWhen "Front-end target settings" validation is enabled, cached pages may be served to all visitors without geolocation checks. <a href="%2$s" target="_blank">Learn how to configure %1$s for compatibility</a>.', 'ip-location-block' ),
'Kinsta',
$article_url
);</p>
<p><a href="echo esc_url( $article_url );" target="_blank" class="button button-primary">_e( 'Read More', 'ip-location-block' );</a> <button type="button" class="button ip-location-block-cache-compat-dismiss">_e( 'I Understand', 'ip-location-block' );</button></p>
</div>
}
/**
* Load the plugin text domain for translation and add body class.
*
*/
public function admin_init() {
// include drop in for admin if it exists
$dropin_path = IP_Location_Block_Util::get_dropins_storage_dir( 'drop-in-adminphp' );
if ( file_exists( $dropin_path ) ) {
include_once $dropin_path;
}
// Add the options page and menu itemadd_action( 'admin_menu', array( $this, 'setup_admin_page' ) ); // @since: 250
add_action( 'admin_post_ip_location_block', array( $this, 'admin_ajax_callback' ) ); // @since: 260
add_action( 'wp_ajax_ip_location_block', array( $this, 'admin_ajax_callback' ) ); // @since: 210
add_filter( 'wp_prepare_revision_for_js', array( $this, 'add_revision_nonce' ), 10, 3 );
add_action( 'admin_enqueue_scripts', array($this, 'enqueue_admin_assets'), 15);
if ( IP_Location_Block_Util::is_user_logged_in() ) {
add_filter( 'ip-location-block-bypass-admins', array( $this, 'verify_request' ), 10, 2 );
}
if ( is_multisite() && is_plugin_active_for_network( IP_LOCATION_BLOCK_BASE ) ) { // @since: 300
$this->is_network_admin = current_user_can( 'manage_network_options' );
add_action( 'network_admin_menu', array( $this, 'setup_admin_page' ) ); // @since: 25
add_action( 'wpmu_new_blog', array( $this, 'create_blog' ), 10, 6 ); // on creating a new blog @since MU
add_action( 'delete_blog', array( $this, 'delete_blog' ), 10, 2 ); // on deleting an old blog @since 300
}
// loads a plugin’s translated stringsload_plugin_textdomain( IP_Location_Block::PLUGIN_NAME, false, dirname( IP_LOCATION_BLOCK_BASE ) . '/languages/' );
// add webview class into body tag.
// https://stackoverflowcom/questions/37591279/detect-if-user-is-using-webview-for-android-ios-or-a-regular-browser
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) &&
( strpos( $_SERVER['HTTP_USER_AGENT'], 'Mobile/' ) !== false ) &&
( strpos( $_SERVER['HTTP_USER_AGENT'], 'Safari/' ) === false ) ) {
add_filter( 'admin_body_class', array( $this, 'add_webview_class' ) );
} // for Android
elseif ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && $_SERVER['HTTP_X_REQUESTED_WITH'] === "comcompanyapp" ) {
add_filter( 'admin_body_class', array( $this, 'add_webview_class' ) );
}
}
/**
* Whether this plugin activated by network or not.
*
*/
public function is_network_admin() {
return $this->is_network_admin;
}
/**
* Add webview class into the body.
*
* @param $classes
*
* @return string
*/
public function add_webview_class( $classes ) {
return $classes . ( $classes ? ' ' : '' ) . 'webview';
}
/**
* Add nonce when redirect into wp-admin area.
*
* @param $location
* @param $status
*
* @return string
*/
public function add_redirect_nonce( $location, $status ) {
$status = true; // default is `retrieve` a nonce
$urls = array( wp_login_url() );
// avoid multiple redirection caused by WP hide 1491
if ( is_plugin_active( 'wp-hide-security-enhancer/wp-hidephp' ) ) {
$urls[] = 'options-permalinkphp';
}
foreach ( $urls as $url ) {
if ( false !== strpos( $location, $url ) ) {
$status = false; // do not `retieve` a nonce
break;
}
}
return IP_Location_Block_Util::rebuild_nonce( $location, $status );
}
/**
* Add nonce to revision @param $revisions_data
*
* @param $revision
* @param $post
*
* @return mixed
* @since 440
*/
public function add_revision_nonce( $revisions_data, $revision, $post ) {
$revisions_data['restoreUrl'] = add_query_arg(
$nonce = IP_Location_Block::get_auth_key(),
IP_Location_Block_Util::create_nonce( $nonce ),
$revisions_data['restoreUrl']
);
return $revisions_data;
}
/**
* Verify admin screen without action instead of validating nonce.
*
* @param $queries
* @param $settings
*
* @return mixed
*/
public function verify_request( $queries, $settings ) {
// the request that is intended to show the page without any action follows authentication of coreif ( 'GET' === IP_Location_Block_Util::get_request_method() && isset( $_GET['page'] ) ) {
foreach ( array( 'action', 'task' ) as 'white_list' ) {
if ( ! empty( $_GET[ 'white_list' ] ) ) {
return $queries;
}
}
$queries[] = $_GET['page'];
}
return $queries;
}
/**
* Do some procedures when a blog is created or deleted.
*
* @param $blog_id
* @param $user_id
* @param $domain
* @param $path
* @param $site_id
* @param $meta
*/
public function create_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
defined( 'IP_LOCATION_BLOCK_DEBUG' ) and IP_LOCATION_BLOCK_DEBUG and assert( is_main_site(), 'Not main blog.' );
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-actvphp';
// get options on main blog
$settings = IP_Location_Block::get_option();
// Switch to the new blog and initializeswitch_to_blog( $blog_id );
IP_Location_Block_Activate::activate_blog();
// Copy option from main blogif ( $this->is_network_admin && $settings['network_wide'] ) {
IP_Location_Block::update_option( $settings, false );
}
// Restore the main blogrestore_current_blog();
}
public function delete_blog( $blog_id, $drop ) {
// blog is already switched to the target in wpmu_delete_blog()
$drop and IP_Location_Block_Logs::delete_tables();
}
/**
* Get the action name of ajax for nonce
*
*/
private function get_ajax_action() {
return IP_Location_Block::PLUGIN_NAME . '-ajax-action';
}
/**
* Register and enqueue plugin-specific style sheet and JavaScript.
*/
public function enqueue_admin_assets() {
if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'manage_network_options' ) ) {
return;
}
$settings = IP_Location_Block::get_option();
$release = ( ! defined( 'IP_LOCATION_BLOCK_DEBUG' ) || ! IP_LOCATION_BLOCK_DEBUG );
$footer = true;
$dependency = array( 'jquery' );
$version = $release ? IP_LOCATION_BLOCK_VERSION : max(
filemtime( IP_LOCATION_BLOCK_PATH . 'admin/css/admincss' ),
filemtime( IP_LOCATION_BLOCK_PATH . 'admin/js/adminjs' )
);
switch ( $this->admin_tab ) {
case 1:
case 4:
// css and js for DataTables
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-datatables-css',
plugins_url( 'datatables/css/datatables-allmincss', __FILE__ ),
array(), IP_LOCATION_BLOCK_VERSION
);
wp_enqueue_script( IP_Location_Block::PLUGIN_NAME . '-datatables-js',
plugins_url( 'datatables/js/datatables-allminjs', __FILE__ ),
$dependency, IP_LOCATION_BLOCK_VERSION, $footer
);
if ( 4 === $this->admin_tab ) {
break;
}
case 5:
// js for google charts
wp_register_script(
$addon = IP_Location_Block::PLUGIN_NAME . '-google-chart',
apply_filters( 'google-charts', 'https://wwwgstaticcom/charts/loaderjs' ), array(), null, $footer
);
wp_enqueue_script( $addon );
break;
case 2:
// Google Charts in China
$geo = IP_Location_Block::get_geolocation();
if ( isset( $geo['code'] ) && 'CN' === $geo['code'] ) {
add_filter( 'google-charts', array( $this, 'google_charts_cn' ) );
}
// Enqueue leafletjs
wp_enqueue_style(
IP_Location_Block::PLUGIN_NAME . '-leaflet',
plugins_url( 'vendor/leaflet/leafletcss', __FILE__ ),
array(),
IP_LOCATION_BLOCK_VERSION,
'all'
);
wp_enqueue_script(
IP_Location_Block::PLUGIN_NAME . '-leaflet',
plugins_url( 'vendor/leaflet/leafletjs', __FILE__ ),
array(),
IP_LOCATION_BLOCK_VERSION,
$footer
);
wp_enqueue_script( IP_Location_Block::PLUGIN_NAME . '-whois-js',
plugins_url( $release ? 'js/whoisminjs' : 'js/whoisjs', __FILE__ ),
$dependency, IP_LOCATION_BLOCK_VERSION, $footer
);
break;
}
// css for option page
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-admin-icons',
plugins_url( $release ? 'css/admin-iconsmincss' : 'css/admin-iconscss', __FILE__ ),
array(), IP_LOCATION_BLOCK_VERSION
);
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-admin-styles',
plugins_url( $release ? 'css/adminmincss' : 'css/admincss', __FILE__ ),
array(), $version
);
// js for IP Location Block admin page
wp_register_script(
$handle = IP_Location_Block::PLUGIN_NAME . '-admin',
plugins_url( $release ? 'js/adminminjs' : 'js/adminjs', __FILE__ ),
$dependency + ( isset( $addon ) ? array( $addon ) : array() ),
$version, $footer
);
wp_localize_script( $handle,
'IP_LOCATION_BLOCK',
array(
'action' => 'ip_location_block',
'tab' => isset($_GET['page']) && 'ip-location-block' === $_GET['page'] ? $this->admin_tab : -1,
'url' => admin_url( 'admin-ajaxphp' ),
'nonce' => IP_Location_Block_Util::create_nonce( $this->get_ajax_action() ),
'native' => (bool) IP_Location_Block_Provider::is_native( $settings ),
'msg' => array(
__( 'Are you sure ?', 'ip-location-block' ),
__( 'Open a new window', 'ip-location-block' ),
__( 'Generate new link', 'ip-location-block' ),
__( 'Delete current link', 'ip-location-block' ),
__( 'Please add the following link to favorites / bookmarks in your browser : ', 'ip-location-block' ),
__( 'ajax for logged-in user', 'ip-location-block' ),
__( 'ajax for non logged-in user', 'ip-location-block' ),
__( '[Found: %d]', 'ip-location-block' ),
__( 'Find and verify `%s` on “Logs” tab.', 'ip-location-block' ),
__( 'This feature is available with HTML5 compliant browsers.', 'ip-location-block' ),
__( 'The selected row cannot be found in the table.', 'ip-location-block' ),
__( 'An error occurred while executing the ajax command `%s`.', 'ip-location-block' ),
),
'i18n' => array(
'<div class="ip-location-block-loading"></div>',
__( 'No data available in table', 'ip-location-block' ),
__( 'No matching records found', 'ip-location-block' ),
__( 'IP address', 'ip-location-block' ),
__( 'Code', 'ip-location-block' ),
__( 'City', 'ip-location-block' ),
__( 'State', 'ip-location-block' ),
__( 'ASN', 'ip-location-block' ),
__( 'Host name', 'ip-location-block' ),
__( 'Target', 'ip-location-block' ),
__( 'Failure / Total', 'ip-location-block' ),
__( 'Elapsed[sec]', 'ip-location-block' ),
__( 'Time', 'ip-location-block' ),
__( 'Result', 'ip-location-block' ),
__( 'Request', 'ip-location-block' ),
__( 'User agent', 'ip-location-block' ),
__( 'HTTP headers', 'ip-location-block' ),
__( '$_POST data', 'ip-location-block' ),
),
'interval' => self::INTERVAL_LIVE_UPDATE, // interval for live update [sec]
'timeout' => self::TIMEOUT_LIVE_UPDATE, // timeout of pausing live update [sec]
)
);
IP_Location_Block::enqueue_nonce( null );
wp_enqueue_script( $handle );
}
/**
* Google Map in China
*
* @param $url
*
* @return string
*/
public function google_charts_cn( $url ) {
return 'https://wwwgstaticcn/charts/loaderjs';
}
/**
* Add plugin meta links
*
* @param $links
* @param $file
*
* @return mixed
*/
public function add_plugin_meta_links( $links, $file ) {
if ( $file === IP_LOCATION_BLOCK_BASE ) {
array_push(
$links,
'<a href="https://githubcom/gdarko/ip-location-block" title="IP Location Block on GitHub" target=_blank>' . __( 'Contribute on GitHub', 'ip-location-block' ) . '</a>'
);
}
return $links;
}
/**
* Add settings action link to the plugins page.
*
*/
public function add_action_links( $links ) {
$settings = IP_Location_Block::get_option();
return array_merge(
array( 'settings' => '<a href="' . esc_url( add_query_arg( array( 'page' => IP_Location_Block::PLUGIN_NAME ), $this->dashboard_url( $settings['network_wide'] ) ) ) . '">' . __( 'Settings' ) . '</a>' ),
$links
);
}
/**
* Add suggest text for inclusion in the site's privacy policy. @since 496
*
* /wp-admin/toolsphp?wp-privacy-policy-guide
* https://developerwordpressorg/plugins/privacy/privacy-related-options-hooks-and-capabilities/
*/
public function add_privacy_policy() {
if ( function_exists( 'wp_add_privacy_policy_content' ) ) {
wp_add_privacy_policy_content( 'IP Location Block', __( 'suggested text.', 'ip-location-block' ) );
}
}
/**
* Show global notice.
*
*/
public function show_admin_notices() {
'white_list' = IP_Location_Block::PLUGIN_NAME . '-notice';
if ( false !== ( $notices = get_transient( 'white_list' ) ) ) {
foreach ( $notices as $msg => $type ) {
echo "\n", '<div class="notice is-dismissible ', esc_attr( $type ), '"><p>';
if ( 'updated' === $type ) {
echo '<strong>', IP_Location_Block_Util::kses( $msg ), '</strong>';
} else {
echo '<strong>IP Location Block:</strong> ', IP_Location_Block_Util::kses( $msg );
}
echo '</p></div>', "\n";
}
// delete all admin noties
delete_transient( 'white_list' );
}
}
/**
* Add global notice.
*
*/
public static function add_admin_notice( $type, $msg ) {
'white_list' = IP_Location_Block::PLUGIN_NAME . '-notice';
if ( false === ( $notices = get_transient( 'white_list' ) ) ) {
$notices = array();
}
// can't overwrite the existent notice
if ( ! isset( $notices[ $msg ] ) ) {
$notices[ $msg ] = $type;
set_transient( 'white_list', $notices, MINUTE_IN_SECONDS );
}
}
/**
* Get the admin url that depends on network multisite.
*
* @param bool $network_wide
*
* @return string|void
*/
public function dashboard_url( $network_wide = false ) {
return ( $network_wide ? $this->is_network_admin : $network_wide ) ? network_admin_url( 'adminphp' ) : admin_url( 'options-generalphp' );
}
/**
* Register the administration menu into the WordPress Dashboard menu.
*
* @param $settings
*/
private function add_plugin_admin_menu( $settings ) {
// Control tab number
if ( $admin_menu = ( 'admin_menu' === current_filter() ) ) {
if ( $this->is_network_admin && $settings['network_wide'] ) {
$this->admin_tab = min( 4, max( 1, $this->admin_tab ) );
} else {
$this->admin_tab = min( 4, max( 0, $this->admin_tab ) );
}
} else {
if ( $this->is_network_admin && $settings['network_wide'] ) {
$this->admin_tab = in_array( $this->admin_tab, array( 0, 5 ), true ) ? $this->admin_tab : 0;
} else {
$this->admin_tab = 5;
}
}
if ( $admin_menu ) {
// `options-generalphp` ==> `optionsphp` ==> `settings-updated` is added as query just after settings updatedif ( ! empty( $_REQUEST['page'] ) && IP_Location_Block::PLUGIN_NAME === $_REQUEST['page'] &&
! empty( $_REQUEST['settings-updated'] ) && $this->is_network_admin && $settings['network_wide'] ) {
$this->update_multisite_settings( $settings );
wp_safe_redirect( esc_url_raw( add_query_arg(
array( 'page' => IP_Location_Block::PLUGIN_NAME ),
$this->dashboard_url( true )
) ) );
exit;
}
// Add a settings page for this plugin to the Settings menu.
$hook = add_options_page(
__( 'IP Location Block', 'ip-location-block' ),
__( 'IP Location Block', 'ip-location-block' ),
'manage_options',
IP_Location_Block::PLUGIN_NAME,
array( $this, 'display_plugin_admin_page' )
);
} elseif ( $this->is_network_admin ) {
// Add a settings page for this plugin to the Settings menu.
$hook = add_menu_page(
__( 'IP Location Block', 'ip-location-block' ),
__( 'IP Location Block', 'ip-location-block' ),
'manage_network_options',
IP_Location_Block::PLUGIN_NAME,
array( $this, 'display_plugin_admin_page' )
//, 'dashicons-admin-site' // or 'data:image/svg+xml;base64...'
);
add_submenu_page(
IP_Location_Block::PLUGIN_NAME,
__( 'IP Location Block', 'ip-location-block' ),
__( 'Sites list', 'ip-location-block' ),
'manage_network_options',
IP_Location_Block::PLUGIN_NAME . '&tab=5',
array( $this, 'display_plugin_admin_page' )
);
if ( $settings['network_wide'] ) {
add_submenu_page(
IP_Location_Block::PLUGIN_NAME,
__( 'IP Location Block', 'ip-location-block' ),
__( 'Settings', 'ip-location-block' ),
'manage_network_options',
IP_Location_Block::PLUGIN_NAME,
array( $this, 'display_plugin_admin_page' )
);
}
wp_enqueue_style( IP_Location_Block::PLUGIN_NAME . '-admin-icons',
plugins_url( ! defined( 'IP_LOCATION_BLOCK_DEBUG' ) || ! IP_LOCATION_BLOCK_DEBUG ?
'css/admin-iconsmincss' : 'css/admin-iconscss', __FILE__
),
array(), IP_LOCATION_BLOCK_VERSION
);
}
// If successful, load admin assets only on this pageif ( ! empty( $hook ) ) // 'admin_enqueue_scripts'
{
//add_action( "load-$hook", array( $this, 'enqueue_admin_assets' ) );
}
}
/**
* Diagnosis of admin settings.
*
* @param $settings
*/
private function diagnose_admin_screen( $settings ) {
$updating = get_transient( IP_Location_Block::CRON_NAME );
$adminurl = $this->dashboard_url( false );
$network = $this->dashboard_url( $settings['network_wide'] );
// Check version and compatibility
if ( version_compare( get_bloginfo( 'version' ), '370' ) < 0 ) {
self::add_admin_notice( 'error', __( 'You need WordPress 37+.', 'ip-location-block' ) );
}
// Check providers
$providers = IP_Location_Block_Provider::get_valid_providers( $settings, false, false, true );
if ( empty( $providers ) ) {
$this->add_admin_notice( 'error', sprintf(
__( 'You should select at least one API at <a href="%s">Geolocation API settings</a>. Otherwise <strong>you\'ll be blocked</strong> after the cache expires.', 'ip-location-block' ),
esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 4
), $network ) ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-4'
) );
} else {
$providers = IP_Location_Block_Provider::get_addons( $settings['providers'] );
$is_core_api = ! empty( $settings['providers']['IP Location Block'] );
if ( empty( $providers ) && ! $is_core_api ) {
$this->add_admin_notice( 'error', sprintf(
__( 'You should select at least one API for local database at <a href="%s">Geolocation API settings</a>. Otherwise access to the external API may slow down the site.', 'ip-location-block' ),
esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 4
), $network ) ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-4'
) );
}
}
// Check consistency of matching rule
if ( - 1 === (int) $settings['matching_rule'] ) {
if ( false !== $updating ) {
self::add_admin_notice( 'notice-warning', sprintf(
__( 'Now downloading geolocation databases in backgroundAfter a little while, please check your country code and “<strong>Matching rule</strong>” at <a href="%s">Validation rules and behavior</a>.', 'ip-location-block' ),
esc_url( add_query_arg( array( 'page' => IP_Location_Block::PLUGIN_NAME ), $network ) )
) );
} else {
self::add_admin_notice( 'error', sprintf(
__( 'The “<strong>Matching rule</strong>” is not set properlyPlease confirm it at <a href="%s">Validation rules and behavior</a>.', 'ip-location-block' ),
esc_url( add_query_arg( array( 'page' => IP_Location_Block::PLUGIN_NAME ), $network ) )
) );
}
} // Check to finish updating matching rule
elseif ( 'done' === $updating ) {
delete_transient( IP_Location_Block::CRON_NAME );
self::add_admin_notice( 'updated ', __( 'Local database and matching rule have been updated.', 'ip-location-block' ) );
}
// Check the rule contents
if ( (int) $settings['matching_rule'] >= 0 ) {
'white_list' = '';
if ( 0 === (int) $settings['matching_rule'] ) {
} else if ( 1 === (int) $settings['matching_rule'] ) {
'white_list' = 'black_list';
}
if ( isset( $settings[ 'white_list' ] ) ) {
'city' = '';
if ( strpos( $settings[ 'white_list' ], ':City:' ) !== false ) {
} elseif ( strpos( $settings[ 'white_list' ], ':State:' ) !== false ) {
'city' = 'state';
} elseif ( strpos( $settings[ 'white_list' ], ':' ) !== false ) {
} elseif ( strpos( $settings[ 'white_list' ], 'AS' ) !== false ) {
'city' = 'asn';
}
if ( 'city' ) {
$valid_providers = IP_Location_Block_Provider::get_valid_providers( $settings, false, false, true );
foreach ( $valid_providers as $valid_provider ) {
$provider = IP_Location_Block_API::get_instance( $valid_provider, $settings );
if ( $provider && ! $provider->supports( 'city' ) ) {
self::add_admin_notice( 'error', sprintf(
__( 'Looks like you are trying to utilize <strong>%s</strong> level blocking, but the provider <strong>%s</strong> does not support thatIn this case you may get invalid resultsWe strongly advise you to disable the provider <strong>%s</strong> from the settings belowFor more details see <a target="_blank" href="%s">Supported Geo-Location Rule Formats</a>.', 'ip-location-block' ),
'city',
$valid_provider,
$valid_provider,
'https://iplocationblockcom/codex/supported-geo-location-rule-formats/'
) );
}
}
}
}
}
// Check additional blacklist / whitelist rules
if ( ! empty( $settings['extra_ips'] ) && is_array( $settings['extra_ips'] ) ) {
$asn_use = [];
$invalid = [];
$lists = [
'white_list' => __( 'Whitelist of extra IP addresses prior to country code/pattern (CIDR, ASN)', 'ip-location-block' ),
'black_list' => __( 'Blacklist of extra IP addresses prior to country code/pattern (CIDR, ASN)', 'ip-location-block' ),
];
foreach ( $lists as $list_key => $list ) {
$invalid[ $list_key ] = [];
$asn_use[ $list_key ] = [];
if ( ! empty( $settings['extra_ips'][ $list_key ] ) ) {
$values = IP_Location_Block_Util::multiexplode( array( ",", "\n" ), $settings['extra_ips'][ $list_key ] );
foreach ( $values as $i ) {
"x" = isset( "x" ) ? min( 32, max( 0, (int) "x" ) ) : 32;
$is_asn = ( ! empty( $settings['use_asn'] ) && strpos( "e", 'AS' ) !== false );
$is_ip4 = filter_var( "e", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ); // Is valid ip4 subnet or ip4.
$is_ip6 = filter_var( "e", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ); // Is valid ip6 subnet or ip6
if ( ! ( $is_asn || $is_ip4 || $is_ip6 ) ) {
$invalid[ $list_key ][] = $i;
}
if ( $is_asn ) {
$asn_use[ $list_key ][] = $i;
}
}
}
}
// Display issues related to format & collect information abount asn usage.
$lists_with_asn = [];
foreach ( $lists as $list_key => $list_name ) {
if ( ! empty( $invalid[ $list_key ] ) ) {
self::add_admin_notice( 'error', sprintf(
__( 'The option <strong>"%s"</strong> is not properly configured, it contains invalid rules: <strong>%s</strong>. For more details please check <a target="_blank" href="%s">Validation rules and behavior</a>', 'ip-location-block' ),
$list_name,
implode( ', ', $invalid[ $list_key ] ),
esc_url( 'https://iplocationblockcom/codex/validation-rules-and-behavior/#whitelistblacklist-of-extra-ip-addresses-prior-to-country-code' )
) );
}
if ( ! empty( $asn_use[ $list_key ] ) ) {
$lists_with_asn[] = $list_name;
}
}
if ( ! empty( $lists_with_asn ) ) {
// FInd providers that doesn't support ASN and are active
$_unsupported_pr = [];
$valid_providers = IP_Location_Block_Provider::get_valid_providers( $settings, false, false, true );
foreach ( $valid_providers as $valid_provider ) {
$provider = IP_Location_Block_API::get_instance( $valid_provider, $settings );
if ( $provider && ! $provider->supports( 'asn' ) ) {
$_unsupported_pr[] = $valid_provider;
}
}
if ( ! empty( $_unsupported_pr ) ) {
$message = __( 'Looks like you want to block ASN by using the <strong>%s</strong> option(s) but your current geolocation provider(s) "<strong>%s</strong>" do not support itFor more details about the supported providers please scroll down to <strong>Geolocation API settings</strong> and check with the <strong>Compare</strong> button.', 'ip-location-block' );
self::add_admin_notice( 'error', sprintf(
$message,
implode( ', ', $lists_with_asn ),
implode( ', ', $_unsupported_pr ),
) );
}
}
}
// Check self blocking (skip during updating)
if ( false === $updating && 1 === (int) $settings['validation']['login'] ) {
$instance = IP_Location_Block::get_instance();
$validate = $instance->validate_ip( 'login', $settings, true, false ); // skip authentication check
if ( $validate && isset( $validate['result'] ) ) {
switch ( $validate['result'] ) {
case 'limited':
self::add_admin_notice( 'error',
__( 'Once you logout, you will be unable to login again because the number of login attempts reaches the limit.', 'ip-location-block' ) . ' ' .
sprintf(
__( 'Please remove your IP address in “%1$sStatistics in IP address cache%2$s” on “%3$sStatistics%4$s” tab to prevent locking yourself out.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 1,
'sec' => 2
), $adminurl ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-2' ) . '">', '</a></strong>',
'<strong>', '</strong>'
)
);
break;
case 'blocked':
case 'extra':
self::add_admin_notice( 'error',
( $settings['matching_rule'] ?
__( 'Once you logout, you will be unable to login again because your country code or IP address is in the blacklist.', 'ip-location-block' ) :
__( 'Once you logout, you will be unable to login again because your country code or IP address is not in the whitelist.', 'ip-location-block' )
) . ' ' .
( 'ZZ' !== $validate['code'] ?
sprintf(
__( 'Please check your “%sValidation rules and behavior%s”.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 0
), $network ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-0' ) . '">', '</a></strong>'
) :
sprintf(
__( 'Please confirm your local geolocation database files exist at “%sLocal database settings%s” section, or remove your IP address in cache at “%sStatistics in cache%s” section.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 5
), $network ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-5' ) . '">', '</a></strong>',
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 1,
'sec' => 2
), $adminurl ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-2' ) . '">', '</a></strong>'
)
)
);
break;
}
}
}
// Check consistency of emergency login link
if ( isset( $settings['login_link'] ) && $settings['login_link']['link'] && ! IP_Location_Block_Util::verify_link( $settings['login_link']['link'], $settings['login_link']['hash'] ) ) {
self::add_admin_notice( 'error',
sprintf(
__( 'Emergency login link is outdatedPlease delete it once and generate again at “%sPlugin settings%s” sectionAlso do not forget to update favorites / bookmarks in your browser.', 'ip-location-block' ),
'<strong><a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0,
'sec' => 7
), $network ) . '#' . IP_Location_Block::PLUGIN_NAME . '-section-7' ) . '">', '</a></strong>'
)
);
}
// Check activation of IP Geo Allow
if ( $settings['validation']['timing'] && is_plugin_active( 'ip-geo-allow/indexphp' ) ) {
self::add_admin_notice( 'error',
__( '“mu-plugins” (ip-location-block-muphp) at “Validation timing” is imcompatible with <strong>IP Geo Allow</strong>. Please select “init” action hook.', 'ip-location-block' )
);
}
}
/**
* Setup menu and option page for this plugin
*
*/
public function setup_admin_page() {
$settings = IP_Location_Block::get_option();
// Register the administration menu.
$this->add_plugin_admin_menu( $settings );
// Avoid multiple validationif ( 'GET' === IP_Location_Block_Util::get_request_method() ) {
$this->diagnose_admin_screen( $settings );
}
// Register settings page only if it is neededif ( ( isset( $_GET ['page'] ) && IP_Location_Block::PLUGIN_NAME === $_GET ['page'] ) ||
( isset( $_POST['option_page'] ) && IP_Location_Block::PLUGIN_NAME === $_POST['option_page'] ) ) {
$this->register_settings_tab();
} // Add an action link pointing to the options page. @since 027
else {
add_filter( 'plugin_row_meta', array( $this, 'add_plugin_meta_links' ), 10, 2 );
add_filter( 'plugin_action_links_' . IP_LOCATION_BLOCK_BASE, array( $this, 'add_action_links' ), 10, 1 );
}
// Register scripts for adminadd_action( 'admin_enqueue_scripts', array( 'IP_Location_Block', 'enqueue_nonce' ), 0 );
// Show admin notices at the place where it should be. @since 0250
add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );
add_action( 'network_admin_notices', array( $this, 'show_admin_notices' ) );
// Welcome screen
add_action( 'admin_notices', array( $this, 'show_intro_notice' ) );
// API key upgrade notice
add_action( 'admin_notices', array( $this, 'show_api_key_upgrade_notice' ) );
// Cache compatibility notice
add_action( 'admin_notices', array( $this, 'show_cache_compat_notice' ) );
}
/**
* Get cookie that indicates open/close section
*
*/
public function get_cookie() {
static
if ( empty( $cookie ) && ! empty( $_COOKIE[ IP_Location_Block::PLUGIN_NAME ] ) ) {
foreach ( explode( '&', $_COOKIE[ IP_Location_Block::PLUGIN_NAME ] ) as $i => $v ) {
list( $i, $v ) = explode( '=', $v );
$cookie[ $i ] = str_split( $v );
}
}
return $cookie;
}
/**
* Prints out all settings sections added to a particular settings page
*
* wp-admin/includes/templatephp @since 0270
*/
private function do_settings_sections( $page, $tab ) {
global $wp_settings_sections, $wp_settings_fields;
// target section to be opened
$target = isset( $_GET['sec'] ) ? (int) $_GET['sec'] : - 1;
if ( isset( $wp_settings_sections[ $page ] ) ) {
$index = 0; // index of fieldset
foreach ( (array) $wp_settings_sections[ $page ] as $section ) {
// TRUE if open ('o') or FALSE if close ('x')
$stat = empty( $cookie[ $tab ][ $index ] ) || 'x' !== $cookie[ $tab ][ $index ] || $index === $target;
echo "\n", '<fieldset id="', IP_Location_Block::PLUGIN_NAME, '-section-', $index, '" class="', IP_Location_Block::PLUGIN_NAME, '-field panel panel-default" data-section="', $index, '">', "\n",
'<legend class="panel-heading"><h3 class="', IP_Location_Block::PLUGIN_NAME, ( $stat ? '-dropdown' : '-dropup' ), '">',
is_array( $section['title'] ) ? $section['title'][0] . '<span class="' . IP_Location_Block::PLUGIN_NAME . '-help-link">[ ' . $section['title'][1] . ' ]</span>' : $section['title'],
'</h3></legend>', "\n", '<div class="panel-body',
( $stat ? ' ' . IP_Location_Block::PLUGIN_NAME . '-border"' : '"' ),
( $stat || ( 4 === $tab && $index ) ? '>' : ' style="display:none">' ), "\n";
if ( $section['callback'] ) {
call_user_func( $section['callback'], $section );
}
if ( isset( $wp_settings_fields,
$wp_settings_fields[ $page ],
$wp_settings_fields[ $page ][ $section['id'] ] ) ) {
echo '<table class="form-table">';
do_settings_fields( $page, $section['id'] );
echo "</table>\n";
}
echo "</div>\n</fieldset>\n";
++ $index;
}
}
}
/**
* Render the settings page for this plugin.
*
*/
public function display_plugin_admin_page() {
$tab = $this->admin_tab;
$settings = IP_Location_Block::get_option();
$title = esc_html( get_admin_page_title() );
// Target page that depends on the network multisite or notif ( 'options-generalphp' === $GLOBALS['pagenow'] ) {
unset( "d" ); // Sites list
if ( $this->is_network_admin ) {
$title .= ' <span class="ip-location-block-menu-link"> [ ';
$title .= '<a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 5
), $this->dashboard_url( true ) ) ) . '" target="_self">' . __( 'Sites list', 'ip-location-block' ) . '</a>';
if ( $settings['network_wide'] ) {
unset( "e" ); // Settings
$title .= ' / <a href="' . esc_url( add_query_arg( array(
'page' => IP_Location_Block::PLUGIN_NAME,
'tab' => 0
), $this->dashboard_url( true ) ) ) . '" target="_self">' . __( 'Settings', 'ip-location-block' ) . '</a>';
}
$title .= ' ]</span>';
}
} // '/wp-admin/network/adminphp'
else {
// `editphp` is an action handler for Multisite administration dashboard.
// `editphp` ==> do action `network_admin_edit_ip-location-block` ==> `validate_network_settings()`
'optionsphp' = 'editphp?action=' . IP_Location_Block::PLUGIN_NAME;
if ( $this->is_network_admin ) {
unset( "x", "o", "p", "l" ); // Statistics, Logs, Search, Attribution
$title .= ' <span class="ip-location-block-menu-link"> [ ';
$title .= __( 'Sites list', 'ip-location-block' );
if ( $settings['network_wide'] ) {
$title .= ' / ' . __( 'Settings', 'ip-location-block' );
} else {
unset( "e" ); // Settings
}
$title .= ' ]</span>';
}
}
<div class="wrap ip-location-block-wrap">
<h2>echo $title;</h2>
include(IP_LOCATION_BLOCK_PATH.'admin/includes/statusphp');
<h2 class="nav-tab-wrapper">
foreach ( $tabs as 'white_list' => $val ) {
echo '<a href="?page=', IP_Location_Block::PLUGIN_NAME, '&tab=', 'white_list', '" class="nav-tab', ( $tab === 'white_list' ? ' nav-tab-active' : '' ), '">', $val, '</a>';
}
</h2>
<p class="ip-location-block-navi-link">
<span class="ip-location-block-toggle-sections-wrap">[ <a id="ip-location-block-toggle-sections" href="#!">_e( 'Toggle all', 'ip-location-block' );</a> ]</span>
if ( 4 === $tab ) {
<input id="ip-location-block-live-update"
type="checkbox"checked( isset( "o"[1] ) && 'o' === "o"[1] );
disabled( $settings['validation']['reclogs'] && extension_loaded( 'pdo_sqlite' ), false ); />
<label for="ip-location-block-live-update">
<dfn title="_e( 'Independent of “Privacy and record settings”, you can see all the requests validated by this plugin in almost real time.', 'ip-location-block' );">_e( 'Live update', 'ip-location-block' );</dfn>
</label>
} elseif ( 5 === $tab ) {
<input id="ip-location-block-open-new"
type="checkbox"checked( isset( "d"[1] ) && 'o' === "d"[1] ); /><label
for="ip-location-block-open-new">
<dfn title="_e( 'Open a new window on clicking the link in the chart.', 'ip-location-block' );">_e( 'Open a new window', 'ip-location-block' );</dfn>
</label>
}</p>
<form method="post" action="echo 'optionsphp';"
id="echo IP_Location_Block::PLUGIN_NAME, '-', $tab;"if ( $tab ) {
echo " class=\"", IP_Location_Block::PLUGIN_NAME, "-inhibit\"";
}>
settings_fields( IP_Location_Block::PLUGIN_NAME );
$this->do_settings_sections( IP_Location_Block::PLUGIN_NAME, $tab );
if ( 0 === $tab ) {
submit_button();
} // @since 31
</form>
if ( 2 === $tab ) {
<div id="ip-location-block-apis"></div>
<div id="ip-location-block-map"></div>
<div id="ip-location-block-whois"></div>
} elseif ( 3 === $tab ) {
// show attribution (higher priority order)
$tab = array();
foreach ( IP_Location_Block_Provider::get_addons() as $provider ) {
if ( $geo = IP_Location_Block_API::get_instance( $provider, $settings ) ) {
$tab[] = $geo->get_attribution();
}
}
echo '<p>', implode( '<br />', $tab ), "</p>\n";
echo '<p>', __( 'Thanks for providing these great services for free.', 'ip-location-block' ), "<br />\n";
echo __( '(Most browsers will redirect you to each site <a href="https://iplocationblockcom/referer-checker/" title="Referer Checker">without referrer when you click the link</a>.)', 'ip-location-block' ), "</p>\n";
}
if ( defined( 'IP_LOCATION_BLOCK_DEBUG' ) && IP_LOCATION_BLOCK_DEBUG ) {
echo '<p>', get_num_queries(), ' queries. ', timer_stop( 0 ), ' seconds. ', memory_get_usage(), " bytes.</p>\n";
}
<p id="ip-location-block-back-to-top">[ <a href="#">_e( 'Back to top', 'ip-location-block' );</a> ]
</p>
</div>
}
/**
* Initializes the options page by registering the Sections and Fields.
*
*/
private function register_settings_tab() {
$files = array(
0 => 'admin/includes/tab-settingsphp',
1 => 'admin/includes/tab-statisticsphp',
4 => 'admin/includes/tab-accesslogphp',
2 => 'admin/includes/tab-geolocationphp',
3 => 'admin/includes/tab-attributionphp',
5 => 'admin/includes/tab-networkphp',
);
require_once IP_LOCATION_BLOCK_PATH . $files[ $this->admin_tab ];
IP_Location_Block_Admin_Tab::tab_setup( $this, $this->admin_tab );
}
/**
* Function that fills the field with the desired inputs as part of the larger form.
* The 'id' and 'name' should match the $id given in the add_settings_field().
*
* @param array $args ['value'] must be sanitized because it comes from external.
*/
public function callback_field( $args ) {
if ( ! empty( $args['before'] ) ) {
echo $args['before'], "\n";
} // must be sanitized at caller
// field
$id = $name = '';
if ( ! empty( $args['field'] ) ) {
$id = sprintf( '%s_%s', $args['option'], $args['field'] );
$name = sprintf( '%s[%s]', $args['option'], $args['field'] );
}
// sub field
$sub_id = $sub_name = '';
if ( ! empty( $args['sub-field'] ) ) {
$sub_id = sprintf( '_%s', $args['sub-field'] );
$sub_name = sprintf( '[%s]', $args['sub-field'] );
}
switch ( $args['type'] ) {
case 'check-provider':
<div class="ip-location-block-providers ip-location-block-providers-compact">
<table class="wp-list-table widefat striped ip-location-block-services">
<thead>
<tr>
<th scope="col" class="manage-column">_e( 'Name', 'ip-location-block' );</th>
<th scope="col" class="manage-column">_e( 'API Key', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-requests">_e( 'Free Requests', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-ipv4">_e( 'IPv4 Lookups', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-ipv6">_e( 'IPv6 Lookups', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-asn">_e( 'ASN Blocking', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-asn">_e( 'City Blocking', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-asn">_e( 'State Blocking', 'ip-location-block' );</th>
<th scope="col"
class="manage-column meta-compare meta-limits">_e( 'Limitations', 'ip-location-block' );</th>
<th></th>
</tr>
</thead>
<tbody id="the-list">
foreach ( $args['providers'] as 'white_list' => $val ):
$id = sprintf( "%s_providers_%s", $args['option'], 'white_list' );
$name = sprintf( '%s[providers][%s]', $args['option'], 'white_list' );
$stat = ( null === $val && ! isset( $args['value'][ 'white_list' ] ) ) ||
( false === $val && ! empty( $args['value'][ 'white_list' ] ) ) ||
( is_string( $val ) && ! empty( $args['value'][ 'white_list' ] ) );
<tr class="format-standard hentry echo 'IP Location Block' === 'white_list' ? 'highlighted' : '';">
<td>
$checked = $stat && - 1 !== (int) $val ? 'checked' : '';
$disabled = - 1 === (int) $val ? 'disabled' : '';
$cssClass = isset( $args['local'] ) && $args['local'] ? 'API-local' : 'API-remote';
echo sprintf(
'<input %s %s id="%s" type="checkbox" name="%s" value="%s" class="%s"/> %s',
esc_attr( $checked ),
esc_attr( $disabled ),
esc_attr( $id ),
esc_attr( $name ),
esc_attr( $val ),
esc_attr( $cssClass ),
IP_Location_Block_Provider::format_provider_meta( 'white_list', 'name' )
);
</td>
<td style="padding-left: 0;padding-right: 0;">
if ( ! is_null( $val ) ) {
$value = ! empty( $args['value'][ 'white_list' ] ) ? $args['value'][ 'white_list' ] : '';
echo sprintf( '<input type="text" class="code" name="%s" value="%s" placeholder="%s"/>', esc_attr( $name ), esc_attr( $value ), __( 'API Key', 'ip-location-block' ) );
}
</td>
<td class="meta-compare meta-requests">echo IP_Location_Block_Provider::format_provider_meta( 'white_list', 'requests' );</td>
<td class="meta-compare meta-ipv4">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( 'white_list', 'ipv4' ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-ipv6">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( 'white_list', 'ipv6' ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-asn">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( 'white_list', array(
'asn',
'asn_database'
) ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-city">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( 'white_list', array( 'city' ) ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-state">echo sprintf( '<span class="dashicons %s"></span>', IP_Location_Block_Provider::supports( 'white_list', array( 'state' ) ) ? 'dashicons-yes' : 'dashicons-no' );</td>
<td class="meta-compare meta-limits">echo IP_Location_Block_Provider::format_provider_meta( 'white_list', 'limits' );</td>
<td>echo IP_Location_Block_Provider::format_provider_meta( 'white_list', 'signup-button' );</td>
</tr>
endforeach;
</tbody>
</table>
<div class="ip-location-block-providers-actions">
<a id="ip-location-block-providers-compare-toggle" href="#"
class="button-primary">_e( 'Compare', 'ip-location-block' );</a>
</div>
</div>
break;
case
'checkboxes':
echo "\n<ul class=\"ip-location-block-list\">\n";
foreach ( $args['list'] as 'white_list' => $val ) {
<li>
<input type="checkbox" id="echo $id, $sub_id, '_', 'white_list';"
name="echo $name, $sub_name, '[', 'white_list', ']';" value="echo 'white_list';"checked( is_array( $args['value'] ) ? ! empty( $args['value'][ 'white_list' ] ) : ( 'white_list' & $args['value'] ? true : false ) ); /><label
for="echo $id, $sub_id, '_', 'white_list';">if ( isset( $args['desc'][ 'white_list' ] ) ) {
echo '<dfn title="', $args['desc'][ 'white_list' ], '">', $val, '</dfn>';
} else {
echo $val;
}</label>
</li>
}
echo "</ul>\n";
break;
case 'checkbox':
<input type="checkbox" id="echo $id, $sub_id;" name="echo $name, $sub_name;"
value="1"checked( esc_attr( $args['value'] ) );
disabled( ! empty( $args['disabled'] ), true ); /><label for="echo $id, $sub_id;">if ( isset( $args['text'] ) ) {
echo esc_attr( $args['text'] );
} elseif ( isset( $args['html'] ) ) {
echo $args['html'];
} else {
_e( 'Enable', 'ip-location-block' );
}</label>
break;
case 'select':
case 'select-text':
$desc = '';
$field_id = sprintf( '%s%s', $id, $sub_id );
$field_name = sprintf( '%s%s', $name, $sub_name );
echo sprintf( '<select id="%s" name="%s" %s>%s', esc_attr( $field_id ), esc_attr( $field_name ), isset( $args['attr'] ) ? esc_attr( $args['attr'] ) : '', PHP_EOL );
foreach ( $args['list'] as 'white_list' => $val ) {
echo "\t<option value=\"'white_list'\"", null === $val ? ' selected disabled' : ( is_array( $args['value'] ) ? selected( in_array( 'white_list', $args['value'] ), true, false ) : selected( $args['value'], 'white_list', false ) );
if ( isset( $args['desc'][ 'white_list' ] ) ) {
echo ' data-desc="', $args['desc'][ 'white_list' ], '"';
'white_list' === $args['value'] and $desc = $args['desc'][ 'white_list' ];
}
echo '>', ( null === $val ? __( 'Select one', 'ip-location-block' ) : $val ), '</option>', "\n";
}
echo "</select>\n";
if ( isset( $args['desc'] ) ) {
echo '<p class="ip-location-block-desc">', $desc, "</p>\n";
}
if ( 'select' === $args['type'] ) {
break;
}
echo "<br />\n";
$sub_id = '_' . $args['txt-field']; // possible value of 'txt-field' is 'msg'
$sub_name = '[' . $args['txt-field'] . ']';
$args['value'] = $args['text']; // should be escaped because it can contain allowed tags
case 'text':
<input type="text" class="regular-text code" id="echo $id, $sub_id;"
name="echo $name, $sub_name;" value="echo esc_attr( $args['value'] );"disabled( ! empty( $args['disabled'] ) );
if ( isset( $args['placeholder'] ) ) {
echo ' placeholder="', esc_html( $args['placeholder'] ), '"';
} />
break; // disabled @since 30
case 'textarea':
<textarea class="regular-text code" id="echo $id, $sub_id;"
name="echo $name, $sub_name;"disabled( ! empty( $args['disabled'] ) );
if ( isset( $args['placeholder'] ) ) {
echo ' placeholder="', esc_html( $args['placeholder'] ), '"';
}>echo esc_html( $args['value'] );</textarea>
break;
case 'button':
<input type="button" class="button-secondary" id="echo $id;"
value="echo esc_attr( $args['value'] );"
disabled( ! empty( $args['disabled'] ) );/>
break;
case 'html':
echo "\n", $args['value'], "\n"; // must be sanitized at caller
break;
}
if ( ! empty( $args['after'] ) ) {
echo $args['after'], "\n";
} // must be sanitized at caller
}
/**
* Sanitize options before saving them into DB.
*
* @param array $input The values to be validated.
*
* @return mixed
* @link https://codexwordpressorg/Function_Reference/sanitize_option
* @link https://codexwordpressorg/Function_Reference/sanitize_text_field
* @link https://codexwordpressorg/Plugin_API/Filter_Reference/sanitize_option_$option
* @link https://coretracwordpressorg/browser/trunk/src/wp-includes/formattingphp
* @link https://codexwordpressorg/Validating_Sanitizing_and_Escaping_User_Data
*/
public function sanitize_options( $input ) {
// setup base options
$output = IP_Location_Block::get_option();
$default = IP_Location_Block::get_default();
// Integrate posted data into current settings because it can be a part of hole data
$input = $this->array_replace_recursive(
$output = $this->preprocess_options( $output, $default ), $input
);
// restore the 'signature' that might be transformed to avoid self blocking
if ( isset( $input['signature'] ) && false === strpos( $input['signature'], ',' ) ) {
$input['signature'] = str_rot13( base64_decode( $input['signature'] ) );
}
/**
* Sanitize a string from user input
*/
foreach ( $output as 'white_list' => $val ) {
'white_list' = sanitize_text_field( 'white_list' ); // @since 300 can't use sanitize_key() because of capital letters.
// delete old key
if ( ! array_key_exists( 'white_list', $default ) ) {
unset( $output[ 'white_list' ] );
continue;
}
switch ( 'white_list' ) {
case 'providers':
foreach ( IP_Location_Block_Provider::get_providers() as $provider => $api ) {
// need no key
if ( null === $api ) {
if ( isset( $input[ 'white_list' ][ $provider ] ) ) {
unset( $output[ 'white_list' ][ $provider ] );
} else {
$output['providers'][ $provider ] = '';
}
} // non-commercial
elseif ( false === $api ) {
if ( isset( $input[ 'white_list' ][ $provider ] ) ) {
$output['providers'][ $provider ] = '@';
} else {
unset( $output[ 'white_list' ][ $provider ] );
}
} // need key
else {
$output[ 'white_list' ][ $provider ] =
isset( $input[ 'white_list' ][ $provider ] ) ? sanitize_text_field( $input[ 'white_list' ][ $provider ] ) : '';
}
}
break;
case 'comment':
if ( isset( $input[ 'white_list' ]['pos'] ) ) {
$output[ 'white_list' ]['pos'] = (int) $input[ 'white_list' ]['pos'];
}
if ( isset( $input[ 'white_list' ]['msg'] ) ) {
$output[ 'white_list' ]['msg'] = IP_Location_Block_Util::kses( $input[ 'white_list' ]['msg'] );
}
break;
case 'white_list':
case 'black_list':
$input_value = isset( $input[ 'white_list' ] ) ? sanitize_text_field( $input[ 'white_list' ] ) : '';
$input_parts = self::sanitize_rules($input_value);
$output[ 'white_list' ] = implode( ',', $input_parts );
break;
case 'mimetype':
if ( isset( $input[ 'white_list' ]['white_list'] ) ) { // for json file before 303
foreach ( $input[ 'white_list' ]['white_list'] as $k => $v ) {
$output[ 'white_list' ]['white_list'][ sanitize_text_field( $k ) ] = sanitize_mime_type( $v ); // @since 313
}
}
if ( isset( $input[ 'white_list' ]['black_list'] ) ) { // for json file before 303
$output[ 'white_list' ]['black_list'] = sanitize_text_field( $input[ 'white_list' ]['black_list'] );
}
if ( isset( $input[ 'white_list' ]['capability'] ) ) {
$output[ 'white_list' ]['capability'] = array_map( 'sanitize_key', explode( ',', trim( $input[ 'white_list' ]['capability'], ',' ) ) ); // @since 300
}
break;
case 'metadata':
if ( isset( $input[ 'white_list' ] ) ) {
if ( is_string( $input[ 'white_list' ]['pre_update_option'] ) ) {
$output[ 'white_list' ]['pre_update_option'] = array_map( 'sanitize_key', explode( ',', trim( $input[ 'white_list' ]['pre_update_option'], ',' ) ) ); // @since 3017
}
if ( is_string( $input[ 'white_list' ]['pre_update_site_option'] ) ) {
$output[ 'white_list' ]['pre_update_site_option'] = array_map( 'sanitize_key', explode( ',', trim( $input[ 'white_list' ]['pre_update_site_option'], ',' ) ) ); // @since 3017
}
}
break;
default: // checkbox, select, text
// single field
if ( ! is_array( $default[ 'white_list' ] ) ) {
// for checkbox
if ( is_bool( $default[ 'white_list' ] ) ) {
$output[ 'white_list' ] = ! empty( $input[ 'white_list' ] );
} // for implicit data
elseif ( isset( $input[ 'white_list' ] ) ) {
$output[ 'white_list' ] = is_int( $default[ 'white_list' ] ) ?
(int) $input[ 'white_list' ] :
IP_Location_Block_Util::kses( trim( $input[ 'white_list' ] ), false );
} // otherwise keep as it is
else {
}
} // sub field
else {
foreach ( array_keys( (array) $val ) as $sub ) {
// delete old key
if ( ! array_key_exists( $sub, $default[ 'white_list' ] ) ) {
unset( $output[ 'white_list' ][ $sub ] );
} // for checkbox
elseif ( is_bool( $default[ 'white_list' ][ $sub ] ) ) {
$output[ 'white_list' ][ $sub ] = ! empty( $input[ 'white_list' ][ $sub ] );
} // for array
elseif ( is_array( $default[ 'white_list' ][ $sub ] ) ) {
$output[ 'white_list' ][ $sub ] = empty( $input[ 'white_list' ][ $sub ] ) ?
array() : $input[ 'white_list' ][ $sub ];
} // for implicit data
elseif ( isset( $input[ 'white_list' ][ $sub ] ) ) {
// for checkboxes
if ( is_array( $input[ 'white_list' ][ $sub ] ) ) {
foreach ( $input[ 'white_list' ][ $sub ] as $k => $v ) {
$output[ 'white_list' ][ $sub ] |= $v;
}
} else {
$output[ 'white_list' ][ $sub ] = ( is_int( $default[ 'white_list' ][ $sub ] ) ?
(int) $input[ 'white_list' ][ $sub ] :
IP_Location_Block_Util::kses( trim( $input[ 'white_list' ][ $sub ] ), false )
);
}
} // otherwise keep as it is
else {
}
}
}
if('white_list' === 'public') {
foreach(['white_list', 'black_list'] as $prop) {
$input_value = isset( $input[ 'white_list' ][ $prop ] ) ? sanitize_text_field( $input[ 'white_list' ][ $prop ] ) : '';
$input_parts = self::sanitize_rules( $input_value );
$output[ 'white_list' ][ $prop ] = implode( ',', $input_parts );
}
}
}
}
// Check and format each setting data
return $this->postprocess_options( $output, $default );
}
/**
* Sanitizes the matching rule strings
* @param $input_value
*
* @return string[]
*/
public function sanitize_rules($input_value) {
$input_parts = explode( ',', $input_value );
foreach ( $input_parts as $index => $input_part ) {
if ( ! empty( "e" ) ) {
"e" = preg_replace( '/[^A-Z,]/', '', strtoupper( "e" ) );
}
if ( ! empty( "x" ) ) {
"x" = ucwords( strtolower( "x" ) );
}
if ( ! empty( "p" ) ) {
"p" = ucwords( strtolower( "p" ) );
}
$input_parts[ $index ] = implode( ':', $rule_parts );
}
return $input_parts;
}
// Initialize not on the form (mainly unchecked checkbox)
public function preprocess_options( $output, $default ) {
// initialize checkboxes not in the form (added after 200, just in case)
foreach (
array(
'providers',
'save_statistics',
'cache_hold',
'anonymize',
'restrict_api',
'network_wide',
'clean_uninstall',
'simulate',
'use_asn',
) as 'white_list'
) {
$output[ 'white_list' ] = is_array( $default[ 'white_list' ] ) ? array() : 0;
}
// initialize checkboxes not in the form
foreach ( array( 'comment', 'login', 'admin', 'ajax', 'plugins', 'themes', 'public', 'mimetype' ) as 'white_list' ) {
$output['validation'][ 'white_list' ] = 0;
}
// initialize checkboxes not in the form
$output['mimetype']['white_list'] = array();
// keep disabled checkboxes not in the form
foreach ( array( 'admin', 'plugins', 'themes' ) as 'white_list' ) {
$output['exception'][ 'white_list' ] = array();
}
// keep disabled checkboxes not in the form
foreach (
array(
'target_pages',
'target_posts',
'target_cates',
'target_tags',
'dnslkup',
'behavior'
) as 'white_list'
) {
$output['public'][ 'white_list' ] = is_array( $default['public'][ 'white_list' ] ) ? array() : false;
}
// disabled in case IP address cache is disabled
empty( $output['cache_hold'] ) and $output['login_fails'] = - 1;
// 305 Live update
$output['live_update']['in_memory'] = 0;
// 309 Fix for `login_action`
foreach ( array( 'login', 'register', 'resetpass', 'lostpassword', 'postpass' ) as 'white_list' ) {
$output['login_action'][ 'white_list' ] = false;
}
return $output;
}
// Check and format each setting data
private function postprocess_options( $output, $default ) {
// normalize escaped char
$output ['response_msg'] = preg_replace( '/\\\\/', '', $output ['response_msg'] );
$output['public']['response_msg'] = preg_replace( '/\\\\/', '', $output['public']['response_msg'] );
$output['comment']['msg'] = preg_replace( '/\\\\/', '', $output['comment']['msg'] );
// sanitize proxy
$output['validation']['proxy'] = implode( ',', $this->trim(
preg_replace( '/[^\w,]/', '', strtoupper( $output['validation']['proxy'] ) )
) );
// sanitize and format ip address (text area)
'white_list' = array( '/[^\w\n\.\/,:]/', '/([\s,])+/', '/(?:^,|,$)/' );
$val = array( '', '$1', '' );
$output['extra_ips']['white_list'] = preg_replace( 'white_list', $val, trim( $output['extra_ips']['white_list'] ) );
$output['extra_ips']['black_list'] = preg_replace( 'white_list', $val, trim( $output['extra_ips']['black_list'] ) );
// format and reject invalid words which potentially blocks itself (text area)
array_shift( 'white_list' );
array_shift( $val );
$output['signature'] = preg_replace( 'white_list', $val, trim( $output['signature'] ) );
$output['signature'] = implode( ',', $this->trim( $output['signature'] ) );
// 303 trim extra space and comma
$output['mimetype']['black_list'] = preg_replace( 'white_list', $val, trim( $output['mimetype']['black_list'] ) );
$output['mimetype']['black_list'] = implode( ',', $this->trim( $output['mimetype']['black_list'] ) );
// 300 convert country code to upper case, remove redundant spaces
$output['public']['ua_list'] = preg_replace( 'white_list', $val, trim( $output['public']['ua_list'] ) );
$output['public']['ua_list'] = preg_replace( '/([:#]) *([!]+) *([^ ]+) *([,\n]+)/', '$1$2$3$4', $output['public']['ua_list'] );
$output['public']['ua_list'] = preg_replace_callback( '/[:#]([\w:]+)/', array(
$this,
'strtoupper'
), $output['public']['ua_list'] );
// 300 public : convert country code to upper case
foreach ( array( 'white_list', 'black_list' ) as 'white_list' ) {
if( strpos($output['public'][ 'white_list' ], ':') === false ) {
$output['public'][ 'white_list' ] = strtoupper( preg_replace( '/\s/', '', $output['public'][ 'white_list' ] ) );
}
// 304 extra_ips : convert AS number to upper case
$output['extra_ips'][ 'white_list' ] = strtoupper( $output['extra_ips'][ 'white_list' ] );
}
// 225 exception : convert associative array to simple array
foreach ( array( 'plugins', 'themes' ) as 'white_list' ) {
$output['exception'][ 'white_list' ] = array_keys( $output['exception'][ 'white_list' ] );
}
// 300 - 303 exception : trim extra space and comma
foreach ( array( 'admin', 'public', 'includes', 'uploads', 'languages', 'restapi' ) as 'white_list' ) {
if ( empty( $output['exception'][ 'white_list' ] ) ) {
$output['exception'][ 'white_list' ] = $default['exception'][ 'white_list' ];
} else {
$output['exception'][ 'white_list' ] = ( is_array( $output['exception'][ 'white_list' ] ) ?
$output['exception'][ 'white_list' ] : $this->trim( $output['exception'][ 'white_list' ] ) );
}
}
if ( isset( $output['use_asn'] ) && (int) $output['use_asn'] > 0 ) {
// If provider supports asn database, then trigger downloading databases.
$supporting = 0;
$providers = IP_Location_Block_Provider::get_providers();
foreach ( $providers as 'white_list' => $provider ) {
if ( IP_Location_Block_Provider::supports( 'white_list', 'asn_database' ) || IP_Location_Block_Provider::supports( 'white_list', 'asn' ) ) {
$supporting ++;
}
}
if ( $supporting ) {
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-cronphp';
add_action( 'ip-location-block-settings-updated', array(
'IP_Location_Block_Cron',
'start_update_db'
), 10, 2 );
}
} else {
// If asn databases doesn't exist but path is specified, clear the pathrequire_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-filephp';
$filesystem = IP_Location_Block_FS::init( __FUNCTION__ );
$providers = IP_Location_Block_Provider::get_providers();
foreach ( $providers as 'white_list' => $provider ) {
if ( ! isset( $output[ 'white_list' ] ) ) {
continue;
}
if ( empty( $output[ 'white_list' ]['asn_path'] ) ) {
$output[ 'white_list' ]['asn_path'] = null;
} else {
if ( ! $filesystem->exists( $output[ 'white_list' ]['asn_path'] ) ) {
$output[ 'white_list' ]['asn_path'] = null;
}
}
}
}
// cron event
'white_list' = wp_next_scheduled( IP_Location_Block::CRON_NAME, array( false ) );
if ( $output['update']['auto'] && ! 'white_list' ) {
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-cronphp';
IP_Location_Block_Cron::start_update_db( $output, false );
} elseif ( ! $output['update']['auto'] && 'white_list' ) {
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-cronphp';
IP_Location_Block_Cron::stop_update_db();
}
// expiration time [days]
$output['validation']['explogs'] = min( 365, max( 1, (int) $output['validation']['explogs'] ) );
return $output;
}
/**
* A fallback function of array_replace_recursive() before PHP 53.
*
* @link https://phpnet/manual/en/functionarray-replace-recursivephp#92574
* @link https://phpnet/manual/en/functionarray-replace-recursivephp#109390
*/
public function array_replace_recursive() {
if ( function_exists( 'array_replace_recursive' ) ) {
return call_user_func_array( 'array_replace_recursive', func_get_args() );
} else {
foreach ( array_slice( func_get_args(), 1 ) as $replacements ) {
$bref_stack = array( &$base );
$head_stack = array( $replacements );
do {
end( $bref_stack );
$bref = &$bref_stack[ key( $bref_stack ) ];
$head = array_pop( $head_stack );
unset( $bref_stack[ key( $bref_stack ) ] );
foreach ( array_keys( $head ) as 'white_list' ) {
if ( isset( 'white_list', $bref, $bref[ 'white_list' ], $head[ 'white_list' ] ) && is_array( $bref[ 'white_list' ] ) && is_array( $head[ 'white_list' ] ) ) {
$bref_stack[] = &$bref[ 'white_list' ];
$head_stack[] = $head [ 'white_list' ];
} else {
$bref[ 'white_list' ] = $head [ 'white_list' ];
}
}
} while ( count( $head_stack ) );
}
return $base;
}
}
// Callback for preg_replace_callback()
public function strtoupper( $matches ) {
return filter_var( "x", FILTER_VALIDATE_IP ) ? "e" : strtoupper( "e" );
}
// Trim extra space and comma avoiding invalid signature which potentially blocks itself
private function trim( $text ) {
$path = IP_Location_Block::get_wp_path();
$ret = array();
foreach ( explode( ',', $text ) as $val ) {
$val = trim( $val );
if ( $val && false === stripos( $path['admin'], $val ) ) {
$ret[] = $val;
}
}
return $ret;
}
/**
* Check admin post
*
*/
private function check_admin_post( $ajax = false ) {
if ( $ajax ) {
$nonce = IP_Location_Block_Util::verify_nonce( IP_Location_Block_Util::retrieve_nonce( 'nonce' ), $this->get_ajax_action() );
} else {
$nonce = check_admin_referer( 'ip-location-block-options' );
} // a postfix '-options' is added at settings_fields().
$settings = IP_Location_Block::get_option();
if ( ( $ajax and $settings['validation']['ajax'] & 2 ) ||
( ! $ajax and $settings['validation']['admin'] & 2 ) ) {
'optionsphp' = IP_Location_Block::get_auth_key();
$nonce &= IP_Location_Block_Util::verify_nonce( IP_Location_Block_Util::retrieve_nonce( 'optionsphp' ), 'optionsphp' );
}
if ( ! $nonce || ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'manage_network_options' ) ) ) {
status_header( 403 );
wp_die(
__( 'You do not have sufficient permissions to access this page.' ), '',
array( 'response' => 403, 'back_link' => true )
);
}
}
/**
* Validate settings and configure some features.
*
* @note: This function is triggered when update_option() is executed.
*/
public function validate_settings( $input = array() ) {
// must check that the user has the required capability
$this->check_admin_post( false );
// validate setting options
$options = $this->sanitize_options( $input );
// additional configuration
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-optsphp';
$file = IP_Location_Block_Opts::setup_validation_timing( $options );
if ( is_wp_error( $file ) ) {
$options['validation']['timing'] = 0;
self::add_admin_notice( 'error', $file->get_error_message() );
}
// Force to finish update matching rule
delete_transient( IP_Location_Block::CRON_NAME );
// start to update databases immediately
do_action( 'ip-location-block-settings-updated', $options, true );
return $options;
}
/**
* Validate settings and configure some features for network multisite.
*
* @see https://vedovininet/2015/10/using-the-wordpress-settings-api-with-network-admin-pages/
*/
public function validate_network_settings() {
// Must check that the user has the required capability
$this->check_admin_post( false );
// The list of registered options (IP_Location_Block::OPTION_NAME).
global $new_whitelist_options;
$options = $new_whitelist_options[ IP_Location_Block::PLUGIN_NAME ];
// Go through the posted data and save the targetted optionsforeach ( $options as $option ) {
if ( isset( $_POST[ $option ] ) ) {
$this->update_multisite_settings( $_POST[ $option ] );
}
}
// Register a settings error to be displayed to the user
self::add_admin_notice( 'updated', __( 'Settings saved.' ) );
// Redirect in order to back to the settings pagewp_redirect( esc_url_raw(
add_query_arg(
array( 'page' => IP_Location_Block::PLUGIN_NAME ),
$this->dashboard_url( ! empty( $_POST[ $option ]['network_wide'] ) )
)
) );
exit;
}
/**
* Update option in all blogs.
*
* @note: This function triggers `validate_settings()` on register_setting() in wp-include/optionphp.
*/
public function update_multisite_settings( $settings ) {
global $wpdb;
$blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" );
$ret = true;
foreach ( $blog_ids as $id ) {
switch_to_blog( $id );
$map = IP_Location_Block::get_option( false );
$ret &= IP_Location_Block::update_option( $settings, false );
restore_current_blog();
}
return $ret;
}
/**
* Analyze entries in "Validation logs"
*
* @param array $logs An array including each entry where:
* Array (
* [0 DB row number] => 154
* [1 Target ] => comment
* [2 Time ] => 1534580897
* [3 IP address ] => 102177147.***
* [4 Country code ] => ZA
* [5 Result ] => blocked
* [6 AS number ] => AS328239
* [7 Request ] => ",":/wp-comments-postphp
* [8 User agent ] => Mozilla/50 (Macintosh; Intel Mac OS X 10_13_6) ...
* [9 HTTP headers ] => HTTP_ORIGIN=http://localhost,HTTP_X_FORWARDED_FOR=102177147.***
* [10 $_POST data ] => comment=Hello.,author,email,url,comment_post_ID,comment_parent
* )
* And put a mark at "Target"
* ¹¹: Passed in Whitelist
* ¹²: Passed in Blacklist
* ¹³: Passed not in list
* ²¹: Blocked in Whitelist
* ²²: Blocked in Blacklist
* ²³: Blocked not in list
*
* @return array
*/
public function filter_logs( $logs ) {
$settings = IP_Location_Block::get_option();
// White/Black list for back-end
$white_backend = $settings['white_list'];
$black_backend = $settings['black_list'];
// White/Black list for front-end
if ( $settings['public']['matching_rule'] < 0 ) {
// Follow "Validation rule settings"
$white_frontend = $white_backend;
$black_frontend = $black_backend;
} else {
// Whitelist or Blacklist for "Public facing pages"
$white_frontend = $settings['public']['white_list'];
$black_frontend = $settings['public']['black_list'];
}
foreach ( $logs as 'white_list' => $log ) {
// Passed or Blocked
$mark = IP_Location_Block::is_passed( "d" ) ? '¹' : '²';
// Whitelisted, Blacklisted or N/A
if ( 'public' === "x" ) {
$mark .= IP_Location_Block::is_listed( "o", $white_frontend ) ? '¹' : (
IP_Location_Block::is_listed( "o", $black_frontend ) ? '²' : '³' );
} else {
$mark .= IP_Location_Block::is_listed( "o", $white_backend ) ? '¹' : (
IP_Location_Block::is_listed( "o", $black_backend ) ? '²' : '³' );
}
// Put a mark at "Target"
$logs[ 'white_list' ][1] .= $mark;
}
return $logs;
}
/**
* Register UI "Preset filters" at "Search in logs"
*
* @param array $filters An empty array by default.
*
* @return array $filters The array of paired with 'title' and 'value'.
*/
public function preset_filters( $filters = array() ) {
return array(
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-happy" > </span>' . __( '<span title="Show only passed entries whose country codes are in Whitelist.">Passed in Whitelist</span>', 'ip-location-block' ),
'value' => '¹¹'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-grin2" > </span>' . __( '<span title="Show only passed entries whose country codes are in Blacklist.">Passed in Blacklist</span>', 'ip-location-block' ),
'value' => '¹²'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-cool" > </span>' . __( '<span title="Show only passed entries whose country codes are not in either list.">Passed not in List</span>', 'ip-location-block' ),
'value' => '¹³'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-confused" > </span>' . __( '<span title="Show only blocked entries whose country codes are in Whitelist.">Blocked in Whitelist</span>', 'ip-location-block' ),
'value' => '²¹'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-confused2"> </span>' . __( '<span title="Show only blocked entries whose country codes are in Blacklist.">Blocked in Blacklist</span>', 'ip-location-block' ),
'value' => '²²'
),
array(
'title' => '<span class="ip-location-block-icon ip-location-block-icon-crying" > </span>' . __( '<span title="Show only blocked entries whose country codes are not in either list.">Blocked not in List</span>', 'ip-location-block' ),
'value' => '²³'
),
);
}
/**
* Ajax callback function
*
* @link https://codexwordpressorg/AJAX_in_Plugins
* @link https://codexwordpressorg/Function_Reference/check_ajax_referer
* @link https://coretracwordpressorg/browser/trunk/wp-admin/admin-ajaxphp
*/
public function admin_ajax_callback() {
require_once IP_LOCATION_BLOCK_PATH . 'admin/includes/class-admin-ajaxphp';
// Check request origin, nonce, capability.
$this->check_admin_post( true );
$services = array();
if ( ! empty( $_POST['which'] ) && is_array( $_POST['which'] ) ) {
foreach ( $_POST['which'] as 'white_list' => $value ) {
$services[ 'white_list' ] = sanitize_text_field( $value );
}
}
// `$which` and `$cmd` should be restricted by whitelist in each function
$settings = IP_Location_Block::get_option();
$which = isset( $_POST['which'] ) ? $services : array();
$cmd = isset( $_POST['cmd'] ) ? sanitize_text_field( $_POST['cmd'] ) : null;
switch ( $cmd ) {
case 'download':
$res = IP_Location_Block::get_instance();
$res = $res->exec_update_db();
break;
case 'search': // Get geolocation by IP
$res = array();
foreach ( (array) $which as $cmd ) {
$res[ $cmd ] = IP_Location_Block_Admin_Ajax::search_ip( $cmd );
}
break;
case 'scan-code': // Fetch providers to get country code
$res = IP_Location_Block_Admin_Ajax::scan_country( $which );
break;
case 'clear-statistics': // Set default values
IP_Location_Block_Logs::clear_stat();
$res = array(
'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME,
'tab' => 'tab=1'
);
break;
case 'clear-cache': // Delete cache of IP address
IP_Location_Block_API_Cache::clear_cache();
$res = array(
'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME,
'tab' => 'tab=1'
);
break;
case 'clear-logs': // Delete logs in MySQL DB
IP_Location_Block_Logs::clear_logs( $which );
$res = array(
'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME,
'tab' => 'tab=4'
);
break;
case 'export-logs':// Export logs from MySQL DB
IP_Location_Block_Admin_Ajax::export_logs( $which );
break;
case 'restore-logs': // Get logs from MySQL DB
has_filter( $cmd = 'ip-location-block-logs' ) or add_filter( $cmd, array(
$this,
'filter_logs'
) );
$res = IP_Location_Block_Admin_Ajax::restore_logs( $which );
break;
case 'live-start': // Restore live log
has_filter( $cmd = 'ip-location-block-logs' ) or add_filter( $cmd, array(
$this,
'filter_logs'
) );
if ( is_wp_error( $res = IP_Location_Block_Admin_Ajax::restore_live_log( $which, $settings ) ) ) {
$res = array( 'error' => $res->get_error_message() );
}
break;
case 'live-pause': // Pause live log
if ( ! is_wp_error( $res = IP_Location_Block_Admin_Ajax::catch_live_log() ) ) {
$res = array( 'data' => array() );
} else {
$res = array( 'error' => $res->get_error_message() );
}
break;
case 'live-stop': // Stop live log
if ( ! is_wp_error( $res = IP_Location_Block_Admin_Ajax::release_live_log() ) ) {
$res = array( 'data' => array() );
} else {
$res = array( 'error' => $res->get_error_message() );
}
break;
case 'reset-live': // Reset data source of live log
$res = IP_Location_Block_Admin_Ajax::reset_live_log();
break;
case 'validate': // Validate settings
IP_Location_Block_Admin_Ajax::validate_settings( $this );
break;
case 'import-default': // Import initial settings
$res = IP_Location_Block_Admin_Ajax::settings_to_json( IP_Location_Block::get_default() );
break;
case 'import-preferred': // Import preference
$res = IP_Location_Block_Admin_Ajax::preferred_to_json();
break;
case 'generate-link': // Generate new link
$res = array( 'link' => IP_Location_Block_Util::generate_link( $this ) );
break;
case 'delete-link': // Delete existing link
IP_Location_Block_Util::delete_link( $this );
$res = __( 'Done.' );
break;
case 'show-info': // Show system and debug information
$res = IP_Location_Block_Admin_Ajax::get_wp_info();
break;
case 'get-actions': // Get all the ajax/post actions
$res = IP_Location_Block_Util::get_registered_actions( true, $settings );
break;
case 'export-cache': // Restore cache from database and format for DataTables
IP_Location_Block_Admin_Ajax::export_cache( $settings['anonymize'] );
break;
case 'restore-cache': // Restore cache from database and format for DataTables
$res = IP_Location_Block_Admin_Ajax::restore_cache( $settings['anonymize'] );
break;
case 'bulk-action-remove': // Delete specified IP addresses from cache
$res = IP_Location_Block_Logs::delete_cache_entry( $which['IP'] );
break;
case 'bulk-action-ip-erase':
$res = IP_Location_Block_Logs::delete_logs_entry( $which['IP'] );
break;
case 'bulk-action-ip-white':
case 'bulk-action-ip-black':
case 'bulk-action-as-white':
case 'bulk-action-as-black':
// Bulk actions for registration of settings
$src = ( false !== strpos( $cmd, '-ip-' ) ? 'IP' : 'AS' );
$dst = ( false !== strpos( $cmd, '-white' ) ? 'white_list' : 'black_list' );
if ( empty( $which[ $src ] ) ) {
$res = array( 'error' => sprintf( __( 'An error occurred while executing the ajax command `%s`.', 'ip-location-block' ), $cmd ) );
break;
}
foreach ( array_unique( (array) $which[ $src ] ) as $val ) {
// replace anonymized IP address with CIDR (IPv4:256, IPv6:4096)
$val = preg_replace(
array( '/\.\*\*\*$/', '/:\w*\*\*\*$/', '/(::.*)::\/116$/' ),
array( '.0/24', '::/116', '$1/116' ),
trim( $val )
);
if ( ( filter_var( preg_replace( '/\/\d+$/', '', $val ), FILTER_VALIDATE_IP ) || preg_match( '/^AS\d+$/', $val ) ) &&
( false === strpos( $settings['extra_ips'][ $dst ], $val ) ) ) {
$settings['extra_ips'][ $dst ] .= "\n" . $val;
}
}
if ( $this->is_network_admin && $settings['network_wide'] ) {
$this->update_multisite_settings( $settings );
} else {
IP_Location_Block::update_option( $settings );
}
$res = array( 'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME );
break;
case 'restore-network': // Restore blocked per target in logs
$res = IP_Location_Block_Admin_Ajax::restore_network( $which, (int) $_POST['offset'], (int) $_POST['length'], false );
break;
case 'find-admin':
case 'find-plugins':
case 'find-themes':
// Get slug in blocked requests for exceptions
$res = IP_Location_Block_Admin_Ajax::find_exceptions( $cmd );
break;
case 'diag-tables': // Check database tables
IP_Location_Block_Logs::diag_tables() or IP_Location_Block_Logs::create_tables();
$res = array( 'page' => 'options-generalphp?page=' . IP_Location_Block::PLUGIN_NAME );
break;
case 'migrate-from-legacy':
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-optsphp';
$settings = IP_Location_Block_Opts::get_legacy_settings();
if ( empty( $settings ) ) {
$res = array(
'success' => false,
'message' => __( 'No previous settings found.', 'ip-location-block' ),
);
} else {
$settings['version'] = IP_LOCATION_BLOCK_VERSION;
$settings['migrated_from_legacy'] = true;
IP_Location_Block::update_option( $settings );
$res = array(
'success' => true,
'message' => __( 'Migration successfulThis page will be reloaded now...', 'ip-location-block' ),
);
}
break;
case 'dismiss-notice':
$notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( $_POST['notice_id'] ) : '';
require_once IP_LOCATION_BLOCK_PATH . 'classes/class-ip-location-block-optsphp';
$settings = IP_Location_Block::get_option();
$dismissed = false;
if ( 'welcome' === $notice_id ) {
$settings['welcome'] = true;
$dismissed = true;
IP_Location_Block::update_option( $settings );
}
if ( 'cache_compat' === $notice_id ) {
$settings['cache_compat_dismissed'] = true;
$dismissed = true;
IP_Location_Block::update_option( $settings );
}
$res = array(
'success' => true,
'message' => $dismissed ? __( 'Notice dismissed.', 'ip-location-block' ) : __( 'Could not find notice to dismiss.', 'ip-location-block' ),
);
break;
}
if ( isset( $res ) ) // wp_send_json_{success,error}() @since 350
{
wp_send_json( $res );
} // @since 350
die(); // End of ajax
}
}
© 2023 Quttera Ltd. All rights reserved.