Shield Security for WordPress - Version 4.0.0

Version Description

  • ADDED: New Feature - Audit Trail
  • ADDED: Audit Trail options include: Plugins, Themes, Email, WordPress Core, Posts/Pages, WordPress Simple Firewall
  • FIXED: Full and proper cleanup of plugin options, crons, and databases upon deactivation.
  • REMOVED: Firewall Log. This is no longer an option and is instead integrated into the "WordPress Simple Firewall" Audit Trail.
Download this release

Release Info

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

Code changes from version 3.5.5 to 4.0.0

Files changed (49) hide show
  1. icwp-plugin-controller.php +445 -91
  2. icwp-wpsf-main.php +0 -426
  3. icwp-wpsf.php +201 -142
  4. plugin-spec.txt +43 -0
  5. readme.txt +13 -5
  6. resources/css/plugin.css +5 -1
  7. src/config/feature-admin_access_restriction.txt +1 -0
  8. src/config/feature-audit_trail.txt +13 -1
  9. src/config/feature-firewall.txt +7 -7
  10. src/config/feature-logging.txt +0 -27
  11. src/config/feature-plugin.txt +3 -5
  12. src/icwp-options-vo.php +17 -0
  13. src/icwp-optionshandler-admin_access_restriction.php +10 -13
  14. src/icwp-optionshandler-audit_trail.php +29 -13
  15. src/icwp-optionshandler-autoupdates.php +1 -7
  16. src/icwp-optionshandler-base.php +83 -82
  17. src/icwp-optionshandler-comments_filter.php +1 -7
  18. src/icwp-optionshandler-email.php +8 -10
  19. src/icwp-optionshandler-firewall.php +1 -14
  20. src/icwp-optionshandler-lockdown.php +7 -16
  21. src/icwp-optionshandler-logging.php +0 -105
  22. src/icwp-optionshandler-login_protect.php +1 -7
  23. src/icwp-optionshandler-plugin.php +20 -17
  24. src/icwp-optionshandler-privacy_protect.php +1 -13
  25. src/icwp-optionshandler-user_management.php +3 -15
  26. src/icwp-processor-admin_access_restriction.php +53 -37
  27. src/icwp-processor-audit_trail.php +69 -21
  28. src/icwp-processor-audit_trail_emails.php +72 -0
  29. src/icwp-processor-audit_trail_plugins.php +23 -2
  30. src/icwp-processor-audit_trail_themes.php +23 -2
  31. src/icwp-processor-audit_trail_users.php +3 -4
  32. src/icwp-processor-audit_trail_wpsf.php +48 -0
  33. src/icwp-processor-base.php +84 -83
  34. src/icwp-processor-basedb.php +17 -68
  35. src/icwp-processor-comments_filter.php +0 -1
  36. src/icwp-processor-commentsfilter_antibotspam.php +0 -1
  37. src/icwp-processor-email.php +7 -13
  38. src/icwp-processor-firewall.php +546 -531
  39. src/icwp-processor-logging.php +0 -122
  40. src/icwp-processor-login_protect.php +4 -25
  41. src/icwp-processor-loginprotect_gasp.php +5 -13
  42. src/icwp-processor-loginprotect_twofactorauth.php +426 -434
  43. src/icwp-processor-loginprotect_yubikey.php +121 -126
  44. src/icwp-processor-plugin.php +5 -5
  45. src/icwp-processor-privacyprotect.php +112 -113
  46. src/icwp-processor-user_management.php +7 -26
  47. src/icwp-pure-base.php +0 -376
  48. views/icwp-wpsf-audit_trail_viewer_index.php +17 -20
  49. views/icwp-wpsf-state_summary.php +4 -1
icwp-plugin-controller.php CHANGED
@@ -19,28 +19,27 @@
19
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20
  */
21
 
 
 
 
 
22
  require_once(dirname(__FILE__).ICWP_DS.'src'.ICWP_DS.'icwp-foundation.php');
23
  class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
24
 
25
  /**
26
- * @var ICWP_WPSF_Spec
27
- */
28
- private static $oPluginSpec;
29
-
30
- /**
31
- * @const string
32
  */
33
- const ViewDir = 'views';
34
 
35
  /**
36
- * @const string
37
  */
38
- const SrcDir = 'src';
39
 
40
  /**
41
- * @var string
42
  */
43
- protected static $fLoggingEnabled;
44
 
45
  /**
46
  * @var string
@@ -53,32 +52,61 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
53
  private $sPluginBaseFile;
54
 
55
  /**
56
- * @var ICWP_WPSF_Plugin_Controller
57
- */
58
- public static $oInstance;
59
-
60
- /**
61
- * @param ICWP_WPSF_Spec $oPluginSpec
62
  * @return ICWP_WPSF_Plugin_Controller
63
  */
64
- public static function GetInstance( $oPluginSpec ) {
65
  if ( !isset( self::$oInstance ) ) {
66
- self::$oInstance = new self( $oPluginSpec );
67
  }
68
  return self::$oInstance;
69
  }
70
 
71
  /**
72
- * @param ICWP_WPSF_Spec $oPluginSpec
73
  */
74
- private function __construct( $oPluginSpec ) {
75
- if ( empty( self::$oPluginSpec ) ) {
76
- self::$oPluginSpec = $oPluginSpec;
 
 
 
 
 
 
 
 
 
77
  add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
 
 
 
 
 
78
  add_action( 'shutdown', array( $this, 'onWpShutdown' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
  }
81
 
 
 
 
 
82
  /**
83
  * Hooked to 'plugins_loaded'
84
  */
@@ -94,19 +122,171 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
94
  $this->doLoadTextDomain();
95
  }
96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  /**
98
  */
99
  public function onWpAdminNotices() {
100
- // Do we have admin priviledges?
101
  if ( !$this->getIsValidAdminArea() ) {
102
  return true;
103
  }
104
  $aAdminNotices = apply_filters( $this->doPluginPrefix( 'admin_notices' ), array() );
105
- if ( empty( $aAdminNotices ) || !is_array( $aAdminNotices ) ) {
106
- return;
 
 
 
107
  }
108
- foreach( $aAdminNotices as $sAdminNotice ) {
109
- echo $sAdminNotice;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
  }
112
 
@@ -184,39 +364,6 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
184
  return $oPlugins;
185
  }
186
 
187
- /**
188
- * @return string
189
- */
190
- public function getAdminMenuTitle() {
191
- return self::$oPluginSpec->getAdminMenuTitle();;
192
- }
193
-
194
- /**
195
- * @return string
196
- */
197
- public function getBasePermissions() {
198
- return self::$oPluginSpec->getBasePermissions();
199
- }
200
-
201
- /**
202
- * @param bool $fCheckUserPermissions
203
- * @return bool
204
- */
205
- public function getIsValidAdminArea( $fCheckUserPermissions = true ) {
206
- if ( $fCheckUserPermissions && !current_user_can( $this->getBasePermissions() ) ) {
207
- return false;
208
- }
209
-
210
- $oWp = $this->loadWpFunctionsProcessor();
211
- if ( !$oWp->isMultisite() && is_admin() ) {
212
- return true;
213
- }
214
- else if ( $oWp->isMultisite() && $this->getIsWpmsNetworkAdminOnly() && is_network_admin() ) {
215
- return true;
216
- }
217
- return false;
218
- }
219
-
220
  /**
221
  */
222
  protected function doLoadTextDomain() {
@@ -227,6 +374,9 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
227
  );
228
  }
229
 
 
 
 
230
  protected function doPluginFormSubmit() {
231
  if ( !$this->getIsPluginFormSubmit() ) {
232
  return false;
@@ -265,6 +415,79 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
265
  return $this->doPluginPrefix( $sSuffix, '_' );
266
  }
267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  /**
269
  * @param string
270
  * @return string
@@ -285,24 +508,32 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
285
  * @return string
286
  */
287
  public function getHumanName() {
288
- return self::$oPluginSpec->getHumanName();
289
  }
290
 
291
  /**
292
  * @return string
293
  */
294
  public function getIsLoggingEnabled() {
295
- return self::$oPluginSpec->getIsLoggingEnabled();
296
  }
297
 
298
  /**
299
  * @return bool
300
  */
301
- protected function getIsPage_PluginAdmin() {
302
  $oWp = $this->loadWpFunctionsProcessor();
303
  return ( strpos( $oWp->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
304
  }
305
 
 
 
 
 
 
 
 
 
306
  /**
307
  * @return bool
308
  */
@@ -326,17 +557,17 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
326
  }
327
 
328
  /**
329
- * @return string
330
  */
331
  public function getIsWpmsNetworkAdminOnly() {
332
- return self::$oPluginSpec->getIsWpmsNetworkAdminOnly();
333
  }
334
 
335
  /**
336
  * @return string
337
  */
338
  public function getParentSlug() {
339
- return self::$oPluginSpec->getParentSlug();
340
  }
341
 
342
  /**
@@ -355,7 +586,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
355
  * @return string
356
  */
357
  public function getPluginSlug() {
358
- return self::$oPluginSpec->getPluginSlug();
359
  }
360
 
361
  /**
@@ -401,13 +632,20 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
401
  return network_admin_url( sprintf( 'admin.php?page=%s', $this->doPluginPrefix( $sFeature ) ) );
402
  }
403
 
 
 
 
 
 
 
 
404
  /**
405
  * get the root directory for the plugin with the trailing slash
406
  *
407
  * @return string
408
  */
409
- public function getPath_Languages() {
410
- return $this->getRootDir().'languages'.ICWP_DS;
411
  }
412
 
413
  /**
@@ -415,15 +653,17 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
415
  *
416
  * @return string
417
  */
418
- public function getRootDir() {
419
- return dirname( $this->getRootFile() ).ICWP_DS;
420
  }
421
 
422
  /**
 
 
423
  * @return string
424
  */
425
- public function getRootFile() {
426
- return self::$oPluginSpec->getRootFile();
427
  }
428
 
429
  /**
@@ -432,48 +672,162 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
432
  * @param string $sSourceFile
433
  * @return string
434
  */
435
- public function getSourceDir( $sSourceFile = '' ) {
436
- return $this->getRootDir().self::SrcDir.ICWP_DS.$sSourceFile;
437
  }
438
 
439
  /**
 
 
440
  * @return string
441
  */
442
- public function getTextDomain() {
443
- return self::$oPluginSpec->getTextDomain();
444
  }
445
 
446
  /**
 
 
 
447
  * @return string
448
  */
449
- public function getVersion() {
450
- return self::$oPluginSpec->getVersion();
451
  }
452
 
453
  /**
454
- * get the directory for the plugin view with the trailing slash
455
- *
456
  * @return string
457
  */
458
- public function getViewDir() {
459
- return $this->getRootDir().self::ViewDir.ICWP_DS;
460
  }
461
 
462
  /**
463
- * Retrieve the full path to the plugin view
464
  *
465
- * @param string $sView
466
  * @return string
467
  */
468
- public function getViewPath( $sView ) {
469
- return $this->getViewDir().$sView.'.php';
470
  }
471
 
472
  /**
473
- * @param string $sSnippet
474
  * @return string
475
  */
476
- public function getViewSnippet( $sSnippet ) {
477
- return $this->getViewDir().'snippets'.ICWP_DS.$sSnippet.'.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  }
479
  }
19
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20
  */
21
 
22
+ if ( class_exists( 'ICWP_WPSF_Plugin_Controller' ) ) {
23
+ return;
24
+ }
25
+
26
  require_once(dirname(__FILE__).ICWP_DS.'src'.ICWP_DS.'icwp-foundation.php');
27
  class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
28
 
29
  /**
30
+ * @var array
 
 
 
 
 
31
  */
32
+ private static $aPluginSpec;
33
 
34
  /**
35
+ * @var string
36
  */
37
+ private static $sRootFile;
38
 
39
  /**
40
+ * @var ICWP_WPSF_Plugin_Controller
41
  */
42
+ public static $oInstance;
43
 
44
  /**
45
  * @var string
52
  private $sPluginBaseFile;
53
 
54
  /**
 
 
 
 
 
 
55
  * @return ICWP_WPSF_Plugin_Controller
56
  */
57
+ public static function GetInstance( $sRootFile ) {
58
  if ( !isset( self::$oInstance ) ) {
59
+ self::$oInstance = new self( $sRootFile );
60
  }
61
  return self::$oInstance;
62
  }
63
 
64
  /**
65
+ * @param string $sRootFile
66
  */
67
+ private function __construct( $sRootFile ) {
68
+ self::$sRootFile = $sRootFile;
69
+ if ( empty( self::$aPluginSpec ) ) {
70
+ try {
71
+ self::$aPluginSpec = $this->readPluginConfiguration();
72
+ if ( empty( self::$aPluginSpec ) ) {
73
+ return null;
74
+ }
75
+ }
76
+ catch( Exception $oE ) {
77
+ return null;
78
+ }
79
  add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
80
+ add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
81
+ add_filter( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
82
+ add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
83
+ add_action( 'network_admin_menu', array( $this, 'onWpAdminMenu' ) );
84
+ add_action( 'init', array( $this, 'onWpInit' ) );
85
  add_action( 'shutdown', array( $this, 'onWpShutdown' ) );
86
+ $this->registerActivationHooks();
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Registers the plugins activation, deactivate and uninstall hooks.
92
+ */
93
+ protected function registerActivationHooks() {
94
+ register_activation_hook( $this->getRootFile(), array( $this, 'onWpActivatePlugin' ) );
95
+ register_deactivation_hook( $this->getRootFile(), array( $this, 'onWpDeactivatePlugin' ) );
96
+ // register_uninstall_hook( $this->oPluginVo->getRootFile(), array( $this, 'onWpUninstallPlugin' ) );
97
+ }
98
+
99
+ // TODO: this is dependent on a specific plugin option variable - need to move it into the handlers
100
+ public function onWpDeactivatePlugin() {
101
+ if ( $this->loadCorePluginFeatureHandler()->getOptIs( 'delete_on_deactivate', 'Y' ) && current_user_can( $this->getBasePermissions() ) ) {
102
+ do_action( $this->doPluginPrefix( 'delete_plugin' ) );
103
  }
104
  }
105
 
106
+ public function onWpActivatePlugin() {
107
+ $this->loadAllFeatures( true, true );
108
+ }
109
+
110
  /**
111
  * Hooked to 'plugins_loaded'
112
  */
122
  $this->doLoadTextDomain();
123
  }
124
 
125
+ /**
126
+ * Hooked to 'plugins_loaded'
127
+ */
128
+ public function onWpAdminInit() {
129
+ add_action( 'admin_enqueue_scripts', array( $this, 'onWpEnqueueAdminCss' ), 99 );
130
+ }
131
+
132
+ /**
133
+ */
134
+ public function onWpInit() {
135
+ add_action( 'wp_enqueue_scripts', array( $this, 'onWpEnqueueFrontendCss' ), 0 );
136
+ }
137
+
138
+ /**
139
+ * @return bool|void
140
+ */
141
+ public function onWpAdminMenu() {
142
+ if ( !$this->getIsValidAdminArea() ) {
143
+ return true;
144
+ }
145
+ return $this->createPluginMenu();
146
+ }
147
+
148
+ /**
149
+ */
150
+ protected function createPluginMenu() {
151
+
152
+ if ( !$this->getPluginSpec_Menu( 'show' ) ) {
153
+ return true;
154
+ }
155
+
156
+ if ( $this->getPluginSpec_Menu( 'top_level' ) ) {
157
+
158
+ $sFullParentMenuId = $this->getPluginPrefix();
159
+ add_menu_page(
160
+ $this->getHumanName(),
161
+ $this->getAdminMenuTitle(),
162
+ $this->getBasePermissions(),
163
+ $sFullParentMenuId,
164
+ array( $this, $this->getPluginSpec_Menu( 'callback' ) ),
165
+ $this->getPluginUrl_Image( $this->getPluginSpec_Menu( 'icon_image' ) )
166
+ );
167
+
168
+ if ( $this->getPluginSpec_Menu( 'has_submenu' ) ) {
169
+
170
+ $aPluginMenuItems = apply_filters( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array() );
171
+ if ( !empty( $aPluginMenuItems ) ) {
172
+ foreach ( $aPluginMenuItems as $sMenuTitle => $aMenu ) {
173
+ list( $sMenuItemText, $sMenuItemId, $aMenuCallBack ) = $aMenu;
174
+ add_submenu_page(
175
+ $sFullParentMenuId,
176
+ $sMenuTitle,
177
+ $sMenuItemText,
178
+ $this->getBasePermissions(),
179
+ $sMenuItemId,
180
+ $aMenuCallBack
181
+ );
182
+ }
183
+ }
184
+ }
185
+
186
+ if ( $this->getPluginSpec_Menu( 'do_submenu_fix' ) ) {
187
+ $this->fixSubmenu();
188
+ }
189
+ }
190
+ }
191
+
192
+ protected function fixSubmenu() {
193
+ global $submenu;
194
+ $sFullParentMenuId = $this->getPluginPrefix();
195
+ if ( isset( $submenu[$sFullParentMenuId] ) ) {
196
+ unset( $submenu[$sFullParentMenuId][0] );
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Displaying all views now goes through this central function and we work out
202
+ * what to display based on the name of current hook/filter being processed.
203
+ */
204
+ public function onDisplayTopMenu() { }
205
+
206
+ /**
207
+ * On the plugins listing page, hides the edit and deactivate links
208
+ * for this plugin based on permissions
209
+ *
210
+ * @param $aActionLinks
211
+ * @param $sPluginFile
212
+ * @return mixed
213
+ */
214
+ public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
215
+
216
+ if ( $this->getIsValidAdminArea() && $sPluginFile == $this->getPluginBaseFile() ) {
217
+
218
+ $aLinksToAdd = $this->getPluginSpec_ActionLinks( 'add' );
219
+ if ( !empty( $aLinksToAdd ) && is_array( $aLinksToAdd ) ) {
220
+ foreach( $aLinksToAdd as $aLink ){
221
+ if ( empty( $aLink['name'] ) || empty( $aLink['url_method_name'] ) ) {
222
+ continue;
223
+ }
224
+ $sMethod = $aLink['url_method_name'];
225
+ if ( method_exists( $this, $sMethod ) ) {
226
+ $sSettingsLink = sprintf( '<a href="%s">%s</a>', $this->{$sMethod}(), $aLink['name'] ); ;
227
+ array_unshift( $aActionLinks, $sSettingsLink );
228
+ }
229
+ }
230
+ }
231
+ }
232
+ return $aActionLinks;
233
+ }
234
+
235
  /**
236
  */
237
  public function onWpAdminNotices() {
 
238
  if ( !$this->getIsValidAdminArea() ) {
239
  return true;
240
  }
241
  $aAdminNotices = apply_filters( $this->doPluginPrefix( 'admin_notices' ), array() );
242
+ if ( !empty( $aAdminNotices ) && is_array( $aAdminNotices ) ) {
243
+
244
+ foreach( $aAdminNotices as $sAdminNotice ) {
245
+ echo $sAdminNotice;
246
+ }
247
  }
248
+ return true;
249
+ }
250
+
251
+ public function onWpEnqueueFrontendCss() {
252
+
253
+ $aFrontendIncludes = $this->getPluginSpec_Include( 'frontend' );
254
+ if ( isset( $aFrontendIncludes['css'] ) && !empty( $aFrontendIncludes['css'] ) && is_array( $aFrontendIncludes['css'] ) ) {
255
+ foreach( $aFrontendIncludes['css'] as $sCssAsset ) {
256
+ $sUnique = $this->doPluginPrefix( $sCssAsset );
257
+ wp_register_style( $sUnique, $this->getPluginUrl_Css( $sCssAsset.'.css' ), ( empty( $sDependent ) ? false : $sDependent ), $this->getVersion() );
258
+ wp_enqueue_style( $sUnique );
259
+ $sDependent = $sUnique;
260
+ }
261
+ }
262
+ }
263
+
264
+ public function onWpEnqueueAdminCss() {
265
+
266
+ $sDependent = '';
267
+
268
+ if ( $this->getIsValidAdminArea() ) {
269
+ $aAdminCss = $this->getPluginSpec_Include( 'admin' );
270
+ if ( isset( $aAdminCss['css'] ) && !empty( $aAdminCss['css'] ) && is_array( $aAdminCss['css'] ) ) {
271
+ foreach( $aAdminCss['css'] as $sCssAsset ) {
272
+ $sUnique = $this->doPluginPrefix( $sCssAsset );
273
+ wp_register_style( $sUnique, $this->getPluginUrl_Css( $sCssAsset.'.css' ), ( empty( $sDependent ) ? false : $sDependent ), $this->getVersion() );
274
+ wp_enqueue_style( $sUnique );
275
+ $sDependent = $sUnique;
276
+ }
277
+ }
278
+ }
279
+
280
+ if ( $this->getIsPage_PluginAdmin() ) {
281
+ $aAdminCss = $this->getPluginSpec_Include( 'plugin_admin' );
282
+ if ( isset( $aAdminCss['css'] ) && !empty( $aAdminCss['css'] ) && is_array( $aAdminCss['css'] ) ) {
283
+ foreach( $aAdminCss['css'] as $sCssAsset ) {
284
+ $sUnique = $this->doPluginPrefix( $sCssAsset );
285
+ wp_register_style( $sUnique, $this->getPluginUrl_Css( $sCssAsset.'.css' ), ( empty( $sDependent ) ? false : $sDependent ), $this->getVersion() );
286
+ wp_enqueue_style( $sUnique );
287
+ $sDependent = $sUnique;
288
+ }
289
+ }
290
  }
291
  }
292
 
364
  return $oPlugins;
365
  }
366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
  /**
368
  */
369
  protected function doLoadTextDomain() {
374
  );
375
  }
376
 
377
+ /**
378
+ * @return bool
379
+ */
380
  protected function doPluginFormSubmit() {
381
  if ( !$this->getIsPluginFormSubmit() ) {
382
  return false;
415
  return $this->doPluginPrefix( $sSuffix, '_' );
416
  }
417
 
418
+ /**
419
+ * @param string $sKey
420
+ * @return mixed|null
421
+ */
422
+ protected function getPluginSpec_ActionLinks( $sKey ) {
423
+ return isset( self::$aPluginSpec['action_links'][$sKey] ) ? self::$aPluginSpec['action_links'][$sKey] : null;
424
+ }
425
+
426
+ /**
427
+ * @param string $sKey
428
+ * @return mixed|null
429
+ */
430
+ protected function getPluginSpec_Include( $sKey ) {
431
+ return isset( self::$aPluginSpec['includes'][$sKey] ) ? self::$aPluginSpec['includes'][$sKey] : null;
432
+ }
433
+
434
+ /**
435
+ * @param string $sKey
436
+ * @return mixed|null
437
+ */
438
+ protected function getPluginSpec_Menu( $sKey ) {
439
+ return isset( self::$aPluginSpec['menu'][$sKey] ) ? self::$aPluginSpec['menu'][$sKey] : null;
440
+ }
441
+
442
+ /**
443
+ * @param string $sKey
444
+ * @return mixed|null
445
+ */
446
+ protected function getPluginSpec_Path( $sKey ) {
447
+ return isset( self::$aPluginSpec['paths'][$sKey] ) ? self::$aPluginSpec['paths'][$sKey] : null;
448
+ }
449
+
450
+ /**
451
+ * @param string $sKey
452
+ * @return mixed|null
453
+ */
454
+ protected function getPluginSpec_Property( $sKey ) {
455
+ return isset( self::$aPluginSpec['properties'][$sKey] ) ? self::$aPluginSpec['properties'][$sKey] : null;
456
+ }
457
+
458
+ /**
459
+ * @return string
460
+ */
461
+ public function getAdminMenuTitle() {
462
+ return $this->getPluginSpec_Property( 'menu_title' );
463
+ }
464
+
465
+ /**
466
+ * @return string
467
+ */
468
+ public function getBasePermissions() {
469
+ return $this->getPluginSpec_Property( 'base_permissions' );
470
+ }
471
+
472
+ /**
473
+ * @param bool $fCheckUserPermissions
474
+ * @return bool
475
+ */
476
+ public function getIsValidAdminArea( $fCheckUserPermissions = true ) {
477
+ if ( $fCheckUserPermissions && !current_user_can( $this->getBasePermissions() ) ) {
478
+ return false;
479
+ }
480
+
481
+ $oWp = $this->loadWpFunctionsProcessor();
482
+ if ( !$oWp->isMultisite() && is_admin() ) {
483
+ return true;
484
+ }
485
+ else if ( $oWp->isMultisite() && $this->getIsWpmsNetworkAdminOnly() && is_network_admin() ) {
486
+ return true;
487
+ }
488
+ return false;
489
+ }
490
+
491
  /**
492
  * @param string
493
  * @return string
508
  * @return string
509
  */
510
  public function getHumanName() {
511
+ return $this->getPluginSpec_Property( 'human_name' );
512
  }
513
 
514
  /**
515
  * @return string
516
  */
517
  public function getIsLoggingEnabled() {
518
+ return $this->getPluginSpec_Property( 'logging_enabled' );
519
  }
520
 
521
  /**
522
  * @return bool
523
  */
524
+ public function getIsPage_PluginAdmin() {
525
  $oWp = $this->loadWpFunctionsProcessor();
526
  return ( strpos( $oWp->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
527
  }
528
 
529
+ /**
530
+ * @return bool
531
+ */
532
+ public function getIsPage_PluginMainDashboard() {
533
+ $oWp = $this->loadWpFunctionsProcessor();
534
+ return ( $oWp->getCurrentWpAdminPage() == $this->getPluginPrefix() );
535
+ }
536
+
537
  /**
538
  * @return bool
539
  */
557
  }
558
 
559
  /**
560
+ * @return boolean
561
  */
562
  public function getIsWpmsNetworkAdminOnly() {
563
+ return $this->getPluginSpec_Property( 'wpms_network_admin_only' );
564
  }
565
 
566
  /**
567
  * @return string
568
  */
569
  public function getParentSlug() {
570
+ return $this->getPluginSpec_Property( 'slug_parent' );
571
  }
572
 
573
  /**
586
  * @return string
587
  */
588
  public function getPluginSlug() {
589
+ return $this->getPluginSpec_Property( 'slug_plugin' );
590
  }
591
 
592
  /**
632
  return network_admin_url( sprintf( 'admin.php?page=%s', $this->doPluginPrefix( $sFeature ) ) );
633
  }
634
 
635
+ /**
636
+ * @return string
637
+ */
638
+ public function getPluginUrl_AdminMainPage() {
639
+ return $this->getPluginUrl_AdminPage( 'plugin' );
640
+ }
641
+
642
  /**
643
  * get the root directory for the plugin with the trailing slash
644
  *
645
  * @return string
646
  */
647
+ public function getPath_Assets() {
648
+ return $this->getRootDir().$this->getPluginSpec_Path( 'assets' ).ICWP_DS;
649
  }
650
 
651
  /**
653
  *
654
  * @return string
655
  */
656
+ public function getPath_Languages() {
657
+ return $this->getRootDir().$this->getPluginSpec_Path( 'languages' ).ICWP_DS;
658
  }
659
 
660
  /**
661
+ * get the root directory for the plugin with the trailing slash
662
+ *
663
  * @return string
664
  */
665
+ public function getPath_Source() {
666
+ return $this->getRootDir().$this->getPluginSpec_Path( 'source' ).ICWP_DS;
667
  }
668
 
669
  /**
672
  * @param string $sSourceFile
673
  * @return string
674
  */
675
+ public function getPath_SourceFile( $sSourceFile = '' ) {
676
+ return $this->getPath_Source().$sSourceFile;
677
  }
678
 
679
  /**
680
+ * get the root directory for the plugin with the trailing slash
681
+ *
682
  * @return string
683
  */
684
+ public function getPath_Views() {
685
+ return $this->getRootDir().$this->getPluginSpec_Path( 'views' ).ICWP_DS;
686
  }
687
 
688
  /**
689
+ * Retrieve the full path to the plugin view
690
+ *
691
+ * @param string $sView
692
  * @return string
693
  */
694
+ public function getPath_ViewsFile( $sView ) {
695
+ return $this->getPath_Views().$sView.'.php';
696
  }
697
 
698
  /**
699
+ * @param string $sSnippet
 
700
  * @return string
701
  */
702
+ public function getPath_ViewsSnippet( $sSnippet ) {
703
+ return $this->getPath_Views().'snippets'.ICWP_DS.$sSnippet.'.php';
704
  }
705
 
706
  /**
707
+ * get the root directory for the plugin with the trailing slash
708
  *
 
709
  * @return string
710
  */
711
+ public function getRootDir() {
712
+ return dirname( $this->getRootFile() ).ICWP_DS;
713
  }
714
 
715
  /**
 
716
  * @return string
717
  */
718
+ public function getRootFile() {
719
+ if ( !isset( self::$sRootFile ) ) {
720
+ self::$sRootFile = __FILE__;
721
+ }
722
+ return self::$sRootFile;
723
+ }
724
+
725
+ /**
726
+ * @return string
727
+ */
728
+ public function getTextDomain() {
729
+ return $this->getPluginSpec_Property( 'text_domain' );
730
+ }
731
+
732
+ /**
733
+ * @return string
734
+ */
735
+ public function getVersion() {
736
+ return $this->getPluginSpec_Property( 'version' );
737
+ }
738
+
739
+ /**
740
+ * @return ICWP_WPSF_FeatureHandler_Plugin
741
+ */
742
+ public function loadCorePluginFeatureHandler() {
743
+ if ( !isset( $this->oFeatureHandlerPlugin ) ) {
744
+ $this->loadFeatureHandler( array( 'slug' => 'plugin' ) );
745
+ }
746
+ return $this->oFeatureHandlerPlugin;
747
+ }
748
+
749
+ /**
750
+ * @param bool $fRecreate
751
+ * @param bool $fFullBuild
752
+ * @return bool
753
+ */
754
+ public function loadAllFeatures( $fRecreate = false, $fFullBuild = false ) {
755
+
756
+ $oMainPluginFeature = $this->loadCorePluginFeatureHandler();
757
+ $aPluginFeatures = $oMainPluginFeature->getActivePluginFeatures();
758
+
759
+ $fSuccess = true;
760
+ foreach( $aPluginFeatures as $sSlug => $aFeatureProperties ) {
761
+ try {
762
+ $this->loadFeatureHandler( $aFeatureProperties, $fRecreate, $fFullBuild );
763
+ $fSuccess = true;
764
+ }
765
+ catch( Exception $oE ) {
766
+ wp_die( $oE->getMessage() );
767
+ }
768
+ }
769
+ return $fSuccess;
770
+ }
771
+
772
+ /**
773
+ * @param array $aFeatureProperties
774
+ * @param bool $fRecreate
775
+ * @param bool $fFullBuild
776
+ * @return mixed
777
+ * @throws Exception
778
+ */
779
+ public function loadFeatureHandler( $aFeatureProperties, $fRecreate = false, $fFullBuild = false ) {
780
+
781
+ $sFeatureSlug = $aFeatureProperties['slug'];
782
+
783
+ $sFeatureName = str_replace( ' ', '', ucwords( str_replace( '_', ' ', $sFeatureSlug ) ) );
784
+ $sOptionsVarName = sprintf( 'oFeatureHandler%s', $sFeatureName ); // e.g. oFeatureHandlerPlugin
785
+
786
+ if ( isset( $this->{$sOptionsVarName} ) ) {
787
+ return $this->{$sOptionsVarName};
788
+ }
789
+
790
+ $sSourceFile = $this->getPath_SourceFile(
791
+ sprintf(
792
+ '%s-optionshandler-%s.php',
793
+ $this->getParentSlug(),
794
+ $sFeatureSlug
795
+ )
796
+ ); // e.g. icwp-optionshandler-plugin.php
797
+ $sClassName = sprintf(
798
+ '%s_%s_FeatureHandler_%s',
799
+ strtoupper( $this->getParentSlug() ),
800
+ strtoupper( $this->getPluginSlug() ),
801
+ $sFeatureName
802
+ ); // e.g. ICWP_WPSF_FeatureHandler_Plugin
803
+
804
+ require_once( $sSourceFile );
805
+ if ( $fRecreate || !isset( $this->{$sOptionsVarName} ) ) {
806
+ $this->{$sOptionsVarName} = new $sClassName( $this, $aFeatureProperties );
807
+ }
808
+ if ( $fFullBuild ) {
809
+ $this->{$sOptionsVarName}->buildOptions();
810
+ }
811
+ return $this->{$sOptionsVarName};
812
+ }
813
+
814
+ /**
815
+ * @return array
816
+ * @throws Exception
817
+ */
818
+ private function readPluginConfiguration() {
819
+ $oFs = $this->loadFileSystemProcessor();
820
+
821
+ $aConfig = array();
822
+ $sConfigFile = $this->getRootDir().'plugin-spec.txt';
823
+ $sContents = $oFs->getFileContent( $sConfigFile );
824
+ if ( !empty( $sContents ) ) {
825
+ $oYaml = $this->loadYamlProcessor();
826
+ $aConfig = $oYaml->parseYamlString( $sContents );
827
+ if ( is_null( $aConfig ) ) {
828
+ throw new Exception( 'YAML parser could not load to process the plugin spec configuration.' );
829
+ }
830
+ }
831
+ return $aConfig;
832
  }
833
  }
icwp-wpsf-main.php DELETED
@@ -1,426 +0,0 @@
1
- <?php
2
- /**
3
- * Copyright (c) 2014 iControlWP <support@icontrolwp.com>
4
- * All rights reserved.
5
- *
6
- * "WordPress Simple Firewall" is
7
- * distributed under the GNU General Public License, Version 2,
8
- * June 1991. Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin
9
- * St, Fifth Floor, Boston, MA 02110, USA
10
- *
11
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
12
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
15
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
- */
22
-
23
- require_once( dirname(__FILE__).ICWP_DS.'src'.ICWP_DS.'icwp-pure-base.php' );
24
-
25
- if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
26
-
27
- class ICWP_Wordpress_Simple_Firewall extends ICWP_Pure_Base_V6 {
28
-
29
- /**
30
- * @var ICWP_WPSF_FeatureHandler_Plugin
31
- */
32
- protected $oFeatureHandlerPlugin;
33
- /**
34
- * @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction
35
- */
36
- protected $oFeatureHandlerAdminAccessRestriction;
37
- /**
38
- * @var ICWP_WPSF_FeatureHandler_Firewall
39
- */
40
- protected $oFeatureHandlerFirewall;
41
- /**
42
- * @var ICWP_WPSF_FeatureHandler_LoginProtect
43
- */
44
- protected $oFeatureHandlerLoginProtect;
45
-
46
- /**
47
- * @var ICWP_WPSF_FeatureHandler_PrivacyProtect
48
- */
49
- protected $oFeatureHandlerPrivacyProtect;
50
-
51
- /**
52
- * @var ICWP_WPSF_FeatureHandler_AuditTrail
53
- */
54
- protected $oFeatureHandlerAuditTrail;
55
-
56
- /**
57
- * @var ICWP_WPSF_FeatureHandler_CommentsFilter
58
- */
59
- protected $oFeatureHandlerCommentsFilter;
60
-
61
- /**
62
- * @var ICWP_WPSF_FeatureHandler_Lockdown
63
- */
64
- protected $oFeatureHandlerLockdown;
65
-
66
- /**
67
- * @var ICWP_WPSF_FeatureHandler_Autoupdates
68
- */
69
- protected $oFeatureHandlerAutoupdates;
70
-
71
- /**
72
- * @var ICWP_WPSF_FeatureHandler_Email
73
- */
74
- protected $oFeatureHandlerEmail;
75
-
76
- /**
77
- * @var ICWP_WPSF_FeatureHandler_Logging
78
- */
79
- protected $oFeatureHandlerLogging;
80
-
81
- /**
82
- */
83
- public function __construct( ICWP_WPSF_Plugin_Controller $oPluginVo ) {
84
- parent::__construct( $oPluginVo );
85
-
86
- $this->loadAllFeatures();
87
- add_filter( $this->doPluginPrefix( 'has_permission_to_view' ), array( $this, 'hasPermissionToView' ) );
88
- add_filter( $this->doPluginPrefix( 'has_permission_to_submit' ), array( $this, 'hasPermissionToSubmit' ) );
89
- add_filter( $this->doPluginPrefix( 'plugin_update_message' ), array( $this, 'getPluginsListUpdateMessage' ) );
90
- }
91
-
92
- public function onWpActivatePlugin() {
93
- $this->loadAllFeatures( true, true );
94
- }
95
-
96
- /**
97
- * @return ICWP_WPSF_FeatureHandler_Plugin
98
- */
99
- protected function loadCorePluginFeature() {
100
- if ( isset( $this->oPluginOptions ) ) {
101
- return $this->oPluginOptions;
102
- }
103
- return $this->loadFeatureHandler( 'plugin' );
104
- }
105
-
106
- /**
107
- * @param bool $fRecreate
108
- * @param bool $fFullBuild
109
- * @return bool
110
- */
111
- protected function loadAllFeatures( $fRecreate = false, $fFullBuild = false ) {
112
-
113
- $oMainPluginFeature = $this->loadCorePluginFeature();
114
- $aPluginFeatures = $oMainPluginFeature->getActivePluginFeatures();
115
-
116
- $fSuccess = true;
117
- foreach( $aPluginFeatures as $sSlug => $sStorageKey ) {
118
- try {
119
- $this->loadFeatureHandler( $sSlug, $fRecreate, $fFullBuild );
120
- $fSuccess = true;
121
- }
122
- catch( Exception $oE ) {
123
- wp_die( $oE->getMessage() );
124
- }
125
- }
126
- return $fSuccess;
127
- }
128
-
129
- /**
130
- * @param string $sFeatureSlug
131
- * @param bool $fRecreate
132
- * @param bool $fFullBuild
133
- * @return mixed
134
- * @throws Exception
135
- */
136
- protected function loadFeatureHandler( $sFeatureSlug, $fRecreate = false, $fFullBuild = false ) {
137
-
138
- $sFeatureName = str_replace( ' ', '', ucwords( str_replace( '_', ' ', $sFeatureSlug ) ) );
139
- $sOptionsVarName = sprintf( 'oFeatureHandler%s', $sFeatureName ); // e.g. oFeatureHandlerOptions
140
-
141
- if ( isset( $this->{$sOptionsVarName} ) ) {
142
- return $this->{$sOptionsVarName};
143
- }
144
-
145
- $sSourceFile = $this->getController()->getSourceDir( sprintf( 'icwp-optionshandler-%s.php', $sFeatureSlug ) ); // e.g. icwp-optionshandler-plugin.php
146
- $sClassName = sprintf( 'ICWP_WPSF_FeatureHandler_%s', $sFeatureName ); // e.g. ICWP_WPSF_FeatureHandler_Plugin
147
-
148
- require_once( $sSourceFile );
149
- if ( $fRecreate || !isset( $this->{$sOptionsVarName} ) ) {
150
- $this->{$sOptionsVarName} = new $sClassName( $this->getController() );
151
- }
152
- if ( $fFullBuild ) {
153
- $this->{$sOptionsVarName}->buildOptions();
154
- }
155
- return $this->{$sOptionsVarName};
156
- }
157
-
158
- /**
159
- * @param array $aItems
160
- * @return array $aItems
161
- */
162
- public function filter_addExtraAdminMenuItems( $aItems ) {
163
- $aItems[ _wpsf__('Firewall Log' ) ] = array( 'Firewall Log', $this->doPluginPrefix('firewall_log'), array( $this, 'onDisplayAll' ) );
164
- // $aItems[ _wpsf__('Audit Trail Viewer' ) ] = array( 'Audit Trail Viewer', $this->doPluginPrefix('audit_trail_viewer'), array( $this, 'onDisplayAll' ) );
165
- return $aItems;
166
- }
167
-
168
- /**
169
- * Displaying all views now goes through this central function and we work out
170
- * what to display based on the name of current hook/filter being processed.
171
- */
172
- public function onDisplayAll() {
173
-
174
- if ( !$this->hasPermissionToView() ) {
175
- $this->onDisplayAccessKeyRequest();
176
- return;
177
- }
178
-
179
- // Just to ensure the nag bar disappears if/when they visit the dashboard
180
- // regardless of clicking the button.
181
- $this->updateVersionUserMeta();
182
-
183
- $sPrefix = str_replace(' ', '-', strtolower( $this->getController()->getAdminMenuTitle() ) ) .'_page_'.$this->getPluginPrefix().'-';
184
- $sCurrent = str_replace( $sPrefix, '', current_filter() );
185
-
186
- switch( $sCurrent ) {
187
- case 'privacy_protect_log' :
188
- $this->onDisplayPrivacyProtectLog();
189
- break;
190
- case 'firewall_log' :
191
- $this->onDisplayFirewallLog();
192
- break;
193
- case 'audit_trail_viewer' :
194
- $this->onDisplayAuditTrailViewer();
195
- break;
196
- default:
197
- $this->getFeatureHandler_MainPlugin()->displayFeatureConfigPage();
198
- break;
199
- }
200
- }
201
-
202
- protected function onDisplayPrivacyProtectLog() {
203
-
204
- $oPrivacyProcessor = $this->getProcessor_PrivacyProtect();
205
- $aData = array(
206
- 'urlrequests_log' => $oPrivacyProcessor->getLogs( true )
207
- );
208
- $aData = array_merge( $this->getBaseDisplayData(), $aData );
209
- $this->display( $this->doPluginPrefix( 'privacy_protect_log_index' ), $aData );
210
- }
211
-
212
- protected function onDisplayFirewallLog() {
213
-
214
- $oFirewallHandler = $this->loadFeatureHandler( 'firewall' );
215
- if ( $oFirewallHandler instanceof ICWP_WPSF_FeatureHandler_Firewall ) {
216
- $aIpWhitelist = $oFirewallHandler->getOpt( 'ips_whitelist' );
217
- $aIpBlacklist = $oFirewallHandler->getOpt( 'ips_blacklist' );
218
- }
219
-
220
- $oLoggingProcessor = $this->getProcessor_Logging();
221
- if ( $oLoggingProcessor instanceof ICWP_WPSF_Processor_Logging ) {
222
- $aLogData = $oLoggingProcessor->getLogs( true );
223
- }
224
-
225
- $aData = array(
226
- 'sFeatureName' => _wpsf__('Firewall Log'),
227
- 'firewall_log' => $aLogData,
228
- 'ip_whitelist' => isset( $aIpWhitelist['ips'] )? $aIpWhitelist['ips'] : array(),
229
- 'ip_blacklist' => isset( $aIpBlacklist['ips'] )? $aIpBlacklist['ips'] : array(),
230
- );
231
- $aData = array_merge( $this->getBaseDisplayData(), $aData );
232
- $this->display( $this->doPluginPrefix( 'firewall_log_index' ), $aData );
233
- }
234
-
235
- protected function onDisplayAuditTrailViewer() {
236
-
237
- $oAuditTrail = $this->getProcessor_AuditTrail();
238
- $aAuditData = $oAuditTrail->getAllAuditEntries();
239
-
240
- $aAuditDataUsers = array();
241
- $aAuditDataPlugins = array();
242
- $aAuditDataThemes = array();
243
- $aAuditDataWordpress = array();
244
- $aAuditDataPosts = array();
245
- foreach( $aAuditData as $aAudit ) {
246
- if ( $aAudit['context'] == 'users' ) {
247
- $aAuditDataUsers[] = $aAudit;
248
- }
249
- if ( $aAudit['context'] == 'plugins' ) {
250
- $aAuditDataPlugins[] = $aAudit;
251
- }
252
- if ( $aAudit['context'] == 'themes' ) {
253
- $aAuditDataThemes[] = $aAudit;
254
- }
255
- if ( $aAudit['context'] == 'wordpress' ) {
256
- $aAuditDataWordpress[] = $aAudit;
257
- }
258
- if ( $aAudit['context'] == 'posts' ) {
259
- $aAuditDataPosts[] = $aAudit;
260
- }
261
- }
262
-
263
- $aData = array(
264
- 'sFeatureName' => _wpsf__('Audit Trail Viewer'),
265
- 'aAuditDataUsers' => $aAuditDataUsers,
266
- 'aAuditDataPlugins' => $aAuditDataPlugins,
267
- 'aAuditDataThemes' => $aAuditDataThemes,
268
- 'aAuditDataWordpress' => $aAuditDataWordpress,
269
- 'aAuditDataPosts' => $aAuditDataPosts
270
- );
271
- $aData = array_merge( $this->getBaseDisplayData(), $aData );
272
- $this->display( $this->doPluginPrefix( 'audit_trail_viewer_index' ), $aData );
273
- }
274
-
275
- public function onWpAdminInit() {
276
- parent::onWpAdminInit();
277
-
278
- if ( $this->getController()->getIsValidAdminArea() ) {
279
- $oDp = $this->loadDataProcessor();
280
- $oWp = $this->loadWpFunctionsProcessor();
281
-
282
- $sRedirect = $oDp->FetchPost( 'redirect_page' );
283
- $sRedirect = empty( $sRedirect ) ? $this->getController()->getPluginUrl_AdminPage() : $sRedirect;
284
- //Someone clicked the button to acknowledge the update
285
- if ( $oDp->FetchRequest( $this->doPluginPrefix( 'hide_update_notice' ) ) == 1 ) {
286
- $this->updateVersionUserMeta();
287
- $oWp->doRedirect( $sRedirect );
288
- }
289
-
290
- if ( $oDp->FetchRequest( $this->doPluginPrefix( 'hide_translation_notice' ) ) == 1 ) {
291
- $this->updateTranslationNoticeShownUserMeta();
292
- $oWp->doRedirect( $sRedirect );
293
- }
294
-
295
- if ( $oDp->FetchRequest( $this->doPluginPrefix( 'hide_mailing_list_signup' ) ) == 1 ) {
296
- $this->updateMailingListSignupShownUserMeta();
297
- }
298
- }
299
- }
300
-
301
- /**
302
- * @return bool
303
- */
304
- protected function isShowMarketing() {
305
- return apply_filters( $this->doPluginPrefix( 'show_marketing' ), true );
306
- }
307
-
308
- public function getPluginsListUpdateMessage( $sMessage ) {
309
- return _wpsf__( 'Upgrade Now To Keep Your Firewall Up-To-Date With The Latest Features.' );
310
- }
311
-
312
- /**
313
- * @return bool
314
- */
315
- protected function getShowAdminNotices() {
316
- return $this->loadCorePluginFeature()->getOpt( 'enable_upgrade_admin_notice' ) == 'Y';
317
- }
318
-
319
- /**
320
- * @return int
321
- */
322
- protected function getInstallationDays() {
323
- $nTimeInstalled = $this->loadCorePluginFeature()->getOpt( 'installation_time' );
324
- if ( empty($nTimeInstalled) ) {
325
- return 0;
326
- }
327
- return round( ( time() - $nTimeInstalled ) / DAY_IN_SECONDS );
328
- }
329
-
330
- protected function getAdminBarNodes() {
331
- return array(); //disabled for now
332
- $aMenu = array(
333
- 'id' => $this->doPluginOptionPrefix( 'admin_menu' ),
334
- 'title' => '<span class="pluginlogo_16">&nbsp;</span>'._wpsf__('Firewall').'',
335
- 'href' => 'bob',
336
- );
337
- return array( $aMenu );
338
- }
339
-
340
- public function onWpDeactivatePlugin() {
341
- if ( $this->getFeatureHandler_MainPlugin()->getOpt( 'delete_on_deactivate' ) == 'Y' && current_user_can( $this->getController()->getBasePermissions() ) ) {
342
- do_action( $this->doPluginPrefix( 'delete_plugin' ) );
343
- }
344
- }
345
-
346
- /**
347
- * @return ICWP_WPSF_FeatureHandler_Plugin|null
348
- */
349
- public function getFeatureHandler_MainPlugin() {
350
- return $this->loadFeatureHandler( 'plugin' );
351
- }
352
-
353
- /**
354
- * @return ICWP_WPSF_FeatureHandler_AdminAccessRestriction|null
355
- */
356
- public function getFeatureHandler_AdminAccessRestriction() {
357
- return $this->loadFeatureHandler( 'admin_access_restriction' );
358
- }
359
-
360
- /**
361
- * @return ICWP_WPSF_FeatureHandler_AdminAccessRestriction|null
362
- */
363
- public function getProcessor_AdminAccessRestriction() {
364
- return $this->getFeatureHandler_AdminAccessRestriction()->getProcessor();
365
- }
366
-
367
- /**
368
- * @return ICWP_WPSF_Processor_Firewall|null
369
- */
370
- public function getProcessor_Firewall() {
371
- $this->loadFeatureHandler( 'firewall' );
372
- return $this->oFeatureHandlerFirewall->getProcessor();
373
- }
374
-
375
- /**
376
- * @return ICWP_WPSF_Processor_LoginProtect|null
377
- */
378
- public function getProcessor_LoginProtect() {
379
- $this->loadFeatureHandler( 'login_protect' );
380
- return $this->oFeatureHandlerLoginProtect->getProcessor();
381
- }
382
-
383
- /**
384
- * @return ICWP_WPSF_Processor_Autoupdates|null
385
- */
386
- public function getProcessor_Autoupdates() {
387
- $this->loadFeatureHandler( 'autoupdates' );
388
- return $this->oFeatureHandlerAutoupdates->getProcessor();
389
- }
390
-
391
- /**
392
- * @return ICWP_WPSF_Processor_PrivacyProtect|null
393
- */
394
- public function getProcessor_PrivacyProtect() {
395
- $this->loadFeatureHandler( 'privacy_protect' );
396
- return $this->oFeatureHandlerPrivacyProtect->getProcessor();
397
- }
398
-
399
- /**
400
- * @return ICWP_WPSF_Processor_AuditTrail|null
401
- */
402
- public function getProcessor_AuditTrail() {
403
- $this->loadFeatureHandler( 'audit_trail' );
404
- return $this->oFeatureHandlerAuditTrail->getProcessor();
405
- }
406
-
407
- /**
408
- * @return ICWP_WPSF_Processor_Logging|null
409
- */
410
- public function getProcessor_Logging() {
411
- $this->loadFeatureHandler( 'logging' );
412
- return $this->oFeatureHandlerLogging->getProcessor();
413
- }
414
-
415
- /**
416
- * @return ICWP_WPSF_Processor_Email|null
417
- */
418
- public function getProcessor_Email() {
419
- return $this->oFeatureHandlerEmail->getEmailProcessor();
420
- }
421
- }
422
-
423
- endif;
424
-
425
- require_once( 'icwp-plugin-controller.php');
426
- $oICWP_Wpsf = new ICWP_Wordpress_Simple_Firewall( ICWP_WPSF_Plugin_Controller::GetInstance( ICWP_WPSF_Spec::GetInstance() ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WordPress Simple Firewall
4
  * Plugin URI: http://icwp.io/2f
5
  * Description: A Simple WordPress Firewall
6
- * Version: 3.5.5
7
  * Text Domain: wp-simple-firewall
8
  * Author: iControlWP
9
  * Author URI: http://icwp.io/2e
@@ -43,157 +43,216 @@ if ( !function_exists( '_wpsf__' ) ) {
43
  return __( $insStr, 'wp-simple-firewall' );
44
  }
45
  }
46
- class ICWP_WPSF_Spec {
47
-
48
- /**
49
- * @const string
50
- */
51
- const ViewDir = 'views';
52
-
53
- /**
54
- * @const string
55
- */
56
- const SrcDir = 'src';
57
-
58
- /**
59
- * @var string
60
- */
61
- protected static $fLoggingEnabled = true;
62
-
63
- /**
64
- * @var string
65
- */
66
- private static $sVersion = '3.5.5';
67
-
68
- /**
69
- * @var string
70
- */
71
- private static $sParentSlug = 'icwp';
72
-
73
- /**
74
- * @var string
75
- */
76
- private static $sPluginSlug = 'wpsf';
77
-
78
- /**
79
- * @var string
80
- */
81
- private static $sRootFile;
82
-
83
- /**
84
- * @var string
85
- */
86
- private static $sHumanName = 'WordPress Simple Firewall';
87
-
88
- /**
89
- * @var string
90
- */
91
- private static $sMenuTitleName = 'Simple Firewall';
92
-
93
- /**
94
- * @var string
95
- */
96
- private static $sTextDomain = 'wp-simple-firewall';
97
-
98
- /**
99
- * @var string
100
- */
101
- private static $sBasePermissions = 'manage_options';
102
-
103
- /**
104
- * @var string
105
- */
106
- private static $sWpmsNetworkAdminOnly = true;
107
-
108
- /**
109
- * @var ICWP_WPSF_Spec
110
- */
111
- public static $oInstance;
112
-
113
- /**
114
- * @return ICWP_WPSF_Spec
115
- */
116
- public static function GetInstance() {
117
- if ( !isset( self::$oInstance ) ) {
118
- self::$oInstance = new self();
119
  }
120
- return self::$oInstance;
121
- }
122
 
123
- /**
124
- */
125
- private function __construct() {
126
- self::$sRootFile = __FILE__;
127
- }
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
- /**
130
- * @return string
131
- */
132
- public function getAdminMenuTitle() {
133
- return self::$sMenuTitleName;
134
- }
135
 
136
- /**
137
- * @return string
138
- */
139
- public function getBasePermissions() {
140
- return self::$sBasePermissions;
141
- }
 
142
 
143
- /**
144
- * @return string
145
- */
146
- public function getHumanName() {
147
- return self::$sHumanName;
148
- }
149
 
150
- /**
151
- * @return string
152
- */
153
- public function getIsLoggingEnabled() {
154
- return self::$fLoggingEnabled;
155
- }
156
 
157
- /**
158
- * @return string
159
- */
160
- public function getIsWpmsNetworkAdminOnly() {
161
- return self::$sWpmsNetworkAdminOnly;
162
- }
163
 
164
- /**
165
- * @return string
166
- */
167
- public function getParentSlug() {
168
- return self::$sParentSlug;
169
- }
170
 
171
- /**
172
- * @return string
173
- */
174
- public function getPluginSlug() {
175
- return self::$sPluginSlug;
176
- }
 
177
 
178
- /**
179
- * @return string
180
- */
181
- public function getRootFile() {
182
- return self::$sRootFile;
183
- }
 
 
184
 
185
- /**
186
- * @return string
187
- */
188
- public function getTextDomain() {
189
- return self::$sTextDomain;
190
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
- /**
193
- * @return string
194
- */
195
- public function getVersion() {
196
- return self::$sVersion;
 
 
 
 
197
  }
198
- }
199
- require_once( 'icwp-wpsf-main.php' );
 
 
 
 
 
 
 
3
  * Plugin Name: WordPress Simple Firewall
4
  * Plugin URI: http://icwp.io/2f
5
  * Description: A Simple WordPress Firewall
6
+ * Version: 4.0.0
7
  * Text Domain: wp-simple-firewall
8
  * Author: iControlWP
9
  * Author URI: http://icwp.io/2e
43
  return __( $insStr, 'wp-simple-firewall' );
44
  }
45
  }
46
+
47
+ require_once( dirname(__FILE__).ICWP_DS.'src'.ICWP_DS.'icwp-foundation.php' );
48
+ if ( !class_exists('ICWP_Wordpress_Simple_Firewall') ):
49
+
50
+ class ICWP_Wordpress_Simple_Firewall extends ICWP_WPSF_Foundation {
51
+
52
+ /**
53
+ * @var ICWP_WPSF_FeatureHandler_Plugin
54
+ */
55
+ protected $oFeatureHandlerPlugin;
56
+ /**
57
+ * @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction
58
+ */
59
+ protected $oFeatureHandlerAdminAccessRestriction;
60
+ /**
61
+ * @var ICWP_WPSF_FeatureHandler_Firewall
62
+ */
63
+ protected $oFeatureHandlerFirewall;
64
+ /**
65
+ * @var ICWP_WPSF_FeatureHandler_LoginProtect
66
+ */
67
+ protected $oFeatureHandlerLoginProtect;
68
+
69
+ /**
70
+ * @var ICWP_WPSF_FeatureHandler_PrivacyProtect
71
+ */
72
+ protected $oFeatureHandlerPrivacyProtect;
73
+
74
+ /**
75
+ * @var ICWP_WPSF_FeatureHandler_AuditTrail
76
+ */
77
+ protected $oFeatureHandlerAuditTrail;
78
+
79
+ /**
80
+ * @var ICWP_WPSF_FeatureHandler_CommentsFilter
81
+ */
82
+ protected $oFeatureHandlerCommentsFilter;
83
+
84
+ /**
85
+ * @var ICWP_WPSF_FeatureHandler_Lockdown
86
+ */
87
+ protected $oFeatureHandlerLockdown;
88
+
89
+ /**
90
+ * @var ICWP_WPSF_FeatureHandler_Autoupdates
91
+ */
92
+ protected $oFeatureHandlerAutoupdates;
93
+
94
+ /**
95
+ * @var ICWP_WPSF_FeatureHandler_Email
96
+ */
97
+ protected $oFeatureHandlerEmail;
98
+
99
+ /**
100
+ * @var ICWP_WPSF_Plugin_Controller
101
+ */
102
+ protected $oPluginController;
103
+
104
+ /**
105
+ * @param ICWP_WPSF_Plugin_Controller $oPluginController
106
+ */
107
+ public function __construct( ICWP_WPSF_Plugin_Controller $oPluginController ) {
108
+
109
+ // All core values of the plugin are derived from the values stored in this value object.
110
+ $this->oPluginController = $oPluginController;
111
+ $this->oPluginController->loadAllFeatures();
112
+ add_filter( $this->oPluginController->doPluginPrefix( 'has_permission_to_view' ), array( $this, 'hasPermissionToView' ) );
113
+ add_filter( $this->oPluginController->doPluginPrefix( 'has_permission_to_submit' ), array( $this, 'hasPermissionToSubmit' ) );
114
+ add_filter( $this->oPluginController->doPluginPrefix( 'plugin_update_message' ), array( $this, 'getPluginsListUpdateMessage' ) );
115
+
116
+ add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
117
+ add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
 
118
  }
 
 
119
 
120
+ // protected function onDisplayFirewallLog() {
121
+ //
122
+ // $oFirewallHandler = $this->loadFeatureHandler( 'firewall' );
123
+ // if ( $oFirewallHandler instanceof ICWP_WPSF_FeatureHandler_Firewall ) {
124
+ // $aIpWhitelist = $oFirewallHandler->getOpt( 'ips_whitelist' );
125
+ // $aIpBlacklist = $oFirewallHandler->getOpt( 'ips_blacklist' );
126
+ // }
127
+ //
128
+ // $aData = array(
129
+ // 'sFeatureName' => _wpsf__('Firewall Log'),
130
+ // 'firewall_log' => $aLogData,
131
+ // 'ip_whitelist' => isset( $aIpWhitelist['ips'] )? $aIpWhitelist['ips'] : array(),
132
+ // 'ip_blacklist' => isset( $aIpBlacklist['ips'] )? $aIpBlacklist['ips'] : array(),
133
+ // );
134
+ // $aData = array_merge( $this->getBaseDisplayData(), $aData );
135
+ // $this->display( $this->doPluginPrefix( 'firewall_log_index' ), $aData );
136
+ // }
137
 
138
+ public function onWpAdminInit() {
139
+ $oCon = $this->getController();
140
+ if ( $oCon->getIsValidAdminArea() ) {
141
+ $oDp = $oCon->loadDataProcessor();
142
+ $oWp = $oCon->loadWpFunctionsProcessor();
 
143
 
144
+ $sRedirect = $oDp->FetchPost( 'redirect_page' );
145
+ $sRedirect = empty( $sRedirect ) ? $this->getController()->getPluginUrl_AdminPage() : $sRedirect;
146
+ //Someone clicked the button to acknowledge the update
147
+ if ( $oDp->FetchRequest( $oCon->doPluginPrefix( 'hide_update_notice' ) ) == 1 ) {
148
+ $this->updateVersionUserMeta();
149
+ $oWp->doRedirect( $sRedirect );
150
+ }
151
 
152
+ if ( $oDp->FetchRequest( $oCon->doPluginPrefix( 'hide_translation_notice' ) ) == 1 ) {
153
+ $this->updateTranslationNoticeShownUserMeta();
154
+ $oWp->doRedirect( $sRedirect );
155
+ }
 
 
156
 
157
+ if ( $oDp->FetchRequest( $oCon->doPluginPrefix( 'hide_mailing_list_signup' ) ) == 1 ) {
158
+ $this->updateMailingListSignupShownUserMeta();
159
+ }
160
+ }
161
+ }
 
162
 
163
+ public function getPluginsListUpdateMessage( $sMessage ) {
164
+ return _wpsf__( 'Upgrade Now To Keep Your Firewall Up-To-Date With The Latest Features.' );
165
+ }
 
 
 
166
 
167
+ /**
168
+ * @return ICWP_WPSF_Plugin_Controller
169
+ */
170
+ public function getController() {
171
+ return $this->oPluginController;
172
+ }
173
 
174
+ /**
175
+ * @param boolean $fHasPermission
176
+ * @return boolean
177
+ */
178
+ public function hasPermissionToView( $fHasPermission = true ) {
179
+ return $this->hasPermissionToSubmit( $fHasPermission );
180
+ }
181
 
182
+ /**
183
+ * @param boolean $fHasPermission
184
+ * @return boolean
185
+ */
186
+ public function hasPermissionToSubmit( $fHasPermission = true ) {
187
+ // first a basic admin check
188
+ return $fHasPermission && is_super_admin() && current_user_can( $this->getController()->getBasePermissions() );
189
+ }
190
 
191
+ /**
192
+ * On the plugins listing page, hides the edit and deactivate links
193
+ * for this plugin based on permissions
194
+ *
195
+ * @param $aActionLinks
196
+ * @param $sPluginFile
197
+ * @return mixed
198
+ */
199
+ public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
200
+ $oCon = $this->getController();
201
+ if ( !$oCon->getIsValidAdminArea() ) {
202
+ return $aActionLinks;
203
+ }
204
+
205
+ if ( $sPluginFile == $oCon->getPluginBaseFile() ) {
206
+ if ( !$this->hasPermissionToSubmit() ) {
207
+ if ( array_key_exists( 'edit', $aActionLinks ) ) {
208
+ unset( $aActionLinks['edit'] );
209
+ }
210
+ if ( array_key_exists( 'deactivate', $aActionLinks ) ) {
211
+ unset( $aActionLinks['deactivate'] );
212
+ }
213
+ }
214
+ }
215
+ return $aActionLinks;
216
+ }
217
+
218
+ /**
219
+ * Updates the current (or supplied user ID) user meta data with the version of the plugin
220
+ *
221
+ * @param $nId
222
+ * @param $sValue
223
+ */
224
+ protected function updateTranslationNoticeShownUserMeta( $nId = '', $sValue = 'Y' ) {
225
+ $oCon = $this->getController();
226
+ $oCon->loadWpFunctionsProcessor()->updateUserMeta( $oCon->doPluginOptionPrefix( 'plugin_translation_notice' ), $sValue, $nId );
227
+ }
228
+
229
+ /**
230
+ * Updates the current (or supplied user ID) user meta data with the version of the plugin
231
+ *
232
+ * @param $nId
233
+ * @param $sValue
234
+ */
235
+ protected function updateMailingListSignupShownUserMeta( $nId = '', $sValue = 'Y' ) {
236
+ $oCon = $this->getController();
237
+ $oCon->loadWpFunctionsProcessor()->updateUserMeta( $oCon->doPluginOptionPrefix( 'plugin_mailing_list_signup' ), $sValue, $nId );
238
+ }
239
 
240
+ /**
241
+ * Updates the current (or supplied user ID) user meta data with the version of the plugin
242
+ *
243
+ * @param integer $nId
244
+ */
245
+ protected function updateVersionUserMeta( $nId = null ) {
246
+ $oCon = $this->getController();
247
+ $oCon->loadWpFunctionsProcessor()->updateUserMeta( $oCon->doPluginOptionPrefix( 'current_version' ), $oCon->getVersion(), $nId );
248
+ }
249
  }
250
+
251
+ endif;
252
+
253
+ require_once( 'icwp-plugin-controller.php' );
254
+
255
+ $oICWP_Wpsf_Controller = ICWP_WPSF_Plugin_Controller::GetInstance( __FILE__ );
256
+ if ( !is_null( $oICWP_Wpsf_Controller ) ) {
257
+ $oICWP_Wpsf = new ICWP_Wordpress_Simple_Firewall( $oICWP_Wpsf_Controller );
258
+ }
plugin-spec.txt ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ properties:
3
+ version: '4.0.0'
4
+ slug_parent: 'icwp'
5
+ slug_plugin: 'wpsf'
6
+ human_name: 'WordPress Simple Firewall'
7
+ menu_title: 'Simple Firewall'
8
+ text_domain: 'wp-simple-firewall'
9
+ base_permissions: 'manage_options'
10
+ wpms_network_admin_only: true
11
+ logging_enabled: true
12
+ paths:
13
+ source: 'src'
14
+ assets: 'resources'
15
+ languages: 'languages'
16
+ views: 'views'
17
+ includes:
18
+ admin:
19
+ css:
20
+ - global-plugin
21
+ plugin_admin:
22
+ css:
23
+ - bootstrap-wpadmin-legacy
24
+ - bootstrap-wpadmin-fixes
25
+ - plugin
26
+ frontend:
27
+ css:
28
+
29
+ menu:
30
+ show: true
31
+ top_level: true # to-do is allow for non-top-level menu items.
32
+ do_submenu_fix: true
33
+ callback: 'onDisplayTopMenu'
34
+ icon_image: 'pluginlogo_16x16.png'
35
+ has_submenu: true # to-do is allow for non-top-level menu items.
36
+
37
+ # This is on the plugins.php page with the option to remove or add custom links.
38
+ action_links:
39
+ remove:
40
+ add:
41
+ -
42
+ name: 'Dashboard'
43
+ url_method_name: 'getPluginUrl_AdminMainPage'
readme.txt CHANGED
@@ -3,12 +3,12 @@ Contributors: paultgoodchild, dlgoodchild
3
  Donate link: http://icwp.io/q
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
- Tags: WordPress Firewall, audit trail, protection, whitelist, blacklist, two-factor authentication, GASP, comment spam, automatic updates, lockdown, login, hack, login
7
  Requires at least: 3.2.0
8
  Tested up to: 4.0
9
- Stable tag: 3.5.5
10
 
11
- Complete and Simple WordPress Security. Unrestricted, Easy, No Premium Features.
12
 
13
  == Description ==
14
 
@@ -17,6 +17,9 @@ The WordPress Simple Firewall is [all you need to secure your WordPress](http://
17
  = Plugin Admin Access Protection =
18
  The **only** WordPress security plugin with a WordPress-independent security key to protects itself. [more info](http://icwp.io/wpsf05)
19
 
 
 
 
20
  = Firewall Protection =
21
  Blocks all web requests to the site that violate the firewall rules with easy setup! [more info](http://icwp.io/wpsf06)
22
 
@@ -225,11 +228,16 @@ You can either manually upgrade, or WordPress will handle it in due course.
225
 
226
  == Changelog ==
227
 
228
- * KNOWN ISSUE: Login Protection logs are not being properly created.
 
 
229
 
230
  = 4.0.0 =
231
 
232
- * ADDED: New Feature - Audit Trail ( Coming Soon! )
 
 
 
233
 
234
  = 3.5.5 =
235
 
3
  Donate link: http://icwp.io/q
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
+ Tags: WordPress Firewall, audit trail, ddos, brute force, protection, activity monitor, whitelist, blacklist, two-factor authentication, GASP, comment spam, automatic updates, lockdown, login, hack
7
  Requires at least: 3.2.0
8
  Tested up to: 4.0
9
+ Stable tag: 4.0.0
10
 
11
+ Complete and Simple WordPress Security. Unrestricted. No Premium Features.
12
 
13
  == Description ==
14
 
17
  = Plugin Admin Access Protection =
18
  The **only** WordPress security plugin with a WordPress-independent security key to protects itself. [more info](http://icwp.io/wpsf05)
19
 
20
+ = Audit Trail Activity Monitor =
21
+ The **only** WordPress security plugin with a WordPress-independent security key to protects itself. [more info](http://icwp.io/wpsf05)
22
+
23
  = Firewall Protection =
24
  Blocks all web requests to the site that violate the firewall rules with easy setup! [more info](http://icwp.io/wpsf06)
25
 
228
 
229
  == Changelog ==
230
 
231
+ = 4.1.0 (Coming Soon) =
232
+
233
+ * ADDED: Audit Trail for more WordPress Simple Firewall events such as User Sessions, Login Protections, Comments Filtering etc.
234
 
235
  = 4.0.0 =
236
 
237
+ * ADDED: New Feature - Audit Trail
238
+ * ADDED: Audit Trail options include: Plugins, Themes, Email, WordPress Core, Posts/Pages, WordPress Simple Firewall
239
+ * FIXED: Full and proper cleanup of plugin options, crons, and databases upon deactivation.
240
+ * REMOVED: Firewall Log. This is no longer an option and is instead integrated into the "WordPress Simple Firewall" Audit Trail.
241
 
242
  = 3.5.5 =
243
 
resources/css/plugin.css CHANGED
@@ -120,7 +120,7 @@ p.code-description {
120
  .form-horizontal legend {
121
  border-bottom: 1px dashed #aaa;
122
  margin-bottom: 8px;
123
- margin-top: 10px;
124
  }
125
  .form-horizontal .item_group .control-group {
126
  margin-bottom: 0;
@@ -163,6 +163,10 @@ p.code-description {
163
  background-color: #f6f6f6;
164
  border-color: #dddddd;
165
  }
 
 
 
 
166
  table.tbl_tbs_options {
167
  width: 100%;
168
  border: 1px solid transparent;
120
  .form-horizontal legend {
121
  border-bottom: 1px dashed #aaa;
122
  margin-bottom: 8px;
123
+ padding-top: 10px;
124
  }
125
  .form-horizontal .item_group .control-group {
126
  margin-bottom: 0;
163
  background-color: #f6f6f6;
164
  border-color: #dddddd;
165
  }
166
+ table.table th {
167
+ border-bottom: 1px solid #777777;
168
+ }
169
+
170
  table.tbl_tbs_options {
171
  width: 100%;
172
  border: 1px solid transparent;
src/config/feature-admin_access_restriction.txt CHANGED
@@ -4,6 +4,7 @@ properties:
4
  name: 'Admin Access Restriction'
5
  show_feature_menu_item: true
6
  storage_key: 'admin_access_restriction' # should correspond exactly to that in the plugin.yaml
 
7
  # Options Sections
8
  sections:
9
  -
4
  name: 'Admin Access Restriction'
5
  show_feature_menu_item: true
6
  storage_key: 'admin_access_restriction' # should correspond exactly to that in the plugin.yaml
7
+ menu_title: 'Admin Access'
8
  # Options Sections
9
  sections:
10
  -
src/config/feature-audit_trail.txt CHANGED
@@ -22,7 +22,7 @@ options:
22
  section: 'section_enable_plugin_feature_audit_trail'
23
  default: 'N'
24
  type: 'checkbox'
25
- link_info: ''
26
  link_blog: ''
27
  -
28
  key: 'enable_audit_context_users'
@@ -59,6 +59,13 @@ options:
59
  type: 'checkbox'
60
  link_info: ''
61
  link_blog: ''
 
 
 
 
 
 
 
62
  -
63
  key: 'enable_audit_context_wpsf'
64
  section: 'section_enable_audit_contexts'
@@ -73,3 +80,8 @@ options:
73
  key: 'audit_trail_table_name'
74
  section: 'section_non_ui'
75
  value: 'audit_trail'
 
 
 
 
 
22
  section: 'section_enable_plugin_feature_audit_trail'
23
  default: 'N'
24
  type: 'checkbox'
25
+ link_info: 'http://icwp.io/5p'
26
  link_blog: ''
27
  -
28
  key: 'enable_audit_context_users'
59
  type: 'checkbox'
60
  link_info: ''
61
  link_blog: ''
62
+ -
63
+ key: 'enable_audit_context_emails'
64
+ section: 'section_enable_audit_contexts'
65
+ default: 'Y'
66
+ type: 'checkbox'
67
+ link_info: ''
68
+ link_blog: ''
69
  -
70
  key: 'enable_audit_context_wpsf'
71
  section: 'section_enable_audit_contexts'
80
  key: 'audit_trail_table_name'
81
  section: 'section_non_ui'
82
  value: 'audit_trail'
83
+ menu_items:
84
+ -
85
+ slug: 'audit_trail_viewer'
86
+ title: 'Audit Trail Viewer'
87
+ callback: 'displayAuditTrailViewer'
src/config/feature-firewall.txt CHANGED
@@ -81,6 +81,13 @@ options:
81
  type: 'checkbox'
82
  link_info: ''
83
  link_blog: ''
 
 
 
 
 
 
 
84
  -
85
  key: 'block_response'
86
  section: 'section_choose_firewall_block_response'
@@ -143,13 +150,6 @@ options:
143
  type: 'ip_addresses'
144
  link_info: ''
145
  link_blog: ''
146
- -
147
- key: 'enable_firewall_log'
148
- section: 'section_firewall_logging'
149
- default: 'N'
150
- type: 'checkbox'
151
- link_info: ''
152
- link_blog: ''
153
  -
154
  key: 'current_plugin_version'
155
  section: 'section_non_ui'
81
  type: 'checkbox'
82
  link_info: ''
83
  link_blog: ''
84
+ -
85
+ key: 'block_leading_schema'
86
+ section: 'section_firewall_blocking_options'
87
+ default: 'N'
88
+ type: 'checkbox'
89
+ link_info: ''
90
+ link_blog: ''
91
  -
92
  key: 'block_response'
93
  section: 'section_choose_firewall_block_response'
150
  type: 'ip_addresses'
151
  link_info: ''
152
  link_blog: ''
 
 
 
 
 
 
 
153
  -
154
  key: 'current_plugin_version'
155
  section: 'section_non_ui'
src/config/feature-logging.txt DELETED
@@ -1,27 +0,0 @@
1
- ---
2
- slug: 'logging'
3
- properties:
4
- name: 'Logging'
5
- show_feature_menu_item: false
6
- storage_key: 'logging' # should correspond exactly to that in the plugin.yaml
7
- # Options Sections
8
- sections:
9
- -
10
- slug: 'section_non_ui'
11
- hidden: true
12
-
13
- # Define Options
14
- options:
15
- -
16
- key: 'enable_logging'
17
- section: 'section_non_ui'
18
- type: 'boolean'
19
- default: true
20
- -
21
- key: 'general_logging_table_name'
22
- section: 'section_non_ui'
23
- type: 'text'
24
- value: 'general_logging'
25
- -
26
- key: 'current_plugin_version'
27
- section: 'section_non_ui'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/config/feature-plugin.txt CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
- slug: 'plugin'
3
  properties:
 
4
  name: 'Dashboard'
5
  show_feature_menu_item: true
6
  storage_key: 'plugin' # should correspond exactly to that in the plugin.yaml
@@ -85,10 +85,8 @@ options:
85
  -
86
  slug: 'audit_trail'
87
  storage_key: 'audit_trail'
88
- hidden: true
 
89
  -
90
  slug: 'email'
91
  storage_key: 'email'
92
- -
93
- slug: 'logging'
94
- storage_key: 'logging'
1
  ---
 
2
  properties:
3
+ slug: 'plugin'
4
  name: 'Dashboard'
5
  show_feature_menu_item: true
6
  storage_key: 'plugin' # should correspond exactly to that in the plugin.yaml
85
  -
86
  slug: 'audit_trail'
87
  storage_key: 'audit_trail'
88
+ load_priority: 0
89
+ hidden: false
90
  -
91
  slug: 'email'
92
  storage_key: 'email'
 
 
 
src/icwp-options-vo.php CHANGED
@@ -146,6 +146,13 @@ class ICWP_WPSF_OptionsVO extends ICWP_WPSF_Foundation {
146
  return $aLegacyData;
147
  }
148
 
 
 
 
 
 
 
 
149
  /**
150
  * @return string
151
  */
@@ -237,6 +244,16 @@ class ICWP_WPSF_OptionsVO extends ICWP_WPSF_Foundation {
237
  return isset( $aAllRawOptions['options'] ) ? $aAllRawOptions['options'] : array();
238
  }
239
 
 
 
 
 
 
 
 
 
 
 
240
  /**
241
  * Return the section of the Raw config that is the "options" key only.
242
  *
146
  return $aLegacyData;
147
  }
148
 
149
+ /**
150
+ * @return array
151
+ */
152
+ public function getAdditionalMenuItems() {
153
+ return $this->getRawData_MenuItems();
154
+ }
155
+
156
  /**
157
  * @return string
158
  */
244
  return isset( $aAllRawOptions['options'] ) ? $aAllRawOptions['options'] : array();
245
  }
246
 
247
+ /**
248
+ * Return the section of the Raw config that is the "options" key only.
249
+ *
250
+ * @return array
251
+ */
252
+ protected function getRawData_MenuItems() {
253
+ $aAllRawOptions = $this->getRawData_FullFeatureConfig();
254
+ return isset( $aAllRawOptions['menu_items'] ) ? $aAllRawOptions['menu_items'] : array();
255
+ }
256
+
257
  /**
258
  * Return the section of the Raw config that is the "options" key only.
259
  *
src/icwp-optionshandler-admin_access_restriction.php CHANGED
@@ -28,11 +28,13 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
28
  */
29
  protected $oFeatureProcessor;
30
 
31
- public function __construct( $oPluginVo ) {
32
- $this->sFeatureName = _wpsf__('Admin Access');
33
- $this->sFeatureSlug = 'admin_access_restriction';
34
- parent::__construct( $oPluginVo );
35
-
 
 
36
  add_filter( $this->doPluginPrefix( 'has_permission_to_submit' ), array( $this, 'doCheckHasPermissionToSubmit' ) );
37
  add_filter( $this->doPluginPrefix( 'has_permission_to_view' ), array( $this, 'doCheckHasPermissionToSubmit' ) );
38
  }
@@ -42,7 +44,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
42
  */
43
  protected function loadFeatureProcessor() {
44
  if ( !isset( $this->oFeatureProcessor ) ) {
45
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
46
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_AdminAccessRestriction( $this );
47
  }
48
  return $this->oFeatureProcessor;
@@ -104,7 +106,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
104
  // We should only use setPermissionToSubmit() here, before any headers elsewhere are sent out.
105
  if ( $this->checkAdminAccessKeySubmission() ) {
106
  $this->setPermissionToSubmit( true );
107
- wp_safe_redirect( network_admin_url() );
108
  }
109
  }
110
 
@@ -176,7 +178,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
176
  switch( $sKey ) {
177
 
178
  case 'enable_admin_access_restriction' :
179
- $sName = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Admin Access') );
180
  $sSummary = _wpsf__( 'Enforce Admin Access Restriction' );
181
  $sDescription = _wpsf__( 'Enable this with great care and consideration. When this Access Key option is enabled, you must specify a key below and use it to gain access to this plugin.' );
182
  break;
@@ -213,11 +215,6 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
213
  $this->getOptionsVo()->resetOptToDefault( 'admin_access_timeout' );
214
  }
215
 
216
- $sNotificationEmail = $this->getOpt( 'enable_admin_login_email_notification' );
217
- if ( !empty( $sNotificationEmail ) && !is_email( $sNotificationEmail ) ) {
218
- $this->setOpt( 'enable_admin_login_email_notification', '' );
219
- }
220
-
221
  $sAccessKey = $this->getOpt( 'admin_access_key' );
222
  if ( empty( $sAccessKey ) ) {
223
  $this->setOpt( 'enable_admin_access_restriction', 'N' );
28
  */
29
  protected $oFeatureProcessor;
30
 
31
+ /**
32
+ * @param $oPluginVo
33
+ * @param array $aFeatureProperties
34
+ * @throws Exception
35
+ */
36
+ public function __construct( $oPluginVo, $aFeatureProperties = array() ) {
37
+ parent::__construct( $oPluginVo, $aFeatureProperties );
38
  add_filter( $this->doPluginPrefix( 'has_permission_to_submit' ), array( $this, 'doCheckHasPermissionToSubmit' ) );
39
  add_filter( $this->doPluginPrefix( 'has_permission_to_view' ), array( $this, 'doCheckHasPermissionToSubmit' ) );
40
  }
44
  */
45
  protected function loadFeatureProcessor() {
46
  if ( !isset( $this->oFeatureProcessor ) ) {
47
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
48
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_AdminAccessRestriction( $this );
49
  }
50
  return $this->oFeatureProcessor;
106
  // We should only use setPermissionToSubmit() here, before any headers elsewhere are sent out.
107
  if ( $this->checkAdminAccessKeySubmission() ) {
108
  $this->setPermissionToSubmit( true );
109
+ // wp_safe_redirect( network_admin_url() );
110
  }
111
  }
112
 
178
  switch( $sKey ) {
179
 
180
  case 'enable_admin_access_restriction' :
181
+ $sName = sprintf( _wpsf__( 'Enable %s' ), _wpsf__('Admin Access') );
182
  $sSummary = _wpsf__( 'Enforce Admin Access Restriction' );
183
  $sDescription = _wpsf__( 'Enable this with great care and consideration. When this Access Key option is enabled, you must specify a key below and use it to gain access to this plugin.' );
184
  break;
215
  $this->getOptionsVo()->resetOptToDefault( 'admin_access_timeout' );
216
  }
217
 
 
 
 
 
 
218
  $sAccessKey = $this->getOpt( 'admin_access_key' );
219
  if ( empty( $sAccessKey ) ) {
220
  $this->setOpt( 'enable_admin_access_restriction', 'N' );
src/icwp-optionshandler-audit_trail.php CHANGED
@@ -26,18 +26,12 @@ class ICWP_WPSF_FeatureHandler_AuditTrail_V1 extends ICWP_WPSF_FeatureHandler_Ba
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- public function __construct( $oPluginVo ) {
30
- $this->sFeatureName = _wpsf__('Audit Trail');
31
- $this->sFeatureSlug = 'audit_trail';
32
- parent::__construct( $oPluginVo );
33
- }
34
-
35
  /**
36
- * @return ICWP_WPSF_Processor_Autoupdates|null
37
  */
38
  protected function loadFeatureProcessor() {
39
  if ( !isset( $this->oFeatureProcessor ) ) {
40
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
41
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_AuditTrail( $this );
42
  }
43
  return $this->oFeatureProcessor;
@@ -50,6 +44,22 @@ class ICWP_WPSF_FeatureHandler_AuditTrail_V1 extends ICWP_WPSF_FeatureHandler_Ba
50
 
51
  public function doPrePluginOptionsSave() {}
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  /**
54
  * @return string
55
  */
@@ -107,31 +117,37 @@ class ICWP_WPSF_FeatureHandler_AuditTrail_V1 extends ICWP_WPSF_FeatureHandler_Ba
107
  case 'enable_audit_context_plugins' :
108
  $sName = _wpsf__( 'Plugins' );
109
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Plugins' ) );
110
- $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
111
  break;
112
 
113
  case 'enable_audit_context_themes' :
114
  $sName = _wpsf__( 'Themes' );
115
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Themes' ) );
116
- $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
117
  break;
118
 
119
  case 'enable_audit_context_posts' :
120
  $sName = _wpsf__( 'Posts And Pages' );
121
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Posts And Pages' ) );
122
- $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
123
  break;
124
 
125
  case 'enable_audit_context_wordpress' :
126
  $sName = _wpsf__( 'WordPress And Settings' );
127
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'WordPress And Settings' ) );
128
- $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
 
 
 
 
 
 
129
  break;
130
 
131
  case 'enable_audit_context_wpsf' :
132
  $sName = _wpsf__( 'Simple Firewall' );
133
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Simple Firewall' ) );
134
- $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track user activity and significant events such as user login etc.' );
135
  break;
136
 
137
  default:
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
29
  /**
30
+ * @return ICWP_WPSF_Processor_AuditTrail|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_AuditTrail( $this );
36
  }
37
  return $this->oFeatureProcessor;
44
 
45
  public function doPrePluginOptionsSave() {}
46
 
47
+ public function displayAuditTrailViewer() {
48
+
49
+ $oAuditTrail = $this->loadFeatureProcessor();
50
+ $aData = array(
51
+ 'nYourIp' => $this->loadDataProcessor()->GetVisitorIpAddress(),
52
+ 'sFeatureName' => _wpsf__('Audit Trail Viewer'),
53
+ 'aAuditDataUsers' => $oAuditTrail->getAuditEntriesForContext( 'users' ),
54
+ 'aAuditDataPlugins' => $oAuditTrail->getAuditEntriesForContext( 'plugins' ),
55
+ 'aAuditDataThemes' => $oAuditTrail->getAuditEntriesForContext( 'themes' ),
56
+ 'aAuditDataWordpress' => $oAuditTrail->getAuditEntriesForContext( 'wordpress' ),
57
+ 'aAuditDataPosts' => $oAuditTrail->getAuditEntriesForContext( 'posts' ),
58
+ 'aAuditDataEmails' => $oAuditTrail->getAuditEntriesForContext( 'emails' ),
59
+ 'aAuditDataWpsf' => $oAuditTrail->getAuditEntriesForContext( 'wpsf' )
60
+ );
61
+ $this->display( $aData, $this->doPluginPrefix( 'audit_trail_viewer_index' ) );
62
+ }
63
  /**
64
  * @return string
65
  */
117
  case 'enable_audit_context_plugins' :
118
  $sName = _wpsf__( 'Plugins' );
119
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Plugins' ) );
120
+ $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track activity relating to WordPress plugins.' );
121
  break;
122
 
123
  case 'enable_audit_context_themes' :
124
  $sName = _wpsf__( 'Themes' );
125
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Themes' ) );
126
+ $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track activity relating to WordPress themes.' );
127
  break;
128
 
129
  case 'enable_audit_context_posts' :
130
  $sName = _wpsf__( 'Posts And Pages' );
131
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Posts And Pages' ) );
132
+ $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track activity relating to the editing and publishing of posts and pages.' );
133
  break;
134
 
135
  case 'enable_audit_context_wordpress' :
136
  $sName = _wpsf__( 'WordPress And Settings' );
137
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'WordPress And Settings' ) );
138
+ $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track WordPress upgrades and changes to particular WordPress settings.' );
139
+ break;
140
+
141
+ case 'enable_audit_context_emails' :
142
+ $sName = _wpsf__( 'Emails' );
143
+ $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Emails' ) );
144
+ $sDescription = _wpsf__( 'When this context is enabled, the audit trail will attempt to track attempts at sending email.' );
145
  break;
146
 
147
  case 'enable_audit_context_wpsf' :
148
  $sName = _wpsf__( 'Simple Firewall' );
149
  $sSummary = sprintf( _wpsf__( 'Enable Audit Context - %s' ), _wpsf__( 'Simple Firewall' ) );
150
+ $sDescription = _wpsf__( 'When this context is enabled, the audit trail will track activity directly related to the WordPress Simple Firewall plugin.' );
151
  break;
152
 
153
  default:
src/icwp-optionshandler-autoupdates.php CHANGED
@@ -26,18 +26,12 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Autoupdates_V3') ):
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- public function __construct( $oPluginVo ) {
30
- $this->sFeatureName = _wpsf__('Automatic Updates');
31
- $this->sFeatureSlug = 'autoupdates';
32
- parent::__construct( $oPluginVo );
33
- }
34
-
35
  /**
36
  * @return ICWP_WPSF_Processor_Autoupdates|null
37
  */
38
  protected function loadFeatureProcessor() {
39
  if ( !isset( $this->oFeatureProcessor ) ) {
40
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
41
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Autoupdates( $this );
42
  }
43
  return $this->oFeatureProcessor;
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
29
  /**
30
  * @return ICWP_WPSF_Processor_Autoupdates|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Autoupdates( $this );
36
  }
37
  return $this->oFeatureProcessor;
src/icwp-optionshandler-base.php CHANGED
@@ -69,11 +69,6 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
69
  */
70
  protected static $oEmailHandler;
71
 
72
- /**
73
- * @var ICWP_WPSF_FeatureHandler_Email
74
- */
75
- protected static $oLoggingHandler;
76
-
77
  /**
78
  * @var ICWP_WPSF_Processor_Base
79
  */
@@ -84,23 +79,32 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
84
  */
85
  protected $fOverrideState;
86
 
87
- public function __construct( $oPluginController, $sOptionsStoreKey = null ) {
 
 
 
 
 
88
  if ( empty( $oPluginController ) ) {
89
  throw new Exception();
90
  }
91
  $this->oPluginController = $oPluginController;
92
- $this->sOptionsStoreKey = $this->prefixOptionKey(
93
- ( is_null( $sOptionsStoreKey ) ? $this->getFeatureSlug() : $sOptionsStoreKey )
94
- .'_options'
95
- );
96
 
 
 
 
 
 
 
 
 
 
97
  // Handle any upgrades as necessary (only go near this if it's the admin area)
98
- add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
99
  add_action( 'init', array( $this, 'onWpInit' ), 1 );
100
  add_action( $this->doPluginPrefix( 'form_submit' ), array( $this, 'handleFormSubmit' ) );
101
  add_filter( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addPluginSubMenuItem' ) );
102
  add_filter( $this->doPluginPrefix( 'get_feature_summary_data' ), array( $this, 'filter_getFeatureSummaryData' ) );
103
- add_filter( $this->doPluginPrefix( 'flush_logs' ), array( $this, 'filter_flushFeatureLogs' ) );
104
  add_action( $this->doPluginPrefix( 'plugin_shutdown' ), array( $this, 'action_doFeatureShutdown' ) );
105
  add_action( $this->doPluginPrefix( 'delete_plugin' ), array( $this, 'deletePluginOptions' ) );
106
  add_filter( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array( $this, 'aggregateOptionsValues' ) );
@@ -154,28 +158,28 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
154
  * Hooked to the plugin's main plugin_shutdown action
155
  */
156
  public function action_doFeatureShutdown() {
157
-
158
- if ( ! $this->fPluginDeleting ) {
159
  $this->savePluginOptions();
160
-
161
- if ( $this->getController()->getIsLoggingEnabled() ) {
162
- $aLogData = apply_filters( $this->doPluginPrefix( 'flush_logs' ), array() );
163
- $oLoggingProcessor = $this->getLoggingProcessor();
164
- $oLoggingProcessor->addDataToWrite( $aLogData );
165
- $oLoggingProcessor->commitData();
166
- }
167
  }
168
  }
169
 
 
 
 
 
 
 
 
170
  /**
171
  * @return string
172
  */
173
  protected function getOptionsStorageKey() {
174
  if ( !isset( $this->sOptionsStoreKey ) ) {
175
  // not ideal as it doesn't take into account custom storage keys as when passed into the constructor
176
- $this->sOptionsStoreKey = $this->prefixOptionKey( $this->getFeatureSlug().'_options' );
177
  }
178
- return $this->sOptionsStoreKey;
 
179
  }
180
 
181
  /**
@@ -190,7 +194,7 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
190
  */
191
  public function getEmailHandler() {
192
  if ( is_null( self::$oEmailHandler ) ) {
193
- self::$oEmailHandler = new ICWP_WPSF_FeatureHandler_Email( $this->getController() );
194
  }
195
  return self::$oEmailHandler;
196
  }
@@ -202,24 +206,6 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
202
  return $this->getEmailHandler()->getProcessor();
203
  }
204
 
205
- /**
206
- * @return ICWP_WPSF_FeatureHandler_Logging
207
- */
208
- public function getLoggingHandler() {
209
- if ( is_null( self::$oLoggingHandler ) ) {
210
- require_once( 'icwp-optionshandler-logging.php' );
211
- self::$oLoggingHandler = new ICWP_WPSF_FeatureHandler_Logging( $this->getController() );
212
- }
213
- return self::$oLoggingHandler;
214
- }
215
-
216
- /**
217
- * @return ICWP_WPSF_Processor_Logging
218
- */
219
- public function getLoggingProcessor() {
220
- return $this->getLoggingHandler()->getProcessor();
221
- }
222
-
223
  /**
224
  * @param $fEnable
225
  */
@@ -261,6 +247,9 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
261
  * @return string
262
  */
263
  protected function getMainFeatureName() {
 
 
 
264
  return $this->sFeatureName;
265
  }
266
 
@@ -275,6 +264,9 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
275
  * @return string
276
  */
277
  public function getFeatureSlug() {
 
 
 
278
  return $this->sFeatureSlug;
279
  }
280
 
@@ -288,36 +280,51 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
288
  }
289
 
290
  /**
291
- * @param array $aLogs
292
  * @return array
293
  */
294
- public function filter_flushFeatureLogs( $aLogs ) {
295
- if ( $this->getIsMainFeatureEnabled() ) {
296
- $aFeatureLogs = $this->getProcessor()->flushLogData();
297
- if ( !empty( $aFeatureLogs ) ) {
298
- $aLogs = array_merge( $aLogs, $aFeatureLogs );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  }
300
  }
301
- return $aLogs;
302
  }
303
 
304
  /**
305
- * @param array $aItems
306
  * @return array
307
  */
308
- public function filter_addPluginSubMenuItem( $aItems ) {
309
- $sName = $this->getMainFeatureName();
310
- if ( !$this->getIfShowFeatureMenuItem() || empty( $sName ) ) {
311
- return $aItems;
312
- }
313
-
314
- $sMenuPageTitle = $this->getController()->getHumanName().' - '.$sName;
315
- $aItems[ $sMenuPageTitle ] = array(
316
- $sName,
317
- $this->doPluginPrefix( $this->getFeatureSlug() ),
318
- array( $this, 'displayFeatureConfigPage' )
319
- );
320
- return $aItems;
321
  }
322
 
323
  /**
@@ -782,18 +789,11 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
782
 
783
  /**
784
  */
785
- public function displayFeatureConfigPage( ) {
786
-
787
- if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_view' ), true ) ) {
788
- $this->displayViewAccessRestrictedPage();
789
- return;
790
- }
791
-
792
  // $aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
793
  $aData = array(
794
  'aSummaryData' => isset( $aPluginSummaryData ) ? $aPluginSummaryData : array()
795
  );
796
- $aData = array_merge( $this->getBaseDisplayData(), $aData );
797
  $this->display( $aData );
798
  }
799
 
@@ -805,13 +805,6 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
805
  return $oWpFunctions->getCurrentWpAdminPage() == $this->doPluginPrefix( $this->getFeatureSlug() );
806
  }
807
 
808
- /**
809
- */
810
- public function displayViewAccessRestrictedPage( ) {
811
- $aData = $this->getBaseDisplayData();
812
- $this->display( $aData, 'access_restricted_index' );
813
- }
814
-
815
  /**
816
  * @return array
817
  */
@@ -845,14 +838,22 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
845
  */
846
  protected function display( $aData = array(), $sView = '' ) {
847
 
 
 
 
 
 
 
 
 
848
  if ( empty( $sView ) ) {
849
  $oWpFs = $this->loadFileSystemProcessor();
850
- $sCustomViewSource = $this->getController()->getViewPath( $this->doPluginPrefix( 'config_'.$this->getFeatureSlug().'_index' ) );
851
- $sNormalViewSource = $this->getController()->getViewPath( $this->doPluginPrefix( 'config_index' ) );
852
  $sFile = $oWpFs->exists( $sCustomViewSource ) ? $sCustomViewSource : $sNormalViewSource;
853
  }
854
  else {
855
- $sFile = $this->getController()->getViewPath( $this->doPluginPrefix( $sView ) );
856
  }
857
 
858
  if ( !is_file( $sFile ) ) {
@@ -878,7 +879,7 @@ if ( !class_exists('ICWP_WPSF_FeatureHandler_Base_V2') ):
878
  * @return string
879
  */
880
  public function getViewSnippet( $sSnippet = '' ) {
881
- return $this->getController()->getViewSnippet( $sSnippet );
882
  }
883
 
884
  /**
69
  */
70
  protected static $oEmailHandler;
71
 
 
 
 
 
 
72
  /**
73
  * @var ICWP_WPSF_Processor_Base
74
  */
79
  */
80
  protected $fOverrideState;
81
 
82
+ /**
83
+ * @param ICWP_WPSF_Plugin_Controller $oPluginController
84
+ * @param array $aFeatureProperties
85
+ * @throws Exception
86
+ */
87
+ public function __construct( $oPluginController, $aFeatureProperties = array() ) {
88
  if ( empty( $oPluginController ) ) {
89
  throw new Exception();
90
  }
91
  $this->oPluginController = $oPluginController;
 
 
 
 
92
 
93
+ if ( isset( $aFeatureProperties['storage_key'] ) ) {
94
+ $this->sOptionsStoreKey = $aFeatureProperties['storage_key'];
95
+ }
96
+
97
+ if ( isset( $aFeatureProperties['slug'] ) ) {
98
+ $this->sFeatureSlug = $aFeatureProperties['slug'];
99
+ }
100
+
101
+ $nRunPriority = isset( $aFeatureProperties['load_priority'] ) ? $aFeatureProperties['load_priority'] : 100;
102
  // Handle any upgrades as necessary (only go near this if it's the admin area)
103
+ add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ), $nRunPriority );
104
  add_action( 'init', array( $this, 'onWpInit' ), 1 );
105
  add_action( $this->doPluginPrefix( 'form_submit' ), array( $this, 'handleFormSubmit' ) );
106
  add_filter( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addPluginSubMenuItem' ) );
107
  add_filter( $this->doPluginPrefix( 'get_feature_summary_data' ), array( $this, 'filter_getFeatureSummaryData' ) );
 
108
  add_action( $this->doPluginPrefix( 'plugin_shutdown' ), array( $this, 'action_doFeatureShutdown' ) );
109
  add_action( $this->doPluginPrefix( 'delete_plugin' ), array( $this, 'deletePluginOptions' ) );
110
  add_filter( $this->doPluginPrefix( 'aggregate_all_plugin_options' ), array( $this, 'aggregateOptionsValues' ) );
158
  * Hooked to the plugin's main plugin_shutdown action
159
  */
160
  public function action_doFeatureShutdown() {
161
+ if ( ! $this->getIsPluginDeleting() ) {
 
162
  $this->savePluginOptions();
 
 
 
 
 
 
 
163
  }
164
  }
165
 
166
+ /**
167
+ * @return bool
168
+ */
169
+ public function getIsPluginDeleting() {
170
+ return $this->fPluginDeleting;
171
+ }
172
+
173
  /**
174
  * @return string
175
  */
176
  protected function getOptionsStorageKey() {
177
  if ( !isset( $this->sOptionsStoreKey ) ) {
178
  // not ideal as it doesn't take into account custom storage keys as when passed into the constructor
179
+ $this->sOptionsStoreKey = $this->getOptionsVo()->getFeatureProperty( 'storage_key' );
180
  }
181
+
182
+ return $this->prefixOptionKey( $this->sOptionsStoreKey ).'_options' ;
183
  }
184
 
185
  /**
194
  */
195
  public function getEmailHandler() {
196
  if ( is_null( self::$oEmailHandler ) ) {
197
+ self::$oEmailHandler = $this->getController()->loadFeatureHandler( array( 'slug' => 'email' ) );
198
  }
199
  return self::$oEmailHandler;
200
  }
206
  return $this->getEmailHandler()->getProcessor();
207
  }
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  /**
210
  * @param $fEnable
211
  */
247
  * @return string
248
  */
249
  protected function getMainFeatureName() {
250
+ if ( !isset( $this->sFeatureName ) ) {
251
+ $this->sFeatureName = $this->getOptionsVo()->getFeatureProperty( 'name' );
252
+ }
253
  return $this->sFeatureName;
254
  }
255
 
264
  * @return string
265
  */
266
  public function getFeatureSlug() {
267
+ if ( !isset( $this->sFeatureSlug ) ) {
268
+ $this->sFeatureSlug = $this->getOptionsVo()->getFeatureProperty( 'slug' );
269
+ }
270
  return $this->sFeatureSlug;
271
  }
272
 
280
  }
281
 
282
  /**
283
+ * @param array $aItems
284
  * @return array
285
  */
286
+ public function filter_addPluginSubMenuItem( $aItems ) {
287
+ $sMenuTitleName = $this->getOptionsVo()->getFeatureProperty( 'menu_title' );
288
+ if ( is_null( $sMenuTitleName ) ) {
289
+ $sMenuTitleName = $this->getMainFeatureName();
290
+ }
291
+ if ( $this->getIfShowFeatureMenuItem() && !empty( $sMenuTitleName ) ) {
292
+
293
+ $sHumanName = $this->getController()->getHumanName();
294
+
295
+ $sMenuPageTitle = $sHumanName.' - '.$sMenuTitleName;
296
+ $aItems[ $sMenuPageTitle ] = array(
297
+ $sMenuTitleName,
298
+ $this->doPluginPrefix( $this->getFeatureSlug() ),
299
+ array( $this, 'displayFeatureConfigPage' )
300
+ );
301
+
302
+ $aAdditionalItems = $this->getOptionsVo()->getAdditionalMenuItems();
303
+ if ( !empty( $aAdditionalItems ) && is_array( $aAdditionalItems ) ) {
304
+
305
+ foreach( $aAdditionalItems as $aMenuItem ) {
306
+
307
+ if ( empty( $aMenuItem['callback'] ) || !method_exists( $this, $aMenuItem['callback'] ) ) {
308
+ continue;
309
+ }
310
+
311
+ $sMenuPageTitle = $sHumanName.' - '.$aMenuItem['title'];
312
+ $aItems[ $sMenuPageTitle ] = array(
313
+ $aMenuItem['title'],
314
+ $this->doPluginPrefix( $aMenuItem['slug'] ),
315
+ array( $this, $aMenuItem['callback'] )
316
+ );
317
+ }
318
  }
319
  }
320
+ return $aItems;
321
  }
322
 
323
  /**
 
324
  * @return array
325
  */
326
+ protected function getAdditionalMenuItem() {
327
+ return array();
 
 
 
 
 
 
 
 
 
 
 
328
  }
329
 
330
  /**
789
 
790
  /**
791
  */
792
+ public function displayFeatureConfigPage() {
 
 
 
 
 
 
793
  // $aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
794
  $aData = array(
795
  'aSummaryData' => isset( $aPluginSummaryData ) ? $aPluginSummaryData : array()
796
  );
 
797
  $this->display( $aData );
798
  }
799
 
805
  return $oWpFunctions->getCurrentWpAdminPage() == $this->doPluginPrefix( $this->getFeatureSlug() );
806
  }
807
 
 
 
 
 
 
 
 
808
  /**
809
  * @return array
810
  */
838
  */
839
  protected function display( $aData = array(), $sView = '' ) {
840
 
841
+ // Get Base Data
842
+ $aData = array_merge( $this->getBaseDisplayData(), $aData );
843
+ $fPermissionToView = apply_filters( $this->doPluginPrefix( 'has_permission_to_view' ), true );
844
+
845
+ if ( !$fPermissionToView ) {
846
+ $sView = 'access_restricted_index';
847
+ }
848
+
849
  if ( empty( $sView ) ) {
850
  $oWpFs = $this->loadFileSystemProcessor();
851
+ $sCustomViewSource = $this->getController()->getPath_ViewsFile( $this->doPluginPrefix( 'config_'.$this->getFeatureSlug().'_index' ) );
852
+ $sNormalViewSource = $this->getController()->getPath_ViewsFile( $this->doPluginPrefix( 'config_index' ) );
853
  $sFile = $oWpFs->exists( $sCustomViewSource ) ? $sCustomViewSource : $sNormalViewSource;
854
  }
855
  else {
856
+ $sFile = $this->getController()->getPath_ViewsFile( $this->doPluginPrefix( $sView ) );
857
  }
858
 
859
  if ( !is_file( $sFile ) ) {
879
  * @return string
880
  */
881
  public function getViewSnippet( $sSnippet = '' ) {
882
+ return $this->getController()->getPath_ViewsSnippet( $sSnippet );
883
  }
884
 
885
  /**
src/icwp-optionshandler-comments_filter.php CHANGED
@@ -26,18 +26,12 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- public function __construct( $oPluginVo ) {
30
- $this->sFeatureName = _wpsf__('Comments Filter');
31
- $this->sFeatureSlug = 'comments_filter';
32
- parent::__construct( $oPluginVo, 'commentsfilter' ); //TODO: align this naming with the feature slug etc. as with the other features.
33
- }
34
-
35
  /**
36
  * @return ICWP_WPSF_Processor_CommentsFilter|null
37
  */
38
  protected function loadFeatureProcessor() {
39
  if ( !isset( $this->oFeatureProcessor ) ) {
40
- require_once( $this->getController()->getSourceDir().sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) );
41
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_CommentsFilter( $this );
42
  }
43
  return $this->oFeatureProcessor;
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
29
  /**
30
  * @return ICWP_WPSF_Processor_CommentsFilter|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile().sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_CommentsFilter( $this );
36
  }
37
  return $this->oFeatureProcessor;
src/icwp-optionshandler-email.php CHANGED
@@ -26,26 +26,24 @@ class ICWP_WPSF_FeatureHandler_Email extends ICWP_WPSF_FeatureHandler_Base {
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- /**
30
- * @param $oPluginVo
31
- */
32
- public function __construct( $oPluginVo ) {
33
- $this->sFeatureName = _wpsf__('Email');
34
- $this->sFeatureSlug = 'email';
35
- parent::__construct( $oPluginVo );
36
- }
37
-
38
  /**
39
  * @return ICWP_WPSF_Processor_Email|null
40
  */
41
  protected function loadFeatureProcessor() {
42
  if ( !isset( $this->oFeatureProcessor ) ) {
43
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
44
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Email( $this );
45
  }
46
  return $this->oFeatureProcessor;
47
  }
48
 
 
 
 
 
 
 
 
49
  /**
50
  * @param array $aOptionsParams
51
  * @return array
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
 
 
 
29
  /**
30
  * @return ICWP_WPSF_Processor_Email|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Email( $this );
36
  }
37
  return $this->oFeatureProcessor;
38
  }
39
 
40
+ /**
41
+ * @return mixed
42
+ */
43
+ public function getIsMainFeatureEnabled() {
44
+ return true;
45
+ }
46
+
47
  /**
48
  * @param array $aOptionsParams
49
  * @return array
src/icwp-optionshandler-firewall.php CHANGED
@@ -26,18 +26,12 @@ class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- public function __construct( $oPluginVo ) {
30
- $this->sFeatureName = _wpsf__('Firewall');
31
- $this->sFeatureSlug = 'firewall';
32
- parent::__construct( $oPluginVo );
33
- }
34
-
35
  /**
36
  * @return ICWP_WPSF_Processor_Firewall|null
37
  */
38
  protected function loadFeatureProcessor() {
39
  if ( !isset( $this->oFeatureProcessor ) ) {
40
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
41
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Firewall( $this );
42
  }
43
  return $this->oFeatureProcessor;
@@ -247,17 +241,10 @@ class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_Base {
247
  protected function doExtraSubmitProcessing() {
248
  $oDp = $this->loadDataProcessor();
249
 
250
- if ( $oDp->FetchPost( 'clear_log_submit' ) ) {
251
- $oLoggingProcessor = $this->getLoggingProcessor();
252
- $oLoggingProcessor->recreateTable();
253
- return true;
254
- }
255
-
256
  $this->addRawIpsToFirewallList( 'ips_whitelist', array( $oDp->FetchGet( 'whiteip' ) ) );
257
  $this->removeRawIpsFromFirewallList( 'ips_whitelist', array( $oDp->FetchGet( 'unwhiteip' ) ) );
258
  $this->addRawIpsToFirewallList( 'ips_blacklist', array( $oDp->FetchGet( 'blackip' ) ) );
259
  $this->removeRawIpsFromFirewallList( 'ips_blacklist', array( $oDp->FetchGet( 'unblackip' ) ) );
260
-
261
  return true;
262
  }
263
 
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
29
  /**
30
  * @return ICWP_WPSF_Processor_Firewall|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Firewall( $this );
36
  }
37
  return $this->oFeatureProcessor;
241
  protected function doExtraSubmitProcessing() {
242
  $oDp = $this->loadDataProcessor();
243
 
 
 
 
 
 
 
244
  $this->addRawIpsToFirewallList( 'ips_whitelist', array( $oDp->FetchGet( 'whiteip' ) ) );
245
  $this->removeRawIpsFromFirewallList( 'ips_whitelist', array( $oDp->FetchGet( 'unwhiteip' ) ) );
246
  $this->addRawIpsToFirewallList( 'ips_blacklist', array( $oDp->FetchGet( 'blackip' ) ) );
247
  $this->removeRawIpsFromFirewallList( 'ips_blacklist', array( $oDp->FetchGet( 'unblackip' ) ) );
 
248
  return true;
249
  }
250
 
src/icwp-optionshandler-lockdown.php CHANGED
@@ -26,21 +26,12 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_Base {
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- /**
30
- * @param $oPluginVo
31
- */
32
- public function __construct( $oPluginVo ) {
33
- $this->sFeatureName = _wpsf__('Lockdown');
34
- $this->sFeatureSlug = 'lockdown';
35
- parent::__construct( $oPluginVo );
36
- }
37
-
38
  /**
39
  * @return ICWP_WPSF_Processor_Lockdown|null
40
  */
41
  protected function loadFeatureProcessor() {
42
  if ( !isset( $this->oFeatureProcessor ) ) {
43
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
44
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Lockdown( $this );
45
  }
46
  return $this->oFeatureProcessor;
@@ -48,12 +39,12 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_Base {
48
 
49
  public function doPrePluginOptionsSave() {
50
 
51
- if ( $this->getOpt( 'action_reset_auth_salts' ) == 'Y' ) {
52
- $this->setOpt( 'action_reset_auth_salts', 'P' );
53
- }
54
- else if ( $this->getOpt( 'action_reset_auth_salts' ) == 'P' ) {
55
- $this->setOpt( 'action_reset_auth_salts', 'N' );
56
- }
57
 
58
  $sCurrent = $this->getOpt( 'mask_wordpress_version' );
59
  if ( !empty( $sCurrent ) ) {
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
 
 
 
29
  /**
30
  * @return ICWP_WPSF_Processor_Lockdown|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Lockdown( $this );
36
  }
37
  return $this->oFeatureProcessor;
39
 
40
  public function doPrePluginOptionsSave() {
41
 
42
+ // if ( $this->getOpt( 'action_reset_auth_salts' ) == 'Y' ) {
43
+ // $this->setOpt( 'action_reset_auth_salts', 'P' );
44
+ // }
45
+ // else if ( $this->getOpt( 'action_reset_auth_salts' ) == 'P' ) {
46
+ // $this->setOpt( 'action_reset_auth_salts', 'N' );
47
+ // }
48
 
49
  $sCurrent = $this->getOpt( 'mask_wordpress_version' );
50
  if ( !empty( $sCurrent ) ) {
src/icwp-optionshandler-logging.php DELETED
@@ -1,105 +0,0 @@
1
- <?php
2
- /**
3
- * Copyright (c) 2014 iControlWP <support@icontrolwp.com>
4
- * All rights reserved.
5
- *
6
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
10
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
13
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
- */
17
-
18
- require_once( dirname(__FILE__).'/icwp-optionshandler-base.php' );
19
-
20
- if ( !class_exists('ICWP_WPSF_FeatureHandler_Logging') ):
21
-
22
- class ICWP_WPSF_FeatureHandler_Logging extends ICWP_WPSF_FeatureHandler_Base {
23
-
24
- /**
25
- * @var ICWP_WPSF_Processor_Logging
26
- */
27
- protected $oFeatureProcessor;
28
-
29
- /**
30
- * @param $oPluginVo
31
- */
32
- public function __construct( $oPluginVo ) {
33
- $this->sFeatureName = _wpsf__('Logging');
34
- $this->sFeatureSlug = 'logging';
35
- parent::__construct( $oPluginVo );
36
- }
37
-
38
- /**
39
- * @return ICWP_WPSF_Processor_Logging|null
40
- */
41
- protected function loadFeatureProcessor() {
42
-
43
- if ( !isset( $this->oFeatureProcessor ) ) {
44
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
45
- $this->oFeatureProcessor = new ICWP_WPSF_Processor_Logging( $this );
46
- }
47
- return $this->oFeatureProcessor;
48
- }
49
-
50
- /**
51
- * @param array $aOptionsParams
52
- * @return array
53
- * @throws Exception
54
- */
55
- protected function loadStrings_SectionTitles( $aOptionsParams ) {
56
-
57
- $sSectionSlug = $aOptionsParams['section_slug'];
58
- switch( $aOptionsParams['section_slug'] ) {
59
-
60
- case 'section_logging_options' :
61
- $sTitle = sprintf( _wpsf__( 'Enable Plugin Feature: %s' ), _wpsf__('Logging') );
62
- break;
63
-
64
- default:
65
- throw new Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
66
- }
67
- $aOptionsParams['section_title'] = $sTitle;
68
- return $aOptionsParams;
69
- }
70
-
71
- /**
72
- * @param array $aOptionsParams
73
- * @return array
74
- * @throws Exception
75
- */
76
- protected function loadStrings_Options( $aOptionsParams ) {
77
-
78
- $sKey = $aOptionsParams['key'];
79
- switch( $sKey ) {
80
-
81
- case 'enable_logging' :
82
- $sName = sprintf( _wpsf__( 'Enable %s' ), $this->getMainFeatureName() );
83
- $sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Feature' ), $this->getMainFeatureName() );
84
- $sDescription = sprintf( _wpsf__( 'Checking/Un-Checking this option will completely turn on/off the whole %s feature.' ), $this->getMainFeatureName() );
85
- break;
86
-
87
- default:
88
- throw new Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
89
- }
90
-
91
- $aOptionsParams['name'] = $sName;
92
- $aOptionsParams['summary'] = $sSummary;
93
- $aOptionsParams['description'] = $sDescription;
94
- return $aOptionsParams;
95
- }
96
-
97
- /**
98
- * @return string
99
- */
100
- public function getGeneralLoggingTableName() {
101
- return $this->doPluginPrefix( $this->getOpt( 'general_logging_table_name' ), '_' );
102
- }
103
- }
104
-
105
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/icwp-optionshandler-login_protect.php CHANGED
@@ -26,18 +26,12 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- public function __construct( $oPluginVo ) {
30
- $this->sFeatureName = _wpsf__('Login Protection');
31
- $this->sFeatureSlug = 'login_protect';
32
- parent::__construct( $oPluginVo, 'loginprotect' ); //TODO: align this naming with the feature slug etc. as with the other features.
33
- }
34
-
35
  /**
36
  * @return ICWP_WPSF_Processor_LoginProtect|null
37
  */
38
  protected function loadFeatureProcessor() {
39
  if ( !isset( $this->oFeatureProcessor ) ) {
40
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
41
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_LoginProtect( $this );
42
  }
43
  return $this->oFeatureProcessor;
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
29
  /**
30
  * @return ICWP_WPSF_Processor_LoginProtect|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_LoginProtect( $this );
36
  }
37
  return $this->oFeatureProcessor;
src/icwp-optionshandler-plugin.php CHANGED
@@ -26,10 +26,8 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- public function __construct( $oPluginVo ) {
30
- $this->sFeatureName = _wpsf__('Dashboard');
31
- $this->sFeatureSlug = 'plugin';
32
- parent::__construct( $oPluginVo, 'plugin' );
33
 
34
  add_action( 'deactivate_plugin', array( $this, 'onWpHookDeactivatePlugin' ), 1, 1 );
35
  add_filter( $this->doPluginPrefix( 'report_email_address' ), array( $this, 'getPluginReportEmail' ) );
@@ -40,7 +38,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
40
  */
41
  protected function loadFeatureProcessor() {
42
  if ( !isset( $this->oFeatureProcessor ) ) {
43
- require_once( $this->getController()->getSourceDir().'icwp-processor-plugin.php' );
44
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Plugin( $this );
45
  }
46
  return $this->oFeatureProcessor;
@@ -75,11 +73,11 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
75
  return $aPluginFeatures;
76
  }
77
 
78
- foreach( $aActiveFeatures['value'] as $aFeature ) {
79
  if ( isset( $aFeature['hidden'] ) && $aFeature['hidden'] ) {
80
  continue;
81
  }
82
- $aPluginFeatures[ $aFeature['slug'] ] = $aFeature['storage_key'];
83
  }
84
  return $aPluginFeatures;
85
  }
@@ -102,18 +100,10 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
102
  /**
103
  */
104
  public function displayFeatureConfigPage( ) {
105
-
106
- if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_view' ), true ) ) {
107
- $this->displayViewAccessRestrictedPage();
108
- return;
109
- }
110
-
111
  $aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
112
-
113
  $aData = array(
114
  'aSummaryData' => $aPluginSummaryData
115
  );
116
- $aData = array_merge( $this->getBaseDisplayData(), $aData );
117
  $this->display( $aData );
118
  }
119
 
@@ -209,8 +199,6 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
209
  */
210
  protected function doPrePluginOptionsSave() {
211
 
212
- $this->setOpt( 'enable_logging', 'Y' );
213
-
214
  $nInstalledAt = $this->getOpt( 'installation_time' );
215
  if ( empty($nInstalledAt) || $nInstalledAt <= 0 ) {
216
  $this->setOpt( 'installation_time', time() );
@@ -243,6 +231,21 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_Base {
243
  $wpdb->query( $sQuery );
244
  }
245
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
  }
248
 
26
  */
27
  protected $oFeatureProcessor;
28
 
29
+ public function __construct( $oPluginVo, $aFeatureProperties = array() ) {
30
+ parent::__construct( $oPluginVo, $aFeatureProperties );
 
 
31
 
32
  add_action( 'deactivate_plugin', array( $this, 'onWpHookDeactivatePlugin' ), 1, 1 );
33
  add_filter( $this->doPluginPrefix( 'report_email_address' ), array( $this, 'getPluginReportEmail' ) );
38
  */
39
  protected function loadFeatureProcessor() {
40
  if ( !isset( $this->oFeatureProcessor ) ) {
41
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', 'plugin' ) ) );
42
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_Plugin( $this );
43
  }
44
  return $this->oFeatureProcessor;
73
  return $aPluginFeatures;
74
  }
75
 
76
+ foreach( $aActiveFeatures['value'] as $nPosition => $aFeature ) {
77
  if ( isset( $aFeature['hidden'] ) && $aFeature['hidden'] ) {
78
  continue;
79
  }
80
+ $aPluginFeatures[ $aFeature['slug'] ] = $aFeature;
81
  }
82
  return $aPluginFeatures;
83
  }
100
  /**
101
  */
102
  public function displayFeatureConfigPage( ) {
 
 
 
 
 
 
103
  $aPluginSummaryData = apply_filters( $this->doPluginPrefix( 'get_feature_summary_data' ), array() );
 
104
  $aData = array(
105
  'aSummaryData' => $aPluginSummaryData
106
  );
 
107
  $this->display( $aData );
108
  }
109
 
199
  */
200
  protected function doPrePluginOptionsSave() {
201
 
 
 
202
  $nInstalledAt = $this->getOpt( 'installation_time' );
203
  if ( empty($nInstalledAt) || $nInstalledAt <= 0 ) {
204
  $this->setOpt( 'installation_time', time() );
231
  $wpdb->query( $sQuery );
232
  }
233
  }
234
+
235
+ // clean out old database tables as we've moved to the audit trail now.
236
+ if ( version_compare( $this->getVersion(), '4.0.0', '<' ) ) {
237
+ $aOldTables = array(
238
+ 'icwp_wpsf_general_logging'
239
+ );
240
+ global $wpdb;
241
+ foreach( $aOldTables as $sTable ) {
242
+ $sQuery = sprintf( 'DROP TABLE IF EXISTS `%s%s`', $wpdb->prefix, $sTable ) ;
243
+ $wpdb->query( $sQuery );
244
+ }
245
+
246
+ // remove old database cleanup crons
247
+ wp_clear_scheduled_hook( 'icwp_wpsf_cron_cleanupactionhook' );
248
+ }
249
  }
250
  }
251
 
src/icwp-optionshandler-privacy_protect.php CHANGED
@@ -26,18 +26,12 @@ class ICWP_WPSF_FeatureHandler_PrivacyProtect extends ICWP_WPSF_FeatureHandler_B
26
  */
27
  protected $oFeatureProcessor;
28
 
29
- public function __construct( $oPluginVo ) {
30
- $this->sFeatureName = _wpsf__('Privacy Protect');
31
- $this->sFeatureSlug = 'privacy_protect';
32
- parent::__construct( $oPluginVo );
33
- }
34
-
35
  /**
36
  * @return ICWP_WPSF_Processor_PrivacyProtect|null
37
  */
38
  protected function loadFeatureProcessor() {
39
  if ( !isset( $this->oFeatureProcessor ) ) {
40
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
41
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_PrivacyProtect( $this );
42
  }
43
  return $this->oFeatureProcessor;
@@ -107,12 +101,6 @@ class ICWP_WPSF_FeatureHandler_PrivacyProtect extends ICWP_WPSF_FeatureHandler_B
107
  }
108
 
109
  protected function doExtraSubmitProcessing() {
110
- $oDp = $this->loadDataProcessor();
111
- if ( $oDp->FetchPost( 'clear_log_submit' ) ) {
112
- $oLoggingProcessor = $this->getLoggingProcessor();
113
- $oLoggingProcessor->recreateTable();
114
- return true;
115
- }
116
  return true;
117
  }
118
  }
26
  */
27
  protected $oFeatureProcessor;
28
 
 
 
 
 
 
 
29
  /**
30
  * @return ICWP_WPSF_Processor_PrivacyProtect|null
31
  */
32
  protected function loadFeatureProcessor() {
33
  if ( !isset( $this->oFeatureProcessor ) ) {
34
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
35
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_PrivacyProtect( $this );
36
  }
37
  return $this->oFeatureProcessor;
101
  }
102
 
103
  protected function doExtraSubmitProcessing() {
 
 
 
 
 
 
104
  return true;
105
  }
106
  }
src/icwp-optionshandler-user_management.php CHANGED
@@ -28,18 +28,12 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
28
  */
29
  protected $oFeatureProcessor;
30
 
31
- public function __construct( $oPluginVo ) {
32
- $this->sFeatureName = _wpsf__('User Management');
33
- $this->sFeatureSlug = 'user_management';
34
- parent::__construct( $oPluginVo );
35
- }
36
-
37
  /**
38
  * @return ICWP_WPSF_FeatureHandler_UserManagement|null
39
  */
40
  protected function loadFeatureProcessor() {
41
  if ( !isset( $this->oFeatureProcessor ) ) {
42
- require_once( $this->getController()->getSourceDir( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
43
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_UserManagement( $this );
44
  }
45
  return $this->oFeatureProcessor;
@@ -49,7 +43,8 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
49
  */
50
  public function doPrePluginOptionsSave() {
51
 
52
- if ( !is_email( $this->getOpt( 'enable_admin_login_email_notification' ) ) ) {
 
53
  $this->getOptionsVo()->resetOptToDefault( 'enable_admin_login_email_notification' );
54
  }
55
 
@@ -65,17 +60,10 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
65
  /**
66
  */
67
  public function displayFeatureConfigPage( ) {
68
-
69
- if ( !apply_filters( $this->doPluginPrefix( 'has_permission_to_view' ), true ) ) {
70
- $this->displayViewAccessRestrictedPage();
71
- return;
72
- }
73
-
74
  $aData = array(
75
  'aActiveSessions' => $this->getIsMainFeatureEnabled()? $this->oFeatureProcessor->getActiveUserSessionRecords() : array(),
76
  'aFailedSessions' => $this->getIsMainFeatureEnabled()? $this->oFeatureProcessor->getPendingOrFailedUserSessionRecordsSince() : array()
77
  );
78
- $aData = array_merge( $this->getBaseDisplayData(), $aData );
79
  $this->display( $aData );
80
  }
81
 
28
  */
29
  protected $oFeatureProcessor;
30
 
 
 
 
 
 
 
31
  /**
32
  * @return ICWP_WPSF_FeatureHandler_UserManagement|null
33
  */
34
  protected function loadFeatureProcessor() {
35
  if ( !isset( $this->oFeatureProcessor ) ) {
36
+ require_once( $this->getController()->getPath_SourceFile( sprintf( 'icwp-processor-%s.php', $this->getFeatureSlug() ) ) );
37
  $this->oFeatureProcessor = new ICWP_WPSF_Processor_UserManagement( $this );
38
  }
39
  return $this->oFeatureProcessor;
43
  */
44
  public function doPrePluginOptionsSave() {
45
 
46
+ $sAdminEmail = $this->getOpt( 'enable_admin_login_email_notification' );
47
+ if ( !empty( $sAdminEmail ) && !is_email( $sAdminEmail ) ) {
48
  $this->getOptionsVo()->resetOptToDefault( 'enable_admin_login_email_notification' );
49
  }
50
 
60
  /**
61
  */
62
  public function displayFeatureConfigPage( ) {
 
 
 
 
 
 
63
  $aData = array(
64
  'aActiveSessions' => $this->getIsMainFeatureEnabled()? $this->oFeatureProcessor->getActiveUserSessionRecords() : array(),
65
  'aFailedSessions' => $this->getIsMainFeatureEnabled()? $this->oFeatureProcessor->getPendingOrFailedUserSessionRecordsSince() : array()
66
  );
 
67
  $this->display( $aData );
68
  }
69
 
src/icwp-processor-admin_access_restriction.php CHANGED
@@ -15,52 +15,68 @@
15
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
  */
17
 
18
- require_once( dirname(__FILE__).'/icwp-processor-base.php' );
19
-
20
  if ( !class_exists('ICWP_WPSF_Processor_AdminAccessRestriction') ):
21
 
22
- class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Base {
23
 
24
- /**
25
- * @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction
26
- */
27
- protected $oFeatureOptions;
28
 
29
- /**
30
- * @var string
31
- */
32
- protected $sOptionRegexPattern;
33
 
34
- /**
35
- * @param ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFeatureOptions
36
- */
37
- public function __construct( ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFeatureOptions ) {
38
- parent::__construct( $oFeatureOptions );
39
- }
40
 
41
- public function run() {
42
- $oWp = $this->loadWpFunctionsProcessor();
43
- if ( ! $this->oFeatureOptions->getIsUpgrading() && ! $oWp->getIsLoginRequest() ) {
44
- $this->sOptionRegexPattern = '/^'. $this->oFeatureOptions->getOptionStoragePrefix() . '.*_options$/';
45
- add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
- }
48
 
49
- /**
50
- * Right before a plugin option is due to update it will check that we have permissions to do so and if not, will
51
- * revert the option to save to the previous one.
52
- *
53
- * @param $mValue
54
- * @param $sOption
55
- * @param $mOldValue
56
- * @return mixed
57
- */
58
- public function blockOptionsSaves( $mValue, $sOption, $mOldValue ) {
59
- if ( !preg_match( $this->sOptionRegexPattern, $sOption ) ) {
60
- return $mValue;
61
  }
62
- return apply_filters( $this->oFeatureOptions->doPluginPrefix( 'has_permission_to_submit' ), true )? $mValue : $mOldValue;
63
  }
64
- }
65
 
66
  endif;
15
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
  */
17
 
18
+ require_once( dirname(__FILE__).ICWP_DS.'icwp-processor-base.php' );
 
19
  if ( !class_exists('ICWP_WPSF_Processor_AdminAccessRestriction') ):
20
 
21
+ class ICWP_WPSF_Processor_AdminAccessRestriction extends ICWP_WPSF_Processor_Base {
22
 
23
+ /**
24
+ * @var ICWP_WPSF_FeatureHandler_AdminAccessRestriction
25
+ */
26
+ protected $oFeatureOptions;
27
 
28
+ /**
29
+ * @var string
30
+ */
31
+ protected $sOptionRegexPattern;
32
 
33
+ /**
34
+ * @param ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFeatureOptions
35
+ */
36
+ public function __construct( ICWP_WPSF_FeatureHandler_AdminAccessRestriction $oFeatureOptions ) {
37
+ parent::__construct( $oFeatureOptions );
38
+ }
39
 
40
+ public function run() {
41
+ $oWp = $this->loadWpFunctionsProcessor();
42
+ if ( ! $this->getFeatureOptions()->getIsUpgrading() && ! $oWp->getIsLoginRequest() ) {
43
+ add_filter( 'pre_update_option', array( $this, 'blockOptionsSaves' ), 1, 3 );
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Right before a plugin option is due to update it will check that we have permissions to do so and if not, will
49
+ * revert the option to save to the previous one.
50
+ *
51
+ * @param mixed $mNewOptionValue
52
+ * @param string $sOption
53
+ * @param mixed $mOldValue
54
+ * @return mixed
55
+ */
56
+ public function blockOptionsSaves( $mNewOptionValue, $sOption, $mOldValue ) {
57
+ if ( !preg_match( $this->getOptionRegexPattern(), $sOption ) ) {
58
+ return $mNewOptionValue;
59
+ }
60
+
61
+ $fHasPermissionToChangeOptions = apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'has_permission_to_submit' ), true );
62
+ if ( !$fHasPermissionToChangeOptions ) {
63
+ $sAuditMessage = sprintf( _wpsf__('Attempt to save/update option "%s" was blocked.'), $sOption );
64
+ // $this->addToAuditEntry( $sAuditMessage, 3, 'admin_access_option_block' );
65
+ return $mOldValue;
66
+ }
67
+
68
+ return $mNewOptionValue;
69
  }
 
70
 
71
+ /**
72
+ * @return string
73
+ */
74
+ protected function getOptionRegexPattern() {
75
+ if ( !isset( $this->sOptionRegexPattern ) ) {
76
+ $this->sOptionRegexPattern = '/^'. $this->getFeatureOptions()->getOptionStoragePrefix() . '.*_options$/';
77
+ }
78
+ return $this->sOptionRegexPattern;
 
 
 
 
79
  }
 
80
  }
 
81
 
82
  endif;
src/icwp-processor-audit_trail.php CHANGED
@@ -31,47 +31,61 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_V1') ):
31
  */
32
  public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
33
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getAuditTrailTableName() );
34
- add_action( $this->oFeatureOptions->doPluginPrefix( 'plugin_shutdown' ), array( $this, 'commitAuditTrial' ) );
 
 
 
 
 
35
  }
36
 
37
  /**
38
  */
39
  public function run() {
40
 
 
 
41
  if ( $this->getIsOption( 'enable_audit_context_users', 'Y' ) ) {
42
  require_once( 'icwp-processor-audit_trail_users.php' );
43
- $oUsers = new ICWP_WPSF_Processor_AuditTrail_Users( $this->oFeatureOptions );
44
  $oUsers->run();
45
  }
46
 
47
  if ( $this->getIsOption( 'enable_audit_context_plugins', 'Y' ) ) {
48
  require_once( 'icwp-processor-audit_trail_plugins.php' );
49
- $oUsers = new ICWP_WPSF_Processor_AuditTrail_Plugins( $this->oFeatureOptions );
50
- $oUsers->run();
51
  }
52
 
53
  if ( $this->getIsOption( 'enable_audit_context_themes', 'Y' ) ) {
54
  require_once( 'icwp-processor-audit_trail_themes.php' );
55
- $oUsers = new ICWP_WPSF_Processor_AuditTrail_Themes( $this->oFeatureOptions );
56
- $oUsers->run();
57
  }
58
 
59
  if ( $this->getIsOption( 'enable_audit_context_wordpress', 'Y' ) ) {
60
  require_once( 'icwp-processor-audit_trail_wordpress.php' );
61
- $oUsers = new ICWP_WPSF_Processor_AuditTrail_Wordpress( $this->oFeatureOptions );
62
- $oUsers->run();
63
  }
64
 
65
  if ( $this->getIsOption( 'enable_audit_context_posts', 'Y' ) ) {
66
  require_once( 'icwp-processor-audit_trail_posts.php' );
67
- $oUsers = new ICWP_WPSF_Processor_AuditTrail_Posts( $this->oFeatureOptions );
68
- $oUsers->run();
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
- // if ( $this->getIsOption( 'enable_audit_context_wpsf', 'Y' ) ) {
71
- // require_once( 'icwp-processor-audit_trail_wpsf.php' );
72
- // $oUsers = new ICWP_WPSF_Processor_AuditTrail_Wpsf( $this->oFeatureOptions );
73
- // $oUsers->run();
74
- // }
75
  }
76
 
77
  /**
@@ -81,15 +95,42 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_V1') ):
81
  return array_reverse( $this->selectAllFromTable() );
82
  }
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  /**
85
  */
86
- public function commitAuditTrial() {
87
  $aEntries = $this->getAuditTrailEntries()->getAuditTrailEntries( true );
 
88
  if ( empty( $aEntries ) || !is_array( $aEntries ) ) {
89
  return;
90
  }
91
 
 
92
  foreach( $aEntries as $aEntry ) {
 
 
 
 
 
 
93
  $this->insertIntoTable( $aEntry );
94
  }
95
  }
@@ -108,6 +149,7 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_V1') ):
108
  $sSqlTables = "
109
  CREATE TABLE IF NOT EXISTS `%s` (
110
  `id` INT(11) NOT NULL AUTO_INCREMENT,
 
111
  `wp_username` VARCHAR(255) NOT NULL DEFAULT 'none',
112
  `context` VARCHAR(25) NOT NULL DEFAULT 'none',
113
  `event` VARCHAR(25) NOT NULL DEFAULT 'none',
@@ -150,17 +192,23 @@ class ICWP_WPSF_AuditTrail_Entries {
150
  */
151
  protected $aEntries;
152
 
153
- public function add( $sContext, $sEvent, $nCategory, $sMessage = '' ) {
154
  $oDp = $this->loadDataProcessor();
155
- $oWp = $this->loadWpFunctionsProcessor();
156
- $oCurrentUser = $oWp->getCurrentWpUser();
 
 
 
 
 
157
  $aNewEntry = array(
 
158
  'created_at' => $oDp->GetRequestTime(),
159
- 'wp_username' => empty( $oCurrentUser ) ? 'unknown' : $oCurrentUser->get( 'user_login' ),
160
  'context' => $sContext,
161
  'event' => $sEvent,
162
  'category' => $nCategory,
163
- 'message' => $sMessage,
164
  );
165
  $aEntries = $this->getAuditTrailEntries();
166
  $aEntries[] = $aNewEntry;
31
  */
32
  public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
33
  parent::__construct( $oFeatureOptions, $oFeatureOptions->getAuditTrailTableName() );
34
+ }
35
+
36
+ public function action_doFeatureProcessorShutdown () {
37
+ if ( ! $this->getFeatureOptions()->getIsPluginDeleting() ) {
38
+ $this->commitAuditTrial();
39
+ }
40
  }
41
 
42
  /**
43
  */
44
  public function run() {
45
 
46
+ $oFo = $this->getFeatureOptions();
47
+
48
  if ( $this->getIsOption( 'enable_audit_context_users', 'Y' ) ) {
49
  require_once( 'icwp-processor-audit_trail_users.php' );
50
+ $oUsers = new ICWP_WPSF_Processor_AuditTrail_Users( $oFo );
51
  $oUsers->run();
52
  }
53
 
54
  if ( $this->getIsOption( 'enable_audit_context_plugins', 'Y' ) ) {
55
  require_once( 'icwp-processor-audit_trail_plugins.php' );
56
+ $oPlugins = new ICWP_WPSF_Processor_AuditTrail_Plugins( $oFo );
57
+ $oPlugins->run();
58
  }
59
 
60
  if ( $this->getIsOption( 'enable_audit_context_themes', 'Y' ) ) {
61
  require_once( 'icwp-processor-audit_trail_themes.php' );
62
+ $oThemes = new ICWP_WPSF_Processor_AuditTrail_Themes( $oFo );
63
+ $oThemes->run();
64
  }
65
 
66
  if ( $this->getIsOption( 'enable_audit_context_wordpress', 'Y' ) ) {
67
  require_once( 'icwp-processor-audit_trail_wordpress.php' );
68
+ $oWp = new ICWP_WPSF_Processor_AuditTrail_Wordpress( $oFo );
69
+ $oWp->run();
70
  }
71
 
72
  if ( $this->getIsOption( 'enable_audit_context_posts', 'Y' ) ) {
73
  require_once( 'icwp-processor-audit_trail_posts.php' );
74
+ $oPosts = new ICWP_WPSF_Processor_AuditTrail_Posts( $oFo );
75
+ $oPosts->run();
76
+ }
77
+
78
+ if ( $this->getIsOption( 'enable_audit_context_emails', 'Y' ) ) {
79
+ require_once( 'icwp-processor-audit_trail_emails.php' );
80
+ $oEmails = new ICWP_WPSF_Processor_AuditTrail_Emails( $oFo );
81
+ $oEmails->run();
82
+ }
83
+
84
+ if ( $this->getIsOption( 'enable_audit_context_wpsf', 'Y' ) ) {
85
+ require_once( 'icwp-processor-audit_trail_wpsf.php' );
86
+ $oWpsf = new ICWP_WPSF_Processor_AuditTrail_Wpsf( $oFo );
87
+ $oWpsf->run();
88
  }
 
 
 
 
 
89
  }
90
 
91
  /**
95
  return array_reverse( $this->selectAllFromTable() );
96
  }
97
 
98
+ /**
99
+ * @param string $sContext
100
+ * @param int $nLimit
101
+ * @return array|bool
102
+ */
103
+ public function getAuditEntriesForContext( $sContext, $nLimit = 50 ) {
104
+ $sQuery = "
105
+ SELECT *
106
+ FROM `%s`
107
+ WHERE
108
+ `context` = '%s'
109
+ AND `deleted_at` = '0'
110
+ ORDER BY `created_at` DESC
111
+ LIMIT %s
112
+ ";
113
+ $sQuery = sprintf( $sQuery, $this->getTableName(), $sContext, $nLimit );
114
+ return $this->selectCustomFromTable( $sQuery );
115
+ }
116
+
117
  /**
118
  */
119
+ protected function commitAuditTrial() {
120
  $aEntries = $this->getAuditTrailEntries()->getAuditTrailEntries( true );
121
+ $aEntries = apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'wpsf_audit_trail_gather' ), $aEntries );
122
  if ( empty( $aEntries ) || !is_array( $aEntries ) ) {
123
  return;
124
  }
125
 
126
+ $nIp = $this->loadDataProcessor()->GetVisitorIpAddress();
127
  foreach( $aEntries as $aEntry ) {
128
+ if ( empty( $aEntry['ip_long'] ) ) {
129
+ $aEntry['ip_long'] = $nIp;
130
+ }
131
+ if ( is_array( $aEntry['message'] ) ) {
132
+ $aEntry['message'] = implode( ' ', $aEntry['message'] );
133
+ }
134
  $this->insertIntoTable( $aEntry );
135
  }
136
  }
149
  $sSqlTables = "
150
  CREATE TABLE IF NOT EXISTS `%s` (
151
  `id` INT(11) NOT NULL AUTO_INCREMENT,
152
+ `ip_long` bigint(20) NOT NULL DEFAULT '0',
153
  `wp_username` VARCHAR(255) NOT NULL DEFAULT 'none',
154
  `context` VARCHAR(25) NOT NULL DEFAULT 'none',
155
  `event` VARCHAR(25) NOT NULL DEFAULT 'none',
192
  */
193
  protected $aEntries;
194
 
195
+ public function add( $sContext, $sEvent, $nCategory, $sMessage = '', $sWpUsername = '' ) {
196
  $oDp = $this->loadDataProcessor();
197
+
198
+ if ( empty( $sWpUsername ) ) {
199
+ $oWp = $this->loadWpFunctionsProcessor();
200
+ $oCurrentUser = $oWp->getCurrentWpUser();
201
+ $sWpUsername = empty( $oCurrentUser ) ? 'unknown' : $oCurrentUser->get( 'user_login' );
202
+ }
203
+
204
  $aNewEntry = array(
205
+ 'ip_long' => $oDp->GetVisitorIpAddress(),
206
  'created_at' => $oDp->GetRequestTime(),
207
+ 'wp_username' => $sWpUsername,
208
  'context' => $sContext,
209
  'event' => $sEvent,
210
  'category' => $nCategory,
211
+ 'message' => $sMessage
212
  );
213
  $aEntries = $this->getAuditTrailEntries();
214
  $aEntries[] = $aNewEntry;
src/icwp-processor-audit_trail_emails.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2014 iControlWP <support@icontrolwp.com>
4
+ * All rights reserved.
5
+ *
6
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
10
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
13
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
+ */
17
+
18
+ require_once( dirname(__FILE__).'/icwp-processor-base.php' );
19
+
20
+ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Emails') ):
21
+
22
+ class ICWP_WPSF_Processor_AuditTrail_Emails extends ICWP_WPSF_Processor_Base {
23
+
24
+ /**
25
+ * @var ICWP_WPSF_FeatureHandler_AuditTrail
26
+ */
27
+ protected $oFeatureOptions;
28
+
29
+ /**
30
+ * @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
31
+ */
32
+ public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
33
+ parent::__construct( $oFeatureOptions );
34
+ }
35
+
36
+ /**
37
+ */
38
+ public function run() {
39
+ if ( $this->getIsOption( 'enable_audit_context_emails', 'Y' ) ) {
40
+ add_filter( 'wp_mail', array( $this, 'auditEmailSend' ) );
41
+ }
42
+ }
43
+
44
+ /**
45
+ * @param array $aEmailParameters
46
+ * @return bool
47
+ */
48
+ public function auditEmailSend( $aEmailParameters ) {
49
+
50
+
51
+ $oAuditTrail = $this->getAuditTrailEntries();
52
+ $oAuditTrail->add(
53
+ 'emails',
54
+ 'email_attempt_send',
55
+ 1,
56
+ sprintf( _wpsf__( 'There was an attempt to send an email using the "%s" function.' ), 'wp_mail' )
57
+ .' '.sprintf( _wpsf__( 'It was sent to "%s" with the subject "%s".' ), $aEmailParameters['to'], $aEmailParameters['subject'] )
58
+ );
59
+
60
+
61
+ return $aEmailParameters;
62
+ }
63
+
64
+ /**
65
+ * @return ICWP_WPSF_AuditTrail_Entries
66
+ */
67
+ protected function getAuditTrailEntries() {
68
+ return ICWP_WPSF_AuditTrail_Entries::GetInstance();
69
+ }
70
+ }
71
+
72
+ endif;
src/icwp-processor-audit_trail_plugins.php CHANGED
@@ -36,12 +36,11 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Plugins') ):
36
  /**
37
  */
38
  public function run() {
39
-
40
  if ( $this->getIsOption( 'enable_audit_context_plugins', 'Y' ) ) {
41
  add_action( 'deactivated_plugin', array( $this, 'auditDeactivatedPlugin' ) );
42
  add_action( 'activated_plugin', array( $this, 'auditActivatedPlugin' ) );
 
43
  }
44
-
45
  }
46
 
47
  /**
@@ -82,6 +81,28 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Plugins') ):
82
  );
83
  }
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  /**
86
  * @return ICWP_WPSF_AuditTrail_Entries
87
  */
36
  /**
37
  */
38
  public function run() {
 
39
  if ( $this->getIsOption( 'enable_audit_context_plugins', 'Y' ) ) {
40
  add_action( 'deactivated_plugin', array( $this, 'auditDeactivatedPlugin' ) );
41
  add_action( 'activated_plugin', array( $this, 'auditActivatedPlugin' ) );
42
+ add_action( 'check_admin_referer', array( $this, 'auditEditedPluginFile' ), 10, 2 );
43
  }
 
44
  }
45
 
46
  /**
81
  );
82
  }
83
 
84
+ /**
85
+ * @param string $sAction
86
+ * @param boolean $fResult
87
+ */
88
+ public function auditEditedPluginFile( $sAction, $fResult ) {
89
+
90
+ $sStub = 'edit-plugin_';
91
+ if ( strpos( $sAction, $sStub ) !== 0 ) {
92
+ return;
93
+ }
94
+
95
+ $sFileName = str_replace( $sStub, '', $sAction );
96
+
97
+ $oAuditTrail = $this->getAuditTrailEntries();
98
+ $oAuditTrail->add(
99
+ 'plugins',
100
+ 'file_edited',
101
+ 2,
102
+ sprintf( _wpsf__( 'An attempt was made to edit the plugin file "%s" directly through the WordPress editor.' ), $sFileName )
103
+ );
104
+ }
105
+
106
  /**
107
  * @return ICWP_WPSF_AuditTrail_Entries
108
  */
src/icwp-processor-audit_trail_themes.php CHANGED
@@ -36,12 +36,11 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Themes') ):
36
  /**
37
  */
38
  public function run() {
39
-
40
  if ( $this->getIsOption( 'enable_audit_context_themes', 'Y' ) ) {
41
  add_action( 'switch_theme', array( $this, 'auditSwitchTheme' ) );
 
42
  // add_action( 'upgrader_process_complete', array( $this, 'auditInstalledTheme' ) );
43
  }
44
-
45
  }
46
 
47
  /**
@@ -63,6 +62,28 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Themes') ):
63
  );
64
  }
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  /**
67
  * @return ICWP_WPSF_AuditTrail_Entries
68
  */
36
  /**
37
  */
38
  public function run() {
 
39
  if ( $this->getIsOption( 'enable_audit_context_themes', 'Y' ) ) {
40
  add_action( 'switch_theme', array( $this, 'auditSwitchTheme' ) );
41
+ add_action( 'check_admin_referer', array( $this, 'auditEditedThemeFile' ), 10, 2 );
42
  // add_action( 'upgrader_process_complete', array( $this, 'auditInstalledTheme' ) );
43
  }
 
44
  }
45
 
46
  /**
62
  );
63
  }
64
 
65
+ /**
66
+ * @param string $sAction
67
+ * @param boolean $fResult
68
+ */
69
+ public function auditEditedThemeFile( $sAction, $fResult ) {
70
+
71
+ $sStub = 'edit-theme_';
72
+ if ( strpos( $sAction, $sStub ) !== 0 ) {
73
+ return;
74
+ }
75
+
76
+ $sFileName = str_replace( $sStub, '', $sAction );
77
+
78
+ $oAuditTrail = $this->getAuditTrailEntries();
79
+ $oAuditTrail->add(
80
+ 'themes',
81
+ 'file_edited',
82
+ 2,
83
+ sprintf( _wpsf__( 'An attempt was made to edit the theme file "%s" directly through the WordPress editor.' ), $sFileName )
84
+ );
85
+ }
86
+
87
  /**
88
  * @return ICWP_WPSF_AuditTrail_Entries
89
  */
src/icwp-processor-audit_trail_users.php CHANGED
@@ -36,14 +36,12 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Users') ):
36
  /**
37
  */
38
  public function run() {
39
-
40
  if ( $this->getIsOption( 'enable_audit_context_users', 'Y' ) ) {
41
  add_action( 'wp_login_failed', array( $this, 'auditUserLoginFail' ) );
42
  add_action( 'wp_login', array( $this, 'auditUserLoginSuccess' ) );
43
  add_action( 'user_register', array( $this, 'auditNewUserRegistered' ) );
44
  add_action( 'delete_user', array( $this, 'auditDeleteUser' ), 30, 2 );
45
  }
46
-
47
  }
48
 
49
  /**
@@ -61,7 +59,8 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Users') ):
61
  'users',
62
  'login_success',
63
  1,
64
- sprintf( _wpsf__( 'Attempted user login by "%s" was successful.' ), $sUsername )
 
65
  );
66
  }
67
 
@@ -80,7 +79,7 @@ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Users') ):
80
  'users',
81
  'login_failure',
82
  2,
83
- sprintf( _wpsf__( 'Attempted user login by "%s" was failed.' ), $sUsername )
84
  );
85
  }
86
 
36
  /**
37
  */
38
  public function run() {
 
39
  if ( $this->getIsOption( 'enable_audit_context_users', 'Y' ) ) {
40
  add_action( 'wp_login_failed', array( $this, 'auditUserLoginFail' ) );
41
  add_action( 'wp_login', array( $this, 'auditUserLoginSuccess' ) );
42
  add_action( 'user_register', array( $this, 'auditNewUserRegistered' ) );
43
  add_action( 'delete_user', array( $this, 'auditDeleteUser' ), 30, 2 );
44
  }
 
45
  }
46
 
47
  /**
59
  'users',
60
  'login_success',
61
  1,
62
+ sprintf( _wpsf__( 'Attempted user login by "%s" was successful.' ), $sUsername ),
63
+ $sUsername
64
  );
65
  }
66
 
79
  'users',
80
  'login_failure',
81
  2,
82
+ sprintf( _wpsf__( 'Attempted user login by "%s" failed.' ), $sUsername )
83
  );
84
  }
85
 
src/icwp-processor-audit_trail_wpsf.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2014 iControlWP <support@icontrolwp.com>
4
+ * All rights reserved.
5
+ *
6
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
10
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
13
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
+ */
17
+
18
+ require_once( dirname(__FILE__).'/icwp-processor-base.php' );
19
+
20
+ if ( !class_exists('ICWP_WPSF_Processor_AuditTrail_Wpsf') ):
21
+
22
+ class ICWP_WPSF_Processor_AuditTrail_Wpsf extends ICWP_WPSF_Processor_Base {
23
+
24
+ /**
25
+ * @var ICWP_WPSF_FeatureHandler_AuditTrail
26
+ */
27
+ protected $oFeatureOptions;
28
+
29
+ /**
30
+ * @param ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions
31
+ */
32
+ public function __construct( ICWP_WPSF_FeatureHandler_AuditTrail $oFeatureOptions ) {
33
+ parent::__construct( $oFeatureOptions );
34
+ }
35
+
36
+ /**
37
+ */
38
+ public function run() { }
39
+
40
+ /**
41
+ * @return ICWP_WPSF_AuditTrail_Entries
42
+ */
43
+ protected function getAuditTrailEntries() {
44
+ return ICWP_WPSF_AuditTrail_Entries::GetInstance();
45
+ }
46
+ }
47
+
48
+ endif;
src/icwp-processor-base.php CHANGED
@@ -18,25 +18,9 @@
18
 
19
  if ( !class_exists('ICWP_BaseProcessor_V3') ):
20
 
21
- class ICWP_BaseProcessor_V3 extends ICWP_WPSF_Foundation {
22
 
23
  const PcreDelimiter = '/';
24
- const LOG_MESSAGE_LEVEL_INFO = 0;
25
- const LOG_MESSAGE_LEVEL_WARNING = 1;
26
- const LOG_MESSAGE_LEVEL_CRITICAL = 2;
27
-
28
- const LOG_CATEGORY_DEFAULT = 0;
29
- const LOG_CATEGORY_FIREWALL = 1;
30
- const LOG_CATEGORY_LOGINPROTECT = 2;
31
-
32
- /**
33
- * @var array
34
- */
35
- protected $m_aLog;
36
- /**
37
- * @var array
38
- */
39
- protected $m_aLogMessages;
40
 
41
  /**
42
  * @var long
@@ -51,6 +35,11 @@ if ( !class_exists('ICWP_BaseProcessor_V3') ):
51
  */
52
  protected static $nRequestTimestamp;
53
 
 
 
 
 
 
54
  /**
55
  * @var ICWP_WPSF_FeatureHandler_Base
56
  */
@@ -58,9 +47,20 @@ if ( !class_exists('ICWP_BaseProcessor_V3') ):
58
 
59
  public function __construct( ICWP_WPSF_FeatureHandler_Base $oFeatureOptions ) {
60
  $this->oFeatureOptions = $oFeatureOptions;
 
 
61
  $this->reset();
62
  }
63
 
 
 
 
 
 
 
 
 
 
64
  /**
65
  * Resets the object values to be re-used anew
66
  */
@@ -72,13 +72,12 @@ if ( !class_exists('ICWP_BaseProcessor_V3') ):
72
  if ( !isset( self::$nRequestTimestamp ) ) {
73
  self::$nRequestTimestamp = $oDp->GetRequestTime();
74
  }
75
- $this->resetLog();
76
  }
77
 
78
  /**
79
  * Override to set what this processor does when it's "run"
80
  */
81
- public function run() { }
82
 
83
  /**
84
  * @param $sOptionKey
@@ -115,86 +114,87 @@ if ( !class_exists('ICWP_BaseProcessor_V3') ):
115
  }
116
 
117
  /**
118
- * Resets the log
119
  */
120
- public function resetLog() {
121
- $this->m_aLogMessages = array();
 
 
 
122
  }
123
 
124
  /**
125
- * @return bool
 
 
126
  */
127
- public function getIsLogging() {
128
- return false;
129
- }
130
 
131
- /**
132
- * Should return false when logging is disabled.
133
- *
134
- * @return false|array - false when logging is disabled, array with log data otherwise
135
- * @see ICWP_WPSF_Processor_Base::getLogData()
136
- */
137
- public function flushLogData() {
138
- if ( !$this->getIsLogging() ) {
139
- return false;
 
 
 
 
140
  }
141
- return false;
142
- }
143
 
144
- /**
145
- * Builds and returns the full log.
146
- *
147
- * @return array (associative)
148
- */
149
- public function getLogData() {
150
 
151
- if ( $this->getIsLogging() ) {
152
- $this->m_aLog = array( 'messages' => serialize( $this->m_aLogMessages ) );
153
  }
154
- else {
155
- $this->m_aLog = false;
156
  }
157
-
158
- return $this->m_aLog;
159
  }
160
 
161
  /**
162
- * @return array
 
163
  */
164
- public function getLogMessages() {
165
- if ( !is_array( $this->m_aLogMessages ) ) {
166
- $this->m_aLogMessages = array();
167
- }
168
- return $this->m_aLogMessages;
169
  }
170
 
171
  /**
172
- * @param string $sLogMessage
173
- * @param integer $sMessageType
174
  */
175
- public function writeLog( $sLogMessage = '', $sMessageType = self::LOG_MESSAGE_LEVEL_INFO ) {
176
- if ( !is_array( $this->m_aLogMessages ) ) {
177
- $this->resetLog();
 
 
 
 
178
  }
179
- $this->m_aLogMessages[] = array( $sMessageType, $sLogMessage );
180
- }
181
- /**
182
- * @param string $insLogMessage
183
- */
184
- public function logInfo( $insLogMessage ) {
185
- $this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_INFO );
186
- }
187
- /**
188
- * @param string $insLogMessage
189
- */
190
- public function logWarning( $insLogMessage ) {
191
- $this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_WARNING );
192
  }
 
193
  /**
194
- * @param string $insLogMessage
 
 
195
  */
196
- public function logCritical( $insLogMessage ) {
197
- $this->writeLog( $insLogMessage, self::LOG_MESSAGE_LEVEL_CRITICAL );
 
 
 
 
 
 
 
 
 
198
  }
199
 
200
  /**
@@ -258,17 +258,18 @@ if ( !class_exists('ICWP_BaseProcessor_V3') ):
258
  }
259
 
260
  /**
261
- * @return ICWP_WPSF_Processor_Email
262
  */
263
- public function getEmailProcessor() {
264
- return $this->getFeatureOptions()->getEmailProcessor();
 
265
  }
266
 
267
  /**
268
- * @return ICWP_WPSF_Processor_Logging
269
  */
270
- public function getLoggingProcessor() {
271
- return $this->getFeatureOptions()->getLoggingProcessor();
272
  }
273
 
274
  /**
@@ -329,5 +330,5 @@ if ( !class_exists('ICWP_BaseProcessor_V3') ):
329
  endif;
330
 
331
  if ( !class_exists('ICWP_WPSF_Processor_Base') ):
332
- class ICWP_WPSF_Processor_Base extends ICWP_BaseProcessor_V3 { }
333
  endif;
18
 
19
  if ( !class_exists('ICWP_BaseProcessor_V3') ):
20
 
21
+ abstract class ICWP_BaseProcessor_V3 extends ICWP_WPSF_Foundation {
22
 
23
  const PcreDelimiter = '/';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  /**
26
  * @var long
35
  */
36
  protected static $nRequestTimestamp;
37
 
38
+ /**
39
+ * @var array
40
+ */
41
+ private $aAuditEntry;
42
+
43
  /**
44
  * @var ICWP_WPSF_FeatureHandler_Base
45
  */
47
 
48
  public function __construct( ICWP_WPSF_FeatureHandler_Base $oFeatureOptions ) {
49
  $this->oFeatureOptions = $oFeatureOptions;
50
+ add_action( $this->getFeatureOptions()->doPluginPrefix( 'plugin_shutdown' ), array( $this, 'action_doFeatureProcessorShutdown' ) );
51
+ add_filter( $this->getFeatureOptions()->doPluginPrefix( 'wpsf_audit_trail_gather' ), array( $this, 'getAuditEntry' ) );
52
  $this->reset();
53
  }
54
 
55
+ /**
56
+ * @return ICWP_WPSF_Plugin_Controller
57
+ */
58
+ public function getController() {
59
+ return $this->getFeatureOptions()->getController();
60
+ }
61
+
62
+ public function action_doFeatureProcessorShutdown() { }
63
+
64
  /**
65
  * Resets the object values to be re-used anew
66
  */
72
  if ( !isset( self::$nRequestTimestamp ) ) {
73
  self::$nRequestTimestamp = $oDp->GetRequestTime();
74
  }
 
75
  }
76
 
77
  /**
78
  * Override to set what this processor does when it's "run"
79
  */
80
+ abstract public function run();
81
 
82
  /**
83
  * @param $sOptionKey
114
  }
115
 
116
  /**
117
+ * @return array
118
  */
119
+ public function getAuditEntry( $aAuditEntries ) {
120
+ if ( isset( $this->aAuditEntry ) && is_array( $this->aAuditEntry ) ) {
121
+ $aAuditEntries[] = $this->aAuditEntry;
122
+ }
123
+ return $aAuditEntries;
124
  }
125
 
126
  /**
127
+ * @param string $sAdditionalMessage
128
+ * @param int $nCategory
129
+ * @param string $sEvent
130
  */
131
+ protected function addToAuditEntry( $sAdditionalMessage = '', $nCategory = 1, $sEvent = '', $sWpUsername = '' ) {
132
+ if ( !isset( $this->aAuditEntry ) ) {
 
133
 
134
+ if ( empty( $sWpUsername ) ) {
135
+ $oCurrentUser = $this->loadWpFunctionsProcessor()->getCurrentWpUser();
136
+ $sWpUsername = empty( $oCurrentUser ) ? 'unknown' : $oCurrentUser->get( 'user_login' );
137
+ }
138
+
139
+ $this->aAuditEntry = array(
140
+ 'created_at' => $this->loadDataProcessor()->GetRequestTime(),
141
+ 'wp_username' => $sWpUsername,
142
+ 'context' => 'wpsf',
143
+ 'event' => $sEvent,
144
+ 'category' => $nCategory,
145
+ 'message' => array()
146
+ );
147
  }
 
 
148
 
149
+ $this->aAuditEntry['message'][] = $sAdditionalMessage;
 
 
 
 
 
150
 
151
+ if ( $nCategory > $this->aAuditEntry['category'] ) {
152
+ $this->aAuditEntry['category'] = $nCategory;
153
  }
154
+ if ( !empty( $sEvent ) ) {
155
+ $this->aAuditEntry['event'] = $sEvent;
156
  }
 
 
157
  }
158
 
159
  /**
160
+ * @param string $sSeparator
161
+ * @return string
162
  */
163
+ protected function getAuditMessage( $sSeparator = ' ' ) {
164
+ return implode( $sSeparator, $this->getRawAuditMessage() );
 
 
 
165
  }
166
 
167
  /**
168
+ * @param string $sLinePrefix
169
+ * @return array
170
  */
171
+ protected function getRawAuditMessage( $sLinePrefix = '' ) {
172
+ if ( isset( $this->aAuditEntry['message'] ) && is_array( $this->aAuditEntry['message'] ) && !empty( $sLinePrefix ) ) {
173
+ $aAuditMessages = array();
174
+ foreach( $this->aAuditEntry['message'] as $sMessage ) {
175
+ $aAuditMessages[] = $sLinePrefix.$sMessage;
176
+ }
177
+ return $aAuditMessages;
178
  }
179
+ return isset( $this->aAuditEntry['message'] ) ? $this->aAuditEntry['message'] : array();
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
181
+
182
  /**
183
+ * @param string $sEvent
184
+ * @param int $nCategory
185
+ * @param string $sMessage
186
  */
187
+ public function writeAuditEntry( $sEvent, $nCategory = 1, $sMessage = '' ) {
188
+ $oWp = $this->loadWpFunctionsProcessor();
189
+ $oCurrentUser = $oWp->getCurrentWpUser();
190
+ $this->aAuditEntry = array(
191
+ 'created_at' => $this->loadDataProcessor()->GetRequestTime(),
192
+ 'wp_username' => empty( $oCurrentUser ) ? 'unknown' : $oCurrentUser->get( 'user_login' ),
193
+ 'context' => 'wpsf',
194
+ 'event' => $sEvent,
195
+ 'category' => $nCategory,
196
+ 'message' => $sMessage
197
+ );
198
  }
199
 
200
  /**
258
  }
259
 
260
  /**
261
+ * @return mixed
262
  */
263
+ public function getPluginDefaultRecipientAddress() {
264
+ $oWp = $this->loadWpFunctionsProcessor();
265
+ return apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'report_email_address' ), $oWp->getSiteAdminEmail() );
266
  }
267
 
268
  /**
269
+ * @return ICWP_WPSF_Processor_Email
270
  */
271
+ public function getEmailProcessor() {
272
+ return $this->getFeatureOptions()->getEmailProcessor();
273
  }
274
 
275
  /**
330
  endif;
331
 
332
  if ( !class_exists('ICWP_WPSF_Processor_Base') ):
333
+ abstract class ICWP_WPSF_Processor_Base extends ICWP_BaseProcessor_V3 { }
334
  endif;
src/icwp-processor-basedb.php CHANGED
@@ -22,8 +22,6 @@ if ( !class_exists('ICWP_WPSF_BaseDbProcessor') ):
22
 
23
  abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_Base {
24
 
25
- const CleanupCronActionHook = 'icwp_wpsf_cron_cleanupactionhook';
26
-
27
  /**
28
  * A link to the WordPress Database object so we don't have to "global" that every time.
29
  * @var wpdb
@@ -35,10 +33,6 @@ abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_Base {
35
  * @var string
36
  */
37
  protected $sFullTableName;
38
- /**
39
- * @var array
40
- */
41
- protected $m_aDataToWrite;
42
 
43
  /**
44
  * @var boolean
@@ -52,15 +46,11 @@ abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_Base {
52
  add_action( $this->getFeatureOptions()->doPluginPrefix( 'delete_plugin' ), array( $this, 'deleteDatabase' ) );
53
  }
54
 
55
- /**
56
- * Override to set what this processor does when it's "run"
57
- */
58
- public function run() { }
59
-
60
  /**
61
  */
62
  public function deleteDatabase() {
63
  if ( apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'has_permission_to_submit' ), true ) && $this->getTableExists() ) {
 
64
  $this->dropTable();
65
  }
66
  }
@@ -100,68 +90,13 @@ abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_Base {
100
  */
101
  protected function initializeTable() {
102
  if ( $this->getTableExists() ) {
103
- $sFullHookName = $this->getFeatureOptions()->doPluginPrefix( self::CleanupCronActionHook, '_' );
104
  add_action( $sFullHookName, array( $this, 'cleanupDatabase' ) );
105
  }
106
  else {
107
  $this->createTable();
108
  }
109
  }
110
-
111
- /**
112
- * @param array $inaLogData
113
- * @return type
114
- */
115
- public function addDataToWrite( $inaLogData ) {
116
- if ( empty( $inaLogData ) ) {
117
- return;
118
- }
119
- if ( empty( $this->m_aDataToWrite ) ) {
120
- $this->m_aDataToWrite = array();
121
- }
122
- $this->m_aDataToWrite[] = $this->completeDataForWrite( $inaLogData );
123
- }
124
-
125
- /**
126
- * Ensures the data provided for writing to the db meets all the requirements.
127
- *
128
- * This should be overridden per implementation
129
- *
130
- * @param array $aLogData
131
- * @return array
132
- */
133
- protected function completeDataForWrite( $aLogData ) {
134
- if ( is_null( $aLogData ) ) {
135
- return array();
136
- }
137
- return $aLogData;
138
- }
139
-
140
- /**
141
- * @return boolean - whether the write to the DB was successful.
142
- */
143
- public function commitData() {
144
- if ( empty( $this->m_aDataToWrite ) || !$this->getTableExists() ) {
145
- return;
146
- }
147
- $fSuccess = true;
148
- foreach( $this->m_aDataToWrite as $aDataEntry ) {
149
- if ( empty( $aDataEntry ) ) {
150
- continue;
151
- }
152
- $fSuccess = $fSuccess && $this->insertIntoTable( $aDataEntry );
153
- }
154
- if ( $fSuccess ) {
155
- $this->flushData();
156
- }
157
- return $fSuccess;
158
- }
159
-
160
- /**
161
- */
162
- protected function flushData() {
163
- $this->m_aDataToWrite = null;
164
- }
165
 
166
  /**
167
  * @param $aData
@@ -311,13 +246,27 @@ abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_Base {
311
  * Will setup the cleanup cron to clean out old entries. This should be overridden per implementation.
312
  */
313
  protected function createCleanupCron() {
314
- $sFullHookName = $this->getFeatureOptions()->doPluginPrefix( self::CleanupCronActionHook, '_' );
315
  if ( ! wp_next_scheduled( $sFullHookName ) && ! defined( 'WP_INSTALLING' ) ) {
316
  $nNextRun = strtotime( 'tomorrow 6am' ) - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
317
  wp_schedule_event( $nNextRun, 'daily', $sFullHookName );
318
  }
319
  }
320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  // by default does nothing - override this method
322
  public function cleanupDatabase() { }
323
 
22
 
23
  abstract class ICWP_WPSF_BaseDbProcessor extends ICWP_WPSF_Processor_Base {
24
 
 
 
25
  /**
26
  * A link to the WordPress Database object so we don't have to "global" that every time.
27
  * @var wpdb
33
  * @var string
34
  */
35
  protected $sFullTableName;
 
 
 
 
36
 
37
  /**
38
  * @var boolean
46
  add_action( $this->getFeatureOptions()->doPluginPrefix( 'delete_plugin' ), array( $this, 'deleteDatabase' ) );
47
  }
48
 
 
 
 
 
 
49
  /**
50
  */
51
  public function deleteDatabase() {
52
  if ( apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'has_permission_to_submit' ), true ) && $this->getTableExists() ) {
53
+ $this->deleteCleanupCron();
54
  $this->dropTable();
55
  }
56
  }
90
  */
91
  protected function initializeTable() {
92
  if ( $this->getTableExists() ) {
93
+ $sFullHookName = $this->getDbCleanupHookName();
94
  add_action( $sFullHookName, array( $this, 'cleanupDatabase' ) );
95
  }
96
  else {
97
  $this->createTable();
98
  }
99
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  /**
102
  * @param $aData
246
  * Will setup the cleanup cron to clean out old entries. This should be overridden per implementation.
247
  */
248
  protected function createCleanupCron() {
249
+ $sFullHookName = $this->getDbCleanupHookName();
250
  if ( ! wp_next_scheduled( $sFullHookName ) && ! defined( 'WP_INSTALLING' ) ) {
251
  $nNextRun = strtotime( 'tomorrow 6am' ) - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
252
  wp_schedule_event( $nNextRun, 'daily', $sFullHookName );
253
  }
254
  }
255
 
256
+ /**
257
+ * Will setup the cleanup cron to clean out old entries. This should be overridden per implementation.
258
+ */
259
+ protected function deleteCleanupCron() {
260
+ wp_clear_scheduled_hook( $this->getDbCleanupHookName() );
261
+ }
262
+
263
+ /**
264
+ * @return string
265
+ */
266
+ protected function getDbCleanupHookName() {
267
+ return $this->getController()->doPluginPrefix( $this->getFeatureOptions()->getFeatureSlug().'_db_cleanup' );
268
+ }
269
+
270
  // by default does nothing - override this method
271
  public function cleanupDatabase() { }
272
 
src/icwp-processor-comments_filter.php CHANGED
@@ -31,7 +31,6 @@ class ICWP_WPSF_Processor_CommentsFilter_V2 extends ICWP_WPSF_Processor_Base {
31
  /**
32
  */
33
  public function run() {
34
- parent::run();
35
 
36
  if ( $this->getIsOption( 'enable_comments_gasp_protection', 'Y' ) ) {
37
  require_once('icwp-processor-commentsfilter_antibotspam.php');
31
  /**
32
  */
33
  public function run() {
 
34
 
35
  if ( $this->getIsOption( 'enable_comments_gasp_protection', 'Y' ) ) {
36
  require_once('icwp-processor-commentsfilter_antibotspam.php');
src/icwp-processor-commentsfilter_antibotspam.php CHANGED
@@ -61,7 +61,6 @@ class ICWP_WPSF_Processor_CommentsFilter_AntiBotSpam extends ICWP_WPSF_BaseDbPro
61
  /**
62
  */
63
  public function run() {
64
- parent::run();
65
 
66
  // Add GASP checking to the comment form.
67
  add_action( 'comment_form', array( $this, 'printGaspFormHook_Action' ), 1 );
61
  /**
62
  */
63
  public function run() {
 
64
 
65
  // Add GASP checking to the comment form.
66
  add_action( 'comment_form', array( $this, 'printGaspFormHook_Action' ), 1 );
src/icwp-processor-email.php CHANGED
@@ -62,6 +62,8 @@ class ICWP_EmailProcessor_V1 extends ICWP_WPSF_Processor_Base {
62
  parent::reset();
63
  self::$sModeFile_EmailThrottled = dirname( __FILE__ ).'/../mode.email_throttled';
64
  }
 
 
65
 
66
  /**
67
  * @param string $sEmailAddress
@@ -94,12 +96,12 @@ class ICWP_EmailProcessor_V1 extends ICWP_WPSF_Processor_Base {
94
  /**
95
  * Will send email to the default recipient setup in the object.
96
  *
97
- * @param string $insEmailSubject
98
- * @param array $inaMessage
99
  * @return boolean
100
  */
101
- public function sendEmail( $insEmailSubject, $inaMessage ) {
102
- return $this->sendEmailTo( null, $insEmailSubject, $inaMessage );
103
  }
104
 
105
  /**
@@ -171,15 +173,7 @@ class ICWP_EmailProcessor_V1 extends ICWP_WPSF_Processor_Base {
171
  * @return string
172
  */
173
  public function verifyEmailAddress( $sEmailAddress = '' ) {
174
- return ( empty( $sEmailAddress ) || !is_email( $sEmailAddress ) ) ? $this->getDefaultRecipientAddress() : $sEmailAddress;
175
- }
176
-
177
- /**
178
- * @return mixed
179
- */
180
- public function getDefaultRecipientAddress() {
181
- $oWpFunctions = $this->loadWpFunctionsProcessor();
182
- return apply_filters( $this->getFeatureOptions()->doPluginPrefix( 'report_email_address' ), $oWpFunctions->getSiteAdminEmail() );
183
  }
184
 
185
  /**
62
  parent::reset();
63
  self::$sModeFile_EmailThrottled = dirname( __FILE__ ).'/../mode.email_throttled';
64
  }
65
+
66
+ public function run() {}
67
 
68
  /**
69
  * @param string $sEmailAddress
96
  /**
97
  * Will send email to the default recipient setup in the object.
98
  *
99
+ * @param string $sEmailSubject
100
+ * @param array $aMessage
101
  * @return boolean
102
  */
103
+ public function sendEmail( $sEmailSubject, $aMessage ) {
104
+ return $this->sendEmailTo( null, $sEmailSubject, $aMessage );
105
  }
106
 
107
  /**
173
  * @return string
174
  */
175
  public function verifyEmailAddress( $sEmailAddress = '' ) {
176
+ return ( empty( $sEmailAddress ) || !is_email( $sEmailAddress ) ) ? $this->getPluginDefaultRecipientAddress() : $sEmailAddress;
 
 
 
 
 
 
 
 
177
  }
178
 
179
  /**
src/icwp-processor-firewall.php CHANGED
@@ -15,607 +15,622 @@
15
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
  */
17
 
18
- require_once( dirname(__FILE__).'/icwp-processor-base.php' );
19
 
20
  if ( !class_exists('ICWP_FirewallProcessor_V1') ):
21
 
22
- class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_Processor_Base {
23
-
24
- protected $m_aWhitelistPages;
25
- protected $m_aWhitelistPagesPatterns;
26
- protected $m_aCustomWhitelistPageParams;
27
-
28
- protected $m_aRequestUriParts;
29
-
30
- private $m_nLoopProtect;
31
- private $m_sFirewallMessage;
32
-
33
- /**
34
- * @var boolean
35
- */
36
- protected $m_fRequestIsWhitelisted;
37
-
38
- /**
39
- * @var string
40
- */
41
- protected $m_sListItemLabel;
42
-
43
- /**
44
- * A combination of all current request $_GET and $_POST (and optionally $_COOKIE)
45
- * @var array
46
- */
47
- protected $m_aOrigPageParams;
48
-
49
- /**
50
- * This is $m_aOrigPageParams after any parameter whitelisting has taken place
51
- * @var array
52
- */
53
- protected $m_aPageParams;
54
-
55
- /**
56
- * All the array values of $m_aPageParams
57
- * @var array
58
- */
59
- protected $m_aPageParamValuesToCheck;
60
-
61
- /**
62
- * All the remaining values of the page parameters after they've been filtered
63
- * @var array
64
- */
65
- protected $m_aPageParamValues;
66
-
67
- /**
68
- * @param ICWP_WPSF_FeatureHandler_Firewall $oFeatureOptions
69
- */
70
- public function __construct( ICWP_WPSF_FeatureHandler_Firewall $oFeatureOptions ) {
71
- parent::__construct( $oFeatureOptions );
72
-
73
- $sMessage = _wpsf__( "You were blocked by the %sWordPress Simple Firewall%s." );
74
- $this->m_sFirewallMessage = sprintf( $sMessage, '<a href="http://wordpress.org/plugins/wp-simple-firewall/" target="_blank">', '</a>');
75
- }
76
-
77
- public function reset() {
78
- parent::reset();
79
- $this->m_nLoopProtect = 0;
80
- $this->m_fRequestIsWhitelisted = false;
81
- }
82
-
83
- /**
84
- * @return bool|void
85
- */
86
- public function getIsLogging() {
87
- return $this->getIsOption( 'enable_firewall_log', 'Y' );
88
- }
89
-
90
- /**
91
- * Should return false when logging is disabled.
92
- *
93
- * @return false|array - false when logging is disabled, array with log data otherwise
94
- * @see ICWP_WPSF_Processor_Base::getLogData()
95
- */
96
- public function flushLogData() {
97
-
98
- if ( !$this->getIsLogging() || empty( $this->m_aLogMessages ) ) {
99
- return false;
100
  }
101
 
102
- $this->m_aLog = array(
103
- 'category' => self::LOG_CATEGORY_FIREWALL,
104
- 'messages' => serialize( $this->m_aLogMessages ),
105
- 'created_at' => self::$nRequestTimestamp,
106
- 'ip' => long2ip( self::$nRequestIp ),
107
- 'ip_long' => self::$nRequestIp,
108
- );
109
- $this->resetLog();
110
- return $this->m_aLog;
111
- }
112
-
113
- public function run() {
114
- $fIfFirewallBlockUser = !$this->doFirewallCheck();
115
 
116
- if ( $fIfFirewallBlockUser ) {
 
117
  $this->doPreFirewallBlock();
118
  $this->doFirewallBlock();
119
  }
120
- }
121
 
122
- /**
123
- * @return boolean - true if visitor is permitted, false if it should be blocked.
124
- */
125
- public function doFirewallCheck() {
126
-
127
- if ( $this->getOption('whitelist_admins') == 'Y' && is_super_admin() ) {
128
- $this->logInfo( _wpsf__('Logged-in administrators currently by-pass all firewall checking.') );
129
- return true;
130
  }
131
 
132
- // if we couldn't process the REQUEST_URI parts, we can't firewall so we effectively whitelist without erroring.
133
- $this->setRequestUriPageParts();
134
- if ( empty( $this->m_aRequestUriParts ) ) {
135
- $this->logInfo( _wpsf__('Cannot Run Firewall checking because parsing the URI failed.') );
136
- return true;
137
- }
138
 
139
- $oDp = $this->loadDataProcessor();
140
- if ( $this->getOption('ignore_search_engines') == 'Y' && $oDp->IsSearchEngineBot() ) {
141
- $this->logInfo( _wpsf__('Visitor detected as Search Engine Bot so by-passing Firewall Checking.') );
142
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  }
144
 
145
- // Set up the page parameters ($_GET and $_POST and optionally $_COOKIE). If there are none, quit since there's nothing for the firewall to check.
146
- $this->setPageParams();
147
- if ( empty( $this->m_aPageParams ) ) {
148
- $this->logInfo( _wpsf__('After whitelist options were applied, there were no page parameters to check on this visit.') );
149
- return true;
150
  }
151
- $this->m_aPageParamValuesToCheck = array_values( $this->m_aPageParams );
152
-
153
- if ( self::$nRequestIp === false ) {
154
- $this->logCritical(
155
- _wpsf__("Visitor IP address could not be determined, so by-passing the Firewall.")
 
 
 
 
156
  );
157
- return true;
 
 
 
 
 
 
158
  }
159
-
160
- // Check if the visitor is excluded from the firewall from the outset.
161
- if ( $this->isVisitorOnWhitelist() ) {
162
- $this->logInfo(
163
- sprintf( _wpsf__('Visitor is white-listed by IP Address. Label: %s'),
164
- empty( $this->m_sListItemLabel )? _wpsf__('No label.') : $this->m_sListItemLabel
165
- )
166
  );
167
- $this->doStatIncrement( 'firewall.allowed.whitelist' );
168
- return true;
 
 
 
 
 
169
  }
170
-
171
- // Check if the visitor is excluded from the firewall from the outset.
172
- if ( $this->isVisitorOnBlacklist() ) {
173
- $this->m_sFirewallMessage .= ' Your IP is Blacklisted.';
174
- $this->logWarning(
175
- sprintf( _wpsf__('Visitor was black-listed by IP Address. Label: %s'),
176
- empty( $this->m_sListItemLabel )? _wpsf__('No label.') : $this->m_sListItemLabel
177
- )
 
 
 
178
  );
179
- $this->doStatIncrement( 'firewall.blocked.blacklist' );
180
- return false;
 
 
 
 
 
 
181
  }
182
-
183
- $this->logInfo( _wpsf__('Visitor IP was neither white-listed nor black-listed. Firewall checking started...') );
184
-
185
- $fIsPermittedVisitor = true;
186
-
187
- // Check if the page and its parameters are whitelisted.
188
- if ( $fIsPermittedVisitor && $this->isPageWhitelisted() ) {
189
- $this->logWarning(
190
- _wpsf__('All page request parameters were white-listed.' )
191
  );
192
- $this->doStatIncrement( 'firewall.allowed.pagewhitelist' );
193
- return true;
194
- }
195
-
196
- if ( $fIsPermittedVisitor && $this->getIsOption( 'block_dir_traversal', 'Y' ) ) {
197
- $fIsPermittedVisitor = $this->doPassCheckBlockDirTraversal();
198
- }
199
- if ( $fIsPermittedVisitor && $this->getIsOption( 'block_sql_queries', 'Y' ) ) {
200
- $fIsPermittedVisitor = $this->doPassCheckBlockSqlQueries();
201
- }
202
- if ( $fIsPermittedVisitor && $this->getIsOption( 'block_wordpress_terms', 'Y' ) ) {
203
- $fIsPermittedVisitor = $this->doPassCheckBlockWordpressTerms();
204
- }
205
- if ( $fIsPermittedVisitor && $this->getIsOption( 'block_field_truncation', 'Y' ) ) {
206
- $fIsPermittedVisitor = $this->doPassCheckBlockFieldTruncation();
207
- }
208
- if ( $fIsPermittedVisitor && $this->getIsOption( 'block_php_code', 'Y' ) ) {
209
- $fIsPermittedVisitor = $this->doPassCheckPhpCode();
210
- }
211
- if ( $fIsPermittedVisitor && $this->getIsOption( 'block_exe_file_uploads', 'Y' ) ) {
212
- $fIsPermittedVisitor = $this->doPassCheckBlockExeFileUploads();
213
- }
214
- if ( $fIsPermittedVisitor && $this->getIsOption( 'block_leading_schema', 'Y' ) ) {
215
- $fIsPermittedVisitor = $this->doPassCheckBlockLeadingSchema();
216
  }
217
 
218
- return $fIsPermittedVisitor;
219
- }
220
-
221
- protected function doPassCheckBlockDirTraversal() {
222
- $aTerms = array(
223
- 'etc/passwd',
224
- 'proc/self/environ',
225
- '../'
226
- );
227
- $fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms );
228
- if ( !$fPass ) {
229
- $this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('Directory Traversal') ) );
230
- $this->doStatIncrement( 'firewall.blocked.dirtraversal' );
231
- }
232
- return $fPass;
233
- }
234
-
235
- protected function doPassCheckBlockSqlQueries() {
236
- $aTerms = array(
237
- '/concat\s*\(/i',
238
- '/group_concat/i',
239
- '/union.*select/i'
240
- );
241
- $fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
242
- if ( !$fPass ) {
243
- $this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('SQL Queries') ) );
244
- $this->doStatIncrement( 'firewall.blocked.sqlqueries' );
245
- }
246
- return $fPass;
247
- }
248
-
249
- protected function doPassCheckBlockWordpressTerms() {
250
- $aTerms = array(
251
- '/wp_/i',
252
- '/user_login/i',
253
- '/user_pass/i',
254
- '/0x[0-9a-f][0-9a-f]/i',
255
- '/\/\*\*\//'
256
- );
257
-
258
- $fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
259
- if ( !$fPass ) {
260
- $this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('WordPress Terms') ) );
261
- $this->doStatIncrement( 'firewall.blocked.wpterms' );
262
- }
263
- return $fPass;
264
- }
265
-
266
- protected function doPassCheckBlockFieldTruncation() {
267
- $aTerms = array(
268
- '/\s{49,}/i',
269
- '/\x00/'
270
- );
271
- $fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
272
- if ( !$fPass ) {
273
- $this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('Field Truncation') ) );
274
- $this->doStatIncrement( 'firewall.blocked.fieldtruncation' );
275
  }
276
- return $fPass;
277
- }
278
 
279
- protected function doPassCheckPhpCode() {
280
- $aTerms = array(
281
- '/(include|include_once|require|require_once)(\s*\(|\s*\'|\s*"|\s+\w+)/i'
282
- );
283
- $fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
284
- if ( !$fPass ) {
285
- $this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('PHP Code') ) );
286
- $this->doStatIncrement( 'firewall.blocked.phpcode' );
287
- }
288
- return $fPass;
289
- }
290
 
291
- protected function doPassCheckBlockExeFileUploads() {
292
- $aTerms = array(
293
- '/\.dll$/i', '/\.rb$/i', '/\.py$/i', '/\.exe$/i', '/\.php[3-6]?$/i', '/\.pl$/i',
294
- '/\.perl$/i', '/\.ph[34]$/i', '/\.phl$/i', '/\.phtml$/i', '/\.phtm$/i'
295
- );
296
-
297
- if ( isset( $_FILES ) && !empty( $_FILES ) ) {
298
- $aFileNames = array();
299
- foreach( $_FILES as $aFile ) {
300
- if ( !empty( $aFile['name'] ) ) {
301
- $aFileNames[] = $aFile['name'];
 
302
  }
 
303
  }
304
- $fPass = $this->doPassCheck( $aFileNames, $aTerms, true );
 
 
 
 
 
 
 
305
  if ( !$fPass ) {
306
- $this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('EXE File Uploads') ) );
307
- $this->doStatIncrement( 'firewall.blocked.exefile' );
 
308
  }
309
  return $fPass;
310
  }
311
- return true;
312
- }
313
-
314
- protected function doPassCheckBlockLeadingSchema() {
315
- $aTerms = array(
316
- '/^http/i', '/\.shtml$/i'
317
- );
318
- $fPass = $this->doPassCheck( $this->m_aPageParamValuesToCheck, $aTerms, true );
319
- if ( !$fPass ) {
320
- $this->logWarning( sprintf( _wpsf__('Firewall Blocked: %s'), _wpsf__('Leading Schema') ) );
321
- $this->doStatIncrement( 'firewall.blocked.schema' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  }
323
- return $fPass;
324
- }
325
-
326
- /**
327
- * Returns false when check fails - that is to say, it should be blocked by the firewall.
328
- *
329
- * @param array $inaParamValues
330
- * @param array $inaMatchTerms
331
- * @param boolean $infRegex
332
- * @return boolean
333
- */
334
- private function doPassCheck( $inaParamValues, $inaMatchTerms, $infRegex = false ) {
335
-
336
- $fFAIL = false;
337
- foreach ( $inaParamValues as $mValue ) {
338
- if ( is_array( $mValue ) ) {
339
-
340
- // Protection against an infinite loop and we limit depth to 3.
341
- if ( $this->m_nLoopProtect > 2 ) {
342
- return true;
 
 
 
 
 
 
 
 
 
 
343
  }
344
  else {
345
- $this->m_nLoopProtect++;
346
  }
347
-
348
- if ( !$this->doPassCheck( $mValue, $inaMatchTerms, $infRegex ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
349
  return false;
350
  }
351
-
352
- $this->m_nLoopProtect--;
353
  }
354
- else {
355
- $mValue = (string) $mValue;
356
- foreach ( $inaMatchTerms as $sTerm ) {
357
-
358
- if ( $infRegex && preg_match( $sTerm, $mValue ) ) { //dodgy term pattern found in a parameter value
359
- $fFAIL = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  }
361
- else if ( strpos( $mValue, $sTerm ) !== false ) { //dodgy term found in a parameter value
362
- $fFAIL = true;
 
 
 
 
 
363
  }
364
-
365
- if ( $fFAIL ) {
366
- $this->m_sFirewallMessage .= " Something in the URL, Form or Cookie data wasn't appropriate.";
367
- $this->logWarning(
368
- sprintf( 'Page parameter failed firewall check. The offending value was %s', $mValue )
369
- );
370
- return false;
 
371
  }
372
-
373
- }//foreach
374
  }
375
- }//foreach
376
 
377
- return true;
378
- }
 
 
 
 
 
 
 
 
 
 
379
 
380
- public function doPreFirewallBlock() {
381
-
382
- switch( $this->getOption( 'block_response' ) ) {
383
- case 'redirect_die':
384
- $this->logWarning(
385
- sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor connection was killed with wp_die()') )
386
- );
387
- break;
388
- case 'redirect_die_message':
389
- $this->logWarning(
390
- sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor connection was killed with wp_die() and message') )
391
- );
392
- break;
393
- case 'redirect_home':
394
- $this->logWarning(
395
- sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor was sent HOME') )
396
- );
397
- break;
398
- case 'redirect_404':
399
- $this->logWarning(
400
- sprintf( _wpsf__('Firewall Block Response: %s'), _wpsf__('Visitor was sent 404') )
401
- );
402
- break;
403
  }
404
-
405
- if ( $this->getIsOption( 'block_send_email', 'Y' ) ) {
406
- $this->sendBlockEmail();
 
 
 
407
  }
408
- }
409
 
410
- public function doFirewallBlock() {
411
-
412
- switch( $this->getOption( 'block_response' ) ) {
413
- case 'redirect_die':
414
- break;
415
- case 'redirect_die_message':
416
- wp_die( $this->m_sFirewallMessage );
417
- break;
418
- case 'redirect_home':
419
- header( "Location: ".home_url() );
420
- exit();
421
- break;
422
- case 'redirect_404':
423
- header( "Location: ".home_url().'/404' );
424
- break;
425
- default:
426
- break;
427
  }
428
- exit();
429
- }
430
-
431
- /**
432
- * @return boolean
433
- */
434
- public function isPageWhitelisted() {
435
- return empty( $this->m_aPageParams ) || $this->m_fRequestIsWhitelisted;
436
- }
437
-
438
- public function filterWhitelistedPagesAndParams() {
439
 
440
- if ( empty( $this->m_aWhitelistPages ) ) {
441
- $this->setWhitelistPages();
442
- if ( empty( $this->m_aWhitelistPages ) ) {
 
443
  return false;
444
  }
445
- }
446
- // Check normal whitelisting pages without patterns.
447
- if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPages ) ) {
448
- return true;
449
- }
450
- // Check pattern-based whitelisting pages.
451
- if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPagesPatterns, true ) ) {
452
  return true;
453
  }
454
- }
455
-
456
- /**
457
- * @param array $inaWhitelistPagesParams
458
- * @param boolean $infUseRegex
459
- * @return boolean
460
- */
461
- protected function checkPagesForWhiteListing( $inaWhitelistPagesParams = array(), $infUseRegex = false ) {
462
-
463
- if ( !is_array( $this->m_aRequestUriParts ) || count( $this->m_aRequestUriParts ) < 1 ) {
464
- return true;
465
- }
466
- $sRequestPage = $this->m_aRequestUriParts[0];
467
-
468
- // Now we compare pages in the whitelist with the parts of the request uri. If we get a match, that page is whitelisted
469
- $aWhitelistPages = array_keys( $inaWhitelistPagesParams );
470
-
471
- // 1. Is the page in the list of white pages?
472
- $fPageWhitelisted = false;
473
- foreach ( $inaWhitelistPagesParams as $sPageName => $aWhitlistedParams ) {
474
-
475
- if ( $infUseRegex ) {
476
- if ( preg_match( $sPageName, $sRequestPage ) ) {
477
- $fPageWhitelisted = true;
478
- break;
479
- }
480
  }
481
- else {
482
- $sWhitelistedPageAsPreg = preg_quote( $sPageName, self::PcreDelimiter );
483
- $sWhitelistedPageAsPreg = sprintf( '%s%s$%s', self::PcreDelimiter, $sWhitelistedPageAsPreg, self::PcreDelimiter );
484
- if ( preg_match( $sWhitelistedPageAsPreg, $sRequestPage ) ) {
485
- $fPageWhitelisted = true;
486
- break;
487
- }
488
  }
489
- }
490
-
491
- // There's a list of globally whitelisted parameters (i.e. parameter ignored for all pages)
492
- if ( array_key_exists( '*', $inaWhitelistPagesParams ) ) {
493
- foreach ( $inaWhitelistPagesParams['*'] as $sWhitelistParam ) {
494
- if ( array_key_exists( $sWhitelistParam, $this->m_aPageParams ) ) {
495
- unset( $this->m_aPageParams[ $sWhitelistParam ] );
496
- }
497
  }
 
498
  }
499
-
500
- // Given the page is found to be on the whitelist, we want to check if it's the whole page, or certain parameters only
501
- if ( $fPageWhitelisted ) {
502
- // the current page is whitelisted - now check if it has request parameters.
503
- if ( empty( $aWhitlistedParams ) ) {
504
- $this->m_fRequestIsWhitelisted = true;
505
- return true; //because it's just plain whitelisted as represented by an empty or unset array
506
- }
507
- foreach ( $aWhitlistedParams as $sWhitelistParam ) {
508
- if ( array_key_exists( $sWhitelistParam, $this->m_aPageParams ) ) {
509
- unset( $this->m_aPageParams[ $sWhitelistParam ] );
510
- }
511
- }
512
 
513
- // After removing all the whitelisted params, we now check if there are any params left that'll
514
- // need matched later in the firewall checking. If there are no parameters left, we return true.
515
- if ( empty( $this->m_aPageParams ) ) {
516
- $this->m_fRequestIsWhitelisted = true;
517
- return true;
 
 
518
  }
519
- }
520
- return false;
521
- }
522
-
523
- protected function setRequestUriPageParts() {
524
-
525
- if ( !isset( $_SERVER['REQUEST_URI'] ) || empty( $_SERVER['REQUEST_URI'] ) ) {
526
- $this->m_aRequestUriParts = false;
527
- $this->logWarning(
528
- sprintf( _wpsf__('Could not parse the details of this page call as "%s" was empty or not defined '), $_SERVER['REQUEST_URI'] )
 
 
 
 
 
 
 
 
 
 
 
 
529
  );
530
- return false;
531
- }
532
- $this->m_aRequestUriParts = explode( '?', $_SERVER['REQUEST_URI'] );
533
- $this->logInfo(
534
- sprintf( _wpsf__('Page Request URI: %s'), $_SERVER['REQUEST_URI'] )
535
- );
536
- return true;
537
- }
538
-
539
- protected function setPageParams() {
540
- $this->m_aPageParams = array_merge( $_GET, $_POST );
541
 
542
- if ( $this->getIsOption( 'include_cookie_checks', 'Y' ) ) {
543
- $this->m_aPageParams = array_merge( $this->m_aPageParams, $_COOKIE );
544
- }
545
-
546
- if ( !empty( $this->m_aPageParams ) ) {
547
- $this->filterWhitelistedPagesAndParams();
 
 
 
548
  }
549
- else {
550
- $this->m_fRequestIsWhitelisted = true;
 
551
  }
552
- return true;
553
- }
554
-
555
- private function setWhitelistPages() {
556
-
557
- $aDefaultWlPages = array(
558
- '/wp-admin/options-general.php' => array(),
559
- '/wp-admin/post-new.php' => array(),
560
- '/wp-admin/page-new.php' => array(),
561
- '/wp-admin/link-add.php' => array(),
562
- '/wp-admin/media-upload.php' => array(),
563
- '/wp-admin/post.php' => array( 'content' ),
564
- '/wp-admin/plugin-editor.php' => array( 'newcontent' ),
565
- '/wp-admin/page.php' => array(),
566
- '/wp-admin/admin-ajax.php' => array(),
567
- '/wp-comments-post.php' => array(
568
- 'url',
569
- 'comment'
570
- ),
571
- '/wp-login.php' => array(
572
- 'redirect_to'
573
- )
574
- );
575
-
576
- $aCustomWhitelistPageParams = is_array( $this->getOption( 'page_params_whitelist' ) )? $this->getOption( 'page_params_whitelist' ) : array();
577
- $this->m_aWhitelistPages = array_merge( $aDefaultWlPages, $aCustomWhitelistPageParams );
578
-
579
- $this->m_aWhitelistPagesPatterns = array(
580
- self::PcreDelimiter.'\/wp-admin\/\*'.self::PcreDelimiter => array(
581
- '_wp_original_http_referer',
582
- '_wp_http_referer'
583
- ),
584
- );
585
- }
586
-
587
- public function isVisitorOnWhitelist() {
588
- return $this->isIpOnlist( $this->getOption( 'ips_whitelist', array() ), self::$nRequestIp, $this->m_sListItemLabel );
589
- }
590
-
591
- public function isVisitorOnBlacklist() {
592
- return $this->isIpOnlist( $this->getOption( 'ips_blacklist', array() ), self::$nRequestIp, $this->m_sListItemLabel );
593
- }
594
 
595
- /**
596
- * @return boolean
597
- */
598
- public function sendBlockEmail() {
599
-
600
- $oEmailProcessor = $this->getEmailProcessor();
601
-
602
- $sIp = long2ip( self::$nRequestIp );
603
- $aMessage = array(
604
- _wpsf__('WordPress Simple Firewall has blocked a page visit to your site.'),
605
- _wpsf__('Log details for this visitor are below:'),
606
- '- '.sprintf( _wpsf__('IP Address: %s'), $sIp )
607
- );
608
- foreach( $this->m_aLogMessages as $aLogItem ) {
609
- list( $sLogType, $sLogMessage ) = $aLogItem;
610
- $aMessage[] = '- '.$sLogMessage;
611
  }
612
- $aMessage[] = sprintf( _wpsf__('You can look up the offending IP Address here: %s'), 'http://ip-lookup.net/?ip='.$sIp );
613
 
614
- $sEmailSubject = sprintf( _wpsf__('Firewall Block Email Alert: %s'), home_url() );
615
- $fSendSuccess = $oEmailProcessor->sendEmail( $sEmailSubject, $aMessage );
616
- $this->logInfo( sprintf( _wpsf__('Firewall block email alert sent %s.'), $fSendSuccess? _wpsf__('successfully') : _wpsf__('unsuccessfully') ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  }
618
- }
619
 
620
  endif;
621
 
15
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
  */
17
 
18
+ require_once( dirname(__FILE__).ICWP_DS.'icwp-processor-base.php' );
19
 
20
  if ( !class_exists('ICWP_FirewallProcessor_V1') ):
21
 
22
+ class ICWP_FirewallProcessor_V1 extends ICWP_WPSF_Processor_Base {
23
+
24
+ protected $m_aWhitelistPages;
25
+ protected $m_aWhitelistPagesPatterns;
26
+ protected $m_aCustomWhitelistPageParams;
27
+
28
+ protected $m_aRequestUriParts;
29
+
30
+ private $m_nLoopProtect;
31
+ private $sFirewallDieMessage;
32
+
33
+ private $fDoFirewallBlock;
34
+
35
+ /**
36
+ * @var boolean
37
+ */
38
+ protected $fRequestIsWhitelisted;
39
+
40
+ /**
41
+ * @var string
42
+ */
43
+ protected $m_sListItemLabel;
44
+
45
+ /**
46
+ * A combination of all current request $_GET and $_POST (and optionally $_COOKIE)
47
+ * @var array
48
+ */
49
+ protected $m_aOrigPageParams;
50
+
51
+ /**
52
+ * This is $m_aOrigPageParams after any parameter whitelisting has taken place
53
+ * @var array
54
+ */
55
+ protected $m_aPageParams;
56
+
57
+ /**
58
+ * All the remaining values of the page parameters after they've been filtered
59
+ * @var array
60
+ */
61
+ protected $m_aPageParamValues;
62
+
63
+ /**
64
+ * @param ICWP_WPSF_FeatureHandler_Firewall $oFeatureOptions
65
+ */
66
+ public function __construct( ICWP_WPSF_FeatureHandler_Firewall $oFeatureOptions ) {
67
+ parent::__construct( $oFeatureOptions );
68
+
69
+ $sMessage = _wpsf__( "You were blocked by the %s." );
70
+ $this->sFirewallDieMessage = sprintf(
71
+ $sMessage,
72
+ '<a href="http://wordpress.org/plugins/wp-simple-firewall/" target="_blank">'
73
+ .( $this->getController()->getHumanName() )
74
+ .'</a>'
75
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
 
78
+ public function reset() {
79
+ parent::reset();
80
+ $this->m_nLoopProtect = 0;
81
+ $this->setRequestIsWhiteListed( false );
82
+ }
 
 
 
 
 
 
 
 
83
 
84
+ public function run() {
85
+ $this->fDoFirewallBlock = !$this->doFirewallCheck();
86
  $this->doPreFirewallBlock();
87
  $this->doFirewallBlock();
88
  }
 
89
 
90
+ /**
91
+ * @return bool
92
+ */
93
+ public function getIfDoFirewallBlock() {
94
+ return isset( $this->fDoFirewallBlock ) ? $this->fDoFirewallBlock : false;
 
 
 
95
  }
96
 
97
+ /**
98
+ * @return boolean - true if visitor is permitted, false if it should be blocked.
99
+ */
100
+ public function doFirewallCheck() {
 
 
101
 
102
+ if ( $this->getOption('whitelist_admins') == 'Y' && is_super_admin() ) {
103
+ $sAuditMessage = sprintf( _wpsf__('Skipping firewall checking for this visit: %s.'), _wpsf__('Logged-in administrators by-pass firewall') );
104
+ $this->addToAuditEntry( $sAuditMessage, 2, 'firewall_skip' );
105
+ return true;
106
+ }
107
+
108
+ // Check if the visitor is excluded from the firewall from the outset.
109
+ if ( self::$nRequestIp !== false && $this->isVisitorOnWhitelist() ) {
110
+ $sAuditMessage = _wpsf__('Visitor is white-listed by IP Address.')
111
+ .' '.sprintf( _wpsf__('Label: %s.'), empty( $this->m_sListItemLabel )? _wpsf__('No label') : $this->m_sListItemLabel );
112
+ $this->addToAuditEntry( $sAuditMessage, 1, 'firewall_skip' );
113
+ $this->doStatIncrement( 'firewall.allowed.whitelist' );
114
+ return true;
115
+ }
116
+
117
+ // Check if the visitor is excluded from the firewall from the outset.
118
+ if ( self::$nRequestIp !== false && $this->isVisitorOnBlacklist() ) {
119
+ $this->sFirewallDieMessage .= ' Your IP is Blacklisted.';
120
+ $sAuditMessage = _wpsf__('Visitor was black-listed by IP Address.')
121
+ .' '.sprintf( _wpsf__('Label: %s.'), empty( $this->m_sListItemLabel )? _wpsf__('No label') : $this->m_sListItemLabel );
122
+ $this->addToAuditEntry( $sAuditMessage, 2, 'firewall_skip' );
123
+ $this->doStatIncrement( 'firewall.blocked.blacklist' );
124
+ return false;
125
+ }
126
+
127
+ // if we couldn't process the REQUEST_URI parts, we can't firewall so we effectively whitelist without erroring.
128
+ $this->setRequestUriPageParts();
129
+ if ( empty( $this->m_aRequestUriParts ) ) {
130
+ $sAuditMessage = sprintf( _wpsf__('Skipping firewall checking for this visit: %s.'), _wpsf__('Parsing the URI failed') );
131
+ $this->addToAuditEntry( $sAuditMessage, 2, 'firewall_skip' );
132
+ return true;
133
+ }
134
+
135
+ $oDp = $this->loadDataProcessor();
136
+ if ( $this->getOption('ignore_search_engines') == 'Y' && $oDp->IsSearchEngineBot() ) {
137
+ $sAuditMessage = sprintf( _wpsf__('Skipping firewall checking for this visit: %s.'), _wpsf__('Visitor detected as Search Engine Bot') );
138
+ $this->addToAuditEntry( $sAuditMessage, 2, 'firewall_skip' );
139
+ return true;
140
+ }
141
+
142
+ // Set up the page parameters ($_GET and $_POST and optionally $_COOKIE). If there are none, quit since there's nothing for the firewall to check.
143
+ $this->getPageParams();
144
+ if ( empty( $this->m_aPageParams ) ) {
145
+ $sAuditMessage = sprintf( _wpsf__('Skipping firewall checking for this visit: %s.'), _wpsf__('After whitelist options were applied, there were no page parameters to check') );
146
+ // $this->addToAuditEntry( $sAuditMessage, 1, 'firewall_skip' );
147
+ return true;
148
+ }
149
+
150
+ $fIsPermittedVisitor = true;
151
+ // Check if the page and its parameters are whitelisted.
152
+ if ( $fIsPermittedVisitor && $this->isPageWhitelisted() ) {
153
+ $sAuditMessage = _wpsf__('All page request parameters were white-listed.');
154
+ // $this->addToAuditEntry( $sAuditMessage, 1, 'firewall_skip' );
155
+ $this->doStatIncrement( 'firewall.allowed.pagewhitelist' );
156
+ return true;
157
+ }
158
+
159
+ if ( $fIsPermittedVisitor && $this->getIsOption( 'block_dir_traversal', 'Y' ) ) {
160
+ $fIsPermittedVisitor = $this->doPassCheckBlockDirTraversal();
161
+ }
162
+ if ( $fIsPermittedVisitor && $this->getIsOption( 'block_sql_queries', 'Y' ) ) {
163
+ $fIsPermittedVisitor = $this->doPassCheckBlockSqlQueries();
164
+ }
165
+ if ( $fIsPermittedVisitor && $this->getIsOption( 'block_wordpress_terms', 'Y' ) ) {
166
+ $fIsPermittedVisitor = $this->doPassCheckBlockWordpressTerms();
167
+ }
168
+ if ( $fIsPermittedVisitor && $this->getIsOption( 'block_field_truncation', 'Y' ) ) {
169
+ $fIsPermittedVisitor = $this->doPassCheckBlockFieldTruncation();
170
+ }
171
+ if ( $fIsPermittedVisitor && $this->getIsOption( 'block_php_code', 'Y' ) ) {
172
+ $fIsPermittedVisitor = $this->doPassCheckPhpCode();
173
+ }
174
+ if ( $fIsPermittedVisitor && $this->getIsOption( 'block_exe_file_uploads', 'Y' ) ) {
175
+ $fIsPermittedVisitor = $this->doPassCheckBlockExeFileUploads();
176
+ }
177
+ if ( $fIsPermittedVisitor && $this->getIsOption( 'block_leading_schema', 'Y' ) ) {
178
+ $fIsPermittedVisitor = $this->doPassCheckBlockLeadingSchema();
179
+ }
180
+
181
+ return $fIsPermittedVisitor;
182
  }
183
 
184
+ /**
185
+ * @return array
186
+ */
187
+ protected function getParamsToCheck() {
188
+ return $this->m_aPageParams;
189
  }
190
+
191
+ /**
192
+ * @return bool
193
+ */
194
+ protected function doPassCheckBlockDirTraversal() {
195
+ $aTerms = array(
196
+ 'etc/passwd',
197
+ 'proc/self/environ',
198
+ '../'
199
  );
200
+ $fPass = $this->doPassCheck( $this->getParamsToCheck(), $aTerms );
201
+ if ( !$fPass ) {
202
+ $sAuditMessage = sprintf( _wpsf__('Firewall Trigger: %s.'), _wpsf__('Directory Traversal') );
203
+ $this->addToAuditEntry( $sAuditMessage, 3, 'firewall_block' );
204
+ $this->doStatIncrement( 'firewall.blocked.dirtraversal' );
205
+ }
206
+ return $fPass;
207
  }
208
+
209
+ protected function doPassCheckBlockSqlQueries() {
210
+ $aTerms = array(
211
+ '/concat\s*\(/i',
212
+ '/group_concat/i',
213
+ '/union.*select/i'
 
214
  );
215
+ $fPass = $this->doPassCheck( $this->getParamsToCheck(), $aTerms, true );
216
+ if ( !$fPass ) {
217
+ $sAuditMessage = sprintf( _wpsf__('Firewall Trigger: %s.'), _wpsf__('SQL Queries') );
218
+ $this->addToAuditEntry( $sAuditMessage, 3, 'firewall_block' );
219
+ $this->doStatIncrement( 'firewall.blocked.sqlqueries' );
220
+ }
221
+ return $fPass;
222
  }
223
+
224
+ /**
225
+ * @return bool
226
+ */
227
+ protected function doPassCheckBlockWordpressTerms() {
228
+ $aTerms = array(
229
+ '/wp_/i',
230
+ '/user_login/i',
231
+ '/user_pass/i',
232
+ '/0x[0-9a-f][0-9a-f]/i',
233
+ '/\/\*\*\//'
234
  );
235
+
236
+ $fPass = $this->doPassCheck( $this->getParamsToCheck(), $aTerms, true );
237
+ if ( !$fPass ) {
238
+ $sAuditMessage = sprintf( _wpsf__('Firewall Trigger: %s.'), _wpsf__('WordPress Terms') );
239
+ $this->addToAuditEntry( $sAuditMessage, 3, 'firewall_block' );
240
+ $this->doStatIncrement( 'firewall.blocked.wpterms' );
241
+ }
242
+ return $fPass;
243
  }
244
+
245
+ /**
246
+ * @return bool
247
+ */
248
+ protected function doPassCheckBlockFieldTruncation() {
249
+ $aTerms = array(
250
+ '/\s{49,}/i',
251
+ '/\x00/'
 
252
  );
253
+ $fPass = $this->doPassCheck( $this->getParamsToCheck(), $aTerms, true );
254
+ if ( !$fPass ) {
255
+ $sAuditMessage = sprintf( _wpsf__('Firewall Trigger: %s.'), _wpsf__('Field Truncation') );
256
+ $this->addToAuditEntry( $sAuditMessage, 3, 'firewall_block' );
257
+ $this->doStatIncrement( 'firewall.blocked.fieldtruncation' );
258
+ }
259
+ return $fPass;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  }
261
 
262
+ protected function doPassCheckPhpCode() {
263
+ $aTerms = array(
264
+ '/(include|include_once|require|require_once)(\s*\(|\s*\'|\s*"|\s+\w+)/i'
265
+ );
266
+ $fPass = $this->doPassCheck( $this->getParamsToCheck(), $aTerms, true );
267
+ if ( !$fPass ) {
268
+ $sAuditMessage = sprintf( _wpsf__('Firewall Trigger: %s.'), _wpsf__('PHP Code') );
269
+ $this->addToAuditEntry( $sAuditMessage, 3, 'firewall_block' );
270
+ $this->doStatIncrement( 'firewall.blocked.phpcode' );
271
+ }
272
+ return $fPass;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  }
 
 
274
 
275
+ protected function doPassCheckBlockExeFileUploads() {
276
+ $aTerms = array(
277
+ '/\.dll$/i', '/\.rb$/i', '/\.py$/i', '/\.exe$/i', '/\.php[3-6]?$/i', '/\.pl$/i',
278
+ '/\.perl$/i', '/\.ph[34]$/i', '/\.phl$/i', '/\.phtml$/i', '/\.phtm$/i'
279
+ );
 
 
 
 
 
 
280
 
281
+ if ( isset( $_FILES ) && !empty( $_FILES ) ) {
282
+ $aFileNames = array();
283
+ foreach( $_FILES as $aFile ) {
284
+ if ( !empty( $aFile['name'] ) ) {
285
+ $aFileNames[] = $aFile['name'];
286
+ }
287
+ }
288
+ $fPass = $this->doPassCheck( $aFileNames, $aTerms, true );
289
+ if ( !$fPass ) {
290
+ $sAuditMessage = sprintf( _wpsf__('Firewall Trigger: %s.'), _wpsf__('EXE File Uploads') );
291
+ $this->addToAuditEntry( $sAuditMessage, 3, 'firewall_block' );
292
+ $this->doStatIncrement( 'firewall.blocked.exefile' );
293
  }
294
+ return $fPass;
295
  }
296
+ return true;
297
+ }
298
+
299
+ protected function doPassCheckBlockLeadingSchema() {
300
+ $aTerms = array(
301
+ '/^http/i', '/\.shtml$/i'
302
+ );
303
+ $fPass = $this->doPassCheck( $this->getParamsToCheck(), $aTerms, true );
304
  if ( !$fPass ) {
305
+ $sAuditMessage = sprintf( _wpsf__('Firewall Trigger: %s.'), _wpsf__('Leading Schema') );
306
+ $this->addToAuditEntry( $sAuditMessage, 3, 'firewall_block' );
307
+ $this->doStatIncrement( 'firewall.blocked.schema' );
308
  }
309
  return $fPass;
310
  }
311
+
312
+ /**
313
+ * Returns false when check fails - that is to say, it should be blocked by the firewall.
314
+ *
315
+ * @param array $aParamValues
316
+ * @param array $aMatchTerms
317
+ * @param boolean $fRegex
318
+ * @return boolean
319
+ */
320
+ private function doPassCheck( $aParamValues, $aMatchTerms, $fRegex = false ) {
321
+
322
+ $fFAIL = false;
323
+ foreach ( $aParamValues as $sParam => $mValue ) {
324
+ if ( is_array( $mValue ) ) {
325
+
326
+ // Protection against an infinite loop and we limit depth to 3.
327
+ if ( $this->m_nLoopProtect > 2 ) {
328
+ return true;
329
+ }
330
+ else {
331
+ $this->m_nLoopProtect++;
332
+ }
333
+
334
+ if ( !$this->doPassCheck( $mValue, $aMatchTerms, $fRegex ) ) {
335
+ return false;
336
+ }
337
+
338
+ $this->m_nLoopProtect--;
339
+ }
340
+ else {
341
+ $mValue = (string) $mValue;
342
+ foreach ( $aMatchTerms as $sTerm ) {
343
+
344
+ if ( $fRegex && preg_match( $sTerm, $mValue ) ) { //dodgy term pattern found in a parameter value
345
+ $fFAIL = true;
346
+ }
347
+ else if ( strpos( $mValue, $sTerm ) !== false ) { //dodgy term found in a parameter value
348
+ $fFAIL = true;
349
+ }
350
+
351
+ if ( $fFAIL ) {
352
+ $this->sFirewallDieMessage .= ' '._wpsf__("Something in the URL, Form or Cookie data wasn't appropriate.");
353
+ $sAuditMessage = _wpsf__('Page parameter failed firewall check.')
354
+ .' '.sprintf( _wpsf__( 'The offending parameter was "%s" with a value of "%s".' ), $sParam, $mValue );
355
+ $this->addToAuditEntry( $sAuditMessage, 3 );
356
+ return false;
357
+ }
358
+
359
+ }//foreach
360
+ }
361
+ }//foreach
362
+
363
+ return true;
364
  }
365
+
366
+ protected function doPreFirewallBlock() {
367
+
368
+ if ( !$this->getIfDoFirewallBlock() ) {
369
+ return true;
370
+ }
371
+
372
+ switch( $this->getOption( 'block_response' ) ) {
373
+ case 'redirect_die':
374
+ $sEntry = sprintf( _wpsf__('Firewall Block Response: %s.'), _wpsf__('Visitor connection was killed with wp_die()') );
375
+ break;
376
+ case 'redirect_die_message':
377
+ $sEntry = sprintf( _wpsf__('Firewall Block Response: %s.'), _wpsf__('Visitor connection was killed with wp_die() and a message') );
378
+ break;
379
+ case 'redirect_home':
380
+ $sEntry = sprintf( _wpsf__('Firewall Block Response: %s.'), _wpsf__('Visitor was sent HOME') );
381
+ break;
382
+ case 'redirect_404':
383
+ $sEntry = sprintf( _wpsf__('Firewall Block Response: %s.'), _wpsf__('Visitor was sent 404') );
384
+ break;
385
+ }
386
+
387
+ $this->addToAuditEntry( $sEntry );
388
+
389
+ if ( $this->getIsOption( 'block_send_email', 'Y' ) ) {
390
+
391
+ $sRecipient = $this->getPluginDefaultRecipientAddress();
392
+ $fSendSuccess = $this->sendBlockEmail( $sRecipient );
393
+ if ( $fSendSuccess ) {
394
+ $this->addToAuditEntry( sprintf( _wpsf__('Successfully sent Firewall Block email alert to: %s'), $sRecipient ) );
395
  }
396
  else {
397
+ $this->addToAuditEntry( sprintf( _wpsf__('Failed to send Firewall Block email alert to: %s'), $sRecipient ) );
398
  }
399
+ }
400
+ }
401
+
402
+ /**
403
+ */
404
+ protected function doFirewallBlock() {
405
+
406
+ if ( !$this->getIfDoFirewallBlock() ) {
407
+ return true;
408
+ }
409
+
410
+ switch( $this->getOption( 'block_response' ) ) {
411
+ case 'redirect_die':
412
+ break;
413
+ case 'redirect_die_message':
414
+ wp_die( $this->sFirewallDieMessage );
415
+ break;
416
+ case 'redirect_home':
417
+ header( "Location: ".home_url() );
418
+ exit();
419
+ break;
420
+ case 'redirect_404':
421
+ header( "Location: ".home_url().'/404' );
422
+ break;
423
+ default:
424
+ break;
425
+ }
426
+ exit();
427
+ }
428
+
429
+ /**
430
+ * @return boolean
431
+ */
432
+ public function isPageWhitelisted() {
433
+ $aPageParams = $this->getPageParams();
434
+ return empty( $aPageParams ) || $this->getRequestIsWhiteListed();
435
+ }
436
+
437
+ public function filterWhitelistedPagesAndParams() {
438
+
439
+ if ( empty( $this->m_aWhitelistPages ) ) {
440
+ $this->setWhitelistPages();
441
+ if ( empty( $this->m_aWhitelistPages ) ) {
442
  return false;
443
  }
 
 
444
  }
445
+ // Check normal whitelisting pages without patterns.
446
+ if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPages ) ) {
447
+ return true;
448
+ }
449
+ // Check pattern-based whitelisting pages.
450
+ if ( $this->checkPagesForWhiteListing( $this->m_aWhitelistPagesPatterns, true ) ) {
451
+ return true;
452
+ }
453
+ }
454
+
455
+ /**
456
+ * @param array $inaWhitelistPagesParams
457
+ * @param boolean $infUseRegex
458
+ * @return boolean
459
+ */
460
+ protected function checkPagesForWhiteListing( $inaWhitelistPagesParams = array(), $infUseRegex = false ) {
461
+
462
+ if ( !is_array( $this->m_aRequestUriParts ) || count( $this->m_aRequestUriParts ) < 1 ) {
463
+ return true;
464
+ }
465
+ $sRequestPage = $this->m_aRequestUriParts[0];
466
+
467
+ // Now we compare pages in the whitelist with the parts of the request uri. If we get a match, that page is whitelisted
468
+ $aWhitelistPages = array_keys( $inaWhitelistPagesParams );
469
+
470
+ // 1. Is the page in the list of white pages?
471
+ $fPageWhitelisted = false;
472
+ foreach ( $inaWhitelistPagesParams as $sPageName => $aWhitlistedParams ) {
473
+
474
+ if ( $infUseRegex ) {
475
+ if ( preg_match( $sPageName, $sRequestPage ) ) {
476
+ $fPageWhitelisted = true;
477
+ break;
478
  }
479
+ }
480
+ else {
481
+ $sWhitelistedPageAsPreg = preg_quote( $sPageName, self::PcreDelimiter );
482
+ $sWhitelistedPageAsPreg = sprintf( '%s%s$%s', self::PcreDelimiter, $sWhitelistedPageAsPreg, self::PcreDelimiter );
483
+ if ( preg_match( $sWhitelistedPageAsPreg, $sRequestPage ) ) {
484
+ $fPageWhitelisted = true;
485
+ break;
486
  }
487
+ }
488
+ }
489
+
490
+ // There's a list of globally whitelisted parameters (i.e. parameter ignored for all pages)
491
+ if ( array_key_exists( '*', $inaWhitelistPagesParams ) ) {
492
+ foreach ( $inaWhitelistPagesParams['*'] as $sWhitelistParam ) {
493
+ if ( array_key_exists( $sWhitelistParam, $this->m_aPageParams ) ) {
494
+ unset( $this->m_aPageParams[ $sWhitelistParam ] );
495
  }
496
+ }
 
497
  }
 
498
 
499
+ // Given the page is found to be on the whitelist, we want to check if it's the whole page, or certain parameters only
500
+ if ( $fPageWhitelisted ) {
501
+ // the current page is whitelisted - now check if it has request parameters.
502
+ if ( empty( $aWhitlistedParams ) ) {
503
+ $this->setRequestIsWhiteListed( true );
504
+ return true; //because it's just plain whitelisted as represented by an empty or unset array
505
+ }
506
+ foreach ( $aWhitlistedParams as $sWhitelistParam ) {
507
+ if ( array_key_exists( $sWhitelistParam, $this->m_aPageParams ) ) {
508
+ unset( $this->m_aPageParams[ $sWhitelistParam ] );
509
+ }
510
+ }
511
 
512
+ // After removing all the whitelisted params, we now check if there are any params left that'll
513
+ // need matched later in the firewall checking. If there are no parameters left, we return true.
514
+ if ( empty( $this->m_aPageParams ) ) {
515
+ $this->setRequestIsWhiteListed( true );
516
+ return true;
517
+ }
518
+ }
519
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  }
521
+
522
+ /**
523
+ * @return bool
524
+ */
525
+ protected function getRequestIsWhiteListed() {
526
+ return $this->fRequestIsWhitelisted;
527
  }
 
528
 
529
+ /**
530
+ * @param bool $fWhitelisted
531
+ */
532
+ protected function setRequestIsWhiteListed( $fWhitelisted = true ) {
533
+ $this->fRequestIsWhitelisted = $fWhitelisted;
 
 
 
 
 
 
 
 
 
 
 
 
534
  }
 
 
 
 
 
 
 
 
 
 
 
535
 
536
+ protected function setRequestUriPageParts() {
537
+
538
+ if ( !isset( $_SERVER['REQUEST_URI'] ) || empty( $_SERVER['REQUEST_URI'] ) ) {
539
+ $this->m_aRequestUriParts = false;
540
  return false;
541
  }
542
+ $this->m_aRequestUriParts = explode( '?', $_SERVER['REQUEST_URI'] );
 
 
 
 
 
 
543
  return true;
544
  }
545
+
546
+ protected function getPageParams() {
547
+
548
+ if ( isset( $this->m_aPageParams ) ) {
549
+ return $this->m_aPageParams;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550
  }
551
+
552
+ $this->m_aPageParams = $this->getRequestParams();
553
+ if ( empty( $this->m_aPageParams ) ) {
554
+ $this->setRequestIsWhiteListed( true );
 
 
 
555
  }
556
+ else {
557
+ $this->filterWhitelistedPagesAndParams();
 
 
 
 
 
 
558
  }
559
+ return true;
560
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
561
 
562
+ /**
563
+ * @return array
564
+ */
565
+ protected function getRequestParams() {
566
+ $aParams = array_merge( $_GET, $_POST );
567
+ if ( $this->getIsOption( 'include_cookie_checks', 'Y' ) ) {
568
+ $aParams = array_merge( $aParams, $_COOKIE );
569
  }
570
+ return $aParams;
571
+ }
572
+
573
+ private function setWhitelistPages() {
574
+
575
+ $aDefaultWlPages = array(
576
+ '/wp-admin/options-general.php' => array(),
577
+ '/wp-admin/post-new.php' => array(),
578
+ '/wp-admin/page-new.php' => array(),
579
+ '/wp-admin/link-add.php' => array(),
580
+ '/wp-admin/media-upload.php' => array(),
581
+ '/wp-admin/post.php' => array( 'content' ),
582
+ '/wp-admin/plugin-editor.php' => array( 'newcontent' ),
583
+ '/wp-admin/page.php' => array(),
584
+ '/wp-admin/admin-ajax.php' => array(),
585
+ '/wp-comments-post.php' => array(
586
+ 'url',
587
+ 'comment'
588
+ ),
589
+ '/wp-login.php' => array(
590
+ 'redirect_to'
591
+ )
592
  );
 
 
 
 
 
 
 
 
 
 
 
593
 
594
+ $aCustomWhitelistPageParams = is_array( $this->getOption( 'page_params_whitelist' ) )? $this->getOption( 'page_params_whitelist' ) : array();
595
+ $this->m_aWhitelistPages = array_merge( $aDefaultWlPages, $aCustomWhitelistPageParams );
596
+
597
+ $this->m_aWhitelistPagesPatterns = array(
598
+ self::PcreDelimiter.'\/wp-admin\/\*'.self::PcreDelimiter => array(
599
+ '_wp_original_http_referer',
600
+ '_wp_http_referer'
601
+ ),
602
+ );
603
  }
604
+
605
+ public function isVisitorOnWhitelist() {
606
+ return $this->isIpOnlist( $this->getOption( 'ips_whitelist', array() ), self::$nRequestIp, $this->m_sListItemLabel );
607
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
 
609
+ public function isVisitorOnBlacklist() {
610
+ return $this->isIpOnlist( $this->getOption( 'ips_blacklist', array() ), self::$nRequestIp, $this->m_sListItemLabel );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
  }
 
612
 
613
+ /**
614
+ * @param string $sRecipient
615
+ * @return bool
616
+ */
617
+ protected function sendBlockEmail( $sRecipient ) {
618
+
619
+ $sIp = long2ip( self::$nRequestIp );
620
+ $aMessage = array(
621
+ _wpsf__('WordPress Simple Firewall has blocked a page visit to your site.'),
622
+ _wpsf__('Log details for this visitor are below:'),
623
+ '- '.sprintf( _wpsf__('IP Address: %s'), $sIp )
624
+ );
625
+ $aMessage = array_merge( $aMessage, $this->getRawAuditMessage( '- ' ) );
626
+ // TODO: Get audit trail messages
627
+ $aMessage[] = sprintf( _wpsf__('You can look up the offending IP Address here: %s'), 'http://ip-lookup.net/?ip='.$sIp );
628
+ $sEmailSubject = sprintf( _wpsf__('Firewall Block Email Alert: %s'), home_url() );
629
+
630
+ $fSendSuccess = $this->getEmailProcessor()->sendEmailTo( $sRecipient, $sEmailSubject, $aMessage );
631
+ return $fSendSuccess;
632
+ }
633
  }
 
634
 
635
  endif;
636
 
src/icwp-processor-logging.php DELETED
@@ -1,122 +0,0 @@
1
- <?php
2
- /**
3
- * Copyright (c) 2014 iControlWP <support@icontrolwp.com>
4
- * All rights reserved.
5
- *
6
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
10
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
12
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
13
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
15
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
- */
17
-
18
- require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
19
-
20
- if ( !class_exists('ICWP_LoggingProcessor_V1') ):
21
-
22
- class ICWP_LoggingProcessor_V1 extends ICWP_WPSF_BaseDbProcessor {
23
-
24
- const DaysToKeepLog = 7;
25
-
26
- protected $sVisitorRequestId;
27
-
28
- /**
29
- * @param ICWP_WPSF_FeatureHandler_Logging $oFeatureOptions
30
- */
31
- public function __construct( ICWP_WPSF_FeatureHandler_Logging $oFeatureOptions ) {
32
- parent::__construct( $oFeatureOptions, $oFeatureOptions->getGeneralLoggingTableName() );
33
- }
34
-
35
- public function reset() {
36
- parent::reset();
37
- $this->m_sRequestId = uniqid();
38
- }
39
-
40
- /**
41
- * @param boolean $infReverseOrder
42
- * @return array - numerical array of all log data entries.
43
- */
44
- public function getLogs( $infReverseOrder = false ) {
45
- $aLogData = $this->selectAllFromTable();
46
- if ( $infReverseOrder && $aLogData && is_array( $aLogData ) ) {
47
- $aLogData = array_reverse( $aLogData );
48
- }
49
- return $aLogData;
50
- }
51
-
52
- /**
53
- * Ensures the log data provided has all the necessary data points to be written to the DB
54
- *
55
- * @param array $inaLogData
56
- * @return array
57
- */
58
- protected function completeDataForWrite( $inaLogData ) {
59
-
60
- if ( !isset( $inaLogData['category'] ) ) {
61
- $inaLogData['category'] = self::LOG_CATEGORY_DEFAULT;
62
- }
63
- if ( !isset( $inaLogData['request_id'] ) ) {
64
- $inaLogData['request_id'] = $this->sVisitorRequestId;
65
- }
66
- if ( !isset( $inaLogData['ip'] ) ) {
67
- $inaLogData['ip'] = self::$nRequestIp;
68
- }
69
- if ( !isset( $inaLogData['ip_long'] ) ) {
70
- $inaLogData['ip_long'] = ip2long( self::$nRequestIp );
71
- }
72
- if ( !isset( $inaLogData['created_at'] ) ) {
73
- $inaLogData['created_at'] = self::$nRequestTimestamp;
74
- }
75
- return $inaLogData;
76
- }
77
-
78
- /**
79
- * @return string
80
- */
81
- public function getCreateTableSql() {
82
- // Set up log table
83
- $sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
84
- `id` int(11) NOT NULL AUTO_INCREMENT,
85
- `request_id` varchar(255) NOT NULL DEFAULT '',
86
- `category` int(5) NOT NULL DEFAULT '0',
87
- `messages` text NOT NULL,
88
- `ip` varchar(20) NOT NULL DEFAULT '',
89
- `ip_long` bigint(20) NOT NULL DEFAULT '0',
90
- `created_at` int(15) NOT NULL DEFAULT '0',
91
- `deleted_at` int(15) NOT NULL DEFAULT '0',
92
- PRIMARY KEY (`id`)
93
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
94
- return sprintf( $sSqlTables, $this->getTableName() );
95
- }
96
-
97
- public function handleInstallUpgrade( $insCurrentVersion = '' ) {
98
- if ( version_compare( $insCurrentVersion, '1.3.0', '<' ) ) {
99
- // full delete of the log and recreate
100
- $this->recreateTable();
101
- }
102
- }
103
-
104
- /**
105
- * This is hooked into a cron in the base class and overrides the parent method.
106
- *
107
- * It'll delete everything older than 7 days.
108
- */
109
- public function cleanupDatabase() {
110
- if ( !$this->getTableExists() ) {
111
- return;
112
- }
113
- $nTimeStamp = self::$nRequestTimestamp - DAY_IN_SECONDS * self::DaysToKeepLog;
114
- $this->deleteAllRowsOlderThan( $nTimeStamp );
115
- }
116
- }
117
-
118
- endif;
119
-
120
- if ( !class_exists('ICWP_WPSF_Processor_Logging') ):
121
- class ICWP_WPSF_Processor_Logging extends ICWP_LoggingProcessor_V1 { }
122
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/icwp-processor-login_protect.php CHANGED
@@ -64,7 +64,6 @@ class ICWP_WPSF_Processor_LoginProtect_V4 extends ICWP_WPSF_Processor_Base {
64
  /**
65
  */
66
  public function run() {
67
- parent::run();
68
  $oDp = $this->loadDataProcessor();
69
  $fIsPost = $oDp->GetIsRequestPost();
70
 
@@ -118,7 +117,7 @@ class ICWP_WPSF_Processor_LoginProtect_V4 extends ICWP_WPSF_Processor_Base {
118
  $oDp = $this->loadDataProcessor();
119
  $sForceLogout = $oDp->FetchGet( 'wpsf-forcelogout' );
120
  if ( $sForceLogout == 6 ) {
121
- $oError->add( 'wpsf-forcelogout', _wpsf__('Your Two-Factor Authentication Was Verified.').'<br />'._wpsf__('Please login again.') );
122
  }
123
  return $oError;
124
  }
@@ -143,10 +142,10 @@ class ICWP_WPSF_Processor_LoginProtect_V4 extends ICWP_WPSF_Processor_Base {
143
  }
144
  }
145
 
146
- $this->logWarning(
147
- sprintf( _wpsf__('User "%s" attempted to login but the HTTP REFERER was either empty or it was a remote login attempt. Bot Perhaps? HTTP REFERER: "%s".'), $sUsername, $sHttpRef )
148
- );
149
  $this->doStatIncrement( 'login.remotepost.fail' );
 
 
 
150
  wp_die(
151
  _wpsf__( 'Sorry, you must login directly from within the site.' )
152
  .' '._wpsf__( 'Remote login is not supported.' )
@@ -154,26 +153,6 @@ class ICWP_WPSF_Processor_LoginProtect_V4 extends ICWP_WPSF_Processor_Base {
154
  );
155
  }
156
 
157
- /**
158
- * Should return false when logging is disabled.
159
- *
160
- * @return false|array - false when logging is disabled, array with log data otherwise
161
- * @see ICWP_WPSF_Processor_Base::getLogData()
162
- */
163
- public function flushLogData() {
164
-
165
- if ( !$this->getIsLogging() || empty( $this->m_aLogMessages ) ) {
166
- return false;
167
- }
168
-
169
- $this->m_aLog = array(
170
- 'category' => self::LOG_CATEGORY_LOGINPROTECT,
171
- 'messages' => serialize( $this->m_aLogMessages )
172
- );
173
- $this->resetLog();
174
- return $this->m_aLog;
175
- }
176
-
177
  /**
178
  * @return ICWP_WPSF_Processor_LoginProtect_Cooldown
179
  */
64
  /**
65
  */
66
  public function run() {
 
67
  $oDp = $this->loadDataProcessor();
68
  $fIsPost = $oDp->GetIsRequestPost();
69
 
117
  $oDp = $this->loadDataProcessor();
118
  $sForceLogout = $oDp->FetchGet( 'wpsf-forcelogout' );
119
  if ( $sForceLogout == 6 ) {
120
+ $oError->add( 'wpsf-forcelogout', _wpsf__('Your Two-Factor Authentication was un-verified or invalidated by a login from another location or browser.').'<br />'._wpsf__('Please login again.') );
121
  }
122
  return $oError;
123
  }
142
  }
143
  }
144
 
 
 
 
145
  $this->doStatIncrement( 'login.remotepost.fail' );
146
+ $sAuditMessage = sprintf( _wpsf__( 'Blocked Remote Login Attempt by user "%s", where HTTP_REFERER was "%s".' ), $sUsername, $sHttpRef );
147
+ $this->addToAuditEntry( $sAuditMessage, 3, 'login_protect_block_remote' );
148
+
149
  wp_die(
150
  _wpsf__( 'Sorry, you must login directly from within the site.' )
151
  .' '._wpsf__( 'Remote login is not supported.' )
153
  );
154
  }
155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  /**
157
  * @return ICWP_WPSF_Processor_LoginProtect_Cooldown
158
  */
src/icwp-processor-loginprotect_gasp.php CHANGED
@@ -142,23 +142,15 @@ class ICWP_WPSF_Processor_LoginProtect_Gasp extends ICWP_WPSF_Processor_Base {
142
  $sHoney = $oDp->FetchPost( 'icwp_wpsf_login_email' );
143
 
144
  if ( empty( $sGaspCheckBox ) ) {
145
- $this->logWarning(
146
- sprintf( _wpsf__('User "%s" attempted to login but GASP checkbox was not present. Bot Perhaps? IP Address: "%s".'),
147
- $sUsername,
148
- $oDp->FetchPost( false )
149
- )
150
- );
151
  $this->doStatIncrement( 'login.gasp.checkbox.fail' );
152
- wp_die( "You must check that box to say you're not a bot." );
153
  return false;
154
  }
155
  else if ( !empty( $sHoney ) ) {
156
- $this->logWarning(
157
- sprintf( _wpsf__('User "%s" attempted to login but they were caught by the GASP honey pot. Bot Perhaps? IP Address: "%s".'),
158
- $sUsername,
159
- $oDp->FetchPost( false )
160
- )
161
- );
162
  $this->doStatIncrement( 'login.gasp.honeypot.fail' );
163
  wp_die( _wpsf__('You appear to be a bot - terminating login attempt.') );
164
  return false;
142
  $sHoney = $oDp->FetchPost( 'icwp_wpsf_login_email' );
143
 
144
  if ( empty( $sGaspCheckBox ) ) {
145
+ $sAuditMessage = sprintf( _wpsf__('User "%s" attempted to login but GASP checkbox was not present.'), $sUsername ).' '._wpsf__('Probably a BOT.');
146
+ $this->addToAuditEntry( $sAuditMessage, 3, 'login_protect_block_gasp_checkbox' );
 
 
 
 
147
  $this->doStatIncrement( 'login.gasp.checkbox.fail' );
148
+ wp_die( _wpsf__( "You must check that box to say you're not a bot." ) );
149
  return false;
150
  }
151
  else if ( !empty( $sHoney ) ) {
152
+ $sAuditMessage = sprintf( _wpsf__('User "%s" attempted to login but they were caught by the GASP honeypot.'), $sUsername ).' '._wpsf__('Probably a BOT.');
153
+ $this->addToAuditEntry( $sAuditMessage, 3, 'login_protect_block_gasp_honeypot' );
 
 
 
 
154
  $this->doStatIncrement( 'login.gasp.honeypot.fail' );
155
  wp_die( _wpsf__('You appear to be a bot - terminating login attempt.') );
156
  return false;
src/icwp-processor-loginprotect_twofactorauth.php CHANGED
@@ -19,326 +19,319 @@ require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
19
 
20
  if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth') ):
21
 
22
- class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_BaseDbProcessor {
23
-
24
- const AuthActiveCookie = 'wpsf_auth';
25
-
26
- /**
27
- * @var ICWP_WPSF_FeatureHandler_LoginProtect
28
- */
29
- protected $oFeatureOptions;
30
- /**
31
- * @var string
32
- */
33
- protected $nDaysToKeepLog = 1;
34
-
35
- /**
36
- * @param ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions
37
- */
38
- public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
39
- parent::__construct( $oFeatureOptions, $oFeatureOptions->getTwoFactorAuthTableName() );
40
- }
41
-
42
- /**
43
- */
44
- public function run() {
45
- parent::run();
46
- $oDp = $this->loadDataProcessor();
47
-
48
- // User has clicked a link in their email to validate their IP address for login.
49
- if ( $oDp->FetchGet( 'wpsf-action' ) == 'linkauth' ) {
50
- add_action( 'init', array( $this, 'validateUserAuthLink' ), 10 );
51
  }
52
 
53
- // Check the current logged-in user every page load.
54
- add_action( 'init', array( $this, 'checkCurrentUserAuth' ), 11 );
 
 
55
 
56
- // At this stage (30,3) WordPress has already (20) authenticated the user. So if the login
57
- // is valid, the filter will have a valid WP_User object passed to it.
58
- add_filter( 'authenticate', array( $this, 'doUserTwoFactorAuth' ), 30, 3);
59
- }
 
 
 
60
 
61
- /**
62
- * Checks whether the current user that is logged-in is authenticated by IP address.
63
- *
64
- * If the user is not found to be valid, they're logged out.
65
- *
66
- * Should be hooked to 'init' so we have is_user_logged_in()
67
- */
68
- public function checkCurrentUserAuth() {
69
 
70
- if ( is_user_logged_in() ) {
 
 
 
 
 
 
 
71
 
72
- $oWp = $this->loadWpFunctionsProcessor();
73
- $oUser = $oWp->getCurrentWpUser();
74
- if ( !is_null( $oUser ) ) {
75
 
76
- if ( $this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) && !$this->getUserHasValidAuth( $oUser ) ) {
 
 
77
 
78
- $this->logWarning(
79
- sprintf( _wpsf__('User "%s" was forcefully logged out as they are not verified by either cookie or IP address (or both).'), $oUser->user_login )
80
- );
81
 
82
- $this->doStatIncrement( 'login.userverify.fail' );
83
- $oWp->forceUserRelogin( array( 'wpsf-forcelogout' => 6 ) );
 
 
 
84
  }
85
  }
86
  }
87
- }
88
 
89
- /**
90
- * Checks whether a given user is authenticated.
91
- *
92
- * @param WP_User $oUser
93
- * @return boolean
94
- */
95
- public function getUserHasValidAuth( $oUser ) {
 
 
 
96
 
97
- $fVerified = false;
98
- $aUserAuthData = $this->query_GetActiveAuthForUser( $oUser );
99
 
100
- if ( !is_null( $aUserAuthData ) ) {
 
 
 
 
101
 
102
- // Now we test based on which types of 2-factor auth is enabled
103
- $fVerified = true;
104
- if ( $this->oFeatureOptions->getIsTwoFactorAuthOn('ip') && ( self::$nRequestIp != $aUserAuthData['ip_long'] ) ) {
105
- $fVerified = false;
106
  }
107
 
108
- if ( $fVerified && $this->oFeatureOptions->getIsTwoFactorAuthOn('cookie') && !$this->getIsAuthCookieValid( $aUserAuthData['unique_id'] ) ) {
109
- $fVerified = false;
 
110
  }
111
- }
112
 
113
- if ( !$fVerified ) {
114
- $this->logWarning(
115
- sprintf( _wpsf__('User "%s" was found to be un-verified at the given IP Address "%s"'), $oUser->user_login, long2ip( self::$nRequestIp ) )
116
- );
117
  }
118
 
119
- return $fVerified;
120
- }
 
 
 
 
121
 
122
- /**
123
- * Checks the link details to ensure all is valid before authorizing the user.
124
- */
125
- public function validateUserAuthLink() {
126
- $oDp = $this->loadDataProcessor();
127
- // wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid
128
-
129
- if ( $oDp->FetchGet( 'wpsfkey' ) !== $this->oFeatureOptions->getTwoAuthSecretKey() ) {
130
- return false;
131
- }
132
-
133
- $sUsername = $oDp->FetchGet( 'username' );
134
- $sUniqueId = $oDp->FetchGet( 'uniqueid' );
135
 
136
- if ( empty( $sUsername ) || empty( $sUniqueId ) ) {
137
- return false;
138
- }
139
 
140
- $oWp = $this->loadWpFunctionsProcessor();
141
- if ( $this->setLoginAuthActive( $sUniqueId, $sUsername ) ) {
142
- $this->logInfo(
143
- sprintf( _wpsf__('User "%s" verified their identity using Two-Factor Authentication.'), $sUsername )
144
- );
145
- $this->doStatIncrement( 'login.twofactor.verified' );
146
- $oWp->setUserLoggedIn( $sUsername );
147
- $oWp->redirectToAdmin();
148
- }
149
- else {
150
- $oWp->redirectToLogin();
151
- }
152
- }
153
 
154
- /**
155
- * If $inoUser is a valid WP_User object, then the user logged in correctly.
156
- *
157
- * The flow is as follows:
158
- * 0. If username is empty, there was no login attempt.
159
- * 1. First we determine whether the user's login credentials were valid according to WordPress ($fUserLoginSuccess)
160
- * 2. Then we ask our 2-factor processor whether the current IP address + username combination is authenticated.
161
- * a) if yes, we return the WP_User object and login proceeds as per usual.
162
- * b) if no, we return null, which will send the message back to the user that the login details were invalid.
163
- * 3. If however the user's IP address + username combination is not authenticated, we react differently. We do not want
164
- * to give away whether a login was successful, or even the login username details exist. So:
165
- * a) if the login was a success we add a pending record to the authentication DB for this username+IP address combination and send the appropriate verification email
166
- * b) then, we give back a message saying that if the login was successful, they would have received a verification email. In this way we give nothing away.
167
- * c) note at this stage, if the username was empty, we give back nothing (this happens when wp-login.php is loaded as normal.
168
- *
169
- * @param WP_User|string $oUser - the docs say the first parameter a string, WP actually gives a WP_User object (or null)
170
- * @param string $sUsername
171
- * @param string $sPassword
172
- * @return WP_Error|WP_User|null - WP_User when the login success AND the IP is authenticated. null when login not successful but IP is valid. WP_Error otherwise.
173
- */
174
- public function doUserTwoFactorAuth( $oUser, $sUsername, $sPassword ) {
175
-
176
- if ( empty( $sUsername ) ) {
177
- return $oUser;
178
  }
179
-
180
- $fUserLoginSuccess = is_object( $oUser ) && ( $oUser instanceof WP_User );
181
 
182
- if ( $fUserLoginSuccess ) {
183
-
184
- if ( !$this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) ) {
185
- return $oUser;
186
- }
187
- if ( $this->getUserHasValidAuth( $oUser ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  return $oUser;
189
  }
190
 
191
- // Create a new 2-factor auth pending entry
192
- $aNewAuthData = $this->query_DoCreatePendingLoginAuth( $oUser->user_login );
193
 
194
- // Now send email with authentication link for user.
195
- if ( is_array( $aNewAuthData ) ) {
196
- $this->doStatIncrement( 'login.twofactor.started' );
197
- $fEmailSuccess = $this->sendEmailTwoFactorVerify( $oUser, $aNewAuthData['ip'], $aNewAuthData['unique_id'] );
198
 
199
- // Failure to send email - log them in.
200
- if ( !$fEmailSuccess && $this->getIsOption( 'enable_two_factor_bypass_on_email_fail', 'Y' ) ) {
201
- $this->setLoginAuthActive( $aNewAuthData['unique_id'], $aNewAuthData['wp_username'] );
 
202
  return $oUser;
203
  }
204
- }
205
- }
206
 
207
- // We default to returning a login cooldown error if that's in place.
208
- if ( is_wp_error( $oUser ) ) {
209
- $aCodes = $oUser->get_error_codes();
210
- if ( in_array( 'wpsf_logininterval', $aCodes ) ) {
211
- return $oUser;
212
- }
213
- }
214
 
215
- $sErrorString = _wpsf__( "Login is protected by 2-factor authentication." )
216
- .' '._wpsf__( "If your login details were correct, you will have received an email to complete the login process." ) ;
217
- return new WP_Error( 'wpsf_loginauth', $sErrorString );
218
- }
219
 
220
- /**
221
- * @param string $sUniqueId
222
- * @param string $sUsername
223
- * @return boolean
224
- */
225
- public function setLoginAuthActive( $sUniqueId, $sUsername ) {
226
- // 1. Terminate old entries
227
- $this->query_DoTerminateActiveLoginForUser( $sUsername );
228
-
229
- // 2. Authenticate new entry
230
- $aWhere = array(
231
- 'unique_id' => $sUniqueId,
232
- 'wp_username' => $sUsername
233
- );
234
- $this->query_DoMakePendingLoginAuthActive( $aWhere );
235
-
236
- // 3. Set Auth Cookie
237
- $this->setAuthActiveCookie( $sUniqueId );
238
-
239
- return true;
240
- }
241
 
242
- /**
243
- * TODO: http://stackoverflow.com/questions/3499104/how-to-know-the-role-of-current-user-in-wordpress
244
- * @param integer $nUserLevel
245
- * @return bool
246
- */
247
- protected function getIsUserLevelSubjectToTwoFactorAuth( $nUserLevel ) {
 
248
 
249
- $aSubjectedUserLevels = $this->getOption( 'two_factor_auth_user_roles' );
250
- if ( empty($aSubjectedUserLevels) || !is_array($aSubjectedUserLevels) ) {
251
- $aSubjectedUserLevels = array( 1, 2, 3, 8 ); // by default all roles except subscribers!
252
  }
253
 
254
- // see: https://codex.wordpress.org/Roles_and_Capabilities#User_Level_to_Role_Conversion
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
- // authors, contributors and subscribers
257
- if ( $nUserLevel < 3 && in_array( $nUserLevel, $aSubjectedUserLevels ) ) {
258
- return true;
259
- }
260
- // editors
261
- if ( $nUserLevel >= 3 && $nUserLevel < 8 && in_array( 3, $aSubjectedUserLevels ) ) {
262
- return true;
263
- }
264
- // administrators
265
- if ( $nUserLevel >= 8 && $nUserLevel <= 10 && in_array( 8, $aSubjectedUserLevels ) ) {
266
  return true;
267
  }
268
- return false;
269
- }
270
 
271
- /**
272
- * @param string $sUsername
273
- * @return boolean
274
- */
275
- protected function query_DoCreatePendingLoginAuth( $sUsername ) {
276
-
277
- if ( empty( $sUsername ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  return false;
279
  }
280
-
281
- // First set any other pending entries for the given user to be deleted.
282
- $aSetDeleted = array(
283
- 'deleted_at' => self::$nRequestTimestamp,
284
- 'expired_at' => self::$nRequestTimestamp,
285
- );
286
- $aOldPendingAuth = array(
287
- 'pending' => 1,
288
- 'deleted_at' => 0,
289
- 'wp_username' => $sUsername
290
- );
291
- $this->updateRowsFromTable( $aSetDeleted, $aOldPendingAuth );
292
-
293
- // Now add new pending entry
294
- $aNewData = array();
295
- $aNewData[ 'unique_id' ] = uniqid();
296
- $aNewData[ 'ip_long' ] = self::$nRequestIp;
297
- $aNewData[ 'ip' ] = long2ip( self::$nRequestIp );
298
- $aNewData[ 'wp_username' ] = $sUsername;
299
- $aNewData[ 'pending' ] = 1;
300
- $aNewData[ 'created_at' ] = self::$nRequestTimestamp;
301
-
302
- $mResult = $this->insertIntoTable( $aNewData );
303
- return $mResult ? $aNewData : $mResult;
304
- }
305
-
306
- /**
307
- * Given a unique ID and a corresponding WordPress username, will update the authentication table so that it is active (pending=0).
308
- *
309
- * @param array $aWhere - unique_id, wp_username
310
- * @return boolean
311
- */
312
- public function query_DoMakePendingLoginAuthActive( $aWhere ) {
313
-
314
- $aChecks = array( 'unique_id', 'wp_username' );
315
- if ( !$this->validateParameters( $aWhere, $aChecks ) ) {
316
- return false;
317
  }
318
 
319
- // Activate the new one.
320
- $aWhere['pending'] = 1;
321
- $aWhere['deleted_at'] = 0;
322
- $mResult = $this->updateRowsFromTable( array( 'pending' => 0 ), $aWhere );
323
- return $mResult;
324
- }
 
 
 
 
 
 
325
 
326
- /**
327
- * Invalidates all currently active two-factor logins and redirects to admin (->login)
328
- */
329
- public function doTerminateAllVerifiedLogins() {
330
- $this->query_DoTerminateAllVerifiedLogins();
331
- $oWp = $this->loadWpFunctionsProcessor();
332
- $oWp->redirectToAdmin();
333
- }
334
 
335
- /**
336
- * Given a username will soft-delete any currently active two-factor authentication.
337
- *
338
- * @param $sUsername
339
- */
340
- protected function query_DoTerminateActiveLoginForUser( $sUsername ) {
341
- $sQuery = "
 
 
 
 
 
 
 
 
 
342
  UPDATE `%s`
343
  SET `deleted_at` = '%s',
344
  `expired_at` = '%s'
@@ -347,20 +340,20 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_BaseDbPro
347
  AND `deleted_at` = '0'
348
  AND `pending` = '0'
349
  ";
350
- $sQuery = sprintf( $sQuery,
351
- $this->getTableName(),
352
- self::$nRequestTimestamp,
353
- self::$nRequestTimestamp,
354
- esc_sql( $sUsername )
355
- );
356
- $this->doSql( $sQuery );
357
- }
358
 
359
- /**
360
- *
361
- */
362
- protected function query_DoTerminateAllVerifiedLogins() {
363
- $sQuery = "
364
  UPDATE `%s`
365
  SET `deleted_at` = '%s',
366
  `expired_at` = '%s'
@@ -368,28 +361,28 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_BaseDbPro
368
  `deleted_at` = '0'
369
  AND `pending` = '0'
370
  ";
371
- $sQuery = sprintf( $sQuery,
372
- $this->getTableName(),
373
- self::$nRequestTimestamp,
374
- self::$nRequestTimestamp
375
- );
376
- return $this->doSql( $sQuery );
377
- }
378
 
379
- /**
380
- * @param $sUniqueId
381
- */
382
- public function setAuthActiveCookie( $sUniqueId ) {
383
- $nWeek = defined( 'WEEK_IN_SECONDS' )? WEEK_IN_SECONDS : 24*60*60;
384
- setcookie( $this->oFeatureOptions->getTwoFactorAuthCookieName(), $sUniqueId, self::$nRequestTimestamp+$nWeek, COOKIEPATH, COOKIE_DOMAIN, false );
385
- }
386
 
387
- /**
388
- * @param WP_User $oUser
389
- * @return mixed
390
- */
391
- protected function query_GetActiveAuthForUser( $oUser ) {
392
- $sQuery = "
393
  SELECT *
394
  FROM `%s`
395
  WHERE
@@ -399,150 +392,149 @@ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_BaseDbPro
399
  AND `expired_at` = '0'
400
  ";
401
 
402
- $sQuery = sprintf( $sQuery,
403
- $this->getTableName(),
404
- $oUser->user_login
405
- );
406
- $mResult = $this->selectCustomFromTable( $sQuery );
407
- return ( is_array( $mResult ) && count( $mResult ) == 1 ) ? $mResult[0] : null ;
408
- }
409
-
410
- /**
411
- * @param $sUniqueId
412
- * @return bool
413
- */
414
- protected function getIsAuthCookieValid( $sUniqueId ) {
415
- $oDp = $this->loadDataProcessor();
416
- return $oDp->FetchCookie( $this->oFeatureOptions->getTwoFactorAuthCookieName() ) == $sUniqueId;
417
- }
418
 
419
- /**
420
- * Given the necessary components, creates the 2-factor verification link for giving to the user.
421
- *
422
- * @param string $sUser
423
- * @param string $sUniqueId
424
- * @return string
425
- */
426
- protected function generateTwoFactorVerifyLink( $sUser, $sUniqueId ) {
427
- $aQueryArgs = array(
428
- 'wpsfkey' => $this->oFeatureOptions->getTwoAuthSecretKey(),
429
- 'wpsf-action' => 'linkauth',
430
- 'username' => $sUser,
431
- 'uniqueid' => $sUniqueId
432
- );
433
- return add_query_arg( $aQueryArgs, home_url() );
434
- }
435
 
436
- /**
437
- * @param WP_User $oUser
438
- * @param string $sIpAddress
439
- * @param string $insUniqueId
440
- * @return boolean
441
- */
442
- public function sendEmailTwoFactorVerify( WP_User $oUser, $sIpAddress, $insUniqueId ) {
443
-
444
- $sEmail = $oUser->user_email;
445
- $sAuthLink = $this->generateTwoFactorVerifyLink( $oUser->user_login, $insUniqueId );
446
-
447
- $aMessage = array(
448
- _wpsf__('You, or someone pretending to be you, just attempted to login into your WordPress site.'),
449
- _wpsf__('The IP Address / Cookie from which they tried to login is not currently verified.'),
450
- _wpsf__('Click the following link to validate and complete the login process.') .' '._wpsf__('You will be logged in automatically upon successful authentication.'),
451
- sprintf( _wpsf__('Username: %s'), $oUser->user_login ),
452
- sprintf( _wpsf__('IP Address: %s'), $sIpAddress ),
453
- sprintf( _wpsf__('Authentication Link: %s'), $sAuthLink ),
454
- );
455
- $sEmailSubject = sprintf( _wpsf__('Two-Factor Login Verification for: %s'), home_url() );
456
-
457
- // add filters to email sending (for now only Mandrill)
458
- add_filter( 'mandrill_payload', array ($this, 'customiseMandrill' ) );
459
-
460
- $fResult = $this->getEmailProcessor()->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
461
- if ( $fResult ) {
462
- $this->logInfo(
463
- sprintf( _wpsf__('User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".'), $oUser->user_login, $sIpAddress )
464
  );
 
465
  }
466
- else {
467
- $this->logCritical(
468
- sprintf( _wpsf__('Tried to send User "%s" email to verify their Identity using Two-Factor Login Auth for IP Address "%s", but email sending failed.'), $oUser->user_login, $sIpAddress )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  }
471
- return $fResult;
472
- }
473
 
474
- /**
475
- * @param array $aMessage
476
- * @return array
477
- */
478
- public function customiseMandrill( $aMessage ) {
479
- if ( empty( $aMessage['text'] ) ) {
480
- $aMessage['text'] = $aMessage['html'];
 
 
 
 
 
 
 
 
 
 
481
  }
482
- return $aMessage;
483
- }
484
 
485
- /**
486
- * @return string
487
- */
488
- public function getCreateTableSql() {
489
- $sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
490
- `id` int(11) NOT NULL AUTO_INCREMENT,
491
- `unique_id` varchar(20) NOT NULL DEFAULT '',
492
- `wp_username` varchar(255) NOT NULL DEFAULT '',
493
- `ip` varchar(20) NOT NULL DEFAULT '',
494
- `ip_long` bigint(20) NOT NULL DEFAULT '0',
495
- `pending` int(1) NOT NULL DEFAULT '0',
496
- `created_at` int(15) NOT NULL DEFAULT '0',
497
- `deleted_at` int(15) NOT NULL DEFAULT '0',
498
- `expired_at` int(15) NOT NULL DEFAULT '0',
499
- PRIMARY KEY (`id`)
500
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
501
- return sprintf( $sSqlTables, $this->getTableName() );
502
- }
503
-
504
- /**
505
- * Assumes that unique_id AND wp_username have been set correctly in the data array (no checking done).
506
- *
507
- * @param array $inaData
508
- * @return array
509
- */
510
- protected function getLoginAuthData( $inaData ) {
511
-
512
- $sQuery = "SELECT * FROM %s WHERE `unique_id` = `%s` AND `wp_username` = %s";
513
- $sQuery = sprintf( $sQuery, $this->getTableName(), $inaData['unique_id'], $inaData['wp_username'] );
514
- return $this->selectRowFromTable( $sQuery );
515
- }
516
 
517
- /**
518
- * This is hooked into a cron in the base class and overrides the parent method.
519
- *
520
- * It'll delete everything older than 24hrs.
521
- */
522
- public function cleanupDatabase() {
523
- if ( !$this->getTableExists() ) {
524
- return;
 
 
 
 
 
 
 
 
525
  }
526
- $nTimeStamp = self::$nRequestTimestamp - (DAY_IN_SECONDS * $this->nDaysToKeepLog);
527
- $this->deleteAllRowsOlderThan( $nTimeStamp );
528
- }
529
 
530
- /**
531
- * @param $nTimeStamp
532
- */
533
- protected function deleteAllRowsOlderThan( $nTimeStamp ) {
534
- $sQuery = "
535
- DELETE from `%s`
536
- WHERE
537
- `created_at` < '%s'
538
- AND `pending` = '1'
539
- ";
540
- $sQuery = sprintf( $sQuery,
541
- $this->getTableName(),
542
- esc_sql( $nTimeStamp )
543
- );
544
- $this->doSql( $sQuery );
545
  }
546
-
547
- }
548
  endif;
19
 
20
  if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth') ):
21
 
22
+ class ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth extends ICWP_WPSF_BaseDbProcessor {
23
+
24
+ /**
25
+ * @var ICWP_WPSF_FeatureHandler_LoginProtect
26
+ */
27
+ protected $oFeatureOptions;
28
+ /**
29
+ * @var string
30
+ */
31
+ protected $nDaysToKeepLog = 1;
32
+
33
+ /**
34
+ * @param ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions
35
+ */
36
+ public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
37
+ parent::__construct( $oFeatureOptions, $oFeatureOptions->getTwoFactorAuthTableName() );
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
 
40
+ /**
41
+ */
42
+ public function run() {
43
+ $oDp = $this->loadDataProcessor();
44
 
45
+ // User has clicked a link in their email to validate their IP address for login.
46
+ if ( $oDp->FetchGet( 'wpsf-action' ) == 'linkauth' ) {
47
+ add_action( 'init', array( $this, 'validateUserAuthLink' ), 10 );
48
+ }
49
+
50
+ // Check the current logged-in user every page load.
51
+ add_action( 'init', array( $this, 'checkCurrentUserAuth' ), 11 );
52
 
53
+ // At this stage (30,3) WordPress has already (20) authenticated the user. So if the login
54
+ // is valid, the filter will have a valid WP_User object passed to it.
55
+ add_filter( 'authenticate', array( $this, 'doUserTwoFactorAuth' ), 30, 3);
56
+ }
 
 
 
 
57
 
58
+ /**
59
+ * Checks whether the current user that is logged-in is authenticated by IP address.
60
+ *
61
+ * If the user is not found to be valid, they're logged out.
62
+ *
63
+ * Should be hooked to 'init' so we have is_user_logged_in()
64
+ */
65
+ public function checkCurrentUserAuth() {
66
 
67
+ if ( is_user_logged_in() ) {
 
 
68
 
69
+ $oWp = $this->loadWpFunctionsProcessor();
70
+ $oUser = $oWp->getCurrentWpUser();
71
+ if ( !is_null( $oUser ) ) {
72
 
73
+ if ( $this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) && !$this->getUserHasValidAuth( $oUser ) ) {
 
 
74
 
75
+ $sAuditMessage = sprintf( _wpsf__('User "%s" was forcefully logged out as they were not verified by either cookie or IP address (or both).'), $oUser->user_login );
76
+ $this->addToAuditEntry( $sAuditMessage, 3, 'login_protect_logout_unverified' );
77
+ $this->doStatIncrement( 'login.userverify.fail' );
78
+ $oWp->forceUserRelogin( array( 'wpsf-forcelogout' => 6 ) );
79
+ }
80
  }
81
  }
82
  }
 
83
 
84
+ /**
85
+ * Checks whether a given user is authenticated.
86
+ *
87
+ * @param WP_User $oUser
88
+ * @return boolean
89
+ */
90
+ public function getUserHasValidAuth( $oUser ) {
91
+
92
+ $fVerified = false;
93
+ $aUserAuthData = $this->query_GetActiveAuthForUser( $oUser );
94
 
95
+ if ( !is_null( $aUserAuthData ) ) {
 
96
 
97
+ // Now we test based on which types of 2-factor auth is enabled
98
+ $fVerified = true;
99
+ if ( $this->getFeatureOptions()->getIsTwoFactorAuthOn('ip') && ( self::$nRequestIp != $aUserAuthData['ip_long'] ) ) {
100
+ $fVerified = false;
101
+ }
102
 
103
+ if ( $fVerified && $this->getFeatureOptions()->getIsTwoFactorAuthOn('cookie') && !$this->getIsAuthCookieValid( $aUserAuthData['unique_id'] ) ) {
104
+ $fVerified = false;
105
+ }
 
106
  }
107
 
108
+ if ( !$fVerified ) {
109
+ $sAuditMessage = sprintf( _wpsf__('User "%s" was found to be un-verified at the given IP Address: "%s".'), $oUser->user_login, long2ip( self::$nRequestIp ) );
110
+ $this->addToAuditEntry( $sAuditMessage, 3, 'login_protect_two_factor_unverified_ip', $oUser->user_login );
111
  }
 
112
 
113
+ return $fVerified;
 
 
 
114
  }
115
 
116
+ /**
117
+ * Checks the link details to ensure all is valid before authorizing the user.
118
+ */
119
+ public function validateUserAuthLink() {
120
+ $oDp = $this->loadDataProcessor();
121
+ // wpsfkey=%s&wpsf-action=%s&username=%s&uniqueid
122
 
123
+ if ( $oDp->FetchGet( 'wpsfkey' ) !== $this->getFeatureOptions()->getTwoAuthSecretKey() ) {
124
+ return false;
125
+ }
 
 
 
 
 
 
 
 
 
 
126
 
127
+ $sUsername = $oDp->FetchGet( 'username' );
128
+ $sUniqueId = $oDp->FetchGet( 'uniqueid' );
 
129
 
130
+ if ( empty( $sUsername ) || empty( $sUniqueId ) ) {
131
+ return false;
132
+ }
 
 
 
 
 
 
 
 
 
 
133
 
134
+ $oWp = $this->loadWpFunctionsProcessor();
135
+ if ( $this->setLoginAuthActive( $sUniqueId, $sUsername ) ) {
136
+ $sAuditMessage = sprintf( _wpsf__('User "%s" verified their identity using Two-Factor Authentication.'), $sUsername );
137
+ $this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_two_factor_verified' );
138
+ $this->doStatIncrement( 'login.twofactor.verified' );
139
+ $oWp->setUserLoggedIn( $sUsername );
140
+ $oWp->redirectToAdmin();
141
+ }
142
+ else {
143
+ $oWp->redirectToLogin();
144
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  }
 
 
146
 
147
+ /**
148
+ * If $inoUser is a valid WP_User object, then the user logged in correctly.
149
+ *
150
+ * The flow is as follows:
151
+ * 0. If username is empty, there was no login attempt.
152
+ * 1. First we determine whether the user's login credentials were valid according to WordPress ($fUserLoginSuccess)
153
+ * 2. Then we ask our 2-factor processor whether the current IP address + username combination is authenticated.
154
+ * a) if yes, we return the WP_User object and login proceeds as per usual.
155
+ * b) if no, we return null, which will send the message back to the user that the login details were invalid.
156
+ * 3. If however the user's IP address + username combination is not authenticated, we react differently. We do not want
157
+ * to give away whether a login was successful, or even the login username details exist. So:
158
+ * a) if the login was a success we add a pending record to the authentication DB for this username+IP address combination and send the appropriate verification email
159
+ * b) then, we give back a message saying that if the login was successful, they would have received a verification email. In this way we give nothing away.
160
+ * c) note at this stage, if the username was empty, we give back nothing (this happens when wp-login.php is loaded as normal.
161
+ *
162
+ * @param WP_User|string $oUser - the docs say the first parameter a string, WP actually gives a WP_User object (or null)
163
+ * @param string $sUsername
164
+ * @param string $sPassword
165
+ * @return WP_Error|WP_User|null - WP_User when the login success AND the IP is authenticated. null when login not successful but IP is valid. WP_Error otherwise.
166
+ */
167
+ public function doUserTwoFactorAuth( $oUser, $sUsername, $sPassword ) {
168
+
169
+ if ( empty( $sUsername ) ) {
170
  return $oUser;
171
  }
172
 
173
+ $fUserLoginSuccess = is_object( $oUser ) && ( $oUser instanceof WP_User );
 
174
 
175
+ if ( $fUserLoginSuccess ) {
 
 
 
176
 
177
+ if ( !$this->getIsUserLevelSubjectToTwoFactorAuth( $oUser->user_level ) ) {
178
+ return $oUser;
179
+ }
180
+ if ( $this->getUserHasValidAuth( $oUser ) ) {
181
  return $oUser;
182
  }
 
 
183
 
184
+ // Create a new 2-factor auth pending entry
185
+ $aNewAuthData = $this->query_DoCreatePendingLoginAuth( $oUser->user_login );
 
 
 
 
 
186
 
187
+ // Now send email with authentication link for user.
188
+ if ( is_array( $aNewAuthData ) ) {
189
+ $this->doStatIncrement( 'login.twofactor.started' );
190
+ $fEmailSuccess = $this->sendEmailTwoFactorVerify( $oUser, $aNewAuthData['ip'], $aNewAuthData['unique_id'] );
191
 
192
+ // Failure to send email - log them in.
193
+ if ( !$fEmailSuccess && $this->getIsOption( 'enable_two_factor_bypass_on_email_fail', 'Y' ) ) {
194
+ $this->setLoginAuthActive( $aNewAuthData['unique_id'], $aNewAuthData['wp_username'] );
195
+ return $oUser;
196
+ }
197
+ }
198
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
+ // We default to returning a login cooldown error if that's in place.
201
+ if ( is_wp_error( $oUser ) ) {
202
+ $aCodes = $oUser->get_error_codes();
203
+ if ( in_array( 'wpsf_logininterval', $aCodes ) ) {
204
+ return $oUser;
205
+ }
206
+ }
207
 
208
+ $sErrorString = _wpsf__( "Login is protected by 2-factor authentication." )
209
+ .' '._wpsf__( "If your login details were correct, you will have received an email to complete the login process." ) ;
210
+ return new WP_Error( 'wpsf_loginauth', $sErrorString );
211
  }
212
 
213
+ /**
214
+ * @param string $sUniqueId
215
+ * @param string $sUsername
216
+ * @return boolean
217
+ */
218
+ public function setLoginAuthActive( $sUniqueId, $sUsername ) {
219
+ // 1. Terminate old entries
220
+ $this->query_DoTerminateActiveLoginForUser( $sUsername );
221
+
222
+ // 2. Authenticate new entry
223
+ $aWhere = array(
224
+ 'unique_id' => $sUniqueId,
225
+ 'wp_username' => $sUsername
226
+ );
227
+ $this->query_DoMakePendingLoginAuthActive( $aWhere );
228
+
229
+ // 3. Set Auth Cookie
230
+ $this->setAuthActiveCookie( $sUniqueId );
231
 
 
 
 
 
 
 
 
 
 
 
232
  return true;
233
  }
 
 
234
 
235
+ /**
236
+ * TODO: http://stackoverflow.com/questions/3499104/how-to-know-the-role-of-current-user-in-wordpress
237
+ * @param integer $nUserLevel
238
+ * @return bool
239
+ */
240
+ protected function getIsUserLevelSubjectToTwoFactorAuth( $nUserLevel ) {
241
+
242
+ $aSubjectedUserLevels = $this->getOption( 'two_factor_auth_user_roles' );
243
+ if ( empty($aSubjectedUserLevels) || !is_array($aSubjectedUserLevels) ) {
244
+ $aSubjectedUserLevels = array( 1, 2, 3, 8 ); // by default all roles except subscribers!
245
+ }
246
+
247
+ // see: https://codex.wordpress.org/Roles_and_Capabilities#User_Level_to_Role_Conversion
248
+
249
+ // authors, contributors and subscribers
250
+ if ( $nUserLevel < 3 && in_array( $nUserLevel, $aSubjectedUserLevels ) ) {
251
+ return true;
252
+ }
253
+ // editors
254
+ if ( $nUserLevel >= 3 && $nUserLevel < 8 && in_array( 3, $aSubjectedUserLevels ) ) {
255
+ return true;
256
+ }
257
+ // administrators
258
+ if ( $nUserLevel >= 8 && $nUserLevel <= 10 && in_array( 8, $aSubjectedUserLevels ) ) {
259
+ return true;
260
+ }
261
  return false;
262
  }
263
+
264
+ /**
265
+ * @param string $sUsername
266
+ * @return boolean
267
+ */
268
+ protected function query_DoCreatePendingLoginAuth( $sUsername ) {
269
+
270
+ if ( empty( $sUsername ) ) {
271
+ return false;
272
+ }
273
+
274
+ // First set any other pending entries for the given user to be deleted.
275
+ $aSetDeleted = array(
276
+ 'deleted_at' => self::$nRequestTimestamp,
277
+ 'expired_at' => self::$nRequestTimestamp,
278
+ );
279
+ $aOldPendingAuth = array(
280
+ 'pending' => 1,
281
+ 'deleted_at' => 0,
282
+ 'wp_username' => $sUsername
283
+ );
284
+ $this->updateRowsFromTable( $aSetDeleted, $aOldPendingAuth );
285
+
286
+ // Now add new pending entry
287
+ $aNewData = array();
288
+ $aNewData[ 'unique_id' ] = uniqid();
289
+ $aNewData[ 'ip_long' ] = self::$nRequestIp;
290
+ $aNewData[ 'ip' ] = long2ip( self::$nRequestIp );
291
+ $aNewData[ 'wp_username' ] = $sUsername;
292
+ $aNewData[ 'pending' ] = 1;
293
+ $aNewData[ 'created_at' ] = self::$nRequestTimestamp;
294
+
295
+ $mResult = $this->insertIntoTable( $aNewData );
296
+ return $mResult ? $aNewData : $mResult;
 
 
 
297
  }
298
 
299
+ /**
300
+ * Given a unique ID and a corresponding WordPress username, will update the authentication table so that it is active (pending=0).
301
+ *
302
+ * @param array $aWhere - unique_id, wp_username
303
+ * @return boolean
304
+ */
305
+ public function query_DoMakePendingLoginAuthActive( $aWhere ) {
306
+
307
+ $aChecks = array( 'unique_id', 'wp_username' );
308
+ if ( !$this->validateParameters( $aWhere, $aChecks ) ) {
309
+ return false;
310
+ }
311
 
312
+ // Activate the new one.
313
+ $aWhere['pending'] = 1;
314
+ $aWhere['deleted_at'] = 0;
315
+ $mResult = $this->updateRowsFromTable( array( 'pending' => 0 ), $aWhere );
316
+ return $mResult;
317
+ }
 
 
318
 
319
+ /**
320
+ * Invalidates all currently active two-factor logins and redirects to admin (->login)
321
+ */
322
+ public function doTerminateAllVerifiedLogins() {
323
+ $this->query_DoTerminateAllVerifiedLogins();
324
+ $oWp = $this->loadWpFunctionsProcessor();
325
+ $oWp->redirectToAdmin();
326
+ }
327
+
328
+ /**
329
+ * Given a username will soft-delete any currently active two-factor authentication.
330
+ *
331
+ * @param $sUsername
332
+ */
333
+ protected function query_DoTerminateActiveLoginForUser( $sUsername ) {
334
+ $sQuery = "
335
  UPDATE `%s`
336
  SET `deleted_at` = '%s',
337
  `expired_at` = '%s'
340
  AND `deleted_at` = '0'
341
  AND `pending` = '0'
342
  ";
343
+ $sQuery = sprintf( $sQuery,
344
+ $this->getTableName(),
345
+ self::$nRequestTimestamp,
346
+ self::$nRequestTimestamp,
347
+ esc_sql( $sUsername )
348
+ );
349
+ $this->doSql( $sQuery );
350
+ }
351
 
352
+ /**
353
+ *
354
+ */
355
+ protected function query_DoTerminateAllVerifiedLogins() {
356
+ $sQuery = "
357
  UPDATE `%s`
358
  SET `deleted_at` = '%s',
359
  `expired_at` = '%s'
361
  `deleted_at` = '0'
362
  AND `pending` = '0'
363
  ";
364
+ $sQuery = sprintf( $sQuery,
365
+ $this->getTableName(),
366
+ self::$nRequestTimestamp,
367
+ self::$nRequestTimestamp
368
+ );
369
+ return $this->doSql( $sQuery );
370
+ }
371
 
372
+ /**
373
+ * @param $sUniqueId
374
+ */
375
+ public function setAuthActiveCookie( $sUniqueId ) {
376
+ $nWeek = defined( 'WEEK_IN_SECONDS' )? WEEK_IN_SECONDS : 24*60*60;
377
+ setcookie( $this->getFeatureOptions()->getTwoFactorAuthCookieName(), $sUniqueId, self::$nRequestTimestamp+$nWeek, COOKIEPATH, COOKIE_DOMAIN, false );
378
+ }
379
 
380
+ /**
381
+ * @param WP_User $oUser
382
+ * @return mixed
383
+ */
384
+ protected function query_GetActiveAuthForUser( $oUser ) {
385
+ $sQuery = "
386
  SELECT *
387
  FROM `%s`
388
  WHERE
392
  AND `expired_at` = '0'
393
  ";
394
 
395
+ $sQuery = sprintf( $sQuery,
396
+ $this->getTableName(),
397
+ $oUser->user_login
398
+ );
399
+ $mResult = $this->selectCustomFromTable( $sQuery );
400
+ return ( is_array( $mResult ) && count( $mResult ) == 1 ) ? $mResult[0] : null ;
401
+ }
 
 
 
 
 
 
 
 
 
402
 
403
+ /**
404
+ * @param $sUniqueId
405
+ * @return bool
406
+ */
407
+ protected function getIsAuthCookieValid( $sUniqueId ) {
408
+ $oDp = $this->loadDataProcessor();
409
+ return $oDp->FetchCookie( $this->getFeatureOptions()->getTwoFactorAuthCookieName() ) == $sUniqueId;
410
+ }
 
 
 
 
 
 
 
 
411
 
412
+ /**
413
+ * Given the necessary components, creates the 2-factor verification link for giving to the user.
414
+ *
415
+ * @param string $sUser
416
+ * @param string $sUniqueId
417
+ * @return string
418
+ */
419
+ protected function generateTwoFactorVerifyLink( $sUser, $sUniqueId ) {
420
+ $aQueryArgs = array(
421
+ 'wpsfkey' => $this->getFeatureOptions()->getTwoAuthSecretKey(),
422
+ 'wpsf-action' => 'linkauth',
423
+ 'username' => $sUser,
424
+ 'uniqueid' => $sUniqueId
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  );
426
+ return add_query_arg( $aQueryArgs, home_url() );
427
  }
428
+
429
+ /**
430
+ * @param WP_User $oUser
431
+ * @param string $sIpAddress
432
+ * @param string $insUniqueId
433
+ * @return boolean
434
+ */
435
+ public function sendEmailTwoFactorVerify( WP_User $oUser, $sIpAddress, $insUniqueId ) {
436
+
437
+ $sEmail = $oUser->user_email;
438
+ $sAuthLink = $this->generateTwoFactorVerifyLink( $oUser->user_login, $insUniqueId );
439
+
440
+ $aMessage = array(
441
+ _wpsf__('You, or someone pretending to be you, just attempted to login into your WordPress site.'),
442
+ _wpsf__('The IP Address / Cookie from which they tried to login is not currently verified.'),
443
+ _wpsf__('Click the following link to validate and complete the login process.') .' '._wpsf__('You will be logged in automatically upon successful authentication.'),
444
+ sprintf( _wpsf__('Username: %s'), $oUser->user_login ),
445
+ sprintf( _wpsf__('IP Address: %s'), $sIpAddress ),
446
+ sprintf( _wpsf__('Authentication Link: %s'), $sAuthLink ),
447
  );
448
+ $sEmailSubject = sprintf( _wpsf__('Two-Factor Login Verification for: %s'), home_url() );
449
+
450
+ // add filters to email sending (for now only Mandrill)
451
+ add_filter( 'mandrill_payload', array ($this, 'customiseMandrill' ) );
452
+
453
+ $fResult = $this->getEmailProcessor()->sendEmailTo( $sEmail, $sEmailSubject, $aMessage );
454
+ if ( $fResult ) {
455
+ $sAuditMessage = sprintf( _wpsf__('User "%s" was sent an email to verify their Identity using Two-Factor Login Auth for IP address "%s".'), $oUser->user_login, $sIpAddress );
456
+ $this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_two_factor_email_send' );
457
+ }
458
+ else {
459
+ $sAuditMessage = sprintf( _wpsf__('Tried to send email to User "%s" to verify their identity using Two-Factor Login Auth for IP address "%s", but email sending failed.'), $oUser->user_login, $sIpAddress );
460
+ $this->addToAuditEntry( $sAuditMessage, 3, 'login_protect_two_factor_email_send_fail' );
461
+ }
462
+ return $fResult;
463
+ }
464
+
465
+ /**
466
+ * @param array $aMessage
467
+ * @return array
468
+ */
469
+ public function customiseMandrill( $aMessage ) {
470
+ if ( empty( $aMessage['text'] ) ) {
471
+ $aMessage['text'] = $aMessage['html'];
472
+ }
473
+ return $aMessage;
474
  }
 
 
475
 
476
+ /**
477
+ * @return string
478
+ */
479
+ public function getCreateTableSql() {
480
+ $sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
481
+ `id` int(11) NOT NULL AUTO_INCREMENT,
482
+ `unique_id` varchar(20) NOT NULL DEFAULT '',
483
+ `wp_username` varchar(255) NOT NULL DEFAULT '',
484
+ `ip` varchar(20) NOT NULL DEFAULT '',
485
+ `ip_long` bigint(20) NOT NULL DEFAULT '0',
486
+ `pending` int(1) NOT NULL DEFAULT '0',
487
+ `created_at` int(15) NOT NULL DEFAULT '0',
488
+ `deleted_at` int(15) NOT NULL DEFAULT '0',
489
+ `expired_at` int(15) NOT NULL DEFAULT '0',
490
+ PRIMARY KEY (`id`)
491
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
492
+ return sprintf( $sSqlTables, $this->getTableName() );
493
  }
 
 
494
 
495
+ /**
496
+ * Assumes that unique_id AND wp_username have been set correctly in the data array (no checking done).
497
+ *
498
+ * @param array $inaData
499
+ * @return array
500
+ */
501
+ protected function getLoginAuthData( $inaData ) {
502
+
503
+ $sQuery = "SELECT * FROM %s WHERE `unique_id` = `%s` AND `wp_username` = %s";
504
+ $sQuery = sprintf( $sQuery, $this->getTableName(), $inaData['unique_id'], $inaData['wp_username'] );
505
+ return $this->selectRowFromTable( $sQuery );
506
+ }
507
+
508
+ /**
509
+ * This is hooked into a cron in the base class and overrides the parent method.
510
+ *
511
+ * It'll delete everything older than 24hrs.
512
+ */
513
+ public function cleanupDatabase() {
514
+ if ( !$this->getTableExists() ) {
515
+ return;
516
+ }
517
+ $nTimeStamp = self::$nRequestTimestamp - (DAY_IN_SECONDS * $this->nDaysToKeepLog);
518
+ $this->deleteAllRowsOlderThan( $nTimeStamp );
519
+ }
 
 
 
 
 
 
520
 
521
+ /**
522
+ * @param int $nTimeStamp
523
+ * @return bool|int
524
+ */
525
+ protected function deleteAllRowsOlderThan( $nTimeStamp ) {
526
+ $sQuery = "
527
+ DELETE from `%s`
528
+ WHERE
529
+ `created_at` < '%s'
530
+ AND `pending` = '1'
531
+ ";
532
+ $sQuery = sprintf( $sQuery,
533
+ $this->getTableName(),
534
+ esc_sql( $nTimeStamp )
535
+ );
536
+ return $this->doSql( $sQuery );
537
  }
 
 
 
538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  }
 
 
540
  endif;
src/icwp-processor-loginprotect_yubikey.php CHANGED
@@ -19,149 +19,144 @@ require_once( dirname(__FILE__).'/icwp-processor-base.php' );
19
 
20
  if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_Yubikey') ):
21
 
22
- class ICWP_WPSF_Processor_LoginProtect_Yubikey extends ICWP_WPSF_Processor_Base {
23
-
24
- /**
25
- * @const string
26
- */
27
- const YubikeyVerifyApiUrl = 'https://api.yubico.com/wsapi/2.0/verify?id=%s&otp=%s&nonce=%s';
28
-
29
- /**
30
- * @var ICWP_WPSF_FeatureHandler_LoginProtect
31
- */
32
- protected $oFeatureOptions;
33
-
34
- /**
35
- */
36
- public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
37
- parent::__construct( $oFeatureOptions );
38
- }
39
-
40
- /**
41
- */
42
- public function run() {
43
- if ( $this->getIsYubikeyConfigReady() ) {
44
- add_filter( 'wp_authenticate_user', array( $this, 'checkYubikeyOtpAuth_Filter' ) );
45
- add_action( 'login_form', array( $this, 'printYubikeyOtp_Action' ) );
46
  }
47
- }
48
-
49
- /**
50
- * @param WP_User $oUser
51
- * @return WP_User|WP_Error
52
- */
53
- public function checkYubikeyOtpAuth_Filter( $oUser ) {
54
- $oError = new WP_Error();
55
 
56
- // Before anything else we check that a Yubikey pair has been provided for this username (and that there are pairs in the first place!)
57
- $aYubikeyUsernamePairs = $this->getOption('yubikey_unique_keys');
58
- if ( !$this->getIsYubikeyConfigReady() ) { // configuration is clearly not completed yet.
59
- return $oUser;
 
 
 
60
  }
61
 
62
- $sOneTimePassword = empty( $_POST['yubiotp'] )? '' : trim( $_POST['yubiotp'] );
63
- $sAppId = $this->getOption('yubikey_app_id');
64
- $sApiKey = $this->getOption('yubikey_api_key');
65
-
66
- // check that if we have a list of permitted keys, that the one used is on that list connected with the username.
67
- $sYubikey12 = substr( $sOneTimePassword, 0 , 12 );
68
- $fUsernameFound = false; // if username is never found, it means there's no yubikey specified which means we can bypass this authentication method.
69
- $fFoundMatch = false;
70
- foreach( $aYubikeyUsernamePairs as $aUsernameYubikeyPair ) {
71
- if ( isset( $aUsernameYubikeyPair[$oUser->user_login] ) ) {
72
- $fUsernameFound = true;
73
- if ( $aUsernameYubikeyPair[$oUser->user_login] == $sYubikey12 ) {
74
- $fFoundMatch = true;
75
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
  }
78
- }
79
 
80
- // If no yubikey-username pair found for given username, we by-pass Yubikey auth.
81
- if ( !$fUsernameFound ) {
82
- $this->logWarning(
83
- sprintf( _wpsf__('User "%s" logged in without a Yubikey One Time Password because no username-yubikey pair was found for this user.'), $oUser->user_login )
84
- );
85
- return $oUser;
86
- }
87
 
88
- // Username was found in the list of key pairs, but the yubikey provided didn't match that username.
89
- if ( !$fFoundMatch ) {
90
- $oError->add(
91
- 'yubikey_not_allowed',
92
- sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey provided is not on the list of permitted keys for this user.') )
93
- );
94
- $this->logWarning(
95
- sprintf( _wpsf__('User "%s" attempted to login but Yubikey ID used was not in list of authorised keys: "%s".'), $oUser->user_login, $sYubikey12 )
96
- );
97
- return $oError;
98
- }
99
 
100
- $oFs = $this->loadFileSystemProcessor();
101
-
102
- $sNonce = md5( uniqid( rand() ) );
103
- $sUrl = sprintf( self::YubikeyVerifyApiUrl, $sAppId, $sOneTimePassword, $sNonce );
104
- $sRawYubiRequest = $oFs->getUrlContent( $sUrl );
105
-
106
- // Validate response.
107
- // 1. Check OTP and Nonce
108
- if ( !preg_match( '/otp='.$sOneTimePassword.'/', $sRawYubiRequest, $aMatches )
109
- || !preg_match( '/nonce='.$sNonce.'/', $sRawYubiRequest, $aMatches )
110
- ) {
111
- $oError->add(
112
- 'yubikey_validate_fail',
113
- sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
114
- );
115
- $this->logWarning(
116
- sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API.'), $oUser->user_login )
117
- );
118
- return $oError;
119
- }
120
 
121
- // Optionally we can check the hash, but since we're using HTTPS, this isn't necessary and adds more PHP requirements
122
-
123
- // 2. Check status directly within response
124
- preg_match( '/status=([a-zA-Z0-9_]+)/', $sRawYubiRequest, $aMatches );
125
- $sStatus = $aMatches[1];
126
-
127
- if ( $sStatus != 'OK' && $sStatus != 'REPLAYED_OTP' ) {
128
- $oError->add(
129
- 'yubikey_validate_fail',
130
- sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
131
- );
132
- $this->logWarning(
133
- sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API response status: %s.'), $oUser->user_login, $sStatus )
134
- );
135
- return $oError;
136
- }
137
 
138
- $this->logInfo(
139
- sprintf( _wpsf__('User "%s" successfully logged in using a validated Yubikey One Time Password.'), $oUser->user_login )
140
- );
141
- return $oUser;
142
- }
 
 
 
 
 
 
 
 
143
 
144
- /**
145
- */
146
- public function printYubikeyOtp_Action() {
147
- $sHtml =
148
- '<p class="yubikey-otp">
 
 
 
 
 
149
  <label>%s<br />
150
  <input type="text" name="yubiotp" class="input" value="" size="20" />
151
  </label>
152
  </p>
153
  ';
154
- echo sprintf( $sHtml, '<a href="http://icwp.io/4i" target="_blank">'._wpsf__('Yubikey OTP').'</a>' );
155
- }
156
 
157
- /**
158
- * @return bool
159
- */
160
- protected function getIsYubikeyConfigReady() {
161
- $sAppId = $this->getOption('yubikey_app_id');
162
- $sApiKey = $this->getOption('yubikey_api_key');
163
- $aYubikeyKeys = $this->getOption('yubikey_unique_keys');
164
- return !empty($sAppId) && !empty($sApiKey) && !empty($aYubikeyKeys);
 
165
  }
166
- }
167
  endif;
19
 
20
  if ( !class_exists('ICWP_WPSF_Processor_LoginProtect_Yubikey') ):
21
 
22
+ class ICWP_WPSF_Processor_LoginProtect_Yubikey extends ICWP_WPSF_Processor_Base {
23
+
24
+ /**
25
+ * @const string
26
+ */
27
+ const YubikeyVerifyApiUrl = 'https://api.yubico.com/wsapi/2.0/verify?id=%s&otp=%s&nonce=%s';
28
+
29
+ /**
30
+ * @var ICWP_WPSF_FeatureHandler_LoginProtect
31
+ */
32
+ protected $oFeatureOptions;
33
+
34
+ /**
35
+ */
36
+ public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
37
+ parent::__construct( $oFeatureOptions );
 
 
 
 
 
 
 
 
38
  }
 
 
 
 
 
 
 
 
39
 
40
+ /**
41
+ */
42
+ public function run() {
43
+ if ( $this->getIsYubikeyConfigReady() ) {
44
+ add_filter( 'wp_authenticate_user', array( $this, 'checkYubikeyOtpAuth_Filter' ) );
45
+ add_action( 'login_form', array( $this, 'printYubikeyOtp_Action' ) );
46
+ }
47
  }
48
 
49
+ /**
50
+ * @param WP_User $oUser
51
+ * @return WP_User|WP_Error
52
+ */
53
+ public function checkYubikeyOtpAuth_Filter( $oUser ) {
54
+ $oError = new WP_Error();
55
+
56
+ // Before anything else we check that a Yubikey pair has been provided for this username (and that there are pairs in the first place!)
57
+ $aYubikeyUsernamePairs = $this->getOption('yubikey_unique_keys');
58
+ if ( !$this->getIsYubikeyConfigReady() ) { // configuration is clearly not completed yet.
59
+ return $oUser;
60
+ }
61
+
62
+ $sOneTimePassword = empty( $_POST['yubiotp'] )? '' : trim( $_POST['yubiotp'] );
63
+ $sAppId = $this->getOption('yubikey_app_id');
64
+ $sApiKey = $this->getOption('yubikey_api_key');
65
+
66
+ // check that if we have a list of permitted keys, that the one used is on that list connected with the username.
67
+ $sYubikey12 = substr( $sOneTimePassword, 0 , 12 );
68
+ $fUsernameFound = false; // if username is never found, it means there's no yubikey specified which means we can bypass this authentication method.
69
+ $fFoundMatch = false;
70
+ foreach( $aYubikeyUsernamePairs as $aUsernameYubikeyPair ) {
71
+ if ( isset( $aUsernameYubikeyPair[$oUser->user_login] ) ) {
72
+ $fUsernameFound = true;
73
+ if ( $aUsernameYubikeyPair[$oUser->user_login] == $sYubikey12 ) {
74
+ $fFoundMatch = true;
75
+ break;
76
+ }
77
  }
78
  }
 
79
 
80
+ // If no yubikey-username pair found for given username, we by-pass Yubikey auth.
81
+ if ( !$fUsernameFound ) {
82
+ $sAuditMessage = sprintf( _wpsf__('User "%s" logged in without a Yubikey One Time Password because no username-yubikey pair was found for this user.'), $oUser->user_login );
83
+ $this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_bypass' );
84
+ return $oUser;
85
+ }
 
86
 
87
+ // Username was found in the list of key pairs, but the yubikey provided didn't match that username.
88
+ if ( !$fFoundMatch ) {
89
+ $oError->add(
90
+ 'yubikey_not_allowed',
91
+ sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey provided is not on the list of permitted keys for this user.') )
92
+ );
93
+ $sAuditMessage = sprintf( _wpsf__('User "%s" attempted to login but Yubikey ID "%s" used was not in list of authorised keys.'), $oUser->user_login, $sYubikey12 );
94
+ $this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_fail_permitted_id' );
95
+ return $oError;
96
+ }
 
97
 
98
+ $oFs = $this->loadFileSystemProcessor();
99
+
100
+ $sNonce = md5( uniqid( rand() ) );
101
+ $sUrl = sprintf( self::YubikeyVerifyApiUrl, $sAppId, $sOneTimePassword, $sNonce );
102
+ $sRawYubiRequest = $oFs->getUrlContent( $sUrl );
103
+
104
+ // Validate response.
105
+ // 1. Check OTP and Nonce
106
+ if ( !preg_match( '/otp='.$sOneTimePassword.'/', $sRawYubiRequest, $aMatches )
107
+ || !preg_match( '/nonce='.$sNonce.'/', $sRawYubiRequest, $aMatches )
108
+ ) {
109
+ $oError->add(
110
+ 'yubikey_validate_fail',
111
+ sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
112
+ );
113
+ $sAuditMessage = sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API.'), $oUser->user_login );
114
+ $this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_fail_invalid_api' );
115
+ return $oError;
116
+ }
 
117
 
118
+ // Optionally we can check the hash, but since we're using HTTPS, this isn't necessary and adds more PHP requirements
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
+ // 2. Check status directly within response
121
+ preg_match( '/status=([a-zA-Z0-9_]+)/', $sRawYubiRequest, $aMatches );
122
+ $sStatus = $aMatches[1];
123
+
124
+ if ( $sStatus != 'OK' && $sStatus != 'REPLAYED_OTP' ) {
125
+ $oError->add(
126
+ 'yubikey_validate_fail',
127
+ sprintf( _wpsf__( 'ERROR: %s' ), _wpsf__('The Yubikey authentication was not validated successfully.') )
128
+ );
129
+ $sAuditMessage = sprintf( _wpsf__('User "%s" attempted to login but Yubikey One Time Password failed to validate due to invalid Yubi API response status: "%s".'), $oUser->user_login, $sStatus );
130
+ $this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_fail_invalid_api_response' );
131
+ return $oError;
132
+ }
133
 
134
+ $sAuditMessage = sprintf( _wpsf__('User "%s" successfully logged in using a validated Yubikey One Time Password.'), $oUser->user_login );
135
+ $this->addToAuditEntry( $sAuditMessage, 2, 'login_protect_yubikey_login_success' );
136
+ return $oUser;
137
+ }
138
+
139
+ /**
140
+ */
141
+ public function printYubikeyOtp_Action() {
142
+ $sHtml =
143
+ '<p class="yubikey-otp">
144
  <label>%s<br />
145
  <input type="text" name="yubiotp" class="input" value="" size="20" />
146
  </label>
147
  </p>
148
  ';
149
+ echo sprintf( $sHtml, '<a href="http://icwp.io/4i" target="_blank">'._wpsf__('Yubikey OTP').'</a>' );
150
+ }
151
 
152
+ /**
153
+ * @return bool
154
+ */
155
+ protected function getIsYubikeyConfigReady() {
156
+ $sAppId = $this->getOption('yubikey_app_id');
157
+ $sApiKey = $this->getOption('yubikey_api_key');
158
+ $aYubikeyKeys = $this->getOption('yubikey_unique_keys');
159
+ return !empty($sAppId) && !empty($sApiKey) && !empty($aYubikeyKeys);
160
+ }
161
  }
 
162
  endif;
src/icwp-processor-plugin.php CHANGED
@@ -40,7 +40,7 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_Base {
40
  $this->removePluginConflicts();
41
  add_filter( $oFO->doPluginPrefix( 'show_marketing' ), array( $this, 'getIsShowMarketing' ) );
42
 
43
- if ( $oFO->getController()->getIsValidAdminArea() ) {
44
 
45
  // always show this notice
46
  add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticeForceOffActive' ) );
@@ -130,7 +130,7 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_Base {
130
  return $aAdminNotices;
131
  }
132
 
133
- $sNoticeMessage = '<p>'.sprintf( _wpsf__( 'There is an update available for your WordPress Security plugin: %s.' ), '<strong>'.$this->getFeatureOptions()->getController()->getHumanName().'</strong>' ).'</p>';
134
  $sNoticeMessage .= sprintf( '<a href="%s" class="button">'._wpsf__( 'Please click to update immediately' ).'</a>', $oWp->getPluginUpgradeLink( $this->getFeatureOptions()->getPluginBaseFile() ) );
135
 
136
  $aAdminNotices[] = $this->getAdminNoticeHtml( $sNoticeMessage, 'updated', false );
@@ -142,7 +142,7 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_Base {
142
  * @return array
143
  */
144
  public function adminNoticePostPluginUpgrade( $aAdminNotices ) {
145
- $oController = $this->getFeatureOptions()->getController();
146
  $oWp = $this->loadWpFunctionsProcessor();
147
 
148
  $sCurrentMetaValue = $oWp->getUserMeta( $oController->doPluginOptionPrefix( 'current_version' ) );
@@ -152,7 +152,7 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_Base {
152
 
153
  if ( $this->getInstallationDays() <= 1 ) {
154
  $sMessage = sprintf(
155
- _wpsf__( "Note: The %s plugin does not automatically turn on feature when you install." ),
156
  $oController->getHumanName()
157
  );
158
  }
@@ -191,7 +191,7 @@ class ICWP_WPSF_Processor_Plugin extends ICWP_WPSF_Processor_Base {
191
  return $aAdminNotices;
192
  }
193
 
194
- $oController = $this->getFeatureOptions()->getController();
195
 
196
  $oWp = $this->loadWpFunctionsProcessor();
197
  $sCurrentMetaValue = $oWp->getUserMeta( $oController->doPluginOptionPrefix( 'plugin_translation_notice' ) );
40
  $this->removePluginConflicts();
41
  add_filter( $oFO->doPluginPrefix( 'show_marketing' ), array( $this, 'getIsShowMarketing' ) );
42
 
43
+ if ( $this->getController()->getIsValidAdminArea() ) {
44
 
45
  // always show this notice
46
  add_filter( $oFO->doPluginPrefix( 'admin_notices' ), array( $this, 'adminNoticeForceOffActive' ) );
130
  return $aAdminNotices;
131
  }
132
 
133
+ $sNoticeMessage = '<p>'.sprintf( _wpsf__( 'There is an update available for your WordPress Security plugin: %s.' ), '<strong>'.$this->getController()->getHumanName().'</strong>' ).'</p>';
134
  $sNoticeMessage .= sprintf( '<a href="%s" class="button">'._wpsf__( 'Please click to update immediately' ).'</a>', $oWp->getPluginUpgradeLink( $this->getFeatureOptions()->getPluginBaseFile() ) );
135
 
136
  $aAdminNotices[] = $this->getAdminNoticeHtml( $sNoticeMessage, 'updated', false );
142
  * @return array
143
  */
144
  public function adminNoticePostPluginUpgrade( $aAdminNotices ) {
145
+ $oController = $this->getController();
146
  $oWp = $this->loadWpFunctionsProcessor();
147
 
148
  $sCurrentMetaValue = $oWp->getUserMeta( $oController->doPluginOptionPrefix( 'current_version' ) );
152
 
153
  if ( $this->getInstallationDays() <= 1 ) {
154
  $sMessage = sprintf(
155
+ _wpsf__( "Note: The %s plugin does not automatically turn on features when you install." ),
156
  $oController->getHumanName()
157
  );
158
  }
191
  return $aAdminNotices;
192
  }
193
 
194
+ $oController = $this->getController();
195
 
196
  $oWp = $this->loadWpFunctionsProcessor();
197
  $sCurrentMetaValue = $oWp->getUserMeta( $oController->doPluginOptionPrefix( 'plugin_translation_notice' ) );
src/icwp-processor-privacyprotect.php CHANGED
@@ -19,83 +19,82 @@ require_once( dirname(__FILE__).'/icwp-processor-basedb.php' );
19
 
20
  if ( !class_exists('ICWP_PrivacyProtectProcessor_V1') ):
21
 
22
- class ICWP_PrivacyProtectProcessor_V1 extends ICWP_WPSF_BaseDbProcessor {
23
 
24
- const TableName = 'privacy_protect';
25
 
26
- /**
27
- * @param ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions
28
- */
29
- public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
30
- parent::__construct( $oFeatureOptions, self::TableName );
31
- $this->reset();
32
- }
33
-
34
- /**
35
- */
36
- public function run() {
37
- parent::run();
38
- if ( $this->getOption('enable_privacy_protect') == 'Y' ) {
39
- add_action( 'http_api_debug', array( $this, 'logHttpRequest' ), 1000, 5 );
40
- add_filter( 'http_request_args', array( $this, 'cleanHttpRequestData' ), 1000, 2 );
41
  }
42
- }
43
 
44
- /**
45
- * @param $oHttpResponse
46
- * @param $sResponse
47
- * @param $sCallingClass
48
- * @param $aRequestArgs
49
- * @param $sRequestUrl
50
- * @return bool
51
- */
52
- public function logHttpRequest( $oHttpResponse, $sResponse, $sCallingClass, $aRequestArgs, $sRequestUrl ) {
53
-
54
- if ( $this->getOption('ignore_local_requests') == 'Y' && $this->getIsLocalRequest($aRequestArgs) ) {
55
- return true;
56
  }
57
 
58
- // Now add new pending entry
59
- $aData = array();
60
- $aData[ 'request_url' ] = $sRequestUrl;
61
- $aData[ 'request_method' ] = $aRequestArgs['method'];
62
- $aData[ 'is_ssl' ] = strpos( $sRequestUrl, 'https' ) === 0? 1 : 0;
63
- $aData[ 'is_error' ] = is_wp_error( $oHttpResponse )? 1 : 0;
64
- $aData[ 'request_args' ] = serialize( $aRequestArgs );
65
- $aData[ 'requested_at' ] = self::$nRequestTimestamp;
66
-
67
- $mResult = $this->insertIntoTable( $aData );
68
- return $mResult;
69
- }
 
70
 
71
- /**
72
- * @param $aRequestArgs
73
- * @param $sRequestUrl
74
- * @return mixed
75
- */
76
- public function cleanHttpRequestData( $aRequestArgs, $sRequestUrl ) {
 
 
 
 
 
 
77
 
78
- $sSiteUrl = str_replace( array( 'http://', 'https://' ), '', network_home_url() );
79
- $sRandomUrl = $this->generateRandomString().'.com';
 
 
 
 
80
 
81
- if ( $this->getOption('filter_site_url') == 'Y'
82
- || ( $this->getOption('filter_wordpressorg_update_data') == 'Y' && ( strpos( $sRequestUrl, 'wordpress.org' ) !== false ) )
83
- ) {
84
- $aRequestArgs['user-agent'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['user-agent'] );
85
 
86
- $aHeaders = $aRequestArgs['headers'];
87
- foreach( $aHeaders as $sKey => $sValue ) {
88
- $aHeaders[$sKey] = str_replace( $sSiteUrl, $sRandomUrl, $aHeaders[$sKey] );
89
- }
90
- $aRequestArgs['headers'] = $aHeaders;
91
 
92
- $aRequestArgs['icwp_wpsf'] = _wpsf__( 'Site URL filtered by the WordPress Simple Firewall plugin' );
 
 
 
 
93
 
94
- // Now filter the URL only if it isn't LOCAL
95
- if ( isset( $aRequestArgs['local'] ) && $aRequestArgs['local'] != 1 ) {
96
- //unfortunately can't filter the URL.
97
- //TODO: $pre = apply_filters( 'pre_http_request', false, $r, $url );
98
- }
 
 
99
 
100
  // if ( isset($aRequestArgs['headers']['wp_install']) ) {
101
  // $aRequestArgs['headers']['wp_install'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['headers']['wp_install'] );
@@ -103,62 +102,62 @@ class ICWP_PrivacyProtectProcessor_V1 extends ICWP_WPSF_BaseDbProcessor {
103
  // if ( isset($aRequestArgs['headers']['wp_blog']) ) {
104
  // $aRequestArgs['headers']['wp_blog'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['headers']['wp_blog'] );
105
  // }
 
 
106
  }
107
- return $aRequestArgs;
108
- }
109
 
110
- /**
111
- * @param $aRequestArgs
112
- * @return bool
113
- */
114
- protected function getIsLocalRequest( &$aRequestArgs ) {
115
- return isset( $aRequestArgs['local'] ) && $aRequestArgs['local'] == 1;
116
- }
117
 
118
- /**
119
- * @param int $nLength
120
- * @return string
121
- */
122
- protected function generateRandomString( $nLength = 10 ) {
123
- $sCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
124
- $sRandomString = '';
125
- for ($i = 0; $i < $nLength; $i++) {
126
- $sRandomString .= $sCharacters[rand(0, strlen($sCharacters) - 1)];
 
 
127
  }
128
- return $sRandomString;
129
- }
130
 
131
- /**
132
- * @param boolean $infReverseOrder
133
- * @return array - numerical array of all log data entries.
134
- */
135
- public function getLogs( $infReverseOrder = false ) {
136
- $aLogData = $this->selectAllFromTable();
137
- if ( $infReverseOrder && $aLogData && is_array( $aLogData ) ) {
138
- $aLogData = array_reverse( $aLogData );
 
 
139
  }
140
- return $aLogData;
141
- }
142
 
143
- /**
144
- * @return string
145
- */
146
- public function getCreateTableSql() {
147
- $sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
148
- `id` int(11) NOT NULL AUTO_INCREMENT,
149
- `request_url` varchar(255) NOT NULL DEFAULT '',
150
- `request_port` mediumint(5) UNSIGNED NOT NULL DEFAULT 80,
151
- `request_method` varchar(4) NOT NULL DEFAULT 'GET',
152
- `request_args` text NOT NULL DEFAULT '',
153
- `is_ssl` tinyint(1) NOT NULL DEFAULT 0,
154
- `is_error` tinyint(1) NOT NULL DEFAULT 0,
155
- `requested_at` int(15) NOT NULL DEFAULT 0,
156
- `deleted_at` int(15) NOT NULL DEFAULT 0,
157
- PRIMARY KEY (`id`)
158
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
159
- return sprintf( $sSqlTables, $this->getTableName() );
 
160
  }
161
- }
162
 
163
  endif;
164
 
19
 
20
  if ( !class_exists('ICWP_PrivacyProtectProcessor_V1') ):
21
 
22
+ class ICWP_PrivacyProtectProcessor_V1 extends ICWP_WPSF_BaseDbProcessor {
23
 
24
+ const TableName = 'privacy_protect';
25
 
26
+ /**
27
+ * @param ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions
28
+ */
29
+ public function __construct( ICWP_WPSF_FeatureHandler_LoginProtect $oFeatureOptions ) {
30
+ parent::__construct( $oFeatureOptions, self::TableName );
31
+ $this->reset();
 
 
 
 
 
 
 
 
 
32
  }
 
33
 
34
+ /**
35
+ */
36
+ public function run() {
37
+ if ( $this->getOption('enable_privacy_protect') == 'Y' ) {
38
+ add_action( 'http_api_debug', array( $this, 'logHttpRequest' ), 1000, 5 );
39
+ add_filter( 'http_request_args', array( $this, 'cleanHttpRequestData' ), 1000, 2 );
40
+ }
 
 
 
 
 
41
  }
42
 
43
+ /**
44
+ * @param $oHttpResponse
45
+ * @param $sResponse
46
+ * @param $sCallingClass
47
+ * @param $aRequestArgs
48
+ * @param $sRequestUrl
49
+ * @return bool
50
+ */
51
+ public function logHttpRequest( $oHttpResponse, $sResponse, $sCallingClass, $aRequestArgs, $sRequestUrl ) {
52
+
53
+ if ( $this->getOption('ignore_local_requests') == 'Y' && $this->getIsLocalRequest($aRequestArgs) ) {
54
+ return true;
55
+ }
56
 
57
+ // Now add new pending entry
58
+ $aData = array();
59
+ $aData[ 'request_url' ] = $sRequestUrl;
60
+ $aData[ 'request_method' ] = $aRequestArgs['method'];
61
+ $aData[ 'is_ssl' ] = strpos( $sRequestUrl, 'https' ) === 0? 1 : 0;
62
+ $aData[ 'is_error' ] = is_wp_error( $oHttpResponse )? 1 : 0;
63
+ $aData[ 'request_args' ] = serialize( $aRequestArgs );
64
+ $aData[ 'requested_at' ] = self::$nRequestTimestamp;
65
+
66
+ $mResult = $this->insertIntoTable( $aData );
67
+ return $mResult;
68
+ }
69
 
70
+ /**
71
+ * @param $aRequestArgs
72
+ * @param $sRequestUrl
73
+ * @return mixed
74
+ */
75
+ public function cleanHttpRequestData( $aRequestArgs, $sRequestUrl ) {
76
 
77
+ $sSiteUrl = str_replace( array( 'http://', 'https://' ), '', network_home_url() );
78
+ $sRandomUrl = $this->generateRandomString().'.com';
 
 
79
 
80
+ if ( $this->getOption('filter_site_url') == 'Y'
81
+ || ( $this->getOption('filter_wordpressorg_update_data') == 'Y' && ( strpos( $sRequestUrl, 'wordpress.org' ) !== false ) )
82
+ ) {
83
+ $aRequestArgs['user-agent'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['user-agent'] );
 
84
 
85
+ $aHeaders = $aRequestArgs['headers'];
86
+ foreach( $aHeaders as $sKey => $sValue ) {
87
+ $aHeaders[$sKey] = str_replace( $sSiteUrl, $sRandomUrl, $aHeaders[$sKey] );
88
+ }
89
+ $aRequestArgs['headers'] = $aHeaders;
90
 
91
+ $aRequestArgs['icwp_wpsf'] = _wpsf__( 'Site URL filtered by the WordPress Simple Firewall plugin' );
92
+
93
+ // Now filter the URL only if it isn't LOCAL
94
+ if ( isset( $aRequestArgs['local'] ) && $aRequestArgs['local'] != 1 ) {
95
+ //unfortunately can't filter the URL.
96
+ //TODO: $pre = apply_filters( 'pre_http_request', false, $r, $url );
97
+ }
98
 
99
  // if ( isset($aRequestArgs['headers']['wp_install']) ) {
100
  // $aRequestArgs['headers']['wp_install'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['headers']['wp_install'] );
102
  // if ( isset($aRequestArgs['headers']['wp_blog']) ) {
103
  // $aRequestArgs['headers']['wp_blog'] = str_replace( $sSiteUrl, $sRandomUrl, $aRequestArgs['headers']['wp_blog'] );
104
  // }
105
+ }
106
+ return $aRequestArgs;
107
  }
 
 
108
 
109
+ /**
110
+ * @param $aRequestArgs
111
+ * @return bool
112
+ */
113
+ protected function getIsLocalRequest( &$aRequestArgs ) {
114
+ return isset( $aRequestArgs['local'] ) && $aRequestArgs['local'] == 1;
115
+ }
116
 
117
+ /**
118
+ * @param int $nLength
119
+ * @return string
120
+ */
121
+ protected function generateRandomString( $nLength = 10 ) {
122
+ $sCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
123
+ $sRandomString = '';
124
+ for ($i = 0; $i < $nLength; $i++) {
125
+ $sRandomString .= $sCharacters[rand(0, strlen($sCharacters) - 1)];
126
+ }
127
+ return $sRandomString;
128
  }
 
 
129
 
130
+ /**
131
+ * @param boolean $infReverseOrder
132
+ * @return array - numerical array of all log data entries.
133
+ */
134
+ public function getLogs( $infReverseOrder = false ) {
135
+ $aLogData = $this->selectAllFromTable();
136
+ if ( $infReverseOrder && $aLogData && is_array( $aLogData ) ) {
137
+ $aLogData = array_reverse( $aLogData );
138
+ }
139
+ return $aLogData;
140
  }
 
 
141
 
142
+ /**
143
+ * @return string
144
+ */
145
+ public function getCreateTableSql() {
146
+ $sSqlTables = "CREATE TABLE IF NOT EXISTS `%s` (
147
+ `id` int(11) NOT NULL AUTO_INCREMENT,
148
+ `request_url` varchar(255) NOT NULL DEFAULT '',
149
+ `request_port` mediumint(5) UNSIGNED NOT NULL DEFAULT 80,
150
+ `request_method` varchar(4) NOT NULL DEFAULT 'GET',
151
+ `request_args` text NOT NULL DEFAULT '',
152
+ `is_ssl` tinyint(1) NOT NULL DEFAULT 0,
153
+ `is_error` tinyint(1) NOT NULL DEFAULT 0,
154
+ `requested_at` int(15) NOT NULL DEFAULT 0,
155
+ `deleted_at` int(15) NOT NULL DEFAULT 0,
156
+ PRIMARY KEY (`id`)
157
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8;";
158
+ return sprintf( $sSqlTables, $this->getTableName() );
159
+ }
160
  }
 
161
 
162
  endif;
163
 
src/icwp-processor-user_management.php CHANGED
@@ -47,10 +47,10 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_WPSF_BaseDbProcessor {
47
  /**
48
  */
49
  public function run() {
50
- parent::run();
51
  $oDp = $this->loadDataProcessor();
 
52
 
53
- $oWp = $this->oFeatureOptions->loadWpFunctionsProcessor();
54
  // XML-RPC Compatibility
55
  if ( $oWp->getIsXmlrpc() && $this->getIsOption( 'enable_xmlrpc_compatibility', 'Y' ) ) {
56
  return true;
@@ -58,7 +58,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_WPSF_BaseDbProcessor {
58
 
59
  if ( is_email( $this->getOption( 'enable_admin_login_email_notification' ) ) ) {
60
  require_once('icwp-processor-usermanagement_adminloginnotification.php');
61
- $oNotificationProcessor = new ICWP_WPSF_Processor_UserManagement_AdminLoginNotification( $this->oFeatureOptions );
62
  $oNotificationProcessor->run();
63
  }
64
 
@@ -202,26 +202,6 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_WPSF_BaseDbProcessor {
202
  return ( ( $nSessionTimeoutInterval > 0 )? $nSessionTimeoutInterval : $nTimeout );
203
  }
204
 
205
- /**
206
- * Should return false when logging is disabled.
207
- *
208
- * @return false|array - false when logging is disabled, array with log data otherwise
209
- * @see ICWP_WPSF_Processor_Base::getLogData()
210
- */
211
- public function flushLogData() {
212
-
213
- if ( !$this->getIsLogging() || empty( $this->m_aLogMessages ) ) {
214
- return false;
215
- }
216
-
217
- $this->m_aLog = array(
218
- 'category' => self::LOG_CATEGORY_LOGINPROTECT,
219
- 'messages' => serialize( $this->m_aLogMessages )
220
- );
221
- $this->resetLog();
222
- return $this->m_aLog;
223
- }
224
-
225
  /**
226
  * If $oUser is a valid WP_User object, then the user logged in correctly.
227
  *
@@ -621,7 +601,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_WPSF_BaseDbProcessor {
621
  protected function getSessionId() {
622
  if ( empty( $this->sSessionId ) ) {
623
  $oDp = $this->loadDataProcessor();
624
- $this->sSessionId = $oDp->FetchCookie( $this->oFeatureOptions->getUserSessionCookieName() );
625
  if ( empty( $this->sSessionId ) ) {
626
  $this->sSessionId = md5( uniqid() );
627
  $this->setSessionCookie();
@@ -666,7 +646,8 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_WPSF_BaseDbProcessor {
666
  }
667
 
668
  /**
669
- * @param $nTimeStamp
 
670
  */
671
  protected function deleteAllRowsOlderThan( $nTimeStamp ) {
672
  $sQuery = "
@@ -679,7 +660,7 @@ class ICWP_WPSF_Processor_UserManagement_V1 extends ICWP_WPSF_BaseDbProcessor {
679
  $this->getTableName(),
680
  esc_sql( $nTimeStamp )
681
  );
682
- $this->doSql( $sQuery );
683
  }
684
 
685
  }
47
  /**
48
  */
49
  public function run() {
50
+
51
  $oDp = $this->loadDataProcessor();
52
+ $oWp = $this->loadWpFunctionsProcessor();
53
 
 
54
  // XML-RPC Compatibility
55
  if ( $oWp->getIsXmlrpc() && $this->getIsOption( 'enable_xmlrpc_compatibility', 'Y' ) ) {
56
  return true;
58
 
59
  if ( is_email( $this->getOption( 'enable_admin_login_email_notification' ) ) ) {
60
  require_once('icwp-processor-usermanagement_adminloginnotification.php');
61
+ $oNotificationProcessor = new ICWP_WPSF_Processor_UserManagement_AdminLoginNotification( $this->getFeatureOptions() );
62
  $oNotificationProcessor->run();
63
  }
64
 
202
  return ( ( $nSessionTimeoutInterval > 0 )? $nSessionTimeoutInterval : $nTimeout );
203
  }
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  /**
206
  * If $oUser is a valid WP_User object, then the user logged in correctly.
207
  *
601
  protected function getSessionId() {
602
  if ( empty( $this->sSessionId ) ) {
603
  $oDp = $this->loadDataProcessor();
604
+ $this->sSessionId = $oDp->FetchCookie( $this->getFeatureOptions()->getUserSessionCookieName() );
605
  if ( empty( $this->sSessionId ) ) {
606
  $this->sSessionId = md5( uniqid() );
607
  $this->setSessionCookie();
646
  }
647
 
648
  /**
649
+ * @param int $nTimeStamp
650
+ * @return bool|int
651
  */
652
  protected function deleteAllRowsOlderThan( $nTimeStamp ) {
653
  $sQuery = "
660
  $this->getTableName(),
661
  esc_sql( $nTimeStamp )
662
  );
663
+ return $this->doSql( $sQuery );
664
  }
665
 
666
  }
src/icwp-pure-base.php DELETED
@@ -1,376 +0,0 @@
1
- <?php
2
-
3
- require_once( dirname(__FILE__).ICWP_DS.'icwp-foundation.php' );
4
-
5
- if ( !class_exists('ICWP_Pure_Base_V6') ):
6
-
7
- class ICWP_Pure_Base_V6 extends ICWP_WPSF_Foundation {
8
-
9
- /**
10
- * @var ICWP_WPSF_Plugin_Controller
11
- */
12
- protected $oPluginController;
13
-
14
- protected $fShowMarketing;
15
-
16
- public function __construct( ICWP_WPSF_Plugin_Controller $oPluginController ) {
17
-
18
- // All core values of the plugin are derived from the values stored in this value object.
19
- $this->oPluginController = $oPluginController;
20
-
21
- // add_action( 'plugins_loaded', array( $this, 'onWpPluginsLoaded' ) );
22
- // add_action( 'init', array( $this, 'onWpInit' ), 0 );
23
- if ( $this->getController()->getIsValidAdminArea( false ) ) {
24
- add_action( 'admin_init', array( $this, 'onWpAdminInit' ) );
25
- add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
26
- add_action( 'network_admin_menu', array( $this, 'onWpAdminMenu' ) );
27
- add_action( 'plugin_action_links', array( $this, 'onWpPluginActionLinks' ), 10, 4 );
28
- // add_action( 'wp_before_admin_bar_render', array( $this, 'onWpAdminBar' ), 1, 9999 );
29
- }
30
- $this->registerActivationHooks();
31
- }
32
-
33
- /**
34
- * @return ICWP_WPSF_Plugin_Controller
35
- */
36
- public function getController() {
37
- return $this->oPluginController;
38
- }
39
-
40
- /**
41
- * Returns this unique plugin prefix
42
- *
43
- * @param string $sGlue
44
- * @return string
45
- */
46
- public function getPluginPrefix( $sGlue = '-' ) {
47
- return $this->getController()->getPluginPrefix( $sGlue );
48
- }
49
-
50
- /**
51
- * Will prefix and return any string with the unique plugin prefix.
52
- *
53
- * @param string $sSuffix
54
- * @param string $sGlue
55
- * @return string
56
- */
57
- public function doPluginPrefix( $sSuffix = '', $sGlue = '-' ) {
58
- return $this->getController()->doPluginPrefix( $sSuffix, $sGlue );
59
- }
60
-
61
- /**
62
- * Registers the plugins activation, deactivate and uninstall hooks.
63
- */
64
- protected function registerActivationHooks() {
65
- register_activation_hook( $this->getController()->getRootFile(), array( $this, 'onWpActivatePlugin' ) );
66
- register_deactivation_hook( $this->getController()->getRootFile(), array( $this, 'onWpDeactivatePlugin' ) );
67
- // register_uninstall_hook( $this->oPluginVo->getRootFile(), array( $this, 'onWpUninstallPlugin' ) );
68
- }
69
-
70
- /**
71
- * This is the path to the main plugin file relative to the WordPress plugins directory.
72
- *
73
- * @return string
74
- */
75
- public function getPluginBaseFile() {
76
- return $this->getController()->getPluginBaseFile();
77
- }
78
-
79
- /**
80
- * @param boolean $fHasPermission
81
- * @return boolean
82
- */
83
- public function hasPermissionToView( $fHasPermission = true ) {
84
- return $this->hasPermissionToSubmit( $fHasPermission );
85
- }
86
-
87
- /**
88
- * @param boolean $fHasPermission
89
- * @return boolean
90
- */
91
- public function hasPermissionToSubmit( $fHasPermission = true ) {
92
- // first a basic admin check
93
- return $fHasPermission && is_super_admin() && current_user_can( $this->getController()->getBasePermissions() );
94
- }
95
-
96
- /**
97
- * @param string $sView
98
- * @param array $aData
99
- * @return bool
100
- */
101
- protected function display( $sView, $aData = array() ) {
102
- $sFile = $this->getController()->getViewPath( $sView );
103
-
104
- if ( !is_file( $sFile ) ) {
105
- echo "View not found: ".$sFile;
106
- return false;
107
- }
108
-
109
- if ( count( $aData ) > 0 ) {
110
- extract( $aData, EXTR_PREFIX_ALL, $this->getController()->getParentSlug() ); //slug being 'icwp'
111
- }
112
-
113
- ob_start();
114
- include( $sFile );
115
- $sContents = ob_get_contents();
116
- ob_end_clean();
117
-
118
- echo $sContents;
119
- return true;
120
- }
121
-
122
- public function onWpAdminInit() {
123
- //Do Plugin-Specific Admin Work
124
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueuePluginGlobalAdminCss' ), 99 );
125
- if ( $this->getIsPage_PluginAdmin() ) {
126
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueueBootstrapLegacyAdminCss' ), 99 );
127
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueuePluginAdminCss' ), 99 );
128
- }
129
- }
130
-
131
- public function onWpAdminMenu() {
132
- if ( !$this->getController()->getIsValidAdminArea() ) {
133
- return true;
134
- }
135
- $this->createMenu();
136
- }
137
-
138
- protected function createMenu() {
139
- $oPluginController = $this->getController();
140
-
141
- $sFullParentMenuId = $this->getPluginPrefix();
142
- add_menu_page(
143
- $oPluginController->getHumanName(),
144
- $oPluginController->getAdminMenuTitle(),
145
- $oPluginController->getBasePermissions(),
146
- $sFullParentMenuId,
147
- array( $this, 'onDisplayAll' ),
148
- $this->getController()->getPluginUrl_Image( 'pluginlogo_16x16.png' )
149
- );
150
- //Create and Add the submenu items
151
-
152
- // allow for any plugin menu items that don't come from filters
153
- add_filter( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array( $this, 'filter_addExtraAdminMenuItems' ) );
154
-
155
- $aPluginMenuItems = apply_filters( $this->doPluginPrefix( 'filter_plugin_submenu_items' ), array() );
156
- if ( !empty( $aPluginMenuItems ) ) {
157
- foreach ( $aPluginMenuItems as $sMenuTitle => $aMenu ) {
158
- list( $sMenuItemText, $sMenuItemId, $aMenuCallBack ) = $aMenu;
159
- add_submenu_page(
160
- $sFullParentMenuId,
161
- $sMenuTitle,
162
- $sMenuItemText,
163
- $oPluginController->getBasePermissions(),
164
- $sMenuItemId,
165
- $aMenuCallBack
166
- );
167
- }
168
- }
169
- $this->fixSubmenu();
170
- }
171
-
172
- /**
173
- * @param array $aItems
174
- * @return array
175
- */
176
- public function filter_addExtraAdminMenuItems( $aItems ) {
177
- return $aItems;
178
- }
179
-
180
- protected function fixSubmenu() {
181
- global $submenu;
182
- $sFullParentMenuId = $this->getPluginPrefix();
183
- if ( isset( $submenu[$sFullParentMenuId] ) ) {
184
- unset( $submenu[$sFullParentMenuId][0] );
185
- }
186
- }
187
-
188
- /**
189
- * Displaying all views now goes through this central function and we work out
190
- * what to display based on the name of current hook/filter being processed.
191
- */
192
- public function onDisplayAll() { }
193
-
194
- protected function getBaseDisplayData() {
195
- $oWp = $this->loadWpFunctionsProcessor();
196
- return array(
197
- 'plugin_url' => $this->getController()->getPluginUrl(),
198
- 'var_prefix' => $this->getController()->getOptionStoragePrefix(),
199
- 'sPluginName' => $this->getController()->getHumanName(),
200
- 'fShowAds' => $this->isShowMarketing(),
201
- 'nonce_field' => $this->getPluginPrefix(),
202
- 'form_action' => 'admin.php?page='.$oWp->getCurrentWpAdminPage()
203
- );
204
- }
205
-
206
- /**
207
- * @return bool
208
- */
209
- protected function getIsPage_PluginMainDashboard() {
210
- $oWp = $this->loadWpFunctionsProcessor();
211
- return ( $oWp->getCurrentWpAdminPage() == $this->getPluginPrefix() );
212
- }
213
-
214
- /**
215
- * @return bool
216
- */
217
- protected function getIsPage_PluginAdmin() {
218
- $oWp = $this->loadWpFunctionsProcessor();
219
- return ( strpos( $oWp->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
220
- }
221
-
222
- /**
223
- * @return bool
224
- */
225
- protected function isShowMarketing() {
226
-
227
- if ( isset($this->fShowMarketing) ) {
228
- return $this->fShowMarketing;
229
- }
230
- $this->fShowMarketing = true;
231
- if ( class_exists( 'Worpit_Plugin' ) ) {
232
- if ( method_exists( 'Worpit_Plugin', 'IsLinked' ) ) {
233
- $this->fShowMarketing = !Worpit_Plugin::IsLinked();
234
- }
235
- else if ( function_exists( 'get_option' )
236
- && get_option( Worpit_Plugin::$VariablePrefix.'assigned' ) == 'Y'
237
- && get_option( Worpit_Plugin::$VariablePrefix.'assigned_to' ) != '' ) {
238
-
239
- $this->fShowMarketing = false;
240
- }
241
- }
242
- return $this->fShowMarketing ;
243
- }
244
-
245
- /**
246
- * On the plugins listing page, hides the edit and deactivate links
247
- * for this plugin based on permissions
248
- *
249
- * @see ICWP_Pure_Base_V1::onWpPluginActionLinks()
250
- */
251
- public function onWpPluginActionLinks( $aActionLinks, $sPluginFile ) {
252
-
253
- if ( $sPluginFile == $this->getPluginBaseFile() ) {
254
- if ( !$this->hasPermissionToSubmit() ) {
255
- if ( array_key_exists( 'edit', $aActionLinks ) ) {
256
- unset( $aActionLinks['edit'] );
257
- }
258
- if ( array_key_exists( 'deactivate', $aActionLinks ) ) {
259
- unset( $aActionLinks['deactivate'] );
260
- }
261
- }
262
-
263
- $sSettingsLink = sprintf( '<a href="%s">%s</a>', $this->getController()->getPluginUrl_AdminPage(), 'Dashboard' ); ;
264
- array_unshift( $aActionLinks, $sSettingsLink );
265
- }
266
- return $aActionLinks;
267
- }
268
-
269
- /**
270
- * @return bool
271
- */
272
- protected function getShowAdminNotices() {
273
- return true;
274
- }
275
-
276
- /**
277
- * Updates the current (or supplied user ID) user meta data with the version of the plugin
278
- *
279
- * @param $nId
280
- * @param $sValue
281
- */
282
- protected function updateTranslationNoticeShownUserMeta( $nId = '', $sValue = 'Y' ) {
283
- $oWp = $this->loadWpFunctionsProcessor();
284
- $oWp->updateUserMeta( $this->getController()->doPluginOptionPrefix( 'plugin_translation_notice' ), $sValue, $nId );
285
- }
286
-
287
- /**
288
- * Updates the current (or supplied user ID) user meta data with the version of the plugin
289
- *
290
- * @param $nId
291
- * @param $sValue
292
- */
293
- protected function updateMailingListSignupShownUserMeta( $nId = '', $sValue = 'Y' ) {
294
- $oWp = $this->loadWpFunctionsProcessor();
295
- $oWp->updateUserMeta( $this->getController()->doPluginOptionPrefix( 'plugin_mailing_list_signup' ), $sValue, $nId );
296
- }
297
-
298
- /**
299
- * Updates the current (or supplied user ID) user meta data with the version of the plugin
300
- *
301
- * @param integer $nId
302
- */
303
- protected function updateVersionUserMeta( $nId = null ) {
304
- $oWp = $this->loadWpFunctionsProcessor();
305
- $oWp->updateUserMeta( $this->getController()->doPluginOptionPrefix( 'current_version' ), $this->getController()->getVersion(), $nId );
306
- }
307
-
308
- public function enqueueBootstrapAdminCss() {
309
- $sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_css' );
310
- wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css( 'bootstrap-wpadmin.css' ), false, $this->getController()->getVersion() );
311
- wp_enqueue_style( $sUnique );
312
- }
313
-
314
- public function enqueueBootstrapLegacyAdminCss() {
315
- $sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_legacy_css' );
316
- wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css( 'bootstrap-wpadmin-legacy.css' ), false, $this->getController()->getVersion() );
317
- wp_enqueue_style( $sUnique );
318
-
319
- $sUnique = $this->doPluginPrefix( 'bootstrap_wpadmin_css_fixes' );
320
- wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css('bootstrap-wpadmin-fixes.css'), array( $this->doPluginPrefix( 'bootstrap_wpadmin_legacy_css' ) ), $this->getController()->getVersion() );
321
- wp_enqueue_style( $sUnique );
322
- }
323
-
324
- public function enqueuePluginAdminCss() {
325
- $sUnique = $this->doPluginPrefix( 'plugin_css' );
326
- wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css('plugin.css'), array( $this->doPluginPrefix( 'bootstrap_wpadmin_css_fixes' ) ), $this->getController()->getVersion().rand() );
327
- wp_enqueue_style( $sUnique );
328
- }
329
-
330
- public function enqueuePluginGlobalAdminCss() {
331
- $sUnique = $this->doPluginPrefix( 'global_plugin_css' );
332
- wp_register_style( $sUnique, $this->getController()->getPluginUrl_Css('global-plugin.css'), false, $this->getController()->getVersion().rand() );
333
- wp_enqueue_style( $sUnique );
334
- }
335
-
336
- public function onWpActivatePlugin() { }
337
-
338
- public function onWpDeactivatePlugin() {
339
- if ( current_user_can( $this->getController()->getBasePermissions() ) ) {
340
- do_action( $this->doPluginPrefix( 'delete_plugin' ) );
341
- }
342
- }
343
-
344
- /**
345
- */
346
- public function onWpAdminBar() {
347
- $aNodes = $this->getAdminBarNodes();
348
- if ( !is_array( $aNodes ) ) {
349
- return;
350
- }
351
- foreach( $aNodes as $aNode ) {
352
- $this->addAdminBarNode( $aNode );
353
- }
354
- }
355
-
356
- protected function getAdminBarNodes() { }
357
-
358
- protected function addAdminBarNode( $aNode ) {
359
- global $wp_admin_bar;
360
-
361
- if ( isset( $aNode['children'] ) ) {
362
- $aChildren = $aNode['children'];
363
- unset( $aNode['children'] );
364
- }
365
- $wp_admin_bar->add_node( $aNode );
366
-
367
- if ( !empty($aChildren) ) {
368
- foreach( $aChildren as $aChild ) {
369
- $aChild['parent'] = $aNode['id'];
370
- $this->addAdminBarNode( $aChild );
371
- }
372
- }
373
- }
374
- }
375
-
376
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/icwp-wpsf-audit_trail_viewer_index.php CHANGED
@@ -1,16 +1,15 @@
1
  <?php
2
  include_once( 'icwp-wpsf-config_header.php' );
3
 
4
- $aLogTypes = array(
5
- 0 => _wpsf__('Info'),
6
- 1 => _wpsf__('Warning'),
7
- 2 => _wpsf__('Critical')
8
- );
9
 
10
- function printAuditTrailTable( $aAuditData ) {
11
  if ( empty( $aAuditData ) ) {
 
12
  return;
13
  }
 
14
  ?>
15
  <table class="table table-hover table-striped table-audit_trail">
16
  <tr>
@@ -19,6 +18,7 @@ function printAuditTrailTable( $aAuditData ) {
19
  <th class="cell-message"><?php _wpsf_e('Message'); ?></th>
20
  <th class="cell-username"><?php _wpsf_e('Username'); ?></th>
21
  <th class="cell-category"><?php _wpsf_e('Category'); ?></th>
 
22
  </tr>
23
  <?php foreach( $aAuditData as $aAuditEntry ) : ?>
24
  <tr>
@@ -27,6 +27,10 @@ function printAuditTrailTable( $aAuditData ) {
27
  <td><?php echo $aAuditEntry['message']; ?></td>
28
  <td><?php echo $aAuditEntry['wp_username']; ?></td>
29
  <td><?php echo $aAuditEntry['category']; ?></td>
 
 
 
 
30
  </tr>
31
  <?php endforeach; ?>
32
  </table>
@@ -36,20 +40,13 @@ function printAuditTrailTable( $aAuditData ) {
36
  <div class="row">
37
  <div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
38
 
39
- <h4 class="table-title"><?php _wpsf_e( 'Users' ); ?></h4>
40
- <?php printAuditTrailTable( $icwp_aAuditDataUsers ); ?>
41
-
42
- <h4 class="table-title"><?php _wpsf_e( 'Plugins' ); ?></h4>
43
- <?php printAuditTrailTable( $icwp_aAuditDataPlugins ); ?>
44
-
45
- <h4 class="table-title"><?php _wpsf_e( 'Themes' ); ?></h4>
46
- <?php printAuditTrailTable( $icwp_aAuditDataThemes ); ?>
47
-
48
- <h4 class="table-title"><?php _wpsf_e( 'WordPress' ); ?></h4>
49
- <?php printAuditTrailTable( $icwp_aAuditDataWordpress ); ?>
50
-
51
- <h4 class="table-title"><?php _wpsf_e( 'Posts' ); ?></h4>
52
- <?php printAuditTrailTable( $icwp_aAuditDataPosts ); ?>
53
 
54
  </div><!-- / span9 -->
55
 
1
  <?php
2
  include_once( 'icwp-wpsf-config_header.php' );
3
 
4
+ function printAuditTrailTable( $sTitle, $aAuditData, $nYourIp = -1 ) {
5
+
6
+ ?><h4 class="table-title"><?php echo $sTitle; ?></h4><?php
 
 
7
 
 
8
  if ( empty( $aAuditData ) ) {
9
+ _wpsf_e( 'There are currently no audit entries this is section.' );
10
  return;
11
  }
12
+
13
  ?>
14
  <table class="table table-hover table-striped table-audit_trail">
15
  <tr>
18
  <th class="cell-message"><?php _wpsf_e('Message'); ?></th>
19
  <th class="cell-username"><?php _wpsf_e('Username'); ?></th>
20
  <th class="cell-category"><?php _wpsf_e('Category'); ?></th>
21
+ <th class="cell-ip"><?php _wpsf_e('IP Address'); ?></th>
22
  </tr>
23
  <?php foreach( $aAuditData as $aAuditEntry ) : ?>
24
  <tr>
27
  <td><?php echo $aAuditEntry['message']; ?></td>
28
  <td><?php echo $aAuditEntry['wp_username']; ?></td>
29
  <td><?php echo $aAuditEntry['category']; ?></td>
30
+ <td>
31
+ <?php echo long2ip( $aAuditEntry['ip_long'] ); ?>
32
+ <?php echo ( $nYourIp == $aAuditEntry['ip_long'] ) ? '<br />('._wpsf__('You').')' : ''; ?>
33
+ </td>
34
  </tr>
35
  <?php endforeach; ?>
36
  </table>
40
  <div class="row">
41
  <div class="<?php echo $icwp_fShowAds? 'span9' : 'span12'; ?>">
42
 
43
+ <?php printAuditTrailTable( _wpsf__( 'WordPress Simple Firewall' ), $icwp_aAuditDataWpsf, $icwp_nYourIp ); ?>
44
+ <?php printAuditTrailTable( _wpsf__( 'Users' ), $icwp_aAuditDataUsers, $icwp_nYourIp ); ?>
45
+ <?php printAuditTrailTable( _wpsf__( 'Plugins' ), $icwp_aAuditDataPlugins, $icwp_nYourIp ); ?>
46
+ <?php printAuditTrailTable( _wpsf__( 'Themes' ), $icwp_aAuditDataThemes, $icwp_nYourIp ); ?>
47
+ <?php printAuditTrailTable( _wpsf__( 'WordPress' ), $icwp_aAuditDataWordpress, $icwp_nYourIp ); ?>
48
+ <?php printAuditTrailTable( _wpsf__( 'Posts' ), $icwp_aAuditDataPosts, $icwp_nYourIp ); ?>
49
+ <?php printAuditTrailTable( _wpsf__( 'Emails' ), $icwp_aAuditDataEmails, $icwp_nYourIp ); ?>
 
 
 
 
 
 
 
50
 
51
  </div><!-- / span9 -->
52
 
views/icwp-wpsf-state_summary.php CHANGED
@@ -72,7 +72,7 @@ function printFeatureSummaryBlock( $fOn, $sName, $sSettingsHref= '', $sInnerSpan
72
  vertical-align: top;
73
  }
74
  #feature-dashboard .feature-icon:before,
75
- #feature-adminaccess .feature-icon:before {
76
  content: "\f332";
77
  }
78
  #feature-firewall .feature-icon:before {
@@ -93,6 +93,9 @@ function printFeatureSummaryBlock( $fOn, $sName, $sSettingsHref= '', $sInnerSpan
93
  #feature-lockdown .feature-icon:before {
94
  content: "\f160";
95
  }
 
 
 
96
 
97
  </style>
98
 
72
  vertical-align: top;
73
  }
74
  #feature-dashboard .feature-icon:before,
75
+ #feature-adminaccessrestriction .feature-icon:before {
76
  content: "\f332";
77
  }
78
  #feature-firewall .feature-icon:before {
93
  #feature-lockdown .feature-icon:before {
94
  content: "\f160";
95
  }
96
+ #feature-audittrail .feature-icon:before {
97
+ content: "\f115";
98
+ }
99
 
100
  </style>
101