IP Geo Block - Version 3.0.3.4

Version Description

  • Improvement: Some minor refactoring for the future release.
  • Improvement: Better throughput against attacks on admin area when "mu-plugins" (ip-geo-block-mu.php) is enable.
  • Improvement: Avoid annoying error message related to private IP address.
  • Bug fix: Fix the issue of excessive blocking by bad signature.
  • Bug fix: Fix the issue of illegal usage of switch_to_blog(). See this notes on codex.
  • Bug fix: Fix the issue of illegal JSON format on "Export settings".
Download this release

Release Info

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

Code changes from version 3.0.2.2 to 3.0.3.4

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.7.3
7
- Stable tag: 3.0.2.2
8
License: GPLv2 or later
9
License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
@@ -12,13 +12,11 @@ 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") for example. It means that many WordPress sites can be always exposed to the threats of being exploited caused by those vulnerabilities.
16
17
- This plugin protects your site against such threats of attack to the back-end of your site not only by blocking requests from undesired countries but also with the original feature 'Zero-day Exploit Prevention' (WP-ZEP).
18
19
- And it also blocks undesired requests to the login form (login attempt), comment form (spam and trackback) and XML-RPC (login attempt and pingback).
20
-
21
- Up to version 2.x, this plugin had been dedicated to protect the back-end of your site. From version 3.x, it becomes to be able to block access to your public facing pages, aka front-end. See [this analysis](http://www.ipgeoblock.com/codex/analysis-of-attack-vectors.html "Analysis of Attack Vectors | IP Geo Block") about protection performance against 50 samples of vulnerable plugins.
22
23
= Features =
24
@@ -26,45 +24,46 @@ Up to version 2.x, this plugin had been dedicated to protect the back-end of you
26
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.
27
28
* **Zero-day Exploit Prevention:**
29
- The original feature "**Z**ero-day **E**xploit **P**revention for WP" (WP-ZEP) 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 in your site**. Find more details in [FAQ](https://wordpress.org/plugins/ip-geo-block/faq/ "IP Geo Block - WordPress Plugins") and [this plugin's blog](http://www.ipgeoblock.com/article/how-wpzep-works.html "How does WP-ZEP prevent zero-day attack? | IP Geo Block").
30
31
* **Guard against login attempts:**
32
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.
33
34
- * **Protection of wp-config.php:**
35
- A malicious request to try to expose `wp-config.php` via vulnerable plugins or themes can be blocked. A numerous such attacks can be found in [this article](http://www.ipgeoblock.com/article/exposure-of-wp-config-php.html "Prevent exposure of wp-config.php").
36
-
37
* **Minimize server load against brute-force attacks:**
38
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").
39
- And furthermore, a cache mechanism for the fetched IP addresses and country code can help to reduce load on the server against the burst accesses with a short period of time.
40
41
* **Support of BuddyPress and bbPress:**
42
- 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/ "WordPress › BuddyPress « WordPress Plugins") and [bbPress](https://wordpress.org/plugins/bbpress/ "WordPress › bbPress « WordPress Plugins") to help reducing spams.
43
44
* **Referrer suppressor for external links:**
45
- When you click an external hyperlink on admin screen, http referrer will be liminated to hide a footprint of your site.
46
47
* **Multiple source of IP Geolocation databases:**
48
- Free IP Geolocation database and REST APIs are installed into this plugin to get a country code from an IP address. [MaxMind](http://www.maxmind.com "MaxMind - IP Geolocation and Online Fraud Prevention") GeoLite free databases and [IP2Location](http://www.ip2location.com/ "IP Address Geolocation to Identify Website Visitor's Geographical Location") LITE databases can be available in this plugin. Those will be downloaded and updated (once a month) automatically.
49
50
* **Customizing response:**
51
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.
52
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.
53
54
* **Validation logs:**
55
- Logs will be recorded into MySQL data table to audit posting pattern under the specified condition.
56
57
* **Cooperation with full spec security plugin:**
58
- This plugin is simple and lite enough to be able to cooperate with other full spec security plugin such as [Wordfence Security](https://wordpress.org/plugins/wordfence/ "WordPress › Wordfence Security « WordPress Plugins") (because country bloking is available only for premium users). See [this report](http://www.ipgeoblock.com/codex/page-speed-performance.html "Page speed performance | IP Geo Block") about page speed performance.
59
60
* **Extendability:**
61
- "Settings minimum, Customizability maximum" is the basic concept of this plugin. You can customize the behavior of this plugin via `add_filter()` with pre-defined filter hook. See various use cases in [the documents](http://www.ipgeoblock.com/codex/ "Codex | IP Geo Block") and [samples.php](https://github.com/tokkonopapa/WordPress-IP-Geo-Block/blob/master/ip-geo-block/samples.php "WordPress-IP-Geo-Block/samples.php at master - tokkonopapa/WordPress-IP-Geo-Block - GitHub") bundled within this package.
62
63
* **Self blocking prevention and easy rescue:**
64
- Most of users do not prefer themselves to be blocked. This plugin prevents such a sad thing unless you force it. And futhermore, if such a situation occurs, you can [rescue yourself](http://www.ipgeoblock.com/codex/what-should-i-do-when-i-m-locked-out.html "What should I do when I'm locked out? | IP Geo Block") easily.
65
66
* **Clean uninstallation:**
67
- Nothing is left in your precious mySQL database after uninstallation. So you can feel free to install and activate to make a trial of this plugin's functionality. Several days later, you'll find many undesirable accesses in your validation logs if all validation targets are enabled.
68
69
= Attribution =
70
@@ -116,6 +115,9 @@ or following descriptions for your best setup.
116
* **Bad signatures in query**
117
It validates malicious signatures independently of **Block by country** and **Prevent Zero-day Exploit** for the target **Admin area**, **Admin ajax/post**, **Plugins area** and **Themes area**. Typically, `/wp-config.php` and `/passwd`.
118
119
* **Response code**
120
Choose one of the [response code](http://tools.ietf.org/html/rfc2616#section-10 "RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1") to be sent when it blocks a comment.
121
The 2xx code will lead to your top page, the 3xx code will redirect to [Black Hole Server](http://blackhole.webpagetest.org/), the 4xx code will lead to WordPress error page, and the 5xx will pretend an server error.
@@ -160,6 +162,9 @@ or following descriptions for your best setup.
160
* **UA string and qualification**
161
Additional rules targeted at SEO which can specify acceptable requests based on user agent.
162
163
* **Simulation mode**
164
You can simulate the 'blocking on front-end' functionality before deploying.
165
@@ -211,49 +216,40 @@ or following descriptions for your best setup.
211
212
It works on multisite, but there's no network setting at this moment.
213
214
- = I was locked down. What shall I do? =
215
216
- You can find the "**Emergent Functionality**" code section near the bottom of `ip-geo-block.php`. This code block can be activated by replacing `/*` (opening multi-line comment) at the top of the line to `//` (single line comment), or `*` at the end of the line to `*/` (closing multi-line comment).
217
218
- `/**
219
- * Invalidate blocking behavior in case yourself is locked out.
220
- *
221
- * How to use: Activate the following code and upload this file via FTP.
222
- */
223
- /* -- ADD `/` TO THE TOP OR END OF THIS LINE TO ACTIVATE THE FOLLOWINGS -- */
224
- function ip_geo_block_emergency( $validate ) {
225
- $validate['result'] = 'passed';
226
- return $validate;
227
- }
228
- add_filter( 'ip-geo-block-login', 'ip_geo_block_emergency' );
229
- add_filter( 'ip-geo-block-admin', 'ip_geo_block_emergency' );
230
- // */`
231
232
- Please not that you have to use an [appropriate editor](https://codex.wordpress.org/Editing_Files#Using_Text_Editors "Editing Files « WordPress Codex").
233
234
- 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.
235
236
- Remember that you should upload the original one after re-configuration to deactivate this feature.
237
238
- [This document](http://www.ipgeoblock.com/codex/what-should-i-do-when-i-m-locked-out.html "What should I do when I'm locked out? | IP Geo Block") can also help you.
239
240
- = How to resolve "Sorry, your request cannot be accepted."? =
241
242
- If you encounter this message, please refer to [this document](http://www.ipgeoblock.com/codex/you-are-not-allowed-to-access.html "Why “Sorry, your request cannot be accepted” ? | IP Geo Block") to resolve your blocking issue.
243
244
- If you can't solve your issue, please let me know about it on the [support forum](https://wordpress.org/support/plugin/ip-geo-block/ "View: Plugin Support « WordPress.org Forums"). Your logs in this plugin and "**Installation information**" at "**Plugin settings**" will be a great help to resolve the issue.
245
246
- = How can I fix "Unable to write" error? =
247
248
- When you enable "**Force to load WP core**" options, this plugin will try to configure `.htaccess` in your `/wp-content/plugins/` and `/wp-content/themes/` directory in order to protect your site against the malicous attacks to the [OMG plugins and shemes](http://www.ipgeoblock.com/article/exposure-of-wp-config-php.html "Prevent exposure of wp-config.php | IP Geo Block").
249
250
- But some servers doesn't give reading / writing permission against `.htaccess` to WordPress. In this case, you can configure these `.htaccess` files by your own hand instead of enabling "**Force to load WP core**" options.
251
252
- Please refer to "[How can I fix permission troubles?](http://www.ipgeoblock.com/codex/how-can-i-fix-permission-troubles.html 'How can I fix permission troubles? | IP Geo Block')" in order to fix this error.
253
254
- = I still have access from blacklisted country. Does it work correctly? =
255
256
- Absolutely, YES. But unfortunately, accuracy of country code depends on the geolocation databases. Actually, there is a case that a same IP address has different country code.
257
258
For more detail, please refer to "[I still have access from blacklisted country.](http://www.ipgeoblock.com/codex/access-from-blacklisted-country.html 'I still have access from blacklisted country. | IP Geo Block')".
259
@@ -267,24 +263,31 @@ You can add an IP address to the `X-Forwarded-For` header to emulate the access
267
268
See more details at "[How to test prevention of attacks](http://www.ipgeoblock.com/codex/#how-to-test-prevention-of-attacks 'Codex | IP Geo Block')".
269
270
- = Does this plugin works well with caching? =
271
-
272
- For the back-end protection, the answer is YES if you disable caching on back-end. But for the front-end, the answer depends on the caching method you are employing.
273
274
- Currently, the following cache plugins and configurations can be supported:
275
276
- - [WP Super Cache](https://wordpress.org/plugins/wp-super-cache/ "WP Super Cache — WordPress Plugins")
277
- Select "**Use PHP to serve cache files**" and enable "**Late init**".
278
279
- - [W3 Total Cache](https://wordpress.org/plugins/w3-total-cache/ "W3 Total Cache — WordPress Plugins")
280
- Select "**Disk: Basic**" and enable "**Late initialization**" for page cache. "**Disk: Enhanced**" (where "**Late initialization**" is not available) in W3TC 0.9.5.1 seems to work good without any imcompatibility with this plugin.
281
282
- - [Vendi Cache](https://wordpress.org/plugins/vendi-cache/ "Vendi Cache — WordPress Plugins")
283
- This was formerly built in Wordfence. Select "**basic caching**" for Vendi Cache and **"mu-plugin" (ip-geo-block-mu.php)** for IP Geo Block.
284
285
- If your plugin serves page caching by `mod_rewrite` via `.htaccess` (e.g. WP Fastest Cache) or caching by `advanced-cache.php` drop-in (e.g. Comet Cache) or your hosting provider serves page caching at server side, "**Blocking on front-end**" might lead to generate inconsistent pages.
286
287
- For more details, please refer to some documents at "[Blocking on front-end](http://www.ipgeoblock.com/codex/#blocking-on-front-end 'Codex | IP Geo Block')".
288
289
= Do I have to turn on all the selection to enhance security? =
290
@@ -302,7 +305,7 @@ Yes. Roughly speaking, the strategy of this plugin has been constructed as follo
302
- **Bad signatures in query**
303
It blocks the request which has not been covered in the above three.
304
305
- Please try "**Best settings**" button at the bottom of this plugin's setting page for easy setup. And also see more details in "[The best practice of target settings](http://www.ipgeoblock.com/codex/the-best-practice-for-target-settings.html 'The best practice of target settings | IP Geo Block')".
306
307
= Does this plugin validate all the requests? =
308
@@ -310,12 +313,26 @@ Unfortunately, no. This plugin can't handle the requests that are not parsed by
310
311
But there're exceptions: When you enable "**Force to load WP core**" for **Plugins area** or **Themes area**, a standalone PHP file becomes to be able to be blocked. Sometimes this kind of file has some vulnerabilities. This function protects your site against such a case.
312
313
== Other Notes ==
314
315
= Known issues =
316
317
* No image is shown after drag & drop a image in grid view at "Media Library". For more details, please refer to [this ticket at Github](https://github.com/tokkonopapa/WordPress-IP-Geo-Block/issues/2 "No image is shown after drag & drop a image in grid view at "Media Library". - Issue #2 - tokkonopapa/WordPress-IP-Geo-Block - GitHub").
318
- * From [WordPress 4.5](https://make.wordpress.org/core/2016/03/09/comment-changes-in-wordpress-4-5/ "Comment Changes in WordPress 4.5 – Make WordPress Core"), `rel=nofollow` attribute and value pair had no longer be added to relative or same domain links within `comment_content`. This change prevents to block "Server Side Request Forgeries" (not Cross Site but a malicious link in the comment field of own site).
319
320
== Screenshots ==
321
@@ -332,6 +349,49 @@ But there're exceptions: When you enable "**Force to load WP core**" for **Plugi
332
333
== Changelog ==
334
335
= 3.0.2.2 =
336
* **Improvement:** Change the behavior of "Referrer Suppressor" not to open a new window on public facing pages.
337
* **Improvement:** Improve some of the descriptions of help text.
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
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
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.
54
55
* **Cooperation with full spec security plugin:**
56
+ This plugin is simple and lite enough to be able to cooperate with other full spec security plugin such as [Wordfence Security](https://wordpress.org/plugins/wordfence/ "Wordfence Security — WordPress Plugins"). See [this report](http://www.ipgeoblock.com/codex/page-speed-performance.html "Page speed performance | IP Geo Block") about page speed performance.
57
58
* **Extendability:**
59
+ You can customize the behavior of this plugin via `add_filter()` with [pre-defined filter hook](http://www.ipgeoblock.com/codex/ "Codex | IP Geo Block"). See various use cases in [samples.php](https://github.com/tokkonopapa/WordPress-IP-Geo-Block/blob/master/ip-geo-block/samples.php "WordPress-IP-Geo-Block/samples.php at master - tokkonopapa/WordPress-IP-Geo-Block - GitHub") bundled within this package.
60
+ You can also get the extension [IP Geo Allow](https://github.com/ddur/WordPress-IP-Geo-Allow "GitHub - ddur/WordPress-IP-Geo-Allow: WordPress Plugin Exension for WordPress-IP-Geo-Block Plugin") by [Dragan](https://github.com/ddur "ddur (Dragan) - GitHub"). It makes admin screens strictly private with more flexible way than specifying IP addresses.
61
62
* **Self blocking prevention and easy rescue:**
63
+ Website owners do not prefer themselves to be blocked. This plugin prevents such a sad thing unless you force it. And futhermore, if such a situation occurs, you can [rescue yourself](http://www.ipgeoblock.com/codex/what-should-i-do-when-i-m-locked-out.html "What should I do when I'm locked out? | IP Geo Block") easily.
64
65
* **Clean uninstallation:**
66
+ Nothing is left in your precious mySQL database after uninstallation. So you can feel free to install and activate to make a trial of this plugin's functionality.
67
68
= Attribution =
69
115
* **Bad signatures in query**
116
It validates malicious signatures independently of **Block by country** and **Prevent Zero-day Exploit** for the target **Admin area**, **Admin ajax/post**, **Plugins area** and **Themes area**. Typically, `/wp-config.php` and `/passwd`.
117
118
+ * **Prevent malicious file uploading**
119
+ It restricts the file types on upload to block malware and backdoor via both back-end and front-end.
120
+
121
* **Response code**
122
Choose one of the [response code](http://tools.ietf.org/html/rfc2616#section-10 "RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1") to be sent when it blocks a comment.
123
The 2xx code will lead to your top page, the 3xx code will redirect to [Black Hole Server](http://blackhole.webpagetest.org/), the 4xx code will lead to WordPress error page, and the 5xx will pretend an server error.
162
* **UA string and qualification**
163
Additional rules targeted at SEO which can specify acceptable requests based on user agent.
164
165
+ * **DNS reverse lookup**
166
+ It enables to verify the host by reverse DNS lookup which would spend some server resources.
167
+
168
* **Simulation mode**
169
You can simulate the 'blocking on front-end' functionality before deploying.
170
216
217
It works on multisite, but there's no network setting at this moment.
218
219
+ = Does this plugin works well with caching? =
220
221
+ The short answer is **YES**, especially for the purpose of security e.g. blocking malicious access both on the back-end and on the front-end.
222
223
+ The long answer is as follows:
224
225
+ For the back-end protection, both blocking malicious access and blocking by country works fine, if you disable caching on the back-end. As for the front-end, there are 2 scenarios.
226
227
+ The first one is the case that there's no cached page against a request to the specific page. In this scenario, this plugin responds a specific HTTP status code (including redirection) and defines the symbol `DONOTCACHEPAGE` when the request comes from blacklisted countries (or IPs). When the request comes from the whitelisted countries (or IPs), this plugin passes it to the caching plugin in order to generate a new cache.
228
229
+ The second scenario is the case that there's a cached page. In this case, the response depends on the caching method you are employing. Currently, the following plugins and configurations can be supported if you want to [restrict content by geo-blocking](https://en.wikipedia.org/wiki/Geo-blocking "Geo-blocking - Wikipedia"):
230
231
+ - [WP Super Cache](https://wordpress.org/plugins/wp-super-cache/ "WP Super Cache — WordPress Plugins")
232
+ Select "**Use PHP to serve cache files**" and enable "**Late init**".
233
234
+ - [W3 Total Cache](https://wordpress.org/plugins/w3-total-cache/ "W3 Total Cache — WordPress Plugins")
235
+ Select "**Disk: Basic**" and enable "**Late initialization**" for page cache. "**Disk: Enhanced**" (where "**Late initialization**" is not available) in W3TC 0.9.5.1 seems to work good without any imcompatibility with this plugin.
236
237
+ - [Vendi Cache](https://wordpress.org/plugins/vendi-cache/ "Vendi Cache — WordPress Plugins")
238
+ This plugin was formerly built in Wordfence. Select "**basic caching**" for Vendi Cache and **"mu-plugin" (ip-geo-block-mu.php)** for IP Geo Block.
239
240
+ Other plugins adopting `mod_rewrite` (e.g. WP Fastest Cache) or `advanced-cache.php` [drop-in](https://make.wordpress.org/core/2016/08/13/global-overloading-in-advanced-cache-php/ "Global overloading in advanced-cache.php – Make WordPress Core") (e.g. Comet Cache) or other caching method at server side might serve a normal page.
241
242
+ Thus your site would have less risk against the exploiting via vulnerable plugins and themes.
243
244
+ For more details, please refer to some documents at "[Blocking on front-end](http://www.ipgeoblock.com/codex/#blocking-on-front-end 'Codex | IP Geo Block')".
245
246
+ = I still have access from blacklisted country. Does it work correctly? =
247
248
+ Absolutely, YES.
249
250
+ Sometimes, a Wordfence Security user would report this type of claim when he/she found some accesses in its Live traffic view. But please don't worry. Before WordPress runs, Wordfence cleverly filters out malicious requests to your site using <a href="http://php.net/manual/en/ini.core.php#ini.auto-prepend-file" title="PHP: Description of core php.ini directives - Manual">auto_prepend_file</a> directive to include PHP based Web Application Firewall. Then this plugin validates the rest of the requests that pass over Wordfence because those were not in WAF rules, especially you enables "**Prevent Zero-day Exploit**".
251
252
+ It would also possibly be caused by the accuracy of country code in the geolocation databases. Actually, there is a case that a same IP address has different country code.
253
254
For more detail, please refer to "[I still have access from blacklisted country.](http://www.ipgeoblock.com/codex/access-from-blacklisted-country.html 'I still have access from blacklisted country. | IP Geo Block')".
255
263
264
See more details at "[How to test prevention of attacks](http://www.ipgeoblock.com/codex/#how-to-test-prevention-of-attacks 'Codex | IP Geo Block')".
265
266
+ = I was locked down. What shall I do? =
267
268
+ You can find the "**Emergent Functionality**" code section near the bottom of `ip-geo-block.php`. This code block can be activated by replacing `/*` (opening multi-line comment) at the top of the line to `//` (single line comment), or `*` at the end of the line to `*/` (closing multi-line comment).
269
270
+ `/**
271
+ * Invalidate blocking behavior in case yourself is locked out.
272
+ *
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
288
+ Remember that you should upload the original one after re-configuration to deactivate this feature.
289
290
+ [This document](http://www.ipgeoblock.com/codex/what-should-i-do-when-i-m-locked-out.html "What should I do when I'm locked out? | IP Geo Block") can also help you.
291
292
= Do I have to turn on all the selection to enhance security? =
293
305
- **Bad signatures in query**
306
It blocks the request which has not been covered in the above three.
307
308
+ Please try "**Best for Back-end**" button at the bottom of this plugin's setting page for easy setup. And also see more details in "[The best practice of target settings](http://www.ipgeoblock.com/codex/the-best-practice-for-target-settings.html 'The best practice of target settings | IP Geo Block')".
309
310
= Does this plugin validate all the requests? =
311
313
314
But there're exceptions: When you enable "**Force to load WP core**" for **Plugins area** or **Themes area**, a standalone PHP file becomes to be able to be blocked. Sometimes this kind of file has some vulnerabilities. This function protects your site against such a case.
315
316
+ = How to resolve "Sorry, your request cannot be accepted."? =
317
+
318
+ If you encounter this message, please refer to [this document](http://www.ipgeoblock.com/codex/you-are-not-allowed-to-access.html "Why &ldquo;Sorry, your request cannot be accepted&rdquo; ? | IP Geo Block") to resolve your blocking issue.
319
+
320
+ If you can't solve your issue, please let me know about it on the [support forum](https://wordpress.org/support/plugin/ip-geo-block/ "View: Plugin Support &laquo; WordPress.org Forums"). Your logs in this plugin and "**Installation information**" at "**Plugin settings**" will be a great help to resolve the issue.
321
+
322
+ = How can I fix "Unable to write" error? =
323
+
324
+ When you enable "**Force to load WP core**" options, this plugin will try to configure `.htaccess` in your `/wp-content/plugins/` and `/wp-content/themes/` directory in order to protect your site against the malicous attacks to the [OMG plugins and themes](http://www.ipgeoblock.com/article/exposure-of-wp-config-php.html "Prevent exposure of wp-config.php | IP Geo Block").
325
+
326
+ But some servers doesn't give read / write permission against `.htaccess` to WordPress. In this case, you can configure `.htaccess` files by your own hand instead of enabling "**Force to load WP core**" options.
327
+
328
+ Please refer to "[How can I fix permission troubles?](http://www.ipgeoblock.com/codex/how-can-i-fix-permission-troubles.html 'How can I fix permission troubles? | IP Geo Block')" in order to fix this error.
329
+
330
== Other Notes ==
331
332
= Known issues =
333
334
* No image is shown after drag & drop a image in grid view at "Media Library". For more details, please refer to [this ticket at Github](https://github.com/tokkonopapa/WordPress-IP-Geo-Block/issues/2 "No image is shown after drag & drop a image in grid view at "Media Library". - Issue #2 - tokkonopapa/WordPress-IP-Geo-Block - GitHub").
335
+ * From [WordPress 4.5](https://make.wordpress.org/core/2016/03/09/comment-changes-in-wordpress-4-5/ "Comment Changes in WordPress 4.5 &#8211; Make WordPress Core"), `rel=nofollow` had no longer be attached to the links in `comment_content`. This change prevents to block "[Server Side Request Forgeries](https://www.owasp.org/index.php/Server_Side_Request_Forgery 'Server Side Request Forgery - OWASP')" (not Cross Site but a malicious internal link in the comment field).
336
337
== Screenshots ==
338
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.
355
+ * **Improvement:** Avoid annoying error message related to private IP address.
356
+ * **Bug fix:** Fix the issue of excessive blocking by bad signature.
357
+ * **Bug fix:** Fix the issue of illegal usage of `switch_to_blog()`. See [this notes on codex](https://codex.wordpress.org/Function_Reference/restore_current_blog#Notes "Function Reference/restore current blog &laquo; WordPress Codex").
358
+ * **Bug fix:** Fix the issue of illegal JSON format on "Export settings".
359
+
360
+ = 3.0.3.3 =
361
+ Thank you for your patience and understanding in frequent update.
362
+
363
+ * **Bug fix:** Fixed the issue of "Notice: Undefined variable" in WP cron. This bug caused frequent refreshing of IP address cache.
364
+ * **Bug fix:** Fixed the issue of "Fatal Error" in validating user authentication.
365
+
366
+ = 3.0.3.2 =
367
+ * **Bug fix:** Fixed the issue where nonce for WP-ZEP didn't match on front-end.
368
+ * **Bug fix:** Fixed the issue which deleted all expired cache on multisite.
369
+
370
+ = 3.0.3.1 =
371
+ This is a maintenance release addressing various internal improvement.
372
+
373
+ * **Bug fix:** Fixed an issue where deletion of the expired cache was not executed in subordinate blogs when this plugin was activated on the network wide.
374
+ * **Bug fix:** Some issues caused by IE10/11 on admin pages had been fixed.
375
+ * **Bug fix:** Turning off check boxes in "**API selection and key settings**" section now becomes to work.
376
+ * **Improvement:** Better validation performance for logged in user authentication.
377
+ * **Improvement:** Better rendering by CSS and JS for sections.
378
+ * **Improvement:** Better handling of click event for embedding a nonce.
379
+ * **Improvement:** Better handling of cookie for sections.
380
+ * **Improvement:** Better handling of server and private IP address.
381
+ * **Improvement:** Better compatibility with file operations using Filesystem API. FTP or SSH based operations are now supported only when [some symbols are defined in `wp-config.php`](https://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants "Editing wp-config.php &laquo; WordPress Codex").
382
+ * **Improvement:** Better timing of upgrade check at activation phase instead of `init` action hook.
383
+
384
+ = 3.0.3 =
385
+ * **New feature:** New option "Prevent malicious upload" to restrict MIME types.
386
+ * **New feature:** New option "Response code" and "Response message" for front-end. This is useful not to violate your affiliate program.
387
+ * **Improvement:** New Option "DNS reverse lookup" to enable/disable.
388
+ * **Improvement:** Stop rendering by javascript on setting pages to reduce flash of unstyled content.
389
+ * **Improvement:** Better compatibility of WP-ZEP with some plugins (Wordfence, Imagify) that request ajax from server side.
390
+ * **Improvement:** Better handling of server and private IP address.
391
+ * **Bug fix:** Fix the bug of "Export/Import settings". **Please export json file again if you hold it as backup purpose** because some of settings data might be incompatible.
392
+ * **Bug fix:** Fix the bug of "Password Reset" caused by miss-spelling "resetpasss".
393
+ * See some details at [release 3.0.3](http://www.ipgeoblock.com/changelog/release-3.0.3.html "3.0.3 Release Note | IP Geo Block").
394
+
395
= 3.0.2.2 =
396
* **Improvement:** Change the behavior of "Referrer Suppressor" not to open a new window on public facing pages.
397
* **Improvement:** Improve some of the descriptions of help text.
admin/class-ip-geo-block-admin.php CHANGED
@@ -12,15 +12,10 @@
12
class IP_Geo_Block_Admin {
13
14
/**
15
- * Instance of this class.
16
- *
17
- */
18
- protected static $instance = null;
19
-
20
- /**
21
- * Tab of the admin page.
22
*
23
*/
24
private $admin_tab = 0;
25
26
/**
@@ -28,22 +23,11 @@ class IP_Geo_Block_Admin {
28
* and adding a settings page and menu.
29
*/
30
private function __construct() {
31
- // Load plugin text domain.
32
- add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
33
34
// Setup a nonce to validate authentication.
35
- add_filter( 'wp_redirect', array( $this, 'add_admin_nonce' ), 10, 2 );
36
-
37
- // Add the options page and menu item.
38
- add_action( 'admin_menu', array( $this, 'setup_admin_page' ) );
39
- add_action( 'wp_ajax_ip_geo_block', array( $this, 'admin_ajax_callback' ) );
40
- add_action( 'admin_post_ip_geo_block', array( $this, 'admin_ajax_callback' ) );
41
- add_filter( 'wp_prepare_revision_for_js', array( $this, 'add_revision_nonce' ), 10, 3 );
42
-
43
- // If multisite, then enque the authentication script for network admin
44
- if ( is_multisite() ) {
45
- add_action( 'network_admin_menu', 'IP_Geo_Block::enqueue_nonce' );
46
- }
47
}
48
49
/**
@@ -55,21 +39,103 @@ class IP_Geo_Block_Admin {
55
}
56
57
/**
58
- * Load the plugin text domain for translation.
59
*
60
*/
61
- public function load_plugin_textdomain() {
62
load_plugin_textdomain( IP_Geo_Block::PLUGIN_NAME, FALSE, dirname( IP_GEO_BLOCK_BASE ) . '/languages/' );
63
}
64
65
/**
66
* Add nonce when redirect into wp-admin area.
67
*
68
*/
69
- public function add_admin_nonce( $location, $status ) {
70
return IP_Geo_Block_Util::rebuild_nonce( $location, $status );
71
}
72
73
/**
74
* Get the action name of ajax for nonce
75
*
@@ -83,7 +149,7 @@ class IP_Geo_Block_Admin {
83
*
84
*/
85
public function enqueue_admin_assets() {
86
- $footer = FALSE;
87
$dependency = array( 'jquery' );
88
89
// css for option page
@@ -137,6 +203,7 @@ class IP_Geo_Block_Admin {
137
plugins_url( 'js/footable.min.js', __FILE__ ),
138
$dependency, IP_Geo_Block::VERSION, $footer
139
);
140
}
141
142
// js for IP Geo Block admin page
@@ -170,20 +237,6 @@ class IP_Geo_Block_Admin {
170
wp_enqueue_script( $handle );
171
}
172
173
- /**
174
- * Add nonce to revision @since 4.4.0
175
- *
176
- */
177
- public function add_revision_nonce( $revisions_data, $revision, $post ) {
178
- $revisions_data['restoreUrl'] = add_query_arg(
179
- $nonce = IP_Geo_Block::PLUGIN_NAME . '-auth-nonce',
180
- IP_Geo_Block_Util::create_nonce( $nonce ),
181
- $revisions_data['restoreUrl']
182
- );
183
-
184
- return $revisions_data;
185
- }
186
-
187
/**
188
* Add plugin meta links
189
*
@@ -256,7 +309,7 @@ class IP_Geo_Block_Admin {
256
*
257
*/
258
private function add_plugin_admin_menu() {
259
- // Setup the tab number
260
$this->admin_tab = isset( $_GET['tab'] ) ? (int)$_GET['tab'] : 0;
261
$this->admin_tab = min( 4, max( 0, $this->admin_tab ) );
262
@@ -270,7 +323,7 @@ class IP_Geo_Block_Admin {
270
);
271
272
// If successful, load admin assets only on this page.
273
- if ( $hook )
274
add_action( "load-$hook", array( $this, 'enqueue_admin_assets' ) );
275
}
276
@@ -279,13 +332,13 @@ class IP_Geo_Block_Admin {
279
*
280
*/
281
private function diagnose_admin_screen() {
282
// Check version and compatibility
283
if ( version_compare( get_bloginfo( 'version' ), '3.7.0' ) < 0 )
284
self::add_admin_notice( 'error', __( 'You need WordPress 3.7+.', 'ip-geo-block' ) );
285
286
- $settings = IP_Geo_Block::get_option();
287
- $adminurl = 'options-general.php';
288
-
289
// Check consistency of matching rule
290
if ( -1 === (int)$settings['matching_rule'] ) {
291
if ( FALSE !== get_transient( IP_Geo_Block::CRON_NAME ) ) {
@@ -333,17 +386,25 @@ class IP_Geo_Block_Admin {
333
) . ' ' .
334
sprintf(
335
__( 'Please check your <a href="%s">Validation rule settings</a>.', 'ip-geo-block' ),
336
- esc_url( add_query_arg( array( 'page' => IP_Geo_Block::PLUGIN_NAME ), $adminurl ) ) . '#' . IP_Geo_Block::PLUGIN_NAME . '-settings-0'
337
)
338
);
339
}
340
}
341
342
if ( defined( 'IP_GEO_BLOCK_DEBUG' ) && IP_GEO_BLOCK_DEBUG ) {
343
// Check creation of database table
344
if ( $settings['validation']['reclogs'] ) {
345
if ( ( $warn = IP_Geo_Block_Logs::diag_tables() ) &&
346
- FALSE === IP_Geo_Block_Logs::create_tables() ) {
347
self::add_admin_notice( 'notice-warning', $warn );
348
}
349
}
@@ -355,11 +416,12 @@ class IP_Geo_Block_Admin {
355
*
356
*/
357
public function setup_admin_page() {
358
// Avoid multiple validation.
359
- if ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
360
$this->diagnose_admin_screen();
361
- $this->add_plugin_admin_menu();
362
- }
363
364
// Register settings page only if it is needed.
365
if ( ( isset( $_GET ['page' ] ) && IP_Geo_Block::PLUGIN_NAME === $_GET ['page' ] ) ||
@@ -369,15 +431,71 @@ class IP_Geo_Block_Admin {
369
370
// Add an action link pointing to the options page. @since 2.7
371
else {
372
- add_filter( 'plugin_row_meta', array( $this, 'add_plugin_meta_links' ), 10, 2 );
373
- add_filter( 'plugin_action_links_' . IP_GEO_BLOCK_BASE, array( $this, 'add_action_links' ), 10, 1 );
374
}
375
376
// Register scripts for admin.
377
- add_action( 'admin_enqueue_scripts', array( 'IP_Geo_Block', 'enqueue_nonce' ) );
378
379
- // Show admin notices at the place where it should be.
380
- add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );
381
}
382
383
/**
@@ -401,13 +519,11 @@ class IP_Geo_Block_Admin {
401
echo '<a href="?page=', IP_Geo_Block::PLUGIN_NAME, '&amp;tab=', $key, '" class="nav-tab', ($tab === $key ? ' nav-tab-active' : ''), '">', $val, '</a>';
402
} ?>
403
</h2>
404
- <?php if ( 0 <= $tab && $tab <= 1 ) { ?>
405
<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>
406
- <?php } ?>
407
- <form method="post" action="options.php"<?php if ( 0 !== $tab ) echo " id=\"", IP_Geo_Block::PLUGIN_NAME, "-inhibit\""; ?>>
408
<?php
409
settings_fields( IP_Geo_Block::PLUGIN_NAME );
410
- do_settings_sections( IP_Geo_Block::PLUGIN_NAME );
411
if ( 0 === $tab )
412
submit_button(); // @since 3.1
413
?>
@@ -417,28 +533,27 @@ class IP_Geo_Block_Admin {
417
<div id="ip-geo-block-map"></div>
418
<?php } elseif ( 3 === $tab ) {
419
// show attribution (higher priority order)
420
- $providers = IP_Geo_Block_Provider::get_addons();
421
$tab = array();
422
- foreach ( $providers as $provider ) {
423
if ( $geo = IP_Geo_Block_API::get_instance( $provider, NULL ) ) {
424
$tab[] = $geo->get_attribution();
425
}
426
}
427
echo '<p>', implode( '<br />', $tab ), "</p>\n";
428
429
- echo "<p>", __( 'Thanks for providing these great services for free.', 'ip-geo-block' ), "<br />\n";
430
echo __( '(Most browsers will redirect you to each site <a href="http://www.ipgeoblock.com/etc/referer.html" title="Referer Checker">without referrer when you click the link</a>.)', 'ip-geo-block' ), "</p>\n";
431
} ?>
432
<?php if ( defined( 'IP_GEO_BLOCK_DEBUG' ) && IP_GEO_BLOCK_DEBUG ) {
433
echo '<p>', get_num_queries(), ' queries. ', timer_stop(0), ' seconds. ', memory_get_usage(), " bytes.</p>\n";
434
} ?>
435
- <p style="margin:0; text-align:right">[ <a id="ip-geo-block-back-to-top" href="#"><?php _e( 'Back to top', 'ip-geo-block' ); ?></a> ]</p>
436
</div>
437
<?php
438
}
439
440
/**
441
- * Initializes the options page by registering the Sections, Fields, and Settings
442
*
443
*/
444
private function register_settings_tab() {
@@ -451,12 +566,13 @@ class IP_Geo_Block_Admin {
451
);
452
453
require_once IP_GEO_BLOCK_PATH . $files[ $this->admin_tab ];
454
- IP_Geo_Block_Admin_Tab::tab_setup( $this );
455
}
456
457
/**
458
* Function that fills the field with the desired inputs as part of the larger form.
459
* The 'id' and 'name' should match the $id given in the add_settings_field().
460
* @param array $args['value'] must be sanitized because it comes from external.
461
*/
462
public function callback_field( $args ) {
@@ -507,7 +623,7 @@ class IP_Geo_Block_Admin {
507
foreach ( $args['list'] as $key => $val ) { ?>
508
<li>
509
<input type="checkbox" id="<?php echo $id, $sub_id, '_', $key; ?>" name="<?php echo $name, $sub_name, '[', $key, ']'; ?>" value="<?php echo $key; ?>"<?php
510
- checked( $key & $args['value'] ? TRUE : FALSE ); ?> />
511
<label for="<?php echo $id, $sub_id, '_', $key; ?>"><?php
512
if ( isset( $args['desc'][ $key ] ) )
513
echo '<dfn title="', $args['desc'][ $key ], '">', $val, '</dfn>';
@@ -524,22 +640,34 @@ class IP_Geo_Block_Admin {
524
<input type="checkbox" id="<?php echo $id, $sub_id; ?>" name="<?php echo $name, $sub_name; ?>" value="1"<?php
525
checked( esc_attr( $args['value'] ) );
526
disabled( ! empty( $args['disabled'] ), TRUE ); ?> />
527
- <label for="<?php echo $id, $sub_id; ?>"><?php echo esc_attr( isset( $args['text'] ) ? $args['text'] : __( 'Enable', 'ip-geo-block' ) ); ?></label>
528
<?php
529
break;
530
531
case 'select':
532
case 'select-text':
533
echo "\n<select id=\"${id}${sub_id}\" name=\"${name}${sub_name}\">\n";
534
foreach ( $args['list'] as $key => $val ) {
535
echo "\t<option value=\"$key\"", ( NULL === $val ? ' selected disabled' : selected( $args['value'], $key, FALSE ) );
536
- if ( isset( $args['desc'][ $key ] ) )
537
- echo " data-desc=\"", $args['desc'][ $key ], "\"";
538
echo ">$val</option>\n";
539
}
540
echo "</select>\n";
541
if ( 'select' === $args['type'] )
542
break;
543
echo "<br />\n";
544
$sub_id = '_' . $args['txt-field']; // possible value of 'txt-field' is 'msg'
545
$sub_name = '[' . $args['txt-field'] . ']';
@@ -547,7 +675,8 @@ class IP_Geo_Block_Admin {
547
548
case 'text': ?>
549
<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'] ); ?>"
550
- <?php disabled( ! empty( $args['disabled'] ), TRUE ); ?> />
551
<?php
552
break; // disabled @since 3.0
553
@@ -583,20 +712,16 @@ class IP_Geo_Block_Admin {
583
* @link http://codex.wordpress.org/Plugin_API/Filter_Reference/sanitize_option_$option
584
* @link https://core.trac.wordpress.org/browser/trunk/src/wp-includes/formatting.php
585
*/
586
- public function validate_options( $input ) {
587
// setup base options
588
$output = IP_Geo_Block::get_option();
589
$default = IP_Geo_Block::get_default();
590
591
- // initialize checkboxes not in the form (added after 2.0.0, just in case)
592
- foreach ( array( 'anonymize', 'network_wide' ) as $key ) {
593
- $output[ $key ] = 0;
594
- }
595
-
596
- // initialize checkboxes not in the form
597
- foreach ( array( 'login', 'admin', 'ajax', 'plugins', 'themes', 'public' ) as $key ) {
598
- $output['validation'][ $key ] = 0;
599
- }
600
601
// restore the 'signature' that might be transformed to avoid self blocking
602
if ( isset( $input['signature'] ) && FALSE === strpos( $input['signature'], ',' ) )
@@ -662,6 +787,17 @@ class IP_Geo_Block_Admin {
662
) : '';
663
break;
664
665
default: // checkbox, select, text
666
// single field
667
if ( ! is_array( $default[ $key ] ) ) {
@@ -670,12 +806,16 @@ class IP_Geo_Block_Admin {
670
$output[ $key ] = ! empty( $input[ $key ] );
671
}
672
673
- // otherwise if implicit
674
elseif ( isset( $input[ $key ] ) ) {
675
$output[ $key ] = is_int( $default[ $key ] ) ?
676
(int)$input[ $key ] :
677
IP_Geo_Block_Util::kses( trim( $input[ $key ] ), FALSE );
678
}
679
}
680
681
// sub field
@@ -696,7 +836,7 @@ class IP_Geo_Block_Admin {
696
array() : $input[ $key ][ $sub ];
697
}
698
699
- // otherwise if implicit
700
elseif ( isset( $input[ $key ][ $sub ] ) ) {
701
// for checkboxes
702
if ( is_array( $input[ $key ][ $sub ] ) ) {
@@ -712,50 +852,96 @@ class IP_Geo_Block_Admin {
712
);
713
}
714
}
715
}
716
}
717
}
718
719
- //----------------------------------------
720
// Check and format each setting data
721
- //----------------------------------------
722
723
// sanitize proxy
724
$output['validation']['proxy'] = implode( ',', $this->trim(
725
preg_replace( '/[^\w,]/', '', strtoupper( $output['validation']['proxy'] ) )
726
) );
727
728
- // sanitize and format ip address
729
$key = array( '/[^\w\n\.\/,:]/', '/([\s,])+/', '/(?:^,|,$)/' );
730
$val = array( '', '$1', '' );
731
$output['extra_ips']['white_list'] = preg_replace( $key, $val, trim( $output['extra_ips']['white_list'] ) );
732
$output['extra_ips']['black_list'] = preg_replace( $key, $val, trim( $output['extra_ips']['black_list'] ) );
733
734
- // format signature, ua_list (text area)
735
array_shift( $key );
736
array_shift( $val );
737
$output['signature'] = preg_replace( $key, $val, trim( $output['signature'] ) );
738
739
// 3.0.0 convert country code to upper case, remove redundant spaces
740
$output['public']['ua_list'] = preg_replace( $key, $val, trim( $output['public']['ua_list'] ) );
741
$output['public']['ua_list'] = preg_replace( '/([:#]) *([!]+) *([^ ]+) *([,\n]+)/', '$1$2$3$4', $output['public']['ua_list'] );
742
$output['public']['ua_list'] = preg_replace_callback( '/[:#]([\w:]+)/', array( $this, 'strtoupper' ), $output['public']['ua_list'] );
743
744
- // reject invalid signature which potentially blocks itself
745
- $output['signature'] = implode( ',', $this->trim( $output['signature'] ) );
746
747
// 2.2.5 exception : convert associative array to simple array
748
foreach ( array( 'plugins', 'themes' ) as $key ) {
749
$output['exception'][ $key ] = array_keys( $output['exception'][ $key ] );
750
}
751
752
- // 3.0.0 public : convert country code to upper case
753
- foreach ( array( 'white_list', 'black_list' ) as $key ) {
754
- $output['public'][ $key ] = strtoupper( preg_replace( '/\s/', '', $output['public'][ $key ] ) );
755
- }
756
-
757
- // 3.0.0 exception : trim extra space and comma
758
- foreach ( array( 'admin', 'public', 'includes', 'uploads', 'languages' ) as $key ) {
759
if ( empty( $output['exception'][ $key ] ) ) {
760
$output['exception'][ $key ] = $default['exception'][ $key ];
761
} else {
@@ -774,13 +960,16 @@ class IP_Geo_Block_Admin {
774
775
// Trim extra space and comma avoiding invalid signature which potentially blocks itself
776
private function trim( $text ) {
777
$ret = array();
778
foreach ( explode( ',', $text ) as $val ) {
779
$val = trim( $val );
780
- if ( $val && FALSE === stripos( IP_Geo_Block::$wp_path['admin'], $val ) ) {
781
$ret[] = $val;
782
}
783
}
784
return $ret;
785
}
786
@@ -811,13 +1000,14 @@ class IP_Geo_Block_Admin {
811
/**
812
* Validate settings and configure some features.
813
*
814
*/
815
public function validate_settings( $input = array() ) {
816
// must check that the user has the required capability
817
$this->check_admin_post( FALSE );
818
819
// validate setting options
820
- $options = $this->validate_options( $input );
821
822
// activate rewrite rules
823
require_once IP_GEO_BLOCK_PATH . 'admin/includes/class-admin-rewrite.php';
@@ -837,7 +1027,7 @@ class IP_Geo_Block_Admin {
837
}
838
839
self::add_admin_notice( 'error',
840
- sprintf( __( 'Unable to write %s. Please check the permission.', 'ip-geo-block' ), implode( ', ', $file ) ) . '&nbsp;' .
841
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>' )
842
);
843
}
@@ -848,7 +1038,7 @@ class IP_Geo_Block_Admin {
848
if ( TRUE !== $file ) {
849
$options['validation']['timing'] = 0;
850
self::add_admin_notice( 'error', sprintf(
851
- __( 'Unable to write %s. Please check the permission.', 'ip-geo-block' ), $file
852
) );
853
}
854
12
class IP_Geo_Block_Admin {
13
14
/**
15
+ * Globals in this class
16
*
17
*/
18
+ private static $instance = NULL;
19
private $admin_tab = 0;
20
21
/**
23
* and adding a settings page and menu.
24
*/
25
private function __construct() {
26
+ // Load plugin text domain and add body class
27
+ add_action( 'init', array( $this, 'admin_init' ) );
28
29
// Setup a nonce to validate authentication.
30
+ add_filter( 'wp_redirect', array( $this, 'add_redirect_nonce' ), 10, 2 );
31
}
32
33
/**
39
}
40
41
/**
42
+ * Load the plugin text domain for translation and add body class.
43
*
44
*/
45
+ public function admin_init() {
46
+ require_once ABSPATH . 'wp-admin/includes/plugin.php'; // is_plugin_active_for_network() @since 3.0.0
47
+
48
+ // Add the options page and menu item.
49
+ add_action( 'admin_menu', array( $this, 'setup_admin_page' ) );
50
+ add_action( 'admin_post_ip_geo_block', array( $this, 'admin_ajax_callback' ) );
51
+ add_action( 'wp_ajax_ip_geo_block', array( $this, 'admin_ajax_callback' ) );
52
+ add_filter( 'wp_prepare_revision_for_js', array( $this, 'add_revision_nonce' ), 10, 3 );
53
+
54
+ // If multisite, then enque the authentication script for network admin
55
+ if ( is_multisite() ) {
56
+ add_action( 'network_admin_menu', array( $this, 'setup_admin_page' ) );
57
+
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.
64
load_plugin_textdomain( IP_Geo_Block::PLUGIN_NAME, FALSE, dirname( IP_GEO_BLOCK_BASE ) . '/languages/' );
65
+
66
+ // add webview class into body tag.
67
+ // https://stackoverflow.com/questions/37591279/detect-if-user-is-using-webview-for-android-ios-or-a-regular-browser
68
+ if ( isset( $_SERVER['HTTP_USER_AGENT'] ) &&
69
+ ( strpos( $_SERVER['HTTP_USER_AGENT'], 'Mobile/' ) !== FALSE ) &&
70
+ ( strpos( $_SERVER['HTTP_USER_AGENT'], 'Safari/' ) === FALSE ) ) {
71
+ add_filter( 'admin_body_class', array( $this, 'add_webview_class' ) );
72
+ }
73
+
74
+ // for Android
75
+ elseif ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && $_SERVER['HTTP_X_REQUESTED_WITH'] === "com.company.app" ) {
76
+ add_filter( 'admin_body_class', array( $this, 'add_webview_class' ) );
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Add webview class into the body.
82
+ *
83
+ */
84
+ public function add_webview_class( $classes ) {
85
+ return $classes . ($classes ? ' ' : '') . 'webview';
86
}
87
88
/**
89
* Add nonce when redirect into wp-admin area.
90
*
91
*/
92
+ public function add_redirect_nonce( $location, $status ) {
93
return IP_Geo_Block_Util::rebuild_nonce( $location, $status );
94
}
95
96
+ /**
97
+ * Add nonce to revision @since 4.4.0
98
+ *
99
+ */
100
+ public function add_revision_nonce( $revisions_data, $revision, $post ) {
101
+ $revisions_data['restoreUrl'] = add_query_arg(
102
+ $nonce = IP_Geo_Block::PLUGIN_NAME . '-auth-nonce',
103
+ IP_Geo_Block_Util::create_nonce( $nonce ),
104
+ $revisions_data['restoreUrl']
105
+ );
106
+
107
+ return $revisions_data;
108
+ }
109
+
110
+ /**
111
+ * Do some procedures when a blog is created or deleted.
112
+ *
113
+ */
114
+ public function create_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
115
+ defined( 'IP_GEO_BLOCK_DEBUG' ) and IP_GEO_BLOCK_DEBUG and assert( 'is_main_site()', 'Not main blog.' );
116
+
117
+ require_once IP_GEO_BLOCK_PATH . 'classes/class-ip-geo-block-actv.php';
118
+
119
+ // Get option of main blog.
120
+ $settings = IP_Geo_Block::get_option();
121
+
122
+ // Switch to the new blog and initialize.
123
+ switch_to_blog( $blog_id );
124
+ IP_Geo_Block_Activate::activate_blog();
125
+
126
+ // Copy option from main blog.
127
+ if ( is_plugin_active_for_network( IP_GEO_BLOCK_BASE ) && $settings['network_wide'] )
128
+ update_option( IP_Geo_Block::OPTION_NAME, $settings );
129
+
130
+ // Restore the main blog.
131
+ restore_current_blog();
132
+ }
133
+
134
+ public function delete_blog( $blog_id, $drop ) {
135
+ if ( $drop )
136
+ IP_Geo_Block_Logs::delete_tables(); // blog is already switched to the target in wpmu_delete_blog()
137
+ }
138
+
139
/**
140
* Get the action name of ajax for nonce
141
*
149
*
150
*/
151
public function enqueue_admin_assets() {
152
+ $footer = TRUE;
153
$dependency = array( 'jquery' );
154
155
// css for option page
203
plugins_url( 'js/footable.min.js', __FILE__ ),
204
$dependency, IP_Geo_Block::VERSION, $footer
205
);
206
+ break;
207
}
208
209
// js for IP Geo Block admin page
237
wp_enqueue_script( $handle );
238
}
239
240
/**
241
* Add plugin meta links
242
*
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
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
332
*
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 )
340
self::add_admin_notice( 'error', __( 'You need WordPress 3.7+.', 'ip-geo-block' ) );
341
342
// Check consistency of matching rule
343
if ( -1 === (int)$settings['matching_rule'] ) {
344
if ( FALSE !== get_transient( IP_Geo_Block::CRON_NAME ) ) {
386
) . ' ' .
387
sprintf(
388
__( 'Please check your <a href="%s">Validation rule settings</a>.', 'ip-geo-block' ),
389
+ esc_url( add_query_arg( array( 'page' => IP_Geo_Block::PLUGIN_NAME ), $adminurl ) ) . '#' . IP_Geo_Block::PLUGIN_NAME . '-section-0'
390
)
391
);
392
+ break;
393
}
394
}
395
396
+ // Check activation of IP Geo Allow
397
+ if ( $settings['validation']['timing'] && is_plugin_active( 'ip-geo-allow/index.php' ) ) {
398
+ self::add_admin_notice( 'error',
399
+ __( '&#8220;mu-plugins&#8221; (ip-geo-block-mu.php) at &#8220;Validation timing&#8221; is imcompatible with <strong>IP Geo Allow</strong>. Please select &#8220;init&#8221; action hook.', 'ip-geo-block' )
400
+ );
401
+ }
402
+
403
if ( defined( 'IP_GEO_BLOCK_DEBUG' ) && IP_GEO_BLOCK_DEBUG ) {
404
// Check creation of database table
405
if ( $settings['validation']['reclogs'] ) {
406
if ( ( $warn = IP_Geo_Block_Logs::diag_tables() ) &&
407
+ ( FALSE === IP_Geo_Block_Logs::create_tables() ) ) {
408
self::add_admin_notice( 'notice-warning', $warn );
409
}
410
}
416
*
417
*/
418
public function setup_admin_page() {
419
+ // Register the administration menu.
420
+ $this->add_plugin_admin_menu();
421
+
422
// Avoid multiple validation.
423
+ if ( 'POST' !== $_SERVER['REQUEST_METHOD'] )
424
$this->diagnose_admin_screen();
425
426
// Register settings page only if it is needed.
427
if ( ( isset( $_GET ['page' ] ) && IP_Geo_Block::PLUGIN_NAME === $_GET ['page' ] ) ||
431
432
// Add an action link pointing to the options page. @since 2.7
433
else {
434
+ add_filter( 'plugin_row_meta', array( $this, 'add_plugin_meta_links' ), 10, 2 );
435
+ add_filter( 'plugin_action_links_' . IP_GEO_BLOCK_BASE, array( $this, 'add_action_links' ), 10, 1 );
436
}
437
438
// Register scripts for admin.
439
+ add_action( 'admin_enqueue_scripts', 'IP_Geo_Block::enqueue_nonce', 0 );
440
441
+ // Show admin notices at the place where it should be. @since 2.5.0
442
+ add_action( 'admin_notices', array( $this, 'show_admin_notices' ) );
443
+ add_action( 'network_admin_notices', array( $this, 'show_admin_notices' ) );
444
+ }
445
+
446
+ /**
447
+ * Get cookie that indicates open/close section
448
+ *
449
+ */
450
+ public function get_cookie( $name ) {
451
+ $cookie = array();
452
+ if ( ! empty( $_COOKIE[ $name ] ) ) {
453
+ foreach ( explode( '&', $_COOKIE[ $name ] ) as $i => $v ) {
454
+ list( $i, $v ) = explode( '=', $v );
455
+ $cookie[ $i ] = str_split( $v );
456
+ }
457
+ }
458
+ return $cookie;
459
+ }
460
+
461
+ /**
462
+ * Prints out all settings sections added to a particular settings page
463
+ *
464
+ * wp-admin/includes/template.php @since 2.7.0
465
+ */
466
+ private function do_settings_sections( $page, $tab ) {
467
+ global $wp_settings_sections, $wp_settings_fields;
468
+
469
+ if ( isset( $wp_settings_sections[ $page ] ) ) {
470
+ $index = 0; // index of fieldset
471
+ $cookie = $this->get_cookie( IP_Geo_Block::PLUGIN_NAME );
472
+
473
+ foreach ( (array) $wp_settings_sections[ $page ] as $section ) {
474
+ // TRUE if open ('o') or FALSE if close ('x')
475
+ $stat = empty( $cookie[ $tab ][ $index ] ) || 'x' !== $cookie[ $tab ][ $index ];
476
+
477
+ echo '<fieldset id="', IP_Geo_Block::PLUGIN_NAME, '-section-', $index, '" class="', IP_Geo_Block::PLUGIN_NAME, '-field panel panel-default" data-section="', $index, '">', "\n",
478
+ '<legend class="panel-heading"><h3 class="', IP_Geo_Block::PLUGIN_NAME, ( $stat ? '-dropdown' : '-dropup' ), '">', $section['title'],
479
+ '</h3></legend>', "\n", '<div class="panel-body',
480
+ ($stat ? ' ' . IP_Geo_Block::PLUGIN_NAME . '-border"' : '"'),
481
+ ($stat || (4 === $tab && $index) ? '>' : ' style="display:none">'), "\n";
482
+
483
+ ++$index;
484
+
485
+ if ( $section['callback'] )
486
+ call_user_func( $section['callback'], $section );
487
+
488
+ if ( isset( $wp_settings_fields,
489
+ $wp_settings_fields[ $page ],
490
+ $wp_settings_fields[ $page ][ $section['id'] ] ) ) {
491
+ echo '<table class="form-table">';
492
+ do_settings_fields( $page, $section['id'] );
493
+ echo "</table>\n";
494
+ }
495
+
496
+ echo "</div>\n</fieldset>\n";
497
+ }
498
+ }
499
}
500
501
/**
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 );
527
if ( 0 === $tab )
528
submit_button(); // @since 3.1
529
?>
533
<div id="ip-geo-block-map"></div>
534
<?php } elseif ( 3 === $tab ) {
535
// show attribution (higher priority order)
536
$tab = array();
537
+ foreach ( IP_Geo_Block_Provider::get_addons() as $provider ) {
538
if ( $geo = IP_Geo_Block_API::get_instance( $provider, NULL ) ) {
539
$tab[] = $geo->get_attribution();
540
}
541
}
542
echo '<p>', implode( '<br />', $tab ), "</p>\n";
543
544
+ echo '<p>', __( 'Thanks for providing these great services for free.', 'ip-geo-block' ), "<br />\n";
545
echo __( '(Most browsers will redirect you to each site <a href="http://www.ipgeoblock.com/etc/referer.html" title="Referer Checker">without referrer when you click the link</a>.)', 'ip-geo-block' ), "</p>\n";
546
} ?>
547
<?php if ( defined( 'IP_GEO_BLOCK_DEBUG' ) && IP_GEO_BLOCK_DEBUG ) {
548
echo '<p>', get_num_queries(), ' queries. ', timer_stop(0), ' seconds. ', memory_get_usage(), " bytes.</p>\n";
549
} ?>
550
+ <p id="ip-geo-block-back-to-top">[ <a href="#"><?php _e( 'Back to top', 'ip-geo-block' ); ?></a> ]</p>
551
</div>
552
<?php
553
}
554
555
/**
556
+ * Initializes the options page by registering the Sections and Fields.
557
*
558
*/
559
private function register_settings_tab() {
566
);
567
568
require_once IP_GEO_BLOCK_PATH . $files[ $this->admin_tab ];
569
+ IP_Geo_Block_Admin_Tab::tab_setup( $this, $this->admin_tab );
570
}
571
572
/**
573
* Function that fills the field with the desired inputs as part of the larger form.
574
* The 'id' and 'name' should match the $id given in the add_settings_field().
575
+ *
576
* @param array $args['value'] must be sanitized because it comes from external.
577
*/
578
public function callback_field( $args ) {
623
foreach ( $args['list'] as $key => $val ) { ?>
624
<li>
625
<input type="checkbox" id="<?php echo $id, $sub_id, '_', $key; ?>" name="<?php echo $name, $sub_name, '[', $key, ']'; ?>" value="<?php echo $key; ?>"<?php
626
+ checked( is_array( $args['value'] ) ? ! empty( $args['value'][ $key ] ) : ( $key & $args['value'] ? TRUE : FALSE ) ); ?> />
627
<label for="<?php echo $id, $sub_id, '_', $key; ?>"><?php
628
if ( isset( $args['desc'][ $key ] ) )
629
echo '<dfn title="', $args['desc'][ $key ], '">', $val, '</dfn>';
640
<input type="checkbox" id="<?php echo $id, $sub_id; ?>" name="<?php echo $name, $sub_name; ?>" value="1"<?php
641
checked( esc_attr( $args['value'] ) );
642
disabled( ! empty( $args['disabled'] ), TRUE ); ?> />
643
+ <label for="<?php echo $id, $sub_id; ?>"><?php
644
+ if ( isset( $args['text'] ) ) echo esc_attr( $args['text'] );
645
+ else if ( isset( $args['html'] ) ) echo $args['html'];
646
+ else _e( 'Enable', 'ip-geo-block' ); ?>
647
+ </label>
648
<?php
649
break;
650
651
case 'select':
652
case 'select-text':
653
+ $desc = '';
654
echo "\n<select id=\"${id}${sub_id}\" name=\"${name}${sub_name}\">\n";
655
foreach ( $args['list'] as $key => $val ) {
656
echo "\t<option value=\"$key\"", ( NULL === $val ? ' selected disabled' : selected( $args['value'], $key, FALSE ) );
657
+ if ( isset( $args['desc'][ $key ] ) ) {
658
+ echo ' data-desc="', $args['desc'][ $key ], '"';
659
+ $key === $args['value'] and $desc = $args['desc'][ $key ];
660
+ }
661
echo ">$val</option>\n";
662
}
663
echo "</select>\n";
664
+
665
+ if ( isset( $args['desc'] ) )
666
+ echo '<p class="ip-geo-block-desc">', $desc, "</p>\n";
667
+
668
if ( 'select' === $args['type'] )
669
break;
670
+
671
echo "<br />\n";
672
$sub_id = '_' . $args['txt-field']; // possible value of 'txt-field' is 'msg'
673
$sub_name = '[' . $args['txt-field'] . ']';
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
712
* @link http://codex.wordpress.org/Plugin_API/Filter_Reference/sanitize_option_$option
713
* @link https://core.trac.wordpress.org/browser/trunk/src/wp-includes/formatting.php
714
*/
715
+ public function sanitize_options( $input ) {
716
// setup base options
717
$output = IP_Geo_Block::get_option();
718
$default = IP_Geo_Block::get_default();
719
720
+ // Integrate posted data into current settings because if can be a part of hole data
721
+ $input = array_replace_recursive(
722
+ $output = $this->preprocess_options( $output, $default ),
723
+ $input
724
+ );
725
726
// restore the 'signature' that might be transformed to avoid self blocking
727
if ( isset( $input['signature'] ) && FALSE === strpos( $input['signature'], ',' ) )
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
802
// single field
803
if ( ! is_array( $default[ $key ] ) ) {
806
$output[ $key ] = ! empty( $input[ $key ] );
807
}
808
809
+ // for implicit data
810
elseif ( isset( $input[ $key ] ) ) {
811
$output[ $key ] = is_int( $default[ $key ] ) ?
812
(int)$input[ $key ] :
813
IP_Geo_Block_Util::kses( trim( $input[ $key ] ), FALSE );
814
}
815
+
816
+ // otherwise keep as it is
817
+ else {
818
+ }
819
}
820
821
// sub field
836
array() : $input[ $key ][ $sub ];
837
}
838
839
+ // for implicit data
840
elseif ( isset( $input[ $key ][ $sub ] ) ) {
841
// for checkboxes
842
if ( is_array( $input[ $key ][ $sub ] ) ) {
852
);
853
}
854
}
855
+
856
+ // otherwise keep as it is
857
+ else {
858
+ }
859
}
860
}
861
}
862
863
// Check and format each setting data
864
+ return $this->postprocess_options( $output, $default );
865
+ }
866
+
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
+
874
+ // initialize checkboxes not in the form
875
+ foreach ( array( 'comment', 'login', 'admin', 'ajax', 'plugins', 'themes', 'public', 'mimetype' ) as $key ) {
876
+ $output['validation'][ $key ] = 0;
877
+ }
878
+
879
+ // initialize checkboxes not in the form
880
+ foreach ( array( 'plugins', 'themes', 'includes', 'uploads', 'languages' ) as $key ) {
881
+ $output['rewrite'][ $key ] = FALSE;
882
+ }
883
+
884
+ // initialize checkboxes not in the form
885
+ $output['mimetype']['white_list'] = array();
886
+
887
+ // keep disabled checkboxes not in the form
888
+ foreach ( array( 'admin', 'plugins', 'themes' ) as $key ) {
889
+ $output['exception'][ $key ] = array();
890
+ }
891
+
892
+ // keep disabled checkboxes not in the form
893
+ foreach ( array( 'target_pages', 'target_posts', 'target_cates', 'target_tags', 'simulate', 'dnslkup' ) as $key ) {
894
+ $output['public'][ $key ] = array();
895
+ }
896
+
897
+ return $output;
898
+ }
899
+
900
+ // Check and format each setting data
901
+ private function postprocess_options( $output, $default ) {
902
+ // normalize escaped char
903
+ $output ['response_msg'] = preg_replace( '/\\\\/', '', $output ['response_msg'] );
904
+ $output['public' ]['response_msg'] = preg_replace( '/\\\\/', '', $output['public' ]['response_msg'] );
905
+ $output['comment']['msg' ] = preg_replace( '/\\\\/', '', $output['comment']['msg' ] );
906
907
// sanitize proxy
908
$output['validation']['proxy'] = implode( ',', $this->trim(
909
preg_replace( '/[^\w,]/', '', strtoupper( $output['validation']['proxy'] ) )
910
) );
911
912
+ // sanitize and format ip address (text area)
913
$key = array( '/[^\w\n\.\/,:]/', '/([\s,])+/', '/(?:^,|,$)/' );
914
$val = array( '', '$1', '' );
915
$output['extra_ips']['white_list'] = preg_replace( $key, $val, trim( $output['extra_ips']['white_list'] ) );
916
$output['extra_ips']['black_list'] = preg_replace( $key, $val, trim( $output['extra_ips']['black_list'] ) );
917
918
+ // format and reject invalid words which potentially blocks itself (text area)
919
array_shift( $key );
920
array_shift( $val );
921
$output['signature'] = preg_replace( $key, $val, trim( $output['signature'] ) );
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'] ) );
930
$output['public']['ua_list'] = preg_replace( '/([:#]) *([!]+) *([^ ]+) *([,\n]+)/', '$1$2$3$4', $output['public']['ua_list'] );
931
$output['public']['ua_list'] = preg_replace_callback( '/[:#]([\w:]+)/', array( $this, 'strtoupper' ), $output['public']['ua_list'] );
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
939
foreach ( array( 'plugins', 'themes' ) as $key ) {
940
$output['exception'][ $key ] = array_keys( $output['exception'][ $key ] );
941
}
942
943
+ // 3.0.0 - 3.0.3 exception : trim extra space and comma
944
+ foreach ( array( 'admin', 'public', 'includes', 'uploads', 'languages', 'restapi' ) as $key ) {
945
if ( empty( $output['exception'][ $key ] ) ) {
946
$output['exception'][ $key ] = $default['exception'][ $key ];
947
} else {
960
961
// Trim extra space and comma avoiding invalid signature which potentially blocks itself
962
private function trim( $text ) {
963
+ $path = IP_Geo_Block::get_wp_path();
964
+
965
$ret = array();
966
foreach ( explode( ',', $text ) as $val ) {
967
$val = trim( $val );
968
+ if ( $val && FALSE === stripos( $path['admin'], $val ) ) {
969
$ret[] = $val;
970
}
971
}
972
+
973
return $ret;
974
}
975
1000
/**
1001
* Validate settings and configure some features.
1002
*
1003
+ * @note: This function is triggered when update_option() is executed.
1004
*/
1005
public function validate_settings( $input = array() ) {
1006
// must check that the user has the required capability
1007
$this->check_admin_post( FALSE );
1008
1009
// validate setting options
1010
+ $options = $this->sanitize_options( $input );
1011
1012
// activate rewrite rules
1013
require_once IP_GEO_BLOCK_PATH . 'admin/includes/class-admin-rewrite.php';
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
}
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
admin/css/admin.css CHANGED
@@ -4,20 +4,74 @@ dfn {
4
border-bottom: 1px dotted #888;
5
}
6
7
- /* legend and fieldset in the form */
8
- .form-table {
9
- margin: 0 1em;
10
}
11
fieldset.ip-geo-block-field {
12
- border: 1px solid #ccc;
13
- padding: 0.35em 0.625em 0.75em 1em;
14
- margin: 1.35em 0 1.5em;
15
}
16
fieldset.ip-geo-block-field h2,
17
fieldset.ip-geo-block-field h3 {
18
padding: 0;
19
margin: 0;
20
}
21
fieldset.ip-geo-block-field .ip-geo-block-dropup,
22
fieldset.ip-geo-block-field .ip-geo-block-dropdown {
23
cursor: pointer;
@@ -49,20 +103,26 @@ fieldset.ip-geo-block-field ul.ip-geo-block-dropdown:before {
49
top: 0.45em;
50
}
51
fieldset.ip-geo-block-field .form-table {
52
- margin: 0.5em 0 0;
53
}
54
55
textarea.regular-text {
56
width: 25em;
57
}
58
59
- ul.ip_geo_block_settings_folding {
60
margin: 0.5em 0;
61
}
62
- ul.ip_geo_block_settings_folding ul {
63
margin-bottom: 0;
64
}
65
- ul.ip_geo_block_settings_folding li:first-child {
66
margin-top: 0.5em;
67
}
68
.folding-disable {
@@ -74,6 +134,11 @@ ul.ip_geo_block_settings_folding li:first-child {
74
font-style:oblique !important;
75
}
76
77
ul#ip-geo-block-actions dfn {
78
border: none;
79
}
@@ -99,8 +164,8 @@ ul#ip-geo-block-actions span.dashicons {
99
}
100
101
ul.ip-geo-block-note {
102
- list-style: disc outside;
103
- margin-left: 1em;
104
}
105
ul.ip-geo-block-list {
106
margin-top: 0.25em;
@@ -109,11 +174,6 @@ ul.ip-geo-block-list {
109
ul.ip-geo-block-list label {
110
display: inline-block;
111
}
112
- .ip-geo-block-desc {
113
- display: inline-block;
114
- margin-top: 0.25em;
115
- margin-bottom: 0.25em;
116
- }
117
@media screen and (min-width:782px) {
118
ul.ip-geo-block-list .code {
119
width: 15em;
@@ -133,6 +193,10 @@ ul.ip-geo-block-list label {
133
vertical-align: middle;
134
}
135
136
.ip-geo-block-notice {
137
color: #dd3d36;
138
}
@@ -187,19 +251,40 @@ table.ip-geo-block-statistics-table td {
187
word-wrap: break-word;
188
}
189
table.ip-geo-block-statistics-table tr:nth-child(even) {
190
- background-color: #f7f7f7;
191
}
192
table.ip-geo-block-statistics-table tr:nth-child(odd) {
193
}
194
table.ip-geo-block-table {
195
white-space: normal;
196
word-wrap: break-word;
197
word-break: break-all;
198
}
199
200
/* for footable */
201
.ip-geo-block-log {
202
width: 100% !important;
203
}
204
.ip-geo-block-log * {
205
font-size: 13px !important;
@@ -209,9 +294,8 @@ table.ip-geo-block-table {
209
.ip-geo-block-log .pagination ul {
210
border-radius: 4px;
211
display: inline-block;
212
- margin-bottom: 0;
213
- margin-left: 0;
214
- padding-left: 0;
215
}
216
.ip-geo-block-log .pagination ul > li {
217
display: inline;
@@ -304,6 +388,7 @@ table.ip-geo-block-table {
304
}
305
.ip-geo-block-log > tbody > tr > td:first-child {
306
text-align: left;
307
}
308
.ip-geo-block-log .footable-row-detail-row,
309
.ip-geo-block-log .footable-row-detail-name,
@@ -331,31 +416,28 @@ input#ip_geo_block_settings_filter_logs {
331
}
332
333
/* for google chart */
334
- #ip-geo-block-countries,
335
- #ip-geo-block-targets {
336
- display: none;
337
- }
338
#ip-geo-block-chart-countries {
339
height: 200px;
340
}
341
#ip-geo-block-chart-daily {
342
height: 240px;
343
}
344
#ip_geo_block_settings_validation_plugins,
345
#ip_geo_block_settings_validation_themes {
346
- margin-top: 0.5em;
347
}
348
- #ip-geo-block-toggle-sections,
349
- #ip-geo-block-back-to-top {
350
- box-shadow: none;
351
}
352
- #ip-geo-block-decode {
353
box-shadow: none;
354
- text-decoration: none;
355
- }
356
- #ip-geo-block-decode:active {
357
- position: relative;
358
- top: 1px;
359
}
360
#ip-geo-block-wp-info textarea {
361
margin-top: 0.5em;
@@ -365,20 +447,50 @@ input#ip_geo_block_settings_filter_logs {
365
word-break: normal;
366
white-space: pre;
367
}
368
- #ip-geo-block-cycle {
369
height: 16px;
370
width: 16px;
371
margin: 0;
372
border: none;
373
display: inline-block;
374
- vertical-align: text-bottom;
375
background-size: 16px 16px;
376
background-position: center center;
377
background-repeat: no-repeat;
378
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);
379
}
380
/* https://developer.wordpress.org/resource/dashicons/ for WordPress 3.8
381
- #ip-geo-block-cycle:before {
382
background: none;
383
content: "\f463";
384
display: inline-block;
@@ -391,4 +503,26 @@ input#ip_geo_block_settings_filter_logs {
391
-webkit-font-smoothing: antialiased;
392
-moz-osx-font-smoothing: grayscale;
393
}
394
- */
4
border-bottom: 1px dotted #888;
5
}
6
7
+ /* style legend and fieldset as panel */
8
+ fieldset, legend {
9
+ padding: 0;
10
+ margin: 0;
11
+ border: 0;
12
+ -webkit-box-sizing: border-box;
13
+ -moz-box-sizing: border-box;
14
+ box-sizing: border-box;
15
+ }
16
+ fieldset {
17
+ min-width: 0;
18
+ }
19
+ legend {
20
+ display: block;
21
+ line-height: inherit;
22
+ width: 100%;
23
+ }
24
+ label {
25
+ display: inline-block;
26
+ max-width: 100%;
27
+ }
28
+ .panel {
29
+ border-color: gray;
30
+ border: 1px solid #e5e5e5;
31
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.04);
32
+ -moz-box-shadow: 0 1px 1px rgba(0,0,0,.04);
33
+ box-shadow: 0 1px 1px rgba(0,0,0,.04);
34
+ background: #f5f5f5;
35
+ }
36
+ .panel-heading {
37
+ float: left !important;
38
+ background: #fff;
39
}
40
+ .panel-default > .panel-heading {
41
+ border-color: inherit;
42
+ }
43
+ .panel-body {
44
+ width: 100%;
45
+ padding: 0 1em;
46
+ display: inline-block;
47
+ -webkit-box-sizing: border-box;
48
+ -moz-box-sizing: border-box;
49
+ box-sizing: border-box;
50
+ }
51
+ .panel-body:before,
52
+ .panel-body:after {
53
+ content: " ";
54
+ display: table;
55
+ }
56
+ .panel-body:after {
57
+ clear: both;
58
+ }
59
+
60
+ /* style legend and fieldset */
61
fieldset.ip-geo-block-field {
62
+ /* padding: 0 10px;*/
63
+ margin: 1em 0;
64
}
65
fieldset.ip-geo-block-field h2,
66
fieldset.ip-geo-block-field h3 {
67
padding: 0;
68
margin: 0;
69
+ font-size: 14px !important;
70
+ }
71
+ fieldset.ip-geo-block-field legend.panel-heading {
72
+ padding: 10px;
73
}
74
+
75
fieldset.ip-geo-block-field .ip-geo-block-dropup,
76
fieldset.ip-geo-block-field .ip-geo-block-dropdown {
77
cursor: pointer;
103
top: 0.45em;
104
}
105
fieldset.ip-geo-block-field .form-table {
106
+ margin: 0;
107
+ width: 100%;
108
+ }
109
+ fieldset.ip-geo-block-field .ip-geo-block-desc {
110
+ color: #666;
111
+ font-size: 13px;
112
+ /* font-style: italic;*/
113
}
114
115
textarea.regular-text {
116
width: 25em;
117
}
118
119
+ ul.ip-geo-block-settings-folding {
120
margin: 0.5em 0;
121
}
122
+ ul.ip-geo-block-settings-folding ul {
123
margin-bottom: 0;
124
}
125
+ ul.ip-geo-block-settings-folding li:first-child {
126
margin-top: 0.5em;
127
}
128
.folding-disable {
134
font-style:oblique !important;
135
}
136
137
+ ul.ip-geo-block-float li {
138
+ display: inline-block;
139
+ width: 18em;
140
+ }
141
+
142
ul#ip-geo-block-actions dfn {
143
border: none;
144
}
164
}
165
166
ul.ip-geo-block-note {
167
+ margin-top: 1em;
168
+ list-style: disc inside;
169
}
170
ul.ip-geo-block-list {
171
margin-top: 0.25em;
174
ul.ip-geo-block-list label {
175
display: inline-block;
176
}
177
@media screen and (min-width:782px) {
178
ul.ip-geo-block-list .code {
179
width: 15em;
193
vertical-align: middle;
194
}
195
196
+ .ip-geo-block-border {
197
+ border-top: inherit;
198
+ }
199
+
200
.ip-geo-block-notice {
201
color: #dd3d36;
202
}
251
word-wrap: break-word;
252
}
253
table.ip-geo-block-statistics-table tr:nth-child(even) {
254
+ background-color: #eee;
255
}
256
table.ip-geo-block-statistics-table tr:nth-child(odd) {
257
}
258
table.ip-geo-block-table {
259
+ margin: 1em 0;
260
white-space: normal;
261
word-wrap: break-word;
262
word-break: break-all;
263
}
264
+ table.ip-geo-block-table td:first-child {
265
+ min-width: 4.3em;
266
+ }
267
+
268
+ /* for whois */
269
+ @media screen and (max-width:782px) {
270
+ #ip-geo-block-whois .panel-body {
271
+ padding: 0 0.5em;
272
+ }
273
+ }
274
275
/* for footable */
276
+ #ip-geo-block-4 #ip-geo-block-section-1 .panel-body,
277
+ #ip-geo-block-4 #ip-geo-block-section-2 .panel-body,
278
+ #ip-geo-block-4 #ip-geo-block-section-3 .panel-body,
279
+ #ip-geo-block-4 #ip-geo-block-section-4 .panel-body,
280
+ #ip-geo-block-4 #ip-geo-block-section-5 .panel-body {
281
+ padding: 0;
282
+ display: table-cell;
283
+ /* border-collapse: collapse; *//* Bug of IE10, IE11 */
284
+ }
285
.ip-geo-block-log {
286
width: 100% !important;
287
+ margin: 0.5em 0;
288
}
289
.ip-geo-block-log * {
290
font-size: 13px !important;
294
.ip-geo-block-log .pagination ul {
295
border-radius: 4px;
296
display: inline-block;
297
+ margin: 0.5em 0 0 0;
298
+ padding: 0;
299
}
300
.ip-geo-block-log .pagination ul > li {
301
display: inline;
388
}
389
.ip-geo-block-log > tbody > tr > td:first-child {
390
text-align: left;
391
+ padding-left: 0.5em;
392
}
393
.ip-geo-block-log .footable-row-detail-row,
394
.ip-geo-block-log .footable-row-detail-name,
416
}
417
418
/* for google chart */
419
#ip-geo-block-chart-countries {
420
height: 200px;
421
}
422
#ip-geo-block-chart-daily {
423
height: 240px;
424
}
425
+ #ip_geo_block_settings_validation_mimetype + label {
426
+ padding-top: 0.25em;
427
+ }
428
+ #ip_geo_block_settings_validation_mimetype + label + ul {
429
+ margin-top: 0.7em;
430
+ }
431
#ip_geo_block_settings_validation_plugins,
432
#ip_geo_block_settings_validation_themes {
433
+ margin-top: 0.7em;
434
}
435
+ #ip_geo_block_settings_create_user {
436
+ margin-bottom: 0.5em;
437
}
438
+ #ip-geo-block-toggle-sections,
439
+ #ip-geo-block-back-to-top a {
440
box-shadow: none;
441
}
442
#ip-geo-block-wp-info textarea {
443
margin-top: 0.5em;
447
word-break: normal;
448
white-space: pre;
449
}
450
+ #ip-geo-block-preferred {
451
+ color: #fff;
452
+ background: #00838f !important;
453
+ border-color: #00707a !important;
454
+ text-shadow: none; /* for WordPress 3.7.21 */
455
+ }
456
+ #ip-geo-block-preferred:hover {
457
+ background-color: #00919e !important;
458
+ border-color: #00525a !important;
459
+ }
460
+
461
+ span.ip-geo-block-title-link {
462
+ font-size: 13px;
463
+ }
464
+ /*span.ip-geo-block-title-link a {
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;
484
border: none;
485
display: inline-block;
486
+ vertical-align: middle;
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;
495
content: "\f463";
496
display: inline-block;
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;
519
+ list-style-position: outside;
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
+ }
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-log .footable-row-detail-value,table.ip-geo-block-table{white-space:normal;word-wrap:break-word;word-break:break-all}#ip-geo-block-scan-code,.ip-geo-block-loading,.ip-geo-block-log *{vertical-align:middle}#ip-geo-block-cycle,.ip-geo-block-loading{background-size:16px 16px;background-position:center center;background-repeat:no-repeat}dfn{cursor:help;border-bottom:1px dotted #888}.form-table{margin:0 1em}fieldset.ip-geo-block-field{border:1px solid #ccc;padding:.35em .625em .75em 1em;margin:1.35em 0 1.5em}fieldset.ip-geo-block-field h2,fieldset.ip-geo-block-field h3{padding:0;margin:0}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:.5em 0 0}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}.ip-geo-block-desc,ul.ip-geo-block-list{margin-top:.25em;margin-bottom:.25em}.folding-disable{pointer-events:none;opacity:.5}.folding-inactive{opacity:.5;font-style:oblique!important}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-desc,.ip-geo-block-loading,.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{list-style:disc;margin-left:1em}@media screen and (min-width:782px){ul.ip-geo-block-list .code{width:15em}}.ip-geo-block-loading{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}.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:#f7f7f7}.ip-geo-block-log{width:100%!important}.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-bottom:0;margin-left:0;padding-left: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}.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}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-countries,#ip-geo-block-targets{display:none}#ip-geo-block-chart-countries{height:200px}#ip-geo-block-chart-daily{height:240px}#ip_geo_block_settings_validation_plugins,#ip_geo_block_settings_validation_themes{margin-top:.5em}#ip-geo-block-back-to-top,#ip-geo-block-toggle-sections{box-shadow:none}#ip-geo-block-decode{box-shadow:none;text-decoration:none}#ip-geo-block-decode:active{position:relative;top:1px}#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-cycle{height:16px;width:16px;margin:0;border:none;display:inline-block;vertical-align:text-bottom;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)}
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}
admin/css/footable.core.min.css CHANGED
@@ -7,4 +7,4 @@
7
* Released under the MIT license
8
* You are free to use FooTable in commercial projects as long as this copyright header is left intact.
9
*/
10
- @font-face{font-family:'footable';src:url('fonts/footable.eot');src:url('fonts/footable.eot?#iefix') format('embedded-opentype'),url('fonts/footable.woff') format('woff'),url('fonts/footable.ttf') format('truetype'),url('fonts/footable.svg#footable') format('svg');font-weight:normal;font-style:normal}@media screen and (-webkit-min-device-pixel-ratio:0){@font-face{font-family:'footable';src:url('fonts/footable.svg#footable') format('svg');font-weight:normal;font-style:normal}}.footable{width:100%}.footable.breakpoint>tbody>tr.footable-detail-show>td{border-bottom:0}.footable.breakpoint>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e001"}.footable.breakpoint>tbody>tr:hover:not(.footable-row-detail){cursor:pointer}.footable.breakpoint>tbody>tr>td.footable-cell-detail{background:#eee;border-top:0}.footable.breakpoint>tbody>tr>td>span.footable-toggle{display:inline-block;font-family:'footable';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;-webkit-font-smoothing:antialiased;padding-right:5px;font-size:14px;color:#888}.footable.breakpoint>tbody>tr>td>span.footable-toggle:before{content:"\e000"}.footable.breakpoint.toggle-circle>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e005"}.footable.breakpoint.toggle-circle>tbody>tr>td>span.footable-toggle:before{content:"\e004"}.footable.breakpoint.toggle-circle-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e003"}.footable.breakpoint.toggle-circle-filled>tbody>tr>td>span.footable-toggle:before{content:"\e002"}.footable.breakpoint.toggle-square>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e007"}.footable.breakpoint.toggle-square>tbody>tr>td>span.footable-toggle:before{content:"\e006"}.footable.breakpoint.toggle-square-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e009"}.footable.breakpoint.toggle-square-filled>tbody>tr>td>span.footable-toggle:before{content:"\e008"}.footable.breakpoint.toggle-arrow>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e00f"}.footable.breakpoint.toggle-arrow>tbody>tr>td>span.footable-toggle:before{content:"\e011"}.footable.breakpoint.toggle-arrow-small>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e013"}.footable.breakpoint.toggle-arrow-small>tbody>tr>td>span.footable-toggle:before{content:"\e015"}.footable.breakpoint.toggle-arrow-circle>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e01b"}.footable.breakpoint.toggle-arrow-circle>tbody>tr>td>span.footable-toggle:before{content:"\e01d"}.footable.breakpoint.toggle-arrow-circle-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e00b"}.footable.breakpoint.toggle-arrow-circle-filled>tbody>tr>td>span.footable-toggle:before{content:"\e00d"}.footable.breakpoint.toggle-arrow-tiny>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e01f"}.footable.breakpoint.toggle-arrow-tiny>tbody>tr>td>span.footable-toggle:before{content:"\e021"}.footable.breakpoint.toggle-arrow-alt>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e017"}.footable.breakpoint.toggle-arrow-alt>tbody>tr>td>span.footable-toggle:before{content:"\e019"}.footable.breakpoint.toggle-medium>tbody>tr>td>span.footable-toggle{font-size:18px}.footable.breakpoint.toggle-large>tbody>tr>td>span.footable-toggle{font-size:24px}.footable>thead>tr>th{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;user-select:none}.footable>thead>tr>th.footable-sortable:hover{cursor:pointer}.footable>thead>tr>th.footable-sorted>span.footable-sort-indicator:before{content:"\e013"}.footable>thead>tr>th.footable-sorted-desc>span.footable-sort-indicator:before{content:"\e012"}.footable>thead>tr>th>span.footable-sort-indicator{display:inline-block;font-family:'footable';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;-webkit-font-smoothing:antialiased;padding-left:5px}.footable>thead>tr>th>span.footable-sort-indicator:before{content:"\e022"}.footable>tfoot .pagination{margin:0}.footable.no-paging .hide-if-no-paging{display:none}.footable-row-detail-inner{display:table}.footable-row-detail-row{display:table-row;line-height:1.5em}.footable-row-detail-group{display:block;line-height:2em;font-size:1.2em;font-weight:bold}.footable-row-detail-name{display:table-cell;font-weight:bold;padding-right:.5em}.footable-row-detail-value{display:table-cell}.footable-odd{background-color:#f7f7f7}
7
* Released under the MIT license
8
* You are free to use FooTable in commercial projects as long as this copyright header is left intact.
9
*/
10
+ @font-face{font-family:'footable';src:url('fonts/footable.eot');src:url('fonts/footable.eot?#iefix') format('embedded-opentype'),url('fonts/footable.woff') format('woff'),url('fonts/footable.ttf') format('truetype'),url('fonts/footable.svg#footable') format('svg');font-weight:normal;font-style:normal}@media screen and (-webkit-min-device-pixel-ratio:0){@font-face{font-family:'footable';src:url('fonts/footable.svg#footable') format('svg');font-weight:normal;font-style:normal}}.footable{width:100%}.footable.breakpoint>tbody>tr.footable-detail-show>td{border-bottom:0}.footable.breakpoint>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e001"}.footable.breakpoint>tbody>tr:hover:not(.footable-row-detail){cursor:pointer}.footable.breakpoint>tbody>tr>td.footable-cell-detail{background:#eee;border-top:0}.footable.breakpoint>tbody>tr>td>span.footable-toggle{display:inline-block;font-family:'footable';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;-webkit-font-smoothing:antialiased;padding-right:5px;font-size:14px;color:#888}.footable.breakpoint>tbody>tr>td>span.footable-toggle:before{content:"\e000"}.footable.breakpoint.toggle-circle>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e005"}.footable.breakpoint.toggle-circle>tbody>tr>td>span.footable-toggle:before{content:"\e004"}.footable.breakpoint.toggle-circle-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e003"}.footable.breakpoint.toggle-circle-filled>tbody>tr>td>span.footable-toggle:before{content:"\e002"}.footable.breakpoint.toggle-square>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e007"}.footable.breakpoint.toggle-square>tbody>tr>td>span.footable-toggle:before{content:"\e006"}.footable.breakpoint.toggle-square-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e009"}.footable.breakpoint.toggle-square-filled>tbody>tr>td>span.footable-toggle:before{content:"\e008"}.footable.breakpoint.toggle-arrow>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e00f"}.footable.breakpoint.toggle-arrow>tbody>tr>td>span.footable-toggle:before{content:"\e011"}.footable.breakpoint.toggle-arrow-small>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e013"}.footable.breakpoint.toggle-arrow-small>tbody>tr>td>span.footable-toggle:before{content:"\e015"}.footable.breakpoint.toggle-arrow-circle>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e01b"}.footable.breakpoint.toggle-arrow-circle>tbody>tr>td>span.footable-toggle:before{content:"\e01d"}.footable.breakpoint.toggle-arrow-circle-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e00b"}.footable.breakpoint.toggle-arrow-circle-filled>tbody>tr>td>span.footable-toggle:before{content:"\e00d"}.footable.breakpoint.toggle-arrow-tiny>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e01f"}.footable.breakpoint.toggle-arrow-tiny>tbody>tr>td>span.footable-toggle:before{content:"\e021"}.footable.breakpoint.toggle-arrow-alt>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e017"}.footable.breakpoint.toggle-arrow-alt>tbody>tr>td>span.footable-toggle:before{content:"\e019"}.footable.breakpoint.toggle-medium>tbody>tr>td>span.footable-toggle{font-size:18px}.footable.breakpoint.toggle-large>tbody>tr>td>span.footable-toggle{font-size:24px}.footable>thead>tr>th{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;user-select:none}.footable>thead>tr>th.footable-sortable:hover{cursor:pointer}.footable>thead>tr>th.footable-sorted>span.footable-sort-indicator:before{content:"\e013"}.footable>thead>tr>th.footable-sorted-desc>span.footable-sort-indicator:before{content:"\e012"}.footable>thead>tr>th>span.footable-sort-indicator{display:inline-block;font-family:'footable';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;-webkit-font-smoothing:antialiased;padding-left:5px}.footable>thead>tr>th>span.footable-sort-indicator:before{content:"\e022"}.footable>tfoot .pagination{margin:0}.footable.no-paging .hide-if-no-paging{display:none}.footable-row-detail-inner{display:table}.footable-row-detail-row{display:table-row;line-height:1.5em}.footable-row-detail-group{display:block;line-height:2em;font-size:1.2em;font-weight:bold}.footable-row-detail-name{display:table-cell;font-weight:bold;padding-right:.5em}.footable-row-detail-value{display:table-cell}.footable-odd{background-color:#eee}
admin/includes/class-admin-ajax.php CHANGED
@@ -162,26 +162,31 @@ class IP_Geo_Block_Admin_Ajax {
162
*/
163
static public function validate_settings( $parent ) {
164
// restore escaped characters (see wp_magic_quotes() in wp-includes/load.php)
165
- $json = str_replace(
166
- array( '\\"', '\\\\', "'" ),
167
- array( '"', '\\', '\"' ),
168
- isset( $_POST['data'] ) ? $_POST['data'] : ''
169
);
170
171
- if ( NULL === ( $data = json_decode( $json, TRUE ) ) )
172
wp_die( 'Illegal JSON format.', '', array( 'response' => 500, 'back_link' => TRUE ) ); // @Since 2.0.4
173
174
// Convert json to setting data
175
- $temp = self::json_to_settings( $data );
176
177
// Integrate posted data into current settings because if can be a part of hole data
178
- unset( $temp['version'] );
179
- $temp = array_replace_recursive( IP_Geo_Block::get_option(), $temp );
180
181
// Validate options and convert to json
182
- $temp = $parent->validate_options( $temp );
183
- $data = self::settings_to_json( $temp );
184
- $json = self::json_unsafe_encode( $data );
185
186
mbstring_binary_safe_encoding(); // @since 3.7.0
187
$length = strlen( $json );
@@ -203,33 +208,42 @@ class IP_Geo_Block_Admin_Ajax {
203
*
204
*/
205
static private function json_to_settings( $input ) {
206
- $settings = array();
207
$prfx = IP_Geo_Block::OPTION_NAME;
208
209
- foreach ( $input as $key => $val ) {
210
- if ( preg_match( "/${prfx}\[(.+?)\](?:\[(.+?)\](?:\[(.+?)\])?)?/", $key, $m ) ) {
211
- switch ( count( $m ) ) {
212
- case 2:
213
- $settings[ $m[1] ] = $val;
214
- break;
215
-
216
- case 3:
217
- $settings[ $m[1] ][ $m[2] ] = $val;
218
- break;
219
220
- case 4:
221
- if ( is_numeric( $m[3] ) ) {
222
- if ( empty( $settings[ $m[1] ][ $m[2] ] ) )
223
- $settings[ $m[1] ][ $m[2] ] = 0;
224
- $settings[ $m[1] ][ $m[2] ] |= $val;
225
- } else {
226
- $settings[ $m[1] ][ $m[2] ][ $m[3] ] = $val;
227
}
228
- break;
229
}
230
}
231
}
232
233
return $settings;
234
}
235
@@ -238,6 +252,7 @@ class IP_Geo_Block_Admin_Ajax {
238
*
239
*/
240
static public function settings_to_json( $input, $overwrite = TRUE ) {
241
$keys = array(
242
'[version]',
243
'[matching_rule]',
@@ -257,7 +272,7 @@ class IP_Geo_Block_Admin_Ajax {
257
'[validation][login]',
258
'[login_action][login]', // 2.2.8
259
'[login_action][register]', // 2.2.8
260
- '[login_action][resetpasss]', // 2.2.8
261
'[login_action][lostpassword]', // 2.2.8
262
'[login_action][postpass]', // 2.2.8
263
'[validation][admin][1]',
@@ -270,6 +285,8 @@ class IP_Geo_Block_Admin_Ajax {
270
'[validation][uploads]', // 3.0.0
271
'[validation][languages]', // 3.0.0
272
'[validation][public]', // 3.0.0
273
'[rewrite][plugins]',
274
'[rewrite][themes]',
275
'[rewrite][includes]', // 3.0.0
@@ -282,6 +299,7 @@ class IP_Geo_Block_Admin_Ajax {
282
'[exception][includes][$]', // 3.0.0
283
'[exception][uploads][$]', // 3.0.0
284
'[exception][languages][$]', // 3.0.0
285
'[public][matching_rule]', // 3.0.0
286
'[public][white_list]', // 3.0.0
287
'[public][black_list]', // 3.0.0
@@ -292,6 +310,9 @@ class IP_Geo_Block_Admin_Ajax {
292
'[public][target_tags][$]', // 3.0.0
293
'[public][ua_list]', // 3.0.0
294
'[public][simulate]', // 3.0.0
295
'[providers][Maxmind]',
296
'[providers][IP2Location]',
297
'[providers][freegeoip.net]',
@@ -317,6 +338,9 @@ class IP_Geo_Block_Admin_Ajax {
317
'[clean_uninstall]',
318
'[api_key][GoogleMap]', // 2.2.7
319
'[network_wide]', // 3.0.0
320
);
321
$json = array();
322
$prfx = IP_Geo_Block::OPTION_NAME;
@@ -331,7 +355,13 @@ class IP_Geo_Block_Admin_Ajax {
331
break;
332
333
case 3:
334
- if ( !@is_null( $input[ $m[1] ][ $m[2] ] ) || $overwrite ) {
335
$json[ $prfx.'['.$m[1].']['.$m[2].']' ] = (
336
isset( $input[ $m[1] ][ $m[2] ] ) &&
337
'@' !== $input[ $m[1] ][ $m[2] ] ?
@@ -347,11 +377,15 @@ class IP_Geo_Block_Admin_Ajax {
347
strval( $input[ $m[1] ][ $m[2] ] ) & (int)$m[3];
348
}
349
elseif ( isset( $input[ $m[1] ][ $m[2] ] ) ) {
350
- if ( '*' === $m[3] ) {
351
foreach ( $input[ $m[1] ][ $m[2] ] as $val ) {
352
- $json[ $prfx.'['.$m[1].']['.$m[2].']'.'['.$val.']' ] = 1;
353
}
354
- } elseif ( is_array( $input[ $m[1] ][ $m[2] ] ) ) {
355
$json[ $prfx.'['.$m[1].']['.$m[2].']' ] = implode( ',', $input[ $m[1] ][ $m[2] ] );
356
}
357
}
@@ -376,7 +410,7 @@ class IP_Geo_Block_Admin_Ajax {
376
'admin' => 3, // Validate on admin (1:country 2:ZEP)
377
'ajax' => 3, // Validate on ajax/post (1:country 2:ZEP)
378
'xmlrpc' => 1, // Validate on xmlrpc (1:country 2:close)
379
- 'postkey' => 'action,comment,log,pwd', // Keys in $_POST
380
'plugins' => 2, // Validate on wp-content/plugins
381
'themes' => 2, // Validate on wp-content/themes
382
'timing' => 1, // 0:init, 1:mu-plugins, 2:drop-in
@@ -447,7 +481,7 @@ class IP_Geo_Block_Admin_Ajax {
447
'WordPress:' => $GLOBALS['wp_version'],
448
'Multisite:' => is_multisite() ? 'yes' : 'no',
449
'Zlib:' => function_exists( 'gzopen' ) ? 'yes' : 'no',
450
- 'ZipArchive:' => class_exists( 'ZipArchive' ) ? 'yes' : 'no',
451
'BC Math:' => (extension_loaded('gmp') ? 'gmp ' : '') . (function_exists('bcadd') ? 'yes' : 'no'),
452
'mb_strcut:' => function_exists( 'mb_strcut' ) ? 'yes' : 'no',
453
'DNS lookup:' => ('8.8.8.8' !== $val ? 'available' : 'n/a') . sprintf( ' [%.1f msec]', $key * 1000.0 ),
162
*/
163
static public function validate_settings( $parent ) {
164
// restore escaped characters (see wp_magic_quotes() in wp-includes/load.php)
165
+ $json = json_decode(
166
+ str_replace(
167
+ array( '\\"', '\\\\', "\'" ),
168
+ array( '"', '\\', "'" ),
169
+ isset( $_POST['data'] ) ? $_POST['data'] : ''
170
+ ),
171
+ TRUE
172
);
173
174
+ if ( NULL === $json )
175
wp_die( 'Illegal JSON format.', '', array( 'response' => 500, 'back_link' => TRUE ) ); // @Since 2.0.4
176
177
// Convert json to setting data
178
+ $input = self::json_to_settings( $json );
179
+ unset( $input['version'] );
180
181
// Integrate posted data into current settings because if can be a part of hole data
182
+ $input = array_replace_recursive(
183
+ $parent->preprocess_options( IP_Geo_Block::get_option(), IP_Geo_Block::get_default() ),
184
+ $input
185
+ );
186
187
// Validate options and convert to json
188
+ $output = $parent->sanitize_options( $input );
189
+ $json = self::json_unsafe_encode( self::settings_to_json( $output ) );
190
191
mbstring_binary_safe_encoding(); // @since 3.7.0
192
$length = strlen( $json );
208
*
209
*/
210
static private function json_to_settings( $input ) {
211
+ $settings = $m = array();
212
$prfx = IP_Geo_Block::OPTION_NAME;
213
214
+ try {
215
+ foreach ( $input as $key => $val ) {
216
+ if ( preg_match( "/${prfx}\[(.+?)\](?:\[(.+?)\](?:\[(.+?)\])?)?/", $key, $m ) ) {
217
+ switch ( count( $m ) ) {
218
+ case 2:
219
+ $settings[ $m[1] ] = $val;
220
+ break;
221
+
222
+ case 3:
223
+ $settings[ $m[1] ][ $m[2] ] = $val;
224
+ break;
225
+
226
+ case 4:
227
+ if ( is_numeric( $m[3] ) ) {
228
+ if ( empty( $settings[ $m[1] ][ $m[2] ] ) )
229
+ $settings[ $m[1] ][ $m[2] ] = 0;
230
+ $settings[ $m[1] ][ $m[2] ] |= $val;
231
+ } else { // [*]:checkbox
232
+ $settings[ $m[1] ][ $m[2] ][ $m[3] ] = $val;
233
+ }
234
+ break;
235
236
+ default:
237
+ throw new Exception();
238
}
239
}
240
}
241
}
242
243
+ catch ( Exception $e ) { // should be returned as ajax response
244
+ wp_die( sprintf( __( 'illegal format at %s. Please delete the corresponding line and try again.', 'ip-geo-block' ), print_r( @$m[0], TRUE ) ) );
245
+ }
246
+
247
return $settings;
248
}
249
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]',
272
'[validation][login]',
273
'[login_action][login]', // 2.2.8
274
'[login_action][register]', // 2.2.8
275
+ '[login_action][resetpass]', // 2.2.8
276
'[login_action][lostpassword]', // 2.2.8
277
'[login_action][postpass]', // 2.2.8
278
'[validation][admin][1]',
285
'[validation][uploads]', // 3.0.0
286
'[validation][languages]', // 3.0.0
287
'[validation][public]', // 3.0.0
288
+ '[validation][restapi]', // 3.0.3
289
+ '[validation][mimetype]', // 3.0.3
290
'[rewrite][plugins]',
291
'[rewrite][themes]',
292
'[rewrite][includes]', // 3.0.0
299
'[exception][includes][$]', // 3.0.0
300
'[exception][uploads][$]', // 3.0.0
301
'[exception][languages][$]', // 3.0.0
302
+ '[exception][restapi][$]', // 3.0.3
303
'[public][matching_rule]', // 3.0.0
304
'[public][white_list]', // 3.0.0
305
'[public][black_list]', // 3.0.0
310
'[public][target_tags][$]', // 3.0.0
311
'[public][ua_list]', // 3.0.0
312
'[public][simulate]', // 3.0.0
313
+ '[public][dnslkup]', // 3.0.3
314
+ '[public][response_code]', // 3.0.3
315
+ '[public][redirect_uri]', // 3.0.3
316
'[providers][Maxmind]',
317
'[providers][IP2Location]',
318
'[providers][freegeoip.net]',
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;
355
break;
356
357
case 3:
358
+ if ( '%' === $m[2] ) { // [%]:associative array
359
+ foreach ( isset( $input[ $m[1] ] ) ? $input[ $m[1] ] : array() as $key => $val ) {
360
+ $json[ $prfx.'['.$m[1].']['.$key.']' ] = $val;
361
+ }
362
+ break;
363
+ }
364
+ if ( isset( $input[ $m[1] ][ $m[2] ] ) || $overwrite ) {
365
$json[ $prfx.'['.$m[1].']['.$m[2].']' ] = (
366
isset( $input[ $m[1] ][ $m[2] ] ) &&
367
'@' !== $input[ $m[1] ][ $m[2] ] ?
377
strval( $input[ $m[1] ][ $m[2] ] ) & (int)$m[3];
378
}
379
elseif ( isset( $input[ $m[1] ][ $m[2] ] ) ) {
380
+ if ( '*' === $m[3] ) { // [*]:checkbox
381
foreach ( $input[ $m[1] ][ $m[2] ] as $val ) {
382
+ $json[ $prfx.'['.$m[1].']['.$m[2].']'.'['.$val.']' ] = '1';
383
+ }
384
+ } elseif ( '%' === $m[3] ) { // [%]:associative array
385
+ foreach ( $input[ $m[1] ][ $m[2] ] as $key => $val ) {
386
+ $json[ $prfx.'['.$m[1].']['.$m[2].']'.'['.$key.']' ] = $val;
387
}
388
+ } elseif ( is_array( $input[ $m[1] ][ $m[2] ] ) ) { // [$]:comma separated text to array
389
$json[ $prfx.'['.$m[1].']['.$m[2].']' ] = implode( ',', $input[ $m[1] ][ $m[2] ] );
390
}
391
}
410
'admin' => 3, // Validate on admin (1:country 2:ZEP)
411
'ajax' => 3, // Validate on ajax/post (1:country 2:ZEP)
412
'xmlrpc' => 1, // Validate on xmlrpc (1:country 2:close)
413
+ 'postkey' => 'action,comment,log,pwd,FILES', // Keys in $_POST and $_FILES
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
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 ),
admin/includes/class-admin-rewrite.php CHANGED
@@ -92,7 +92,7 @@ class IP_Geo_Block_Admin_Rewrite {
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
}
@@ -126,23 +126,23 @@ class IP_Geo_Block_Admin_Rewrite {
126
* @return array contents of configuration file
127
*/
128
private function get_rewrite_rule( $which ) {
129
$file = $this->get_rewrite_file( $which );
130
- $exist = @file_exists( $file );
131
132
// check permission
133
if ( $exist ) {
134
- if ( ! @is_readable( $file ) )
135
return FALSE;
136
} else {
137
- if ( ! @is_readable( dirname( $file ) ) )
138
return FALSE;
139
}
140
141
- // http://php.net/manual/en/function.file.php#refsect1-function.file-returnvalues
142
- @ini_set( 'auto_detect_line_endings', TRUE );
143
-
144
// get file contents as an array
145
- return $exist ? @file( $file, FILE_IGNORE_NEW_LINES ) : array();
146
}
147
148
/**
@@ -152,13 +152,16 @@ class IP_Geo_Block_Admin_Rewrite {
152
* @param array contents of configuration file
153
*/
154
private function put_rewrite_rule( $which, $content ) {
155
$file = $this->get_rewrite_file( $which );
156
- if ( ! $file || FALSE === file_put_contents( $file, implode( PHP_EOL, $content ), LOCK_EX ) )
157
return FALSE;
158
159
// if content is empty then remove file
160
if ( empty( $content ) )
161
- unlink( $file );
162
163
return TRUE;
164
}
@@ -203,8 +206,7 @@ class IP_Geo_Block_Admin_Rewrite {
203
reset( $block );
204
while (
205
( list( $key_end, $val_end ) = each( $block ) ) &&
206
- ( list( $key_begin, $val_begin ) = each( $block ) )
207
- ) {
208
array_splice( $content, $key_begin, $key_end - $key_begin + 1 );
209
}
210
}
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
}
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
/**
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
}
206
reset( $block );
207
while (
208
( list( $key_end, $val_end ) = each( $block ) ) &&
209
+ ( list( $key_begin, $val_begin ) = each( $block ) ) ) {
210
array_splice( $content, $key_begin, $key_end - $key_begin + 1 );
211
}
212
}
admin/includes/tab-accesslog.php CHANGED
@@ -1,17 +1,15 @@
1
<?php
2
class IP_Geo_Block_Admin_Tab {
3
4
- public static function tab_setup( $context ) {
5
- $option_slug = IP_Geo_Block::PLUGIN_NAME;
6
- $option_name = IP_Geo_Block::OPTION_NAME;
7
- $settings = IP_Geo_Block::get_option();
8
9
register_setting(
10
- $option_slug,
11
- $option_name
12
);
13
14
- if ( $settings['validation']['reclogs'] ) :
15
16
/*----------------------------------------*
17
* Validation logs
@@ -20,7 +18,7 @@ if ( $settings['validation']['reclogs'] ) :
20
add_settings_section(
21
$section,
22
__( 'Validation logs', 'ip-geo-block' ),
23
- array( __CLASS__, 'list_accesslog' ),
24
$option_slug
25
);
26
@@ -71,6 +69,25 @@ if ( $settings['validation']['reclogs'] ) :
71
)
72
);
73
74
else:
75
76
/*----------------------------------------*
@@ -104,30 +121,24 @@ endif;
104
* Function that fills the section with the desired content.
105
*
106
*/
107
- public static function list_accesslog() {
108
- // same as in tab-settings.php
109
- $dfn = __( '<dfn title="Validation log of request to %s.">%s</dfn>', 'ip-geo-block' );
110
- $target = array(
111
- 'comment' => sprintf( $dfn, 'wp-comments-post.php', __( 'Comment post', 'ip-geo-block' ) ),
112
- 'xmlrpc' => sprintf( $dfn, 'xmlrpc.php', __( 'XML-RPC', 'ip-geo-block' ) ),
113
- 'login' => sprintf( $dfn, 'wp-login.php', __( 'Login form', 'ip-geo-block' ) ),
114
- 'admin' => sprintf( $dfn, 'wp-admin/*.php', __( 'Admin area', 'ip-geo-block' ) ),
115
- 'public' => sprintf( $dfn, __( 'public facing pages', 'ip-geo-block' ), __( 'Public facing pages', 'ip-geo-block' ) ),
116
- );
117
-
118
- foreach ( $target as $key => $val ) {
119
- echo '<h4>', $val, '</h4>', "\n";
120
- 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"><thead><tr>', "\n";
121
- echo '<th data-type="numeric">', __( 'Date', 'ip-geo-block' ), '</th>', "\n";
122
- echo '<th>', __( 'IP address', 'ip-geo-block' ), '</th>', "\n";
123
- echo '<th>', __( 'Code', 'ip-geo-block' ), '</th>', "\n";
124
- echo '<th>', __( 'Result', 'ip-geo-block' ), '</th>', "\n";
125
- echo '<th data-hide="phone,tablet">', __( 'Request', 'ip-geo-block' ), '</th>', "\n";
126
- echo '<th data-hide="all">', __( 'User agent', 'ip-geo-block' ), '</th>', "\n";
127
- echo '<th data-hide="all">', __( 'HTTP headers', 'ip-geo-block' ), '</th>', "\n";
128
- echo '<th data-hide="all">', __( '$_POST data', 'ip-geo-block' ), '</th>', "\n";
129
- echo '</tr></thead><tbody id="', IP_Geo_Block::PLUGIN_NAME, '-log-', $key, '">', "\n";
130
- echo <<<EOT
131
</tbody>
132
<tfoot class="hide-if-no-paging">
133
<tr>
@@ -139,7 +150,6 @@ endif;
139
</table>
140
141
EOT;
142
- }
143
}
144
145
public static function warn_accesslog() {
1
<?php
2
class IP_Geo_Block_Admin_Tab {
3
4
+ public static function tab_setup( $context, $tab ) {
5
+ $options = IP_Geo_Block::get_option();
6
7
register_setting(
8
+ $option_slug = IP_Geo_Block::PLUGIN_NAME,
9
+ $option_name = IP_Geo_Block::OPTION_NAME
10
);
11
12
+ if ( $options['validation']['reclogs'] ) :
13
14
/*----------------------------------------*
15
* Validation logs
18
add_settings_section(
19
$section,
20
__( 'Validation logs', 'ip-geo-block' ),
21
+ NULL,
22
$option_slug
23
);
24
69
)
70
);
71
72
+ // same as in tab-settings.php
73
+ $dfn = __( '<dfn title="Validation log of request to %s.">%s</dfn>', 'ip-geo-block' );
74
+ $target = array(
75
+ 'comment' => sprintf( $dfn, 'wp-comments-post.php', __( 'Comment post', 'ip-geo-block' ) ),
76
+ 'xmlrpc' => sprintf( $dfn, 'xmlrpc.php', __( 'XML-RPC', 'ip-geo-block' ) ),
77
+ 'login' => sprintf( $dfn, 'wp-login.php', __( 'Login form', 'ip-geo-block' ) ),
78
+ 'admin' => sprintf( $dfn, 'wp-admin/*.php', __( 'Admin area', 'ip-geo-block' ) ),
79
+ 'public' => sprintf( $dfn, __( 'public facing pages', 'ip-geo-block' ), __( 'Public facing pages', 'ip-geo-block' ) ),
80
+ );
81
+
82
+ foreach ( $target as $key => $val ) {
83
+ add_settings_section(
84
+ $key,
85
+ $val,
86
+ array( __CLASS__, 'accesslog_' . $key ),
87
+ $option_slug
88
+ );
89
+ }
90
+
91
else:
92
93
/*----------------------------------------*
121
* Function that fills the section with the desired content.
122
*
123
*/
124
+ public static function accesslog_comment() { self::list_accesslog( 'comment' ); }
125
+ public static function accesslog_xmlrpc () { self::list_accesslog( 'xmlrpc' ); }
126
+ public static function accesslog_login () { self::list_accesslog( 'login' ); }
127
+ public static function accesslog_admin () { self::list_accesslog( 'admin' ); }
128
+ public static function accesslog_public () { self::list_accesslog( 'public' ); }
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";
140
+ echo '</tr></thead><tbody id="', IP_Geo_Block::PLUGIN_NAME, '-log-', $key, '">', "\n";
141
+ echo <<<EOT
142
</tbody>
143
<tfoot class="hide-if-no-paging">
144
<tr>
150
</table>
151
152
EOT;
153
}
154
155
public static function warn_accesslog() {
admin/includes/tab-attribution.php CHANGED
@@ -1,16 +1,16 @@
1
<?php
2
class IP_Geo_Block_Admin_Tab {
3
4
- public static function tab_setup( $context ) {
5
- $option_slug = IP_Geo_Block::PLUGIN_NAME;
6
- $option_name = IP_Geo_Block::OPTION_NAME;
7
8
register_setting(
9
- $option_slug,
10
- $option_name
11
);
12
13
$section = IP_Geo_Block::PLUGIN_NAME . '-attribution';
14
add_settings_section(
15
$section,
16
__( 'Attribution links', 'ip-geo-block' ),
@@ -18,7 +18,6 @@ class IP_Geo_Block_Admin_Tab {
18
$option_slug
19
);
20
21