Shield Security for WordPress - Version 5.0.0

Version Description

Latest Point Release = Released: 1st March, 2016

  • (v.0) NEW: WordPress Simple Firewall plugin has been re-branded and is called Shield
  • (v.0) ADDED: Support for this plugin is now Premium. Added Premium Support page that links to Helpdesk.
  • (v.0) ADDED: NEW feature - Google ReCaptcha for Comment SPAM and Login protection.
  • (v.0) CHANGED: Refactor of comment spam code.
  • (v.0) CHANGED: Core File Scanner now handles the odd Hungarian distribution.
Download this release

Release Info

Developer paultgoodchild
Plugin Icon 128x128 Shield Security for WordPress
Version 5.0.0
Comparing to
See all releases

Code changes from version 4.17.0 to 5.0.0

Files changed (53) hide show
  1. icwp-wpsf.php +3 -3
  2. plugin-spec.php +6 -7
  3. readme.txt +36 -29
  4. resources/css/global-plugin.css +4 -0
  5. resources/css/plugin.css +51 -20
  6. src/common/googlerecaptcha/ReCaptcha/ReCaptcha.php +97 -0
  7. src/common/googlerecaptcha/ReCaptcha/RequestMethod.php +42 -0
  8. src/common/googlerecaptcha/ReCaptcha/RequestMethod/Curl.php +74 -0
  9. src/common/googlerecaptcha/ReCaptcha/RequestMethod/CurlPost.php +88 -0
  10. src/common/googlerecaptcha/ReCaptcha/RequestMethod/Post.php +70 -0
  11. src/common/googlerecaptcha/ReCaptcha/RequestMethod/Socket.php +105 -0
  12. src/common/googlerecaptcha/ReCaptcha/RequestMethod/SocketPost.php +121 -0
  13. src/common/googlerecaptcha/ReCaptcha/RequestParameters.php +103 -0
  14. src/common/googlerecaptcha/ReCaptcha/Response.php +102 -0
  15. src/common/googlerecaptcha/autoload.php +38 -0
  16. src/common/icwp-data.php +10 -2
  17. src/common/icwp-foundation.php +15 -0
  18. src/common/icwp-googlearecaptcha.php +45 -0
  19. src/common/icwp-wpfilesystem.php +6 -7
  20. src/config/feature-comments_filter.php +19 -12
  21. src/config/feature-hack_protect.php +2 -0
  22. src/config/feature-login_protect.php +11 -4
  23. src/config/feature-plugin.php +21 -0
  24. src/config/feature-support.php +41 -0
  25. src/features/base.php +16 -1
  26. src/features/base_wpsf.php +26 -0
  27. src/features/comments_filter.php +8 -2
  28. src/features/login_protect.php +24 -11
  29. src/features/plugin.php +35 -18
  30. src/features/support.php +124 -0
  31. src/processors/audit_trail.php +13 -14
  32. src/processors/base_commentsfilter.php +120 -0
  33. src/processors/basedb.php +32 -2
  34. src/processors/comments_filter.php +6 -0
  35. src/processors/commentsfilter_antibotspam.php +9 -22
  36. src/processors/commentsfilter_googlerecaptcha.php +106 -0
  37. src/processors/commentsfilter_humanspam.php +19 -90
  38. src/processors/firewall.php +1 -0
  39. src/processors/ips.php +11 -16
  40. src/processors/login_protect.php +13 -0
  41. src/processors/loginprotect_gasp.php +2 -2
  42. src/processors/loginprotect_googlerecaptcha.php +97 -0
  43. src/processors/loginprotect_twofactorauth.php +8 -12
  44. src/processors/plugin.php +2 -2
  45. src/processors/support.php +15 -0
  46. src/processors/user_management.php +3 -2
  47. src/processors/usermanagement_sessions.php +8 -13
  48. templates/html/plugin_badge.html +1 -1
  49. templates/php/feature-support.php +55 -0
  50. templates/php/index_header.php +1 -5
  51. templates/php/notices/rate-plugin.php +1 -1
  52. templates/php/snippets/icwp_options_helper.php +1 -1
  53. templates/php/snippets/state_summary.php +8 -6
icwp-wpsf.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
  /*
3
- * Plugin Name: Simple Security Firewall
4
  * Plugin URI: http://icwp.io/2f
5
  * Description: Easy-To-Use WordPress Security System
6
- * Version: 4.17.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: iControlWP
@@ -14,7 +14,7 @@
14
  * Copyright (c) 2016 iControlWP <support@icontrolwp.com>
15
  * All rights reserved.
16
  *
17
- * "WordPress Simple Security Firewall" is distributed under the GNU General Public License, Version 2,
18
  * June 1991. Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin
19
  * St, Fifth Floor, Boston, MA 02110, USA
20
  *
1
  <?php
2
  /*
3
+ * Plugin Name: Shield
4
  * Plugin URI: http://icwp.io/2f
5
  * Description: Easy-To-Use WordPress Security System
6
+ * Version: 5.0.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: iControlWP
14
  * Copyright (c) 2016 iControlWP <support@icontrolwp.com>
15
  * All rights reserved.
16
  *
17
+ * "Shield" (formerly WordPress Simple Firewall) is distributed under the GNU General Public License, Version 2,
18
  * June 1991. Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin
19
  * St, Fifth Floor, Boston, MA 02110, USA
20
  *
plugin-spec.php CHANGED
@@ -1,11 +1,11 @@
1
  <?php
2
  return "---
3
  properties:
4
- version: '4.17.0'
5
  slug_parent: 'icwp'
6
  slug_plugin: 'wpsf'
7
- human_name: 'WordPress Security Firewall'
8
- menu_title: 'Security Firewall'
9
  text_domain: 'wp-simple-firewall'
10
  base_permissions: 'manage_options'
11
  wpms_network_admin_only: true
@@ -39,18 +39,17 @@ includes:
39
 
40
  menu:
41
  show: true
42
- title: 'Security Firewall'
43
  top_level: true # to-do is allow for non-top-level menu items.
44
  do_submenu_fix: true
45
  callback: 'onDisplayTopMenu'
46
  icon_image: 'pluginlogo_16x16.png'
47
  has_submenu: true # to-do is allow for non-top-level menu items.
48
 
49
-
50
  labels: #the keys below must correspond exactly for the 'all_plugins' filter
51
- Name: 'WordPress Security Firewall'
52
  Description: \"Secure Your Sites With The World's Most Powerful WordPress Security Protection System\"
53
- Title: 'WordPress Security Firewall'
54
  Author: 'iControlWP'
55
  AuthorName: 'iControlWP'
56
  PluginURI: 'http://icwp.io/home'
1
  <?php
2
  return "---
3
  properties:
4
+ version: '5.0.0'
5
  slug_parent: 'icwp'
6
  slug_plugin: 'wpsf'
7
+ human_name: 'Shield'
8
+ menu_title: 'Shield'
9
  text_domain: 'wp-simple-firewall'
10
  base_permissions: 'manage_options'
11
  wpms_network_admin_only: true
39
 
40
  menu:
41
  show: true
42
+ title: 'Shield'
43
  top_level: true # to-do is allow for non-top-level menu items.
44
  do_submenu_fix: true
45
  callback: 'onDisplayTopMenu'
46
  icon_image: 'pluginlogo_16x16.png'
47
  has_submenu: true # to-do is allow for non-top-level menu items.
48
 
 
49
  labels: #the keys below must correspond exactly for the 'all_plugins' filter
50
+ Name: 'Shield'
51
  Description: \"Secure Your Sites With The World's Most Powerful WordPress Security Protection System\"
52
+ Title: 'Shield'
53
  Author: 'iControlWP'
54
  AuthorName: 'iControlWP'
55
  PluginURI: 'http://icwp.io/home'
readme.txt CHANGED
@@ -1,20 +1,20 @@
1
- === Simple Security Firewall ===
2
  Contributors: paultgoodchild
3
  Donate link: http://icwp.io/q
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
  Tags: security, firewall, rename wp login, two-factor authentication, audit trail, dos, brute force, whitelist, blacklist, GASP, spam, automatic updates, ithemes, better wp security, all-in-one, lockdown, login, hack
7
  Requires at least: 3.5.0
8
- Tested up to: 4.4
9
- Stable tag: 4.17.0
10
 
11
- Comprehensive and Easy-To-Use WordPress Security - No "Premium" Features
12
 
13
  == Description ==
14
 
15
- > The Simple Security Firewall is the **most powerful [WordPress protection system](http://icwp.io/wpsf09) available**.
16
- We're designed for maximum compatibility with your WordPress sites, while providing an uncomplicated approach for beginner
17
- and advanced users alike - with NO nasty site lockouts. Experience the difference that a great security plugin makes,
18
  alongside common-sense security design. You'll never look back!
19
 
20
  Do you want to secure your WordPress site, without getting overwhelmed?
@@ -66,13 +66,13 @@ Take back control of your WordPress Automatic Updates.
66
 
67
  [youtube http://www.youtube.com/watch?v=r307fu3Eqbo]
68
 
69
- = The Simple Security Firewall Explained =
70
 
71
- The WordPress Simple Security Firewall is built to be highly reliable, and easy to use by **anyone**!
72
 
73
  Originally built off the WordPress Firewall 2, it now includes much more:
74
 
75
- * 7 Simple, clear, Firewall blocking options - pick and choose for ultimate protection and compatibility.
76
  * Option: Ignore already logged-in Administrators so you don't firewall yourself as you work on the site.
77
  * Option: IP Address Whitelist. So you can vet your own IP addresses and 3rd Party Services.
78
  * Option: Developer option for 3rd Party Services to dynamically add IP Addresses to whitelist
@@ -146,23 +146,23 @@ See FAQs.
146
  Note: When you enable the plugin, the firewall is not automatically turned on. This plugin contains various different sections of
147
  protection for your site and you should choose which you need based on your own requirements.
148
 
149
- Why do we do this? Simple, performance and optimization - there is no reason to automatically turn on features for people that don't
150
  need it as each site and set of requirements is different.
151
 
152
  This plugin should install as any other WordPress.org respository plugin.
153
 
154
  1. Browse to Plugins -> Add Plugin
155
- 1. Search: WordPress Simple Firewall
156
  1. Click Install
157
  1. Click to Activate.
158
 
159
- A new menu item will appear on the left-hand side called 'Simple Firewall'.
160
 
161
  == Frequently Asked Questions ==
162
 
163
  Please see the dedicated [help centre](http://icwp.io/firewallhelp) for details on features and some FAQs.
164
 
165
- = How does the Simple Security Firewall compare with other WordPress Security Plugins? =
166
 
167
  Easy - we're just better! ;)
168
 
@@ -177,7 +177,7 @@ Ideally you shouldn't use this along side other Anti-SPAM plugins or security pl
177
  This plugin is an application layer firewall, not a server/network firewall. It is designed to interpret web calls to your site to
178
  look for attempts to circumvent it and gain unauthorized access.
179
 
180
- Your network firewall is designed to restrict access to your server based on certain types of network traffic. The WordPress Simple Firewall
181
  is designed to restrict access to your site, based on certain type of web calls.
182
 
183
  = How does the IP Whitelist work? =
@@ -199,14 +199,14 @@ This happens when any the following 3 conditions are met:
199
  * you have added your IP address to the firewall blacklist,
200
  * you have enabled 2 factor authentication and email doesn't work on your site (and you haven't chosen the override option)
201
 
202
- You can completely turn OFF (and ON) the WordPress Simple Firewall by creating a special file in the plugin folder.
203
 
204
  Here's how:
205
 
206
  1. Open up an FTP connection to your site, browse to the plugin folder <your site WordPress root>/wp-content/plugins/wp-simple-firewall/
207
  1. Create a new file in here called: "forceOff".
208
  1. Load any page on your WordPress site.
209
- 1. After this, you'll find your WordPress Simple Firewall has been switched off.
210
 
211
  If you want to turn the firewall on in the same way, create a file called "forceOn".
212
 
@@ -278,18 +278,25 @@ You can add some custom code to your functions.php exactly as the following:
278
 
279
  == Changelog ==
280
 
281
- = 4.17.0 Latest Point Release =
282
- *Released: 1st February, 2016*
283
 
284
- * **(v.0)** ADDED: NEW feature - [Google Authenticator Login option](http://icwp.io/wpsf43).
285
- * **(v.0)** ADDED: [Core File Scanner](http://icwp.io/wpsf40) now includes an automatic link to repair files (you must be logged in as admin for this link to work!).
286
- * **(v.0)** ADDED: NEW - if you already have a logged-in session and you open the login screen, you'll be provided with a link to go straight to the admin area.
287
- * **(v.0)** CHANGED: Email-based Two-Factor Authentication is now stateless/session-less - it will not check validity per-page load.
288
- * **(v.0)** CHANGED: Changes to the email-based authentication system - now only 1 option and it no longer locks to IP or browser.
289
- * **(v.0)** CHANGED: Various efficiency improvements including reduced SQL updates.
290
- * **(v.0)** CHANGED: Email system is improved and now send emails from the default WordPress sender. This may be [changed with filter](https://icontrolwp.freshdesk.com/support/solutions/articles/3000048723).
 
 
 
 
 
 
291
 
292
  = 4.17 Series =
 
293
 
294
  * **(v.0)** ADDED: NEW feature - [Google Authenticator Login option](http://icwp.io/wpsf43).
295
  * **(v.0)** ADDED: [Core File Scanner](http://icwp.io/wpsf40) now includes an automatic link to repair files (you must be logged in as admin for this link to work!).
@@ -563,9 +570,9 @@ Which actions will trigger an ABLE transgression?
563
  = 4.0.0 =
564
 
565
  * ADDED: New Feature - Audit Trail
566
- * ADDED: Audit Trail options include: Plugins, Themes, Email, WordPress Core, Posts/Pages, WordPress Simple Firewall
567
  * FIXED: Full and proper cleanup of plugin options, crons, and databases upon deactivation.
568
- * REMOVED: Firewall Log. This is no longer an option and is instead integrated into the "WordPress Simple Firewall" Audit Trail.
569
 
570
  = 3.5.5 =
571
 
@@ -678,7 +685,7 @@ Which actions will trigger an ABLE transgression?
678
 
679
  1. More robust cookie values using MD5s
680
  1. Blocks plugin options updating right at the point of WordPress options update so nothing can rewrite the actual plugin options.
681
- 1. Locks the current Admin Access session to your IP address - effectively only 1 Simple Firewall admin allowed at a time.
682
 
683
  = 2.6.2 =
684
 
1
+ === Shield (formerly Simple Firewall) ===
2
  Contributors: paultgoodchild
3
  Donate link: http://icwp.io/q
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
  Tags: security, firewall, rename wp login, two-factor authentication, audit trail, dos, brute force, whitelist, blacklist, GASP, spam, automatic updates, ithemes, better wp security, all-in-one, lockdown, login, hack
7
  Requires at least: 3.5.0
8
+ Tested up to: 4.5
9
+ Stable tag: 5.0.0
10
 
11
+ The Comprehensive and Easy-To-Use Security System for WordPress
12
 
13
  == Description ==
14
 
15
+ > Shield is the **most powerful [WordPress protection system](http://icwp.io/wpsf09) available**.
16
+ Designed for maximum compatibility with your WordPress sites, it provides a super simple approach for both beginner
17
+ and advanced users. NO more nasty site lockouts! Experience the difference that a great security plugin makes,
18
  alongside common-sense security design. You'll never look back!
19
 
20
  Do you want to secure your WordPress site, without getting overwhelmed?
66
 
67
  [youtube http://www.youtube.com/watch?v=r307fu3Eqbo]
68
 
69
+ = Shield Security Explained =
70
 
71
+ The Shield is built to be highly reliable and easy to use by **anyone**!
72
 
73
  Originally built off the WordPress Firewall 2, it now includes much more:
74
 
75
+ * 9 effective and clear, Firewall blocking options - pick and choose for ultimate protection and compatibility.
76
  * Option: Ignore already logged-in Administrators so you don't firewall yourself as you work on the site.
77
  * Option: IP Address Whitelist. So you can vet your own IP addresses and 3rd Party Services.
78
  * Option: Developer option for 3rd Party Services to dynamically add IP Addresses to whitelist
146
  Note: When you enable the plugin, the firewall is not automatically turned on. This plugin contains various different sections of
147
  protection for your site and you should choose which you need based on your own requirements.
148
 
149
+ Why do we do this? It's simple: performance and optimization - there is no reason to automatically turn on features for people that don't
150
  need it as each site and set of requirements is different.
151
 
152
  This plugin should install as any other WordPress.org respository plugin.
153
 
154
  1. Browse to Plugins -> Add Plugin
155
+ 1. Search: Shield
156
  1. Click Install
157
  1. Click to Activate.
158
 
159
+ A new menu item will appear on the left-hand side called 'Shield'.
160
 
161
  == Frequently Asked Questions ==
162
 
163
  Please see the dedicated [help centre](http://icwp.io/firewallhelp) for details on features and some FAQs.
164
 
165
+ = How does the Shield compare with other WordPress Security Plugins? =
166
 
167
  Easy - we're just better! ;)
168
 
177
  This plugin is an application layer firewall, not a server/network firewall. It is designed to interpret web calls to your site to
178
  look for attempts to circumvent it and gain unauthorized access.
179
 
180
+ Your network firewall is designed to restrict access to your server based on certain types of network traffic. The Shield
181
  is designed to restrict access to your site, based on certain type of web calls.
182
 
183
  = How does the IP Whitelist work? =
199
  * you have added your IP address to the firewall blacklist,
200
  * you have enabled 2 factor authentication and email doesn't work on your site (and you haven't chosen the override option)
201
 
202
+ You can completely turn OFF (and ON) the Shield by creating a special file in the plugin folder.
203
 
204
  Here's how:
205
 
206
  1. Open up an FTP connection to your site, browse to the plugin folder <your site WordPress root>/wp-content/plugins/wp-simple-firewall/
207
  1. Create a new file in here called: "forceOff".
208
  1. Load any page on your WordPress site.
209
+ 1. After this, you'll find your Shield has been switched off.
210
 
211
  If you want to turn the firewall on in the same way, create a file called "forceOn".
212
 
278
 
279
  == Changelog ==
280
 
281
+ = 5.0.0 Latest Point Release =
282
+ *Released: 1st March, 2016*
283
 
284
+ * **(v.0)** NEW: WordPress Simple Firewall plugin has been [re-branded and is called **Shield**](http://icwp.io/shld4)
285
+ * **(v.0)** ADDED: Support for this plugin [is now Premium](http://icwp.io/shld3). Added Premium Support page that links to Helpdesk.
286
+ * **(v.0)** ADDED: NEW feature - [Google ReCaptcha](http://icwp.io/shld2) for Comment SPAM and Login protection.
287
+ * **(v.0)** CHANGED: Refactor of comment spam code.
288
+ * **(v.0)** CHANGED: [Core File Scanner](http://icwp.io/wpsf40) now handles the odd Hungarian distribution.
289
+
290
+ = 5.0 Series =
291
+
292
+ * **(v.0)** NEW: WordPress Simple Firewall plugin has been re-branded and is called **Shield**
293
+ * **(v.0)** ADDED: NEW feature - [Google ReCaptcha](http://icwp.io/wpsf43) for Comment SPAM and Login protection.
294
+ * **(v.0)** ADDED: Support for this plugin is now Premium. Added Premium Support page that links to Helpdesk.
295
+ * **(v.0)** CHANGED: Refactor of comment spam code.
296
+ * **(v.0)** CHANGED: [Core File Scanner](http://icwp.io/wpsf40) now handles the odd Hungarian distribution.
297
 
298
  = 4.17 Series =
299
+ *Released: 17th February, 2016*
300
 
301
  * **(v.0)** ADDED: NEW feature - [Google Authenticator Login option](http://icwp.io/wpsf43).
302
  * **(v.0)** ADDED: [Core File Scanner](http://icwp.io/wpsf40) now includes an automatic link to repair files (you must be logged in as admin for this link to work!).
570
  = 4.0.0 =
571
 
572
  * ADDED: New Feature - Audit Trail
573
+ * ADDED: Audit Trail options include: Plugins, Themes, Email, WordPress Core, Posts/Pages, Shield plugin
574
  * FIXED: Full and proper cleanup of plugin options, crons, and databases upon deactivation.
575
+ * REMOVED: Firewall Log. This is no longer an option and is instead integrated into the "Shield" Audit Trail.
576
 
577
  = 3.5.5 =
578
 
685
 
686
  1. More robust cookie values using MD5s
687
  1. Blocks plugin options updating right at the point of WordPress options update so nothing can rewrite the actual plugin options.
688
+ 1. Locks the current Admin Access session to your IP address - effectively only 1 Shield admin allowed at a time.
689
 
690
  = 2.6.2 =
691
 
resources/css/global-plugin.css CHANGED
@@ -122,4 +122,8 @@ tr.icwp-plugin-vulnerability dd {
122
  border: 1px solid rgba(0,0,0,0.1);
123
  padding: 0 7px;
124
  background-color: whitesmoke;
 
 
 
 
125
  }
122
  border: 1px solid rgba(0,0,0,0.1);
123
  padding: 0 7px;
124
  background-color: whitesmoke;
125
+ }
126
+
127
+ .wp-submenu-wrap a .icwp_highlighted {
128
+ color: yellow;
129
  }
resources/css/plugin.css CHANGED
@@ -218,18 +218,19 @@ p.code-description {
218
  margin-bottom: 0;
219
  }
220
  .form-horizontal .item_group {
 
221
  border-radius: 4px;
222
  box-sizing: border-box;
223
  margin-bottom: 10px;
224
  padding: 20px 20px 20px 0;
225
  }
226
  .form-horizontal .selected_item_group {
 
227
  border: 1px solid rgba(135, 232, 38, 0.55);
228
- background-color: rgba(135, 232, 38, 0.1);
229
  }
230
  .option_section {
231
  background-color: rgba(0, 0, 0, 0.008);
232
- border: 1px solid #E6E6E6;
233
  border-radius: 4px;
234
  padding: 8px 10px;
235
  }
@@ -252,8 +253,6 @@ p.code-description {
252
  }
253
 
254
  .option_section.active {
255
- background-color: #f6f6f6;
256
- border-color: #dddddd;
257
  }
258
  table.table th {
259
  border-bottom: 1px solid #777777;
@@ -282,34 +281,30 @@ table#tbl_tbs_options_javascript td {
282
 
283
  /** OPTIONS PAGES **/
284
  .bootstrap-wpadmin .row.row_number_1 {
285
- padding-top: 18px;
286
  }
287
-
288
  label input[type=checkbox] {
289
  height: 16px !important;
290
  }
291
 
292
  /** FEature summaries **/
293
-
294
- .feature-summary-blocks {
295
- margin: 10px 0 25px;
 
 
 
 
296
  }
297
-
298
  .feature-summary-blocks .feature-icon:before {
299
  -webkit-font-smoothing: antialiased;
300
  display: inline-block;
301
  font: 48px/1 'dashicons';
302
  vertical-align: top;
303
  }
304
- .feature-summary-blocks {
305
- background-color: rgba(255, 255, 255, 0.4);
306
- border: 1px solid rgba(0, 0, 0, 0.06);
307
- border-radius: 2px;
308
- margin: 0 0 25px;
309
- padding: 24px 0;
310
- }
311
  .feature-summary-blocks a {
 
312
  text-shadow: 1px 0 0 rgba(0, 0, 0, 0.4);
 
313
  }
314
  .feature-summary-blocks .feature-icon:before {
315
  -webkit-font-smoothing: antialiased;
@@ -317,6 +312,28 @@ label input[type=checkbox] {
317
  font: 48px/1 'dashicons';
318
  vertical-align: top;
319
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  .feature-summary-blocks .state-on a {
321
  color: rgba( 82, 196, 45, 0.85 );
322
  }
@@ -336,7 +353,9 @@ label input[type=checkbox] {
336
  .feature-summary-blocks .feature-summary-block.state-off {
337
  background-color: rgba( 239, 141, 49, 0.2 );
338
  }
339
- #feature-dashboard .feature-icon:before,
 
 
340
  #feature-admin_access_restriction .feature-icon:before {
341
  content: "\f332";
342
  }
@@ -347,7 +366,7 @@ label input[type=checkbox] {
347
  content: "\f307";
348
  }
349
  #feature-hack_protect .feature-icon:before {
350
- content: "\f312";
351
  }
352
  #feature-login_protect .feature-icon:before {
353
  content: "\f112";
@@ -367,7 +386,19 @@ label input[type=checkbox] {
367
  #feature-ips .feature-icon:before {
368
  content: "\f230";
369
  }
 
 
 
370
 
371
  input[type="email"] {
372
  height: 28px;
373
- }
 
 
 
 
 
 
 
 
 
218
  margin-bottom: 0;
219
  }
220
  .form-horizontal .item_group {
221
+ border: 1px solid rgba(0, 0, 0, 0.08);
222
  border-radius: 4px;
223
  box-sizing: border-box;
224
  margin-bottom: 10px;
225
  padding: 20px 20px 20px 0;
226
  }
227
  .form-horizontal .selected_item_group {
228
+ background-color: rgba(135, 232, 38, 0.05);
229
  border: 1px solid rgba(135, 232, 38, 0.55);
 
230
  }
231
  .option_section {
232
  background-color: rgba(0, 0, 0, 0.008);
233
+ border: 1px dashed rgba(0, 0, 0, 0.1);
234
  border-radius: 4px;
235
  padding: 8px 10px;
236
  }
253
  }
254
 
255
  .option_section.active {
 
 
256
  }
257
  table.table th {
258
  border-bottom: 1px solid #777777;
281
 
282
  /** OPTIONS PAGES **/
283
  .bootstrap-wpadmin .row.row_number_1 {
 
284
  }
 
285
  label input[type=checkbox] {
286
  height: 16px !important;
287
  }
288
 
289
  /** FEature summaries **/
290
+ .bootstrap-wpadmin .row-fluid.feature-summary-blocks {
291
+ background-color: rgba(255, 255, 255, 0.4);
292
+ border: 1px solid rgba(0, 0, 0, 0.06);
293
+ border-radius: 2px;
294
+ margin: 0 0 25px;
295
+ padding: 16px 10px 16px 10px;
296
+ width: 99.0%;
297
  }
 
298
  .feature-summary-blocks .feature-icon:before {
299
  -webkit-font-smoothing: antialiased;
300
  display: inline-block;
301
  font: 48px/1 'dashicons';
302
  vertical-align: top;
303
  }
 
 
 
 
 
 
 
304
  .feature-summary-blocks a {
305
+ display: block;
306
  text-shadow: 1px 0 0 rgba(0, 0, 0, 0.4);
307
+ width: 100%;
308
  }
309
  .feature-summary-blocks .feature-icon:before {
310
  -webkit-font-smoothing: antialiased;
312
  font: 48px/1 'dashicons';
313
  vertical-align: top;
314
  }
315
+
316
+ .feature-summary-blocks .summary-state {
317
+ overflow: hidden;
318
+ text-align: center;
319
+ padding: 6px 0;
320
+ }
321
+ .feature-summary-blocks .summary-state.active-feature {
322
+ background-color: rgba(255, 255, 255, 0.8);
323
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
324
+ }
325
+ .feature-summary-blocks .summary-state p {
326
+ font-size: 12px;
327
+ margin: 0;
328
+ }
329
+ @media (max-width: 800px) {
330
+ .feature-summary-blocks .summary-state p {
331
+ font-size: 8px;
332
+ }
333
+ .feature-summary-blocks .feature-icon:before {
334
+ font-size: 32px;
335
+ }
336
+ }
337
  .feature-summary-blocks .state-on a {
338
  color: rgba( 82, 196, 45, 0.85 );
339
  }
353
  .feature-summary-blocks .feature-summary-block.state-off {
354
  background-color: rgba( 239, 141, 49, 0.2 );
355
  }
356
+ #feature-plugin .feature-icon:before{
357
+ content: "\f111";
358
+ }
359
  #feature-admin_access_restriction .feature-icon:before {
360
  content: "\f332";
361
  }
366
  content: "\f307";
367
  }
368
  #feature-hack_protect .feature-icon:before {
369
+ content: "\f153";
370
  }
371
  #feature-login_protect .feature-icon:before {
372
  content: "\f112";
386
  #feature-ips .feature-icon:before {
387
  content: "\f230";
388
  }
389
+ #feature-support .feature-icon:before {
390
+ content: "\f525";
391
+ }
392
 
393
  input[type="email"] {
394
  height: 28px;
395
+ }
396
+
397
+ .bootstrap-wpadmin .row .shield-free-block {
398
+ background-color: rgba(255, 255, 255, 0.7);
399
+ border: 1px solid rgba(0, 0, 0, 0.1);
400
+ padding: 20px 50px;
401
+ }
402
+ .bootstrap-wpadmin .row .shield-free-block p {
403
+ margin-bottom: 18px;
404
+ }
src/common/googlerecaptcha/ReCaptcha/ReCaptcha.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha;
28
+
29
+ /**
30
+ * reCAPTCHA client.
31
+ */
32
+ class ReCaptcha
33
+ {
34
+ /**
35
+ * Version of this client library.
36
+ * @const string
37
+ */
38
+ const VERSION = 'php_1.1.2';
39
+
40
+ /**
41
+ * Shared secret for the site.
42
+ * @var type string
43
+ */
44
+ private $secret;
45
+
46
+ /**
47
+ * Method used to communicate with service. Defaults to POST request.
48
+ * @var RequestMethod
49
+ */
50
+ private $requestMethod;
51
+
52
+ /**
53
+ * Create a configured instance to use the reCAPTCHA service.
54
+ *
55
+ * @param string $secret shared secret between site and reCAPTCHA server.
56
+ * @param RequestMethod $requestMethod method used to send the request. Defaults to POST.
57
+ */
58
+ public function __construct($secret, RequestMethod $requestMethod = null)
59
+ {
60
+ if (empty($secret)) {
61
+ throw new \RuntimeException('No secret provided');
62
+ }
63
+
64
+ if (!is_string($secret)) {
65
+ throw new \RuntimeException('The provided secret must be a string');
66
+ }
67
+
68
+ $this->secret = $secret;
69
+
70
+ if (!is_null($requestMethod)) {
71
+ $this->requestMethod = $requestMethod;
72
+ } else {
73
+ $this->requestMethod = new RequestMethod\Post();
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Calls the reCAPTCHA siteverify API to verify whether the user passes
79
+ * CAPTCHA test.
80
+ *
81
+ * @param string $response The value of 'g-recaptcha-response' in the submitted form.
82
+ * @param string $remoteIp The end user's IP address.
83
+ * @return Response Response from the service.
84
+ */
85
+ public function verify($response, $remoteIp = null)
86
+ {
87
+ // Discard empty solution submissions
88
+ if (empty($response)) {
89
+ $recaptchaResponse = new Response(false, array('missing-input-response'));
90
+ return $recaptchaResponse;
91
+ }
92
+
93
+ $params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION);
94
+ $rawResponse = $this->requestMethod->submit($params);
95
+ return Response::fromJson($rawResponse);
96
+ }
97
+ }
src/common/googlerecaptcha/ReCaptcha/RequestMethod.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha;
28
+
29
+ /**
30
+ * Method used to send the request to the service.
31
+ */
32
+ interface RequestMethod
33
+ {
34
+
35
+ /**
36
+ * Submit the request with the specified parameters.
37
+ *
38
+ * @param RequestParameters $params Request parameters
39
+ * @return string Body of the reCAPTCHA response
40
+ */
41
+ public function submit(RequestParameters $params);
42
+ }
src/common/googlerecaptcha/ReCaptcha/RequestMethod/Curl.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha\RequestMethod;
28
+
29
+ /**
30
+ * Convenience wrapper around the cURL functions to allow mocking.
31
+ */
32
+ class Curl
33
+ {
34
+
35
+ /**
36
+ * @see http://php.net/curl_init
37
+ * @param string $url
38
+ * @return resource cURL handle
39
+ */
40
+ public function init($url = null)
41
+ {
42
+ return curl_init($url);
43
+ }
44
+
45
+ /**
46
+ * @see http://php.net/curl_setopt_array
47
+ * @param resource $ch
48
+ * @param array $options
49
+ * @return bool
50
+ */
51
+ public function setoptArray($ch, array $options)
52
+ {
53
+ return curl_setopt_array($ch, $options);
54
+ }
55
+
56
+ /**
57
+ * @see http://php.net/curl_exec
58
+ * @param resource $ch
59
+ * @return mixed
60
+ */
61
+ public function exec($ch)
62
+ {
63
+ return curl_exec($ch);
64
+ }
65
+
66
+ /**
67
+ * @see http://php.net/curl_close
68
+ * @param resource $ch
69
+ */
70
+ public function close($ch)
71
+ {
72
+ curl_close($ch);
73
+ }
74
+ }
src/common/googlerecaptcha/ReCaptcha/RequestMethod/CurlPost.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha\RequestMethod;
28
+
29
+ use ReCaptcha\RequestMethod;
30
+ use ReCaptcha\RequestParameters;
31
+
32
+ /**
33
+ * Sends cURL request to the reCAPTCHA service.
34
+ * Note: this requires the cURL extension to be enabled in PHP
35
+ * @see http://php.net/manual/en/book.curl.php
36
+ */
37
+ class CurlPost implements RequestMethod
38
+ {
39
+ /**
40
+ * URL to which requests are sent via cURL.
41
+ * @const string
42
+ */
43
+ const SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
44
+
45
+ /**
46
+ * Curl connection to the reCAPTCHA service
47
+ * @var Curl
48
+ */
49
+ private $curl;
50
+
51
+ public function __construct(Curl $curl = null)
52
+ {
53
+ if (!is_null($curl)) {
54
+ $this->curl = $curl;
55
+ } else {
56
+ $this->curl = new Curl();
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Submit the cURL request with the specified parameters.
62
+ *
63
+ * @param RequestParameters $params Request parameters
64
+ * @return string Body of the reCAPTCHA response
65
+ */
66
+ public function submit(RequestParameters $params)
67
+ {
68
+ $handle = $this->curl->init(self::SITE_VERIFY_URL);
69
+
70
+ $options = array(
71
+ CURLOPT_POST => true,
72
+ CURLOPT_POSTFIELDS => $params->toQueryString(),
73
+ CURLOPT_HTTPHEADER => array(
74
+ 'Content-Type: application/x-www-form-urlencoded'
75
+ ),
76
+ CURLINFO_HEADER_OUT => false,
77
+ CURLOPT_HEADER => false,
78
+ CURLOPT_RETURNTRANSFER => true,
79
+ CURLOPT_SSL_VERIFYPEER => true
80
+ );
81
+ $this->curl->setoptArray($handle, $options);
82
+
83
+ $response = $this->curl->exec($handle);
84
+ $this->curl->close($handle);
85
+
86
+ return $response;
87
+ }
88
+ }
src/common/googlerecaptcha/ReCaptcha/RequestMethod/Post.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha\RequestMethod;
28
+
29
+ use ReCaptcha\RequestMethod;
30
+ use ReCaptcha\RequestParameters;
31
+
32
+ /**
33
+ * Sends POST requests to the reCAPTCHA service.
34
+ */
35
+ class Post implements RequestMethod
36
+ {
37
+ /**
38
+ * URL to which requests are POSTed.
39
+ * @const string
40
+ */
41
+ const SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
42
+
43
+ /**
44
+ * Submit the POST request with the specified parameters.
45
+ *
46
+ * @param RequestParameters $params Request parameters
47
+ * @return string Body of the reCAPTCHA response
48
+ */
49
+ public function submit(RequestParameters $params)
50
+ {
51
+ /**
52
+ * PHP 5.6.0 changed the way you specify the peer name for SSL context options.
53
+ * Using "CN_name" will still work, but it will raise deprecated errors.
54
+ */
55
+ $peer_key = version_compare(PHP_VERSION, '5.6.0', '<') ? 'CN_name' : 'peer_name';
56
+ $options = array(
57
+ 'http' => array(
58
+ 'header' => "Content-type: application/x-www-form-urlencoded\r\n",
59
+ 'method' => 'POST',
60
+ 'content' => $params->toQueryString(),
61
+ // Force the peer to validate (not needed in 5.6.0+, but still works
62
+ 'verify_peer' => true,
63
+ // Force the peer validation to use www.google.com
64
+ $peer_key => 'www.google.com',
65
+ ),
66
+ );
67
+ $context = stream_context_create($options);
68
+ return file_get_contents(self::SITE_VERIFY_URL, false, $context);
69
+ }
70
+ }
src/common/googlerecaptcha/ReCaptcha/RequestMethod/Socket.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha\RequestMethod;
28
+
29
+ /**
30
+ * Convenience wrapper around native socket and file functions to allow for
31
+ * mocking.
32
+ */
33
+ class Socket
34
+ {
35
+ private $handle = null;
36
+
37
+ /**
38
+ * fsockopen
39
+ *
40
+ * @see http://php.net/fsockopen
41
+ * @param string $hostname
42
+ * @param int $port
43
+ * @param int $errno
44
+ * @param string $errstr
45
+ * @param float $timeout
46
+ * @return resource
47
+ */
48
+ public function fsockopen($hostname, $port = -1, &$errno = 0, &$errstr = '', $timeout = null)
49
+ {
50
+ $this->handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout));
51
+
52
+ if ($this->handle != false && $errno === 0 && $errstr === '') {
53
+ return $this->handle;
54
+ } else {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * fwrite
61
+ *
62
+ * @see http://php.net/fwrite
63
+ * @param string $string
64
+ * @param int $length
65
+ * @return int | bool
66
+ */
67
+ public function fwrite($string, $length = null)
68
+ {
69
+ return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length));
70
+ }
71
+
72
+ /**
73
+ * fgets
74
+ *
75
+ * @see http://php.net/fgets
76
+ * @param int $length
77
+ * @return string
78
+ */
79
+ public function fgets($length = null)
80
+ {
81
+ return fgets($this->handle, $length);
82
+ }
83
+
84
+ /**
85
+ * feof
86
+ *
87
+ * @see http://php.net/feof
88
+ * @return bool
89
+ */
90
+ public function feof()
91
+ {
92
+ return feof($this->handle);
93
+ }
94
+
95
+ /**
96
+ * fclose
97
+ *
98
+ * @see http://php.net/fclose
99
+ * @return bool
100
+ */
101
+ public function fclose()
102
+ {
103
+ return fclose($this->handle);
104
+ }
105
+ }
src/common/googlerecaptcha/ReCaptcha/RequestMethod/SocketPost.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha\RequestMethod;
28
+
29
+ use ReCaptcha\RequestMethod;
30
+ use ReCaptcha\RequestParameters;
31
+
32
+ /**
33
+ * Sends a POST request to the reCAPTCHA service, but makes use of fsockopen()
34
+ * instead of get_file_contents(). This is to account for people who may be on
35
+ * servers where allow_furl_open is disabled.
36
+ */
37
+ class SocketPost implements RequestMethod
38
+ {
39
+ /**
40
+ * reCAPTCHA service host.
41
+ * @const string
42
+ */
43
+ const RECAPTCHA_HOST = 'www.google.com';
44
+
45
+ /**
46
+ * @const string reCAPTCHA service path
47
+ */
48
+ const SITE_VERIFY_PATH = '/recaptcha/api/siteverify';
49
+
50
+ /**
51
+ * @const string Bad request error
52
+ */
53
+ const BAD_REQUEST = '{"success": false, "error-codes": ["invalid-request"]}';
54
+
55
+ /**
56
+ * @const string Bad response error
57
+ */
58
+ const BAD_RESPONSE = '{"success": false, "error-codes": ["invalid-response"]}';
59
+
60
+ /**
61
+ * Socket to the reCAPTCHA service
62
+ * @var Socket
63
+ */
64
+ private $socket;
65
+
66
+ /**
67
+ * Constructor
68
+ *
69
+ * @param \ReCaptcha\RequestMethod\Socket $socket optional socket, injectable for testing
70
+ */
71
+ public function __construct(Socket $socket = null)
72
+ {
73
+ if (!is_null($socket)) {
74
+ $this->socket = $socket;
75
+ } else {
76
+ $this->socket = new Socket();
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Submit the POST request with the specified parameters.
82
+ *
83
+ * @param RequestParameters $params Request parameters
84
+ * @return string Body of the reCAPTCHA response
85
+ */
86
+ public function submit(RequestParameters $params)
87
+ {
88
+ $errno = 0;
89
+ $errstr = '';
90
+
91
+ if (false === $this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30)) {
92
+ return self::BAD_REQUEST;
93
+ }
94
+
95
+ $content = $params->toQueryString();
96
+
97
+ $request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n";
98
+ $request .= "Host: " . self::RECAPTCHA_HOST . "\r\n";
99
+ $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
100
+ $request .= "Content-length: " . strlen($content) . "\r\n";
101
+ $request .= "Connection: close\r\n\r\n";
102
+ $request .= $content . "\r\n\r\n";
103
+
104
+ $this->socket->fwrite($request);
105
+ $response = '';
106
+
107
+ while (!$this->socket->feof()) {
108
+ $response .= $this->socket->fgets(4096);
109
+ }
110
+
111
+ $this->socket->fclose();
112
+
113
+ if (0 !== strpos($response, 'HTTP/1.1 200 OK')) {
114
+ return self::BAD_RESPONSE;
115
+ }
116
+
117
+ $parts = preg_split("#\n\s*\n#Uis", $response);
118
+
119
+ return $parts[1];
120
+ }
121
+ }
src/common/googlerecaptcha/ReCaptcha/RequestParameters.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha;
28
+
29
+ /**
30
+ * Stores and formats the parameters for the request to the reCAPTCHA service.
31
+ */
32
+ class RequestParameters
33
+ {
34
+ /**
35
+ * Site secret.
36
+ * @var string
37
+ */
38
+ private $secret;
39
+
40
+ /**
41
+ * Form response.
42
+ * @var string
43
+ */
44
+ private $response;
45
+
46
+ /**
47
+ * Remote user's IP address.
48
+ * @var string
49
+ */
50
+ private $remoteIp;
51
+
52
+ /**
53
+ * Client version.
54
+ * @var string
55
+ */
56
+ private $version;
57
+
58
+ /**
59
+ * Initialise parameters.
60
+ *
61
+ * @param string $secret Site secret.
62
+ * @param string $response Value from g-captcha-response form field.
63
+ * @param string $remoteIp User's IP address.
64
+ * @param string $version Version of this client library.
65
+ */
66
+ public function __construct($secret, $response, $remoteIp = null, $version = null)
67
+ {
68
+ $this->secret = $secret;
69
+ $this->response = $response;
70
+ $this->remoteIp = $remoteIp;
71
+ $this->version = $version;
72
+ }
73
+
74
+ /**
75
+ * Array representation.
76
+ *
77
+ * @return array Array formatted parameters.
78
+ */
79
+ public function toArray()
80
+ {
81
+ $params = array('secret' => $this->secret, 'response' => $this->response);
82
+
83
+ if (!is_null($this->remoteIp)) {
84
+ $params['remoteip'] = $this->remoteIp;
85
+ }
86
+
87
+ if (!is_null($this->version)) {
88
+ $params['version'] = $this->version;
89
+ }
90
+
91
+ return $params;
92
+ }
93
+
94
+ /**
95
+ * Query string representation for HTTP request.
96
+ *
97
+ * @return string Query string formatted parameters.
98
+ */
99
+ public function toQueryString()
100
+ {
101
+ return http_build_query($this->toArray(), '', '&');
102
+ }
103
+ }
src/common/googlerecaptcha/ReCaptcha/Response.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is a PHP library that handles calling reCAPTCHA.
4
+ *
5
+ * @copyright Copyright (c) 2015, Google Inc.
6
+ * @link http://www.google.com/recaptcha
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ namespace ReCaptcha;
28
+
29
+ /**
30
+ * The response returned from the service.
31
+ */
32
+ class Response
33
+ {
34
+ /**
35
+ * Succes or failure.
36
+ * @var boolean
37
+ */
38
+ private $success = false;
39
+
40
+ /**
41
+ * Error code strings.
42
+ * @var array
43
+ */
44
+ private $errorCodes = array();
45
+
46
+ /**
47
+ * Build the response from the expected JSON returned by the service.
48
+ *
49
+ * @param string $json
50
+ * @return \ReCaptcha\Response
51
+ */
52
+ public static function fromJson($json)
53
+ {
54
+ $responseData = json_decode($json, true);
55
+
56
+ if (!$responseData) {
57
+ return new Response(false, array('invalid-json'));
58
+ }
59
+
60
+ if (isset($responseData['success']) && $responseData['success'] == true) {
61
+ return new Response(true);
62
+ }
63
+
64
+ if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) {
65
+ return new Response(false, $responseData['error-codes']);
66
+ }
67
+
68
+ return new Response(false);
69
+ }
70
+
71
+ /**
72
+ * Constructor.
73
+ *
74
+ * @param boolean $success
75
+ * @param array $errorCodes
76
+ */
77
+ public function __construct($success, array $errorCodes = array())
78
+ {
79
+ $this->success = $success;
80
+ $this->errorCodes = $errorCodes;
81
+ }
82
+
83
+ /**
84
+ * Is success?
85
+ *
86
+ * @return boolean
87
+ */
88
+ public function isSuccess()
89
+ {
90
+ return $this->success;
91
+ }
92
+
93
+ /**
94
+ * Get error codes.
95
+ *
96
+ * @return array
97
+ */
98
+ public function getErrorCodes()
99
+ {
100
+ return $this->errorCodes;
101
+ }
102
+ }
src/common/googlerecaptcha/autoload.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* An autoloader for ReCaptcha\Foo classes. This should be require()d
4
+ * by the user before attempting to instantiate any of the ReCaptcha
5
+ * classes.
6
+ */
7
+
8
+ spl_autoload_register(function ($class) {
9
+ if (substr($class, 0, 10) !== 'ReCaptcha\\') {
10
+ /* If the class does not lie under the "ReCaptcha" namespace,
11
+ * then we can exit immediately.
12
+ */
13
+ return;
14
+ }
15
+
16
+ /* All of the classes have names like "ReCaptcha\Foo", so we need
17
+ * to replace the backslashes with frontslashes if we want the
18
+ * name to map directly to a location in the filesystem.
19
+ */
20
+ $class = str_replace('\\', '/', $class);
21
+
22
+ /* First, check under the current directory. It is important that
23
+ * we look here first, so that we don't waste time searching for
24
+ * test classes in the common case.
25
+ */
26
+ $path = dirname(__FILE__).'/'.$class.'.php';
27
+ if (is_readable($path)) {
28
+ require_once $path;
29
+ }
30
+
31
+ /* If we didn't find what we're looking for already, maybe it's
32
+ * a test class?
33
+ */
34
+ $path = dirname(__FILE__).'/../tests/'.$class.'.php';
35
+ if (is_readable($path)) {
36
+ require_once $path;
37
+ }
38
+ });
src/common/icwp-data.php CHANGED
@@ -765,10 +765,18 @@ if ( !class_exists( 'ICWP_WPSF_DataProcessor', false ) ):
765
  }
766
 
767
  /**
768
- * @return string
 
769
  */
770
  public function getPhpVersionIsAtLeast( $sAtLeastVersion ) {
771
- return ( version_compare( $this->getPhpVersion(), $sAtLeastVersion, '>=' ) );
 
 
 
 
 
 
 
772
  }
773
 
774
  /**
765
  }
766
 
767
  /**
768
+ * @param string $sAtLeastVersion
769
+ * @return bool
770
  */
771
  public function getPhpVersionIsAtLeast( $sAtLeastVersion ) {
772
+ return version_compare( $this->getPhpVersion(), $sAtLeastVersion, '>=' );
773
+ }
774
+
775
+ /**
776
+ * @return bool
777
+ */
778
+ public function getPhpSupportsNamespaces() {
779
+ return $this->getPhpVersionIsAtLeast( '5.3' );
780
  }
781
 
782
  /**
src/common/icwp-foundation.php CHANGED
@@ -50,6 +50,10 @@ if ( !class_exists( 'ICWP_WPSF_Foundation', false ) ) :
50
  * @var ICWP_WPSF_WpComments
51
  */
52
  private static $oWpComments;
 
 
 
 
53
 
54
  /**
55
  * @return ICWP_WPSF_DataProcessor
@@ -135,6 +139,17 @@ if ( !class_exists( 'ICWP_WPSF_Foundation', false ) ) :
135
  return self::$oGA;
136
  }
137
 
 
 
 
 
 
 
 
 
 
 
 
138
  /**
139
  * @param string $sTemplatePath
140
  * @return ICWP_WPSF_Render
50
  * @var ICWP_WPSF_WpComments
51
  */
52
  private static $oWpComments;
53
+ /**
54
+ * @var ICWP_WPSF_GoogleRecaptcha
55
+ */
56
+ private static $oGR;
57
 
58
  /**
59
  * @return ICWP_WPSF_DataProcessor
139
  return self::$oGA;
140
  }
141
 
142
+ /**
143
+ * @return ICWP_WPSF_GoogleRecaptcha
144
+ */
145
+ static public function loadGoogleRecaptcha() {
146
+ if ( !isset( self::$oGR ) ) {
147
+ require_once( dirname(__FILE__).ICWP_DS.'icwp-googlearecaptcha.php' );
148
+ self::$oGR = ICWP_WPSF_GoogleRecaptcha::GetInstance();
149
+ }
150
+ return self::$oGR;
151
+ }
152
+
153
  /**
154
  * @param string $sTemplatePath
155
  * @return ICWP_WPSF_Render
src/common/icwp-googlearecaptcha.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !class_exists( 'ICWP_WPSF_GoogleRecaptcha', false ) ):
3
+
4
+ class ICWP_WPSF_GoogleRecaptcha {
5
+
6
+ /**
7
+ * @var ICWP_WPSF_GoogleRecaptcha
8
+ */
9
+ protected static $oInstance = NULL;
10
+
11
+ /**
12
+ * @var \ReCaptcha\ReCaptcha
13
+ */
14
+ protected static $oGR;
15
+
16
+ /**
17
+ * @return ICWP_WPSF_GoogleRecaptcha
18
+ */
19
+ public static function GetInstance() {
20
+ if ( is_null( self::$oInstance ) ) {
21
+ self::$oInstance = new self();
22
+ }
23
+ return self::$oInstance;
24
+ }
25
+
26
+ /**
27
+ */
28
+ protected function loadGoogleRecaptchaLib() {
29
+ return require_once( dirname(__FILE__).ICWP_DS.'googlerecaptcha/autoload.php' );
30
+ }
31
+
32
+ /**
33
+ * @param string $sSecret
34
+ * @return \ReCaptcha\ReCaptcha
35
+ */
36
+ public function getGoogleRecaptchaLib( $sSecret ) {
37
+ if ( !isset( self::$oGR ) ) {
38
+ if ( $this->loadGoogleRecaptchaLib() ) {
39
+ self::$oGR = new \ReCaptcha\ReCaptcha( $sSecret );
40
+ }
41
+ }
42
+ return self::$oGR;
43
+ }
44
+ }
45
+ endif;
src/common/icwp-wpfilesystem.php CHANGED
@@ -476,14 +476,13 @@ if ( !class_exists( 'ICWP_WPSF_WpFilesystem', false ) ):
476
  */
477
  private function initFileSystem() {
478
  if ( is_null( $this->oWpfs ) ) {
 
479
  require_once( ABSPATH . 'wp-admin'.ICWP_DS.'includes'.ICWP_DS.'file.php' );
480
- WP_Filesystem();
481
- global $wp_filesystem;
482
- if ( isset( $wp_filesystem ) && is_object( $wp_filesystem ) ) {
483
- $this->oWpfs = $wp_filesystem;
484
- }
485
- else {
486
- $this->oWpfs = false;
487
  }
488
  }
489
  }
476
  */
477
  private function initFileSystem() {
478
  if ( is_null( $this->oWpfs ) ) {
479
+ $this->oWpfs = false;
480
  require_once( ABSPATH . 'wp-admin'.ICWP_DS.'includes'.ICWP_DS.'file.php' );
481
+ if ( WP_Filesystem() ) {
482
+ global $wp_filesystem;
483
+ if ( isset( $wp_filesystem ) && is_object( $wp_filesystem ) ) {
484
+ $this->oWpfs = $wp_filesystem;
485
+ }
 
 
486
  }
487
  }
488
  }
src/config/feature-comments_filter.php CHANGED
@@ -23,11 +23,11 @@ sections:
23
  slug: 'section_enable_plugin_feature_spam_comments_protection_filter'
24
  primary: true
25
  -
26
- slug: 'section_enable_automatic_bot_comment_spam_protection_filter'
27
  -
28
- slug: 'section_customize_messages_shown_to_user'
29
  -
30
- slug: 'section_enable_human_comment_spam_protection_filter'
31
  -
32
  slug: 'section_non_ui'
33
  hidden: true
@@ -43,14 +43,14 @@ options:
43
  link_blog: 'http://icwp.io/wpsf04'
44
  -
45
  key: 'enable_comments_human_spam_filter'
46
- section: 'section_enable_human_comment_spam_protection_filter'
47
  default: 'N'
48
  type: 'checkbox'
49
  link_info: 'http://icwp.io/57'
50
  link_blog: ''
51
  -
52
  key: 'enable_comments_human_spam_filter_items'
53
- section: 'section_enable_human_comment_spam_protection_filter'
54
  type: 'multiple_select'
55
  default:
56
  - 'author_name'
@@ -83,7 +83,7 @@ options:
83
  link_blog: ''
84
  -
85
  key: 'comments_default_action_human_spam'
86
- section: 'section_enable_human_comment_spam_protection_filter'
87
  default: 0
88
  type: 'select'
89
  value_options:
@@ -101,14 +101,21 @@ options:
101
  text: 'Reject And Redirect'
102
  -
103
  key: 'enable_comments_gasp_protection'
104
- section: 'section_enable_automatic_bot_comment_spam_protection_filter'
105
  default: 'Y'
106
  type: 'checkbox'
107
  link_info: 'http://icwp.io/3n'
108
  link_blog: 'http://icwp.io/2n'
 
 
 
 
 
 
 
109
  -
110
  key: 'enable_comments_gasp_protection_for_logged_in'
111
- section: 'section_enable_automatic_bot_comment_spam_protection_filter'
112
  hidden: true #since version v4.0.1 this has been removed.
113
  default: 'N'
114
  type: 'checkbox'
@@ -116,7 +123,7 @@ options:
116
  link_blog: ''
117
  -
118
  key: 'comments_default_action_spam_bot'
119
- section: 'section_enable_automatic_bot_comment_spam_protection_filter'
120
  default: 'trash'
121
  type: 'select'
122
  value_options:
@@ -137,14 +144,14 @@ options:
137
  link_blog: ''
138
  -
139
  key: 'comments_cooldown_interval'
140
- section: 'section_enable_automatic_bot_comment_spam_protection_filter'
141
  default: 30
142
  type: 'integer'
143
  link_info: 'http://icwp.io/3o'
144
  link_blog: ''
145
  -
146
  key: 'comments_token_expire_interval'
147
- section: 'section_enable_automatic_bot_comment_spam_protection_filter'
148
  default: 600
149
  type: 'integer'
150
  link_info: 'http://icwp.io/3o'
@@ -200,6 +207,6 @@ options:
200
  section: 'section_non_ui'
201
  default: false
202
  ",
203
- _wpsf__( 'Comments Filter' ),
204
  _wpsf__( 'Block comment SPAM and retain your privacy' ) //tagline
205
  );
23
  slug: 'section_enable_plugin_feature_spam_comments_protection_filter'
24
  primary: true
25
  -
26
+ slug: 'section_bot_comment_spam_protection_filter'
27
  -
28
+ slug: 'section_human_spam_filter'
29
  -
30
+ slug: 'section_customize_messages_shown_to_user'
31
  -
32
  slug: 'section_non_ui'
33
  hidden: true
43
  link_blog: 'http://icwp.io/wpsf04'
44
  -
45
  key: 'enable_comments_human_spam_filter'
46
+ section: 'section_human_spam_filter'
47
  default: 'N'
48
  type: 'checkbox'
49
  link_info: 'http://icwp.io/57'
50
  link_blog: ''
51
  -
52
  key: 'enable_comments_human_spam_filter_items'
53
+ section: 'section_human_spam_filter'
54
  type: 'multiple_select'
55
  default:
56
  - 'author_name'
83
  link_blog: ''
84
  -
85
  key: 'comments_default_action_human_spam'
86
+ section: 'section_human_spam_filter'
87
  default: 0
88
  type: 'select'
89
  value_options:
101
  text: 'Reject And Redirect'
102
  -
103
  key: 'enable_comments_gasp_protection'
104
+ section: 'section_bot_comment_spam_protection_filter'
105
  default: 'Y'
106
  type: 'checkbox'
107
  link_info: 'http://icwp.io/3n'
108
  link_blog: 'http://icwp.io/2n'
109
+ -
110
+ key: 'enable_google_recaptcha'
111
+ section: 'section_bot_comment_spam_protection_filter'
112
+ default: 'N'
113
+ type: 'checkbox'
114
+ link_info: ''
115
+ link_blog: ''
116
  -
117
  key: 'enable_comments_gasp_protection_for_logged_in'
118
+ section: 'section_bot_comment_spam_protection_filter'
119
  hidden: true #since version v4.0.1 this has been removed.
120
  default: 'N'
121
  type: 'checkbox'
123
  link_blog: ''
124
  -
125
  key: 'comments_default_action_spam_bot'
126
+ section: 'section_bot_comment_spam_protection_filter'
127
  default: 'trash'
128
  type: 'select'
129
  value_options:
144
  link_blog: ''
145
  -
146
  key: 'comments_cooldown_interval'
147
+ section: 'section_bot_comment_spam_protection_filter'
148
  default: 30
149
  type: 'integer'
150
  link_info: 'http://icwp.io/3o'
151
  link_blog: ''
152
  -
153
  key: 'comments_token_expire_interval'
154
+ section: 'section_bot_comment_spam_protection_filter'
155
  default: 600
156
  type: 'integer'
157
  link_info: 'http://icwp.io/3o'
207
  section: 'section_non_ui'
208
  default: false
209
  ",
210
+ _wpsf__( 'Comments SPAM' ),
211
  _wpsf__( 'Block comment SPAM and retain your privacy' ) //tagline
212
  );
src/config/feature-hack_protect.php CHANGED
@@ -67,6 +67,8 @@ definitions:
67
  - 'hello.php'
68
  - 'wp-config-sample.php'
69
  - 'akismet'
 
 
70
  - 'themes/twenty'
71
  - 'wp-content/languages/'
72
  corechecksum_exclusions_missing_only:
67
  - 'hello.php'
68
  - 'wp-config-sample.php'
69
  - 'akismet'
70
+ - '/azigen/'
71
+ - '/magyar-video-embed/'
72
  - 'themes/twenty'
73
  - 'wp-content/languages/'
74
  corechecksum_exclusions_missing_only:
src/config/feature-login_protect.php CHANGED
@@ -105,12 +105,19 @@ options:
105
  link_info: 'http://icwp.io/4v'
106
  link_blog: ''
107
  -
108
- key: 'enable_user_register_checking'
109
  section: 'section_brute_force_login_protection'
110
- default: 'Y'
111
  type: 'checkbox'
112
  link_info: ''
113
  link_blog: ''
 
 
 
 
 
 
 
114
  -
115
  key: 'login_limit_interval'
116
  section: 'section_brute_force_login_protection'
@@ -119,11 +126,11 @@ options:
119
  link_info: 'http://icwp.io/3q'
120
  link_blog: ''
121
  -
122
- key: 'enable_login_gasp_check'
123
  section: 'section_brute_force_login_protection'
124
  default: 'Y'
125
  type: 'checkbox'
126
- link_info: 'http://icwp.io/3r'
127
  link_blog: ''
128
  -
129
  key: 'enable_prevent_remote_post'
105
  link_info: 'http://icwp.io/4v'
106
  link_blog: ''
107
  -
108
+ key: 'enable_google_recaptcha'
109
  section: 'section_brute_force_login_protection'
110
+ default: 'N'
111
  type: 'checkbox'
112
  link_info: ''
113
  link_blog: ''
114
+ -
115
+ key: 'enable_login_gasp_check'
116
+ section: 'section_brute_force_login_protection'
117
+ default: 'Y'
118
+ type: 'checkbox'
119
+ link_info: 'http://icwp.io/3r'
120
+ link_blog: ''
121
  -
122
  key: 'login_limit_interval'
123
  section: 'section_brute_force_login_protection'
126
  link_info: 'http://icwp.io/3q'
127
  link_blog: ''
128
  -
129
+ key: 'enable_user_register_checking'
130
  section: 'section_brute_force_login_protection'
131
  default: 'Y'
132
  type: 'checkbox'
133
+ link_info: ''
134
  link_blog: ''
135
  -
136
  key: 'enable_prevent_remote_post'
src/config/feature-plugin.php CHANGED
@@ -56,6 +56,8 @@ sections:
56
  primary: true
57
  -
58
  slug: 'section_general_plugin_options'
 
 
59
  -
60
  slug: 'section_non_ui'
61
  hidden: true
@@ -104,6 +106,20 @@ options:
104
  type: 'noneditable_text'
105
  link_info: ''
106
  link_blog: ''
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  -
108
  key: 'current_plugin_version'
109
  section: 'section_non_ui'
@@ -158,6 +174,11 @@ options:
158
  storage_key: 'audit_trail'
159
  load_priority: 11
160
  hidden: false
 
 
 
 
 
161
  -
162
  slug: 'email'
163
  storage_key: 'email'
56
  primary: true
57
  -
58
  slug: 'section_general_plugin_options'
59
+ -
60
+ slug: 'section_third_party'
61
  -
62
  slug: 'section_non_ui'
63
  hidden: true
106
  type: 'noneditable_text'
107
  link_info: ''
108
  link_blog: ''
109
+ -
110
+ key: 'google_recaptcha_secret_key'
111
+ section: 'section_third_party'
112
+ default: ''
113
+ type: 'text'
114
+ link_info: ''
115
+ link_blog: ''
116
+ -
117
+ key: 'google_recaptcha_site_key'
118
+ section: 'section_third_party'
119
+ default: ''
120
+ type: 'text'
121
+ link_info: ''
122
+ link_blog: ''
123
  -
124
  key: 'current_plugin_version'
125
  section: 'section_non_ui'
174
  storage_key: 'audit_trail'
175
  load_priority: 11
176
  hidden: false
177
+ -
178
+ slug: 'support'
179
+ storage_key: 'support'
180
+ load_priority: 20
181
+ hidden: false
182
  -
183
  slug: 'email'
184
  storage_key: 'email'
src/config/feature-support.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return
3
+ sprintf(
4
+ "---
5
+ properties:
6
+ slug: 'support'
7
+ name: '%s'
8
+ show_feature_menu_item: true
9
+ storage_key: 'support' # should correspond exactly to that in the plugin.yaml
10
+ tagline: '%s'
11
+ auto_enabled: true
12
+ highlight_menu_item: true
13
+ # Options Sections
14
+ sections:
15
+ -
16
+ slug: 'section_enable_plugin_feature_support'
17
+ primary: true
18
+ -
19
+ slug: 'section_non_ui'
20
+ hidden: true
21
+
22
+ # Define Options
23
+ options:
24
+ -
25
+ key: 'enable_support'
26
+ section: 'section_enable_plugin_feature_support'
27
+ default: 'Y'
28
+ type: 'checkbox'
29
+ link_info: ''
30
+ link_blog: ''
31
+ -
32
+ key: 'current_plugin_version'
33
+ section: 'section_non_ui'
34
+
35
+ # Definitions for constant data that doesn't need store in the options
36
+ definitions:
37
+ default_helpdesk_url: 'http://icwp.io/shieldhelpdesk'
38
+ ",
39
+ _wpsf__( 'Premium Support' ),
40
+ _wpsf__( 'Premium Plugin Support Centre' ) //tagline
41
+ );
src/features/base.php CHANGED
@@ -63,6 +63,11 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Base', false ) ):
63
  */
64
  protected $oFeatureProcessor;
65
 
 
 
 
 
 
66
  /**
67
  * @param ICWP_WPSF_Plugin_Controller $oPluginController
68
  * @param array $aFeatureProperties
@@ -371,7 +376,11 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Base', false ) ):
371
 
372
  $sHumanName = $this->getController()->getHumanName();
373
 
374
- $sMenuPageTitle = $sHumanName.' - '.$sMenuTitleName;
 
 
 
 
375
  $aItems[ $sMenuPageTitle ] = array(
376
  $sMenuTitleName,
377
  $this->doPluginPrefix( $this->getFeatureSlug() ),
@@ -415,10 +424,13 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Base', false ) ):
415
  return $aSummaryData;
416
  }
417
 
 
418
  $aSummaryData[] = array(
419
  'enabled' => $this->getIsMainFeatureEnabled(),
 
420
  'slug' => $this->getFeatureSlug(),
421
  'name' => $this->getMainFeatureName(),
 
422
  'href' => network_admin_url( 'admin.php?page='.$this->doPluginPrefix( $this->getFeatureSlug() ) )
423
  );
424
 
@@ -1011,6 +1023,7 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Base', false ) ):
1011
  */
1012
  protected function getBaseDisplayData() {
1013
  $oCon = $this->getController();
 
1014
  return array(
1015
  'var_prefix' => $oCon->getOptionStoragePrefix(),
1016
  'sPluginName' => $oCon->getHumanName(),
@@ -1023,7 +1036,9 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Base', false ) ):
1023
  'form_action' => 'admin.php?page='.$this->doPluginPrefix( $this->getFeatureSlug() ),
1024
  'nOptionsPerRow' => 1,
1025
  'aPluginLabels' => $oCon->getPluginLabels(),
 
1026
  'bShowStateSummary' => false,
 
1027
 
1028
  'aAllOptions' => $this->buildOptions(),
1029
  'aHiddenOptions' => $this->getOptionsVo()->getHiddenOptions(),
63
  */
64
  protected $oFeatureProcessor;
65
 
66
+ /**
67
+ * @var string
68
+ */
69
+ protected static $sActivelyDisplayedModuleOptions = '';
70
+
71
  /**
72
  * @param ICWP_WPSF_Plugin_Controller $oPluginController
73
  * @param array $aFeatureProperties
376
 
377
  $sHumanName = $this->getController()->getHumanName();
378
 
379
+ $bMenuHighlighted = $this->getOptionsVo()->getFeatureProperty( 'highlight_menu_item' );
380
+ if ( $bMenuHighlighted ) {
381
+ $sMenuTitleName = sprintf( '<span class="icwp_highlighted">%s</span>', $sMenuTitleName );
382
+ }
383
+ $sMenuPageTitle = $sMenuTitleName.' - '.$sHumanName;
384
  $aItems[ $sMenuPageTitle ] = array(
385
  $sMenuTitleName,
386
  $this->doPluginPrefix( $this->getFeatureSlug() ),
424
  return $aSummaryData;
425
  }
426
 
427
+ $sMenuTitle = $this->getOptionsVo()->getFeatureProperty( 'menu_title' );
428
  $aSummaryData[] = array(
429
  'enabled' => $this->getIsMainFeatureEnabled(),
430
+ 'active' => self::$sActivelyDisplayedModuleOptions == $this->getFeatureSlug(),
431
  'slug' => $this->getFeatureSlug(),
432
  'name' => $this->getMainFeatureName(),
433
+ 'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : $sMenuTitle,
434
  'href' => network_admin_url( 'admin.php?page='.$this->doPluginPrefix( $this->getFeatureSlug() ) )
435
  );
436
 
1023
  */
1024
  protected function getBaseDisplayData() {
1025
  $oCon = $this->getController();
1026
+ self::$sActivelyDisplayedModuleOptions = $this->getFeatureSlug();
1027
  return array(
1028
  'var_prefix' => $oCon->getOptionStoragePrefix(),
1029
  'sPluginName' => $oCon->getHumanName(),
1036
  'form_action' => 'admin.php?page='.$this->doPluginPrefix( $this->getFeatureSlug() ),
1037
  'nOptionsPerRow' => 1,
1038
  'aPluginLabels' => $oCon->getPluginLabels(),
1039
+
1040
  'bShowStateSummary' => false,
1041
+ 'aSummaryData' => apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() ),
1042
 
1043
  'aAllOptions' => $this->buildOptions(),
1044
  'aHiddenOptions' => $this->getOptionsVo()->getHiddenOptions(),
src/features/base_wpsf.php CHANGED
@@ -5,6 +5,32 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_BaseWpsf', false ) ):
5
  require_once( dirname(__FILE__).ICWP_DS.'base.php' );
6
 
7
  class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  /**
9
  * @return array
10
  */
5
  require_once( dirname(__FILE__).ICWP_DS.'base.php' );
6
 
7
  class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
8
+
9
+ /**
10
+ * Overriden in the plugin handler getting the option value
11
+ * @return string
12
+ */
13
+ public function getGoogleRecaptchaSecretKey() {
14
+ return apply_filters( $this->doPluginPrefix( 'google_recaptcha_secret_key' ), '' );
15
+ }
16
+
17
+ /**
18
+ * Overriden in the plugin handler getting the option value
19
+ * @return string
20
+ */
21
+ public function getGoogleRecaptchaSiteKey() {
22
+ return apply_filters( $this->doPluginPrefix( 'google_recaptcha_site_key' ), '' );
23
+ }
24
+
25
+ /**
26
+ * @return bool
27
+ */
28
+ public function getIsGoogleRecaptchaReady() {
29
+ $sKey = $this->getGoogleRecaptchaSiteKey();
30
+ $sSecret = $this->getGoogleRecaptchaSecretKey();
31
+ return ( !empty( $sSecret ) && !empty( $sKey ) );
32
+ }
33
+
34
  /**
35
  * @return array
36
  */
src/features/comments_filter.php CHANGED
@@ -45,7 +45,7 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_CommentsFilter', false ) ):
45
  $sTitleShort = sprintf( '%s / %s', _wpsf__( 'Enable' ), _wpsf__( 'Disable' ) );
46
  break;
47
 
48
- case 'section_enable_automatic_bot_comment_spam_protection_filter' :
49
  $sTitle = sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Automatic Bot') );
50
  $aSummary = array(
51
  sprintf( _wpsf__( 'Purpose - %s' ), _wpsf__( 'Blocks 100% of all automated bot-generated comment SPAM.' ) ),
@@ -54,7 +54,7 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_CommentsFilter', false ) ):
54
  $sTitleShort = _wpsf__( 'Bot SPAM' );
55
  break;
56
 
57
- case 'section_enable_human_comment_spam_protection_filter' :
58
  $sTitle = sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Human') );
59
  $aSummary = array(
60
  sprintf( _wpsf__( 'Purpose - %s' ), _wpsf__( 'Uses a 3rd party SPAM dictionary to detect human-based comment SPAM.' ) ),
@@ -116,6 +116,12 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_CommentsFilter', false ) ):
116
  $sDescription = sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('a human commenter').'</span>' );
117
  break;
118
 
 
 
 
 
 
 
119
  case 'enable_comments_gasp_protection' :
120
  $sName = _wpsf__( 'GASP Protection' );
121
  $sSummary = _wpsf__( 'Add Growmap Anti Spambot Protection to your comments' );
45
  $sTitleShort = sprintf( '%s / %s', _wpsf__( 'Enable' ), _wpsf__( 'Disable' ) );
46
  break;
47
 
48
+ case 'section_bot_comment_spam_protection_filter' :
49
  $sTitle = sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Automatic Bot') );
50
  $aSummary = array(
51
  sprintf( _wpsf__( 'Purpose - %s' ), _wpsf__( 'Blocks 100% of all automated bot-generated comment SPAM.' ) ),
54
  $sTitleShort = _wpsf__( 'Bot SPAM' );
55
  break;
56
 
57
+ case 'section_human_spam_filter' :
58
  $sTitle = sprintf( _wpsf__( '%s Comment SPAM Protection Filter' ), _wpsf__('Human') );
59
  $aSummary = array(
60
  sprintf( _wpsf__( 'Purpose - %s' ), _wpsf__( 'Uses a 3rd party SPAM dictionary to detect human-based comment SPAM.' ) ),
116
  $sDescription = sprintf( _wpsf__( 'When a comment is detected as being SPAM from %s, the comment will be categorised based on this setting.' ), '<span style"text-decoration:underline;">'._wpsf__('a human commenter').'</span>' );
117
  break;
118
 
119
+ case 'enable_google_recaptcha' :
120
+ $sName = _wpsf__( 'Google ReCaptcha' );
121
+ $sSummary = _wpsf__( 'Enable Google ReCaptcha For Comments' );
122
+ $sDescription = _wpsf__( 'Use Google ReCaptcha on the comments form to prevent bot-spam comments.' );
123
+ break;
124
+
125
  case 'enable_comments_gasp_protection' :
126
  $sName = _wpsf__( 'GASP Protection' );
127
  $sSummary = _wpsf__( 'Add Growmap Anti Spambot Protection to your comments' );
src/features/login_protect.php CHANGED
@@ -251,23 +251,29 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_LoginProtect', false ) ):
251
  $sName = _wpsf__( 'Login Cooldown Interval' );
252
  $sSummary = _wpsf__( 'Limit login attempts to every X seconds' );
253
  $sDescription = _wpsf__( 'WordPress will process only ONE login attempt for every number of seconds specified.' )
254
- .'<br />'._wpsf__( 'Zero (0) turns this off.' )
255
- .' '.sprintf( _wpsf__( 'Default: "%s".' ), $this->getOptionsVo()->getOptDefault( 'login_limit_interval' ) );
256
  break;
257
 
258
  case 'enable_login_gasp_check' :
259
  $sName = _wpsf__( 'G.A.S.P Protection' );
260
  $sSummary = _wpsf__( 'Use G.A.S.P. Protection To Prevent Login Attempts By Bots' );
261
  $sDescription = _wpsf__( 'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques.' )
262
- .' '.sprintf( _wpsf__( 'Recommended: %s' ), _wpsf__('ON') );
 
 
 
 
 
 
263
  break;
264
 
265
  case 'enable_prevent_remote_post' :
266
  $sName = _wpsf__( 'Prevent Remote Login' );
267
  $sSummary = _wpsf__( 'Prevents Remote Login Attempts From Anywhere Except Your Site' );
268
  $sDescription = _wpsf__( 'Prevents login by bots attempting to login remotely to your site.' )
269
- .' '._wpsf__( 'You will not be able to enable this option if your web server does not support it.' )
270
- .' '.sprintf( _wpsf__( 'Recommended: %s' ), _wpsf__('ON') );
271
  break;
272
 
273
  case 'enable_yubikey' :
@@ -280,23 +286,23 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_LoginProtect', false ) ):
280
  $sName = _wpsf__( 'Yubikey App ID' );
281
  $sSummary = _wpsf__( 'Your Unique Yubikey App ID' );
282
  $sDescription = _wpsf__( 'Combined with your Yubikey API Key this will form the basis of your Yubikey Authentication' )
283
- . _wpsf__( 'Please review the info link on how to obtain your own Yubikey App ID and API Key.' );
284
  break;
285
 
286
  case 'yubikey_api_key' :
287
  $sName = _wpsf__( 'Yubikey API Key' );
288
  $sSummary = _wpsf__( 'Your Unique Yubikey App API Key' );
289
  $sDescription = _wpsf__( 'Combined with your Yubikey App ID this will form the basis of your Yubikey Authentication.' )
290
- . _wpsf__( 'Please review the info link on how to get your own Yubikey App ID and API Key.' );
291
  break;
292
 
293
  case 'yubikey_unique_keys' :
294
  $sName = _wpsf__( 'Yubikey Unique Keys' );
295
  $sSummary = _wpsf__( 'Permitted "Username - Yubikey" Pairs For This Site' );
296
- $sDescription = '<strong>'. sprintf( _wpsf__( 'Format: %s' ), 'Username,Yubikey' ).'</strong>'
297
- .'<br />- '. _wpsf__( 'Provide Username<->Yubikey Pairs that are usable for this site.')
298
- .'<br />- '. _wpsf__( 'If a Username if not assigned a Yubikey, Yubikey Authentication is OFF for that user.' )
299
- .'<br />- '. _wpsf__( 'Each [Username,Key] pair should be separated by a new line: you only need to provide the first 12 characters of the yubikey.' );
300
  break;
301
 
302
  default:
@@ -427,6 +433,13 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_LoginProtect', false ) ):
427
  return $this->getIfCanSendEmail() && $this->getIsEmailAuthenticationOptionOn();
428
  }
429
 
 
 
 
 
 
 
 
430
  /**
431
  * @return int
432
  */
251
  $sName = _wpsf__( 'Login Cooldown Interval' );
252
  $sSummary = _wpsf__( 'Limit login attempts to every X seconds' );
253
  $sDescription = _wpsf__( 'WordPress will process only ONE login attempt for every number of seconds specified.' )
254
+ . '<br />' . _wpsf__( 'Zero (0) turns this off.' )
255
+ . ' ' . sprintf( _wpsf__( 'Default: "%s".' ), $this->getOptionsVo()->getOptDefault( 'login_limit_interval' ) );
256
  break;
257
 
258
  case 'enable_login_gasp_check' :
259
  $sName = _wpsf__( 'G.A.S.P Protection' );
260
  $sSummary = _wpsf__( 'Use G.A.S.P. Protection To Prevent Login Attempts By Bots' );
261
  $sDescription = _wpsf__( 'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques.' )
262
+ . ' ' . sprintf( _wpsf__( 'Recommended: %s' ), _wpsf__( 'ON' ) );
263
+ break;
264
+
265
+ case 'enable_google_recaptcha' :
266
+ $sName = _wpsf__( 'Google ReCaptcha' );
267
+ $sSummary = _wpsf__( 'Enable Google ReCaptcha' );
268
+ $sDescription = _wpsf__( 'Use Google ReCaptcha on the login screen.' );
269
  break;
270
 
271
  case 'enable_prevent_remote_post' :
272
  $sName = _wpsf__( 'Prevent Remote Login' );
273
  $sSummary = _wpsf__( 'Prevents Remote Login Attempts From Anywhere Except Your Site' );
274
  $sDescription = _wpsf__( 'Prevents login by bots attempting to login remotely to your site.' )
275
+ . ' ' . _wpsf__( 'You will not be able to enable this option if your web server does not support it.' )
276
+ . ' ' . sprintf( _wpsf__( 'Recommended: %s' ), _wpsf__( 'ON' ) );
277
  break;
278
 
279
  case 'enable_yubikey' :
286
  $sName = _wpsf__( 'Yubikey App ID' );
287
  $sSummary = _wpsf__( 'Your Unique Yubikey App ID' );
288
  $sDescription = _wpsf__( 'Combined with your Yubikey API Key this will form the basis of your Yubikey Authentication' )
289
+ . _wpsf__( 'Please review the info link on how to obtain your own Yubikey App ID and API Key.' );
290
  break;
291
 
292
  case 'yubikey_api_key' :
293
  $sName = _wpsf__( 'Yubikey API Key' );
294
  $sSummary = _wpsf__( 'Your Unique Yubikey App API Key' );
295
  $sDescription = _wpsf__( 'Combined with your Yubikey App ID this will form the basis of your Yubikey Authentication.' )
296
+ . _wpsf__( 'Please review the info link on how to get your own Yubikey App ID and API Key.' );
297
  break;
298
 
299
  case 'yubikey_unique_keys' :
300
  $sName = _wpsf__( 'Yubikey Unique Keys' );
301
  $sSummary = _wpsf__( 'Permitted "Username - Yubikey" Pairs For This Site' );
302
+ $sDescription = '<strong>' . sprintf( _wpsf__( 'Format: %s' ), 'Username,Yubikey' ) . '</strong>'
303
+ . '<br />- ' . _wpsf__( 'Provide Username<->Yubikey Pairs that are usable for this site.' )
304
+ . '<br />- ' . _wpsf__( 'If a Username if not assigned a Yubikey, Yubikey Authentication is OFF for that user.' )
305
+ . '<br />- ' . _wpsf__( 'Each [Username,Key] pair should be separated by a new line: you only need to provide the first 12 characters of the yubikey.' );
306
  break;
307
 
308
  default:
433
  return $this->getIfCanSendEmail() && $this->getIsEmailAuthenticationOptionOn();
434
  }
435
 
436
+ /**
437
+ * @return bool
438
+ */
439
+ public function getIsGoogleRecaptchaEnabled() {
440
+ return ( $this->getOptIs( 'enable_google_recaptcha', 'Y' ) && $this->loadDataProcessor()->getPhpSupportsNamespaces() );
441
+ }
442
+
443
  /**
444
  * @return int
445
  */
src/features/plugin.php CHANGED
@@ -10,6 +10,24 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Plugin', false ) ):
10
  add_action( 'deactivate_plugin', array( $this, 'onWpHookDeactivatePlugin' ), 1, 1 );
11
  add_filter( $this->doPluginPrefix( 'report_email_address' ), array( $this, 'getPluginReportEmail' ) );
12
  add_filter( $this->doPluginPrefix( 'globally_disabled' ), array( $this, 'filter_IsPluginGloballyDisabled' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
 
15
  /**
@@ -50,24 +68,6 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Plugin', false ) ):
50
  return true;
51
  }
52
 
53
- /**
54
- * @param array $aSummaryData
55
- * @return array
56
- */
57
- public function filter_getFeatureSummaryData( $aSummaryData ) {
58
- return $aSummaryData;
59
- }
60
-
61
- /**
62
- */
63
- public function displayFeatureConfigPage( ) {
64
- $aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
65
- $aData = array(
66
- 'aSummaryData' => $aPluginSummaryData
67
- );
68
- $this->display( $aData );
69
- }
70
-
71
  /**
72
  * Hooked to 'deactivate_plugin' and can be used to interrupt the deactivation of this plugin.
73
  *
@@ -116,6 +116,11 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Plugin', false ) ):
116
  $sTitleShort = _wpsf__( 'General Options' );
117
  break;
118
 
 
 
 
 
 
119
  default:
120
  throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
121
  }
@@ -170,6 +175,18 @@ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Plugin', false ) ):
170
  case 'delete_on_deactivate' :
171
  $sName = _wpsf__( 'Delete Plugin Settings' );
172
  $sSummary = _wpsf__( 'Delete All Plugin Settings Upon Plugin Deactivation' );
 
 
 
 
 
 
 
 
 
 
 
 
173
  $sDescription = _wpsf__( 'Careful: Removes all plugin options when you deactivate the plugin' );
174
  break;
175
 
10
  add_action( 'deactivate_plugin', array( $this, 'onWpHookDeactivatePlugin' ), 1, 1 );
11
  add_filter( $this->doPluginPrefix( 'report_email_address' ), array( $this, 'getPluginReportEmail' ) );
12
  add_filter( $this->doPluginPrefix( 'globally_disabled' ), array( $this, 'filter_IsPluginGloballyDisabled' ) );
13
+ add_filter( $this->doPluginPrefix( 'google_recaptcha_secret_key' ), array( $this, 'supplyGoogleRecaptchaSecretKey' ) );
14
+ add_filter( $this->doPluginPrefix( 'google_recaptcha_site_key' ), array( $this, 'supplyGoogleRecaptchaSiteKey' ) );
15
+ }
16
+
17
+ /**
18
+ * @param string $sKey
19
+ * @return string
20
+ */
21
+ public function supplyGoogleRecaptchaSecretKey( $sKey ) {
22
+ return $this->getOpt( 'google_recaptcha_secret_key', $sKey );
23
+ }
24
+
25
+ /**
26
+ * @param string $sKey
27
+ * @return string
28
+ */
29
+ public function supplyGoogleRecaptchaSiteKey( $sKey ) {
30
+ return $this->getOpt( 'google_recaptcha_site_key', $sKey );
31
  }
32
 
33
  /**
68
  return true;
69
  }
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  /**
72
  * Hooked to 'deactivate_plugin' and can be used to interrupt the deactivation of this plugin.
73
  *
116
  $sTitleShort = _wpsf__( 'General Options' );
117
  break;
118
 
119
+ case 'section_third_party' :
120
+ $sTitle = _wpsf__( 'Third Party Services' );
121
+ $sTitleShort = _wpsf__( 'Third Party Services' );
122
+ break;
123
+
124
  default:
125
  throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
126
  }
175
  case 'delete_on_deactivate' :
176
  $sName = _wpsf__( 'Delete Plugin Settings' );
177
  $sSummary = _wpsf__( 'Delete All Plugin Settings Upon Plugin Deactivation' );
178
+ $sDescription = _wpsf__( 'Enter your Google Recaptcha secret key for use throughout the plugin.' );
179
+ break;
180
+
181
+ case 'google_recaptcha_secret_key' :
182
+ $sName = _wpsf__( 'Recaptcha Secret' );
183
+ $sSummary = _wpsf__( 'Google Recaptcha Secret Key' );
184
+ $sDescription = _wpsf__( 'Enter your Google Recaptcha site key for use throughout the plugin.' );
185
+ break;
186
+
187
+ case 'google_recaptcha_site_key' :
188
+ $sName = _wpsf__( 'Recaptcha Site Key' );
189
+ $sSummary = _wpsf__( 'Google Recaptcha Site Key' );
190
  $sDescription = _wpsf__( 'Careful: Removes all plugin options when you deactivate the plugin' );
191
  break;
192
 
src/features/support.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !class_exists( 'ICWP_WPSF_FeatureHandler_Support', false ) ):
4
+
5
+ require_once( dirname(__FILE__).ICWP_DS.'base_wpsf.php' );
6
+
7
+ class ICWP_WPSF_FeatureHandler_Support extends ICWP_WPSF_FeatureHandler_BaseWpsf {
8
+
9
+ /**
10
+ */
11
+ public function displayFeatureConfigPage( ) {
12
+ $aData = array(
13
+ 'has_premium_support' => $this->getHasPremiumSupport(),
14
+ 'premium_support_registered_email' => $this->getPremiumSupportRegisteredEmail(),
15
+ 'aHrefs' => array(
16
+ 'support_centre_sso' => $this->getPremiumSupportHelpdeskUrl(),
17
+ 'shield_pro_url' => 'http://icwp.io/shieldpro',
18
+ 'shield_pro_more_info_url' => 'http://icwp.io/shld1'
19
+ )
20
+ );
21
+ $this->display( $aData, 'feature-support' );
22
+ }
23
+
24
+ /**
25
+ * @return bool
26
+ */
27
+ public function getPremiumSupportRegisteredEmail() {
28
+ return $this->getHasPremiumSupport() ? ICWP_Plugin::GetAssignedToEmail() : '';
29
+ }
30
+
31
+ /**
32
+ * @return bool
33
+ */
34
+ public function getPremiumSupportHelpdeskUrl() {
35
+ $sHelpdesk = $this->getHasPremiumSupport() ? ICWP_Plugin::GetHelpdeskSsoUrl() : '';
36
+ return empty( $sHelpdesk ) ? $this->getDefinition( 'default_helpdesk_url' ) : $sHelpdesk;
37
+ }
38
+
39
+ /**
40
+ * @return bool
41
+ */
42
+ public function getHasPremiumSupport() {
43
+ return apply_filters( $this->doPluginPrefix( 'has_premium_support' ), $this->getIcwpLinked() );
44
+ }
45
+
46
+ /**
47
+ * @return bool
48
+ */
49
+ protected function getHasIcwpPluginActive() {
50
+ return ( class_exists( 'ICWP_Plugin' ) && method_exists( 'ICWP_Plugin', 'IsLinked' ) );
51
+ }
52
+
53
+ /**
54
+ * @return bool
55
+ */
56
+ protected function getIcwpLinked() {
57
+ return ( $this->getHasIcwpPluginActive() && ICWP_Plugin::IsLinked() && $this->getIcwpPluginMeetsMinimumVersion() );
58
+ }
59
+
60
+ /**
61
+ * @return boolean
62
+ */
63
+ protected function getIcwpPluginMeetsMinimumVersion() {
64
+ return version_compare( ICWP_Plugin::GetVersion(), '2.13', '>=' );
65
+ }
66
+
67
+ public function doPrePluginOptionsSave() {}
68
+
69
+ /**
70
+ * @param array $aOptionsParams
71
+ * @return array
72
+ * @throws Exception
73
+ */
74
+ protected function loadStrings_SectionTitles( $aOptionsParams ) {
75
+
76
+ $sSectionSlug = $aOptionsParams['section_slug'];
77
+ switch( $aOptionsParams['section_slug'] ) {
78
+
79
+ case 'section_enable_plugin_feature_support' :
80
+ $sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
81
+ $aSummary = array(
82
+ sprintf( _wpsf__( 'Purpose - %s' ), _wpsf__( 'Contact Plugin Premium Support Centre.' ) ),
83
+ sprintf( _wpsf__( 'Recommendation - %s' ), sprintf( _wpsf__( 'Keep the %s feature turned on.' ), $this->getMainFeatureName() ) )
84
+ );
85
+ $sTitleShort = sprintf( '%s / %s', _wpsf__( 'Enable' ), _wpsf__( 'Disable' ) );
86
+ break;
87
+
88
+ default:
89
+ throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
90
+ }
91
+ $aOptionsParams['section_title'] = $sTitle;
92
+ $aOptionsParams['section_summary'] = ( isset( $aSummary ) && is_array( $aSummary ) ) ? $aSummary : array();
93
+ $aOptionsParams['section_title_short'] = $sTitleShort;
94
+ return $aOptionsParams;
95
+ }
96
+
97
+ /**
98
+ * @param array $aOptionsParams
99
+ * @return array
100
+ * @throws Exception
101
+ */
102
+ protected function loadStrings_Options( $aOptionsParams ) {
103
+
104
+ $sKey = $aOptionsParams['key'];
105
+ switch( $sKey ) {
106
+
107
+ case 'enable_support' :
108
+ $sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
109
+ $sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
110
+ $sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
111
+ break;
112
+
113
+ default:
114
+ throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
115
+ }
116
+
117
+ $aOptionsParams['name'] = $sName;
118
+ $aOptionsParams['summary'] = $sSummary;
119
+ $aOptionsParams['description'] = $sDescription;
120
+ return $aOptionsParams;
121
+ }
122
+ }
123
+
124
+ endif;
src/processors/audit_trail.php CHANGED
@@ -13,6 +13,19 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AuditTrail_V1', false ) ):
13
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getAuditTrailTableName() );
14
  }
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  public function action_doFeatureProcessorShutdown () {
17
  if ( ! $this->getFeatureOptions()->getIsPluginDeleting() ) {
18
  $this->commitAuditTrial();
@@ -149,20 +162,6 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AuditTrail_V1', false ) ):
149
  protected function getTableColumnsByDefinition() {
150
  return $this->getOption( 'audit_trail_table_columns' );
151
  }
152
-
153
- /**
154
- * This is hooked into a cron in the base class and overrides the parent method.
155
- *
156
- * It'll delete everything older than 30 days.
157
- */
158
- public function cleanupDatabase() {
159
- $nDays = $this->getOption( 'audit_trail_auto_clean' );
160
- if ( !$this->getTableExists() || $nDays <= 0 ) {
161
- return;
162
- }
163
- $nTimeStamp = $this->time() - $nDays * DAY_IN_SECONDS;
164
- $this->deleteAllRowsOlderThan( $nTimeStamp );
165
- }
166
  }
167
 
168
  endif;
13
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getAuditTrailTableName() );
14
  }
15
 
16
+ /**
17
+ * Resets the object values to be re-used anew
18
+ */
19
+ public function init() {
20
+ parent::init();
21
+
22
+ // Auto delete db entries
23
+ $nDays = $this->getOption( 'audit_trail_auto_clean' );
24
+ if ( $nDays > 0 ) {
25
+ $this->setAutoExpirePeriod( $nDays * DAY_IN_SECONDS );
26
+ }
27
+ }
28
+
29
  public function action_doFeatureProcessorShutdown () {
30
  if ( ! $this->getFeatureOptions()->getIsPluginDeleting() ) {
31
  $this->commitAuditTrial();
162
  protected function getTableColumnsByDefinition() {
163
  return $this->getOption( 'audit_trail_table_columns' );
164
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  }
166
 
167
  endif;
src/processors/base_commentsfilter.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !class_exists( 'ICWP_WPSF_Processor_CommentsFilter_GoogleRecaptcha', false ) ):
4
+
5
+ require_once( dirname(__FILE__).ICWP_DS.'base_wpsf.php' );
6
+
7
+ class ICWP_WPSF_Processor_CommentsFilter_Base extends ICWP_WPSF_Processor_BaseWpsf {
8
+
9
+ /**
10
+ * @var array
11
+ */
12
+ static protected $aRawCommentData;
13
+ /**
14
+ * @var string
15
+ */
16
+ static protected $sCommentStatus;
17
+ /**
18
+ * @var string
19
+ */
20
+ static protected $sCommentStatusExplanation = '';
21
+
22
+ /**
23
+ * Resets the object values to be re-used anew
24
+ */
25
+ public function init() {
26
+ parent::init();
27
+ self::$sCommentStatus = '';
28
+ self::$sCommentStatusExplanation = '';
29
+ }
30
+
31
+ /**
32
+ */
33
+ public function run() {
34
+ add_filter( 'preprocess_comment', array( $this, 'doCommentChecking' ), 1, 1 );
35
+ add_filter( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status' ), array( $this, 'getCommentStatus' ), 1 );
36
+ add_filter( $this->getFeatureOptions()->doPluginPrefix( 'comments_filter_status_explanation' ), array( $this, 'getCommentStatusExplanation' ), 1 );
37
+ }
38
+
39
+ /**
40
+ * @param array $aCommentData
41
+ * @return array
42
+ */
43
+ public function doCommentChecking( $aCommentData ) {
44
+ if ( empty( self::$aRawCommentData ) ) {
45
+ self::$aRawCommentData = $aCommentData;
46
+ }
47
+ return $aCommentData;
48
+ }
49
+
50
+ /**
51
+ * A private plugin filter that lets us return up the newly set comment status.
52
+ *
53
+ * @param $sCurrentCommentStatus
54
+ * @return string
55
+ */
56
+ public function getCommentStatus( $sCurrentCommentStatus ) {
57
+ return empty( $sCurrentCommentStatus )? self::$sCommentStatus : $sCurrentCommentStatus;
58
+ }
59
+
60
+ /**
61
+ * @return string
62
+ */
63
+ protected function getExpanation() {
64
+ return self::$sCommentStatusExplanation;
65
+ }
66
+
67
+ /**
68
+ * @param string $sKey
69
+ * @return string|array|null
70
+ */
71
+ protected function getRawCommentData( $sKey = '' ) {
72
+ if ( !isset( self::$aRawCommentData ) ) {
73
+ self::$aRawCommentData = array();
74
+ }
75
+ if ( !empty( $sKey ) ) {
76
+ return isset( self::$aRawCommentData[$sKey] ) ? self::$aRawCommentData[$sKey] : null;
77
+ }
78
+ return self::$aRawCommentData;
79
+ }
80
+
81
+ /**
82
+ * @return string
83
+ */
84
+ protected function getStatus() {
85
+ return self::$sCommentStatus;
86
+ }
87
+
88
+ /**
89
+ * A private plugin filter that lets us return up the newly set comment status explanation
90
+ *
91
+ * @param $sCurrentCommentStatusExplanation
92
+ * @return string
93
+ */
94
+ public function getCommentStatusExplanation( $sCurrentCommentStatusExplanation ) {
95
+ return empty( $sCurrentCommentStatusExplanation )? self::$sCommentStatusExplanation : $sCurrentCommentStatusExplanation;
96
+ }
97
+
98
+ /**
99
+ * @param string $sStatus
100
+ * @return $this
101
+ */
102
+ protected function setCommentStatus( $sStatus ) {
103
+ self::$sCommentStatus = $sStatus;
104
+ return $this;
105
+ }
106
+
107
+ /**
108
+ * @param $sExplanation
109
+ */
110
+ protected function setCommentStatusExplanation( $sExplanation ) {
111
+ self::$sCommentStatusExplanation =
112
+ '[* '.sprintf(
113
+ _wpsf__('%s plugin marked this comment as "%s".').' '._wpsf__( 'Reason: %s' ),
114
+ $this->getController()->getHumanName(),
115
+ self::$sCommentStatus,
116
+ $sExplanation
117
+ )." *]\n";
118
+ }
119
+ }
120
+ endif;
src/processors/basedb.php CHANGED
@@ -17,6 +17,11 @@ if ( !class_exists( 'ICWP_WPSF_BaseDbProcessor', false ) ):
17
  */
18
  protected $bTableExists;
19
 
 
 
 
 
 
20
  /**
21
  * @param ICWP_WPSF_FeatureHandler_Base $oFeatureOptions
22
  * @param string $sTableName
@@ -209,8 +214,17 @@ if ( !class_exists( 'ICWP_WPSF_BaseDbProcessor', false ) ):
209
  return $this->getController()->doPluginPrefix( $this->getFeatureOptions()->getFeatureSlug().'_db_cleanup' );
210
  }
211
 
212
- // by default does nothing - override this method
213
- public function cleanupDatabase() { }
 
 
 
 
 
 
 
 
 
214
 
215
  /**
216
  * @return bool
@@ -225,6 +239,22 @@ if ( !class_exists( 'ICWP_WPSF_BaseDbProcessor', false ) ):
225
  $this->bTableExists = $this->loadDbProcessor()->getIfTableExists( $this->getTableName() );
226
  return $this->bTableExists;
227
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  }
229
 
230
  endif;
17
  */
18
  protected $bTableExists;
19
 
20
+ /**
21
+ * @var integer
22
+ */
23
+ protected $nAutoExpirePeriod = null;
24
+
25
  /**
26
  * @param ICWP_WPSF_FeatureHandler_Base $oFeatureOptions
27
  * @param string $sTableName
214
  return $this->getController()->doPluginPrefix( $this->getFeatureOptions()->getFeatureSlug().'_db_cleanup' );
215
  }
216
 
217
+ /**
218
+ * @return bool|int
219
+ */
220
+ public function cleanupDatabase() {
221
+ $nAutoExpirePeriod = $this->getAutoExpirePeriod();
222
+ if ( is_null( $nAutoExpirePeriod ) || !$this->getTableExists() ) {
223
+ return false;
224
+ }
225
+ $nTimeStamp = $this->time() - $nAutoExpirePeriod;
226
+ return $this->deleteAllRowsOlderThan( $nTimeStamp );
227
+ }
228
 
229
  /**
230
  * @return bool
239
  $this->bTableExists = $this->loadDbProcessor()->getIfTableExists( $this->getTableName() );
240
  return $this->bTableExists;
241
  }
242
+
243
+ /**
244
+ * @return int
245
+ */
246
+ protected function getAutoExpirePeriod() {
247
+ return $this->nAutoExpirePeriod;
248
+ }
249
+
250
+ /**
251
+ * @param int $nTimePeriod
252
+ * @return $this
253
+ */
254
+ protected function setAutoExpirePeriod( $nTimePeriod ) {
255
+ $this->nAutoExpirePeriod = $nTimePeriod;
256
+ return $this;
257
+ }
258
  }
259
 
260
  endif;
src/processors/comments_filter.php CHANGED
@@ -25,6 +25,12 @@ class ICWP_WPSF_Processor_CommentsFilter extends ICWP_WPSF_Processor_BaseWpsf {
25
  $oHumanSpamProcessor->run();
26
  }
27
 
 
 
 
 
 
 
28
  add_filter( 'pre_comment_approved', array( $this, 'doSetCommentStatus' ), 1 );
29
  add_filter( 'pre_comment_content', array( $this, 'doInsertCommentStatusExplanation' ), 1, 1 );
30
  add_filter( 'comment_notification_recipients', array( $this, 'doClearCommentNotificationEmail_Filter' ), 100, 1 );
25
  $oHumanSpamProcessor->run();
26
  }
27
 
28
+ if ( $this->getIsOption( 'enable_google_recaptcha', 'Y' ) ) {
29
+ require_once( dirname(__FILE__).ICWP_DS.'commentsfilter_googlerecaptcha.php' );
30
+ $oHumanSpamProcessor = new ICWP_WPSF_Processor_CommentsFilter_GoogleRecaptcha( $oFO );
31
+ $oHumanSpamProcessor->run();
32
+ }
33
+
34
  add_filter( 'pre_comment_approved', array( $this, 'doSetCommentStatus' ), 1 );
35
  add_filter( 'pre_comment_content', array( $this, 'doInsertCommentStatusExplanation' ), 1, 1 );
36
  add_filter( 'comment_notification_recipients', array( $this, 'doClearCommentNotificationEmail_Filter' ), 100, 1 );
src/processors/commentsfilter_antibotspam.php CHANGED
@@ -37,6 +37,15 @@ class ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam extends ICWP_WPSF_BaseDbPro
37
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getCommentsFilterTableName() );
38
  }
39
 
 
 
 
 
 
 
 
 
 
40
  /**
41
  * @param bool $fIfDoCheck
42
  * @return bool
@@ -62,16 +71,6 @@ class ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam extends ICWP_WPSF_BaseDbPro
62
 
63
  return $fIfDoCheck;
64
  }
65
-
66
- /**
67
- * Resets the object values to be re-used anew
68
- */
69
- public function init() {
70
- parent::init();
71
- $this->sCommentStatus = '';
72
- $this->sCommentStatusExplanation = '';
73
- $this->getUniqueCommentToken(); //ensures the necessary cookie is set early
74
- }
75
 
76
  /**
77
  */
@@ -498,17 +497,5 @@ class ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam extends ICWP_WPSF_BaseDbPro
498
  $sExplanation
499
  )." *]\n";
500
  }
501
-
502
- /**
503
- * This is hooked into a cron in the base class and overrides the parent method.
504
- * It'll delete everything older than 24hrs.
505
- */
506
- public function cleanupDatabase() {
507
- if ( !$this->getTableExists() ) {
508
- return;
509
- }
510
- $nTimeStamp = $this->time() - DAY_IN_SECONDS;
511
- $this->deleteAllRowsOlderThan( $nTimeStamp );
512
- }
513
  }
514
  endif;
37
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getCommentsFilterTableName() );
38
  }
39
 
40
+ /**
41
+ * Resets the object values to be re-used anew
42
+ */
43
+ public function init() {
44
+ parent::init();
45
+ $this->setAutoExpirePeriod( DAY_IN_SECONDS );
46
+ $this->getUniqueCommentToken(); //ensures the necessary cookie is set early
47
+ }
48
+
49
  /**
50
  * @param bool $fIfDoCheck
51
  * @return bool
71
 
72
  return $fIfDoCheck;
73
  }
 
 
 
 
 
 
 
 
 
 
74
 
75
  /**
76
  */
497
  $sExplanation
498
  )." *]\n";
499
  }
 
 
 
 
 
 
 
 
 
 
 
 
500
  }
501
  endif;
src/processors/commentsfilter_googlerecaptcha.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !class_exists( 'ICWP_WPSF_Processor_CommentsFilter_GoogleRecaptcha', false ) ):
4
+
5
+ require_once( dirname(__FILE__).ICWP_DS.'base_commentsfilter.php' );
6
+
7
+ class ICWP_WPSF_Processor_CommentsFilter_GoogleRecaptcha extends ICWP_WPSF_Processor_CommentsFilter_Base {
8
+
9
+ /**
10
+ */
11
+ public function run() {
12
+ /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oFO */
13
+ $oFO = $this->getFeatureOptions();
14
+ if ( !$this->loadDataProcessor()->getPhpSupportsNamespaces() || !$oFO->getIsGoogleRecaptchaReady() ) {
15
+ return;
16
+ }
17
+
18
+ parent::run();
19
+
20
+ add_action( 'wp_enqueue_scripts', array( $this, 'loadGoogleRecaptchaJs' ), 99 );
21
+ add_action( 'comment_form', array( $this, 'printGoogleRecaptchaCheck' ) );
22
+ }
23
+
24
+ public function loadGoogleRecaptchaJs() {
25
+ wp_register_script( 'google-recaptcha', 'https://www.google.com/recaptcha/api.js' );
26
+ wp_enqueue_script( 'google-recaptcha' );
27
+ }
28
+
29
+ /**
30
+ * @return string
31
+ */
32
+ public function printGoogleRecaptchaCheck_Filter() {
33
+ return $this->getGoogleRecaptchaHtml();
34
+ }
35
+
36
+ /**
37
+ */
38
+ public function printGoogleRecaptchaCheck() {
39
+ echo $this->getGoogleRecaptchaHtml();
40
+ }
41
+
42
+ /**
43
+ * @return string
44
+ */
45
+ protected function getGoogleRecaptchaHtml() {
46
+ /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oFO */
47
+ $oFO = $this->getFeatureOptions();
48
+ $sSiteKey = $oFO->getGoogleRecaptchaSiteKey();
49
+ return sprintf(
50
+ '<div class="g-recaptcha" data-sitekey="%s" style="margin: 10px 0;"></div>',
51
+ $sSiteKey
52
+ );
53
+ }
54
+
55
+ /**
56
+ * @param array $aCommentData
57
+ * @return array
58
+ */
59
+ public function doCommentChecking( $aCommentData ) {
60
+ parent::doCommentChecking( $aCommentData );
61
+
62
+ /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oFO */
63
+ $oFO = $this->getFeatureOptions();
64
+ if ( !$oFO->getIfDoCommentsCheck() ) {
65
+ return $aCommentData;
66
+ }
67
+
68
+ $sCaptchaResponse = $this->loadDataProcessor()->FetchPost( 'g-recaptcha-response' );
69
+
70
+ $bIsSpam = false;
71
+ $sStatKey = '';
72
+ $sExplanation = '';
73
+ if ( empty( $sCaptchaResponse ) ) {
74
+ $bIsSpam = true;
75
+ $sStatKey = 'empty';
76
+ $sExplanation = _wpsf__( 'Google Recaptcha was not submitted.' );
77
+ }
78
+ else {
79
+ $oRecaptcha = $this->loadGoogleRecaptcha()->getGoogleRecaptchaLib( $oFO->getGoogleRecaptchaSecretKey() );
80
+ $oResponse = $oRecaptcha->verify( $sCaptchaResponse, $this->human_ip() );
81
+ if ( empty( $oResponse ) || !$oResponse->isSuccess() ) {
82
+ $bIsSpam = true;
83
+ $sStatKey = 'failed';
84
+ $sExplanation = _wpsf__( 'Google Recaptcha verification failed.' );
85
+ }
86
+ }
87
+
88
+ // Now we check whether comment status is to completely reject and then we simply redirect to "home"
89
+
90
+ if ( $bIsSpam ) {
91
+ $this->doStatIncrement( sprintf( 'spam.recaptcha.%s', $sStatKey ) );
92
+ self::$sCommentStatus = $this->getOption( 'comments_default_action_spam_bot' );
93
+ $this->setCommentStatusExplanation( $sExplanation );
94
+
95
+ // We now black mark this IP
96
+ add_filter( $oFO->doPluginPrefix( 'ip_black_mark' ), '__return_true' );
97
+
98
+ if ( self::$sCommentStatus == 'reject' ) {
99
+ $oWp = $this->loadWpFunctionsProcessor();
100
+ $oWp->doRedirect( $oWp->getHomeUrl(), array(), true, false );
101
+ }
102
+ }
103
+ return $aCommentData;
104
+ }
105
+ }
106
+ endif;
src/processors/commentsfilter_humanspam.php CHANGED
@@ -2,41 +2,18 @@
2
 
3
  if ( !class_exists( 'ICWP_WPSF_Processor_CommentsFilter_HumanSpam', false ) ):
4
 
5
- require_once( dirname(__FILE__).ICWP_DS.'base_wpsf.php' );
6
 
7
- class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_BaseWpsf {
8
 
9
  const Spam_Blacklist_Source = 'https://raw.githubusercontent.com/splorp/wordpress-comment-blacklist/master/blacklist.txt';
10
 
11
- /**
12
- * @var array
13
- */
14
- private $aRawCommentData;
15
-
16
- /**
17
- * @var string
18
- */
19
- static protected $sSpamBlacklistFile;
20
-
21
- /**
22
- * @var string
23
- */
24
- protected $sCommentStatus = '';
25
-
26
- /**
27
- * @var string
28
- */
29
- protected $sCommentStatusExplanation = '';
30
-
31
  /**
32
  */
33
  public function run() {
34
  /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oFO */
35
  $oFO = $this->getFeatureOptions();
36
- add_filter( 'preprocess_comment', array( $this, 'doCommentChecking' ), 1, 1 );
37
  add_filter( $oFO->doPluginPrefix( 'if-do-comments-check' ), array( $this, 'getIfDoCommentsCheck' ) );
38
- add_filter( $oFO->doPluginPrefix( 'comments_filter_status' ), array( $this, 'getCommentStatus' ), 2 );
39
- add_filter( $oFO->doPluginPrefix( 'comments_filter_status_explanation' ), array( $this, 'getCommentStatusExplanation' ), 2 );
40
  }
41
 
42
  /**
@@ -66,56 +43,12 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
66
  return $fIfDoCheck;
67
  }
68
 
69
- /**
70
- * @param string $sKey
71
- * @return array|mixed|null
72
- */
73
- public function getRawCommentData( $sKey = '' ) {
74
- if ( !isset( $this->aRawCommentData ) ) {
75
- $this->aRawCommentData = array();
76
- }
77
- if ( !empty( $sKey ) ) {
78
- return isset( $this->aRawCommentData[$sKey] ) ? $this->aRawCommentData[$sKey] : null;
79
- }
80
- return $this->aRawCommentData;
81
- }
82
-
83
- /**
84
- * Resets the object values to be re-used anew
85
- */
86
- public function init() {
87
- parent::init();
88
- $this->sCommentStatus = '';
89
- $this->sCommentStatusExplanation = '';
90
- self::$sSpamBlacklistFile = $this->getFeatureOptions()->getResourcesDir().'spamblacklist.txt';
91
- }
92
-
93
- /**
94
- * A private plugin filter that lets us return up the newly set comment status.
95
- *
96
- * @param $sCurrentCommentStatus
97
- * @return string
98
- */
99
- public function getCommentStatus( $sCurrentCommentStatus ) {
100
- return empty( $sCurrentCommentStatus )? $this->sCommentStatus : $sCurrentCommentStatus;
101
- }
102
-
103
- /**
104
- * A private plugin filter that lets us return up the newly set comment status explanation
105
- *
106
- * @param $sCurrentCommentStatusExplanation
107
- * @return string
108
- */
109
- public function getCommentStatusExplanation( $sCurrentCommentStatusExplanation ) {
110
- return empty( $sCurrentCommentStatusExplanation )? $this->sCommentStatusExplanation : $sCurrentCommentStatusExplanation;
111
- }
112
-
113
  /**
114
  * @param array $aCommentData
115
  * @return array
116
  */
117
  public function doCommentChecking( $aCommentData ) {
118
- $this->aRawCommentData = $aCommentData;
119
 
120
  /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oFO */
121
  $oFO = $this->getFeatureOptions();
@@ -126,7 +59,7 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
126
  $this->doBlacklistSpamCheck( $aCommentData );
127
 
128
  // Now we check whether comment status is to completely reject and then we simply redirect to "home"
129
- if ( $this->sCommentStatus == 'reject' ) {
130
  $oWp = $this->loadWpFunctionsProcessor();
131
  $oWp->doRedirect( $oWp->getHomeUrl(), array(), true, false );
132
  }
@@ -163,8 +96,9 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
163
  */
164
  public function doBlacklistSpamCheck_Action( $sAuthor, $sEmail, $sUrl, $sComment, $sUserIp, $sUserAgent ) {
165
 
 
166
  // Check that we haven't already marked the comment through another scan, say GASP
167
- if ( !empty( $this->sCommentStatus ) || !$this->getIsOption('enable_comments_human_spam_filter', 'Y') ) {
168
  return;
169
  }
170
 
@@ -195,12 +129,11 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
195
  //mark as spam and exit;
196
  $this->doStatIncrement( sprintf( 'spam.human.%s', $sKey ) );
197
  $this->doStatHumanSpamWords( $sWord );
198
- $this->sCommentStatus = $this->getOption( 'comments_default_action_human_spam' );
199
- $this->setCommentStatusExplanation( sprintf( _wpsf__('Human SPAM filter found "%s" in "%s"' ), $sWord, $sKey ) );
200
 
201
  // We now black mark this IP
202
  add_filter( $this->getFeatureOptions()->doPluginPrefix( 'ip_black_mark' ), '__return_true' );
203
-
204
  break 2;
205
  }
206
  }
@@ -222,17 +155,18 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
222
  */
223
  protected function getSpamBlacklist() {
224
  $oFs = $this->loadFileSystemProcessor();
 
225
 
226
  // first, does the file exist? If not import
227
- if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
228
  $this->doSpamBlacklistImport();
229
  }
230
  // second, if it exists and it's older than 48hrs, update
231
- else if ( $this->time() - $oFs->getModifiedTime( self::$sSpamBlacklistFile ) > ( DAY_IN_SECONDS * 2 ) ) {
232
  $this->doSpamBlacklistUpdate();
233
  }
234
 
235
- $sList = $oFs->getFileContent( self::$sSpamBlacklistFile );
236
  return empty($sList)? '' : $sList;
237
  }
238
 
@@ -240,7 +174,7 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
240
  */
241
  protected function doSpamBlacklistUpdate() {
242
  $oFs = $this->loadFileSystemProcessor();
243
- $oFs->deleteFile( self::$sSpamBlacklistFile );
244
  $this->doSpamBlacklistImport();
245
  }
246
 
@@ -248,7 +182,8 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
248
  */
249
  protected function doSpamBlacklistImport() {
250
  $oFs = $this->loadFileSystemProcessor();
251
- if ( !$oFs->exists( self::$sSpamBlacklistFile ) ) {
 
252
 
253
  $sRawList = $this->doSpamBlacklistDownload();
254
 
@@ -268,7 +203,7 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
268
  }
269
 
270
  // save the list to disk for the future.
271
- $oFs->putFileContent( self::$sSpamBlacklistFile, $sList );
272
  }
273
  }
274
 
@@ -281,16 +216,10 @@ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_B
281
  }
282
 
283
  /**
284
- * @param $sExplanation
285
  */
286
- protected function setCommentStatusExplanation( $sExplanation ) {
287
- $this->sCommentStatusExplanation =
288
- '[* '.sprintf(
289
- _wpsf__( '%s plugin marked this comment as "%s".' ).' '._wpsf__( 'Reason: %s' ),
290
- $this->getController()->getHumanName(),
291
- ( $this->sCommentStatus == 0 ) ? _wpsf__('pending') : $this->sCommentStatus,
292
- $sExplanation
293
- )." *]\n";
294
  }
295
  }
296
  endif;
2
 
3
  if ( !class_exists( 'ICWP_WPSF_Processor_CommentsFilter_HumanSpam', false ) ):
4
 
5
+ require_once( dirname(__FILE__).ICWP_DS.'base_commentsfilter.php' );
6
 
7
+ class ICWP_WPSF_Processor_CommentsFilter_HumanSpam extends ICWP_WPSF_Processor_CommentsFilter_Base {
8
 
9
  const Spam_Blacklist_Source = 'https://raw.githubusercontent.com/splorp/wordpress-comment-blacklist/master/blacklist.txt';
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  */
13
  public function run() {
14
  /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oFO */
15
  $oFO = $this->getFeatureOptions();
 
16
  add_filter( $oFO->doPluginPrefix( 'if-do-comments-check' ), array( $this, 'getIfDoCommentsCheck' ) );
 
 
17
  }
18
 
19
  /**
43
  return $fIfDoCheck;
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  /**
47
  * @param array $aCommentData
48
  * @return array
49
  */
50
  public function doCommentChecking( $aCommentData ) {
51
+ parent::doCommentChecking( $aCommentData );
52
 
53
  /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oFO */
54
  $oFO = $this->getFeatureOptions();
59
  $this->doBlacklistSpamCheck( $aCommentData );
60
 
61
  // Now we check whether comment status is to completely reject and then we simply redirect to "home"
62
+ if ( self::$sCommentStatus == 'reject' ) {
63
  $oWp = $this->loadWpFunctionsProcessor();
64
  $oWp->doRedirect( $oWp->getHomeUrl(), array(), true, false );
65
  }
96
  */
97
  public function doBlacklistSpamCheck_Action( $sAuthor, $sEmail, $sUrl, $sComment, $sUserIp, $sUserAgent ) {
98
 
99
+ $sCurrentStatus = $this->getStatus();
100
  // Check that we haven't already marked the comment through another scan, say GASP
101
+ if ( !empty( $sCurrentStatus ) || !$this->getIsOption('enable_comments_human_spam_filter', 'Y') ) {
102
  return;
103
  }
104
 
129
  //mark as spam and exit;
130
  $this->doStatIncrement( sprintf( 'spam.human.%s', $sKey ) );
131
  $this->doStatHumanSpamWords( $sWord );
132
+ $this->setCommentStatus( $this->getOption( 'comments_default_action_human_spam' ) );
133
+ $this->setCommentStatusExplanation( sprintf( _wpsf__( 'Human SPAM filter found "%s" in "%s"' ), $sWord, $sKey ) );
134
 
135
  // We now black mark this IP
136
  add_filter( $this->getFeatureOptions()->doPluginPrefix( 'ip_black_mark' ), '__return_true' );
 
137
  break 2;
138
  }
139
  }
155
  */
156
  protected function getSpamBlacklist() {
157
  $oFs = $this->loadFileSystemProcessor();
158
+ $sBLFile = $this->getSpamBlacklistFile();
159
 
160
  // first, does the file exist? If not import
161
+ if ( !$oFs->exists( $sBLFile ) ) {
162
  $this->doSpamBlacklistImport();
163
  }
164
  // second, if it exists and it's older than 48hrs, update
165
+ else if ( $this->time() - $oFs->getModifiedTime( $sBLFile ) > ( DAY_IN_SECONDS * 2 ) ) {
166
  $this->doSpamBlacklistUpdate();
167
  }
168
 
169
+ $sList = $oFs->getFileContent( $sBLFile );
170
  return empty($sList)? '' : $sList;
171
  }
172
 
174
  */
175
  protected function doSpamBlacklistUpdate() {
176
  $oFs = $this->loadFileSystemProcessor();
177
+ $oFs->deleteFile( $this->getSpamBlacklistFile() );
178
  $this->doSpamBlacklistImport();
179
  }
180
 
182
  */
183
  protected function doSpamBlacklistImport() {
184
  $oFs = $this->loadFileSystemProcessor();
185
+ $sBLFile = $this->getSpamBlacklistFile();
186
+ if ( !$oFs->exists( $sBLFile ) ) {
187
 
188
  $sRawList = $this->doSpamBlacklistDownload();
189
 
203
  }
204
 
205
  // save the list to disk for the future.
206
+ $oFs->putFileContent( $sBLFile, $sList );
207
  }
208
  }
209
 
216
  }
217
 
218
  /**
219
+ * @return string
220
  */
221
+ protected function getSpamBlacklistFile() {
222
+ return $this->getFeatureOptions()->getResourcesDir() . 'spamblacklist.txt';
 
 
 
 
 
 
223
  }
224
  }
225
  endif;
src/processors/firewall.php CHANGED
@@ -438,6 +438,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_Firewall', false ) ):
438
  'txn_id',
439
  '_wp_http_referer',
440
  '_wp_original_http_referer',
 
441
  'url',
442
  'referredby',
443
  'redirect_to'
438
  'txn_id',
439
  '_wp_http_referer',
440
  '_wp_original_http_referer',
441
+ 'pwd',
442
  'url',
443
  'referredby',
444
  'redirect_to'
src/processors/ips.php CHANGED
@@ -22,6 +22,17 @@ if ( !class_exists( 'ICWP_WPSF_Processor_Ips', false ) ):
22
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getIpListsTableName() );
23
  }
24
 
 
 
 
 
 
 
 
 
 
 
 
25
  /**
26
  */
27
  public function run() {
@@ -670,22 +681,6 @@ if ( !class_exists( 'ICWP_WPSF_Processor_Ips', false ) ):
670
  return $this->getFeatureOptions()->getOptionsVo()->getOptDefault( 'ip_list_table_columns' );
671
  }
672
 
673
- /**
674
- * This is hooked into a cron in the base class and overrides the parent method.
675
- * It'll delete everything older than 24hrs.
676
- */
677
- public function cleanupDatabase() {
678
-
679
- if ( !$this->getTableExists() ) {
680
- return;
681
- }
682
-
683
- /** @var ICWP_WPSF_FeatureHandler_Ips $oFO */
684
- $oFO = $this->getFeatureOptions();
685
- $nSinceTimeToConsider = $this->time() - $oFO->getAutoExpireTime();
686
- $this->deleteAllRowsOlderThan( $nSinceTimeToConsider );
687
- }
688
-
689
  /**
690
  * @param int $nTimeStamp
691
  * @return bool|int
22
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getIpListsTableName() );
23
  }
24
 
25
+ /**
26
+ * Resets the object values to be re-used anew
27
+ */
28
+ public function init() {
29
+ parent::init();
30
+
31
+ /** @var ICWP_WPSF_FeatureHandler_Ips $oFO */
32
+ $oFO = $this->getFeatureOptions();
33
+ $this->setAutoExpirePeriod( $oFO->getAutoExpireTime() );
34
+ }
35
+
36
  /**
37
  */
38
  public function run() {
681
  return $this->getFeatureOptions()->getOptionsVo()->getOptDefault( 'ip_list_table_columns' );
682
  }
683
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
684
  /**
685
  * @param int $nTimeStamp
686
  * @return bool|int
src/processors/login_protect.php CHANGED
@@ -50,6 +50,10 @@ class ICWP_WPSF_Processor_LoginProtect extends ICWP_WPSF_Processor_BaseWpsf {
50
  $this->getProcessorTwoFactor()->run();
51
  }
52
 
 
 
 
 
53
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
54
  return true;
55
  }
@@ -167,6 +171,15 @@ class ICWP_WPSF_Processor_LoginProtect extends ICWP_WPSF_Processor_BaseWpsf {
167
  return $oProc;
168
  }
169
 
 
 
 
 
 
 
 
 
 
170
  /**
171
  * @return ICWP_WPSF_Processor_LoginProtect_Yubikey
172
  */
50
  $this->getProcessorTwoFactor()->run();
51
  }
52
 
53
+ if ( $oFO->getIsGoogleRecaptchaEnabled() ) {
54
+ $this->getProcessorGoogleRecaptcha()->run();
55
+ }
56
+
57
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
58
  return true;
59
  }
171
  return $oProc;
172
  }
173
 
174
+ /**
175
+ * @return ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha
176
+ */
177
+ protected function getProcessorGoogleRecaptcha() {
178
+ require_once( dirname(__FILE__).ICWP_DS.'loginprotect_googlerecaptcha.php' );
179
+ $oProc = new ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha( $this->getFeatureOptions() );
180
+ return $oProc;
181
+ }
182
+
183
  /**
184
  * @return ICWP_WPSF_Processor_LoginProtect_Yubikey
185
  */
src/processors/loginprotect_gasp.php CHANGED
@@ -99,9 +99,9 @@ class ICWP_WPSF_Processor_LoginProtect_Gasp extends ICWP_WPSF_Processor_BaseWpsf
99
  <style>
100
  #'.$sUniqElem.' {
101
  clear:both;
102
- border: 1px solid #888;
103
  padding: 6px 8px 4px 10px;
104
- margin: 0 0px 12px !important;
105
  border-radius: 2px;
106
  background-color: #f9f9f9;
107
  }
99
  <style>
100
  #'.$sUniqElem.' {
101
  clear:both;
102
+ border: 1px solid #dddddd;
103
  padding: 6px 8px 4px 10px;
104
+ margin: 0 0 12px !important;
105
  border-radius: 2px;
106
  background-color: #f9f9f9;
107
  }
src/processors/loginprotect_googlerecaptcha.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !class_exists( 'ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha', false ) ):
4
+
5
+ require_once( dirname(__FILE__).ICWP_DS.'base_wpsf.php' );
6
+
7
+ class ICWP_WPSF_Processor_LoginProtect_GoogleRecaptcha extends ICWP_WPSF_Processor_BaseWpsf {
8
+
9
+ /**
10
+ */
11
+ public function run() {
12
+ /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
13
+ $oFO = $this->getFeatureOptions();
14
+
15
+ if ( !$this->loadDataProcessor()->getPhpSupportsNamespaces()
16
+ || !$this->loadWpFunctionsProcessor()->getIsLoginUrl()
17
+ || !$oFO->getIsGoogleRecaptchaReady() ) {
18
+ return;
19
+ }
20
+
21
+ add_action( 'login_enqueue_scripts', array( $this, 'loadGoogleRecaptchaJs' ), 99 );
22
+
23
+ add_action( 'login_form', array( $this, 'printGoogleRecaptchaCheck' ) );
24
+ add_action( 'woocommerce_login_form', array( $this, 'printGoogleRecaptchaCheck' ) );
25
+ add_filter( 'login_form_middle', array( $this, 'printGoogleRecaptchaCheck_Filter' ) );
26
+
27
+ // after GASP but before email-based two-factor auth
28
+ add_filter( 'authenticate', array( $this, 'checkLoginForGoogleRecaptcha_Filter' ), 24, 3 );
29
+ }
30
+
31
+ public function loadGoogleRecaptchaJs() {
32
+ wp_register_script( 'google-recaptcha', 'https://www.google.com/recaptcha/api.js' );
33
+ wp_enqueue_script( 'google-recaptcha' );
34
+ }
35
+
36
+ /**
37
+ * @return string
38
+ */
39
+ public function printGoogleRecaptchaCheck_Filter() {
40
+ return $this->getGoogleRecaptchaHtml();
41
+ }
42
+
43
+ /**
44
+ */
45
+ public function printGoogleRecaptchaCheck() {
46
+ echo $this->getGoogleRecaptchaHtml();
47
+ }
48
+
49
+ /**
50
+ * @return string
51
+ */
52
+ protected function getGoogleRecaptchaHtml() {
53
+ /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
54
+ $oFO = $this->getFeatureOptions();
55
+ $sSiteKey = $oFO->getGoogleRecaptchaSiteKey();
56
+ return sprintf(
57
+ '%s<div class="g-recaptcha" data-sitekey="%s"></div>',
58
+ '<style>@media screen {
59
+ #rc-imageselect, .g-recaptcha iframe {transform:scale(0.90);-webkit-transform:scale(0.90);transform-origin:0 0;-webkit-transform-origin:0 0;}</style>',
60
+ $sSiteKey
61
+ );
62
+ }
63
+
64
+ /**
65
+ * @param WP_User $oUser
66
+ * @return WP_Error
67
+ */
68
+ public function checkLoginForGoogleRecaptcha_Filter( $oUser ) {
69
+ /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
70
+ $oFO = $this->getFeatureOptions();
71
+
72
+ $oError = new WP_Error();
73
+ $bIsUser = is_object( $oUser ) && ( $oUser instanceof WP_User );
74
+
75
+ if ( $bIsUser ) {
76
+
77
+ $sCaptchaResponse = $this->loadDataProcessor()->FetchPost( 'g-recaptcha-response' );
78
+
79
+ if ( empty( $sCaptchaResponse ) ) {
80
+ $oError->add( 'shield_google_recaptcha_empty', _wpsf__( 'Whoops.' )
81
+ .' '. _wpsf__( 'Google Recaptcha was not submitted.' ) );
82
+ $oUser = $oError;
83
+ }
84
+ else {
85
+ $oRecaptcha = $this->loadGoogleRecaptcha()->getGoogleRecaptchaLib( $oFO->getGoogleRecaptchaSecretKey() );
86
+ $oResponse = $oRecaptcha->verify( $sCaptchaResponse, $this->human_ip() );
87
+ if ( empty( $oResponse ) || !$oResponse->isSuccess() ) {
88
+ $oError->add( 'shield_google_recaptcha_failed', _wpsf__( 'Whoops.' )
89
+ .' '. _wpsf__( 'Google Recaptcha verification failed.' ) );
90
+ $oUser = $oError;
91
+ }
92
+ }
93
+ }
94
+ return $oUser;
95
+ }
96
+ }
97
+ endif;
src/processors/loginprotect_twofactorauth.php CHANGED
@@ -18,6 +18,14 @@ if ( !class_exists( 'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth', false ) ):
18
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getTwoFactorAuthTableName() );
19
  }
20
 
 
 
 
 
 
 
 
 
21
  /**
22
  */
23
  public function run() {
@@ -364,18 +372,6 @@ if ( !class_exists( 'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth', false ) ):
364
  return $this->getFeatureOptions()->getOptionsVo()->getOptDefault( 'two_factor_auth_table_columns' );
365
  }
366
 
367
- /**
368
- * This is hooked into a cron in the base class and overrides the parent method.
369
- * It'll delete everything older than 24hrs.
370
- */
371
- public function cleanupDatabase() {
372
- if ( !$this->getTableExists() ) {
373
- return;
374
- }
375
- $nTimeStamp = $this->time() - ( DAY_IN_SECONDS * $this->nDaysToKeepLog );
376
- $this->deleteAllRowsOlderThan( $nTimeStamp );
377
- }
378
-
379
  /**
380
  * @param int $nTimeStamp
381
  * @return bool|int
18
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getTwoFactorAuthTableName() );
19
  }
20
 
21
+ /**
22
+ * Resets the object values to be re-used anew
23
+ */
24
+ public function init() {
25
+ parent::init();
26
+ $this->setAutoExpirePeriod( DAY_IN_SECONDS * $this->nDaysToKeepLog );
27
+ }
28
+
29
  /**
30
  */
31
  public function run() {
372
  return $this->getFeatureOptions()->getOptionsVo()->getOptDefault( 'two_factor_auth_table_columns' );
373
  }
374
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  /**
376
  * @param int $nTimeStamp
377
  * @return bool|int
src/processors/plugin.php CHANGED
@@ -120,8 +120,8 @@ if ( !class_exists( 'ICWP_WPSF_Processor_Plugin', false ) ):
120
  'your_name' => _wpsf__( 'Your Name' ),
121
  'your_email' => _wpsf__( 'Your Email' ),
122
  'dismiss' => "No thanks, I'm not interested in such informative groups",
123
- 'summary' => 'The WordPress Simple Firewall team is running an initiative (with currently 1500+ members) to raise awareness of WordPress Security
124
- and to provide further help with the WordPress Simple Firewall plugin. Get Involved here:',
125
  ),
126
  'hrefs' => array(
127
  'form_action' => '//hostliketoast.us2.list-manage.com/subscribe/post?u=e736870223389e44fb8915c9a&id=0e1d527259'
120
  'your_name' => _wpsf__( 'Your Name' ),
121
  'your_email' => _wpsf__( 'Your Email' ),
122
  'dismiss' => "No thanks, I'm not interested in such informative groups",
123
+ 'summary' => 'The Shield security team is running an initiative (with currently 2000+ members) to raise awareness of WordPress Security
124
+ and to provide further help with the Shield security plugin. Get Involved here:',
125
  ),
126
  'hrefs' => array(
127
  'form_action' => '//hostliketoast.us2.list-manage.com/subscribe/post?u=e736870223389e44fb8915c9a&id=0e1d527259'
src/processors/support.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( !class_exists('ICWP_WPSF_Processor_Support') ):
4
+
5
+ require_once( dirname(__FILE__).ICWP_DS.'base.php' );
6
+
7
+ class ICWP_WPSF_Processor_Support extends ICWP_WPSF_Processor_Base {
8
+
9
+ /**
10
+ */
11
+ public function run() {
12
+ }
13
+ }
14
+
15
+ endif;
src/processors/user_management.php CHANGED
@@ -50,6 +50,7 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
50
  /**
51
  * Only show Go To Admin link for Authors and above.
52
  *
 
53
  * @return string
54
  * @throws Exception
55
  */
@@ -60,8 +61,8 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
60
  $oFO = $this->getFeatureOptions();
61
  if ( $oFO->getIsUserSessionsManagementEnabled() && $this->getProcessorSessions()->getCurrentUserHasValidSession() ) {
62
  $sMessage = sprintf(
63
- '<p class="message">%s<br />%s<hr/></p>',
64
- _wpsf__( "It looks like you're already logged-in." ),
65
  ( $oWpUsers->getCurrentUserLevel() >= 2 ) ? sprintf( '<a href="%s">%s</a>', $this->loadWpFunctionsProcessor()->getUrl_WpAdmin(), _wpsf__( "Go To Admin" ) . ' &rarr;' ) : ''
66
  ).$sMessage;
67
  }
50
  /**
51
  * Only show Go To Admin link for Authors and above.
52
  *
53
+ * @param string $sMessage
54
  * @return string
55
  * @throws Exception
56
  */
61
  $oFO = $this->getFeatureOptions();
62
  if ( $oFO->getIsUserSessionsManagementEnabled() && $this->getProcessorSessions()->getCurrentUserHasValidSession() ) {
63
  $sMessage = sprintf(
64
+ '<p class="message">%s<br />%s</p>',
65
+ _wpsf__( "It appears you're already logged-in." ).sprintf( ' <span style="white-space: nowrap">(%s)</span>', $oWpUsers->getCurrentWpUser()->get('user_login') ),
66
  ( $oWpUsers->getCurrentUserLevel() >= 2 ) ? sprintf( '<a href="%s">%s</a>', $this->loadWpFunctionsProcessor()->getUrl_WpAdmin(), _wpsf__( "Go To Admin" ) . ' &rarr;' ) : ''
67
  ).$sMessage;
68
  }
src/processors/usermanagement_sessions.php CHANGED
@@ -23,6 +23,14 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_BaseDbProces
23
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getUserSessionsTableName() );
24
  }
25
 
 
 
 
 
 
 
 
 
26
  public function run() {
27
 
28
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
@@ -462,18 +470,5 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_BaseDbProces
462
 
463
  return $this->selectCustom( $sQuery );
464
  }
465
-
466
- /**
467
- * This is hooked into a cron in the base class and overrides the parent method.
468
- *
469
- * It'll delete everything older than 24hrs.
470
- */
471
- public function cleanupDatabase() {
472
- if ( !$this->getTableExists() ) {
473
- return;
474
- }
475
- $nTimeStamp = $this->time() - (DAY_IN_SECONDS * $this->nDaysToKeepLog);
476
- $this->deleteAllRowsOlderThan( $nTimeStamp );
477
- }
478
  }
479
  endif;
23
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getUserSessionsTableName() );
24
  }
25
 
26
+ /**
27
+ * Resets the object values to be re-used anew
28
+ */
29
+ public function init() {
30
+ parent::init();
31
+ $this->setAutoExpirePeriod( DAY_IN_SECONDS * $this->nDaysToKeepLog );
32
+ }
33
+
34
  public function run() {
35
 
36
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
470
 
471
  return $this->selectCustom( $sQuery );
472
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  }
474
  endif;
templates/html/plugin_badge.html CHANGED
@@ -58,7 +58,7 @@
58
  </style>
59
  <div id="icwpWpsfSiteBadge">
60
  <a id="icwpWpsfCloseButton" onclick="getElementById('icwpWpsfSiteBadge').remove();">x</a>
61
- <a href="http://icwp.io/wpsecurityfirewall" target="_blank" title="WordPress Security Firewall">
62
  <img src="%s" alt="%s Logo" /> <div class="badge-text">This Site Is Protected By <span style="font-style: italic;">The</span><br/>%s &rarr;</div>
63
  </a>
64
  </div>
58
  </style>
59
  <div id="icwpWpsfSiteBadge">
60
  <a id="icwpWpsfCloseButton" onclick="getElementById('icwpWpsfSiteBadge').remove();">x</a>
61
+ <a href="http://icwp.io/wpsecurityfirewall" target="_blank" title="Shield">
62
  <img src="%s" alt="%s Logo" /> <div class="badge-text">This Site Is Protected By <span style="font-style: italic;">The</span><br/>%s &rarr;</div>
63
  </a>
64
  </div>
templates/php/feature-support.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( false && $has_premium_support ) : ?>
2
+
3
+ <div class="row">
4
+ <div class="span12">
5
+ <h2>Shield Pro Support</h2>
6
+ <p>
7
+ You currently have full access to Shield Pro and support from the iControlWP team.
8
+ </p>
9
+ <p>
10
+ Thank you for supporting us!
11
+ </p>
12
+ <p>
13
+ <a href="<?php echo $aHrefs['support_centre_sso']; ?>" class="btn" target="_blank">Launch My Support Centre</a>
14
+ </p>
15
+ </div>
16
+ </div>
17
+
18
+ <?php else : ?>
19
+
20
+ <div class="row">
21
+ <div class="span6 shield-free-block">
22
+ <h2>Shield Free</h2>
23
+ <p>
24
+ We offer Shield as-is without business-grade support.
25
+ </p>
26
+ <p>
27
+ <span style="font-style: italic">You have access to all the features in the plugin without any restriction.</span>
28
+ </p>
29
+ <p>
30
+ But if you manage many websites, you need support, or you just want to give back,
31
+ we ask that you go Pro and support future development of your WordPress site security.
32
+ </p>
33
+ <p>
34
+ We currently provide Shield Pro to all iControlWP clients. This means that you not only benefit from
35
+ centralized WordPress management and daily, automated offsite backups, you also get the gain from the huge
36
+ advantages of central WordPress security.
37
+ </p>
38
+ <p>
39
+ With your ongoing support, we plan to make WordPress security centralized and easier than ever - no more
40
+ individual on-site plugin management. You'll be able to finally control website security from a central control panel.
41
+ </p>
42
+ <p>
43
+ It's coming... you can be a part of the journey and be more secure than ever.
44
+ </p>
45
+ <p style="font-weight: bolder;">
46
+ Dare to believe in better. We do! :D
47
+ </p>
48
+ <p>
49
+ <a href="<?php echo $aHrefs['shield_pro_url']; ?>" class="btn btn-success btn-large" target="_blank">Go Pro!</a>
50
+ <br/><a style="float:right" href="<?php echo $aHrefs['shield_pro_more_info_url']; ?>" class="" target="_blank">Learn More</a>
51
+ </p>
52
+ </div>
53
+ </div>
54
+
55
+ <?php endif;
templates/php/index_header.php CHANGED
@@ -14,9 +14,5 @@ include_once( $sBaseDirName.'widgets'.ICWP_DS.'icwp_widgets.php' ); ?>
14
  </h2>
15
  </div>
16
  <?php if ( isset( $bShowStateSummary ) && $bShowStateSummary ) : ?>
17
- <div class="row">
18
- <div class="span12">
19
- <?php include_once( $sBaseDirName.'snippets'.ICWP_DS.'state_summary.php' ); ?>
20
- </div>
21
- </div>
22
  <?php endif; ?>
14
  </h2>
15
  </div>
16
  <?php if ( isset( $bShowStateSummary ) && $bShowStateSummary ) : ?>
17
+ <?php include_once( $sBaseDirName.'snippets'.ICWP_DS.'state_summary.php' ); ?>
 
 
 
 
18
  <?php endif; ?>
templates/php/notices/rate-plugin.php CHANGED
@@ -6,7 +6,7 @@
6
  <div class="notice-content">
7
  <h3>Would you like show us your support? We need only your words &hellip;</h3>
8
 
9
- <p>The authors of the Simple Firewall plugin need your help to spread the word about this Firewall plugin.</p>
10
 
11
  <p>Simply by talking about our plugin to other people in the community about how effective it has been for your site security, you lend us your
12
  incredible support.</p>
6
  <div class="notice-content">
7
  <h3>Would you like show us your support? We need only your words &hellip;</h3>
8
 
9
+ <p>The authors of the Shield plugin need your help to spread the word about this Security plugin.</p>
10
 
11
  <p>Simply by talking about our plugin to other people in the community about how effective it has been for your site security, you lend us your
12
  incredible support.</p>
templates/php/snippets/icwp_options_helper.php CHANGED
@@ -6,7 +6,7 @@ function printOptionsPageHeader( $insSection = '' ) {
6
  $sLinkedIcwp = '<a href="http://icwp.io/3a" target="_blank">iControlWP</a>';
7
  echo '<div class="page-header">';
8
  echo '<h2><a id="pluginlogo_32" class="header-icon32" href="http://icwp.io/2k" target="_blank"></a>';
9
- $sBaseTitle = sprintf( _wpsf__( 'WordPress Simple Firewall (from %s)' ), $sLinkedIcwp );
10
  if ( !empty($insSection) ) {
11
  echo sprintf( '%s :: %s', $insSection, $sBaseTitle );
12
  }
6
  $sLinkedIcwp = '<a href="http://icwp.io/3a" target="_blank">iControlWP</a>';
7
  echo '<div class="page-header">';
8
  echo '<h2><a id="pluginlogo_32" class="header-icon32" href="http://icwp.io/2k" target="_blank"></a>';
9
+ $sBaseTitle = sprintf( _wpsf__( 'Shield (from %s)' ), $sLinkedIcwp );
10
  if ( !empty($insSection) ) {
11
  echo sprintf( '%s :: %s', $insSection, $sBaseTitle );
12
  }
templates/php/snippets/state_summary.php CHANGED
@@ -4,12 +4,14 @@ if ( empty($aSummaryData) ) {
4
  } ?>
5
 
6
  <div class="row-fluid feature-summary-blocks">
7
- <div class="span1"></div>
8
  <?php foreach( $aSummaryData as $nKey => $aSummary ) : ?>
9
- <div class="span1 state-<?php echo $aSummary['enabled'] ? 'on' : 'off'; ?>" id="feature-<?php echo $aSummary['slug']; ?>" >
10
- <a class="" <?php echo sprintf( 'href="%s"', $aSummary['href'] ) ;?> title="<?php echo $aSummary['name']; ?> : <?php echo $aSummary['enabled'] ? $strings['on'] : $strings['off']; ?>" >
11
- <div class="feature-icon span3"></div>
12
- </a>
13
- </div>
 
 
 
14
  <?php endforeach; ?>
15
  </div>
4
  } ?>
5
 
6
  <div class="row-fluid feature-summary-blocks">
 
7
  <?php foreach( $aSummaryData as $nKey => $aSummary ) : ?>
8
+ <div class="span1 summary-state state-<?php echo $aSummary['enabled'] ? 'on' : 'off'; ?> <?php echo $aSummary['active'] ? 'active-feature' : ''; ?> " id="feature-<?php echo $aSummary['slug']; ?>" >
9
+ <a class="feature-icon span3"
10
+ <?php echo sprintf( 'href="%s"', $aSummary['href'] ) ;?>
11
+ title="<?php echo $aSummary['name']; ?> : <?php echo $aSummary['enabled'] ? $strings['on'] : $strings['off']; ?>"
12
+ style="display: block; text-align: center; width: 100%;"
13
+ ></a>
14
+ <p><?php echo $aSummary['menu_title']; ?></p>
15
+ </div>
16
  <?php endforeach; ?>
17
  </div>