IP Geo Block - Version 3.0.4.6

Version Description

  • Bug fix: Fix the issue that the emergent functionality didn't work when the number of login attempts reached to the limit.
  • Bug fix: Fix the issue that the result would be always limited when "Max number of failed login attempts per IP address" is "Disabled".
Download this release

Release Info

Developer tokkonopapa
Plugin Icon 128x128 IP Geo Block
Version 3.0.4.6
Comparing to
See all releases

Code changes from version 3.0.3.4 to 3.0.4.6

README.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: tokkonopapa
3
Donate link:
4
Tags: security, firewall, brute force, vulnerability, login, wp-admin, admin, ajax, xmlrpc, comment, pingback, trackback, spam, IP address, geo, geolocation, buddypress, bbPress
5
Requires at least: 3.7
6
- Tested up to: 4.8
7
- Stable tag: 3.0.3.4
8
License: GPLv2 or later
9
License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
@@ -12,42 +12,42 @@ It blocks spam posts, login attempts and malicious access to the back-end reques
12
13
== Description ==
14
15
- A considerable number of WordPress vulnerabilities in plugins and themes have been disclosed every month. You can easily find them at [WPScan Vulnerability Database](https://wpvulndb.com/ "WPScan Vulnerability Database") and [Exploits Database](https://www.exploit-db.com/ "Exploits Database by Offensive Security"). It means that we're always exposed to the threats of being exploited caused by those vulnerabilities.
16
17
- This plugin protects your site against such threats of attack against the back-end of your site such as login form, XML-RPC (login attempt) and admin area. It also blocks undesired comment spam, trackback and pingback spam and any requests to public facing pages aka front-end from undesired countries.
18
19
After several days of installation, you'll be supprised to find many malicious or undesirable accesses are blocked especially if you enable Zero-day Expoit Prevention.
20
21
= Features =
22
23
* **Immigration control:**
24
- Access to the basic and important entrances into the back-end such as `wp-comments-post.php`, `xmlrpc.php`, `wp-login.php`, `wp-signup.php`, `wp-admin/admin.php`, `wp-admin/admin-ajax.php`, `wp-admin/admin-post.php` will be validated by means of a country code based on IP address. It allows you to configure either whitelist or blacklist to specify the countires.
25
26
* **Zero-day Exploit Prevention:**
27
- Unlike other security plugins and firewalls based on attack patterns, the original feature "**W**ord**P**ress **Z**ero-day **E**xploit **P**revention" (WP-ZEP) is focused on vulnerability patterns. It is simple but still smart and strong enough to block any malicious accesses to `wp-admin/*.php`, `plugins/*.php` and `themes/*.php` even from the permitted countries. It will protect your site against certain types of attack such as CSRF, LFI, SQLi, XSS and so on, **even if you have some vulnerable plugins and themes in your site**.
28
29
* **Guard against login attempts:**
30
In order to prevent hacking through the login form and XML-RPC by brute-force and the reverse-brute-force attacks, the number of login attempts will be limited per IP address even from the permitted countries.
31
32
* **Minimize server load against brute-force attacks:**
33
- You can configure this plugin as a [Must Use Plugins](https://codex.wordpress.org/Must_Use_Plugins "Must Use Plugins « WordPress Codex") which would be loaded prior to regular plugins and can massively [reduce the load on server](http://www.ipgeoblock.com/codex/validation-timing.html "Validation timing | IP Geo Block").
34
35
* **Prevent malicious down/uploading:**
36
- A malicious request such as exposing `wp-config.php` and uploading undesired files via vulnerable plugins or themes can be blocked.
37
38
* **Support of BuddyPress and bbPress:**
39
- You can configure this plugin such that a registered user can login as the membership from anywhere, but a request such as a new user registration, lost password, creating a new topic, and subscribing comment is blocked by the country code. It is suitable for [BuddyPress](https://wordpress.org/plugins/buddypress/ "BuddyPress — WordPress Plugins") and [bbPress](https://wordpress.org/plugins/bbpress/ "WordPress bbPress « WordPress Plugins") to help reducing spams.
40
41
* **Referrer suppressor for external links:**
42
When you click an external hyperlink on admin screens, http referrer will be eliminated to hide a footprint of your site.
43
44
* **Multiple source of IP Geolocation databases:**
45
- [MaxMind GeoLite free databases](http://www.maxmind.com "MaxMind - IP Geolocation and Online Fraud Prevention") and [IP2Location LITE databases](http://www.ip2location.com/ "IP Address Geolocation to Identify Website Visitor's Geographical Location") can be installed in this plugin. Those will be downloaded and updated (once a month) automatically. Also free Geolocation REST APIs and whois information can be available for audit purposes.
46
- Father more, if you use CloudFlare or CloudFront as a reverse proxy service, you can get [dedicated API class libraries](http://www.ipgeoblock.com/article/api-class-library.html "CloudFlare & CloudFront API class library | IP Geo Block") for these services.
47
48
* **Customizing response:**
49
HTTP response code can be selectable as `403 Forbidden` to deny access pages, `404 Not Found` to hide pages or even `200 OK` to redirect to the top page.
50
- You can also have the custom error page (for example `403.php`) in your theme template directory or child theme directory to fit your theme.
51
52
* **Validation logs:**
53
Validation logs can be recorded with useful information to audit attack patterns.
@@ -107,7 +107,10 @@ or following descriptions for your best setup.
107
Specify the country code with two letters (see [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements "ISO 3166-1 alpha-2 - Wikipedia, the free encyclopedia")). Each of them should be separated by comma.
108
109
* **White/Black list of extra IPs for prior validation**
110
- The list of extra IP addresses prior to the validation of country code. [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing "Classless Inter-Domain Routing - Wikipedia, the free encyclopedia") is acceptable to specify the range.
111
112
* **$_SERVER keys for extra IPs**
113
Additional IP addresses will be validated if some of keys in `$_SERVER` variable are specified in this textfield. Typically `HTTP_X_FORWARDED_FOR`.
@@ -143,10 +146,10 @@ or following descriptions for your best setup.
143
Validate access to `wp-admin/admin-(ajax|post)*.php`.
144
145
* **Plugins area**
146
- Validate direct access to plugins. Typically `wp-content/plugins/…/*.php`.
147
148
* **Themes area**
149
- Validate direct access to themes. Typically `wp-content/themes/…/*.php`.
150
151
= Front-end target settings =
152
@@ -273,15 +276,15 @@ You can find the "**Emergent Functionality**" code section near the bottom of `i
273
* How to use: Activate the following code and upload this file via FTP.
274
*/
275
/* -- ADD '/' TO THE TOP OR END OF THIS LINE TO ACTIVATE THE FOLLOWINGS -- */
276
- function ip_geo_block_emergency( $validate ) {
277
$validate['result'] = 'passed';
278
return $validate;
279
}
280
- add_filter( 'ip-geo-block-login', 'ip_geo_block_emergency' );
281
- add_filter( 'ip-geo-block-admin', 'ip_geo_block_emergency' );
282
// */`
283
284
- Please not that you have to use an [appropriate editor](https://codex.wordpress.org/Editing_Files#Using_Text_Editors "Editing Files « WordPress Codex").
285
286
After saving and uploading it to `/wp-content/plugins/ip-geo-block/` on your server via FTP, you become to be able to login again as an admin.
287
@@ -349,6 +352,49 @@ Please refer to "[How can I fix permission troubles?](http://www.ipgeoblock.com/
349
350
== Changelog ==
351
352
= 3.0.3.4 =
353
* **Improvement:** Some minor refactoring for the future release.
354
* **Improvement:** Better throughput against attacks on admin area when `"mu-plugins" (ip-geo-block-mu.php)` is enable.
@@ -489,14 +535,14 @@ This is a maintenance release addressing some issues.
489
* **Improvement:** Support clean uninstall for network / multisite.
490
* **Improvement:** Improve the compatibility of downloading IP address databases for Microsoft IIS.
491
* **Bug fix:** Support `FORCE_SSL_ADMIN`.
492
- * **Bug fix:** Fix the issue of [@](https://wordpress.org/support/topic/compatibility-with-ag-custom-admin "WordPress Support » Compatibility with AG Custom Admin") and change the option name "**Important files**" to "**Bad signatures in query**" to avoid misuse.
493
- * **Bug fix:** Fix the issue of [@](https://wordpress.org/support/topic/gb-added-to-whitelist "WordPress Support » GB added to whitelist") which might be caused by some race condition.
494
* **Bug fix:** Fix the issue of restoring post revisions which was blocked.
495
496
= 2.2.4.1 =
497
Sorry for frequent updating.
498
499
- * **Bug fix:** Fixed the issue of `Warning: strpos(): Empty needle in...` that was reported in [@](https://wordpress.org/support/topic/version-224-produces-warning-message "WordPress Support » Version 2.2.4 Produces Warning Message") and [@](https://wordpress.org/support/topic/error-after-update-to-newest-version "WordPress › Support » Error after Update to newest version").
500
501
= 2.2.4 =
502
* **Bug fix:** Fixed the issue that some links on network admin of multisite were blocked when WP-ZEP for `admin area` or `admin ajax/post` was enabled.
@@ -553,7 +599,7 @@ Sorry for frequent update.
553
* **Improvement:** Improved connectivity with Jetpack.
554
* **Improvement:** Improved immediacy of downloading databases at upgrading.
555
* **Improvement:** Replaced a terminated RESTful API service with a new stuff.
556
- * **Bug fix:** Fixed issue that clicking a link tag without href always refreshed the page. Thanks to [wyclef](https://wordpress.org/support/topic/conflict-with-menu-editor-plugin "WordPress Support » Conflict with Menu Editor plugin?").
557
* **Bug fix:** Fixed issue that deactivating and activating repeatedly caused to show the welcome message.
558
* **Bug fix:** Fixed issue that a misaligned argument in the function caused 500 internal server error when a request to the php files in plugins/themes area was rewrited to `rewrite.php`.
559
@@ -565,25 +611,25 @@ Sorry for frequent update.
565
= 2.2.0 =
566
* **Important:** Now **Block by country** and **Prevent Zero-day Exploit** become to work independently on **Admin area**, **Admin ajax/post** at **Validation target settings**. Please reconfirm them.
567
* **Important:** Previously, a request whose country code can't be available was always blocked. But from this release, such a request is considered as comming from the country whose code is `ZZ`. It means that you can put `ZZ` into the white list and black list.
568
- * **New feature:** White list and Black list of extra IP addresses prior to the validation of country code. Thanks to Fabiano for good suggestions at [support forum](https://wordpress.org/support/topic/white-list-of-ip-addresses-or-ranges "WordPress Support » White list of IP addresses or ranges?")
569
* **New feature:** Malicious signatures to prevent disclosing the important files via vulnerable plugins or themes. A malicious request to try to expose `wp-config.php` or `passwd` can be blocked.
570
* **New feature:** Add privacy considerations related to IP address. Add **Anonymize IP address** at **Record settings**.
571
* **Bug fix:** Fix the issue that spaces in **Text message on comment form** are deleted.
572
* See details at [2.2.0 release note](http://www.ipgeoblock.com/changelog/release-2.2.0.html "2.2.0 Release Note").
573
574
= 2.1.5.1 =
575
- * **Bug fix:** Fixed the issue that the Blacklist did not work properly. Thanks to TJayYay for reporting this issue at [support forum](https://wordpress.org/support/topic/hackers-from-country-in-blocked-list-of-countries-trying-to-login "WordPress Support » Hackers from country in Blocked List of Countries trying to login").
576
577
= 2.1.5 =
578
- * **Enhancement:** Enforce preventing self blocking at the first installation. And add the scan button to get all the country code using selected API. Thanks to **Nils** for a nice idea at [support forum](https://wordpress.org/support/topic/locked-out-due-to-eu-vs-country "WordPress Support » Locked out due to EU vs. Country").
579
* **New feature:** Add pie chart to display statistics of "Blocked by country".
580
* **Enhancement:** WP-ZEP is reinforced against CSRF.
581
* **Bug fix:** Fix illegal handling of the fragment in a link.
582
* See details at [2.1.5 release note](http://www.ipgeoblock.com/changelog/release-2.1.5.html "2.1.5 Release Note").
583
584
= 2.1.4 =
585
- * **Bug fix:** Fix the issue that this plugin broke functionality of a certain plugin. Thanks to **opsec** for reporting this issue at [support forum](https://wordpress.org/support/topic/blocks-saves-in-types-or-any-plugins-from-wp-typescom "WordPress Support » Blocks saves in Types or any plugins from wp-types.com").
586
- * **Improvement:** Add checking process for validation rule to prevent being blocked itself. Thanks to **internationals** for proposing at [support forum](https://wordpress.org/support/topic/locked-out-due-to-eu-vs-country "WordPress Support » Locked out due to EU vs. Country")
587
* **Improvement:** Arrage the order of setting sections to focus the goal of this plugin.
588
* See details at [2.1.4 release note](http://www.ipgeoblock.com/changelog/release-2.1.4.html "2.1.4 Release Note").
589
@@ -601,7 +647,7 @@ This is a maintenance release.
601
602
* **Bug fix:** Fix the issue that the login-fail-counter didn't work when the validation at `Login form` was `block by country (register, lost password)`. In this release, the login-fail-counter works correctly.
603
* **Bug fix:** Fix the issue that the validation settings of `Admin area` and `Admin ajax/post` were influential with each other. Now each of those works individually.
604
- * **Bug fix:** "Site Stats" of Jetpack is now shown on the admin bar which issue was reported on [support forum](https://wordpress.org/support/topic/admin-area-prevent-zero-day-exploit-incompatible-with-jetpack-site-stats-in-a "WordPress Support » Admin area - Prevent zero-day exploit: Incompatible with Jetpack Site Stats in A").
605
* **Improvement:** Hide checking the existence of log db behind the symbol `IP_GEO_BLOCK_DEBUG` to reduce 1 query on admin screen.
606
* **Improvement:** Add alternative functions of BCMath extension to avoid `PHP Fatal error: Call to undefined function` in `IP2Location.php` when IPv6 is specified.
607
* **Improvement:** Use MaxMind database at the activating process not to be locked out by means of inconsistency of database at the activation and after.
3
Donate link:
4
Tags: security, firewall, brute force, vulnerability, login, wp-admin, admin, ajax, xmlrpc, comment, pingback, trackback, spam, IP address, geo, geolocation, buddypress, bbPress
5
Requires at least: 3.7
6
+ Tested up to: 4.8.2
7
+ Stable tag: 3.0.4.6
8
License: GPLv2 or later
9
License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
12
13
== Description ==
14
15
+ A considerable number of WordPress vulnerabilities in plugins and themes have been disclosed every month on a site like [WPScan Vulnerability Database](https://wpvulndb.com/ "WPScan Vulnerability Database") and [Exploits Database](https://www.exploit-db.com/ "Exploits Database by Offensive Security"). It means that we're always exposed to the threats of being exploited caused by them.
16
17
+ This plugin guards your site against threats of attack to back-end of your site such as login form, XML-RPC (login attempt) and admin area. It also blocks undesired comment spam, trackback and pingback spam and any requests to public facing pages aka front-end from undesired countries.
18
19
After several days of installation, you'll be supprised to find many malicious or undesirable accesses are blocked especially if you enable Zero-day Expoit Prevention.
20
21
= Features =
22
23
* **Immigration control:**
24
+ Access to the basic and important entrances into back-end such as `wp-comments-post.php`, `xmlrpc.php`, `wp-login.php`, `wp-signup.php`, `wp-admin/admin.php`, `wp-admin/admin-ajax.php`, `wp-admin/admin-post.php` will be validated by means of a country code based on IP address. It allows you to configure either whitelist or blacklist to [specify the countires](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements "ISO 3166-1 alpha-2 - Wikipedia"), [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing "Classless Inter-Domain Routing - Wikipedia") for a range of IP addresses and [AS number](https://en.wikipedia.org/wiki/Autonomous_system_(Internet) "Autonomous system (Internet) - Wikipedia") for a group of IP networks.
25
26
* **Zero-day Exploit Prevention:**
27
+ Unlike other security firewalls based on attack patterns (vectors), the original feature "**W**ord**P**ress **Z**ero-day **E**xploit **P**revention" (WP-ZEP) is focused on patterns of vulnerability. It is simple but still smart and strong enough to block any malicious accesses to `wp-admin/*.php`, `plugins/*.php` and `themes/*.php` even from the permitted countries. It will protect your site against certain types of attack such as CSRF, LFI, SQLi, XSS and so on, **even if you have some vulnerable plugins and themes in your site**.
28
29
* **Guard against login attempts:**
30
In order to prevent hacking through the login form and XML-RPC by brute-force and the reverse-brute-force attacks, the number of login attempts will be limited per IP address even from the permitted countries.
31
32
* **Minimize server load against brute-force attacks:**
33
+ You can configure this plugin as a [Must Use Plugins](https://codex.wordpress.org/Must_Use_Plugins "Must Use Plugins « WordPress Codex") so that this plugin can be loaded prior to regular plugins. It can massively [reduce the load on server](http://www.ipgeoblock.com/codex/validation-timing.html "Validation timing | IP Geo Block").
34
35
* **Prevent malicious down/uploading:**
36
+ A malicious request such as exposing `wp-config.php` or uploading malwares via vulnerable plugins/themes can be blocked.
37
38
* **Support of BuddyPress and bbPress:**
39
+ You can configure this plugin so that a registered user can login as a membership from anywhere, while a request such as a new user registration, lost password, creating a new topic and subscribing comment can be blocked by country. It is suitable for [BuddyPress](https://wordpress.org/plugins/buddypress/ "BuddyPress — WordPress Plugins") and [bbPress](https://wordpress.org/plugins/bbpress/ "WordPress › bbPress « WordPress Plugins") to help reducing spams.
40
41
* **Referrer suppressor for external links:**
42
When you click an external hyperlink on admin screens, http referrer will be eliminated to hide a footprint of your site.
43
44
* **Multiple source of IP Geolocation databases:**
45
+ [MaxMind GeoLite free databases](http://www.maxmind.com "MaxMind - IP Geolocation and Online Fraud Prevention") and [IP2Location LITE databases](http://www.ip2location.com/ "IP Address Geolocation to Identify Website Visitor's Geographical Location") can be installed in this plugin. Also free Geolocation REST APIs and whois information can be available for audit purposes.
46
+ Father more, if you use CloudFlare or CloudFront as a reverse proxy service, you can install the [dedicated API class libraries](http://www.ipgeoblock.com/article/api-class-library.html "CloudFlare & CloudFront API class library | IP Geo Block") for these services.
47
48
* **Customizing response:**
49
HTTP response code can be selectable as `403 Forbidden` to deny access pages, `404 Not Found` to hide pages or even `200 OK` to redirect to the top page.
50
+ You can also have a human friendly page (like `404.php`) in your theme template directory or child theme directory to fit your theme.
51
52
* **Validation logs:**
53
Validation logs can be recorded with useful information to audit attack patterns.
107
Specify the country code with two letters (see [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements "ISO 3166-1 alpha-2 - Wikipedia, the free encyclopedia")). Each of them should be separated by comma.
108
109
* **White/Black list of extra IPs for prior validation**
110
+ The list of extra IP addresses prior to the validation of country code. [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing "Classless Inter-Domain Routing - Wikipedia, the free encyclopedia") and [AS number](https://en.wikipedia.org/wiki/Autonomous_system_(Internet) "Autonomous system (Internet) - Wikipedia") are also acceptable to specify the range.
111
+
112
+ * **Use Autonomous System Number (ASN)**
113
+ It enables you to use "AS number" in the whitelist and blacklist of extra IP addresses to specify a group of IP networks.
114
115
* **$_SERVER keys for extra IPs**
116
Additional IP addresses will be validated if some of keys in `$_SERVER` variable are specified in this textfield. Typically `HTTP_X_FORWARDED_FOR`.
146
Validate access to `wp-admin/admin-(ajax|post)*.php`.
147
148
* **Plugins area**
149
+ Validate direct access to plugins. Typically `wp-content/plugins/…/*.php`.
150
151
* **Themes area**
152
+ Validate direct access to themes. Typically `wp-content/themes/…/*.php`.
153
154
= Front-end target settings =
155
276
* How to use: Activate the following code and upload this file via FTP.
277
*/
278
/* -- ADD '/' TO THE TOP OR END OF THIS LINE TO ACTIVATE THE FOLLOWINGS -- */
279
+ function ip_geo_block_emergency( $validate, $settings ) {
280
$validate['result'] = 'passed';
281
return $validate;
282
}
283
+ add_filter( 'ip-geo-block-login', 'ip_geo_block_emergency', 1, 2 );
284
+ add_filter( 'ip-geo-block-admin', 'ip_geo_block_emergency', 1, 2 );
285
// */`
286
287
+ Please not that you have to use an [appropriate editor](https://codex.wordpress.org/Editing_Files#Using_Text_Editors "Editing Files « WordPress Codex").
288
289
After saving and uploading it to `/wp-content/plugins/ip-geo-block/` on your server via FTP, you become to be able to login again as an admin.
290
352
353
== Changelog ==
354
355
+ = 3.0.4.6 =
356
+ * **Bug fix:** Fix the issue that the emergent functionality didn't work when the number of login attempts reached to the limit.
357
+ * **Bug fix:** Fix the issue that the result would be always `limited` when "Max number of failed login attempts per IP address" is "Disabled".
358
+
359
+ = 3.0.4.5 =
360
+ * **Improvement:** Avoid conflict with [WP Limit Login Attempts](https://wordpress.org/plugins/wp-limit-login-attempts/ "WP Limit Login Attempts — WordPress Plugins"). See some details in ["Sorry, your request cannot be accepted."](https://wordpress.org/support/topic/sorry-your-request-cannot-be-accepted/#post-9544556 "Topic: “Sorry, your request cannot be accepted.” « WordPress.org Forums").
361
+
362
+ = 3.0.4.4 =
363
+ Sorry for the frequent update, but it should be fixed before the next release.
364
+ * **Bug fix:** Fix the issue that limit of login attempts took precedence over authority of admin.
365
+ * **Improvement:** Suppress "Unable to read" error message on dashboard in a certain type of server.
366
+
367
+ = 3.0.4.3 =
368
+ * **Bug fix:** Fix a bug of "Missing argument 2 for IP_Geo_Block_Admin_Rewrite::show_message()".
369
+
370
+ = 3.0.4.2 =
371
+ This is a maintenance release addressing various internal improvement toward the next version.
372
+ * **Bug fix:** Fix a bug that the counter of login attempt counted illegally.
373
+ * **Bug fix:** Fix a bug that the emergency functionality did not work properly.
374
+ * **Bug fix:** Fix a bug that an error messages was not displayed when downloading database file.
375
+ * **Improvement:** Improve the compatibility with a certain type of server using "ftpext" as a method of file system.
376
+ * **Improvement:** Change rewrite setting from server type base to server function base.
377
+ * **Improvement:** Strict evaluation of URL on anchor tags for zero-day exploit prevention.
378
+ * **Improvement:** Avoid blocking on redirection between multisite admin screen.
379
+
380
+ = 3.0.4.1 =
381
+ Thank you all for taking your time again since last update.
382
+ * **Bug fix:** Fix the error on updating 3.0.4. ([@](https://wordpress.org/support/topic/error-on-updating-3-0-4/ "Topic: Error on updating 3.0.4 « WordPress.org Forums"))
383
+ * **Bug fix:** Fix the issue of unexpected redirection on anchor tag with empty href in multisite. ([@](https://wordpress.org/support/topic/refresh-the-backend-page/ "Topic: refresh the backend page « WordPress.org Forums"))
384
+ * **Bug fix:** Fix the issue that "Remove all settings at uninstallation" could not be unchecked. ([@](https://github.com/tokkonopapa/WordPress-IP-Geo-Block/issues/19 "Bugs in v3.0.4 - Issue #19 - tokkonopapa/WordPress-IP-Geo-Block"))
385
+
386
+ = 3.0.4 =
387
+ * **New feature:** Autonomous System Number (ASN) in whitelist and blacklist of extra IP addresses instead of specifying many IP addresses.
388
+ * **New feature:** Statistics in logs - a new section in Statistics tab.
389
+ * **Deprecated:** Add a new filter hook `ip-geo-block-upload-forbidden` instead of `ip-geo-block-forbidden-upload`.
390
+ * **Improvement:** Add a new filter hook `ip-geo-block-upload-capability` to improve compatibility with other plugins that have uploading functionality.
391
+ * **Improvement:** Add a new option for verifying file upload capability. It can be set apart from verifying file extension and MIME type in "Prevent malicious file uploading".
392
+ * **Improvement:** Improve ability to extract Ajax actions for "Exception" in "Admin post/ajax".
393
+ * **Improvement:** Inhibit to embed a special nonce into links when WP-ZEP is disabled at each target. This may improve compatibility with some plugins and themes.
394
+ * **Bug fix:** Fix the issue of verifying file upload. It could not handle multiple files. ([@](https://wordpress.org/support/topic/incompatible-with-awesome-support-plugin/#post-9403708 "Topic: incompatible with Awesome Support plugin « WordPress.org Forums"))
395
+ * **Bug fix:** Fix the issue of illegal click event handling on anchor tag without href. ([@](https://wordpress.org/support/topic/pagebuilder-broken-by-ipgeoblock-v3-0-3-4/ "Topic: Pagebuilder broken by IPGeoblock v3.0.3.4 « WordPress.org Forums"))
396
+ * See [3.0.4 release note](http://www.ipgeoblock.com/changelog/release-3.0.4.html "3.0.4 Release Note | IP Geo Block") for some details.
397
+
398
= 3.0.3.4 =
399
* **Improvement:** Some minor refactoring for the future release.
400
* **Improvement:** Better throughput against attacks on admin area when `"mu-plugins" (ip-geo-block-mu.php)` is enable.
535
* **Improvement:** Support clean uninstall for network / multisite.
536
* **Improvement:** Improve the compatibility of downloading IP address databases for Microsoft IIS.
537
* **Bug fix:** Support `FORCE_SSL_ADMIN`.
538
+ * **Bug fix:** Fix the issue of [@](https://wordpress.org/support/topic/compatibility-with-ag-custom-admin "WordPress › Support » Compatibility with AG Custom Admin") and change the option name "**Important files**" to "**Bad signatures in query**" to avoid misuse.
539
+ * **Bug fix:** Fix the issue of [@](https://wordpress.org/support/topic/gb-added-to-whitelist "WordPress › Support » GB added to whitelist") which might be caused by some race condition.
540
* **Bug fix:** Fix the issue of restoring post revisions which was blocked.
541
542
= 2.2.4.1 =
543
Sorry for frequent updating.
544
545
+ * **Bug fix:** Fixed the issue of `Warning: strpos(): Empty needle in...` that was reported in [@](https://wordpress.org/support/topic/version-224-produces-warning-message "WordPress › Support » Version 2.2.4 Produces Warning Message") and [@](https://wordpress.org/support/topic/error-after-update-to-newest-version "WordPress › Support » Error after Update to newest version").
546
547
= 2.2.4 =
548
* **Bug fix:** Fixed the issue that some links on network admin of multisite were blocked when WP-ZEP for `admin area` or `admin ajax/post` was enabled.
599
* **Improvement:** Improved connectivity with Jetpack.
600
* **Improvement:** Improved immediacy of downloading databases at upgrading.
601
* **Improvement:** Replaced a terminated RESTful API service with a new stuff.
602
+ * **Bug fix:** Fixed issue that clicking a link tag without href always refreshed the page. Thanks to [wyclef](https://wordpress.org/support/topic/conflict-with-menu-editor-plugin "WordPress › Support » Conflict with Menu Editor plugin?").
603
* **Bug fix:** Fixed issue that deactivating and activating repeatedly caused to show the welcome message.
604
* **Bug fix:** Fixed issue that a misaligned argument in the function caused 500 internal server error when a request to the php files in plugins/themes area was rewrited to `rewrite.php`.
605
611
= 2.2.0 =
612
* **Important:** Now **Block by country** and **Prevent Zero-day Exploit** become to work independently on **Admin area**, **Admin ajax/post** at **Validation target settings**. Please reconfirm them.
613
* **Important:** Previously, a request whose country code can't be available was always blocked. But from this release, such a request is considered as comming from the country whose code is `ZZ`. It means that you can put `ZZ` into the white list and black list.
614
+ * **New feature:** White list and Black list of extra IP addresses prior to the validation of country code. Thanks to Fabiano for good suggestions at [support forum](https://wordpress.org/support/topic/white-list-of-ip-addresses-or-ranges "WordPress › Support » White list of IP addresses or ranges?")
615
* **New feature:** Malicious signatures to prevent disclosing the important files via vulnerable plugins or themes. A malicious request to try to expose `wp-config.php` or `passwd` can be blocked.
616
* **New feature:** Add privacy considerations related to IP address. Add **Anonymize IP address** at **Record settings**.
617
* **Bug fix:** Fix the issue that spaces in **Text message on comment form** are deleted.
618
* See details at [2.2.0 release note](http://www.ipgeoblock.com/changelog/release-2.2.0.html "2.2.0 Release Note").
619
620
= 2.1.5.1 =
621
+ * **Bug fix:** Fixed the issue that the Blacklist did not work properly. Thanks to TJayYay for reporting this issue at [support forum](https://wordpress.org/support/topic/hackers-from-country-in-blocked-list-of-countries-trying-to-login "WordPress › Support » Hackers from country in Blocked List of Countries trying to login").
622
623
= 2.1.5 =
624
+ * **Enhancement:** Enforce preventing self blocking at the first installation. And add the scan button to get all the country code using selected API. Thanks to **Nils** for a nice idea at [support forum](https://wordpress.org/support/topic/locked-out-due-to-eu-vs-country "WordPress › Support » Locked out due to EU vs. Country").
625
* **New feature:** Add pie chart to display statistics of "Blocked by country".
626
* **Enhancement:** WP-ZEP is reinforced against CSRF.
627
* **Bug fix:** Fix illegal handling of the fragment in a link.
628
* See details at [2.1.5 release note](http://www.ipgeoblock.com/changelog/release-2.1.5.html "2.1.5 Release Note").
629
630
= 2.1.4 =
631
+ * **Bug fix:** Fix the issue that this plugin broke functionality of a certain plugin. Thanks to **opsec** for reporting this issue at [support forum](https://wordpress.org/support/topic/blocks-saves-in-types-or-any-plugins-from-wp-typescom "WordPress › Support » Blocks saves in Types or any plugins from wp-types.com").
632
+ * **Improvement:** Add checking process for validation rule to prevent being blocked itself. Thanks to **internationals** for proposing at [support forum](https://wordpress.org/support/topic/locked-out-due-to-eu-vs-country "WordPress › Support » Locked out due to EU vs. Country")
633
* **Improvement:** Arrage the order of setting sections to focus the goal of this plugin.
634
* See details at [2.1.4 release note](http://www.ipgeoblock.com/changelog/release-2.1.4.html "2.1.4 Release Note").
635
647
648
* **Bug fix:** Fix the issue that the login-fail-counter didn't work when the validation at `Login form` was `block by country (register, lost password)`. In this release, the login-fail-counter works correctly.
649
* **Bug fix:** Fix the issue that the validation settings of `Admin area` and `Admin ajax/post` were influential with each other. Now each of those works individually.
650
+ * **Bug fix:** "Site Stats" of Jetpack is now shown on the admin bar which issue was reported on [support forum](https://wordpress.org/support/topic/admin-area-prevent-zero-day-exploit-incompatible-with-jetpack-site-stats-in-a "WordPress › Support » Admin area - Prevent zero-day exploit: Incompatible with Jetpack Site Stats in A").
651
* **Improvement:** Hide checking the existence of log db behind the symbol `IP_GEO_BLOCK_DEBUG` to reduce 1 query on admin screen.
652
* **Improvement:** Add alternative functions of BCMath extension to avoid `PHP Fatal error: Call to undefined function` in `IP2Location.php` when IPv6 is specified.
653
* **Improvement:** Use MaxMind database at the activating process not to be locked out by means of inconsistency of database at the activation and after.
admin/class-ip-geo-block-admin.php CHANGED
@@ -17,6 +17,7 @@ class IP_Geo_Block_Admin {
17
*/
18
private static $instance = NULL;
19
private $admin_tab = 0;
20
21
/**
22
* Initialize the plugin by loading admin scripts & styles
@@ -58,6 +59,10 @@ class IP_Geo_Block_Admin {
58
// when a blog is created or deleted.
59
add_action( 'wpmu_new_blog', array( $this, 'create_blog' ), 10, 6 ); // @since MU
60
add_action( 'delete_blog', array( $this, 'delete_blog' ), 10, 2 ); // @since 3.0.0
61
}
62
63
// loads a plugin’s translated strings.
@@ -107,6 +112,20 @@ class IP_Geo_Block_Admin {
107
return $revisions_data;
108
}
109
110
/**
111
* Do some procedures when a blog is created or deleted.
112
*
@@ -162,6 +181,7 @@ class IP_Geo_Block_Admin {
162
163
switch ( $this->admin_tab ) {
164
case 1:
165
// js for google chart
166
wp_register_script(
167
$addon = IP_Geo_Block::PLUGIN_NAME . '-google-chart',
@@ -224,12 +244,14 @@ class IP_Geo_Block_Admin {
224
'url' => admin_url( 'admin-ajax.php' ),
225
'nonce' => IP_Geo_Block_Util::create_nonce( $this->get_ajax_action() ),
226
'msg' => array(
227
- __( 'Import settings ?', 'ip-geo-block' ),
228
- __( 'Create table ?', 'ip-geo-block' ),
229
- __( 'Delete table ?', 'ip-geo-block' ),
230
- __( 'Clear statistics ?', 'ip-geo-block' ),
231
- __( 'Clear cache ?', 'ip-geo-block' ),
232
- __( 'Clear logs ?', 'ip-geo-block' ),
233
__( 'This feature is available with HTML5 compliant browsers.', 'ip-geo-block' ),
234
),
235
)
@@ -304,26 +326,84 @@ class IP_Geo_Block_Admin {
304
}
305
}
306
307
/**
308
* Register the administration menu into the WordPress Dashboard menu.
309
*
310
*/
311
private function add_plugin_admin_menu() {
312
// Setup the tab number.
313
$this->admin_tab = isset( $_GET['tab'] ) ? (int)$_GET['tab'] : 0;
314
- $this->admin_tab = min( 4, max( 0, $this->admin_tab ) );
315
-
316
- // Add a settings page for this plugin to the Settings menu.
317
- $hook = add_options_page(
318
- __( 'IP Geo Block', 'ip-geo-block' ),
319
- __( 'IP Geo Block', 'ip-geo-block' ),
320
- 'manage_options',
321
- IP_Geo_Block::PLUGIN_NAME,
322
- array( $this, 'display_plugin_admin_page' )
323
- );
324
325
// If successful, load admin assets only on this page.
326
- if ( ! empty( $hook ) )
327
add_action( "load-$hook", array( $this, 'enqueue_admin_assets' ) );
328
}
329
@@ -333,7 +413,7 @@ class IP_Geo_Block_Admin {
333
*/
334
private function diagnose_admin_screen() {
335
$settings = IP_Geo_Block::get_option();
336
- $adminurl = 'options-general.php';
337
338
// Check version and compatibility
339
if ( version_compare( get_bloginfo( 'version' ), '3.7.0' ) < 0 )
@@ -505,22 +585,50 @@ class IP_Geo_Block_Admin {
505
public function display_plugin_admin_page() {
506
$tab = $this->admin_tab;
507
$tabs = array(
508
- 0 => __( 'Settings', 'ip-geo-block' ),
509
- 1 => __( 'Statistics', 'ip-geo-block' ),
510
- 4 => __( 'Logs', 'ip-geo-block' ),
511
- 2 => __( 'Search', 'ip-geo-block' ),
512
- 3 => __( 'Attribution', 'ip-geo-block' ),
513
);
514
?>
515
<div class="wrap">
516
- <h2><?php echo esc_html( get_admin_page_title() ); ?></h2>
517
<h2 class="nav-tab-wrapper">
518
<?php foreach ( $tabs as $key => $val ) {
519
echo '<a href="?page=', IP_Geo_Block::PLUGIN_NAME, '&amp;tab=', $key, '" class="nav-tab', ($tab === $key ? ' nav-tab-active' : ''), '">', $val, '</a>';
520
} ?>
521
</h2>
522
<p style="text-align:left">[ <a id="ip-geo-block-toggle-sections" href="javascript:void(0)"><?php _e( 'Toggle all', 'ip-geo-block' ); ?></a> ]</p>
523
- <form method="post" action="options.php" id="<?php echo IP_Geo_Block::PLUGIN_NAME, '-', $tab; ?>"<?php if ( $tab ) echo " class=\"", IP_Geo_Block::PLUGIN_NAME, "-inhibit\""; ?>>
524
<?php
525
settings_fields( IP_Geo_Block::PLUGIN_NAME );
526
$this->do_settings_sections( IP_Geo_Block::PLUGIN_NAME, $tab );
@@ -562,6 +670,7 @@ class IP_Geo_Block_Admin {
562
1 => 'admin/includes/tab-statistics.php',
563
4 => 'admin/includes/tab-accesslog.php',
564
2 => 'admin/includes/tab-geolocation.php',
565
3 => 'admin/includes/tab-attribution.php',
566
);
567
@@ -674,9 +783,9 @@ class IP_Geo_Block_Admin {
674
$args['value'] = $args['text']; // should be escaped because it can contain allowed tags
675
676
case 'text': ?>
677
- <input type="text" class="regular-text code" id="<?php echo $id, $sub_id; ?>" name="<?php echo $name, $sub_name; ?>" value="<?php echo esc_attr( $args['value'] ); ?>"
678
- <?php disabled( ! empty( $args['disabled'] ), TRUE ); ?>
679
- <?php if ( isset( $args['placeholder'] ) ) echo ' placeholder="', $args['placeholder'], '"'; ?> />
680
<?php
681
break; // disabled @since 3.0
682
@@ -731,7 +840,7 @@ class IP_Geo_Block_Admin {
731
* Sanitize a string from user input
732
*/
733
foreach ( $output as $key => $val ) {
734
- $key = sanitize_text_field( $key );
735
736
// delete old key
737
if ( ! array_key_exists( $key, $default ) ) {
@@ -761,8 +870,7 @@ class IP_Geo_Block_Admin {
761
// need key
762
else {
763
$output[ $key ][ $provider ] =
764
- isset( $input[ $key ][ $provider ] ) ?
765
- sanitize_text_field( $input[ $key ][ $provider ] ) : '';
766
}
767
}
768
@@ -781,21 +889,21 @@ class IP_Geo_Block_Admin {
781
782
case 'white_list':
783
case 'black_list':
784
- $output[ $key ] = isset( $input[ $key ] ) ?
785
- sanitize_text_field(
786
- preg_replace( '/[^A-Z,]/', '', strtoupper( $input[ $key ] ) )
787
- ) : '';
788
break;
789
790
case 'mimetype':
791
if ( isset( $input[ $key ]['white_list'] ) ) { // for json file before 3.0.3
792
foreach ( $input[ $key ]['white_list'] as $k => $v ) {
793
- $output[ $key ]['white_list'][ $k ] = sanitize_text_field( $v );
794
}
795
}
796
if ( isset( $input[ $key ]['black_list'] ) ) { // for json file before 3.0.3
797
$output[ $key ]['black_list'] = sanitize_text_field( $input[ $key ]['black_list'] );
798
}
799
break;
800
801
default: // checkbox, select, text
@@ -867,7 +975,7 @@ class IP_Geo_Block_Admin {
867
// Initialize not on the form (mainly unchecked checkbox)
868
public function preprocess_options( $output, $default ) {
869
// initialize checkboxes not in the form (added after 2.0.0, just in case)
870
- foreach ( array( 'providers', 'save_statistics', 'anonymize', 'network_wide' ) as $key ) {
871
$output[ $key ] = is_array( $default[ $key ] ) ? array() : 0;
872
}
873
@@ -894,6 +1002,9 @@ class IP_Geo_Block_Admin {
894
$output['public'][ $key ] = array();
895
}
896
897
return $output;
898
}
899
@@ -922,8 +1033,8 @@ class IP_Geo_Block_Admin {
922
$output['signature'] = implode ( ',', $this->trim( $output['signature'] ) );
923
924
// 3.0.3 trim extra space and comma
925
- $output['mimetype' ]['black_list'] = preg_replace( $key, $val, trim( $output['mimetype']['black_list'] ) );
926
- $output['mimetype' ]['black_list'] = implode ( ',', $this->trim( $output['mimetype']['black_list'] ) );
927
928
// 3.0.0 convert country code to upper case, remove redundant spaces
929
$output['public']['ua_list'] = preg_replace( $key, $val, trim( $output['public']['ua_list'] ) );
@@ -932,7 +1043,9 @@ class IP_Geo_Block_Admin {
932
933
// 3.0.0 public : convert country code to upper case
934
foreach ( array( 'white_list', 'black_list' ) as $key ) {
935
- $output['public'][ $key ] = strtoupper( preg_replace( '/\s/', '', $output['public'][ $key ] ) );
936
}
937
938
// 2.2.5 exception : convert associative array to simple array
@@ -950,6 +1063,16 @@ class IP_Geo_Block_Admin {
950
}
951
}
952
953
return $output;
954
}
955
@@ -978,17 +1101,19 @@ class IP_Geo_Block_Admin {
978
*
979
*/
980
private function check_admin_post( $ajax = FALSE ) {
981
- if ( FALSE === $ajax ) {
982
- // a postfix '-options' is added at settings_fields().
983
- $nonce = check_admin_referer( IP_Geo_Block::PLUGIN_NAME . '-options' );
984
- } else {
985
$nonce = IP_Geo_Block_Util::verify_nonce( IP_Geo_Block_Util::retrieve_nonce( 'nonce' ), $this->get_ajax_action() );
986
- }
987
988
- $action = IP_Geo_Block::PLUGIN_NAME . '-auth-nonce';
989
- $nonce &= IP_Geo_Block_Util::verify_nonce( IP_Geo_Block_Util::retrieve_nonce( $action ), $action );
990
991
- if ( ! $nonce || ( ! current_user_can( 'manage_options' ) ) ) {
992
status_header( 403 );
993
wp_die(
994
__( 'You do not have sufficient permissions to access this page.' ), '',
@@ -1011,26 +1136,7 @@ class IP_Geo_Block_Admin {
1011
1012
// activate rewrite rules
1013
require_once IP_GEO_BLOCK_PATH . 'admin/includes/class-admin-rewrite.php';
1014
- $stat = IP_Geo_Block_Admin_Rewrite::activate_rewrite_all( $options['rewrite'] );
1015
-
1016
- // check the status of rewrite rules
1017
- $diff = array_diff_assoc( $options['rewrite'], $stat );
1018
- if ( ! empty( $diff ) ) {
1019
- $options['rewrite'] = $stat;
1020
-
1021
- $file = array();
1022
- $dirs = IP_Geo_Block_Admin_Rewrite::get_dirs();
1023
-
1024
- // show which file would be the issue
1025
- foreach ( $diff as $key => $stat ) {
1026
- $file[] = '<code>' . $dirs[ $key ] . '.htaccess</code>';
1027
- }
1028
-
1029
- self::add_admin_notice( 'error',
1030
- sprintf( __( 'Unable to write %s. Please check the permission.', 'ip-geo-block' ), implode( ', ', $file ) ) . ' ' .
1031
- sprintf( _n( 'Or please refer to %s to set it manually.', 'Or please refer to %s to set them manually.', count( $file ), 'ip-geo-block' ), '<a href="http://ipgeoblock.com/codex/how-to-fix-permission-troubles.html" title="How to fix permission troubles? | IP Geo Block">How to fix permission troubles?</a>' )
1032
- );
1033
- }
1034
1035
// additional configuration
1036
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-opts.php';
@@ -1038,7 +1144,7 @@ class IP_Geo_Block_Admin {
1038
if ( TRUE !== $file ) {
1039
$options['validation']['timing'] = 0;
1040
self::add_admin_notice( 'error', sprintf(
1041
- __( 'Unable to write <code>%s</code>. Please check the permission.', 'ip-geo-block' ), $file
1042
) );
1043
}
1044
@@ -1048,6 +1154,54 @@ class IP_Geo_Block_Admin {
1048
return $options;
1049
}
1050
1051
/**
1052
* Ajax callback function
1053
*
@@ -1065,7 +1219,7 @@ class IP_Geo_Block_Admin {
1065
switch ( isset( $_POST['cmd' ] ) ? $_POST['cmd' ] : NULL ) {
1066
case 'download':
1067
$res = IP_Geo_Block::get_instance();
1068
- $res = $res->update_database();
1069
break;
1070
1071
case 'search':
@@ -1149,6 +1303,11 @@ class IP_Geo_Block_Admin {
1149
$res = IP_Geo_Block_Admin_Ajax::get_wp_info();
1150
break;
1151
1152
case 'create-table':
1153
case 'delete-table':
1154
// Need to define `IP_GEO_BLOCK_DEBUG` to true
@@ -1160,7 +1319,6 @@ class IP_Geo_Block_Admin {
1160
$res = array(
1161
'page' => 'options-general.php?page=' . IP_Geo_Block::PLUGIN_NAME,
1162
);
1163
- break;
1164
}
1165
1166
if ( isset( $res ) ) // wp_send_json_{success,error}() @since 3.5.0
17
*/
18
private static $instance = NULL;
19
private $admin_tab = 0;
20
+ private $is_network = NULL;
21
22
/**
23
* Initialize the plugin by loading admin scripts & styles
59
// when a blog is created or deleted.
60
add_action( 'wpmu_new_blog', array( $this, 'create_blog' ), 10, 6 ); // @since MU
61
add_action( 'delete_blog', array( $this, 'delete_blog' ), 10, 2 ); // @since 3.0.0
62
+
63
+ // validate capability instead of nonce. @since 2.0.0 && 3.0.0
64
+ if ( $this->is_network = is_plugin_active_for_network( IP_GEO_BLOCK_BASE ) )
65
+ add_filter( IP_Geo_Block::PLUGIN_NAME . '-bypass-admins', array( $this, 'verify_network_redirect' ), 10, 2 );
66
}
67
68
// loads a plugin’s translated strings.
112
return $revisions_data;
113
}
114
115
+ /**
116
+ * Verify admin screen without action instead of validating nonce.
117
+ *
118
+ */
119
+ public function verify_network_redirect( $queries, $settings ) {
120
+ if ( IP_Geo_Block_Util::is_user_logged_in() && $settings['network_wide'] ) {
121
+ if ( 'GET' === $_SERVER['REQUEST_METHOD'] && isset( $_GET['page'] ) ) {
122
+ $queries[] = $_GET['page']; // $_GET['action'] should be checked in IP_Geo_Block::validate_admin()
123
+ }
124
+ }
125
+
126
+ return $queries;
127
+ }
128
+
129
/**
130
* Do some procedures when a blog is created or deleted.
131
*
181
182
switch ( $this->admin_tab ) {
183
case 1:
184
+ case 5:
185
// js for google chart
186
wp_register_script(
187
$addon = IP_Geo_Block::PLUGIN_NAME . '-google-chart',
244
'url' => admin_url( 'admin-ajax.php' ),
245
'nonce' => IP_Geo_Block_Util::create_nonce( $this->get_ajax_action() ),
246
'msg' => array(
247
+ __( 'Import settings ?', 'ip-geo-block' ),
248
+ __( 'Create table ?', 'ip-geo-block' ),
249
+ __( 'Delete table ?', 'ip-geo-block' ),
250
+ __( 'Clear statistics ?', 'ip-geo-block' ),
251
+ __( 'Clear cache ?', 'ip-geo-block' ),
252
+ __( 'Clear logs ?', 'ip-geo-block' ),
253
+ __( 'ajax for logged-in user', 'ip-geo-block' ),
254
+ __( 'ajax for non logged-in user', 'ip-geo-block' ),
255
__( 'This feature is available with HTML5 compliant browsers.', 'ip-geo-block' ),
256
),
257
)
326
}
327
}
328
329
+ /**
330
+ * Get the admin url that depends on network multisite.
331
+ *
332
+ */
333
+ private function dashboard_url( $network ) {
334
+ return $network ? network_admin_url( 'admin.php' /*'settings.php'*/ ) : admin_url( 'options-general.php' );
335
+ }
336
+
337
/**
338
* Register the administration menu into the WordPress Dashboard menu.
339
*
340
*/
341
private function add_plugin_admin_menu() {
342
+ $settings = IP_Geo_Block::get_option();
343
+
344
+ // Network wide or not
345
+ $admin_menu = 'admin_menu' === current_filter();
346
+ $this->is_network &= current_user_can( 'manage_network_options' ) && $settings['network_wide'];
347
+
348
// Setup the tab number.
349
$this->admin_tab = isset( $_GET['tab'] ) ? (int)$_GET['tab'] : 0;
350
+ $this->admin_tab = min( 5, max( 0, $this->admin_tab ) );
351
+
352
+ if ( $this->is_network ) {
353
+ if ( $admin_menu ) {
354
+ $this->admin_tab = max( $this->admin_tab, 1 );
355
+ } elseif ( ! in_array( $this->admin_tab, array( 0, 5 ), TRUE ) ) {
356
+ $this->admin_tab = 0;
357
+ }
358
+ } else {
359
+ $this->admin_tab = min( 4, $this->admin_tab ); // exclude `Sites` in multisite.
360
+ }
361
+
362
+ if ( $admin_menu ) {
363
+ // `settings-updated` would be added when `network_wide` is saved as TRUE
364
+ if ( $this->is_network && isset( $_REQUEST['settings-updated'] ) ) {
365
+ $this->sync_multisite_option( $settings );
366
+ wp_safe_redirect(
367
+ esc_url_raw( add_query_arg(
368
+ array( 'page' => IP_Geo_Block::PLUGIN_NAME ),
369
+ $this->dashboard_url( TRUE )
370
+ ) )
371
+ );
372
+ exit;
373
+ }
374
+
375
+ // Add a settings page for this plugin to the Settings menu.
376
+ $hook = add_options_page(
377
+ __( 'IP Geo Block', 'ip-geo-block' ),
378
+ __( 'IP Geo Block', 'ip-geo-block' ),
379
+ 'manage_options',
380
+ IP_Geo_Block::PLUGIN_NAME,
381
+ array( $this, 'display_plugin_admin_page' )
382
+ );
383
+ }
384
+
385
+ elseif ( $this->is_network ) {
386
+ // Add a settings page for this plugin to the Settings menu.
387
+ $hook = add_menu_page(
388
+ __( 'IP Geo Block', 'ip-geo-block' ),
389
+ __( 'IP Geo Block', 'ip-geo-block' ),
390
+ 'manage_network_options',
391
+ IP_Geo_Block::PLUGIN_NAME,
392
+ array( $this, 'display_plugin_admin_page' ),
393
+ 'dashicons-shield' // plugins_url( 'img/icon-72x72.png', __FILE__ )
394
+ );
395
+ /*$hook = add_submenu_page(
396
+ 'settings.php',
397
+ __( 'IP Geo Block', 'ip-geo-block' ),
398
+ __( 'IP Geo Block', 'ip-geo-block' ),
399
+ 'manage_network_options',
400
+ IP_Geo_Block::PLUGIN_NAME,
401
+ array( $this, 'display_plugin_admin_page' )
402
+ );*/
403
+ }
404
405
// If successful, load admin assets only on this page.
406
+ if ( ! empty( $hook ) ) // 'admin_enqueue_scripts'
407
add_action( "load-$hook", array( $this, 'enqueue_admin_assets' ) );
408
}
409
413
*/
414
private function diagnose_admin_screen() {
415
$settings = IP_Geo_Block::get_option();
416
+ $adminurl = $this->dashboard_url( FALSE );
417
418
// Check version and compatibility
419
if ( version_compare( get_bloginfo( 'version' ), '3.7.0' ) < 0 )
585
public function display_plugin_admin_page() {
586
$tab = $this->admin_tab;
587
$tabs = array(
588
+ 0 => __( 'Settings', 'ip-geo-block' ),
589
+ 1 => __( 'Statistics', 'ip-geo-block' ),
590
+ 4 => __( 'Logs', 'ip-geo-block' ),
591
+ 2 => __( 'Search', 'ip-geo-block' ),
592
+ 5 => __( 'Sites', 'ip-geo-block' ),
593
+ 3 => __( 'Attribution', 'ip-geo-block' ),
594
);
595
+
596
+ $settings = IP_Geo_Block::get_option();
597
+ $title = esc_html( get_admin_page_title() );
598
+
599
+ // Target page that depends on the network multisite or not.
600
+ if ( 'options-general.php' === $GLOBALS['pagenow'] ) {
601
+ $action = 'options.php';
602
+
603
+ if ( $this->is_network ) {
604
+ unset( $tabs[0], $tabs[5] ); // Settings, Sites
605
+ $title .= ' <span class="ip-geo-block-title-link">';
606
+ $title .= ' [ <a href="' . esc_url( add_query_arg( array( 'page' => IP_Geo_Block::PLUGIN_NAME, 'tab' => 0 ), $this->dashboard_url( TRUE ) ) ) . '" target="_self">' . __( 'Settings', 'ip-geo-block' ) . '</a> ]';
607
+ $title .= ' [ <a href="' . esc_url( add_query_arg( array( 'page' => IP_Geo_Block::PLUGIN_NAME, 'tab' => 5 ), $this->dashboard_url( TRUE ) ) ) . '" target="_self">' . __( 'Sites', 'ip-geo-block' ) . '</a> ]';
608
+ $title .= '</span>';
609
+ } else {
610
+ unset( $tabs[5] ); // Sites
611
+ }
612
+ } else {
613
+ $action = 'edit.php?action=' . IP_Geo_Block::PLUGIN_NAME;
614
+
615
+ if ( $settings['network_wide'] ) {
616
+ unset( $tabs[1], $tabs[4], $tabs[2], $tabs[3] ); // Statistics, Logs, Search, Attribution
617
+ $title .= ' <span class="ip-geo-block-title-link">[ ' . __( 'Network', 'ip-geo-block' ) . ' ]';
618
+ $title .= '</span>';
619
+ }
620
+ }
621
+
622
?>
623
<div class="wrap">
624
+ <h2><?php echo $title; ?></h2>
625
<h2 class="nav-tab-wrapper">
626
<?php foreach ( $tabs as $key => $val ) {
627
echo '<a href="?page=', IP_Geo_Block::PLUGIN_NAME, '&amp;tab=', $key, '" class="nav-tab', ($tab === $key ? ' nav-tab-active' : ''), '">', $val, '</a>';
628
} ?>
629
</h2>
630
<p style="text-align:left">[ <a id="ip-geo-block-toggle-sections" href="javascript:void(0)"><?php _e( 'Toggle all', 'ip-geo-block' ); ?></a> ]</p>
631
+ <form method="post" action="<?php echo $action; ?>" id="<?php echo IP_Geo_Block::PLUGIN_NAME, '-', $tab; ?>"<?php if ( $tab ) echo " class=\"", IP_Geo_Block::PLUGIN_NAME, "-inhibit\""; ?>>
632
<?php
633
settings_fields( IP_Geo_Block::PLUGIN_NAME );
634
$this->do_settings_sections( IP_Geo_Block::PLUGIN_NAME, $tab );
670
1 => 'admin/includes/tab-statistics.php',
671
4 => 'admin/includes/tab-accesslog.php',
672
2 => 'admin/includes/tab-geolocation.php',
673
+ 5 => 'admin/includes/tab-network.php',
674
3 => 'admin/includes/tab-attribution.php',
675
);
676
783
$args['value'] = $args['text']; // should be escaped because it can contain allowed tags
784
785
case 'text': ?>
786
+ <input type="text" class="regular-text code" id="<?php echo $id, $sub_id; ?>" name="<?php echo $name, $sub_name; ?>" value="<?php echo esc_attr( $args['value'] ); ?>"<?php
787
+ disabled( ! empty( $args['disabled'] ), TRUE );
788
+ if ( isset( $args['placeholder'] ) ) echo ' placeholder="', esc_html( $args['placeholder'] ), '"'; ?> />
789
<?php
790
break; // disabled @since 3.0
791
840
* Sanitize a string from user input
841
*/
842
foreach ( $output as $key => $val ) {
843
+ $key = sanitize_text_field( $key ); // @since 3.0.0 can't use sanitize_key() because of capital letters.
844
845
// delete old key
846
if ( ! array_key_exists( $key, $default ) ) {
870
// need key
871
else {
872
$output[ $key ][ $provider ] =
873
+ isset( $input[ $key ][ $provider ] ) ? sanitize_text_field( $input[ $key ][ $provider ] ) : '';
874
}
875
}
876
889
890
case 'white_list':
891
case 'black_list':
892
+ $output[ $key ] = isset( $input[ $key ] ) ? preg_replace( '/[^A-Z,]/', '', strtoupper( $input[ $key ] ) ) : '';
893
break;
894
895
case 'mimetype':
896
if ( isset( $input[ $key ]['white_list'] ) ) { // for json file before 3.0.3
897
foreach ( $input[ $key ]['white_list'] as $k => $v ) {
898
+ $output[ $key ]['white_list'][ sanitize_text_field( $k ) ] = sanitize_mime_type( $v ); // @since 3.1.3
899
}
900
}
901
if ( isset( $input[ $key ]['black_list'] ) ) { // for json file before 3.0.3
902
$output[ $key ]['black_list'] = sanitize_text_field( $input[ $key ]['black_list'] );
903
}
904
+ if ( isset( $input[ $key ]['capability'] ) ) {
905
+ $output[ $key ]['capability'] = array_map( 'sanitize_key', explode( ',', trim( $input[ $key ]['capability'], ',' ) ) ); // @since 3.0.0
906
+ }
907
break;
908
909
default: // checkbox, select, text
975
// Initialize not on the form (mainly unchecked checkbox)
976
public function preprocess_options( $output, $default ) {
977
// initialize checkboxes not in the form (added after 2.0.0, just in case)
978
+ foreach ( array( 'providers', 'save_statistics', 'anonymize', 'network_wide', 'clean_uninstall' ) as $key ) {
979
$output[ $key ] = is_array( $default[ $key ] ) ? array() : 0;
980
}
981
1002
$output['public'][ $key ] = array();
1003
}
1004
1005
+ // 3.0.4 AS number
1006
+ $output['Maxmind']['use_asn'] = FALSE;
1007
+
1008
return $output;
1009
}
1010
1033
$output['signature'] = implode ( ',', $this->trim( $output['signature'] ) );
1034
1035
// 3.0.3 trim extra space and comma
1036
+ $output['mimetype']['black_list'] = preg_replace( $key, $val, trim( $output['mimetype']['black_list'] ) );
1037
+ $output['mimetype']['black_list'] = implode ( ',', $this->trim( $output['mimetype']['black_list'] ) );
1038
1039
// 3.0.0 convert country code to upper case, remove redundant spaces
1040
$output['public']['ua_list'] = preg_replace( $key, $val, trim( $output['public']['ua_list'] ) );
1043
1044
// 3.0.0 public : convert country code to upper case
1045
foreach ( array( 'white_list', 'black_list' ) as $key ) {
1046
+ $output['public' ][ $key ] = strtoupper( preg_replace( '/\s/', '', $output['public'][ $key ] ) );
1047
+ // 3.0.4 extra_ips : convert AS number to upper case
1048
+ $output['extra_ips'][ $key ] = strtoupper( $output['extra_ips'][ $key ] );
1049
}
1050
1051
// 2.2.5 exception : convert associative array to simple array
1063
}
1064
}
1065
1066
+ // 3.0.4 AS number
1067
+ if ( $output['Maxmind']['use_asn'] && empty( $output['Maxmind']['asn4_path'] ) ) {
1068
+ require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-cron.php';
1069
+ IP_Geo_Block_Cron::start_update_db( $output, TRUE ); // force to update
1070
+ }
1071
+ elseif ( ! $output['Maxmind']['use_asn'] && ! @file_exists( $output['Maxmind']['asn4_path'] ) ) {
1072
+ $output['Maxmind']['asn4_path'] = NULL; // force to delete
1073
+ $output['Maxmind']['asn6_path'] = NULL;
1074
+ }
1075
+
1076
return $output;
1077
}
1078
1101
*
1102
*/
1103
private function check_admin_post( $ajax = FALSE ) {
1104
+ if ( $ajax )
1105
$nonce = IP_Geo_Block_Util::verify_nonce( IP_Geo_Block_Util::retrieve_nonce( 'nonce' ), $this->get_ajax_action() );
1106
+ else
1107
+ $nonce = check_admin_referer( IP_Geo_Block::PLUGIN_NAME . '-options' ); // a postfix '-options' is added at settings_fields().
1108
1109
+ $settings = IP_Geo_Block::get_option();
1110
+ if ( ( $ajax and $settings['validation']['ajax' ] & 2 ) ||
1111
+ ( ! $ajax and $settings['validation']['admin'] & 2 ) ) {
1112
+ $action = IP_Geo_Block::PLUGIN_NAME . '-auth-nonce';
1113
+ $nonce &= IP_Geo_Block_Util::verify_nonce( IP_Geo_Block_Util::retrieve_nonce( $action ), $action );
1114
+ }
1115
1116
+ if ( ! $nonce || ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'manage_network_options' ) ) ) {
1117
status_header( 403 );
1118
wp_die(
1119
__( 'You do not have sufficient permissions to access this page.' ), '',
1136
1137
// activate rewrite rules
1138
require_once IP_GEO_BLOCK_PATH . 'admin/includes/class-admin-rewrite.php';
1139
+ $options['rewrite'] = IP_Geo_Block_Admin_Rewrite::activate_rewrite_all( $options['rewrite'] );
1140
1141
// additional configuration
1142
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-opts.php';
1144
if ( TRUE !== $file ) {
1145
$options['validation']['timing'] = 0;
1146
self::add_admin_notice( 'error', sprintf(
1147
+ __( 'Unable to write <code>%s</code>. Please check the permission.', 'ip-geo-block' ), '<code>' . $file . '</code>'
1148
) );
1149
}
1150
1154
return $options;
1155
}
1156
1157
+ /**
1158
+ * Validate settings and configure some features for network multisite.
1159
+ *
1160
+ * @see https://vedovini.net/2015/10/using-the-wordpress-settings-api-with-network-admin-pages/
1161
+ */
1162
+ public function validate_network_settings() {
1163
+ // Must check that the user has the required capability
1164
+ $this->check_admin_post( FALSE );
1165
+
1166
+ // The list of registered options (IP_Geo_Block::OPTION_NAME).
1167
+ global $new_whitelist_options;
1168
+ $options = $new_whitelist_options[ IP_Geo_Block::PLUGIN_NAME ];
1169
+
1170
+ // Go through the posted data and save the targetted options.
1171
+ foreach ( $options as $option ) {
1172
+ if ( isset( $_POST[ $option ] ) )
1173
+ $this->sync_multisite_option( $_POST[ $option ] );
1174
+ }
1175
+
1176
+ // Register a settings error to be displayed to the user
1177
+ self::add_admin_notice( 'updated', __( 'Settings saved.' ) );
1178
+
1179
+ // Redirect in order to back to the settings page.
1180
+ wp_redirect( esc_url_raw(
1181
+ add_query_arg(
1182
+ array( 'page' => IP_Geo_Block::PLUGIN_NAME ),
1183
+ $this->dashboard_url( ! empty( $_POST[ $option ]['network_wide'] ) )
1184
+ )
1185
+ ) );
1186
+ exit;
1187
+ }
1188
+
1189
+ /**
1190
+ * Update option in all blogs.
1191
+ *
1192
+ * @note: This function triggers `validate_settings()` on register_setting() in wp-include/option.php.
1193
+ */
1194
+ private function sync_multisite_option( $option ) {
1195
+ global $wpdb;
1196
+ $blog_ids = $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" );
1197
+
1198
+ foreach ( $blog_ids as $id ) {
1199
+ switch_to_blog( $id );
1200
+ update_option( IP_Geo_Block::OPTION_NAME, $option );
1201
+ restore_current_blog();
1202
+ }
1203
+ }
1204
+
1205
/**
1206
* Ajax callback function
1207
*
1219
switch ( isset( $_POST['cmd' ] ) ? $_POST['cmd' ] : NULL ) {
1220
case 'download':
1221
$res = IP_Geo_Block::get_instance();
1222
+ $res = $res->exec_update_db();
1223
break;
1224
1225
case 'search':
1303
$res = IP_Geo_Block_Admin_Ajax::get_wp_info();
1304
break;
1305
1306
+ case 'get-actions':
1307
+ // Get all the ajax/post actions
1308
+ $res = IP_Geo_Block_Util::get_registered_actions( TRUE );
1309
+ break;
1310
+
1311
case 'create-table':
1312
case 'delete-table':
1313
// Need to define `IP_GEO_BLOCK_DEBUG` to true
1319
$res = array(
1320
'page' => 'options-general.php?page=' . IP_Geo_Block::PLUGIN_NAME,
1321
);
1322
}
1323
1324
if ( isset( $res ) ) // wp_send_json_{success,error}() @since 3.5.0
admin/css/admin.css CHANGED
@@ -143,7 +143,7 @@ ul#ip-geo-block-actions dfn {
143
border: none;
144
}
145
ul#ip-geo-block-actions span.dashicons {
146
- font-size: 90%;
147
}
148
.ip-geo-block-checked {
149
list-style-type: disc;
@@ -465,19 +465,27 @@ span.ip-geo-block-title-link {
465
box-shadow: none;
466
}*/
467
468
- dfn + a.ip-geo-block-cycle {
469
- margin-left: 0.5em;
470
- }
471
- .ip-geo-block-cycle {
472
cursor: pointer;
473
box-shadow: none;
474
text-decoration: none;
475
}
476
- .ip-geo-block-cycle:active {
477
position: relative;
478
top: 1px;
479
}
480
- .ip-geo-block-cycle span {
481
height: 16px;
482
width: 16px;
483
margin: 0;
@@ -487,8 +495,17 @@ dfn + a.ip-geo-block-cycle {
487
background-size: 16px 16px;
488
background-position: center center;
489
background-repeat: no-repeat;
490
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAh1BMVEUAda2otLp+rsSHprWHr8IBd7EpfKRGhaNajqeUqrRymKuKoq5yo7prlKgAcqoVe6w8gqQmgq5Tj6wIdqsVdKIshrEMea1Uhp+Anqw0hawDdq4gfKhljqE7hqoLdKYbgbM4jLQygKUGeK8CdawQd6gVeKcad6NKkrSerrZAj7UAc6sAc6rc3NySrVGQAAAALXRSTlP//////////////////////////////////////////////////////////wCl7wv9AAACOklEQVR4Ae2W15rzKgxF9xTZzhTX9B7S/gN6/9ebYqzzGZsw/S7LV3FZgCSIwD/kQ8FVcBU8xatZUczy8luC/ABNOn0DSHEsvyZ4PgLatNCYR3efFxyhTQ8g+qQgJxgv2JefERzJXATRh4LHOUwAHD4S7OGEztRJaN86hAUxtaNWDUf/bRdDBbQMWVDAO8jn89WUhag1MeyCAh6hHofyrliLgZKggDMYgzF3eVAwFq0uCZq5KY0TezjIHDDzC0qqmkwe2ctGDOQVLMkgu+F3/rGXwb4xIPcJ6P3JgkM8wFjmfcFAWfeKQywaAz33BJVuHsUcAt09gVbuLDThAJkdR687ggLmf4gDJLIGV7BydtB8yn3u+fbtuj/LS7G9wZAd1AKK+yxJ1x+aBmibTtgCcEHGHsh0wdbOgNLek4L7lI5BigY8nWuZUQ3qGEXes9JzOKGJztPaGtLslu3lIXJirdxCWkASHGDTMqg7V1DKPplygDG61YJukLHjEErGSXqCSos6xNSOgzP3BDmsQBcchNwkoV8oiNnPA78zIefUgCdJeGIfE7LmFWXsFTCFdzTJ/RlfEMRiSGnFXXbkC7AIeqcKDu4ynseozeouKJiSEYBDwkJyIC1nRUjgblkNWp/e/1vXc2gjoAoLksYgjrrFMi0oDgjEEIDij1scBXMJSH6DAj6RNl7o8MkuLak8Co15/Pk+MRmT0xilQJV/sdWNKg2kTaeroudvNNsDjmejYjSL+e6v2/2r4Cp4BXNajr0H7hRfAAAAAElFTkSuQmCC);
491
}
492
/* https://developer.wordpress.org/resource/dashicons/ for WordPress 3.8
493
.ip-geo-block-cycle span:before {
494
background: none;
@@ -502,17 +519,17 @@ dfn + a.ip-geo-block-cycle {
502
vertical-align: text-top;
503
-webkit-font-smoothing: antialiased;
504
-moz-osx-font-smoothing: grayscale;
505
- }
506
- */
507
#ip-geo-block-back-to-top {
508
margin:0;
509
text-align:right;
510
}
511
512
- /* for multisite */
513
.ip-geo-block-multisite {
514
margin-bottom: 1em;
515
}
516
/* for statistics */
517
ol.ip-geo-block-top-list {
518
display: inline-table;
@@ -520,9 +537,20 @@ ol.ip-geo-block-top-list {
520
margin: 0 2em 0.5em 1.75em;
521
}
522
ol.ip-geo-block-top-list h4 {
523
- font-size: 13px;
524
- margin: 0.5em 0;
525
}
526
ol.ip-geo-block-top-list li code {
527
background: none;
528
}
143
border: none;
144
}
145
ul#ip-geo-block-actions span.dashicons {
146
+ font-size: 14px;
147
}
148
.ip-geo-block-checked {
149
list-style-type: disc;
465
box-shadow: none;
466
}*/
467
468
+ dfn ~ .ip-geo-block-cycle,
469
+ dfn ~ .ip-geo-block-lock,
470
+ dfn ~ .ip-geo-block-unlock {
471
+ margin-left: 0.75em;
472
+ }
473
+ .ip-geo-block-cycle,
474
+ .ip-geo-block-lock,
475
+ .ip-geo-block-unlock {
476
cursor: pointer;
477
box-shadow: none;
478
text-decoration: none;
479
}
480
+ .ip-geo-block-cycle:active,
481
+ .ip-geo-block-lock:active,
482
+ .ip-geo-block-unlock:active {
483
position: relative;
484
top: 1px;
485
}
486
+ .ip-geo-block-cycle span,
487
+ .ip-geo-block-lock span,
488
+ .ip-geo-block-unlock span {
489
height: 16px;
490
width: 16px;
491
margin: 0;
495
background-size: 16px 16px;
496
background-position: center center;
497
background-repeat: no-repeat;
498
+ }
499
+ .ip-geo-block-cycle span {
500
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAh1BMVEUAda2otLp+rsSHprWHr8IBd7EpfKRGhaNajqeUqrRymKuKoq5yo7prlKgAcqoVe6w8gqQmgq5Tj6wIdqsVdKIshrEMea1Uhp+Anqw0hawDdq4gfKhljqE7hqoLdKYbgbM4jLQygKUGeK8CdawQd6gVeKcad6NKkrSerrZAj7UAc6sAc6rc3NySrVGQAAAALXRSTlP//////////////////////////////////////////////////////////wCl7wv9AAACOklEQVR4Ae2W15rzKgxF9xTZzhTX9B7S/gN6/9ebYqzzGZsw/S7LV3FZgCSIwD/kQ8FVcBU8xatZUczy8luC/ABNOn0DSHEsvyZ4PgLatNCYR3efFxyhTQ8g+qQgJxgv2JefERzJXATRh4LHOUwAHD4S7OGEztRJaN86hAUxtaNWDUf/bRdDBbQMWVDAO8jn89WUhag1MeyCAh6hHofyrliLgZKggDMYgzF3eVAwFq0uCZq5KY0TezjIHDDzC0qqmkwe2ctGDOQVLMkgu+F3/rGXwb4xIPcJ6P3JgkM8wFjmfcFAWfeKQywaAz33BJVuHsUcAt09gVbuLDThAJkdR687ggLmf4gDJLIGV7BydtB8yn3u+fbtuj/LS7G9wZAd1AKK+yxJ1x+aBmibTtgCcEHGHsh0wdbOgNLek4L7lI5BigY8nWuZUQ3qGEXes9JzOKGJztPaGtLslu3lIXJirdxCWkASHGDTMqg7V1DKPplygDG61YJukLHjEErGSXqCSos6xNSOgzP3BDmsQBcchNwkoV8oiNnPA78zIefUgCdJeGIfE7LmFWXsFTCFdzTJ/RlfEMRiSGnFXXbkC7AIeqcKDu4ynseozeouKJiSEYBDwkJyIC1nRUjgblkNWp/e/1vXc2gjoAoLksYgjrrFMi0oDgjEEIDij1scBXMJSH6DAj6RNl7o8MkuLak8Co15/Pk+MRmT0xilQJV/sdWNKg2kTaeroudvNNsDjmejYjSL+e6v2/2r4Cp4BXNajr0H7hRfAAAAAElFTkSuQmCC);
501
}
502
+ .ip-geo-block-lock span {
503
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAYFBMVEXc3Ny3y9Zzq8dRmb7M1dlXnsIFdK0AcawAcqwphrYAcKvZ29wAb6oJd680jrqlw9MBcqxmo8MUfbJLl75eoMI7kbzX2ttqp8VSmL1YnL8NeK+Tu89DlL1ImMEOebBNmL4OkqMoAAAAAXRSTlMAQObYZgAAAPlJREFUeAG9kAWyhTAQBIPOsCzufv9TPnf4Ll0CSbpmxXwNy3Yc23rz2fV8kPA99433AIQIiGDTCD0lojiOQPXCDSFJIbF16CMWItkQMkF+inZzSLYhFKLl+a9UKTZaqJTZJYtarZuo40chrv9CqJTN+behVi+Cm7RdDgRld6AMgLxrE/dxBz0BEjwBEmD/uIsWPAOAF9A+CE56ufSryr8oqfOYcBbQJ8YkES7COkFOYzTypqCDOTDo2wljaEw4vp1APYyWKd8WMBozylvCpcvmXeHQ5fCegHia4s1FgZcIVeVFeFx1M4MvYG4eBHdYWufC+addBtf8E3vdjBNhWnVQqAAAAABJRU5ErkJggg==);
504
+ }
505
+ .ip-geo-block-unlock span {
506
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAYFBMVEXc3NyzydRzq8dRmb7I09hYnsEFdK0AcawAcqzP1toqhrYAcKvZ29wAb6oMeK8zjbqrxtQBcazBz9Zko8MVfbLF0thMmL07kbtpp8WjwtJSmL1YnL+Tu89DlL1JmMEPebBFV++UAAAAAXRSTlMAQObYZgAAAONJREFUeAG9kAWChDAMAIMmJaTFXf7/ynXflvMbnE5j8DU8Pwh8D1yEUYxEGEchWFEJEjEflESBhTQSQm2MRpIotQhZTmgKgMIg5ZlFKBmrGg7UFXJpEQKW8qIKN7YeikJdBJI2BTtXwfyx0L3XoPphvBEliNU49OoxqEa6g4cTST/OYshvi3hV8+FxSNfluG3jqxG8C6h7gF6jU+AODnTsFGSCA5O4I8wpQDq7I5CUAKWQW+AZYOYtoQPoGDeECWDaioBmWQxeBduoWURso+5WpBdw7R4ENTVDcGE435tJwT+xB+vMEnZRNB0YAAAAAElFTkSuQmCC);
507
+ }
508
+
509
/* https://developer.wordpress.org/resource/dashicons/ for WordPress 3.8
510
.ip-geo-block-cycle span:before {
511
background: none;
519
vertical-align: text-top;
520
-webkit-font-smoothing: antialiased;
521
-moz-osx-font-smoothing: grayscale;
522
+ }*/
523
#ip-geo-block-back-to-top {
524
margin:0;
525
text-align:right;
526
}
527
528
+ /* embeded data for multisite */
529
.ip-geo-block-multisite {
530
margin-bottom: 1em;
531
}
532
+
533
/* for statistics */
534
ol.ip-geo-block-top-list {
535
display: inline-table;
537
margin: 0 2em 0.5em 1.75em;
538
}
539
ol.ip-geo-block-top-list h4 {
540
+ margin: 1em 0;
541
}
542
ol.ip-geo-block-top-list li code {
543
background: none;
544
+ }
545
+
546
+ /* icon for top level menu */
547
+ #toplevel_page_ip-geo-block .wp-menu-image img {
548
+ height: 18px;
549
+ width: 18px;
550
+ }
551
+
552
+ /* action for admin post */
553
+ .ip-geo-block-admin-post {
554
+ color: #c43322;
555
+ margin-left: 0.25em;
556
}
admin/css/admin.min.css CHANGED
@@ -1,2 +1,2 @@
1
/* This stylesheet is used to style the admin option form of the plugin. */
2
- #ip-geo-block-scan-code,.ip-geo-block-loading,.ip-geo-block-log *{vertical-align:middle}dfn{cursor:help;border-bottom:1px dotted #888}fieldset,legend{padding:0;margin:0;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}fieldset{min-width:0}legend{display:block;line-height:inherit;width:100%}.panel-body,label{display:inline-block}label{max-width:100%}.panel{border:1px solid #e5e5e5;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.04);-moz-box-shadow:0 1px 1px rgba(0,0,0,.04);box-shadow:0 1px 1px rgba(0,0,0,.04);background:#f5f5f5}.panel-heading{float:left!important;background:#fff}.panel-default>.panel-heading{border-color:inherit}.panel-body{width:100%;padding:0 1em;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.panel-body:after,.panel-body:before{content:" ";display:table}.panel-body:after{clear:both}fieldset.ip-geo-block-field{margin:1em 0}fieldset.ip-geo-block-field h2,fieldset.ip-geo-block-field h3{padding:0;margin:0;font-size:14px!important}fieldset.ip-geo-block-field legend.panel-heading{padding:10px}fieldset.ip-geo-block-field .ip-geo-block-dropdown,fieldset.ip-geo-block-field .ip-geo-block-dropup{cursor:pointer;position:relative;padding-left:1em}fieldset.ip-geo-block-field .ip-geo-block-dropdown:before,fieldset.ip-geo-block-field .ip-geo-block-dropup:before{content:'';height:0;width:0;border:.4em solid transparent;position:absolute}fieldset.ip-geo-block-field .ip-geo-block-dropup:before{border-left:.4em solid #555;left:3px;top:15%}fieldset.ip-geo-block-field .ip-geo-block-dropdown:before{border-top:.4em solid #555;left:0;top:35%}fieldset.ip-geo-block-field ul.ip-geo-block-dropup:before{top:.25em}fieldset.ip-geo-block-field ul.ip-geo-block-dropdown:before{top:.45em}fieldset.ip-geo-block-field .form-table{margin:0;width:100%}fieldset.ip-geo-block-field .ip-geo-block-desc{color:#666;font-size:13px}textarea.regular-text{width:25em}ul.ip-geo-block-settings-folding{margin:.5em 0}ul.ip-geo-block-settings-folding ul{margin-bottom:0}ul.ip-geo-block-settings-folding li:first-child{margin-top:.5em}.folding-disable{pointer-events:none;opacity:.5}.folding-inactive{opacity:.5;font-style:oblique!important}ul.ip-geo-block-float li{display:inline-block;width:18em}ul#ip-geo-block-actions dfn{border:none}ul#ip-geo-block-actions span.dashicons{font-size:90%}.ip-geo-block-checked{list-style-type:disc}.ip-geo-block-ip-addr{display:inline-block;padding-top:5px}.ip-geo-block-hide{display:none}.ip-geo-block-result,.ip-geo-block-sup,.ip-geo-block-title,ul.ip-geo-block-list label{display:inline-block}.ip-geo-block-sup{margin-left:.2em}ul.ip-geo-block-note{margin-top:1em;list-style:disc inside}ul.ip-geo-block-list{margin-top:.25em;margin-bottom:.25em}@media screen and (min-width:782px){ul.ip-geo-block-list .code{width:15em}}.ip-geo-block-loading{background-size:16px 16px;background-position:center center;background-repeat:no-repeat;background-image:url(data:image/gif;base64,R0lGODlhEAAQAPIGAAAAAMLCwkJCQpKSkmJiYoKCgv///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAGACwAAAAAEAAQAAADM2i63P4wyklrC0IEKgAQnAdOmGYFBLExwboQWcG2rlHEwTDQLUsUOd2mBxkUCgNKa+dIAAAh+QQJCgAGACwAAAIACgAOAAADLWgWIqHQCABEVLPe1R4MBOFFRFNsRUNsYDFewTC8iixvQ1EMyxjEvyBLODQkAAAh+QQJCgAGACwAAAAACgAOAAADLWi6IRJrCQCECoU0ag1xxeBARuEQ0UUU5DUM7fK+qTEUYR0EcM3Ev51uB7wAEwAh+QQJCgAGACwAAAAADgAKAAADLWi6URQrLiJEkSaM0eqrkLFtAVEEAgAIylAUQ5SuSqCFNZjhWG3zmB8wOJQkAAAh+QQJCgAGACwCAAAADgAKAAADK2hqMRMrLuekCnCU8gqBDCZ2glBcYkSUxIJJgQdaUVDOtAAAAr3oPN/llgAAIfkECQoABgAsBgAAAAoADgAAAytoEdauiz0Yx5BQFTvN2EMXWNgUFETZFIJQdERLiGgZtKohAIDQ7T0RrpEAACH5BAkKAAYALAYAAgAKAA4AAAMqaKoR+609Fie1K4zhZiibNRSg1XAQUXQPIQgE835voQgAIARqh+ummSUBACH5BAUKAAYALAIABgAOAAoAAAMsaLpsES2+F9mEddEgBFbBMGACAAiMOCrlGRBFWBQD2L0dYYjfUuQZEKynSAAAOw==);height:16px;width:16px;margin-left:1em;margin-top:.2em;display:inline-block}.ip-geo-block-border{border-top:inherit}.ip-geo-block-notice{color:#dd3d36}.ip-geo-block-title{width:100px}.ip-geo-block-result{color:#2786C2}#ip-geo-block-map{height:400px;margin:1em auto}.gm-style-iw{width:18em;height:auto!important;height:100%;min-height:100%:}.gm-style-iw ul{margin:.1em}.gm-style-iw li{margin:.2em}ul.ip-geo-block-statistics-countries li{width:12em;float:left;text-align:right;padding:.2em}table.ip-geo-block-statistics-table{float:right}table.ip-geo-block-statistics-table td,table.ip-geo-block-statistics-table th{width:12em;margin:0;padding:.2em;text-align:right;line-height:1.5em;word-wrap:break-word}table.ip-geo-block-statistics-table tr:nth-child(even){background-color:#eee}table.ip-geo-block-table{margin:1em 0;white-space:normal;word-wrap:break-word;word-break:break-all}table.ip-geo-block-table td:first-child{min-width:4.3em}@media screen and (max-width:782px){#ip-geo-block-whois .panel-body{padding:0 .5em}}#ip-geo-block-4 #ip-geo-block-section-1 .panel-body,#ip-geo-block-4 #ip-geo-block-section-2 .panel-body,#ip-geo-block-4 #ip-geo-block-section-3 .panel-body,#ip-geo-block-4 #ip-geo-block-section-4 .panel-body,#ip-geo-block-4 #ip-geo-block-section-5 .panel-body{padding:0;display:table-cell}.ip-geo-block-log{width:100%!important;margin:.5em 0}.ip-geo-block-log *{font-size:13px!important;line-height:1.5em}.ip-geo-block-log .pagination ul{border-radius:4px;display:inline-block;margin:.5em 0 0;padding:0}.ip-geo-block-log .pagination ul>li{display:inline}.ip-geo-block-log .pagination ul>li:first-child>a,.ip-geo-block-log .pagination ul>li:first-child>span{border-bottom-left-radius:4px;border-left-width:1px;border-top-left-radius:4px}.ip-geo-block-log .pagination ul>li:last-child>a,.ip-geo-block-log .pagination ul>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.ip-geo-block-log .pagination ul>.disabled>a,.ip-geo-block-log .pagination ul>.disabled>a:focus,.ip-geo-block-log .pagination ul>.disabled>a:hover,.ip-geo-block-log .pagination ul>.disabled>span{background-color:transparent;color:#999;cursor:default}.ip-geo-block-log .pagination ul>li>a,.ip-geo-block-log .pagination ul>li>span{border-color:#ddd;border-image:none;border-style:solid;border-width:1px 1px 1px 0;float:left;line-height:20px;padding:4px;width:20px;text-decoration:none}.ip-geo-block-log .pagination ul>.active>a,.ip-geo-block-log .pagination ul>.active>span{color:#999;cursor:default}.ip-geo-block-log .pagination ul>.active>a,.ip-geo-block-log .pagination ul>.active>span,.ip-geo-block-log .pagination ul>li>a:focus,.ip-geo-block-log .pagination ul>li>a:hover{background-color:#f7f7f7}.ip-geo-block-log .pagination-centered{text-align:center}.ip-geo-block-log.breakpoint>tbody>tr>td>span.footable-toggle{font-size:60%!important;position:relative;top:-1px;left:2px}.ip-geo-block-log>tbody>tr>td,.ip-geo-block-log>thead>tr>th{padding:4px 0;word-wrap:break-word;width:20%}.ip-geo-block-log>tbody>tr>td:first-child,.ip-geo-block-log>thead>tr>th:first-child{width:25%}.ip-geo-block-log>tbody>tr>td:first-child+td,.ip-geo-block-log>thead>tr>th:first-child+th{width:35%}.ip-geo-block-log>tbody>tr>td:nth-child(5),.ip-geo-block-log>tbody>tr>td:nth-child(5)+td,.ip-geo-block-log>thead>tr>th:nth-child(5),.ip-geo-block-log>thead>tr>th:nth-child(5)+th{width:60%;text-align:left}@media screen and (min-width:1024px){.ip-geo-block-log>tbody>tr>td:nth-child(3),.ip-geo-block-log>tbody>tr>td:nth-child(3)+td,.ip-geo-block-log>thead>tr>th:nth-child(3),.ip-geo-block-log>thead>tr>th:nth-child(3)+th{width:10%}}.ip-geo-block-log>thead>tr>th>span.footable-sort-indicator{color:#888}.ip-geo-block-log>tbody>tr>td{text-align:center}.ip-geo-block-log>tbody>tr>td:first-child{text-align:left;padding-left:.5em}.ip-geo-block-log .footable-row-detail-name,.ip-geo-block-log .footable-row-detail-row,.ip-geo-block-log .footable-row-detail-value{display:block}.ip-geo-block-log .footable-row-detail-value{padding:0 1em 4px;white-space:normal;word-wrap:break-word;word-break:break-all}input#ip_geo_block_settings_filter_logs{width:16em;padding-top:3px}#ip-geo-block-code-list{display:none;margin-bottom:0}#ip-geo-block-chart-countries{height:200px}#ip-geo-block-chart-daily{height:240px}#ip_geo_block_settings_validation_mimetype+label{padding-top:.25em}#ip_geo_block_settings_validation_mimetype+label+ul,#ip_geo_block_settings_validation_plugins,#ip_geo_block_settings_validation_themes{margin-top:.7em}#ip_geo_block_settings_create_user{margin-bottom:.5em}#ip-geo-block-back-to-top a,#ip-geo-block-toggle-sections{box-shadow:none}#ip-geo-block-wp-info textarea{margin-top:.5em;overflow:auto;width:100%;word-wrap:normal;word-break:normal;white-space:pre}#ip-geo-block-preferred{color:#fff;background:#00838f!important;border-color:#00707a!important;text-shadow:none}#ip-geo-block-preferred:hover{background-color:#00919e!important;border-color:#00525a!important}span.ip-geo-block-title-link{font-size:13px}dfn+a.ip-geo-block-cycle{margin-left:.5em}.ip-geo-block-cycle{cursor:pointer;box-shadow:none;text-decoration:none}.ip-geo-block-cycle:active{position:relative;top:1px}.ip-geo-block-cycle span{height:16px;width:16px;margin:0;border:none;display:inline-block;vertical-align:middle;background-size:16px 16px;background-position:center center;background-repeat:no-repeat;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAh1BMVEUAda2otLp+rsSHprWHr8IBd7EpfKRGhaNajqeUqrRymKuKoq5yo7prlKgAcqoVe6w8gqQmgq5Tj6wIdqsVdKIshrEMea1Uhp+Anqw0hawDdq4gfKhljqE7hqoLdKYbgbM4jLQygKUGeK8CdawQd6gVeKcad6NKkrSerrZAj7UAc6sAc6rc3NySrVGQAAAALXRSTlP//////////////////////////////////////////////////////////wCl7wv9AAACOklEQVR4Ae2W15rzKgxF9xTZzhTX9B7S/gN6/9ebYqzzGZsw/S7LV3FZgCSIwD/kQ8FVcBU8xatZUczy8luC/ABNOn0DSHEsvyZ4PgLatNCYR3efFxyhTQ8g+qQgJxgv2JefERzJXATRh4LHOUwAHD4S7OGEztRJaN86hAUxtaNWDUf/bRdDBbQMWVDAO8jn89WUhag1MeyCAh6hHofyrliLgZKggDMYgzF3eVAwFq0uCZq5KY0TezjIHDDzC0qqmkwe2ctGDOQVLMkgu+F3/rGXwb4xIPcJ6P3JgkM8wFjmfcFAWfeKQywaAz33BJVuHsUcAt09gVbuLDThAJkdR687ggLmf4gDJLIGV7BydtB8yn3u+fbtuj/LS7G9wZAd1AKK+yxJ1x+aBmibTtgCcEHGHsh0wdbOgNLek4L7lI5BigY8nWuZUQ3qGEXes9JzOKGJztPaGtLslu3lIXJirdxCWkASHGDTMqg7V1DKPplygDG61YJukLHjEErGSXqCSos6xNSOgzP3BDmsQBcchNwkoV8oiNnPA78zIefUgCdJeGIfE7LmFWXsFTCFdzTJ/RlfEMRiSGnFXXbkC7AIeqcKDu4ynseozeouKJiSEYBDwkJyIC1nRUjgblkNWp/e/1vXc2gjoAoLksYgjrrFMi0oDgjEEIDij1scBXMJSH6DAj6RNl7o8MkuLak8Co15/Pk+MRmT0xilQJV/sdWNKg2kTaeroudvNNsDjmejYjSL+e6v2/2r4Cp4BXNajr0H7hRfAAAAAElFTkSuQmCC)}#ip-geo-block-back-to-top{margin:0;text-align:right}.ip-geo-block-multisite{margin-bottom:1em}ol.ip-geo-block-top-list{display:inline-table;list-style-position:outside;margin:0 2em .5em 1.75em}ol.ip-geo-block-top-list h4{font-size:13px;margin:.5em 0}ol.ip-geo-block-top-list li code{background:0 0}
1
/* This stylesheet is used to style the admin option form of the plugin. */
2
+ #ip-geo-block-scan-code,.ip-geo-block-loading,.ip-geo-block-log *{vertical-align:middle}dfn{cursor:help;border-bottom:1px dotted #888}fieldset,legend{padding:0;margin:0;border:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}fieldset{min-width:0}legend{display:block;line-height:inherit;width:100%}.panel-body,label{display:inline-block}label{max-width:100%}.panel{border:1px solid #e5e5e5;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.04);-moz-box-shadow:0 1px 1px rgba(0,0,0,.04);box-shadow:0 1px 1px rgba(0,0,0,.04);background:#f5f5f5}.panel-heading{float:left!important;background:#fff}.panel-default>.panel-heading{border-color:inherit}.panel-body{width:100%;padding:0 1em;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.panel-body:after,.panel-body:before{content:" ";display:table}.panel-body:after{clear:both}fieldset.ip-geo-block-field{margin:1em 0}fieldset.ip-geo-block-field h2,fieldset.ip-geo-block-field h3{padding:0;margin:0;font-size:14px!important}fieldset.ip-geo-block-field legend.panel-heading{padding:10px}fieldset.ip-geo-block-field .ip-geo-block-dropdown,fieldset.ip-geo-block-field .ip-geo-block-dropup{cursor:pointer;position:relative;padding-left:1em}fieldset.ip-geo-block-field .ip-geo-block-dropdown:before,fieldset.ip-geo-block-field .ip-geo-block-dropup:before{content:'';height:0;width:0;border:.4em solid transparent;position:absolute}fieldset.ip-geo-block-field .ip-geo-block-dropup:before{border-left:.4em solid #555;left:3px;top:15%}fieldset.ip-geo-block-field .ip-geo-block-dropdown:before{border-top:.4em solid #555;left:0;top:35%}fieldset.ip-geo-block-field ul.ip-geo-block-dropup:before{top:.25em}fieldset.ip-geo-block-field ul.ip-geo-block-dropdown:before{top:.45em}fieldset.ip-geo-block-field .form-table{margin:0;width:100%}fieldset.ip-geo-block-field .ip-geo-block-desc{color:#666;font-size:13px}textarea.regular-text{width:25em}ul.ip-geo-block-settings-folding{margin:.5em 0}ul.ip-geo-block-settings-folding ul{margin-bottom:0}ul.ip-geo-block-settings-folding li:first-child{margin-top:.5em}.folding-disable{pointer-events:none;opacity:.5}.folding-inactive{opacity:.5;font-style:oblique!important}ul.ip-geo-block-float li{display:inline-block;width:18em}ul#ip-geo-block-actions dfn{border:none}ul#ip-geo-block-actions span.dashicons{font-size:14px}.ip-geo-block-checked{list-style-type:disc}.ip-geo-block-ip-addr{display:inline-block;padding-top:5px}.ip-geo-block-hide{display:none}.ip-geo-block-result,.ip-geo-block-sup,.ip-geo-block-title,ul.ip-geo-block-list label{display:inline-block}.ip-geo-block-sup{margin-left:.2em}ul.ip-geo-block-note{margin-top:1em;list-style:disc inside}ul.ip-geo-block-list{margin-top:.25em;margin-bottom:.25em}@media screen and (min-width:782px){ul.ip-geo-block-list .code{width:15em}}.ip-geo-block-loading{background-size:16px 16px;background-position:center center;background-repeat:no-repeat;background-image:url(data:image/gif;base64,R0lGODlhEAAQAPIGAAAAAMLCwkJCQpKSkmJiYoKCgv///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAGACwAAAAAEAAQAAADM2i63P4wyklrC0IEKgAQnAdOmGYFBLExwboQWcG2rlHEwTDQLUsUOd2mBxkUCgNKa+dIAAAh+QQJCgAGACwAAAIACgAOAAADLWgWIqHQCABEVLPe1R4MBOFFRFNsRUNsYDFewTC8iixvQ1EMyxjEvyBLODQkAAAh+QQJCgAGACwAAAAACgAOAAADLWi6IRJrCQCECoU0ag1xxeBARuEQ0UUU5DUM7fK+qTEUYR0EcM3Ev51uB7wAEwAh+QQJCgAGACwAAAAADgAKAAADLWi6URQrLiJEkSaM0eqrkLFtAVEEAgAIylAUQ5SuSqCFNZjhWG3zmB8wOJQkAAAh+QQJCgAGACwCAAAADgAKAAADK2hqMRMrLuekCnCU8gqBDCZ2glBcYkSUxIJJgQdaUVDOtAAAAr3oPN/llgAAIfkECQoABgAsBgAAAAoADgAAAytoEdauiz0Yx5BQFTvN2EMXWNgUFETZFIJQdERLiGgZtKohAIDQ7T0RrpEAACH5BAkKAAYALAYAAgAKAA4AAAMqaKoR+609Fie1K4zhZiibNRSg1XAQUXQPIQgE835voQgAIARqh+ummSUBACH5BAUKAAYALAIABgAOAAoAAAMsaLpsES2+F9mEddEgBFbBMGACAAiMOCrlGRBFWBQD2L0dYYjfUuQZEKynSAAAOw==);height:16px;width:16px;margin-left:1em;margin-top:.2em;display:inline-block}.ip-geo-block-border{border-top:inherit}.ip-geo-block-notice{color:#dd3d36}.ip-geo-block-title{width:100px}.ip-geo-block-result{color:#2786C2}#ip-geo-block-map{height:400px;margin:1em auto}.gm-style-iw{width:18em;height:auto!important;height:100%;min-height:100%:}.gm-style-iw ul{margin:.1em}.gm-style-iw li{margin:.2em}ul.ip-geo-block-statistics-countries li{width:12em;float:left;text-align:right;padding:.2em}table.ip-geo-block-statistics-table{float:right}table.ip-geo-block-statistics-table td,table.ip-geo-block-statistics-table th{width:12em;margin:0;padding:.2em;text-align:right;line-height:1.5em;word-wrap:break-word}table.ip-geo-block-statistics-table tr:nth-child(even){background-color:#eee}table.ip-geo-block-table{margin:1em 0;white-space:normal;word-wrap:break-word;word-break:break-all}table.ip-geo-block-table td:first-child{min-width:4.3em}@media screen and (max-width:782px){#ip-geo-block-whois .panel-body{padding:0 .5em}}#ip-geo-block-4 #ip-geo-block-section-1 .panel-body,#ip-geo-block-4 #ip-geo-block-section-2 .panel-body,#ip-geo-block-4 #ip-geo-block-section-3 .panel-body,#ip-geo-block-4 #ip-geo-block-section-4 .panel-body,#ip-geo-block-4 #ip-geo-block-section-5 .panel-body{padding:0;display:table-cell}.ip-geo-block-log{width:100%!important;margin:.5em 0}.ip-geo-block-log *{font-size:13px!important;line-height:1.5em}.ip-geo-block-log .pagination ul{border-radius:4px;display:inline-block;margin:.5em 0 0;padding:0}.ip-geo-block-log .pagination ul>li{display:inline}.ip-geo-block-log .pagination ul>li:first-child>a,.ip-geo-block-log .pagination ul>li:first-child>span{border-bottom-left-radius:4px;border-left-width:1px;border-top-left-radius:4px}.ip-geo-block-log .pagination ul>li:last-child>a,.ip-geo-block-log .pagination ul>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.ip-geo-block-log .pagination ul>.disabled>a,.ip-geo-block-log .pagination ul>.disabled>a:focus,.ip-geo-block-log .pagination ul>.disabled>a:hover,.ip-geo-block-log .pagination ul>.disabled>span{background-color:transparent;color:#999;cursor:default}.ip-geo-block-log .pagination ul>li>a,.ip-geo-block-log .pagination ul>li>span{border-color:#ddd;border-image:none;border-style:solid;border-width:1px 1px 1px 0;float:left;line-height:20px;padding:4px;width:20px;text-decoration:none}.ip-geo-block-log .pagination ul>.active>a,.ip-geo-block-log .pagination ul>.active>span{color:#999;cursor:default}.ip-geo-block-log .pagination ul>.active>a,.ip-geo-block-log .pagination ul>.active>span,.ip-geo-block-log .pagination ul>li>a:focus,.ip-geo-block-log .pagination ul>li>a:hover{background-color:#f7f7f7}.ip-geo-block-log .pagination-centered{text-align:center}.ip-geo-block-log.breakpoint>tbody>tr>td>span.footable-toggle{font-size:60%!important;position:relative;top:-1px;left:2px}.ip-geo-block-log>tbody>tr>td,.ip-geo-block-log>thead>tr>th{padding:4px 0;word-wrap:break-word;width:20%}.ip-geo-block-log>tbody>tr>td:first-child,.ip-geo-block-log>thead>tr>th:first-child{width:25%}.ip-geo-block-log>tbody>tr>td:first-child+td,.ip-geo-block-log>thead>tr>th:first-child+th{width:35%}.ip-geo-block-log>tbody>tr>td:nth-child(5),.ip-geo-block-log>tbody>tr>td:nth-child(5)+td,.ip-geo-block-log>thead>tr>th:nth-child(5),.ip-geo-block-log>thead>tr>th:nth-child(5)+th{width:60%;text-align:left}@media screen and (min-width:1024px){.ip-geo-block-log>tbody>tr>td:nth-child(3),.ip-geo-block-log>tbody>tr>td:nth-child(3)+td,.ip-geo-block-log>thead>tr>th:nth-child(3),.ip-geo-block-log>thead>tr>th:nth-child(3)+th{width:10%}}.ip-geo-block-log>thead>tr>th>span.footable-sort-indicator{color:#888}.ip-geo-block-log>tbody>tr>td{text-align:center}.ip-geo-block-log>tbody>tr>td:first-child{text-align:left;padding-left:.5em}.ip-geo-block-log .footable-row-detail-name,.ip-geo-block-log .footable-row-detail-row,.ip-geo-block-log .footable-row-detail-value{display:block}.ip-geo-block-log .footable-row-detail-value{padding:0 1em 4px;white-space:normal;word-wrap:break-word;word-break:break-all}input#ip_geo_block_settings_filter_logs{width:16em;padding-top:3px}#ip-geo-block-code-list{display:none;margin-bottom:0}#ip-geo-block-chart-countries{height:200px}#ip-geo-block-chart-daily{height:240px}#ip_geo_block_settings_validation_mimetype+label{padding-top:.25em}#ip_geo_block_settings_validation_mimetype+label+ul,#ip_geo_block_settings_validation_plugins,#ip_geo_block_settings_validation_themes{margin-top:.7em}#ip_geo_block_settings_create_user{margin-bottom:.5em}#ip-geo-block-back-to-top a,#ip-geo-block-toggle-sections{box-shadow:none}#ip-geo-block-wp-info textarea{margin-top:.5em;overflow:auto;width:100%;word-wrap:normal;word-break:normal;white-space:pre}#ip-geo-block-preferred{color:#fff;background:#00838f!important;border-color:#00707a!important;text-shadow:none}#ip-geo-block-preferred:hover{background-color:#00919e!important;border-color:#00525a!important}span.ip-geo-block-title-link{font-size:13px}dfn~.ip-geo-block-cycle,dfn~.ip-geo-block-lock,dfn~.ip-geo-block-unlock{margin-left:.75em}.ip-geo-block-cycle,.ip-geo-block-lock,.ip-geo-block-unlock{cursor:pointer;box-shadow:none;text-decoration:none}.ip-geo-block-cycle:active,.ip-geo-block-lock:active,.ip-geo-block-unlock:active{position:relative;top:1px}.ip-geo-block-cycle span,.ip-geo-block-lock span,.ip-geo-block-unlock span{height:16px;width:16px;margin:0;border:none;display:inline-block;vertical-align:middle;background-size:16px 16px;background-position:center center;background-repeat:no-repeat}.ip-geo-block-cycle span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAh1BMVEUAda2otLp+rsSHprWHr8IBd7EpfKRGhaNajqeUqrRymKuKoq5yo7prlKgAcqoVe6w8gqQmgq5Tj6wIdqsVdKIshrEMea1Uhp+Anqw0hawDdq4gfKhljqE7hqoLdKYbgbM4jLQygKUGeK8CdawQd6gVeKcad6NKkrSerrZAj7UAc6sAc6rc3NySrVGQAAAALXRSTlP//////////////////////////////////////////////////////////wCl7wv9AAACOklEQVR4Ae2W15rzKgxF9xTZzhTX9B7S/gN6/9ebYqzzGZsw/S7LV3FZgCSIwD/kQ8FVcBU8xatZUczy8luC/ABNOn0DSHEsvyZ4PgLatNCYR3efFxyhTQ8g+qQgJxgv2JefERzJXATRh4LHOUwAHD4S7OGEztRJaN86hAUxtaNWDUf/bRdDBbQMWVDAO8jn89WUhag1MeyCAh6hHofyrliLgZKggDMYgzF3eVAwFq0uCZq5KY0TezjIHDDzC0qqmkwe2ctGDOQVLMkgu+F3/rGXwb4xIPcJ6P3JgkM8wFjmfcFAWfeKQywaAz33BJVuHsUcAt09gVbuLDThAJkdR687ggLmf4gDJLIGV7BydtB8yn3u+fbtuj/LS7G9wZAd1AKK+yxJ1x+aBmibTtgCcEHGHsh0wdbOgNLek4L7lI5BigY8nWuZUQ3qGEXes9JzOKGJztPaGtLslu3lIXJirdxCWkASHGDTMqg7V1DKPplygDG61YJukLHjEErGSXqCSos6xNSOgzP3BDmsQBcchNwkoV8oiNnPA78zIefUgCdJeGIfE7LmFWXsFTCFdzTJ/RlfEMRiSGnFXXbkC7AIeqcKDu4ynseozeouKJiSEYBDwkJyIC1nRUjgblkNWp/e/1vXc2gjoAoLksYgjrrFMi0oDgjEEIDij1scBXMJSH6DAj6RNl7o8MkuLak8Co15/Pk+MRmT0xilQJV/sdWNKg2kTaeroudvNNsDjmejYjSL+e6v2/2r4Cp4BXNajr0H7hRfAAAAAElFTkSuQmCC)}.ip-geo-block-lock span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAYFBMVEXc3Ny3y9Zzq8dRmb7M1dlXnsIFdK0AcawAcqwphrYAcKvZ29wAb6oJd680jrqlw9MBcqxmo8MUfbJLl75eoMI7kbzX2ttqp8VSmL1YnL8NeK+Tu89DlL1ImMEOebBNmL4OkqMoAAAAAXRSTlMAQObYZgAAAPlJREFUeAG9kAWyhTAQBIPOsCzufv9TPnf4Ll0CSbpmxXwNy3Yc23rz2fV8kPA99433AIQIiGDTCD0lojiOQPXCDSFJIbF16CMWItkQMkF+inZzSLYhFKLl+a9UKTZaqJTZJYtarZuo40chrv9CqJTN+behVi+Cm7RdDgRld6AMgLxrE/dxBz0BEjwBEmD/uIsWPAOAF9A+CE56ufSryr8oqfOYcBbQJ8YkES7COkFOYzTypqCDOTDo2wljaEw4vp1APYyWKd8WMBozylvCpcvmXeHQ5fCegHia4s1FgZcIVeVFeFx1M4MvYG4eBHdYWufC+addBtf8E3vdjBNhWnVQqAAAAABJRU5ErkJggg==)}.ip-geo-block-unlock span{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAYFBMVEXc3NyzydRzq8dRmb7I09hYnsEFdK0AcawAcqzP1toqhrYAcKvZ29wAb6oMeK8zjbqrxtQBcazBz9Zko8MVfbLF0thMmL07kbtpp8WjwtJSmL1YnL+Tu89DlL1JmMEPebBFV++UAAAAAXRSTlMAQObYZgAAAONJREFUeAG9kAWChDAMAIMmJaTFXf7/ynXflvMbnE5j8DU8Pwh8D1yEUYxEGEchWFEJEjEflESBhTQSQm2MRpIotQhZTmgKgMIg5ZlFKBmrGg7UFXJpEQKW8qIKN7YeikJdBJI2BTtXwfyx0L3XoPphvBEliNU49OoxqEa6g4cTST/OYshvi3hV8+FxSNfluG3jqxG8C6h7gF6jU+AODnTsFGSCA5O4I8wpQDq7I5CUAKWQW+AZYOYtoQPoGDeECWDaioBmWQxeBduoWURso+5WpBdw7R4ENTVDcGE435tJwT+xB+vMEnZRNB0YAAAAAElFTkSuQmCC)}#ip-geo-block-back-to-top{margin:0;text-align:right}.ip-geo-block-multisite{margin-bottom:1em}ol.ip-geo-block-top-list{display:inline-table;list-style-position:outside;margin:0 2em .5em 1.75em}ol.ip-geo-block-top-list h4{margin:1em 0}ol.ip-geo-block-top-list li code{background:0 0}#toplevel_page_ip-geo-block .wp-menu-image img{height:18px;width:18px}.ip-geo-block-admin-post{color:#c43322;margin-left:.25em}
admin/images/icon-72x72.png ADDED
Binary file
admin/images/lock.png ADDED
Binary file
admin/images/unlock.png ADDED
Binary file
admin/img/icon-72x72.png ADDED
Binary file
admin/img/lock.png ADDED
Binary file
admin/img/unlock.png ADDED
Binary file
admin/includes/class-admin-ajax.php CHANGED
@@ -27,8 +27,17 @@ class IP_Geo_Block_Admin_Ajax {
27
}
28
29
if ( empty( $res['errorMessage'] ) ) {
30
$tmp = microtime( TRUE );
31
- $res['host'] = IP_Geo_Block_Lkup::gethostbyaddr( $ip );
32
$tmp = microtime( TRUE ) - $tmp;
33
$res['DNS lookup'] = sprintf( '%.1f [msec]', $tmp * 1000.0 );
34
}
@@ -135,10 +144,12 @@ class IP_Geo_Block_Admin_Ajax {
135
$n = 0;
136
137
foreach ( $rows as $row ) {
138
$log = (int)array_shift( $row );
139
$html .= '<tr><td data-value='.$log.'>';
140
$html .= IP_Geo_Block_Util::localdate( $log, 'Y-m-d H:i:s' ) . "</td>";
141
142
$log = array_shift( $row );
143
$html .= '<td><a href="#!">' . esc_html( $log ) . '</a></td>';
144
@@ -252,7 +263,7 @@ class IP_Geo_Block_Admin_Ajax {
252
*
253
*/
254
static public function settings_to_json( $input, $overwrite = TRUE ) {
255
- // [*]:checkbox, [$]:comma separated text to array, [%]:associative array
256
$keys = array(
257
'[version]',
258
'[matching_rule]',
@@ -338,9 +349,11 @@ class IP_Geo_Block_Admin_Ajax {
338
'[clean_uninstall]',
339
'[api_key][GoogleMap]', // 2.2.7
340
'[network_wide]', // 3.0.0
341
'[mimetype][white_list][%]', // 3.0.3
342
'[mimetype][black_list]', // 3.0.3
343
- '[others][%]', // 3.0.3
344
);
345
$json = array();
346
$prfx = IP_Geo_Block::OPTION_NAME;
@@ -404,6 +417,7 @@ class IP_Geo_Block_Admin_Ajax {
404
static public function preferred_to_json() {
405
return self::settings_to_json(
406
array(
407
'validation' => array( // Action hook for validation
408
'comment' => TRUE, // Validate on comment post
409
'login' => 1, // Validate on login
@@ -414,6 +428,7 @@ class IP_Geo_Block_Admin_Ajax {
414
'plugins' => 2, // Validate on wp-content/plugins
415
'themes' => 2, // Validate on wp-content/themes
416
'timing' => 1, // 0:init, 1:mu-plugins, 2:drop-in
417
),
418
'signature' => "../,/wp-config.php,/passwd\ncurl,wget,eval,base64\nselect:.5,where:.5,union:.5\nload_file:.5,create:.6,password:.4",
419
'rewrite' => array( // Apply rewrite rule
@@ -468,6 +483,8 @@ class IP_Geo_Block_Admin_Ajax {
468
469
static public function get_wp_info() {
470
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-lkup.php';
471
472
// DNS reverse lookup
473
$key = microtime( TRUE );
@@ -476,15 +493,16 @@ class IP_Geo_Block_Admin_Ajax {
476
477
// Server, PHP, WordPress
478
$res = array(
479
- 'Server:' => $_SERVER['SERVER_SOFTWARE'],
480
- 'PHP:' => PHP_VERSION,
481
- 'WordPress:' => $GLOBALS['wp_version'],
482
- 'Multisite:' => is_multisite() ? 'yes' : 'no',
483
- 'Zlib:' => function_exists( 'gzopen' ) ? 'yes' : 'no',
484
- 'ZipArchive:' => class_exists( 'ZipArchive', FALSE ) ? 'yes' : 'no',
485
- 'BC Math:' => (extension_loaded('gmp') ? 'gmp ' : '') . (function_exists('bcadd') ? 'yes' : 'no'),
486
- 'mb_strcut:' => function_exists( 'mb_strcut' ) ? 'yes' : 'no',
487
- 'DNS lookup:' => ('8.8.8.8' !== $val ? 'available' : 'n/a') . sprintf( ' [%.1f msec]', $key * 1000.0 ),
488
);
489
490
// Child and parent themes
27
}
28
29
if ( empty( $res['errorMessage'] ) ) {
30
+ if ( $options['Maxmind']['asn4_path'] && ( $geo = IP_Geo_Block_API::get_instance( 'Maxmind', $options ) ) ) {
31
+ $tmp = microtime( TRUE );
32
+ $geo = $geo->get_location( $ip, array( 'ASN' => TRUE ) );
33
+ $tmp = microtime( TRUE ) - $tmp;
34
+
35
+ $res['AS number'] = isset( $geo['ASN'] ) ? esc_html( $geo['ASN'] ) : '';
36
+ $res['AS number'] .= sprintf( ' (%.1f [msec])', $tmp * 1000.0 );
37
+ }
38
+
39
$tmp = microtime( TRUE );
40
+ $res['host'] = esc_html( IP_Geo_Block_Lkup::gethostbyaddr( $ip ) );
41
$tmp = microtime( TRUE ) - $tmp;
42
$res['DNS lookup'] = sprintf( '%.1f [msec]', $tmp * 1000.0 );
43
}
144
$n = 0;
145
146
foreach ( $rows as $row ) {
147
+ // Time of date
148
$log = (int)array_shift( $row );
149
$html .= '<tr><td data-value='.$log.'>';
150
$html .= IP_Geo_Block_Util::localdate( $log, 'Y-m-d H:i:s' ) . "</td>";
151
152
+ // IP address
153
$log = array_shift( $row );
154
$html .= '<td><a href="#!">' . esc_html( $log ) . '</a></td>';
155
263
*
264
*/
265
static public function settings_to_json( $input, $overwrite = TRUE ) {
266
+ // [*]:list of checkboxes, [$]:comma separated text to array, [%]:associative array
267
$keys = array(
268
'[version]',
269
'[matching_rule]',
349
'[clean_uninstall]',
350
'[api_key][GoogleMap]', // 2.2.7
351
'[network_wide]', // 3.0.0
352
+ '[others][%]', // 3.0.3
353
'[mimetype][white_list][%]', // 3.0.3
354
'[mimetype][black_list]', // 3.0.3
355
+ '[mimetype][capability][$]', // 3.0.4
356
+ '[Maxmind][use_asn]', // 3.0.4
357
);
358
$json = array();
359
$prfx = IP_Geo_Block::OPTION_NAME;
417
static public function preferred_to_json() {
418
return self::settings_to_json(
419
array(
420
+ 'login_fails' => 10, // Limited number of login attempts
421
'validation' => array( // Action hook for validation
422
'comment' => TRUE, // Validate on comment post
423
'login' => 1, // Validate on login
428
'plugins' => 2, // Validate on wp-content/plugins
429
'themes' => 2, // Validate on wp-content/themes
430
'timing' => 1, // 0:init, 1:mu-plugins, 2:drop-in
431
+ 'mimetype' => 1, // 0:disable, 1:white_list, 2:black_list
432
),
433
'signature' => "../,/wp-config.php,/passwd\ncurl,wget,eval,base64\nselect:.5,where:.5,union:.5\nload_file:.5,create:.6,password:.4",
434
'rewrite' => array( // Apply rewrite rule
483
484
static public function get_wp_info() {
485
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-lkup.php';
486
+ require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-file.php';
487
+ $fs = IP_Geo_Block_FS::init( 'get_wp_info' );
488
489
// DNS reverse lookup
490
$key = microtime( TRUE );
493
494
// Server, PHP, WordPress
495
$res = array(
496
+ 'Server:' => $_SERVER['SERVER_SOFTWARE'],
497
+ 'PHP:' => PHP_VERSION,
498
+ 'WordPress:' => $GLOBALS['wp_version'],
499
+ 'Multisite:' => is_multisite() ? 'yes' : 'no',
500
+ 'File system:' => $fs->get_method(),
501
+ 'Zlib:' => function_exists( 'gzopen' ) ? 'yes' : 'no',
502
+ 'ZipArchive:' => class_exists( 'ZipArchive', FALSE ) ? 'yes' : 'no',
503
+ 'BC Math:' => (extension_loaded('gmp') ? 'gmp ' : '') . (function_exists('bcadd') ? 'yes' : 'no'),
504
+ 'mb_strcut:' => function_exists( 'mb_strcut' ) ? 'yes' : 'no',
505
+ 'DNS lookup:' => ('8.8.8.8' !== $val ? 'available' : 'n/a') . sprintf( ' [%.1f msec]', $key * 1000.0 ),
506
);
507
508
// Child and parent themes
admin/includes/class-admin-rewrite.php CHANGED
@@ -4,16 +4,17 @@ class IP_Geo_Block_Admin_Rewrite {
4
/**
5
* Instance of this class.
6
*/
7
- protected static $instance = NULL;
8
9
// private values
10
- private $doc_root = NULL; // document root
11
- private $base_uri = NULL; // plugins base uri
12
- private $wp_dirs = array();
13
14
// template of rewrite rule in wp-content/(plugins|themes)/
15
private $rewrite_rule = array(
16
- 'apache' => array(
17
'plugins' => array(
18
'# BEGIN IP Geo Block',
19
'<IfModule mod_rewrite.c>',
@@ -34,36 +35,57 @@ class IP_Geo_Block_Admin_Rewrite {
34
'# END IP Geo Block',
35
),
36
),
37
- 'nginx' => array(
38
'plugins' => array(
39
- '# BEGIN IP Geo Block',
40
- 'location ~ %REWRITE_BASE%rewrite.php$ {}',
41
- 'location %WP_CONTENT_DIR%/plugins/ {',
42
- ' rewrite ^%WP_CONTENT_DIR%/plugins/.*/.*\.php$ %REWRITE_BASE%rewrite.php break;',
43
- '}',
44
- '# END IP Geo Block',
45
),
46
'themes' => array(
47
- '# BEGIN IP Geo Block',
48
- 'location %WP_CONTENT_DIR%/themes/ {',
49
- ' rewrite ^%WP_CONTENT_DIR%/themes/.*/.*\.php$ %REWRITE_BASE%rewrite.php break;',
50
- '}',
51
- '# END IP Geo Block',
52
),
53
),
54
);
55
56
- public function __construct() {
57
// http://stackoverflow.com/questions/25017381/setting-php-document-root-on-webserver
58
$this->doc_root = str_replace( $_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME'] );
59
$this->base_uri = str_replace( $this->doc_root, '', IP_GEO_BLOCK_PATH );
60
61
// target directories
62
- $condir = str_replace( $this->doc_root, '', WP_CONTENT_DIR );
63
$this->wp_dirs = array(
64
- 'plugins' => $condir . '/plugins/',
65
- 'themes' => $condir . '/themes/',
66
);
67
}
68
69
/**
@@ -74,129 +96,135 @@ class IP_Geo_Block_Admin_Rewrite {
74
return self::$instance ? self::$instance : ( self::$instance = new self );
75
}
76
77
- /**
78
- * Get type of server
79
- *
80
- * @return string 'apache', 'nginx' or NULL
81
- */
82
- private function get_server_type() {
83
- global $is_apache, $is_nginx; // wp-includes/vars.php
84
- return $is_apache ? 'apache' : ( $is_nginx ? 'nginx' : NULL );
85
- }
86
-
87
/**
88
* Extract the block of rewrite rule
89
*
90
- * @param array contents of configuration file
91
* @return array list of begin and end
92
*/
93
private function find_rewrite_block( $content ) {
94
return preg_grep(
95
- '/^\s*?[#;]\s*?(BEGIN|END)?\s*?IP Geo Block\s*?(BEGIN|END)?\s*?#x2F;i',
96
- $content
97
);
98
}
99
100
/**
101
* Get the path of .htaccess in wp-content/plugins/themes/
102
*
103
- * @param string 'plugins' or 'themes'
104
- * @return string absolute path to the .htaccess
105
*/
106
private function get_rewrite_file( $which ) {
107
- global $is_apache, $is_nginx; // wp-includes/vars.php
108
-
109
- if ( $is_apache ) {
110
- return $this->doc_root . $this->wp_dirs[ $which ] . '.htaccess';
111
- }
112
-
113
- elseif ( $is_nginx ) {
114
- return NULL; /* MUST FIX */
115
- }
116
-
117
- else {
118
return NULL; /* NOT SUPPORTED */
119
- }
120
}
121
122
/**
123
* Get contents in .htaccess in wp-content/(plugins|themes)/
124
*
125
* @param string 'plugins' or 'themes'
126
- * @return array contents of configuration file
127
*/
128
private function get_rewrite_rule( $which ) {
129
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-file.php';
130
$fs = IP_Geo_Block_FS::init( 'get_rewrite_rule' );
131
132
$file = $this->get_rewrite_file( $which );
133
- $exist = $fs->exists( $file );
134
135
// check permission
136
if ( $exist ) {
137
- if ( ! $fs->is_readable( $file ) )
138
- return FALSE;
139
- } else {
140
- if ( ! $fs->is_readable( dirname( $file ) ) )
141
- return FALSE;
142
}
143
144
// get file contents as an array
145
- return $exist ? $fs->get_contents_array( $file ) : array();
146
}
147
148
/**
149
* Put contents to .htaccess in wp-content/(plugins|themes)/
150
*
151
- * @param string 'plugins' or 'themes'
152
- * @param array contents of configuration file
153
*/
154
private function put_rewrite_rule( $which, $content ) {
155
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-file.php';
156
$fs = IP_Geo_Block_FS::init( 'put_rewrite_rule' );
157
158
$file = $this->get_rewrite_file( $which );
159
- if ( ! $file || FALSE === $fs->put_contents( $file, implode( PHP_EOL, $content ) ) )
160
return FALSE;
161
162
// if content is empty then remove file
163
- if ( empty( $content ) )
164
- return $fs->delete( $file );
165
-
166
- return TRUE;
167
}
168
169
/**
170
* Check if the block of rewrite rule exists
171
*
172
* @param string 'plugins' or 'themes'
173
- * @return bool TRUE or FALSE
174
*/
175
private function get_rewrite_stat( $which ) {
176
- global $is_apache, $is_nginx; // wp-includes/vars.php
177
178
- if ( $is_apache ) {
179
- if ( FALSE === ( $content = $this->get_rewrite_rule( $which ) ) )
180
- return FALSE;
181
182
$block = $this->find_rewrite_block( $content );
183
- return empty( $block ) ? FALSE : TRUE;
184
- }
185
186
- elseif ( $is_nginx ) {
187
- // https://www.wordfence.com/blog/2014/05/nginx-wordfence-falcon-engine-php-fpm-fastcgi-fast-cgi/
188
- return -1; /* CURRENTLY NOT SUPPORTED */
189
- }
190
191
- else {
192
- return -1; /* NOT SUPPORTED */
193
}
194
}
195
196
/**
197
* Remove the block of rewrite rule
198
*
199
- * @param array contents of configuration file
200
* @return array array of contents without rewrite rule
201
*/
202
private function remove_rewrite_block( $content, $block ) {
@@ -218,67 +246,102 @@ class IP_Geo_Block_Admin_Rewrite {
218
* Append the block of rewrite rule
219
*
220
* @param string 'plugins' or 'themes'
221
- * @param array contents of configuration file
222
* @return array array of contents with the block of rewrite rule
223
*/
224
private function append_rewrite_block( $which, $content ) {
225
- $server_type = $this->get_server_type();
226
-
227
- return $server_type ? array_merge(
228
- $content,
229
- str_replace(
230
- array( '%REWRITE_BASE%', '%WP_CONTENT_DIR%' ),
231
- array( $this->base_uri, WP_CONTENT_DIR ),
232
- $this->rewrite_rule[ $server_type ][ $which ]
233
- )
234
- ) : array();
235
}
236
237
/**
238
* Add rewrite rule to server configration
239
*
240
* @param string 'plugins' or 'themes'
241
*/
242
private function add_rewrite_rule( $which ) {
243
- global $is_apache, $is_nginx; // wp-includes/vars.php
244
245
- if ( $is_apache ) {
246
- if ( FALSE === ( $content = $this->get_rewrite_rule( $which ) ) )
247
- return FALSE;
248
249
- $block = $this->find_rewrite_block( $content );
250
251
- if ( empty( $block ) ) {
252
- $content = $this->remove_rewrite_block( $content, $block );
253
- $content = $this->append_rewrite_block( $which, $content );
254
- return $this->put_rewrite_rule( $which, $content );
255
}
256
}
257
258
- return TRUE;
259
}
260
261
/**
262
* Delete rewrite rule to server configration
263
*
264
* @param string 'plugins' or 'themes'
265
*/
266
private function del_rewrite_rule( $which ) {
267
- global $is_apache, $is_nginx; // wp-includes/vars.php
268
269
- if ( $is_apache ) {
270
- if ( FALSE === ( $content = $this->get_rewrite_rule( $which ) ) )
271
- return FALSE;
272
273
- $block = $this->find_rewrite_block( $content );
274
275
- if ( ! empty( $block ) ) {
276
- $content = $this->remove_rewrite_block( $content, $block );
277
- return $this->put_rewrite_rule( $which, $content );
278
}
279
}
280
281
- return TRUE;
282
}
283
284
/**
@@ -286,11 +349,12 @@ class IP_Geo_Block_Admin_Rewrite {
286
*
287
*/
288
public static function check_rewrite_all() {
289
- $status = array();
290
$rewrite = self::get_instance();
291
292
- foreach ( array_keys( $rewrite->rewrite_rule['apache'] ) as $key ) {
293
- $status[ $key ] = $rewrite->get_rewrite_stat( $key );
294
}
295
296
return $status;
@@ -303,7 +367,7 @@ class IP_Geo_Block_Admin_Rewrite {
303
public static function activate_rewrite_all( $options ) {
304
$rewrite = self::get_instance();
305
306
- foreach ( array_keys( $rewrite->rewrite_rule['apache'] ) as $key ) {
307
if ( $options[ $key ] )
308
// if it fails to write, then return FALSE
309
$options[ $key ] = $rewrite->add_rewrite_rule( $key ) ? TRUE : FALSE;
@@ -322,9 +386,8 @@ class IP_Geo_Block_Admin_Rewrite {
322
public static function deactivate_rewrite_all() {
323
$rewrite = self::get_instance();
324
325
- foreach ( array_keys( $rewrite->rewrite_rule['apache'] ) as $key ) {
326
- if ( FALSE === $rewrite->del_rewrite_rule( $key ) )
327
- return FALSE;
328
}
329
330
return TRUE;
@@ -339,4 +402,13 @@ class IP_Geo_Block_Admin_Rewrite {
339
return str_replace( $rewrite->doc_root, '', $rewrite->wp_dirs );
340
}
341
342
}
4
/**
5
* Instance of this class.
6
*/
7
+ private static $instance = NULL;
8
9
// private values
10
+ private $doc_root = NULL; // document root
11
+ private $base_uri = NULL; // plugins base uri
12
+ private $config_file = NULL; // `.htaccess` or `.user.ini`
13
+ private $wp_dirs = array(); // path to `plugins` and `themes`
14
15
// template of rewrite rule in wp-content/(plugins|themes)/
16
private $rewrite_rule = array(
17
+ '.htaccess' => array(
18
'plugins' => array(
19
'# BEGIN IP Geo Block',
20
'<IfModule mod_rewrite.c>',
35
'# END IP Geo Block',
36
),
37
),
38
+ '.user.ini' => array(
39
'plugins' => array(
40
+ '; BEGIN IP Geo Block',
41
+ 'auto_prepend_file = "%ABSPATH%wp-load.php"',
42
+ '; END IP Geo Block',
43
),
44
'themes' => array(
45
+ '; BEGIN IP Geo Block',
46
+ 'auto_prepend_file = "%ABSPATH%wp-load.php"',
47
+ '; END IP Geo Block',
48
),
49
),
50
+ // https://www.wordfence.com/blog/2014/05/nginx-wordfence-falcon-engine-php-fpm-fastcgi-fast-cgi/
51
+ // 'nginx' => array(
52
+ // 'plugins' => array(
53
+ // '# BEGIN IP Geo Block',
54
+ // 'location ~ %REWRITE_BASE%rewrite.php$ {}',
55
+ // 'location %WP_CONTENT_DIR%/plugins/ {',
56
+ // ' rewrite ^%WP_CONTENT_DIR%/plugins/.*/.*\.php$ %REWRITE_BASE%rewrite.php break;',
57
+ // '}',
58
+ // '# END IP Geo Block',
59
+ // 'themes' => array(
60
+ // '# BEGIN IP Geo Block',
61
+ // 'location %WP_CONTENT_DIR%/themes/ {',
62
+ // ' rewrite ^%WP_CONTENT_DIR%/themes/.*/.*\.php$ %REWRITE_BASE%rewrite.php break;',
63
+ // '}',
64
+ // '# END IP Geo Block',
65
+ // ),
66
+ // ),
67
);
68
69
+ private function __construct() {
70
// http://stackoverflow.com/questions/25017381/setting-php-document-root-on-webserver
71
$this->doc_root = str_replace( $_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME'] );
72
$this->base_uri = str_replace( $this->doc_root, '', IP_GEO_BLOCK_PATH );
73
74
// target directories
75
+ $path = str_replace( $this->doc_root, '', WP_CONTENT_DIR );
76
$this->wp_dirs = array(
77
+ 'plugins' => $path . '/plugins/',
78
+ 'themes' => $path . '/themes/',
79
);
80
+
81
+ // Apache in wp-includes/vars.php
82
+ global $is_apache;
83
+ if ( $is_apache )
84
+ $this->config_file = '.htaccess';
85
+
86
+ // CGI/FastCGI SAPI (cgi, cgi-fcgi, fpm-fcgi)
87
+ // elseif ( version_compare( PHP_VERSION, '5.3' ) >= 0 && FALSE !== strpos( php_sapi_name(), 'cgi' ) )
88
+ // $this->config_file = ini_get( 'user_ini.filename' );
89
}
90
91
/**
96
return self::$instance ? self::$instance : ( self::$instance = new self );
97
}
98
99
/**
100
* Extract the block of rewrite rule
101
*
102
+ * @param array contents of configuration file
103
* @return array list of begin and end
104
*/
105
private function find_rewrite_block( $content ) {
106
return preg_grep(
107
+ '/^\s*?[#;]\s*?(?:BEGIN|END)\s*?IP Geo Block\s*?#x2F;i',
108
+ (array)$content
109
);
110
}
111
112
/**
113
* Get the path of .htaccess in wp-content/plugins/themes/
114
*
115
+ * @param string 'plugins' or 'themes'
116
+ * @return string absolute path to the .htaccess or NULL
117
*/
118
private function get_rewrite_file( $which ) {
119
+ if ( $this->config_file )
120
+ return $this->doc_root . $this->wp_dirs[ $which ] . $this->config_file;
121
+ else
122
return NULL; /* NOT SUPPORTED */
123
}
124
125
/**
126
* Get contents in .htaccess in wp-content/(plugins|themes)/
127
*
128
* @param string 'plugins' or 'themes'
129
+ * @return array contents of configuration file or WP_Error
130
*/
131
private function get_rewrite_rule( $which ) {
132
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-file.php';
133
$fs = IP_Geo_Block_FS::init( 'get_rewrite_rule' );
134
135
+ // check the existence of configuration file
136
$file = $this->get_rewrite_file( $which );
137
+ $exist = $file ? $fs->exists( $file ) : FALSE;
138
139
// check permission
140
if ( $exist ) {
141
+ if ( ! $fs->is_readable( $file ) ) {
142
+ return new WP_Error( 'Error',
143
+ sprintf( __( 'Unable to read <code>%s</code>. Please check the permission.', 'ip-geo-block' ), $file ) . ' ' .
144
+ sprintf( __( 'Or please refer to %s to set it manually.', 'ip-geo-block' ), '<a href="http://www.ipgeoblock.com/codex/how-to-fix-permission-troubles.html" title="How to fix permission troubles? | IP Geo Block">How to fix permission troubles?</a>' )
145
+ );
146
+ }
147
}
148
149
// get file contents as an array
150
+ $exist = $fs->get_contents_array( $file );
151
+ return FALSE !== $exist ? $exist : array();
152
}
153
154
/**
155
* Put contents to .htaccess in wp-content/(plugins|themes)/
156
*
157
+ * @param string $which 'plugins' or 'themes'
158
+ * @param array contents of configuration file
159
+ * @return bool TRUE (success) or FALSE (failure)
160
*/
161
private function put_rewrite_rule( $which, $content ) {
162
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-file.php';
163
$fs = IP_Geo_Block_FS::init( 'put_rewrite_rule' );
164
165
$file = $this->get_rewrite_file( $which );
166
+
167
+ if ( ! $file || FALSE === $fs->put_contents( $file, implode( PHP_EOL, $content ) ) ) {
168
+ $this->show_message(
169
+ sprintf( __( 'Unable to write <code>%s</code>. Please check the permission.', 'ip-geo-block' ), $file ) . ' ' .
170
+ sprintf( __( 'Or please refer to %s to set it manually.', 'ip-geo-block' ), '<a href="http://www.ipgeoblock.com/codex/how-to-fix-permission-troubles.html" title="How to fix permission troubles? | IP Geo Block">How to fix permission troubles?</a>' )
171
+ );
172
return FALSE;
173
+ }
174
175
// if content is empty then remove file
176
+ return empty( $content ) ? $fs->delete( $file ) : TRUE;
177
}
178
179
/**
180
* Check if the block of rewrite rule exists
181
*
182
* @param string 'plugins' or 'themes'
183
+ * @return bool TRUE (found), FALSE (not found or unavailable) or WP_Error
184
*/
185
private function get_rewrite_stat( $which ) {
186
+ if ( $this->config_file ) {
187
+ $content = $this->get_rewrite_rule( $which );
188
189
+ if ( is_wp_error( $content ) )
190
+ return $content;
191
192
$block = $this->find_rewrite_block( $content );
193
194
+ if ( '.htaccess' === $this->config_file ) {
195
+ return empty( $block ) ? FALSE : TRUE;
196
+ }
197
198
+ else {
199
+ if ( empty( $block ) ) {
200
+ $block = preg_grep( '/auto_prepend_file/i', $content );
201
+
202
+ if ( empty( $block ) ) {
203
+ return FALSE; // rewrite rule is not found in configuration file
204
+ }
205
+
206
+ else {
207
+ return new WP_Error( 'Error', sprintf(
208
+ __( '&#8220;auto_prepend_file&#8221; already defined in %s.', 'ip-geo-block' ),
209
+ $this->get_rewrite_file( $which )
210
+ ) );
211
+ }
212
+ }
213
+
214
+ else {
215
+ return TRUE; // rewrite rule already exists in configuration file
216
+ }
217
+ }
218
}
219
+
220
+ return -1; /* NOT SUPPORTED */
221
}
222
223
/**
224
* Remove the block of rewrite rule
225
*
226
+ * @param array contents of configuration file
227
+ * @param array contents to be removed
228
* @return array array of contents without rewrite rule
229
*/
230
private function remove_rewrite_block( $content, $block ) {
246
* Append the block of rewrite rule
247
*
248
* @param string 'plugins' or 'themes'
249
+ * @param array contents of configuration file
250
* @return array array of contents with the block of rewrite rule
251
*/
252
private function append_rewrite_block( $which, $content ) {
253
+ if ( $type = $this->config_file ) {
254
+ // in case `.user.ini` is configured differently
255
+ if ( '.htaccess' !== $type && '.user.ini' !== $type )
256
+ $type = '.user.ini';
257
+
258
+ return array_merge(
259
+ $content,
260
+ str_replace(
261
+ array( '%REWRITE_BASE%', '%WP_CONTENT_DIR%', '%ABSPATH%' ),
262
+ array( $this->base_uri, WP_CONTENT_DIR, ABSPATH ),
263
+ $this->rewrite_rule[ $type ][ $which ]
264
+ )
265
+ );
266
+ }
267
+
268
+ return array();
269
}
270
271
/**
272
* Add rewrite rule to server configration
273
*
274
* @param string 'plugins' or 'themes'
275
+ * @return bool TRUE (found), FALSE (not found or unavailable)
276
*/
277
private function add_rewrite_rule( $which ) {
278
+ $stat = $this->get_rewrite_stat( $which );
279
280
+ if ( is_wp_error( $stat ) ) {
281
+ $this->show_message( $stat->get_error_message() );
282
+ return FALSE;
283
+ }
284
285
+ elseif ( TRUE === $stat ) {
286
+ return TRUE;
287
+ }
288
289
+ elseif ( FALSE === $stat ) {
290
+ $content = $this->get_rewrite_rule( $which );
291
+
292
+ if ( is_wp_error( $content ) ) {
293
+ $this->show_message( $content->get_error_message() );
294
+ return FALSE;
295
}
296
+
297
+ $content = $this->append_rewrite_block( $which, $content );
298
+ return $this->put_rewrite_rule( $which, $content );
299
}
300
301
+ return -1; /* NOT SUPPORTED */
302
}
303
304
/**
305
* Delete rewrite rule to server configration
306
*
307
* @param string 'plugins' or 'themes'
308
+ * @return bool TRUE (found), FALSE (not found or unavailable)
309
*/
310
private function del_rewrite_rule( $which ) {
311
+ $stat = $this->get_rewrite_stat( $which );
312
313
+ if ( is_wp_error( $stat ) ) {
314
+ $this->show_message( $stat->get_error_message() );
315
+ return FALSE;
316
+ }
317
318
+ elseif ( FALSE === $stat ) {
319
+ return TRUE;
320
+ }
321
+
322
+ elseif ( TRUE === $stat ) {
323
+ $content = $this->get_rewrite_rule( $which );
324
325
+ if ( is_wp_error( $content ) ) {
326
+ $this->show_message( $content->get_error_message() );
327
+ return FALSE;
328
}
329
+
330
+ $block = $this->find_rewrite_block( $content );
331
+ $content = $this->remove_rewrite_block( $content, $block );
332
+ return $this->put_rewrite_rule( $which, $content );
333
}
334
335
+ return -1; /* NOT SUPPORTED */
336
+ }
337
+
338
+ /**
339
+ * Show notice message
340
+ *
341
+ */
342
+ private function show_message( $msg ) {
343
+ if ( class_exists( 'IP_Geo_Block_Admin' ) )
344
+ IP_Geo_Block_Admin::add_admin_notice( 'error', $msg );
345
}
346
347
/**
349
*
350
*/
351
public static function check_rewrite_all() {
352
$rewrite = self::get_instance();
353
354
+ $status = array();
355
+ foreach ( array_keys( $rewrite->rewrite_rule['.htaccess'] ) as $key ) {
356
+ $stat = $rewrite->get_rewrite_stat( $key );
357
+ $status[ $key ] = is_wp_error( $stat ) ? FALSE : $stat;
358
}
359
360
return $status;
367
public static function activate_rewrite_all( $options ) {
368
$rewrite = self::get_instance();
369
370
+ foreach ( array_keys( $rewrite->rewrite_rule['.htaccess'] ) as $key ) {
371
if ( $options[ $key ] )
372
// if it fails to write, then return FALSE
373
$options[ $key ] = $rewrite->add_rewrite_rule( $key ) ? TRUE : FALSE;
386
public static function deactivate_rewrite_all() {
387
$rewrite = self::get_instance();
388
389
+ foreach ( array_keys( $rewrite->rewrite_rule['.htaccess'] ) as $key ) {
390
+ $rewrite->del_rewrite_rule( $key );
391
}
392
393
return TRUE;
402
return str_replace( $rewrite->doc_root, '', $rewrite->wp_dirs );
403
}
404
405
+ /**
406
+ * Return configuration file type.
407
+ *
408
+ */
409
+ public static function get_config_file() {
410
+ $rewrite = self::get_instance();
411
+ return $rewrite->config_file;
412
+ }
413
+
414
}
admin/includes/tab-accesslog.php CHANGED
@@ -14,9 +14,8 @@ if ( $options['validation']['reclogs'] ) :
14
/*----------------------------------------*
15
* Validation logs
16
*----------------------------------------*/
17
- $section = IP_Geo_Block::PLUGIN_NAME . '-accesslog';
18
add_settings_section(
19
- $section,
20
__( 'Validation logs', 'ip-geo-block' ),
21
NULL,
22
$option_slug
@@ -34,7 +33,7 @@ if ( $options['validation']['reclogs'] ) :
34
'type' => 'text',
35
'option' => $option_name,
36
'field' => $field,
37
- 'value' => '',
38
'after' => '<a class="button button-secondary" id="ip-geo-block-reset-filter" title="' . __( 'Reset', 'ip-geo-block' ) . '" href="javascript:void(0)">'. __( 'Reset', 'ip-geo-block' ) . '</a>',
39
)
40
);
@@ -88,14 +87,13 @@ if ( $options['validation']['reclogs'] ) :
88
);
89
}
90
91
- else:
92
93
/*----------------------------------------*
94
* Warning
95
*----------------------------------------*/
96
- $section = IP_Geo_Block::PLUGIN_NAME . '-accesslog';
97
add_settings_section(
98
- $section,
99
__( 'Validation logs', 'ip-geo-block' ),
100
array( __CLASS__, 'warn_accesslog' ),
101
$option_slug
@@ -114,7 +112,8 @@ else:
114
)
115
);
116
117
- endif;
118
}
119
120
/**
@@ -129,11 +128,12 @@ endif;
129
130
private static function list_accesslog( $key ) {
131
echo '<table class="fixed ', IP_Geo_Block::PLUGIN_NAME, '-log" data-page-size="10" data-limit-navigation="5" data-filter="#', IP_Geo_Block::OPTION_NAME, '_filter_logs" data-filter-text-only="true" style="display:none"><thead><tr>', "\n";
132
- echo '<th data-type="numeric">', __( 'Date', 'ip-geo-block' ), '</th>', "\n";
133
- echo '<th>', __( 'IP address', 'ip-geo-block' ), '</th>', "\n";
134
- echo '<th>', __( 'Code', 'ip-geo-block' ), '</th>', "\n";
135
- echo '<th>', __( 'Result', 'ip-geo-block' ), '</th>', "\n";
136
- echo '<th data-hide="phone,tablet">', __( 'Request', 'ip-geo-block' ), '</th>', "\n";
137
echo '<th data-hide="all">', __( 'User agent', 'ip-geo-block' ), '</th>', "\n";
138
echo '<th data-hide="all">', __( 'HTTP headers', 'ip-geo-block' ), '</th>', "\n";
139
echo '<th data-hide="all">', __( '$_POST data', 'ip-geo-block' ), '</th>', "\n";
14
/*----------------------------------------*
15
* Validation logs
16
*----------------------------------------*/
17
add_settings_section(
18
+ $section = IP_Geo_Block::PLUGIN_NAME . '-accesslog',
19
__( 'Validation logs', 'ip-geo-block' ),
20
NULL,
21
$option_slug
33
'type' => 'text',
34
'option' => $option_name,
35
'field' => $field,
36
+ 'value' => isset( $_GET['s'] ) ? esc_html( $_GET['s'] ) : '', // preset filter
37
'after' => '<a class="button button-secondary" id="ip-geo-block-reset-filter" title="' . __( 'Reset', 'ip-geo-block' ) . '" href="javascript:void(0)">'. __( 'Reset', 'ip-geo-block' ) . '</a>',
38
)
39
);
87
);
88
}
89
90
+ else: // $options['validation']['reclogs']
91
92
/*----------------------------------------*
93
* Warning
94
*----------------------------------------*/
95
add_settings_section(
96
+ $section = IP_Geo_Block::PLUGIN_NAME . '-accesslog',
97
__( 'Validation logs', 'ip-geo-block' ),
98
array( __CLASS__, 'warn_accesslog' ),
99
$option_slug
112
)
113
);
114
115
+ endif; // $options['validation']['reclogs']
116
+
117
}
118
119
/**
128
129
private static function list_accesslog( $key ) {
130
echo '<table class="fixed ', IP_Geo_Block::PLUGIN_NAME, '-log" data-page-size="10" data-limit-navigation="5" data-filter="#', IP_Geo_Block::OPTION_NAME, '_filter_logs" data-filter-text-only="true" style="display:none"><thead><tr>', "\n";
131
+ echo '<th data-type="numeric">', __( 'Date', 'ip-geo-block' ), '</th>', "\n";
132
+ echo '<th>', __( 'IP address', 'ip-geo-block' ), '</th>', "\n";
133
+ echo '<th>', __( 'Code', 'ip-geo-block' ), '</th>', "\n";
134
+ echo '<th>', __( 'Result', 'ip-geo-block' ), '</th>', "\n";
135
+ echo '<th data-hide="phone,tablet">', __( 'AS number', 'ip-geo-block' ), '</th>', "\n";
136
+ echo '<th data-hide="all">', __( 'Request', 'ip-geo-block' ), '</th>', "\n";
137
echo '<th data-hide="all">', __( 'User agent', 'ip-geo-block' ), '</th>', "\n";
138
echo '<th data-hide="all">', __( 'HTTP headers', 'ip-geo-block' ), '</th>', "\n";
139
echo '<th data-hide="all">', __( '$_POST data', 'ip-geo-block' ), '</th>', "\n";
admin/includes/tab-network.php ADDED
@@ -0,0 +1,99 @@
1
+ <?php
2
+ class IP_Geo_Block_Admin_Tab {
3
+
4
+ public static function tab_setup( $context, $tab ) {
5
+
6
+ register_setting(
7
+ $option_slug = IP_Geo_Block::PLUGIN_NAME,
8
+ $option_name = IP_Geo_Block::OPTION_NAME
9
+ );
10
+
11
+ $section = IP_Geo_Block::PLUGIN_NAME . '-multisite';
12
+ $field = 'multisite';
13
+
14
+ global $wpdb;
15
+ foreach ( $wpdb->get_col( "SELECT `blog_id` FROM `$wpdb->blogs`" ) as $id ) {
16
+ switch_to_blog( $id );
17
+
18
+ add_settings_section(
19
+ $section . '-' . $id,
20
+ get_bloginfo( 'name' ),
21
+ array( __CLASS__, 'render_log' ),
22
+ $option_slug
23
+ );
24
+
25
+ restore_current_blog();
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Render log data
31
+ *
32
+ * @param array $args associative array of `id`, `title`, `callback`.
33
+ */
34
+ public static function render_log( $args ) {
35
+ switch_to_blog( str_replace( IP_Geo_Block::PLUGIN_NAME . '-multisite-', '', $args['id'] ) );
36
+
37
+ echo '<p>';
38
+ echo '[ <a target="_self" href="', add_query_arg( array( 'page' => IP_Geo_Block::PLUGIN_NAME, 'tab' => 1 ), admin_url( 'options-general.php' ) ), '">', __( 'Statistics', 'ip-geo-block' ), '</a> ] ';
39
+ echo '[ <a target="_self" href="', add_query_arg( array( 'page' => IP_Geo_Block::PLUGIN_NAME, 'tab' => 4 ), admin_url( 'options-general.php' ) ), '">', __( 'Logs', 'ip-geo-block' ), '</a> ]';
40
+ echo '</p>', "\n";
41
+
42
+ // array of ( `time`, `ip`, `hook`, `code`, `method`, `data` )
43
+ $logs = IP_Geo_Block_Logs::get_recent_logs( DAY_IN_SECONDS ); // YEAR_IN_SECONDS
44
+
45
+ // duration time
46
+ $interval = MINUTE_IN_SECONDS * 15; // DAY_IN_SECONDS
47
+
48
+ // Blocked hooks by time
49
+ $count = array();
50
+ foreach( $logs as $val ) {
51
+ $key = (int)( $val['time'] / $interval ) * $interval;
52
+ $count[ $key ][] = $val['hook'];
53
+ }
54
+
55
+ // Add current time
56
+ if ( ! empty( $count ) ) {
57
+ $key = (int)( $_SERVER['REQUEST_TIME'] / $interval + 1 ) * $interval;
58
+ if ( empty( $count[ $key ] ) ) {
59
+ $count[ $key ] = array();
60
+ }
61
+ }
62
+
63
+ // Count of hooks by time
64
+ $logs = array();
65
+ foreach ( $count as $key => $val ) {
66
+ $logs[ $key ] = array_count_values( $val );
67
+ }
68
+
69
+ $zero = array(
70
+ 'comment' => 0,
71
+ 'xmlrpc' => 0,
72
+ 'login' => 0,
73
+ 'admin' => 0,
74
+ 'public' => 0,
75
+ );
76
+
77
+ $prev = 0;
78
+ $count = array();
79
+
80
+ // Make array( `time`, `comment`, `xlmrpc`, `login`, `admin`, `public` )
81
+ foreach ( $logs as $key => $val ) {
82
+ while ( $prev && $key - $prev > $interval ) {
83
+ $count[] = array( $prev += $interval, 0, 0, 0, 0, 0 );
84
+ }
85
+ $count[] = array_merge(
86
+ array( $prev = $key ),
87
+ array_values( array_merge( $zero, $val ) )
88
+ );
89
+ }
90
+
91
+ // Embed array into data attribute as json
92
+ echo '<div class="', IP_Geo_Block::PLUGIN_NAME, '-multisite" id="', $args['id'], '" data-', $args['id'], '=\'', json_encode( $count ), '\'></div>';
93
+ // http://jsdo.it/taw_yame_bury/tG9t
94
+ // https://developers.google.com/chart/
95
+
96
+ restore_current_blog();
97
+ }
98
+
99
+ }
admin/includes/tab-settings.php CHANGED
@@ -1,17 +1,13 @@
1
<?php
2
require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-opts.php';
3
require_once IP_GEO_BLOCK_PATH . 'admin/includes/class-admin-rewrite.php';
4
5
- if ( ! function_exists( 'get_plugins' ) )
6
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
7
-
8
class IP_Geo_Block_Admin_Tab {
9
10
public static function tab_setup( $context, $tab ) {
11
- $plugin_slug = IP_Geo_Block::PLUGIN_NAME; // 'ip-geo-block'
12
- $option_slug = IP_Geo_Block::PLUGIN_NAME; // 'ip-geo-block'
13
- $option_name = IP_Geo_Block::OPTION_NAME; // 'ip_geo_block_settings'
14
$options = IP_Geo_Block::get_option();
15
16
/**
17
* Register a setting and its sanitization callback.
@@ -24,8 +20,8 @@ class IP_Geo_Block_Admin_Tab {
24
* @since 2.7.0
25
*/
26
register_setting(
27
- $option_slug,
28
- $option_name,
29
array( $context, 'validate_settings' )
30
);
31
@@ -43,9 +39,8 @@ class IP_Geo_Block_Admin_Tab {
43
/*----------------------------------------*
44
* Validation rule settings
45
*----------------------------------------*/
46
- $section = $plugin_slug . '-validation-rule';
47
add_settings_section(
48
- $section,
49
__( 'Validation rule settings', 'ip-geo-block' ),
50
NULL,
51
$option_slug
@@ -120,6 +115,7 @@ endif;
120
$comma = array(
121
'<span class="ip-geo-block-sup">' . __( '(comma separated)', 'ip-geo-block' ) . '</span>',
122
'<span class="ip-geo-block-sup">' . __( '(comma or RET separated)', 'ip-geo-block' ) . '</span>',
123
);
124
125
// Matching rule
@@ -180,13 +176,34 @@ endif;
180
)
181
);
182
183
- // White list of extra IP addresses prior to country code (CIDR)
184
$field = 'extra_ips';
185
$key = 'white_list';
186
add_settings_field(
187
$option_name.'_'.$field.'_'.$key,
188
- __( '<dfn title="e.g. &#8220;192.0.64.0/18&#8221; for Jetpack server, &#8220;69.46.36.0/27&#8221; for WordFence server">Whitelist of extra IP addresses prior to country code</dfn>', 'ip-geo-block' ) .
189
- ' (<a rel="noreferrer" href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing" title="Classless Inter-Domain Routing - Wikipedia, the free encyclopedia">CIDR</a>)',
190
array( $context, 'callback_field' ),
191
$option_slug,
192
$section,
@@ -200,12 +217,13 @@ endif;
200
)
201
);
202
203
- // Black list of extra IP addresses prior to country code (CIDR)
204
$key = 'black_list';
205
add_settings_field(
206
$option_name.'_'.$field.'_'.$key,
207
__( '<dfn title="Server level access control is recommended (e.g. .htaccess).">Blacklist of extra IP addresses prior to country code</dfn>', 'ip-geo-block' ) .
208
- ' (<a rel="noreferrer" href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing" title="Classless Inter-Domain Routing - Wikipedia, the free encyclopedia">CIDR</a>)',
209
array( $context, 'callback_field' ),
210
$option_slug,
211
$section,
@@ -257,7 +275,7 @@ endif;
257
);
258
259
// Prevent malicious upload - white list of file extention and MIME type
260
- $list = '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . __( '<dfn title="Select allowed MIME type.">Whitelist of allowed MIME type</dfn>', 'ip-geo-block' ) . "<a class=\"ip-geo-block-cycle ip-geo-block-hide\"><span></span></a>\n<li class=\"ip-geo-block-hide\"><ul class=\"ip-geo-block-float\">\n";
261
262
// get_allowed_mime_types() in wp-includes/functions.php @since 2.8.6
263
foreach ( IP_Geo_Block_Util::get_allowed_mime_types() as $key => $val ) {
@@ -271,11 +289,15 @@ endif;
271
$list .= '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . __( '<dfn title="Put forbidden file extensions.">Blacklist of forbidden file extensions</dfn>', 'ip-geo-block' ) . "\n" . '<li class="ip-geo-block-hide"><ul><li><input type="text" class="regular-text code" id="ip_geo_block_settings_mimetype_black_list" name="ip_geo_block_settings[mimetype][black_list]" value="' . esc_attr( $options['mimetype']['black_list'] ) . '"/></li>';
272
$list .= "</ul></li></ul>\n";
273
274
$field = 'validation';
275
$key = 'mimetype';
276
add_settings_field(
277
$option_name.'_'.$field.'_'.$key,
278
- __( '<dfn title="It restricts the file types on upload to block malware and backdoor via both back-end and front-end. Please consider to select &#8220;mu-plugins&#8221; (ip-geo-block-mu.php) at &#8220;Validation timing&#8221; so that other staff would not fetch uploaded files before this validation.">Prevent malicious file uploading</dfn>', 'ip-geo-block' ),
279
array( $context, 'callback_field' ),
280
$option_slug,
281
$section,
@@ -286,39 +308,14 @@ endif;
286
'sub-field' => $key,
287
'value' => $options[ $field ][ $key ],
288
'list' => array(
289
- 0 => __( 'Disable', 'ip-geo-block' ),
290
- 1 => __( 'Verify capability and MIME type', 'ip-geo-block' ),
291
- 2 => __( 'Verify only file extension', 'ip-geo-block' ),
292
),
293
'after' => $list,
294
)
295
);
296
- /*
297
- // Create a new user
298
- $field = 'others';
299
- $key = 'create_user';
300
- add_settings_field(
301
- $option_name.'_'.$field,
302
- __( '<dfn title="It enables/disables to restrict creation of new user accounts.">Create a newe user</dfn>', 'ip-geo-block' ),
303
- array( $context, 'callback_field' ),
304
- $option_slug,
305
- $section,
306
- array(
307
- 'type' => 'select',
308
- 'option' => $option_name,
309
- 'field' => $field,
310
- 'sub-field' => $key,
311
- 'value' => $options[ $field ][ $key ],
312
- 'list' => array(
313
- 0 => __( 'Disable', 'ip-geo-block' ),
314
- 1 => __( 'Block by country', 'ip-geo-block' ),
315
- 2 => 'Only by admin',
316
- 3 => 'Prohibit',
317
- ),
318
- 'after' => '<br /><input id="ip_geo_block_settings_' . $field . '_' . $key . '" name="ip_geo_block_settings[' . $field . '][' . $key . ']" type="checkbox"' . checked( ! empty( $options[ $field ][ $key ] ), TRUE, FALSE ) . '/><label for="ip_geo_block_settings_' . $field . '_' . $key . '"><dfn title="It enables to send email to administrator when a new user count is created.">Send email</dfn></label>',
319
- )
320
- );
321
- */
322
// Response code (RFC 2616)
323
$field = 'response_code';
324
add_settings_field(
@@ -363,6 +360,7 @@ endif;
363
'field' => $field,
364
'value' => $options[ $field ],
365
'class' => $options['response_code'] < 400 ? '' : 'ip-geo-block-hide',
366
)
367
);
368
@@ -439,9 +437,8 @@ endif;
439
/*----------------------------------------*
440
* Back-end target settings
441
*----------------------------------------*/
442
- $section = $plugin_slug . '-validation-target';
443
add_settings_section(
444
- $section,
445
__( 'Back-end target settings', 'ip-geo-block' ),
446
array( __CLASS__, 'note_target' ),
447
$option_slug
@@ -527,7 +524,7 @@ endif;
527
'sub-field' => $key,
528
'value' => $options[ $field ][ $key ],
529
'text' => __( 'Block by country', 'ip-geo-block' ),
530
- 'after' => '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . __( '<dfn title="Specify the individual action as a blocking target.">Target actions</dfn>', 'ip-geo-block' ) . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>' . "\n<li class=\"ip-geo-block-hide\"><ul>\n" . $list . "</ul></li></ul>\n",
531
)
532
);
533
@@ -560,43 +557,19 @@ endif;
560
)
561
);
562
563
- // Get all the ajax/post actions
564
- $exception = '';
565
- $installed = array();
566
-
567
- global $wp_filter;
568
- foreach ( $wp_filter as $key => $val ) {
569
- if ( FALSE !== strpos( $key, 'wp_ajax_' ) ) {
570
- if ( 0 === strpos( $key, 'wp_ajax_nopriv_' ) ) {
571
- $key = substr( $key, 15 );
572
- $val = 2;
573
- } else {
574
- $key = substr( $key, 8 );
575
- $val = 1;
576
- }
577
- $installed[ $key ] = isset( $installed[ $key ] ) ? $installed[ $key ] | $val : $val;
578
- } elseif ( FALSE !== strpos( $key, 'admin_post_' ) ) {
579
- if ( 0 === strpos( $key, 'admin_post_nopriv_' ) ) {
580
- $key = substr( $key, 18 );
581
- $val = 2;
582
- } else {
583
- $key = substr( $key, 11 );
584
- $val = 1;
585
- }
586
- $installed[ $key ] = isset( $installed[ $key ] ) ? $installed[ $key ] | $val : $val;
587
- }
588
- }
589
- unset( $installed['ip_geo_block'] );
590
591
$tmp = array(
592
- __( 'for logged-in user', 'ip-geo-block' ),
593
- __( 'for non logged-in user', 'ip-geo-block' ),
594
);
595
596
foreach ( $installed as $key => $val ) {
597
$val = '';
598
- $val .= $installed[ $key ] & 1 ? '<dfn title="' . $tmp[0] . '"><span class="dashicons dashicons-lock"></span></dfn>' : '';
599
- $val .= $installed[ $key ] & 2 ? '<dfn title="' . $tmp[1] . '"><span class="dashicons dashicons-unlock"></span></dfn>' : '';
600
$key = esc_attr( $key );
601
$exception .= '<li>'
602
. '<input id="ip_geo_block_' . $key . '" type="checkbox" value="1"' . checked( in_array( $key, $options['exception']['admin'] ), TRUE, FALSE ) . ' />'
@@ -624,7 +597,7 @@ endif;
624
'list' => $list,
625
'desc' => $desc,
626
'after' => '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">'
627
- . __( '<dfn title="Specify the page name (&#8220;page=&hellip;&#8221;) or the action name (&#8220;action=&hellip;&#8221;) to prevent undesired blocking caused by &#8220;Block by country&#8221; for non logged-in user and &#8220;Prevent Zero-day Exploit&#8221; for logged-in user.">Exceptions</dfn>', 'ip-geo-block' ) . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>'
628
. "\n<li class=\"ip-geo-block-hide\"><ul><li>\n"
629
. '<input class="regular-text code" id="ip_geo_block_settings_exception_admin" name="ip_geo_block_settings[exception][admin]" type="text" value="' . esc_attr( implode( ',', $options['exception']['admin'] ) ) . '">' . "\n"
630
. $comma[0]
@@ -638,11 +611,13 @@ endif;
638
array_unshift( $list, __( 'Disable', 'ip-geo-block' ) );
639
$desc = array(
640
__( 'Regardless of the country code, it will block a malicious request to <code>%s&ctdot;/*.php</code>.', 'ip-geo-block' ),
641
- __( 'It configures &#8220;%s&#8221; to validate a request to the PHP file which does not load WordPress core.', 'ip-geo-block' ),
642
__( '<dfn title="Select the item which causes undesired blocking in order to exclude from the validation target. Grayed item indicates &#8220;INACTIVE&#8221;.">Exceptions</dfn>', 'ip-geo-block' ),
643
);
644
645
// Set rewrite condition
646
$options['rewrite'] = IP_Geo_Block_Admin_Rewrite::check_rewrite_all();
647
648
// Get all the plugins
@@ -674,7 +649,7 @@ endif;
674
. ' value="1"' . checked( $options['rewrite'][ $key ], TRUE, FALSE )
675
. disabled( $options['rewrite'][ $key ], -1, FALSE ) . ' />'
676
. '<label for="ip_geo_block_settings_rewrite_' . $key . '"><dfn title="'
677
- . sprintf( $desc[1], $val . '.htaccess' )
678
. '">' . __( 'Force to load WP core', 'ip-geo-block' )
679
. '</dfn></label><br />';
680
@@ -695,7 +670,7 @@ endif;
695
2 => sprintf( $desc[0], $val ),
696
),
697
'before' => $tmp,
698
- 'after' => '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . $desc[2] . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>' . "\n<li class=\"ip-geo-block-hide\"><ul>\n" . $exception . "</ul></li></ul>\n",
699
)
700
);
701
@@ -724,7 +699,7 @@ endif;
724
. ' value="1"' . checked( $options['rewrite'][ $key ], TRUE, FALSE )
725
. disabled( $options['rewrite'][ $key ], -1, FALSE ) . ' />'
726
. '<label for="ip_geo_block_settings_rewrite_' . $key . '"><dfn title="'
727
- . sprintf( $desc[1], $val . '.htaccess' )
728
. '">' . __( 'Force to load WP core', 'ip-geo-block' )
729
. '</dfn></label><br />';
730
@@ -745,16 +720,15 @@ endif;
745
2 => sprintf( $desc[0], $val ),
746
),
747
'before' => $tmp,
748
- 'after' => '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . $desc[2] . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>' . "\n<li class=\"ip-geo-block-hide\"><ul>\n" . $exception . "</ul></li></ul>\n",
749
)
750
);
751
752
/*----------------------------------------*
753
* Front-end settings
754
*----------------------------------------*/
755
- $section = $plugin_slug . '-public';
756
add_settings_section(
757
- $section,
758
__( 'Front-end target settings', 'ip-geo-block' ),
759
array( __CLASS__, 'note_public' ),
760
$option_slug
@@ -884,6 +858,7 @@ endif;
884
'sub-field' => $key,
885
'value' => $options[ $field ][ $key ],
886
'class' => $options[ $field ]['matching_rule'] != -1 && $options[ $field ]['response_code'] < 400 ? '' : 'ip-geo-block-hide',
887
)
888
);
889
@@ -906,7 +881,7 @@ endif;
906
);
907
908
// List of page
909
- $exception = '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . __( '<dfn title="Specify the individual page as a blocking target.">Page</dfn>', 'ip-geo-block' ) . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>' . "\n<li class=\"ip-geo-block-hide\"><ul>\n";
910
$tmp = get_pages();
911
if ( ! empty( $tmp ) ) {
912
foreach ( $tmp as $key ) {
@@ -918,7 +893,7 @@ endif;
918
$exception .= '</ul></li></ul>' . "\n";
919
920
// List of post type
921
- $exception .= '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . __( '<dfn title="Specify the individual post type on a single page as a blocking target.">Post type</dfn>', 'ip-geo-block' ) . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>' . "\n<li class=\"ip-geo-block-hide\"><ul>\n";
922
$tmp = get_post_types( array( 'public' => TRUE ) );
923
if ( ! empty( $tmp ) ) {
924
foreach ( $tmp as $key ) {
@@ -930,7 +905,7 @@ endif;
930
$exception .= '</ul></li></ul>' . "\n";
931
932
// List of category
933
- $exception .= '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . __( '<dfn title="Specify the individual category on a single page or archive page as a blocking target.">Category</dfn>', 'ip-geo-block' ) . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>' . "\n<li class=\"ip-geo-block-hide\"><ul>\n";
934
$tmp = get_categories( array( 'hide_empty' => FALSE ) );
935
if ( ! empty( $tmp ) ) {
936
foreach ( $tmp as $key ) {
@@ -942,7 +917,7 @@ endif;
942
$exception .= '</ul></li></ul>' . "\n";
943
944
// List of tag
945
- $exception .= '<ul class="ip-geo-block-settings-folding ip-geo-block-dropup">' . __( '<dfn title="Specify the individual tag on a single page or archive page as a blocking target.">Tag</dfn>', 'ip-geo-block' ) . '<a class="ip-geo-block-cycle ip-geo-block-hide"><span></span></a>' . "\n<li class=\"ip-geo-block-hide\"><ul>\n";
946
$tmp = get_tags( array( 'hide_empty' => FALSE ) );
947
if ( ! empty( $tmp ) ) {
948
foreach ( $tmp as $key ) {
@@ -1053,9 +1028,8 @@ endif;
1053
/*----------------------------------------*
1054
* Geolocation service settings
1055
*----------------------------------------*/
1056
- $section = $plugin_slug . '-provider';
1057
add_settings_section(
1058
- $section,
1059
__( 'Geolocation API settings', 'ip-geo-block' ),
1060
array( __CLASS__, 'note_services' ),
1061
$option_slug
@@ -1111,9 +1085,8 @@ endif;
1111
);
1112
}
1113
1114
- $section = $plugin_slug . '-database';
1115