Shield Security for WordPress - Version 6.2.0

Version Description

  • Current Release = Released: 31st January, 2018 - Release Notes

  • (v.0) IMPROVED: Major overhaul of the Shield User Sessions system.

  • (v.0) IMPROVED: Link the Security Admin authentication with the new Sessions system.

  • (v.0) IMPROVED: Major overhaul to plugin's user meta data storage, limiting to a single DB entry for all data.

  • (v.0) ADDED: [PRO] Ability to increase frequency of file system scans up to once every hour.

  • (v.0) ADDED: [PRO] Add a remember me option, allowing users to skip Multi-factor authentication for a set number of days.

Download this release

Release Info

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

Code changes from version 6.1.1 to 6.2.0

Files changed (111) hide show
  1. icwp-plugin-controller.php +10 -6
  2. icwp-wpsf.php +1 -1
  3. plugin-spec.php +2 -1
  4. readme.txt +52 -20
  5. resources/css/global-plugin.css +55 -39
  6. resources/css/plugin.css +10 -10
  7. resources/css/wizard.css +10 -0
  8. resources/js/global-plugin.js +1 -0
  9. src/common/Components/Tables/SessionsTable.php +1 -1
  10. src/common/icwp-data.php +7 -0
  11. src/common/icwp-usermeta.php +118 -0
  12. src/common/icwp-wpcron.php +44 -9
  13. src/common/icwp-wpdb.php +1 -1
  14. src/common/icwp-wpfunctions.php +0 -101
  15. src/common/lib/composer.lock +5 -5
  16. src/common/lib/vendor/composer/installed.json +70 -70
  17. src/common/lib/vendor/nesbot/carbon/.php_cs.dist +0 -57
  18. src/common/lib/vendor/nesbot/carbon/LICENSE +0 -19
  19. src/common/lib/vendor/nesbot/carbon/readme.md +0 -92
  20. src/common/lib/vendor/symfony/polyfill-mbstring/LICENSE +0 -19
  21. src/common/lib/vendor/symfony/translation/Dumper/FileDumper.php +1 -1
  22. src/common/lib/vendor/symfony/translation/LICENSE +1 -1
  23. src/common/lib/vendor/symfony/translation/Loader/XliffFileLoader.php +5 -1
  24. src/common/lib/vendor/symfony/translation/Translator.php +1 -1
  25. src/common/lib/vendor/symfony/translation/Writer/TranslationWriter.php +1 -1
  26. src/common/wp-admin-notices.php +40 -16
  27. src/common/wp-users.php +39 -2
  28. src/config/feature-admin_access_restriction.php +0 -1
  29. src/config/feature-hack_protect.php +56 -10
  30. src/config/feature-ips.php +1 -1
  31. src/config/feature-login_protect.php +12 -11
  32. src/config/feature-plugin.php +8 -3
  33. src/config/feature-sessions.php +63 -0
  34. src/config/feature-support.php +0 -48
  35. src/config/feature-user_management.php +5 -15
  36. src/features/admin_access_restriction.php +81 -44
  37. src/features/base.php +108 -97
  38. src/features/base_wpsf.php +53 -24
  39. src/features/hack_protect.php +67 -13
  40. src/features/login_protect.php +71 -7
  41. src/features/plugin.php +1 -9
  42. src/features/sessions.php +93 -0
  43. src/features/support.php +0 -118
  44. src/features/user_management.php +33 -14
  45. src/processors/admin_access_restriction.php +57 -35
  46. src/processors/base.php +44 -31
  47. src/processors/base_plugin.php +20 -18
  48. src/processors/comments_filter.php +1 -0
  49. src/processors/hack_protect.php +1 -1
  50. src/processors/hackprotect_corechecksumscan.php +22 -18
  51. src/processors/hackprotect_filecleanerscan.php +12 -16
  52. src/processors/ips.php +5 -5
  53. src/processors/login_protect.php +9 -4
  54. src/processors/loginprotect_googleauthenticator.php +9 -9
  55. src/processors/loginprotect_intent.php +97 -69
  56. src/processors/loginprotect_intent_base.php +56 -26
  57. src/processors/loginprotect_twofactorauth.php +11 -11
  58. src/processors/plugin.php +9 -4
  59. src/processors/plugin_tracking.php +5 -5
  60. src/processors/sessions.php +294 -0
  61. src/processors/statistics_reporting.php +1 -1
  62. src/processors/support.php +0 -15
  63. src/processors/user_management.php +17 -62
  64. src/processors/usermanagement_sessions.php +81 -340
  65. src/query/ICWP_WPSF_SessionVO.php +95 -0
  66. src/query/base.php +29 -0
  67. src/query/sessions_create.php +37 -0
  68. src/query/sessions_retrieve.php +73 -0
  69. src/query/sessions_terminate.php +43 -0
  70. src/query/sessions_update.php +70 -0
  71. src/query/statistics_base.php +4 -4
  72. src/query/statistics_consolidation.php +1 -1
  73. src/query/statistics_reporting.php +1 -1
  74. src/wizards/base_wpsf.php +1 -2
  75. src/wizards/hack_protect.php +2 -2
  76. src/wizards/plugin.php +114 -71
  77. templates/php/feature-default.php +3 -4
  78. templates/php/index_header.php +2 -2
  79. templates/php/notices/admin-notice-template.php +16 -4
  80. templates/php/notices/allow-tracking.php +16 -13
  81. templates/php/notices/email-verification-sent.php +2 -1
  82. templates/php/notices/override-forceoff.php +1 -1
  83. templates/php/notices/php54_version_warning.php +0 -1
  84. templates/php/notices/plugin-update-available.php +1 -1
  85. templates/php/notices/rate-plugin.php +10 -52
  86. templates/php/notices/translate-plugin.php +0 -1
  87. templates/php/notices/visitor-whitelisted.php +1 -1
  88. templates/php/notices/wizard_welcome.php +6 -46
  89. templates/php/page/login_intent.php +13 -1
  90. templates/php/snippets/admin_access_login.php +2 -2
  91. templates/php/snippets/icwp_options_helper.php +0 -172
  92. templates/php/snippets/module-help-login_protect.php +2 -1
  93. templates/php/snippets/options_form.php +77 -79
  94. templates/php/subfeature-access_restricted.php +17 -8
  95. templates/twig/features/feature-base.twig +1 -1
  96. templates/twig/features/feature-default.twig +1 -1
  97. templates/twig/features/subfeature-access_restricted.twig +3 -3
  98. templates/twig/snippets/options_form.twig +4 -4
  99. templates/twig/snippets/user_sessions.twig +0 -2
  100. templates/twig/wizard/slides/importexport/import.twig +1 -1
  101. templates/twig/wizard/slides/mfa/authga.twig +4 -4
  102. templates/twig/wizard/slides/mfa/multiselect.twig +2 -2
  103. templates/twig/wizard/slides/ufc/config.twig +4 -3
  104. templates/twig/wizard/slides/wcf/config.twig +3 -2
  105. templates/twig/wizard/slides/welcome/admin_access_restriction.twig +1 -1
  106. templates/twig/wizard/slides/welcome/audit_trail.twig +11 -9
  107. templates/twig/wizard/slides/welcome/comments_filter.twig +12 -10
  108. templates/twig/wizard/slides/welcome/ip_detect.twig +3 -0
  109. templates/twig/wizard/slides/welcome/ips.twig +14 -18
  110. templates/twig/wizard/slides/welcome/login_protect.twig +11 -11
  111. templates/twig/wizard/slides/welcome/optin.twig +10 -10
icwp-plugin-controller.php CHANGED
@@ -1053,10 +1053,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1053
  return false;
1054
  }
1055
 
1056
- $aFormSubmitOptions = array(
1057
- $this->doPluginOptionPrefix( 'plugin_form_submit' ),
1058
- 'icwp_link_action'
1059
- );
1060
 
1061
  $oDp = $this->loadDataProcessor();
1062
  foreach ( $aFormSubmitOptions as $sOption ) {
@@ -1337,6 +1334,13 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1337
  return self::$sRootFile;
1338
  }
1339
 
 
 
 
 
 
 
 
1340
  /**
1341
  * @return string
1342
  */
@@ -1435,7 +1439,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1435
  /**
1436
  */
1437
  public function clearSession() {
1438
- $this->loadDataProcessor()->setDeleteCookie( $this->getPluginPrefix() );
1439
  self::$sSessionId = null;
1440
  }
1441
 
@@ -1455,7 +1459,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1455
  */
1456
  public function getSessionId( $bSetIfNeeded = true ) {
1457
  if ( empty( self::$sSessionId ) ) {
1458
- self::$sSessionId = $this->loadDataProcessor()->FetchCookie( $this->getPluginPrefix(), '' );
1459
  if ( empty( self::$sSessionId ) && $bSetIfNeeded ) {
1460
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1461
  $this->setSessionCookie();
1053
  return false;
1054
  }
1055
 
1056
+ $aFormSubmitOptions = array( 'plugin_form_submit', 'icwp_link_action' );
 
 
 
1057
 
1058
  $oDp = $this->loadDataProcessor();
1059
  foreach ( $aFormSubmitOptions as $sOption ) {
1334
  return self::$sRootFile;
1335
  }
1336
 
1337
+ /**
1338
+ * @return int
1339
+ */
1340
+ public function getReleaseTimestamp() {
1341
+ return $this->getPluginSpec_Property( 'release_timestamp' );
1342
+ }
1343
+
1344
  /**
1345
  * @return string
1346
  */
1439
  /**
1440
  */
1441
  public function clearSession() {
1442
+ $this->loadDP()->setDeleteCookie( $this->getPluginPrefix() );
1443
  self::$sSessionId = null;
1444
  }
1445
 
1459
  */
1460
  public function getSessionId( $bSetIfNeeded = true ) {
1461
  if ( empty( self::$sSessionId ) ) {
1462
+ self::$sSessionId = $this->loadDP()->FetchCookie( $this->getPluginPrefix(), '' );
1463
  if ( empty( self::$sSessionId ) && $bSetIfNeeded ) {
1464
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1465
  $this->setSessionCookie();
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: http://icwp.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 6.1.1
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: iControlWP
3
  * Plugin Name: Shield Security
4
  * Plugin URI: http://icwp.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 6.2.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: iControlWP
plugin-spec.php CHANGED
@@ -1,6 +1,7 @@
1
  {
2
  "properties": {
3
- "version": "6.1.1",
 
4
  "slug_parent": "icwp",
5
  "slug_plugin": "wpsf",
6
  "human_name": "Shield",
1
  {
2
  "properties": {
3
+ "version": "6.2.0",
4
+ "release_timestamp": 1517390273,
5
  "slug_parent": "icwp",
6
  "slug_plugin": "wpsf",
7
  "human_name": "Shield",
readme.txt CHANGED
@@ -3,15 +3,32 @@ Contributors: onedollarplugin, 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, protect, spam, scan, recaptcha, two-factor authentication, login, 2FA, ithemes, wordfence, better wp security, all-in-one, lockdown, hack
7
  Requires at least: 3.5.0
8
  Tested up to: 4.9
9
- Stable tag: 6.1.1
10
 
11
- Protect your reputation, your customers' reputation, and your WordPress sites for free with Shield - the most powerful security system for WordPress
12
 
13
  == Description ==
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  > <strong>Don't Leave Your Site At Risk</strong><br />
16
  > If your site is vulnerable to attack, you're putting your business and your reputation at serious risk. Getting hacked can mean you're locked out of your site, client data stolen, your website defaced or offline, and Google *will* penalise you.
17
  >
@@ -24,19 +41,20 @@ Protect your reputation, your customers' reputation, and your WordPress sites fo
24
 
25
  = The New Shield Pro =
26
 
27
- As of 23rd November 2017, Shield Security now has a Pro version. But, it's important to know that anything we consider standard website security *will always be free* - no upgrade necessary.
28
 
29
- For the equivalent of just $1/month:
30
 
31
  1. Exclusive Pro customer email support.
32
- 1. Support for working with 3rd party plugins e.g. Woocommerce and Easy Digital Downloads, BuddyPress.
 
 
 
33
  1. Exclusive early access to new security features
34
  1. Text customisations for visitors.
35
  1. No manual Pro plugin downloads - we handle this all for you automatically.
36
- 1. Plugin Vulnerability Scanner.
37
- 1. (coming soon) Import/Export of options across sites.
38
- 1. (coming soon) Improved Audit Trail logging
39
- 1. (coming soon) Improved performance
40
  1. (coming soon) Statistics and Reporting
41
  1. (coming soon) Select individual automatic plugin updates
42
 
@@ -44,7 +62,7 @@ Learn more and go Pro at [our One Dollar Plugin store](http://icwp.io/ab).
44
 
45
  = Our Mission =
46
 
47
- All the wonderful features of how we protect you and your site are set out below in detail, but there are a few things about us, that you should know first:
48
 
49
  * We're on a mission to liberate people who manage websites from unnecessarily repetitive work, and by 2022 we want to
50
  be saving our clients over 62.5 million hours per year (and we'd love you to join us in our quest)
@@ -338,21 +356,35 @@ Technical support, and some newer options and features will not be available to
338
 
339
  You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is available to premium clients only.
340
 
341
- = 6.1.1 Latest Release =
342
- *Released: 17th January, 2018*
343
 
344
- * **(v.1)** FIXED: Verify link missing from the two-factor authentication verification email.
 
 
 
 
345
 
346
- = 6.1.0 Series =
 
 
 
 
 
 
 
 
 
347
  *Released: 15th January, 2018* - [Release Notes](http://icwp.io/ay)
348
 
 
349
  * **(v.0)** ADDED: 3x more Shield Wizards: Multi-factor Authentication, Core File Scanning, Unrecognised File Scanning.
350
  * **(v.0)** ADDED: You can now use regular expressions for file exclusions in the 'Unrecognised File Scanner'.
351
  * **(v.0)** CHANGED: File Scanner email notifications now link to the appropriate scanner wizard directly.
352
  * **(v.0)** IMPROVED: Plugin options pages restyling.
353
  * **(v.0)** IMPROVED: Plugin refactoring and improvements.
354
 
355
- = 6.0.0 Series =
356
  *Released: 18th December, 2017*
357
 
358
  * **(v.0)** ADDED: All-new Shield Welcome and Setup Wizard - more helpful guided wizards to come.
@@ -360,7 +392,7 @@ You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is avai
360
  * **(v.0)** ADDED: [**PRO**] In conjunction with import/export - Shield Security Network: automated options syncing.
361
  * **(v.0)** CHANGED: Going forward, new features and options will [support only PHP 5.4+](http://icwp.io/au). Existing features will remain unaffected.
362
 
363
- = 5.20.0 Series =
364
  *Released: 11th December, 2017*
365
 
366
  * **(v.0)** IMPROVED: [**PRO**] Audit Trail length are configurable. Length for free is 50 entries (the original unpaginated limit)
@@ -370,7 +402,7 @@ You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is avai
370
  * **(v.0)** IMPROVED: Audit Trails are now ajax-paginated. You can browse through all your audit trail entries
371
  * **(v.0)** IMPROVED: User session tables are also ajax-paginated.
372
 
373
- = 5.19.0 Series =
374
  *Released: 4th December, 2017*
375
 
376
  * **(v.1)** FIXED: Plugin Vulnerabilities scan for premium plugins.
@@ -379,14 +411,14 @@ You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is avai
379
  * **(v.0)** ADDED: [**PRO**] Support for Multi-Factor Authentication for WooCommerce and other 3rd party plugins.
380
  * **(v.0)** ADDED: [**PRO**] Bot-protection/Google reCAPTCHA support for BuddyPress register pages.
381
 
382
- = 5.18.0 Series =
383
  *Released: 27th November, 2017*
384
 
385
  * **(v.0)** ADDED: [**PRO**] Invisible Google reCAPTCHA option.
386
  * **(v.0)** ADDED: [**PRO**] Support for Google reCAPTCHA themes - light and dark.
387
  * **(v.0)** IMPROVEMENT: Google reCAPTCHA is more reliable and configurable.
388
 
389
- = 5.17.0 Series =
390
  *Released: 23rd November, 2017*
391
 
392
  * **(v.0)** ADDED: Shield Security goes Pro! Added new options and extras to premium clients.
3
  Donate link: http://icwp.io/q
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
+ Tags: security, all in one, protect, spam, scan, recaptcha, two-factor authentication, login, 2FA, ithemes, wordfence, better wp security, all-in-one, lockdown, hack
7
  Requires at least: 3.5.0
8
  Tested up to: 4.9
9
+ Stable tag: 6.2.0
10
 
11
+ Free All-In-One Protection for your data, reputation, and users on your WordPress sites - the Highest-Rated Security Plugin for WordPress
12
 
13
  == Description ==
14
 
15
+ Shield handles it all for you:
16
+
17
+ * Easy-To-Use Guided Setup Wizards
18
+ * Login Protection against bots (including Limit Login Attempts)
19
+ * Automatic IP Black List
20
+ * 2-Factor Authentication
21
+ * Comments SPAM - block 100% of bot spam.
22
+ * Audit Trail & Logging
23
+ * reCAPTCHA
24
+ * Firewall
25
+ * Security Admin Users
26
+ * Core file scanners
27
+ * Block REST API / XML-RPC
28
+ * HTTP Headers
29
+ * Automatic Updates Control
30
+ * and much, much more...
31
+
32
  > <strong>Don't Leave Your Site At Risk</strong><br />
33
  > If your site is vulnerable to attack, you're putting your business and your reputation at serious risk. Getting hacked can mean you're locked out of your site, client data stolen, your website defaced or offline, and Google *will* penalise you.
34
  >
41
 
42
  = The New Shield Pro =
43
 
44
+ From November 2017, Shield Security now has a Pro version.
45
 
46
+ For just $1/month:
47
 
48
  1. Exclusive Pro customer email support.
49
+ 1. Plugin Vulnerability Scanner.
50
+ 1. Import/Export of options across sites.
51
+ 1. Protect WooCommerce login and user registration, along with other 3rd party plugins e.g. Easy Digital Downloads, BuddyPress.
52
+ 1. Improved Audit Trail logging
53
  1. Exclusive early access to new security features
54
  1. Text customisations for visitors.
55
  1. No manual Pro plugin downloads - we handle this all for you automatically.
56
+ 1. (coming soon) White Labelling
57
+ 1. (coming soon) Improved performance
 
 
58
  1. (coming soon) Statistics and Reporting
59
  1. (coming soon) Select individual automatic plugin updates
60
 
62
 
63
  = Our Mission =
64
 
65
+ All the great features of how Shield protects your sites and your customers data are set out below in detail, but there are a few things about us, that you should know first:
66
 
67
  * We're on a mission to liberate people who manage websites from unnecessarily repetitive work, and by 2022 we want to
68
  be saving our clients over 62.5 million hours per year (and we'd love you to join us in our quest)
356
 
357
  You can [go Pro for just $1/month](http://icwp.io/aa). Technical support is available to premium clients only.
358
 
359
+ = 6.2.0 - Current Release =
360
+ *Released: 31st January, 2018* - [Release Notes](http://icwp.io/b6)
361
 
362
+ * **(v.0)** IMPROVED: Major overhaul of the Shield User Sessions system.
363
+ * **(v.0)** IMPROVED: Link the Security Admin authentication with the new Sessions system.
364
+ * **(v.0)** IMPROVED: Major overhaul to plugin's user meta data storage, limiting to a single DB entry for all data.
365
+ * **(v.0)** ADDED: [**PRO**] Ability to [increase frequency](http://icwp.io/b7) of file system scans up to once every hour.
366
+ * **(v.0)** ADDED: [**PRO**] Add a [remember me option](http://icwp.io/b8), allowing users to skip Multi-factor authentication for a set number of days.
367
 
368
+ = 6.2 Series =
369
+ *Released: 31st January, 2018* - [Release Notes](http://icwp.io/b6)
370
+
371
+ * **(v.0)** IMPROVED: Major overhaul of the Shield User Sessions system.
372
+ * **(v.0)** IMPROVED: Link the Security Admin authentication with the new Sessions system.
373
+ * **(v.0)** IMPROVED: Major overhaul to plugin's user meta data storage, limiting to a single DB entry for all data.
374
+ * **(v.0)** ADDED: [**PRO**] Ability to increase frequency of file system scans up to once every hour.
375
+ * **(v.0)** ADDED: [**PRO**] Add a "remember me" option, to allow users to skip Multi-factor authentication for a set number of days.
376
+
377
+ = 6.1 Series =
378
  *Released: 15th January, 2018* - [Release Notes](http://icwp.io/ay)
379
 
380
+ * **(v.1)** FIXED: Verify link missing from the two-factor authentication verification email.
381
  * **(v.0)** ADDED: 3x more Shield Wizards: Multi-factor Authentication, Core File Scanning, Unrecognised File Scanning.
382
  * **(v.0)** ADDED: You can now use regular expressions for file exclusions in the 'Unrecognised File Scanner'.
383
  * **(v.0)** CHANGED: File Scanner email notifications now link to the appropriate scanner wizard directly.
384
  * **(v.0)** IMPROVED: Plugin options pages restyling.
385
  * **(v.0)** IMPROVED: Plugin refactoring and improvements.
386
 
387
+ = 6.0 Series =
388
  *Released: 18th December, 2017*
389
 
390
  * **(v.0)** ADDED: All-new Shield Welcome and Setup Wizard - more helpful guided wizards to come.
392
  * **(v.0)** ADDED: [**PRO**] In conjunction with import/export - Shield Security Network: automated options syncing.
393
  * **(v.0)** CHANGED: Going forward, new features and options will [support only PHP 5.4+](http://icwp.io/au). Existing features will remain unaffected.
394
 
395
+ = 5.20 Series =
396
  *Released: 11th December, 2017*
397
 
398
  * **(v.0)** IMPROVED: [**PRO**] Audit Trail length are configurable. Length for free is 50 entries (the original unpaginated limit)
402
  * **(v.0)** IMPROVED: Audit Trails are now ajax-paginated. You can browse through all your audit trail entries
403
  * **(v.0)** IMPROVED: User session tables are also ajax-paginated.
404
 
405
+ = 5.19 Series =
406
  *Released: 4th December, 2017*
407
 
408
  * **(v.1)** FIXED: Plugin Vulnerabilities scan for premium plugins.
411
  * **(v.0)** ADDED: [**PRO**] Support for Multi-Factor Authentication for WooCommerce and other 3rd party plugins.
412
  * **(v.0)** ADDED: [**PRO**] Bot-protection/Google reCAPTCHA support for BuddyPress register pages.
413
 
414
+ = 5.18 Series =
415
  *Released: 27th November, 2017*
416
 
417
  * **(v.0)** ADDED: [**PRO**] Invisible Google reCAPTCHA option.
418
  * **(v.0)** ADDED: [**PRO**] Support for Google reCAPTCHA themes - light and dark.
419
  * **(v.0)** IMPROVEMENT: Google reCAPTCHA is more reliable and configurable.
420
 
421
+ = 5.17 Series =
422
  *Released: 23rd November, 2017*
423
 
424
  * **(v.0)** ADDED: Shield Security goes Pro! Added new options and extras to premium clients.
resources/css/global-plugin.css CHANGED
@@ -1,13 +1,5 @@
1
  @CHARSET "ISO-8859-1";
2
 
3
- #wpbody-content .icwp-admin-notice {
4
- margin: 25px 5px 20px;
5
- padding: 10px 20px 8px;
6
- border: 1px solid rgba(51, 240, 4, 0.56);
7
- background-color: rgba(175, 230, 152, 0.5);
8
- border-right-width: 5px;
9
- border-left-width: 5px;
10
- }
11
  #wpbody-content .icwp-admin-notice,
12
  #wpbody-content .icwp-admin-notice p {
13
  text-shadow: -1px -1px 0 rgba(255, 255, 255, 0.4);
@@ -19,9 +11,6 @@
19
  #wpbody-content .icwp-admin-notice form {
20
  margin: 0;
21
  }
22
- #wpbody-content .icwp-admin-notice p.dismiss-p {
23
- margin: 10px 4px 0 0;
24
- }
25
  #wpbody-content .icwp-admin-notice .button:hover {
26
  text-decoration: none;
27
  }
@@ -31,35 +20,62 @@
31
  line-height: 21px;
32
  padding-right: 4px;
33
  }
34
- #wpbody-content .info.icwp-admin-notice,
35
- #wpbody-content .promo.icwp-admin-notice {
36
- background-color: rgba(199, 226, 239, 0.25);
37
- border-color: rgba(108, 138, 150, 0.99);
38
- }
39
- #wpbody-content .info.icwp-admin-notice,
40
- #wpbody-content .info.icwp-admin-notice p,
41
- #wpbody-content .promo.icwp-admin-notice,
42
- #wpbody-content .promo.icwp-admin-notice p {
43
- color: rgba(21, 77, 111, 0.99);
44
- }
45
- #wpbody-content .error.icwp-admin-notice {
46
- border-color: rgba(240, 51, 4, 0.56);
47
- background-color: rgba(255, 185, 167, 0.25);
48
- }
49
- #wpbody-content .error.icwp-admin-notice h3 {
50
- color: rgba(199, 41, 0, 1);
51
- }
52
  #wpbody-content .icwp-admin-notice .dismiss-p {
53
- float: right;
54
- position: relative;
55
- bottom: 24px;
56
- margin: 0;
57
  }
58
  #wpbody-content .icwp-admin-notice .dismiss-p,
59
  #wpbody-content .icwp-admin-notice .dismiss-p a {
60
  color: rgb(103, 21, 0);
61
  text-align: right;
62
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  ul.nav-tabs li a {
64
  color: rgba(69, 119, 0, 1);
65
  }
@@ -167,7 +183,7 @@ tr.icwp-plugin-vulnerability dd {
167
  .icwp-toggle-switch {
168
  cursor: pointer;
169
  }
170
- .icwp-toggle-switch .slider {
171
  position: absolute;
172
  top: 0;
173
  left: 0;
@@ -177,7 +193,7 @@ tr.icwp-plugin-vulnerability dd {
177
  -webkit-transition: .4s;
178
  transition: .4s;
179
  }
180
- .icwp-toggle-switch .slider:before {
181
  position: absolute;
182
  content: "";
183
  height: 26px;
@@ -188,16 +204,16 @@ tr.icwp-plugin-vulnerability dd {
188
  -webkit-transition: .4s;
189
  transition: .4s;
190
  }
191
- .icwp-toggle-switch input:checked + .slider {
192
  background-color: #65bd84;
193
  }
194
- .icwp-toggle-switch.disabled input + .slider {
195
  background-color: #bd7429;
196
  }
197
- .icwp-toggle-switch input:focus + .slider {
198
  box-shadow: 0 0 1px #65bd84;
199
  }
200
- .icwp-toggle-switch input:checked + .slider:before {
201
  -webkit-transform: translateX(26px);
202
  -ms-transform: translateX(26px);
203
  transform: translateX(26px);
1
  @CHARSET "ISO-8859-1";
2
 
 
 
 
 
 
 
 
 
3
  #wpbody-content .icwp-admin-notice,
4
  #wpbody-content .icwp-admin-notice p {
5
  text-shadow: -1px -1px 0 rgba(255, 255, 255, 0.4);
11
  #wpbody-content .icwp-admin-notice form {
12
  margin: 0;
13
  }
 
 
 
14
  #wpbody-content .icwp-admin-notice .button:hover {
15
  text-decoration: none;
16
  }
20
  line-height: 21px;
21
  padding-right: 4px;
22
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  #wpbody-content .icwp-admin-notice .dismiss-p {
24
+ margin: 10px;
 
 
 
25
  }
26
  #wpbody-content .icwp-admin-notice .dismiss-p,
27
  #wpbody-content .icwp-admin-notice .dismiss-p a {
28
  color: rgb(103, 21, 0);
29
  text-align: right;
30
  }
31
+
32
+ .notice-icon {
33
+ display: none;
34
+ float: left;
35
+ height: 43px;
36
+ line-height: 176px;
37
+ min-width: 64px;
38
+ padding: 10px 0;
39
+ }
40
+ .notice-title {
41
+ padding: 0;
42
+ }
43
+ .notice-content {
44
+ margin: 10px;
45
+ }
46
+ .notice-content p {
47
+ margin-left: 0;
48
+ }
49
+
50
+ @media (min-width: 884px) {
51
+ .notice-icon {
52
+ display: block;
53
+ }
54
+ .notice-content {
55
+ margin-left: 62px;
56
+ }
57
+ }
58
+
59
+ .notice-icon-right {
60
+ float: right;
61
+ width: 74px;
62
+ }
63
+ .notice-content p {
64
+ margin-left: 62px;
65
+ }
66
+ .notice-icon .dashicons {
67
+ display: inline-block;
68
+ font-size: 48px;
69
+ }
70
+ .notice-content p a {
71
+ text-shadow: none;
72
+ font-weight: bold;
73
+ }
74
+
75
+
76
+
77
+
78
+
79
  ul.nav-tabs li a {
80
  color: rgba(69, 119, 0, 1);
81
  }
183
  .icwp-toggle-switch {
184
  cursor: pointer;
185
  }
186
+ .icwp-toggle-switch .icwp-slider {
187
  position: absolute;
188
  top: 0;
189
  left: 0;
193
  -webkit-transition: .4s;
194
  transition: .4s;
195
  }
196
+ .icwp-toggle-switch .icwp-slider:before {
197
  position: absolute;
198
  content: "";
199
  height: 26px;
204
  -webkit-transition: .4s;
205
  transition: .4s;
206
  }
207
+ .icwp-toggle-switch input:checked + .icwp-slider {
208
  background-color: #65bd84;
209
  }
210
+ .icwp-toggle-switch.disabled input + .icwp-slider {
211
  background-color: #bd7429;
212
  }
213
+ .icwp-toggle-switch input:focus + .icwp-slider {
214
  box-shadow: 0 0 1px #65bd84;
215
  }
216
+ .icwp-toggle-switch input:checked + .icwp-slider:before {
217
  -webkit-transform: translateX(26px);
218
  -ms-transform: translateX(26px);
219
  transform: translateX(26px);
resources/css/plugin.css CHANGED
@@ -269,11 +269,11 @@ p.code-description {
269
  display: block;
270
  color: #333333;
271
  font-size: 24px;
272
- margin: 25px auto auto auto;
273
- padding: 0 20px;
274
  width: auto;
275
  background: rgba(255, 255, 255, 0.8);
276
- line-height: 50px;
277
  text-align: center;
278
  user-select: none;
279
  }
@@ -595,7 +595,7 @@ label.forcheckbox .summary {
595
  .bootstrap-wpadmin .switch input {display:none; !important;}
596
 
597
  /* The slider */
598
- .slider {
599
  position: absolute;
600
  cursor: pointer;
601
  top: 0;
@@ -606,7 +606,7 @@ label.forcheckbox .summary {
606
  -webkit-transition: .1s;
607
  transition: .1s;
608
  }
609
- .slider:before {
610
  position: absolute;
611
  content: "";
612
  height: 16px;
@@ -617,21 +617,21 @@ label.forcheckbox .summary {
617
  -webkit-transition: .1s;
618
  transition: .1s;
619
  }
620
- input:checked + .slider {
621
  background-color: rgba(69, 119, 0, 1);
622
  }
623
- input:focus + .slider {
624
  box-shadow: 0 0 1px rgba(69, 119, 0, 1);
625
  }
626
- input:checked + .slider:before {
627
  -webkit-transform: translateX(20px);
628
  -ms-transform: translateX(20px);
629
  transform: translateX(20px);
630
  }
631
  /* Rounded sliders */
632
- .slider.round {
633
  border-radius: 3px;
634
  }
635
- .slider.round:before {
636
  border-radius: 10%;
637
  }
269
  display: block;
270
  color: #333333;
271
  font-size: 24px;
272
+ margin: 15px auto auto auto;
273
+ padding: 0 10px;
274
  width: auto;
275
  background: rgba(255, 255, 255, 0.8);
276
+ line-height: 40px;
277
  text-align: center;
278
  user-select: none;
279
  }
595
  .bootstrap-wpadmin .switch input {display:none; !important;}
596
 
597
  /* The slider */
598
+ .icwp-slider {
599
  position: absolute;
600
  cursor: pointer;
601
  top: 0;
606
  -webkit-transition: .1s;
607
  transition: .1s;
608
  }
609
+ .icwp-slider:before {
610
  position: absolute;
611
  content: "";
612
  height: 16px;
617
  -webkit-transition: .1s;
618
  transition: .1s;
619
  }
620
+ input:checked + .icwp-slider {
621
  background-color: rgba(69, 119, 0, 1);
622
  }
623
+ input:focus + .icwp-slider {
624
  box-shadow: 0 0 1px rgba(69, 119, 0, 1);
625
  }
626
+ input:checked + .icwp-slider:before {
627
  -webkit-transform: translateX(20px);
628
  -ms-transform: translateX(20px);
629
  transform: translateX(20px);
630
  }
631
  /* Rounded sliders */
632
+ .icwp-slider.round {
633
  border-radius: 3px;
634
  }
635
+ .icwp-slider.round:before {
636
  border-radius: 10%;
637
  }
resources/css/wizard.css CHANGED
@@ -11,6 +11,9 @@ body.wait {
11
  background: #ffffff;
12
  box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
13
  }
 
 
 
14
  .wizard.vertical > .steps {
15
  width: 20%; /** from 30 **/
16
  }
@@ -86,6 +89,13 @@ body.wait {
86
  background-color: #ffffff;
87
  }
88
 
 
 
 
 
 
 
 
89
  #GoProBtn {
90
  width: 128px;
91
  display: block;
11
  background: #ffffff;
12
  box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
13
  }
14
+ .wizard > .steps .current a {
15
+ text-shadow: 1px 1px 0 rgba(0,0,0,0.1);
16
+ }
17
  .wizard.vertical > .steps {
18
  width: 20%; /** from 30 **/
19
  }
89
  background-color: #ffffff;
90
  }
91
 
92
+ .wizard form label {
93
+ }
94
+ .wizard form input[type="radio"]:checked + span {
95
+ font-weight: bolder;
96
+ letter-spacing: -0.4px;
97
+ }
98
+
99
  #GoProBtn {
100
  width: 128px;
101
  display: block;
resources/js/global-plugin.js CHANGED
@@ -80,6 +80,7 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
80
 
81
  jQuery.post( ajaxurl, $oForm.serialize(),
82
  function ( oResponse ) {
 
83
  if ( oResponse.data.message === undefined ) {
84
  sMessage = oResponse.success ? 'Success' : 'Failure';
85
  }
80
 
81
  jQuery.post( ajaxurl, $oForm.serialize(),
82
  function ( oResponse ) {
83
+ var sMessage;
84
  if ( oResponse.data.message === undefined ) {
85
  sMessage = oResponse.success ? 'Success' : 'Failure';
86
  }
src/common/Components/Tables/SessionsTable.php CHANGED
@@ -14,7 +14,7 @@ class SessionsTable extends ICWP_BaseTable {
14
  'wp_username' => 'Username',
15
  'logged_in_at' => 'Logged In',
16
  'last_activity_at' => 'Last Activity',
17
- 'used_mfa' => 'MFA',
18
  'ip' => 'IP Address',
19
  );
20
  }
14
  'wp_username' => 'Username',
15
  'logged_in_at' => 'Logged In',
16
  'last_activity_at' => 'Last Activity',
17
+ 'is_secadmin' => 'Sec. Admin',
18
  'ip' => 'IP Address',
19
  );
20
  }
src/common/icwp-data.php CHANGED
@@ -112,6 +112,13 @@ class ICWP_WPSF_DataProcessor extends ICWP_WPSF_Foundation {
112
  return $this->FetchServer( 'REQUEST_URI' );
113
  }
114
 
 
 
 
 
 
 
 
115
  /**
116
  * @param bool $bIncludeCookie
117
  * @return array
112
  return $this->FetchServer( 'REQUEST_URI' );
113
  }
114
 
115
+ /**
116
+ * @return string
117
+ */
118
+ public function getUserAgent() {
119
+ return $this->FetchServer( 'HTTP_USER_AGENT' );
120
+ }
121
+
122
  /**
123
  * @param bool $bIncludeCookie
124
  * @return array
src/common/icwp-usermeta.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( class_exists( 'ICWP_UserMeta', false ) ) {
3
+ return;
4
+ }
5
+
6
+ /**
7
+ * @property string $email_secret
8
+ * @property bool $email_validated
9
+ * @property string $ga_secret
10
+ * @property bool $ga_validated
11
+ * @property array $hash_loginmfa
12
+ * @property string $yubi_secret
13
+ * @property bool $yubi_validated
14
+ * @property string $code_tfaemail
15
+ * @property int $last_login_at
16
+ * @property int $login_intent_expires_at
17
+ * @property string $prefix
18
+ * @property int $user_id
19
+ * Class ICWP_UserMeta
20
+ */
21
+ class ICWP_UserMeta extends ICWP_WPSF_Foundation {
22
+
23
+ /**
24
+ * @var array
25
+ */
26
+ protected $aData;
27
+
28
+ /**
29
+ * @param string $sPrefix
30
+ * @param int $nUserId
31
+ */
32
+ public function __construct( $sPrefix, $nUserId = 0 ) {
33
+ $this->load( $sPrefix, $nUserId );
34
+ }
35
+
36
+ /**
37
+ */
38
+ public function __destruct() {
39
+ $this->save();
40
+ }
41
+
42
+ /**
43
+ * Cannot use Data store (__get()) yet
44
+ * @param int $sPrefix
45
+ * @param int $nUserId
46
+ * @return $this
47
+ */
48
+ private function load( $sPrefix, $nUserId ) {
49
+ $aStore = $this->loadWpUsers()->getUserMeta( $sPrefix.'-meta', $nUserId );
50
+ if ( !is_array( $aStore ) ) {
51
+ $aStore = array();
52
+ }
53
+ $this->aData = $aStore;
54
+ $this->prefix = $sPrefix;
55
+ $this->user_id = $nUserId;
56
+ return $this;
57
+ }
58
+
59
+ /**
60
+ * @return $this
61
+ */
62
+ public function delete() {
63
+ if ( $this->user_id > 0 ) {
64
+ $this->loadWpUsers()->deleteUserMeta( $this->getStorageKey(), $this->user_id );
65
+ }
66
+ return $this;
67
+ }
68
+
69
+ /**
70
+ * @return $this
71
+ */
72
+ public function save() {
73
+ if ( $this->user_id > 0 ) {
74
+ $this->loadWpUsers()->updateUserMeta( $this->getStorageKey(), $this->aData, $this->user_id );
75
+ }
76
+ return $this;
77
+ }
78
+
79
+ /**
80
+ * @param string $sKey
81
+ * @return mixed|null
82
+ */
83
+ public function __get( $sKey ) {
84
+ return isset( $this->aData[ $sKey ] ) ? $this->aData[ $sKey ] : null;
85
+ }
86
+
87
+ /**
88
+ * @param string $sKey
89
+ * @return bool
90
+ */
91
+ public function __isset( $sKey ) {
92
+ return isset( $this->aData[ $sKey ] );
93
+ }
94
+
95
+ /**
96
+ * @param string $sKey
97
+ * @param $mValue
98
+ */
99
+ public function __set( $sKey, $mValue ) {
100
+ $this->aData[ $sKey ] = $mValue;
101
+ $this->save();
102
+ }
103
+
104
+ /**
105
+ * @param string $sKey
106
+ */
107
+ public function __unset( $sKey ) {
108
+ unset( $this->aData[ $sKey ] );
109
+ $this->save();
110
+ }
111
+
112
+ /**
113
+ * @return string
114
+ */
115
+ private function getStorageKey() {
116
+ return $this->prefix.'-meta';
117
+ }
118
+ }
src/common/icwp-wpcron.php CHANGED
@@ -9,7 +9,6 @@ class ICWP_WPSF_WpCron {
9
  * @var ICWP_WPSF_WpCron
10
  */
11
  protected static $oInstance = null;
12
- private function __construct() { }
13
 
14
  /**
15
  * @var int
@@ -21,6 +20,11 @@ class ICWP_WPSF_WpCron {
21
  */
22
  protected $sRecurrence;
23
 
 
 
 
 
 
24
  /**
25
  * @return ICWP_WPSF_WpCron
26
  */
@@ -31,6 +35,42 @@ class ICWP_WPSF_WpCron {
31
  return self::$oInstance;
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  /**
35
  * @param string $sCronName
36
  * @return bool
@@ -53,7 +93,7 @@ class ICWP_WPSF_WpCron {
53
  * @return string
54
  */
55
  public function getRecurrence() {
56
- if ( empty( $this->sRecurrence ) || !in_array( $this->sRecurrence, $this->getPermittedRecurrences() ) ) {
57
  return 'daily';
58
  }
59
  return $this->sRecurrence;
@@ -102,9 +142,11 @@ class ICWP_WPSF_WpCron {
102
 
103
  /**
104
  * @param string $sUniqueCronName
 
105
  */
106
  public function deleteCronJob( $sUniqueCronName ) {
107
  wp_clear_scheduled_hook( $sUniqueCronName );
 
108
  }
109
 
110
  /**
@@ -118,11 +160,4 @@ class ICWP_WPSF_WpCron {
118
  }
119
  return $this;
120
  }
121
-
122
- /**
123
- * @return array
124
- */
125
- private function getPermittedRecurrences() {
126
- return array( 'hourly', 'twicedaily', 'daily' );
127
- }
128
  }
9
  * @var ICWP_WPSF_WpCron
10
  */
11
  protected static $oInstance = null;
 
12
 
13
  /**
14
  * @var int
20
  */
21
  protected $sRecurrence;
22
 
23
+ /**
24
+ * @var array
25
+ */
26
+ protected $aSchedules;
27
+
28
  /**
29
  * @return ICWP_WPSF_WpCron
30
  */
35
  return self::$oInstance;
36
  }
37
 
38
+ private function __construct() {
39
+ add_filter( 'cron_schedules', array( $this, 'addSchedules' ) );
40
+ }
41
+
42
+ /**
43
+ * @param array $aSchedules
44
+ * @return array
45
+ */
46
+ public function addSchedules( $aSchedules ) {
47
+ return array_merge( $aSchedules, $this->getSchedules() );
48
+ }
49
+
50
+ /**
51
+ * @param string $sSlug
52
+ * @param array $aNewSchedule
53
+ * @return $this
54
+ */
55
+ public function addNewSchedule( $sSlug, $aNewSchedule ) {
56
+ if ( !empty( $aNewSchedule ) && is_array( $aNewSchedule ) ) {
57
+ $aSchedules = $this->getSchedules();
58
+ $aSchedules[ $sSlug ] = $aNewSchedule;
59
+ $this->aSchedules = $aSchedules;
60
+ }
61
+ return $this;
62
+ }
63
+
64
+ /**
65
+ * @return array
66
+ */
67
+ protected function getSchedules() {
68
+ if ( !is_array( $this->aSchedules ) ) {
69
+ $this->aSchedules = array();
70
+ }
71
+ return $this->aSchedules;
72
+ }
73
+
74
  /**
75
  * @param string $sCronName
76
  * @return bool
93
  * @return string
94
  */
95
  public function getRecurrence() {
96
+ if ( empty( $this->sRecurrence ) ) {
97
  return 'daily';
98
  }
99
  return $this->sRecurrence;
142
 
143
  /**
144
  * @param string $sUniqueCronName
145
+ * @return $this
146
  */
147
  public function deleteCronJob( $sUniqueCronName ) {
148
  wp_clear_scheduled_hook( $sUniqueCronName );
149
+ return $this;
150
  }
151
 
152
  /**
160
  }
161
  return $this;
162
  }
 
 
 
 
 
 
 
163
  }
src/common/icwp-wpdb.php CHANGED
@@ -156,7 +156,7 @@ class ICWP_WPSF_WpDb {
156
  /**
157
  * @param string $sTable
158
  * @param array $aData
159
- * @return int|boolean
160
  */
161
  public function insertDataIntoTable( $sTable, $aData ) {
162
  return $this->loadWpdb()->insert( $sTable, $aData );
156
  /**
157
  * @param string $sTable
158
  * @param array $aData
159
+ * @return int|false
160
  */
161
  public function insertDataIntoTable( $sTable, $aData ) {
162
  return $this->loadWpdb()->insert( $sTable, $aData );
src/common/icwp-wpfunctions.php CHANGED
@@ -856,105 +856,4 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
856
  }
857
  wp_die( $sMessage, $sTitle );
858
  }
859
-
860
- /** DEPRECATED: */
861
-
862
- /**
863
- * @deprecated
864
- * @param array $aLoginUrlParams
865
- */
866
- public function forceUserRelogin( $aLoginUrlParams = array() ) {
867
- $this->loadWpUsers()->forceUserRelogin( $aLoginUrlParams );
868
- }
869
-
870
- /**
871
- * @deprecated
872
- * @return null|WP_User
873
- */
874
- public function getCurrentWpUser() {
875
- return $this->loadWpUsers()->getCurrentWpUser();
876
- }
877
-
878
- /**
879
- * @deprecated
880
- * @return integer
881
- */
882
- public function getCurrentUserLevel() {
883
- return $this->loadWpUsers()->getCurrentUserLevel();
884
- }
885
-
886
- /**
887
- * @deprecated
888
- * @param int $nId
889
- * @return WP_User|null
890
- */
891
- public function getUserById( $nId ) {
892
- return $this->loadWpUsers()->getUserById( $nId );
893
- }
894
-
895
- /**
896
- * @deprecated
897
- * @param $sUsername
898
- * @return bool|WP_User
899
- */
900
- public function getUserByUsername( $sUsername ) {
901
- return $this->loadWpUsers()->getUserByUsername( $sUsername );
902
- }
903
-
904
- /**
905
- * @deprecated
906
- * @param string $sKey should be already prefixed
907
- * @param int|null $nId - if omitted get for current user
908
- * @return bool|string
909
- */
910
- public function getUserMeta( $sKey, $nId = null ) {
911
- return $this->loadWpUsers()->getUserMeta( $sKey, $nId );
912
- }
913
-
914
- /**
915
- * Updates the user meta data for the current (or supplied user ID)
916
- * @deprecated
917
- * @param string $sKey
918
- * @param mixed $mValue
919
- * @param integer $nId -user ID
920
- * @return boolean
921
- */
922
- public function updateUserMeta( $sKey, $mValue, $nId = null ) {
923
- return $this->loadWpUsers()->updateUserMeta( $sKey, $mValue, $nId );
924
- }
925
-
926
- /**
927
- * @deprecated
928
- * @param string $sUsername
929
- * @return bool
930
- */
931
- public function setUserLoggedIn( $sUsername ) {
932
- return $this->loadWpUsers()->setUserLoggedIn( $sUsername );
933
- }
934
-
935
- /**
936
- * @deprecated
937
- * @return bool
938
- */
939
- public function comments_getIsCommentPost() {
940
- return $this->loadWpCommentsProcessor()->isCommentPost();
941
- }
942
-
943
- /**
944
- * @deprecated
945
- * @param string $sAuthorEmail
946
- * @return bool
947
- */
948
- public function comments_getIfCommentAuthorPreviouslyApproved( $sAuthorEmail ) {
949
- return $this->loadWpCommentsProcessor()->isCommentAuthorPreviouslyApproved( $sAuthorEmail );
950
- }
951
-
952
- /**
953
- * @deprecated
954
- * @param WP_Post $oPost
955
- * @return bool
956
- */
957
- public function comments_getIfCommentsOpen( $oPost = null ) {
958
- return $this->loadWpCommentsProcessor()->isCommentsOpen( $oPost );
959
- }
960
  }
856
  }
857
  wp_die( $sMessage, $sTitle );
858
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
859
  }
src/common/lib/composer.lock CHANGED
@@ -154,16 +154,16 @@
154
  },
155
  {
156
  "name": "symfony/translation",
157
- "version": "v3.4.2",
158
  "source": {
159
  "type": "git",
160
  "url": "https://github.com/symfony/translation.git",
161
- "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6"
162
  },
163
  "dist": {
164
  "type": "zip",
165
- "url": "https://api.github.com/repos/symfony/translation/zipball/4c5d5582baf2829751a5207659329c1f52eedeb6",
166
- "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6",
167
  "shasum": ""
168
  },
169
  "require": {
@@ -218,7 +218,7 @@
218
  ],
219
  "description": "Symfony Translation Component",
220
  "homepage": "https://symfony.com",
221
- "time": "2017-12-12T08:27:14+00:00"
222
  },
223
  {
224
  "name": "twig/twig",
154
  },
155
  {
156
  "name": "symfony/translation",
157
+ "version": "v3.4.4",
158
  "source": {
159
  "type": "git",
160
  "url": "https://github.com/symfony/translation.git",
161
+ "reference": "10b32cf0eae28b9b39fe26c456c42b19854c4b84"
162
  },
163
  "dist": {
164
  "type": "zip",
165
+ "url": "https://api.github.com/repos/symfony/translation/zipball/10b32cf0eae28b9b39fe26c456c42b19854c4b84",
166
+ "reference": "10b32cf0eae28b9b39fe26c456c42b19854c4b84",
167
  "shasum": ""
168
  },
169
  "require": {
218
  ],
219
  "description": "Symfony Translation Component",
220
  "homepage": "https://symfony.com",
221
+ "time": "2018-01-18T22:16:57+00:00"
222
  },
223
  {
224
  "name": "twig/twig",
src/common/lib/vendor/composer/installed.json CHANGED
@@ -151,76 +151,6 @@
151
  ],
152
  "description": "Collection of simple utilities and traits"
153
  },
154
- {
155
- "name": "symfony/translation",
156
- "version": "v3.4.2",
157
- "version_normalized": "3.4.2.0",
158
- "source": {
159
- "type": "git",
160
- "url": "https://github.com/symfony/translation.git",
161
- "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6"
162
- },
163
- "dist": {
164
- "type": "zip",
165
- "url": "https://api.github.com/repos/symfony/translation/zipball/4c5d5582baf2829751a5207659329c1f52eedeb6",
166
- "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6",
167
- "shasum": ""
168
- },
169
- "require": {
170
- "php": "^5.5.9|>=7.0.8",
171
- "symfony/polyfill-mbstring": "~1.0"
172
- },
173
- "conflict": {
174
- "symfony/config": "<2.8",
175
- "symfony/dependency-injection": "<3.4",
176
- "symfony/yaml": "<3.4"
177
- },
178
- "require-dev": {
179
- "psr/log": "~1.0",
180
- "symfony/config": "~2.8|~3.0|~4.0",
181
- "symfony/dependency-injection": "~3.4|~4.0",
182
- "symfony/finder": "~2.8|~3.0|~4.0",
183
- "symfony/intl": "^2.8.18|^3.2.5|~4.0",
184
- "symfony/yaml": "~3.4|~4.0"
185
- },
186
- "suggest": {
187
- "psr/log": "To use logging capability in translator",
188
- "symfony/config": "",
189
- "symfony/yaml": ""
190
- },
191
- "time": "2017-12-12T08:27:14+00:00",
192
- "type": "library",
193
- "extra": {
194
- "branch-alias": {
195
- "dev-master": "3.4-dev"
196
- }
197
- },
198
- "installation-source": "dist",
199
- "autoload": {
200
- "psr-4": {
201
- "Symfony\\Component\\Translation\\": ""
202
- },
203
- "exclude-from-classmap": [
204
- "/Tests/"
205
- ]
206
- },
207
- "notification-url": "https://packagist.org/downloads/",
208
- "license": [
209
- "MIT"
210
- ],
211
- "authors": [
212
- {
213
- "name": "Fabien Potencier",
214
- "email": "fabien@symfony.com"
215
- },
216
- {
217
- "name": "Symfony Community",
218
- "homepage": "https://symfony.com/contributors"
219
- }
220
- ],
221
- "description": "Symfony Translation Component",
222
- "homepage": "https://symfony.com"
223
- },
224
  {
225
  "name": "twig/twig",
226
  "version": "v1.35.0",
@@ -287,5 +217,75 @@
287
  "keywords": [
288
  "templating"
289
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  }
291
  ]
151
  ],
152
  "description": "Collection of simple utilities and traits"
153
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  {
155
  "name": "twig/twig",
156
  "version": "v1.35.0",
217
  "keywords": [
218
  "templating"
219
  ]
220
+ },
221
+ {
222
+ "name": "symfony/translation",
223
+ "version": "v3.4.4",
224
+ "version_normalized": "3.4.4.0",
225
+ "source": {
226
+ "type": "git",
227
+ "url": "https://github.com/symfony/translation.git",
228
+ "reference": "10b32cf0eae28b9b39fe26c456c42b19854c4b84"
229
+ },
230
+ "dist": {
231
+ "type": "zip",
232
+ "url": "https://api.github.com/repos/symfony/translation/zipball/10b32cf0eae28b9b39fe26c456c42b19854c4b84",
233
+ "reference": "10b32cf0eae28b9b39fe26c456c42b19854c4b84",
234
+ "shasum": ""
235
+ },
236
+ "require": {
237
+ "php": "^5.5.9|>=7.0.8",
238
+ "symfony/polyfill-mbstring": "~1.0"
239
+ },
240
+ "conflict": {
241
+ "symfony/config": "<2.8",
242
+ "symfony/dependency-injection": "<3.4",
243
+ "symfony/yaml": "<3.4"
244
+ },
245
+ "require-dev": {
246
+ "psr/log": "~1.0",
247
+ "symfony/config": "~2.8|~3.0|~4.0",
248
+ "symfony/dependency-injection": "~3.4|~4.0",
249
+ "symfony/finder": "~2.8|~3.0|~4.0",
250
+ "symfony/intl": "^2.8.18|^3.2.5|~4.0",
251
+ "symfony/yaml": "~3.4|~4.0"
252
+ },
253
+ "suggest": {
254
+ "psr/log": "To use logging capability in translator",
255
+ "symfony/config": "",
256
+ "symfony/yaml": ""
257
+ },
258
+ "time": "2018-01-18T22:16:57+00:00",
259
+ "type": "library",
260
+ "extra": {
261
+ "branch-alias": {
262
+ "dev-master": "3.4-dev"
263
+ }
264
+ },
265
+ "installation-source": "dist",
266
+ "autoload": {
267
+ "psr-4": {
268
+ "Symfony\\Component\\Translation\\": ""
269
+ },
270
+ "exclude-from-classmap": [
271
+ "/Tests/"
272
+ ]
273
+ },
274
+ "notification-url": "https://packagist.org/downloads/",
275
+ "license": [
276
+ "MIT"
277
+ ],
278
+ "authors": [
279
+ {
280
+ "name": "Fabien Potencier",
281
+ "email": "fabien@symfony.com"
282
+ },
283
+ {
284
+ "name": "Symfony Community",
285
+ "homepage": "https://symfony.com/contributors"
286
+ }
287
+ ],
288
+ "description": "Symfony Translation Component",
289
+ "homepage": "https://symfony.com"
290
  }
291
  ]
src/common/lib/vendor/nesbot/carbon/.php_cs.dist DELETED
@@ -1,57 +0,0 @@
1
- <?php
2
-
3
- use PhpCsFixer\Config;
4
- use PhpCsFixer\Finder;
5
-
6
- $rules = [
7
- '@PSR2' => true,
8
- 'array_syntax' => [
9
- 'syntax' => 'long',
10
- ],
11
- 'binary_operator_spaces' => [
12
- 'align_double_arrow' => false,
13
- 'align_equals' => false,
14
- ],
15
- 'blank_line_before_return' => true,
16
- 'cast_spaces' => true,
17
- 'concat_space' => [
18
- 'spacing' => 'none',
19
- ],
20
- 'ereg_to_preg' => true,
21
- 'method_separation' => true,
22
- 'no_blank_lines_after_phpdoc' => true,
23
- 'no_extra_consecutive_blank_lines' => true,
24
- 'no_short_bool_cast' => true,
25
- 'no_unneeded_control_parentheses' => true,
26
- 'no_unused_imports' => true,
27
- 'no_whitespace_in_blank_line' => true,
28
- 'ordered_imports' => true,
29
- 'phpdoc_align' => true,
30
- 'phpdoc_indent' => true,
31
- 'phpdoc_inline_tag' => true,
32
- 'phpdoc_no_access' => true,
33
- 'phpdoc_no_alias_tag' => [
34
- 'type' => 'var',
35
- ],
36
- 'phpdoc_no_package' => true,
37
- 'phpdoc_order' => true,
38
- 'phpdoc_scalar' => true,
39
- 'phpdoc_separation' => true,
40
- 'phpdoc_to_comment' => true,
41
- 'phpdoc_trim' => true,
42
- 'phpdoc_types' => true,
43
- 'phpdoc_var_without_name' => true,
44
- 'self_accessor' => true,
45
- 'single_quote' => true,
46
- 'space_after_semicolon' => true,
47
- 'standardize_not_equals' => true,
48
- 'ternary_operator_spaces' => true,
49
- 'trailing_comma_in_multiline_array' => true,
50
- 'trim_array_spaces' => true,
51
- 'unary_operator_spaces' => true,
52
- ];
53
-
54
- return Config::create()->setRules($rules)
55
- ->setFinder(Finder::create()->in(__DIR__))
56
- ->setUsingCache(true)
57
- ->setRiskyAllowed(true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/common/lib/vendor/nesbot/carbon/LICENSE DELETED
@@ -1,19 +0,0 @@
1
- Copyright (C) Brian Nesbitt
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to deal
5
- in the Software without restriction, including without limitation the rights
6
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- copies of the Software, and to permit persons to whom the Software is furnished
8
- to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all
11
- copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- THE SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/common/lib/vendor/nesbot/carbon/readme.md DELETED
@@ -1,92 +0,0 @@
1
- # Carbon
2
-
3
- [![Latest Stable Version](https://poser.pugx.org/nesbot/carbon/v/stable.png)](https://packagist.org/packages/nesbot/carbon)
4
- [![Total Downloads](https://poser.pugx.org/nesbot/carbon/downloads.png)](https://packagist.org/packages/nesbot/carbon)
5
- [![Build Status](https://travis-ci.org/briannesbitt/Carbon.svg?branch=master)](https://travis-ci.org/briannesbitt/Carbon)
6
- [![StyleCI](https://styleci.io/repos/5724990/shield?style=flat)](https://styleci.io/repos/5724990)
7
- [![codecov.io](https://codecov.io/github/briannesbitt/Carbon/coverage.svg?branch=master)](https://codecov.io/github/briannesbitt/Carbon?branch=master)
8
- [![PHP-Eye](https://php-eye.com/badge/nesbot/carbon/tested.svg?style=flat)](https://php-eye.com/package/nesbot/carbon)
9
-
10
- A simple PHP API extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com)
11
-
12
- ```php
13
- use Carbon\Carbon;
14
-
15
- printf("Right now is %s", Carbon::now()->toDateTimeString());
16
- printf("Right now in Vancouver is %s", Carbon::now('America/Vancouver')); //implicit __toString()
17
- $tomorrow = Carbon::now()->addDay();
18
- $lastWeek = Carbon::now()->subWeek();
19
- $nextSummerOlympics = Carbon::createFromDate(2012)->addYears(4);
20
-
21
- $officialDate = Carbon::now()->toRfc2822String();
22
-
23
- $howOldAmI = Carbon::createFromDate(1975, 5, 21)->age;
24
-
25
- $noonTodayLondonTime = Carbon::createFromTime(12, 0, 0, 'Europe/London');
26
-
27
- $worldWillEnd = Carbon::createFromDate(2012, 12, 21, 'GMT');
28
-
29
- // Don't really want to die so mock now
30
- Carbon::setTestNow(Carbon::createFromDate(2000, 1, 1));
31
-
32
- // comparisons are always done in UTC
33
- if (Carbon::now()->gte($worldWillEnd)) {
34
- die();
35
- }
36
-
37
- // Phew! Return to normal behaviour
38
- Carbon::setTestNow();
39
-
40
- if (Carbon::now()->isWeekend()) {
41
- echo 'Party!';
42
- }
43
- echo Carbon::now()->subMinutes(2)->diffForHumans(); // '2 minutes ago'
44
-
45
- // ... but also does 'from now', 'after' and 'before'
46
- // rolling up to seconds, minutes, hours, days, months, years
47
-
48
- $daysSinceEpoch = Carbon::createFromTimestamp(0)->diffInDays();
49
- ```
50
-
51
- ## Installation
52
-
53
- ### With Composer
54
-
55
- ```
56
- $ composer require nesbot/carbon
57
- ```
58
-
59
- ```json
60
- {
61
- "require": {
62
- "nesbot/carbon": "~1.21"
63
- }
64
- }
65
- ```
66
-
67
- ```php
68
- <?php
69
- require 'vendor/autoload.php';
70
-
71
- use Carbon\Carbon;
72
-
73
- printf("Now: %s", Carbon::now());
74
- ```
75
-
76
- <a name="install-nocomposer"/>
77
- ### Without Composer
78
-
79
- Why are you not using [composer](http://getcomposer.org/)? Download [Carbon.php](https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Carbon.php) from the repo and save the file into your project path somewhere.
80
-
81
- ```php
82
- <?php
83
- require 'path/to/Carbon.php';
84
-
85
- use Carbon\Carbon;
86
-
87
- printf("Now: %s", Carbon::now());
88
- ```
89
-
90
- ## Docs
91
-
92
- [http://carbon.nesbot.com/docs](http://carbon.nesbot.com/docs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/common/lib/vendor/symfony/polyfill-mbstring/LICENSE DELETED
@@ -1,19 +0,0 @@
1
- Copyright (c) 2014-2016 Fabien Potencier
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to deal
5
- in the Software without restriction, including without limitation the rights
6
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- copies of the Software, and to permit persons to whom the Software is furnished
8
- to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all
11
- copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- THE SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/common/lib/vendor/symfony/translation/Dumper/FileDumper.php CHANGED
@@ -75,7 +75,7 @@ abstract class FileDumper implements DumperInterface
75
  $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
76
  if (file_exists($fullpath)) {
77
  if ($this->backup) {
78
- @trigger_error('Creating a backup while dumping a message catalogue is deprecated since version 3.1 and will be removed in 4.0. Use TranslationWriter::disableBackup() to disable the backup.', E_USER_DEPRECATED);
79
  copy($fullpath, $fullpath.'~');
80
  }
81
  } else {
75
  $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
76
  if (file_exists($fullpath)) {
77
  if ($this->backup) {
78
+ @trigger_error('Creating a backup while dumping a message catalogue is deprecated since Symfony 3.1 and will be removed in 4.0. Use TranslationWriter::disableBackup() to disable the backup.', E_USER_DEPRECATED);
79
  copy($fullpath, $fullpath.'~');
80
  }
81
  } else {
src/common/lib/vendor/symfony/translation/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2017 Fabien Potencier
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
  of this software and associated documentation files (the "Software"), to deal
1
+ Copyright (c) 2004-2018 Fabien Potencier
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
  of this software and associated documentation files (the "Software"), to deal
src/common/lib/vendor/symfony/translation/Loader/XliffFileLoader.php CHANGED
@@ -234,16 +234,20 @@ class XliffFileLoader implements LoaderInterface
234
  {
235
  $newPath = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd';
236
  $parts = explode('/', $newPath);
 
237
  if (0 === stripos($newPath, 'phar://')) {
238
  $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
239
  if ($tmpfile) {
240
  copy($newPath, $tmpfile);
241
  $parts = explode('/', str_replace('\\', '/', $tmpfile));
 
 
 
242
  }
243
  }
244
 
245
  $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
246
- $newPath = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));
247
 
248
  return str_replace($xmlUri, $newPath, $schemaSource);
249
  }
234
  {
235
  $newPath = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd';
236
  $parts = explode('/', $newPath);
237
+ $locationstart = 'file:///';
238
  if (0 === stripos($newPath, 'phar://')) {
239
  $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
240
  if ($tmpfile) {
241
  copy($newPath, $tmpfile);
242
  $parts = explode('/', str_replace('\\', '/', $tmpfile));
243
+ } else {
244
+ array_shift($parts);
245
+ $locationstart = 'phar:///';
246
  }
247
  }
248
 
249
  $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
250
+ $newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts));
251
 
252
  return str_replace($xmlUri, $newPath, $schemaSource);
253
  }
src/common/lib/vendor/symfony/translation/Translator.php CHANGED
@@ -87,7 +87,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
87
 
88
  if ($formatter instanceof MessageSelector) {
89
  $formatter = new MessageFormatter($formatter);
90
- @trigger_error(sprintf('Passing a "%s" instance into the "%s" as a second argument is deprecated since version 3.4 and will be removed in 4.0. Inject a "%s" implementation instead.', MessageSelector::class, __METHOD__, MessageFormatterInterface::class), E_USER_DEPRECATED);
91
  } elseif (null === $formatter) {
92
  $formatter = new MessageFormatter();
93
  }
87
 
88
  if ($formatter instanceof MessageSelector) {
89
  $formatter = new MessageFormatter($formatter);
90
+ @trigger_error(sprintf('Passing a "%s" instance into the "%s" as a second argument is deprecated since Symfony 3.4 and will be removed in 4.0. Inject a "%s" implementation instead.', MessageSelector::class, __METHOD__, MessageFormatterInterface::class), E_USER_DEPRECATED);
91
  } elseif (null === $formatter) {
92
  $formatter = new MessageFormatter();
93
  }
src/common/lib/vendor/symfony/translation/Writer/TranslationWriter.php CHANGED
@@ -97,7 +97,7 @@ class TranslationWriter implements TranslationWriterInterface
97
  */
98
  public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array())
99
  {
100
- @trigger_error(sprintf('Method %s() is deprecated since version 3.4 and will be removed in 4.0. Use write() instead.', __METHOD__), E_USER_DEPRECATED);
101
  $this->write($catalogue, $format, $options);
102
  }
103
  }
97
  */
98
  public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array())
99
  {
100
+ @trigger_error(sprintf('Method %s() is deprecated since Symfony 3.4 and will be removed in 4.0. Use write() instead.', __METHOD__), E_USER_DEPRECATED);
101
  $this->write($catalogue, $format, $options);
102
  }
103
  }
src/common/wp-admin-notices.php CHANGED
@@ -39,9 +39,8 @@ class ICWP_WPSF_WpAdminNotices extends ICWP_WPSF_Foundation {
39
  add_action( 'admin_notices', array( $this, 'onWpAdminNotices' ) );
40
  add_action( 'network_admin_notices', array( $this, 'onWpAdminNotices' ) );
41
  add_action( 'wp_loaded', array( $this, 'flushFlashMessage' ) );
42
-
43
  if ( $this->loadWp()->isAjax() ) {
44
- add_action( 'wp_ajax_icwp_DismissAdminNotice', array( $this, 'ajaxDismissAdminNotice' ) );
45
  }
46
  }
47
 
@@ -55,13 +54,12 @@ class ICWP_WPSF_WpAdminNotices extends ICWP_WPSF_Foundation {
55
 
56
  public function ajaxDismissAdminNotice() {
57
 
58
- $bSuccess = $this->checkAjaxNonce();
59
- if ( $bSuccess ) {
60
  // Get all notices and if this notice exists, we set it to "hidden"
61
- $sNoticeId = sanitize_key( $this->loadDataProcessor()->FetchGet( 'notice_id', '' ) );
62
  $aNotices = apply_filters( $this->getActionPrefix().'register_admin_notices', array() );
63
  if ( !empty( $sNoticeId ) && array_key_exists( $sNoticeId, $aNotices ) ) {
64
- $this->setAdminNoticeAsDismissed( $aNotices[ $sNoticeId ] );
65
  }
66
  $this->sendAjaxResponse( true );
67
  }
@@ -71,24 +69,50 @@ class ICWP_WPSF_WpAdminNotices extends ICWP_WPSF_Foundation {
71
  * @param string $sNoticeId
72
  * @return true
73
  */
74
- public function getAdminNoticeIsDismissed( $sNoticeId ) {
75
- $sCurrentMetaValue = $this->getAdminNoticeMeta( $sNoticeId );
76
- return ( $sCurrentMetaValue == 'Y' );
77
  }
78
 
79
  /**
80
  * @param string $sNoticeId
81
  * @return false|string
82
  */
83
- public function getAdminNoticeMeta( $sNoticeId ) {
84
- return $this->loadWpUsers()->getUserMeta( $this->getActionPrefix().$sNoticeId );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  /**
88
- * @param array $aNotice
 
89
  */
90
- public function setAdminNoticeAsDismissed( $aNotice ) {
91
- $this->loadWpUsers()->updateUserMeta( $this->getActionPrefix().$aNotice[ 'id' ], 'Y' );
 
 
 
 
 
 
 
92
  }
93
 
94
  /**
@@ -97,7 +121,7 @@ class ICWP_WPSF_WpAdminNotices extends ICWP_WPSF_Foundation {
97
  */
98
  protected function checkAjaxNonce() {
99
 
100
- $sNonce = $this->loadDataProcessor()->FetchRequest( '_ajax_nonce', '' );
101
  if ( empty( $sNonce ) ) {
102
  $sMessage = 'Nonce security checking failed - the nonce value was empty.';
103
  }
@@ -215,7 +239,7 @@ class ICWP_WPSF_WpAdminNotices extends ICWP_WPSF_Foundation {
215
  * @param string $sType
216
  */
217
  public function addFlashMessage( $sMessage, $sType = 'updated' ) {
218
- $this->loadDataProcessor()->setCookie(
219
  $this->getActionPrefix().'flash', $sType.'::'.esc_attr( $sMessage )
220
  );
221
  }
39
  add_action( 'admin_notices', array( $this, 'onWpAdminNotices' ) );
40
  add_action( 'network_admin_notices', array( $this, 'onWpAdminNotices' ) );
41
  add_action( 'wp_loaded', array( $this, 'flushFlashMessage' ) );
 
42
  if ( $this->loadWp()->isAjax() ) {
43
+ add_action( 'wp_ajax_icwp_wpsf_DismissAdminNotice', array( $this, 'ajaxDismissAdminNotice' ) );
44
  }
45
  }
46
 
54
 
55
  public function ajaxDismissAdminNotice() {
56
 
57
+ if ( $this->checkAjaxNonce() ) {
 
58
  // Get all notices and if this notice exists, we set it to "hidden"
59
+ $sNoticeId = sanitize_key( $this->loadDP()->query( 'notice_id', '' ) );
60
  $aNotices = apply_filters( $this->getActionPrefix().'register_admin_notices', array() );
61
  if ( !empty( $sNoticeId ) && array_key_exists( $sNoticeId, $aNotices ) ) {
62
+ $this->setMeta( $aNotices[ $sNoticeId ][ 'id' ] );
63
  }
64
  $this->sendAjaxResponse( true );
65
  }
69
  * @param string $sNoticeId
70
  * @return true
71
  */
72
+ public function isDismissed( $sNoticeId ) {
73
+ $aMeta = $this->getMeta( $sNoticeId );
74
+ return ( isset( $aMeta[ 'time' ] ) && $aMeta[ 'time' ] > 0 );
75
  }
76
 
77
  /**
78
  * @param string $sNoticeId
79
  * @return false|string
80
  */
81
+ public function getMeta( $sNoticeId ) {
82
+ $mValue = array();
83
+
84
+ $oMeta = $this->loadWpUsers()->metaVoForUser( rtrim( $this->getActionPrefix(), '-' ) );
85
+
86
+ $sCleanNotice = 'notice_'.str_replace( array( '-', '_' ), '', $sNoticeId );
87
+ if ( isset( $oMeta->{$sCleanNotice} ) && is_array( $oMeta->{$sCleanNotice} ) ) {
88
+ $mValue = $oMeta->{$sCleanNotice};
89
+ }
90
+ else {
91
+ $oWp = $this->loadWpUsers();
92
+ $mOldValue = $oWp->getUserMeta( $this->getActionPrefix().$sNoticeId );
93
+ if ( !empty( $mOldValue ) ) {
94
+ $oWp->deleteUserMeta( $this->getActionPrefix().$sNoticeId );
95
+ $this->setMeta( $sNoticeId );
96
+ $mValue = $oMeta->{$sCleanNotice};
97
+ }
98
+ }
99
+
100
+ return $mValue;
101
  }
102
 
103
  /**
104
+ * @param string $sNoticeId
105
+ * @param array $aMeta
106
  */
107
+ public function setMeta( $sNoticeId, $aMeta = array() ) {
108
+ if ( !is_array( $aMeta ) ) {
109
+ $aMeta = array();
110
+ }
111
+
112
+ $oMeta = $this->loadWpUsers()->metaVoForUser( rtrim( $this->getActionPrefix(), '-' ) );
113
+ $sCleanNotice = 'notice_'.str_replace( array( '-', '_' ), '', $sNoticeId );
114
+ $oMeta->{$sCleanNotice} = array_merge( array( 'time' => $this->loadDP()->time() ), $aMeta );
115
+ return;
116
  }
117
 
118
  /**
121
  */
122
  protected function checkAjaxNonce() {
123
 
124
+ $sNonce = $this->loadDP()->FetchRequest( '_ajax_nonce', '' );
125
  if ( empty( $sNonce ) ) {
126
  $sMessage = 'Nonce security checking failed - the nonce value was empty.';
127
  }
239
  * @param string $sType
240
  */
241
  public function addFlashMessage( $sMessage, $sType = 'updated' ) {
242
+ $this->loadDP()->setCookie(
243
  $this->getActionPrefix().'flash', $sType.'::'.esc_attr( $sMessage )
244
  );
245
  }
src/common/wp-users.php CHANGED
@@ -5,12 +5,18 @@ if ( class_exists( 'ICWP_WPSF_WpUsers', false ) ) {
5
 
6
  class ICWP_WPSF_WpUsers extends ICWP_WPSF_Foundation {
7
 
 
 
 
 
 
8
  /**
9
  * @var ICWP_WPSF_WpUsers
10
  */
11
  protected static $oInstance = null;
12
 
13
- private function __construct() {}
 
14
 
15
  /**
16
  * @return ICWP_WPSF_WpUsers
@@ -61,7 +67,7 @@ class ICWP_WPSF_WpUsers extends ICWP_WPSF_Foundation {
61
  /**
62
  * @return bool
63
  */
64
- public function getCanAddUpdateCurrentUserMeta() {
65
  $bCanMeta = false;
66
  try {
67
  if ( $this->isUserLoggedIn() ) {
@@ -168,6 +174,37 @@ class ICWP_WPSF_WpUsers extends ICWP_WPSF_Foundation {
168
  return function_exists( 'is_user_logged_in' ) && is_user_logged_in();
169
  }
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  /**
172
  * Fires the WordPress logout functions. If $bQuiet is true, it'll manually
173
  * call the WordPress logout code, so as not to fire any other logout actions
5
 
6
  class ICWP_WPSF_WpUsers extends ICWP_WPSF_Foundation {
7
 
8
+ /**
9
+ * @var ICWP_UserMeta[]
10
+ */
11
+ private $aMetas;
12
+
13
  /**
14
  * @var ICWP_WPSF_WpUsers
15
  */
16
  protected static $oInstance = null;
17
 
18
+ private function __construct() {
19
+ }
20
 
21
  /**
22
  * @return ICWP_WPSF_WpUsers
67
  /**
68
  * @return bool
69
  */
70
+ public function canSaveMeta() {
71
  $bCanMeta = false;
72
  try {
73
  if ( $this->isUserLoggedIn() ) {
174
  return function_exists( 'is_user_logged_in' ) && is_user_logged_in();
175
  }
176
 
177
+ /**
178
+ * @param string $sPrefix
179
+ * @param int $nUserId
180
+ * @return ICWP_UserMeta
181
+ */
182
+ public function metaVoForUser( $sPrefix, $nUserId = null ) {
183
+ if ( !class_exists( 'ICWP_UserMeta' ) ) {
184
+ $this->requireCommonLib( 'icwp-usermeta.php' );
185
+ }
186
+ if ( is_null( $nUserId ) ) {
187
+ $nUserId = $this->getCurrentWpUserId();
188
+ }
189
+
190
+ $aMetas = $this->getMetas();
191
+ if ( !isset( $aMetas[ $nUserId ] ) ) {
192
+ $aMetas[ $nUserId ] = new ICWP_UserMeta( $sPrefix, $nUserId );
193
+ $this->aMetas = $aMetas;
194
+ }
195
+ return $this->aMetas[ $nUserId ];
196
+ }
197
+
198
+ /**
199
+ * @return ICWP_UserMeta[]
200
+ */
201
+ protected function getMetas() {
202
+ if ( empty( $this->aMetas ) ) {
203
+ $this->aMetas = array();
204
+ }
205
+ return $this->aMetas;
206
+ }
207
+
208
  /**
209
  * Fires the WordPress logout functions. If $bQuiet is true, it'll manually
210
  * call the WordPress logout code, so as not to fire any other logout actions
src/config/feature-admin_access_restriction.php CHANGED
@@ -207,7 +207,6 @@
207
  ],
208
  "definitions": {
209
  "help_video_id": "214855538",
210
- "security_admin_cookie_name": "icwp_wpsf_aakcook",
211
  "admin_access_options_to_restrict": {
212
  "wpms_options": [
213
  "admin_email",
207
  ],
208
  "definitions": {
209
  "help_video_id": "214855538",
 
210
  "admin_access_options_to_restrict": {
211
  "wpms_options": [
212
  "admin_email",
src/config/feature-hack_protect.php CHANGED
@@ -21,15 +21,6 @@
21
  "Recommendation - Keep the Hack Protection feature turned on."
22
  ]
23
  },
24
- {
25
- "slug": "section_wpvuln_scan",
26
- "title": "Vulnerability Scanner",
27
- "title_short": "Vulnerability Scanner",
28
- "summary": [
29
- "Purpose - Regularly scan your WordPress plugins and themes for known security vulnerabilities.",
30
- "Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
31
- ]
32
- },
33
  {
34
  "slug": "section_core_file_integrity_scan",
35
  "title": "Core File Integrity Scanner",
@@ -48,6 +39,15 @@
48
  "Recommendation - Keep the Unrecognised Files Scanner feature turned on."
49
  ]
50
  },
 
 
 
 
 
 
 
 
 
51
  {
52
  "slug": "section_non_ui",
53
  "hidden": true
@@ -136,7 +136,7 @@
136
  "link_info": "http://icwp.io/wpsf36",
137
  "link_blog": "http://icwp.io/wpsf37",
138
  "name": "Core File Scanner",
139
- "summary": "Daily Cron - Scans WordPress Core Files For Alterations",
140
  "description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
141
  },
142
  {
@@ -150,6 +150,52 @@
150
  "summary": "Automatically Repair WordPress Core Files That Have Been Altered",
151
  "description": "Attempts to automatically repair WordPress Core files with the official WordPress file data, for files that have been altered or are missing."
152
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  {
154
  "key": "enable_unrecognised_file_cleaner_scan",
155
  "section": "section_unrecognised_file_scan",
21
  "Recommendation - Keep the Hack Protection feature turned on."
22
  ]
23
  },
 
 
 
 
 
 
 
 
 
24
  {
25
  "slug": "section_core_file_integrity_scan",
26
  "title": "Core File Integrity Scanner",
39
  "Recommendation - Keep the Unrecognised Files Scanner feature turned on."
40
  ]
41
  },
42
+ {
43
+ "slug": "section_wpvuln_scan",
44
+ "title": "Vulnerability Scanner",
45
+ "title_short": "Vulnerability Scanner",
46
+ "summary": [
47
+ "Purpose - Regularly scan your WordPress plugins and themes for known security vulnerabilities.",
48
+ "Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
49
+ ]
50
+ },
51
  {
52
  "slug": "section_non_ui",
53
  "hidden": true
136
  "link_info": "http://icwp.io/wpsf36",
137
  "link_blog": "http://icwp.io/wpsf37",
138
  "name": "Core File Scanner",
139
+ "summary": "Scans WordPress Core Files For Alterations",
140
  "description": "Compares all WordPress core files on your site against the official WordPress files. WordPress Core files should never be altered for any reason."
141
  },
142
  {
150
  "summary": "Automatically Repair WordPress Core Files That Have Been Altered",
151
  "description": "Attempts to automatically repair WordPress Core files with the official WordPress file data, for files that have been altered or are missing."
152
  },
153
+ {
154
+ "key": "scan_frequency",
155
+ "section": "section_enable_plugin_feature_hack_protection_tools",
156
+ "premium": true,
157
+ "default": 1,
158
+ "type": "select",
159
+ "value_options": [
160
+ {
161
+ "value_key": "1",
162
+ "text": "Once"
163
+ },
164
+ {
165
+ "value_key": "2",
166
+ "text": "Twice (scan every 12hrs)"
167
+ },
168
+ {
169
+ "value_key": "3",
170
+ "text": "3 Times (scan every 8hrs)"
171
+ },
172
+ {
173
+ "value_key": "4",
174
+ "text": "4 Times (scan every 6hrs)"
175
+ },
176
+ {
177
+ "value_key": "6",
178
+ "text": "6 Times (scan every 4hrs)"
179
+ },
180
+ {
181
+ "value_key": "8",
182
+ "text": "8 Times (scan every 3hrs)"
183
+ },
184
+ {
185
+ "value_key": "12",
186
+ "text": "12 Times (scan every 2hrs)"
187
+ },
188
+ {
189
+ "value_key": "24",
190
+ "text": "24 Times (scan every hour)"
191
+ }
192
+ ],
193
+ "link_info": "http://icwp.io/b2",
194
+ "link_blog": "",
195
+ "name": "Daily Frequency",
196
+ "summary": "Number Of Times To Automatically Scan Core Files In 24 Hours",
197
+ "description": "Default: Once every 24hrs. To improve security, increase the number of scans per day."
198
+ },
199
  {
200
  "key": "enable_unrecognised_file_cleaner_scan",
201
  "section": "section_unrecognised_file_scan",
src/config/feature-ips.php CHANGED
@@ -153,7 +153,7 @@
153
  "value_options": [
154
  {
155
  "value_key": "disabled",
156
- "text": "Ingore 404s"
157
  },
158
  {
159
  "value_key": "log-only",
153
  "value_options": [
154
  {
155
  "value_key": "disabled",
156
+ "text": "Ignore 404s"
157
  },
158
  {
159
  "value_key": "log-only",
src/config/feature-login_protect.php CHANGED
@@ -149,6 +149,18 @@
149
  "summary": "Require All Active Authentication Factors",
150
  "description": "When enabled, all multi-factor authentication methods will be applied to a user login. Disable to only require one to pass."
151
  },
 
 
 
 
 
 
 
 
 
 
 
 
152
  {
153
  "key": "enable_google_authenticator",
154
  "section": "section_multifactor_authentication",
@@ -374,17 +386,6 @@
374
  ],
375
  "definitions": {
376
  "login_intent_timeout": 5,
377
- "two_factor_auth_table_name": "login_auth",
378
- "two_factor_auth_table_columns": [
379
- "id",
380
- "session_id",
381
- "wp_username",
382
- "ip",
383
- "pending",
384
- "expired_at",
385
- "created_at",
386
- "deleted_at"
387
- ],
388
  "wizards": {
389
  "mfa": {
390
  "title": "Configure Multi-Factor Login Authentication",
149
  "summary": "Require All Active Authentication Factors",
150
  "description": "When enabled, all multi-factor authentication methods will be applied to a user login. Disable to only require one to pass."
151
  },
152
+ {
153
+ "key": "mfa_skip",
154
+ "section": "section_multifactor_authentication",
155
+ "premium": true,
156
+ "default": 0,
157
+ "type": "integer",
158
+ "link_info": "http://icwp.io/b1",
159
+ "link_blog": "",
160
+ "name": "Multi-Factor By-Pass",
161
+ "summary": "A User Can By-Pass Multi-Factor Authentication (MFA) For The Set Number Of Days",
162
+ "description": "Enter the number of days a user can by-pass future MFA after a successful MFA-login. 0 to disable."
163
+ },
164
  {
165
  "key": "enable_google_authenticator",
166
  "section": "section_multifactor_authentication",
386
  ],
387
  "definitions": {
388
  "login_intent_timeout": 5,
 
 
 
 
 
 
 
 
 
 
 
389
  "wizards": {
390
  "mfa": {
391
  "title": "Configure Multi-Factor Login Authentication",
src/config/feature-plugin.php CHANGED
@@ -20,7 +20,7 @@
20
  },
21
  "plugin-update-available": {
22
  "id": "plugin-update-available",
23
- "schedule": "version",
24
  "valid_admin": true,
25
  "type": "warning"
26
  },
@@ -33,9 +33,9 @@
33
  },
34
  "allow-tracking": {
35
  "id": "allow-tracking",
36
- "schedule": "never",
37
  "valid_admin": true,
38
- "delay_days": 0,
39
  "type": "promo"
40
  },
41
  "plugin-mailing-list-signup": {
@@ -435,6 +435,11 @@
435
  "load_priority": 11,
436
  "hidden": false
437
  },
 
 
 
 
 
438
  {
439
  "slug": "audit_trail",
440
  "storage_key": "audit_trail",
20
  },
21
  "plugin-update-available": {
22
  "id": "plugin-update-available",
23
+ "schedule": "conditions",
24
  "valid_admin": true,
25
  "type": "warning"
26
  },
33
  },
34
  "allow-tracking": {
35
  "id": "allow-tracking",
36
+ "schedule": "conditions",
37
  "valid_admin": true,
38
+ "delay_days": 1,
39
  "type": "promo"
40
  },
41
  "plugin-mailing-list-signup": {
435
  "load_priority": 11,
436
  "hidden": false
437
  },
438
+ {
439
+ "slug": "sessions",
440
+ "storage_key": "sessions",
441
+ "load_priority": 5
442
+ },
443
  {
444
  "slug": "audit_trail",
445
  "storage_key": "audit_trail",
src/config/feature-sessions.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "properties": {
3
+ "slug": "sessions",
4
+ "name": "Sessions",
5
+ "show_feature_menu_item": false,
6
+ "storage_key": "sessions",
7
+ "tagline": "User Sessions",
8
+ "auto_enabled": true,
9
+ "show_central": false,
10
+ "premium": false,
11
+ "access_restricted": true
12
+ },
13
+ "sections": [
14
+ {
15
+ "slug": "section_enable_plugin_feature_sessions",
16
+ "primary": true,
17
+ "title": "Enable Plugin Feature: Sessions",
18
+ "title_short": "Enable / Disable",
19
+ "summary": [
20
+ "Purpose - Creates and Manages User Sessions.",
21
+ "Recommendation - Keep the Sessions feature turned on."
22
+ ]
23
+ },
24
+ {
25
+ "slug": "section_non_ui",
26
+ "hidden": true
27
+ }
28
+ ],
29
+ "options": [
30
+ {
31
+ "key": "enable_sessions",
32
+ "section": "section_enable_plugin_feature_sessions",
33
+ "default": "Y",
34
+ "type": "checkbox",
35
+ "link_info": "",
36
+ "link_blog": "",
37
+ "name": "Enable Sessions",
38
+ "summary": "Enable (or Disable) The Sessions Feature",
39
+ "description": "Checking/Un-Checking this option will completely turn on/off the whole Sessions feature"
40
+ },
41
+ {
42
+ "key": "autoadd_sessions_started_at",
43
+ "transferable": false,
44
+ "section": "section_non_ui"
45
+ }
46
+ ],
47
+ "definitions": {
48
+ "sessions_table_name": "sessions",
49
+ "sessions_table_columns": [
50
+ "id",
51
+ "session_id",
52
+ "wp_username",
53
+ "ip",
54
+ "browser",
55
+ "logged_in_at",
56
+ "last_activity_at",
57
+ "last_activity_uri",
58
+ "secadmin_at",
59
+ "created_at",
60
+ "deleted_at"
61
+ ]
62
+ }
63
+ }
src/config/feature-support.php DELETED
@@ -1,48 +0,0 @@
1
- {
2
- "properties": {
3
- "slug": "support",
4
- "name": "Shield Central Pro",
5
- "show_feature_menu_item": false,
6
- "hide_summary": true,
7
- "storage_key": "support",
8
- "tagline": "Premium Plugin Support Centre",
9
- "auto_enabled": true,
10
- "highlight_menu_item": true,
11
- "show_central": false,
12
- "premium": false,
13
- "access_restricted": false
14
- },
15
- "sections": [
16
- {
17
- "slug": "section_enable_plugin_feature_support",
18
- "primary": true,
19
- "title": "Enable Plugin Feature: Premium",
20
- "title_short": "Enable / Disable",
21
- "summary": [
22
- "Purpose - Contact Plugin Premium Support Centre.",
23
- "Recommendation - Keep the Premium Support feature turned on."
24
- ]
25
- },
26
- {
27
- "slug": "section_non_ui",
28
- "hidden": true
29
- }
30
- ],
31
- "options": [
32
- {
33
- "key": "enable_support",
34
- "section": "section_enable_plugin_feature_support",
35
- "default": "Y",
36
- "type": "checkbox",
37
- "link_info": "",
38
- "link_blog": "",
39
- "name": "Enable Premium Support",
40
- "summary": "Enable (or Disable) The Premium Support Feature",
41
- "description": "Checking/Un-Checking this option will completely turn on/off the whole Premium Support feature"
42
- }
43
- ],
44
- "definitions": {
45
- "default_helpdesk_url": "http://icwp.io/shieldhelpdesk",
46
- "landing_page_url": "//icwp.io/shieldcentralpluginframe"
47
- }
48
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/config/feature-user_management.php CHANGED
@@ -123,23 +123,13 @@
123
  "name": "Max Simultaneous Sessions",
124
  "summary": "Limit Simultaneous Sessions For The Same Username",
125
  "description": "The number provided here is the maximum number of simultaneous, distinct, sessions allowed for any given username. Use '0' for no limits."
 
 
 
 
 
126
  }
127
  ],
128
  "definitions": {
129
- "user_sessions_table_name": "user_management",
130
- "user_sessions_table_columns": [
131
- "id",
132
- "session_id",
133
- "wp_username",
134
- "ip",
135
- "logged_in_at",
136
- "last_activity_at",
137
- "last_activity_uri",
138
- "used_mfa",
139
- "pending",
140
- "login_attempts",
141
- "created_at",
142
- "deleted_at"
143
- ]
144
  }
145
  }
123
  "name": "Max Simultaneous Sessions",
124
  "summary": "Limit Simultaneous Sessions For The Same Username",
125
  "description": "The number provided here is the maximum number of simultaneous, distinct, sessions allowed for any given username. Use '0' for no limits."
126
+ },
127
+ {
128
+ "key": "autoadd_sessions_started_at",
129
+ "transferable": false,
130
+ "section": "section_non_ui"
131
  }
132
  ],
133
  "definitions": {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
135
  }
src/features/admin_access_restriction.php CHANGED
@@ -48,8 +48,13 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
48
  $sResponseData = array();
49
  $bSuccess = $this->checkAdminAccessKeySubmission();
50
  if ( $bSuccess ) {
51
- $this->setPermissionToSubmit( true );
52
- $sResponseData[ 'html' ] = _wpsf__( 'Security Admin Access Key Accepted.' ).' '._wpsf__( 'Please wait' ).' ...';
 
 
 
 
 
53
  }
54
  else {
55
  $sResponseData[ 'html' ] = $this->renderAdminAccessAjaxLoginForm( _wpsf__( 'Error - Invalid Key' ) );
@@ -64,29 +69,23 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
64
  */
65
  public function doCheckHasPermissionToSubmit( $fHasPermission = true ) {
66
 
67
- // We don't use setPermissionToSubmit() here because of timing with headers - we just for now manually
68
- // checking POST for the submission of the key and if it fits, we say "yes"
69
- if ( $this->checkAdminAccessKeySubmission() ) {
70
- $this->bHasPermissionToSubmit = true;
71
- }
72
-
73
- if ( isset( $this->bHasPermissionToSubmit ) ) {
74
- return $this->bHasPermissionToSubmit;
75
- }
76
-
77
  $this->bHasPermissionToSubmit = $fHasPermission;
78
  if ( $this->getIsMainFeatureEnabled() ) {
79
-
80
- $sAccessKey = $this->getOpt( 'admin_access_key' );
81
  if ( !empty( $sAccessKey ) ) {
82
- $oDp = $this->loadDP();
83
- $sCookieValue = $oDp->cookie( $this->getSecurityAdminCookieName() );
84
- $this->bHasPermissionToSubmit = ( $sCookieValue === md5( $sAccessKey ) );
85
  }
86
  }
87
  return $this->bHasPermissionToSubmit;
88
  }
89
 
 
 
 
 
 
 
 
90
  /** TODO
91
  * @return bool
92
  */
@@ -124,11 +123,18 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
124
  return !is_array( $aSettings ) ? array() : $aSettings;
125
  }
126
 
 
 
 
 
 
 
 
127
  /**
128
  * @return array
129
  */
130
  public function getRestrictedOptions() {
131
- $aOptions = $this->getDefinition( 'admin_access_options_to_restrict' );
132
  return is_array( $aOptions ) ? $aOptions : array();
133
  }
134
 
@@ -154,60 +160,84 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
154
  }
155
 
156
  /**
 
157
  */
158
- protected function setAdminAccessCookie() {
159
- $sAccessKey = $this->getOpt( 'admin_access_key' );
160
- if ( !empty( $sAccessKey ) ) {
161
- $this->loadDP()
162
- ->setCookie(
163
- $this->getSecurityAdminCookieName(),
164
- md5( $sAccessKey ),
165
- $this->getOpt( 'admin_access_timeout' )*60
166
- );
167
- }
 
 
168
  }
169
 
170
  /**
171
  */
172
- protected function clearAdminAccessCookie() {
173
- $this->loadDataProcessor()->setDeleteCookie( $this->getSecurityAdminCookieName() );
 
 
174
  }
175
 
176
  /**
177
  */
178
  protected function doExtraSubmitProcessing() {
179
  // We should only use setPermissionToSubmit() here, before any headers elsewhere are sent out.
180
- if ( $this->checkAdminAccessKeySubmission() ) {
181
- $this->setPermissionToSubmit( true );
182
- // wp_safe_redirect( network_admin_url() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  }
184
  }
185
 
186
  /**
187
- * @return string
188
  */
189
- public function getSecurityAdminCookieName() {
190
- return $this->getDefinition( 'security_admin_cookie_name' );
 
 
 
 
 
191
  }
192
 
193
  /**
194
  * @param bool $fPermission
 
195
  */
196
  public function setPermissionToSubmit( $fPermission = false ) {
197
- if ( $fPermission ) {
198
- $this->setAdminAccessCookie();
199
- }
200
- else {
201
- $this->clearAdminAccessCookie();
202
- }
203
  }
204
 
205
  /**
206
  * @return bool
207
  */
208
  protected function checkAdminAccessKeySubmission() {
209
- $sAccessKeyRequest = $this->loadDP()
210
- ->FetchPost( $this->prefix( 'admin_access_key_request', '_' ) );
211
  $bSuccess = $this->verifyAccessKey( $sAccessKeyRequest );
212
  if ( !$bSuccess && !empty( $sAccessKeyRequest ) ) {
213
  add_filter( $this->prefix( 'ip_black_mark' ), '__return_true' );
@@ -215,6 +245,13 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
215
  return $bSuccess;
216
  }
217
 
 
 
 
 
 
 
 
218
  /**
219
  * @param string $sKey
220
  * @return bool
48
  $sResponseData = array();
49
  $bSuccess = $this->checkAdminAccessKeySubmission();
50
  if ( $bSuccess ) {
51
+ $bSuccess = $this->setPermissionToSubmit( true );
52
+ if ( $bSuccess ) {
53
+ $sResponseData[ 'html' ] = _wpsf__( 'Security Admin Access Key Accepted.' ).' '._wpsf__( 'Please wait' ).' ...';
54
+ }
55
+ else {
56
+ $sResponseData[ 'html' ] = _wpsf__( 'Failed to process key - you may need to re-login to WordPress.' );
57
+ }
58
  }
59
  else {
60
  $sResponseData[ 'html' ] = $this->renderAdminAccessAjaxLoginForm( _wpsf__( 'Error - Invalid Key' ) );
69
  */
70
  public function doCheckHasPermissionToSubmit( $fHasPermission = true ) {
71
 
 
 
 
 
 
 
 
 
 
 
72
  $this->bHasPermissionToSubmit = $fHasPermission;
73
  if ( $this->getIsMainFeatureEnabled() ) {
74
+ $sAccessKey = $this->getAccessKeyHash();
 
75
  if ( !empty( $sAccessKey ) ) {
76
+ $this->bHasPermissionToSubmit = $this->isSecAdminSessionValid() || $this->checkAdminAccessKeySubmission();
 
 
77
  }
78
  }
79
  return $this->bHasPermissionToSubmit;
80
  }
81
 
82
+ /**
83
+ * @return string
84
+ */
85
+ protected function getAccessKeyHash() {
86
+ return $this->getOpt( 'admin_access_key' );
87
+ }
88
+
89
  /** TODO
90
  * @return bool
91
  */
123
  return !is_array( $aSettings ) ? array() : $aSettings;
124
  }
125
 
126
+ /**
127
+ * @return bool
128
+ */
129
+ public function getIsMainFeatureEnabled() {
130
+ return parent::getIsMainFeatureEnabled() && $this->hasAccessKey();
131
+ }
132
+
133
  /**
134
  * @return array
135
  */
136
  public function getRestrictedOptions() {
137
+ $aOptions = $this->getDef( 'admin_access_options_to_restrict' );
138
  return is_array( $aOptions ) ? $aOptions : array();
139
  }
140
 
160
  }
161
 
162
  /**
163
+ * @return bool
164
  */
165
+ protected function hasAccessKey() {
166
+ $sKey = $this->getAccessKeyHash();
167
+ return !empty( $sKey ) && strlen( $sKey ) == 32;
168
+ }
169
+
170
+ /**
171
+ * @return bool
172
+ */
173
+ protected function startSecurityAdmin() {
174
+ return $this->getSessionsProcessor()
175
+ ->getSessionUpdater()
176
+ ->startSecurityAdmin( $this->getSession() );
177
  }
178
 
179
  /**
180
  */
181
+ protected function terminateSecurityAdmin() {
182
+ return $this->getSessionsProcessor()
183
+ ->getSessionUpdater()
184
+ ->terminateSecurityAdmin( $this->getSession() );
185
  }
186
 
187
  /**
188
  */
189
  protected function doExtraSubmitProcessing() {
190
  // We should only use setPermissionToSubmit() here, before any headers elsewhere are sent out.
191
+ if ( $this->isAccessKeyRequest() ) {
192
+ if ( $this->checkAdminAccessKeySubmission() ) {
193
+ $this->setPermissionToSubmit( true );
194
+ }
195
+ }
196
+ }
197
+
198
+ protected function setSaveUserResponse() {
199
+ if ( $this->isAccessKeyRequest() ) {
200
+ $bSuccess = $this->doCheckHasPermissionToSubmit();
201
+ if ( $bSuccess ) {
202
+ $sMessage = sprintf( _wpsf__( '%s Security Admin key accepted.' ), self::getConn()->getHumanName() );
203
+ }
204
+ else {
205
+ $sMessage = sprintf( _wpsf__( '%s Security Admin key not accepted.' ), self::getConn()
206
+ ->getHumanName() );
207
+ }
208
+ $this->loadAdminNoticesProcessor()
209
+ ->addFlashMessage( $sMessage, $bSuccess ? 'updated' : 'error' );
210
+ }
211
+ else {
212
+ parent::setSaveUserResponse();
213
  }
214
  }
215
 
216
  /**
217
+ * @return bool
218
  */
219
+ protected function isSecAdminSessionValid() {
220
+ $bValid = false;
221
+ if ( $this->hasSession() ) {
222
+ $nStartedAt = $this->getSession()->getSecAdminAt();
223
+ $bValid = ( $this->loadDP()->time() - $nStartedAt ) < $this->getOpt( 'admin_access_timeout' )*60;
224
+ }
225
+ return $bValid;
226
  }
227
 
228
  /**
229
  * @param bool $fPermission
230
+ * @return bool
231
  */
232
  public function setPermissionToSubmit( $fPermission = false ) {
233
+ return $fPermission ? $this->startSecurityAdmin() : $this->terminateSecurityAdmin();
 
 
 
 
 
234
  }
235
 
236
  /**
237
  * @return bool
238
  */
239
  protected function checkAdminAccessKeySubmission() {
240
+ $sAccessKeyRequest = $this->loadDP()->post( 'admin_access_key_request', '' );
 
241
  $bSuccess = $this->verifyAccessKey( $sAccessKeyRequest );
242
  if ( !$bSuccess && !empty( $sAccessKeyRequest ) ) {
243
  add_filter( $this->prefix( 'ip_black_mark' ), '__return_true' );
245
  return $bSuccess;
246
  }
247
 
248
+ /**
249
+ * @return bool
250
+ */
251
+ protected function isAccessKeyRequest() {
252
+ return strlen( $this->loadDP()->post( 'admin_access_key_request', '' ) ) > 0;
253
+ }
254
+
255
  /**
256
  * @param string $sKey
257
  * @return bool
src/features/base.php CHANGED
@@ -360,7 +360,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
360
  public function getUrl_AdminPage() {
361
  return $this->loadWp()
362
  ->getUrl_AdminPage(
363
- $this->prefix( $this->getFeatureSlug() ),
364
  self::getConn()->getIsWpmsNetworkAdminOnly()
365
  );
366
  }
@@ -426,6 +426,14 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
426
  return $this->sFeatureSlug;
427
  }
428
 
 
 
 
 
 
 
 
 
429
  /**
430
  * @return int
431
  */
@@ -463,8 +471,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
463
  $sMenuPageTitle = $sMenuTitleName.' - '.$sHumanName;
464
  $aItems[ $sMenuPageTitle ] = array(
465
  $sMenuTitleName,
466
- $this->prefix( $this->getFeatureSlug() ),
467
- array( $this, 'displayFeatureConfigPage' )
468
  );
469
 
470
  $aAdditionalItems = $this->getOptionsVo()->getAdditionalMenuItems();
@@ -511,7 +519,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
511
  'slug' => $this->getFeatureSlug(),
512
  'name' => $this->getMainFeatureName(),
513
  'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : $sMenuTitle,
514
- 'href' => network_admin_url( 'admin.php?page='.$this->prefix( $this->getFeatureSlug() ) ),
515
  );
516
  $aSummary[ 'content' ] = $this->renderTemplate( 'snippets/summary_single', $aSummary );
517
 
@@ -541,11 +549,21 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
541
  }
542
 
543
  /**
544
- * @param string $sDefinitionKey
 
545
  * @return mixed|null
546
  */
547
- public function getDefinition( $sDefinitionKey ) {
548
- return $this->getOptionsVo()->getFeatureDefinition( $sDefinitionKey );
 
 
 
 
 
 
 
 
 
549
  }
550
 
551
  /**
@@ -694,10 +712,10 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
694
  * @return bool
695
  */
696
  protected function isValidAjaxRequestForModule() {
697
- $oDp = $this->loadDataProcessor();
698
 
699
  $bValid = $this->loadWp()->isAjax()
700
- && ( $this->prefix( $this->getFeatureSlug() ) == $oDp->post( 'icwp_action_module', '' ) );
701
  if ( $bValid ) {
702
  $aItems = array_keys( $this->getBaseAjaxActionRenderData() );
703
  foreach ( $aItems as $sKey ) {
@@ -720,7 +738,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
720
  'icwp_ajax_action' => $this->prefix( $sAction ),
721
  'icwp_nonce' => $this->genNonce( $sAction ),
722
  'icwp_nonce_action' => $sAction,
723
- 'icwp_action_module' => $this->prefix( $this->getFeatureSlug() ),
724
  'ajaxurl' => admin_url( 'admin-ajax.php' ),
725
  );
726
  return $bAsJsonEncodedObject ? json_encode( (object)$aData ) : $aData;
@@ -730,7 +748,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
730
  add_action( 'wp_ajax_icwp_OptionsFormSave', array( $this, 'ajaxOptionsFormSave' ) );
731
 
732
  // TODO: move this to the wizard handler itself
733
- if ( $this->getCanRunWizards() && $this->hasWizard() ) {
734
  $oWiz = $this->getWizardHandler();
735
  if ( !is_null( $oWiz ) ) {
736
  add_action( $this->prefixWpAjax( 'WizardProcessStepSubmit' ), array(
@@ -879,10 +897,11 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
879
 
880
  if ( !empty( $aSection[ 'options' ] ) ) {
881
 
882
- foreach ( $aSection[ 'options' ] as $nKey => $aOptionParams ) {
883
- $bIsPrem = isset( $aOptionParams[ 'premium' ] ) && $aOptionParams[ 'premium' ];
 
884
  if ( !$bIsPrem || $bPremiumEnabled ) {
885
- $aSection[ 'options' ][ $nKey ] = $this->buildOptionForUi( $aOptionParams );
886
  }
887
  else {
888
  unset( $aSection[ 'options' ][ $nKey ] );
@@ -911,53 +930,53 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
911
  */
912
  protected function buildOptionForUi( $aOptParams ) {
913
 
914
- $mCurrentVal = $aOptParams[ 'value' ];
915
 
916
  switch ( $aOptParams[ 'type' ] ) {
917
 
918
  case 'password':
919
- if ( !empty( $mCurrentVal ) ) {
920
- $mCurrentVal = '';
921
  }
922
  break;
923
 
924
  case 'array':
925
 
926
- if ( empty( $mCurrentVal ) || !is_array( $mCurrentVal ) ) {
927
- $mCurrentVal = array();
928
  }
929
 
930
- $aOptParams[ 'rows' ] = count( $mCurrentVal ) + 2;
931
- $mCurrentVal = stripslashes( implode( "\n", $mCurrentVal ) );
932
 
933
  break;
934
 
935
  case 'comma_separated_lists':
936
 
937
  $aNewValues = array();
938
- if ( !empty( $mCurrentVal ) && is_array( $mCurrentVal ) ) {
939
 
940
- foreach ( $mCurrentVal as $sPage => $aParams ) {
941
  $aNewValues[] = $sPage.', '.implode( ", ", $aParams );
942
  }
943
  }
944
  $aOptParams[ 'rows' ] = count( $aNewValues ) + 1;
945
- $mCurrentVal = implode( "\n", $aNewValues );
946
 
947
  break;
948
 
949
  case 'multiple_select':
950
- if ( !is_array( $mCurrentVal ) ) {
951
- $mCurrentVal = array();
952
  }
953
  break;
954
 
955
  case 'text':
956
- $mCurrentVal = stripslashes( $this->getTextOpt( $aOptParams[ 'key' ] ) );
957
  break;
958
  }
959
 
960
- $aOptParams[ 'value' ] = is_scalar( $mCurrentVal ) ? esc_attr( $mCurrentVal ) : $mCurrentVal;
961
  $aOptParams[ 'disabled' ] = !$this->isPremium() && ( isset( $aOptParams[ 'premium' ] ) && $aOptParams[ 'premium' ] );
962
  $aOptParams[ 'enabled' ] = !$aOptParams[ 'disabled' ];
963
  // add strings
@@ -1018,8 +1037,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1018
 
1019
  public function ajaxOptionsFormSave() {
1020
 
1021
- $sProcessingModule = $this->loadDataProcessor()->FetchPost( $this->prefixOptionKey( 'feature_slug' ) );
1022
- if ( $this->getFeatureSlug() != $sProcessingModule ) {
1023
  return;
1024
  }
1025
 
@@ -1055,6 +1073,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1055
  if ( $bVerified ) {
1056
  $this->doSaveStandardOptions();
1057
  $this->doExtraSubmitProcessing();
 
1058
  }
1059
  return $bVerified;
1060
  }
@@ -1073,9 +1092,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1073
  * @return void
1074
  */
1075
  protected function doSaveStandardOptions() {
1076
- $sAllOptions = $this->loadDataProcessor()
1077
- ->FetchPost( $this->prefixOptionKey( 'all_options_input' ) );
1078
-
1079
  if ( !empty( $sAllOptions ) ) {
1080
  $this->updatePluginOptionsFromSubmit( $sAllOptions );
1081
  }
@@ -1084,6 +1101,14 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1084
  protected function doExtraSubmitProcessing() {
1085
  }
1086
 
 
 
 
 
 
 
 
 
1087
  /**
1088
  * @return bool
1089
  */
@@ -1114,7 +1139,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1114
  * @param string $sAllOptionsInput - comma separated list of all the input keys to be processed from the $_POST
1115
  * @return void
1116
  */
1117
- public function updatePluginOptionsFromSubmit( $sAllOptionsInput ) {
1118
  if ( empty( $sAllOptionsInput ) ) {
1119
  return;
1120
  }
@@ -1125,7 +1150,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1125
  $aInput = explode( ':', $sInputKey );
1126
  list( $sOptionType, $sOptionKey ) = $aInput;
1127
 
1128
- $sOptionValue = $oDp->FetchPost( $this->prefixOptionKey( $sOptionKey ) );
1129
  if ( is_null( $sOptionValue ) ) {
1130
 
1131
  if ( $sOptionType == 'text' || $sOptionType == 'email' ) { //if it was a text box, and it's null, don't update anything
@@ -1184,7 +1209,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1184
  /**
1185
  */
1186
  protected function runWizards() {
1187
- if ( $this->getCanRunWizards() && $this->isWizardPage() && $this->hasWizard() ) {
1188
  $oWiz = $this->getWizardHandler();
1189
  if ( $oWiz instanceof ICWP_WPSF_Wizard_Base ) {
1190
  $oWiz->init();
@@ -1196,7 +1221,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1196
  * @return bool
1197
  */
1198
  protected function isModulePage() {
1199
- return $this->loadDP()->query( 'page' ) == $this->prefix( $this->getFeatureSlug() );
1200
  }
1201
 
1202
  /**
@@ -1244,6 +1269,21 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1244
  );
1245
  }
1246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1247
  /**
1248
  * @param string
1249
  * @return string
@@ -1254,7 +1294,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1254
 
1255
  /**
1256
  */
1257
- public function displayFeatureConfigPage() {
1258
  if ( $this->canDisplayOptionsForm() ) {
1259
  $this->displayModulePage();
1260
  }
@@ -1285,15 +1325,12 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1285
  self::$sActivelyDisplayedModuleOptions = $this->getFeatureSlug();
1286
 
1287
  $aData = array(
1288
- 'var_prefix' => $oCon->getOptionStoragePrefix(),
1289
  'sPluginName' => $oCon->getHumanName(),
1290
  'sFeatureName' => $this->getMainFeatureName(),
1291
  'bFeatureEnabled' => $this->getIsMainFeatureEnabled(),
1292
- 'feature_slug' => self::$sActivelyDisplayedModuleOptions,
1293
  'sTagline' => $this->getOptionsVo()->getFeatureTagline(),
1294
  'nonce_field' => wp_nonce_field( $oCon->getPluginPrefix(), '_wpnonce', true, false ), //don't echo!
1295
- 'sFeatureSlug' => $this->prefix( $this->getFeatureSlug() ),
1296
- 'form_action' => 'admin.php?page='.$this->prefix( $this->getFeatureSlug() ),
1297
  'nOptionsPerRow' => 1,
1298
  'aPluginLabels' => $oCon->getPluginLabels(),
1299
  'help_video' => array(
@@ -1310,11 +1347,14 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1310
 
1311
  'aSummaryData' => apply_filters( $this->prefix( 'get_feature_summary_data' ), array() ),
1312
 
1313
- 'aAllOptions' => $this->buildOptions(),
1314
- 'aHiddenOptions' => $this->getOptionsVo()->getHiddenOptions(),
1315
- 'all_options_input' => $this->collateAllFormInputsForAllOptions(),
1316
-
1317
  'sPageTitle' => sprintf( '%s: %s', $oCon->getHumanName(), $this->getMainFeatureName() ),
 
 
 
 
 
 
 
1318
  'strings' => array(
1319
  'go_to_settings' => __( 'Settings' ),
1320
  'on' => __( 'On' ),
@@ -1331,8 +1371,9 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1331
  'wrap_page_content' => true,
1332
  'show_standard_options' => true,
1333
  'show_content_actions' => $this->hasCustomActions(),
 
1334
  'show_alt_content' => false,
1335
- 'can_wizard' => $this->getCanRunWizards(),
1336
  'has_wizard' => $this->hasWizard(),
1337
  ),
1338
  'hrefs' => array(
@@ -1343,9 +1384,10 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1343
  'primary_wizard' => $this->getUrl_WizardPrimary(),
1344
  ),
1345
  'content' => array(
1346
- 'alt' => '',
1347
- 'actions' => $this->getContentCustomActions(),
1348
- 'help' => $this->getContentHelp()
 
1349
  )
1350
  );
1351
  $aData[ 'flags' ][ 'show_content_help' ] = strpos( $aData[ 'content' ][ 'help' ], 'Error:' ) !== 0;
@@ -1359,13 +1401,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1359
  return '<h3 style="margin: 10px 0 100px">'._wpsf__( 'No Actions For This Module' ).'</h3>';
1360
  }
1361
 
1362
- /**
1363
- * @return bool
1364
- */
1365
- public function getCanRunWizards() {
1366
- return $this->loadDP()->getPhpVersionIsAtLeast( '5.4.0' );
1367
- }
1368
-
1369
  /**
1370
  * @return string
1371
  */
@@ -1388,7 +1423,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1388
  public function getUrl_Wizard( $sWizardSlug ) {
1389
  return add_query_arg(
1390
  array(
1391
- 'page' => $this->prefix( $this->getFeatureSlug() ),
1392
  'shield_action' => 'wizard',
1393
  'wizard' => $sWizardSlug,
1394
  'nonwizard' => wp_create_nonce( 'wizard'.$sWizardSlug )
@@ -1416,7 +1451,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1416
  * @return array
1417
  */
1418
  public function getWizardDefinitions() {
1419
- $aW = $this->getDefinition( 'wizards' );
1420
  return is_array( $aW ) ? $aW : array();
1421
  }
1422
 
@@ -1438,7 +1473,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1438
  * @return boolean
1439
  */
1440
  protected function getIsShowMarketing() {
1441
- return apply_filters( $this->prefix( 'show_marketing' ), !$this->isPremium() );
1442
  }
1443
 
1444
  /**
@@ -1455,7 +1490,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1455
  }
1456
 
1457
  // Get the same Base Data as normal display
1458
- $aData = apply_filters( $this->prefix( $this->getFeatureSlug().'display_data' ), $this->getBaseDisplayData() );
1459
  $aData[ 'strings' ] = array_merge( $aData[ 'strings' ], $this->getDisplayStrings() );
1460
  return $this->loadRenderer( self::getConn()->getPath_Templates() )
1461
  ->setTemplate( $sTemplate )
@@ -1471,6 +1506,13 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1471
  ->getHasPermissionToView() : true;
1472
  }
1473
 
 
 
 
 
 
 
 
1474
  /**
1475
  * @param array $aData
1476
  * @param string $sSubView
@@ -1486,9 +1528,9 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1486
  $sSubView = $oRndr->getTemplateExists( $sModuleView ) ? $sModuleView : 'feature-default';
1487
  }
1488
 
1489
- $aData[ 'sFeatureInclude' ] = $this->loadDataProcessor()->addExtensionToFilePath( $sSubView, '.php' );
1490
  $aData[ 'strings' ] = array_merge( $aData[ 'strings' ], $this->getDisplayStrings() );
1491
- $aData[ 'options_form' ] = $this->renderOptionsForm();
1492
  try {
1493
  echo $oRndr
1494
  ->setTemplate( 'index.php' )
@@ -1500,38 +1542,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1500
  }
1501
  }
1502
 
1503
- /**
1504
- * @param array $aData
1505
- * @param string $sSubView
1506
- */
1507
- protected function displayByTemplate( $aData = array(), $sSubView = '' ) {
1508
-
1509
- $oCon = self::getConn();
1510
- // Get Base Data
1511
- $aData = apply_filters( $this->prefix( $this->getFeatureSlug().'display_data' ), array_merge( $this->getBaseDisplayData(), $aData ) );
1512
- $bPermissionToView = $oCon->getHasPermissionToView();
1513
-
1514
- if ( !$bPermissionToView ) {
1515
- $sSubView = 'subfeature-access_restricted';
1516
- }
1517
-
1518
- if ( empty( $sSubView ) ) {
1519
- $oWpFs = $this->loadFS();
1520
- $sFeatureInclude = 'feature-'.$this->getFeatureSlug();
1521
- if ( $oWpFs->exists( $oCon->getPath_TemplatesFile( $sFeatureInclude ) ) ) {
1522
- $sSubView = $sFeatureInclude;
1523
- }
1524
- else {
1525
- $sSubView = 'feature-default';
1526
- }
1527
- }
1528
-
1529
- $aData[ 'sFeatureInclude' ] = $sSubView;
1530
- $aData[ 'strings' ] = array_merge( $aData[ 'strings' ], $this->getDisplayStrings() );
1531
-
1532
- echo $this->renderTemplate( 'features/'.$sSubView, $aData );
1533
- }
1534
-
1535
  /**
1536
  * @param array $aData
1537
  * @return string
@@ -1553,10 +1563,11 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1553
  $aData[ 'notice_classes' ] = array();
1554
  }
1555
  if ( is_array( $aData[ 'notice_classes' ] ) ) {
1556
- if ( empty( $aData[ 'notice_classes' ] ) ) {
 
 
1557
  $aData[ 'notice_classes' ][] = 'updated';
1558
  }
1559
- $aData[ 'notice_classes' ][] = $aData[ 'notice_attributes' ][ 'type' ];
1560
  }
1561
  $aData[ 'notice_classes' ] = implode( ' ', $aData[ 'notice_classes' ] );
1562
 
360
  public function getUrl_AdminPage() {
361
  return $this->loadWp()
362
  ->getUrl_AdminPage(
363
+ $this->getModSlug(),
364
  self::getConn()->getIsWpmsNetworkAdminOnly()
365
  );
366
  }
426
  return $this->sFeatureSlug;
427
  }
428
 
429
+ /**
430
+ * @param bool $bWithPrefix
431
+ * @return string
432
+ */
433
+ public function getModSlug( $bWithPrefix = true ) {
434
+ return $bWithPrefix ? $this->prefix( $this->getFeatureSlug() ) : $this->getFeatureSlug();
435
+ }
436
+
437
  /**
438
  * @return int
439
  */
471
  $sMenuPageTitle = $sMenuTitleName.' - '.$sHumanName;
472
  $aItems[ $sMenuPageTitle ] = array(
473
  $sMenuTitleName,
474
+ $this->getModSlug(),
475
+ array( $this, 'displayModuleAdminPage' )
476
  );
477
 
478
  $aAdditionalItems = $this->getOptionsVo()->getAdditionalMenuItems();
519
  'slug' => $this->getFeatureSlug(),
520
  'name' => $this->getMainFeatureName(),
521
  'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : $sMenuTitle,
522
+ 'href' => network_admin_url( 'admin.php?page='.$this->getModSlug() ),
523
  );
524
  $aSummary[ 'content' ] = $this->renderTemplate( 'snippets/summary_single', $aSummary );
525
 
549
  }
550
 
551
  /**
552
+ * Get config 'definition'.
553
+ * @param string $sKey
554
  * @return mixed|null
555
  */
556
+ public function getDef( $sKey ) {
557
+ return $this->getOptionsVo()->getFeatureDefinition( $sKey );
558
+ }
559
+
560
+ /**
561
+ * @deprecated
562
+ * @param string $sKey
563
+ * @return mixed|null
564
+ */
565
+ public function getDefinition( $sKey ) {
566
+ return $this->getDef( $sKey );
567
  }
568
 
569
  /**
712
  * @return bool
713
  */
714
  protected function isValidAjaxRequestForModule() {
715
+ $oDp = $this->loadDP();
716
 
717
  $bValid = $this->loadWp()->isAjax()
718
+ && ( $this->getModSlug() == $oDp->post( 'icwp_action_module', '' ) );
719
  if ( $bValid ) {
720
  $aItems = array_keys( $this->getBaseAjaxActionRenderData() );
721
  foreach ( $aItems as $sKey ) {
738
  'icwp_ajax_action' => $this->prefix( $sAction ),
739
  'icwp_nonce' => $this->genNonce( $sAction ),
740
  'icwp_nonce_action' => $sAction,
741
+ 'icwp_action_module' => $this->getModSlug(),
742
  'ajaxurl' => admin_url( 'admin-ajax.php' ),
743
  );
744
  return $bAsJsonEncodedObject ? json_encode( (object)$aData ) : $aData;
748
  add_action( 'wp_ajax_icwp_OptionsFormSave', array( $this, 'ajaxOptionsFormSave' ) );
749
 
750
  // TODO: move this to the wizard handler itself
751
+ if ( $this->canRunWizards() && $this->hasWizard() ) {
752
  $oWiz = $this->getWizardHandler();
753
  if ( !is_null( $oWiz ) ) {
754
  add_action( $this->prefixWpAjax( 'WizardProcessStepSubmit' ), array(
897
 
898
  if ( !empty( $aSection[ 'options' ] ) ) {
899
 
900
+ foreach ( $aSection[ 'options' ] as $nKey => $aOption ) {
901
+ $aOption[ 'is_value_default' ] = ( $aOption[ 'value' ] === $aOption[ 'default' ] );
902
+ $bIsPrem = isset( $aOption[ 'premium' ] ) && $aOption[ 'premium' ];
903
  if ( !$bIsPrem || $bPremiumEnabled ) {
904
+ $aSection[ 'options' ][ $nKey ] = $this->buildOptionForUi( $aOption );
905
  }
906
  else {
907
  unset( $aSection[ 'options' ][ $nKey ] );
930
  */
931
  protected function buildOptionForUi( $aOptParams ) {
932
 
933
+ $mCurrent = $aOptParams[ 'value' ];
934
 
935
  switch ( $aOptParams[ 'type' ] ) {
936
 
937
  case 'password':
938
+ if ( !empty( $mCurrent ) ) {
939
+ $mCurrent = '';
940
  }
941
  break;
942
 
943
  case 'array':
944
 
945
+ if ( empty( $mCurrent ) || !is_array( $mCurrent ) ) {
946
+ $mCurrent = array();
947
  }
948
 
949
+ $aOptParams[ 'rows' ] = count( $mCurrent ) + 2;
950
+ $mCurrent = stripslashes( implode( "\n", $mCurrent ) );
951
 
952
  break;
953
 
954
  case 'comma_separated_lists':
955
 
956
  $aNewValues = array();
957
+ if ( !empty( $mCurrent ) && is_array( $mCurrent ) ) {
958
 
959
+ foreach ( $mCurrent as $sPage => $aParams ) {
960
  $aNewValues[] = $sPage.', '.implode( ", ", $aParams );
961
  }
962
  }
963
  $aOptParams[ 'rows' ] = count( $aNewValues ) + 1;
964
+ $mCurrent = implode( "\n", $aNewValues );
965
 
966
  break;
967
 
968
  case 'multiple_select':
969
+ if ( !is_array( $mCurrent ) ) {
970
+ $mCurrent = array();
971
  }
972
  break;
973
 
974
  case 'text':
975
+ $mCurrent = stripslashes( $this->getTextOpt( $aOptParams[ 'key' ] ) );
976
  break;
977
  }
978
 
979
+ $aOptParams[ 'value' ] = is_scalar( $mCurrent ) ? esc_attr( $mCurrent ) : $mCurrent;
980
  $aOptParams[ 'disabled' ] = !$this->isPremium() && ( isset( $aOptParams[ 'premium' ] ) && $aOptParams[ 'premium' ] );
981
  $aOptParams[ 'enabled' ] = !$aOptParams[ 'disabled' ];
982
  // add strings
1037
 
1038
  public function ajaxOptionsFormSave() {
1039
 
1040
+ if ( $this->getModSlug() != $this->loadDP()->post( 'mod_slug' ) ) {
 
1041
  return;
1042
  }
1043
 
1073
  if ( $bVerified ) {
1074
  $this->doSaveStandardOptions();
1075
  $this->doExtraSubmitProcessing();
1076
+ $this->setSaveUserResponse();
1077
  }
1078
  return $bVerified;
1079
  }
1092
  * @return void
1093
  */
1094
  protected function doSaveStandardOptions() {
1095
+ $sAllOptions = $this->loadDP()->post( 'all_options_input' );
 
 
1096
  if ( !empty( $sAllOptions ) ) {
1097
  $this->updatePluginOptionsFromSubmit( $sAllOptions );
1098
  }
1101
  protected function doExtraSubmitProcessing() {
1102
  }
1103
 
1104
+ protected function setSaveUserResponse() {
1105
+ if ( !$this->loadWp()->isAjax() && $this->isModulePage() ) {
1106
+ $this->loadAdminNoticesProcessor()
1107
+ ->addFlashMessage( sprintf( _wpsf__( '%s Plugin options updated successfully.' ), self::getConn()
1108
+ ->getHumanName() ) );
1109
+ }
1110
+ }
1111
+
1112
  /**
1113
  * @return bool
1114
  */
1139
  * @param string $sAllOptionsInput - comma separated list of all the input keys to be processed from the $_POST
1140
  * @return void
1141
  */
1142
+ protected function updatePluginOptionsFromSubmit( $sAllOptionsInput ) {
1143
  if ( empty( $sAllOptionsInput ) ) {
1144
  return;
1145
  }
1150
  $aInput = explode( ':', $sInputKey );
1151
  list( $sOptionType, $sOptionKey ) = $aInput;
1152
 
1153
+ $sOptionValue = $oDp->post( $sOptionKey );
1154
  if ( is_null( $sOptionValue ) ) {
1155
 
1156
  if ( $sOptionType == 'text' || $sOptionType == 'email' ) { //if it was a text box, and it's null, don't update anything
1209
  /**
1210
  */
1211
  protected function runWizards() {
1212
+ if ( $this->canRunWizards() && $this->isWizardPage() && $this->hasWizard() ) {
1213
  $oWiz = $this->getWizardHandler();
1214
  if ( $oWiz instanceof ICWP_WPSF_Wizard_Base ) {
1215
  $oWiz->init();
1221
  * @return bool
1222
  */
1223
  protected function isModulePage() {
1224
+ return $this->loadDP()->query( 'page' ) == $this->getModSlug();
1225
  }
1226
 
1227
  /**
1269
  );
1270
  }
1271
 
1272
+ /**
1273
+ * @param $oUser WP_User
1274
+ * @return ICWP_UserMeta
1275
+ */
1276
+ public function getUserMeta( $oUser ) {
1277
+ return $this->loadWpUsers()->metaVoForUser( $this->prefix(), $oUser->ID );
1278
+ }
1279
+
1280
+ /**
1281
+ * @return ICWP_UserMeta
1282
+ */
1283
+ public function getCurrentUserMeta() {
1284
+ return $this->loadWpUsers()->metaVoForUser( $this->prefix() );
1285
+ }
1286
+
1287
  /**
1288
  * @param string
1289
  * @return string
1294
 
1295
  /**
1296
  */
1297
+ public function displayModuleAdminPage() {
1298
  if ( $this->canDisplayOptionsForm() ) {
1299
  $this->displayModulePage();
1300
  }
1325
  self::$sActivelyDisplayedModuleOptions = $this->getFeatureSlug();
1326
 
1327
  $aData = array(
 
1328
  'sPluginName' => $oCon->getHumanName(),
1329
  'sFeatureName' => $this->getMainFeatureName(),
1330
  'bFeatureEnabled' => $this->getIsMainFeatureEnabled(),
 
1331
  'sTagline' => $this->getOptionsVo()->getFeatureTagline(),
1332
  'nonce_field' => wp_nonce_field( $oCon->getPluginPrefix(), '_wpnonce', true, false ), //don't echo!
1333
+ 'form_action' => 'admin.php?page='.$this->getModSlug(),
 
1334
  'nOptionsPerRow' => 1,
1335
  'aPluginLabels' => $oCon->getPluginLabels(),
1336
  'help_video' => array(
1347
 
1348
  'aSummaryData' => apply_filters( $this->prefix( 'get_feature_summary_data' ), array() ),
1349
 
 
 
 
 
1350
  'sPageTitle' => sprintf( '%s: %s', $oCon->getHumanName(), $this->getMainFeatureName() ),
1351
+ 'data' => array(
1352
+ 'form_nonce' => $this->genNonce( '' ),
1353
+ 'mod_slug' => $this->getModSlug(),
1354
+ 'all_options' => $this->buildOptions(),
1355
+ 'all_options_input' => $this->collateAllFormInputsForAllOptions(),
1356
+ 'hidden_options' => $this->getOptionsVo()->getHiddenOptions()
1357
+ ),
1358
  'strings' => array(
1359
  'go_to_settings' => __( 'Settings' ),
1360
  'on' => __( 'On' ),
1371
  'wrap_page_content' => true,
1372
  'show_standard_options' => true,
1373
  'show_content_actions' => $this->hasCustomActions(),
1374
+ 'show_content_help' => true,
1375
  'show_alt_content' => false,
1376
+ 'can_wizard' => $this->canRunWizards(),
1377
  'has_wizard' => $this->hasWizard(),
1378
  ),
1379
  'hrefs' => array(
1384
  'primary_wizard' => $this->getUrl_WizardPrimary(),
1385
  ),
1386
  'content' => array(
1387
+ 'options_form' => 'no form',
1388
+ 'alt' => '',
1389
+ 'actions' => $this->getContentCustomActions(),
1390
+ 'help' => $this->getContentHelp()
1391
  )
1392
  );
1393
  $aData[ 'flags' ][ 'show_content_help' ] = strpos( $aData[ 'content' ][ 'help' ], 'Error:' ) !== 0;
1401
  return '<h3 style="margin: 10px 0 100px">'._wpsf__( 'No Actions For This Module' ).'</h3>';
1402
  }
1403
 
 
 
 
 
 
 
 
1404
  /**
1405
  * @return string
1406
  */
1423
  public function getUrl_Wizard( $sWizardSlug ) {
1424
  return add_query_arg(
1425
  array(
1426
+ 'page' => $this->getModSlug(),
1427
  'shield_action' => 'wizard',
1428
  'wizard' => $sWizardSlug,
1429
  'nonwizard' => wp_create_nonce( 'wizard'.$sWizardSlug )
1451
  * @return array
1452
  */
1453
  public function getWizardDefinitions() {
1454
+ $aW = $this->getDef( 'wizards' );
1455
  return is_array( $aW ) ? $aW : array();
1456
  }
1457
 
1473
  * @return boolean
1474
  */
1475
  protected function getIsShowMarketing() {
1476
+ return false && apply_filters( $this->prefix( 'show_marketing' ), !$this->isPremium() );
1477
  }
1478
 
1479
  /**
1490
  }
1491
 
1492
  // Get the same Base Data as normal display
1493
+ $aData = $this->getBaseDisplayData();
1494
  $aData[ 'strings' ] = array_merge( $aData[ 'strings' ], $this->getDisplayStrings() );
1495
  return $this->loadRenderer( self::getConn()->getPath_Templates() )
1496
  ->setTemplate( $sTemplate )
1506
  ->getHasPermissionToView() : true;
1507
  }
1508
 
1509
+ /**
1510
+ * @return bool
1511
+ */
1512
+ public function canRunWizards() {
1513
+ return $this->loadDP()->getPhpVersionIsAtLeast( '5.4.0' );
1514
+ }
1515
+
1516
  /**
1517
  * @param array $aData
1518
  * @param string $sSubView
1528
  $sSubView = $oRndr->getTemplateExists( $sModuleView ) ? $sModuleView : 'feature-default';
1529
  }
1530
 
1531
+ $aData[ 'sFeatureInclude' ] = $this->loadDP()->addExtensionToFilePath( $sSubView, '.php' );
1532
  $aData[ 'strings' ] = array_merge( $aData[ 'strings' ], $this->getDisplayStrings() );
1533
+ $aData[ 'content' ][ 'options_form' ] = $this->renderOptionsForm();
1534
  try {
1535
  echo $oRndr
1536
  ->setTemplate( 'index.php' )
1542
  }
1543
  }
1544
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1545
  /**
1546
  * @param array $aData
1547
  * @return string
1563
  $aData[ 'notice_classes' ] = array();
1564
  }
1565
  if ( is_array( $aData[ 'notice_classes' ] ) ) {
1566
+ $aData[ 'notice_classes' ][] = $aData[ 'notice_attributes' ][ 'type' ];
1567
+ if ( empty( $aData[ 'notice_classes' ] )
1568
+ || ( !in_array( 'error', $aData[ 'notice_classes' ] ) && !in_array( 'updated', $aData[ 'notice_classes' ] ) ) ) {
1569
  $aData[ 'notice_classes' ][] = 'updated';
1570
  }
 
1571
  }
1572
  $aData[ 'notice_classes' ] = implode( ' ', $aData[ 'notice_classes' ] );
1573
 
src/features/base_wpsf.php CHANGED
@@ -8,6 +8,32 @@ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base.php' );
8
 
9
  class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  * @return array
13
  */
@@ -66,33 +92,36 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
66
  * @return array
67
  */
68
  protected function getBaseDisplayData() {
69
- $aData = parent::getBaseDisplayData();
70
- $aData[ 'strings' ] = array_merge(
71
- $aData[ 'strings' ],
72
  array(
73
- 'go_to_settings' => _wpsf__( 'Settings' ),
74
- 'on' => _wpsf__( 'On' ),
75
- 'off' => _wpsf__( 'Off' ),
76
- 'more_info' => _wpsf__( 'More Info' ),
77
- 'blog' => _wpsf__( 'Blog' ),
78
- 'plugin_activated_features_summary' => _wpsf__( 'Plugin Activated Features Summary:' ),
79
- 'save_all_settings' => _wpsf__( 'Save All Settings' ),
80
- 'options_title' => _wpsf__( 'Options' ),
81
- 'options_summary' => _wpsf__( 'Configure Module' ),
82
- 'actions_title' => _wpsf__( 'Actions and Info' ),
83
- 'actions_summary' => _wpsf__( 'Perform actions for this module' ),
84
- 'help_title' => _wpsf__( 'Help' ),
85
- 'help_summary' => _wpsf__( 'Learn More' ),
86
-
87
- 'aar_what_should_you_enter' => _wpsf__( 'What should you enter here?' ),
88
- 'aar_must_supply_key_first' => _wpsf__( 'At some point you entered a Security Admin Access Key - to manage this plugin, you must supply it here first.' ),
89
- 'aar_to_manage_must_enter_key' => _wpsf__( 'To manage this plugin you must enter the access key.' ),
90
- 'aar_enter_access_key' => _wpsf__( 'Enter Access Key' ),
91
- 'aar_submit_access_key' => _wpsf__( 'Submit Security Admin Key' )
 
 
 
 
 
 
92
  )
93
  );
94
- $aData[ 'flags' ][ 'show_summary' ] = true;
95
- return $aData;
96
  }
97
 
98
  protected function getTranslatedString( $sKey, $sDefault ) {
8
 
9
  class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
10
 
11
+ /**
12
+ * @var ICWP_WPSF_Processor_Sessions
13
+ */
14
+ static protected $oSessProcessor;
15
+
16
+ /**
17
+ * @return ICWP_WPSF_Processor_Sessions
18
+ */
19
+ public function getSessionsProcessor() {
20
+ return self::$oSessProcessor;
21
+ }
22
+
23
+ /**
24
+ * @return ICWP_WPSF_SessionVO
25
+ */
26
+ public function getSession() {
27
+ return $this->getSessionsProcessor()->getCurrentSession();
28
+ }
29
+
30
+ /**
31
+ * @return bool
32
+ */
33
+ public function hasSession() {
34
+ return !is_null( $this->getSession() );
35
+ }
36
+
37
  /**
38
  * @return array
39
  */
92
  * @return array
93
  */
94
  protected function getBaseDisplayData() {
95
+ return $this->loadDP()->mergeArraysRecursive(
96
+ parent::getBaseDisplayData(),
 
97
  array(
98
+ 'strings' => array(
99
+ 'go_to_settings' => _wpsf__( 'Settings' ),
100
+ 'on' => _wpsf__( 'On' ),
101
+ 'off' => _wpsf__( 'Off' ),
102
+ 'more_info' => _wpsf__( 'More Info' ),
103
+ 'blog' => _wpsf__( 'Blog' ),
104
+ 'plugin_activated_features_summary' => _wpsf__( 'Plugin Activated Features Summary:' ),
105
+ 'save_all_settings' => _wpsf__( 'Save All Settings' ),
106
+ 'options_title' => _wpsf__( 'Options' ),
107
+ 'options_summary' => _wpsf__( 'Configure Module' ),
108
+ 'actions_title' => _wpsf__( 'Actions and Info' ),
109
+ 'actions_summary' => _wpsf__( 'Perform actions for this module' ),
110
+ 'help_title' => _wpsf__( 'Help' ),
111
+ 'help_summary' => _wpsf__( 'Learn More' ),
112
+
113
+ 'aar_what_should_you_enter' => _wpsf__( 'What should you enter here?' ),
114
+ 'aar_must_supply_key_first' => _wpsf__( 'At some point you entered a Security Admin Access Key - to manage this plugin, you must supply it here first.' ),
115
+ 'aar_to_manage_must_enter_key' => _wpsf__( 'To manage this plugin you must enter the access key.' ),
116
+ 'aar_enter_access_key' => _wpsf__( 'Enter Access Key' ),
117
+ 'aar_submit_access_key' => _wpsf__( 'Submit Security Admin Key' )
118
+ ),
119
+ 'flags' => array(
120
+ 'show_summary' => true,
121
+ 'has_session' => $this->hasSession()
122
+ )
123
  )
124
  );
 
 
125
  }
126
 
127
  protected function getTranslatedString( $sKey, $sDefault ) {
src/features/hack_protect.php CHANGED
@@ -8,6 +8,46 @@ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
8
 
9
  class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_BaseWpsf {
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  * @return string
13
  */
@@ -16,11 +56,10 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
16
  }
17
 
18
  /**
19
- * @param string $sOption
20
- * @return $this
21
  */
22
- public function setUfcOption( $sOption ) {
23
- return $this->setOpt( 'enable_unrecognised_file_cleaner_scan', $sOption );
24
  }
25
 
26
  /**
@@ -34,6 +73,14 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
34
  return $aExclusions;
35
  }
36
 
 
 
 
 
 
 
 
 
37
  /**
38
  * @param array $aExclusions
39
  * @return $this
@@ -45,12 +92,6 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
45
  return $this->setOpt( 'ufc_exclusions', array_filter( array_map( 'trim', $aExclusions ) ) );
46
  }
47
 
48
- /**
49
- */
50
- protected function doExtraSubmitProcessing() {
51
- $this->cleanFileExclusions();
52
- }
53
-
54
  /**
55
  * @return $this
56
  */
@@ -79,7 +120,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
79
  /**
80
  * @return string
81
  */
82
- public function isUfsDeleteFiles() {
83
  return in_array( $this->getUnrecognisedFileScannerOption(), array(
84
  'enabled_delete_only',
85
  'enabled_delete_report'
@@ -89,7 +130,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
89
  /**
90
  * @return bool
91
  */
92
- public function isUfsEnabled() {
93
  return ( $this->getUnrecognisedFileScannerOption() != 'disabled' );
94
  }
95
 
@@ -110,6 +151,13 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
110
  ) );
111
  }
112
 
 
 
 
 
 
 
 
113
  /**
114
  * @return bool
115
  */
@@ -286,6 +334,12 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
286
  $sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
287
  break;
288
 
 
 
 
 
 
 
289
  case 'enable_plugin_vulnerabilities_scan' :
290
  $sName = _wpsf__( 'Plugin Vulnerabilities Scanner' );
291
  $sSummary = sprintf( _wpsf__( 'Daily Cron - %s' ), _wpsf__( 'Scans Plugins For Known Vulnerabilities' ) );
@@ -312,7 +366,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
312
 
313
  case 'enable_core_file_integrity_scan' :
314
  $sName = _wpsf__( 'Core File Scanner' );
315
- $sSummary = sprintf( _wpsf__( 'Daily Cron - %s' ), _wpsf__( 'Scans WordPress Core Files For Alterations' ) );
316
  $sDescription = _wpsf__( 'Compares all WordPress core files on your site against the official WordPress files.' )
317
  .'<br />'._wpsf__( 'WordPress Core files should never be altered for any reason.' );
318
  break;
8
 
9
  class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_BaseWpsf {
10
 
11
+ protected function doPostConstruction() {
12
+ $this->setCustomCronSchedules();
13
+ }
14
+
15
+ /**
16
+ */
17
+ protected function doExtraSubmitProcessing() {
18
+ $this->clearCrons();
19
+ $this->cleanFileExclusions();
20
+ }
21
+
22
+ protected function clearCrons() {
23
+ $this->loadWpCronProcessor()
24
+ ->deleteCronJob( $this->getUfcCronName() )
25
+ ->deleteCronJob( $this->getWcfCronName() );
26
+ }
27
+
28
+ /**
29
+ * @return int
30
+ */
31
+ public function getScanFrequency() {
32
+ return (int)$this->getOpt( 'scan_frequency', 1 );
33
+ }
34
+
35
+ /**
36
+ * @return $this
37
+ */
38
+ protected function setCustomCronSchedules() {
39
+ $nFreq = $this->getScanFrequency();
40
+ $this->loadWpCronProcessor()
41
+ ->addNewSchedule(
42
+ $this->prefix( sprintf( 'per-day-%s', $nFreq ) ),
43
+ array(
44
+ 'interval' => DAY_IN_SECONDS/$nFreq,
45
+ 'display' => sprintf( _wpsf__( '%s per day' ), $nFreq )
46
+ )
47
+ );
48
+ return $this;
49
+ }
50
+
51
  /**
52
  * @return string
53
  */
56
  }
57
 
58
  /**
59
+ * @return string
 
60
  */
61
+ public function getUfcCronName() {
62
+ return $this->prefixOptionKey( $this->getDefinition( 'unrecognisedscan_cron_name' ) );
63
  }
64
 
65
  /**
73
  return $aExclusions;
74
  }
75
 
76
+ /**
77
+ * @param string $sOption
78
+ * @return $this
79
+ */
80
+ public function setUfcOption( $sOption ) {
81
+ return $this->setOpt( 'enable_unrecognised_file_cleaner_scan', $sOption );
82
+ }
83
+
84
  /**
85
  * @param array $aExclusions
86
  * @return $this
92
  return $this->setOpt( 'ufc_exclusions', array_filter( array_map( 'trim', $aExclusions ) ) );
93
  }
94
 
 
 
 
 
 
 
95
  /**
96
  * @return $this
97
  */
120
  /**
121
  * @return string
122
  */
123
+ public function isUfcDeleteFiles() {
124
  return in_array( $this->getUnrecognisedFileScannerOption(), array(
125
  'enabled_delete_only',
126
  'enabled_delete_report'
130
  /**
131
  * @return bool
132
  */
133
+ public function isUfcEnabled() {
134
  return ( $this->getUnrecognisedFileScannerOption() != 'disabled' );
135
  }
136
 
151
  ) );
152
  }
153
 
154
+ /**
155
+ * @return string
156
+ */
157
+ public function getWcfCronName() {
158
+ return $this->prefixOptionKey( $this->getDef( 'corechecksum_cron_name' ) );
159
+ }
160
+
161
  /**
162
  * @return bool
163
  */
334
  $sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
335
  break;
336
 
337
+ case 'scan_frequency' :
338
+ $sName = _wpsf__( 'Daily Scan Frequency' );
339
+ $sSummary = _wpsf__( 'Number Of Times To Automatically Run File Scan In 24hrs' );
340
+ $sDescription = _wpsf__( 'Default: Once every 24hrs. To improve security, increase the number of scans per day.' );
341
+ break;
342
+
343
  case 'enable_plugin_vulnerabilities_scan' :
344
  $sName = _wpsf__( 'Plugin Vulnerabilities Scanner' );
345
  $sSummary = sprintf( _wpsf__( 'Daily Cron - %s' ), _wpsf__( 'Scans Plugins For Known Vulnerabilities' ) );
366
 
367
  case 'enable_core_file_integrity_scan' :
368
  $sName = _wpsf__( 'Core File Scanner' );
369
+ $sSummary = _wpsf__( 'Scans WordPress Core Files For Alterations' );
370
  $sDescription = _wpsf__( 'Compares all WordPress core files on your site against the official WordPress files.' )
371
  .'<br />'._wpsf__( 'WordPress Core files should never be altered for any reason.' );
372
  break;
src/features/login_protect.php CHANGED
@@ -65,9 +65,9 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
65
  }
66
 
67
  public function doPrePluginOptionsSave() {
68
- // TODO: remove as it's a temporary transition for clashing options name
69
- if ( $this->getOptIs( 'enable_google_recaptcha', 'Y' ) ) {
70
- $this->setOpt( 'enable_google_recaptcha_login', 'Y' );
71
  }
72
  }
73
 
@@ -189,15 +189,73 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
189
  /**
190
  * @return string
191
  */
192
- public function getTwoFactorAuthTableName() {
193
- return $this->prefix( $this->getDefinition( 'two_factor_auth_table_name' ), '_' );
194
  }
195
 
196
  /**
197
  * @return string
198
  */
199
- public function getCanEmailVerifyCode() {
200
- return strtoupper( substr( $this->getTwoAuthSecretKey(), 4, 6 ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  }
202
 
203
  /**
@@ -470,6 +528,12 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
470
  $sDescription = _wpsf__( 'When enabled, all multi-factor authentication methods will be applied to a user login. Disable to require only one to login.' );
471
  break;
472
 
 
 
 
 
 
 
473
  case 'enable_google_authenticator' :
474
  $sName = sprintf( _wpsf__( 'Enable %s' ), _wpsf__( 'Google Authenticator' ) );
475
  $sSummary = _wpsf__( 'Allow Users To Use Google Authenticator' );
65
  }
66
 
67
  public function doPrePluginOptionsSave() {
68
+ $nSkipDays = $this->getMfaSkip();
69
+ if ( !is_numeric( $nSkipDays ) || $nSkipDays < 0 ) {
70
+ $this->getOptionsVo()->resetOptToDefault( 'mfa_skip' );
71
  }
72
  }
73
 
189
  /**
190
  * @return string
191
  */
192
+ public function getCanEmailVerifyCode() {
193
+ return strtoupper( substr( $this->getTwoAuthSecretKey(), 4, 6 ) );
194
  }
195
 
196
  /**
197
  * @return string
198
  */
199
+ public function getCanMfaSkip() {
200
+ return;
201
+ }
202
+
203
+ /**
204
+ * @param WP_User $oUser
205
+ * @return bool
206
+ */
207
+ public function canUserMfaSkip( $oUser ) {
208
+ $bCanSkip = false;
209
+
210
+ if ( $this->getMfaSkipEnabled() ) {
211
+ $aHashes = $this->getMfaLoginHashes( $oUser );
212
+ $nSkipTime = $this->getMfaSkip()*DAY_IN_SECONDS;
213
+
214
+ $sHash = md5( $this->loadDP()->getUserAgent() );
215
+ $bCanSkip = isset( $aHashes[ $sHash ] )
216
+ && ( (int)$aHashes[ $sHash ] + $nSkipTime ) > $this->loadDP()->time();
217
+ }
218
+ return $bCanSkip;
219
+ }
220
+
221
+ /**
222
+ * @param WP_User $oUser
223
+ * @return $this
224
+ */
225
+ public function addMfaLoginHash( $oUser ) {
226
+ $oDp = $this->loadDP();
227
+ $aHashes = $this->getMfaLoginHashes( $oUser );
228
+ $aHashes[ md5( $oDp->getUserAgent() ) ] = $oDp->time();
229
+ $this->getCurrentUserMeta()->hash_loginmfa = $aHashes;
230
+ return $this;
231
+ }
232
+
233
+ /**
234
+ * @param WP_User $oUser
235
+ * @return array
236
+ */
237
+ public function getMfaLoginHashes( $oUser ) {
238
+ $oMeta = $this->getUserMeta( $oUser );
239
+ $aHashes = $oMeta->hash_loginmfa;
240
+ if ( !is_array( $aHashes ) ) {
241
+ $aHashes = array();
242
+ $oMeta->hash_loginmfa = $aHashes;
243
+ }
244
+ return $aHashes;
245
+ }
246
+
247
+ /**
248
+ * @return bool
249
+ */
250
+ public function getMfaSkipEnabled() {
251
+ return $this->getMfaSkip() > 0;
252
+ }
253
+
254
+ /**
255
+ * @return int
256
+ */
257
+ public function getMfaSkip() {
258
+ return (int)$this->getOpt( 'mfa_skip', 0 );
259
  }
260
 
261
  /**
528
  $sDescription = _wpsf__( 'When enabled, all multi-factor authentication methods will be applied to a user login. Disable to require only one to login.' );
529
  break;
530
 
531
+ case 'mfa_skip' :
532
+ $sName = _wpsf__( 'Multi-Factor By-Pass' );
533
+ $sSummary = _wpsf__( 'A User Can By-Pass Multi-Factor Authentication (MFA) For The Set Number Of Days' );
534
+ $sDescription = _wpsf__( 'Enter the number of days a user can by-pass future MFA after a successful MFA-login. 0 to disable.' );
535
+ break;
536
+
537
  case 'enable_google_authenticator' :
538
  $sName = sprintf( _wpsf__( 'Enable %s' ), _wpsf__( 'Google Authenticator' ) );
539
  $sSummary = _wpsf__( 'Allow Users To Use Google Authenticator' );
src/features/plugin.php CHANGED
@@ -36,7 +36,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
36
  return parent::getContentCustomActions();
37
  }
38
 
39
- $bCanWizard = $this->getCanRunWizards();
40
  $bCanWizardWelcome = $bCanWizard;
41
  $bCanWizardImport = $bCanWizard && $this->isPremium();
42
 
@@ -230,14 +230,6 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
230
  return $bGloballyDisabled || !$this->getOptIs( 'global_enable_plugin_features', 'Y' );
231
  }
232
 
233
- public function doExtraSubmitProcessing() {
234
- if ( !$this->loadWp()->isAjax() ) {
235
- $this->loadAdminNoticesProcessor()
236
- ->addFlashMessage( sprintf( _wpsf__( '%s Plugin options updated successfully.' ), self::getConn()
237
- ->getHumanName() ) );
238
- }
239
- }
240
-
241
  /**
242
  * @return array
243
  */
36
  return parent::getContentCustomActions();
37
  }
38
 
39
+ $bCanWizard = $this->canRunWizards();
40
  $bCanWizardWelcome = $bCanWizard;
41
  $bCanWizardImport = $bCanWizard && $this->isPremium();
42
 
230
  return $bGloballyDisabled || !$this->getOptIs( 'global_enable_plugin_features', 'Y' );
231
  }
232
 
 
 
 
 
 
 
 
 
233
  /**
234
  * @return array
235
  */
src/features/sessions.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'ICWP_WPSF_FeatureHandler_Sessions', false ) ) {
4
+ return;
5
+ }
6
+
7
+ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
8
+
9
+ class ICWP_WPSF_FeatureHandler_Sessions extends ICWP_WPSF_FeatureHandler_BaseWpsf {
10
+
11
+ /**
12
+ * Override this and adapt per feature
13
+ * @return ICWP_WPSF_Processor_Base
14
+ */
15
+ protected function loadFeatureProcessor() {
16
+ $oP = parent::loadFeatureProcessor();
17
+ self::$oSessProcessor = $oP;
18
+ return $oP;
19
+ }
20
+
21
+ /**
22
+ * @return string
23
+ */
24
+ public function getSessionsTableName() {
25
+ return $this->prefix( $this->getDef( 'sessions_table_name' ), '_' );
26
+ }
27
+
28
+ /**
29
+ * @return bool
30
+ */
31
+ public function isAutoAddSessions() {
32
+ $nStartedAt = $this->getOpt( 'autoadd_sessions_started_at', 0 );
33
+ if ( $nStartedAt < 1 ) {
34
+ $nStartedAt = $this->loadDP()->time();
35
+ $this->setOpt( 'autoadd_sessions_started_at', $nStartedAt );
36
+ }
37
+ return ( $this->loadDP()->time() - $nStartedAt ) < 20;
38
+ }
39
+
40
+ /**
41
+ * @param array $aOptionsParams
42
+ * @return array
43
+ * @throws Exception
44
+ */
45
+ protected function loadStrings_SectionTitles( $aOptionsParams ) {
46
+
47
+ $sSectionSlug = $aOptionsParams[ 'slug' ];
48
+ switch ( $sSectionSlug ) {
49
+
50
+ case 'section_enable_plugin_feature_sessions' :
51
+ $sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
52
+ $aSummary = array(
53
+ sprintf( _wpsf__( 'Purpose - %s' ), _wpsf__( 'Creates and Manages User Sessions.' ) ),
54
+ sprintf( _wpsf__( 'Recommendation - %s' ), sprintf( _wpsf__( 'Keep the %s feature turned on.' ), _wpsf__( 'User Management' ) ) )
55
+ );
56
+ $sTitleShort = sprintf( '%s / %s', _wpsf__( 'Enable' ), _wpsf__( 'Disable' ) );
57
+ break;
58
+
59
+ default:
60
+ throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
61
+ }
62
+ $aOptionsParams[ 'title' ] = $sTitle;
63
+ $aOptionsParams[ 'summary' ] = ( isset( $aSummary ) && is_array( $aSummary ) ) ? $aSummary : array();
64
+ $aOptionsParams[ 'title_short' ] = $sTitleShort;
65
+ return $aOptionsParams;
66
+ }
67
+
68
+ /**
69
+ * @param array $aOptionsParams
70
+ * @return array
71
+ * @throws Exception
72
+ */
73
+ protected function loadStrings_Options( $aOptionsParams ) {
74
+
75
+ $sKey = $aOptionsParams[ 'key' ];
76
+ switch ( $sKey ) {
77
+
78
+ case 'enable_sessions' :
79
+ $sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
80
+ $sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
81
+ $sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
82
+ break;
83
+
84
+ default:
85
+ throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
86
+ }
87
+
88
+ $aOptionsParams[ 'name' ] = $sName;
89
+ $aOptionsParams[ 'summary' ] = $sSummary;
90
+ $aOptionsParams[ 'description' ] = $sDescription;
91
+ return $aOptionsParams;
92
+ }
93
+ }
src/features/support.php DELETED
@@ -1,118 +0,0 @@
1
- <?php
2
-
3
- if ( class_exists( 'ICWP_WPSF_FeatureHandler_Support', false ) ) {
4
- return;
5
- }
6
-
7
- require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'base_wpsf.php' );
8
-
9
- class ICWP_WPSF_FeatureHandler_Support extends ICWP_WPSF_FeatureHandler_BaseWpsf {
10
-
11
- /**
12
- */
13
- public function displayModulePage() {
14
- $aData = array(
15
- 'has_premium_support' => $this->getHasPremiumSupport(),
16
- 'aHrefs' => array(
17
- 'shield_pro_url' => 'http://icwp.io/shieldpro',
18
- 'shield_pro_more_info_url' => 'http://icwp.io/shld1',
19
- 'iframe_url' => $this->getDefinition( 'landing_page_url' ),
20
- ),
21
- 'bShowStateSummary' => false,
22
- 'flags' => array(
23
- 'wrap_page_content' => false,
24
- ),
25
- );
26
- $this->display( $aData );
27
- }
28
-
29
- /**
30
- * @return bool
31
- */
32
- public function getIfShowFeatureMenuItem() {
33
- return !$this->getHasPremiumSupport();
34
- }
35
-
36
- /**
37
- * @return bool
38
- */
39
- public function getHasPremiumSupport() {
40
- return $this->getIcwpLinked(); // todo - detect whether Shield addon is active for this site.
41
- // return apply_filters( $this->prefix( 'has_premium_support' ), $this->getIcwpLinked() );
42
- }
43
-
44
- /**
45
- * @return bool
46
- */
47
- protected function getHasIcwpPluginActive() {
48
- return ( class_exists( 'ICWP_Plugin' ) && method_exists( 'ICWP_Plugin', 'IsLinked' ) );
49
- }
50
-
51
- /**
52
- * @return bool
53
- */
54
- protected function getIcwpLinked() {
55
- return ( $this->getHasIcwpPluginActive() && ICWP_Plugin::IsLinked() && $this->getIcwpPluginMeetsMinimumVersion() );
56
- }
57
-
58
- /**
59
- * @return bool
60
- */
61
- protected function getIcwpPluginMeetsMinimumVersion() {
62
- return version_compare( ICWP_Plugin::GetVersion(), '3.4', '>=' );
63
- }
64
-
65
- /**
66
- * @param array $aOptionsParams
67
- * @return array
68
- * @throws Exception
69
- */
70
- protected function loadStrings_SectionTitles( $aOptionsParams ) {
71
-
72
- $sSectionSlug = $aOptionsParams[ 'slug' ];
73
- switch ( $sSectionSlug ) {
74
-
75
- case 'section_enable_plugin_feature_support' :
76
- $sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), $this->getMainFeatureName() );
77
- $aSummary = array(
78
- sprintf( _wpsf__( 'Purpose - %s' ), _wpsf__( 'Contact Plugin Premium Support Centre.' ) ),
79
- sprintf( _wpsf__( 'Recommendation - %s' ), sprintf( _wpsf__( 'Keep the %s feature turned on.' ), $this->getMainFeatureName() ) )
80
- );
81
- $sTitleShort = sprintf( '%s / %s', _wpsf__( 'Enable' ), _wpsf__( 'Disable' ) );
82
- break;
83
-
84
- default:
85
- throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
86
- }
87
- $aOptionsParams[ 'title' ] = $sTitle;
88
- $aOptionsParams[ 'summary' ] = ( isset( $aSummary ) && is_array( $aSummary ) ) ? $aSummary : array();
89
- $aOptionsParams[ 'title_short' ] = $sTitleShort;
90
- return $aOptionsParams;
91
- }
92
-
93
- /**
94
- * @param array $aOptionsParams
95
- * @return array
96
- * @throws Exception
97
- */
98
- protected function loadStrings_Options( $aOptionsParams ) {
99
-
100
- $sKey = $aOptionsParams[ 'key' ];
101
- switch ( $sKey ) {
102
-
103
- case 'enable_support' :
104
- $sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
105
- $sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
106
- $sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
107
- break;
108
-
109
- default:
110
- throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
111
- }
112
-
113
- $aOptionsParams[ 'name' ] = $sName;
114
- $aOptionsParams[ 'summary' ] = $sSummary;
115
- $aOptionsParams[ 'description' ] = $sDescription;
116
- return $aOptionsParams;
117
- }
118
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/features/user_management.php CHANGED
@@ -8,6 +8,17 @@ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
8
 
9
  class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_BaseWpsf {
10
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  * @return string
13
  */
@@ -19,19 +30,23 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
19
  }
20
 
21
  protected function renderUserSessions() {
22
-
23
  $aActiveSessions = $this->getActiveSessionsData();
24
 
 
 
25
  $oWp = $this->loadWp();
26
  $sTimeFormat = $oWp->getTimeFormat();
27
  $sDateFormat = $oWp->getDateFormat();
28
- foreach ( $aActiveSessions as &$aSession ) {
29
- $aSession[ 'logged_in_at' ] = $oWp->getTimeStringForDisplay( $aSession[ 'logged_in_at' ] );
30
- $aSession[ 'last_activity_at' ] = $oWp->getTimeStringForDisplay( $aSession[ 'last_activity_at' ] );
 
 
 
31
  }
32
 
33
  $oTable = $this->getTableRendererForSessions()
34
- ->setItemEntries( $aActiveSessions )
35
  ->setPerPage( 5 )
36
  ->prepare_items();
37
  ob_start();
@@ -40,7 +55,8 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
40
 
41
  $aData = array(
42
  'strings' => $this->getDisplayStrings(),
43
- 'time_now' => sprintf( _wpsf__( 'now: %s' ), date_i18n( $sTimeFormat.' '.$sDateFormat, $this->loadDP()->time() ) ),
 
44
  'sUserSessionsTable' => $sUserSessionsTable
45
  );
46
  return $this->renderTemplate( 'snippets/module-user_management-sessions', $aData );
@@ -60,12 +76,11 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
60
  }
61
 
62
  /**
63
- * @return array[]
64
  */
65
  protected function getActiveSessionsData() {
66
- /** @var ICWP_WPSF_Processor_UserManagement $oProcessor */
67
- $oProcessor = $this->getProcessor();
68
- return $this->getIsMainFeatureEnabled() ? $oProcessor->getActiveUserSessionRecords() : array();
69
  }
70
 
71
  /**
@@ -112,16 +127,20 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
112
  'um_last_activity_at' => _wpsf__( 'Last Activity At' ),
113
  'um_last_activity_uri' => _wpsf__( 'Last Activity URI' ),
114
  'um_login_ip' => _wpsf__( 'Login IP' ),
115
- 'um_login_attempts' => _wpsf__( 'Login Attempts' ),
116
  'um_need_to_enable_user_management' => _wpsf__( 'You need to enable the User Management feature to view and manage user sessions.' ),
117
  );
118
  }
119
 
120
  /**
121
- * @return string
122
  */
123
- public function getUserSessionsTableName() {
124
- return $this->prefix( $this->getDefinition( 'user_sessions_table_name' ), '_' );
 
 
 
 
 
125
  }
126
 
127
  /**
8
 
9
  class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_BaseWpsf {
10
 
11
+ /**
12
+ * TODO: remove on next release
13
+ */
14
+ protected function updateHandler() {
15
+ $oDb = $this->loadDbProcessor();
16
+ $sDbName = $oDb->getPrefix().$this->prefix( 'user_management', '_' );
17
+ if ( $oDb->getIfTableExists( $sDbName ) ) {
18
+ $oDb->doDropTable( $sDbName );
19
+ }
20
+ }
21
+
22
  /**
23
  * @return string
24
  */
30
  }
31
 
32
  protected function renderUserSessions() {
 
33
  $aActiveSessions = $this->getActiveSessionsData();
34
 
35
+ $aFormatted = array();
36
+
37
  $oWp = $this->loadWp();
38
  $sTimeFormat = $oWp->getTimeFormat();
39
  $sDateFormat = $oWp->getDateFormat();
40
+ foreach ( $aActiveSessions as $oSession ) {
41
+ $aSession = (array)$oSession->getRowData();
42
+ $aSession[ 'logged_in_at' ] = $oWp->getTimeStringForDisplay( $oSession->getLoggedInAt() );
43
+ $aSession[ 'last_activity_at' ] = $oWp->getTimeStringForDisplay( $oSession->getLastActivityAt() );
44
+ $aSession[ 'is_secadmin' ] = ( $oSession->getSecAdminAt() > 0 ) ? __( 'Yes' ) : __( 'No' );
45
+ $aFormatted[] = $aSession;
46
  }
47
 
48
  $oTable = $this->getTableRendererForSessions()
49
+ ->setItemEntries( $aFormatted )
50
  ->setPerPage( 5 )
51
  ->prepare_items();
52
  ob_start();
55
 
56
  $aData = array(
57
  'strings' => $this->getDisplayStrings(),
58
+ 'time_now' => sprintf( _wpsf__( 'now: %s' ), date_i18n( $sTimeFormat.' '.$sDateFormat, $this->loadDP()
59
+ ->time() ) ),
60
  'sUserSessionsTable' => $sUserSessionsTable
61
  );
62
  return $this->renderTemplate( 'snippets/module-user_management-sessions', $aData );
76
  }
77
 
78
  /**
79
+ * @return ICWP_WPSF_SessionVO[]
80
  */
81
  protected function getActiveSessionsData() {
82
+ return $this->getSessionsProcessor()
83
+ ->queryGetActiveSessions();
 
84
  }
85
 
86
  /**
127
  'um_last_activity_at' => _wpsf__( 'Last Activity At' ),
128
  'um_last_activity_uri' => _wpsf__( 'Last Activity URI' ),
129
  'um_login_ip' => _wpsf__( 'Login IP' ),
 
130
  'um_need_to_enable_user_management' => _wpsf__( 'You need to enable the User Management feature to view and manage user sessions.' ),
131
  );
132
  }
133
 
134
  /**
135
+ * @return bool
136
  */
137
+ public function isAutoAddSessions() {
138
+ $nStartedAt = $this->getOpt( 'autoadd_sessions_started_at', 0 );
139
+ if ( $nStartedAt < 1 ) {
140
+ $nStartedAt = $this->loadDP()->time();
141
+ $this->setOpt( 'autoadd_sessions_started_at', $nStartedAt );
142
+ }
143
+ return ( $this->loadDP()->time() - $nStartedAt ) < 20;
144
  }
145
 
146
  /**
src/processors/admin_access_restriction.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
4
 
5
- require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'base_wpsf.php' );
6
 
7
  class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_BaseWpsf {
8
 
@@ -23,7 +23,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
23
  add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
24
  }
25
 
26
- if ( $oFO->getOptIs( 'admin_access_restrict_admin_users', 'Y') ) {
27
  add_filter( 'user_has_cap', array( $this, 'restrictAdminUserChanges' ), 0, 3 );
28
  add_action( 'delete_user', array( $this, 'restrictAdminUserDelete' ), 0, 1 );
29
  }
@@ -61,8 +61,8 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
61
  'admin_access_restrict_posts'
62
  );
63
  foreach ( $aKeysToBoolean as $sKeyToBoolean ) {
64
- $aData[$sSlug][ 'options' ][ $sKeyToBoolean ]
65
- = empty( $aData[$sSlug][ 'options' ][ $sKeyToBoolean ] ) ? 0 : 1;
66
  }
67
  return $aData;
68
  }
@@ -90,7 +90,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
90
 
91
  /**
92
  * @param array $aAllCaps
93
- * @param $cap
94
  * @param array $aArgs
95
  * @return array
96
  */
@@ -104,7 +104,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
104
  $oDp = $this->loadDataProcessor();
105
 
106
  /** @var string $sRequestedCapability */
107
- $sRequestedCapability = $aArgs[0];
108
  $aUserCapabilities = array( 'edit_users', 'create_users' );
109
 
110
  $bBlockCapability = false;
@@ -161,23 +161,25 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
161
  }
162
 
163
  $sCurrentPage = $this->loadWp()->getCurrentPage();
164
- $sCurrentGetPage = $this->loadDataProcessor()->FetchGet( 'page' );
165
  if ( !in_array( $sCurrentPage, $oFO->getOptionsPagesToRestrict() ) || !empty( $sCurrentGetPage ) ) {
166
  return;
167
  }
168
 
 
169
  $aRenderData = array(
170
  'notice_attributes' => $aNoticeAttributes,
171
- 'strings' => array(
 
172
  'notice_message' => _wpsf__( 'Altering certain options has been restricted by your WordPress security administrator.' )
173
- .' '._wpsf__( 'Repeated failed attempts to authenticate will probably lock you out of this site.' )
174
  ),
175
- 'hrefs' => array(
176
  'setting_page' => sprintf(
177
  '<a href="%s" title="%s">%s</a>',
178
  $oFO->getUrl_AdminPage(),
179
  _wpsf__( 'Admin Access Login' ),
180
- sprintf( _wpsf__('Go here to manage settings and authenticate with the %s plugin.'), $this->getController()->getHumanName() )
181
  )
182
  )
183
  );
@@ -200,19 +202,21 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
200
  return;
201
  }
202
 
 
203
  $aRenderData = array(
204
  'notice_attributes' => $aNoticeAttributes,
205
- 'strings' => array(
 
206
  'notice_message' => _wpsf__( 'Editing existing administrators, promoting existing users to the administrator role, or deleting administrator users is currently restricted.' )
207
- . ' ' . _wpsf__( 'Please authenticate with the Security Admin system before attempting any administrator user modifications.' ),
208
- 'unlock_link' => $this->getUnlockLinkHtml( _wpsf__( 'Unlock Now' ) ),
209
  ),
210
- 'hrefs' => array(
211
  'setting_page' => sprintf(
212
  '<a href="%s" title="%s">%s</a>',
213
  $oFO->getUrl_AdminPage(),
214
  _wpsf__( 'Security Admin Login' ),
215
- sprintf( _wpsf__('Go here to manage settings and authenticate with the %s plugin.'), $this->getController()->getHumanName() )
216
  )
217
  )
218
  );
@@ -224,7 +228,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
224
  */
225
  protected function getUserPagesToRestrict() {
226
  return array(
227
- // 'user-new.php',
228
  'user-edit.php',
229
  'users.php',
230
  );
@@ -233,10 +237,9 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
233
  /**
234
  * Right before a plugin option is due to update it will check that we have permissions to do so and if not, will
235
  * revert the option to save to the previous one.
236
- *
237
- * @param mixed $mNewOptionValue
238
  * @param string $sOptionKey
239
- * @param mixed $mOldValue
240
  * @return mixed
241
  */
242
  public function blockOptionsSaves( $mNewOptionValue, $sOptionKey, $mOldValue ) {
@@ -281,7 +284,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
281
 
282
  /**
283
  * @param array $aAllCaps
284
- * @param $cap
285
  * @param array $aArgs
286
  * @return array
287
  */
@@ -295,7 +298,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
295
  $oFO = $this->getFeature();
296
 
297
  /** @var string $sRequestedCapability */
298
- $sRequestedCapability = $aArgs[0];
299
  $aEditCapabilities = array( 'activate_plugins', 'delete_plugins', 'install_plugins', 'update_plugins' );
300
 
301
  if ( in_array( $sRequestedCapability, $aEditCapabilities ) ) {
@@ -310,7 +313,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
310
 
311
  /**
312
  * @param array $aAllCaps
313
- * @param $cap
314
  * @param array $aArgs
315
  * @return array
316
  */
@@ -325,8 +328,14 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
325
  $oFO = $this->getFeature();
326
 
327
  /** @var string $sRequestedCapability */
328
- $sRequestedCapability = $aArgs[0];
329
- $aEditCapabilities = array( 'switch_themes', 'edit_theme_options', 'install_themes', 'update_themes', 'delete_themes' );
 
 
 
 
 
 
330
 
331
  if ( in_array( $sRequestedCapability, $aEditCapabilities ) ) {
332
  $aAreaRestrictions = $oFO->getAdminAccessArea_Themes();
@@ -340,7 +349,7 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
340
 
341
  /**
342
  * @param array $aAllCaps
343
- * @param $cap
344
  * @param array $aArgs
345
  * @return array
346
  */
@@ -355,15 +364,28 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
355
  $oFO = $this->getFeature();
356
 
357
  /** @var string $sRequestedCapability */
358
- $sRequestedCapability = $aArgs[0];
359
  $aEditCapabilities = array(
360
- 'edit_post', 'publish_post', 'delete_post',
361
- 'edit_posts', 'publish_posts', 'delete_posts',
362
- 'edit_page', 'publish_page', 'delete_page',
363
- 'edit_pages', 'publish_pages', 'delete_pages'
 
 
 
 
 
 
 
 
364
  );
365
  if ( in_array( $sRequestedCapability, $aEditCapabilities ) ) {
366
- $sRequestedCapabilityTrimmed = str_replace( array( '_posts', '_pages', '_post', '_page' ), '', $sRequestedCapability ); //Order of items in this array is important!
 
 
 
 
 
367
  $aAreaRestrictions = $oFO->getAdminAccessArea_Posts();
368
  if ( in_array( $sRequestedCapabilityTrimmed, $aAreaRestrictions ) ) {
369
  $aAllCaps[ $sRequestedCapability ] = false;
@@ -393,11 +415,11 @@ if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
393
  }
394
 
395
  $aRenderData = array(
396
- 'strings' => array(
397
  'editing_restricted' => _wpsf__( 'Editing this option is currently restricted.' ),
398
- 'unlock_link' => $this->getUnlockLinkHtml(),
399
  ),
400
- 'sAjaxNonce' => wp_create_nonce( 'icwp_ajax' ),
401
  'js_snippets' => array(
402
  'options_to_restrict' => "'".implode( "','", $oFO->getOptionsToRestrict() )."'",
403
  )
2
 
3
  if ( !class_exists( 'ICWP_WPSF_Processor_AdminAccessRestriction', false ) ):
4
 
5
+ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
6
 
7
  class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_BaseWpsf {
8
 
23
  add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
24
  }
25
 
26
+ if ( $oFO->getOptIs( 'admin_access_restrict_admin_users', 'Y' ) ) {
27
  add_filter( 'user_has_cap', array( $this, 'restrictAdminUserChanges' ), 0, 3 );
28
  add_action( 'delete_user', array( $this, 'restrictAdminUserDelete' ), 0, 1 );
29
  }
61
  'admin_access_restrict_posts'
62
  );
63
  foreach ( $aKeysToBoolean as $sKeyToBoolean ) {
64
+ $aData[ $sSlug ][ 'options' ][ $sKeyToBoolean ]
65
+ = empty( $aData[ $sSlug ][ 'options' ][ $sKeyToBoolean ] ) ? 0 : 1;
66
  }
67
  return $aData;
68
  }
90
 
91
  /**
92
  * @param array $aAllCaps
93
+ * @param $cap
94
  * @param array $aArgs
95
  * @return array
96
  */
104
  $oDp = $this->loadDataProcessor();
105
 
106
  /** @var string $sRequestedCapability */
107
+ $sRequestedCapability = $aArgs[ 0 ];
108
  $aUserCapabilities = array( 'edit_users', 'create_users' );
109
 
110
  $bBlockCapability = false;
161
  }
162
 
163
  $sCurrentPage = $this->loadWp()->getCurrentPage();
164
+ $sCurrentGetPage = $this->loadDP()->query( 'page' );
165
  if ( !in_array( $sCurrentPage, $oFO->getOptionsPagesToRestrict() ) || !empty( $sCurrentGetPage ) ) {
166
  return;
167
  }
168
 
169
+ $sName = $this->getController()->getHumanName();
170
  $aRenderData = array(
171
  'notice_attributes' => $aNoticeAttributes,
172
+ 'strings' => array(
173
+ 'title' => sprintf( _wpsf__( '%s Security Restrictions Applied' ), $sName ),
174
  'notice_message' => _wpsf__( 'Altering certain options has been restricted by your WordPress security administrator.' )
175
+ .' '._wpsf__( 'Repeated failed attempts to authenticate will probably lock you out of this site.' )
176
  ),
177
+ 'hrefs' => array(
178
  'setting_page' => sprintf(
179
  '<a href="%s" title="%s">%s</a>',
180
  $oFO->getUrl_AdminPage(),
181
  _wpsf__( 'Admin Access Login' ),
182
+ sprintf( _wpsf__( 'Go here to manage settings and authenticate with the %s plugin.' ), $sName )
183
  )
184
  )
185
  );
202
  return;
203
  }
204
 
205
+ $sName = $this->getController()->getHumanName();
206
  $aRenderData = array(
207
  'notice_attributes' => $aNoticeAttributes,
208
+ 'strings' => array(
209
+ 'title' => sprintf( _wpsf__( '%s Security Restrictions Applied' ), $sName ),
210
  'notice_message' => _wpsf__( 'Editing existing administrators, promoting existing users to the administrator role, or deleting administrator users is currently restricted.' )
211
+ .' '._wpsf__( 'Please authenticate with the Security Admin system before attempting any administrator user modifications.' ),
212
+ 'unlock_link' => $this->getUnlockLinkHtml( _wpsf__( 'Unlock Now' ) ),
213
  ),
214
+ 'hrefs' => array(
215
  'setting_page' => sprintf(
216
  '<a href="%s" title="%s">%s</a>',
217
  $oFO->getUrl_AdminPage(),
218
  _wpsf__( 'Security Admin Login' ),
219
+ sprintf( _wpsf__( 'Go here to manage settings and authenticate with the %s plugin.' ), $sName )
220
  )
221
  )
222
  );
228
  */
229
  protected function getUserPagesToRestrict() {
230
  return array(
231
+ /* 'user-new.php', */
232
  'user-edit.php',
233
  'users.php',
234
  );
237
  /**
238
  * Right before a plugin option is due to update it will check that we have permissions to do so and if not, will
239
  * revert the option to save to the previous one.
240
+ * @param mixed $mNewOptionValue
 
241
  * @param string $sOptionKey
242
+ * @param mixed $mOldValue
243
  * @return mixed
244
  */
245
  public function blockOptionsSaves( $mNewOptionValue, $sOptionKey, $mOldValue ) {
284
 
285
  /**
286
  * @param array $aAllCaps
287
+ * @param $cap
288
  * @param array $aArgs
289
  * @return array
290
  */
298
  $oFO = $this->getFeature();
299
 
300
  /** @var string $sRequestedCapability */
301
+ $sRequestedCapability = $aArgs[ 0 ];
302
  $aEditCapabilities = array( 'activate_plugins', 'delete_plugins', 'install_plugins', 'update_plugins' );
303
 
304
  if ( in_array( $sRequestedCapability, $aEditCapabilities ) ) {
313
 
314
  /**
315
  * @param array $aAllCaps
316
+ * @param $cap
317
  * @param array $aArgs
318
  * @return array
319
  */
328
  $oFO = $this->getFeature();
329
 
330
  /** @var string $sRequestedCapability */
331
+ $sRequestedCapability = $aArgs[ 0 ];
332
+ $aEditCapabilities = array(
333
+ 'switch_themes',
334
+ 'edit_theme_options',
335
+ 'install_themes',
336
+ 'update_themes',
337
+ 'delete_themes'
338
+ );
339
 
340
  if ( in_array( $sRequestedCapability, $aEditCapabilities ) ) {
341
  $aAreaRestrictions = $oFO->getAdminAccessArea_Themes();
349
 
350
  /**
351
  * @param array $aAllCaps
352
+ * @param $cap
353
  * @param array $aArgs
354
  * @return array
355
  */
364
  $oFO = $this->getFeature();
365
 
366
  /** @var string $sRequestedCapability */
367
+ $sRequestedCapability = $aArgs[ 0 ];
368
  $aEditCapabilities = array(
369
+ 'edit_post',
370
+ 'publish_post',
371
+ 'delete_post',
372
+ 'edit_posts',
373
+ 'publish_posts',
374
+ 'delete_posts',
375
+ 'edit_page',
376
+ 'publish_page',
377
+ 'delete_page',
378
+ 'edit_pages',
379
+ 'publish_pages',
380
+ 'delete_pages'
381
  );
382
  if ( in_array( $sRequestedCapability, $aEditCapabilities ) ) {
383
+ $sRequestedCapabilityTrimmed = str_replace( array(
384
+ '_posts',
385
+ '_pages',
386
+ '_post',
387
+ '_page'
388
+ ), '', $sRequestedCapability ); //Order of items in this array is important!
389
  $aAreaRestrictions = $oFO->getAdminAccessArea_Posts();
390
  if ( in_array( $sRequestedCapabilityTrimmed, $aAreaRestrictions ) ) {
391
  $aAllCaps[ $sRequestedCapability ] = false;
415
  }
416
 
417
  $aRenderData = array(
418
+ 'strings' => array(
419
  'editing_restricted' => _wpsf__( 'Editing this option is currently restricted.' ),
420
+ 'unlock_link' => $this->getUnlockLinkHtml(),
421
  ),
422
+ 'sAjaxNonce' => wp_create_nonce( 'icwp_ajax' ),
423
  'js_snippets' => array(
424
  'options_to_restrict' => "'".implode( "','", $oFO->getOptionsToRestrict() )."'",
425
  )
src/processors/base.php CHANGED
@@ -41,7 +41,7 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
41
  * @return int
42
  */
43
  protected function getPromoNoticesCount() {
44
- return self::$nPromoNoticesCount++;
45
  }
46
 
47
  /**
@@ -62,18 +62,19 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
62
  public function autoAddToAdminNotices() {
63
  $oCon = $this->getController();
64
 
65
- foreach ( $this->getFeature()->getAdminNotices() as $sNoticeId => $aNoticeAttributes ) {
66
 
67
- if ( !$this->getIfDisplayAdminNotice( $aNoticeAttributes ) ) {
68
  continue;
69
  }
70
 
71
  $sMethodName = 'addNotice_'.str_replace( '-', '_', $sNoticeId );
72
- if ( method_exists( $this, $sMethodName ) && isset( $aNoticeAttributes[ 'valid_admin' ] )
73
- && $aNoticeAttributes[ 'valid_admin' ] && $oCon->getIsValidAdminArea() ) {
74
 
75
- $aNoticeAttributes[ 'notice_id' ] = $sNoticeId;
76
- call_user_func( array( $this, $sMethodName ), $aNoticeAttributes );
 
77
  }
78
  }
79
  }
@@ -85,11 +86,8 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
85
  protected function getIfDisplayAdminNotice( $aAttrs ) {
86
  $oWpNotices = $this->loadAdminNoticesProcessor();
87
 
88
- if ( empty( $aAttrs[ 'schedule' ] ) || !in_array( $aAttrs[ 'schedule' ], array(
89
- 'once',
90
- 'conditions',
91
- 'version'
92
- ) ) ) {
93
  $aAttrs[ 'schedule' ] = 'conditions';
94
  }
95
 
@@ -98,17 +96,11 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
98
  }
99
 
100
  if ( $aAttrs[ 'schedule' ] == 'once'
101
- && ( !$this->loadWpUsers()->getCanAddUpdateCurrentUserMeta()
102
- || $oWpNotices->getAdminNoticeIsDismissed( $aAttrs[ 'id' ] ) )
103
  ) {
104
  return false;
105
  }
106
 
107
- if ( $aAttrs[ 'schedule' ] == 'version'
108
- && ( $this->getFeature()->getVersion() == $oWpNotices->getAdminNoticeMeta( $aAttrs[ 'id' ] ) ) ) {
109
- return false;
110
- }
111
-
112
  if ( isset( $aAttrs[ 'type' ] ) && $aAttrs[ 'type' ] == 'promo' ) {
113
  if ( $this->loadWp()->getIsMobile() ) {
114
  return false;
@@ -143,19 +135,24 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
143
  * @throws Exception
144
  */
145
  protected function insertAdminNotice( $aNoticeData ) {
146
- $bIsPromo = isset( $aNoticeData[ 'notice_attributes' ][ 'type' ] ) && $aNoticeData[ 'notice_attributes' ][ 'type' ] == 'promo';
 
147
  if ( $bIsPromo && $this->getPromoNoticesCount() > 0 ) {
148
  return;
149
  }
150
 
151
- $sRenderedNotice = $this->getFeature()->renderAdminNotice( $aNoticeData );
152
- if ( !empty( $sRenderedNotice ) ) {
153
- $this->loadAdminNoticesProcessor()->addAdminNotice(
154
- $sRenderedNotice,
155
- $aNoticeData[ 'notice_attributes' ][ 'notice_id' ]
156
- );
157
- if ( $bIsPromo ) {
158
- $this->incrementPromoNoticesCount();
 
 
 
 
159
  }
160
  }
161
  }
@@ -185,8 +182,7 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
185
  * @return string
186
  */
187
  protected function getGoogleRecaptchaLocale() {
188
- $aLocaleParts = explode( '_', $this->loadWp()->getLocale(), 2 );
189
- return $aLocaleParts[ 0 ];
190
  }
191
 
192
  /**
@@ -230,6 +226,23 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
230
  return $this->aSubProcessors;
231
  }
232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  /**
234
  * @return bool|int|string
235
  */
@@ -241,6 +254,6 @@ abstract class ICWP_WPSF_Processor_Base extends ICWP_WPSF_Foundation {
241
  * @return int
242
  */
243
  protected function time() {
244
- return $this->loadDataProcessor()->GetRequestTime();
245
  }
246
  }
41
  * @return int
42
  */
43
  protected function getPromoNoticesCount() {
44
+ return self::$nPromoNoticesCount;
45
  }
46
 
47
  /**
62
  public function autoAddToAdminNotices() {
63
  $oCon = $this->getController();
64
 
65
+ foreach ( $this->getFeature()->getAdminNotices() as $sNoticeId => $aAttrs ) {
66
 
67
+ if ( !$this->getIfDisplayAdminNotice( $aAttrs ) ) {
68
  continue;
69
  }
70
 
71
  $sMethodName = 'addNotice_'.str_replace( '-', '_', $sNoticeId );
72
+ if ( method_exists( $this, $sMethodName ) && isset( $aAttrs[ 'valid_admin' ] )
73
+ && $aAttrs[ 'valid_admin' ] && $oCon->getIsValidAdminArea() ) {
74
 
75
+ $aAttrs[ 'id' ] = $sNoticeId;
76
+ $aAttrs[ 'notice_id' ] = $sNoticeId;
77
+ call_user_func( array( $this, $sMethodName ), $aAttrs );
78
  }
79
  }
80
  }
86
  protected function getIfDisplayAdminNotice( $aAttrs ) {
87
  $oWpNotices = $this->loadAdminNoticesProcessor();
88
 
89
+ if ( empty( $aAttrs[ 'schedule' ] )
90
+ || !in_array( $aAttrs[ 'schedule' ], array( 'once', 'conditions', 'version', 'never' ) ) ) {
 
 
 
91
  $aAttrs[ 'schedule' ] = 'conditions';
92
  }
93
 
96
  }
97
 
98
  if ( $aAttrs[ 'schedule' ] == 'once'
99
+ && ( !$this->loadWpUsers()->canSaveMeta() || $oWpNotices->isDismissed( $aAttrs[ 'id' ] ) )
 
100
  ) {
101
  return false;
102
  }
103
 
 
 
 
 
 
104
  if ( isset( $aAttrs[ 'type' ] ) && $aAttrs[ 'type' ] == 'promo' ) {
105
  if ( $this->loadWp()->getIsMobile() ) {
106
  return false;
135
  * @throws Exception
136
  */
137
  protected function insertAdminNotice( $aNoticeData ) {
138
+ $aAttrs = $aNoticeData[ 'notice_attributes' ];
139
+ $bIsPromo = isset( $aAttrs[ 'type' ] ) && $aAttrs[ 'type' ] == 'promo';
140
  if ( $bIsPromo && $this->getPromoNoticesCount() > 0 ) {
141
  return;
142
  }
143
 
144
+ $oNotices = $this->loadAdminNoticesProcessor();
145
+ if ( !$oNotices->isDismissed( $aAttrs[ 'id' ] ) ) {
146
+
147
+ $sRenderedNotice = $this->getFeature()->renderAdminNotice( $aNoticeData );
148
+ if ( !empty( $sRenderedNotice ) ) {
149
+ $oNotices->addAdminNotice(
150
+ $sRenderedNotice,
151
+ $aNoticeData[ 'notice_attributes' ][ 'notice_id' ]
152
+ );
153
+ if ( $bIsPromo ) {
154
+ $this->incrementPromoNoticesCount();
155
+ }
156
  }
157
  }
158
  }
182
  * @return string
183
  */
184
  protected function getGoogleRecaptchaLocale() {
185
+ return str_replace( '_', '-', $this->loadWp()->getLocale() );
 
186
  }
187
 
188
  /**
226
  return $this->aSubProcessors;
227
  }
228
 
229
+ /**
230
+ * @return ICWP_UserMeta
231
+ */
232
+ protected function getCurrentUserMeta() {
233
+ return $this->getFeature()->getCurrentUserMeta();
234
+ }
235
+
236
+ /**
237
+ * Will prefix and return any string with the unique plugin prefix.
238
+ * @param string $sSuffix
239
+ * @param string $sGlue
240
+ * @return string
241
+ */
242
+ protected function prefix( $sSuffix = '', $sGlue = '-' ) {
243
+ return $this->getFeature()->prefix( $sSuffix, $sGlue );
244
+ }
245
+
246
  /**
247
  * @return bool|int|string
248
  */
254
  * @return int
255
  */
256
  protected function time() {
257
+ return $this->loadDP()->time();
258
  }
259
  }
src/processors/base_plugin.php CHANGED
@@ -63,6 +63,7 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
63
  $aRenderData = array(
64
  'notice_attributes' => $aAttr,
65
  'strings' => array(
 
66
  'dismiss' => _wpsf__( "I'd rather not show this support" ).' / '._wpsf__( "I've done this already" ).' :D',
67
  'forums' => __( 'Support Forums' )
68
  ),
@@ -81,15 +82,15 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
81
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
82
  $oFO = $this->getFeature();
83
 
84
- $bCanWizardWelcome = $oFO->getCanRunWizards();
85
 
86
  $aRenderData = array(
87
  'notice_attributes' => $aNoticeAttributes,
88
  'strings' => array(
89
  'dismiss' => _wpsf__( "I don't need the setup wizard just now" ),
90
- 'title' => _wpsf__( 'Try the all-new Welcome Wizard for the Shield Security plugin' ),
91
  'setup' => _wpsf__( 'The welcome wizard will help you get setup quickly and become familiar with some of the core Shield Security features.' ),
92
- 'no_setup' => _wpsf__( 'Unfortunately your site is running a PHP version that is too low to run the Setup Wizard. It needs to be PHP 5.4+' )
93
  ),
94
  'hrefs' => array(
95
  'wizard' => $bCanWizardWelcome ? $oFO->getUrl_Wizard( 'welcome' ) : 'javascript:{event.preventDefault();}',
@@ -117,7 +118,7 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
117
  $aRenderData = array(
118
  'notice_attributes' => $aAttr,
119
  'strings' => array(
120
- 'your_version' => sprintf( _wpsf__( 'Your PHP version is very old: %s' ), $oDp->getPhpVersion() ),
121
  'not_supported' => sprintf( _wpsf__( 'Newer features of %s do not support your PHP version.' ), $oCon->getHumanName() ),
122
  'ask_host' => _wpsf__( 'You should ask your host to upgrade or provide a much newer PHP version.' ),
123
  'questions' => _wpsf__( 'Please read here for further information:' ),
@@ -137,13 +138,14 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
137
  * @throws Exception
138
  */
139
  protected function addNotice_plugin_update_available( $aNoticeAttributes ) {
140
- $oFO = $this->getFeature();
141
- $oWpUsers = $this->loadWpUsers();
142
 
143
- $sAdminNoticeMetaKey = $oFO->prefix( 'plugin-update-available' );
144
- if ( $this->loadAdminNoticesProcessor()->getAdminNoticeIsDismissed( 'plugin-update-available' ) ) {
145
- $oWpUsers->updateUserMeta( $sAdminNoticeMetaKey, $oFO->getVersion() ); // so they've hidden it. Now we set the current version so it doesn't display below
146
- return;
 
147
  }
148
 
149
  if ( !$this->getIfShowAdminNotices() ) {
@@ -152,16 +154,16 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
152
 
153
  $oWp = $this->loadWp();
154
  $oWpPlugins = $this->loadWpPlugins();
155
- $sBaseFile = $this->getController()->getPluginBaseFile();
156
  if ( !$oWp->getIsPage_Updates() && $oWpPlugins->isUpdateAvailable( $sBaseFile ) ) { // Don't show on the update page
157
  $aRenderData = array(
158
  'notice_attributes' => $aNoticeAttributes,
159
  'render_slug' => 'plugin-update-available',
160
  'strings' => array(
161
- 'plugin_update_available' => sprintf( _wpsf__( 'There is an update available for the "%s" plugin.' ), $this->getController()
162
- ->getHumanName() ),
163
- 'click_update' => _wpsf__( 'Please click to update immediately' ),
164
- 'dismiss' => _wpsf__( 'Dismiss this notice' )
165
  ),
166
  'hrefs' => array(
167
  'upgrade_link' => $oWpPlugins->getLinkPluginUpgrade( $sBaseFile )
@@ -176,13 +178,13 @@ class ICWP_WPSF_Processor_BasePlugin extends ICWP_WPSF_Processor_BaseWpsf {
176
  * @param array $aNoticeAttributes
177
  */
178
  protected function addNotice_translate_plugin( $aNoticeAttributes ) {
179
-
180
  if ( $this->getIfShowAdminNotices() ) {
181
  $aRenderData = array(
182
  'notice_attributes' => $aNoticeAttributes,
183
  'strings' => array(
184
- 'like_to_help' => sprintf( _wpsf__( "Would you like to help translate the %s plugin into your language?" ), $this->getController()
185
- ->getHumanName() ),
 
186
  'head_over_to' => sprintf( _wpsf__( 'Head over to: %s' ), '' ),
187
  'site_url' => 'translate.icontrolwp.com',
188
  'dismiss' => _wpsf__( 'Dismiss this notice' )
63
  $aRenderData = array(
64
  'notice_attributes' => $aAttr,
65
  'strings' => array(
66
+ 'title' => 'Will you help us out with a quick WordPress.org review?',
67
  'dismiss' => _wpsf__( "I'd rather not show this support" ).' / '._wpsf__( "I've done this already" ).' :D',
68
  'forums' => __( 'Support Forums' )
69
  ),
82
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oFO */
83
  $oFO = $this->getFeature();
84
 
85
+ $bCanWizardWelcome = $oFO->canRunWizards();
86
 
87
  $aRenderData = array(
88
  'notice_attributes' => $aNoticeAttributes,
89
  'strings' => array(
90
  'dismiss' => _wpsf__( "I don't need the setup wizard just now" ),
91
+ 'title' => _wpsf__( 'Get started quickly with the Shield Security Setup Wizard' ),
92
  'setup' => _wpsf__( 'The welcome wizard will help you get setup quickly and become familiar with some of the core Shield Security features.' ),
93
+ 'no_setup' => _wpsf__( "Shield Security has a helpful setup wizard to walk you through the main features. Unfortunately your PHP version is reeeaally old as it needs PHP 5.4+ " )
94
  ),
95
  'hrefs' => array(
96
  'wizard' => $bCanWizardWelcome ? $oFO->getUrl_Wizard( 'welcome' ) : 'javascript:{event.preventDefault();}',
118
  $aRenderData = array(
119
  'notice_attributes' => $aAttr,
120
  'strings' => array(
121
+ 'title' => sprintf( _wpsf__( 'Your PHP version is very old: %s' ), $oDp->getPhpVersion() ),
122
  'not_supported' => sprintf( _wpsf__( 'Newer features of %s do not support your PHP version.' ), $oCon->getHumanName() ),
123
  'ask_host' => _wpsf__( 'You should ask your host to upgrade or provide a much newer PHP version.' ),
124
  'questions' => _wpsf__( 'Please read here for further information:' ),
138
  * @throws Exception
139
  */
140
  protected function addNotice_plugin_update_available( $aNoticeAttributes ) {
141
+ $oPlugin = $this->getController();
142
+ $oNotices = $this->loadAdminNoticesProcessor();
143
 
144
+ if ( $oNotices->isDismissed( 'plugin-update-available' ) ) {
145
+ $aMeta = $oNotices->getMeta( 'plugin-update-available' );
146
+ if ( $aMeta[ 'time' ] > $oPlugin->getReleaseTimestamp() ) {
147
+ return;
148
+ }
149
  }
150
 
151
  if ( !$this->getIfShowAdminNotices() ) {
154
 
155
  $oWp = $this->loadWp();
156
  $oWpPlugins = $this->loadWpPlugins();
157
+ $sBaseFile = $oPlugin->getPluginBaseFile();
158
  if ( !$oWp->getIsPage_Updates() && $oWpPlugins->isUpdateAvailable( $sBaseFile ) ) { // Don't show on the update page
159
  $aRenderData = array(
160
  'notice_attributes' => $aNoticeAttributes,
161
  'render_slug' => 'plugin-update-available',
162
  'strings' => array(
163
+ 'title' => sprintf( _wpsf__( 'Update available for the %s plugin.' ), $this->getController()
164
+ ->getHumanName() ),
165
+ 'click_update' => _wpsf__( 'Please click to update immediately' ),
166
+ 'dismiss' => _wpsf__( 'Dismiss this notice' )
167
  ),
168
  'hrefs' => array(
169
  'upgrade_link' => $oWpPlugins->getLinkPluginUpgrade( $sBaseFile )
178
  * @param array $aNoticeAttributes
179
  */
180
  protected function addNotice_translate_plugin( $aNoticeAttributes ) {
 
181
  if ( $this->getIfShowAdminNotices() ) {
182
  $aRenderData = array(
183
  'notice_attributes' => $aNoticeAttributes,
184
  'strings' => array(
185
+ 'title' => 'Você não fala Inglês? No hablas Inglés? Heeft u geen Engels spreekt?',
186
+ 'like_to_help' => sprintf( _wpsf__( "Can you help translate the %s plugin?" ), $this->getController()
187
+ ->getHumanName() ),
188
  'head_over_to' => sprintf( _wpsf__( 'Head over to: %s' ), '' ),
189
  'site_url' => 'translate.icontrolwp.com',
190
  'dismiss' => _wpsf__( 'Dismiss this notice' )
src/processors/comments_filter.php CHANGED
@@ -60,6 +60,7 @@ class ICWP_WPSF_Processor_CommentsFilter extends ICWP_WPSF_Processor_BaseWpsf {
60
  $aRenderData = array(
61
  'notice_attributes' => $aNoticeAttributes,
62
  'strings' => array(
 
63
  'appears_running_akismet' => _wpsf__( 'It appears you have Akismet Anti-SPAM running alongside the our human Anti-SPAM filter.' ),
64
  'not_recommended' => _wpsf__('This is not recommended and you should disable Akismet.'),
65
  'click_to_deactivate' => _wpsf__('Click to deactivate Akismet now.'),
60
  $aRenderData = array(
61
  'notice_attributes' => $aNoticeAttributes,
62
  'strings' => array(
63
+ 'title' => 'Akismet is Running',
64
  'appears_running_akismet' => _wpsf__( 'It appears you have Akismet Anti-SPAM running alongside the our human Anti-SPAM filter.' ),
65
  'not_recommended' => _wpsf__('This is not recommended and you should disable Akismet.'),
66
  'click_to_deactivate' => _wpsf__('Click to deactivate Akismet now.'),
src/processors/hack_protect.php CHANGED
@@ -26,7 +26,7 @@ class ICWP_WPSF_Processor_HackProtect extends ICWP_WPSF_Processor_BaseWpsf {
26
  if ( $oFO->isWcfScanEnabled() ) {
27
  $this->runChecksumScan();
28
  }
29
- if ( $oFO->isUfsEnabled() ) {
30
  $this->runFileCleanerScan();
31
  }
32
  if ( $oFO->isWpvulnEnabled() ) {
26
  if ( $oFO->isWcfScanEnabled() ) {
27
  $this->runChecksumScan();
28
  }
29
+ if ( $oFO->isUfcEnabled() ) {
30
  $this->runFileCleanerScan();
31
  }
32
  if ( $oFO->isWpvulnEnabled() ) {
src/processors/hackprotect_corechecksumscan.php CHANGED
@@ -4,7 +4,7 @@ if ( class_exists( 'ICWP_WPSF_Processor_HackProtect_CoreChecksumScan', false ) )
4
  return;
5
  }
6
 
7
- require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'base_wpsf.php' );
8
 
9
  class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Processor_BaseWpsf {
10
 
@@ -24,7 +24,7 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
24
  switch ( $sAction ) {
25
 
26
  case 'repair_file':
27
- $sPath = '/' . trim( $oDp->FetchGet( 'repair_file_path' ) ); // "/" prevents esc_url() from prepending http.
28
  $sMd5FilePath = urldecode( esc_url( $sPath ) );
29
  if ( !empty( $sMd5FilePath ) ) {
30
  if ( $this->repairCoreFile( $sMd5FilePath ) ) {
@@ -46,19 +46,23 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
46
  }
47
 
48
  protected function setupChecksumCron() {
 
 
49
  $this->loadWpCronProcessor()
50
- ->setRecurrence( 'daily' )
51
  ->createCronJob(
52
- $this->getCronName(),
53
  array( $this, 'cron_dailyChecksumScan' )
54
  );
55
- add_action( $this->getFeature()->prefix( 'delete_plugin' ), array( $this, 'deleteCron' ) );
56
  }
57
 
58
  /**
59
  */
60
  public function deleteCron() {
61
- $this->loadWpCronProcessor()->deleteCronJob( $this->getCronName() );
 
 
62
  }
63
 
64
  /**
@@ -82,8 +86,8 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
82
  $aAutoFixIndexFiles = array();
83
  }
84
 
85
- $sFullExclusionsPattern = '#(' . implode( '|', $this->getFullExclusions() ) . ')#i';
86
- $sMissingOnlyExclusionsPattern = '#(' . implode( '|', $this->getMissingOnlyExclusions() ) . ')#i';
87
 
88
  $oFS = $this->loadFS();
89
  foreach ( $aChecksumData as $sMd5FilePath => $sWpOrgChecksum ) {
@@ -141,7 +145,7 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
141
  }
142
 
143
  $bOptionRepair = $this->getIsOption( 'attempt_auto_file_repair', 'Y' )
144
- || ( $this->loadDataProcessor()->FetchGet( 'checksum_repair' ) == 1 );
145
 
146
  $aDiscoveredFiles = $this->doChecksumScan( $bOptionRepair );
147
  if ( !empty( $aDiscoveredFiles[ 'checksum_mismatch' ] ) || !empty( $aDiscoveredFiles[ 'missing' ] ) ) {
@@ -193,7 +197,7 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
193
  $sLocale = $this->loadWp()->getLocale( true );
194
  $bUseInternational = $bUseLocale && ( $sLocale != 'en_US' );
195
  if ( $bUseInternational ) {
196
- $sRootUrl = $this->getFeature()->getDefinition( 'url_wordress_core_svn_il8n' ) . $sLocale;
197
  }
198
  else {
199
  $sRootUrl = $this->getFeature()->getDefinition( 'url_wordress_core_svn' );
@@ -202,7 +206,7 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
202
  '%s/tags/%s/%s',
203
  $sRootUrl,
204
  $this->loadWp()->getVersion(),
205
- ( $bUseInternational ? 'dist/' : '' ) . $sPath
206
  );
207
 
208
  $sContent = (string)$this->loadFS()->getUrlContent( $sFileUrl );
@@ -242,7 +246,7 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
242
  sprintf( _wpsf__( '%s has detected files on your site with potential problems.' ), $this->getController()
243
  ->getHumanName() ),
244
  _wpsf__( 'This is part of the Hack Protection feature for the WordPress Core File Scanner.' )
245
- . ' [<a href="http://icwp.io/moreinfochecksum">' . _wpsf__( 'More Info' ) . ']</a>',
246
  sprintf( _wpsf__( 'Site Home URL - %s' ), sprintf( '<a href="%s" target="_blank">%s</a>', $sHomeUrl, $sHomeUrl ) ),
247
  '',
248
  _wpsf__( 'Details for the problem files are below:' ),
@@ -252,33 +256,33 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
252
  $aContent[] = '';
253
  $aContent[] = _wpsf__( 'The MD5 Checksum Hashes for following core files do not match the official WordPress.org Checksum Hashes:' );
254
  foreach ( $aFiles[ 'checksum_mismatch' ] as $sFile ) {
255
- $aContent[] = ' - ' . $sFile . $this->getFileRepairLink( $sFile );
256
  }
257
  }
258
  if ( !empty( $aFiles[ 'missing' ] ) ) {
259
  $aContent[] = '';
260
  $aContent[] = _wpsf__( 'The following official WordPress core files are missing from your site:' );
261
  foreach ( $aFiles[ 'missing' ] as $sFile ) {
262
- $aContent[] = ' - ' . $sFile . $this->getFileRepairLink( $sFile );
263
  }
264
  }
265
 
266
  $aContent[] = '';
267
  if ( $this->getIsOption( 'attempt_auto_file_repair', 'Y' ) ) {
268
  $aContent[] = _wpsf__( 'We have already attempted to repair these files based on your current settings.' )
269
- . ' ' . _wpsf__( 'But, you should always check these files to ensure everything is as you expect.' );
270
  }
271
  else {
272
  $aContent[] = _wpsf__( 'You should review these files and replace them with official versions if required.' );
273
  $aContent[] = _wpsf__( 'Alternatively you can have the plugin attempt to repair/replace these files automatically.' )
274
- . ' [<a href="http://icwp.io/moreinfochecksum">' . _wpsf__( 'More Info' ) . ']</a>';
275
  }
276
 
277
  $aContent[] = '';
278
 
279
  /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
280
  $oFO = $this->getFeature();
281
- if ( $oFO->getCanRunWizards() ) {
282
  $aContent[] = sprintf( '<a href="%s" target="_blank" style="%s">%s →</a>',
283
  $oFO->getUrl_Wizard( 'wcf' ),
284
  'border:1px solid;padding:20px;line-height:19px;margin:10px 20px;display:inline-block;text-align:center;width:290px;font-size:18px;',
@@ -333,7 +337,7 @@ class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Process
333
  $sFullPath = path_join( WP_CONTENT_DIR, str_replace( 'wp-content/', '', $sMd5FilePath ) );
334
  }
335
  else {
336
- $sFullPath = ABSPATH . $sMd5FilePath;
337
  }
338
  return $sFullPath;
339
  }
4
  return;
5
  }
6
 
7
+ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
8
 
9
  class ICWP_WPSF_Processor_HackProtect_CoreChecksumScan extends ICWP_WPSF_Processor_BaseWpsf {
10
 
24
  switch ( $sAction ) {
25
 
26
  case 'repair_file':
27
+ $sPath = '/'.trim( $oDp->FetchGet( 'repair_file_path' ) ); // "/" prevents esc_url() from prepending http.
28
  $sMd5FilePath = urldecode( esc_url( $sPath ) );
29
  if ( !empty( $sMd5FilePath ) ) {
30
  if ( $this->repairCoreFile( $sMd5FilePath ) ) {
46
  }
47
 
48
  protected function setupChecksumCron() {
49
+ /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
50
+ $oFO = $this->getFeature();
51
  $this->loadWpCronProcessor()
52
+ ->setRecurrence( $this->prefix( sprintf( 'per-day-%s', $oFO->getScanFrequency() ) ) )
53
  ->createCronJob(
54
+ $oFO->getWcfCronName(),
55
  array( $this, 'cron_dailyChecksumScan' )
56
  );
57
+ add_action( $oFO->prefix( 'delete_plugin' ), array( $this, 'deleteCron' ) );
58
  }
59
 
60
  /**
61
  */
62
  public function deleteCron() {
63
+ /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
64
+ $oFO = $this->getFeature();
65
+ $this->loadWpCronProcessor()->deleteCronJob( $oFO->getWcfCronName() );
66
  }
67
 
68
  /**
86
  $aAutoFixIndexFiles = array();
87
  }
88
 
89
+ $sFullExclusionsPattern = '#('.implode( '|', $this->getFullExclusions() ).')#i';
90
+ $sMissingOnlyExclusionsPattern = '#('.implode( '|', $this->getMissingOnlyExclusions() ).')#i';
91
 
92
  $oFS = $this->loadFS();
93
  foreach ( $aChecksumData as $sMd5FilePath => $sWpOrgChecksum ) {
145
  }
146
 
147
  $bOptionRepair = $this->getIsOption( 'attempt_auto_file_repair', 'Y' )
148
+ || ( $this->loadDP()->query( 'checksum_repair' ) == 1 );
149
 
150
  $aDiscoveredFiles = $this->doChecksumScan( $bOptionRepair );
151
  if ( !empty( $aDiscoveredFiles[ 'checksum_mismatch' ] ) || !empty( $aDiscoveredFiles[ 'missing' ] ) ) {
197
  $sLocale = $this->loadWp()->getLocale( true );
198
  $bUseInternational = $bUseLocale && ( $sLocale != 'en_US' );
199
  if ( $bUseInternational ) {
200
+ $sRootUrl = $this->getFeature()->getDefinition( 'url_wordress_core_svn_il8n' ).$sLocale;
201
  }
202
  else {
203
  $sRootUrl = $this->getFeature()->getDefinition( 'url_wordress_core_svn' );
206
  '%s/tags/%s/%s',
207
  $sRootUrl,
208
  $this->loadWp()->getVersion(),
209
+ ( $bUseInternational ? 'dist/' : '' ).$sPath
210
  );
211
 
212
  $sContent = (string)$this->loadFS()->getUrlContent( $sFileUrl );
246
  sprintf( _wpsf__( '%s has detected files on your site with potential problems.' ), $this->getController()
247
  ->getHumanName() ),
248
  _wpsf__( 'This is part of the Hack Protection feature for the WordPress Core File Scanner.' )
249
+ .' [<a href="http://icwp.io/moreinfochecksum">'._wpsf__( 'More Info' ).']</a>',
250
  sprintf( _wpsf__( 'Site Home URL - %s' ), sprintf( '<a href="%s" target="_blank">%s</a>', $sHomeUrl, $sHomeUrl ) ),
251
  '',
252
  _wpsf__( 'Details for the problem files are below:' ),
256
  $aContent[] = '';
257
  $aContent[] = _wpsf__( 'The MD5 Checksum Hashes for following core files do not match the official WordPress.org Checksum Hashes:' );
258
  foreach ( $aFiles[ 'checksum_mismatch' ] as $sFile ) {
259
+ $aContent[] = ' - '.$sFile.$this->getFileRepairLink( $sFile );
260
  }
261
  }
262
  if ( !empty( $aFiles[ 'missing' ] ) ) {
263
  $aContent[] = '';
264
  $aContent[] = _wpsf__( 'The following official WordPress core files are missing from your site:' );
265
  foreach ( $aFiles[ 'missing' ] as $sFile ) {
266
+ $aContent[] = ' - '.$sFile.$this->getFileRepairLink( $sFile );
267
  }
268
  }
269
 
270
  $aContent[] = '';
271
  if ( $this->getIsOption( 'attempt_auto_file_repair', 'Y' ) ) {
272
  $aContent[] = _wpsf__( 'We have already attempted to repair these files based on your current settings.' )
273
+ .' '._wpsf__( 'But, you should always check these files to ensure everything is as you expect.' );
274
  }
275
  else {
276
  $aContent[] = _wpsf__( 'You should review these files and replace them with official versions if required.' );
277
  $aContent[] = _wpsf__( 'Alternatively you can have the plugin attempt to repair/replace these files automatically.' )
278
+ .' [<a href="http://icwp.io/moreinfochecksum">'._wpsf__( 'More Info' ).']</a>';
279
  }
280
 
281
  $aContent[] = '';
282
 
283
  /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
284
  $oFO = $this->getFeature();
285
+ if ( $oFO->canRunWizards() ) {
286
  $aContent[] = sprintf( '<a href="%s" target="_blank" style="%s">%s →</a>',
287
  $oFO->getUrl_Wizard( 'wcf' ),
288
  'border:1px solid;padding:20px;line-height:19px;margin:10px 20px;display:inline-block;text-align:center;width:290px;font-size:18px;',
337
  $sFullPath = path_join( WP_CONTENT_DIR, str_replace( 'wp-content/', '', $sMd5FilePath ) );
338
  }
339
  else {
340
+ $sFullPath = ABSPATH.$sMd5FilePath;
341
  }
342
  return $sFullPath;
343
  }
src/processors/hackprotect_filecleanerscan.php CHANGED
@@ -35,19 +35,23 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
35
  }
36
 
37
  protected function setupChecksumCron() {
 
 
38
  $this->loadWpCronProcessor()
39
- ->setRecurrence( 'daily' )
40
  ->createCronJob(
41
- $this->getCronName(),
42
  array( $this, 'cron_dailyFileCleanerScan' )
43
  );
44
- add_action( $this->getFeature()->prefix( 'delete_plugin' ), array( $this, 'deleteCron' ) );
45
  }
46
 
47
  /**
48
  */
49
  public function deleteCron() {
50
- $this->loadWpCronProcessor()->deleteCronJob( $this->getCronName() );
 
 
51
  }
52
 
53
  /**
@@ -170,7 +174,7 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
170
  }
171
  /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
172
  $oFO = $this->getFeature();
173
- if ( $oFO->isUfsEnabled() ) {
174
  try {
175
  $this->runScan(); // The file scanning part can exception with permission & exists
176
  }
@@ -187,7 +191,7 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
187
  $oFO = $this->getFeature();
188
  $aDiscoveredFiles = $this->discoverFiles();
189
  if ( !empty( $aDiscoveredFiles ) ) {
190
- if ( $oFO->isUfsDeleteFiles() ) {
191
  $this->deleteFiles( $aDiscoveredFiles );
192
  }
193
  if ( $oFO->isUfsSendReport() ) {
@@ -237,7 +241,7 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
237
  }
238
 
239
  $aContent[] = '';
240
- if ( $oFO->getCanRunWizards() ) {
241
  $aContent[] = sprintf( '<a href="%s" target="_blank" style="%s">%s →</a>',
242
  $oFO->getUrl_Wizard( 'ufc' ),
243
  'border:1px solid;padding:20px;line-height:19px;margin:10px 20px;display:inline-block;text-align:center;width:290px;font-size:18px;',
@@ -246,7 +250,7 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
246
  $aContent[] = '';
247
  }
248
 
249
- if ( $oFO->isUfsDeleteFiles() ) {
250
  $aContent[] = _wpsf__( 'We have already attempted to delete these files based on your current settings.' )
251
  .' '._wpsf__( 'But, you should always check these files to ensure everything is as you expect.' );
252
  }
@@ -300,14 +304,6 @@ class ICWP_WPSF_Processor_HackProtect_FileCleanerScan extends ICWP_WPSF_Processo
300
  _wpsf__( 'WordPress.org source file' )
301
  );
302
  }
303
-
304
- /**
305
- * @return string
306
- */
307
- protected function getCronName() {
308
- $oFO = $this->getFeature();
309
- return $oFO->prefixOptionKey( $oFO->getDefinition( 'unrecognisedscan_cron_name' ) );
310
- }
311
  }
312
 
313
  class CleanerRecursiveFilterIterator extends RecursiveFilterIterator {
35
  }
36
 
37
  protected function setupChecksumCron() {
38
+ /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
39
+ $oFO = $this->getFeature();
40
  $this->loadWpCronProcessor()
41
+ ->setRecurrence( $this->prefix( sprintf( 'per-day-%s', $oFO->getScanFrequency() ) ) )
42
  ->createCronJob(
43
+ $oFO->getUfcCronName(),
44
  array( $this, 'cron_dailyFileCleanerScan' )
45
  );
46
+ add_action( $oFO->prefix( 'delete_plugin' ), array( $this, 'deleteCron' ) );
47
  }
48
 
49
  /**
50
  */
51
  public function deleteCron() {
52
+ /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
53
+ $oFO = $this->getFeature();
54
+ $this->loadWpCronProcessor()->deleteCronJob( $oFO->getUfcCronName() );
55
  }
56
 
57
  /**
174
  }
175
  /** @var ICWP_WPSF_FeatureHandler_HackProtect $oFO */
176
  $oFO = $this->getFeature();
177
+ if ( $oFO->isUfcEnabled() ) {
178
  try {
179
  $this->runScan(); // The file scanning part can exception with permission & exists
180
  }
191
  $oFO = $this->getFeature();
192
  $aDiscoveredFiles = $this->discoverFiles();
193
  if ( !empty( $aDiscoveredFiles ) ) {
194
+ if ( $oFO->isUfcDeleteFiles() ) {
195
  $this->deleteFiles( $aDiscoveredFiles );
196
  }
197
  if ( $oFO->isUfsSendReport() ) {
241
  }
242
 
243
  $aContent[] = '';
244
+ if ( $oFO->canRunWizards() ) {
245
  $aContent[] = sprintf( '<a href="%s" target="_blank" style="%s">%s →</a>',
246
  $oFO->getUrl_Wizard( 'ufc' ),
247
  'border:1px solid;padding:20px;line-height:19px;margin:10px 20px;display:inline-block;text-align:center;width:290px;font-size:18px;',
250
  $aContent[] = '';
251
  }
252
 
253
+ if ( $oFO->isUfcDeleteFiles() ) {
254
  $aContent[] = _wpsf__( 'We have already attempted to delete these files based on your current settings.' )
255
  .' '._wpsf__( 'But, you should always check these files to ensure everything is as you expect.' );
256
  }
304
  _wpsf__( 'WordPress.org source file' )
305
  );
306
  }
 
 
 
 
 
 
 
 
307
  }
308
 
309
  class CleanerRecursiveFilterIterator extends RecursiveFilterIterator {
src/processors/ips.php CHANGED
@@ -11,6 +11,7 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
11
  const LIST_MANUAL_WHITE = 'MW';
12
  const LIST_MANUAL_BLACK = 'MB';
13
  const LIST_AUTO_BLACK = 'AB';
 
14
  /**
15
  * @var bool
16
  */
@@ -102,15 +103,14 @@ class ICWP_WPSF_Processor_Ips extends ICWP_WPSF_BaseDbProcessor {
102
  */
103
  public function addNotice_visitor_whitelisted( $aNoticeAttributes ) {
104
 
105
- if ( $this->getController()->getIsPage_PluginAdmin() && $this->getIsVisitorWhitelisted() ) {
 
106
  $aRenderData = array(
107
  'notice_attributes' => $aNoticeAttributes,
108
  'strings' => array(
 
109
  'your_ip' => sprintf( _wpsf__( 'Your IP address is: %s' ), $this->ip() ),
110
- 'notice_message' => sprintf(
111
- _wpsf__( 'Notice - %s' ),
112
- _wpsf__( 'You should know that your IP address is whitelisted and features you activate do not apply to you.' )
113
- ),
114
  'including_message' => _wpsf__( 'Including the Rename WP Login feature.' )
115
  )
116
  );
11
  const LIST_MANUAL_WHITE = 'MW';
12
  const LIST_MANUAL_BLACK = 'MB';
13
  const LIST_AUTO_BLACK = 'AB';
14
+
15
  /**
16
  * @var bool
17
  */
103
  */
104
  public function addNotice_visitor_whitelisted( $aNoticeAttributes ) {
105
 
106
+ if ( $this->getController()->getIsPage_PluginAdmin() && $this->getIsVisitorWhitelisted() ) {#
107
+ $oCon = $this->getController();
108
  $aRenderData = array(
109
  'notice_attributes' => $aNoticeAttributes,
110
  'strings' => array(
111
+ 'title' => sprintf( _wpsf__( '%s is ignoring you' ), $oCon->getHumanName() ),
112
  'your_ip' => sprintf( _wpsf__( 'Your IP address is: %s' ), $this->ip() ),
113
+ 'notice_message' => _wpsf__( 'Your IP address is whitelisted and NO features you activate apply to you.' ),
 
 
 
114
  'including_message' => _wpsf__( 'Including the Rename WP Login feature.' )
115
  )
116
  );
src/processors/login_protect.php CHANGED
@@ -66,11 +66,16 @@ class ICWP_WPSF_Processor_LoginProtect extends ICWP_WPSF_Processor_BaseWpsf {
66
  $aRenderData = array(
67
  'notice_attributes' => $aNoticeAttributes,
68
  'strings' => array(
69
- 'need_you_confirm' => _wpsf__( "Before completing activation of email-based two-factor authentication we need you to confirm your site can send emails." ),
 
 
70
  'please_click_link' => _wpsf__( "Please click the link in the email you received." ),
71
- 'email_sent_to' => sprintf( _wpsf__( "The email has been sent to you at blog admin address: %s" ), get_bloginfo( 'admin_email' ) ),
72
- 'how_resend_email' => _wpsf__( "To have this email resent, re-save your Login Protection settings." ),
73
- 'how_turn_off' => _wpsf__( "To turn this notice off, disable Two Factor authentication." ),
 
 
 
74
  )
75
  );
76
  $this->insertAdminNotice( $aRenderData );
66
  $aRenderData = array(
67
  'notice_attributes' => $aNoticeAttributes,
68
  'strings' => array(
69
+ 'title' => $this->getController()->getHumanName()
70
+ .': '._wpsf__( 'Please verify email has been received' ),
71
+ 'need_you_confirm' => _wpsf__( "Before we can activate email 2-factor authentication, we need you to confirm your website can send emails." ),
72
  'please_click_link' => _wpsf__( "Please click the link in the email you received." ),
73
+ 'email_sent_to' => sprintf(
74
+ _wpsf__( "The email has been sent to you at blog admin address: %s" ),
75
+ '<strong>'.get_bloginfo( 'admin_email' ).'</strong>'
76
+ ),
77
+ 'how_resend_email' => _wpsf__( "To resend the email, re-save your Login Protection settings." ),
78
+ 'how_turn_off' => _wpsf__( "To turn this notice off, disable 2-Factor Authentication." ),
79
  )
80
  );
81
  $this->insertAdminNotice( $aRenderData );
src/processors/loginprotect_googleauthenticator.php CHANGED
@@ -12,7 +12,7 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
12
  */
13
  public function run() {
14
  parent::run();
15
- if ( $this->loadDataProcessor()->FetchGet( 'wpsf-action' ) == 'garemovalconfirm' ) {
16
  add_action( 'init', array( $this, 'validateUserGaRemovalLink' ), 10 );
17
  }
18
  }
@@ -127,14 +127,14 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
127
  }
128
 
129
  /**
130
- * @param WP_User $oSavingUser
 
131
  */
132
- protected function processRemovalFromAccount( $oSavingUser ) {
133
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
134
- $oFO = $this->getFeature();
135
- $oWpUsers = $this->loadWpUsers();
136
- $oWpUsers->updateUserMeta( $oFO->prefixOptionKey( 'ga_validated' ), 'N', $oSavingUser->ID );
137
- $oWpUsers->updateUserMeta( $oFO->prefixOptionKey( 'ga_secret' ), '', $oSavingUser->ID );
138
  }
139
 
140
  /**
@@ -368,7 +368,7 @@ class ICWP_WPSF_Processor_LoginProtect_GoogleAuthenticator extends ICWP_WPSF_Pro
368
  */
369
  protected function generateGaRemovalConfirmationLink() {
370
  $aQueryArgs = array(
371
- 'wpsf-action' => 'garemovalconfirm',
372
  'sessionid' => $this->getController()->getSessionId()
373
  );
374
  return add_query_arg( $aQueryArgs, $this->loadWp()->getUrl_WpAdmin() );
12
  */
13
  public function run() {
14
  parent::run();
15
+ if ( $this->loadDP()->query( 'shield_action' ) == 'garemovalconfirm' ) {
16
  add_action( 'init', array( $this, 'validateUserGaRemovalLink' ), 10 );
17
  }
18
  }
127
  }
128
 
129
  /**
130
+ * @param WP_User $oUser
131
+ * @return $this
132
  */
133
+ protected function processRemovalFromAccount( $oUser ) {
134
+ $oMeta = $this->loadWpUsers()->metaVoForUser( $this->prefix(), $oUser->ID );
135
+ $oMeta->ga_validated = 'N';
136
+ $oMeta->ga_secret = 'N';
137
+ return $this;
 
138
  }
139
 
140
  /**
368
  */
369
  protected function generateGaRemovalConfirmationLink() {
370
  $aQueryArgs = array(
371
+ 'shield_action' => 'garemovalconfirm',
372
  'sessionid' => $this->getController()->getSessionId()
373
  );
374
  return add_query_arg( $aQueryArgs, $this->loadWp()->getUrl_WpAdmin() );
src/processors/loginprotect_intent.php CHANGED
@@ -16,8 +16,18 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
16
  /**
17
  */
18
  public function run() {
 
 
 
 
 
 
 
 
 
19
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
20
  $oFO = $this->getFeature();
 
21
 
22
  $oLoginTracker = $this->getLoginTrack();
23
 
@@ -39,25 +49,20 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
39
 
40
  if ( $oLoginTracker->hasFactorsRemainingToTrack() ) {
41
  if ( $this->loadWp()->isRequestUserLogin() || $oFO->getIfSupport3rdParty() ) {
42
- add_filter( 'authenticate', array( $this, 'setUserLoginIntent' ), 100, 1 );
43
  }
44
- add_action( 'init', array( $this, 'onWpInit' ), 0 );
45
- }
46
 
47
- add_action( 'wp_logout', array( $this, 'onWpLogout' ) );
48
- return true;
49
- }
50
-
51
- public function onWpInit() {
52
- if ( $this->loadWpUsers()->isUserLoggedIn() ) {
53
 
54
- if ( $this->isCurrentUserSubjectToLoginIntent() ) {
55
- $this->processUserLoginIntent();
56
- }
57
- else if ( $this->getUserLoginIntent() !== false ) {
58
- // This handles the case where an admin changes a setting while a user is logged-in
59
- // So to prevent this, we remove any intent for a user that isn't subject to it right now
60
- $this->removeLoginIntent();
 
61
  }
62
  }
63
  }
@@ -65,18 +70,23 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
65
  /**
66
  * hooked to 'init' and only run if a user is logged in
67
  */
68
- public function processUserLoginIntent() {
 
 
 
 
 
69
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
70
  $oFO = $this->getFeature();
71
 
72
- if ( $this->userHasPendingLoginIntent() ) {
73
  $oDp = $this->loadDP();
74
 
75
  $bIsLoginIntentSubmission = $oDp->FetchRequest( $oFO->getLoginIntentRequestFlag() ) == 1;
76
  if ( $bIsLoginIntentSubmission ) {
77
 
78
  if ( $oDp->post( 'cancel' ) == 1 ) {
79
- $this->loadWpUsers()->logoutUser(); // clears the login and login intent
80
  $this->loadWp()->redirectToLogin();
81
  return;
82
  }
@@ -91,13 +101,14 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
91
  }
92
 
93
  if ( $bLoginIntentValidated ) {
 
 
 
 
 
94
  $this->removeLoginIntent();
95
- $sRedirect = $oDp->post( 'redirect_to' );
96
  $this->loadAdminNoticesProcessor()->addFlashMessage(
97
  _wpsf__( 'Success' ).'! '._wpsf__( 'Thank you for authenticating your login.' ) );
98
- if ( !empty( $sRedirect ) ) {
99
- // $this->loadWp()->doRedirect( site_url( rawurldecode( $sRedirect ) ) );
100
- }
101
  }
102
  else {
103
  $this->loadAdminNoticesProcessor()->addFlashMessage(
@@ -109,91 +120,104 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
109
  die();
110
  }
111
  }
 
 
 
 
112
  else {
113
- $nIntent = $this->getUserLoginIntent();
114
- if ( $nIntent === false ) {
115
- // the login has already been fully validated and the login intent was deleted.
116
- // false also means new installation don't get booted out
117
- }
118
- else if ( $nIntent > 0 ) { // there was an old login intent
119
- $this->loadWpUsers()->logoutUser(); // clears the login and login intent
120
- $this->loadWp()->redirectHere();
121
- }
122
  }
123
  }
124
 
125
  /**
126
  */
127
  public function onWpLogout() {
128
- $this->resetUserLoginIntent();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  }
130
 
131
  /**
132
  * Use this ONLY when the login intent has been successfully verified.
 
133
  */
134
  protected function removeLoginIntent() {
135
- $this->loadWpUsers()->deleteUserMeta( $this->getOptionKey() );
 
136
  }
137
 
138
  /**
139
  * Reset will put the counter to zero - this should be used when the user HAS NOT
140
  * verified the login intent. To indicate that they have successfully verified, use removeLoginIntent()
 
141
  */
142
- public function resetUserLoginIntent() {
143
- $this->setLoginIntentExpiration( 0 );
 
144
  }
145
 
146
  /**
147
- * @param int $nExpirationTime
148
- * @param null $oUser
 
149
  */
150
- protected function setLoginIntentExpiration( $nExpirationTime, $oUser = null ) {
151
- $this->loadWpUsers()->updateUserMeta( $this->getOptionKey(), max( 0, (int)$nExpirationTime ), $oUser );
 
 
152
  }
153
 
154
  /**
155
- * @return string
156
  */
157
- protected function getOptionKey() {
158
- return $this->getFeature()->prefixOptionKey( 'login_intent' );
 
 
 
159
  }
160
 
161
  /**
162
- * If it's a valid login attempt (by password) then $oUser is a WP_User
163
- * @param WP_User|WP_Error $oUser
164
- * @return WP_User
165
  */
166
- public function setUserLoginIntent( $oUser ) {
167
- if ( !empty( $oUser ) && ( $oUser instanceof WP_User ) ) {
168
- $oF = $this->getFeature();
169
- $nTimeout = (int)apply_filters(
170
- $oF->prefix( 'login_intent_timeout' ),
171
- $oF->getDefinition( 'login_intent_timeout' )
172
- );
173
- $this->setLoginIntentExpiration( $this->time() + MINUTE_IN_SECONDS*$nTimeout, $oUser );
174
- }
175
- return $oUser;
176
  }
177
 
178
  /**
179
  * @return bool
180
  */
181
- protected function userHasPendingLoginIntent() {
182
- return ( $this->getUserLoginIntent() > $this->time() );
183
  }
184
 
185
  /**
186
  * @return bool
187
  */
188
- protected function isCurrentUserSubjectToLoginIntent() {
189
- return apply_filters( $this->getFeature()->prefixOptionKey( 'user_subject_to_login_intent' ), false );
190
- }
191
-
192
- /**
193
- * @return int|false
194
- */
195
- protected function getUserLoginIntent() {
196
- return $this->loadWpUsers()->getUserMeta( $this->getOptionKey() );
197
  }
198
 
199
  /**
@@ -239,11 +263,12 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
239
  'more_info' => _wpsf__( 'More Info' ),
240
  'what_is_this' => _wpsf__( 'What is this?' ),
241
  'message' => $sMessage,
242
- 'page_title' => sprintf( _wpsf__( '%s Login Verification' ), $oCon->getHumanName() )
 
243
  ),
244
  'data' => array(
245
  'login_fields' => $aLoginIntentFields,
246
- 'time_remaining' => $this->getUserLoginIntent() - $this->time(),
247
  'message_type' => $sMessageType,
248
  'login_intent_flag' => $oFO->getLoginIntentRequestFlag()
249
  ),
@@ -255,6 +280,9 @@ class ICWP_WPSF_Processor_LoginProtect_Intent extends ICWP_WPSF_Processor_BaseWp
255
  'redirect_to' => $sRedirectTo,
256
  'what_is_this' => 'https://icontrolwp.freshdesk.com/support/solutions/articles/3000064840',
257
  'favicon' => $oCon->getPluginUrl_Image( 'pluginlogo_24x24.png' ),
 
 
 
258
  )
259
  );
260
 
16
  /**
17
  */
18
  public function run() {
19
+ add_action( 'init', array( $this, 'onWpInit' ), 0 );
20
+ add_action( 'wp_logout', array( $this, 'onWpLogout' ) );
21
+ }
22
+
23
+ public function onWpInit() {
24
+ $this->setupLoginIntent();
25
+ }
26
+
27
+ protected function setupLoginIntent() {
28
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
29
  $oFO = $this->getFeature();
30
+ $oWpUsers = $this->loadWpUsers();
31
 
32
  $oLoginTracker = $this->getLoginTrack();
33
 
49
 
50
  if ( $oLoginTracker->hasFactorsRemainingToTrack() ) {
51
  if ( $this->loadWp()->isRequestUserLogin() || $oFO->getIfSupport3rdParty() ) {
52
+ add_filter( 'authenticate', array( $this, 'initLoginIntent' ), 100, 1 );
53
  }
 
 
54
 
55
+ // process the current login intent
56
+ if ( $oWpUsers->isUserLoggedIn() ) {
 
 
 
 
57
 
58
+ if ( $this->isCurrentUserSubjectToLoginIntent() ) {
59
+ $this->processLoginIntent();
60
+ }
61
+ else if ( $this->hasLoginIntent() ) {
62
+ // This handles the case where an admin changes a setting while a user is logged-in
63
+ // So to prevent this, we remove any intent for a user that isn't subject to it right now
64
+ $this->removeLoginIntent();
65
+ }
66
  }
67
  }
68
  }
70
  /**
71
  * hooked to 'init' and only run if a user is logged in
72
  */
73
+ protected function processLoginIntent() {
74
+ $oWpUsers = $this->loadWpUsers();
75
+ if ( !$oWpUsers->isUserLoggedIn() ) {
76
+ return;
77
+ }
78
+
79
  /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
80
  $oFO = $this->getFeature();
81
 
82
+ if ( $this->hasValidLoginIntent() ) { // ie. valid login intent present
83
  $oDp = $this->loadDP();
84
 
85
  $bIsLoginIntentSubmission = $oDp->FetchRequest( $oFO->getLoginIntentRequestFlag() ) == 1;
86
  if ( $bIsLoginIntentSubmission ) {
87
 
88
  if ( $oDp->post( 'cancel' ) == 1 ) {
89
+ $oWpUsers->logoutUser(); // clears the login and login intent
90
  $this->loadWp()->redirectToLogin();
91
  return;
92
  }
101
  }
102
 
103
  if ( $bLoginIntentValidated ) {
104
+
105
+ if ( $oDp->post( 'skip_mfa' ) === 'Y' ) { // store the browser hash
106
+ $oFO->addMfaLoginHash( $oWpUsers->getCurrentWpUser() );
107
+ }
108
+
109
  $this->removeLoginIntent();
 
110
  $this->loadAdminNoticesProcessor()->addFlashMessage(
111
  _wpsf__( 'Success' ).'! '._wpsf__( 'Thank you for authenticating your login.' ) );
 
 
 
112
  }
113
  else {
114
  $this->loadAdminNoticesProcessor()->addFlashMessage(
120
  die();
121
  }
122
  }
123
+ else if ( $this->hasLoginIntent() ) { // there was an old login intent
124
+ $oWpUsers->logoutUser(); // clears the login and login intent
125
+ $this->loadWp()->redirectHere();
126
+ }
127
  else {
128
+ // no login intent present -
129
+ // the login has already been fully validated and the login intent was deleted.
130
+ // also means new installation don't get booted out
 
 
 
 
 
 
131
  }
132
  }
133
 
134
  /**
135
  */
136
  public function onWpLogout() {
137
+ $this->resetLoginIntent();
138
+ }
139
+
140
+ /**
141
+ * If it's a valid login attempt (by password) then $oUser is a WP_User
142
+ * @param WP_User|WP_Error $oUser
143
+ * @return WP_User
144
+ */
145
+ public function initLoginIntent( $oUser ) {
146
+ if ( $oUser instanceof WP_User ) {
147
+
148
+ /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
149
+ $oFO = $this->getFeature();
150
+ if ( !$oFO->canUserMfaSkip( $oUser ) ) {
151
+ $oF = $this->getFeature();
152
+ $nTimeout = (int)apply_filters(
153
+ $oF->prefix( 'login_intent_timeout' ),
154
+ $oF->getDef( 'login_intent_timeout' )
155
+ );
156
+ $this->setLoginIntentExpiresAt( $this->time() + MINUTE_IN_SECONDS*$nTimeout, $oUser );
157
+ }
158
+ }
159
+ return $oUser;
160
  }
161
 
162
  /**
163
  * Use this ONLY when the login intent has been successfully verified.
164
+ * @return $this
165
  */
166
  protected function removeLoginIntent() {
167
+ unset( $this->getCurrentUserMeta()->login_intent_expires_at );
168
+ return $this;
169
  }
170
 
171
  /**
172
  * Reset will put the counter to zero - this should be used when the user HAS NOT
173
  * verified the login intent. To indicate that they have successfully verified, use removeLoginIntent()
174
+ * @return $this
175
  */
176
+ public function resetLoginIntent() {
177
+ $this->setLoginIntentExpiresAt( 0, $this->loadWpUsers()->getCurrentWpUser() );
178
+ return $this;
179
  }
180
 
181
  /**
182
+ * @param int $nExpirationTime
183
+ * @param WP_User $oUser
184
+ * @return $this
185
  */
186
+ protected function setLoginIntentExpiresAt( $nExpirationTime, $oUser ) {
187
+ $oMeta = $this->loadWpUsers()->metaVoForUser( $this->prefix(), $oUser->ID );
188
+ $oMeta->login_intent_expires_at = max( 0, (int)$nExpirationTime );
189
+ return $this;
190
  }
191
 
192
  /**
193
+ * @return bool
194
  */
195
+ protected function isCurrentUserSubjectToLoginIntent() {
196
+ /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
197
+ $oFO = $this->getFeature();
198
+ return !$oFO->canUserMfaSkip( $this->loadWpUsers()->getCurrentWpUser() )
199
+ && apply_filters( $this->prefix( 'user_subject_to_login_intent' ), false );
200
  }
201
 
202
  /**
203
+ * @return int
 
 
204
  */
205
+ protected function getLoginIntentExpiresAt() {
206
+ return (int)$this->getCurrentUserMeta()->login_intent_expires_at;
 
 
 
 
 
 
 
 
207
  }
208
 
209
  /**
210
  * @return bool
211
  */
212
+ protected function hasLoginIntent() {
213
+ return isset( $this->getCurrentUserMeta()->login_intent_expires_at );
214
  }
215
 
216
  /**
217
  * @return bool
218
  */
219
+ protected function hasValidLoginIntent() {
220
+ return $this->hasLoginIntent() && ( $this->getLoginIntentExpiresAt() > $this->time() );
 
 
 
 
 
 
 
221
  }
222
 
223
  /**
263
  'more_info' => _wpsf__( 'More Info' ),
264
  'what_is_this' => _wpsf__( 'What is this?' ),
265
  'message' => $sMessage,
266
+ 'page_title' => sprintf( _wpsf__( '%s Login Verification' ), $oCon->getHumanName() ),
267
+ 'skip_mfa' => sprintf( _wpsf__( "Don't ask again on this browser for %s day(s)" ), $oFO->getMfaSkip() )
268
  ),
269
  'data' => array(
270
  'login_fields' => $aLoginIntentFields,
271
+ 'time_remaining' => $this->getLoginIntentExpiresAt() - $this->time(),
272
  'message_type' => $sMessageType,
273
  'login_intent_flag' => $oFO->getLoginIntentRequestFlag()
274
  ),
280
  'redirect_to' => $sRedirectTo,
281
  'what_is_this' => 'https://icontrolwp.freshdesk.com/support/solutions/articles/3000064840',
282
  'favicon' => $oCon->getPluginUrl_Image( 'pluginlogo_24x24.png' ),
283
+ ),
284
+ 'flags' => array(
285
+ 'can_skip_mfa' => $oFO->getMfaSkipEnabled()
286
  )
287
  );
288
 
src/processors/loginprotect_intent_base.php CHANGED
@@ -29,7 +29,7 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
29
  }
30
 
31
  // Necessary so we don't show user intent to people without it
32
- add_filter( $oFO->prefixOptionKey( 'user_subject_to_login_intent' ), array( $this, 'userSubjectToLoginIntent_Filter' ) );
33
 
34
  add_action( 'show_user_profile', array( $this, 'addOptionsToUserProfile' ) );
35
  add_action( 'personal_options_update', array( $this, 'handleUserProfileSubmit' ) );
@@ -74,7 +74,26 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
74
  * @return bool
75
  */
76
  protected function hasValidatedProfile( $oUser ) {
77
- return ( $this->loadWpUsers()->getUserMeta( $this->getFeature()->prefixOptionKey( $this->getStub().'_validated' ), $oUser->ID ) == 'Y' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
79
 
80
  /**
@@ -82,14 +101,29 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
82
  * @return string
83
  */
84
  protected function getSecret( WP_User $oUser ) {
85
- $oWpUser = $this->loadWpUsers();
86
- $sSecret = $oWpUser->getUserMeta(
87
- $this->getFeature()->prefixOptionKey( $this->getStub().'_secret' ),
88
- $oUser->ID
89
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  if ( empty( $sSecret ) ) {
91
  $this->resetSecret( $oUser );
92
  }
 
93
  return $sSecret;
94
  }
95
 
@@ -109,12 +143,9 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
109
  * @return $this
110
  */
111
  public function setProfileValidated( $oUser, $bValidated = true ) {
112
- $this->loadWpUsers()
113
- ->updateUserMeta(
114
- $this->getFeature()->prefixOptionKey( $this->getStub().'_validated' ),
115
- $bValidated ? 'Y' : 'N',
116
- $oUser->ID
117
- );
118
  return $this;
119
  }
120
 
@@ -124,12 +155,9 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
124
  * @return $this
125
  */
126
  protected function setSecret( $oUser, $sNewSecret ) {
127
- $this->loadWpUsers()
128
- ->updateUserMeta(
129
- $this->getFeature()->prefixOptionKey( $this->getStub().'_secret' ),
130
- $sNewSecret,
131
- $oUser->ID
132
- );
133
  return $this;
134
  }
135
 
@@ -158,28 +186,30 @@ abstract class ICWP_WPSF_Processor_LoginProtect_IntentBase extends ICWP_WPSF_Pro
158
  * functions. Otherwise we need to be careful of mixing up users.
159
  * @param WP_User $oUser
160
  */
161
- public function addOptionsToUserProfile( $oUser ) {}
 
162
 
163
  /**
164
  * The only thing we can do is REMOVE Google Authenticator from an account that is not our own
165
  * But, only admins can do this. If Security Admin feature is enabled, then only they can do it.
166
- *
167
  * @param int $nSavingUserId
168
  */
169
- public function handleEditOtherUserProfileSubmit( $nSavingUserId ) { }
 
170
 
171
  /**
172
- * @param WP_User $oSavingUser
173
  */
174
- protected function processRemovalFromAccount( $oSavingUser ) { }
 
175
 
176
  /**
177
  * This MUST only ever be hooked into when the User is looking at their OWN profile,
178
  * so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
179
- *
180
  * @param int $nSavingUserId
181
  */
182
- public function handleUserProfileSubmit( $nSavingUserId ) {}
 
183
 
184
  /**
185
  * @param WP_Error|WP_User $oUser
29
  }
30
 
31
  // Necessary so we don't show user intent to people without it
32
+ add_filter( $oFO->prefix( 'user_subject_to_login_intent' ), array( $this, 'userSubjectToLoginIntent_Filter' ) );
33
 
34
  add_action( 'show_user_profile', array( $this, 'addOptionsToUserProfile' ) );
35
  add_action( 'personal_options_update', array( $this, 'handleUserProfileSubmit' ) );
74
  * @return bool
75
  */
76
  protected function hasValidatedProfile( $oUser ) {
77
+ $oWpUsers = $this->loadWpUsers();
78
+
79
+ $sKey = $this->getStub().'_validated';
80
+ $oMeta = $oWpUsers->metaVoForUser( $this->prefix(), $oUser->ID );
81
+
82
+ $bValidated = (bool)$oMeta->{$sKey};
83
+
84
+ // fallback to old meta
85
+ // 2018-01: needs to be left here for a long time for ensure all users update to new meta.
86
+ if ( !$bValidated ) {
87
+ $sOldMetaKey = $this->getFeature()->prefixOptionKey( $sKey );
88
+ // look for the old style meta
89
+ $bValidated = ( $oWpUsers->getUserMeta( $sOldMetaKey, $oUser->ID ) == 'Y' );
90
+ if ( $bValidated ) {
91
+ $this->setProfileValidated( $oUser, $bValidated );
92
+ $oWpUsers->deleteUserMeta( $sOldMetaKey, $oUser->ID );
93
+ }
94
+ }
95
+
96
+ return $bValidated;
97
  }
98
 
99
  /**
101
  * @return string
102
  */
103
  protected function getSecret( WP_User $oUser ) {
104
+ $oWpUsers = $this->loadWpUsers();
105
+
106
+ $sKey = $this->getStub().'_secret';
107
+ $oMeta = $oWpUsers->metaVoForUser( $this->prefix(), $oUser->ID );
108
+
109
+ $sSecret = $oMeta->{$sKey};
110
+
111
+ // fallback to old meta
112
+ // 2018-01: needs to be left here for a long time for ensure all users update to new meta.
113
+ if ( empty( $sSecret ) ) {
114
+ $sOldMetaKey = $this->getFeature()->prefixOptionKey( $sKey );
115
+ // look for the old style meta
116
+ $sSecret = $oWpUsers->getUserMeta( $sOldMetaKey, $oUser->ID );
117
+ if ( !empty( $sSecret ) ) {
118
+ $this->setSecret( $oUser, $sSecret );
119
+ $oWpUsers->deleteUserMeta( $sOldMetaKey, $oUser->ID );
120
+ }
121
+ }
122
+
123
  if ( empty( $sSecret ) ) {
124
  $this->resetSecret( $oUser );
125
  }
126
+
127
  return $sSecret;
128
  }
129
 
143
  * @return $this
144
  */
145
  public function setProfileValidated( $oUser, $bValidated = true ) {
146
+ $sKey = $this->getStub().'_validated';
147
+ $oMeta = $this->loadWpUsers()->metaVoForUser( $this->prefix(), $oUser->ID );
148
+ $oMeta->{$sKey} = $bValidated;
 
 
 
149
  return $this;
150
  }
151
 
155
  * @return $this
156
  */
157
  protected function setSecret( $oUser, $sNewSecret ) {
158
+ $oMeta = $this->loadWpUsers()->metaVoForUser( $this->prefix(), $oUser->ID );
159
+ $sKey = $this->getStub().'_secret';
160
+ $oMeta->{$sKey} = $sNewSecret;
 
 
 
161
  return $this;
162
  }
163
 
186
  * functions. Otherwise we need to be careful of mixing up users.
187
  * @param WP_User $oUser
188
  */
189
+ public function addOptionsToUserProfile( $oUser ) {
190
+ }
191
 
192
  /**
193
  * The only thing we can do is REMOVE Google Authenticator from an account that is not our own
194
  * But, only admins can do this. If Security Admin feature is enabled, then only they can do it.
 
195
  * @param int $nSavingUserId
196
  */
197
+ public function handleEditOtherUserProfileSubmit( $nSavingUserId ) {
198
+ }
199
 
200
  /**
201
+ * @param WP_User $oUser
202
  */
203
+ protected function processRemovalFromAccount( $oUser ) {
204
+ }
205
 
206
  /**
207
  * This MUST only ever be hooked into when the User is looking at their OWN profile,
208
  * so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
 
209
  * @param int $nSavingUserId
210
  */
211
+ public function handleUserProfileSubmit( $nSavingUserId ) {
212
+ }
213
 
214
  /**
215
  * @param WP_Error|WP_User $oUser
src/processors/loginprotect_twofactorauth.php CHANGED
@@ -18,18 +18,18 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor
18
  * not successful but IP is valid. WP_Error otherwise.
19
  */
20
  public function processLoginAttempt_Filter( $oUser ) {
 
 
21
 
22
- $bUserLoginSuccess = is_object( $oUser ) && ( $oUser instanceof WP_User );
23
- if ( $bUserLoginSuccess && $this->hasValidatedProfile( $oUser ) ) {
24
 
25
  // Now send email with authentication link for user.
26
  $this->doStatIncrement( 'login.twofactor.started' );
27
- $this->loadWpUsers()
28
- ->updateUserMeta(
29
- $this->get2FaCodeUserMetaKey(),
30
- $this->getSessionHashCode(),
31
- $oUser->ID
32
- );
33
  $this->sendEmailTwoFactorVerify( $oUser );
34
  }
35
  return $oUser;
@@ -67,9 +67,9 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor
67
  * @return bool
68
  */
69
  protected function processOtp( $oUser, $sOtpCode ) {
70
- $bValid = $sOtpCode == $this->getStoredSessionHashCode();
71
  if ( $bValid ) {
72
- $this->loadWpUsers()->deleteUserMeta( $this->get2FaCodeUserMetaKey() );
73
  }
74
  return $bValid;
75
  }
@@ -157,7 +157,7 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_Processor
157
  * @return string The unique 2FA 6-digit code
158
  */
159
  protected function getStoredSessionHashCode() {
160
- return $this->loadWpUsers()->getUserMeta( $this->get2FaCodeUserMetaKey() );
161
  }
162
 
163
  /**
18
  * not successful but IP is valid. WP_Error otherwise.
19
  */
20
  public function processLoginAttempt_Filter( $oUser ) {
21
+ /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oFO */
22
+ $oFO = $this->getFeature();
23
 
24
+ $bLoginSuccess = is_object( $oUser ) && ( $oUser instanceof WP_User );
25
+ if ( $bLoginSuccess && $this->hasValidatedProfile( $oUser ) && !$oFO->canUserMfaSkip( $oUser ) ) {
26
 
27
  // Now send email with authentication link for user.
28
  $this->doStatIncrement( 'login.twofactor.started' );
29
+
30
+ $oMeta = $this->loadWpUsers()->metaVoForUser( $this->prefix(), $oUser->ID );
31
+ $oMeta->code_tfaemail = $this->getSessionHashCode();
32
+
 
 
33
  $this->sendEmailTwoFactorVerify( $oUser );
34
  }
35
  return $oUser;
67
  * @return bool
68
  */
69
  protected function processOtp( $oUser, $sOtpCode ) {
70
+ $bValid = ( $sOtpCode == $this->getStoredSessionHashCode() );
71
  if ( $bValid ) {
72
+ unset( $this->loadWpUsers()->metaVoForUser( $this->prefix() )->code_tfaemail );
73
  }
74
  return $bValid;
75
  }
157
  * @return string The unique 2FA 6-digit code
158
  */
159
  protected function getStoredSessionHashCode() {
160
+ return $this->getCurrentUserMeta()->code_tfaemail;
161
  }
162
 
163
  /**
src/processors/plugin.php CHANGED
@@ -151,13 +151,17 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
151
  */
152
  protected function addNotice_override_forceoff( $aNoticeAttributes ) {
153
 
154
- if ( $this->getController()->getIfForceOffActive() ) {
 
155
  $aRenderData = array(
156
  'notice_attributes' => $aNoticeAttributes,
157
  'strings' => array(
158
- 'message' => sprintf( _wpsf__( 'Warning - %s' ), sprintf( _wpsf__( '%s is not currently running' ), $this->getController()
159
- ->getHumanName() ) ),
160
- 'force_off' => sprintf( _wpsf__( 'Please delete the "%s" file to reactivate the Firewall processing' ), 'forceOff' )
 
 
 
161
  )
162
  );
163
  $this->insertAdminNotice( $aRenderData );
@@ -175,6 +179,7 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_BasePlugin {
175
  $aRenderData = array(
176
  'notice_attributes' => $aNoticeAttributes,
177
  'strings' => array(
 
178
  'yes' => "Yes please! I'd love to join in and learn more",
179
  'no' => "No thanks, I'm not interested in such groups",
180
  'we_dont_spam' => "( Fear not! SPAM is for losers. And we're not losers! )",
151
  */
152
  protected function addNotice_override_forceoff( $aNoticeAttributes ) {
153
 
154
+ $oCon = $this->getController();
155
+ if ( $oCon->getIfForceOffActive() ) {
156
  $aRenderData = array(
157
  'notice_attributes' => $aNoticeAttributes,
158
  'strings' => array(
159
+ 'title' => sprintf( _wpsf__( 'Warning - %s' ), sprintf( _wpsf__( '%s plugin is not currently processing requests' ), $oCon->getHumanName() ) ),
160
+ 'message' => sprintf(
161
+ _wpsf__( 'Please delete the "%s" file to reactivate the %s protection' ),
162
+ 'forceOff',
163
+ $oCon->getHumanName()
164
+ )
165
  )
166
  );
167
  $this->insertAdminNotice( $aRenderData );
179
  $aRenderData = array(
180
  'notice_attributes' => $aNoticeAttributes,
181
  'strings' => array(
182
+ 'title' => 'Join Us!',
183
  'yes' => "Yes please! I'd love to join in and learn more",
184
  'no' => "No thanks, I'm not interested in such groups",
185
  'we_dont_spam' => "( Fear not! SPAM is for losers. And we're not losers! )",
src/processors/plugin_tracking.php CHANGED
@@ -29,11 +29,11 @@ class ICWP_WPSF_Processor_Plugin_Tracking extends ICWP_WPSF_Processor_BasePlugin
29
  $aRenderData = array(
30
  'notice_attributes' => $aNoticeAttributes,
31
  'strings' => array(
32
- 'help_us' => sprintf( _wpsf__( "Will you help us to make %s even better?" ), $oCon->getHumanName() ),
33
- 'want_to_track' => _wpsf__( "We're working to understand how people, just like you, use this plugin every day." ),
34
- 'what_we_collect' => _wpsf__( "We'd like to better understand the features used most and how effective we are on a global scale." ),
35
- 'data_anon' => _wpsf__( 'The data sent will be always completely anonymous and we will never be able to track you or your website.' ),
36
- 'can_turn_off' => _wpsf__( 'You can easily turn it off at any time within the plugin options if you change your mind.' ),
37
  'click_to_see' => _wpsf__( 'Click to see the RAW data that would be sent' ),
38
  'learn_more' => _wpsf__( 'Learn More.' ),
39
  'site_url' => 'translate.icontrolwp.com',
29
  $aRenderData = array(
30
  'notice_attributes' => $aNoticeAttributes,
31
  'strings' => array(
32
+ 'title' => sprintf( _wpsf__( "Make %s even better by sharing usage info?" ), $oCon->getHumanName() ),
33
+ 'want_to_track' => sprintf( _wpsf__( "We're hoping to understand how %s is configured and used." ), $oCon->getHumanName() ),
34
+ 'what_we_collect' => _wpsf__( "We'd like to understand how effective it is on a global scale." ),
35
+ 'data_anon' => _wpsf__( 'The data sent is always completely anonymous and we can never track you or your site.' ),
36
+ 'can_turn_off' => _wpsf__( 'It can be turned-off at any time within the plugin options.' ),
37
  'click_to_see' => _wpsf__( 'Click to see the RAW data that would be sent' ),
38
  'learn_more' => _wpsf__( 'Learn More.' ),
39
  'site_url' => 'translate.icontrolwp.com',
src/processors/sessions.php ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'ICWP_WPSF_Processor_Sessions', false ) ) {
4
+ return;
5
+ }
6
+
7
+ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'basedb.php' );
8
+
9
+ class ICWP_WPSF_Processor_Sessions extends ICWP_WPSF_BaseDbProcessor {
10
+
11
+ /**
12
+ * @var string
13
+ */
14
+ protected $nDaysToKeep = 30;
15
+
16
+ /**
17
+ * @var ICWP_WPSF_SessionVO
18
+ */
19
+ private $oCurrent;
20
+
21
+ /**
22
+ * @param ICWP_WPSF_Processor_Sessions $oFeatureOptions
23
+ */
24
+ public function __construct( ICWP_WPSF_FeatureHandler_Sessions $oFeatureOptions ) {
25
+ parent::__construct( $oFeatureOptions, $oFeatureOptions->getSessionsTableName() );
26
+ }
27
+
28
+ /**
29
+ * Resets the object values to be re-used anew
30
+ */
31
+ public function init() {
32
+ parent::init();
33
+ $this->setAutoExpirePeriod( DAY_IN_SECONDS*$this->nDaysToKeep );
34
+ }
35
+
36
+ public function run() {
37
+ if ( $this->readyToRun() ) {
38
+ add_action( 'wp_login', array( $this, 'onWpLogin' ), 5, 2 );
39
+ add_action( 'wp_logout', array( $this, 'onWpLogout' ), 0 );
40
+ add_action( 'wp_loaded', array( $this, 'onWpLoaded' ), 0 );
41
+ add_filter( 'login_message', array( $this, 'printLinkToAdmin' ) );
42
+ }
43
+ }
44
+
45
+ /**
46
+ * @param string $sUsername
47
+ * @param WP_User $oUser
48
+ */
49
+ public function onWpLogin( $sUsername, $oUser ) {
50
+ $this->activateUserSession( $sUsername, $oUser );
51
+ }
52
+
53
+ /**
54
+ */
55
+ public function onWpLogout() {
56
+ $this->terminateCurrentSession();
57
+ }
58
+
59
+ /**
60
+ */
61
+ public function onWpLoaded() {
62
+ if ( $this->loadWpUsers()->isUserLoggedIn() && !$this->loadWp()->isRestUrl() ) {
63
+ $this->autoAddSession();
64
+ $this->queryUpdateSessionLastActivity();
65
+ }
66
+ }
67
+
68
+ private function autoAddSession() {
69
+ /** @var ICWP_WPSF_FeatureHandler_Sessions $oFO */
70
+ $oFO = $this->getFeature();
71
+ if ( !$oFO->hasSession() && $oFO->isAutoAddSessions() ) {
72
+ $this->queryCreateSession(
73
+ $oWpUsers = $this->loadWpUsers()->getCurrentWpUser()->user_login,
74
+ $oFO->getConn()->getSessionId( true )
75
+ );
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Only show Go To Admin link for Authors and above.
81
+ * @param string $sMessage
82
+ * @return string
83
+ * @throws Exception
84
+ */
85
+ public function printLinkToAdmin( $sMessage = '' ) {
86
+ $oWpUsers = $this->loadWpUsers();
87
+ if ( $oWpUsers->isUserLoggedIn() ) {
88
+ $oUser = $oWpUsers->getCurrentWpUser();
89
+ /** @var ICWP_WPSF_FeatureHandler_Sessions $oFO */
90
+ $oFO = $this->getFeature();
91
+ if ( $oFO->hasSession() ) {
92
+ $sMessage = sprintf(
93
+ '<p class="message">%s<br />%s</p>',
94
+ _wpsf__( "You're already logged-in." ).sprintf(
95
+ ' <span style="white-space: nowrap">(%s)</span>',
96
+ $oUser->get( 'user_login' ) ),
97
+ ( $oWpUsers->getCurrentUserLevel() >= 2 ) ? sprintf( '<a href="%s">%s</a>',
98
+ $this->loadWp()->getUrl_WpAdmin(),
99
+ _wpsf__( "Go To Admin" ).' &rarr;' ) : '' )
100
+ .$sMessage;
101
+ }
102
+ }
103
+ return $sMessage;
104
+ }
105
+
106
+ /**
107
+ * @param string $sUsername
108
+ * @param WP_User $oUser
109
+ * @return boolean
110
+ */
111
+ private function activateUserSession( $sUsername, $oUser ) {
112
+ if ( !is_a( $oUser, 'WP_User' ) ) {
113
+ return false;
114
+ }
115
+
116
+ // If they have a currently active session, terminate it (i.e. we replace it)
117
+ $oSession = $this->queryGetSession( $sUsername, $this->getSessionId() );
118
+ if ( !empty( $oSession ) ) {
119
+ $this->queryTerminateSession( $oSession );
120
+ }
121
+ $this->queryCreateSession( $sUsername, $this->getSessionId() );
122
+ return true;
123
+ }
124
+
125
+ /**
126
+ * @return string
127
+ */
128
+ private function getSessionId() {
129
+ return $this->getController()->getSessionId();
130
+ }
131
+
132
+ /**
133
+ * @return boolean
134
+ */
135
+ protected function terminateCurrentSession() {
136
+ $oUser = $this->loadWpUsers()->getCurrentWpUser();
137
+ if ( empty( $oUser ) || !is_a( $oUser, 'WP_User' ) ) {
138
+ return false;
139
+ }
140
+ // $this->getCurrentUserMeta()->login_browser = '';
141
+
142
+ $oSession = $this->getCurrentSession();
143
+ $mResult = $this->queryTerminateSession( $oSession );
144
+ $this->getController()->clearSession();
145
+ return $mResult;
146
+ }
147
+
148
+ /**
149
+ * @return string
150
+ */
151
+ public function getCreateTableSql() {
152
+ $sSqlTables = "CREATE TABLE %s (
153
+ id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
154
+ session_id varchar(32) NOT NULL DEFAULT '',
155
+ wp_username varchar(255) NOT NULL DEFAULT '',
156
+ ip varchar(40) NOT NULL DEFAULT '0',
157
+ browser varchar(32) NOT NULL DEFAULT '',
158
+ logged_in_at int(15) NOT NULL DEFAULT 0,
159
+ last_activity_at int(15) UNSIGNED NOT NULL DEFAULT 0,
160
+ last_activity_uri text NOT NULL DEFAULT '',
161
+ secadmin_at int(15) UNSIGNED NOT NULL DEFAULT 0,
162
+ created_at int(15) UNSIGNED NOT NULL DEFAULT 0,
163
+ deleted_at int(15) UNSIGNED NOT NULL DEFAULT 0,
164
+ PRIMARY KEY (id)
165
+ ) %s;";
166
+ return sprintf( $sSqlTables, $this->getTableName(), $this->loadDbProcessor()->getCharCollate() );
167
+ }
168
+
169
+ /**
170
+ * @return ICWP_WPSF_SessionVO|null
171
+ */
172
+ public function getCurrentSession() {
173
+ if ( is_null( $this->oCurrent ) ) {
174
+ $this->oCurrent = $this->loadCurrentSession();
175
+ }
176
+ return $this->oCurrent;
177
+ }
178
+
179
+ /**
180
+ * @return ICWP_WPSF_SessionVO|null
181
+ */
182
+ public function loadCurrentSession() {
183
+ $oSession = null;
184
+ $oWpUsers = $this->loadWpUsers();
185
+ if ( did_action( 'init' ) && $oWpUsers->isUserLoggedIn() ) {
186
+ $oUser = $oWpUsers->getCurrentWpUser();
187
+ if ( $oUser instanceof WP_User ) {
188
+ $oSession = $this->queryGetSession( $oUser->user_login, $this->getSessionId() );
189
+ }
190
+ }
191
+ return $oSession;
192
+ }
193
+
194
+ /**
195
+ * Checks for and gets a user session.
196
+ * @param string $sUsername
197
+ * @param string $sSessionId
198
+ * @return ICWP_WPSF_SessionVO|null
199
+ */
200
+ protected function queryGetSession( $sUsername, $sSessionId ) {
201
+ require_once( dirname( dirname( __FILE__ ) ).'/query/sessions_retrieve.php' );
202
+
203
+ $oRetrieve = new ICWP_WPSF_Query_Sessions_Retrieve();
204
+ return $oRetrieve->setTable( $this->getTableName() )
205
+ ->retrieveUserSession( $sUsername, $sSessionId );
206
+ }
207
+
208
+ /**
209
+ * @return ICWP_WPSF_SessionVO[]
210
+ */
211
+ public function queryGetActiveSessions() {
212
+ return $this->getSessionRetriever()->all();
213
+ }
214
+
215
+ /**
216
+ * @param string $sWpUsername
217
+ * @return ICWP_WPSF_SessionVO[]
218
+ */
219
+ public function queryGetActiveSessionsForUsername( $sWpUsername ) {
220
+ return $this->getSessionRetriever()->retrieveForUsername( $sWpUsername );
221
+ }
222
+
223
+ /**
224
+ * @param string $sUsername
225
+ * @param string $sSessionId
226
+ * @return null|ICWP_WPSF_SessionVO
227
+ */
228
+ public function queryCreateSession( $sUsername, $sSessionId ) {
229
+ if ( empty( $sUsername ) ) {
230
+ return null;
231
+ }
232
+
233
+ require_once( dirname( dirname( __FILE__ ) ).'/query/sessions_create.php' );
234
+ $oCreator = new ICWP_WPSF_Query_Sessions_Create();
235
+ $bSuccess = $oCreator->setTable( $this->getTableName() )
236
+ ->create( $sUsername, $sSessionId );
237
+ if ( $bSuccess ) {
238
+ $this->doStatIncrement( 'user.session.start' );
239
+ }
240
+ return $bSuccess ? $this->queryGetSession( $sUsername, $sSessionId ) : null;
241
+ }
242
+
243
+ /**
244
+ * @param ICWP_WPSF_SessionVO $oSession
245
+ * @return bool|int
246
+ */
247
+ public function queryTerminateSession( $oSession ) {
248
+ if ( empty( $oSession ) ) {
249
+ return true;
250
+ }
251
+ $this->doStatIncrement( 'user.session.terminate' );
252
+
253
+ require_once( dirname( dirname( __FILE__ ) ).'/query/sessions_terminate.php' );
254
+ $oTerminate = new ICWP_WPSF_Query_Sessions_Terminate();
255
+ return $oTerminate->setTable( $this->getTableName() )
256
+ ->forUserSession( $oSession );
257
+ }
258
+
259
+ /**
260
+ */
261
+ protected function queryUpdateSessionLastActivity() {
262
+ /** @var ICWP_WPSF_FeatureHandler_Sessions $oFO */
263
+ $oFO = $this->getFeature();
264
+ if ( $oFO->hasSession() ) {
265
+ $this->getSessionUpdater()->updateLastActivity( $this->getCurrentSession() );
266
+ }
267
+ }
268
+
269
+ /**
270
+ * @return ICWP_WPSF_Query_Sessions_Retrieve
271
+ */
272
+ public function getSessionRetriever() {
273
+ require_once( dirname( dirname( __FILE__ ) ).'/query/sessions_retrieve.php' );
274
+ $oRetrieve = new ICWP_WPSF_Query_Sessions_Retrieve();
275
+ return $oRetrieve->setTable( $this->getTableName() );
276
+ }
277
+
278
+ /**
279
+ * @return ICWP_WPSF_Query_Sessions_Update
280
+ */
281
+ public function getSessionUpdater() {
282
+ require_once( dirname( dirname( __FILE__ ) ).'/query/sessions_update.php' );
283
+ $oUpdate = new ICWP_WPSF_Query_Sessions_Update();
284
+ return $oUpdate->setTable( $this->getTableName() );
285
+ }
286
+
287
+ /**
288
+ * @return array
289
+ */
290
+ protected function getTableColumnsByDefinition() {
291
+ $aDef = $this->getFeature()->getDef( 'sessions_table_columns' );
292
+ return ( is_array( $aDef ) ? $aDef : array() );
293
+ }
294
+ }
src/processors/statistics_reporting.php CHANGED
@@ -83,7 +83,7 @@ class ICWP_WPSF_Processor_Statistics_Reporting extends ICWP_WPSF_BaseDbProcessor
83
  */
84
  protected function getConsolidation() {
85
  if ( !isset( $this->oConsolidation ) ) {
86
- include( dirname( dirname( __FILE__ ) ).DIRECTORY_SEPARATOR.'query'.DIRECTORY_SEPARATOR.'statistics_consolidation.php' );
87
  /** @var ICWP_WPSF_FeatureHandler_Statistics $oFO */
88
  $oFO = $this->getFeature();
89
  $this->oConsolidation = new ICWP_WPSF_Query_Statistics_Consolidation();
83
  */
84
  protected function getConsolidation() {
85
  if ( !isset( $this->oConsolidation ) ) {
86
+ include( dirname( dirname( __FILE__ ) ).'/query/statistics_consolidation.php' );
87
  /** @var ICWP_WPSF_FeatureHandler_Statistics $oFO */
88
  $oFO = $this->getFeature();
89
  $this->oConsolidation = new ICWP_WPSF_Query_Statistics_Consolidation();
src/processors/support.php DELETED
@@ -1,15 +0,0 @@
1
- <?php
2
-
3
- if ( !class_exists('ICWP_WPSF_Processor_Support') ):
4
-
5
- require_once( dirname(__FILE__).DIRECTORY_SEPARATOR.'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
@@ -22,9 +22,6 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
22
  add_filter( 'manage_users_columns', array( $this, 'fAddUserListLastLoginColumn' ) );
23
  add_filter( 'wpmu_users_columns', array( $this, 'fAddUserListLastLoginColumn' ) );
24
 
25
- // Various stuff.
26
- add_action( 'init', array( $this, 'onInit' ), 1 );
27
-
28
  // Handles login notification emails and setting last user login
29
  add_action( 'wp_login', array( $this, 'onWpLogin' ) );
30
 
@@ -35,45 +32,11 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
35
 
36
  /** Everything from this point on must consider XMLRPC compatibility **/
37
 
38
- /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
39
- $oFO = $this->getFeature();
40
-
41
- if ( $oFO->getIsUserSessionsManagementEnabled() ) {
42
- $this->getProcessorSessions()->run();
43
- }
44
 
45
  return true;
46
  }
47
 
48
- public function onInit() {
49
- add_filter( 'login_message', array( $this, 'printLinkToAdmin' ) );
50
- }
51
-
52
- /**
53
- * Only show Go To Admin link for Authors and above.
54
- * @param string $sMessage
55
- * @return string
56
- * @throws Exception
57
- */
58
- public function printLinkToAdmin( $sMessage = '' ) {
59
- $oWpUsers = $this->loadWpUsers();
60
- if ( $oWpUsers->isUserLoggedIn() ) {
61
- /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
62
- $oFO = $this->getFeature();
63
- if ( $oFO->getIsUserSessionsManagementEnabled() && $this->getProcessorSessions()
64
- ->getCurrentUserHasValidSession() ) {
65
- $sMessage = sprintf(
66
- '<p class="message">%s<br />%s</p>',
67
- _wpsf__( "It appears you're already logged-in." ).sprintf( ' <span style="white-space: nowrap">(%s)</span>', $oWpUsers->getCurrentWpUser()
68
- ->get( 'user_login' ) ),
69
- ( $oWpUsers->getCurrentUserLevel() >= 2 ) ? sprintf( '<a href="%s">%s</a>', $this->loadWp()
70
- ->getUrl_WpAdmin(), _wpsf__( "Go To Admin" ).' &rarr;' ) : ''
71
- ).$sMessage;
72
- }
73
- }
74
- return $sMessage;
75
- }
76
-
77
  /**
78
  * Hooked to action wp_login
79
  * @param $sUsername
@@ -81,21 +44,19 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
81
  public function onWpLogin( $sUsername ) {
82
  $oUser = $this->loadWpUsers()->getUserByUsername( $sUsername );
83
  if ( $oUser instanceof WP_User ) {
84
-
85
- if ( $this->loadDataProcessor()
86
- ->validEmail( $this->getOption( 'enable_admin_login_email_notification' ) ) ) {
87
- $this->sendLoginEmailNotification( $oUser );
88
- }
89
  $this->setUserLastLoginTime( $oUser );
90
  }
91
  }
92
 
93
  /**
94
  * @param WP_User $oUser
95
- * @return bool
96
  */
97
  protected function setUserLastLoginTime( $oUser ) {
98
- return $this->loadWpUsers()->updateUserMeta( $this->getUserLastLoginKey(), $this->time(), $oUser->ID );
 
 
99
  }
100
 
101
  /**
@@ -105,7 +66,7 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
105
  */
106
  public function fAddUserListLastLoginColumn( $aColumns ) {
107
 
108
- $sLastLoginColumnName = $this->getUserLastLoginKey();
109
  if ( !isset( $aColumns[ $sLastLoginColumnName ] ) ) {
110
  $aColumns[ $sLastLoginColumnName ] = _wpsf__( 'Last Login' );
111
  add_filter( 'manage_users_custom_column', array( $this, 'aPrintUsersListLastLoginColumnContent' ), 10, 3 );
@@ -114,22 +75,23 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
114
  }
115
 
116
  /**
117
- * Adds the column to the users listing table to indicate whether WordPress will automatically update the plugins
118
  * @param string $sContent
119
  * @param string $sColumnName
120
  * @param int $nUserId
121
  * @return string
122
  */
123
  public function aPrintUsersListLastLoginColumnContent( $sContent, $sColumnName, $nUserId ) {
124
- $sLastLoginKey = $this->getUserLastLoginKey();
125
- if ( $sColumnName != $sLastLoginKey ) {
126
  return $sContent;
127
  }
 
128
  $oWp = $this->loadWp();
129
- $nLastLoginTime = $this->loadWpUsers()->getUserMeta( $sLastLoginKey, $nUserId );
130
 
131
  $sLastLoginText = _wpsf__( 'Not Recorded' );
132
- if ( !empty( $nLastLoginTime ) && is_numeric( $nLastLoginTime ) ) {
133
  $sLastLoginText = $oWp->getTimeStringForDisplay( $nLastLoginTime );
134
  }
135
  return $sLastLoginText;
@@ -153,7 +115,8 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
153
  'subscriber' => 'read',
154
  );
155
 
156
- $sRoleToCheck = strtolower( apply_filters( $this->getFeature()->prefix( 'login-notification-email-role' ), 'administrator' ) );
 
157
  if ( !array_key_exists( $sRoleToCheck, $aUserCapToRolesMap ) ) {
158
  $sRoleToCheck = 'administrator';
159
  }
@@ -219,21 +182,13 @@ class ICWP_WPSF_Processor_UserManagement extends ICWP_WPSF_Processor_BaseWpsf {
219
  * @return array|bool
220
  */
221
  public function getActiveUserSessionRecords( $sWpUsername = '' ) {
222
- return $this->getProcessorSessions()->getActiveUserSessionRecords( $sWpUsername );
223
- }
224
-
225
- /**
226
- * @param integer $nTime - number of seconds back from now to look
227
- * @return array|boolean
228
- */
229
- public function getPendingOrFailedUserSessionRecordsSince( $nTime = 0 ) {
230
- return $this->getProcessorSessions()->getPendingOrFailedUserSessionRecordsSince( $nTime );
231
  }
232
 
233
  /**
234
  * @return string
235
  */
236
  protected function getUserLastLoginKey() {
237
- return $this->getController()->doPluginOptionPrefix( 'userlastlogin' );
238
  }
239
  }
22
  add_filter( 'manage_users_columns', array( $this, 'fAddUserListLastLoginColumn' ) );
23
  add_filter( 'wpmu_users_columns', array( $this, 'fAddUserListLastLoginColumn' ) );
24
 
 
 
 
25
  // Handles login notification emails and setting last user login
26
  add_action( 'wp_login', array( $this, 'onWpLogin' ) );
27
 
32
 
33
  /** Everything from this point on must consider XMLRPC compatibility **/
34
 
35
+ $this->getProcessorSessions()->run();
 
 
 
 
 
36
 
37
  return true;
38
  }
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  /**
41
  * Hooked to action wp_login
42
  * @param $sUsername
44
  public function onWpLogin( $sUsername ) {
45
  $oUser = $this->loadWpUsers()->getUserByUsername( $sUsername );
46
  if ( $oUser instanceof WP_User ) {
47
+ $this->sendLoginEmailNotification( $oUser );
 
 
 
 
48
  $this->setUserLastLoginTime( $oUser );
49
  }
50
  }
51
 
52
  /**
53
  * @param WP_User $oUser
54
+ * @return $this
55
  */
56
  protected function setUserLastLoginTime( $oUser ) {
57
+ $oMeta = $this->loadWpUsers()->metaVoForUser( $this->prefix(), $oUser->ID );
58
+ $oMeta->last_login_at = $this->time();
59
+ return $this;
60
  }
61
 
62
  /**
66
  */
67
  public function fAddUserListLastLoginColumn( $aColumns ) {
68
 
69
+ $sLastLoginColumnName = $this->prefix( 'last_login_at' );
70
  if ( !isset( $aColumns[ $sLastLoginColumnName ] ) ) {
71
  $aColumns[ $sLastLoginColumnName ] = _wpsf__( 'Last Login' );
72
  add_filter( 'manage_users_custom_column', array( $this, 'aPrintUsersListLastLoginColumnContent' ), 10, 3 );
75
  }
76
 
77
  /**
78
+ * Adds the column to the users listing table to stating last login time.
79
  * @param string $sContent
80
  * @param string $sColumnName
81
  * @param int $nUserId
82
  * @return string
83
  */
84
  public function aPrintUsersListLastLoginColumnContent( $sContent, $sColumnName, $nUserId ) {
85
+
86
+ if ( $sColumnName != $this->prefix( 'last_login_at' ) ) {
87
  return $sContent;
88
  }
89
+
90
  $oWp = $this->loadWp();
91
+ $nLastLoginTime = $this->loadWpUsers()->metaVoForUser( $this->prefix(), $nUserId )->last_login_at;
92
 
93
  $sLastLoginText = _wpsf__( 'Not Recorded' );
94
+ if ( is_numeric( $nLastLoginTime ) && $nLastLoginTime > 0 ) {
95
  $sLastLoginText = $oWp->getTimeStringForDisplay( $nLastLoginTime );
96
  }
97
  return $sLastLoginText;
115
  'subscriber' => 'read',
116
  );
117
 
118
+ $sRoleToCheck = strtolower( apply_filters( $this->getFeature()
119
+ ->prefix( 'login-notification-email-role' ), 'administrator' ) );
120
  if ( !array_key_exists( $sRoleToCheck, $aUserCapToRolesMap ) ) {
121
  $sRoleToCheck = 'administrator';
122
  }
182
  * @return array|bool
183
  */
184
  public function getActiveUserSessionRecords( $sWpUsername = '' ) {
185
+ return $this->getProcessorSessions()->getActiveSessionRecordsForUsername( $sWpUsername );
 
 
 
 
 
 
 
 
186
  }
187
 
188
  /**
189
  * @return string
190
  */
191
  protected function getUserLastLoginKey() {
192
+ return $this->getController()->doPluginOptionPrefix( 'last_login_at' );
193
  }
194
  }
src/processors/usermanagement_sessions.php CHANGED
@@ -4,200 +4,116 @@ if ( class_exists( 'ICWP_WPSF_Processor_UserManagement_Sessions', false ) ) {
4
  return;
5
  }
6
 
7
- require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'basedb.php' );
8
 
9
- class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_BaseDbProcessor {
10
-
11
- /**
12
- * @var string
13
- */
14
- protected $nDaysToKeepLog = 30;
15
-
16
- /**
17
- * @var string
18
- */
19
- protected $sSessionId;
20
-
21
- /**
22
- * @param ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions
23
- */
24
- public function __construct( ICWP_WPSF_FeatureHandler_UserManagement $oFeatureOptions ) {
25
- parent::__construct( $oFeatureOptions, $oFeatureOptions->getUserSessionsTableName() );
26
- }
27
-
28
- /**
29
- * Resets the object values to be re-used anew
30
- */
31
- public function init() {
32
- parent::init();
33
- $this->setAutoExpirePeriod( DAY_IN_SECONDS * $this->nDaysToKeepLog );
34
- }
35
 
36
  public function run() {
37
- if ( !$this->readyToRun() ) {
38
- return;
39
- }
40
-
41
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
42
-
43
- // When we know user has successfully authenticated and we activate the session entry in the database
44
- add_action( 'wp_login', array( $this, 'activateUserSession' ), 10, 2 );
45
-
46
- add_action( 'wp_logout', array( $this, 'onWpLogout' ) );
47
-
48
- add_filter( 'auth_cookie_expiration', array( $this, 'setWordpressTimeoutCookieExpiration_Filter' ), 100, 1 );
49
-
50
- // Check the current logged-in user every page load.
51
- add_action( 'wp_loaded', array( $this, 'checkCurrentUser_Action' ), 1 );
52
  }
53
 
54
  /**
55
- * @param string $sUsername
56
- * @param WP_User $oUser
57
- * @return boolean
58
  */
59
- public function activateUserSession( $sUsername, $oUser ) {
60
- if ( !is_a( $oUser, 'WP_User' ) ) {
61
- return false;
62
- }
63
-
64
- // If they have a currently active session, terminate it (i.e. we replace it)
65
- $aSession = $this->getUserSessionRecord( $sUsername, $this->getSessionId() );
66
- if ( !empty( $aSession ) ) {
67
- $this->doTerminateUserSession( $sUsername, $this->getSessionId() );
68
- }
69
-
70
- $this->doAddNewActiveUserSessionRecord( $sUsername );
71
- $this->doLimitUserSession( $sUsername );
72
- return true;
73
  }
74
 
75
  /**
76
- * @return bool
77
  */
78
- public function getCurrentUserHasValidSession() {
79
- return ( $this->doVerifyCurrentSession() == 0 );
 
 
80
  }
81
 
82
  /**
83
  * Should be hooked to 'init' so we have is_user_logged_in()
84
  */
85
- public function checkCurrentUser_Action() {
86
  $oWp = $this->loadWp();
87
  $oWpUsers = $this->loadWpUsers();
88
 
89
- if ( $oWpUsers->isUserLoggedIn() ) {
90
 
91
- $nCode = $this->doVerifyCurrentSession();
92
 
93
  if ( is_admin() ) { // prevent any admin access on invalid Shield sessions.
94
 
95
- if ( $nCode > 0 ) {
96
 
97
- if ( $nCode == 3 ) { // a session was used from the wrong IP. We just block it.
98
- // $this->loadWpUsers()->logoutUser( true ); // so as not to destroy the original, legitimate session
 
 
 
 
 
 
 
 
 
 
99
  $this->addToAuditEntry(
100
  sprintf( 'Access to an established user session from a new IP address "%s". Redirecting request.', $this->ip() ),
101
  2,
102
  'um_session_ip_lock_redirect'
103
  );
104
  $oWp->redirectToHome();
105
- }
106
- else {
 
107
  $this->addToAuditEntry(
108
  'Unable to verify the current User Session. Forcefully logging out session and redirecting to login.',
109
  2,
110
  'um_session_not_found_redirect'
111
  );
112
  $oWpUsers->forceUserRelogin( array( 'wpsf-forcelogout' => $nCode ) );
113
- }
114
  }
115
  }
116
- else if ( $nCode > 0 && !$oWp->isRestUrl() ) { // it's not admin, but the user looks logged into WordPress and not to Shield
117
- wp_set_current_user( 0 ); // ensures that is_user_logged_in() is false going forward.
 
 
 
 
 
118
  }
119
-
120
- // Auto-redirect to admin: UNUSED
121
- if ( $oWp->isRequestLoginUrl() && $this->loadWpUsers()->isUserAdmin() ) {
122
- $sLoginAction = $this->loadDataProcessor()->FetchGet( 'action' );
123
- if ( !in_array( $sLoginAction, array( 'logout', 'postpass' ) ) ) {
124
- // $oWp->redirectToAdmin();
125
- }
126
- }
127
-
128
- // always track last activity
129
- $this->updateSessionLastActivity( $oWpUsers->getCurrentWpUser() );
130
- }
131
- }
132
-
133
- /**
134
- * @param WP_User $oUser
135
- * @return boolean
136
- */
137
- protected function updateSessionLastActivity( $oUser ) {
138
- if ( !is_object( $oUser ) || !( $oUser instanceof WP_User ) ) {
139
- return false;
140
  }
141
-
142
- $aNewData = array(
143
- 'last_activity_at' => $this->time(),
144
- 'last_activity_uri' => $this->loadDataProcessor()->FetchServer( 'REQUEST_URI' )
145
- );
146
- return $this->updateSession( $this->getSessionId(), $oUser->get( 'user_login' ), $aNewData );
147
- }
148
-
149
- /**
150
- * @param string $sSessionId
151
- * @param string $sUsername
152
- * @param array $aUpdateData
153
- * @return boolean
154
- */
155
- protected function updateSession( $sSessionId, $sUsername, $aUpdateData ) {
156
- $aWhere = array(
157
- 'session_id' => $sSessionId,
158
- 'wp_username' => $sUsername,
159
- 'deleted_at' => 0
160
- );
161
- $mResult = $this->updateRowsWhere( $aUpdateData, $aWhere );
162
- return $mResult;
163
  }
164
 
165
  /**
166
  * @return int
167
  */
168
- protected function doVerifyCurrentSession() {
169
- $oUser = $this->loadWpUsers()->getCurrentWpUser();
 
170
 
171
- if ( !is_object( $oUser ) || !( $oUser instanceof WP_User ) ) {
172
  $nForceLogOutCode = 6;
173
  }
174
  else {
175
-
176
- $aLoginSessionData = $this->getUserSessionRecord( $oUser->get( 'user_login' ), $this->getSessionId() );
177
- $nSessionTimeoutInterval = $this->getSessionTimeoutInterval();
178
- $nSessionIdleTimeoutInterval = $this->getOption( 'session_idle_timeout_interval', 0 ) * HOUR_IN_SECONDS;
179
- $bLockToIp = $this->getIsOption( 'session_lock_location', 'Y' );
180
- $sVisitorIp = $this->ip();
181
 
182
  $nForceLogOutCode = 0; // when it's == 0 it's a valid session
183
 
184
- if ( !is_object( $oUser ) || !( $oUser instanceof WP_User ) ) {
185
- $nForceLogOutCode = 6;
186
-
187
- } // session?
188
- else if ( !$aLoginSessionData ) {
189
  $nForceLogOutCode = 4;
190
-
191
  } // timeout interval
192
- else if ( $nSessionTimeoutInterval > 0 && ( $this->time() - $aLoginSessionData[ 'logged_in_at' ] > $nSessionTimeoutInterval ) ) {
193
  $nForceLogOutCode = 1;
194
-
195
  } // idle timeout interval
196
- else if ( $nSessionIdleTimeoutInterval > 0 && ( ( $this->time() - $aLoginSessionData[ 'last_activity_at' ] ) > $nSessionIdleTimeoutInterval ) ) {
197
  $nForceLogOutCode = 2;
198
-
199
  } // login ip address lock
200
- else if ( $bLockToIp && $sVisitorIp != $aLoginSessionData[ 'ip' ] ) {
201
  $nForceLogOutCode = 3;
202
  }
203
  }
@@ -205,188 +121,68 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_BaseDbProces
205
  return $nForceLogOutCode;
206
  }
207
 
208
- /**
209
- * @return string
210
- */
211
- public function getSessionId() {
212
- if ( empty( $this->sSessionId ) ) {
213
- $this->sSessionId = $this->getController()->getSessionId();
214
- }
215
- return $this->sSessionId;
216
- }
217
-
218
  /**
219
  * @param integer $nTimeout
220
  * @return integer
221
  */
222
- public function setWordpressTimeoutCookieExpiration_Filter( $nTimeout ) {
223
  $nSessionTimeoutInterval = $this->getSessionTimeoutInterval();
224
- return ( ( $nSessionTimeoutInterval > 0 ) ? $nSessionTimeoutInterval : $nTimeout );
225
  }
226
 
227
  /**
228
  * @return integer
229
  */
230
  protected function getSessionTimeoutInterval() {
231
- return $this->getOption( 'session_timeout_interval' ) * DAY_IN_SECONDS;
232
- }
233
-
234
- /**
235
- * Checks for and gets a user session.
236
- * @param string $sWpUsername
237
- * @return array|boolean
238
- */
239
- public function getActiveSessionRecordsForUsername( $sWpUsername ) {
240
- return $this->getActiveUserSessionRecords( $sWpUsername );
241
  }
242
 
243
  /**
244
- * Checks for and gets a user session.
245
- * @param string $sUsername
246
- * @param string $sSessionId
247
- * @return array|false
248
  */
249
- protected function getUserSessionRecord( $sUsername, $sSessionId ) {
250
-
251
- $sQuery = "
252
- SELECT *
253
- FROM `%s`
254
- WHERE
255
- `wp_username` = '%s'
256
- AND `session_id` = '%s'
257
- AND `deleted_at` = '0'
258
- ";
259
- $sQuery = sprintf(
260
- $sQuery,
261
- $this->getTableName(),
262
- esc_sql( $sUsername ),
263
- esc_sql( $sSessionId )
264
- );
265
-
266
- $mResult = $this->selectCustom( $sQuery );
267
- if ( is_array( $mResult ) && count( $mResult ) == 1 ) {
268
- return $mResult[ 0 ];
269
- }
270
- return false;
271
  }
272
 
273
  /**
 
 
274
  */
275
- public function onWpLogout() {
276
- $this->doTerminateCurrentUserSession();
 
 
 
277
  }
278
 
279
  /**
280
- * @param string $sUsername
281
- * @return bool|int
282
  */
283
- protected function doAddNewActiveUserSessionRecord( $sUsername ) {
284
- if ( empty( $sUsername ) ) {
285
- return false;
286
- }
287
-
288
- $nTimeStamp = $this->time();
289
-
290
- // Add new session entry
291
- // set attempts = 1 and then when we know it's a valid login, we zero it.
292
- // First set any other entries for the given user to be deleted.
293
- $aNewData = array();
294
- $aNewData[ 'session_id' ] = $this->getSessionId();
295
- $aNewData[ 'ip' ] = $this->ip();
296
- $aNewData[ 'wp_username' ] = $sUsername;
297
- $aNewData[ 'login_attempts' ] = 0;
298
- $aNewData[ 'pending' ] = 0;
299
- $aNewData[ 'logged_in_at' ] = $nTimeStamp;
300
- $aNewData[ 'last_activity_at' ] = $nTimeStamp;
301
- $aNewData[ 'last_activity_uri' ] = $this->loadDataProcessor()->FetchServer( 'REQUEST_URI' );
302
- $aNewData[ 'created_at' ] = $nTimeStamp;
303
- $mResult = $this->insertData( $aNewData );
304
-
305
- $this->doStatIncrement( 'user.session.start' );
306
- return $mResult;
307
  }
308
 
309
  /**
310
  * @param string $sUsername
311
- * @return boolean
312
  */
313
- protected function doLimitUserSession( $sUsername ) {
314
 
315
  $nSessionLimit = $this->getOption( 'session_username_concurrent_limit', 1 );
316
- if ( $nSessionLimit <= 0 ) {
317
- return true;
318
- }
319
 
320
- $aSessions = $this->getActiveSessionRecordsForUsername( $sUsername );
321
- $nSessionsToKill = count( $aSessions ) - $nSessionLimit;
322
- if ( $nSessionsToKill < 1 ) {
323
- return true;
324
- }
325
 
326
- $mResult = true;
327
- for ( $nCount = 0; $nCount < $nSessionsToKill; $nCount++ ) {
328
- $mResult = $this->doTerminateUserSession( $aSessions[ $nCount ][ 'wp_username' ], $aSessions[ $nCount ][ 'session_id' ] );
329
- }
330
- return $mResult;
331
- }
332
 
333
- /**
334
- * @return boolean
335
- */
336
- protected function doTerminateCurrentUserSession() {
337
- $oUser = $this->loadWpUsers()->getCurrentWpUser();
338
- if ( empty( $oUser ) || !is_a( $oUser, 'WP_User' ) ) {
339
- return false;
340
- }
341
- $mResult = $this->doTerminateUserSession( $oUser->get( 'user_login' ), $this->getSessionId() );
342
- $this->getController()->clearSession();
343
- return $mResult;
344
- }
345
-
346
- /**
347
- * @param string $sUsername
348
- * @param string $sSessionId
349
- * @param bool $bHardDelete
350
- * @return bool|int
351
- */
352
- protected function doTerminateUserSession( $sUsername, $sSessionId, $bHardDelete = true ) {
353
- $this->doStatIncrement( 'user.session.terminate' );
354
-
355
- $aWhere = array(
356
- 'session_id' => $sSessionId,
357
- 'wp_username' => $sUsername,
358
- 'deleted_at' => 0
359
- );
360
-
361
- if ( $bHardDelete ) {
362
- return $this->loadDbProcessor()->deleteRowsFromTableWhere( $this->getTableName(), $aWhere );
363
  }
364
-
365
- $aNewData = array( 'deleted_at' => $this->time() );
366
- return $this->updateRowsWhere( $aNewData, $aWhere );
367
- }
368
-
369
- /**
370
- * @param string $sWpUsername
371
- * @return array|bool
372
- */
373
- public function getActiveUserSessionRecords( $sWpUsername = '' ) {
374
-
375
- $sQuery = "
376
- SELECT *
377
- FROM `%s`
378
- WHERE
379
- `pending` = '0'
380
- AND `deleted_at` = '0'
381
- %s
382
- ORDER BY `last_activity_at` ASC
383
- ";
384
- $sQuery = sprintf(
385
- $sQuery,
386
- $this->getTableName(),
387
- empty( $sWpUsername ) ? '' : "AND `wp_username` = '" . esc_sql( $sWpUsername ) . "'"
388
- );
389
- return $this->selectCustom( $sQuery );
390
  }
391
 
392
  /**
@@ -399,7 +195,7 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_BaseDbProces
399
  $oError = new WP_Error();
400
  }
401
 
402
- $sForceLogout = $this->loadDataProcessor()->FetchGet( 'wpsf-forcelogout' );
403
  if ( $sForceLogout ) {
404
 
405
  switch ( $sForceLogout ) {
@@ -433,64 +229,9 @@ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_BaseDbProces
433
  break;
434
  }
435
 
436
- $sMessage .= '<br />' . _wpsf__( 'Please login again.' );
437
  $oError->add( 'wpsf-forcelogout', $sMessage );
438
  }
439
  return $oError;
440
  }
441
-
442
- /**
443
- * @return string
444
- */
445
- public function getCreateTableSql() {
446
- $sSqlTables = "CREATE TABLE %s (
447
- id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
448
- session_id varchar(32) NOT NULL DEFAULT '',
449
- wp_username varchar(255) NOT NULL DEFAULT '',
450
- ip varchar(40) NOT NULL DEFAULT '0',
451
- logged_in_at int(15) NOT NULL DEFAULT 0,
452
- last_activity_at int(15) UNSIGNED NOT NULL DEFAULT 0,
453
- last_activity_uri text NOT NULL DEFAULT '',
454
- used_mfa int(1) NOT NULL DEFAULT 0,
455
- pending tinyint(1) NOT NULL DEFAULT 0,
456
- login_attempts int(1) NOT NULL DEFAULT 0,
457
- created_at int(15) UNSIGNED NOT NULL DEFAULT 0,
458
- deleted_at int(15) UNSIGNED NOT NULL DEFAULT 0,
459
- PRIMARY KEY (id)
460
- ) %s;";
461
- return sprintf( $sSqlTables, $this->getTableName(), $this->loadDbProcessor()->getCharCollate() );
462
- }
463
-
464
- /**
465
- * @return array
466
- */
467
- protected function getTableColumnsByDefinition() {
468
- $aDef = $this->getFeature()->getDefinition( 'user_sessions_table_columns' );
469
- return ( is_array( $aDef ) ? $aDef : array() );
470
- }
471
-
472
- /**
473
- * @param integer $nTime - number of seconds back from now to look
474
- * @return array|boolean
475
- */
476
- public function getPendingOrFailedUserSessionRecordsSince( $nTime = 0 ) {
477
-
478
- $nTime = ( $nTime <= 0 ) ? 2 * DAY_IN_SECONDS : $nTime;
479
-
480
- $sQuery = "
481
- SELECT *
482
- FROM `%s`
483
- WHERE
484
- `pending` = '1'
485
- AND `deleted_at` = '0'
486
- AND `created_at` > '%s'
487
- ";
488
- $sQuery = sprintf(
489
- $sQuery,
490
- $this->getTableName(),
491
- ( $this->time() - $nTime )
492
- );
493
-
494
- return $this->selectCustom( $sQuery );
495
- }
496
  }
4
  return;
5
  }
6
 
7
+ require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'base_wpsf.php' );
8
 
9
+ class ICWP_WPSF_Processor_UserManagement_Sessions extends ICWP_WPSF_Processor_BaseWpsf {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  public function run() {
 
 
 
 
12
  add_filter( 'wp_login_errors', array( $this, 'addLoginMessage' ) );
13
+ add_filter( 'auth_cookie_expiration', array( $this, 'setTimeoutCookieExpiration_Filter' ), 100, 1 );
14
+ add_action( 'wp_loaded', array( $this, 'onWpLoaded' ), 1 ); // Check the current every page load.
15
+ add_action( 'wp_login', array( $this, 'onWpLogin' ), 10, 1 );
 
 
 
 
 
 
 
16
  }
17
 
18
  /**
19
+ * @param string $sUsername
 
 
20
  */
21
+ public function onWpLogin( $sUsername ) {
22
+ $this->enforceSessionLimits( $sUsername );
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
 
25
  /**
 
26
  */
27
+ public function onWpLoaded() {
28
+ if ( $this->loadWpUsers()->isUserLoggedIn() && !$this->loadWp()->isRestUrl() ) {
29
+ $this->checkCurrentSession();
30
+ }
31
  }
32
 
33
  /**
34
  * Should be hooked to 'init' so we have is_user_logged_in()
35
  */
36
+ private function checkCurrentSession() {
37
  $oWp = $this->loadWp();
38
  $oWpUsers = $this->loadWpUsers();
39
 
40
+ $nCode = $this->assessCurrentSession();
41
 
42
+ if ( $nCode > 0 ) { // it's not admin, but the user looks logged into WordPress and not to Shield
43
 
44
  if ( is_admin() ) { // prevent any admin access on invalid Shield sessions.
45
 
46
+ switch ( $nCode ) {
47
 
48
+ case 7:
49
+ $oWpUsers->logoutUser( true );
50
+ $this->addToAuditEntry(
51
+ sprintf( 'Browser signature has changed for this user "%s" session. Redirecting request.', $oWpUsers->getCurrentWpUser()->user_login ),
52
+ 2,
53
+ 'um_session_browser_lock_redirect'
54
+ );
55
+ $oWp->redirectToLogin();
56
+ break;
57
+
58
+ case 3:
59
+ // $this->loadWpUsers()->logoutUser( true ); // so as not to destroy the original, legitimate session
60
  $this->addToAuditEntry(
61
  sprintf( 'Access to an established user session from a new IP address "%s". Redirecting request.', $this->ip() ),
62
  2,
63
  'um_session_ip_lock_redirect'
64
  );
65
  $oWp->redirectToHome();
66
+ break;
67
+
68
+ default:
69
  $this->addToAuditEntry(
70
  'Unable to verify the current User Session. Forcefully logging out session and redirecting to login.',
71
  2,
72
  'um_session_not_found_redirect'
73
  );
74
  $oWpUsers->forceUserRelogin( array( 'wpsf-forcelogout' => $nCode ) );
75
+ break;
76
  }
77
  }
78
+ else {
79
+ $this->addToAuditEntry(
80
+ 'Unable to verify the current User Session. Forcefully logging out session.',
81
+ 2,
82
+ 'um_session_not_found'
83
+ );
84
+ $oWpUsers->logoutUser();
85
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  }
88
 
89
  /**
90
  * @return int
91
  */
92
+ protected function assessCurrentSession() {
93
+ /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
94
+ $oFO = $this->getFeature();
95
 
96
+ if ( !$oFO->hasSession() ) {
97
  $nForceLogOutCode = 6;
98
  }
99
  else {
100
+ $oSess = $oFO->getSession();
101
+ $nTime = $this->time();
102
+ $nTimeout = $this->getSessionTimeoutInterval();
103
+ $nIdleTimeout = $this->getSessionIdleTimeoutInterval();
 
 
104
 
105
  $nForceLogOutCode = 0; // when it's == 0 it's a valid session
106
 
107
+ if ( empty( $oSess ) ) {
 
 
 
 
108
  $nForceLogOutCode = 4;
 
109
  } // timeout interval
110
+ else if ( $nTimeout > 0 && ( $nTime - $oSess->getLoggedInAt() > $nTimeout ) ) {
111
  $nForceLogOutCode = 1;
 
112
  } // idle timeout interval
113
+ else if ( $nIdleTimeout > 0 && ( ( $nTime - $oSess->getLastActivityAt() ) > $nIdleTimeout ) ) {
114
  $nForceLogOutCode = 2;
 
115
  } // login ip address lock
116
+ else if ( $this->isLockToIp() && ( $this->ip() != $oSess->getIp() ) ) { //TODO: sha1
117
  $nForceLogOutCode = 3;
118
  }
119
  }
121
  return $nForceLogOutCode;
122
  }
123
 
 
 
 
 
 
 
 
 
 
 
124
  /**
125
  * @param integer $nTimeout
126
  * @return integer
127
  */
128
+ public function setTimeoutCookieExpiration_Filter( $nTimeout ) {
129
  $nSessionTimeoutInterval = $this->getSessionTimeoutInterval();
130
+ return ( $nSessionTimeoutInterval > 0 ) ? $nSessionTimeoutInterval : $nTimeout;
131
  }
132
 
133
  /**
134
  * @return integer
135
  */
136
  protected function getSessionTimeoutInterval() {
137
+ return $this->getOption( 'session_timeout_interval' )*DAY_IN_SECONDS;
 
 
 
 
 
 
 
 
 
138
  }
139
 
140
  /**
141
+ * @return integer
 
 
 
142
  */
143
+ protected function getSessionIdleTimeoutInterval() {
144
+ return $this->getOption( 'session_idle_timeout_interval' )*HOUR_IN_SECONDS;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  }
146
 
147
  /**
148
+ * @param string $sWpUsername
149
+ * @return ICWP_WPSF_SessionVO[]
150
  */
151
+ public function getActiveSessionRecordsForUsername( $sWpUsername ) {
152
+ /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
153
+ $oFO = $this->getFeature();
154
+ return $oFO->getSessionsProcessor()
155
+ ->queryGetActiveSessionsForUsername( $sWpUsername );
156
  }
157
 
158
  /**
159
+ * @return bool
 
160
  */
161
+ protected function isLockToIp() {
162
+ return $this->getFeature()->getOptIs( 'session_lock_location', 'Y' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  }
164
 
165
  /**
166
  * @param string $sUsername
 
167
  */
168
+ protected function enforceSessionLimits( $sUsername ) {
169
 
170
  $nSessionLimit = $this->getOption( 'session_username_concurrent_limit', 1 );
171
+ if ( $nSessionLimit > 0 ) {
 
 
172
 
173
+ $aSessions = $this->getActiveSessionRecordsForUsername( $sUsername );
174
+ $nSessionsToKill = count( $aSessions ) - $nSessionLimit;
175
+ if ( $nSessionsToKill > 0 ) {
 
 
176
 
177
+ /** @var ICWP_WPSF_FeatureHandler_UserManagement $oFO */
178
+ $oFO = $this->getFeature();
179
+ $oSessProcessor = $oFO->getSessionsProcessor();
 
 
 
180
 
181
+ for ( $nCount = 0 ; $nCount < $nSessionsToKill ; $nCount++ ) {
182
+ $oSessProcessor->queryTerminateSession( $aSessions[ $nCount ] );
183
+ }
184
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  }
187
 
188
  /**
195
  $oError = new WP_Error();
196
  }
197
 
198
+ $sForceLogout = $this->loadDP()->query( 'wpsf-forcelogout' );
199
  if ( $sForceLogout ) {
200
 
201
  switch ( $sForceLogout ) {
229
  break;
230
  }
231
 
232
+ $sMessage .= '<br />'._wpsf__( 'Please login again.' );
233
  $oError->add( 'wpsf-forcelogout', $sMessage );
234
  }
235
  return $oError;
236
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  }
src/query/ICWP_WPSF_SessionVO.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ICWP_WPSF_SessionVO {
4
+
5
+ /**
6
+ * @var stdClass
7
+ */
8
+ protected $oRowData;
9
+
10
+ /**
11
+ * @param stdClass $oRowData
12
+ */
13
+ public function __construct( $oRowData ) {
14
+ $this->oRowData = $oRowData;
15
+ }
16
+
17
+ /**
18
+ * @return int
19
+ */
20
+ public function getCreatedAt() {
21
+ return $this->getRowData()->created_at;
22
+ }
23
+
24
+ /**
25
+ * @return string
26
+ */
27
+ public function getBrowser() {
28
+ return $this->getRowData()->browser;
29
+ }
30
+
31
+ /**
32
+ * @return int
33
+ */
34
+ public function getId() {
35
+ return $this->getRowData()->session_id;
36
+ }
37
+
38
+ /**
39
+ * @return string
40
+ */
41
+ public function getIp() {
42
+ return $this->getRowData()->ip;
43
+ }
44
+
45
+ /**
46
+ * @return int
47
+ */
48
+ public function getLastActivityAt() {
49
+ return $this->getRowData()->last_activity_at;
50
+ }
51
+
52
+ /**
53
+ * @return int
54
+ */
55
+ public function getLoggedInAt() {
56
+ return $this->getRowData()->logged_in_at;
57
+ }
58
+
59
+ /**
60
+ * @return int
61
+ */
62
+ public function getUsername() {
63
+ return $this->getRowData()->wp_username;
64
+ }
65
+
66
+ /**
67
+ * @return int
68
+ */
69
+ public function getSecAdminAt() {
70
+ return $this->getRowData()->secadmin_at;
71
+ }
72
+
73
+ /**
74
+ * @return int
75
+ */
76
+ public function isDeleted() {
77
+ return $this->getRowData()->deleted_at > 0;
78
+ }
79
+
80
+ /**
81
+ * @return stdClass
82
+ */
83
+ public function getRowData() {
84
+ return $this->oRowData;
85
+ }
86
+
87
+ /**
88
+ * @param stdClass $oRowData
89
+ * @return $this
90
+ */
91
+ public function setRowData( $oRowData ) {
92
+ $this->oRowData = $oRowData;
93
+ return $this;
94
+ }
95
+ }
src/query/base.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'ICWP_WPSF_Query_Base', false ) ) {
4
+ return;
5
+ }
6
+
7
+ class ICWP_WPSF_Query_Base extends ICWP_WPSF_Foundation {
8
+
9
+ /**
10
+ * @var string
11
+ */
12
+ protected $sTable;
13
+
14
+ /**
15
+ * @return string
16
+ */
17
+ public function getTable() {
18
+ return $this->sTable;
19
+ }
20
+
21
+ /**
22
+ * @param string $sTable
23
+ * @return $this
24
+ */
25
+ public function setTable( $sTable ) {
26
+ $this->sTable = $sTable;
27
+ return $this;
28
+ }
29
+ }
src/query/sessions_create.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'ICWP_WPSF_Query_Sessions_Create', false ) ) {
4
+ return;
5
+ }
6
+
7
+ require_once( dirname( __FILE__ ).'/base.php' );
8
+
9
+ class ICWP_WPSF_Query_Sessions_Create extends ICWP_WPSF_Query_Base {
10
+
11
+ /**
12
+ * @param string $sUsername
13
+ * @param string $sSessionId
14
+ * @return bool|int
15
+ */
16
+ public function create( $sUsername, $sSessionId ) {
17
+ $oDP = $this->loadDP();
18
+ $nTimeStamp = $oDP->time();
19
+
20
+ // Add new session entry
21
+ // set attempts = 1 and then when we know it's a valid login, we zero it.
22
+ // First set any other entries for the given user to be deleted.
23
+ $aNewData = array(
24
+ 'session_id' => $sSessionId,
25
+ 'ip' => $this->loadIpService()->getRequestIp(), // TODO: SHA1
26
+ 'browser' => md5( $oDP->getUserAgent() ),
27
+ 'wp_username' => $sUsername,
28
+ 'logged_in_at' => $nTimeStamp,
29
+ 'created_at' => $nTimeStamp,
30
+ 'last_activity_at' => $nTimeStamp,
31
+ 'last_activity_uri' => $oDP->FetchServer( 'REQUEST_URI' ),
32
+ );
33
+ $mResult = $this->loadDbProcessor()
34
+ ->insertDataIntoTable( $this->getTable(), $aNewData );
35
+ return ( $mResult === false ) ? false : $mResult > 0;
36
+ }
37
+ }
src/query/sessions_retrieve.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'ICWP_WPSF_Query_Sessions_Retrieve', false ) ) {
4
+ return;
5
+ }
6
+
7
+ require_once( dirname( __FILE__ ).'/base.php' );
8
+
9
+ class ICWP_WPSF_Query_Sessions_Retrieve extends ICWP_WPSF_Query_Base {
10
+
11
+ public function __construct() {
12
+ $this->init();
13
+ }
14
+
15
+ /**
16
+ * @return ICWP_WPSF_SessionVO[]
17
+ */
18
+ public function all() {
19
+ return $this->query_retrieveForUserSession();
20
+ }
21
+
22
+ /**
23
+ * @param string $sWpUsername
24
+ * @return ICWP_WPSF_SessionVO[]
25
+ */
26
+ public function retrieveForUsername( $sWpUsername ) {
27
+ return $this->query_retrieveForUserSession( $sWpUsername );
28
+ }
29
+
30
+ /**
31
+ * @param string $sWpUsername
32
+ * @param string $sSessionId
33
+ * @return ICWP_WPSF_SessionVO|null
34
+ */
35
+ public function retrieveUserSession( $sWpUsername, $sSessionId ) {
36
+ $aData = $this->query_retrieveForUserSession( $sWpUsername, $sSessionId );
37
+ return ( count( $aData ) == 1 ) ? array_shift( $aData ) : null;
38
+ }
39
+
40
+ /**
41
+ * @param string $sWpUsername
42
+ * @param string $sSessionId
43
+ * @return ICWP_WPSF_SessionVO[]
44
+ */
45
+ protected function query_retrieveForUserSession( $sWpUsername = '', $sSessionId = '' ) {
46
+ $sQuery = "
47
+ SELECT *
48
+ FROM `%s`
49
+ WHERE
50
+ `deleted_at` = 0
51
+ %s
52
+ %s
53
+ ORDER BY `last_activity_at` ASC
54
+ ";
55
+ $sQuery = sprintf(
56
+ $sQuery,
57
+ $this->getTable(),
58
+ empty( $sWpUsername ) ? '' : "AND `wp_username` = '".esc_sql( $sWpUsername )."'",
59
+ empty( $sSessionId ) ? '' : "AND `session_id` = '".esc_sql( $sSessionId )."'"
60
+ );
61
+
62
+ $aData = $this->loadDbProcessor()
63
+ ->selectCustom( $sQuery, OBJECT_K );
64
+ foreach ( $aData as $nKey => $oSess ) {
65
+ $aData[ $nKey ] = new ICWP_WPSF_SessionVO( $oSess );
66
+ }
67
+ return $aData;
68
+ }
69
+
70
+ protected function init() {
71
+ require_once( dirname( __FILE__ ).'/ICWP_WPSF_SessionVO.php' );
72
+ }
73
+ }
src/query/sessions_terminate.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'ICWP_WPSF_Query_Sessions_Terminate', false ) ) {
4
+ return;
5
+ }
6
+
7
+ require_once( dirname( __FILE__ ).'/base.php' );
8
+
9
+ class ICWP_WPSF_Query_Sessions_Terminate extends ICWP_WPSF_Query_Base {
10
+
11
+ /**
12
+ * @param string $sWpUsername
13
+ * @return false|int
14
+ */
15
+ public function forUsername( $sWpUsername ) {
16
+ return $this->query_terminateForUser( $sWpUsername );
17
+ }
18
+
19
+ /**
20
+ * @param ICWP_WPSF_SessionVO $oSession
21
+ * @return false|int
22
+ */
23
+ public function forUserSession( $oSession ) {
24
+ return $this->query_terminateForUser( $oSession->getUsername(), $oSession->getId() );
25
+ }
26
+
27
+ /**
28
+ * @param string $sWpUsername
29
+ * @param string $sSessionId
30
+ * @return false|int
31
+ */
32
+ protected function query_terminateForUser( $sWpUsername, $sSessionId = '' ) {
33
+
34
+ $aWhere = array(
35
+ 'wp_username' => $sWpUsername,
36
+ 'deleted_at' => 0
37
+ );
38
+ if ( !empty( $sSessionId ) ) {
39
+ $aWhere[ 'session_id' ] = $sSessionId;
40
+ }
41
+ return $this->loadDbProcessor()->deleteRowsFromTableWhere( $this->getTable(), $aWhere );
42
+ }
43
+ }
src/query/sessions_update.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( class_exists( 'ICWP_WPSF_Query_Sessions_Update', false ) ) {
4
+ return;
5
+ }
6
+
7
+ require_once( dirname( __FILE__ ).'/base.php' );
8
+
9
+ class ICWP_WPSF_Query_Sessions_Update extends ICWP_WPSF_Query_Base {
10
+
11
+ /**
12
+ * @param ICWP_WPSF_SessionVO $oSession
13
+ * @return bool
14
+ */
15
+ public function startSecurityAdmin( $oSession ) {
16
+ return $this->querySecurityAdmin( $oSession, true );
17
+ }
18
+
19
+ /**
20
+ * @param ICWP_WPSF_SessionVO $oSession
21
+ * @return bool
22
+ */
23
+ public function terminateSecurityAdmin( $oSession ) {
24
+ return $this->querySecurityAdmin( $oSession, false );
25
+ }
26
+
27
+ /**
28
+ * @param ICWP_WPSF_SessionVO $oSession
29
+ * @return bool|int
30
+ */
31
+ public function updateLastActivity( $oSession ) {
32
+
33
+ $oDP = $this->loadDP();
34
+ return $this->loadDbProcessor()
35
+ ->updateRowsFromTableWhere(
36
+ $this->getTable(),
37
+ array(
38
+ 'last_activity_at' => $oDP->time(),
39
+ 'last_activity_uri' => $oDP->FetchServer( 'REQUEST_URI' )
40
+ ),
41
+ array(
42
+ 'session_id' => $oSession->getId(),
43
+ 'wp_username' => $oSession->getUsername(),
44
+ 'deleted_at' => 0
45
+ )
46
+ );
47
+ }
48
+
49
+ /**
50
+ * @param ICWP_WPSF_SessionVO $oSession
51
+ * @param bool $bStart - true to start, false to terminate
52
+ * @return bool
53
+ */
54
+ private function querySecurityAdmin( $oSession, $bStart ) {
55
+ $mResult = false;
56
+ if ( $oSession instanceof ICWP_WPSF_SessionVO ) {
57
+ $mResult = $this->loadDbProcessor()
58
+ ->updateRowsFromTableWhere(
59
+ $this->getTable(),
60
+ array( 'secadmin_at' => $bStart ? $this->loadDP()->time() : 0 ),
61
+ array(
62
+ 'session_id' => $oSession->getId(),
63
+ 'wp_username' => $oSession->getUsername(),
64
+ 'deleted_at' => 0
65
+ )
66
+ );
67
+ }
68
+ return ( is_numeric( $mResult ) ) && $mResult == 1;
69
+ }
70
+ }
src/query/statistics_base.php CHANGED
@@ -4,9 +4,9 @@ if ( class_exists( 'ICWP_WPSF_Query_Statistics_Base', false ) ) {
4
  return;
5
  }
6
 
7
- require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'statistics_base.php' );
8
 
9
- class ICWP_WPSF_Query_Statistics_Base extends ICWP_WPSF_Foundation {
10
 
11
  /**
12
  * @var ICWP_WPSF_FeatureHandler_Statistics
@@ -48,7 +48,7 @@ class ICWP_WPSF_Query_Statistics_Base extends ICWP_WPSF_Foundation {
48
 
49
  // TODO: NOT PHP 5.2!
50
  if ( is_array( $mResult ) ) {
51
- include_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'StatisticsReportingVO.php' );
52
  $mResult = array_map(
53
  function ( $oData ) {
54
  return new StatisticsReportingVO( $oData );
@@ -84,7 +84,7 @@ class ICWP_WPSF_Query_Statistics_Base extends ICWP_WPSF_Foundation {
84
  $this->getDateFrom(),
85
  $this->getDateTo(),
86
  $this->isSelectDeleted() ? '>' : '=',
87
- empty( $sStatPart ) ? $sStatPart : 'AND ' . $sStatPart,
88
  $this->getQueryLimit()
89
  );
90
  }
4
  return;
5
  }
6
 
7
+ require_once( dirname( __FILE__ ).'/base.php' );
8
 
9
+ class ICWP_WPSF_Query_Statistics_Base extends ICWP_WPSF_Query_Base {
10
 
11
  /**
12
  * @var ICWP_WPSF_FeatureHandler_Statistics
48
 
49
  // TODO: NOT PHP 5.2!
50
  if ( is_array( $mResult ) ) {
51
+ include_once( dirname( __FILE__ ).'/StatisticsReportingVO.php' );
52
  $mResult = array_map(
53
  function ( $oData ) {
54
  return new StatisticsReportingVO( $oData );
84
  $this->getDateFrom(),
85
  $this->getDateTo(),
86
  $this->isSelectDeleted() ? '>' : '=',
87
+ empty( $sStatPart ) ? $sStatPart : 'AND '.$sStatPart,
88
  $this->getQueryLimit()
89
  );
90
  }
src/query/statistics_consolidation.php CHANGED
@@ -4,7 +4,7 @@ if ( class_exists( 'ICWP_WPSF_Query_Statistics_Consolidation', false ) ) {
4
  return;
5
  }
6
 
7
- require_once( dirname( __FILE__ ).DIRECTORY_SEPARATOR.'statistics_base.php' );
8
 
9
  class ICWP_WPSF_Query_Statistics_Consolidation extends ICWP_WPSF_Query_Statistics_Base {
10
 
4
  return;
5
  }
6
 
7
+ require_once( dirname( __FILE__ ).'/statistics_base.php' );
8
 
9
  class ICWP_WPSF_Query_Statistics_Consolidation extends ICWP_WPSF_Query_Statistics_Base {
10
 
src/query/statistics_reporting.php CHANGED
@@ -4,7 +4,7 @@ if ( class_exists( 'ICWP_WPSF_Query_Statistics_Reporting', false ) ) {
4
  return;
5
  }
6
 
7
- require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'statistics_base.php' );
8
 
9
  class ICWP_WPSF_Query_Statistics_Reporting extends ICWP_WPSF_Query_Statistics_Base {
10
 
4
  return;
5
  }
6
 
7
+ require_once( dirname( __FILE__ ).'/statistics_base.php' );
8
 
9
  class ICWP_WPSF_Query_Statistics_Reporting extends ICWP_WPSF_Query_Statistics_Base {
10
 
src/wizards/base_wpsf.php CHANGED
@@ -113,8 +113,7 @@ abstract class ICWP_WPSF_Wizard_BaseWpsf extends ICWP_WPSF_Wizard_Base {
113
  $sMessage = _wpsf__( 'Security Admin Key was not correct.' );
114
  }
115
  else {
116
- $bSuccess = true;
117
- $oModule->setPermissionToSubmit( true );
118
  $aData = array(
119
  'rerender' => true
120
  );
113
  $sMessage = _wpsf__( 'Security Admin Key was not correct.' );
114
  }
115
  else {
116
+ $bSuccess = $oModule->setPermissionToSubmit( true );
 
117
  $aData = array(
118
  'rerender' => true
119
  );
src/wizards/hack_protect.php CHANGED
@@ -130,7 +130,7 @@ class ICWP_WPSF_Wizard_HackProtect extends ICWP_WPSF_Wizard_BaseWpsf {
130
  $bSuccess = ( $sSetting == $oFO->getUnrecognisedFileScannerOption() );
131
 
132
  if ( $bSuccess ) {
133
- if ( $oFO->isUfsEnabled() ) {
134
  $sMessage = 'Scanner automation has been enabled.';
135
  }
136
  else {
@@ -249,7 +249,7 @@ class ICWP_WPSF_Wizard_HackProtect extends ICWP_WPSF_Wizard_BaseWpsf {
249
  'exclusions',
250
  'scanresult'
251
  );
252
- if ( !$oFO->isUfsEnabled() ) {
253
  $aStepsSlugs[] = 'config';
254
  }
255
  $aStepsSlugs[] = 'finished';
130
  $bSuccess = ( $sSetting == $oFO->getUnrecognisedFileScannerOption() );
131
 
132
  if ( $bSuccess ) {
133
+ if ( $oFO->isUfcEnabled() ) {
134
  $sMessage = 'Scanner automation has been enabled.';
135
  }
136
  else {
249
  'exclusions',
250
  'scanresult'
251
  );
252
+ if ( !$oFO->isUfcEnabled() ) {
253
  $aStepsSlugs[] = 'config';
254
  }
255
  $aStepsSlugs[] = 'finished';
src/wizards/plugin.php CHANGED
@@ -64,7 +64,8 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
64
  $oResponse = $this->wizardLoginProtect();
65
  break;
66
 
67
- case 'optin':
 
68
  $oResponse = $this->wizardOptin();
69
  break;
70
 
@@ -416,21 +417,28 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
416
  * @return \FernleafSystems\Utilities\Response
417
  */
418
  private function wizardAuditTrail() {
419
- $bEnabled = $this->loadDP()->post( 'AuditTrailOption' ) === 'Y';
420
-
421
- /** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
422
- $oModule = $this->getPluginCon()->getModule( 'audit_trail' );
423
- $oModule->setIsMainFeatureEnabled( $bEnabled )
424
- ->savePluginOptions();
425
-
426
- $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
427
- if ( $bSuccess ) {
428
- $sMessage = sprintf( '%s has been %s.', _wpsf__( 'Audit Trail' ),
429
- $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
430
- );
431
- }
432
- else {
433
- $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Audit Trail' ) );
 
 
 
 
 
 
 
434
  }
435
 
436
  $oResponse = new \FernleafSystems\Utilities\Response();
@@ -443,21 +451,27 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
443
  */
444
  private function wizardIps() {
445
 
446
- $bEnabled = $this->loadDP()->post( 'IpManagerOption' ) === 'Y';
 
 
447
 
448
- /** @var ICWP_WPSF_FeatureHandler_Ips $oModule */
449
- $oModule = $this->getPluginCon()->getModule( 'ips' );
450
- $oModule->setIsMainFeatureEnabled( $bEnabled )
451
- ->savePluginOptions();
452
 
453
- $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
454
- if ( $bSuccess ) {
455
- $sMessage = sprintf( '%s has been %s.', _wpsf__( 'IP Manager' ),
456
- $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
457
- );
458
- }
459
- else {
460
- $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'IP Manager' ) );
 
 
 
 
 
 
461
  }
462
 
463
  $oResponse = new \FernleafSystems\Utilities\Response();
@@ -470,24 +484,30 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
470
  */
471
  private function wizardLoginProtect() {
472
 
473
- $bEnabled = $this->loadDP()->post( 'LoginProtectOption' ) === 'Y';
 
 
474
 
475
- /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oModule */
476
- $oModule = $this->getPluginCon()->getModule( 'login_protect' );
477
- if ( $bEnabled ) { // we don't disable the whole module
478
- $oModule->setIsMainFeatureEnabled( true );
479
- }
480
- $oModule->setEnabledGaspCheck( $bEnabled )
481
- ->savePluginOptions();
482
-
483
- $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
484
- if ( $bSuccess ) {
485
- $sMessage = sprintf( '%s has been %s.', _wpsf__( 'Login Protection' ),
486
- $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
487
- );
488
- }
489
- else {
490
- $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Login Protection' ) );
 
 
 
 
491
  }
492
 
493
  $oResponse = new \FernleafSystems\Utilities\Response();
@@ -500,19 +520,36 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
500
  */
501
  private function wizardOptin() {
502
  $oDP = $this->loadDP();
503
-
504
- $bEnabledTracking = $oDP->post( 'AnonymousOption', 'N', true ) === 'Y';
505
- $bEnabledBadge = $oDP->post( 'BadgeOption', 'N', true ) === 'Y';
506
-
507
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oModule */
508
  $oModule = $this->getPluginCon()->getModule( 'plugin' );
509
- $oModule->setIsDisplayPluginBadge( $bEnabledBadge )
510
- ->setPluginTrackingPermission( $bEnabledTracking );
511
 
512
- $sMessage = _wpsf__( 'Preferences have been saved.' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
 
514
  $oResponse = new \FernleafSystems\Utilities\Response();
515
- return $oResponse->setSuccessful( true )
516
  ->setMessageText( $sMessage );
517
  }
518
 
@@ -521,24 +558,30 @@ class ICWP_WPSF_Wizard_Plugin extends ICWP_WPSF_Wizard_BaseWpsf {
521
  */
522
  private function wizardCommentsFilter() {
523
 
524
- $bEnabled = $this->loadDP()->post( 'CommentsFilterOption' ) === 'Y';
 
 
525
 
526
- /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oModule */
527
- $oModule = $this->getPluginCon()->getModule( 'comments_filter' );
528
- if ( $bEnabled ) { // we don't disable the whole module
529
- $oModule->setIsMainFeatureEnabled( true );
530
- }
531
- $oModule->setEnabledGasp( $bEnabled )
532
- ->savePluginOptions();
533
-
534
- $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
535
- if ( $bSuccess ) {
536
- $sMessage = sprintf( '%s has been %s.', _wpsf__( 'Comment SPAM Protection' ),
537
- $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
538
- );
539
- }
540
- else {
541
- $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Comment SPAM Protection' ) );
 
 
 
 
542
  }
543
 
544
  $oResponse = new \FernleafSystems\Utilities\Response();
64
  $oResponse = $this->wizardLoginProtect();
65
  break;
66
 
67
+ case 'optin_usage':
68
+ case 'optin_badge':
69
  $oResponse = $this->wizardOptin();
70
  break;
71
 
417
  * @return \FernleafSystems\Utilities\Response
418
  */
419
  private function wizardAuditTrail() {
420
+
421
+ $sInput = $this->loadDP()->post( 'AuditTrailOption' );
422
+ $bSuccess = false;
423
+ $sMessage = _wpsf__( 'No changes were made as no option was selected' );
424
+
425
+ if ( !empty( $sInput ) ) {
426
+ $bEnabled = $sInput === 'Y';
427
+
428
+ /** @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oModule */
429
+ $oModule = $this->getPluginCon()->getModule( 'audit_trail' );
430
+ $oModule->setIsMainFeatureEnabled( $bEnabled )
431
+ ->savePluginOptions();
432
+
433
+ $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
434
+ if ( $bSuccess ) {
435
+ $sMessage = sprintf( '%s has been %s.', _wpsf__( 'Audit Trail' ),
436
+ $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
437
+ );
438
+ }
439
+ else {
440
+ $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Audit Trail' ) );
441
+ }
442
  }
443
 
444
  $oResponse = new \FernleafSystems\Utilities\Response();
451
  */
452
  private function wizardIps() {
453
 
454
+ $sInput = $this->loadDP()->post( 'IpManagerOption' );
455
+ $bSuccess = false;
456
+ $sMessage = _wpsf__( 'No changes were made as no option was selected' );
457
 
458
+ if ( !empty( $sInput ) ) {
459
+ $bEnabled = $sInput === 'Y';
 
 
460
 
461
+ /** @var ICWP_WPSF_FeatureHandler_Ips $oModule */
462
+ $oModule = $this->getPluginCon()->getModule( 'ips' );
463
+ $oModule->setIsMainFeatureEnabled( $bEnabled )
464
+ ->savePluginOptions();
465
+
466
+ $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
467
+ if ( $bSuccess ) {
468
+ $sMessage = sprintf( '%s has been %s.', _wpsf__( 'IP Manager' ),
469
+ $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
470
+ );
471
+ }
472
+ else {
473
+ $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'IP Manager' ) );
474
+ }
475
  }
476
 
477
  $oResponse = new \FernleafSystems\Utilities\Response();
484
  */
485
  private function wizardLoginProtect() {
486
 
487
+ $sInput = $this->loadDP()->post( 'LoginProtectOption' );
488
+ $bSuccess = false;
489
+ $sMessage = _wpsf__( 'No changes were made as no option was selected' );
490
 
491
+ if ( !empty( $sInput ) ) {
492
+ $bEnabled = $sInput === 'Y';
493
+
494
+ /** @var ICWP_WPSF_FeatureHandler_LoginProtect $oModule */
495
+ $oModule = $this->getPluginCon()->getModule( 'login_protect' );
496
+ if ( $bEnabled ) { // we don't disable the whole module
497
+ $oModule->setIsMainFeatureEnabled( true );
498
+ }
499
+ $oModule->setEnabledGaspCheck( $bEnabled )
500
+ ->savePluginOptions();
501
+
502
+ $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
503
+ if ( $bSuccess ) {
504
+ $sMessage = sprintf( '%s has been %s.', _wpsf__( 'Login Protection' ),
505
+ $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
506
+ );
507
+ }
508
+ else {
509
+ $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Login Protection' ) );
510
+ }
511
  }
512
 
513
  $oResponse = new \FernleafSystems\Utilities\Response();
520
  */
521
  private function wizardOptin() {
522
  $oDP = $this->loadDP();
 
 
 
 
523
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oModule */
524
  $oModule = $this->getPluginCon()->getModule( 'plugin' );
 
 
525
 
526
+ $bSuccess = false;
527
+ $sMessage = _wpsf__( 'No changes were made as no option was selected' );
528
+
529
+ $sForm = $oDP->post( 'wizard-step' );
530
+ if ( $sForm == 'optin_badge' ) {
531
+ $sInput = $oDP->post( 'BadgeOption' );
532
+
533
+ if ( !empty( $sInput ) ) {
534
+ $bEnabled = $sInput === 'Y';
535
+ $oModule->setIsDisplayPluginBadge( $bEnabled );
536
+ $bSuccess = true;
537
+ $sMessage = _wpsf__( 'Preferences have been saved.' );
538
+ }
539
+ }
540
+ else if ( $sForm == 'optin_badge' ) {
541
+ $sInput = $oDP->post( 'AnonymousOption' );
542
+
543
+ if ( !empty( $sInput ) ) {
544
+ $bEnabled = $sInput === 'Y';
545
+ $oModule->setPluginTrackingPermission( $bEnabled );
546
+ $bSuccess = true;
547
+ $sMessage = _wpsf__( 'Preferences have been saved.' );
548
+ }
549
+ }
550
 
551
  $oResponse = new \FernleafSystems\Utilities\Response();
552
+ return $oResponse->setSuccessful( $bSuccess )
553
  ->setMessageText( $sMessage );
554
  }
555
 
558
  */
559
  private function wizardCommentsFilter() {
560
 
561
+ $sInput = $this->loadDP()->post( 'CommentsFilterOption' );
562
+ $bSuccess = false;
563
+ $sMessage = _wpsf__( 'No changes were made as no option was selected' );
564
 
565
+ if ( !empty( $sInput ) ) {
566
+ $bEnabled = $sInput === 'Y';
567
+
568
+ /** @var ICWP_WPSF_FeatureHandler_CommentsFilter $oModule */
569
+ $oModule = $this->getPluginCon()->getModule( 'comments_filter' );
570
+ if ( $bEnabled ) { // we don't disable the whole module
571
+ $oModule->setIsMainFeatureEnabled( true );
572
+ }
573
+ $oModule->setEnabledGasp( $bEnabled )
574
+ ->savePluginOptions();
575
+
576
+ $bSuccess = $oModule->getIsMainFeatureEnabled() === $bEnabled;
577
+ if ( $bSuccess ) {
578
+ $sMessage = sprintf( '%s has been %s.', _wpsf__( 'Comment SPAM Protection' ),
579
+ $oModule->getIsMainFeatureEnabled() ? _wpsf__( 'Enabled' ) : _wpsf__( 'Disabled' )
580
+ );
581
+ }
582
+ else {
583
+ $sMessage = sprintf( _wpsf__( '%s setting could not be changed at this time.' ), _wpsf__( 'Comment SPAM Protection' ) );
584
+ }
585
  }
586
 
587
  $oResponse = new \FernleafSystems\Utilities\Response();
templates/php/feature-default.php CHANGED
@@ -47,22 +47,21 @@
47
  </ul>
48
  <div class="tab-content">
49
  <div class="tab-pane active" id="icwpPillOptions">
50
- <?php echo $flags[ 'show_standard_options' ] ? $options_form : ''; ?>
51
  <?php echo $flags[ 'show_alt_content' ] ? $content[ 'alt' ] : ''; ?>
52
  </div>
 
53
  <?php if ( $flags[ 'show_content_actions' ] ) : ?>
54
  <div class="tab-pane" id="icwpPillActions">
55
  <?php echo $content[ 'actions' ]; ?>
56
  </div>
57
  <?php endif; ?>
 
58
  <?php if ( $flags[ 'show_content_help' ] ) : ?>
59
  <div class="tab-pane" id="icwpPillHelp">
60
  <div class="content-help"><?php echo $content[ 'help' ]; ?></div>
61
  </div>
62
  <?php endif; ?>
63
- <div class="tab-pane" id="icwpPillSelect">
64
- <h3 style="text-align: center">&uarr; <?php echo 'Select Desired Section Above'; ?> &uarr;</h3>
65
- </div>
66
  </div>
67
 
68
  <?php if ( $flags[ 'show_ads' ] ) : ?>
47
  </ul>
48
  <div class="tab-content">
49
  <div class="tab-pane active" id="icwpPillOptions">
50
+ <?php echo $flags[ 'show_standard_options' ] ? $content['options_form'] : ''; ?>
51
  <?php echo $flags[ 'show_alt_content' ] ? $content[ 'alt' ] : ''; ?>
52
  </div>
53
+
54
  <?php if ( $flags[ 'show_content_actions' ] ) : ?>
55
  <div class="tab-pane" id="icwpPillActions">
56
  <?php echo $content[ 'actions' ]; ?>
57
  </div>
58
  <?php endif; ?>
59
+
60
  <?php if ( $flags[ 'show_content_help' ] ) : ?>
61
  <div class="tab-pane" id="icwpPillHelp">
62
  <div class="content-help"><?php echo $content[ 'help' ]; ?></div>
63
  </div>
64
  <?php endif; ?>
 
 
 
65
  </div>
66
 
67
  <?php if ( $flags[ 'show_ads' ] ) : ?>
templates/php/index_header.php CHANGED
@@ -2,7 +2,7 @@
2
  $sBaseDirName = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
3
  include_once( $sBaseDirName.'widgets/icwp_widgets.php' ); ?>
4
  <div class="wrap">
5
- <div class="bootstrap-wpadmin <?php echo isset( $sFeatureSlug ) ? $sFeatureSlug : ''; ?> icwp-options-page">
6
 
7
  <div class="row">
8
  <div class="span11">
@@ -23,7 +23,7 @@ include_once( $sBaseDirName.'widgets/icwp_widgets.php' ); ?>
23
  if ( empty( $sFeatureInclude ) ) {
24
  $sFeatureInclude = 'feature-default';
25
  }
26
- include( $sBaseDirName.$sFeatureInclude );?>
27
  </div>
28
  <div class="span1">
29
  <?php if ( isset( $flags[ 'show_summary' ] ) && $flags[ 'show_summary' ] ) : ?>
2
  $sBaseDirName = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
3
  include_once( $sBaseDirName.'widgets/icwp_widgets.php' ); ?>
4
  <div class="wrap">
5
+ <div class="bootstrap-wpadmin <?php echo $data[ 'mod_slug' ]; ?> icwp-options-page">
6
 
7
  <div class="row">
8
  <div class="span11">
23
  if ( empty( $sFeatureInclude ) ) {
24
  $sFeatureInclude = 'feature-default';
25
  }
26
+ include( $sBaseDirName.$sFeatureInclude ); ?>
27
  </div>
28
  <div class="span1">
29
  <?php if ( isset( $flags[ 'show_summary' ] ) && $flags[ 'show_summary' ] ) : ?>
templates/php/notices/admin-notice-template.php CHANGED
@@ -1,11 +1,23 @@
1
  <?php $sBaseDirName = dirname(__FILE__).DIRECTORY_SEPARATOR; ?>
2
 
3
  <div id="<?php echo $unique_render_id;?>" class="<?php echo $notice_classes; ?> icwp-admin-notice notice is-dismissible notice-<?php echo $icwp_admin_notice_template; ?>">
4
- <?php require_once( $sBaseDirName.$icwp_admin_notice_template.'.php' ); ?>
5
- <div style="clear:both;"></div>
 
 
 
 
 
 
 
 
6
  <?php if ( !empty( $strings['dismiss'] ) ) : ?>
7
- <p class="dismiss-p"><a class="icwp-notice-dismiss" href="#"><?php echo $strings['dismiss']; ?></a></p>
 
 
8
  <?php endif; ?>
 
 
9
  </div>
10
 
11
  <script type="text/javascript">
@@ -18,7 +30,7 @@
18
  function icwp_dismiss_notice() {
19
  var $oContainer = jQuery( '#<?php echo $unique_render_id; ?>' );
20
  var requestData = {
21
- 'action': 'icwp_DismissAdminNotice',
22
  '_ajax_nonce': '<?php echo $icwp_ajax_nonce; ?>',
23
  'hide': '1',
24
  'notice_id': '<?php echo $notice_attributes['notice_id']; ?>'
1
  <?php $sBaseDirName = dirname(__FILE__).DIRECTORY_SEPARATOR; ?>
2
 
3
  <div id="<?php echo $unique_render_id;?>" class="<?php echo $notice_classes; ?> icwp-admin-notice notice is-dismissible notice-<?php echo $icwp_admin_notice_template; ?>">
4
+
5
+ <div class="notice-icon">
6
+ <span class="dashicons dashicons-shield"></span>&nbsp;
7
+ </div>
8
+
9
+ <div class="notice-content">
10
+ <h3 class="notice-title"><?php echo $strings['title'];?></h3>
11
+ <?php require_once( $sBaseDirName.$icwp_admin_notice_template.'.php' ); ?>
12
+ </div>
13
+
14
  <?php if ( !empty( $strings['dismiss'] ) ) : ?>
15
+ <div class="dismiss-p">
16
+ <a class="icwp-notice-dismiss" href="#"><?php echo $strings['dismiss']; ?></a>
17
+ </div>
18
  <?php endif; ?>
19
+
20
+ <div style="clear:both;"></div>
21
  </div>
22
 
23
  <script type="text/javascript">
30
  function icwp_dismiss_notice() {
31
  var $oContainer = jQuery( '#<?php echo $unique_render_id; ?>' );
32
  var requestData = {
33
+ 'action': 'icwp_wpsf_DismissAdminNotice',
34
  '_ajax_nonce': '<?php echo $icwp_ajax_nonce; ?>',
35
  'hide': '1',
36
  'notice_id': '<?php echo $notice_attributes['notice_id']; ?>'
templates/php/notices/allow-tracking.php CHANGED
@@ -1,13 +1,14 @@
1
- <h3><?php echo $strings['help_us']; ?></h3>
2
- <p>
3
- <?php echo $strings['want_to_track']; ?> <?php echo $strings['what_we_collect']; ?>
4
- <br /><?php echo $strings['data_anon']; ?> <?php echo $strings['can_turn_off']; ?>
5
- <a target="_blank" href="<?php echo $hrefs['link_to_see']; ?>"><?php echo $strings['click_to_see']; ?></a>
6
  </p>
7
  <p>
8
- <a href="#" class="button button-primary" id="icwpButtonPluginTrackingAgree">Yes, I want to help by sharing this information!</a>
9
- <a target="_blank" href="<?php echo $hrefs['link_to_moreinfo']; ?>" class="button" id="icwpButtonPluginTrackingMore">Hmm, I'd like to learn more, please.</a>
10
- <a href="#" id="icwpButtonPluginTrackingDisagree">No, I don't want to help!</a>
 
 
 
11
  </p>
12
 
13
  <script type="text/javascript">
@@ -17,22 +18,24 @@
17
  jQuery( document ).on( 'click', 'a#icwpButtonPluginTrackingDisagree', icwp_PluginTrackingDisagree );
18
 
19
  function icwp_PluginTrackingAgree() {
20
- icwp_PluginTrackingAgreement(1);
21
  }
22
 
23
  function icwp_PluginTrackingDisagree() {
24
- icwp_PluginTrackingAgreement(0);
25
  }
26
 
27
  function icwp_PluginTrackingAgreement( $bAgree ) {
28
  var requestData = {
29
  'action': 'icwp_PluginTrackingPermission',
30
- 'agree' : $bAgree,
31
  '_ajax_nonce': '<?php echo $icwp_ajax_nonce; ?>',
32
  'hide': '1',
33
- 'notice_id': '<?php echo $notice_attributes['notice_id']; ?>'
34
  };
35
  jQuery.get( ajaxurl, requestData );
36
- $oContainer.fadeOut( 500, function() { $oContainer.remove(); } );
 
 
37
  }
38
  </script>
1
+ <p><?php echo $strings[ 'want_to_track' ]; ?> <?php echo $strings[ 'what_we_collect' ]; ?></p>
2
+ <p><?php echo $strings[ 'data_anon' ]; ?> <?php echo $strings[ 'can_turn_off' ]; ?>
3
+ <a target="_blank" href="<?php echo $hrefs[ 'link_to_see' ]; ?>"><?php echo $strings[ 'click_to_see' ]; ?></a>
 
 
4
  </p>
5
  <p>
6
+ <a href="#" class="button button-primary" id="icwpButtonPluginTrackingAgree">
7
+ Yes, I'll share this info!</a>
8
+ <a target="_blank" href="<?php echo $hrefs[ 'link_to_moreinfo' ]; ?>" class="button"
9
+ id="icwpButtonPluginTrackingMore">Hmm, I'd like to learn more, please.</a>
10
+ </p><p>
11
+ <a href="#" id="icwpButtonPluginTrackingDisagree" style="float:right">No, I don't want to help!</a>
12
  </p>
13
 
14
  <script type="text/javascript">
18
  jQuery( document ).on( 'click', 'a#icwpButtonPluginTrackingDisagree', icwp_PluginTrackingDisagree );
19
 
20
  function icwp_PluginTrackingAgree() {
21
+ icwp_PluginTrackingAgreement( 1 );
22
  }
23
 
24
  function icwp_PluginTrackingDisagree() {
25
+ icwp_PluginTrackingAgreement( 0 );
26
  }
27
 
28
  function icwp_PluginTrackingAgreement( $bAgree ) {
29
  var requestData = {
30
  'action': 'icwp_PluginTrackingPermission',
31
+ 'agree': $bAgree,
32
  '_ajax_nonce': '<?php echo $icwp_ajax_nonce; ?>',
33
  'hide': '1',
34
+ 'notice_id': '<?php echo $notice_attributes[ 'notice_id' ]; ?>'
35
  };
36
  jQuery.get( ajaxurl, requestData );
37
+ $oContainer.fadeOut( 500, function () {
38
+ $oContainer.remove();
39
+ } );
40
  }
41
  </script>
templates/php/notices/email-verification-sent.php CHANGED
@@ -1,5 +1,6 @@
1
  <p><?php echo $strings['need_you_confirm']; ?>
2
- <br /><?php echo $strings['please_click_link']; ?><?php echo $strings['email_sent_to']; ?>
 
3
  </p>
4
  <p><?php echo $strings['how_resend_email']; ?>
5
  <?php echo $strings['how_turn_off']; ?>
1
  <p><?php echo $strings['need_you_confirm']; ?>
2
+ <br /><?php echo $strings['please_click_link']; ?>
3
+ <?php echo $strings['email_sent_to']; ?>
4
  </p>
5
  <p><?php echo $strings['how_resend_email']; ?>
6
  <?php echo $strings['how_turn_off']; ?>
templates/php/notices/override-forceoff.php CHANGED
@@ -1 +1 @@
1
- <h3><?php echo $strings['message']; ?></h3>
1
+ <p><?php echo $strings[ 'message' ]; ?></p>
templates/php/notices/php54_version_warning.php CHANGED
@@ -1,4 +1,3 @@
1
- <h4 style="margin:10px 0 3px;"><?php echo $strings[ 'your_version' ]; ?></h4>
2
  <p>
3
  <?php echo $strings[ 'not_supported' ]; ?>
4
  <br /><?php echo $strings[ 'ask_host' ]; ?>
 
1
  <p>
2
  <?php echo $strings[ 'not_supported' ]; ?>
3
  <br /><?php echo $strings[ 'ask_host' ]; ?>
templates/php/notices/plugin-update-available.php CHANGED
@@ -1 +1 @@
1
- <p><?php echo $strings['plugin_update_available']; ?> <a href="<?php echo $hrefs['upgrade_link']; ?>"><?php echo $strings['click_update']; ?></a></p>
1
+ <p><a href="<?php echo $hrefs['upgrade_link']; ?>"><?php echo $strings['click_update']; ?></a></p>
templates/php/notices/rate-plugin.php CHANGED
@@ -1,52 +1,10 @@
1
- <div>
2
- <div class="notice-icon">
3
- <span class="dashicons dashicons-heart"></span>&nbsp;
4
- </div>
5
-
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>
13
-
14
- <p>You will help other people find us; you help other people to trust us, and of course, you will help build a more secure
15
- WordPress community. <span style="text-decoration: underline">We simply can't grow without your help</span>.</p>
16
-
17
- <p>
18
- <a href="http://icwp.io/wpsfreview" class="button button-primary" target="_blank">Please, could you leave us a 5&#10030; review on WordPress.org?</a>
19
- If you're having any problems, please leave us a support ticket <strong>instead</strong> and we'll help you out asap!
20
- </p>
21
- </div>
22
- <div class="notice-icon notice-icon-right">
23
- <span class="dashicons dashicons-star-empty"></span>&nbsp;
24
- </div>
25
- </div>
26
-
27
- <style type="text/css">
28
- .notice-icon {
29
- float: left;
30
- height: 74px;
31
- line-height: 176px;
32
- min-width: 85px;
33
- padding: 20px 0;
34
- }
35
- .notice-icon-right {
36
- float: right;
37
- width: 74px;
38
- }
39
- .notice-content {
40
- float: left;
41
- width: 70%;
42
- }
43
- .notice-icon .dashicons {
44
- display: inline-block;
45
- font-size: 75px;
46
- line-height: 70px;
47
- }
48
- .notice-content p a {
49
- text-shadow: none;
50
- font-weight: bold;
51
- }
52
- </style>
1
+ <p>We need your help to spread the word about Shield Security :)</p>
2
+ <p>Talking about us in your WP community, and how effective Shield has been for your site,
3
+ will lend us your invaluable support.</p>
4
+ <p>You'll help others find us; help them to trust us; and of course, you'll help build a more secure
5
+ WordPress community.
6
+ <br/><span style="text-decoration: underline">We simply need your help help to reach others</span>...</p>
7
+ <p>
8
+ <a href="http://icwp.io/wpsfreview" class="button button-primary" target="_blank">
9
+ Please, could you leave us a review on WordPress.org?</a>
10
+ </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/notices/translate-plugin.php CHANGED
@@ -1,4 +1,3 @@
1
- <h5 style="margin:10px 0 3px;">Você não fala Inglês? No hablas Inglés? Heeft u geen Engels spreekt?</h5>
2
  <p>
3
  <?php echo $strings['like_to_help']; ?>
4
  <?php echo $strings['head_over_to']; ?> <a href="<?php echo $hrefs['translate']; ?>" target="_blank"> <strong><?php echo $strings['site_url']; ?></a></strong>
 
1
  <p>
2
  <?php echo $strings['like_to_help']; ?>
3
  <?php echo $strings['head_over_to']; ?> <a href="<?php echo $hrefs['translate']; ?>" target="_blank"> <strong><?php echo $strings['site_url']; ?></a></strong>
templates/php/notices/visitor-whitelisted.php CHANGED
@@ -1,5 +1,5 @@
1
  <p>
2
  <?php echo $strings['notice_message']; ?>
3
- - <strong><?php echo $strings['including_message']; ?></strong>
4
  <br/><?php echo $strings['your_ip']; ?>
5
  </p>
1
  <p>
2
  <?php echo $strings['notice_message']; ?>
3
+ <br/>- <strong><?php echo $strings['including_message']; ?></strong>
4
  <br/><?php echo $strings['your_ip']; ?>
5
  </p>
templates/php/notices/wizard_welcome.php CHANGED
@@ -1,46 +1,6 @@
1
- <div>
2
- <div class="notice-icon">
3
- <span class="dashicons dashicons-shield"></span>&nbsp;
4
- </div>
5
-
6
- <div class="notice-content">
7
- <h3><?php echo $strings['title'];?>!</h3>
8
- <?php if ( $flags['can_wizard'] ) : ?>
9
- <p><strong><a href="<?php echo $hrefs['wizard'];?>" target="_blank">Launch Setup Wizard</a></strong>
10
- - <?php echo $strings['setup'];?></p>
11
- <?php else : ?>
12
- <p><?php echo $strings['no_setup'];?></p>
13
- <?php endif; ?>
14
- </div>
15
- </div>
16
-
17
- <style type="text/css">
18
- .notice-icon {
19
- float: left;
20
- height: 43px;
21
- line-height: 176px;
22
- min-width: 64px;
23
- padding: 10px 0;
24
- }
25
- .notice-icon-right {
26
- float: right;
27
- width: 74px;
28
- }
29
- .notice-content {
30
- }
31
- .notice-content h3 {
32
- margin-top: 5px;
33
- }
34
- .notice-content h3,
35
- .notice-content p {
36
- margin-left: 62px;
37
- }
38
- .notice-icon .dashicons {
39
- display: inline-block;
40
- font-size: 48px;
41
- }
42
- .notice-content p a {
43
- text-shadow: none;
44
- font-weight: bold;
45
- }
46
- </style>
1
+ <?php if ( $flags['can_wizard'] ) : ?>
2
+ <p><strong><a href="<?php echo $hrefs['wizard'];?>" target="_blank">Launch Setup Wizard</a></strong>
3
+ - <?php echo $strings['setup'];?></p>
4
+ <?php else : ?>
5
+ <p><?php echo $strings['no_setup'];?> :(</p>
6
+ <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/page/login_intent.php CHANGED
@@ -81,7 +81,7 @@
81
 
82
  <p class="message bg-<?php echo $data['message_type']; ?>"> <?php echo $strings['message']; ?></p>
83
 
84
- <form action="<?php echo $hrefs['form_action']; ?>" method="post">
85
  <input type="hidden" name="<?php echo $data['login_intent_flag']; ?>" value="1" />
86
  <input type="hidden" name="redirect_to" value="<?php echo $hrefs['redirect_to']; ?>" />
87
 
@@ -112,6 +112,18 @@
112
  </div>
113
  <?php endforeach; ?>
114
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  <div class="form-group submit">
116
  <div class="row">
117
  <div class="col-md-6 pull-right">
81
 
82
  <p class="message bg-<?php echo $data['message_type']; ?>"> <?php echo $strings['message']; ?></p>
83
 
84
+ <form action="<?php echo $hrefs['form_action']; ?>" method="post" class="form-horizontal">
85
  <input type="hidden" name="<?php echo $data['login_intent_flag']; ?>" value="1" />
86
  <input type="hidden" name="redirect_to" value="<?php echo $hrefs['redirect_to']; ?>" />
87
 
112
  </div>
113
  <?php endforeach; ?>
114
 
115
+ <?php if ( $flags['can_skip_mfa']) : ?>
116
+ <div class="form-group">
117
+ <label for="skip_mfa" class="control-label"></label>
118
+ <div class="input-group" style="padding: 5px;">
119
+ <label for="skip_mfa">
120
+ <input type="checkbox" value="Y" name="skip_mfa" id="skip_mfa">
121
+ <?php echo $strings['skip_mfa']; ?>
122
+ </label>
123
+ </div>
124
+ </div>
125
+ <?php endif; ?>
126
+
127
  <div class="form-group submit">
128
  <div class="row">
129
  <div class="col-md-6 pull-right">
templates/php/snippets/admin_access_login.php CHANGED
@@ -1,7 +1,7 @@
1
  <div class="input-holder" id="AdminInputHolder-<?php echo $unique_render_id;?>">
2
  <label>
3
  <?php echo $admin_access_message; ?>:
4
- <input type="password" name="icwp-wpsf-admin_access_key_request" data-nonce="<?php echo $sAjaxNonce; ?>" />
5
  <button type="submit">Go!</button>
6
  </label>
7
  </div>
@@ -31,7 +31,7 @@
31
  'icwp_nonce': '<?php echo $icwp_nonce; ?>',
32
  'icwp_nonce_action': '<?php echo $icwp_nonce_action; ?>',
33
  'icwp_action_module': '<?php echo $icwp_action_module; ?>',
34
- 'icwp_wpsf_admin_access_key_request': $oInput.val()
35
  };
36
 
37
  jQuery.post(ajaxurl, requestData, function( oResponse ) {
1
  <div class="input-holder" id="AdminInputHolder-<?php echo $unique_render_id;?>">
2
  <label>
3
  <?php echo $admin_access_message; ?>:
4
+ <input type="password" name="admin_access_key_request" data-nonce="<?php echo $sAjaxNonce; ?>" />
5
  <button type="submit">Go!</button>
6
  </label>
7
  </div>
31
  'icwp_nonce': '<?php echo $icwp_nonce; ?>',
32
  'icwp_nonce_action': '<?php echo $icwp_nonce_action; ?>',
33
  'icwp_action_module': '<?php echo $icwp_action_module; ?>',
34
+ 'admin_access_key_request': $oInput.val()
35
  };
36
 
37
  jQuery.post(ajaxurl, requestData, function( oResponse ) {
templates/php/snippets/icwp_options_helper.php DELETED
@@ -1,172 +0,0 @@
1
- <?php
2
- /** UNUSED and retained for reference */
3
- die();
4
-
5
- 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__( 'Shield (from %s)' ), $sLinkedIcwp );
10
- if ( !empty($insSection) ) {
11
- echo sprintf( '%s :: %s', $insSection, $sBaseTitle );
12
- }
13
- else {
14
- echo $sBaseTitle;
15
- }
16
- echo '</h2></div>';
17
- }
18
-
19
- function printAllPluginOptionsFormTabs( $aAllOptions, $var_prefix = '', $iOptionsPerRow = 1 ) {
20
- if ( empty($aAllOptions) ) {
21
- return;
22
- }
23
- $iOptionWidth = 8 / $iOptionsPerRow;//8 spans.
24
- ?>
25
-
26
- <ul class="nav nav-tabs">
27
- <?php foreach ( $aAllOptions as $sOptionSection ) : ?>
28
- <li class="<?php echo $sOptionSection['primary'] ? 'active' : '' ?>">
29
- <a href="#<?php echo $sOptionSection['slug'] ?>" data-toggle="tab" ><?php echo $sOptionSection['title_short']; ?></a>
30
- </li>
31
- <?php endforeach; ?>
32
- </ul>
33
-
34
- <div class="tab-content">
35
- <?php foreach ( $aAllOptions as $sOptionSection ) : ?>
36
-
37
- <div class="tab-pane fade <?php echo $sOptionSection['primary'] ? 'active in primary_section' : 'non_primary_section'; ?>"
38
- id="<?php echo $sOptionSection['slug'] ?>">
39
- <div class="row option_section_row <?php echo $sOptionSection['primary'] ? 'primary_section' : 'non_primary_section'; ?>"
40
- id="row-<?php echo $sOptionSection['slug']; ?>">
41
- <div class="span9">
42
- <fieldset>
43
- <legend><?php echo $sOptionSection['title']; ?>
44
- </legend>
45
-
46
- <?php if ( !empty( $sOptionSection['summary'] ) ) : ?>
47
- <div class="row row_section_summary">
48
- <div class="span9">
49
- <?php foreach( $sOptionSection['summary'] as $sItem ) : ?>
50
- <p class="noselect"><?php echo $sItem; ?></p>
51
- <?php endforeach; ?>
52
- </div>
53
- </div>
54
- <?php endif; ?>
55
-
56
-
57
- <?php foreach( $sOptionSection['options'] as $nKeyRow => $aOption ) : ?>
58
- <div class="row row_number_<?php echo $nKeyRow; ?>">
59
- <?php //getPluginOptionSpan( $aOption, $iOptionWidth, $var_prefix ); ?>
60
- </div>
61
- <?php endforeach; ?>
62
- </fieldset>
63
- </div>
64
- </div>
65
- </div>
66
- <?php endforeach; ?>
67
- </div>
68
- <?php
69
- }
70
-
71
- function getPluginOptionSpan( $aOption, $nSpanSize, $var_prefix = '' ) {
72
- $sOptionKey = $aOption['key'];
73
- $sOptionType = $aOption['type']; ?>
74
-
75
- <?php if ( $sOptionKey == 'spacer' ) : ?>
76
- <div class="span8"></div>
77
- <?php else: ?>
78
-
79
- <div class="item_group span8 <?php echo ( $aOption['value'] == 'Y' || $aOption['value'] != $aOption['default'] ) ? 'selected_item_group':''; ?>" id="span_<?php echo $var_prefix.$sOptionKey; ?>">
80
- <div class="control-group">
81
- <label class="control-label" for="<?php echo $var_prefix.$sOptionKey; ?>">
82
- <?php echo $aOption['name']; ?>
83
- <br />
84
- [<a href="<?php echo $aOption['link_info']; ?>" target="_blank"><?php echo $strings['more_info']; ?></a>
85
- <?php if ( !empty( $aOption['link_blog'] ) ) : ?>
86
- | <a href="<?php echo $aOption['link_blog']; ?>" target="_blank"><?php echo $strings['blog']; ?></a>
87
- <?php endif; ?>
88
- ]
89
- </label>
90
- <div class="controls">
91
- <div class="option_section <?php echo ( $aOption['value'] == 'Y' ) ? 'selected_item':''; ?>" id="option_section_<?php echo $var_prefix.$sOptionKey; ?>">
92
- <label>
93
- <?php if ( $sOptionType == 'checkbox' ) : ?>
94
-
95
- <input type="checkbox" name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
96
- value="Y" <?php echo ( $aOption['value'] == 'Y' ) ? 'checked="checked"':''; ?> />
97
- <?php echo $aOption['summary']; ?>
98
-
99
- <?php elseif ( $sOptionType == 'text' ) : ?>
100
-
101
- <p><?php echo $aOption['summary']; ?></p>
102
- <input type="text" name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
103
- value="<?php echo $aOption['value']; ?>" placeholder="<?php echo $aOption['value']; ?>" class="span5" />
104
-
105
- <?php elseif ( $sOptionType == 'password' ) : ?>
106
-
107
- <p><?php echo $aOption['summary']; ?></p>
108
- <input type="password" name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
109
- value="<?php echo $aOption['value']; ?>" placeholder="<?php echo $aOption['value']; ?>" class="span5" />
110
-
111
- <?php elseif ( $sOptionType == 'email' ) : ?>
112
-
113
- <p><?php echo $aOption['summary']; ?></p>
114
- <input type="email" name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
115
- value="<?php echo $aOption['value']; ?>" placeholder="<?php echo $aOption['value']; ?>" class="span5" />
116
-
117
- <?php elseif ( $sOptionType == 'select' ) : ?>
118
-
119
- <p><?php echo $aOption['summary']; ?></p>
120
- <select name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>">
121
- <?php foreach( $aOption['value_options'] as $sOptionValue => $sOptionValueName ) : ?>
122
- <option value="<?php echo $sOptionValue; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>_<?php echo $sOptionValue; ?>"
123
- <?php echo ( $sOptionValue == $aOption['value'] ) ? 'selected="selected"' : ''; ?>
124
- ><?php echo $sOptionValueName; ?></option>
125
- <?php endforeach; ?>
126
- </select>
127
-
128
- <?php elseif ( $sOptionType == 'multiple_select' ) : ?>
129
-
130
- <p><?php echo $aOption['summary']; ?></p>
131
- <select name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
132
- multiple="multiple" size="<?php echo count( $aOption['value_options'] ); ?>">
133
- <?php foreach( $aOption['value_options'] as $sOptionValue => $sOptionValueName ) : ?>
134
- <option value="<?php echo $sOptionValue; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>_<?php echo $sOptionValue; ?>"
135
- <?php echo ( $sOptionValue == $aOption['value'] ) ? 'selected="selected"' : ''; ?>
136
- ><?php echo $sOptionValueName; ?></option>
137
- <?php endforeach; ?>
138
- </select>
139
-
140
- <?php elseif ( $sOptionType == 'array' ) : ?>
141
-
142
- <p><?php echo $aOption['summary']; ?></p>
143
- <textarea name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
144
- placeholder="<?php echo $aOption['value']; ?>" rows="<?php echo $aOption['rows']; ?>"
145
- class="span5" ><?php echo $aOption['value']; ?></textarea>
146
-
147
- <?php elseif ( $sOptionType == 'comma_separated_lists' ) : ?>
148
-
149
- <p><?php echo $aOption['summary']; ?></p>
150
- <textarea name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
151
- placeholder="<?php echo $aOption['value']; ?>" rows="<?php echo $aOption['rows']; ?>"
152
- class="span5" ><?php echo $aOption['value']; ?></textarea>
153
-
154
- <?php elseif ( $sOptionType == 'integer' ) : ?>
155
-
156
- <p><?php echo $aOption['summary']; ?></p>
157
- <input type="text" name="<?php echo $var_prefix.$sOptionKey; ?>" id="<?php echo $var_prefix.$sOptionKey; ?>"
158
- value="<?php echo $aOption['value']; ?>" placeholder="<?php echo $aOption['value']; ?>" class="span5" />
159
-
160
- <?php else : ?>
161
- ERROR: Should never reach this point.
162
- <?php endif; ?>
163
-
164
- </label>
165
- <p class="help-block"><?php echo $aOption['description']; ?></p>
166
- <div style="clear:both"></div>
167
- </div>
168
- </div><!-- controls -->'
169
- </div><!-- control-group -->
170
- </div>
171
- <?php endif;
172
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/php/snippets/module-help-login_protect.php CHANGED
@@ -1,6 +1,7 @@
1
  <h2>What is Login Protection?</h2>
2
  <p>The goal of login protection is to harden-up the WordPress user login process.</p>
3
- <p>It protects again brute force and bots, while also providing added layers of multi-factor authentication.</p>
 
4
  <dl>
5
  <dt>What is multi-factor authentication (MFA)?</dt>
6
  <dd>
1
  <h2>What is Login Protection?</h2>
2
  <p>The goal of login protection is to harden-up the WordPress user login process.</p>
3
+ <p>It protects you against brute force and bots,
4
+ while also providing added layers of multi-factor authentication.</p>
5
  <dl>
6
  <dt>What is multi-factor authentication (MFA)?</dt>
7
  <dd>
templates/php/snippets/options_form.php CHANGED
@@ -1,31 +1,31 @@
1
  <div id="icwpOptionsFormContainer">
2
  <form action="<?php echo $form_action; ?>" method="post" class="form-horizontal icwpOptionsForm">
3
- <?php echo $nonce_field; ?>
4
 
5
  <ul class="nav nav-tabs">
6
- <?php foreach ( $aAllOptions as $sOptionSection ) : ?>
7
- <li class="<?php echo $sOptionSection[ 'primary' ] ? 'active' : '' ?>">
8
- <a href="#<?php echo $sOptionSection[ 'slug' ] ?>" data-toggle="tab">
9
- <?php echo $sOptionSection[ 'title_short' ]; ?>
10
  </a>
11
  </li>
12
  <?php endforeach; ?>
13
  </ul>
14
 
15
  <div class="tab-content">
16
- <?php foreach ( $aAllOptions as $sOptionSection ) : ?>
17
 
18
- <div class="tab-pane fade <?php echo $sOptionSection[ 'primary' ] ? 'active in primary_section' : 'non_primary_section'; ?>"
19
- id="<?php echo $sOptionSection[ 'slug' ] ?>">
20
- <div class="row-fluid option_section_row <?php echo $sOptionSection[ 'primary' ] ? 'primary_section' : 'non_primary_section'; ?>"
21
- id="row-<?php echo $sOptionSection[ 'slug' ]; ?>">
22
  <div class="span12 options-body">
23
  <legend>
24
- <?php echo $sOptionSection[ 'title' ]; ?>
25
- <?php if ( !empty( $sOptionSection[ 'help_video_url' ] ) ) : ?>
26
  <div style="float:right;">
27
 
28
- <a href="<?php echo $sOptionSection[ 'help_video_url' ]; ?>"
29
  class="btn"
30
  data-featherlight-iframe-height="454"
31
  data-featherlight-iframe-width="772"
@@ -36,41 +36,30 @@
36
  <?php endif; ?>
37
  </legend>
38
 
39
- <?php if ( !empty( $sOptionSection[ 'summary' ] ) ) : ?>
40
  <div class="row-fluid row_section_summary">
41
  <div class="span12">
42
- <?php foreach ( $sOptionSection[ 'summary' ] as $sItem ) : ?>
43
  <p class="noselect"><?php echo $sItem; ?></p>
44
  <?php endforeach; ?>
45
  </div>
46
  </div>
47
  <?php endif; ?>
48
 
49
- <?php foreach ( $sOptionSection[ 'options' ] as $nKeyRow => $aOption ) :
50
- $sOptionKey = $aOption[ 'key' ];
51
- $sFullOptionKey = $var_prefix.$sOptionKey;
52
  $mOptValue = $aOption[ 'value' ];
53
- $sOptionType = $aOption[ 'type' ];
54
  $bEnabled = $aOption[ 'enabled' ];
55
  $sDisabledText = $bEnabled ? '' : 'disabled="Disabled"';
56
  ?>
57
  <div class="row-fluid option_row row_number_<?php echo $nKeyRow; ?>">
58
  <div class="item_group span12
59
- <?php echo $bEnabled ? 'enabled' : 'disabled overlay_container' ?>
60
  <?php echo ( $mOptValue == 'Y' || $mOptValue != $aOption[ 'default' ] ) ? 'selected_item_group' : ''; ?>"
61
- id="span_<?php echo $sFullOptionKey; ?>">
62
-
63
- <?php if ( !$bEnabled ) : ?>
64
- <div class="option_overlay">
65
- <div class="overlay_message">
66
- <a href="<?php echo $hrefs[ 'go_pro' ]; ?>" target="_blank">
67
- This is a premium feature</a>
68
- </div>
69
- </div>
70
- <?php endif; ?>
71
 
72
  <div class="control-group">
73
- <label class="control-label" for="<?php echo $sFullOptionKey; ?>">
74
  <span class="optname"><?php echo $aOption[ 'name' ]; ?></span>
75
  <?php if ( !empty( $aOption[ 'link_info' ] ) ) : ?>
76
  <span class="optlinks">
@@ -85,111 +74,121 @@
85
  </span>
86
  <?php endif; ?>
87
  </label>
88
- <div class="controls">
 
 
 
 
 
 
 
 
 
 
89
  <div class="option_section <?php echo ( $mOptValue == 'Y' ) ? 'selected_item' : ''; ?>"
90
- id="option_section_<?php echo $sFullOptionKey; ?>">
91
 
92
- <label class="for<?php echo $sOptionType; ?>">
93
- <?php if ( $sOptionType == 'checkbox' ) : ?>
94
  <span class="switch">
95
  <input type="checkbox"
96
- name="<?php echo $sFullOptionKey; ?>"
97
- id="<?php echo $sFullOptionKey; ?>"
98
  value="Y" <?php echo ( $mOptValue == 'Y' ) ? 'checked="checked"' : ''; ?>
99
  <?php echo $sDisabledText; ?> />
100
- <span class="slider round"></span>
101
  </span>
102
  <span class="summary"><?php echo $aOption[ 'summary' ]; ?></span>
103
 
104
- <?php elseif ( $sOptionType == 'text' ) : ?>
105
 
106
  <p><?php echo $aOption[ 'summary' ]; ?></p>
107
- <textarea name="<?php echo $sFullOptionKey; ?>"
108
- id="<?php echo $sFullOptionKey; ?>"
109
  placeholder="<?php echo $mOptValue; ?>"
110
  rows="<?php echo $aOption[ 'rows' ]; ?>"
111
- class="span5" <?php echo $sDisabledText; ?>><?php echo $mOptValue; ?></textarea>
112
 
113
- <?php elseif ( $sOptionType == 'noneditable_text' ) : ?>
114
 
115
  <p><?php echo $aOption[ 'summary' ]; ?></p>
116
- <input type="text" readonly
117
- value="<?php echo $mOptValue; ?>" class="span5" />
118
 
119
- <?php elseif ( $sOptionType == 'password' ) : ?>
120
 
121
  <p><?php echo $aOption[ 'summary' ]; ?></p>
122
- <input type="password" name="<?php echo $sFullOptionKey; ?>"
123
- id="<?php echo $sFullOptionKey; ?>"
124
  value="<?php echo $mOptValue; ?>"
125
  placeholder="<?php echo $mOptValue; ?>"
126
- class="span5" <?php echo $sDisabledText; ?> />
127
 
128
- <?php elseif ( $sOptionType == 'email' ) : ?>
129
 
130
  <p><?php echo $aOption[ 'summary' ]; ?></p>
131
- <input type="email" name="<?php echo $sFullOptionKey; ?>"
132
- id="<?php echo $sFullOptionKey; ?>"
133
  value="<?php echo $mOptValue; ?>"
134
  placeholder="<?php echo $mOptValue; ?>"
135
- class="span5" <?php echo $sDisabledText; ?> />
136
 
137
- <?php elseif ( $sOptionType == 'select' ) : ?>
138
 
139
  <p><?php echo $aOption[ 'summary' ]; ?></p>
140
- <select name="<?php echo $sFullOptionKey; ?>"
141
- id="<?php echo $sFullOptionKey; ?>"
142
  <?php echo $sDisabledText; ?> >
143
  <?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
144
  <option value="<?php echo $sOptionValue; ?>"
145
- id="<?php echo $sFullOptionKey; ?>_<?php echo $sOptionValue; ?>"
146
  <?php echo ( $sOptionValue == $mOptValue ) ? 'selected="selected"' : ''; ?>
147
  ><?php echo $sOptionValueName; ?></option>
148
  <?php endforeach; ?>
149
  </select>
150
 
151
- <?php elseif ( $sOptionType == 'multiple_select' ) : ?>
152
 
153
  <p><?php echo $aOption[ 'summary' ]; ?></p>
154
- <select name="<?php echo $sFullOptionKey; ?>[]"
155
- id="<?php echo $sFullOptionKey; ?>"
156
  multiple="multiple" multiple
157
  size="<?php echo count( $aOption[ 'value_options' ] ); ?>"
158
  <?php echo $sDisabledText; ?> >
159
  <?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
160
  <option value="<?php echo $sOptionValue; ?>"
161
- id="<?php echo $sFullOptionKey; ?>_<?php echo $sOptionValue; ?>"
162
  <?php echo in_array( $sOptionValue, $mOptValue ) ? 'selected="selected"' : ''; ?>
163
  ><?php echo $sOptionValueName; ?></option>
164
  <?php endforeach; ?>
165
  </select>
166
 
167
- <?php elseif ( $sOptionType == 'array' ) : ?>
168
 
169
  <p><?php echo $aOption[ 'summary' ]; ?></p>
170
- <textarea name="<?php echo $sFullOptionKey; ?>"
171
- id="<?php echo $sFullOptionKey; ?>"
172
  placeholder="<?php echo $mOptValue; ?>"
173
  rows="<?php echo $aOption[ 'rows' ]; ?>"
174
- class="span5" <?php echo $sDisabledText; ?>><?php echo $mOptValue; ?></textarea>
175
 
176
- <?php elseif ( $sOptionType == 'comma_separated_lists' ) : ?>
177
 
178
  <p><?php echo $aOption[ 'summary' ]; ?></p>
179
- <textarea name="<?php echo $sFullOptionKey; ?>"
180
- id="<?php echo $sFullOptionKey; ?>"
181
  placeholder="<?php echo $mOptValue; ?>"
182
  rows="<?php echo $aOption[ 'rows' ]; ?>"
183
- class="span5" <?php echo $sDisabledText; ?> ><?php echo $mOptValue; ?></textarea>
184
 
185
- <?php elseif ( $sOptionType == 'integer' ) : ?>
186
 
187
  <p><?php echo $aOption[ 'summary' ]; ?></p>
188
- <input type="text" name="<?php echo $sFullOptionKey; ?>"
189
- id="<?php echo $sFullOptionKey; ?>"
190
  value="<?php echo $mOptValue; ?>"
191
  placeholder="<?php echo $mOptValue; ?>"
192
- class="span5" <?php echo $sDisabledText; ?> />
193
 
194
  <?php else : ?>
195
  ERROR: Should never reach this point.
@@ -211,10 +210,9 @@
211
  </div>
212
 
213
  <div class="form-actions">
214
- <input type="hidden" name="<?php echo $var_prefix; ?>feature_slug" value="<?php echo $feature_slug; ?>" />
215
- <input type="hidden" name="<?php echo $var_prefix; ?>all_options_input"
216
- value="<?php echo $all_options_input; ?>" />
217
- <input type="hidden" name="<?php echo $var_prefix; ?>plugin_form_submit" value="Y" />
218
  <button type="submit" class="btn btn-success btn-large icwp-form-button"
219
  name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
220
  </div>
@@ -224,14 +222,14 @@
224
  <label class="forcheckbox">
225
  <span class="switch">
226
  <input type="checkbox" name="legend" id="legend" value="Y" checked="checked" disabled="disabled">
227
- <span class="slider round"></span>
228
  </span>
229
  <span class="summary">Option is turned on / enabled</span>
230
  </label>
231
  <label class="forcheckbox">
232
  <span class="switch">
233
  <input type="checkbox" name="legend" id="legend" value="Y" disabled="disabled">
234
- <span class="slider round"></span>
235
  </span>
236
  <span class="summary">Option is turned off / disabled</span>
237
  </label>
1
  <div id="icwpOptionsFormContainer">
2
  <form action="<?php echo $form_action; ?>" method="post" class="form-horizontal icwpOptionsForm">
3
+ <input type="hidden" id="_wpnonce" name="_wpnonce" value="<?php echo $data[ 'form_nonce' ] ?>">
4
 
5
  <ul class="nav nav-tabs">
6
+ <?php foreach ( $data[ 'all_options' ] as $aOptSection ) : ?>
7
+ <li class="<?php echo $aOptSection[ 'primary' ] ? 'active' : '' ?>">
8
+ <a href="#<?php echo $aOptSection[ 'slug' ] ?>" data-toggle="tab">
9
+ <?php echo $aOptSection[ 'title_short' ]; ?>
10
  </a>
11
  </li>
12
  <?php endforeach; ?>
13
  </ul>
14
 
15
  <div class="tab-content">
16
+ <?php foreach ( $data[ 'all_options' ] as $aOptSection ) : ?>
17
 
18
+ <div class="tab-pane fade <?php echo $aOptSection[ 'primary' ] ? 'active in primary_section' : 'non_primary_section'; ?>"
19
+ id="<?php echo $aOptSection[ 'slug' ] ?>">
20
+ <div class="row-fluid option_section_row <?php echo $aOptSection[ 'primary' ] ? 'primary_section' : 'non_primary_section'; ?>"
21
+ id="row-<?php echo $aOptSection[ 'slug' ]; ?>">
22
  <div class="span12 options-body">
23
  <legend>
24
+ <?php echo $aOptSection[ 'title' ]; ?>
25
+ <?php if ( !empty( $aOptSection[ 'help_video_url' ] ) ) : ?>
26
  <div style="float:right;">
27
 
28
+ <a href="<?php echo $aOptSection[ 'help_video_url' ]; ?>"
29
  class="btn"
30
  data-featherlight-iframe-height="454"
31
  data-featherlight-iframe-width="772"
36
  <?php endif; ?>
37
  </legend>
38
 
39
+ <?php if ( !empty( $aOptSection[ 'summary' ] ) ) : ?>
40
  <div class="row-fluid row_section_summary">
41
  <div class="span12">
42
+ <?php foreach ( $aOptSection[ 'summary' ] as $sItem ) : ?>
43
  <p class="noselect"><?php echo $sItem; ?></p>
44
  <?php endforeach; ?>
45
  </div>
46
  </div>
47
  <?php endif; ?>
48
 
49
+ <?php foreach ( $aOptSection[ 'options' ] as $nKeyRow => $aOption ) :
50
+ $sOptKey = $aOption[ 'key' ];
 
51
  $mOptValue = $aOption[ 'value' ];
52
+ $sOptType = $aOption[ 'type' ];
53
  $bEnabled = $aOption[ 'enabled' ];
54
  $sDisabledText = $bEnabled ? '' : 'disabled="Disabled"';
55
  ?>
56
  <div class="row-fluid option_row row_number_<?php echo $nKeyRow; ?>">
57
  <div class="item_group span12
 
58
  <?php echo ( $mOptValue == 'Y' || $mOptValue != $aOption[ 'default' ] ) ? 'selected_item_group' : ''; ?>"
59
+ id="span_<?php echo $sOptKey; ?>">
 
 
 
 
 
 
 
 
 
60
 
61
  <div class="control-group">
62
+ <label class="control-label" for="<?php echo $sOptKey; ?>">
63
  <span class="optname"><?php echo $aOption[ 'name' ]; ?></span>
64
  <?php if ( !empty( $aOption[ 'link_info' ] ) ) : ?>
65
  <span class="optlinks">
74
  </span>
75
  <?php endif; ?>
76
  </label>
77
+ <div class="controls
78
+ <?php echo $bEnabled ? 'enabled' : 'disabled overlay_container' ?>">
79
+
80
+ <?php if ( !$bEnabled ) : ?>
81
+ <div class="option_overlay">
82
+ <div class="overlay_message">
83
+ <a href="<?php echo $hrefs[ 'go_pro' ]; ?>" target="_blank">
84
+ Go Pro!</a>
85
+ </div>
86
+ </div>
87
+ <?php endif; ?>
88
  <div class="option_section <?php echo ( $mOptValue == 'Y' ) ? 'selected_item' : ''; ?>"
89
+ id="option_section_<?php echo $sOptKey; ?>">
90
 
91
+ <label class="for<?php echo $sOptType; ?>">
92
+ <?php if ( $sOptType == 'checkbox' ) : ?>
93
  <span class="switch">
94
  <input type="checkbox"
95
+ name="<?php echo $sOptKey; ?>"
96
+ id="<?php echo $sOptKey; ?>"
97
  value="Y" <?php echo ( $mOptValue == 'Y' ) ? 'checked="checked"' : ''; ?>
98
  <?php echo $sDisabledText; ?> />
99
+ <span class="icwp-slider round"></span>
100
  </span>
101
  <span class="summary"><?php echo $aOption[ 'summary' ]; ?></span>
102
 
103
+ <?php elseif ( $sOptType == 'text' ) : ?>
104
 
105
  <p><?php echo $aOption[ 'summary' ]; ?></p>
106
+ <textarea name="<?php echo $sOptKey; ?>"
107
+ id="<?php echo $sOptKey; ?>"
108
  placeholder="<?php echo $mOptValue; ?>"
109
  rows="<?php echo $aOption[ 'rows' ]; ?>"
110
+ class="span7" <?php echo $sDisabledText; ?>><?php echo $mOptValue; ?></textarea>
111
 
112
+ <?php elseif ( $sOptType == 'noneditable_text' ) : ?>
113
 
114
  <p><?php echo $aOption[ 'summary' ]; ?></p>
115
+ <input type="text" readonly class="span8"
116
+ value="<?php echo $mOptValue; ?>" />
117
 
118
+ <?php elseif ( $sOptType == 'password' ) : ?>
119
 
120
  <p><?php echo $aOption[ 'summary' ]; ?></p>
121
+ <input type="password" name="<?php echo $sOptKey; ?>"
122
+ id="<?php echo $sOptKey; ?>"
123
  value="<?php echo $mOptValue; ?>"
124
  placeholder="<?php echo $mOptValue; ?>"
125
+ class="span7" <?php echo $sDisabledText; ?> />
126
 
127
+ <?php elseif ( $sOptType == 'email' ) : ?>
128
 
129
  <p><?php echo $aOption[ 'summary' ]; ?></p>
130
+ <input type="email" name="<?php echo $sOptKey; ?>"
131
+ id="<?php echo $sOptKey; ?>"
132
  value="<?php echo $mOptValue; ?>"
133
  placeholder="<?php echo $mOptValue; ?>"
134
+ class="span7" <?php echo $sDisabledText; ?> />
135
 
136
+ <?php elseif ( $sOptType == 'select' ) : ?>
137
 
138
  <p><?php echo $aOption[ 'summary' ]; ?></p>
139
+ <select name="<?php echo $sOptKey; ?>"
140
+ id="<?php echo $sOptKey; ?>"
141
  <?php echo $sDisabledText; ?> >
142
  <?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
143
  <option value="<?php echo $sOptionValue; ?>"
144
+ id="<?php echo $sOptKey; ?>_<?php echo $sOptionValue; ?>"
145
  <?php echo ( $sOptionValue == $mOptValue ) ? 'selected="selected"' : ''; ?>
146
  ><?php echo $sOptionValueName; ?></option>
147
  <?php endforeach; ?>
148
  </select>
149
 
150
+ <?php elseif ( $sOptType == 'multiple_select' ) : ?>
151
 
152
  <p><?php echo $aOption[ 'summary' ]; ?></p>
153
+ <select name="<?php echo $sOptKey; ?>[]"
154
+ id="<?php echo $sOptKey; ?>"
155
  multiple="multiple" multiple
156
  size="<?php echo count( $aOption[ 'value_options' ] ); ?>"
157
  <?php echo $sDisabledText; ?> >
158
  <?php foreach ( $aOption[ 'value_options' ] as $sOptionValue => $sOptionValueName ) : ?>
159
  <option value="<?php echo $sOptionValue; ?>"
160
+ id="<?php echo $sOptKey; ?>_<?php echo $sOptionValue; ?>"
161
  <?php echo in_array( $sOptionValue, $mOptValue ) ? 'selected="selected"' : ''; ?>
162
  ><?php echo $sOptionValueName; ?></option>
163
  <?php endforeach; ?>
164
  </select>
165
 
166
+ <?php elseif ( $sOptType == 'array' ) : ?>
167
 
168
  <p><?php echo $aOption[ 'summary' ]; ?></p>
169
+ <textarea name="<?php echo $sOptKey; ?>"
170
+ id="<?php echo $sOptKey; ?>"
171
  placeholder="<?php echo $mOptValue; ?>"
172
  rows="<?php echo $aOption[ 'rows' ]; ?>"
173
+ class="span7" <?php echo $sDisabledText; ?>><?php echo $mOptValue; ?></textarea>
174
 
175
+ <?php elseif ( $sOptType == 'comma_separated_lists' ) : ?>
176
 
177
  <p><?php echo $aOption[ 'summary' ]; ?></p>
178
+ <textarea name="<?php echo $sOptKey; ?>"
179
+ id="<?php echo $sOptKey; ?>"
180
  placeholder="<?php echo $mOptValue; ?>"
181
  rows="<?php echo $aOption[ 'rows' ]; ?>"
182
+ class="span7" <?php echo $sDisabledText; ?> ><?php echo $mOptValue; ?></textarea>
183
 
184
+ <?php elseif ( $sOptType == 'integer' ) : ?>
185
 
186
  <p><?php echo $aOption[ 'summary' ]; ?></p>
187
+ <input type="text" name="<?php echo $sOptKey; ?>"
188
+ id="<?php echo $sOptKey; ?>"
189
  value="<?php echo $mOptValue; ?>"
190
  placeholder="<?php echo $mOptValue; ?>"
191
+ class="span7" <?php echo $sDisabledText; ?> />
192
 
193
  <?php else : ?>
194
  ERROR: Should never reach this point.
210
  </div>
211
 
212
  <div class="form-actions">
213
+ <input type="hidden" name="mod_slug" value="<?php echo $data[ 'mod_slug' ]; ?>" />
214
+ <input type="hidden" name="all_options_input" value="<?php echo $data[ 'all_options_input' ]; ?>" />
215
+ <input type="hidden" name="plugin_form_submit" value="Y" />
 
216
  <button type="submit" class="btn btn-success btn-large icwp-form-button"
217
  name="submit"><?php _wpsf_e( 'Save All Settings' ); ?></button>
218
  </div>
222
  <label class="forcheckbox">
223
  <span class="switch">
224
  <input type="checkbox" name="legend" id="legend" value="Y" checked="checked" disabled="disabled">
225
+ <span class="icwp-slider round"></span>
226
  </span>
227
  <span class="summary">Option is turned on / enabled</span>
228
  </label>
229
  <label class="forcheckbox">
230
  <span class="switch">
231
  <input type="checkbox" name="legend" id="legend" value="Y" disabled="disabled">
232
+ <span class="icwp-slider round"></span>
233
  </span>
234
  <span class="summary">Option is turned off / disabled</span>
235
  </label>
templates/php/subfeature-access_restricted.php CHANGED
@@ -1,28 +1,37 @@
1
  <div class="row">
2
  <div class="span9">
 
 
 
 
 
3
  <div class="well admin_access_restriction_form">
4
- <h3><?php echo $strings['aar_what_should_you_enter']; ?></h3>
5
- <p><?php echo $strings['aar_must_supply_key_first']; ?></p>
6
  <form action="<?php echo $form_action; ?>" method="post" class="form-horizontal">
7
  <div class="control-group">
8
- <label class="control-label" for="<?php echo $var_prefix; ?>admin_access_key_request"><?php echo $strings['aar_enter_access_key']; ?><br></label>
 
 
9
  <div class="controls">
10
  <div class="option_section selected_item active" id="option_section_icwp_wpsf_admin_access_key">
11
  <label>
12
- <input type="password"
13
- name="<?php echo $var_prefix; ?>admin_access_key_request"
14
  value="" autocomplete="off" autofocus />
15
  </label>
16
- <p class="help-block"><?php echo $strings['aar_to_manage_must_enter_key']; ?></p>
17
  </div>
18
  </div>
19
  </div>
20
  <div class="form-actions">
21
  <?php echo $nonce_field; ?>
22
- <input type="hidden" name="<?php echo $var_prefix; ?>plugin_form_submit" value="Y" />
23
- <button type="submit" class="btn btn-success" name="submit"><?php echo $strings['aar_submit_access_key']; ?></button>
 
 
24
  </div>
25
  </form>
26
  </div>
 
27
  </div>
28
  </div>
1
  <div class="row">
2
  <div class="span9">
3
+ <?php if ( !$flags[ 'has_session' ] ) : ?>
4
+ <p>This plugin has been locked-down by a Security Administrator.
5
+ To authenticate with the Security Admin system you need a valid user session
6
+ (which you don't have at the moment). Please log out of WordPress and re-login again.</p>
7
+ <?php else : ?>
8
  <div class="well admin_access_restriction_form">
9
+ <h3><?php echo $strings[ 'aar_what_should_you_enter' ]; ?></h3>
10
+ <p><?php echo $strings[ 'aar_must_supply_key_first' ]; ?></p>
11
  <form action="<?php echo $form_action; ?>" method="post" class="form-horizontal">
12
  <div class="control-group">
13
+ <label class="control-label" for="admin_access_key_request">
14
+ <?php echo $strings[ 'aar_enter_access_key' ]; ?><br>
15
+ </label>
16
  <div class="controls">
17
  <div class="option_section selected_item active" id="option_section_icwp_wpsf_admin_access_key">
18
  <label>
19
+ <input type="password" name="admin_access_key_request"
 
20
  value="" autocomplete="off" autofocus />
21
  </label>
22
+ <p class="help-block"><?php echo $strings[ 'aar_to_manage_must_enter_key' ]; ?></p>
23
  </div>
24
  </div>
25
  </div>
26
  <div class="form-actions">
27
  <?php echo $nonce_field; ?>
28
+ <input type="hidden" name="mod_slug" value="<?php echo $data[ 'mod_slug' ]; ?>" />
29
+ <input type="hidden" name="plugin_form_submit" value="Y" />
30
+ <button type="submit" class="btn btn-success"
31
+ name="submit"><?php echo $strings[ 'aar_submit_access_key' ]; ?></button>
32
  </div>
33
  </form>
34
  </div>
35
+ <?php endif; ?>
36
  </div>
37
  </div>
templates/twig/features/feature-base.twig CHANGED
@@ -1,7 +1,7 @@
1
  {% import "/macros/macros.twig" as icwp_macros %}
2
 
3
  <div class="wrap">
4
- <div class="bootstrap-wpadmin icwp-options-page {{ sFeatureSlug ? sFeatureSlug : '' }}">
5
  {% block options_header %}
6
  <div class="row">
7
  <div class="span12">
1
  {% import "/macros/macros.twig" as icwp_macros %}
2
 
3
  <div class="wrap">
4
+ <div class="bootstrap-wpadmin icwp-options-page {{ data.mod_slug }}">
5
  {% block options_header %}
6
  <div class="row">
7
  <div class="span12">
templates/twig/features/feature-default.twig CHANGED
@@ -4,7 +4,7 @@
4
  <div class="row">
5
  <div class="{{ fShowAds ? 'span10' : 'span12' }}">
6
 
7
- {% if aAllOptions|length %}
8
  <div id="icwp-options-form">
9
  {% include '/snippets/options_form.twig' %}
10
  </div>
4
  <div class="row">
5
  <div class="{{ fShowAds ? 'span10' : 'span12' }}">
6
 
7
+ {% if data.all_options|length %}
8
  <div id="icwp-options-form">
9
  {% include '/snippets/options_form.twig' %}
10
  </div>
templates/twig/features/subfeature-access_restricted.twig CHANGED
@@ -8,11 +8,11 @@
8
  <p>{{ strings.aar_must_supply_key_first }}</p>
9
  <form action="{{ form_action }}" method="post" class="form-horizontal">
10
  <div class="control-group">
11
- <label class="control-label" for="{{ var_prefix }}admin_access_key_request">{{ strings.aar_enter_access_key }}<br></label>
12
  <div class="controls">
13
  <div class="option_section selected_item active" id="option_section_icwp_wpsf_admin_access_key">
14
  <label>
15
- <input type="password" name="{{ var_prefix }}admin_access_key_request" value="" autocomplete="off" />
16
  </label>
17
  <p class="help-block">{{ strings.aar_to_manage_must_enter_key }}</p>
18
  </div>
@@ -20,7 +20,7 @@
20
  </div>
21
  <div class="form-actions">
22
  {{ nonce_field|raw }}
23
- <input type="hidden" name="{{ var_prefix }}plugin_form_submit" value="Y" />
24
  <button type="submit" class="btn btn-success" name="submit">{{ strings.aar_submit_access_key }}</button>
25
  </div>
26
  </form>
8
  <p>{{ strings.aar_must_supply_key_first }}</p>
9
  <form action="{{ form_action }}" method="post" class="form-horizontal">
10
  <div class="control-group">
11
+ <label class="control-label" for="admin_access_key_request">{{ strings.aar_enter_access_key }}<br></label>
12
  <div class="controls">
13
  <div class="option_section selected_item active" id="option_section_icwp_wpsf_admin_access_key">
14
  <label>
15
+ <input type="password" name="admin_access_key_request" value="" autocomplete="off" />
16
  </label>
17
  <p class="help-block">{{ strings.aar_to_manage_must_enter_key }}</p>
18
  </div>
20
  </div>
21
  <div class="form-actions">
22
  {{ nonce_field|raw }}
23
+ <input type="hidden" name="plugin_form_submit" value="Y" />
24
  <button type="submit" class="btn btn-success" name="submit">{{ strings.aar_submit_access_key }}</button>
25
  </div>
26
  </form>
templates/twig/snippets/options_form.twig CHANGED
@@ -2,7 +2,7 @@
2
  {{ nonce_field|raw }}
3
 
4
  <ul class="nav nav-tabs">
5
- {% for sOptionSection in aAllOptions %}
6
  <li class="{{ sOptionSection.primary ? 'active' : '' }}">
7
  <a href="#{{ sOptionSection.slug }}" data-toggle="tab" >{{ sOptionSection.title_short }}</a>
8
  </li>
@@ -10,7 +10,7 @@
10
  </ul>
11
 
12
  <div class="tab-content">
13
- {% for sOptionSection in aAllOptions %}
14
  <div class="tab-pane fade {{ sOptionSection.primary ? 'active in primary_section' : 'non_primary_section' }}"
15
  id="{{ sOptionSection.slug }}">
16
 
@@ -148,8 +148,8 @@
148
  {% endfor %}
149
  </div>
150
  <div class="form-actions">
151
- <input type="hidden" name="{{ var_prefix }}all_options_input" value="{{ all_options_input }}" />
152
- <input type="hidden" name="{{ var_prefix }}plugin_form_submit" value="Y" />
153
  <button type="submit" class="btn btn-success btn-large" name="submit">{{ strings.save_all_settings }}</button>
154
  </div>
155
  </form>
2
  {{ nonce_field|raw }}
3
 
4
  <ul class="nav nav-tabs">
5
+ {% for sOptionSection in data.all_options %}
6
  <li class="{{ sOptionSection.primary ? 'active' : '' }}">
7
  <a href="#{{ sOptionSection.slug }}" data-toggle="tab" >{{ sOptionSection.title_short }}</a>
8
  </li>
10
  </ul>
11
 
12
  <div class="tab-content">
13
+ {% for sOptionSection in data.all_options %}
14
  <div class="tab-pane fade {{ sOptionSection.primary ? 'active in primary_section' : 'non_primary_section' }}"
15
  id="{{ sOptionSection.slug }}">
16
 
148
  {% endfor %}
149
  </div>
150
  <div class="form-actions">
151
+ <input type="hidden" name="all_options_input" value="{{ data.all_options }}" />
152
+ <input type="hidden" name="plugin_form_submit" value="Y" />
153
  <button type="submit" class="btn btn-success btn-large" name="submit">{{ strings.save_all_settings }}</button>
154
  </div>
155
  </form>
templates/twig/snippets/user_sessions.twig CHANGED
@@ -12,7 +12,6 @@
12
  <th>{{ strings.um_last_activity_at }}</th>
13
  <th>{{ strings.um_last_activity_uri }}</th>
14
  <th>{{ strings.um_login_ip }}</th>
15
- <th>{{ strings.um_login_attempts }}</th>
16
  </tr>
17
  {% for aSessionData in aActiveSessions %}
18
  <tr>
@@ -23,7 +22,6 @@
23
  <td>
24
  <a href="http://whois.domaintools.com/{{ aSessionData.ip }}" target="_blank">{{ aSessionData.ip }}</a>
25
  </td>
26
- <td>{{ aSessionData.login_attempts }}</td>
27
  </tr>
28
  {% endfor %}
29
  </table>
12
  <th>{{ strings.um_last_activity_at }}</th>
13
  <th>{{ strings.um_last_activity_uri }}</th>
14
  <th>{{ strings.um_login_ip }}</th>
 
15
  </tr>
16
  {% for aSessionData in aActiveSessions %}
17
  <tr>
22
  <td>
23
  <a href="http://whois.domaintools.com/{{ aSessionData.ip }}" target="_blank">{{ aSessionData.ip }}</a>
24
  </td>
 
25
  </tr>
26
  {% endfor %}
27
  </table>
templates/twig/wizard/slides/importexport/import.twig CHANGED
@@ -53,7 +53,7 @@
53
 
54
  <div class="form-group">
55
  <div class="col-md-offset-4 col-md-8">
56
- <button type="submit" class="btn btn-primary">Submit</button>
57
  </div>
58
  </div>
59
 
53
 
54
  <div class="form-group">
55
  <div class="col-md-offset-4 col-md-8">
56
+ <button type="submit" class="btn btn-primary">Run Import Options</button>
57
  </div>
58
  </div>
59
 
templates/twig/wizard/slides/mfa/authga.twig CHANGED
@@ -32,19 +32,19 @@
32
  <div class="radio">
33
  <label>
34
  <input type="radio" name="enablega" id="enablegaOn" value="Y" checked>
35
- Enable Google Authenticator
36
  </label>
37
  </div>
38
  <div class="radio">
39
  <label>
40
  <input type="radio" name="enablega" id="enablegaOff" value="N">
41
- Disable Google Authenticator
42
  </label>
43
  </div>
44
 
45
  <span id="helpBlock" class="help-block">
46
- When enabled, this will allow any users of this site to configure and
47
- use Google Authenticator on their WordPress accounts.
48
  </span>
49
  </div>
50
  </div>
32
  <div class="radio">
33
  <label>
34
  <input type="radio" name="enablega" id="enablegaOn" value="Y" checked>
35
+ <span>Turn On</span> - Enable Google Authenticator
36
  </label>
37
  </div>
38
  <div class="radio">
39
  <label>
40
  <input type="radio" name="enablega" id="enablegaOff" value="N">
41
+ <span>Turn Off</span> - Disable Google Authenticator
42
  </label>
43
  </div>
44
 
45
  <span id="helpBlock" class="help-block">
46
+ When enabled, this will allow any user of this site to configure and
47
+ use Google Authenticator on their own WordPress account.
48
  </span>
49
  </div>
50
  </div>
templates/twig/wizard/slides/mfa/multiselect.twig CHANGED
@@ -24,13 +24,13 @@
24
  <div class="radio">
25
  <label>
26
  <input type="radio" name="multiselect" id="multiselectOn" value="Y" checked>
27
- Turn On Multi-Factor (all factors required)
28
  </label>
29
  </div>
30
  <div class="radio">
31
  <label>
32
  <input type="radio" name="multiselect" id="multiselectOff" value="N">
33
- Turn Off Multi-Factor (only 1 extra factor)
34
  </label>
35
  </div>
36
 
24
  <div class="radio">
25
  <label>
26
  <input type="radio" name="multiselect" id="multiselectOn" value="Y" checked>
27
+ <span>Turn On Multi-Factor</span> - all factors required
28
  </label>
29
  </div>
30
  <div class="radio">
31
  <label>
32
  <input type="radio" name="multiselect" id="multiselectOff" value="N">
33
+ <span>Turn Off Multi-Factor</span> - only 1 extra factor required
34
  </label>
35
  </div>
36
 
templates/twig/wizard/slides/ufc/config.twig CHANGED
@@ -15,19 +15,20 @@
15
  <div class="radio">
16
  <label>
17
  <input type="radio" name="enable_scan" id="EnableScanReport" value="enabled_report_only">
18
- Send email report only
19
  </label>
20
  </div>
21
  <div class="radio">
22
  <label>
23
  <input type="radio" name="enable_scan" id="EnableScanDelete" value="enabled_delete_only">
24
- Automatically delete discovered files
25
  </label>
26
  </div>
27
  <div class="radio">
28
  <label>
29
  <input type="radio" name="enable_scan" id="EnableScanDeleteReport" value="enabled_delete_report">
30
- Automatically delete discovered files and send email report<br/>(<em>recommended</em>)
 
31
  </label>
32
  </div>
33
  </div>
15
  <div class="radio">
16
  <label>
17
  <input type="radio" name="enable_scan" id="EnableScanReport" value="enabled_report_only">
18
+ <span>Report Only</span> - send email reports only
19
  </label>
20
  </div>
21
  <div class="radio">
22
  <label>
23
  <input type="radio" name="enable_scan" id="EnableScanDelete" value="enabled_delete_only">
24
+ <span>Delete Only</span> - automatically delete discovered files; don't send email report.
25
  </label>
26
  </div>
27
  <div class="radio">
28
  <label>
29
  <input type="radio" name="enable_scan" id="EnableScanDeleteReport" value="enabled_delete_report">
30
+ <span>Delete &amp; Report</span> - automatically delete discovered files; send email report
31
+ <br/>(<em>recommended</em>)
32
  </label>
33
  </div>
34
  </div>
templates/twig/wizard/slides/wcf/config.twig CHANGED
@@ -15,13 +15,14 @@
15
  <div class="radio">
16
  <label>
17
  <input type="radio" name="enable_scan" id="EnableScanReport" value="enabled_report_only">
18
- Scan WordPress Core files and send email report
19
  </label>
20
  </div>
21
  <div class="radio">
22
  <label>
23
  <input type="radio" name="enable_scan" id="EnableScanDeleteReport" value="enabled_restore_report">
24
- Scan and automatically restore any discovered files and send email report<br/>(<em>recommended</em>)
 
25
  </label>
26
  </div>
27
  </div>
15
  <div class="radio">
16
  <label>
17
  <input type="radio" name="enable_scan" id="EnableScanReport" value="enabled_report_only">
18
+ <span>Report Only</span> - send email reports only.
19
  </label>
20
  </div>
21
  <div class="radio">
22
  <label>
23
  <input type="radio" name="enable_scan" id="EnableScanDeleteReport" value="enabled_restore_report">
24
+ <span>Repair &amp; Report</span> - automatically restore any discovered files; send email report
25
+ <br/>(<em>recommended</em>)
26
  </label>
27
  </div>
28
  </div>
templates/twig/wizard/slides/welcome/admin_access_restriction.twig CHANGED
@@ -35,7 +35,7 @@
35
  </div>
36
  <div class="form-group">
37
  <div class="col-md-offset-4 col-md-8">
38
- <button type="submit" class="btn btn-primary">Submit</button>
39
  </div>
40
  </div>
41
  </form>
35
  </div>
36
  <div class="form-group">
37
  <div class="col-md-offset-4 col-md-8">
38
+ <button type="submit" class="btn btn-primary">Turn On Security Admin</button>
39
  </div>
40
  </div>
41
  </form>
templates/twig/wizard/slides/welcome/audit_trail.twig CHANGED
@@ -3,12 +3,14 @@
3
  {% block slide_body %}
4
 
5
  <h3>Security Audit Trail</h3>
6
- <p>One of the most difficult things to do is fix a problem where you don't know the cause.</p>
7
- <p>This is one of the problems that the Audit Trail feature will help you solve.</p>
8
- <p>It provides a log of major events and actions taken on your WordPress site. It lets you see who's
 
 
 
9
  doing what, and when, and from where (IP address).</p>
10
- <p>Note: The Audit Trail is limited to 50 entries. You can increase this limit at any time when you support
11
- development of the plugin by purchasing a Pro license.</p>
12
 
13
  <h4>Turn On/Off The Audit Trail Feature</h4>
14
  <form class="form-horizontal icwp-wizard-form">
@@ -18,21 +20,21 @@
18
  <div class="col-md-8">
19
  <div class="radio">
20
  <label>
21
- <input type="radio" name="AuditTrailOption" id="AuditTrailOn" value="Y" checked>
22
- Turn On - Log important site events
23
  </label>
24
  </div>
25
  <div class="radio">
26
  <label>
27
  <input type="radio" name="AuditTrailOption" id="AuditTrailOff" value="N">
28
- Turn Off - Do not log important site events
29
  </label>
30
  </div>
31
  </div>
32
  </div>
33
  <div class="form-group">
34
  <div class="col-md-offset-4 col-md-8">
35
- <button type="submit" class="btn btn-primary">Submit</button>
36
  </div>
37
  </div>
38
  </form>
3
  {% block slide_body %}
4
 
5
  <h3>Security Audit Trail</h3>
6
+ <h4>Quick Summary:</h4>
7
+ <p>Turn on the Audit Trail below so you can track user activities on your site and troubleshoot problems more easily.</p>
8
+ <h4>The Details:</h4>
9
+ <p>One of the most difficult things to do is fix a problem where you don't know the cause.
10
+ This is one of the problems that the Audit Trail feature will help you solve.</p>
11
+ <p>It provides a log of major events on your WordPress site. It lets you see who's
12
  doing what, and when, and from where (IP address).</p>
13
+ <p>Note: The Audit Trail is limited to 50 entries. You can increase this limit at any time by purchasing a Pro license.</p>
 
14
 
15
  <h4>Turn On/Off The Audit Trail Feature</h4>
16
  <form class="form-horizontal icwp-wizard-form">
20
  <div class="col-md-8">
21
  <div class="radio">
22
  <label>
23
+ <input type="radio" name="AuditTrailOption" id="AuditTrailOn" value="Y">
24
+ <span>Turn On</span> - Log important site events
25
  </label>
26
  </div>
27
  <div class="radio">
28
  <label>
29
  <input type="radio" name="AuditTrailOption" id="AuditTrailOff" value="N">
30
+ <span>Turn Off</span> - Do not log important site events
31
  </label>
32
  </div>
33
  </div>
34
  </div>
35
  <div class="form-group">
36
  <div class="col-md-offset-4 col-md-8">
37
+ <button type="submit" class="btn btn-primary">Update The Audit Trail Setting</button>
38
  </div>
39
  </div>
40
  </form>
templates/twig/wizard/slides/welcome/comments_filter.twig CHANGED
@@ -3,16 +3,18 @@
3
  {% block slide_body %}
4
 
5
  <h3>Comment SPAM</h3>
 
 
 
6
  <p>99%+ of comments spam is by automated bots. You get some human SPAM too, of course.</p>
7
- <p>Shield Security offers a couple of highly effective (read: 100%) techniques to block bot spam, using a
8
- simple technique. Also, and unlike Akismet, we never send your private comment data to 3rd parties for
9
- processing. We keep it all in-house - i.e. it stays on your own website.
10
  </p>
11
  <p>We also offer Google reCAPTCHA for comments, but you'll need to setup some API keys for this first, so we'll
12
  leave you to do that later.</p>
13
- <p>And, for those SPAM comments posted by real humans, we have an option in there too. But again, to get
14
- you going, we'll leave you to set that up later on if you wish.</p>
15
- <p>For now, if you want to block comment SPAM, enable it below.</p>
16
 
17
  <h4>Turn On/Off Comment SPAM Protection Feature</h4>
18
  <form class="form-horizontal icwp-wizard-form">
@@ -22,21 +24,21 @@
22
  <div class="col-md-8">
23
  <div class="radio">
24
  <label>
25
- <input type="radio" name="CommentsFilterOption" id="AuditTrailOn" value="Y" checked>
26
- Turn On - Block comments SPAM by bots
27
  </label>
28
  </div>
29
  <div class="radio">
30
  <label>
31
  <input type="radio" name="CommentsFilterOption" id="AuditTrailOff" value="N">
32
- Turn Off - Do not block comments SPAM by bots
33
  </label>
34
  </div>
35
  </div>
36
  </div>
37
  <div class="form-group">
38
  <div class="col-md-offset-4 col-md-8">
39
- <button type="submit" class="btn btn-primary">Submit</button>
40
  </div>
41
  </div>
42
  </form>
3
  {% block slide_body %}
4
 
5
  <h3>Comment SPAM</h3>
6
+ <h4>Quick Summary:</h4>
7
+ <p>Shield can block 100% of automated Comment SPAM sent by "bots". You can turn it on below.</p>
8
+ <h4>The Details:</h4>
9
  <p>99%+ of comments spam is by automated bots. You get some human SPAM too, of course.</p>
10
+ <p>Shield Security offers a couple of highly effective techniques to block bot spam.
11
+ Also, and unlike Akismet, we never send your private comment data to 3rd parties for
12
+ processing. You keep it all in-house - i.e. it stays on your own website.
13
  </p>
14
  <p>We also offer Google reCAPTCHA for comments, but you'll need to setup some API keys for this first, so we'll
15
  leave you to do that later.</p>
16
+ <p>There's also an option to protect against Human SPAMmers. But again, to get
17
+ you going, we'll leave you to set that up later if you wish.</p>
 
18
 
19
  <h4>Turn On/Off Comment SPAM Protection Feature</h4>
20
  <form class="form-horizontal icwp-wizard-form">
24
  <div class="col-md-8">
25
  <div class="radio">
26
  <label>
27
+ <input type="radio" name="CommentsFilterOption" id="AuditTrailOn" value="Y">
28
+ <span>Turn On</span> - Block comments SPAM by bots
29
  </label>
30
  </div>
31
  <div class="radio">
32
  <label>
33
  <input type="radio" name="CommentsFilterOption" id="AuditTrailOff" value="N">
34
+ <span>Turn Off</span> - Do not block comments SPAM by bots
35
  </label>
36
  </div>
37
  </div>
38
  </div>
39
  <div class="form-group">
40
  <div class="col-md-offset-4 col-md-8">
41
+ <button type="submit" class="btn btn-primary">Update The Comment SPAM Setting</button>
42
  </div>
43
  </div>
44
  </form>
templates/twig/wizard/slides/welcome/ip_detect.twig CHANGED
@@ -3,6 +3,9 @@
3
  {% block slide_body %}
4
 
5
  <h3>IP Detection</h3>
 
 
 
6
  <p>All websites and webhosts are configured differently. This makes certain things a bit tricky
7
  to automate.</p>
8
  <p>An important example of this is detecting the correct IP address of a website visitor.</p>
3
  {% block slide_body %}
4
 
5
  <h3>IP Detection</h3>
6
+ <h4>Quick Summary:</h4>
7
+ <p>Use the steps below to enter your IP address to help Shield detect visitor IP addresses more accurately on your web hosting.</p>
8
+ <h4>The Details:</h4>
9
  <p>All websites and webhosts are configured differently. This makes certain things a bit tricky
10
  to automate.</p>
11
  <p>An important example of this is detecting the correct IP address of a website visitor.</p>
templates/twig/wizard/slides/welcome/ips.twig CHANGED
@@ -3,24 +3,20 @@
3
  {% block slide_body %}
4
 
5
  <h3>Automatic IP Blacklist</h3>
6
- <p>Many security plugins offer the option of blacklisting IP addresses.</p>
7
- <p>But the big secret they're not telling you is that this is complete waste of your time.</p>
 
 
 
8
  <p>Can you think of anything you'd rather be doing, than getting 100s of email notifications and then
9
- having to go in and add IP addresses to some blacklist?</p>
10
- <p>We all have friends and family we'd rather be seeing, important work to be done, and bills to pay.
11
- Life is waaay too short to be manually blocking IPs on every site we manage.</p>
12
- <p>That's why we built our <strong>F</strong>ully <strong>A</strong>utomatic <strong>B</strong>lack
13
- <strong>L</strong>ist <strong>E</strong>ngine (FABLE).</p>
14
- <p>FABLE will track naughty behaviour, and if the same visitor/bot does one-too-many naughty things,
15
- we block that IP. Simples. But not permanently, because that would make our IP list explode, and slow
16
- down our website like it's running Wordfence. ;)</p>
17
- <p>And nobody wants that. So FABLE keeps your IP blacklist nice and lean.</p>
18
 
19
- <p>By default, nefarious visitors are blocked for 1 minute, after 10 naughty requests (aka 'transgressions').</p>
20
- <p>You can change these settings in the IP Manager, but for now, let's just turn it on. Also,
21
- if you turned on the Audit Trail in the previous step, you can use this to monitor IP blacklisting.</p>
22
 
23
- <h4>Turn On/Off FABLE - Automatic Blacklist Engine</h4>
24
  <form class="form-horizontal icwp-wizard-form">
25
  <input name="wizard-step" value="ips" type="hidden" />
26
  <div class="form-group">
@@ -28,14 +24,14 @@ if you turned on the Audit Trail in the previous step, you can use this to monit
28
  <div class="col-md-8">
29
  <div class="radio">
30
  <label>
31
- <input type="radio" name="IpManagerOption" id="IpManagerOptionOn" value="Y" checked>
32
- Turn On - Automatically block bad visitors and bots
33
  </label>
34
  </div>
35
  <div class="radio">
36
  <label>
37
  <input type="radio" name="IpManagerOption" id="IpManagerOptionOff" value="N">
38
- Turn Off - Don't use FABLE to protect against bad visitors and bots
39
  </label>
40
  </div>
41
  </div>
3
  {% block slide_body %}
4
 
5
  <h3>Automatic IP Blacklist</h3>
6
+ <h4>Quick Summary:</h4>
7
+ <p>Turn on the IP Manager below so Shield can automatically limit login attempts and block automated attacks.</p>
8
+ <h4>The Details:</h4>
9
+ <p>Many security plugins offer the option of blacklisting IP addresses. But the big secret they're not telling you is
10
+ that this is complete waste of your time.</p>
11
  <p>Can you think of anything you'd rather be doing, than getting 100s of email notifications and then
12
+ having to add IP addresses to some blacklist?</p>
13
+ <p>The automatic IP Manager will track bad behaviour, and automatically block repeat offenders.
14
+ But not permanently, because that would make your IP list explode, slowing down your site for normal visitors.</p>
15
+ <p>And nobody wants that.</p>
 
 
 
 
 
16
 
17
+ <p>By default, bad visitors are blocked for 1 minute after 10 bad requests.</p>
 
 
18
 
19
+ <h4>Turn On/Off Automatic Blacklist Engine</h4>
20
  <form class="form-horizontal icwp-wizard-form">
21
  <input name="wizard-step" value="ips" type="hidden" />
22
  <div class="form-group">
24
  <div class="col-md-8">
25
  <div class="radio">
26
  <label>
27
+ <input type="radio" name="IpManagerOption" id="IpManagerOptionOn" value="Y">
28
+ <span>Turn On</span> - Automatically block bad visitors and bots
29
  </label>
30
  </div>
31
  <div class="radio">
32
  <label>
33
  <input type="radio" name="IpManagerOption" id="IpManagerOptionOff" value="N">
34
+ <span>Turn Off</span> - Don't use black lists to protect against bad visitors and bots
35
  </label>
36
  </div>
37
  </div>
templates/twig/wizard/slides/welcome/login_protect.twig CHANGED
@@ -3,15 +3,15 @@
3
  {% block slide_body %}
4
 
5
  <h3>Brute Force Login Protection</h3>
6
- <p>The truth is that WordPress is not best suited to protect against <em>Brute Force</em> login attacks.</p>
7
- <p>That said though, we can definitely make it much harder for those bots.</p>
8
- <p>We also offer you the option to use Google reCAPTCHA for login bot protection, but you'll need to
9
- setup some API keys for this first, so we'll leave you to do that later.</p>
10
- <p>Instead, you can turn on our Login Protection system which is highly effective and uses a similar
11
  technique to that for Comments SPAM blocking.</p>
12
- <p>This option will add a simple checkbox to your login form that users have to check. It's easy, and super
13
- simple to do - no annoying reCAPTCHAs. A checkbox might not sound like much, but it's no
14
- ordinary checkbox ;)</p>
 
15
 
16
  <h4>Turn On/Off Login Protection</h4>
17
  <form class="form-horizontal icwp-wizard-form">
@@ -21,14 +21,14 @@
21
  <div class="col-md-8">
22
  <div class="radio">
23
  <label>
24
- <input type="radio" name="LoginProtectOption" id="LoginProtectOptionOn" value="Y" checked>
25
- Turn On - Protect my WordPress login from automated bots
26
  </label>
27
  </div>
28
  <div class="radio">
29
  <label>
30
  <input type="radio" name="CommentsFilterOption" id="LoginProtectOptionOff" value="N">
31
- Turn Off - Do not protect my WordPress login from automated bots
32
  </label>
33
  </div>
34
  </div>
3
  {% block slide_body %}
4
 
5
  <h3>Brute Force Login Protection</h3>
6
+ <h4>Quick Summary:</h4>
7
+ <p>Shield can protect your login form against automated login attacks and bots.</p>
8
+ <h4>The Details:</h4>
9
+ <p>You can turn on Shield Login Protection which is highly effective and uses a similar
 
10
  technique to that for Comments SPAM blocking.</p>
11
+ <p>Shield also offers you the option to use Google reCAPTCHA for login bot protection, but you'll need to
12
+ setup some API keys for this first, so we'll leave you to do that later.</p>
13
+ <p>This option will add a <em>special anti-bot</em> checkbox to your login form that users have to check.
14
+ It's easy, and super simple to use - no annoying CAPTCHAs.</p>
15
 
16
  <h4>Turn On/Off Login Protection</h4>
17
  <form class="form-horizontal icwp-wizard-form">
21
  <div class="col-md-8">
22
  <div class="radio">
23
  <label>
24
+ <input type="radio" name="LoginProtectOption" id="LoginProtectOptionOn" value="Y">
25
+ <span>Turn On</span> - Protect my WordPress login from automated bots
26
  </label>
27
  </div>
28
  <div class="radio">
29
  <label>
30
  <input type="radio" name="CommentsFilterOption" id="LoginProtectOptionOff" value="N">
31
+ <span>Turn Off</span> - Do not protect my WordPress login from automated bots
32
  </label>
33
  </div>
34
  </div>
templates/twig/wizard/slides/welcome/optin.twig CHANGED
@@ -49,21 +49,21 @@
49
  <h4>#2 Anonymous Usage Data</h4>
50
  <p>Helps us determine what features are being used, where we need to do more work and how effective Shield is being.</p>
51
  <form class="form-horizontal icwp-wizard-form">
52
- <input name="wizard-step" value="optin" type="hidden" />
53
 
54
  <div class="form-group">
55
  <label class="col-md-4 control-label" for="AnonymousOption">Anonymous Usage</label>
56
  <div class="col-md-8">
57
  <div class="radio">
58
  <label>
59
- <input type="radio" name="AnonymousOption" id="AnonymousOptionOn" value="Y" checked>
60
- Turn On - allow <em>completely anonymous</em> usage data to be collected
61
  </label>
62
  </div>
63
  <div class="radio">
64
  <label>
65
  <input type="radio" name="AnonymousOption" id="AnonymousOptionOff" value="N">
66
- Turn Off - do not contribute anonymous usage data
67
  </label>
68
  </div>
69
  </div>
@@ -71,7 +71,7 @@
71
 
72
  <div class="form-group">
73
  <div class="col-md-offset-4 col-md-8">
74
- <button type="submit" class="btn btn-primary">Submit</button>
75
  </div>
76
  </div>
77
 
@@ -83,21 +83,21 @@
83
  <p>You can demonstrate to your visitors and customers that you're taking security seriously
84
  by displaying a little 'Shield' badge on the bottom corner of your website.</p>
85
  <form class="form-horizontal icwp-wizard-form">
86
- <input name="wizard-step" value="optin" type="hidden" />
87
 
88
  <div class="form-group">
89
  <label class="col-md-4 control-label" for="BadgeOption">Anonymous Usage</label>
90
  <div class="col-md-8">
91
  <div class="radio">
92
  <label>
93
- <input type="radio" name="BadgeOption" id="BadgeOptionOn" value="Y" checked>
94
- Turn On - display the Shield Security plugin badge on my site
95
  </label>
96
  </div>
97
  <div class="radio">
98
  <label>
99
  <input type="radio" name="BadgeOption" id="BadgeOptionOff" value="N">
100
- Turn Off - do not display the badge on my site
101
  </label>
102
  </div>
103
  </div>
@@ -105,7 +105,7 @@
105
 
106
  <div class="form-group">
107
  <div class="col-md-offset-4 col-md-8">
108
- <button type="submit" class="btn btn-primary">Submit</button>
109
  </div>
110
  </div>
111
 
49
  <h4>#2 Anonymous Usage Data</h4>
50
  <p>Helps us determine what features are being used, where we need to do more work and how effective Shield is being.</p>
51
  <form class="form-horizontal icwp-wizard-form">
52
+ <input name="wizard-step" value="optin_usage" type="hidden" />
53
 
54
  <div class="form-group">
55
  <label class="col-md-4 control-label" for="AnonymousOption">Anonymous Usage</label>
56
  <div class="col-md-8">
57
  <div class="radio">
58
  <label>
59
+ <input type="radio" name="AnonymousOption" id="AnonymousOptionOn" value="Y">
60
+ <span>Turn On</span> - allow <em>completely anonymous</em> usage data to be collected
61
  </label>
62
  </div>
63
  <div class="radio">
64
  <label>
65
  <input type="radio" name="AnonymousOption" id="AnonymousOptionOff" value="N">
66
+ <span>Turn Off</span> - do not contribute anonymous usage data
67
  </label>
68
  </div>
69
  </div>
71
 
72
  <div class="form-group">
73
  <div class="col-md-offset-4 col-md-8">
74
+ <button type="submit" class="btn btn-primary">Set Anonymous Data Usage</button>
75
  </div>
76
  </div>
77
 
83
  <p>You can demonstrate to your visitors and customers that you're taking security seriously
84
  by displaying a little 'Shield' badge on the bottom corner of your website.</p>
85
  <form class="form-horizontal icwp-wizard-form">
86
+ <input name="wizard-step" value="optin_badge" type="hidden" />
87
 
88
  <div class="form-group">
89
  <label class="col-md-4 control-label" for="BadgeOption">Anonymous Usage</label>
90
  <div class="col-md-8">
91
  <div class="radio">
92
  <label>
93
+ <input type="radio" name="BadgeOption" id="BadgeOptionOn" value="Y">
94
+ <span>Turn On</span> - display the Shield Security plugin badge on my site
95
  </label>
96
  </div>
97
  <div class="radio">
98
  <label>
99
  <input type="radio" name="BadgeOption" id="BadgeOptionOff" value="N">
100
+ <span>Turn Off</span> - do not display the badge on my site
101
  </label>
102
  </div>
103
  </div>
105
 
106
  <div class="form-group">
107
  <div class="col-md-offset-4 col-md-8">
108
+ <button type="submit" class="btn btn-primary">Set Plugin Badge Usage</button>
109
  </div>
110
  </div>
111