WP Security Audit Log - Version 2.6.5

Version Description

(2017-07-18) =

  • New Audit Trail Alerts

    • Alert 1007 for when an administrator terminate's a logged in session using the Users Sessions Management Add-On
    • Alert 6023 to log 404 HTTP errors (requests to non-existing pages) by website visitors (non WordPress users)
  • Improvements

    • Seggregated the logging of 404 HTTP Errors by who generates them. Alert 6007 for logged in users, 6023 for anonymous website visitors.
    • Improved the logging of Alert 4014 so it is not reported every time a user's profile page is reloaded with a refresh or when a change is applied.
    • Removed the wsal_wp_session cookie, which was used to store the selected database when archiving of audit trail alerts is enabled. Using LocalStorage instead.
    • Replaced mcrypt (deprecated in PHP 7) with OpenSSL. Mcrypt still used temporarily to convert configured password. Will be removed completely in future updates. Support Ticket
Download this release

Release Info

Developer WPWhiteSecurity
Plugin Icon 128x128 WP Security Audit Log
Version 2.6.5
Comparing to
See all releases

Code changes from version 2.6.4 to 2.6.5

Files changed (76) hide show
  1. classes/AbstractLogger.php +27 -12
  2. classes/AbstractSandboxTask.php +77 -66
  3. classes/AbstractSensor.php +9 -3
  4. classes/AbstractView.php +56 -28
  5. classes/Adapters/ActiveRecordInterface.php +17 -13
  6. classes/Adapters/MetaInterface.php +14 -10
  7. classes/Adapters/MySQL/ActiveRecordAdapter.php +64 -28
  8. classes/Adapters/MySQL/MetaAdapter.php +35 -5
  9. classes/Adapters/MySQL/OccurrenceAdapter.php +60 -18
  10. classes/Adapters/MySQL/OptionAdapter.php +41 -4
  11. classes/Adapters/MySQL/QueryAdapter.php +46 -7
  12. classes/Adapters/MySQL/TmpUserAdapter.php +13 -2
  13. classes/Adapters/OccurrenceInterface.php +5 -1
  14. classes/Adapters/QueryInterface.php +8 -4
  15. classes/Alert.php +30 -16
  16. classes/AlertManager.php +80 -61
  17. classes/AuditLogListView.php +10 -6
  18. classes/Autoloader.php +22 -15
  19. classes/Connector/AbstractConnector.php +6 -1
  20. classes/Connector/ConnectorFactory.php +31 -3
  21. classes/Connector/ConnectorInterface.php +5 -1
  22. classes/Connector/MySQLDB.php +205 -31
  23. classes/Connector/wp-db-custom.php +12 -4
  24. classes/ConstantManager.php +95 -88
  25. classes/EDD_SL_Plugin_Updater.php +49 -46
  26. classes/Helpers/DataHelper.php +11 -6
  27. classes/Lib/class-recursive-arrayaccess.php +0 -139
  28. classes/Lib/class-wp-session-utils.php +0 -139
  29. classes/Lib/class-wp-session.php +0 -322
  30. classes/Lib/wp-session.php +0 -182
  31. classes/LicenseManager.php +51 -31
  32. classes/Loggers/Database.php +50 -7
  33. classes/Models/ActiveRecord.php +103 -39
  34. classes/Models/Meta.php +26 -10
  35. classes/Models/Occurrence.php +52 -4
  36. classes/Models/OccurrenceQuery.php +15 -2
  37. classes/Models/Option.php +52 -4
  38. classes/Models/Query.php +95 -11
  39. classes/Models/TmpUser.php +11 -7
  40. classes/Nicer.php +294 -284
  41. classes/SensorManager.php +19 -9
  42. classes/Sensors/BBPress.php +96 -4
  43. classes/Sensors/Comments.php +56 -2
  44. classes/Sensors/Content.php +282 -13
  45. classes/Sensors/Database.php +35 -1
  46. classes/Sensors/Files.php +83 -51
  47. classes/Sensors/LogInOut.php +68 -6
  48. classes/Sensors/Menus.php +74 -2
  49. classes/Sensors/MetaData.php +60 -11
  50. classes/Sensors/Multisite.php +196 -126
  51. classes/Sensors/PhpErrors.php +137 -102
  52. classes/Sensors/PluginsThemes.php +74 -16
  53. classes/Sensors/Request.php +19 -3
  54. classes/Sensors/System.php +387 -149
  55. classes/Sensors/UserProfile.php +41 -19
  56. classes/Sensors/Widgets.php +90 -61
  57. classes/Sensors/WooCommerce.php +57 -1
  58. classes/Settings.php +344 -130
  59. classes/SimpleProfiler.php +51 -41
  60. classes/ViewManager.php +98 -67
  61. classes/Views/About.php +93 -85
  62. classes/Views/AuditLog.php +43 -22
  63. classes/Views/EmailNotifications.php +10 -3
  64. classes/Views/Extensions.php +16 -7
  65. classes/Views/ExternalDB.php +10 -3
  66. classes/Views/Help.php +20 -10
  67. classes/Views/Licensing.php +98 -86
  68. classes/Views/LogInUsers.php +10 -4
  69. classes/Views/Reports.php +10 -4
  70. classes/Views/Search.php +10 -4
  71. classes/Views/Settings.php +53 -49
  72. classes/Views/ToggleAlerts.php +108 -26
  73. classes/WidgetManager.php +5 -1
  74. defaults.php +2 -0
  75. readme.txt +14 -1
  76. wp-security-audit-log.php +269 -150
classes/AbstractLogger.php CHANGED
@@ -1,14 +1,29 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- abstract class WSAL_AbstractLogger {
4
- /**
5
- * @var WpSecurityAuditLog
6
- */
7
- protected $plugin;
8
-
9
- public function __construct(WpSecurityAuditLog $plugin){
10
- $this->plugin = $plugin;
11
- }
12
-
13
- public abstract function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false);
14
- }
 
 
 
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Abstract class used in the Logger.
6
+ * @see Loggers/Database.php
7
+ */
8
+ abstract class WSAL_AbstractLogger
9
+ {
10
+ /**
11
+ * @var WpSecurityAuditLog
12
+ */
13
+ protected $plugin;
14
 
15
+ public function __construct(WpSecurityAuditLog $plugin)
16
+ {
17
+ $this->plugin = $plugin;
18
+ }
19
+
20
+ /**
21
+ * Log alert abstract.
22
+ * @param integer $type alert code
23
+ * @param array $data Metadata
24
+ * @param integer $date (Optional) created_on
25
+ * @param integer $siteid (Optional) site_id
26
+ * @param bool $migrated (Optional) is_migrated
27
+ */
28
+ public abstract function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false);
29
+ }
classes/AbstractSandboxTask.php CHANGED
@@ -1,68 +1,79 @@
1
  <?php
2
-
3
- abstract class WSAL_AbstractSandboxTask {
4
- public function __construct() {
5
- // remove time limit and clear output buffers
6
- set_time_limit(0);
7
- ob_implicit_flush(true);
8
- while(ob_get_level())ob_end_flush();
9
-
10
- // set up shutdown handler
11
- register_shutdown_function(array($this, 'Shutdown'));
12
-
13
- // run event sequence
14
- $this->Header();
15
- try{
16
- $this->Execute();
17
- }catch(Exception $ex){
18
- $this->Message(get_class($ex) . ' [' . basename($ex->getFile()) . ':' . $ex->getLine() . ']: ' . $ex->getMessage());
19
- $this->Message($ex->getTraceAsString(), true);
20
- }
21
- $this->Footer();
22
-
23
- // shutdown
24
- die();
25
- }
26
-
27
- protected function Header(){
28
- echo '<!DOCTYPE html><html><body style="margin: 0; padding: 8px; font: 12px Arial; color: #333;">';
29
- echo '<div style="position: fixed; top: 0; left: 0; right: 0; padding: 8px; background: #F0F0F0;">';
30
- echo ' <div id="bar" style=" border-top: 2px solid #0AE; top: 20px; height: 0; width: 0%;"> </div>';
31
- echo ' <span id="msg"></span> <span id="prg"></span>';
32
- echo '</div>';
33
- echo '<div id="msgs" style="font-family: Consolas; margin-top: 30px; white-space: pre;"></div>';
34
- echo '<script>';
35
- echo ' var bar = document.getElementById("bar");';
36
- echo ' var msg = document.getElementById("msg");';
37
- echo ' var prg = document.getElementById("prg");';
38
- echo ' var msgs = document.getElementById("msgs");';
39
- echo '</script>';
40
- flush();
41
- }
42
-
43
- protected function Footer(){
44
- echo '<div style="display: none;">';
45
- flush();
46
- }
47
-
48
- protected abstract function Execute();
49
-
50
- public function Shutdown(){
51
- echo '</div></body></html>';
52
- flush();
53
- }
54
-
55
- protected function Progress($percent){
56
- echo '<script>bar.style.width=prg.innerHTML="' . number_format($percent, 2) . '%";</script>';
57
- flush();
58
- }
59
-
60
- protected function Message($message, $sticky = false){
61
- if($sticky){
62
- echo '<script>msgs.appendChild(document.createTextNode(' . json_encode($message . PHP_EOL) . ')); window.scroll(0, document.body.scrollHeight);</script>';
63
- }else{
64
- echo '<script>msg.innerHTML=' . json_encode($message) . ';</script>';
65
- }
66
- flush();
67
- }
 
 
 
 
 
 
 
 
 
 
 
68
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ */
5
+ abstract class WSAL_AbstractSandboxTask
6
+ {
7
+ public function __construct()
8
+ {
9
+ // remove time limit and clear output buffers
10
+ set_time_limit(0);
11
+ ob_implicit_flush(true);
12
+ while (ob_get_level()) {
13
+ ob_end_flush();
14
+ }
15
+
16
+ // set up shutdown handler
17
+ register_shutdown_function(array($this, 'Shutdown'));
18
+
19
+ // run event sequence
20
+ $this->Header();
21
+ try {
22
+ $this->Execute();
23
+ } catch (Exception $ex) {
24
+ $this->Message(get_class($ex) . ' [' . basename($ex->getFile()) . ':' . $ex->getLine() . ']: ' . $ex->getMessage());
25
+ $this->Message($ex->getTraceAsString(), true);
26
+ }
27
+ $this->Footer();
28
+
29
+ // shutdown
30
+ die();
31
+ }
32
+
33
+ protected function Header()
34
+ {
35
+ echo '<!DOCTYPE html><html><body style="margin: 0; padding: 8px; font: 12px Arial; color: #333;">';
36
+ echo '<div style="position: fixed; top: 0; left: 0; right: 0; padding: 8px; background: #F0F0F0;">';
37
+ echo ' <div id="bar" style=" border-top: 2px solid #0AE; top: 20px; height: 0; width: 0%;"> </div>';
38
+ echo ' <span id="msg"></span> <span id="prg"></span>';
39
+ echo '</div>';
40
+ echo '<div id="msgs" style="font-family: Consolas; margin-top: 30px; white-space: pre;"></div>';
41
+ echo '<script>';
42
+ echo ' var bar = document.getElementById("bar");';
43
+ echo ' var msg = document.getElementById("msg");';
44
+ echo ' var prg = document.getElementById("prg");';
45
+ echo ' var msgs = document.getElementById("msgs");';
46
+ echo '</script>';
47
+ flush();
48
+ }
49
+
50
+ protected function Footer()
51
+ {
52
+ echo '<div style="display: none;">';
53
+ flush();
54
+ }
55
+
56
+ protected abstract function Execute();
57
+
58
+ public function Shutdown()
59
+ {
60
+ echo '</div></body></html>';
61
+ flush();
62
+ }
63
+
64
+ protected function Progress($percent)
65
+ {
66
+ echo '<script>bar.style.width=prg.innerHTML="' . number_format($percent, 2) . '%";</script>';
67
+ flush();
68
+ }
69
+
70
+ protected function Message($message, $sticky = false)
71
+ {
72
+ if ($sticky) {
73
+ echo '<script>msgs.appendChild(document.createTextNode(' . json_encode($message . PHP_EOL) . ')); window.scroll(0, document.body.scrollHeight);</script>';
74
+ } else {
75
+ echo '<script>msg.innerHTML=' . json_encode($message) . ';</script>';
76
+ }
77
+ flush();
78
+ }
79
  }
classes/AbstractSensor.php CHANGED
@@ -1,5 +1,10 @@
1
  <?php
2
-
 
 
 
 
 
3
  abstract class WSAL_AbstractSensor
4
  {
5
  /**
@@ -7,7 +12,8 @@ abstract class WSAL_AbstractSensor
7
  */
8
  protected $plugin;
9
 
10
- public function __construct(WpSecurityAuditLog $plugin){
 
11
  $this->plugin = $plugin;
12
  }
13
 
@@ -48,7 +54,7 @@ abstract class WSAL_AbstractSensor
48
  /**
49
  * Check to see whether or not the specified directory is accessible
50
  * @param string $dirPath
51
- * @return bool
52
  */
53
  protected function CheckDirectory($dirPath)
54
  {
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Abstract class used in all the sensors.
6
+ * @see Sensors/*.php
7
+ */
8
  abstract class WSAL_AbstractSensor
9
  {
10
  /**
12
  */
13
  protected $plugin;
14
 
15
+ public function __construct(WpSecurityAuditLog $plugin)
16
+ {
17
  $this->plugin = $plugin;
18
  }
19
 
54
  /**
55
  * Check to see whether or not the specified directory is accessible
56
  * @param string $dirPath
57
+ * @return boolean
58
  */
59
  protected function CheckDirectory($dirPath)
60
  {
classes/AbstractView.php CHANGED
@@ -1,9 +1,14 @@
1
  <?php
2
-
3
- abstract class WSAL_AbstractView {
4
-
 
 
 
 
 
5
  /**
6
- * @var WpSecurityAuditLog
7
  */
8
  protected $_plugin;
9
 
@@ -20,35 +25,40 @@ abstract class WSAL_AbstractView {
20
  * @var boolean
21
  */
22
  public $is_active = false;
 
 
23
 
24
  /**
25
  * @param WpSecurityAuditLog $plugin
26
  */
27
- public function __construct(WpSecurityAuditLog $plugin){
 
28
  $this->_plugin = $plugin;
29
 
30
  // get and store wordpress version
31
  global $wp_version;
32
- if(!isset($wp_version))
33
  $wp_version = get_bloginfo('version');
 
34
  $this->_wpversion = floatval($wp_version);
35
 
36
  // handle admin notices
37
  add_action('wp_ajax_AjaxDismissNotice', array($this, 'AjaxDismissNotice'));
38
  }
39
 
40
- public static $AllowedNoticeNames = array();
41
-
42
  /**
43
  * Dismiss an admin notice through ajax.
44
  * @internal
45
  */
46
- public function AjaxDismissNotice(){
47
- if(!$this->_plugin->settings->CurrentUserCan('view'))
 
48
  die('Access Denied.');
 
49
 
50
- if(!isset($_REQUEST['notice']))
51
  die('Notice name expected as "notice" parameter.');
 
52
 
53
  $this->DismissNotice($_REQUEST['notice']);
54
  }
@@ -57,7 +67,8 @@ abstract class WSAL_AbstractView {
57
  * @param string $name Name of notice.
58
  * @return boolean Whether notice got dismissed or not.
59
  */
60
- public function IsNoticeDismissed($name){
 
61
  $user_id = get_current_user_id();
62
  $meta_key = 'wsal-notice-' . $name;
63
  self::$AllowedNoticeNames[] = $name;
@@ -67,18 +78,21 @@ abstract class WSAL_AbstractView {
67
  /**
68
  * @param string $name Name of notice to dismiss.
69
  */
70
- public function DismissNotice($name){
 
71
  $user_id = get_current_user_id();
72
  $meta_key = 'wsal-notice-' . $name;
73
  $old_value = get_user_meta($user_id, $meta_key, true);
74
- if (in_array($name, self::$AllowedNoticeNames) || $old_value === false)
75
  update_user_meta($user_id, $meta_key, '1');
 
76
  }
77
 
78
  /**
79
  * @param string $name Makes this notice available.
80
  */
81
- public function RegisterNotice($name){
 
82
  self::$AllowedNoticeNames[] = $name;
83
  }
84
 
@@ -110,48 +124,60 @@ abstract class WSAL_AbstractView {
110
  /**
111
  * Renders the view icon (this has been deprecated in newwer WP versions).
112
  */
113
- public function RenderIcon(){
 
114
  ?><div id="icon-plugins" class="icon32"><br></div><?php
115
  }
116
 
117
  /**
118
  * Renders the view title.
119
  */
120
- public function RenderTitle(){
 
121
  ?><h2><?php echo esc_html($this->GetTitle()); ?></h2><?php
122
  }
123
 
124
  /**
125
  * @link self::Render()
126
  */
127
- public function RenderContent(){
 
128
  $this->Render();
129
  }
130
 
131
  /**
132
  * @return boolean Whether page should appear in menu or not.
133
  */
134
- public function IsVisible(){ return true; }
 
 
 
135
 
136
  /**
137
  * @return boolean Whether page should be accessible or not.
138
  */
139
- public function IsAccessible(){ return true; }
 
 
 
140
 
141
  /**
142
  * Used for rendering stuff into head tag.
143
  */
144
- public function Header(){}
 
145
 
146
  /**
147
  * Used for rendering stuff in page fotoer.
148
  */
149
- public function Footer(){}
 
150
 
151
  /**
152
  * @return string Safe view menu name.
153
  */
154
- public function GetSafeViewName(){
 
155
  return 'wsal-' . preg_replace('/[^A-Za-z0-9\-]/', '-', $this->GetViewName());
156
  }
157
 
@@ -159,14 +185,16 @@ abstract class WSAL_AbstractView {
159
  * Override this and make it return true to create a shortcut link in plugin page to the view.
160
  * @return boolean
161
  */
162
- public function HasPluginShortcutLink(){
 
163
  return false;
164
  }
165
 
166
  /**
167
  * @return string URL to backend page for displaying view.
168
  */
169
- public function GetUrl(){
 
170
  $fn = function_exists('network_admin_url') ? 'network_admin_url' : 'admin_url';
171
  return $fn('admin.php?page=' . $this->GetSafeViewName());
172
  }
@@ -174,8 +202,8 @@ abstract class WSAL_AbstractView {
174
  /**
175
  * @return string Generates view name out of class name.
176
  */
177
- public function GetViewName(){
 
178
  return strtolower(str_replace(array('WSAL_Views_', 'WSAL_'), '', get_class($this)));
179
  }
180
-
181
- }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Abstract class used in all the views.
6
+ * @see Views/*.php
7
+ */
8
+ abstract class WSAL_AbstractView
9
+ {
10
  /**
11
+ * @var WpSecurityAuditLog
12
  */
13
  protected $_plugin;
14
 
25
  * @var boolean
26
  */
27
  public $is_active = false;
28
+
29
+ public static $AllowedNoticeNames = array();
30
 
31
  /**
32
  * @param WpSecurityAuditLog $plugin
33
  */
34
+ public function __construct(WpSecurityAuditLog $plugin)
35
+ {
36
  $this->_plugin = $plugin;
37
 
38
  // get and store wordpress version
39
  global $wp_version;
40
+ if (!isset($wp_version)) {
41
  $wp_version = get_bloginfo('version');
42
+ }
43
  $this->_wpversion = floatval($wp_version);
44
 
45
  // handle admin notices
46
  add_action('wp_ajax_AjaxDismissNotice', array($this, 'AjaxDismissNotice'));
47
  }
48
 
 
 
49
  /**
50
  * Dismiss an admin notice through ajax.
51
  * @internal
52
  */
53
+ public function AjaxDismissNotice()
54
+ {
55
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
56
  die('Access Denied.');
57
+ }
58
 
59
+ if (!isset($_REQUEST['notice'])) {
60
  die('Notice name expected as "notice" parameter.');
61
+ }
62
 
63
  $this->DismissNotice($_REQUEST['notice']);
64
  }
67
  * @param string $name Name of notice.
68
  * @return boolean Whether notice got dismissed or not.
69
  */
70
+ public function IsNoticeDismissed($name)
71
+ {
72
  $user_id = get_current_user_id();
73
  $meta_key = 'wsal-notice-' . $name;
74
  self::$AllowedNoticeNames[] = $name;
78
  /**
79
  * @param string $name Name of notice to dismiss.
80
  */
81
+ public function DismissNotice($name)
82
+ {
83
  $user_id = get_current_user_id();
84
  $meta_key = 'wsal-notice-' . $name;
85
  $old_value = get_user_meta($user_id, $meta_key, true);
86
+ if (in_array($name, self::$AllowedNoticeNames) || $old_value === false) {
87
  update_user_meta($user_id, $meta_key, '1');
88
+ }
89
  }
90
 
91
  /**
92
  * @param string $name Makes this notice available.
93
  */
94
+ public function RegisterNotice($name)
95
+ {
96
  self::$AllowedNoticeNames[] = $name;
97
  }
98
 
124
  /**
125
  * Renders the view icon (this has been deprecated in newwer WP versions).
126
  */
127
+ public function RenderIcon()
128
+ {
129
  ?><div id="icon-plugins" class="icon32"><br></div><?php
130
  }
131
 
132
  /**
133
  * Renders the view title.
134
  */
135
+ public function RenderTitle()
136
+ {
137
  ?><h2><?php echo esc_html($this->GetTitle()); ?></h2><?php
138
  }
139
 
140
  /**
141
  * @link self::Render()
142
  */
143
+ public function RenderContent()
144
+ {
145
  $this->Render();
146
  }
147
 
148
  /**
149
  * @return boolean Whether page should appear in menu or not.
150
  */
151
+ public function IsVisible()
152
+ {
153
+ return true;
154
+ }
155
 
156
  /**
157
  * @return boolean Whether page should be accessible or not.
158
  */
159
+ public function IsAccessible()
160
+ {
161
+ return true;
162
+ }
163
 
164
  /**
165
  * Used for rendering stuff into head tag.
166
  */
167
+ public function Header()
168
+ {}
169
 
170
  /**
171
  * Used for rendering stuff in page fotoer.
172
  */
173
+ public function Footer()
174
+ {}
175
 
176
  /**
177
  * @return string Safe view menu name.
178
  */
179
+ public function GetSafeViewName()
180
+ {
181
  return 'wsal-' . preg_replace('/[^A-Za-z0-9\-]/', '-', $this->GetViewName());
182
  }
183
 
185
  * Override this and make it return true to create a shortcut link in plugin page to the view.
186
  * @return boolean
187
  */
188
+ public function HasPluginShortcutLink()
189
+ {
190
  return false;
191
  }
192
 
193
  /**
194
  * @return string URL to backend page for displaying view.
195
  */
196
+ public function GetUrl()
197
+ {
198
  $fn = function_exists('network_admin_url') ? 'network_admin_url' : 'admin_url';
199
  return $fn('admin.php?page=' . $this->GetSafeViewName());
200
  }
202
  /**
203
  * @return string Generates view name out of class name.
204
  */
205
+ public function GetViewName()
206
+ {
207
  return strtolower(str_replace(array('WSAL_Views_', 'WSAL_'), '', get_class($this)));
208
  }
209
+ }
 
classes/Adapters/ActiveRecordInterface.php CHANGED
@@ -1,15 +1,19 @@
1
  <?php
2
-
3
- interface WSAL_Adapters_ActiveRecordInterface {
4
-
5
- public function IsInstalled();
6
- public function Install();
7
- public function Uninstall();
8
- public function Load($cond = '%d', $args = array(1));
9
- public function Save($activeRecord);
10
- public function Delete($activeRecord);
11
- public function LoadMulti($cond, $args = array());
12
- public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1));
13
- public function Count($cond = '%d', $args = array(1));
14
- public function LoadMultiQuery($query, $args = array());
 
 
 
 
15
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Interface used by the ActiveRecord.
6
+ */
7
+ interface WSAL_Adapters_ActiveRecordInterface
8
+ {
9
+ public function IsInstalled();
10
+ public function Install();
11
+ public function Uninstall();
12
+ public function Load($cond = '%d', $args = array(1));
13
+ public function Save($activeRecord);
14
+ public function Delete($activeRecord);
15
+ public function LoadMulti($cond, $args = array());
16
+ public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1));
17
+ public function Count($cond = '%d', $args = array(1));
18
+ public function LoadMultiQuery($query, $args = array());
19
  }
classes/Adapters/MetaInterface.php CHANGED
@@ -1,13 +1,17 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- interface WSAL_Adapters_MetaInterface {
4
- /**
5
- * Create a meta object
6
- * @param $metaData Array of meta data
7
- * @return int ID of the new meta data
8
- */
9
- public function deleteByOccurenceIds($occurenceIds);
10
-
11
- public function loadByNameAndOccurenceId($metaName, $occurenceId);
12
-
13
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Interface used by the Metadata.
6
+ */
7
+ interface WSAL_Adapters_MetaInterface
8
+ {
9
+ /**
10
+ * Create a meta object
11
+ * @param $metaData Array of meta data
12
+ * @return int ID of the new meta data
13
+ */
14
+ public function deleteByOccurenceIds($occurenceIds);
15
 
16
+ public function loadByNameAndOccurenceId($metaName, $occurenceId);
 
 
 
 
 
 
 
 
 
17
  }
classes/Adapters/MySQL/ActiveRecordAdapter.php CHANGED
@@ -1,5 +1,12 @@
1
  <?php
2
-
 
 
 
 
 
 
 
3
  class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInterface
4
  {
5
  protected $connection;
@@ -21,6 +28,9 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
21
  $this->connection = $conn;
22
  }
23
 
 
 
 
24
  public function GetModel()
25
  {
26
  return new WSAL_Models_ActiveRecord();
@@ -62,9 +72,11 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
62
 
63
  if (!isset($this->_column_cache)) {
64
  $this->_column_cache = array();
65
- foreach (array_keys(get_object_vars($model)) as $col)
66
- if (trim($col) && $col[0] != '_')
67
  $this->_column_cache[] = $col;
 
 
68
  }
69
  return $this->_column_cache;
70
  }
@@ -73,8 +85,8 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
73
  * @deprecated
74
  * @return boolean Returns whether table structure is installed or not.
75
  */
76
- public function IsInstalled(){
77
- //global $wpdb;
78
  $_wpdb = $this->connection;
79
  $sql = 'SHOW TABLES LIKE "' . $this->GetTable() . '"';
80
  return strtolower($_wpdb->get_var($sql)) == strtolower($this->GetTable());
@@ -83,36 +95,36 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
83
  /**
84
  * Install this ActiveRecord structure into DB.
85
  */
86
- public function Install(){
 
87
  $_wpdb = $this->connection;
88
  $_wpdb->query($this->_GetInstallQuery());
89
  }
90
 
91
- /**
92
  * Install this ActiveRecord structure into DB WordPress.
93
  */
94
- public function InstallOriginal(){
 
95
  global $wpdb;
96
  $wpdb->query($this->_GetInstallQuery(true));
97
  }
98
 
99
  /**
100
- * Remove this ActiveRecord structure into DB.
101
  */
102
  public function Uninstall()
103
  {
104
- //global $wpdb;
105
  $_wpdb = $this->connection;
106
  $_wpdb->query($this->_GetUninstallQuery());
107
  }
108
 
109
  /**
110
- * Save an active record to DB.
111
  * @return integer|boolean Either the number of modified/inserted rows or false on failure.
112
  */
113
  public function Save($activeRecord)
114
  {
115
- //global $wpdb;
116
  $_wpdb = $this->connection;
117
  $copy = $activeRecord;
118
  $data = array();
@@ -155,13 +167,12 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
155
  }
156
 
157
  /**
158
- * Load record from DB.
159
  * @param string $cond (Optional) Load condition.
160
  * @param array $args (Optional) Load condition arguments.
161
  */
162
  public function Load($cond = '%d', $args = array(1))
163
  {
164
- //global $wpdb;
165
  $_wpdb = $this->connection;
166
 
167
  $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
@@ -170,9 +181,13 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
170
  return $data;
171
  }
172
 
 
 
 
 
 
173
  public function LoadArray($cond, $args = array())
174
  {
175
- //global $wpdb;
176
  $_wpdb = $this->connection;
177
  $result = array();
178
  $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
@@ -188,7 +203,6 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
188
  */
189
  public function Delete($activeRecord)
190
  {
191
- //global $wpdb;
192
  $_wpdb = $this->connection;
193
  $result = $_wpdb->delete(
194
  $this->GetTable(),
@@ -218,7 +232,6 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
218
  */
219
  public function LoadMulti($cond, $args = array())
220
  {
221
- //global $wpdb;
222
  $_wpdb = $this->connection;
223
  $result = array();
224
  $sql = (!is_array($args) || !count($args)) // do we really need to prepare() or not?
@@ -240,7 +253,6 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
240
  */
241
  public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1))
242
  {
243
- //global $wpdb;
244
  $_wpdb = $this->connection;
245
  $class = get_called_class();
246
  $sql = $_wpdb->prepare('SELECT * FROM ' . $this->GetTable() . ' WHERE '.$cond, $args);
@@ -258,7 +270,6 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
258
  */
259
  public function Count($cond = '%d', $args = array(1))
260
  {
261
- //global $wpdb;
262
  $_wpdb = $this->connection;
263
  $class = get_called_class();
264
  $sql = $_wpdb->prepare('SELECT COUNT(*) FROM ' . $this->GetTable() . ' WHERE ' . $cond, $args);
@@ -273,7 +284,6 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
273
  */
274
  public function CountQuery($query, $args = array())
275
  {
276
- //global $wpdb;
277
  $_wpdb = $this->connection;
278
  $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
279
  return (int)$_wpdb->get_var($sql);
@@ -287,7 +297,6 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
287
  */
288
  public function LoadMultiQuery($query, $args = array())
289
  {
290
- //global $wpdb;
291
  $_wpdb = $this->connection;
292
  $class = get_called_class();
293
  $result = array();
@@ -299,6 +308,7 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
299
  }
300
 
301
  /**
 
302
  * @return string Must return SQL for creating table.
303
  */
304
  protected function _GetInstallQuery($prefix = false)
@@ -349,7 +359,6 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
349
  }
350
 
351
  return $sql;
352
-
353
  }
354
 
355
  /**
@@ -360,6 +369,11 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
360
  return 'DROP TABLE ' . $this->GetTable();
361
  }
362
 
 
 
 
 
 
363
  private function GetUserNames($_userId)
364
  {
365
  global $wpdb;
@@ -379,7 +393,16 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
379
  }
380
 
381
  /**
382
- * Function used in WSAL reporting extension
 
 
 
 
 
 
 
 
 
383
  */
384
  public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp, $_nextDate = null, $_limit = 0)
385
  {
@@ -456,8 +479,10 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
456
  }
457
 
458
  /**
459
- * Function used in WSAL reporting extension
460
- * Check if criteria are matching in the DB
 
 
461
  */
462
  public function CheckMatchReportCriteria($criteria)
463
  {
@@ -509,7 +534,17 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
509
  }
510
 
511
  /**
512
- * List of unique IP addresses used by the same user
 
 
 
 
 
 
 
 
 
 
513
  */
514
  public function GetReportGrouped($_siteId, $_startTimestamp, $_endTimestamp, $_userId = 'null', $_roleName = 'null', $_ipAddress = 'null', $_alertCode = 'null', $_limit = 0)
515
  {
@@ -623,8 +658,9 @@ class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInte
623
  }
624
 
625
  /**
626
- * TRUNCATE temp table `tmp_users` and populate with users
627
- * It is used in the query of the above function
 
628
  */
629
  private function TempUsers($tableUsers)
630
  {
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * MySQL database ActiveRecord class.
5
+ *
6
+ * MySQL generic table used for Save, Read, Create or Delete
7
+ * elements in the Database.
8
+ * There are also the functions used in the Report Add-On to get the reports.
9
+ */
10
  class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInterface
11
  {
12
  protected $connection;
28
  $this->connection = $conn;
29
  }
30
 
31
+ /**
32
+ * @return WSAL_Models_ActiveRecord
33
+ */
34
  public function GetModel()
35
  {
36
  return new WSAL_Models_ActiveRecord();
72
 
73
  if (!isset($this->_column_cache)) {
74
  $this->_column_cache = array();
75
+ foreach (array_keys(get_object_vars($model)) as $col) {
76
+ if (trim($col) && $col[0] != '_') {
77
  $this->_column_cache[] = $col;
78
+ }
79
+ }
80
  }
81
  return $this->_column_cache;
82
  }
85
  * @deprecated
86
  * @return boolean Returns whether table structure is installed or not.
87
  */
88
+ public function IsInstalled()
89
+ {
90
  $_wpdb = $this->connection;
91
  $sql = 'SHOW TABLES LIKE "' . $this->GetTable() . '"';
92
  return strtolower($_wpdb->get_var($sql)) == strtolower($this->GetTable());
95
  /**
96
  * Install this ActiveRecord structure into DB.
97
  */
98
+ public function Install()
99
+ {
100
  $_wpdb = $this->connection;
101
  $_wpdb->query($this->_GetInstallQuery());
102
  }
103
 
104
+ /**
105
  * Install this ActiveRecord structure into DB WordPress.
106
  */
107
+ public function InstallOriginal()
108
+ {
109
  global $wpdb;
110
  $wpdb->query($this->_GetInstallQuery(true));
111
  }
112
 
113
  /**
114
+ * Remove this ActiveRecord structure from DB.
115
  */
116
  public function Uninstall()
117
  {
 
118
  $_wpdb = $this->connection;
119
  $_wpdb->query($this->_GetUninstallQuery());
120
  }
121
 
122
  /**
123
+ * Save an active record into DB.
124
  * @return integer|boolean Either the number of modified/inserted rows or false on failure.
125
  */
126
  public function Save($activeRecord)
127
  {
 
128
  $_wpdb = $this->connection;
129
  $copy = $activeRecord;
130
  $data = array();
167
  }
168
 
169
  /**
170
+ * Load record from DB (Single row).
171
  * @param string $cond (Optional) Load condition.
172
  * @param array $args (Optional) Load condition arguments.
173
  */
174
  public function Load($cond = '%d', $args = array(1))
175
  {
 
176
  $_wpdb = $this->connection;
177
 
178
  $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
181
  return $data;
182
  }
183
 
184
+ /**
185
+ * Load records from DB (Multi rows).
186
+ * @param string $cond Load condition.
187
+ * @param array $args (Optional) Load condition arguments.
188
+ */
189
  public function LoadArray($cond, $args = array())
190
  {
 
191
  $_wpdb = $this->connection;
192
  $result = array();
193
  $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
203
  */
204
  public function Delete($activeRecord)
205
  {
 
206
  $_wpdb = $this->connection;
207
  $result = $_wpdb->delete(
208
  $this->GetTable(),
232
  */
233
  public function LoadMulti($cond, $args = array())
234
  {
 
235
  $_wpdb = $this->connection;
236
  $result = array();
237
  $sql = (!is_array($args) || !count($args)) // do we really need to prepare() or not?
253
  */
254
  public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1))
255
  {
 
256
  $_wpdb = $this->connection;
257
  $class = get_called_class();
258
  $sql = $_wpdb->prepare('SELECT * FROM ' . $this->GetTable() . ' WHERE '.$cond, $args);
270
  */
271
  public function Count($cond = '%d', $args = array(1))
272
  {
 
273
  $_wpdb = $this->connection;
274
  $class = get_called_class();
275
  $sql = $_wpdb->prepare('SELECT COUNT(*) FROM ' . $this->GetTable() . ' WHERE ' . $cond, $args);
284
  */
285
  public function CountQuery($query, $args = array())
286
  {
 
287
  $_wpdb = $this->connection;
288
  $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
289
  return (int)$_wpdb->get_var($sql);
297
  */
298
  public function LoadMultiQuery($query, $args = array())
299
  {
 
300
  $_wpdb = $this->connection;
301
  $class = get_called_class();
302
  $result = array();
308
  }
309
 
310
  /**
311
+ * @param string $prefix (Optional) table prefix
312
  * @return string Must return SQL for creating table.
313
  */
314
  protected function _GetInstallQuery($prefix = false)
359
  }
360
 
361
  return $sql;
 
362
  }
363
 
364
  /**
369
  return 'DROP TABLE ' . $this->GetTable();
370
  }
371
 
372
+ /**
373
+ * Get Users user_login.
374
+ * @param int $_userId user ID
375
+ * @return string comma separated users login
376
+ */
377
  private function GetUserNames($_userId)
378
  {
379
  global $wpdb;
393
  }
394
 
395
  /**
396
+ * Function used in WSAL reporting extension.
397
+ * @param int $_siteId site ID
398
+ * @param int $_userId user ID
399
+ * @param string $_roleName user role
400
+ * @param int $_alertCode alert code
401
+ * @param timestamp $_startTimestamp from created_on
402
+ * @param timestamp $_endTimestamp to created_on
403
+ * @param timestamp $_nextDate (Optional) created_on >
404
+ * @param int $_limit (Optional) limit
405
+ * @return array Report results
406
  */
407
  public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp, $_nextDate = null, $_limit = 0)
408
  {
479
  }
480
 
481
  /**
482
+ * Function used in WSAL reporting extension.
483
+ * Check if criteria are matching in the DB.
484
+ * @param mixed $criteria query conditions
485
+ * @return int count of distinct values
486
  */
487
  public function CheckMatchReportCriteria($criteria)
488
  {
534
  }
535
 
536
  /**
537
+ * Function used in WSAL reporting extension.
538
+ * List of unique IP addresses used by the same user.
539
+ * @param int $_siteId site ID
540
+ * @param timestamp $_startTimestamp from created_on
541
+ * @param timestamp $_endTimestamp to created_on
542
+ * @param int $_userId (Optional) user ID
543
+ * @param string $_roleName (Optional) user role
544
+ * @param string $_ipAddress (Optional) IP address
545
+ * @param int $_alertCode (Optional) alert code
546
+ * @param int $_limit (Optional) limit
547
+ * @return array Report results grouped by IP and Username
548
  */
549
  public function GetReportGrouped($_siteId, $_startTimestamp, $_endTimestamp, $_userId = 'null', $_roleName = 'null', $_ipAddress = 'null', $_alertCode = 'null', $_limit = 0)
550
  {
658
  }
659
 
660
  /**
661
+ * DELETE from table `tmp_users` and populate with users.
662
+ * It is used in the query of the above function.
663
+ * @param string $tableUsers table name
664
  */
665
  private function TempUsers($tableUsers)
666
  {
classes/Adapters/MySQL/MetaAdapter.php CHANGED
@@ -1,7 +1,13 @@
1
  <?php
2
-
3
- class WSAL_Adapters_MySQL_Meta extends WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_MetaInterface {
4
-
 
 
 
 
 
 
5
  protected $_table = 'wsal_metadata';
6
  protected $_idkey = 'id';
7
 
@@ -11,6 +17,9 @@ class WSAL_Adapters_MySQL_Meta extends WSAL_Adapters_MySQL_ActiveRecord implemen
11
  public static $name_maxlength = 100;
12
  public $value = array(); // force mixed type
13
 
 
 
 
14
  public function GetModel()
15
  {
16
  return new WSAL_Models_Meta();
@@ -21,11 +30,19 @@ class WSAL_Adapters_MySQL_Meta extends WSAL_Adapters_MySQL_ActiveRecord implemen
21
  parent::__construct($conn);
22
  }
23
 
24
- protected function GetTableOptions(){
 
 
 
 
25
  return parent::GetTableOptions() . ',' . PHP_EOL
26
  . ' KEY occurrence_name (occurrence_id,name)';
27
  }
28
 
 
 
 
 
29
  public function DeleteByOccurenceIds($occurenceIds)
30
  {
31
  if (!empty($occurenceIds)) {
@@ -35,16 +52,29 @@ class WSAL_Adapters_MySQL_Meta extends WSAL_Adapters_MySQL_ActiveRecord implemen
35
  }
36
  }
37
 
 
 
 
 
 
 
38
  public function LoadByNameAndOccurenceId($metaName, $occurenceId)
39
  {
40
  return $this->Load('occurrence_id = %d AND name = %s', array($occurenceId, $metaName));
41
  }
42
 
 
 
 
 
 
43
  public function GetMatchingIPs($limit = null)
44
  {
45
  $_wpdb = $this->connection;
46
  $sql = "SELECT DISTINCT value FROM {$this->GetTable()} WHERE name = \"ClientIP\"";
47
- if (!is_null($limit)) $sql .= ' LIMIT ' . $limit;
 
 
48
  $ips = $_wpdb->get_col($sql);
49
  foreach ($ips as $key => $ip) {
50
  $ips[$key] = str_replace('"', '', $ip);
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * MySQL database Metadata class.
5
+ *
6
+ * MySQL wsal_metadata table used for to store the alert meta data:
7
+ * username, user_roles, client_ip, user_agent, post_id, post_title, etc.
8
+ */
9
+ class WSAL_Adapters_MySQL_Meta extends WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_MetaInterface
10
+ {
11
  protected $_table = 'wsal_metadata';
12
  protected $_idkey = 'id';
13
 
17
  public static $name_maxlength = 100;
18
  public $value = array(); // force mixed type
19
 
20
+ /**
21
+ * @return WSAL_Models_Meta
22
+ */
23
  public function GetModel()
24
  {
25
  return new WSAL_Models_Meta();
30
  parent::__construct($conn);
31
  }
32
 
33
+ /**
34
+ * @return string SQL table options (constraints, foreign keys, indexes etc).
35
+ */
36
+ protected function GetTableOptions()
37
+ {
38
  return parent::GetTableOptions() . ',' . PHP_EOL
39
  . ' KEY occurrence_name (occurrence_id,name)';
40
  }
41
 
42
+ /**
43
+ * Delete metadata by occurrence_id.
44
+ * @param array $occurenceIds list of occurrence IDs
45
+ */
46
  public function DeleteByOccurenceIds($occurenceIds)
47
  {
48
  if (!empty($occurenceIds)) {
52
  }
53
  }
54
 
55
+ /**
56
+ * Load metadata by name and occurrence_id.
57
+ * @param string $metaName metadata name
58
+ * @param string $occurenceId metadata occurrence_id
59
+ * @return WSAL_Meta[]
60
+ */
61
  public function LoadByNameAndOccurenceId($metaName, $occurenceId)
62
  {
63
  return $this->Load('occurrence_id = %d AND name = %s', array($occurenceId, $metaName));
64
  }
65
 
66
+ /**
67
+ * Get distinct values of IPs.
68
+ * @param int $limit (Optional) limit
69
+ * @return array distinct values of IPs
70
+ */
71
  public function GetMatchingIPs($limit = null)
72
  {
73
  $_wpdb = $this->connection;
74
  $sql = "SELECT DISTINCT value FROM {$this->GetTable()} WHERE name = \"ClientIP\"";
75
+ if (!is_null($limit)) {
76
+ $sql .= ' LIMIT ' . $limit;
77
+ }
78
  $ips = $_wpdb->get_col($sql);
79
  foreach ($ips as $key => $ip) {
80
  $ips[$key] = str_replace('"', '', $ip);
classes/Adapters/MySQL/OccurrenceAdapter.php CHANGED
@@ -1,7 +1,12 @@
1
  <?php
2
-
3
- class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_OccurrenceInterface {
4
-
 
 
 
 
 
5
  protected $_table = 'wsal_occurrences';
6
  protected $_idkey = 'id';
7
  protected $_meta;
@@ -13,33 +18,50 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
13
  public $is_read = false;
14
  public $is_migrated = false;
15
 
16
- public function __construct($conn) {
 
17
  parent::__construct($conn);
18
  }
19
 
20
- protected function GetTableOptions(){
 
 
 
 
21
  return parent::GetTableOptions() . ',' . PHP_EOL
22
  . ' KEY site_alert_created (site_id,alert_id,created_on)';
23
  }
24
 
 
 
 
25
  public function GetModel()
26
  {
27
  return new WSAL_Models_Occurrence();
28
  }
 
29
  /**
30
- * Returns all meta data related to this event.
31
- * @return WSAL_Meta[]
 
32
  */
33
- public function GetMeta($occurence){
34
- if(!isset($this->_meta)){
 
35
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
36
  $this->_meta = $meta->Load('occurrence_id = %d', array($occurence->id));
37
  }
38
  return $this->_meta;
39
  }
40
 
41
- public function GetMultiMeta($occurence){
42
- if(!isset($this->_meta)){
 
 
 
 
 
 
43
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
44
  $this->_meta = $meta->LoadArray('occurrence_id = %d', array($occurence->id));
45
  }
@@ -48,10 +70,12 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
48
 
49
  /**
50
  * Loads a meta item given its name.
 
51
  * @param string $name Meta name.
52
  * @return WSAL_Meta The meta item, be sure to checked if it was loaded successfully.
53
  */
54
- public function GetNamedMeta($occurence, $name){
 
55
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
56
  $this->_meta = $meta->Load('occurrence_id = %d AND name = %s', array($occurence->id, $name));
57
 
@@ -63,7 +87,8 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
63
  * @param array $names List of meta names.
64
  * @return WSAL_Meta The first meta item that exists.
65
  */
66
- public function GetFirstNamedMeta($occurence, $names){
 
67
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
68
  $query = '(' . str_repeat('name = %s OR ', count($names)).'0)';
69
  $query = 'occurrence_id = %d AND ' . $query . ' ORDER BY name DESC LIMIT 1';
@@ -81,7 +106,8 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
81
  * @param integer $limit Maximum limit.
82
  * @return WSAL_Occurrence[]
83
  */
84
- public static function GetNewestUnique($limit = PHP_INT_MAX){
 
85
  $temp = new self();
86
  return self::LoadMultiQuery('
87
  SELECT *, COUNT(alert_id) as count
@@ -96,13 +122,14 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
96
  }
97
 
98
  /**
99
- * Gets occurences of the same type by IP and Username within specified time frame
100
  * @param string $ipAddress
101
  * @param string $username
102
  * @param int $alertId Alert type we are lookign for
103
  * @param int $siteId
104
  * @param $startTime mktime
105
  * @param $endTime mktime
 
106
  */
107
  public function CheckKnownUsers($args = array())
108
  {
@@ -122,6 +149,15 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
122
  );
123
  }
124
 
 
 
 
 
 
 
 
 
 
125
  public function CheckUnKnownUsers($args = array())
126
  {
127
  $tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
@@ -136,6 +172,10 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
136
  );
137
  }
138
 
 
 
 
 
139
  protected function prepareOccurrenceQuery($query)
140
  {
141
  $searchQueryParameters = array();
@@ -167,8 +207,9 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
167
  }
168
 
169
  /**
170
- * Gets occurrence by Post_id
171
  * @param int $post_id
 
172
  */
173
  public function GetByPostID($post_id)
174
  {
@@ -185,15 +226,16 @@ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord im
185
  }
186
 
187
  /**
188
- * Gets occurences of the same type by IP within specified time frame
189
  * @param string $ipAddress
190
  * @param string $username
191
  * @param int $alertId Alert type we are lookign for
192
  * @param int $siteId
193
  * @param $startTime mktime
194
  * @param $endTime mktime
 
195
  */
196
- public function CheckAlert404($args = array())
197
  {
198
  $tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
199
  return self::LoadMultiQuery(
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * MySQL database Occurrence class.
5
+ *
6
+ * MySQL wsal_occurrences table used for to store the alerts.
7
+ */
8
+ class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_OccurrenceInterface
9
+ {
10
  protected $_table = 'wsal_occurrences';
11
  protected $_idkey = 'id';
12
  protected $_meta;
18
  public $is_read = false;
19
  public $is_migrated = false;
20
 
21
+ public function __construct($conn)
22
+ {
23
  parent::__construct($conn);
24
  }
25
 
26
+ /**
27
+ * @return string SQL table options (constraints, foreign keys, indexes etc).
28
+ */
29
+ protected function GetTableOptions()
30
+ {
31
  return parent::GetTableOptions() . ',' . PHP_EOL
32
  . ' KEY site_alert_created (site_id,alert_id,created_on)';
33
  }
34
 
35
+ /**
36
+ * @return WSAL_Models_Occurrence
37
+ */
38
  public function GetModel()
39
  {
40
  return new WSAL_Models_Occurrence();
41
  }
42
+
43
  /**
44
+ * Returns metadata related to this event.
45
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Load()
46
+ * @return WSAL_Meta
47
  */
48
+ public function GetMeta($occurence)
49
+ {
50
+ if (!isset($this->_meta)) {
51
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
52
  $this->_meta = $meta->Load('occurrence_id = %d', array($occurence->id));
53
  }
54
  return $this->_meta;
55
  }
56
 
57
+ /**
58
+ * Returns allmeta data related to this event.
59
+ * @see WSAL_Adapters_MySQL_ActiveRecord::LoadArray()
60
+ * @return WSAL_Meta[]
61
+ */
62
+ public function GetMultiMeta($occurence)
63
+ {
64
+ if (!isset($this->_meta)) {
65
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
66
  $this->_meta = $meta->LoadArray('occurrence_id = %d', array($occurence->id));
67
  }
70
 
71
  /**
72
  * Loads a meta item given its name.
73
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Load()
74
  * @param string $name Meta name.
75
  * @return WSAL_Meta The meta item, be sure to checked if it was loaded successfully.
76
  */
77
+ public function GetNamedMeta($occurence, $name)
78
+ {
79
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
80
  $this->_meta = $meta->Load('occurrence_id = %d AND name = %s', array($occurence->id, $name));
81
 
87
  * @param array $names List of meta names.
88
  * @return WSAL_Meta The first meta item that exists.
89
  */
90
+ public function GetFirstNamedMeta($occurence, $names)
91
+ {
92
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
93
  $query = '(' . str_repeat('name = %s OR ', count($names)).'0)';
94
  $query = 'occurrence_id = %d AND ' . $query . ' ORDER BY name DESC LIMIT 1';
106
  * @param integer $limit Maximum limit.
107
  * @return WSAL_Occurrence[]
108
  */
109
+ public static function GetNewestUnique($limit = PHP_INT_MAX)
110
+ {
111
  $temp = new self();
112
  return self::LoadMultiQuery('
113
  SELECT *, COUNT(alert_id) as count
122
  }
123
 
124
  /**
125
+ * Gets occurences of the same type by IP and Username within specified time frame.
126
  * @param string $ipAddress
127
  * @param string $username
128
  * @param int $alertId Alert type we are lookign for
129
  * @param int $siteId
130
  * @param $startTime mktime
131
  * @param $endTime mktime
132
+ * @return WSAL_Occurrence[]
133
  */
134
  public function CheckKnownUsers($args = array())
135
  {
149
  );
150
  }
151
 
152
+ /**
153
+ * Gets occurences of the same type by IP within specified time frame.
154
+ * @param string $ipAddress
155
+ * @param int $alertId Alert type we are lookign for
156
+ * @param int $siteId
157
+ * @param $startTime mktime
158
+ * @param $endTime mktime
159
+ * @return WSAL_Occurrence[]
160
+ */
161
  public function CheckUnKnownUsers($args = array())
162
  {
163
  $tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
172
  );
173
  }
174
 
175
+ /**
176
+ * Add conditions to the Query
177
+ * @param string $query
178
+ */
179
  protected function prepareOccurrenceQuery($query)
180
  {
181
  $searchQueryParameters = array();
207
  }
208
 
209
  /**
210
+ * Gets occurrence by Post_id.
211
  * @param int $post_id
212
+ * @return WSAL_Occurrence[]
213
  */
214
  public function GetByPostID($post_id)
215
  {
226
  }
227
 
228
  /**
229
+ * Gets occurences of the same type by IP within specified time frame.
230
  * @param string $ipAddress
231
  * @param string $username
232
  * @param int $alertId Alert type we are lookign for
233
  * @param int $siteId
234
  * @param $startTime mktime
235
  * @param $endTime mktime
236
+ * @return WSAL_Occurrence[]
237
  */
238
+ public function CheckAlert404($args = array())
239
  {
240
  $tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
241
  return self::LoadMultiQuery(
classes/Adapters/MySQL/OptionAdapter.php CHANGED
@@ -1,8 +1,12 @@
1
  <?php
2
-
 
 
 
 
 
3
  class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
4
  {
5
-
6
  protected $_table = 'wsal_options';
7
  protected $_idkey = 'id';
8
 
@@ -16,19 +20,33 @@ class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
16
  parent::__construct($conn);
17
  }
18
 
 
 
 
19
  public function GetModel()
20
  {
21
  return new WSAL_Models_Option();
22
  }
23
 
 
 
 
 
 
24
  public function GetNamedOption($name)
25
- { if ($this->IsInstalled()) {
 
26
  return $this->Load('option_name = %s', array($name));
27
  } else {
28
  return null;
29
  }
30
  }
31
 
 
 
 
 
 
32
  public function GetNotificationsSetting($opt_prefix)
33
  {
34
  if ($this->IsInstalled()) {
@@ -38,6 +56,11 @@ class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
38
  }
39
  }
40
 
 
 
 
 
 
41
  public function GetNotification($id)
42
  {
43
  if ($this->IsInstalled()) {
@@ -47,6 +70,11 @@ class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
47
  }
48
  }
49
 
 
 
 
 
 
50
  public function DeleteByName($name)
51
  {
52
  if (!empty($name)) {
@@ -58,6 +86,11 @@ class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
58
  }
59
  }
60
 
 
 
 
 
 
61
  public function DeleteByPrefix($opt_prefix)
62
  {
63
  if (!empty($opt_prefix)) {
@@ -69,11 +102,15 @@ class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
69
  }
70
  }
71
 
 
 
 
 
 
72
  public function CountNotifications($opt_prefix)
73
  {
74
  $_wpdb = $this->connection;
75
  $sql = "SELECT COUNT(id) FROM " . $this->GetTable() . " WHERE option_name LIKE '". $opt_prefix ."%'";
76
  return (int)$_wpdb->get_var($sql);
77
  }
78
-
79
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * MySQL database Option class.
5
+ *
6
+ * MySQL wsal_options table used for to store the plugin settings and Add-Ons settings.
7
+ */
8
  class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
9
  {
 
10
  protected $_table = 'wsal_options';
11
  protected $_idkey = 'id';
12
 
20
  parent::__construct($conn);
21
  }
22
 
23
+ /**
24
+ * @return WSAL_Models_Option
25
+ */
26
  public function GetModel()
27
  {
28
  return new WSAL_Models_Option();
29
  }
30
 
31
+ /**
32
+ * Get option by name.
33
+ * @param string $name option_name
34
+ * @return string|null option value
35
+ */
36
  public function GetNamedOption($name)
37
+ {
38
+ if ($this->IsInstalled()) {
39
  return $this->Load('option_name = %s', array($name));
40
  } else {
41
  return null;
42
  }
43
  }
44
 
45
+ /**
46
+ * Get options by prefix (notifications stored in json format).
47
+ * @param string $opt_prefix prefix
48
+ * @return array|null options
49
+ */
50
  public function GetNotificationsSetting($opt_prefix)
51
  {
52
  if ($this->IsInstalled()) {
56
  }
57
  }
58
 
59
+ /**
60
+ * Get option by id (notifications stored in json format).
61
+ * @param int $id option ID
62
+ * @return string|null option
63
+ */
64
  public function GetNotification($id)
65
  {
66
  if ($this->IsInstalled()) {
70
  }
71
  }
72
 
73
+ /**
74
+ * Delete option by name.
75
+ * @param string $name option_name
76
+ * @return boolean.
77
+ */
78
  public function DeleteByName($name)
79
  {
80
  if (!empty($name)) {
86
  }
87
  }
88
 
89
+ /**
90
+ * Delete options start with prefix.
91
+ * @param string $opt_prefix prefix
92
+ * @return boolean.
93
+ */
94
  public function DeleteByPrefix($opt_prefix)
95
  {
96
  if (!empty($opt_prefix)) {
102
  }
103
  }
104
 
105
+ /**
106
+ * Number of options start with prefix.
107
+ * @param string $opt_prefix prefix
108
+ * @return integer Indicates the number of items.
109
+ */
110
  public function CountNotifications($opt_prefix)
111
  {
112
  $_wpdb = $this->connection;
113
  $sql = "SELECT COUNT(id) FROM " . $this->GetTable() . " WHERE option_name LIKE '". $opt_prefix ."%'";
114
  return (int)$_wpdb->get_var($sql);
115
  }
 
116
  }
classes/Adapters/MySQL/QueryAdapter.php CHANGED
@@ -1,5 +1,11 @@
1
  <?php
2
-
 
 
 
 
 
 
3
  class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
4
  {
5
  protected $connection;
@@ -10,6 +16,9 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
10
  }
11
 
12
  /**
 
 
 
13
  * @return string Generated sql.
14
  */
15
  protected function GetSql($query, &$args = array())
@@ -85,13 +94,19 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
85
  return $sql;
86
  }
87
 
 
 
 
 
88
  protected function getActiveRecordAdapter()
89
  {
90
  return new WSAL_Adapters_MySQL_ActiveRecord($this->connection);
91
  }
92
 
93
  /**
94
- * @return WSAL_Models_ActiveRecord[] Execute query and return data as $ar_cls objects.
 
 
95
  */
96
  public function Execute($query)
97
  {
@@ -108,7 +123,9 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
108
  }
109
 
110
  /**
111
- * @return int Use query for counting records.
 
 
112
  */
113
  public function Count($query)
114
  {
@@ -126,6 +143,11 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
126
  return $this->getActiveRecordAdapter()->CountQuery($sql, $args);
127
  }
128
 
 
 
 
 
 
129
  public function CountDelete($query)
130
  {
131
  $result = $this->GetSqlDelete($query, true);
@@ -134,7 +156,8 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
134
  }
135
 
136
  /**
137
- * Use query for deleting records.
 
138
  */
139
  public function Delete($query)
140
  {
@@ -143,6 +166,11 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
143
  return $this->getActiveRecordAdapter()->DeleteQuery($result['sql'], $result['args']);
144
  }
145
 
 
 
 
 
 
146
  public function DeleteMetas($query, $args)
147
  {
148
  // back up columns, use COUNT as default column and generate sql
@@ -163,6 +191,12 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
163
  $meta->DeleteByOccurenceIds($occ_ids);
164
  }
165
 
 
 
 
 
 
 
166
  public function GetSqlDelete($query, $getCount = false)
167
  {
168
  $result = array();
@@ -201,16 +235,22 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
201
  . (!empty($orderBys) ? (' ORDER BY ' . implode(', ', array_keys($orderBys)) . ' ' . implode(', ', array_values($orderBys))) : '')
202
  . $sLimitClause;
203
  $result['args'] = $args;
204
- //restore columns
205
  $query->setColumns($cols);
206
 
207
  return $result;
208
  }
209
 
 
 
 
 
210
  public function SearchCondition($query)
211
  {
212
  $condition = $query->getSearchCondition();
213
- if (empty($condition)) return null;
 
 
214
  $searchConditions = array();
215
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
216
  $occurrence = new WSAL_Adapters_MySQL_Occurrence($this->connection);
@@ -226,5 +266,4 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
226
  $searchConditions['args'] = "%". $condition. "%";
227
  return $searchConditions;
228
  }
229
-
230
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * MySQL database Query class.
5
+ *
6
+ * The SQL query is created in this class, here the SQL is filled with
7
+ * the arguments.
8
+ */
9
  class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
10
  {
11
  protected $connection;
16
  }
17
 
18
  /**
19
+ * Get the SQL filled with the args.
20
+ * @param object $query query object
21
+ * @param array $args args of the query
22
  * @return string Generated sql.
23
  */
24
  protected function GetSql($query, &$args = array())
94
  return $sql;
95
  }
96
 
97
+ /**
98
+ * Get an instance of the ActiveRecord Adapter.
99
+ * @return WSAL_Adapters_MySQL_ActiveRecord
100
+ */
101
  protected function getActiveRecordAdapter()
102
  {
103
  return new WSAL_Adapters_MySQL_ActiveRecord($this->connection);
104
  }
105
 
106
  /**
107
+ * Execute query and return data as $ar_cls objects.
108
+ * @param object $query query object
109
+ * @return WSAL_Models_ActiveRecord[]
110
  */
111
  public function Execute($query)
112
  {
123
  }
124
 
125
  /**
126
+ * Count query
127
+ * @param object $query query object
128
+ * @return integer counting records.
129
  */
130
  public function Count($query)
131
  {
143
  return $this->getActiveRecordAdapter()->CountQuery($sql, $args);
144
  }
145
 
146
+ /**
147
+ * Count DELETE query
148
+ * @param object $query query object
149
+ * @return integer counting records.
150
+ */
151
  public function CountDelete($query)
152
  {
153
  $result = $this->GetSqlDelete($query, true);
156
  }
157
 
158
  /**
159
+ * Query for deleting records
160
+ * @param object $query query object.
161
  */
162
  public function Delete($query)
163
  {
166
  return $this->getActiveRecordAdapter()->DeleteQuery($result['sql'], $result['args']);
167
  }
168
 
169
+ /**
170
+ * Load occurrence IDs then delete Metadata by occurrence_id
171
+ * @param object $query query object
172
+ * @param array $args args of the query
173
+ */
174
  public function DeleteMetas($query, $args)
175
  {
176
  // back up columns, use COUNT as default column and generate sql
191
  $meta->DeleteByOccurenceIds($occ_ids);
192
  }
193
 
194
+ /**
195
+ * Get the DELETE query SQL filled with the args.
196
+ * @param object $query query object
197
+ * @param array $args args of the query
198
+ * @return string Generated sql.
199
+ */
200
  public function GetSqlDelete($query, $getCount = false)
201
  {
202
  $result = array();
235
  . (!empty($orderBys) ? (' ORDER BY ' . implode(', ', array_keys($orderBys)) . ' ' . implode(', ', array_values($orderBys))) : '')
236
  . $sLimitClause;
237
  $result['args'] = $args;
238
+ // restore columns
239
  $query->setColumns($cols);
240
 
241
  return $result;
242
  }
243
 
244
+ /**
245
+ * Search by alert code OR by Metadata value.
246
+ * @param object $query query object
247
+ */
248
  public function SearchCondition($query)
249
  {
250
  $condition = $query->getSearchCondition();
251
+ if (empty($condition)) {
252
+ return null;
253
+ }
254
  $searchConditions = array();
255
  $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
256
  $occurrence = new WSAL_Adapters_MySQL_Occurrence($this->connection);
266
  $searchConditions['args'] = "%". $condition. "%";
267
  return $searchConditions;
268
  }
 
269
  }
classes/Adapters/MySQL/TmpUserAdapter.php CHANGED
@@ -1,12 +1,23 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
3
  class WSAL_Adapters_MySQL_TmpUser extends WSAL_Adapters_MySQL_ActiveRecord {
4
 
5
  protected $_table = 'wsal_tmp_users';
6
 
 
 
 
7
  public function GetModel()
8
  {
9
- return new WSAL_Models_Meta();
10
  }
11
 
12
  public function __construct($conn)
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * MySQL database TmpUser class.
5
+ *
6
+ * This class is used for create a temporary table to store the WP users
7
+ * when the External DB Add-On is activated and the Alerts are stored on an external DB
8
+ * because the query between plugin tables and the internal wp_uses table is not possible.
9
+ * @see WSAL_Adapters_MySQL_ActiveRecord->GetReportGrouped()
10
+ */
11
  class WSAL_Adapters_MySQL_TmpUser extends WSAL_Adapters_MySQL_ActiveRecord {
12
 
13
  protected $_table = 'wsal_tmp_users';
14
 
15
+ /**
16
+ * @return WSAL_Models_TmpUser
17
+ */
18
  public function GetModel()
19
  {
20
+ return new WSAL_Models_TmpUser();
21
  }
22
 
23
  public function __construct($conn)
classes/Adapters/OccurrenceInterface.php CHANGED
@@ -1,5 +1,9 @@
1
  <?php
2
-
 
 
 
 
3
  interface WSAL_Adapters_OccurrenceInterface
4
  {
5
  public function GetMeta($occurence);
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Interface used by the Occurrence.
6
+ */
7
  interface WSAL_Adapters_OccurrenceInterface
8
  {
9
  public function GetMeta($occurence);
classes/Adapters/QueryInterface.php CHANGED
@@ -1,8 +1,12 @@
1
  <?php
2
-
 
 
 
 
3
  interface WSAL_Adapters_QueryInterface
4
  {
5
- public function Execute($query);
6
- public function Count($query);
7
- public function Delete($query);
8
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Interface used by the Query.
6
+ */
7
  interface WSAL_Adapters_QueryInterface
8
  {
9
+ public function Execute($query);
10
+ public function Count($query);
11
+ public function Delete($query);
12
  }
classes/Alert.php CHANGED
@@ -1,7 +1,11 @@
1
  <?php
2
-
3
- final class WSAL_Alert {
4
-
 
 
 
 
5
  /**
6
  * Alert type (used when triggering an alert etc).
7
  * @var integer
@@ -38,7 +42,8 @@ final class WSAL_Alert {
38
  */
39
  public $mesg = '';
40
 
41
- public function __construct($type = 0, $code = 0, $catg = '', $subcatg = '', $desc = '', $mesg = '') {
 
42
  $this->type = $type;
43
  $this->code = $code;
44
  $this->catg = $catg;
@@ -53,13 +58,16 @@ final class WSAL_Alert {
53
  * @param array $metaData (Optional) Meta data relevant to expression.
54
  * @return mixed The value nearest to the expression.
55
  */
56
- protected function GetMetaExprValue($expr, $metaData = array()){
 
57
  // TODO Handle function calls (and methods?)
58
  $expr = explode('->', $expr);
59
  $meta = array_shift($expr);
60
  $meta = isset($metaData[$meta]) ? $metaData[$meta] : null;
61
- foreach($expr as $part){
62
- if(is_scalar($meta) || is_null($meta))return $meta; // this isn't 100% correct
 
 
63
  $meta = is_array($meta) ? $meta[$part] : $meta->$part;
64
  }
65
  return is_scalar($meta) ? (string)$meta : var_export($meta, true);
@@ -73,20 +81,24 @@ final class WSAL_Alert {
73
  * @param string $afterMeta (Optional) Some text to put after meta values.
74
  * @return string The expanded message.
75
  */
76
- protected function GetFormattedMesg($origMesg, $metaData = array(), $metaFormatter = null){
 
77
  // tokenize message with regex
78
  $mesg = preg_split('/(%.*?%)/', (string)$origMesg, -1, PREG_SPLIT_DELIM_CAPTURE);
79
- if(!is_array($mesg))return (string)$origMesg;
 
 
80
  // handle tokenized message
81
- foreach($mesg as $i => $token){
82
  // handle escaped percent sign
83
- if($token == '%%'){
84
  $mesg[$i] = '%';
85
- }else
86
- // handle complex expressions
87
- if(substr($token, 0, 1) == '%' && substr($token, -1, 1) == '%'){
88
  $mesg[$i] = $this->GetMetaExprValue(substr($token, 1, -1), $metaData);
89
- if($metaFormatter)$mesg[$i] = call_user_func($metaFormatter, $token, $mesg[$i]);
 
 
90
  }
91
  }
92
  // compact message and return
@@ -94,12 +106,14 @@ final class WSAL_Alert {
94
  }
95
 
96
  /**
 
97
  * @param array $metaData (Optional) Meta data relevant to message.
98
  * @param callable|null $metaFormatter (Optional) Meta formatter callback.
99
  * @param string|null $mesg (Optional) Override message template to use.
100
  * @return string Fully formatted message.
101
  */
102
- public function GetMessage($metaData = array(), $metaFormatter = null, $mesg = null){
 
103
  return $this->GetFormattedMesg(is_null($mesg) ? $this->mesg : $mesg, $metaData, $metaFormatter);
104
  }
105
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * WSAL_Alert Object class.
6
+ */
7
+ final class WSAL_Alert
8
+ {
9
  /**
10
  * Alert type (used when triggering an alert etc).
11
  * @var integer
42
  */
43
  public $mesg = '';
44
 
45
+ public function __construct($type = 0, $code = 0, $catg = '', $subcatg = '', $desc = '', $mesg = '')
46
+ {
47
  $this->type = $type;
48
  $this->code = $code;
49
  $this->catg = $catg;
58
  * @param array $metaData (Optional) Meta data relevant to expression.
59
  * @return mixed The value nearest to the expression.
60
  */
61
+ protected function GetMetaExprValue($expr, $metaData = array())
62
+ {
63
  // TODO Handle function calls (and methods?)
64
  $expr = explode('->', $expr);
65
  $meta = array_shift($expr);
66
  $meta = isset($metaData[$meta]) ? $metaData[$meta] : null;
67
+ foreach ($expr as $part) {
68
+ if (is_scalar($meta) || is_null($meta)) {
69
+ return $meta; // this isn't 100% correct
70
+ }
71
  $meta = is_array($meta) ? $meta[$part] : $meta->$part;
72
  }
73
  return is_scalar($meta) ? (string)$meta : var_export($meta, true);
81
  * @param string $afterMeta (Optional) Some text to put after meta values.
82
  * @return string The expanded message.
83
  */
84
+ protected function GetFormattedMesg($origMesg, $metaData = array(), $metaFormatter = null)
85
+ {
86
  // tokenize message with regex
87
  $mesg = preg_split('/(%.*?%)/', (string)$origMesg, -1, PREG_SPLIT_DELIM_CAPTURE);
88
+ if (!is_array($mesg)) {
89
+ return (string)$origMesg;
90
+ }
91
  // handle tokenized message
92
+ foreach ($mesg as $i => $token) {
93
  // handle escaped percent sign
94
+ if ($token == '%%') {
95
  $mesg[$i] = '%';
96
+ } else if (substr($token, 0, 1) == '%' && substr($token, -1, 1) == '%') {
97
+ // handle complex expressions
 
98
  $mesg[$i] = $this->GetMetaExprValue(substr($token, 1, -1), $metaData);
99
+ if ($metaFormatter) {
100
+ $mesg[$i] = call_user_func($metaFormatter, $token, $mesg[$i]);
101
+ }
102
  }
103
  }
104
  // compact message and return
106
  }
107
 
108
  /**
109
+ * Gets alert message.
110
  * @param array $metaData (Optional) Meta data relevant to message.
111
  * @param callable|null $metaFormatter (Optional) Meta formatter callback.
112
  * @param string|null $mesg (Optional) Override message template to use.
113
  * @return string Fully formatted message.
114
  */
115
+ public function GetMessage($metaData = array(), $metaFormatter = null, $mesg = null)
116
+ {
117
  return $this->GetFormattedMesg(is_null($mesg) ? $this->mesg : $mesg, $metaData, $metaFormatter);
118
  }
119
  }
classes/AlertManager.php CHANGED
@@ -1,32 +1,50 @@
1
  <?php
2
-
3
- final class WSAL_AlertManager {
4
-
 
 
 
 
 
5
  /**
6
  * @var WSAL_Alert[]
7
  */
8
  protected $_alerts = array();
9
-
10
  /**
11
  * @var WSAL_AbstractLogger[]
12
  */
13
  protected $_loggers = array();
14
-
15
  /**
16
  * @var WpSecurityAuditLog
17
  */
18
  protected $plugin;
19
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  /**
21
  * Create new AlertManager instance.
22
  * @param WpSecurityAuditLog $plugin
23
  */
24
- public function __construct(WpSecurityAuditLog $plugin){
 
25
  $this->plugin = $plugin;
26
  foreach (glob(dirname(__FILE__) . '/Loggers/*.php') as $file) {
27
  $this->AddFromFile($file);
28
  }
29
-
30
  add_action('shutdown', array($this, '_CommitPipeline'));
31
  }
32
 
@@ -34,26 +52,29 @@ final class WSAL_AlertManager {
34
  * Add new logger from file inside autoloader path.
35
  * @param string $file Path to file.
36
  */
37
- public function AddFromFile($file){
 
38
  $this->AddFromClass($this->plugin->GetClassFileClassName($file));
39
  }
40
-
41
  /**
42
  * Add new logger given class name.
43
  * @param string $class Class name.
44
  */
45
- public function AddFromClass($class){
 
46
  $this->AddInstance(new $class($this->plugin));
47
  }
48
-
49
  /**
50
  * Add newly created logger to list.
51
  * @param WSAL_AbstractLogger $logger The new logger.
52
  */
53
- public function AddInstance(WSAL_AbstractLogger $logger){
 
54
  $this->_loggers[] = $logger;
55
  }
56
-
57
  /**
58
  * Remove logger by class name.
59
  * @param string $class The class name.
@@ -66,25 +87,14 @@ final class WSAL_AlertManager {
66
  }
67
  }
68
  }
69
-
70
- /**
71
- * Contains a list of alerts to trigger.
72
- * @var array
73
- */
74
- protected $_pipeline = array();
75
-
76
- /**
77
- * Contains an array of alerts that have been triggered for this request.
78
- * @var int[]
79
- */
80
- protected $_triggered_types = array();
81
-
82
  /**
83
  * Trigger an alert.
84
  * @param integer $type Alert type.
85
  * @param array $data Alert data.
86
  */
87
- public function Trigger($type, $data = array(), $delayed = false){
 
88
  $username = wp_get_current_user()->user_login;
89
  if (empty($username) && !empty($data["Username"])) {
90
  $username = $data['Username'];
@@ -111,7 +121,8 @@ final class WSAL_AlertManager {
111
  * @param array roles
112
  * @return boolean True if enable false otherwise.
113
  */
114
- public function CheckEnableUserRoles($user, $roles) {
 
115
  $is_enable = true;
116
  if ($user != "" && $this->IsDisabledUser($user)) {
117
  $is_enable = false;
@@ -121,17 +132,18 @@ final class WSAL_AlertManager {
121
  }
122
  return $is_enable;
123
  }
124
-
125
  /**
126
  * Trigger only if a condition is met at the end of request.
127
  * @param integer $type Alert type ID.
128
  * @param array $data Alert data.
129
  * @param callable $cond A future condition callback (receives an object of type WSAL_AlertManager as parameter).
130
  */
131
- public function TriggerIf($type, $data, $cond = null) {
 
132
  $username = wp_get_current_user()->user_login;
133
  $roles = $this->plugin->settings->GetCurrentUserRoles();
134
-
135
  if ($this->CheckEnableUserRoles($username, $roles)) {
136
  $this->_pipeline[] = array(
137
  'type' => $type,
@@ -140,7 +152,7 @@ final class WSAL_AlertManager {
140
  );
141
  }
142
  }
143
-
144
  /**
145
  * @internal Commit an alert now.
146
  */
@@ -163,16 +175,17 @@ final class WSAL_AlertManager {
163
  }
164
  }
165
  }
166
-
167
  /**
168
  * @internal Runs over triggered alerts in pipeline and passes them to loggers.
169
  */
170
- public function _CommitPipeline(){
 
171
  foreach ($this->_pipeline as $item) {
172
  $this->_CommitItem($item['type'], $item['data'], $item['cond']);
173
  }
174
  }
175
-
176
  /**
177
  * @param integer $type Alert type ID.
178
  * @return boolean True if at the end of request an alert of this type will be triggered.
@@ -186,16 +199,17 @@ final class WSAL_AlertManager {
186
  }
187
  return false;
188
  }
189
-
190
  /**
191
  * @param int $type Alert type ID.
192
  * @return boolean True if an alert has been or will be triggered in this request, false otherwise.
193
  */
194
- public function WillOrHasTriggered($type){
 
195
  return in_array($type, $this->_triggered_types)
196
  || $this->WillTrigger($type);
197
  }
198
-
199
  /**
200
  * Register an alert type.
201
  * @param array $info Array of [type, code, category, description, message] respectively.
@@ -216,7 +230,7 @@ final class WSAL_AlertManager {
216
  }
217
  }
218
  }
219
-
220
  /**
221
  * Register a whole group of items.
222
  * @param array $groups An array with group name as the index and an array of group items as the value.
@@ -233,38 +247,42 @@ final class WSAL_AlertManager {
233
  }
234
  }
235
  }
236
-
237
  /**
238
  * Returns whether alert of type $type is enabled or not.
239
  * @param integer $type Alert type.
240
  * @return boolean True if enabled, false otherwise.
241
  */
242
- public function IsEnabled($type){
 
243
  return !in_array($type, $this->GetDisabledAlerts());
244
  }
245
-
246
  /**
247
  * Disables a set of alerts by type.
248
  * @param int[] $types Alert type codes to be disabled.
249
  */
250
- public function SetDisabledAlerts($types){
 
251
  $this->plugin->settings->SetDisabledAlerts($types);
252
  }
253
-
254
  /**
255
  * @return int[] Returns an array of disabled alerts' type code.
256
  */
257
- public function GetDisabledAlerts(){
 
258
  return $this->plugin->settings->GetDisabledAlerts();
259
  }
260
-
261
  /**
262
  * @return WSAL_AbstractLogger[] Returns an array of loaded loggers.
263
  */
264
- public function GetLoggers(){
 
265
  return $this->_loggers;
266
  }
267
-
268
  /**
269
  * Converts an Alert into a Log entry (by invoking loggers).
270
  * You should not call this method directly.
@@ -302,24 +320,24 @@ final class WSAL_AlertManager {
302
  }
303
  }
304
  // Check if the user management plugin is loaded and adds the SessionID
305
- if (class_exists('WSAL_User_Management_Plugin')) {
306
- if (function_exists('get_current_user_id')) {
307
- $session_tokens = get_user_meta(get_current_user_id(), 'session_tokens', true);
308
- if (!empty($session_tokens)) {
309
- end($session_tokens);
310
- $data['SessionID'] = key($session_tokens);
311
  }
312
  }
313
  }
314
  //if(isset($_SERVER['REMOTE_HOST']) && $_SERVER['REMOTE_HOST'] != $data['ClientIP'])
315
  // $data['ClientHost'] = $_SERVER['REMOTE_HOST'];
316
  //$data['OtherIPs'] = $_SERVER['REMOTE_HOST'];
317
-
318
  foreach ($this->_loggers as $logger) {
319
  $logger->Log($type, $data);
320
  }
321
  }
322
-
323
  /**
324
  * Return alert given alert type.
325
  * @param integer $type Alert type.
@@ -335,15 +353,16 @@ final class WSAL_AlertManager {
335
  }
336
  return $default;
337
  }
338
-
339
  /**
340
  * Returns all supported alerts.
341
  * @return WSAL_Alert[]
342
  */
343
- public function GetAlerts(){
 
344
  return $this->_alerts;
345
  }
346
-
347
  /**
348
  * Returns all supported alerts.
349
  * @return array
@@ -373,7 +392,7 @@ final class WSAL_AlertManager {
373
  {
374
  return (in_array($user, $this->GetDisabledUsers())) ? true : false;
375
  }
376
-
377
  /**
378
  * @return Returns an array of disabled users.
379
  */
@@ -397,7 +416,7 @@ final class WSAL_AlertManager {
397
  }
398
  return $is_disabled;
399
  }
400
-
401
  /**
402
  * @return Returns an array of disabled users.
403
  */
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * WSAL_AlertManager class.
6
+ * It is the actual trigger for the alerts.
7
+ */
8
+ final class WSAL_AlertManager
9
+ {
10
  /**
11
  * @var WSAL_Alert[]
12
  */
13
  protected $_alerts = array();
14
+
15
  /**
16
  * @var WSAL_AbstractLogger[]
17
  */
18
  protected $_loggers = array();
19
+
20
  /**
21
  * @var WpSecurityAuditLog
22
  */
23
  protected $plugin;
24
 
25
+ /**
26
+ * Contains a list of alerts to trigger.
27
+ * @var array
28
+ */
29
+ protected $_pipeline = array();
30
+
31
+ /**
32
+ * Contains an array of alerts that have been triggered for this request.
33
+ * @var int[]
34
+ */
35
+ protected $_triggered_types = array();
36
+
37
  /**
38
  * Create new AlertManager instance.
39
  * @param WpSecurityAuditLog $plugin
40
  */
41
+ public function __construct(WpSecurityAuditLog $plugin)
42
+ {
43
  $this->plugin = $plugin;
44
  foreach (glob(dirname(__FILE__) . '/Loggers/*.php') as $file) {
45
  $this->AddFromFile($file);
46
  }
47
+
48
  add_action('shutdown', array($this, '_CommitPipeline'));
49
  }
50
 
52
  * Add new logger from file inside autoloader path.
53
  * @param string $file Path to file.
54
  */
55
+ public function AddFromFile($file)
56
+ {
57
  $this->AddFromClass($this->plugin->GetClassFileClassName($file));
58
  }
59
+
60
  /**
61
  * Add new logger given class name.
62
  * @param string $class Class name.
63
  */
64
+ public function AddFromClass($class)
65
+ {
66
  $this->AddInstance(new $class($this->plugin));
67
  }
68
+
69
  /**
70
  * Add newly created logger to list.
71
  * @param WSAL_AbstractLogger $logger The new logger.
72
  */
73
+ public function AddInstance(WSAL_AbstractLogger $logger)
74
+ {
75
  $this->_loggers[] = $logger;
76
  }
77
+
78
  /**
79
  * Remove logger by class name.
80
  * @param string $class The class name.
87
  }
88
  }
89
  }
90
+
 
 
 
 
 
 
 
 
 
 
 
 
91
  /**
92
  * Trigger an alert.
93
  * @param integer $type Alert type.
94
  * @param array $data Alert data.
95
  */
96
+ public function Trigger($type, $data = array(), $delayed = false)
97
+ {
98
  $username = wp_get_current_user()->user_login;
99
  if (empty($username) && !empty($data["Username"])) {
100
  $username = $data['Username'];
121
  * @param array roles
122
  * @return boolean True if enable false otherwise.
123
  */
124
+ public function CheckEnableUserRoles($user, $roles)
125
+ {
126
  $is_enable = true;
127
  if ($user != "" && $this->IsDisabledUser($user)) {
128
  $is_enable = false;
132
  }
133
  return $is_enable;
134
  }
135
+
136
  /**
137
  * Trigger only if a condition is met at the end of request.
138
  * @param integer $type Alert type ID.
139
  * @param array $data Alert data.
140
  * @param callable $cond A future condition callback (receives an object of type WSAL_AlertManager as parameter).
141
  */
142
+ public function TriggerIf($type, $data, $cond = null)
143
+ {
144
  $username = wp_get_current_user()->user_login;
145
  $roles = $this->plugin->settings->GetCurrentUserRoles();
146
+
147
  if ($this->CheckEnableUserRoles($username, $roles)) {
148
  $this->_pipeline[] = array(
149
  'type' => $type,
152
  );
153
  }
154
  }
155
+
156
  /**
157
  * @internal Commit an alert now.
158
  */
175
  }
176
  }
177
  }
178
+
179
  /**
180
  * @internal Runs over triggered alerts in pipeline and passes them to loggers.
181
  */
182
+ public function _CommitPipeline()
183
+ {
184
  foreach ($this->_pipeline as $item) {
185
  $this->_CommitItem($item['type'], $item['data'], $item['cond']);
186
  }
187
  }
188
+
189
  /**
190
  * @param integer $type Alert type ID.
191
  * @return boolean True if at the end of request an alert of this type will be triggered.
199
  }
200
  return false;
201
  }
202
+
203
  /**
204
  * @param int $type Alert type ID.
205
  * @return boolean True if an alert has been or will be triggered in this request, false otherwise.
206
  */
207
+ public function WillOrHasTriggered($type)
208
+ {
209
  return in_array($type, $this->_triggered_types)
210
  || $this->WillTrigger($type);
211
  }
212
+
213
  /**
214
  * Register an alert type.
215
  * @param array $info Array of [type, code, category, description, message] respectively.
230
  }
231
  }
232
  }
233
+
234
  /**
235
  * Register a whole group of items.
236
  * @param array $groups An array with group name as the index and an array of group items as the value.
247
  }
248
  }
249
  }
250
+
251
  /**
252
  * Returns whether alert of type $type is enabled or not.
253
  * @param integer $type Alert type.
254
  * @return boolean True if enabled, false otherwise.
255
  */
256
+ public function IsEnabled($type)
257
+ {
258
  return !in_array($type, $this->GetDisabledAlerts());
259
  }
260
+
261
  /**
262
  * Disables a set of alerts by type.
263
  * @param int[] $types Alert type codes to be disabled.
264
  */
265
+ public function SetDisabledAlerts($types)
266
+ {
267
  $this->plugin->settings->SetDisabledAlerts($types);
268
  }
269
+
270
  /**
271
  * @return int[] Returns an array of disabled alerts' type code.
272
  */
273
+ public function GetDisabledAlerts()
274
+ {
275
  return $this->plugin->settings->GetDisabledAlerts();
276
  }
277
+
278
  /**
279
  * @return WSAL_AbstractLogger[] Returns an array of loaded loggers.
280
  */
281
+ public function GetLoggers()
282
+ {
283
  return $this->_loggers;
284
  }
285
+
286
  /**
287
  * Converts an Alert into a Log entry (by invoking loggers).
288
  * You should not call this method directly.
320
  }
321
  }
322
  // Check if the user management plugin is loaded and adds the SessionID
323
+ if ( class_exists( 'WSAL_User_Management_Plugin' ) ) {
324
+ if ( function_exists( 'get_current_user_id' ) ) {
325
+ $session_tokens = get_user_meta( get_current_user_id(), 'session_tokens', true );
326
+ if ( ! empty( $session_tokens ) ) {
327
+ end( $session_tokens );
328
+ $data['SessionID'] = key( $session_tokens );
329
  }
330
  }
331
  }
332
  //if(isset($_SERVER['REMOTE_HOST']) && $_SERVER['REMOTE_HOST'] != $data['ClientIP'])
333
  // $data['ClientHost'] = $_SERVER['REMOTE_HOST'];
334
  //$data['OtherIPs'] = $_SERVER['REMOTE_HOST'];
335
+
336
  foreach ($this->_loggers as $logger) {
337
  $logger->Log($type, $data);
338
  }
339
  }
340
+
341
  /**
342
  * Return alert given alert type.
343
  * @param integer $type Alert type.
353
  }
354
  return $default;
355
  }
356
+
357
  /**
358
  * Returns all supported alerts.
359
  * @return WSAL_Alert[]
360
  */
361
+ public function GetAlerts()
362
+ {
363
  return $this->_alerts;
364
  }
365
+
366
  /**
367
  * Returns all supported alerts.
368
  * @return array
392
  {
393
  return (in_array($user, $this->GetDisabledUsers())) ? true : false;
394
  }
395
+
396
  /**
397
  * @return Returns an array of disabled users.
398
  */
416
  }
417
  return $is_disabled;
418
  }
419
+
420
  /**
421
  * @return Returns an array of disabled users.
422
  */
classes/AuditLogListView.php CHANGED
@@ -2,10 +2,14 @@
2
 
3
  require_once(ABSPATH . 'wp-admin/includes/admin.php');
4
  require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
5
-
 
 
 
 
 
6
  class WSAL_AuditLogListView extends WP_List_Table
7
  {
8
-
9
  /**
10
  * @var WpSecurityAuditLog
11
  */
@@ -84,8 +88,8 @@ class WSAL_AuditLogListView extends WP_List_Table
84
  // switch to live or archive DB
85
  if ($this->_plugin->settings->IsArchivingEnabled()) {
86
  $selected = 'live';
87
- $wp_session = WP_Session::get_instance();
88
- if (isset($wp_session['selected_db']) && $wp_session['selected_db'] == 'archive') {
89
  $selected = 'archive';
90
  }
91
  ?><div class="wsal-ssa wsal-db">
@@ -418,8 +422,8 @@ class WSAL_AuditLogListView extends WP_List_Table
418
  {
419
  if ($this->_plugin->settings->IsArchivingEnabled()) {
420
  // Switch to Archive DB
421
- $wp_session = WP_Session::get_instance();
422
- if (isset($wp_session['selected_db']) && $wp_session['selected_db'] == 'archive') {
423
  $this->_plugin->settings->SwitchToArchiveDB();
424
  }
425
  }
2
 
3
  require_once(ABSPATH . 'wp-admin/includes/admin.php');
4
  require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
5
+ /**
6
+ * @package Wsal
7
+ *
8
+ * This view is included in Audit Log Viewer Page.
9
+ * @see Views/AuditLog.php
10
+ */
11
  class WSAL_AuditLogListView extends WP_List_Table
12
  {
 
13
  /**
14
  * @var WpSecurityAuditLog
15
  */
88
  // switch to live or archive DB
89
  if ($this->_plugin->settings->IsArchivingEnabled()) {
90
  $selected = 'live';
91
+ $selected_db = get_transient('wsal_wp_selected_db');
92
+ if ($selected_db && $selected_db == 'archive') {
93
  $selected = 'archive';
94
  }
95
  ?><div class="wsal-ssa wsal-db">
422
  {
423
  if ($this->_plugin->settings->IsArchivingEnabled()) {
424
  // Switch to Archive DB
425
+ $selected_db = get_transient('wsal_wp_selected_db');
426
+ if ($selected_db && $selected_db == 'archive') {
427
  $this->_plugin->settings->SwitchToArchiveDB();
428
  }
429
  }
classes/Autoloader.php CHANGED
@@ -1,5 +1,9 @@
1
  <?php
2
-
 
 
 
 
3
  class WSAL_Autoloader {
4
  /**
5
  * @var WpSecurityAuditLog
@@ -8,16 +12,19 @@ class WSAL_Autoloader {
8
 
9
  protected $paths = array();
10
 
11
- public function __construct(WpSecurityAuditLog $plugin){
 
12
  $this->plugin = $plugin;
13
 
14
  // register autoloader
15
  spl_autoload_register(array($this, 'LoadClass'));
16
  }
17
 
18
- public function Register($prefix, $path){
19
- if(!isset($this->paths[$prefix]))
 
20
  $this->paths[$prefix] = array();
 
21
  $this->paths[$prefix][] = rtrim(str_replace('\\', '/', $path), '/') . '/';
22
  }
23
 
@@ -26,12 +33,13 @@ class WSAL_Autoloader {
26
  * @param string $class Class name.
27
  * @return boolean True if class is found and loaded, false otherwise.
28
  */
29
- public function LoadClass($class){
30
- foreach($this->paths as $prefix => $paths){
31
- foreach($paths as $path){
32
- if(strstr($class, $prefix) !== false){
 
33
  $file = $path . str_replace('_', DIRECTORY_SEPARATOR, substr($class, strlen($prefix))) . '.php';
34
- if(file_exists($file)){
35
  $s = $this->plugin->profiler->Start('Autoload ' . basename($file));
36
  require_once($file);
37
  $s->Stop();
@@ -40,7 +48,6 @@ class WSAL_Autoloader {
40
  }
41
  }
42
  }
43
-
44
  return false;
45
  }
46
 
@@ -49,12 +56,13 @@ class WSAL_Autoloader {
49
  * @param string $file File name.
50
  * @return string|false Class name or false on error.
51
  */
52
- public function GetClassFileClassName($file){
 
53
  $file = str_replace('\\', '/', $file); // win/dos hotfix
54
 
55
- foreach($this->paths as $prefix => $paths){
56
- foreach($paths as $path){
57
- if(strstr($file, $path) !== false){
58
  return str_replace(
59
  array($path, '/'),
60
  array($prefix, '_'),
@@ -63,7 +71,6 @@ class WSAL_Autoloader {
63
  }
64
  }
65
  }
66
-
67
  return false;
68
  }
69
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Classes Auto Loader.
6
+ */
7
  class WSAL_Autoloader {
8
  /**
9
  * @var WpSecurityAuditLog
12
 
13
  protected $paths = array();
14
 
15
+ public function __construct(WpSecurityAuditLog $plugin)
16
+ {
17
  $this->plugin = $plugin;
18
 
19
  // register autoloader
20
  spl_autoload_register(array($this, 'LoadClass'));
21
  }
22
 
23
+ public function Register($prefix, $path)
24
+ {
25
+ if (!isset($this->paths[$prefix])) {
26
  $this->paths[$prefix] = array();
27
+ }
28
  $this->paths[$prefix][] = rtrim(str_replace('\\', '/', $path), '/') . '/';
29
  }
30
 
33
  * @param string $class Class name.
34
  * @return boolean True if class is found and loaded, false otherwise.
35
  */
36
+ public function LoadClass($class)
37
+ {
38
+ foreach ($this->paths as $prefix => $paths) {
39
+ foreach ($paths as $path) {
40
+ if (strstr($class, $prefix) !== false) {
41
  $file = $path . str_replace('_', DIRECTORY_SEPARATOR, substr($class, strlen($prefix))) . '.php';
42
+ if (file_exists($file)) {
43
  $s = $this->plugin->profiler->Start('Autoload ' . basename($file));
44
  require_once($file);
45
  $s->Stop();
48
  }
49
  }
50
  }
 
51
  return false;
52
  }
53
 
56
  * @param string $file File name.
57
  * @return string|false Class name or false on error.
58
  */
59
+ public function GetClassFileClassName($file)
60
+ {
61
  $file = str_replace('\\', '/', $file); // win/dos hotfix
62
 
63
+ foreach ($this->paths as $prefix => $paths) {
64
+ foreach ($paths as $path) {
65
+ if (strstr($file, $path) !== false) {
66
  return str_replace(
67
  array($path, '/'),
68
  array($prefix, '_'),
71
  }
72
  }
73
  }
 
74
  return false;
75
  }
76
  }
classes/Connector/AbstractConnector.php CHANGED
@@ -1,7 +1,12 @@
1
  <?php
2
  //require_once('ConnectorInterface.php');
3
  require_once('wp-db-custom.php');
4
-
 
 
 
 
 
5
  abstract class WSAL_Connector_AbstractConnector
6
  {
7
  protected $connection = null;
1
  <?php
2
  //require_once('ConnectorInterface.php');
3
  require_once('wp-db-custom.php');
4
+ /**
5
+ * @package Wsal
6
+ * Adapter Classes loader class.
7
+ *
8
+ * Abstract class used as a class loader.
9
+ */
10
  abstract class WSAL_Connector_AbstractConnector
11
  {
12
  protected $connection = null;
classes/Connector/ConnectorFactory.php CHANGED
@@ -1,7 +1,11 @@
1
  <?php
2
- //require_once(__DIR__ . DIRECTORY_SEPARATOR .'..'. DIRECTORY_SEPARATOR .'Settings.php');
3
- //require_once('MySQLDBConnector.php');
4
-
 
 
 
 
5
  abstract class WSAL_Connector_ConnectorFactory
6
  {
7
  public static $connector;
@@ -41,6 +45,10 @@ abstract class WSAL_Connector_ConnectorFactory
41
  return self::$connector;
42
  }
43
 
 
 
 
 
44
  public static function GetConfig()
45
  {
46
  $conf = new WSAL_Settings(WpSecurityAuditLog::GetInstance());
@@ -59,6 +67,16 @@ abstract class WSAL_Connector_ConnectorFactory
59
  }
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
62
  public static function CheckConfig($type, $user, $password, $name, $hostname, $base_prefix)
63
  {
64
  $result = false;
@@ -73,6 +91,16 @@ abstract class WSAL_Connector_ConnectorFactory
73
  return $result;
74
  }
75
 
 
 
 
 
 
 
 
 
 
 
76
  public static function GetConfigArray($type, $user, $password, $name, $hostname, $base_prefix)
77
  {
78
  return array(
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * Class WSAL_Connector_ConnectorFactory.
5
+ *
6
+ * Abstract class used for create the connector, only MySQL is implemented.
7
+ * @todo add other adapters.
8
+ */
9
  abstract class WSAL_Connector_ConnectorFactory
10
  {
11
  public static $connector;
45
  return self::$connector;
46
  }
47
 
48
+ /**
49
+ * Get the adapter config stored in the DB
50
+ * @return array|null adapter config
51
+ */
52
  public static function GetConfig()
53
  {
54
  $conf = new WSAL_Settings(WpSecurityAuditLog::GetInstance());
67
  }
68
  }
69
 
70
+ /**
71
+ * Check the adapter config with a test connection.
72
+ * @param string $type adapter type
73
+ * @param string $user adapter user
74
+ * @param string $password adapter password
75
+ * @param string $name adapter name
76
+ * @param string $hostname adapter hostname
77
+ * @param string $base_prefix adapter base_prefix
78
+ * @return boolean true|false
79
+ */
80
  public static function CheckConfig($type, $user, $password, $name, $hostname, $base_prefix)
81
  {
82
  $result = false;
91
  return $result;
92
  }
93
 
94
+ /**
95
+ * Create array config.
96
+ * @param string $type adapter type
97
+ * @param string $user adapter user
98
+ * @param string $password adapter password
99
+ * @param string $name adapter name
100
+ * @param string $hostname adapter hostname
101
+ * @param string $base_prefix adapter base_prefix
102
+ * @return array config
103
+ */
104
  public static function GetConfigArray($type, $user, $password, $name, $hostname, $base_prefix)
105
  {
106
  return array(
classes/Connector/ConnectorInterface.php CHANGED
@@ -1,5 +1,9 @@
1
  <?php
2
-
 
 
 
 
3
  interface WSAL_Connector_ConnectorInterface
4
  {
5
  public function getAdapter($class_name);
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Interface used by the WSAL_Connector.
6
+ */
7
  interface WSAL_Connector_ConnectorInterface
8
  {
9
  public function getAdapter($class_name);
classes/Connector/MySQLDB.php CHANGED
@@ -1,9 +1,19 @@
1
  <?php
2
-
 
 
 
 
3
  class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements WSAL_Connector_ConnectorInterface
4
  {
5
  protected $connectionConfig = null;
6
-
 
 
 
 
 
 
7
  public function __construct($connectionConfig = null)
8
  {
9
  $this->connectionConfig = $connectionConfig;
@@ -11,6 +21,10 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
11
  require_once($this->getAdaptersDirectory() . '/OptionAdapter.php');
12
  }
13
 
 
 
 
 
14
  public function TestConnection()
15
  {
16
  error_reporting(E_ALL ^ (E_NOTICE | E_WARNING | E_DEPRECATED));
@@ -43,6 +57,7 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
43
 
44
  /**
45
  * Returns a wpdb instance
 
46
  */
47
  public function getConnection()
48
  {
@@ -65,7 +80,8 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
65
  }
66
 
67
  /**
68
- * Gets an adapter for the specified model
 
69
  */
70
  public function getAdapter($class_name)
71
  {
@@ -80,6 +96,7 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
80
 
81
  /**
82
  * Checks if the necessary tables are available
 
83
  */
84
  public function isInstalled()
85
  {
@@ -90,6 +107,7 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
90
 
91
  /**
92
  * Checks if old version tables are available
 
93
  */
94
  public function canMigrate()
95
  {
@@ -109,22 +127,23 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
109
  $filePath = explode(DIRECTORY_SEPARATOR, $file);
110
  $fileName = $filePath[count($filePath) - 1];
111
  $className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
112
-
113
  $class = new $className($this->getConnection());
114
  if ($excludeOptions && $class instanceof WSAL_Adapters_MySQL_Option) {
115
  continue;
116
  }
 
117
  // exclude the tmp_users table
118
  if (!$excludeOptions && $class instanceof WSAL_Adapters_MySQL_TmpUser) {
119
  continue;
120
  }
121
-
122
  if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
123
  $class->Install();
124
  }
125
  }
126
  }
127
-
128
  /**
129
  * Uninstall all DB tables.
130
  */
@@ -144,6 +163,10 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
144
  }
145
  }
146
 
 
 
 
 
147
  private function GetIncreaseOccurrence()
148
  {
149
  $_wpdb = $this->getConnection();
@@ -152,6 +175,11 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
152
  return (int)$_wpdb->get_var($sql);
153
  }
154
 
 
 
 
 
 
155
  public function MigrateMeta($index, $limit)
156
  {
157
  $result = null;
@@ -192,6 +220,11 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
192
  return $result;
193
  }
194
 
 
 
 
 
 
195
  public function MigrateOccurrence($index, $limit)
196
  {
197
  $result = null;
@@ -229,6 +262,11 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
229
  return $result;
230
  }
231
 
 
 
 
 
 
232
  public function MigrateBackOccurrence($index, $limit)
233
  {
234
  $result = null;
@@ -265,13 +303,18 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
265
  return $result;
266
  }
267
 
 
 
 
 
 
268
  public function MigrateBackMeta($index, $limit)
269
  {
270
  $result = null;
271
  $offset = ($index * $limit);
272
  global $wpdb;
273
  $_wpdb = $this->getConnection();
274
-
275
  // Load data Meta from External DB
276
  $meta = new WSAL_Adapters_MySQL_Meta($_wpdb);
277
  if (!$meta->IsInstalled()) {
@@ -284,7 +327,7 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
284
  // Insert data to WP
285
  if (!empty($metadata)) {
286
  $metaWP = new WSAL_Adapters_MySQL_Meta($wpdb);
287
-
288
  $index++;
289
  $sql = 'INSERT INTO ' . $metaWP->GetWPTable() . ' (occurrence_id, name, value) VALUES ' ;
290
  foreach ($metadata as $entry) {
@@ -301,6 +344,10 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
301
  return $result;
302
  }
303
 
 
 
 
 
304
  private function DeleteAfterMigrate($record)
305
  {
306
  global $wpdb;
@@ -308,31 +355,122 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
308
  $wpdb->query($sql);
309
  }
310
 
311
- public function encryptString($plaintext)
312
- {
313
- $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
314
- $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
315
- $key = $this->truncateKey();
316
- $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  $ciphertext = $iv . $ciphertext;
318
- $ciphertext_base64 = base64_encode($ciphertext);
319
-
320
  return $ciphertext_base64;
 
321
  }
322
-
323
- public function decryptString($ciphertext_base64)
324
- {
325
- $ciphertext_dec = base64_decode($ciphertext_base64);
326
- $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
327
-
328
- $iv_dec = substr($ciphertext_dec, 0, $iv_size);
329
- $ciphertext_dec = substr($ciphertext_dec, $iv_size);
330
- $key = $this->truncateKey();
331
- $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
332
-
333
- return rtrim($plaintext_dec, "\0");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  public function MirroringAlertsToDB($args)
337
  {
338
  $last_created_on = null;
@@ -388,6 +526,11 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
388
  return $last_created_on;
389
  }
390
 
 
 
 
 
 
391
  public function ArchiveOccurrence($args)
392
  {
393
  $_wpdb = $this->getConnection();
@@ -403,8 +546,8 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
403
  }
404
 
405
  if (!empty($args['by_limit'])) {
406
- $sql = 'SELECT occ.* FROM ' . $occurrence->GetTable() . ' occ
407
- LEFT JOIN (SELECT id FROM ' . $occurrence->GetTable() . ' order by created_on DESC limit ' . $args['by_limit'] . ') as ids
408
  on ids.id = occ.id
409
  WHERE ids.id IS NULL';
410
  }
@@ -438,6 +581,11 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
438
  }
439
  }
440
 
 
 
 
 
 
441
  public function ArchiveMeta($args)
442
  {
443
  $_wpdb = $this->getConnection();
@@ -468,13 +616,17 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
468
  }
469
  }
470
 
 
 
 
 
471
  public function DeleteAfterArchive($args)
472
  {
473
  $_wpdb = $this->getConnection();
474
  $archive_db = $args['archive_db'];
475
 
476
  $sOccurenceIds = implode(", ", $args["occurence_ids"]);
477
-
478
  $occurrence = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
479
  $sql = 'DELETE FROM ' . $occurrence->GetTable() . ' WHERE id IN (' . $sOccurenceIds . ')';
480
  $_wpdb->query($sql);
@@ -484,6 +636,11 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
484
  $_wpdb->query($sql);
485
  }
486
 
 
 
 
 
 
487
  private function truncateKey()
488
  {
489
  if (!defined('AUTH_KEY')) {
@@ -496,4 +653,21 @@ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements
496
  return AUTH_KEY;
497
  }
498
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * MySQL Connector Class
5
+ * It uses wpdb WordPress DB Class
6
+ */
7
  class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements WSAL_Connector_ConnectorInterface
8
  {
9
  protected $connectionConfig = null;
10
+
11
+ /**
12
+ * @param string $dbuser MySQL database user
13
+ * @param string $dbpassword MySQL database password
14
+ * @param string $dbname MySQL database name
15
+ * @param string $dbhost MySQL database host
16
+ */
17
  public function __construct($connectionConfig = null)
18
  {
19
  $this->connectionConfig = $connectionConfig;
21
  require_once($this->getAdaptersDirectory() . '/OptionAdapter.php');
22
  }
23
 
24
+ /**
25
+ * Test the connection.
26
+ * @throws Exception Connection failed
27
+ */
28
  public function TestConnection()
29
  {
30
  error_reporting(E_ALL ^ (E_NOTICE | E_WARNING | E_DEPRECATED));
57
 
58
  /**
59
  * Returns a wpdb instance
60
+ * @return wpdb
61
  */
62
  public function getConnection()
63
  {
80
  }
81
 
82
  /**
83
+ * Gets an adapter for the specified model.
84
+ * @return WSAL_Adapters_MySQL_{class_name}
85
  */
86
  public function getAdapter($class_name)
87
  {
96
 
97
  /**
98
  * Checks if the necessary tables are available
99
+ * @return bool true|false
100
  */
101
  public function isInstalled()
102
  {
107
 
108
  /**
109
  * Checks if old version tables are available
110
+ * @return bool true|false
111
  */
112
  public function canMigrate()
113
  {
127
  $filePath = explode(DIRECTORY_SEPARATOR, $file);
128
  $fileName = $filePath[count($filePath) - 1];
129
  $className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
130
+
131
  $class = new $className($this->getConnection());
132
  if ($excludeOptions && $class instanceof WSAL_Adapters_MySQL_Option) {
133
  continue;
134
  }
135
+
136
  // exclude the tmp_users table
137
  if (!$excludeOptions && $class instanceof WSAL_Adapters_MySQL_TmpUser) {
138
  continue;
139
  }
140
+
141
  if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
142
  $class->Install();
143
  }
144
  }
145
  }
146
+
147
  /**
148
  * Uninstall all DB tables.
149
  */
163
  }
164
  }
165
 
166
+ /**
167
+ * Increase occurrence ID
168
+ * @return integer MAX(id)
169
+ */
170
  private function GetIncreaseOccurrence()
171
  {
172
  $_wpdb = $this->getConnection();
175
  return (int)$_wpdb->get_var($sql);
176
  }
177
 
178
+ /**
179
+ * Migrate Metadata from WP DB to External DB.
180
+ * @param integer $index
181
+ * @param integer $limit limit
182
+ */
183
  public function MigrateMeta($index, $limit)
184
  {
185
  $result = null;
220
  return $result;
221
  }
222
 
223
+ /**
224
+ * Migrate Occurrences from WP DB to External DB.
225
+ * @param integer $index
226
+ * @param integer $limit limit
227
+ */
228
  public function MigrateOccurrence($index, $limit)
229
  {
230
  $result = null;
262
  return $result;
263
  }
264
 
265
+ /**
266
+ * Migrate Back Occurrences from External DB to WP DB.
267
+ * @param integer $index
268
+ * @param integer $limit limit
269
+ */
270
  public function MigrateBackOccurrence($index, $limit)
271
  {
272
  $result = null;
303
  return $result;
304
  }
305
 
306
+ /**
307
+ * Migrate Back Metadata from External DB to WP DB.
308
+ * @param integer $index
309
+ * @param integer $limit limit
310
+ */
311
  public function MigrateBackMeta($index, $limit)
312
  {
313
  $result = null;
314
  $offset = ($index * $limit);
315
  global $wpdb;
316
  $_wpdb = $this->getConnection();
317
+
318
  // Load data Meta from External DB
319
  $meta = new WSAL_Adapters_MySQL_Meta($_wpdb);
320
  if (!$meta->IsInstalled()) {
327
  // Insert data to WP
328
  if (!empty($metadata)) {
329
  $metaWP = new WSAL_Adapters_MySQL_Meta($wpdb);
330
+
331
  $index++;
332
  $sql = 'INSERT INTO ' . $metaWP->GetWPTable() . ' (occurrence_id, name, value) VALUES ' ;
333
  foreach ($metadata as $entry) {
344
  return $result;
345
  }
346
 
347
+ /**
348
+ * Delete after Migrate alerts.
349
+ * @param object $record type of record
350
+ */
351
  private function DeleteAfterMigrate($record)
352
  {
353
  global $wpdb;
355
  $wpdb->query($sql);
356
  }
357
 
358
+ /**
359
+ * Encrypt plain text.
360
+ * Encrypt string, before saves it to the DB.
361
+ *
362
+ * @param string $plaintext - Plain text that is going to be encrypted.
363
+ * @return string
364
+ * @since 2.6.3
365
+ */
366
+ public function encryptString( $plaintext ) {
367
+
368
+ // Check for previous version.
369
+ $plugin = WpSecurityAuditLog::GetInstance();
370
+ $version = $plugin->GetGlobalOption( 'version', '0.0.0' );
371
+
372
+ if ( -1 === version_compare( $version, '2.6.2' ) ) {
373
+ return $this->encryptString_fallback( $plaintext );
374
+ }
375
+
376
+ $ciphertext = false;
377
+
378
+ $encrypt_method = 'AES-256-CBC';
379
+ $secret_key = $this->truncateKey();
380
+ $secret_iv = $this->get_openssl_iv();
381
+
382
+ // Hash the key.
383
+ $key = hash( 'sha256', $secret_key );
384
+
385
+ // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning.
386
+ $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
387
+
388
+ $ciphertext = openssl_encrypt( $plaintext, $encrypt_method, $key, 0, $iv );
389
+ $ciphertext = base64_encode( $ciphertext );
390
+
391
+ return $ciphertext;
392
+
393
+ }
394
+
395
+ /**
396
+ * Encrypt plain text - Fallback.
397
+ *
398
+ * @param string $plaintext - Plain text that is going to be encrypted.
399
+ * @return string
400
+ * @since 2.6.3
401
+ */
402
+ public function encryptString_fallback( $plaintext ) {
403
+
404
+ $iv_size = mcrypt_get_iv_size( MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC );
405
+ $iv = mcrypt_create_iv( $iv_size, MCRYPT_RAND );
406
+ $key = $this->truncateKey();
407
+ $ciphertext = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv );
408
  $ciphertext = $iv . $ciphertext;
409
+ $ciphertext_base64 = base64_encode( $ciphertext );
 
410
  return $ciphertext_base64;
411
+
412
  }
413
+
414
+ /**
415
+ * Decrypt the encrypted string.
416
+ * Decrypt string, after reads it from the DB.
417
+ *
418
+ * @param string $ciphertext_base64 - encrypted string.
419
+ * @return string
420
+ * @since 2.6.3
421
+ */
422
+ public function decryptString( $ciphertext_base64 ) {
423
+
424
+ // Check for previous version.
425
+ $plugin = WpSecurityAuditLog::GetInstance();
426
+ $version = $plugin->GetGlobalOption( 'version', '0.0.0' );
427
+
428
+ if ( -1 === version_compare( $version, '2.6.2' ) ) {
429
+ return $this->decryptString_fallback( $ciphertext_base64 );
430
+ }
431
+
432
+ $plaintext = false;
433
+
434
+ $encrypt_method = 'AES-256-CBC';
435
+ $secret_key = $this->truncateKey();
436
+ $secret_iv = $this->get_openssl_iv();
437
+
438
+ // Hash the key.
439
+ $key = hash( 'sha256', $secret_key );
440
+
441
+ // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning.
442
+ $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
443
+
444
+ $plaintext = openssl_decrypt( base64_decode( $ciphertext_base64 ), $encrypt_method, $key, 0, $iv );
445
+
446
+ return $plaintext;
447
+
448
  }
449
 
450
+ /**
451
+ * Decrypt the encrypted string - Fallback.
452
+ *
453
+ * @param string $ciphertext_base64 - encrypted string.
454
+ * @return string
455
+ * @since 2.6.3
456
+ */
457
+ public function decryptString_fallback( $ciphertext_base64 ) {
458
+
459
+ $ciphertext_dec = base64_decode( $ciphertext_base64 );
460
+ $iv_size = mcrypt_get_iv_size( MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC );
461
+ $iv_dec = substr( $ciphertext_dec, 0, $iv_size );
462
+ $ciphertext_dec = substr( $ciphertext_dec, $iv_size );
463
+ $key = $this->truncateKey();
464
+ $plaintext_dec = mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec );
465
+ return rtrim( $plaintext_dec, "\0" );
466
+
467
+ }
468
+
469
+ /**
470
+ * Mirroring Occurrences and Metadata Tables.
471
+ * Read from current DB and copy into Mirroring DB.
472
+ * @param array $args archive Database and limit by date
473
+ */
474
  public function MirroringAlertsToDB($args)
475
  {
476
  $last_created_on = null;
526
  return $last_created_on;
527
  }
528
 
529
+ /**
530
+ * Archiving Occurrences Table.
531
+ * Read from current DB and copy into Archive DB.
532
+ * @param array $args archive Database and limit by count OR by date
533
+ */
534
  public function ArchiveOccurrence($args)
535
  {
536
  $_wpdb = $this->getConnection();
546
  }
547
 
548
  if (!empty($args['by_limit'])) {
549
+ $sql = 'SELECT occ.* FROM ' . $occurrence->GetTable() . ' occ
550
+ LEFT JOIN (SELECT id FROM ' . $occurrence->GetTable() . ' order by created_on DESC limit ' . $args['by_limit'] . ') as ids
551
  on ids.id = occ.id
552
  WHERE ids.id IS NULL';
553
  }
581
  }
582
  }
583
 
584
+ /**
585
+ * Archiving Metadata Table.
586
+ * Read from current DB and copy into Archive DB.
587
+ * @param array $args archive Database and occurrences IDs
588
+ */
589
  public function ArchiveMeta($args)
590
  {
591
  $_wpdb = $this->getConnection();
616
  }
617
  }
618
 
619
+ /**
620
+ * Delete Occurrences and Metadata after archiving.
621
+ * @param array $args archive Database and occurrences IDs
622
+ */
623
  public function DeleteAfterArchive($args)
624
  {
625
  $_wpdb = $this->getConnection();
626
  $archive_db = $args['archive_db'];
627
 
628
  $sOccurenceIds = implode(", ", $args["occurence_ids"]);
629
+
630
  $occurrence = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
631
  $sql = 'DELETE FROM ' . $occurrence->GetTable() . ' WHERE id IN (' . $sOccurenceIds . ')';
632
  $_wpdb->query($sql);
636
  $_wpdb->query($sql);
637
  }
638
 
639
+ /**
640
+ * Truncate string longer than 32 characters.
641
+ * Authentication Unique Key @see wp-config.php
642
+ * @return string AUTH_KEY
643
+ */
644
  private function truncateKey()
645
  {
646
  if (!defined('AUTH_KEY')) {
653
  return AUTH_KEY;
654
  }
655
  }
656
+
657
+ /**
658
+ * Get OpenSSL IV for DB.
659
+ *
660
+ * @since 2.6.3
661
+ */
662
+ private function get_openssl_iv() {
663
+
664
+ $secret_openssl_iv = 'і-(аэ┤#≥и┴зейН';
665
+ $key_size = strlen( $secret_openssl_iv );
666
+ if ( $key_size > 32 ) {
667
+ return substr( $secret_openssl_iv, 0, 32 );
668
+ } else {
669
+ return $secret_openssl_iv;
670
+ }
671
+
672
+ }
673
  }
classes/Connector/wp-db-custom.php CHANGED
@@ -1,10 +1,19 @@
1
  <?php
2
-
 
 
 
 
3
  class wpdbCustom extends wpdb
4
  {
5
- /*
6
- * overwrite wpdb class for set $allow_bail to false
7
  * and hide the print of the error
 
 
 
 
 
8
  */
9
  public function __construct($dbuser, $dbpassword, $dbname, $dbhost)
10
  {
@@ -32,5 +41,4 @@ class wpdbCustom extends wpdb
32
 
33
  $this->db_connect(false);
34
  }
35
-
36
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * Test the DB connection.
5
+ * It uses wpdb WordPress DB Class.
6
+ */
7
  class wpdbCustom extends wpdb
8
  {
9
+ /**
10
+ * Overwrite wpdb class for set $allow_bail to false
11
  * and hide the print of the error
12
+ * @global string $wp_version
13
+ * @param string $dbuser MySQL database user
14
+ * @param string $dbpassword MySQL database password
15
+ * @param string $dbname MySQL database name
16
+ * @param string $dbhost MySQL database host
17
  */
18
  public function __construct($dbuser, $dbpassword, $dbname, $dbhost)
19
  {
41
 
42
  $this->db_connect(false);
43
  }
 
44
  }
classes/ConstantManager.php CHANGED
@@ -1,89 +1,96 @@
1
  <?php
2
-
3
- class WSAL_ConstantManager {
4
-
5
- protected $_constants = array();
6
-
7
- /**
8
- * Use an existing PHP constant.
9
- * @param string $name Constant name.
10
- * @param string $description Constant description.
11
- */
12
- public function UseConstant($name, $description = ''){
13
- $this->_constants[] = (object)array(
14
- 'name' => $name,
15
- 'value' => constant($name),
16
- 'description' => $description,
17
- );
18
- }
19
-
20
- /**
21
- * Add new PHP constant.
22
- * @param string $name Constant name.
23
- * @param integer|string $value Constant value.
24
- * @param string $description Constant description.
25
- */
26
- public function AddConstant($name, $value, $description = ''){
27
-
28
- // check for constant conflict and define new one if required
29
- if(defined($name) && constant($name) !== $value){
30
- throw new Exception('Constant already defined with a different value.');
31
- }else{
32
- define($name, $value);
33
- }
34
-
35
- // add constant to da list.
36
- $this->UseConstant($name, $description);
37
-
38
- }
39
-
40
- /**
41
- * Add multiple constants in one go.
42
- * @param array $items Array of arrays with name, value, description pairs.
43
- */
44
- public function AddConstants($items){
45
- foreach($items as $item)
46
- $this->AddConstant(
47
- $item['name'],
48
- $item['value'],
49
- $item['description']
50
- );
51
- }
52
-
53
- /**
54
- * Use multiple constants in one go.
55
- * @param array $items Array of arrays with name, description pairs.
56
- */
57
- public function UseConstants($items){
58
- foreach($items as $item)
59
- $this->UseConstant(
60
- $item['name'],
61
- $item['description']
62
- );
63
- }
64
-
65
- /**
66
- * Get constant details by a particular detail.
67
- * @param string $what The type of detail: 'name', 'value'
68
- * @param mixed $value The detail expected value.
69
- * @return mixed Either constant details (props: name, value, description) or $default if not found.
70
- */
71
- public function GetConstantBy($what, $value, $default = null){
72
-
73
- // make sure we do have some constants...
74
- if(count($this->_constants)){
75
-
76
- // make sure that constants do have a $what property
77
- if(!isset($this->_constants[0]->$what))
78
- throw new Exception('Unexpected detail type "' . $what . '".');
79
-
80
- // return constant match the property value
81
- foreach($this->_constants as $constant)
82
- if($constant->$what == $value)
83
- return $constant;
84
-
85
- }
86
-
87
- return $default;
88
- }
89
- }
 
 
 
 
 
 
 
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Class used for Constants,
6
+ * E_NOTICE, E_WARNING, E_CRITICAL, etc.
7
+ */
8
+ class WSAL_ConstantManager
9
+ {
10
+ protected $_constants = array();
11
+
12
+ /**
13
+ * Use an existing PHP constant.
14
+ * @param string $name Constant name.
15
+ * @param string $description Constant description.
16
+ */
17
+ public function UseConstant($name, $description = '')
18
+ {
19
+ $this->_constants[] = (object)array(
20
+ 'name' => $name,
21
+ 'value' => constant($name),
22
+ 'description' => $description,
23
+ );
24
+ }
25
+
26
+ /**
27
+ * Add new PHP constant.
28
+ * @param string $name Constant name.
29
+ * @param integer|string $value Constant value.
30
+ * @param string $description Constant description.
31
+ */
32
+ public function AddConstant($name, $value, $description = '')
33
+ {
34
+ // check for constant conflict and define new one if required
35
+ if (defined($name) && constant($name) !== $value) {
36
+ throw new Exception('Constant already defined with a different value.');
37
+ } else {
38
+ define($name, $value);
39
+ }
40
+ // add constant to da list.
41
+ $this->UseConstant($name, $description);
42
+ }
43
+
44
+ /**
45
+ * Add multiple constants in one go.
46
+ * @param array $items Array of arrays with name, value, description pairs.
47
+ */
48
+ public function AddConstants($items)
49
+ {
50
+ foreach ($items as $item) {
51
+ $this->AddConstant(
52
+ $item['name'],
53
+ $item['value'],
54
+ $item['description']
55
+ );
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Use multiple constants in one go.
61
+ * @param array $items Array of arrays with name, description pairs.
62
+ */
63
+ public function UseConstants($items)
64
+ {
65
+ foreach ($items as $item) {
66
+ $this->UseConstant(
67
+ $item['name'],
68
+ $item['description']
69
+ );
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Get constant details by a particular detail.
75
+ * @param string $what The type of detail: 'name', 'value'
76
+ * @param mixed $value The detail expected value.
77
+ * @return mixed Either constant details (props: name, value, description) or $default if not found.
78
+ */
79
+ public function GetConstantBy($what, $value, $default = null)
80
+ {
81
+ // make sure we do have some constants...
82
+ if (count($this->_constants)) {
83
+ // make sure that constants do have a $what property
84
+ if (!isset($this->_constants[0]->$what)) {
85
+ throw new Exception('Unexpected detail type "' . $what . '".');
86
+ }
87
+ // return constant match the property value
88
+ foreach ($this->_constants as $constant) {
89
+ if ($constant->$what == $value) {
90
+ return $constant;
91
+ }
92
+ }
93
+ }
94
+ return $default;
95
+ }
96
+ }
classes/EDD_SL_Plugin_Updater.php CHANGED
@@ -1,15 +1,16 @@
1
  <?php
2
-
3
  // uncomment this line for testing
4
  //set_site_transient( 'update_plugins', null );
5
 
6
  /**
 
7
  * Allows plugins to use their own update API.
8
  *
9
  * @author Pippin Williamson
10
  * @version 1.2
11
  */
12
- class EDD_SL_Plugin_Updater {
 
13
  private $api_url = '';
14
  private $api_data = array();
15
  private $name = '';
@@ -27,11 +28,12 @@ class EDD_SL_Plugin_Updater {
27
  * @param array $_api_data Optional data to send with API calls.
28
  * @return void
29
  */
30
- function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
31
- $this->api_url = trailingslashit( $_api_url );
32
- $this->api_data = urlencode_deep( $_api_data );
33
- $this->name = plugin_basename( $_plugin_file );
34
- $this->slug = basename( $_plugin_file, '.php');
 
35
  $this->version = $_api_data['version'];
36
 
37
  // Set up hooks.
@@ -42,13 +44,13 @@ class EDD_SL_Plugin_Updater {
42
  * Set up WordPress filters to hook into WP's update process.
43
  *
44
  * @uses add_filter()
45
- *
46
  * @return void
47
  */
48
- private function hook() {
49
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins_filter' ) );
50
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
51
- add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
 
52
  }
53
 
54
  /**
@@ -64,30 +66,25 @@ class EDD_SL_Plugin_Updater {
64
  * @param array $_transient_data Update array build by WordPress.
65
  * @return array Modified update array with custom plugin data.
66
  */
67
- function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
68
-
69
- if( empty( $_transient_data ) || ! $this->do_check ) {
70
-
71
  // This ensures that the custom API request only runs on the second time that WP fires the update check
72
  $this->do_check = true;
73
-
74
  return $_transient_data;
75
  }
76
 
77
- $to_send = array( 'slug' => $this->slug );
 
78
 
79
- $api_response = $this->api_request( 'plugin_latest_version', $to_send );
80
-
81
- if( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
82
-
83
- if( version_compare( $this->version, $api_response->new_version, '<' ) ) {
84
  $_transient_data->response[$this->name] = $api_response;
85
  }
86
  }
87
  return $_transient_data;
88
  }
89
 
90
-
91
  /**
92
  * Updates information on the "View version x.x details" page with custom data.
93
  *
@@ -98,18 +95,21 @@ class EDD_SL_Plugin_Updater {
98
  * @param object $_args
99
  * @return object $_data
100
  */
101
- function plugins_api_filter( $_data, $_action = '', $_args = null ) {
102
- if ( ( $_action != 'plugin_information' ) || !isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) return $_data;
103
-
104
- $to_send = array( 'slug' => $this->slug );
 
 
105
 
106
- $api_response = $this->api_request( 'plugin_information', $to_send );
107
- if ( false !== $api_response ) $_data = $api_response;
 
 
108
 
109
  return $_data;
110
  }
111
 
112
-
113
  /**
114
  * Disable SSL verification in order to prevent download update failures
115
  *
@@ -117,9 +117,10 @@ class EDD_SL_Plugin_Updater {
117
  * @param string $url
118
  * @return object $array
119
  */
120
- function http_request_args( $args, $url ) {
 
121
  // If it is an https request and we are performing a package download, disable ssl verification
122
- if( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
123
  $args['sslverify'] = false;
124
  }
125
  return $args;
@@ -136,17 +137,18 @@ class EDD_SL_Plugin_Updater {
136
  * @param array $_data Parameters for the API action.
137
  * @return false||object
138
  */
139
- private function api_request( $_action, $_data ) {
140
-
141
  global $wp_version;
 
142
 
143
- $data = array_merge( $this->api_data, $_data );
144
-
145
- if( $data['slug'] != $this->slug )
146
  return;
 
147
 
148
- if( empty( $data['license'] ) )
149
  return;
 
150
 
151
  $api_params = array(
152
  'edd_action' => 'get_version',
@@ -156,15 +158,16 @@ class EDD_SL_Plugin_Updater {
156
  'author' => $data['author'],
157
  'url' => home_url()
158
  );
159
- $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
160
 
161
- if ( ! is_wp_error( $request ) ):
162
- $request = json_decode( wp_remote_retrieve_body( $request ) );
163
- if( $request && isset( $request->sections ) )
164
- $request->sections = maybe_unserialize( $request->sections );
 
165
  return $request;
166
- else:
167
  return false;
168
- endif;
169
  }
170
  }
1
  <?php
 
2
  // uncomment this line for testing
3
  //set_site_transient( 'update_plugins', null );
4
 
5
  /**
6
+ * @package Wsal
7
  * Allows plugins to use their own update API.
8
  *
9
  * @author Pippin Williamson
10
  * @version 1.2
11
  */
12
+ class EDD_SL_Plugin_Updater
13
+ {
14
  private $api_url = '';
15
  private $api_data = array();
16
  private $name = '';
28
  * @param array $_api_data Optional data to send with API calls.
29
  * @return void
30
  */
31
+ public function __construct($_api_url, $_plugin_file, $_api_data = null)
32
+ {
33
+ $this->api_url = trailingslashit($_api_url);
34
+ $this->api_data = urlencode_deep($_api_data);
35
+ $this->name = plugin_basename($_plugin_file);
36
+ $this->slug = basename($_plugin_file, '.php');
37
  $this->version = $_api_data['version'];
38
 
39
  // Set up hooks.
44
  * Set up WordPress filters to hook into WP's update process.
45
  *
46
  * @uses add_filter()
 
47
  * @return void
48
  */
49
+ private function hook()
50
+ {
51
+ add_filter('pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins_filter'));
52
+ add_filter('plugins_api', array( $this, 'plugins_api_filter' ), 10, 3);
53
+ add_filter('http_request_args', array( $this, 'http_request_args' ), 10, 2);
54
  }
55
 
56
  /**
66
  * @param array $_transient_data Update array build by WordPress.
67
  * @return array Modified update array with custom plugin data.
68
  */
69
+ public function pre_set_site_transient_update_plugins_filter($_transient_data)
70
+ {
71
+ if (empty($_transient_data) || !$this->do_check) {
 
72
  // This ensures that the custom API request only runs on the second time that WP fires the update check
73
  $this->do_check = true;
 
74
  return $_transient_data;
75
  }
76
 
77
+ $to_send = array('slug' => $this->slug);
78
+ $api_response = $this->api_request('plugin_latest_version', $to_send);
79
 
80
+ if (false !== $api_response && is_object($api_response) && isset($api_response->new_version)) {
81
+ if (version_compare($this->version, $api_response->new_version, '<')) {
 
 
 
82
  $_transient_data->response[$this->name] = $api_response;
83
  }
84
  }
85
  return $_transient_data;
86
  }
87
 
 
88
  /**
89
  * Updates information on the "View version x.x details" page with custom data.
90
  *
95
  * @param object $_args
96
  * @return object $_data
97
  */
98
+ public function plugins_api_filter($_data, $_action = '', $_args = null)
99
+ {
100
+ if (($_action != 'plugin_information') || !isset($_args->slug) || ($_args->slug != $this->slug)) {
101
+ return $_data;
102
+ }
103
+ $to_send = array('slug' => $this->slug);
104
 
105
+ $api_response = $this->api_request('plugin_information', $to_send);
106
+ if (false !== $api_response) {
107
+ $_data = $api_response;
108
+ }
109
 
110
  return $_data;
111
  }
112
 
 
113
  /**
114
  * Disable SSL verification in order to prevent download update failures
115
  *
117
  * @param string $url
118
  * @return object $array
119
  */
120
+ public function http_request_args($args, $url)
121
+ {
122
  // If it is an https request and we are performing a package download, disable ssl verification
123
+ if (strpos($url, 'https://') !== false && strpos($url, 'edd_action=package_download')) {
124
  $args['sslverify'] = false;
125
  }
126
  return $args;
137
  * @param array $_data Parameters for the API action.
138
  * @return false||object
139
  */
140
+ private function api_request($_action, $_data)
141
+ {
142
  global $wp_version;
143
+ $data = array_merge($this->api_data, $_data);
144
 
145
+ if ($data['slug'] != $this->slug) {
 
 
146
  return;
147
+ }
148
 
149
+ if (empty($data['license'])) {
150
  return;
151
+ }
152
 
153
  $api_params = array(
154
  'edd_action' => 'get_version',
158
  'author' => $data['author'],
159
  'url' => home_url()
160
  );
161
+ $request = wp_remote_post($this->api_url, array('timeout' => 15, 'sslverify' => false, 'body' => $api_params));
162
 
163
+ if (!is_wp_error($request)) {
164
+ $request = json_decode(wp_remote_retrieve_body($request));
165
+ if ($request && isset($request->sections)) {
166
+ $request->sections = maybe_unserialize($request->sections);
167
+ }
168
  return $request;
169
+ } else {
170
  return false;
171
+ }
172
  }
173
  }
classes/Helpers/DataHelper.php CHANGED
@@ -1,14 +1,18 @@
1
  <?php
2
-
 
 
 
 
3
  class WSAL_Helpers_DataHelper
4
  {
5
-
6
- /**
7
  * A wrapper for JSON encoding that fixes potential issues.
8
  * @param mixed $data The data to encode.
9
  * @return string JSON string.
10
  */
11
- public static function JsonEncode($data){
 
12
  return @json_encode($data);
13
  }
14
 
@@ -17,7 +21,8 @@ class WSAL_Helpers_DataHelper
17
  * @param string $data The JSON string to decode.
18
  * @return mixed Decoded data.
19
  */
20
- public static function JsonDecode($data){
 
21
  return @json_decode($data);
22
  }
23
- }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Helper class used for encode/decode json data.
6
+ */
7
  class WSAL_Helpers_DataHelper
8
  {
9
+ /**
 
10
  * A wrapper for JSON encoding that fixes potential issues.
11
  * @param mixed $data The data to encode.
12
  * @return string JSON string.
13
  */
14
+ public static function JsonEncode($data)
15
+ {
16
  return @json_encode($data);
17
  }
18
 
21
  * @param string $data The JSON string to decode.
22
  * @return mixed Decoded data.
23
  */
24
+ public static function JsonDecode($data)
25
+ {
26
  return @json_decode($data);
27
  }
28
+ }
classes/Lib/class-recursive-arrayaccess.php DELETED
@@ -1,139 +0,0 @@
1
- <?php
2
- /**
3
- * Multidimensional ArrayAccess
4
- *
5
- * Allows ArrayAccess-like functionality with multidimensional arrays. Fully supports
6
- * both sets and unsets.
7
- *
8
- * @package WordPress
9
- * @subpackage Session
10
- * @since 3.6.0
11
- */
12
-
13
- // Exit if accessed directly
14
- if ( ! defined( 'ABSPATH' ) ) exit;
15
-
16
- /**
17
- * Recursive array class to allow multidimensional array access.
18
- *
19
- * @package WordPress
20
- * @since 3.6.0
21
- */
22
- class Recursive_ArrayAccess implements ArrayAccess {
23
- /**
24
- * Internal data collection.
25
- *
26
- * @var array
27
- */
28
- protected $container = array();
29
-
30
- /**
31
- * Flag whether or not the internal collection has been changed.
32
- *
33
- * @var bool
34
- */
35
- protected $dirty = false;
36
-
37
- /**
38
- * Default object constructor.
39
- *
40
- * @param array $data
41
- */
42
- protected function __construct( $data = array() ) {
43
- foreach ( $data as $key => $value ) {
44
- $this[ $key ] = $value;
45
- }
46
- }
47
-
48
- /**
49
- * Allow deep copies of objects
50
- */
51
- public function __clone() {
52
- foreach ( $this->container as $key => $value ) {
53
- if ( $value instanceof self ) {
54
- $this[ $key ] = clone $value;
55
- }
56
- }
57
- }
58
-
59
- /**
60
- * Output the data container as a multidimensional array.
61
- *
62
- * @return array
63
- */
64
- public function toArray() {
65
- $data = $this->container;
66
- foreach ( $data as $key => $value ) {
67
- if ( $value instanceof self ) {
68
- $data[ $key ] = $value->toArray();
69
- }
70
- }
71
- return $data;
72
- }
73
-
74
- /**
75
- * ArrayAccess Implementation
76
- **/
77
-
78
- /**
79
- * Whether a offset exists
80
- *
81
- * @link http://php.net/manual/en/arrayaccess.offsetexists.php
82
- *
83
- * @param mixed $offset An offset to check for.
84
- *
85
- * @return boolean true on success or false on failure.
86
- */
87
- public function offsetExists( $offset ) {
88
- return isset( $this->container[ $offset ]) ;
89
- }
90
-
91
- /**
92
- * Offset to retrieve
93
- *
94
- * @link http://php.net/manual/en/arrayaccess.offsetget.php
95
- *
96
- * @param mixed $offset The offset to retrieve.
97
- *
98
- * @return mixed Can return all value types.
99
- */
100
- public function offsetGet( $offset ) {
101
- return isset( $this->container[ $offset ] ) ? $this->container[ $offset ] : null;
102
- }
103
-
104
- /**
105
- * Offset to set
106
- *
107
- * @link http://php.net/manual/en/arrayaccess.offsetset.php
108
- *
109
- * @param mixed $offset The offset to assign the value to.
110
- * @param mixed $value The value to set.
111
- *
112
- * @return void
113
- */
114
- public function offsetSet( $offset, $data ) {
115
- if ( is_array( $data ) ) {
116
- $data = new self( $data );
117
- }
118
- if ( $offset === null ) { // don't forget this!
119
- $this->container[] = $data;
120
- } else {
121
- $this->container[ $offset ] = $data;
122
- }
123
-
124
- $this->dirty = true;
125
- }
126
-
127
- /**
128
- * Offset to unset
129
- *
130
- * @link http://php.net/manual/en/arrayaccess.offsetunset.php
131
- *
132
- * @param mixed $offset The offset to unset.
133
- *
134
- * @return void
135
- */
136
- public function offsetUnset( $offset ) {
137
- unset( $this->container[ $offset ] );
138
- }
139
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/Lib/class-wp-session-utils.php DELETED
@@ -1,139 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Utility class for sesion utilities
5
- *
6
- * THIS CLASS SHOULD NEVER BE INSTANTIATED
7
- */
8
- class WP_Session_Utils {
9
- /**
10
- * Count the total sessions in the database.
11
- *
12
- * @global wpdb $wpdb
13
- *
14
- * @return int
15
- */
16
- public static function count_sessions() {
17
- global $wpdb;
18
-
19
- $query = "SELECT COUNT(*) FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%'";
20
-
21
- /**
22
- * Filter the query in case tables are non-standard.
23
- *
24
- * @param string $query Database count query
25
- */
26
- $query = apply_filters( 'wp_session_count_query', $query );
27
-
28
- $sessions = $wpdb->get_var( $query );
29
-
30
- return absint( $sessions );
31
- }
32
-
33
- /**
34
- * Create a new, random session in the database.
35
- *
36
- * @param null|string $date
37
- */
38
- public static function create_dummy_session( $date = null ) {
39
- // Generate our date
40
- if ( null !== $date ) {
41
- $time = strtotime( $date );
42
-
43
- if ( false === $time ) {
44
- $date = null;
45
- } else {
46
- $expires = date( 'U', strtotime( $date ) );
47
- }
48
- }
49
-
50
- // If null was passed, or if the string parsing failed, fall back on a default
51
- if ( null === $date ) {
52
- /**
53
- * Filter the expiration of the session in the database
54
- *
55
- * @param int
56
- */
57
- $expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 );
58
- }
59
-
60
- $session_id = self::generate_id();
61
-
62
- // Store the session
63
- add_option( "_wp_session_{$session_id}", array(), '', 'no' );
64
- add_option( "_wp_session_expires_{$session_id}", $expires, '', 'no' );
65
- }
66
-
67
- /**
68
- * Delete old sessions from the database.
69
- *
70
- * @param int $limit Maximum number of sessions to delete.
71
- *
72
- * @global wpdb $wpdb
73
- *
74
- * @return int Sessions deleted.
75
- */
76
- public static function delete_old_sessions( $limit = 1000 ) {
77
- global $wpdb;
78
-
79
- $limit = absint( $limit );
80
- $keys = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%' ORDER BY option_value ASC LIMIT 0, {$limit}" );
81
-
82
- $now = time();
83
- $expired = array();
84
- $count = 0;
85
-
86
- foreach( $keys as $expiration ) {
87
- $key = $expiration->option_name;
88
- $expires = $expiration->option_value;
89
-
90
- if ( $now > $expires ) {
91
- $session_id = preg_replace("/[^A-Za-z0-9_]/", '', substr( $key, 20 ) );
92
-
93
- $expired[] = $key;
94
- $expired[] = "_wp_session_{$session_id}";
95
-
96
- $count += 1;
97
- }
98
- }
99
-
100
- // Delete expired sessions
101
- if ( ! empty( $expired ) ) {
102
- $placeholders = array_fill( 0, count( $expired ), '%s' );
103
- $format = implode( ', ', $placeholders );
104
- $query = "DELETE FROM $wpdb->options WHERE option_name IN ($format)";
105
-
106
- $prepared = $wpdb->prepare( $query, $expired );
107
- $wpdb->query( $prepared );
108
- }
109
-
110
- return $count;
111
- }
112
-
113
- /**
114
- * Remove all sessions from the database, regardless of expiration.
115
- *
116
- * @global wpdb $wpdb
117
- *
118
- * @return int Sessions deleted
119
- */
120
- public static function delete_all_sessions() {
121
- global $wpdb;
122
-
123
- $count = $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_wp_session_%'" );
124
-
125
- return (int) ( $count / 2 );
126
- }
127
-
128
- /**
129
- * Generate a new, random session ID.
130
- *
131
- * @return string
132
- */
133
- public static function generate_id() {
134
- require_once( ABSPATH . 'wp-includes/class-phpass.php' );
135
- $hash = new PasswordHash( 8, false );
136
-
137
- return md5( $hash->get_random_bytes( 32 ) );
138
- }
139
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/Lib/class-wp-session.php DELETED
@@ -1,322 +0,0 @@
1
- <?php
2
- /**
3
- * WordPress session managment.
4
- *
5
- * Standardizes WordPress session data using database-backed options for storage.
6
- * for storing user session information.
7
- *
8
- * @package WordPress
9
- * @subpackage Session
10
- * @since 3.7.0
11
- */
12
-
13
- // Exit if accessed directly
14
- if ( ! defined( 'ABSPATH' ) ) exit;
15
-
16
- /**
17
- * WordPress Session class for managing user session data.
18
- *
19
- * @package WordPress
20
- * @since 3.7.0
21
- */
22
- final class WP_Session extends Recursive_ArrayAccess implements Iterator, Countable {
23
- /**
24
- * ID of the current session.
25
- *
26
- * @var string
27
- */
28
- public $session_id;
29
-
30
- /**
31
- * Unix timestamp when session expires.
32
- *
33
- * @var int
34
- */
35
- protected $expires;
36
-
37
- /**
38
- * Unix timestamp indicating when the expiration time needs to be reset.
39
- *
40
- * @var int
41
- */
42
- protected $exp_variant;
43
-
44
- /**
45
- * Singleton instance.
46
- *
47
- * @var bool|WP_Session
48
- */
49
- private static $instance = false;
50
-
51
- /**
52
- * Retrieve the current session instance.
53
- *
54
- * @param bool $session_id Session ID from which to populate data.
55
- *
56
- * @return bool|WP_Session
57
- */
58
- public static function get_instance() {
59
- if (!self::$instance) {
60
- self::$instance = new self();
61
- }
62
-
63
- return self::$instance;
64
- }
65
-
66
- /**
67
- * Default constructor.
68
- * Will rebuild the session collection from the given session ID if it exists. Otherwise, will
69
- * create a new session with that ID.
70
- *
71
- * @param $session_id
72
- * @uses apply_filters Calls `wp_session_expiration` to determine how long until sessions expire.
73
- */
74
- protected function __construct() {
75
- if ( isset( $_COOKIE[WP_SESSION_COOKIE] ) ) {
76
- $cookie = stripslashes( $_COOKIE[WP_SESSION_COOKIE] );
77
- $cookie_crumbs = explode( '||', $cookie );
78
-
79
- $this->session_id = $cookie_crumbs[0];
80
- $this->expires = $cookie_crumbs[1];
81
- $this->exp_variant = $cookie_crumbs[2];
82
-
83
- // Update the session expiration if we're past the variant time
84
- if ( time() > $this->exp_variant ) {
85
- $this->set_expiration();
86
- delete_option( "_wp_session_expires_{$this->session_id}" );
87
- add_option( "_wp_session_expires_{$this->session_id}", $this->expires, '', 'no' );
88
- }
89
- } else {
90
- $this->session_id = WP_Session_Utils::generate_id();
91
- $this->set_expiration();
92
- }
93
-
94
- $this->read_data();
95
-
96
- $this->set_cookie();
97
- }
98
-
99
- /**
100
- * Set both the expiration time and the expiration variant.
101
- *
102
- * If the current time is below the variant, we don't update the session's expiration time. If it's
103
- * greater than the variant, then we update the expiration time in the database. This prevents
104
- * writing to the database on every page load for active sessions and only updates the expiration
105
- * time if we're nearing when the session actually expires.
106
- *
107
- * By default, the expiration time is set to 30 minutes.
108
- * By default, the expiration variant is set to 24 minutes.
109
- *
110
- * As a result, the session expiration time - at a maximum - will only be written to the database once
111
- * every 24 minutes. After 30 minutes, the session will have been expired. No cookie will be sent by
112
- * the browser, and the old session will be queued for deletion by the garbage collector.
113
- *
114
- * @uses apply_filters Calls `wp_session_expiration_variant` to get the max update window for session data.
115
- * @uses apply_filters Calls `wp_session_expiration` to get the standard expiration time for sessions.
116
- */
117
- protected function set_expiration() {
118
- $this->exp_variant = time() + (int) apply_filters('wp_session_expiration_variant', 24 * 60);
119
- $this->expires = time() + (int) apply_filters('wp_session_expiration', 30 * 60);
120
- }
121
-
122
- /**
123
- * Set the session cookie
124
- */
125
- protected function set_cookie() {
126
- @setcookie(WP_SESSION_COOKIE, $this->session_id . '||' . $this->expires . '||' . $this->exp_variant, $this->expires, COOKIEPATH, COOKIE_DOMAIN);
127
- }
128
-
129
- /**
130
- * Generate a cryptographically strong unique ID for the session token.
131
- *
132
- * @return string
133
- */
134
- protected function generate_id() {
135
- require_once(ABSPATH . 'wp-includes/class-phpass.php');
136
- $hasher = new PasswordHash(8, false);
137
-
138
- return md5($hasher->get_random_bytes(32));
139
- }
140
-
141
- /**
142
- * Checks if is valid md5 string
143
- *
144
- * @param string $md5
145
- * @return int
146
- */
147
- protected function is_valid_md5($md5 = '') {
148
- return preg_match('/^[a-f0-9]{32}$/', $md5);
149
- }
150
-
151
- /**
152
- * Read data from a transient for the current session.
153
- *
154
- * Automatically resets the expiration time for the session transient to some time in the future.
155
- *
156
- * @return array
157
- */
158
- protected function read_data() {
159
- $this->container = get_option("_wp_session_{$this->session_id}", array());
160
-
161
- return $this->container;
162
- }
163
-
164
- /**
165
- * Write the data from the current session to the data storage system.
166
- */
167
- public function write_data() {
168
- $option_key = "_wp_session_{$this->session_id}";
169
-
170
- // Only write the collection to the DB if it's changed.
171
- if ($this->dirty) {
172
- if (false === get_option($option_key)) {
173
- add_option("_wp_session_{$this->session_id}", $this->container, '', 'no');
174
- add_option("_wp_session_expires_{$this->session_id}", $this->expires, '', 'no');
175
- } else {
176
- delete_option("_wp_session_{$this->session_id}");
177
- add_option("_wp_session_{$this->session_id}", $this->container, '', 'no');
178
- }
179
- }
180
- }
181
-
182
- /**
183
- * Output the current container contents as a JSON-encoded string.
184
- *
185
- * @return string
186
- */
187
- public function json_out() {
188
- return json_encode($this->container);
189
- }
190
-
191
- /**
192
- * Decodes a JSON string and, if the object is an array, overwrites the session container with its contents.
193
- *
194
- * @param string $data
195
- *
196
- * @return bool
197
- */
198
- public function json_in($data) {
199
- $array = json_decode($data);
200
-
201
- if (is_array($array)) {
202
- $this->container = $array;
203
- return true;
204
- }
205
-
206
- return false;
207
- }
208
-
209
- /**
210
- * Regenerate the current session's ID.
211
- *
212
- * @param bool $delete_old Flag whether or not to delete the old session data from the server.
213
- */
214
- public function regenerate_id($delete_old = false) {
215
- if ($delete_old) {
216
- delete_option("_wp_session_{$this->session_id}");
217
- }
218
-
219
- $this->session_id = $this->generate_id();
220
-
221
- $this->set_cookie();
222
- }
223
-
224
- /**
225
- * Check if a session has been initialized.
226
- *
227
- * @return bool
228
- */
229
- public function session_started() {
230
- return !!self::$instance;
231
- }
232
-
233
- /**
234
- * Return the read-only cache expiration value.
235
- *
236
- * @return int
237
- */
238
- public function cache_expiration() {
239
- return $this->expires;
240
- }
241
-
242
- /**
243
- * Flushes all session variables.
244
- */
245
- public function reset() {
246
- $this->container = array();
247
- }
248
-
249
- /*****************************************************************/
250
- /* Iterator Implementation */
251
- /*****************************************************************/
252
-
253
- /**
254
- * Current position of the array.
255
- *
256
- * @link http://php.net/manual/en/iterator.current.php
257
- *
258
- * @return mixed
259
- */
260
- public function current() {
261
- return current($this->container);
262
- }
263
-
264
- /**
265
- * Key of the current element.
266
- *
267
- * @link http://php.net/manual/en/iterator.key.php
268
- *
269
- * @return mixed
270
- */
271
- public function key() {
272
- return key($this->container);
273
- }
274
-
275
- /**
276
- * Move the internal point of the container array to the next item
277
- *
278
- * @link http://php.net/manual/en/iterator.next.php
279
- *
280
- * @return void
281
- */
282
- public function next() {
283
- next($this->container);
284
- }
285
-
286
- /**
287
- * Rewind the internal point of the container array.
288
- *
289
- * @link http://php.net/manual/en/iterator.rewind.php
290
- *
291
- * @return void
292
- */
293
- public function rewind() {
294
- reset($this->container);
295
- }
296
-
297
- /**
298
- * Is the current key valid?
299
- *
300
- * @link http://php.net/manual/en/iterator.rewind.php
301
- *
302
- * @return bool
303
- */
304
- public function valid() {
305
- return $this->offsetExists($this->key());
306
- }
307
-
308
- /*****************************************************************/
309
- /* Countable Implementation */
310
- /*****************************************************************/
311
-
312
- /**
313
- * Get the count of elements in the container array.
314
- *
315
- * @link http://php.net/manual/en/countable.count.php
316
- *
317
- * @return int
318
- */
319
- public function count() {
320
- return count($this->container);
321
- }
322
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/Lib/wp-session.php DELETED
@@ -1,182 +0,0 @@
1
- <?php
2
- /**
3
- * WordPress session managment.
4
- *
5
- * Standardizes WordPress session data and uses either database transients or in-memory caching
6
- * for storing user session information.
7
- *
8
- * @package WordPress
9
- * @subpackage Session
10
- * @since 3.7.0
11
- */
12
-
13
- // Exit if accessed directly
14
- if (!defined('ABSPATH')) exit;
15
-
16
- /**
17
- * Return the current cache expire setting.
18
- *
19
- * @return int
20
- */
21
- function wp_session_cache_expire() {
22
- $wp_session = WP_Session::get_instance();
23
-
24
- return $wp_session->cache_expiration();
25
- }
26
-
27
- /**
28
- * Alias of wp_session_write_close()
29
- */
30
- function wp_session_commit() {
31
- wp_session_write_close();
32
- }
33
-
34
- /**
35
- * Load a JSON-encoded string into the current session.
36
- *
37
- * @param string $data
38
- */
39
- function wp_session_decode($data) {
40
- $wp_session = WP_Session::get_instance();
41
-
42
- return $wp_session->json_in($data);
43
- }
44
-
45
- /**
46
- * Encode the current session's data as a JSON string.
47
- *
48
- * @return string
49
- */
50
- function wp_session_encode() {
51
- $wp_session = WP_Session::get_instance();
52
-
53
- return $wp_session->json_out();
54
- }
55
-
56
- /**
57
- * Regenerate the session ID.
58
- *
59
- * @param bool $delete_old_session
60
- *
61
- * @return bool
62
- */
63
- function wp_session_regenerate_id($delete_old_session = false) {
64
- $wp_session = WP_Session::get_instance();
65
-
66
- $wp_session->regenerate_id($delete_old_session);
67
-
68
- return true;
69
- }
70
-
71
- /**
72
- * Start new or resume existing session.
73
- *
74
- * Resumes an existing session based on a value sent by the _wp_session cookie.
75
- *
76
- * @return bool
77
- */
78
- function wp_session_start() {
79
- $wp_session = WP_Session::get_instance();
80
- do_action('wp_session_start');
81
-
82
- return $wp_session->session_started();
83
- }
84
- // Removed
85
- //add_action( 'plugins_loaded', 'wp_session_start' );
86
-
87
- /**
88
- * Return the current session status.
89
- *
90
- * @return int
91
- */
92
- function wp_session_status() {
93
- $wp_session = WP_Session::get_instance();
94
-
95
- if ($wp_session->session_started()) {
96
- return PHP_SESSION_ACTIVE;
97
- }
98
-
99
- return PHP_SESSION_NONE;
100
- }
101
-
102
- /**
103
- * Unset all session variables.
104
- */
105
- function wp_session_unset() {
106
- $wp_session = WP_Session::get_instance();
107
-
108
- $wp_session->reset();
109
- }
110
-
111
- /**
112
- * Write session data and end session
113
- */
114
- function wp_session_write_close() {
115
- $wp_session = WP_Session::get_instance();
116
-
117
- $wp_session->write_data();
118
- do_action('wp_session_commit');
119
- }
120
- add_action('shutdown', 'wp_session_write_close');
121
- add_action('wp_logout', 'wp_session_unset');
122
-
123
- /**
124
- * Clean up expired sessions by removing data and their expiration entries from
125
- * the WordPress options table.
126
- *
127
- * This method should never be called directly and should instead be triggered as part
128
- * of a scheduled task or cron job.
129
- */
130
- if (!function_exists('wp_session_cleanup')) {
131
- function wp_session_cleanup()
132
- {
133
- global $wpdb;
134
-
135
- if (defined('WP_SETUP_CONFIG')) {
136
- return;
137
- }
138
-
139
- if (!defined('WP_INSTALLING')) {
140
- $expiration_keys = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_wp_session_expires_%'");
141
-
142
- $now = current_time('timestamp');
143
- $expired_sessions = array();
144
-
145
- foreach ($expiration_keys as $expiration) {
146
- // If the session has expired
147
- if ($now > intval($expiration->option_value)) {
148
- // Get the session ID by parsing the option_name
149
- $session_id = substr($expiration->option_name, 20);
150
-
151
- if ((int) -1 === (int) $session_id || !preg_match('/^[a-f0-9]{32}$/', $session_id)) {
152
- continue;
153
- }
154
- $expired_sessions[] = $expiration->option_name;
155
- $expired_sessions[] = esc_sql("_wp_session_$session_id");
156
- }
157
- }
158
- // Delete all expired sessions in a single query
159
- if (!empty($expired_sessions)) {
160
- $option_names = implode("','", $expired_sessions);
161
- $wpdb->query("DELETE FROM $wpdb->options WHERE option_name IN ('$option_names')");
162
- }
163
- }
164
-
165
- // Allow other plugins to hook in to the garbage collection process.
166
- do_action('wp_session_cleanup');
167
- }
168
- }
169
- add_action('wp_session_garbage_collection', 'wp_session_cleanup');
170
-
171
- /**
172
- * Register the garbage collector as a twice daily event.
173
- */
174
- if (!function_exists('wp_session_register_garbage_collection')) {
175
- function wp_session_register_garbage_collection()
176
- {
177
- if (!wp_next_scheduled('wp_session_garbage_collection')) {
178
- wp_schedule_event(current_time('timestamp'), 'twicedaily', 'wp_session_garbage_collection');
179
- }
180
- }
181
- }
182
- add_action('wp', 'wp_session_register_garbage_collection');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/LicenseManager.php CHANGED
@@ -4,8 +4,13 @@
4
  if(!class_exists('EDD_SL_Plugin_Updater')){
5
  require_once('EDD_SL_Plugin_Updater.php');
6
  }
7
-
8
- class WSAL_LicenseManager {
 
 
 
 
 
9
  /**
10
  * @var WpSecurityAuditLog
11
  */
@@ -13,30 +18,36 @@ class WSAL_LicenseManager {
13
 
14
  protected $plugins = array();
15
 
16
- public function __construct(WpSecurityAuditLog $plugin){
 
17
  $this->plugin = $plugin;
18
  add_action('plugins_loaded', array($this, 'LoadPlugins'));
19
  }
20
 
21
- protected function GetStoreUrl(){
 
22
  return 'https://www.wpsecurityauditlog.com/';
23
  }
24
 
25
- public function CountPlugins(){
 
26
  return count($this->plugins);
27
  }
28
 
29
- public function Plugins(){
 
30
  return $this->plugins;
31
  }
32
 
33
- public function LoadPlugins(){
34
- foreach(apply_filters('wsal_register', array()) as $pluginFile) {
 
35
  $this->AddPremiumPlugin($pluginFile);
36
  }
37
  }
38
 
39
- protected function GetPluginData($pluginFile, $license){
 
40
  // A hack since get_plugin_data() is not available now
41
  $pluginData = get_file_data($pluginFile, array(
42
  'Name' => 'Plugin Name',
@@ -46,11 +57,11 @@ class WSAL_LicenseManager {
46
  'Author' => 'Author',
47
  'TextDomain' => 'Text Domain',
48
  'DomainPath' => 'Domain Path',
49
- ), 'plugin' );
50
 
51
  $pluginUpdater = is_null($license)
52
- ? null
53
- : new EDD_SL_Plugin_Updater(
54
  $this->GetStoreUrl(),
55
  $pluginFile,
56
  array(
@@ -67,7 +78,8 @@ class WSAL_LicenseManager {
67
  );
68
  }
69
 
70
- public function AddPremiumPlugin($pluginFile) {
 
71
  if (isset($pluginFile)) {
72
  $name = sanitize_key(basename($pluginFile));
73
  $license = $this->plugin->settings->GetLicenseKey($name);
@@ -75,20 +87,23 @@ class WSAL_LicenseManager {
75
  }
76
  }
77
 
78
- public function AddPlugin($pluginFile) {
 
79
  if (isset($pluginFile)) {
80
  $name = sanitize_key(basename($pluginFile));
81
  $this->plugins[$name] = $this->GetPluginData($pluginFile, null);
82
  }
83
  }
84
 
85
- protected function GetBlogIds(){
 
86
  global $wpdb;
87
  $sql = 'SELECT blog_id FROM ' . $wpdb->blogs;
88
  return $wpdb->get_col($sql);
89
  }
90
 
91
- public function ActivateLicense($name, $license){
 
92
  $this->plugin->settings->SetLicenseKey($name, $license);
93
 
94
  $plugins = $this->Plugins();
@@ -101,10 +116,10 @@ class WSAL_LicenseManager {
101
 
102
  $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
103
 
104
- foreach($blog_ids as $blog_id){
105
-
106
- if($this->plugin->IsMultisite())
107
  $api_params['url'] = urlencode(get_home_url($blog_id));
 
108
 
109
  $response = wp_remote_get(
110
  esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
@@ -119,16 +134,18 @@ class WSAL_LicenseManager {
119
 
120
  $license_data = json_decode(wp_remote_retrieve_body($response));
121
 
122
- if(is_object($license_data)){
123
  $this->plugin->settings->SetLicenseStatus($name, $license_data->license);
124
- if($license_data->license !== 'valid'){
125
  $error = 'License Not Valid';
126
- if (isset($license_data->error)) $error .= ': ' . ucfirst(str_replace('_', ' ', $license_data->error));
 
 
127
  $this->plugin->settings->SetLicenseErrors($name, $error);
128
  $this->DeactivateLicense($name, $license);
129
  return false;
130
  }
131
- }else{
132
  $this->plugin->settings->SetLicenseErrors($name, 'Unexpected Licensing Server Response');
133
  $this->DeactivateLicense($name, $license);
134
  return false;
@@ -138,15 +155,16 @@ class WSAL_LicenseManager {
138
  return true;
139
  }
140
 
141
- public function IsLicenseValid($name){
 
142
  return trim(strtolower($this->plugin->settings->GetLicenseStatus($name))) === 'valid';
143
  }
144
 
145
- public function DeactivateLicense($name, $license = null){
 
146
  $this->plugin->settings->SetLicenseStatus($name, '');
147
-
148
  // deactivate it on the server (if license was given)
149
- if(!is_null($license)){
150
  $plugins = $this->Plugins();
151
  $api_params = array(
152
  'edd_action'=> 'deactivate_license',
@@ -157,17 +175,19 @@ class WSAL_LicenseManager {
157
 
158
  $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
159
 
160
- foreach($blog_ids as $blog_id){
161
-
162
- if($this->plugin->IsMultisite())
163
  $api_params['url'] = urlencode(get_home_url($blog_id));
 
164
 
165
  $response = wp_remote_get(
166
  esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
167
  array('timeout' => 15, 'sslverify' => false)
168
  );
169
 
170
- if (is_wp_error($response)) return false;
 
 
171
 
172
  wp_remote_retrieve_body($response);
173
  }
4
  if(!class_exists('EDD_SL_Plugin_Updater')){
5
  require_once('EDD_SL_Plugin_Updater.php');
6
  }
7
+ /**
8
+ * @package Wsal
9
+ *
10
+ * License Manager used in all the Add-Ons licenses.
11
+ */
12
+ class WSAL_LicenseManager
13
+ {
14
  /**
15
  * @var WpSecurityAuditLog
16
  */
18
 
19
  protected $plugins = array();
20
 
21
+ public function __construct(WpSecurityAuditLog $plugin)
22
+ {
23
  $this->plugin = $plugin;
24
  add_action('plugins_loaded', array($this, 'LoadPlugins'));
25
  }
26
 
27
+ protected function GetStoreUrl()
28
+ {
29
  return 'https://www.wpsecurityauditlog.com/';
30
  }
31
 
32
+ public function CountPlugins()
33
+ {
34
  return count($this->plugins);
35
  }
36
 
37
+ public function Plugins()
38
+ {
39
  return $this->plugins;
40
  }
41
 
42
+ public function LoadPlugins()
43
+ {
44
+ foreach (apply_filters('wsal_register', array()) as $pluginFile) {
45
  $this->AddPremiumPlugin($pluginFile);
46
  }
47
  }
48
 
49
+ protected function GetPluginData($pluginFile, $license)
50
+ {
51
  // A hack since get_plugin_data() is not available now
52
  $pluginData = get_file_data($pluginFile, array(
53
  'Name' => 'Plugin Name',
57
  'Author' => 'Author',
58
  'TextDomain' => 'Text Domain',
59
  'DomainPath' => 'Domain Path',
60
+ ), 'plugin');
61
 
62
  $pluginUpdater = is_null($license)
63
+ ? null
64
+ : new EDD_SL_Plugin_Updater(
65
  $this->GetStoreUrl(),
66
  $pluginFile,
67
  array(
78
  );
79
  }
80
 
81
+ public function AddPremiumPlugin($pluginFile)
82
+ {
83
  if (isset($pluginFile)) {
84
  $name = sanitize_key(basename($pluginFile));
85
  $license = $this->plugin->settings->GetLicenseKey($name);
87
  }
88
  }
89
 
90
+ public function AddPlugin($pluginFile)
91
+ {
92
  if (isset($pluginFile)) {
93
  $name = sanitize_key(basename($pluginFile));
94
  $this->plugins[$name] = $this->GetPluginData($pluginFile, null);
95
  }
96
  }
97
 
98
+ protected function GetBlogIds()
99
+ {
100
  global $wpdb;
101
  $sql = 'SELECT blog_id FROM ' . $wpdb->blogs;
102
  return $wpdb->get_col($sql);
103
  }
104
 
105
+ public function ActivateLicense($name, $license)
106
+ {
107
  $this->plugin->settings->SetLicenseKey($name, $license);
108
 
109
  $plugins = $this->Plugins();
116
 
117
  $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
118
 
119
+ foreach ($blog_ids as $blog_id) {
120
+ if ($this->plugin->IsMultisite()) {
 
121
  $api_params['url'] = urlencode(get_home_url($blog_id));
122
+ }
123
 
124
  $response = wp_remote_get(
125
  esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
134
 
135
  $license_data = json_decode(wp_remote_retrieve_body($response));
136
 
137
+ if (is_object($license_data)) {
138
  $this->plugin->settings->SetLicenseStatus($name, $license_data->license);
139
+ if ($license_data->license !== 'valid') {
140
  $error = 'License Not Valid';
141
+ if (isset($license_data->error)) {
142
+ $error .= ': ' . ucfirst(str_replace('_', ' ', $license_data->error));
143
+ }
144
  $this->plugin->settings->SetLicenseErrors($name, $error);
145
  $this->DeactivateLicense($name, $license);
146
  return false;
147
  }
148
+ } else {
149
  $this->plugin->settings->SetLicenseErrors($name, 'Unexpected Licensing Server Response');
150
  $this->DeactivateLicense($name, $license);
151
  return false;
155
  return true;
156
  }
157
 
158
+ public function IsLicenseValid($name)
159
+ {
160
  return trim(strtolower($this->plugin->settings->GetLicenseStatus($name))) === 'valid';
161
  }
162
 
163
+ public function DeactivateLicense($name, $license = null)
164
+ {
165
  $this->plugin->settings->SetLicenseStatus($name, '');
 
166
  // deactivate it on the server (if license was given)
167
+ if (!is_null($license)) {
168
  $plugins = $this->Plugins();
169
  $api_params = array(
170
  'edd_action'=> 'deactivate_license',
175
 
176
  $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
177
 
178
+ foreach ($blog_ids as $blog_id) {
179
+ if ($this->plugin->IsMultisite()) {
 
180
  $api_params['url'] = urlencode(get_home_url($blog_id));
181
+ }
182
 
183
  $response = wp_remote_get(
184
  esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
185
  array('timeout' => 15, 'sslverify' => false)
186
  );
187
 
188
+ if (is_wp_error($response)) {
189
+ return false;
190
+ }
191
 
192
  wp_remote_retrieve_body($response);
193
  }
classes/Loggers/Database.php CHANGED
@@ -1,18 +1,33 @@
1
  <?php
2
-
 
 
 
 
 
 
3
  class WSAL_Loggers_Database extends WSAL_AbstractLogger
4
  {
5
-
6
  public function __construct(WpSecurityAuditLog $plugin)
7
  {
8
  parent::__construct($plugin);
9
  $plugin->AddCleanupHook(array($this, 'CleanUp'));
10
  }
11
 
 
 
 
 
 
 
 
 
12
  public function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false)
13
  {
14
  // is this a php alert, and if so, are we logging such alerts?
15
- if ($type < 0010 && !$this->plugin->settings->IsPhpErrorLoggingEnabled()) return;
 
 
16
 
17
  // create new occurrence
18
  $occ = new WSAL_Models_Occurrence();
@@ -32,6 +47,9 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger
32
  }
33
  }
34
 
 
 
 
35
  public function CleanUp()
36
  {
37
  $now = current_time('timestamp');
@@ -57,15 +75,23 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger
57
  $query = new WSAL_Models_OccurrenceQuery();
58
  $query->addOrderBy("created_on", false);
59
  // TO DO Fixing data
60
- if ($is_date_e) $query->addCondition('created_on <= %s', intval($max_stamp));
61
- if ($is_limt_e) $query->setLimit($max_items);
 
 
 
 
62
 
63
- if (($max_items-1) == 0) return; // nothing to delete
 
 
64
 
65
  $result = $query->getAdapter()->GetSqlDelete($query);
66
  $deletedCount = $query->getAdapter()->Delete($query);
67
 
68
- if ($deletedCount == 0) return; // nothing to delete
 
 
69
  // keep track of what we're doing
70
  $this->plugin->alerts->Trigger(0003, array(
71
  'Message' => 'Running system cleanup.',
@@ -77,6 +103,10 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger
77
  do_action('wsal_prune', $deletedCount, vsprintf($result['sql'], $result['args']));
78
  }
79
 
 
 
 
 
80
  private function AlertInject($occurrence)
81
  {
82
  $count = $this->CheckPromoToShow();
@@ -96,6 +126,11 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger
96
  }
97
  }
98
 
 
 
 
 
 
99
  private function GetPromoAlert()
100
  {
101
  $lastPromoSentId = $this->plugin->GetGlobalOption('promo-send-id');
@@ -115,6 +150,10 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger
115
  return $promoToSend;
116
  }
117
 
 
 
 
 
118
  private function GetActivePromoText()
119
  {
120
  $aPromoAlerts = array();
@@ -136,6 +175,10 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger
136
  return $aPromoAlerts;
137
  }
138
 
 
 
 
 
139
  private function CheckPromoToShow()
140
  {
141
  $promoToShow = null;
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * Loggers Class.
5
+ *
6
+ * This class store the logs in the Database and adds the promo
7
+ * alerts, there is also the function to clean up alerts.
8
+ */
9
  class WSAL_Loggers_Database extends WSAL_AbstractLogger
10
  {
 
11
  public function __construct(WpSecurityAuditLog $plugin)
12
  {
13
  parent::__construct($plugin);
14
  $plugin->AddCleanupHook(array($this, 'CleanUp'));
15
  }
16
 
17
+ /**
18
+ * Log alert.
19
+ * @param integer $type alert code
20
+ * @param array $data Metadata
21
+ * @param integer $date (Optional) created_on
22
+ * @param integer $siteid (Optional) site_id
23
+ * @param bool $migrated (Optional) is_migrated
24
+ */
25
  public function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false)
26
  {
27
  // is this a php alert, and if so, are we logging such alerts?
28
+ if ($type < 0010 && !$this->plugin->settings->IsPhpErrorLoggingEnabled()) {
29
+ return;
30
+ }
31
 
32
  // create new occurrence
33
  $occ = new WSAL_Models_Occurrence();
47
  }
48
  }
49
 
50
+ /**
51
+ * Clean Up alerts by date OR by max number.
52
+ */
53
  public function CleanUp()
54
  {
55
  $now = current_time('timestamp');
75
  $query = new WSAL_Models_OccurrenceQuery();
76
  $query->addOrderBy("created_on", false);
77
  // TO DO Fixing data
78
+ if ($is_date_e) {
79
+ $query->addCondition('created_on <= %s', intval($max_stamp));
80
+ }
81
+ if ($is_limt_e) {
82
+ $query->setLimit($max_items);
83
+ }
84
 
85
+ if (($max_items-1) == 0) {
86
+ return; // nothing to delete
87
+ }
88
 
89
  $result = $query->getAdapter()->GetSqlDelete($query);
90
  $deletedCount = $query->getAdapter()->Delete($query);
91
 
92
+ if ($deletedCount == 0) {
93
+ return; // nothing to delete
94
+ }
95
  // keep track of what we're doing
96
  $this->plugin->alerts->Trigger(0003, array(
97
  'Message' => 'Running system cleanup.',
103
  do_action('wsal_prune', $deletedCount, vsprintf($result['sql'], $result['args']));
104
  }
105
 
106
+ /**
107
+ * Inject Promo alert every $count alerts if no Add-ons are activated.
108
+ * @param WSAL_Models_Occurrence $occurrence occurrence
109
+ */
110
  private function AlertInject($occurrence)
111
  {
112
  $count = $this->CheckPromoToShow();
126
  }
127
  }
128
 
129
+ /**
130
+ * Get the promo id, to send each time a different promo,
131
+ * keeping the last id saved in the DB.
132
+ * @return integer $promoToSend the array index
133
+ */
134
  private function GetPromoAlert()
135
  {
136
  $lastPromoSentId = $this->plugin->GetGlobalOption('promo-send-id');
150
  return $promoToSend;
151
  }
152
 
153
+ /**
154
+ * Array of promo.
155
+ * @return array $aPromoAlerts the array of promo
156
+ */
157
  private function GetActivePromoText()
158
  {
159
  $aPromoAlerts = array();
175
  return $aPromoAlerts;
176
  }
177
 
178
+ /**
179
+ * Check condition to show promo.
180
+ * @return integer|null counter alert
181
+ */
182
  private function CheckPromoToShow()
183
  {
184
  $promoToShow = null;
classes/Models/ActiveRecord.php CHANGED
@@ -1,11 +1,20 @@
1
  <?php
2
- //require_once(__DIR__ . '/../Connector/ConnectorFactory.php');
3
-
 
 
 
 
4
  abstract class WSAL_Models_ActiveRecord
5
  {
 
 
 
 
 
6
 
7
  /**
8
- * @var_$connector Data connector;
9
  */
10
  protected $connector;
11
 
@@ -14,39 +23,48 @@ abstract class WSAL_Models_ActiveRecord
14
  protected $adapterName = null;
15
 
16
  protected $useDefaultAdapter = false;
 
 
 
 
17
 
18
  /**
19
  * @return array Returns this records' fields.
20
  */
21
  public function GetFields()
22
  {
23
- if(!isset($this->_column_cache)){
24
  $this->_column_cache = array();
25
- foreach(array_keys(get_object_vars($this)) as $col)
26
- if(trim($col) && $col[0] != '_')
27
  $this->_column_cache[] = $col;
 
 
28
  }
29
  return $this->_column_cache;
30
  }
31
 
 
 
 
 
32
  public function setId($id)
33
  {
34
  $this->id = $id;
35
  }
36
 
 
 
 
 
37
  public function getId()
38
  {
39
  return $this->id;
40
  }
41
-
42
- const STATE_UNKNOWN = 'unknown';
43
- const STATE_CREATED = 'created';
44
- const STATE_UPDATED = 'updated';
45
- const STATE_DELETED = 'deleted';
46
- const STATE_LOADED = 'loaded';
47
-
48
- protected $_state = self::STATE_UNKNOWN;
49
 
 
 
 
50
  public function __construct($data = null)
51
  {
52
  if (!$this->adapterName) {
@@ -58,6 +76,10 @@ abstract class WSAL_Models_ActiveRecord
58
  }
59
  }
60
 
 
 
 
 
61
  protected function getConnector()
62
  {
63
  if (!empty($this->connector)) {
@@ -71,22 +93,28 @@ abstract class WSAL_Models_ActiveRecord
71
  return $this->connector;
72
  }
73
 
 
 
 
 
 
74
  public function getAdapter()
75
  {
76
  return $this->getConnector()->getAdapter($this->adapterName);
77
  }
78
 
79
-
80
  /**
81
  * Load record from DB.
 
82
  * @param string $cond (Optional) Load condition.
83
  * @param array $args (Optional) Load condition arguments.
84
  */
85
- public function Load($cond = '%d', $args = array(1)){
 
86
  $this->_state = self::STATE_UNKNOWN;
87
 
88
  $data = $this->getAdapter()->Load($cond, $args);
89
- if(!is_null($data)){
90
  $this->LoadData($data);
91
  $this->_state = self::STATE_LOADED;
92
  }
@@ -96,7 +124,8 @@ abstract class WSAL_Models_ActiveRecord
96
  * Load object data from variable.
97
  * @param array|object $data Data array or object.
98
  */
99
- public function LoadData($data){
 
100
  $copy = get_class($this);
101
  $copy = new $copy;
102
  foreach ((array)$data as $key => $val) {
@@ -132,6 +161,7 @@ abstract class WSAL_Models_ActiveRecord
132
 
133
  /**
134
  * Save this active record
 
135
  * @return integer|boolean Either the number of modified/inserted rows or false on failure.
136
  */
137
  public function Save()
@@ -152,47 +182,63 @@ abstract class WSAL_Models_ActiveRecord
152
  }
153
 
154
  /**
155
- * Deletes this active record
 
 
156
  */
157
  public function Delete()
158
  {
159
  $this->_state = self::STATE_UNKNOWN;
160
  $result = $this->getAdapter()->Delete($this);
161
- if($result !== false)
162
  $this->_state = self::STATE_DELETED;
 
163
 
164
  return $result;
165
  }
166
 
167
- public function Count($cond = '%d', $args = array(1)) {
168
- $result = $this->getAdapter()->Count($cond, $args);
 
 
 
 
 
 
169
  return $result;
170
  }
171
 
172
  /**
173
- * @return boolean
 
174
  */
175
- public function IsLoaded(){
 
176
  return $this->_state == self::STATE_LOADED;
177
  }
178
 
179
  /**
180
- * @return boolean
 
181
  */
182
- public function IsSaved(){
 
183
  return $this->_state == self::STATE_CREATED
184
  || $this->_state == self::STATE_UPDATED;
185
  }
186
 
187
  /**
188
- * @return boolean
 
189
  */
190
- public function IsCreated(){
 
191
  return $this->_state == self::STATE_CREATED;
192
  }
193
 
194
  /**
195
- * @return boolean
 
196
  */
197
  public function IsUpdated()
198
  {
@@ -200,28 +246,33 @@ abstract class WSAL_Models_ActiveRecord
200
  }
201
 
202
  /**
203
- * @return boolean
 
 
204
  */
205
  public function IsInstalled()
206
  {
207
  return $this->getAdapter()->IsInstalled();
208
  }
209
 
 
 
 
 
210
  public function Install()
211
  {
212
  return $this->getAdapter()->Install();
213
  }
214
 
215
  /**
216
- * @return boolean
 
217
  */
218
  public function IsDeleted()
219
  {
220
  return $this->_state == self::STATE_DELETED;
221
  }
222
 
223
- protected static $_cache = array();
224
-
225
  /**
226
  * Load ActiveRecord from DB or cache.
227
  * @param string $target ActiveRecord class name.
@@ -229,9 +280,10 @@ abstract class WSAL_Models_ActiveRecord
229
  * @param array $args Arguments used in condition.
230
  * @return WSAL_Models_ActiveRecord
231
  */
232
- protected static function CacheLoad($target, $query, $args){
 
233
  $index = $target . '::' . vsprintf($query, $args);
234
- if(!isset(self::$_cache[$index])){
235
  self::$_cache[$index] = new $target();
236
  self::$_cache[$index]->Load($query, $args);
237
  }
@@ -244,9 +296,10 @@ abstract class WSAL_Models_ActiveRecord
244
  * @param string $query Load condition.
245
  * @param array $args Arguments used in condition.
246
  */
247
- protected static function CacheRemove($target, $query, $args){
 
248
  $index = $target . '::' . sprintf($query, $args);
249
- if(!isset(self::$_cache[$index])){
250
  unset(self::$_cache[$index]);
251
  }
252
  }
@@ -260,7 +313,15 @@ abstract class WSAL_Models_ActiveRecord
260
  }
261
 
262
  /**
263
- * Function used in WSAL reporting extension
 
 
 
 
 
 
 
 
264
  */
265
  public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp)
266
  {
@@ -268,7 +329,10 @@ abstract class WSAL_Models_ActiveRecord
268
  }
269
 
270
  /**
271
- * Check if the float is IPv4 instead
 
 
 
272
  */
273
  private function is_ip_address($ip_address)
274
  {
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Abstract ActiveRecord model is the generic model for any kind
6
+ * of adapter.
7
+ */
8
  abstract class WSAL_Models_ActiveRecord
9
  {
10
+ const STATE_UNKNOWN = 'unknown';
11
+ const STATE_CREATED = 'created';
12
+ const STATE_UPDATED = 'updated';
13
+ const STATE_DELETED = 'deleted';
14
+ const STATE_LOADED = 'loaded';
15
 
16
  /**
17
+ * @var $connector Data connector;
18
  */
19
  protected $connector;
20
 
23
  protected $adapterName = null;
24
 
25
  protected $useDefaultAdapter = false;
26
+
27
+ protected $_state = self::STATE_UNKNOWN;
28
+
29
+ protected static $_cache = array();
30
 
31
  /**
32
  * @return array Returns this records' fields.
33
  */
34
  public function GetFields()
35
  {
36
+ if (!isset($this->_column_cache)) {
37
  $this->_column_cache = array();
38
+ foreach (array_keys(get_object_vars($this)) as $col) {
39
+ if (trim($col) && $col[0] != '_') {
40
  $this->_column_cache[] = $col;
41
+ }
42
+ }
43
  }
44
  return $this->_column_cache;
45
  }
46
 
47
+ /**
48
+ * Sets the id.
49
+ * @param integer $id
50
+ */
51
  public function setId($id)
52
  {
53
  $this->id = $id;
54
  }
55
 
56
+ /**
57
+ * Gets the id.
58
+ * @return integer $id.
59
+ */
60
  public function getId()
61
  {
62
  return $this->id;
63
  }
 
 
 
 
 
 
 
 
64
 
65
+ /**
66
+ * @throws Exception requires adapterName
67
+ */
68
  public function __construct($data = null)
69
  {
70
  if (!$this->adapterName) {
76
  }
77
  }
78
 
79
+ /**
80
+ * Gets the connector.
81
+ * @return WSAL_Connector_ConnectorInterface
82
+ */
83
  protected function getConnector()
84
  {
85
  if (!empty($this->connector)) {
93
  return $this->connector;
94
  }
95
 
96
+ /**
97
+ * Gets an adapter for the specified model
98
+ * based on the adapter name.
99
+ * @see WSAL_Connector_ConnectorInterface::getAdapter()
100
+ */
101
  public function getAdapter()
102
  {
103
  return $this->getConnector()->getAdapter($this->adapterName);
104
  }
105
 
 
106
  /**
107
  * Load record from DB.
108
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Load()
109
  * @param string $cond (Optional) Load condition.
110
  * @param array $args (Optional) Load condition arguments.
111
  */
112
+ public function Load($cond = '%d', $args = array(1))
113
+ {
114
  $this->_state = self::STATE_UNKNOWN;
115
 
116
  $data = $this->getAdapter()->Load($cond, $args);
117
+ if (!is_null($data)) {
118
  $this->LoadData($data);
119
  $this->_state = self::STATE_LOADED;
120
  }
124
  * Load object data from variable.
125
  * @param array|object $data Data array or object.
126
  */
127
+ public function LoadData($data)
128
+ {
129
  $copy = get_class($this);
130
  $copy = new $copy;
131
  foreach ((array)$data as $key => $val) {
161
 
162
  /**
163
  * Save this active record
164
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Save()
165
  * @return integer|boolean Either the number of modified/inserted rows or false on failure.
166
  */
167
  public function Save()
182
  }
183
 
184
  /**
185
+ * Deletes this active record.
186
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Delete()
187
+ * @return int|boolean Either the amount of deleted rows or False on error.
188
  */
189
  public function Delete()
190
  {
191
  $this->_state = self::STATE_UNKNOWN;
192
  $result = $this->getAdapter()->Delete($this);
193
+ if ($result !== false) {
194
  $this->_state = self::STATE_DELETED;
195
+ }
196
 
197
  return $result;
198
  }
199
 
200
+ /**
201
+ * Count records that matching a condition.
202
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Count()
203
+ * @return int count
204
+ */
205
+ public function Count($cond = '%d', $args = array(1))
206
+ {
207
+ $result = $this->getAdapter()->Count($cond, $args);
208
  return $result;
209
  }
210
 
211
  /**
212
+ * Check state loaded.
213
+ * @return bool
214
  */
215
+ public function IsLoaded()
216
+ {
217
  return $this->_state == self::STATE_LOADED;
218
  }
219
 
220
  /**
221
+ * Check state saved.
222
+ * @return bool
223
  */
224
+ public function IsSaved()
225
+ {
226
  return $this->_state == self::STATE_CREATED
227
  || $this->_state == self::STATE_UPDATED;
228
  }
229
 
230
  /**
231
+ * Check state created.
232
+ * @return bool
233
  */
234
+ public function IsCreated()
235
+ {
236
  return $this->_state == self::STATE_CREATED;
237
  }
238
 
239
  /**
240
+ * Check state updated.
241
+ * @return bool
242
  */
243
  public function IsUpdated()
244
  {
246
  }
247
 
248
  /**
249
+ * Check if the Record structure is created.
250
+ * @see WSAL_Adapters_MySQL_ActiveRecord::IsInstalled()
251
+ * @return bool
252
  */
253
  public function IsInstalled()
254
  {
255
  return $this->getAdapter()->IsInstalled();
256
  }
257
 
258
+ /**
259
+ * Install the Record structure.
260
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Install()
261
+ */
262
  public function Install()
263
  {
264
  return $this->getAdapter()->Install();
265
  }
266
 
267
  /**
268
+ * Check state deleted.
269
+ * @return bool
270
  */
271
  public function IsDeleted()
272
  {
273
  return $this->_state == self::STATE_DELETED;
274
  }
275
 
 
 
276
  /**
277
  * Load ActiveRecord from DB or cache.
278
  * @param string $target ActiveRecord class name.
280
  * @param array $args Arguments used in condition.
281
  * @return WSAL_Models_ActiveRecord
282
  */
283
+ protected static function CacheLoad($target, $query, $args)
284
+ {
285
  $index = $target . '::' . vsprintf($query, $args);
286
+ if (!isset(self::$_cache[$index])) {
287
  self::$_cache[$index] = new $target();
288
  self::$_cache[$index]->Load($query, $args);
289
  }
296
  * @param string $query Load condition.
297
  * @param array $args Arguments used in condition.
298
  */
299
+ protected static function CacheRemove($target, $query, $args)
300
+ {
301
  $index = $target . '::' . sprintf($query, $args);
302
+ if (!isset(self::$_cache[$index])) {
303
  unset(self::$_cache[$index]);
304
  }
305
  }
313
  }
314
 
315
  /**
316
+ * Function used in WSAL reporting extension.
317
+ * @see WSAL_Adapters_MySQL_ActiveRecord::GetReporting()
318
+ * @param int $_siteId site ID
319
+ * @param int $_userId user ID
320
+ * @param string $_roleName user role
321
+ * @param int $_alertCode alert code
322
+ * @param timestamp $_startTimestamp from created_on
323
+ * @param timestamp $_endTimestamp to created_on
324
+ * @return array Report results
325
  */
326
  public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp)
327
  {
329
  }
330
 
331
  /**
332
+ * Check if the float is IPv4 instead.
333
+ * @see WSAL_Models_ActiveRecord::LoadData()
334
+ * @param float $ip_address number to check
335
+ * @return bool result validation
336
  */
337
  private function is_ip_address($ip_address)
338
  {
classes/Models/Meta.php CHANGED
@@ -1,15 +1,24 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- class WSAL_Models_Meta extends WSAL_Models_ActiveRecord {
4
-
5
- protected $adapterName = "Meta";
6
-
7
- public $id = 0;
8
- public $occurrence_id = 0;
9
- public $name = '';
10
- public $value = array(); // force mixed type
11
-
12
- public function SaveMeta()
13
  {
14
  $this->_state = self::STATE_UNKNOWN;
15
  $updateId = $this->getId();
@@ -21,6 +30,13 @@ class WSAL_Models_Meta extends WSAL_Models_ActiveRecord {
21
  return $result;
22
  }
23
 
 
 
 
 
 
 
 
24
  public function UpdateByNameAndOccurenceId($name, $value, $occurrenceId)
25
  {
26
  $meta = $this->getAdapter()->LoadByNameAndOccurenceId($name, $occurrenceId);
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Metadata model is the model for the Metadata adapter,
6
+ * used for save and update the metadata.
7
+ */
8
+ class WSAL_Models_Meta extends WSAL_Models_ActiveRecord
9
+ {
10
+ public $id = 0;
11
+ public $occurrence_id = 0;
12
+ public $name = '';
13
+ public $value = array(); // force mixed type
14
+ protected $adapterName = "Meta";
15
 
16
+ /**
17
+ * Save Metadata into Adapter.
18
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Save()
19
+ * @return integer|boolean Either the number of modified/inserted rows or false on failure.
20
+ */
21
+ public function SaveMeta()
 
 
 
 
22
  {
23
  $this->_state = self::STATE_UNKNOWN;
24
  $updateId = $this->getId();
30
  return $result;
31
  }
32
 
33
+ /**
34
+ * Update Metadata by name and occurrence_id.
35
+ * @see WSAL_Adapters_MySQL_Meta::LoadByNameAndOccurenceId()
36
+ * @param string $name meta name
37
+ * @param mixed $value meta value
38
+ * @param integer $occurrenceId occurrence_id
39
+ */
40
  public function UpdateByNameAndOccurenceId($name, $value, $occurrenceId)
41
  {
42
  $meta = $this->getAdapter()->LoadByNameAndOccurenceId($name, $occurrenceId);
classes/Models/Occurrence.php CHANGED
@@ -1,5 +1,10 @@
1
  <?php
2
-
 
 
 
 
 
3
  class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
4
  {
5
  public $id = 0;
@@ -12,6 +17,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
12
 
13
  /**
14
  * Returns the alert related to this occurrence.
 
15
  * @return WSAL_Alert
16
  */
17
  public function GetAlert()
@@ -21,6 +27,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
21
 
22
  /**
23
  * Returns the value of a meta item.
 
24
  * @param string $name Name of meta item.
25
  * @param mixed $default Default value returned when meta does not exist.
26
  * @return mixed The value, if meta item does not exist $default returned.
@@ -28,7 +35,6 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
28
  public function GetMetaValue($name, $default = array())
29
  {
30
  //get meta adapter
31
- //call the function ($name, $this->getId())
32
  $meta = $this->getAdapter()->GetNamedMeta($this, $name);
33
  return maybe_unserialize($meta['value']);
34
 
@@ -37,7 +43,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
37
  }
38
 
39
  /**
40
- * Set the value of a meta item (creates or updates meta item).
41
  * @param string $name Meta name.
42
  * @param mixed $value Meta value.
43
  */
@@ -53,6 +59,12 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
53
  }
54
  }
55
 
 
 
 
 
 
 
56
  public function UpdateMetaValue($name, $value)
57
  {
58
  $model = new WSAL_Models_Meta();
@@ -61,6 +73,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
61
 
62
  /**
63
  * Returns a key-value pair of meta data.
 
64
  * @return array
65
  */
66
  public function GetMetaArray()
@@ -85,6 +98,8 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
85
  }
86
 
87
  /**
 
 
88
  * @param callable|null $metaFormatter (Optional) Meta formatter callback.
89
  * @return string Full-formatted message.
90
  */
@@ -106,6 +121,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
106
 
107
  /**
108
  * Delete occurrence as well as associated meta data.
 
109
  * @return boolean True on success, false on failure.
110
  */
111
  public function Delete()
@@ -117,6 +133,8 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
117
  }
118
 
119
  /**
 
 
120
  * @return string User's username.
121
  */
122
  public function GetUsername()
@@ -134,6 +152,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
134
  }
135
 
136
  /**
 
137
  * @return string IP address of request.
138
  */
139
  public function GetSourceIP()
@@ -142,6 +161,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
142
  }
143
 
144
  /**
 
145
  * @return string IP address of request (from proxies etc).
146
  */
147
  public function GetOtherIPs()
@@ -157,6 +177,7 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
157
  }
158
 
159
  /**
 
160
  * @return array Array of user roles.
161
  */
162
  public function GetUserRoles()
@@ -174,29 +195,56 @@ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
174
  }
175
 
176
  /**
177
- * Finds occurences of the same type by IP and Username within specified time frame
178
  * @param string $ipAddress
179
  * @param string $username
180
  * @param int $alertId Alert type we are lookign for
181
  * @param int $siteId
182
  * @param $startTime mktime
183
  * @param $endTime mktime
 
184
  */
185
  public function CheckKnownUsers($args = array())
186
  {
187
  return $this->getAdapter()->CheckKnownUsers($args);
188
  }
189
 
 
 
 
 
 
 
 
 
 
190
  public function CheckUnKnownUsers($args = array())
191
  {
192
  return $this->getAdapter()->CheckUnKnownUsers($args);
193
  }
194
 
 
 
 
 
 
 
195
  public function GetByPostID($post_id)
196
  {
197
  return $this->getAdapter()->GetByPostID($post_id);
198
  }
199
 
 
 
 
 
 
 
 
 
 
 
 
200
  public function CheckAlert404($args = array())
201
  {
202
  return $this->getAdapter()->CheckAlert404($args);
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Occurrence model is the model for the Occurrence adapter,
6
+ * used for get the alert, set the meta fields, etc.
7
+ */
8
  class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
9
  {
10
  public $id = 0;
17
 
18
  /**
19
  * Returns the alert related to this occurrence.
20
+ * @see WSAL_AlertManager::GetAlert()
21
  * @return WSAL_Alert
22
  */
23
  public function GetAlert()
27
 
28
  /**
29
  * Returns the value of a meta item.
30
+ * @see WSAL_Adapters_MySQL_Occurrence::GetNamedMeta()
31
  * @param string $name Name of meta item.
32
  * @param mixed $default Default value returned when meta does not exist.
33
  * @return mixed The value, if meta item does not exist $default returned.
35
  public function GetMetaValue($name, $default = array())
36
  {
37
  //get meta adapter
 
38
  $meta = $this->getAdapter()->GetNamedMeta($this, $name);
39
  return maybe_unserialize($meta['value']);
40
 
43
  }
44
 
45
  /**
46
+ * Sets the value of a meta item (creates or updates meta item).
47
  * @param string $name Meta name.
48
  * @param mixed $value Meta value.
49
  */
59
  }
60
  }
61
 
62
+ /**
63
+ * Update Metadata of this occurrence by name.
64
+ * @see WSAL_Models_Meta::UpdateByNameAndOccurenceId()
65
+ * @param string $name meta name
66
+ * @param mixed $value meta value
67
+ */
68
  public function UpdateMetaValue($name, $value)
69
  {
70
  $model = new WSAL_Models_Meta();
73
 
74
  /**
75
  * Returns a key-value pair of meta data.
76
+ * @see WSAL_Adapters_MySQL_Occurrence::GetMultiMeta()
77
  * @return array
78
  */
79
  public function GetMetaArray()
98
  }
99
 
100
  /**
101
+ * Gets alert message.
102
+ * @see WSAL_Alert::GetMessage()
103
  * @param callable|null $metaFormatter (Optional) Meta formatter callback.
104
  * @return string Full-formatted message.
105
  */
121
 
122
  /**
123
  * Delete occurrence as well as associated meta data.
124
+ * @see WSAL_Adapters_ActiveRecordInterface::Delete()
125
  * @return boolean True on success, false on failure.
126
  */
127
  public function Delete()
133
  }
134
 
135
  /**
136
+ * Gets the username.
137
+ * @see WSAL_Adapters_MySQL_Occurrence::GetFirstNamedMeta()
138
  * @return string User's username.
139
  */
140
  public function GetUsername()
152
  }
153
 
154
  /**
155
+ * Gets the Client IP.
156
  * @return string IP address of request.
157
  */
158
  public function GetSourceIP()
161
  }
162
 
163
  /**
164
+ * Gets if there are other IPs.
165
  * @return string IP address of request (from proxies etc).
166
  */
167
  public function GetOtherIPs()
177
  }
178
 
179
  /**
180
+ * Gets user roles.
181
  * @return array Array of user roles.
182
  */
183
  public function GetUserRoles()
195
  }
196
 
197
  /**
198
+ * Finds occurences of the same type by IP and Username within specified time frame.
199
  * @param string $ipAddress
200
  * @param string $username
201
  * @param int $alertId Alert type we are lookign for
202
  * @param int $siteId
203
  * @param $startTime mktime
204
  * @param $endTime mktime
205
+ * @return WSAL_Occurrence[]
206
  */
207
  public function CheckKnownUsers($args = array())
208
  {
209
  return $this->getAdapter()->CheckKnownUsers($args);
210
  }
211
 
212
+ /**
213
+ * Finds occurences of the same type by IP within specified time frame.
214
+ * @param string $ipAddress
215
+ * @param int $alertId Alert type we are lookign for
216
+ * @param int $siteId
217
+ * @param $startTime mktime
218
+ * @param $endTime mktime
219
+ * @return WSAL_Occurrence[]
220
+ */
221
  public function CheckUnKnownUsers($args = array())
222
  {
223
  return $this->getAdapter()->CheckUnKnownUsers($args);
224
  }
225
 
226
+ /**
227
+ * Gets occurrence by Post_id
228
+ * @see WSAL_Adapters_MySQL_Occurrence::GetByPostID()
229
+ * @param integer $post_id
230
+ * @return WSAL_Occurrence[]
231
+ */
232
  public function GetByPostID($post_id)
233
  {
234
  return $this->getAdapter()->GetByPostID($post_id);
235
  }
236
 
237
+ /**
238
+ * Gets occurences of the same type by IP within specified time frame.
239
+ * @see WSAL_Adapters_MySQL_Occurrence::CheckAlert404()
240
+ * @param string $ipAddress
241
+ * @param string $username
242
+ * @param int $alertId Alert type we are lookign for
243
+ * @param int $siteId
244
+ * @param $startTime mktime
245
+ * @param $endTime mktime
246
+ * @return WSAL_Occurrence[]
247
+ */
248
  public function CheckAlert404($args = array())
249
  {
250
  return $this->getAdapter()->CheckAlert404($args);
classes/Models/OccurrenceQuery.php CHANGED
@@ -1,15 +1,29 @@
1
  <?php
2
-
 
 
 
 
3
  class WSAL_Models_OccurrenceQuery extends WSAL_Models_Query
4
  {
5
  protected $arguments = array();
6
 
 
 
 
 
 
 
7
  public function addArgument($field, $value)
8
  {
9
  $this->arguments[$field] = $value;
10
  return $this;
11
  }
12
 
 
 
 
 
13
  public function clearArguments()
14
  {
15
  $this->arguments = array();
@@ -25,5 +39,4 @@ class WSAL_Models_OccurrenceQuery extends WSAL_Models_Query
25
  $this->getConnector()->getAdapter("Occurrence")->GetTable()
26
  );
27
  }
28
-
29
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * OccurrenceQuery model adds or clears arguments in the Query model.
6
+ */
7
  class WSAL_Models_OccurrenceQuery extends WSAL_Models_Query
8
  {
9
  protected $arguments = array();
10
 
11
+ /**
12
+ * Sets arguments.
13
+ * @param string $field name field
14
+ * @param mixed $value value
15
+ * @return self
16
+ */
17
  public function addArgument($field, $value)
18
  {
19
  $this->arguments[$field] = $value;
20
  return $this;
21
  }
22
 
23
+ /**
24
+ * Resets arguments.
25
+ * @return self
26
+ */
27
  public function clearArguments()
28
  {
29
  $this->arguments = array();
39
  $this->getConnector()->getAdapter("Occurrence")->GetTable()
40
  );
41
  }
 
42
  }
classes/Models/Option.php CHANGED
@@ -1,20 +1,27 @@
1
  <?php
2
-
3
  /**
 
4
  * Wordpress options are always loaded from the default wordpress database.
 
 
5
  */
6
  class WSAL_Models_Option extends WSAL_Models_ActiveRecord
7
  {
8
-
9
- protected $adapterName = "Option";
10
  public $id = '';
11
  public $option_name = '';
12
  public $option_value = '';
 
 
13
  /**
14
  * Options are always stored in WPDB. This setting ensures that
15
  */
16
  protected $useDefaultAdapter = true;
17
 
 
 
 
 
 
18
  public function SetOptionValue($name, $value)
19
  {
20
  $option = $this->getAdapter()->GetNamedOption($name);
@@ -26,9 +33,15 @@ class WSAL_Models_Option extends WSAL_Models_ActiveRecord
26
  return $this->Save();
27
  }
28
 
 
 
 
 
 
 
29
  public function GetOptionValue($name, $default = array())
30
  {
31
- $option = $this->getAdapter()->GetNamedOption($name);
32
  $this->option_value = (!empty($option)) ? $option['option_value'] : null;
33
  if (!empty($this->option_value)) {
34
  $this->_state = self::STATE_LOADED;
@@ -38,6 +51,11 @@ class WSAL_Models_Option extends WSAL_Models_ActiveRecord
38
  return $this->IsLoaded() ? $this->option_value : $default;
39
  }
40
 
 
 
 
 
 
41
  public function Save()
42
  {
43
  $this->_state = self::STATE_UNKNOWN;
@@ -51,11 +69,23 @@ class WSAL_Models_Option extends WSAL_Models_ActiveRecord
51
  return $result;
52
  }
53
 
 
 
 
 
 
 
54
  public function GetNotificationsSetting($opt_prefix)
55
  {
56
  return $this->getAdapter()->GetNotificationsSetting($opt_prefix);
57
  }
58
 
 
 
 
 
 
 
59
  public function GetNotification($id)
60
  {
61
  return $this->LoadData(
@@ -63,16 +93,34 @@ class WSAL_Models_Option extends WSAL_Models_ActiveRecord
63
  );
64
  }
65
 
 
 
 
 
 
 
66
  public function DeleteByName($name)
67
  {
68
  return $this->getAdapter()->DeleteByName($name);
69
  }
70
 
 
 
 
 
 
 
71
  public function DeleteByPrefix($opt_prefix)
72
  {
73
  return $this->getAdapter()->DeleteByPrefix($opt_prefix);
74
  }
75
 
 
 
 
 
 
 
76
  public function CountNotifications($opt_prefix)
77
  {
78
  return $this->getAdapter()->CountNotifications($opt_prefix);
1
  <?php
 
2
  /**
3
+ * @package Wsal
4
  * Wordpress options are always loaded from the default wordpress database.
5
+ *
6
+ * Option Model gets and sets the options of the wsal_options table in the database.
7
  */
8
  class WSAL_Models_Option extends WSAL_Models_ActiveRecord
9
  {
 
 
10
  public $id = '';
11
  public $option_name = '';
12
  public $option_value = '';
13
+ protected $adapterName = "Option";
14
+
15
  /**
16
  * Options are always stored in WPDB. This setting ensures that
17
  */
18
  protected $useDefaultAdapter = true;
19
 
20
+ /**
21
+ * Sets Option record.
22
+ * @param string $name option name
23
+ * @param mixed $value option value
24
+ */
25
  public function SetOptionValue($name, $value)
26
  {
27
  $option = $this->getAdapter()->GetNamedOption($name);
33
  return $this->Save();
34
  }
35
 
36
+ /**
37
+ * Gets Option record.
38
+ * @param string $name option name
39
+ * @param mixed $default (Optional) default value
40
+ * @return mixed option value
41
+ */
42
  public function GetOptionValue($name, $default = array())
43
  {
44
+ $option = $this->getAdapter()->GetNamedOption($name);
45
  $this->option_value = (!empty($option)) ? $option['option_value'] : null;
46
  if (!empty($this->option_value)) {
47
  $this->_state = self::STATE_LOADED;
51
  return $this->IsLoaded() ? $this->option_value : $default;
52
  }
53
 
54
+ /**
55
+ * Save Option record.
56
+ * @see WSAL_Adapters_MySQL_ActiveRecord::Save()
57
+ * @return integer|boolean Either the number of modified/inserted rows or false on failure.
58
+ */
59
  public function Save()
60
  {
61
  $this->_state = self::STATE_UNKNOWN;
69
  return $result;
70
  }
71
 
72
+ /**
73
+ * Get options by prefix (notifications stored in json format).
74
+ * @see WSAL_Adapters_MySQL_Option::GetNotificationsSetting()
75
+ * @param string $opt_prefix prefix
76
+ * @return array|null options
77
+ */
78
  public function GetNotificationsSetting($opt_prefix)
79
  {
80
  return $this->getAdapter()->GetNotificationsSetting($opt_prefix);
81
  }
82
 
83
+ /**
84
+ * Get option by id (notifications stored in json format).
85
+ * @see WSAL_Adapters_MySQL_Option::GetNotification()
86
+ * @param int $id option ID
87
+ * @return string|null option
88
+ */
89
  public function GetNotification($id)
90
  {
91
  return $this->LoadData(
93
  );
94
  }
95
 
96
+ /**
97
+ * Delete option by name.
98
+ * @see WSAL_Adapters_MySQL_Option::DeleteByName()
99
+ * @param string $name option_name
100
+ * @return boolean
101
+ */
102
  public function DeleteByName($name)
103
  {
104
  return $this->getAdapter()->DeleteByName($name);
105
  }
106
 
107
+ /**
108
+ * Delete options start with prefix.
109
+ * @see WSAL_Adapters_MySQL_Option::DeleteByPrefix()
110
+ * @param string $opt_prefix prefix
111
+ * @return boolean
112
+ */
113
  public function DeleteByPrefix($opt_prefix)
114
  {
115
  return $this->getAdapter()->DeleteByPrefix($opt_prefix);
116
  }
117
 
118
+ /**
119
+ * Number of options start with prefix.
120
+ * @see WSAL_Adapters_MySQL_Option::CountNotifications()
121
+ * @param string $opt_prefix prefix
122
+ * @return integer Indicates the number of items.
123
+ */
124
  public function CountNotifications($opt_prefix)
125
  {
126
  return $this->getAdapter()->CountNotifications($opt_prefix);
classes/Models/Query.php CHANGED
@@ -1,5 +1,10 @@
1
  <?php
2
-
 
 
 
 
 
3
  class WSAL_Models_Query
4
  {
5
  protected $columns = array();
@@ -10,13 +15,16 @@ class WSAL_Models_Query
10
  protected $from = array();
11
  protected $meta_join = false;
12
  protected $searchCondition = null;
13
- protected $useDefaultAdapter = false;
14
 
15
  public function __construct()
16
  {
17
-
18
  }
19
 
 
 
 
 
20
  public function getConnector()
21
  {
22
  if (!empty($this->connector)) {
@@ -30,56 +38,102 @@ class WSAL_Models_Query
30
  return $this->connector;
31
  }
32
 
 
 
 
 
33
  public function getAdapter()
34
  {
35
  return $this->getConnector()->getAdapter('Query');
36
  }
37
 
 
 
 
 
 
38
  public function addColumn($column)
39
  {
40
  $this->columns[] = $column;
41
  return $this;
42
  }
43
 
 
 
 
 
44
  public function clearColumns()
45
  {
46
  $this->columns = array();
47
  return $this;
48
  }
49
 
 
 
 
 
50
  public function getColumns()
51
  {
52
  return $this->columns;
53
  }
54
 
 
 
 
 
 
55
  public function setColumns($columns)
56
  {
57
  $this->columns = $columns;
58
  return $this;
59
  }
60
 
 
 
 
 
 
 
61
  public function addCondition($field, $value)
62
  {
63
  $this->conditions[$field] = $value;
64
  return $this;
65
  }
66
 
 
 
 
 
67
  public function addORCondition($aConditions)
68
  {
69
  $this->conditions[] = $aConditions;
70
  }
71
 
 
 
 
 
72
  public function clearConditions()
73
  {
74
  $this->conditions = array();
75
  return $this;
76
  }
77
 
 
 
 
 
78
  public function getConditions()
79
  {
80
  return $this->conditions;
81
  }
82
 
 
 
 
 
 
 
83
  public function addOrderBy($field, $isDescending = false)
84
  {
85
  $order = ($isDescending) ? 'DESC' : 'ASC';
@@ -87,29 +141,50 @@ class WSAL_Models_Query
87
  return $this;
88
  }
89
 
 
 
 
 
90
  public function clearOrderBy()
91
  {
92
  $this->orderBy = array();
93
  return $this;
94
  }
95
 
 
 
 
 
96
  public function getOrderBy()
97
  {
98
  return $this->orderBy;
99
  }
100
 
 
 
 
 
 
101
  public function addFrom($fromDataSet)
102
  {
103
  $this->from[] = $fromDataSet;
104
  return $this;
105
  }
106
 
 
 
 
 
107
  public function clearFrom()
108
  {
109
  $this->from = array();
110
  return $this;
111
  }
112
 
 
 
 
 
113
  public function getFrom()
114
  {
115
  return $this->from;
@@ -117,7 +192,6 @@ class WSAL_Models_Query
117
 
118
  /**
119
  * Gets the value of limit.
120
- *
121
  * @return mixed
122
  */
123
  public function getLimit()
@@ -127,21 +201,17 @@ class WSAL_Models_Query
127
 
128
  /**
129
  * Sets the value of limit.
130
- *
131
  * @param mixed $limit the limit
132
- *
133
  * @return self
134
  */
135
  public function setLimit($limit)
136
  {
137
  $this->limit = $limit;
138
-
139
  return $this;
140
  }
141
 
142
  /**
143
  * Gets the value of offset.
144
- *
145
  * @return mixed
146
  */
147
  public function getOffset()
@@ -151,34 +221,48 @@ class WSAL_Models_Query
151
 
152
  /**
153
  * Sets the value of offset.
154
- *
155
  * @param mixed $offset the offset
156
- *
157
  * @return self
158
  */
159
  public function setOffset($offset)
160
  {
161
  $this->offset = $offset;
162
-
163
  return $this;
164
  }
165
 
 
 
 
 
 
166
  public function addSearchCondition($value)
167
  {
168
  $this->searchCondition = $value;
169
  return $this;
170
  }
171
 
 
 
 
 
172
  public function getSearchCondition()
173
  {
174
  return $this->searchCondition;
175
  }
176
 
 
 
 
 
177
  public function hasMetaJoin()
178
  {
179
  return $this->meta_join;
180
  }
181
 
 
 
 
 
182
  public function addMetaJoin()
183
  {
184
  $this->meta_join = true;
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * Query Class.
5
+ *
6
+ * Query model is the class for all the query conditions.
7
+ */
8
  class WSAL_Models_Query
9
  {
10
  protected $columns = array();
15
  protected $from = array();
16
  protected $meta_join = false;
17
  protected $searchCondition = null;
18
+ protected $useDefaultAdapter = false;
19
 
20
  public function __construct()
21
  {
 
22
  }
23
 
24
+ /**
25
+ * Initialize a connector singleton.
26
+ * @return WSAL_Connector_ConnectorInterface
27
+ */
28
  public function getConnector()
29
  {
30
  if (!empty($this->connector)) {
38
  return $this->connector;
39
  }
40
 
41
+ /**
42
+ * Gets the adapter.
43
+ * @return WSAL_Adapters_MySQL_Query
44
+ */
45
  public function getAdapter()
46
  {
47
  return $this->getConnector()->getAdapter('Query');
48
  }
49
 
50
+ /**
51
+ * Add a column.
52
+ * @param mixed $column column value
53
+ * @return self
54
+ */
55
  public function addColumn($column)
56
  {
57
  $this->columns[] = $column;
58
  return $this;
59
  }
60
 
61
+ /**
62
+ * Clear all columns.
63
+ * @return self
64
+ */
65
  public function clearColumns()
66
  {
67
  $this->columns = array();
68
  return $this;
69
  }
70
 
71
+ /**
72
+ * Get columns.
73
+ * @return array $columns
74
+ */
75
  public function getColumns()
76
  {
77
  return $this->columns;
78
  }
79
 
80
+ /**
81
+ * Set all columns.
82
+ * @param array $columns columns values
83
+ * @return self
84
+ */
85
  public function setColumns($columns)
86
  {
87
  $this->columns = $columns;
88
  return $this;
89
  }
90
 
91
+ /**
92
+ * Add conditions.
93
+ * @param string $field condition field
94
+ * @param mixed $value condition value
95
+ * @return self
96
+ */
97
  public function addCondition($field, $value)
98
  {
99
  $this->conditions[$field] = $value;
100
  return $this;
101
  }
102
 
103
+ /**
104
+ * Add OR condition.
105
+ * @param array $aConditions multi conditions
106
+ */
107
  public function addORCondition($aConditions)
108
  {
109
  $this->conditions[] = $aConditions;
110
  }
111
 
112
+ /**
113
+ * Clear all conditions.
114
+ * @return self
115
+ */
116
  public function clearConditions()
117
  {
118
  $this->conditions = array();
119
  return $this;
120
  }
121
 
122
+ /**
123
+ * Get all conditions.
124
+ * @return array $conditions
125
+ */
126
  public function getConditions()
127
  {
128
  return $this->conditions;
129
  }
130
 
131
+ /**
132
+ * Add order by.
133
+ * @param string $field field name
134
+ * @param boolean $isDescending (Optional) ascending/descending
135
+ * @return self
136
+ */
137
  public function addOrderBy($field, $isDescending = false)
138
  {
139
  $order = ($isDescending) ? 'DESC' : 'ASC';
141
  return $this;
142
  }
143
 
144
+ /**
145
+ * Clear order by.
146
+ * @return self
147
+ */
148
  public function clearOrderBy()
149
  {
150
  $this->orderBy = array();
151
  return $this;
152
  }
153
 
154
+ /**
155
+ * Get order by.
156
+ * @return array $orderBy
157
+ */
158
  public function getOrderBy()
159
  {
160
  return $this->orderBy;
161
  }
162
 
163
+ /**
164
+ * Add from.
165
+ * @param string $fromDataSet data set
166
+ * @return self
167
+ */
168
  public function addFrom($fromDataSet)
169
  {
170
  $this->from[] = $fromDataSet;
171
  return $this;
172
  }
173
 
174
+ /**
175
+ * Reset from.
176
+ * @return self
177
+ */
178
  public function clearFrom()
179
  {
180
  $this->from = array();
181
  return $this;
182
  }
183
 
184
+ /**
185
+ * Get from.
186
+ * @return string $from data set
187
+ */
188
  public function getFrom()
189
  {
190
  return $this->from;
192
 
193
  /**
194
  * Gets the value of limit.
 
195
  * @return mixed
196
  */
197
  public function getLimit()
201
 
202
  /**
203
  * Sets the value of limit.
 
204
  * @param mixed $limit the limit
 
205
  * @return self
206
  */
207
  public function setLimit($limit)
208
  {
209
  $this->limit = $limit;
 
210
  return $this;
211
  }
212
 
213
  /**
214
  * Gets the value of offset.
 
215
  * @return mixed
216
  */
217
  public function getOffset()
221
 
222
  /**
223
  * Sets the value of offset.
 
224
  * @param mixed $offset the offset
 
225
  * @return self
226
  */
227
  public function setOffset($offset)
228
  {
229
  $this->offset = $offset;
 
230
  return $this;
231
  }
232
 
233
+ /**
234
+ * Adds condition.
235
+ * @param mixed $value condition
236
+ * @return self
237
+ */
238
  public function addSearchCondition($value)
239
  {
240
  $this->searchCondition = $value;
241
  return $this;
242
  }
243
 
244
+ /**
245
+ * Gets condition.
246
+ * @return self
247
+ */
248
  public function getSearchCondition()
249
  {
250
  return $this->searchCondition;
251
  }
252
 
253
+ /**
254
+ * Check meta join.
255
+ * @return boolean
256
+ */
257
  public function hasMetaJoin()
258
  {
259
  return $this->meta_join;
260
  }
261
 
262
+ /**
263
+ * Adds meta join.
264
+ * @return self
265
+ */
266
  public function addMetaJoin()
267
  {
268
  $this->meta_join = true;
classes/Models/TmpUser.php CHANGED
@@ -1,9 +1,13 @@
1
  <?php
2
-
3
- class WSAL_Models_TmpUser extends WSAL_Models_ActiveRecord {
4
-
5
- protected $adapterName = "TmpUser";
6
-
7
- public $id = 0;
8
- public $user_login = '';
 
 
 
 
9
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * Model tmp_users
5
+ *
6
+ * Model used for the Temporary WP_users table.
7
+ */
8
+ class WSAL_Models_TmpUser extends WSAL_Models_ActiveRecord
9
+ {
10
+ public $id = 0;
11
+ public $user_login = '';
12
+ protected $adapterName = "TmpUser";
13
  }
classes/Nicer.php CHANGED
@@ -1,289 +1,299 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- /**
4
- * Inspects and prints out PHP values as HTML in a nicer way than print_r().
5
- * @author Christian Sciberras <christian@sciberras.me>
6
- * @copyright (c) 2013, Christian Sciberras
7
- * @license https://raw.github.com/uuf6429/nice_r/master/LICENSE MIT License
8
- * @link https://github.com/uuf6429/nice_r GitHub Repository
9
- * @version 2.0
10
- * @since 2.0
11
- */
12
- class WSAL_Nicer {
13
- protected $value;
14
-
15
- /**
16
- * Allows modification of CSS class prefix.
17
- * @var string
18
- */
19
- public $css_class = 'nice_r';
20
-
21
- /**
22
- * Allows modification of HTML id prefix.
23
- * @var string
24
- */
25
- public $html_id = 'nice_r_v';
26
-
27
- /**
28
- * Allows modification of JS function used to toggle sections.
29
- * @var string
30
- */
31
- public $js_func = 'nice_r_toggle';
32
-
33
- /**
34
- * Whether to inspect and output methods for objects or not.
35
- * @var boolean
36
- */
37
- public $inspect_methods = false;
38
-
39
- /**
40
- * Since PHP does not support private constants, we'll have to settle for private static fields.
41
- * @var string
42
- */
43
- protected static $BEEN_THERE = '__NICE_R_INFINITE_RECURSION_PROTECT__';
44
-
45
- protected $_has_reflection = null;
46
-
47
- /**
48
- * Constructs new renderer instance.
49
- * @param mixed $value The value to inspect and render.
50
- * @param boolean $inspectMethods Whether to inspect and output methods for objects or not.
51
- */
52
- public function __construct($value, $inspectMethods = false){
53
- $this->value = $value;
54
- $this->inspect_methods = $inspectMethods;
55
-
56
- if(is_null($this->_has_reflection))
57
- $this->_has_reflection = class_exists('ReflectionClass');
58
- }
59
-
60
- /**
61
- * Generates the inspector HTML and returns it as a string.
62
- * @return string Generated HTML.
63
- */
64
- public function generate(){
65
- return $this->_generate_value($this->value, $this->css_class);
66
- }
67
-
68
- /**
69
- * Renders the inspector HTML directly to the browser.
70
- */
71
- public function render(){
72
- echo $this->generate();
73
- }
74
 
75
- /**
76
- * Converts a string to HTML, encoding any special characters.
77
- * @param string $text The original string.
78
- * @return string The string as HTML.
79
- */
80
- protected function _esc_html($text){
81
- return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
82
- }
83
-
84
- protected function _inspect_array(&$html, &$var){
85
- $has_subitems = false;
86
-
87
- foreach($var as $k => $v){
88
- if($k !== self::$BEEN_THERE){
89
- $html .= $this->_generate_keyvalue($k, $v);
90
- $has_subitems = true;
91
- }
92
- }
93
-
94
- if(!$has_subitems){
95
- $html .= '<span class="'.$this->css_class.'_ni">Empty Array</span>';
96
- }
97
- }
98
-
99
- protected function _inspect_object(&$html, &$var){
100
- // render properties
101
- $has_subitems = false;
102
-
103
- foreach((array)$var as $k=>$v){
104
- if($k !== self::$BEEN_THERE){
105
- $html .= $this->_generate_keyvalue($k, $v);
106
- $has_subitems = true;
107
- }
108
- }
109
-
110
- if(!$has_subitems){
111
- $html .= '<span class="'.$this->css_class.'_ni">No Properties</span>';
112
- }
113
 
114
- // render methods (if enabled)
115
- if($this->inspect_methods){
116
- $has_subitems = false;
117
-
118
- foreach((array)get_class_methods($var) as $method){
119
- $html .= $this->_generate_callable($var, $method);
120
- $has_subitems = true;
121
- }
122
-
123
- if(!$has_subitems){
124
- $html .= '<span class="'.$this->css_class.'_ni">No Methods</span>';
125
- }
126
- }
127
- }
128
-
129
- /**
130
- * Render a single particular value.
131
- * @param mixed $var The value to render
132
- * @param string $class Parent CSS class.
133
- * @param string $id Item HTML id.
134
- */
135
- protected function _generate_value($var, $class = '', $id = ''){
136
- $BEENTHERE = self::$BEEN_THERE;
137
- $class .= ' '.$this->css_class.'_t_'.gettype($var);
138
-
139
- $html = '<div id="'.$id.'" class="'.$class.'">';
140
-
141
- switch(true){
142
 
143
- // handle arrays
144
- case is_array($var):
145
- if(isset($var[$BEENTHERE])){
146
- $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
147
- }else{
148
- $var[$BEENTHERE] = true;
149
- $this->_inspect_array($html, $var);
150
- unset($var[$BEENTHERE]);
151
- }
152
- break;
153
-
154
- // handle objects
155
- case is_object($var):
156
- if(isset($var->$BEENTHERE)){
157
- $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
158
- }else{
159
- $var->$BEENTHERE = true;
160
- $this->_inspect_object($html, $var);
161
- unset($var->$BEENTHERE);
162
- }
163
- break;
164
-
165
- // handle simple types
166
- default:
167
- $html .= $this->_generate_keyvalue('', $var);
168
- break;
169
- }
170
-
171
- return $html . '</div>';
172
- }
173
-
174
- /**
175
- * Generates a new unique ID for tagging elements.
176
- * @staticvar int $id
177
- * @return integer An ID unique per request.
178
- */
179
- protected function _generate_dropid(){
180
- static $id = 0;
181
- return ++$id;
182
- }
183
-
184
- /**
185
- * Render a key-value pair.
186
- * @staticvar int $id Specifies element id.
187
- * @param string $key Key name.
188
- * @param mixed $val Key value.
189
- */
190
- protected function _generate_keyvalue($key, $val){
191
- $id = $this->_generate_dropid();
192
- $p = ''; // preview
193
- $d = ''; // description
194
- $t = gettype($val); // get data type
195
- $is_hash = ($t=='array') || ($t=='object');
196
-
197
- switch($t){
198
- case 'boolean':
199
- $p = $val ? 'TRUE' : 'FALSE';
200
- break;
201
- case 'integer':
202
- case 'double':
203
- $p = (string)$val;
204
- break;
205
- case 'string':
206
- $d .= ', '.strlen($val).' characters';
207
- $p = $val;
208
- break;
209
- case 'resource':
210
- $d .= ', '.get_resource_type($val).' type';
211
- $p = (string)$val;
212
- break;
213
- case 'array':
214
- $d .= ', '.count($val).' elements';
215
- break;
216
- case 'object':
217
- $d .= ', '.get_class($val).', '.count(get_object_vars($val)).' properties';
218
- break;
219
- }
220
-
221
- $cls = $this->css_class;
222
- $xcls = !$is_hash ? $cls.'_ad' : '';
223
- $html = '<a '.($is_hash?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
224
- $html .= ' <span class="'.$cls.'_a '.$xcls.'" id="'.$this->html_id.'_a'.$id.'">&#9658;</span>';
225
- $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($key).'</span>';
226
- $html .= ' <span class="'.$cls.'_d">(<span>'.ucwords($t).'</span>'.$d.')</span>';
227
- $html .= ' <span class="'.$cls.'_p '.$cls.'_t_'.$t.'">'.$this->_esc_html($p).'</span>';
228
- $html .= '</a>';
229
-
230
- if($is_hash){
231
- $html .= $this->_generate_value($val, $cls.'_v', $this->html_id.'_v'.$id);
232
- }
233
-
234
- return $html;
235
- }
236
-
237
- protected function _generate_callable($context, $callback){
238
- $id = $this->_generate_dropid();
239
- $ref = null;
240
- $name = 'Anonymous';
241
- $cls = $this->css_class;
242
-
243
- if($this->_has_reflection){
244
- if(is_null($context)){
245
- $ref = new ReflectionFunction($callback);
246
- }else{
247
- $ref = new ReflectionMethod($context, $callback);
248
- }
249
- $name = $ref->getName();
250
- }elseif(is_string($callback)){
251
- $name = $callback;
252
- }
253
-
254
- if(!is_null($ref)){
255
- $doc = $ref->getDocComment();
256
- $prms = array();
257
- foreach($ref->getParameters() as $p){
258
- $prms[] = '$' . $p->getName() . (
259
- $p->isDefaultValueAvailable()
260
- ? (
261
- ' = <span class="'.$cls.'_mv">' . (
262
- $p->isDefaultValueConstant()
263
- ? $p->getDefaultValueConstantName()
264
- : var_export($p->getDefaultValue(), true)
265
- ) . '</span>'
266
- )
267
- : ''
268
- );
269
- }
270
- }else{
271
- $doc = null;
272
- $prms = array('???');
273
- }
274
-
275
- $xcls = !$doc ? $cls.'_ad' : '';
276
- $html = '<a class="'.$cls.'_c" '.($doc?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
277
- $html .= ' <span class="'.$cls.'_a '.$xcls.'">&#9658;</span>';
278
- $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($name).'<span class="'.$cls.'_ma">(<span>'.implode(', ', $prms).'</span>)</span></span>';
279
- $html .= '</a>';
280
-
281
- if($doc){
282
- $html .= '<div id="'.$this->html_id.'_v'.$id.'" class="nice_r_v '.$this->css_class.'_t_comment">';
283
- $html .= nl2br(str_replace(' ', '&nbsp;', $this->_esc_html($doc)));
284
- $html .= '</div>';
285
- }
286
-
287
- return $html;
288
- }
289
- }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * Inspects and prints out PHP values as HTML in a nicer way than print_r().
5
+ * @author Christian Sciberras <christian@sciberras.me>
6
+ * @copyright (c) 2013, Christian Sciberras
7
+ * @license https://raw.github.com/uuf6429/nice_r/master/LICENSE MIT License
8
+ * @link https://github.com/uuf6429/nice_r GitHub Repository
9
+ * @version 2.0
10
+ * @since 2.0
11
+ */
12
+ class WSAL_Nicer
13
+ {
14
+ protected $value;
15
+
16
+ /**
17
+ * Allows modification of CSS class prefix.
18
+ * @var string
19
+ */
20
+ public $css_class = 'nice_r';
21
+
22
+ /**
23
+ * Allows modification of HTML id prefix.
24
+ * @var string
25
+ */
26
+ public $html_id = 'nice_r_v';
27
+
28
+ /**
29
+ * Allows modification of JS function used to toggle sections.
30
+ * @var string
31
+ */
32
+ public $js_func = 'nice_r_toggle';
33
+
34
+ /**
35
+ * Whether to inspect and output methods for objects or not.
36
+ * @var boolean
37
+ */
38
+ public $inspect_methods = false;
39
+
40
+ /**
41
+ * Since PHP does not support private constants, we'll have to settle for private static fields.
42
+ * @var string
43
+ */
44
+ protected static $BEEN_THERE = '__NICE_R_INFINITE_RECURSION_PROTECT__';
45
+
46
+ protected $_has_reflection = null;
47
+
48
+ /**
49
+ * Constructs new renderer instance.
50
+ * @param mixed $value The value to inspect and render.
51
+ * @param boolean $inspectMethods Whether to inspect and output methods for objects or not.
52
+ */
53
+ public function __construct($value, $inspectMethods = false)
54
+ {
55
+ $this->value = $value;
56
+ $this->inspect_methods = $inspectMethods;
57
+
58
+ if (is_null($this->_has_reflection)) {
59
+ $this->_has_reflection = class_exists('ReflectionClass');
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Generates the inspector HTML and returns it as a string.
65
+ * @return string Generated HTML.
66
+ */
67
+ public function generate()
68
+ {
69
+ return $this->_generate_value($this->value, $this->css_class);
70
+ }
71
+
72
+ /**
73
+ * Renders the inspector HTML directly to the browser.
74
+ */
75
+ public function render()
76
+ {
77
+ echo $this->generate();
78
+ }
79
 
80
+ /**
81
+ * Converts a string to HTML, encoding any special characters.
82
+ * @param string $text The original string.
83
+ * @return string The string as HTML.
84
+ */
85
+ protected function _esc_html($text)
86
+ {
87
+ return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
88
+ }
89
+
90
+ protected function _inspect_array(&$html, &$var)
91
+ {
92
+ $has_subitems = false;
93
+
94
+ foreach ($var as $k => $v) {
95
+ if ($k !== self::$BEEN_THERE) {
96
+ $html .= $this->_generate_keyvalue($k, $v);
97
+ $has_subitems = true;
98
+ }
99
+ }
100
+
101
+ if (!$has_subitems) {
102
+ $html .= '<span class="'.$this->css_class.'_ni">Empty Array</span>';
103
+ }
104
+ }
105
+
106
+ protected function _inspect_object(&$html, &$var)
107
+ {
108
+ // render properties
109
+ $has_subitems = false;
110
+
111
+ foreach ((array)$var as $k => $v) {
112
+ if ($k !== self::$BEEN_THERE) {
113
+ $html .= $this->_generate_keyvalue($k, $v);
114
+ $has_subitems = true;
115
+ }
116
+ }
117
+
118
+ if (!$has_subitems) {
119
+ $html .= '<span class="'.$this->css_class.'_ni">No Properties</span>';
120
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
+ // render methods (if enabled)
123
+ if ($this->inspect_methods) {
124
+ $has_subitems = false;
125
+
126
+ foreach ((array)get_class_methods($var) as $method) {
127
+ $html .= $this->_generate_callable($var, $method);
128
+ $has_subitems = true;
129
+ }
130
+
131
+ if (!$has_subitems) {
132
+ $html .= '<span class="'.$this->css_class.'_ni">No Methods</span>';
133
+ }
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Render a single particular value.
139
+ * @param mixed $var The value to render
140
+ * @param string $class Parent CSS class.
141
+ * @param string $id Item HTML id.
142
+ */
143
+ protected function _generate_value($var, $class = '', $id = '')
144
+ {
145
+ $BEENTHERE = self::$BEEN_THERE;
146
+ $class .= ' '.$this->css_class.'_t_'.gettype($var);
147
+
148
+ $html = '<div id="'.$id.'" class="'.$class.'">';
149
+ switch (true) {
150
+ // handle arrays
151
+ case is_array($var):
152
+ if (isset($var[$BEENTHERE])) {
153
+ $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
154
+ } else {
155
+ $var[$BEENTHERE] = true;
156
+ $this->_inspect_array($html, $var);
157
+ unset($var[$BEENTHERE]);
158
+ }
159
+ break;
160
 
161
+ // handle objects
162
+ case is_object($var):
163
+ if (isset($var->$BEENTHERE)) {
164
+ $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
165
+ } else {
166
+ $var->$BEENTHERE = true;
167
+ $this->_inspect_object($html, $var);
168
+ unset($var->$BEENTHERE);
169
+ }
170
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
+ // handle simple types
173
+ default:
174
+ $html .= $this->_generate_keyvalue('', $var);
175
+ break;
176
+ }
177
+
178
+ return $html . '</div>';
179
+ }
180
+
181
+ /**
182
+ * Generates a new unique ID for tagging elements.
183
+ * @staticvar int $id
184
+ * @return integer An ID unique per request.
185
+ */
186
+ protected function _generate_dropid()
187
+ {
188
+ static $id = 0;
189
+ return ++$id;
190
+ }
191
+
192
+ /**
193
+ * Render a key-value pair.
194
+ * @staticvar int $id Specifies element id.
195
+ * @param string $key Key name.
196
+ * @param mixed $val Key value.
197
+ */
198
+ protected function _generate_keyvalue($key, $val)
199
+ {
200
+ $id = $this->_generate_dropid();
201
+ $p = ''; // preview
202
+ $d = ''; // description
203
+ $t = gettype($val); // get data type
204
+ $is_hash = ($t=='array') || ($t=='object');
205
+
206
+ switch ($t) {
207
+ case 'boolean':
208
+ $p = $val ? 'TRUE' : 'FALSE';
209
+ break;
210
+ case 'integer':
211
+ case 'double':
212
+ $p = (string)$val;
213
+ break;
214
+ case 'string':
215
+ $d .= ', '.strlen($val).' characters';
216
+ $p = $val;
217
+ break;
218
+ case 'resource':
219
+ $d .= ', '.get_resource_type($val).' type';
220
+ $p = (string)$val;
221
+ break;
222
+ case 'array':
223
+ $d .= ', '.count($val).' elements';
224
+ break;
225
+ case 'object':
226
+ $d .= ', '.get_class($val).', '.count(get_object_vars($val)).' properties';
227
+ break;
228
+ }
229
+
230
+ $cls = $this->css_class;
231
+ $xcls = !$is_hash ? $cls.'_ad' : '';
232
+ $html = '<a '.($is_hash?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
233
+ $html .= ' <span class="'.$cls.'_a '.$xcls.'" id="'.$this->html_id.'_a'.$id.'">&#9658;</span>';
234
+ $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($key).'</span>';
235
+ $html .= ' <span class="'.$cls.'_d">(<span>'.ucwords($t).'</span>'.$d.')</span>';
236
+ $html .= ' <span class="'.$cls.'_p '.$cls.'_t_'.$t.'">'.$this->_esc_html($p).'</span>';
237
+ $html .= '</a>';
238
+
239
+ if ($is_hash) {
240
+ $html .= $this->_generate_value($val, $cls.'_v', $this->html_id.'_v'.$id);
241
+ }
242
+
243
+ return $html;
244
+ }
245
+
246
+ protected function _generate_callable($context, $callback)
247
+ {
248
+ $id = $this->_generate_dropid();
249
+ $ref = null;
250
+ $name = 'Anonymous';
251
+ $cls = $this->css_class;
252
+
253
+ if ($this->_has_reflection) {
254
+ if (is_null($context)) {
255
+ $ref = new ReflectionFunction($callback);
256
+ } else {
257
+ $ref = new ReflectionMethod($context, $callback);
258
+ }
259
+ $name = $ref->getName();
260
+ } elseif (is_string($callback)) {
261
+ $name = $callback;
262
+ }
263
+
264
+ if (!is_null($ref)) {
265
+ $doc = $ref->getDocComment();
266
+ $prms = array();
267
+ foreach ($ref->getParameters() as $p) {
268
+ $prms[] = '$' . $p->getName() . (
269
+ $p->isDefaultValueAvailable()
270
+ ? (
271
+ ' = <span class="'.$cls.'_mv">' . (
272
+ $p->isDefaultValueConstant()
273
+ ? $p->getDefaultValueConstantName()
274
+ : var_export($p->getDefaultValue(), true)
275
+ ) . '</span>'
276
+ )
277
+ : ''
278
+ );
279
+ }
280
+ } else {
281
+ $doc = null;
282
+ $prms = array('???');
283
+ }
284
+
285
+ $xcls = !$doc ? $cls.'_ad' : '';
286
+ $html = '<a class="'.$cls.'_c" '.($doc?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
287
+ $html .= ' <span class="'.$cls.'_a '.$xcls.'">&#9658;</span>';
288
+ $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($name).'<span class="'.$cls.'_ma">(<span>'.implode(', ', $prms).'</span>)</span></span>';
289
+ $html .= '</a>';
290
+
291
+ if ($doc) {
292
+ $html .= '<div id="'.$this->html_id.'_v'.$id.'" class="nice_r_v '.$this->css_class.'_t_comment">';
293
+ $html .= nl2br(str_replace(' ', '&nbsp;', $this->_esc_html($doc)));
294
+ $html .= '</div>';
295
+ }
296
+
297
+ return $html;
298
+ }
299
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/SensorManager.php CHANGED
@@ -1,13 +1,18 @@
1
  <?php
2
-
3
- final class WSAL_SensorManager extends WSAL_AbstractSensor {
4
-
 
 
 
 
5
  /**
6
  * @var WSAL_AbstractSensor[]
7
  */
8
  protected $sensors = array();
9
 
10
- public function __construct(WpSecurityAuditLog $plugin) {
 
11
  parent::__construct($plugin);
12
 
13
  foreach (glob(dirname(__FILE__) . '/Sensors/*.php') as $file) {
@@ -29,13 +34,15 @@ final class WSAL_SensorManager extends WSAL_AbstractSensor {
29
  }
30
  }
31
 
32
- public function HookEvents() {
 
33
  foreach ($this->sensors as $sensor) {
34
  $sensor->HookEvents();
35
  }
36
  }
37
 
38
- public function GetSensors() {
 
39
  return $this->sensors;
40
  }
41
 
@@ -43,7 +50,8 @@ final class WSAL_SensorManager extends WSAL_AbstractSensor {
43
  * Add new sensor from file inside autoloader path.
44
  * @param string $file Path to file.
45
  */
46
- public function AddFromFile($file) {
 
47
  $this->AddFromClass($this->plugin->GetClassFileClassName($file));
48
  }
49
 
@@ -51,7 +59,8 @@ final class WSAL_SensorManager extends WSAL_AbstractSensor {
51
  * Add new sensor given class name.
52
  * @param string $class Class name.
53
  */
54
- public function AddFromClass($class) {
 
55
  $this->AddInstance(new $class($this->plugin));
56
  }
57
 
@@ -59,7 +68,8 @@ final class WSAL_SensorManager extends WSAL_AbstractSensor {
59
  * Add newly created sensor to list.
60
  * @param WSAL_AbstractSensor $sensor The new sensor.
61
  */
62
- public function AddInstance(WSAL_AbstractSensor $sensor) {
 
63
  $this->sensors[] = $sensor;
64
  }
65
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * This Class load all the sensors and initialize them.
6
+ */
7
+ final class WSAL_SensorManager extends WSAL_AbstractSensor
8
+ {
9
  /**
10
  * @var WSAL_AbstractSensor[]
11
  */
12
  protected $sensors = array();
13
 
14
+ public function __construct(WpSecurityAuditLog $plugin)
15
+ {
16
  parent::__construct($plugin);
17
 
18
  foreach (glob(dirname(__FILE__) . '/Sensors/*.php') as $file) {
34
  }
35
  }
36
 
37
+ public function HookEvents()
38
+ {
39
  foreach ($this->sensors as $sensor) {
40
  $sensor->HookEvents();
41
  }
42
  }
43
 
44
+ public function GetSensors()
45
+ {
46
  return $this->sensors;
47
  }
48
 
50
  * Add new sensor from file inside autoloader path.
51
  * @param string $file Path to file.
52
  */
53
+ public function AddFromFile($file)
54
+ {
55
  $this->AddFromClass($this->plugin->GetClassFileClassName($file));
56
  }
57
 
59
  * Add new sensor given class name.
60
  * @param string $class Class name.
61
  */
62
+ public function AddFromClass($class)
63
+ {
64
  $this->AddInstance(new $class($this->plugin));
65
  }
66
 
68
  * Add newly created sensor to list.
69
  * @param WSAL_AbstractSensor $sensor The new sensor.
70
  */
71
+ public function AddInstance(WSAL_AbstractSensor $sensor)
72
+ {
73
  $this->sensors[] = $sensor;
74
  }
75
  }
classes/Sensors/BBPress.php CHANGED
@@ -1,11 +1,39 @@
1
  <?php
2
  /**
3
- * Support for BBPress Forum Plugin
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  */
5
  class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
6
  {
 
 
 
7
  protected $_OldLink = null;
8
 
 
 
 
9
  public function HookEvents()
10
  {
11
  if (current_user_can("edit_posts")) {
@@ -17,6 +45,9 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
17
  add_action('untrash_post', array($this, 'EventForumUntrashed'));
18
  }
19
 
 
 
 
20
  public function EventAdminInit()
21
  {
22
  // load old data, if applicable
@@ -25,6 +56,10 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
25
  $this->TriggerAjaxChange();
26
  }
27
 
 
 
 
 
28
  protected function RetrieveOldData()
29
  {
30
  if (isset($_POST) && isset($_POST['post_ID'])
@@ -36,6 +71,12 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
36
  }
37
  }
38
 
 
 
 
 
 
 
39
  public function CheckForumChange($post_ID, $newpost, $oldpost)
40
  {
41
  if ($this->CheckBBPress($oldpost)) {
@@ -60,7 +101,8 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
60
  }
61
 
62
  /**
63
- * Permanently deleted
 
64
  */
65
  public function EventForumDeleted($post_id)
66
  {
@@ -78,7 +120,8 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
78
  }
79
 
80
  /**
81
- * Moved to Trash
 
82
  */
83
  public function EventForumTrashed($post_id)
84
  {
@@ -96,7 +139,8 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
96
  }
97
 
98
  /**
99
- * Restored from Trash
 
100
  */
101
  public function EventForumUntrashed($post_id)
102
  {
@@ -113,6 +157,11 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
113
  }
114
  }
115
 
 
 
 
 
 
116
  private function CheckBBPress($post)
117
  {
118
  switch ($post->post_type) {
@@ -125,6 +174,12 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
125
  }
126
  }
127
 
 
 
 
 
 
 
128
  private function EventForumCreation($old_post, $new_post)
129
  {
130
  $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
@@ -153,6 +208,11 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
153
  return 0;
154
  }
155
 
 
 
 
 
 
156
  private function EventForumChangedVisibility($post)
157
  {
158
  $result = 0;
@@ -192,6 +252,11 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
192
  return $result;
193
  }
194
 
 
 
 
 
 
195
  private function EventForumChangedType($post)
196
  {
197
  $result = 0;
@@ -242,6 +307,11 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
242
  return $result;
243
  }
244
 
 
 
 
 
 
245
  private function EventForumChangedStatus($post)
246
  {
247
  $result = 0;
@@ -294,6 +364,12 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
294
  return $result;
295
  }
296
 
 
 
 
 
 
 
297
  private function EventForumChanged($old_post, $new_post)
298
  {
299
  $editorLink = $this->GetEditorLink($new_post);
@@ -356,6 +432,11 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
356
  return 0;
357
  }
358
 
 
 
 
 
 
359
  private function EventForumByCode($post, $event)
360
  {
361
  $editorLink = $this->GetEditorLink($post);
@@ -366,6 +447,11 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
366
  ));
367
  }
368
 
 
 
 
 
 
369
  private function EventTopicByCode($post, $event)
370
  {
371
  $editorLink = $this->GetEditorLink($post);
@@ -378,6 +464,7 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
378
 
379
  /**
380
  * Trigger of ajax events generated in the Topic Grid
 
381
  */
382
  public function TriggerAjaxChange()
383
  {
@@ -432,6 +519,11 @@ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
432
  }
433
  }
434
 
 
 
 
 
 
435
  private function GetEditorLink($post)
436
  {
437
  $name = 'EditorLink';
1
  <?php
2
  /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Support for BBPress Forum Plugin.
6
+ *
7
+ * 8000 User created new forum
8
+ * 8001 User changed status of a forum
9
+ * 8002 User changed visibility of a forum
10
+ * 8003 User changed the URL of a forum
11
+ * 8004 User changed order of a forum
12
+ * 8005 User moved forum to trash
13
+ * 8006 User permanently deleted forum
14
+ * 8007 User restored forum from trash
15
+ * 8008 User changed the parent of a forum
16
+ * 8011 User changed type of a forum
17
+ * 8014 User created new topic
18
+ * 8015 User changed status of a topic
19
+ * 8016 User changed type of a topic
20
+ * 8017 User changed URL of a topic
21
+ * 8018 User changed the forum of a topic
22
+ * 8019 User moved topic to trash
23
+ * 8020 User permanently deleted topic
24
+ * 8021 User restored topic from trash
25
+ * 8022 User changed visibility of a topic
26
  */
27
  class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
28
  {
29
+ /**
30
+ * @var string old permalink
31
+ */
32
  protected $_OldLink = null;
33
 
34
+ /**
35
+ * Listening to events using WP hooks.
36
+ */
37
  public function HookEvents()
38
  {
39
  if (current_user_can("edit_posts")) {
45
  add_action('untrash_post', array($this, 'EventForumUntrashed'));
46
  }
47
 
48
+ /**
49
+ * Triggered when a user accesses the admin area.
50
+ */
51
  public function EventAdminInit()
52
  {
53
  // load old data, if applicable
56
  $this->TriggerAjaxChange();
57
  }
58
 
59
+ /**
60
+ * Retrieve Old data.
61
+ * @global mixed $_POST post data
62
+ */
63
  protected function RetrieveOldData()
64
  {
65
  if (isset($_POST) && isset($_POST['post_ID'])
71
  }
72
  }
73
 
74
+ /**
75
+ * Calls event forum changes.
76
+ * @param integer $post_ID post ID
77
+ * @param stdClass $newpost the new post
78
+ * @param stdClass $oldpost the old post
79
+ */
80
  public function CheckForumChange($post_ID, $newpost, $oldpost)
81
  {
82
  if ($this->CheckBBPress($oldpost)) {
101
  }
102
 
103
  /**
104
+ * Permanently deleted.
105
+ * @param integer $post_id post ID
106
  */
107
  public function EventForumDeleted($post_id)
108
  {
120
  }
121
 
122
  /**
123
+ * Moved to Trash.
124
+ * @param integer $post_id post ID
125
  */
126
  public function EventForumTrashed($post_id)
127
  {
139
  }
140
 
141
  /**
142
+ * Restored from Trash.
143
+ * @param integer $post_id post ID
144
  */
145
  public function EventForumUntrashed($post_id)
146
  {
157
  }
158
  }
159
 
160
+ /**
161
+ * Check post type.
162
+ * @param stdClass $post post
163
+ * @return boolean
164
+ */
165
  private function CheckBBPress($post)
166
  {
167
  switch ($post->post_type) {
174
  }
175
  }
176
 
177
+ /**
178
+ * Event post creation.
179
+ * @param stdClass $old_post the old post
180
+ * @param stdClass $new_post the new post
181
+ * @return boolean
182
+ */
183
  private function EventForumCreation($old_post, $new_post)
184
  {
185
  $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
208
  return 0;
209
  }
210
 
211
+ /**
212
+ * Event post changed visibility.
213
+ * @param stdClass $post the post
214
+ * @return boolean $result
215
+ */
216
  private function EventForumChangedVisibility($post)
217
  {
218
  $result = 0;
252
  return $result;
253
  }
254
 
255
+ /**
256
+ * Event post changed type.
257
+ * @param stdClass $post the post
258
+ * @return boolean $result
259
+ */
260
  private function EventForumChangedType($post)
261
  {
262
  $result = 0;
307
  return $result;
308
  }
309
 
310
+ /**
311
+ * Event post changed status.
312
+ * @param stdClass $post the post
313
+ * @return boolean $result
314
+ */
315
  private function EventForumChangedStatus($post)
316
  {
317
  $result = 0;
364
  return $result;
365
  }
366
 
367
+ /**
368
+ * Event post changed (order, parent, URL).
369
+ * @param stdClass $old_post the old post
370
+ * @param stdClass $new_post the new post
371
+ * @return boolean $result
372
+ */
373
  private function EventForumChanged($old_post, $new_post)
374
  {
375
  $editorLink = $this->GetEditorLink($new_post);
432
  return 0;
433
  }
434
 
435
+ /**
436
+ * Trigger Event (Forum).
437
+ * @param stdClass $post the post
438
+ * @param integer $event event code
439
+ */
440
  private function EventForumByCode($post, $event)
441
  {
442
  $editorLink = $this->GetEditorLink($post);
447
  ));
448
  }
449
 
450
+ /**
451
+ * Trigger Event (Topic).
452
+ * @param stdClass $post the post
453
+ * @param integer $event event code
454
+ */
455
  private function EventTopicByCode($post, $event)
456
  {
457
  $editorLink = $this->GetEditorLink($post);
464
 
465
  /**
466
  * Trigger of ajax events generated in the Topic Grid
467
+ * @global mixed $_GET Get data
468
  */
469
  public function TriggerAjaxChange()
470
  {
519
  }
520
  }
521
 
522
+ /**
523
+ * Get editor link.
524
+ * @param stdClass $post the post
525
+ * @return array $aLink name and value link
526
+ */
527
  private function GetEditorLink($post)
528
  {
529
  $name = 'EditorLink';
classes/Sensors/Comments.php CHANGED
@@ -1,8 +1,25 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_Comments extends WSAL_AbstractSensor
4
  {
5
-
 
 
6
  public function HookEvents()
7
  {
8
  add_action('edit_comment', array($this, 'EventCommentEdit'), 10, 1);
@@ -15,12 +32,22 @@ class WSAL_Sensors_Comments extends WSAL_AbstractSensor
15
  add_action('comment_post', array($this, 'EventComment'), 10, 2);
16
  }
17
 
 
 
 
 
18
  public function EventCommentEdit($comment_ID)
19
  {
20
  $comment = get_comment($comment_ID);
21
  $this->EventGeneric($comment_ID, 2093);
22
  }
23
 
 
 
 
 
 
 
24
  public function EventCommentApprove($new_status, $old_status, $comment)
25
  {
26
  if (!empty($comment) && $old_status != $new_status) {
@@ -42,26 +69,46 @@ class WSAL_Sensors_Comments extends WSAL_AbstractSensor
42
  }
43
  }
44
 
 
 
 
 
45
  public function EventCommentSpam($comment_ID)
46
  {
47
  $this->EventGeneric($comment_ID, 2094);
48
  }
49
 
 
 
 
 
50
  public function EventCommentUnspam($comment_ID)
51
  {
52
  $this->EventGeneric($comment_ID, 2095);
53
  }
54
 
 
 
 
 
55
  public function EventCommentTrash($comment_ID)
56
  {
57
  $this->EventGeneric($comment_ID, 2096);
58
  }
59
 
 
 
 
 
60
  public function EventCommentUntrash($comment_ID)
61
  {
62
  $this->EventGeneric($comment_ID, 2097);
63
  }
64
 
 
 
 
 
65
  public function EventCommentDeleted($comment_ID)
66
  {
67
  $this->EventGeneric($comment_ID, 2098);
@@ -100,6 +147,11 @@ class WSAL_Sensors_Comments extends WSAL_AbstractSensor
100
  }
101
  }
102
 
 
 
 
 
 
103
  private function EventGeneric($comment_ID, $alert_code)
104
  {
105
  $comment = get_comment($comment_ID);
@@ -120,6 +172,8 @@ class WSAL_Sensors_Comments extends WSAL_AbstractSensor
120
  /**
121
  * Shows the username if the comment is owned by a user
122
  * and the email if the comment was posted by a non WordPress user
 
 
123
  */
124
  private function CheckAuthor($comment)
125
  {
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Wordpress comments.
6
+ *
7
+ * 2090 User approved a comment
8
+ * 2091 User unapproved a comment
9
+ * 2092 User replied to a comment
10
+ * 2093 User edited a comment
11
+ * 2094 User marked a comment as Spam
12
+ * 2095 User marked a comment as Not Spam
13
+ * 2096 User moved a comment to trash
14
+ * 2097 User restored a comment from the trash
15
+ * 2098 User permanently deleted a comment
16
+ * 2099 User posted a comment
17
+ */
18
  class WSAL_Sensors_Comments extends WSAL_AbstractSensor
19
  {
20
+ /**
21
+ * Listening to events using WP hooks.
22
+ */
23
  public function HookEvents()
24
  {
25
  add_action('edit_comment', array($this, 'EventCommentEdit'), 10, 1);
32
  add_action('comment_post', array($this, 'EventComment'), 10, 2);
33
  }
34
 
35
+ /**
36
+ * Trigger comment edit.
37
+ * @param integer $comment_ID comment ID
38
+ */
39
  public function EventCommentEdit($comment_ID)
40
  {
41
  $comment = get_comment($comment_ID);
42
  $this->EventGeneric($comment_ID, 2093);
43
  }
44
 
45
+ /**
46
+ * Trigger comment status.
47
+ * @param string $new_status new status
48
+ * @param string $old_status old status
49
+ * @param stdClass $comment comment
50
+ */
51
  public function EventCommentApprove($new_status, $old_status, $comment)
52
  {
53
  if (!empty($comment) && $old_status != $new_status) {
69
  }
70
  }
71
 
72
+ /**
73
+ * Trigger comment spam.
74
+ * @param integer $comment_ID comment ID
75
+ */
76
  public function EventCommentSpam($comment_ID)
77
  {
78
  $this->EventGeneric($comment_ID, 2094);
79
  }
80
 
81
+ /**
82
+ * Trigger comment unspam.
83
+ * @param integer $comment_ID comment ID
84
+ */
85
  public function EventCommentUnspam($comment_ID)
86
  {
87
  $this->EventGeneric($comment_ID, 2095);
88
  }
89
 
90
+ /**
91
+ * Trigger comment trash.
92
+ * @param integer $comment_ID comment ID
93
+ */
94
  public function EventCommentTrash($comment_ID)
95
  {
96
  $this->EventGeneric($comment_ID, 2096);
97
  }
98
 
99
+ /**
100
+ * Trigger comment untrash.
101
+ * @param integer $comment_ID comment ID
102
+ */
103
  public function EventCommentUntrash($comment_ID)
104
  {
105
  $this->EventGeneric($comment_ID, 2097);
106
  }
107
 
108
+ /**
109
+ * Trigger comment deleted.
110
+ * @param integer $comment_ID comment ID
111
+ */
112
  public function EventCommentDeleted($comment_ID)
113
  {
114
  $this->EventGeneric($comment_ID, 2098);
147
  }
148
  }
149
 
150
+ /**
151
+ * Trigger generic event.
152
+ * @param integer $comment_ID comment ID
153
+ * @param integer $alert_code event code
154
+ */
155
  private function EventGeneric($comment_ID, $alert_code)
156
  {
157
  $comment = get_comment($comment_ID);
172
  /**
173
  * Shows the username if the comment is owned by a user
174
  * and the email if the comment was posted by a non WordPress user
175
+ * @param stdClass $comment comment
176
+ * @return string author username or email
177
  */
178
  private function CheckAuthor($comment)
179
  {
classes/Sensors/Content.php CHANGED
@@ -1,8 +1,113 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_Content extends WSAL_AbstractSensor
4
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  public function HookEvents()
7
  {
8
  if (current_user_can("edit_posts")) {
@@ -22,6 +127,14 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
22
  add_filter('post_edit_form_tag', array($this, 'EditingPost'), 10, 1);
23
  }
24
 
 
 
 
 
 
 
 
 
25
  protected function GetEventTypeForPostType($post, $typePost, $typePage, $typeCustom)
26
  {
27
  switch ($post->post_type) {
@@ -34,12 +147,9 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
34
  }
35
  }
36
 
37
- protected $_OldPost = null;
38
- protected $_OldLink = null;
39
- protected $_OldCats = null;
40
- protected $_OldTmpl = null;
41
- protected $_OldStky = null;
42
-
43
  public function EventWordpressInit()
44
  {
45
  // load old data, if applicable
@@ -48,6 +158,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
48
  $this->CheckCategoryDeletion();
49
  }
50
 
 
 
 
 
51
  protected function RetrieveOldData()
52
  {
53
  if (isset($_POST) && isset($_POST['post_ID'])
@@ -63,6 +177,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
63
  }
64
  }
65
 
 
 
 
 
 
66
  protected function GetPostTemplate($post)
67
  {
68
  $id = $post->ID;
@@ -84,11 +203,22 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
84
  return get_query_template('page', $templates);
85
  }
86
 
 
 
 
 
 
87
  protected function GetPostCategories($post)
88
  {
89
  return wp_get_post_categories($post->ID, array('fields' => 'names'));
90
  }
91
 
 
 
 
 
 
 
92
  public function EventPostChanged($newStatus, $oldStatus, $post)
93
  {
94
  // ignorable states
@@ -146,6 +276,12 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
146
  }
147
  }
148
 
 
 
 
 
 
 
149
  protected function CheckPostCreation($oldPost, $newPost)
150
  {
151
  $WPActions = array('editpost', 'heartbeat');
@@ -191,6 +327,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
191
  }
192
  }
193
 
 
 
 
 
194
  public function EventPublishFuture($post_id)
195
  {
196
  $post = get_post($post_id);
@@ -208,6 +348,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
208
  }
209
  }
210
 
 
 
 
 
211
  public function EventPostDeleted($post_id)
212
  {
213
  $post = get_post($post_id);
@@ -234,6 +378,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
234
  }
235
  }
236
 
 
 
 
 
237
  public function EventPostTrashed($post_id)
238
  {
239
  $post = get_post($post_id);
@@ -251,6 +399,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
251
  ));
252
  }
253
 
 
 
 
 
254
  public function EventPostUntrashed($post_id)
255
  {
256
  $post = get_post($post_id);
@@ -267,6 +419,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
267
  ));
268
  }
269
 
 
 
 
 
 
270
  protected function CheckDateChange($oldpost, $newpost)
271
  {
272
  $from = strtotime($oldpost->post_date);
@@ -294,7 +451,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
294
  return 0;
295
  }
296
 
297
- // Revision used
 
 
 
 
298
  protected function CheckReviewPendingChange($oldpost, $newpost)
299
  {
300
  if ($oldpost->post_status == 'pending') {
@@ -310,6 +471,12 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
310
  return 0;
311
  }
312
 
 
 
 
 
 
 
313
  protected function CheckCategoriesChange($oldCats, $newCats, $post)
314
  {
315
  $oldCats = implode(', ', $oldCats);
@@ -331,6 +498,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
331
  }
332
  }
333
 
 
 
 
 
 
334
  protected function CheckAuthorChange($oldpost, $newpost)
335
  {
336
  if ($oldpost->post_author != $newpost->post_author) {
@@ -352,6 +524,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
352
  }
353
  }
354
 
 
 
 
 
 
355
  protected function CheckStatusChange($oldpost, $newpost)
356
  {
357
  if ($oldpost->post_status != $newpost->post_status) {
@@ -382,6 +559,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
382
  }
383
  }
384
 
 
 
 
 
 
385
  protected function CheckParentChange($oldpost, $newpost)
386
  {
387
  if ($oldpost->post_parent != $newpost->post_parent) {
@@ -403,6 +585,12 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
403
  }
404
  }
405
 
 
 
 
 
 
 
406
  protected function CheckPermalinkChange($oldLink, $newLink, $post)
407
  {
408
  if ($oldLink != $newLink) {
@@ -421,6 +609,13 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
421
  return 0;
422
  }
423
 
 
 
 
 
 
 
 
424
  protected function CheckVisibilityChange($oldpost, $newpost, $oldStatus, $newStatus)
425
  {
426
  if ($oldStatus == 'draft' || $newStatus == 'draft') {
@@ -461,6 +656,12 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
461
  }
462
  }
463
 
 
 
 
 
 
 
464
  protected function CheckTemplateChange($oldTmpl, $newTmpl, $post)
465
  {
466
  if ($oldTmpl != $newTmpl) {
@@ -482,6 +683,12 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
482
  }
483
  }
484
 
 
 
 
 
 
 
485
  protected function CheckStickyChange($oldStky, $newStky, $post)
486
  {
487
  if ($oldStky != $newStky) {
@@ -498,6 +705,12 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
498
  }
499
  }
500
 
 
 
 
 
 
 
501
  public function CheckModificationChange($post_ID, $oldpost, $newpost)
502
  {
503
  if ($this->CheckOtherSensors($oldpost)) {
@@ -541,6 +754,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
541
  }
542
  }
543
 
 
 
 
 
544
  public function EventCategoryCreation($category_id)
545
  {
546
  $category = get_category($category_id);
@@ -552,6 +769,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
552
  ));
553
  }
554
 
 
 
 
 
555
  protected function CheckCategoryDeletion()
556
  {
557
  if (empty($_POST)) {
@@ -585,6 +806,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
585
  }
586
  }
587
 
 
 
 
 
588
  public function EventChangedCategoryParent()
589
  {
590
  if (empty($_POST)) {
@@ -615,6 +840,12 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
615
  }
616
  }
617
 
 
 
 
 
 
 
618
  private function CheckAutoDraft($code, $title)
619
  {
620
  if ($code == 2008 && $title == "auto-draft") {
@@ -629,6 +860,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
629
  }
630
  }
631
 
 
 
 
 
 
632
  private function getRevisionLink($revision_id)
633
  {
634
  if (!empty($revision_id)) {
@@ -638,6 +874,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
638
  }
639
  }
640
 
 
 
 
 
 
641
  private function getCategoryLink($category_id)
642
  {
643
  if (!empty($category_id)) {
@@ -650,6 +891,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
650
  /**
651
  * Ignore post from BBPress, WooCommerce Plugin
652
  * Triggered on the Sensors
 
653
  */
654
  private function CheckOtherSensors($post)
655
  {
@@ -665,7 +907,9 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
665
  }
666
 
667
  /**
668
- * Triggered after save post for add revision link
 
 
669
  */
670
  public function SetRevisionLink($post_id, $post, $update)
671
  {
@@ -686,7 +930,9 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
686
  }
687
 
688
  /**
689
- * Alerts for Viewing of Posts, Pages and Custom Posts
 
 
690
  */
691
  public function ViewingPost($title, $post = null)
692
  {
@@ -698,7 +944,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
698
  $currentPath = $_SERVER["REQUEST_URI"];
699
  if (!empty($_SERVER["HTTP_REFERER"])
700
  && strpos($_SERVER["HTTP_REFERER"], $currentPath) !== false) {
701
- //Ignore this if we were on the same page so we avoid double audit entries
702
  return $title;
703
  }
704
  if (!empty($post->post_title)) {
@@ -715,7 +961,8 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
715
  }
716
 
717
  /**
718
- * Alerts for Editing of Posts, Pages and Custom Posts
 
719
  */
720
  public function EditingPost($post)
721
  {
@@ -747,7 +994,9 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
747
  }
748
 
749
  /**
750
- * Check if the alert was triggered
 
 
751
  */
752
  private function WasTriggered($alert_id)
753
  {
@@ -763,6 +1012,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
763
  return false;
764
  }
765
 
 
 
 
 
 
766
  private function CheckTitleChange($oldpost, $newpost)
767
  {
768
  if ($oldpost->post_title != $newpost->post_title) {
@@ -778,6 +1032,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
778
  return 0;
779
  }
780
 
 
 
 
 
 
781
  private function CheckCommentsPings($oldpost, $newpost)
782
  {
783
  $result = 0;
@@ -818,6 +1077,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
818
  return $result;
819
  }
820
 
 
 
 
 
 
821
  private function GetCommentsPingsEvent($post, $status)
822
  {
823
  if ($post->post_type == 'post') {
@@ -852,6 +1116,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
852
  return $event;
853
  }
854
 
 
 
 
 
 
855
  private function GetEditorLink($post)
856
  {
857
  $name = 'EditorLink';
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Wordpress contents (posts, pages and custom posts).
6
+ *
7
+ * 2000 User created a new blog post and saved it as draft
8
+ * 2001 User published a blog post
9
+ * 2002 User modified a published blog post
10
+ * 2003 User modified a draft blog post
11
+ * 2008 User permanently deleted a blog post from the trash
12
+ * 2012 User moved a blog post to the trash
13
+ * 2014 User restored a blog post from trash
14
+ * 2016 User changed blog post category
15
+ * 2017 User changed blog post URL
16
+ * 2019 User changed blog post author
17
+ * 2021 User changed blog post status
18
+ * 2023 User created new category
19
+ * 2024 User deleted category
20
+ * 2025 User changed the visibility of a blog post
21
+ * 2027 User changed the date of a blog post
22
+ * 2049 User set a post as sticky
23
+ * 2050 User removed post from sticky
24
+ * 2052 User changed generic tables
25
+ * 2065 User modified content for a published post
26
+ * 2068 User modified content for a draft post
27
+ * 2072 User modified content of a post
28
+ * 2073 User submitted a post for review
29
+ * 2074 User scheduled a post
30
+ * 2086 User changed title of a post
31
+ * 2100 User opened a post in the editor
32
+ * 2101 User viewed a post
33
+ * 2111 User disabled Comments/Trackbacks and Pingbacks on a published post
34
+ * 2112 User enabled Comments/Trackbacks and Pingbacks on a published post
35
+ * 2113 User disabled Comments/Trackbacks and Pingbacks on a draft post
36
+ * 2114 User enabled Comments/Trackbacks and Pingbacks on a draft post
37
+ * 2004 User created a new WordPress page and saved it as draft
38
+ * 2005 User published a WordPress page
39
+ * 2006 User modified a published WordPress page
40
+ * 2007 User modified a draft WordPress page
41
+ * 2009 User permanently deleted a page from the trash
42
+ * 2013 User moved WordPress page to the trash
43
+ * 2015 User restored a WordPress page from trash
44
+ * 2018 User changed page URL
45
+ * 2020 User changed page author
46
+ * 2022 User changed page status
47
+ * 2026 User changed the visibility of a page post
48
+ * 2028 User changed the date of a page post
49
+ * 2047 User changed the parent of a page
50
+ * 2048 User changed the template of a page
51
+ * 2066 User modified content for a published page
52
+ * 2069 User modified content for a draft page
53
+ * 2075 User scheduled a page
54
+ * 2087 User changed title of a page
55
+ * 2102 User opened a page in the editor
56
+ * 2103 User viewed a page
57
+ * 2115 User disabled Comments/Trackbacks and Pingbacks on a published page
58
+ * 2116 User enabled Comments/Trackbacks and Pingbacks on a published page
59
+ * 2117 User disabled Comments/Trackbacks and Pingbacks on a draft page
60
+ * 2118 User enabled Comments/Trackbacks and Pingbacks on a draft page
61
+ * 2029 User created a new post with custom post type and saved it as draft
62
+ * 2030 User published a post with custom post type
63
+ * 2031 User modified a post with custom post type
64
+ * 2032 User modified a draft post with custom post type
65
+ * 2033 User permanently deleted post with custom post type
66
+ * 2034 User moved post with custom post type to trash
67
+ * 2035 User restored post with custom post type from trash
68
+ * 2036 User changed the category of a post with custom post type
69
+ * 2037 User changed the URL of a post with custom post type
70
+ * 2038 User changed the author or post with custom post type
71
+ * 2039 User changed the status of post with custom post type
72
+ * 2040 User changed the visibility of a post with custom post type
73
+ * 2041 User changed the date of post with custom post type
74
+ * 2067 User modified content for a published custom post type
75
+ * 2070 User modified content for a draft custom post type
76
+ * 2076 User scheduled a custom post type
77
+ * 2088 User changed title of a custom post type
78
+ * 2104 User opened a custom post type in the editor
79
+ * 2105 User viewed a custom post type
80
+ */
81
  class WSAL_Sensors_Content extends WSAL_AbstractSensor
82
  {
83
+ /**
84
+ * @var stdClass old post
85
+ */
86
+ protected $_OldPost = null;
87
+
88
+ /**
89
+ * @var string old permalink
90
+ */
91
+ protected $_OldLink = null;
92
+
93
+ /**
94
+ * @var array old categories
95
+ */
96
+ protected $_OldCats = null;
97
 
98
+ /**
99
+ * @var string old path to file
100
+ */
101
+ protected $_OldTmpl = null;
102
+
103
+ /**
104
+ * @var boolean old post is marked as sticky
105
+ */
106
+ protected $_OldStky = null;
107
+
108
+ /**
109
+ * Listening to events using WP hooks.
110
+ */
111
  public function HookEvents()
112
  {
113
  if (current_user_can("edit_posts")) {
127
  add_filter('post_edit_form_tag', array($this, 'EditingPost'), 10, 1);
128
  }
129
 
130
+ /**
131
+ * Gets the alert code based on the type of post.
132
+ * @param stdClass $post the post
133
+ * @param integer $typePost alert code type post
134
+ * @param integer $typePage alert code type page
135
+ * @param integer $typeCustom alert code type custom
136
+ * @return integer alert code
137
+ */
138
  protected function GetEventTypeForPostType($post, $typePost, $typePage, $typeCustom)
139
  {
140
  switch ($post->post_type) {
147
  }
148
  }
149
 
150
+ /**
151
+ * Triggered when a user accesses the admin area.
152
+ */
 
 
 
153
  public function EventWordpressInit()
154
  {
155
  // load old data, if applicable
158
  $this->CheckCategoryDeletion();
159
  }
160
 
161
+ /**
162
+ * Retrieve Old data.
163
+ * @global mixed $_POST post data
164
+ */
165
  protected function RetrieveOldData()
166
  {
167
  if (isset($_POST) && isset($_POST['post_ID'])
177
  }
178
  }
179
 
180
+ /**
181
+ * Get the template path.
182
+ * @param stdClass $post the post
183
+ * @return string full path to file
184
+ */
185
  protected function GetPostTemplate($post)
186
  {
187
  $id = $post->ID;
203
  return get_query_template('page', $templates);
204
  }
205
 
206
+ /**
207
+ * Get post categories (array of category names).
208
+ * @param stdClass $post the post
209
+ * @return array list of categories
210
+ */
211
  protected function GetPostCategories($post)
212
  {
213
  return wp_get_post_categories($post->ID, array('fields' => 'names'));
214
  }
215
 
216
+ /**
217
+ * Check all the post changes.
218
+ * @param string $newStatus new status
219
+ * @param string $oldStatus old status
220
+ * @param stdClass $post the post
221
+ */
222
  public function EventPostChanged($newStatus, $oldStatus, $post)
223
  {
224
  // ignorable states
276
  }
277
  }
278
 
279
+ /**
280
+ * Check post creation.
281
+ * @global array $_POST
282
+ * @param stdClass $oldPost old post
283
+ * @param stdClass $newPost new post
284
+ */
285
  protected function CheckPostCreation($oldPost, $newPost)
286
  {
287
  $WPActions = array('editpost', 'heartbeat');
327
  }
328
  }
329
 
330
+ /**
331
+ * Post future publishing.
332
+ * @param integer $post_id post ID
333
+ */
334
  public function EventPublishFuture($post_id)
335
  {
336
  $post = get_post($post_id);
348
  }
349
  }
350
 
351
+ /**
352
+ * Post permanently deleted.
353
+ * @param integer $post_id post ID
354
+ */
355
  public function EventPostDeleted($post_id)
356
  {
357
  $post = get_post($post_id);
378
  }
379
  }
380
 
381
+ /**
382
+ * Post moved to the trash.
383
+ * @param integer $post_id post ID
384
+ */
385
  public function EventPostTrashed($post_id)
386
  {
387
  $post = get_post($post_id);
399
  ));
400
  }
401
 
402
+ /**
403
+ * Post restored from trash.
404
+ * @param integer $post_id post ID
405
+ */
406
  public function EventPostUntrashed($post_id)
407
  {
408
  $post = get_post($post_id);
419
  ));
420
  }
421
 
422
+ /**
423
+ * Post date changed.
424
+ * @param stdClass $oldPost old post
425
+ * @param stdClass $newPost new post
426
+ */
427
  protected function CheckDateChange($oldpost, $newpost)
428
  {
429
  $from = strtotime($oldpost->post_date);
451
  return 0;
452
  }
453
 
454
+ /**
455
+ * Revision used.
456
+ * @param stdClass $oldPost old post
457
+ * @param stdClass $newPost new post
458
+ */
459
  protected function CheckReviewPendingChange($oldpost, $newpost)
460
  {
461
  if ($oldpost->post_status == 'pending') {
471
  return 0;
472
  }
473
 
474
+ /**
475
+ * Categories changed.
476
+ * @param array $oldCats old categories
477
+ * @param array $newCats new categories
478
+ * @param stdClass $post the post
479
+ */
480
  protected function CheckCategoriesChange($oldCats, $newCats, $post)
481
  {
482
  $oldCats = implode(', ', $oldCats);
498
  }
499
  }
500
 
501
+ /**
502
+ * Author changed.
503
+ * @param stdClass $oldPost old post
504
+ * @param stdClass $newPost new post
505
+ */
506
  protected function CheckAuthorChange($oldpost, $newpost)
507
  {
508
  if ($oldpost->post_author != $newpost->post_author) {
524
  }
525
  }
526
 
527
+ /**
528
+ * Status changed.
529
+ * @param stdClass $oldPost old post
530
+ * @param stdClass $newPost new post
531
+ */
532
  protected function CheckStatusChange($oldpost, $newpost)
533
  {
534
  if ($oldpost->post_status != $newpost->post_status) {
559
  }
560
  }
561
 
562
+ /**
563
+ * Post parent changed.
564
+ * @param stdClass $oldPost old post
565
+ * @param stdClass $newPost new post
566
+ */
567
  protected function CheckParentChange($oldpost, $newpost)
568
  {
569
  if ($oldpost->post_parent != $newpost->post_parent) {
585
  }
586
  }
587
 
588
+ /**
589
+ * Permalink changed.
590
+ * @param string $oldLink old permalink
591
+ * @param string $newLink new permalink
592
+ * @param stdClass $post the post
593
+ */
594
  protected function CheckPermalinkChange($oldLink, $newLink, $post)
595
  {
596
  if ($oldLink != $newLink) {
609
  return 0;
610
  }
611
 
612
+ /**
613
+ * Post visibility changed.
614
+ * @param stdClass $oldPost old post
615
+ * @param stdClass $newPost new post
616
+ * @param string $oldStatus old status
617
+ * @param string $newStatus new status
618
+ */
619
  protected function CheckVisibilityChange($oldpost, $newpost, $oldStatus, $newStatus)
620
  {
621
  if ($oldStatus == 'draft' || $newStatus == 'draft') {
656
  }
657
  }
658
 
659
+ /**
660
+ * Post template changed.
661
+ * @param string $oldTmpl old template path
662
+ * @param string $newTmpl new template path
663
+ * @param stdClass $post the post
664
+ */
665
  protected function CheckTemplateChange($oldTmpl, $newTmpl, $post)
666
  {
667
  if ($oldTmpl != $newTmpl) {
683
  }
684
  }
685
 
686
+ /**
687
+ * Post sets as sticky changes.
688
+ * @param string $oldTmpl old template path
689
+ * @param string $newTmpl new template path
690
+ * @param stdClass $post the post
691
+ */
692
  protected function CheckStickyChange($oldStky, $newStky, $post)
693
  {
694
  if ($oldStky != $newStky) {
705
  }
706
  }
707
 
708
+ /**
709
+ * Post modified content.
710
+ * @param integer $post_ID post ID
711
+ * @param stdClass $oldPost old post
712
+ * @param stdClass $newPost new post
713
+ */
714
  public function CheckModificationChange($post_ID, $oldpost, $newpost)
715
  {
716
  if ($this->CheckOtherSensors($oldpost)) {
754
  }
755
  }
756
 
757
+ /**
758
+ * New category created.
759
+ * @param integer $category_id category ID
760
+ */
761
  public function EventCategoryCreation($category_id)
762
  {
763
  $category = get_category($category_id);
769
  ));
770
  }
771
 
772
+ /**
773
+ * Category deleted.
774
+ * @global array $_POST post data
775
+ */
776
  protected function CheckCategoryDeletion()
777
  {
778
  if (empty($_POST)) {
806
  }
807
  }
808
 
809
+ /**
810
+ * Changed the parent of the category.
811
+ * @global array $_POST post data
812
+ */
813
  public function EventChangedCategoryParent()
814
  {
815
  if (empty($_POST)) {
840
  }
841
  }
842
 
843
+ /**
844
+ * Check auto draft and the setting: Hide Plugin in Plugins Page
845
+ * @param integer $code alert code
846
+ * @param string $title title
847
+ * @return boolean
848
+ */
849
  private function CheckAutoDraft($code, $title)
850
  {
851
  if ($code == 2008 && $title == "auto-draft") {
860
  }
861
  }
862
 
863
+ /**
864
+ * Builds revision link.
865
+ * @param integer $revision_id revision ID
866
+ * @return string|null link
867
+ */
868
  private function getRevisionLink($revision_id)
869
  {
870
  if (!empty($revision_id)) {
874
  }
875
  }
876
 
877
+ /**
878
+ * Builds category link.
879
+ * @param integer $category_id category ID
880
+ * @return string|null link
881
+ */
882
  private function getCategoryLink($category_id)
883
  {
884
  if (!empty($category_id)) {
891
  /**
892
  * Ignore post from BBPress, WooCommerce Plugin
893
  * Triggered on the Sensors
894
+ * @param stdClass $post the post
895
  */
896
  private function CheckOtherSensors($post)
897
  {
907
  }
908
 
909
  /**
910
+ * Triggered after save post for add revision link.
911
+ * @param integer $post_id post ID
912
+ * @param stdClass $post post
913
  */
914
  public function SetRevisionLink($post_id, $post, $update)
915
  {
930
  }
931
 
932
  /**
933
+ * Alerts for Viewing of Posts, Pages and Custom Posts.
934
+ * @param string $title title
935
+ * @param stdClass $post (Optional) the post
936
  */
937
  public function ViewingPost($title, $post = null)
938
  {
944
  $currentPath = $_SERVER["REQUEST_URI"];
945
  if (!empty($_SERVER["HTTP_REFERER"])
946
  && strpos($_SERVER["HTTP_REFERER"], $currentPath) !== false) {
947
+ // Ignore this if we were on the same page so we avoid double audit entries
948
  return $title;
949
  }
950
  if (!empty($post->post_title)) {
961
  }
962
 
963
  /**
964
+ * Alerts for Editing of Posts, Pages and Custom Posts.
965
+ * @param stdClass $post post
966
  */
967
  public function EditingPost($post)
968
  {
994
  }
995
 
996
  /**
997
+ * Check if the alert was triggered.
998
+ * @param integer $alert_id alert code
999
+ * @return boolean
1000
  */
1001
  private function WasTriggered($alert_id)
1002
  {
1012
  return false;
1013
  }
1014
 
1015
+ /**
1016
+ * Changed title of a post.
1017
+ * @param stdClass $oldPost old post
1018
+ * @param stdClass $newPost new post
1019
+ */
1020
  private function CheckTitleChange($oldpost, $newpost)
1021
  {
1022
  if ($oldpost->post_title != $newpost->post_title) {
1032
  return 0;
1033
  }
1034
 
1035
+ /**
1036
+ * Comments/Trackbacks and Pingbacks check.
1037
+ * @param stdClass $oldPost old post
1038
+ * @param stdClass $newPost new post
1039
+ */
1040
  private function CheckCommentsPings($oldpost, $newpost)
1041
  {
1042
  $result = 0;
1077
  return $result;
1078
  }
1079
 
1080
+ /**
1081
+ * Comments/Trackbacks and Pingbacks event code.
1082
+ * @param stdClass $post the post
1083
+ * @param string $status the status
1084
+ */
1085
  private function GetCommentsPingsEvent($post, $status)
1086
  {
1087
  if ($post->post_type == 'post') {
1116
  return $event;
1117
  }
1118
 
1119
+ /**
1120
+ * Get editor link.
1121
+ * @param stdClass $post the post
1122
+ * @return array $aLink name and value link
1123
+ */
1124
  private function GetEditorLink($post)
1125
  {
1126
  $name = 'EditorLink';
classes/Sensors/Database.php CHANGED
@@ -1,13 +1,34 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_Database extends WSAL_AbstractSensor
4
  {
 
 
 
5
  public function HookEvents()
6
  {
7
  add_action('dbdelta_queries', array($this, 'EventDBDeltaQuery'));
8
  add_action('query', array($this, 'EventDropQuery'));
9
  }
10
 
 
 
 
 
11
  public function EventDropQuery($query)
12
  {
13
  $table_names = array();
@@ -31,6 +52,10 @@ class WSAL_Sensors_Database extends WSAL_AbstractSensor
31
  return $query;
32
  }
33
 
 
 
 
 
34
  public function EventDBDeltaQuery($queries)
35
  {
36
  $typeQueries = array(
@@ -74,6 +99,11 @@ class WSAL_Sensors_Database extends WSAL_AbstractSensor
74
  return $queries;
75
  }
76
 
 
 
 
 
 
77
  protected function GetEventQueryType($type_action, $type_query)
78
  {
79
  switch ($type_action) {
@@ -92,6 +122,10 @@ class WSAL_Sensors_Database extends WSAL_AbstractSensor
92
  }
93
  }
94
 
 
 
 
 
95
  protected function GetActionType($actype)
96
  {
97
  $is_themes = $actype == 'themes';
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Database sensor.
6
+ *
7
+ * 5010 Plugin created tables
8
+ * 5011 Plugin modified tables structure
9
+ * 5012 Plugin deleted tables
10
+ * 5013 Theme created tables
11
+ * 5014 Theme modified tables structure
12
+ * 5015 Theme deleted tables
13
+ * 5016 Unknown component created tables
14
+ * 5017 Unknown component modified tables structure
15
+ * 5018 Unknown component deleted tables
16
+ */
17
  class WSAL_Sensors_Database extends WSAL_AbstractSensor
18
  {
19
+ /**
20
+ * Listening to events using WP hooks.
21
+ */
22
  public function HookEvents()
23
  {
24
  add_action('dbdelta_queries', array($this, 'EventDBDeltaQuery'));
25
  add_action('query', array($this, 'EventDropQuery'));
26
  }
27
 
28
+ /**
29
+ * Checks for drop query.
30
+ * @param WP_Query $query query object
31
+ */
32
  public function EventDropQuery($query)
33
  {
34
  $table_names = array();
52
  return $query;
53
  }
54
 
55
+ /**
56
+ * Checks DB Delta queries.
57
+ * @param array $queries array of query
58
+ */
59
  public function EventDBDeltaQuery($queries)
60
  {
61
  $typeQueries = array(
99
  return $queries;
100
  }
101
 
102
+ /**
103
+ * Get code alert by action and type query.
104
+ * @param string $type_action (plugins, themes or unknown)
105
+ * @param string $type_query (create, update or delete)
106
+ */
107
  protected function GetEventQueryType($type_action, $type_query)
108
  {
109
  switch ($type_action) {
122
  }
123
  }
124
 
125
+ /**
126
+ * Get info by action type.
127
+ * @param string $actype (plugins, themes or unknown)
128
+ */
129
  protected function GetActionType($actype)
130
  {
131
  $is_themes = $actype == 'themes';
classes/Sensors/Files.php CHANGED
@@ -1,55 +1,87 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- class WSAL_Sensors_Files extends WSAL_AbstractSensor {
4
-
5
- public function HookEvents() {
6
- add_action('add_attachment', array($this, 'EventFileUploaded'));
7
- add_action('delete_attachment', array($this, 'EventFileUploadedDeleted'));
8
- add_action('admin_init', array($this, 'EventAdminInit'));
9
- }
10
-
11
- protected $IsFileUploaded = false;
12
-
13
- public function EventFileUploaded($attachmentID){
14
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
15
- if($action != 'upload-theme' && $action != 'upload-plugin'){
16
- $file = get_attached_file($attachmentID);
17
- $this->plugin->alerts->Trigger(2010, array(
18
- 'AttachmentID' => $attachmentID,
19
- 'FileName' => basename($file),
20
- 'FilePath' => dirname($file),
21
- ));
22
- }
23
- $this->IsFileUploaded = true;
24
- }
25
-
26
- public function EventFileUploadedDeleted($attachmentID){
27
- if($this->IsFileUploaded)return;
 
 
 
 
 
 
 
 
 
 
 
 
28
  $file = get_attached_file($attachmentID);
29
- $this->plugin->alerts->Trigger(2011, array(
30
- 'AttachmentID' => $attachmentID,
31
- 'FileName' => basename($file),
32
- 'FilePath' => dirname($file),
33
- ));
34
- }
35
-
36
- public function EventAdminInit(){
37
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
38
- $is_theme_editor = basename($_SERVER['SCRIPT_NAME']) == 'theme-editor.php';
39
- $is_plugin_editor = basename($_SERVER['SCRIPT_NAME']) == 'plugin-editor.php';
40
-
41
- if($is_theme_editor && $action == 'update'){
42
- $this->plugin->alerts->Trigger(2046, array(
43
- 'File' => $_REQUEST['file'],
44
- 'Theme' => $_REQUEST['theme'],
45
- ));
46
- }
47
-
48
- if($is_plugin_editor && $action == 'update'){
49
- $this->plugin->alerts->Trigger(2051, array(
50
- 'File' => $_REQUEST['file'],
51
- 'Plugin' => $_REQUEST['plugin'],
52
- ));
53
- }
54
- }
 
 
 
 
55
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Files sensor.
6
+ *
7
+ * 2010 User uploaded file from Uploads directory
8
+ * 2011 User deleted file from Uploads directory
9
+ * 2046 User changed a file using the theme editor
10
+ * 2051 User changed a file using the plugin editor
11
+ */
12
+ class WSAL_Sensors_Files extends WSAL_AbstractSensor
13
+ {
14
+ /**
15
+ * @var boolean file uploaded
16
+ */
17
+ protected $IsFileUploaded = false;
18
 
19
+ /**
20
+ * Listening to events using WP hooks.
21
+ */
22
+ public function HookEvents()
23
+ {
24
+ add_action('add_attachment', array($this, 'EventFileUploaded'));
25
+ add_action('delete_attachment', array($this, 'EventFileUploadedDeleted'));
26
+ add_action('admin_init', array($this, 'EventAdminInit'));
27
+ }
28
+
29
+ /**
30
+ * File uploaded.
31
+ * @param integer $attachmentID attachment ID
32
+ */
33
+ public function EventFileUploaded($attachmentID)
34
+ {
35
+ $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
36
+ if ($action != 'upload-theme' && $action != 'upload-plugin') {
37
+ $file = get_attached_file($attachmentID);
38
+ $this->plugin->alerts->Trigger(2010, array(
39
+ 'AttachmentID' => $attachmentID,
40
+ 'FileName' => basename($file),
41
+ 'FilePath' => dirname($file),
42
+ ));
43
+ }
44
+ $this->IsFileUploaded = true;
45
+ }
46
+
47
+ /**
48
+ * Deleted file from uploads directory.
49
+ * @param integer $attachmentID attachment ID
50
+ */
51
+ public function EventFileUploadedDeleted($attachmentID)
52
+ {
53
+ if ($this->IsFileUploaded) {
54
+ return;
55
+ }
56
  $file = get_attached_file($attachmentID);
57
+ $this->plugin->alerts->Trigger(2011, array(
58
+ 'AttachmentID' => $attachmentID,
59
+ 'FileName' => basename($file),
60
+ 'FilePath' => dirname($file),
61
+ ));
62
+ }
63
+
64
+ /**
65
+ * Triggered when a user accesses the admin area.
66
+ */
67
+ public function EventAdminInit()
68
+ {
69
+ $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
70
+ $is_theme_editor = basename($_SERVER['SCRIPT_NAME']) == 'theme-editor.php';
71
+ $is_plugin_editor = basename($_SERVER['SCRIPT_NAME']) == 'plugin-editor.php';
72
+
73
+ if ($is_theme_editor && $action == 'update') {
74
+ $this->plugin->alerts->Trigger(2046, array(
75
+ 'File' => $_REQUEST['file'],
76
+ 'Theme' => $_REQUEST['theme'],
77
+ ));
78
+ }
79
+
80
+ if ($is_plugin_editor && $action == 'update') {
81
+ $this->plugin->alerts->Trigger(2051, array(
82
+ 'File' => $_REQUEST['file'],
83
+ 'Plugin' => $_REQUEST['plugin'],
84
+ ));
85
+ }
86
+ }
87
  }
classes/Sensors/LogInOut.php CHANGED
@@ -1,8 +1,33 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
4
  {
 
 
 
 
 
 
 
 
 
 
 
5
 
 
 
 
6
  public function HookEvents()
7
  {
8
  add_action('wp_login', array($this, 'EventLogin'), 10, 2);
@@ -13,13 +38,17 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
13
  add_filter('wp_login_blocked', array($this, 'EventLoginBlocked'), 10, 1);
14
  }
15
 
16
- protected $_current_user = null;
17
-
 
18
  public function GetCurrentUser()
19
  {
20
  $this->_current_user = wp_get_current_user();
21
  }
22
 
 
 
 
23
  public function EventLogin($user_login, $user = null)
24
  {
25
  if (empty($user)) {
@@ -35,6 +64,9 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
35
  ), true);
36
  }
37
 
 
 
 
38
  public function EventLogout()
39
  {
40
  if ($this->_current_user->ID != 0) {
@@ -45,19 +77,31 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
45
  }
46
  }
47
 
48
- const TRANSIENT_FAILEDLOGINS = 'wsal-failedlogins-known';
49
- const TRANSIENT_FAILEDLOGINS_UNKNOWN = 'wsal-failedlogins-unknown';
50
-
 
51
  protected function GetLoginFailureLogLimit()
52
  {
53
  return 10;
54
  }
55
 
 
 
 
 
56
  protected function GetLoginFailureExpiration()
57
  {
58
  return 12 * 60 * 60;
59
  }
60
 
 
 
 
 
 
 
 
61
  protected function IsPastLoginFailureLimit($ip, $site_id, $user)
62
  {
63
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
@@ -70,6 +114,12 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
70
  }
71
  }
72
 
 
 
 
 
 
 
73
  protected function IncrementLoginFailure($ip, $site_id, $user)
74
  {
75
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
@@ -97,6 +147,10 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
97
  }
98
  }
99
 
 
 
 
 
100
  public function EventLoginFailure($username)
101
  {
102
  list($y, $m, $d) = explode('-', date('Y-m-d'));
@@ -193,6 +247,10 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
193
  }
194
  }
195
 
 
 
 
 
196
  public function EventPasswordReset($user, $new_pass)
197
  {
198
  if (!empty($user)) {
@@ -204,6 +262,10 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
204
  }
205
  }
206
 
 
 
 
 
207
  public function EventLoginBlocked($username)
208
  {
209
  $user = get_user_by('login', $username);
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Login/Logout sensor.
6
+ *
7
+ * 1000 User logged in
8
+ * 1001 User logged out
9
+ * 1002 Login failed
10
+ * 1003 Login failed / non existing user
11
+ * 1004 Login blocked
12
+ * 4003 User has changed his or her password
13
+ */
14
  class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
15
  {
16
+ /**
17
+ * Transient name.
18
+ * WordPress will prefix the name with "_transient_" or "_transient_timeout_" in the options table.
19
+ */
20
+ const TRANSIENT_FAILEDLOGINS = 'wsal-failedlogins-known';
21
+ const TRANSIENT_FAILEDLOGINS_UNKNOWN = 'wsal-failedlogins-unknown';
22
+
23
+ /**
24
+ * @var WP_User current user object
25
+ */
26
+ protected $_current_user = null;
27
 
28
+ /**
29
+ * Listening to events using WP hooks.
30
+ */
31
  public function HookEvents()
32
  {
33
  add_action('wp_login', array($this, 'EventLogin'), 10, 2);
38
  add_filter('wp_login_blocked', array($this, 'EventLoginBlocked'), 10, 1);
39
  }
40
 
41
+ /**
42
+ * Sets current user.
43
+ */
44
  public function GetCurrentUser()
45
  {
46
  $this->_current_user = wp_get_current_user();
47
  }
48
 
49
+ /**
50
+ * Event Login.
51
+ */
52
  public function EventLogin($user_login, $user = null)
53
  {
54
  if (empty($user)) {
64
  ), true);
65
  }
66
 
67
+ /**
68
+ * Event Logout.
69
+ */
70
  public function EventLogout()
71
  {
72
  if ($this->_current_user->ID != 0) {
77
  }
78
  }
79
 
80
+ /**
81
+ * Login failure limit count.
82
+ * @return integer limit
83
+ */
84
  protected function GetLoginFailureLogLimit()
85
  {
86
  return 10;
87
  }
88
 
89
+ /**
90
+ * Expiration of the transient saved in the WP database.
91
+ * @return integer Time until expiration in seconds from now
92
+ */
93
  protected function GetLoginFailureExpiration()
94
  {
95
  return 12 * 60 * 60;
96
  }
97
 
98
+ /**
99
+ * Check failure limit.
100
+ * @param string $ip IP address
101
+ * @param integer $site_id blog ID
102
+ * @param WP_User $user user object
103
+ * @return boolean passed limit true|false
104
+ */
105
  protected function IsPastLoginFailureLimit($ip, $site_id, $user)
106
  {
107
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
114
  }
115
  }
116
 
117
+ /**
118
+ * Increment failure limit.
119
+ * @param string $ip IP address
120
+ * @param integer $site_id blog ID
121
+ * @param WP_User $user user object
122
+ */
123
  protected function IncrementLoginFailure($ip, $site_id, $user)
124
  {
125
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
147
  }
148
  }
149
 
150
+ /**
151
+ * Event Login failure.
152
+ * @param string $username username
153
+ */
154
  public function EventLoginFailure($username)
155
  {
156
  list($y, $m, $d) = explode('-', date('Y-m-d'));
247
  }
248
  }
249
 
250
+ /**
251
+ * Event changed password.
252
+ * @param WP_User $user user object
253
+ */
254
  public function EventPasswordReset($user, $new_pass)
255
  {
256
  if (!empty($user)) {
262
  }
263
  }
264
 
265
+ /**
266
+ * Event login blocked.
267
+ * @param string $username username
268
+ */
269
  public function EventLoginBlocked($username)
270
  {
271
  $user = get_user_by('login', $username);
classes/Sensors/Menus.php CHANGED
@@ -1,5 +1,19 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_Menus extends WSAL_AbstractSensor
4
  {
5
  protected $_OldMenu = null;
@@ -7,6 +21,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
7
  protected $_OldMenuItems = array();
8
  protected $_OldMenuLocations = null;
9
 
 
 
 
10
  public function HookEvents()
11
  {
12
  add_action('wp_create_nav_menu', array($this, 'CreateMenu'), 10, 2);
@@ -22,6 +39,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
22
  add_action('customize_save_after', array($this, 'CustomizeSave'));
23
  }
24
 
 
 
 
25
  public function UpdateMenuItem($menu_id, $menu_item_db_id, $args)
26
  {
27
  $oldMenuItems = array();
@@ -81,6 +101,10 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
81
  }
82
  }
83
 
 
 
 
 
84
  public function CreateMenu($term_id, $menu_data)
85
  {
86
  $this->plugin->alerts->Trigger(2078, array(
@@ -88,6 +112,10 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
88
  ));
89
  }
90
 
 
 
 
 
91
  public function ManageMenuLocations()
92
  {
93
  // Manage Location tab
@@ -102,6 +130,10 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
102
  }
103
  }
104
 
 
 
 
 
105
  private function LocationSetting($new_location, $type)
106
  {
107
  $old_locations = get_nav_menu_locations();
@@ -118,6 +150,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
118
  }
119
  }
120
 
 
 
 
121
  public function DeleteMenu($term_id)
122
  {
123
  if ($this->_OldMenu) {
@@ -127,6 +162,10 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
127
  }
128
  }
129
 
 
 
 
 
130
  public function UpdateMenu($menu_id, $menu_data = null)
131
  {
132
  if (!empty($menu_data)) {
@@ -222,6 +261,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
222
  }
223
  }
224
 
 
 
 
225
  private function BuildOldMenuTermsAndItems()
226
  {
227
  $menus = wp_get_nav_menus();
@@ -247,6 +289,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
247
  }
248
  }
249
 
 
 
 
250
  public function EventAdminInit()
251
  {
252
  $is_nav_menu = basename($_SERVER['SCRIPT_NAME']) == 'nav-menus.php';
@@ -262,6 +307,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
262
  }
263
  }
264
 
 
 
 
265
  public function CustomizeInit()
266
  {
267
  $this->BuildOldMenuTermsAndItems();
@@ -269,7 +317,7 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
269
  }
270
 
271
  /**
272
- * Customize Events Function
273
  */
274
  public function CustomizeSave()
275
  {
@@ -382,6 +430,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
382
  }
383
  }
384
 
 
 
 
385
  private function EventAddItems($content_type, $content_name, $menu_name)
386
  {
387
  $this->plugin->alerts->Trigger(2079, array(
@@ -391,6 +442,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
391
  ));
392
  }
393
 
 
 
 
394
  private function EventRemoveItems($content_type, $content_name, $menu_name)
395
  {
396
  $this->plugin->alerts->Trigger(2080, array(
@@ -400,6 +454,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
400
  ));
401
  }
402
 
 
 
 
403
  private function EventMenuSetting($menu_name, $status, $menu_setting)
404
  {
405
  $this->plugin->alerts->Trigger(2082, array(
@@ -409,6 +466,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
409
  ));
410
  }
411
 
 
 
 
412
  private function EventModifiedItems($content_type, $content_name, $menu_name)
413
  {
414
  $this->plugin->alerts->Trigger(2083, array(
@@ -418,6 +478,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
418
  ));
419
  }
420
 
 
 
 
421
  private function EventChangeName($old_menu_name, $new_menu_name)
422
  {
423
  $this->plugin->alerts->Trigger(2084, array(
@@ -426,6 +489,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
426
  ));
427
  }
428
 
 
 
 
429
  private function EventChangeOrder($item_name, $menu_name)
430
  {
431
  $this->plugin->alerts->Trigger(2085, array(
@@ -434,6 +500,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
434
  ));
435
  }
436
 
 
 
 
437
  private function EventChangeSubItem($item_name, $parent_name, $menu_name)
438
  {
439
  $this->plugin->alerts->Trigger(2089, array(
@@ -443,6 +512,9 @@ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
443
  ));
444
  }
445
 
 
 
 
446
  private function GetItemName($term_id, $item_id)
447
  {
448
  $item_name = '';
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Menus sensor.
6
+ *
7
+ * 2078 User created new menu
8
+ * 2079 User added content to a menu
9
+ * 2080 User removed content from a menu
10
+ * 2081 User deleted menu
11
+ * 2082 User changed menu setting
12
+ * 2083 User modified content in a menu
13
+ * 2084 User changed name of a menu
14
+ * 2085 User changed order of the objects in a menu
15
+ * 2089 User moved objects as a sub-item
16
+ */
17
  class WSAL_Sensors_Menus extends WSAL_AbstractSensor
18
  {
19
  protected $_OldMenu = null;
21
  protected $_OldMenuItems = array();
22
  protected $_OldMenuLocations = null;
23
 
24
+ /**
25
+ * Listening to events using WP hooks.
26
+ */
27
  public function HookEvents()
28
  {
29
  add_action('wp_create_nav_menu', array($this, 'CreateMenu'), 10, 2);
39
  add_action('customize_save_after', array($this, 'CustomizeSave'));
40
  }
41
 
42
+ /**
43
+ * Menu item updated.
44
+ */
45
  public function UpdateMenuItem($menu_id, $menu_item_db_id, $args)
46
  {
47
  $oldMenuItems = array();
101
  }
102
  }
103
 
104
+ /**
105
+ * New menu created.
106
+ * @param array $menu_data data
107
+ */
108
  public function CreateMenu($term_id, $menu_data)
109
  {
110
  $this->plugin->alerts->Trigger(2078, array(
112
  ));
113
  }
114
 
115
+ /**
116
+ * New menu created.
117
+ * @global array $_POST data post
118
+ */
119
  public function ManageMenuLocations()
120
  {
121
  // Manage Location tab
130
  }
131
  }
132
 
133
+ /**
134
+ * Menu location.
135
+ * @param integer $new_location location
136
+ */
137
  private function LocationSetting($new_location, $type)
138
  {
139
  $old_locations = get_nav_menu_locations();
150
  }
151
  }
152
 
153
+ /**
154
+ * Menu deleted.
155
+ */
156
  public function DeleteMenu($term_id)
157
  {
158
  if ($this->_OldMenu) {
162
  }
163
  }
164
 
165
+ /**
166
+ * Menu updated.
167
+ * @param array $menu_data (Optional) data
168
+ */
169
  public function UpdateMenu($menu_id, $menu_data = null)
170
  {
171
  if (!empty($menu_data)) {
261
  }
262
  }
263
 
264
+ /**
265
+ * Set old menu terms and items.
266
+ */
267
  private function BuildOldMenuTermsAndItems()
268
  {
269
  $menus = wp_get_nav_menus();
289
  }
290
  }
291
 
292
+ /**
293
+ * Triggered when a user accesses the admin area.
294
+ */
295
  public function EventAdminInit()
296
  {
297
  $is_nav_menu = basename($_SERVER['SCRIPT_NAME']) == 'nav-menus.php';
307
  }
308
  }
309
 
310
+ /**
311
+ * Customize set old data.
312
+ */
313
  public function CustomizeInit()
314
  {
315
  $this->BuildOldMenuTermsAndItems();
317
  }
318
 
319
  /**
320
+ * Customize Events Function.
321
  */
322
  public function CustomizeSave()
323
  {
430
  }
431
  }
432
 
433
+ /**
434
+ * Added content to a menu.
435
+ */
436
  private function EventAddItems($content_type, $content_name, $menu_name)
437
  {
438
  $this->plugin->alerts->Trigger(2079, array(
442
  ));
443
  }
444
 
445
+ /**
446
+ * Removed content from a menu.
447
+ */
448
  private function EventRemoveItems($content_type, $content_name, $menu_name)
449
  {
450
  $this->plugin->alerts->Trigger(2080, array(
454
  ));
455
  }
456
 
457
+ /**
458
+ * Changed menu setting.
459
+ */
460
  private function EventMenuSetting($menu_name, $status, $menu_setting)
461
  {
462
  $this->plugin->alerts->Trigger(2082, array(
466
  ));
467
  }
468
 
469
+ /**
470
+ * Modified content in a menu.
471
+ */
472
  private function EventModifiedItems($content_type, $content_name, $menu_name)
473
  {
474
  $this->plugin->alerts->Trigger(2083, array(
478
  ));
479
  }
480
 
481
+ /**
482
+ * Changed name of a menu.
483
+ */
484
  private function EventChangeName($old_menu_name, $new_menu_name)
485
  {
486
  $this->plugin->alerts->Trigger(2084, array(
489
  ));
490
  }
491
 
492
+ /**
493
+ * Changed order of the objects in a menu.
494
+ */
495
  private function EventChangeOrder($item_name, $menu_name)
496
  {
497
  $this->plugin->alerts->Trigger(2085, array(
500
  ));
501
  }
502
 
503
+ /**
504
+ * Moved objects as a sub-item.
505
+ */
506
  private function EventChangeSubItem($item_name, $parent_name, $menu_name)
507
  {
508
  $this->plugin->alerts->Trigger(2089, array(
512
  ));
513
  }
514
 
515
+ /**
516
+ * Get menu item name.
517
+ */
518
  private function GetItemName($term_id, $item_id)
519
  {
520
  $item_name = '';
classes/Sensors/MetaData.php CHANGED
@@ -1,8 +1,29 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
4
  {
 
5
 
 
 
 
6
  public function HookEvents()
7
  {
8
  add_action('add_post_meta', array($this, 'EventPostMetaCreated'), 10, 3);
@@ -11,11 +32,13 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
11
  add_action('deleted_post_meta', array($this, 'EventPostMetaDeleted'), 10, 4);
12
  }
13
 
14
- protected $old_meta = array();
15
-
 
 
16
  protected function CanLogPostMeta($object_id, $meta_key)
17
  {
18
- //check if excluded meta key or starts with _
19
  if (substr($meta_key, 0, 1) == '_') {
20
  return false;
21
  } else if ($this->IsExcludedCustomFields($meta_key)) {
@@ -25,6 +48,11 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
25
  }
26
  }
27
 
 
 
 
 
 
28
  public function IsExcludedCustomFields($custom)
29
  {
30
  $customFields = $this->plugin->settings->GetExcludedMonitoringCustom();
@@ -50,13 +78,18 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
50
  }
51
  }
52
  return false;
53
- //return (in_array($custom, $customFields)) ? true : false;
54
  }
55
-
 
 
 
56
  public function EventPostMetaCreated($object_id, $meta_key, $meta_value)
57
  {
58
  $post = get_post($object_id);
59
- if (!$this->CanLogPostMeta($object_id, $meta_key)) return;
 
 
60
 
61
  $WPActions = array('add-meta');
62
  if (isset($_POST['action']) && in_array($_POST['action'], $WPActions)) {
@@ -97,6 +130,9 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
97
  }
98
  }
99
 
 
 
 
100
  public function EventPostMetaUpdating($meta_id, $object_id, $meta_key)
101
  {
102
  static $meta_type = 'post';
@@ -106,11 +142,15 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
106
  );
107
  }
108
 
 
 
 
109
  public function EventPostMetaUpdated($meta_id, $object_id, $meta_key, $meta_value)
110
  {
111
  $post = get_post($object_id);
112
-
113
- if (!$this->CanLogPostMeta($object_id, $meta_key)) return;
 
114
 
115
  $WPActions = array('add-meta');
116
  if (isset($_POST['action']) && in_array($_POST['action'], $WPActions)) {
@@ -204,6 +244,9 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
204
  }
205
  }
206
 
 
 
 
207
  public function EventPostMetaDeleted($meta_ids, $object_id, $meta_key, $meta_value)
208
  {
209
  $post = get_post($object_id);
@@ -212,8 +255,9 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
212
  if (isset($_POST['action']) && in_array($_POST['action'], $WPActions)) {
213
  $editorLink = $this->GetEditorLink($post);
214
  foreach ($meta_ids as $meta_id) {
215
- if (!$this->CanLogPostMeta($object_id, $meta_key)) continue;
216
-
 
217
  switch ($post->post_type) {
218
  case 'page':
219
  $this->plugin->alerts->Trigger(2061, array(
@@ -251,6 +295,11 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
251
  }
252
  }
253
 
 
 
 
 
 
254
  private function GetEditorLink($post)
255
  {
256
  $name = 'EditorLink';
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Custom fields (posts, pages and custom posts) sensor.
6
+ *
7
+ * 2053 User created a custom field for a post
8
+ * 2056 User created a custom field for a custom post type
9
+ * 2059 User created a custom field for a page
10
+ * 2062 User updated a custom field name for a post
11
+ * 2063 User updated a custom field name for a custom post type
12
+ * 2064 User updated a custom field name for a page
13
+ * 2060 User updated a custom field value for a page
14
+ * 2057 User updated a custom field for a custom post type
15
+ * 2054 User updated a custom field value for a post
16
+ * 2055 User deleted a custom field from a post
17
+ * 2058 User deleted a custom field from a custom post type
18
+ * 2061 User deleted a custom field from a page
19
+ */
20
  class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
21
  {
22
+ protected $old_meta = array();
23
 
24
+ /**
25
+ * Listening to events using WP hooks.
26
+ */
27
  public function HookEvents()
28
  {
29
  add_action('add_post_meta', array($this, 'EventPostMetaCreated'), 10, 3);
32
  add_action('deleted_post_meta', array($this, 'EventPostMetaDeleted'), 10, 4);
33
  }
34
 
35
+ /**
36
+ * Check "Excluded Custom Fields" or meta keys starts with "_".
37
+ * @return boolean can log true|false
38
+ */
39
  protected function CanLogPostMeta($object_id, $meta_key)
40
  {
41
+ // check if excluded meta key or starts with _
42
  if (substr($meta_key, 0, 1) == '_') {
43
  return false;
44
  } else if ($this->IsExcludedCustomFields($meta_key)) {
48
  }
49
  }
50
 
51
+ /**
52
+ * Check "Excluded Custom Fields".
53
+ * Used in the above function.
54
+ * @return boolean is excluded from monitoring true|false
55
+ */
56
  public function IsExcludedCustomFields($custom)
57
  {
58
  $customFields = $this->plugin->settings->GetExcludedMonitoringCustom();
78
  }
79
  }
80
  return false;
81
+ // return (in_array($custom, $customFields)) ? true : false;
82
  }
83
+
84
+ /**
85
+ * Created a custom field.
86
+ */
87
  public function EventPostMetaCreated($object_id, $meta_key, $meta_value)
88
  {
89
  $post = get_post($object_id);
90
+ if (!$this->CanLogPostMeta($object_id, $meta_key)) {
91
+ return;
92
+ }
93
 
94
  $WPActions = array('add-meta');
95
  if (isset($_POST['action']) && in_array($_POST['action'], $WPActions)) {
130
  }
131
  }
132
 
133
+ /**
134
+ * Sets the old meta.
135
+ */
136
  public function EventPostMetaUpdating($meta_id, $object_id, $meta_key)
137
  {
138
  static $meta_type = 'post';
142
  );
143
  }
144
 
145
+ /**
146
+ * Updated a custom field name/value.
147
+ */
148
  public function EventPostMetaUpdated($meta_id, $object_id, $meta_key, $meta_value)
149
  {
150
  $post = get_post($object_id);
151
+ if (!$this->CanLogPostMeta($object_id, $meta_key)) {
152
+ return;
153
+ }
154
 
155
  $WPActions = array('add-meta');
156
  if (isset($_POST['action']) && in_array($_POST['action'], $WPActions)) {
244
  }
245
  }
246
 
247
+ /**
248
+ * Deleted a custom field.
249
+ */
250
  public function EventPostMetaDeleted($meta_ids, $object_id, $meta_key, $meta_value)
251
  {
252
  $post = get_post($object_id);
255
  if (isset($_POST['action']) && in_array($_POST['action'], $WPActions)) {
256
  $editorLink = $this->GetEditorLink($post);
257
  foreach ($meta_ids as $meta_id) {
258
+ if (!$this->CanLogPostMeta($object_id, $meta_key)) {
259
+ continue;
260
+ }
261
  switch ($post->post_type) {
262
  case 'page':
263
  $this->plugin->alerts->Trigger(2061, array(
295
  }
296
  }
297
 
298
+ /**
299
+ * Get editor link.
300
+ * @param stdClass $post the post
301
+ * @return array $aLink name and value link
302
+ */
303
  private function GetEditorLink($post)
304
  {
305
  $name = 'EditorLink';
classes/Sensors/Multisite.php CHANGED
@@ -1,130 +1,200 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
- public function HookEvents() {
6
- if($this->plugin->IsMultisite()){
7
- add_action('admin_init', array($this, 'EventAdminInit'));
8
- if(current_user_can('switch_themes'))add_action('shutdown', array($this, 'EventAdminShutdown'));
9
- add_action('wpmu_new_blog', array($this, 'EventNewBlog'), 10, 1);
10
- add_action('archive_blog', array($this, 'EventArchiveBlog'));
11
- add_action('unarchive_blog', array($this, 'EventUnarchiveBlog'));
12
- add_action('activate_blog', array($this, 'EventActivateBlog'));
13
- add_action('deactivate_blog', array($this, 'EventDeactivateBlog'));
14
- add_action('delete_blog', array($this, 'EventDeleteBlog'));
15
- add_action('add_user_to_blog', array($this, 'EventUserAddedToBlog'), 10, 3);
16
- add_action('remove_user_from_blog', array($this, 'EventUserRemovedFromBlog'));
17
- }
18
- }
19
-
20
- protected $old_allowedthemes = null;
21
-
22
- public function EventAdminInit(){
23
- $this->old_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
24
- }
25
-
26
- public function EventAdminShutdown(){
27
- if(is_null($this->old_allowedthemes))return;
28
- $new_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
29
-
30
- // check for enabled themes
31
- foreach($new_allowedthemes as $theme)
32
- if(!in_array($theme, (array)$this->old_allowedthemes)){
33
- $theme = wp_get_theme($theme);
34
- $this->plugin->alerts->Trigger(5008, array(
35
- 'Theme' => (object)array(
36
- 'Name' => $theme->Name,
37
- 'ThemeURI' => $theme->ThemeURI,
38
- 'Description' => $theme->Description,
39
- 'Author' => $theme->Author,
40
- 'Version' => $theme->Version,
41
- 'get_template_directory' => $theme->get_template_directory(),
42
- ),
43
- ));
44
- }
45
-
46
- // check for disabled themes
47
- foreach((array)$this->old_allowedthemes as $theme)
48
- if(!in_array($theme, $new_allowedthemes)){
49
- $theme = wp_get_theme($theme);
50
- $this->plugin->alerts->Trigger(5009, array(
51
- 'Theme' => (object)array(
52
- 'Name' => $theme->Name,
53
- 'ThemeURI' => $theme->ThemeURI,
54
- 'Description' => $theme->Description,
55
- 'Author' => $theme->Author,
56
- 'Version' => $theme->Version,
57
- 'get_template_directory' => $theme->get_template_directory(),
58
- ),
59
- ));
60
- }
61
- }
62
-
63
- public function EventNewBlog($blog_id){
64
- $this->plugin->alerts->Trigger(7000, array(
65
- 'BlogID' => $blog_id,
66
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
67
- ));
68
- }
69
-
70
- public function EventArchiveBlog($blog_id){
71
- $this->plugin->alerts->Trigger(7001, array(
72
- 'BlogID' => $blog_id,
73
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
74
- ));
75
- }
76
-
77
- public function EventUnarchiveBlog($blog_id){
78
- $this->plugin->alerts->Trigger(7002, array(
79
- 'BlogID' => $blog_id,
80
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
81
- ));
82
- }
83
-
84
- public function EventActivateBlog($blog_id){
85
- $this->plugin->alerts->Trigger(7003, array(
86
- 'BlogID' => $blog_id,
87
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
88
- ));
89
- }
90
-
91
- public function EventDeactivateBlog($blog_id){
92
- $this->plugin->alerts->Trigger(7004, array(
93
- 'BlogID' => $blog_id,
94
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
95
- ));
96
- }
97
-
98
- public function EventDeleteBlog($blog_id){
99
- $this->plugin->alerts->Trigger(7005, array(
100
- 'BlogID' => $blog_id,
101
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
102
- ));
103
- }
104
-
105
- public function EventUserAddedToBlog($user_id, $role, $blog_id){
106
- $this->plugin->alerts->TriggerIf(4010, array(
107
- 'TargetUserID' => $user_id,
108
- 'TargetUsername' => get_userdata($user_id)->user_login,
109
- 'TargetUserRole' => $role,
110
- 'BlogID' => $blog_id,
111
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
112
- ), array($this, 'MustNotContainCreateUser'));
113
- }
114
-
115
- public function EventUserRemovedFromBlog($user_id){
116
- $user = get_userdata($user_id);
117
  $blog_id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : 0);
118
- $this->plugin->alerts->TriggerIf(4011, array(
119
- 'TargetUserID' => $user_id,
120
- 'TargetUsername' => $user->user_login,
121
- 'TargetUserRole' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
122
- 'BlogID' => $blog_id,
123
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
124
- ), array($this, 'MustNotContainCreateUser'));
125
- }
126
-
127
- public function MustNotContainCreateUser(WSAL_AlertManager $mgr){
128
- return !$mgr->WillTrigger(4012);
129
- }
130
- }
 
 
 
 
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Multisite sensor.
6
+ *
7
+ * 4010 Existing user added to a site
8
+ * 4011 User removed from site
9
+ * 4012 New network user created
10
+ * 7000 New site added on the network
11
+ * 7001 Existing site archived
12
+ * 7002 Archived site has been unarchived
13
+ * 7003 Deactivated site has been activated
14
+ * 7004 Site has been deactivated
15
+ * 7005 Existing site deleted from network
16
+ * 5008 Activated theme on network
17
+ * 5009 Deactivated theme from network
18
+ */
19
+ class WSAL_Sensors_Multisite extends WSAL_AbstractSensor
20
+ {
21
+ protected $old_allowedthemes = null;
22
 
23
+ /**
24
+ * Listening to events using WP hooks.
25
+ */
26
+ public function HookEvents()
27
+ {
28
+ if ($this->plugin->IsMultisite()) {
29
+ add_action('admin_init', array($this, 'EventAdminInit'));
30
+ if (current_user_can('switch_themes')) {
31
+ add_action('shutdown', array($this, 'EventAdminShutdown'));
32
+ }
33
+ add_action('wpmu_new_blog', array($this, 'EventNewBlog'), 10, 1);
34
+ add_action('archive_blog', array($this, 'EventArchiveBlog'));
35
+ add_action('unarchive_blog', array($this, 'EventUnarchiveBlog'));
36
+ add_action('activate_blog', array($this, 'EventActivateBlog'));
37
+ add_action('deactivate_blog', array($this, 'EventDeactivateBlog'));
38
+ add_action('delete_blog', array($this, 'EventDeleteBlog'));
39
+ add_action('add_user_to_blog', array($this, 'EventUserAddedToBlog'), 10, 3);
40
+ add_action('remove_user_from_blog', array($this, 'EventUserRemovedFromBlog'));
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Triggered when a user accesses the admin area.
46
+ */
47
+ public function EventAdminInit()
48
+ {
49
+ $this->old_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
50
+ }
51
+
52
+ /**
53
+ * Activated/Deactivated theme on network.
54
+ */
55
+ public function EventAdminShutdown()
56
+ {
57
+ if (is_null($this->old_allowedthemes)) {
58
+ return;
59
+ }
60
+ $new_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
61
+
62
+ // check for enabled themes
63
+ foreach ($new_allowedthemes as $theme) {
64
+ if (!in_array($theme, (array)$this->old_allowedthemes)) {
65
+ $theme = wp_get_theme($theme);
66
+ $this->plugin->alerts->Trigger(5008, array(
67
+ 'Theme' => (object)array(
68
+ 'Name' => $theme->Name,
69
+ 'ThemeURI' => $theme->ThemeURI,
70
+ 'Description' => $theme->Description,
71
+ 'Author' => $theme->Author,
72
+ 'Version' => $theme->Version,
73
+ 'get_template_directory' => $theme->get_template_directory(),
74
+ ),
75
+ ));
76
+ }
77
+ }
78
+
79
+ // check for disabled themes
80
+ foreach ((array)$this->old_allowedthemes as $theme) {
81
+ if (!in_array($theme, $new_allowedthemes)) {
82
+ $theme = wp_get_theme($theme);
83
+ $this->plugin->alerts->Trigger(5009, array(
84
+ 'Theme' => (object)array(
85
+ 'Name' => $theme->Name,
86
+ 'ThemeURI' => $theme->ThemeURI,
87
+ 'Description' => $theme->Description,
88
+ 'Author' => $theme->Author,
89
+ 'Version' => $theme->Version,
90
+ 'get_template_directory' => $theme->get_template_directory(),
91
+ ),
92
+ ));
93
+ }
94
+ }
95
+ }
96
 
97
+ /**
98
+ * New site added on the network.
99
+ */
100
+ public function EventNewBlog($blog_id)
101
+ {
102
+ $this->plugin->alerts->Trigger(7000, array(
103
+ 'BlogID' => $blog_id,
104
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
105
+ ));
106
+ }
107
+
108
+ /**
109
+ * Existing site archived.
110
+ */
111
+ public function EventArchiveBlog($blog_id)
112
+ {
113
+ $this->plugin->alerts->Trigger(7001, array(
114
+ 'BlogID' => $blog_id,
115
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
116
+ ));
117
+ }
118
+
119
+ /**
120
+ * Archived site has been unarchived.
121
+ */
122
+ public function EventUnarchiveBlog($blog_id)
123
+ {
124
+ $this->plugin->alerts->Trigger(7002, array(
125
+ 'BlogID' => $blog_id,
126
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
127
+ ));
128
+ }
129
+
130
+ /**
131
+ * Deactivated site has been activated.
132
+ */
133
+ public function EventActivateBlog($blog_id)
134
+ {
135
+ $this->plugin->alerts->Trigger(7003, array(
136
+ 'BlogID' => $blog_id,
137
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
138
+ ));
139
+ }
140
+
141
+ /**
142
+ * Site has been deactivated.
143
+ */
144
+ public function EventDeactivateBlog($blog_id)
145
+ {
146
+ $this->plugin->alerts->Trigger(7004, array(
147
+ 'BlogID' => $blog_id,
148
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
149
+ ));
150
+ }
151
+
152
+ /**
153
+ * Existing site deleted from network.
154
+ */
155
+ public function EventDeleteBlog($blog_id)
156
+ {
157
+ $this->plugin->alerts->Trigger(7005, array(
158
+ 'BlogID' => $blog_id,
159
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
160
+ ));
161
+ }
162
+
163
+ /**
164
+ * Existing user added to a site.
165
+ */
166
+ public function EventUserAddedToBlog($user_id, $role, $blog_id)
167
+ {
168
+ $this->plugin->alerts->TriggerIf(4010, array(
169
+ 'TargetUserID' => $user_id,
170
+ 'TargetUsername' => get_userdata($user_id)->user_login,
171
+ 'TargetUserRole' => $role,
172
+ 'BlogID' => $blog_id,
173
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
174
+ ), array($this, 'MustNotContainCreateUser'));
175
+ }
176
+
177
+ /**
178
+ * User removed from site.
179
+ */
180
+ public function EventUserRemovedFromBlog($user_id)
181
+ {
182
+ $user = get_userdata($user_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  $blog_id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : 0);
184
+ $this->plugin->alerts->TriggerIf(4011, array(
185
+ 'TargetUserID' => $user_id,
186
+ 'TargetUsername' => $user->user_login,
187
+ 'TargetUserRole' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
188
+ 'BlogID' => $blog_id,
189
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
190
+ ), array($this, 'MustNotContainCreateUser'));
191
+ }
192
+
193
+ /**
194
+ * New network user created.
195
+ */
196
+ public function MustNotContainCreateUser(WSAL_AlertManager $mgr)
197
+ {
198
+ return !$mgr->WillTrigger(4012);
199
+ }
200
+ }
classes/Sensors/PhpErrors.php CHANGED
@@ -1,104 +1,139 @@
1
  <?php
2
-
3
- class WSAL_Sensors_PhpErrors extends WSAL_AbstractSensor {
4
-
5
- protected $_avoid_error_recursion = false;
6
-
7
- protected $_error_types = array(
8
- 0001 => array(1,4,16,64,256,4096), // errors
9
- 0002 => array(2,32,128,512), // warnings
10
- 0003 => array(8,1024,2048,8192,16384), // notices
11
- 0004 => array(), // exceptions
12
- 0005 => array(), // shutdown
13
- );
14
-
15
- protected $_maybe_last_error = null;
16
-
17
- public function HookEvents() {
18
- if($this->plugin->settings->IsPhpErrorLoggingEnabled()){
19
- set_error_handler(array($this, 'EventError'), E_ALL);
20
- set_exception_handler(array($this, 'EventException'));
21
- register_shutdown_function(array($this, 'EventShutdown'));
22
- }
23
- }
24
-
25
- protected function GetErrorHash($code, $mesg, $file, $line){
26
- return md5(implode(':', func_get_args()));
27
- }
28
-
29
- public function EventError($errno, $errstr, $errfile = 'unknown', $errline = 0, $errcontext = array()){
30
- if($this->_avoid_error_recursion)return;
31
-
32
- $errbacktrace = 'No Backtrace';
33
- if($this->plugin->settings->IsBacktraceLoggingEnabled()){
34
- ob_start();
35
- debug_print_backtrace();
36
- $errbacktrace = ob_get_clean();
37
- }
38
-
39
- $data = array(
40
- 'Code' => $errno,
41
- 'Message' => $errstr,
42
- 'File' => $errfile,
43
- 'Line' => $errline,
44
- 'Context' => $errcontext,
45
- 'Trace' => $errbacktrace,
46
- );
47
-
48
- $type = 0002; // default (middle ground)
49
- foreach($this->_error_types as $temp => $codes){
50
- if(in_array($errno, $codes)){
51
- $type = $temp;
52
- }
53
- }
54
-
55
- $this->_maybe_last_error = $this->GetErrorHash($errno, $errstr, $errfile, $errline);
56
-
57
- $this->_avoid_error_recursion = true;
58
- $this->plugin->alerts->Trigger($type, $data);
59
- $this->_avoid_error_recursion = false;
60
- }
61
-
62
- public function EventException(Exception $ex){
63
- if($this->_avoid_error_recursion)return;
64
-
65
- $errbacktrace = 'No Backtrace';
66
- if($this->plugin->settings->IsBacktraceLoggingEnabled()){
67
- $errbacktrace = $ex->getTraceAsString();
68
- }
69
-
70
- $data = array(
71
- 'Class' => get_class($ex),
72
- 'Code' => $ex->getCode(),
73
- 'Message' => $ex->getMessage(),
74
- 'File' => $ex->getFile(),
75
- 'Line' => $ex->getLine(),
76
- 'Trace' => $errbacktrace,
77
- );
78
-
79
- if(method_exists($ex, 'getContext'))
80
- $data['Context'] = $ex->getContext();
81
-
82
- $this->_avoid_error_recursion = true;
83
- $this->plugin->alerts->Trigger(0004, $data);
84
- $this->_avoid_error_recursion = false;
85
- }
86
-
87
- public function EventShutdown(){
88
- if($this->_avoid_error_recursion)return;
89
-
90
- if(!!($e = error_get_last()) && ($this->_maybe_last_error != $this->GetErrorHash($e['type'], $e['message'], $e['file'], $e['line']))){
91
- $data = array(
92
- 'Code' => $e['type'],
93
- 'Message' => $e['message'],
94
- 'File' => $e['file'],
95
- 'Line' => $e['line'],
96
- );
97
-
98
- $this->_avoid_error_recursion = true;
99
- $this->plugin->alerts->Trigger(0005, $data);
100
- $this->_avoid_error_recursion = false;
101
- }
102
- }
103
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Php Errors sensor.
6
+ *
7
+ * 0001 PHP error
8
+ * 0002 PHP warning
9
+ * 0003 PHP notice
10
+ * 0004 PHP exception
11
+ * 0005 PHP shutdown error
12
+ */
13
+ class WSAL_Sensors_PhpErrors extends WSAL_AbstractSensor
14
+ {
15
+ protected $_avoid_error_recursion = false;
16
+ protected $_maybe_last_error = null;
17
+
18
+ protected $_error_types = array(
19
+ 0001 => array(1,4,16,64,256,4096), // errors
20
+ 0002 => array(2,32,128,512), // warnings
21
+ 0003 => array(8,1024,2048,8192,16384), // notices
22
+ 0004 => array(), // exceptions
23
+ 0005 => array(), // shutdown
24
+ );
25
+
26
+ /**
27
+ * Listening to Php events.
28
+ */
29
+ public function HookEvents()
30
+ {
31
+ if ($this->plugin->settings->IsPhpErrorLoggingEnabled()) {
32
+ set_error_handler(array($this, 'EventError'), E_ALL);
33
+ set_exception_handler(array($this, 'EventException'));
34
+ register_shutdown_function(array($this, 'EventShutdown'));
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Get the hash of the error.
40
+ */
41
+ protected function GetErrorHash($code, $mesg, $file, $line)
42
+ {
43
+ return md5(implode(':', func_get_args()));
44
+ }
45
+
46
+ /**
47
+ * PHP error, warning or notice.
48
+ */
49
+ public function EventError($errno, $errstr, $errfile = 'unknown', $errline = 0, $errcontext = array())
50
+ {
51
+ if ($this->_avoid_error_recursion) {
52
+ return;
53
+ }
54
+
55
+ $errbacktrace = 'No Backtrace';
56
+ if ($this->plugin->settings->IsBacktraceLoggingEnabled()) {
57
+ ob_start();
58
+ debug_print_backtrace();
59
+ $errbacktrace = ob_get_clean();
60
+ }
61
+
62
+ $data = array(
63
+ 'Code' => $errno,
64
+ 'Message' => $errstr,
65
+ 'File' => $errfile,
66
+ 'Line' => $errline,
67
+ 'Context' => $errcontext,
68
+ 'Trace' => $errbacktrace,
69
+ );
70
+
71
+ $type = 0002; // default (middle ground)
72
+ foreach ($this->_error_types as $temp => $codes) {
73
+ if (in_array($errno, $codes)) {
74
+ $type = $temp;
75
+ }
76
+ }
77
+
78
+ $this->_maybe_last_error = $this->GetErrorHash($errno, $errstr, $errfile, $errline);
79
+
80
+ $this->_avoid_error_recursion = true;
81
+ $this->plugin->alerts->Trigger($type, $data);
82
+ $this->_avoid_error_recursion = false;
83
+ }
84
+
85
+ /**
86
+ * PHP exception.
87
+ */
88
+ public function EventException(Exception $ex)
89
+ {
90
+ if ($this->_avoid_error_recursion) {
91
+ return;
92
+ }
93
+
94
+ $errbacktrace = 'No Backtrace';
95
+ if ($this->plugin->settings->IsBacktraceLoggingEnabled()) {
96
+ $errbacktrace = $ex->getTraceAsString();
97
+ }
98
+
99
+ $data = array(
100
+ 'Class' => get_class($ex),
101
+ 'Code' => $ex->getCode(),
102
+ 'Message' => $ex->getMessage(),
103
+ 'File' => $ex->getFile(),
104
+ 'Line' => $ex->getLine(),
105
+ 'Trace' => $errbacktrace,
106
+ );
107
+
108
+ if (method_exists($ex, 'getContext')) {
109
+ $data['Context'] = $ex->getContext();
110
+ }
111
+
112
+ $this->_avoid_error_recursion = true;
113
+ $this->plugin->alerts->Trigger(0004, $data);
114
+ $this->_avoid_error_recursion = false;
115
+ }
116
+
117
+ /**
118
+ * PHP shutdown error.
119
+ */
120
+ public function EventShutdown()
121
+ {
122
+ if ($this->_avoid_error_recursion) {
123
+ return;
124
+ }
125
+
126
+ if (!!($e = error_get_last()) && ($this->_maybe_last_error != $this->GetErrorHash($e['type'], $e['message'], $e['file'], $e['line']))) {
127
+ $data = array(
128
+ 'Code' => $e['type'],
129
+ 'Message' => $e['message'],
130
+ 'File' => $e['file'],
131
+ 'Line' => $e['line'],
132
+ );
133
+
134
+ $this->_avoid_error_recursion = true;
135
+ $this->plugin->alerts->Trigger(0005, $data);
136
+ $this->_avoid_error_recursion = false;
137
+ }
138
+ }
139
  }
classes/Sensors/PluginsThemes.php CHANGED
@@ -1,29 +1,65 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
4
  {
 
 
5
 
6
- public function HookEvents() {
 
 
 
 
7
  $hasPermission = (current_user_can("install_plugins") || current_user_can("activate_plugins") ||
8
  current_user_can("delete_plugins") || current_user_can("update_plugins") || current_user_can("install_themes"));
9
 
10
  add_action('admin_init', array($this, 'EventAdminInit'));
11
- if($hasPermission)add_action('shutdown', array($this, 'EventAdminShutdown'));
 
 
12
  add_action('switch_theme', array($this, 'EventThemeActivated'));
13
  // TO DO
14
  add_action('wp_insert_post', array($this, 'EventPluginPostCreate'), 10, 2);
15
  add_action('delete_post', array($this, 'EventPluginPostDelete'), 10, 1);
16
  }
17
 
18
- protected $old_themes = array();
19
- protected $old_plugins = array();
20
-
21
- public function EventAdminInit() {
 
22
  $this->old_themes = wp_get_themes();
23
  $this->old_plugins = get_plugins();
24
  }
25
 
26
- public function EventAdminShutdown() {
 
 
 
 
27
  $action = (isset($_REQUEST['action']) && $_REQUEST['action'] != "-1") ? $_REQUEST['action'] : '';
28
  $action = (isset($_REQUEST['action2']) && $_REQUEST['action2'] != "-1") ? $_REQUEST['action2'] : $action;
29
  $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
@@ -35,9 +71,9 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
35
  $plugin = array_values(array_diff(array_keys(get_plugins()), array_keys($this->old_plugins)));
36
  if (count($plugin) != 1) {
37
  return $this->LogError(
38
- 'Expected exactly one new plugin but found ' . count($plugin),
39
- array('NewPlugin' => $plugin, 'OldPlugins' => $this->old_plugins, 'NewPlugins' => get_plugins())
40
- );
41
  }
42
  $pluginPath = $plugin[0];
43
  $plugin = get_plugins();
@@ -227,7 +263,12 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
227
  }
228
  }
229
 
230
- public function EventThemeActivated($themeName){
 
 
 
 
 
231
  $theme = null;
232
  foreach (wp_get_themes() as $item) {
233
  if ($item->Name == $themeName) {
@@ -237,9 +278,9 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
237
  }
238
  if ($theme == null) {
239
  return $this->LogError(
240
- 'Could not locate theme named "' . $theme . '".',
241
- array('ThemeName' => $themeName, 'Themes' => wp_get_themes())
242
- );
243
  }
244
  $this->plugin->alerts->Trigger(5006, array(
245
  'Theme' => (object)array(
@@ -254,7 +295,8 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
254
  }
255
 
256
  /**
257
- * Used even for modified post
 
258
  */
259
  public function EventPluginPostCreate($insert, $post)
260
  {
@@ -284,6 +326,10 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
284
  }
285
  }
286
 
 
 
 
 
287
  public function EventPluginPostDelete($post_id)
288
  {
289
  if (empty($_REQUEST['action']) && isset($_REQUEST['page'])) {
@@ -300,6 +346,10 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
300
  }
301
  }
302
 
 
 
 
 
303
  protected function GetRemovedThemes()
304
  {
305
  $result = $this->old_themes;
@@ -311,6 +361,9 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
311
  return array_values($result);
312
  }
313
 
 
 
 
314
  protected function GetEventTypeForPostType($post, $typePost, $typePage, $typeCustom)
315
  {
316
  switch ($post->post_type) {
@@ -323,6 +376,11 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
323
  }
324
  }
325
 
 
 
 
 
 
326
  private function GetEditorLink($post)
327
  {
328
  $name = 'EditorLink';
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Plugins & Themes sensor.
6
+ *
7
+ * 5000 User installed a plugin
8
+ * 5001 User activated a WordPress plugin
9
+ * 5002 User deactivated a WordPress plugin
10
+ * 5003 User uninstalled a plugin
11
+ * 5004 User upgraded a plugin
12
+ * 5005 User installed a theme
13
+ * 5006 User activated a theme
14
+ * 5007 User uninstalled a theme
15
+ * 5019 A plugin created a post
16
+ * 5020 A plugin created a page
17
+ * 5021 A plugin created a custom post
18
+ * 5025 A plugin deleted a post
19
+ * 5026 A plugin deleted a page
20
+ * 5027 A plugin deleted a custom post
21
+ * 5031 User updated a theme
22
+ * 2106 A plugin modified a post
23
+ * 2107 A plugin modified a page
24
+ * 2108 A plugin modified a custom post
25
+ */
26
  class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor
27
  {
28
+ protected $old_themes = array();
29
+ protected $old_plugins = array();
30
 
31
+ /**
32
+ * Listening to events using WP hooks.
33
+ */
34
+ public function HookEvents()
35
+ {
36
  $hasPermission = (current_user_can("install_plugins") || current_user_can("activate_plugins") ||
37
  current_user_can("delete_plugins") || current_user_can("update_plugins") || current_user_can("install_themes"));
38
 
39
  add_action('admin_init', array($this, 'EventAdminInit'));
40
+ if ($hasPermission) {
41
+ add_action('shutdown', array($this, 'EventAdminShutdown'));
42
+ }
43
  add_action('switch_theme', array($this, 'EventThemeActivated'));
44
  // TO DO
45
  add_action('wp_insert_post', array($this, 'EventPluginPostCreate'), 10, 2);
46
  add_action('delete_post', array($this, 'EventPluginPostDelete'), 10, 1);
47
  }
48
 
49
+ /**
50
+ * Triggered when a user accesses the admin area.
51
+ */
52
+ public function EventAdminInit()
53
+ {
54
  $this->old_themes = wp_get_themes();
55
  $this->old_plugins = get_plugins();
56
  }
57
 
58
+ /**
59
+ * Install, uninstall, activate, deactivate, upgrade and update.
60
+ */
61
+ public function EventAdminShutdown()
62
+ {
63
  $action = (isset($_REQUEST['action']) && $_REQUEST['action'] != "-1") ? $_REQUEST['action'] : '';
64
  $action = (isset($_REQUEST['action2']) && $_REQUEST['action2'] != "-1") ? $_REQUEST['action2'] : $action;
65
  $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
71
  $plugin = array_values(array_diff(array_keys(get_plugins()), array_keys($this->old_plugins)));
72
  if (count($plugin) != 1) {
73
  return $this->LogError(
74
+ 'Expected exactly one new plugin but found ' . count($plugin),
75
+ array('NewPlugin' => $plugin, 'OldPlugins' => $this->old_plugins, 'NewPlugins' => get_plugins())
76
+ );
77
  }
78
  $pluginPath = $plugin[0];
79
  $plugin = get_plugins();
263
  }
264
  }
265
 
266
+ /**
267
+ * Activated a theme.
268
+ * @param string $themeName name
269
+ */
270
+ public function EventThemeActivated($themeName)
271
+ {
272
  $theme = null;
273
  foreach (wp_get_themes() as $item) {
274
  if ($item->Name == $themeName) {
278
  }
279
  if ($theme == null) {
280
  return $this->LogError(
281
+ 'Could not locate theme named "' . $theme . '".',
282
+ array('ThemeName' => $themeName, 'Themes' => wp_get_themes())
283
+ );
284
  }
285
  $this->plugin->alerts->Trigger(5006, array(
286
  'Theme' => (object)array(
295
  }
296
 
297
  /**
298
+ * Plugin creates/modifies posts.
299
+ * @param WP_Post $post post object
300
  */
301
  public function EventPluginPostCreate($insert, $post)
302
  {
326
  }
327
  }
328
 
329
+ /**
330
+ * Plugin deletes posts.
331
+ * @param integer $post_id post ID
332
+ */
333
  public function EventPluginPostDelete($post_id)
334
  {
335
  if (empty($_REQUEST['action']) && isset($_REQUEST['page'])) {
346
  }
347
  }
348
 
349
+ /**
350
+ * Get removed themes.
351
+ * @return array of WP_Theme objects
352
+ */
353
  protected function GetRemovedThemes()
354
  {
355
  $result = $this->old_themes;
361
  return array_values($result);
362
  }
363
 
364
+ /**
365
+ * Get event code by post type.
366
+ */
367
  protected function GetEventTypeForPostType($post, $typePost, $typePage, $typeCustom)
368
  {
369
  switch ($post->post_type) {
376
  }
377
  }
378
 
379
+ /**
380
+ * Get editor link.
381
+ * @param stdClass $post the post
382
+ * @return array $aLink name and value link
383
+ */
384
  private function GetEditorLink($post)
385
  {
386
  $name = 'EditorLink';
classes/Sensors/Request.php CHANGED
@@ -1,7 +1,16 @@
1
  <?php
2
-
 
 
 
 
3
  class WSAL_Sensors_Request extends WSAL_AbstractSensor
4
  {
 
 
 
 
 
5
  public function HookEvents()
6
  {
7
  if ($this->plugin->settings->IsRequestLoggingEnabled()) {
@@ -9,6 +18,9 @@ class WSAL_Sensors_Request extends WSAL_AbstractSensor
9
  }
10
  }
11
 
 
 
 
12
  public function EventShutdown()
13
  {
14
  $upload_dir = wp_upload_dir();
@@ -43,13 +55,17 @@ class WSAL_Sensors_Request extends WSAL_AbstractSensor
43
  }
44
  }
45
 
46
- protected static $envvars = array();
47
-
 
48
  public static function SetVar($name, $value)
49
  {
50
  self::$envvars[$name] = $value;
51
  }
52
 
 
 
 
53
  public static function SetVars($data)
54
  {
55
  foreach ($data as $name => $value) {
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Writes the Request.log.php file.
6
+ */
7
  class WSAL_Sensors_Request extends WSAL_AbstractSensor
8
  {
9
+ protected static $envvars = array();
10
+
11
+ /**
12
+ * Listening to events using WP hooks.
13
+ */
14
  public function HookEvents()
15
  {
16
  if ($this->plugin->settings->IsRequestLoggingEnabled()) {
18
  }
19
  }
20
 
21
+ /**
22
+ * Fires just before PHP shuts down execution.
23
+ */
24
  public function EventShutdown()
25
  {
26
  $upload_dir = wp_upload_dir();
55
  }
56
  }
57
 
58
+ /**
59
+ * Sets $envvars element with key and value.
60
+ */
61
  public static function SetVar($name, $value)
62
  {
63
  self::$envvars[$name] = $value;
64
  }
65
 
66
+ /**
67
+ * Copy data array into $envvars array.
68
+ */
69
  public static function SetVars($data)
70
  {
71
  foreach ($data as $name => $value) {
classes/Sensors/System.php CHANGED
@@ -1,32 +1,83 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- class WSAL_Sensors_System extends WSAL_AbstractSensor
4
- {
5
- const TRANSIENT_404 = 'wsal-404-attempts';
 
 
 
6
 
7
- public function HookEvents()
8
- {
9
- add_action('wsal_prune', array($this, 'EventPruneEvents'), 10, 2);
10
- add_action('admin_init', array($this, 'EventAdminInit'));
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- add_action('automatic_updates_complete', array($this, 'WPUpdate'), 10, 1);
13
- add_filter('template_redirect', array($this, 'Event404'));
 
 
 
 
14
 
15
- $upload_dir = wp_upload_dir();
16
- $uploadsDirPath = trailingslashit($upload_dir['basedir']).'wp-security-audit-log/404s/';
17
- if (!$this->CheckDirectory($uploadsDirPath)) {
18
- wp_mkdir_p($uploadsDirPath);
 
19
  }
20
 
21
- // Cron Job 404 log files pruning
22
- add_action('log_files_pruning', array($this,'LogFilesPruning'));
23
- if (!wp_next_scheduled('log_files_pruning')) {
24
- wp_schedule_event(time(), 'daily', 'log_files_pruning');
25
  }
26
- // whitelist options
27
- add_action('whitelist_options', array($this, 'EventOptions'), 10, 1);
28
  }
29
-
30
  /**
31
  * @param int $count The number of deleted events.
32
  * @param string $query Query that selected events for deletion.
@@ -39,25 +90,55 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
39
  ));
40
  }
41
 
 
 
 
 
42
  protected function Get404LogLimit()
43
  {
44
  return $this->plugin->settings->Get404LogLimit();
45
  }
46
-
 
 
 
 
 
 
 
 
47
  protected function Get404Expiration()
48
  {
49
  return 24 * 60 * 60;
50
  }
51
 
 
 
 
 
 
 
 
52
  protected function IsPast404Limit($site_id, $username, $ip)
53
  {
54
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
55
  $data = $get_fn(self::TRANSIENT_404);
56
  return ($data !== false) && isset($data[$site_id.":".$username.":".$ip]) && ($data[$site_id.":".$username.":".$ip] > $this->Get404LogLimit());
57
  }
58
-
59
- protected function Increment404($site_id, $username, $ip)
60
- {
 
 
 
 
 
 
 
 
 
 
 
61
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
62
  $set_fn = $this->IsMultisite() ? 'set_site_transient' : 'set_transient';
63
 
@@ -71,95 +152,187 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
71
  $data[$site_id.":".$username.":".$ip]++;
72
  $set_fn(self::TRANSIENT_404, $data, $this->Get404Expiration());
73
  }
74
-
75
- public function Event404()
76
- {
77
- $attempts = 1;
78
- // Check if the alert is disabled from the "Enable/Disable Alerts" section
79
- if (!$this->plugin->alerts->IsEnabled(6007)) {
80
- return;
 
 
 
 
81
  }
 
 
 
 
 
 
 
 
 
 
 
82
  global $wp_query;
83
- if (!$wp_query->is_404) {
84
  return;
85
  }
86
  $msg = 'times';
87
 
88
- list($y, $m, $d) = explode('-', date('Y-m-d'));
89
 
90
- $site_id = (function_exists('get_current_blog_id') ? get_current_blog_id() : 0);
91
- $ip = $this->plugin->settings->GetMainClientIP();
92
 
93
- if (!is_user_logged_in()) {
94
- $username = "Website Visitor";
95
  } else {
96
  $username = wp_get_current_user()->user_login;
97
  }
98
-
99
- if ($this->IsPast404Limit($site_id, $username, $ip)) {
100
- return;
101
- }
102
 
103
- $objOcc = new WSAL_Models_Occurrence();
104
-
105
- $occ = $objOcc->CheckAlert404(
106
- array(
107
- $ip,
108
- $username,
109
- 6007,
110
- $site_id,
111
- mktime(0, 0, 0, $m, $d, $y),
112
- mktime(0, 0, 0, $m, $d + 1, $y) - 1
113
- )
114
- );
115
-
116
- $occ = count($occ) ? $occ[0] : null;
117
- if (!empty($occ)) {
118
- // update existing record
119
- $this->Increment404($site_id, $username, $ip);
120
- $new = $occ->GetMetaValue('Attempts', 0) + 1;
121
-
122
- if ($new > $this->Get404LogLimit()) {
123
- $new = 'more than ' . $this->Get404LogLimit();
124
- $msg .= ' This could possible be a scan, therefore keep an eye on the activity from this IP Address';
125
- }
126
-
127
- $linkFile = $this->WriteLog($new, $ip, $username);
128
-
129
- $occ->UpdateMetaValue('Attempts', $new);
130
- $occ->UpdateMetaValue('Username', $username);
131
- $occ->UpdateMetaValue('Msg', $msg);
132
- if (!empty($linkFile)) {
133
- $occ->UpdateMetaValue('LinkFile', $linkFile);
134
- }
135
- $occ->created_on = null;
136
- $occ->Save();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  } else {
138
- $linkFile = $this->WriteLog(1, $ip, $username);
139
- // create a new record
140
- $fields = array(
141
- 'Attempts' => 1,
142
- 'Username' => $username,
143
- 'Msg' => $msg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  );
145
- if (!empty($linkFile)) {
146
- $fields['LinkFile'] = $linkFile;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
- $this->plugin->alerts->Trigger(6007, $fields);
149
  }
150
  }
151
 
152
- public function EventAdminInit()
153
- {
154
- // make sure user can actually modify target options
155
- if (!current_user_can('manage_options')) return;
156
-
 
 
 
 
 
 
 
 
 
 
 
157
  $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
158
  $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
159
  $is_option_page = $actype == 'options';
160
  $is_network_settings = $actype == 'settings';
161
  $is_permalink_page = $actype == 'options-permalink';
162
-
163
  if ($is_option_page && (get_option('users_can_register') xor isset($_POST['users_can_register']))) {
164
  $old = get_option('users_can_register') ? 'Enabled' : 'Disabled';
165
  $new = isset($_POST['users_can_register']) ? 'Enabled' : 'Disabled';
@@ -195,7 +368,7 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
195
  ));
196
  }
197
  }
198
-
199
  if ($is_network_settings && !empty($_POST['admin_email'])) {
200
  $old = get_site_option('admin_email');
201
  $new = trim($_POST['admin_email']);
@@ -207,7 +380,7 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
207
  ));
208
  }
209
  }
210
-
211
  if ($is_permalink_page && !empty($_REQUEST['permalink_structure'])) {
212
  $old = get_option('permalink_structure');
213
  $new = trim($_REQUEST['permalink_structure']);
@@ -219,7 +392,7 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
219
  ));
220
  }
221
  }
222
-
223
  if ($action == 'do-core-upgrade' && isset($_REQUEST['version'])) {
224
  $oldVersion = get_bloginfo('version');
225
  $newVersion = $_REQUEST['version'];
@@ -230,7 +403,7 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
230
  ));
231
  }
232
  }
233
-
234
  /* BBPress Forum support Setting */
235
  if ($action == 'update' && isset($_REQUEST['_bbp_default_role'])) {
236
  $oldRole = get_option('_bbp_default_role');
@@ -275,12 +448,6 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
275
  ));
276
  }
277
  }
278
- // Destroy all the session of the same user from user profile page
279
- if ($action == 'destroy-sessions' && isset($_REQUEST['user_id'])) {
280
- $this->plugin->alerts->Trigger(1006, array(
281
- 'TargetUserID' => $_REQUEST['user_id']
282
- ));
283
- }
284
  }
285
 
286
  /**
@@ -299,13 +466,12 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
299
  }
300
 
301
  /**
302
- * Purge log files older than one month
303
  */
304
- public function LogFilesPruning()
305
- {
306
  if ($this->plugin->GetGlobalOption('purge-404-log', 'off') == 'on') {
307
  $upload_dir = wp_upload_dir();
308
- $uploadsDirPath = trailingslashit($upload_dir['basedir']).'wp-security-audit-log/404s/';
309
  if (is_dir($uploadsDirPath)) {
310
  if ($handle = opendir($uploadsDirPath)) {
311
  while (false !== ($entry = readdir($handle))) {
@@ -323,6 +489,26 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
323
  }
324
  }
325
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  }
327
 
328
  /**
@@ -418,60 +604,112 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor
418
  * Write a new line on 404 log file
419
  * Folder: /uploads/wp-security-audit-log/404s/
420
  */
421
- private function WriteLog($attempts, $ip, $username = '')
422
- {
423
  $nameFile = null;
424
- if ($this->plugin->GetGlobalOption('log-404', 'off') == 'on') {
425
- // Request URL
426
- $url = $_SERVER["HTTP_HOST"] . $_SERVER['REQUEST_URI'];
427
- // Create/Append to the log file
428
- $data = 'Attempts: ' . $attempts . ' - Request URL: ' . $url;
429
- if (!is_user_logged_in()) {
430
- $username = '';
431
- } else {
432
- $username = $username . '_';
433
- }
434
-
435
- if ($ip == '127.0.0.1' || $ip == '::1') {
436
- $ip = 'localhost';
437
- }
438
- $upload_dir = wp_upload_dir();
439
- $uploadsDirPath = trailingslashit($upload_dir['basedir']).'wp-security-audit-log/404s/';
440
- $uploadsURL = trailingslashit($upload_dir['baseurl']).'wp-security-audit-log/404s/';
441
-
442
- // Check directory
443
- if ($this->CheckDirectory($uploadsDirPath)) {
444
- $filename = date('Ymd') . '_' . $username . $ip . '.log';
445
- $fp = $uploadsDirPath . $filename;
446
- $nameFile = $uploadsURL . $filename;
447
- if (!$file = fopen($fp, 'a')) {
448
- $i = 1;
449
- $fileOpened = false;
450
- do {
451
- $fp2 = substr($fp, 0, -4) . '_' . $i . '.log';
452
- if (!file_exists($fp2)) {
453
- if ($file = fopen($fp2, 'a')) {
454
- $fileOpened = true;
455
- $nameFile = $uploadsURL . substr($nameFile, 0, -4) . '_' . $i . '.log';
 
 
 
 
 
 
 
 
 
 
456
  }
457
- } else {
458
- $latestFilename = $this->GetLastModified($uploadsDirPath, $filename);
459
- $fpLast = $uploadsDirPath . $latestFilename;
460
- if ($file = fopen($fpLast, 'a')) {
461
- $fileOpened = true;
462
- $nameFile = $uploadsURL . $latestFilename;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
463
  }
464
- }
465
- $i++;
466
- } while (!$fileOpened);
 
 
467
  }
468
- fwrite($file, sprintf("%s\n", $data));
469
- fclose($file);
470
  }
471
  }
 
472
  return $nameFile;
473
  }
474
 
 
 
 
 
475
  private function GetLastModified($uploadsDirPath, $filename)
476
  {
477
  $filename = substr($filename, 0, -4);
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * System Activity sensor.
6
+ *
7
+ * 6000 Events automatically pruned by system
8
+ * 6001 Option Anyone Can Register in WordPress settings changed
9
+ * 6002 New User Default Role changed
10
+ * 6003 WordPress Administrator Notification email changed
11
+ * 6004 WordPress was updated
12
+ * 6005 User changes the WordPress Permalinks
13
+ * 6007 User requests non-existing pages (404 Error Pages)
14
+ * 8009 User changed forum's role
15
+ * 8010 User changed option of a forum
16
+ * 8012 User changed time to disallow post editing
17
+ * 8013 User changed the forum setting posting throttle time
18
+ * 1006 User logged out all other sessions with the same username
19
+ * 6004 WordPress was updated
20
+ * 6008 Enabled/Disabled the option Discourage search engines from indexing this site
21
+ * 6009 Enabled/Disabled comments on all the website
22
+ * 6010 Enabled/Disabled the option Comment author must fill out name and email
23
+ * 6011 Enabled/Disabled the option Users must be logged in and registered to comment
24
+ * 6012 Enabled/Disabled the option to automatically close comments
25
+ * 6013 Changed the value of the option Automatically close comments
26
+ * 6014 Enabled/Disabled the option for comments to be manually approved
27
+ * 6015 Enabled/Disabled the option for an author to have previously approved comments for the comments to appear
28
+ * 6016 Changed the number of links that a comment must have to be held in the queue
29
+ * 6017 Modified the list of keywords for comments moderation
30
+ * 6018 Modified the list of keywords for comments blacklisting
31
+ */
32
+ class WSAL_Sensors_System extends WSAL_AbstractSensor {
33
 
34
+ /**
35
+ * Transient name.
36
+ * WordPress will prefix the name with "_transient_" or "_transient_timeout_" in the options table.
37
+ */
38
+ const TRANSIENT_404 = 'wsal-404-attempts';
39
+ const TRANSIENT_VISITOR_404 = 'wsal-visitor-404-attempts';
40
 
41
+ /**
42
+ * Listening to events using WP hooks.
43
+ */
44
+ public function HookEvents() {
45
+
46
+ add_action( 'wsal_prune', array( $this, 'EventPruneEvents' ), 10, 2 );
47
+ add_action( 'admin_init', array( $this, 'EventAdminInit' ) );
48
+
49
+ add_action( 'automatic_updates_complete', array( $this, 'WPUpdate' ), 10, 1 );
50
+ add_filter( 'template_redirect', array( $this, 'Event404' ) );
51
+
52
+ $upload_dir = wp_upload_dir();
53
+ $uploadsDirPath = trailingslashit( $upload_dir['basedir'] ) . 'wp-security-audit-log/404s/';
54
+ if ( ! $this->CheckDirectory( $uploadsDirPath ) ) {
55
+ wp_mkdir_p( $uploadsDirPath );
56
+ }
57
 
58
+ // Directory for logged in users log files.
59
+ $user_upload_dir = wp_upload_dir();
60
+ $user_upload_path = trailingslashit( $user_upload_dir['basedir'] . '/wp-security-audit-log/404s/users/' );
61
+ if ( ! $this->CheckDirectory( $user_upload_path ) ) {
62
+ wp_mkdir_p( $user_upload_path );
63
+ }
64
 
65
+ // Directory for visitor log files.
66
+ $visitor_upload_dir = wp_upload_dir();
67
+ $visitor_upload_path = trailingslashit( $visitor_upload_dir['basedir'] . '/wp-security-audit-log/404s/visitors/' );
68
+ if ( ! $this->CheckDirectory( $visitor_upload_path ) ) {
69
+ wp_mkdir_p( $visitor_upload_path );
70
  }
71
 
72
+ // Cron Job 404 log files pruning.
73
+ add_action( 'log_files_pruning', array( $this, 'LogFilesPruning' ) );
74
+ if ( ! wp_next_scheduled( 'log_files_pruning' ) ) {
75
+ wp_schedule_event( time(), 'daily', 'log_files_pruning' );
76
  }
77
+ // whitelist options.
78
+ add_action( 'whitelist_options', array( $this, 'EventOptions' ), 10, 1 );
79
  }
80
+
81
  /**
82
  * @param int $count The number of deleted events.
83
  * @param string $query Query that selected events for deletion.
90
  ));
91
  }
92
 
93
+ /**
94
+ * 404 limit count.
95
+ * @return integer limit
96
+ */
97
  protected function Get404LogLimit()
98
  {
99
  return $this->plugin->settings->Get404LogLimit();
100
  }
101
+
102
+ protected function GetVisitor404LogLimit() {
103
+ return $this->plugin->settings->GetVisitor404LogLimit();
104
+ }
105
+
106
+ /**
107
+ * Expiration of the transient saved in the WP database.
108
+ * @return integer Time until expiration in seconds from now
109
+ */
110
  protected function Get404Expiration()
111
  {
112
  return 24 * 60 * 60;
113
  }
114
 
115
+ /**
116
+ * Check 404 limit.
117
+ * @param integer $site_id blog ID
118
+ * @param string $username username
119
+ * @param string $ip IP address
120
+ * @return boolean passed limit true|false
121
+ */
122
  protected function IsPast404Limit($site_id, $username, $ip)
123
  {
124
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
125
  $data = $get_fn(self::TRANSIENT_404);
126
  return ($data !== false) && isset($data[$site_id.":".$username.":".$ip]) && ($data[$site_id.":".$username.":".$ip] > $this->Get404LogLimit());
127
  }
128
+
129
+ protected function IsPastVisitor404Limit( $site_id, $username, $ip ) {
130
+ $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
131
+ $data = $get_fn( self::TRANSIENT_VISITOR_404 );
132
+ return ( false !== $data ) && isset( $data[ $site_id . ':' . $username . ':' . $ip ] ) && ( $data[ $site_id . ':' . $username . ':' . $ip ] > $this->GetVisitor404LogLimit() );
133
+ }
134
+
135
+ /**
136
+ * Increment 404 limit.
137
+ * @param integer $site_id blog ID
138
+ * @param string $username username
139
+ * @param string $ip IP address
140
+ */
141
+ protected function Increment404($site_id, $username, $ip) {
142
  $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
143
  $set_fn = $this->IsMultisite() ? 'set_site_transient' : 'set_transient';
144
 
152
  $data[$site_id.":".$username.":".$ip]++;
153
  $set_fn(self::TRANSIENT_404, $data, $this->Get404Expiration());
154
  }
155
+
156
+ protected function IncrementVisitor404( $site_id, $username, $ip ) {
157
+ $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
158
+ $set_fn = $this->IsMultisite() ? 'set_site_transient' : 'set_transient';
159
+
160
+ $data = $get_fn( self::TRANSIENT_VISITOR_404 );
161
+ if ( ! $data ) {
162
+ $data = array();
163
+ }
164
+ if ( ! isset( $data[ $site_id . ':' . $username . ':' . $ip ] ) ) {
165
+ $data[ $site_id . ':' . $username . ':' . $ip ] = 1;
166
  }
167
+ $data[ $site_id . ':' . $username . ':' . $ip ]++;
168
+ $set_fn( self::TRANSIENT_VISITOR_404, $data, $this->Get404Expiration() );
169
+ }
170
+
171
+ /**
172
+ * Event 404 Not found.
173
+ */
174
+ public function Event404() {
175
+
176
+ $attempts = 1;
177
+
178
  global $wp_query;
179
+ if ( ! $wp_query->is_404 ) {
180
  return;
181
  }
182
  $msg = 'times';
183
 
184
+ list( $y, $m, $d ) = explode( '-', date( 'Y-m-d' ) );
185
 
186
+ $site_id = ( function_exists( 'get_current_blog_id' ) ? get_current_blog_id() : 0 );
187
+ $ip = $this->plugin->settings->GetMainClientIP();
188
 
189
+ if ( ! is_user_logged_in() ) {
190
+ $username = 'Website Visitor';
191
  } else {
192
  $username = wp_get_current_user()->user_login;
193
  }
 
 
 
 
194
 
195
+ if ( 'Website Visitor' !== $username ) {
196
+
197
+ // Check if the alert is disabled from the "Enable/Disable Alerts" section.
198
+ if ( ! $this->plugin->alerts->IsEnabled( 6007 ) ) {
199
+ return;
200
+ }
201
+
202
+ if ( $this->IsPast404Limit( $site_id, $username, $ip ) ) {
203
+ return;
204
+ }
205
+
206
+ $objOcc = new WSAL_Models_Occurrence();
207
+
208
+ $occ = $objOcc->CheckAlert404(
209
+ array(
210
+ $ip,
211
+ $username,
212
+ 6007,
213
+ $site_id,
214
+ mktime(0, 0, 0, $m, $d, $y),
215
+ mktime(0, 0, 0, $m, $d + 1, $y) - 1
216
+ )
217
+ );
218
+
219
+ $occ = count( $occ ) ? $occ[0] : null;
220
+ if ( ! empty( $occ ) ) {
221
+ // update existing record.
222
+ $this->Increment404($site_id, $username, $ip);
223
+ $new = $occ->GetMetaValue('Attempts', 0) + 1;
224
+
225
+ if ($new > $this->Get404LogLimit()) {
226
+ $new = 'more than ' . $this->Get404LogLimit();
227
+ $msg .= ' This could possible be a scan, therefore keep an eye on the activity from this IP Address';
228
+ }
229
+
230
+ $linkFile = $this->WriteLog( $new, $ip, $username );
231
+
232
+ $occ->UpdateMetaValue('Attempts', $new);
233
+ $occ->UpdateMetaValue('Username', $username);
234
+ $occ->UpdateMetaValue('Msg', $msg);
235
+ if (!empty($linkFile)) {
236
+ $occ->UpdateMetaValue('LinkFile', $linkFile);
237
+ }
238
+ $occ->created_on = null;
239
+ $occ->Save();
240
+ } else {
241
+ $linkFile = $this->WriteLog( 1, $ip, $username );
242
+ // create a new record
243
+ $fields = array(
244
+ 'Attempts' => 1,
245
+ 'Username' => $username,
246
+ 'Msg' => $msg
247
+ );
248
+ if (!empty($linkFile)) {
249
+ $fields['LinkFile'] = $linkFile;
250
+ }
251
+ $this->plugin->alerts->Trigger(6007, $fields);
252
+ }
253
  } else {
254
+
255
+ // Check if the alert is disabled from the "Enable/Disable Alerts" section.
256
+ if ( ! $this->plugin->alerts->IsEnabled( 6023 ) ) {
257
+ return;
258
+ }
259
+
260
+ if ( $this->IsPastVisitor404Limit( $site_id, $username, $ip ) ) {
261
+ return;
262
+ }
263
+
264
+ $objOcc = new WSAL_Models_Occurrence();
265
+
266
+ $occ = $objOcc->CheckAlert404(
267
+ array(
268
+ $ip,
269
+ $username,
270
+ 6023,
271
+ $site_id,
272
+ mktime(0, 0, 0, $m, $d, $y),
273
+ mktime(0, 0, 0, $m, $d + 1, $y) - 1
274
+ )
275
  );
276
+
277
+ $occ = count( $occ ) ? $occ[0] : null;
278
+ if ( ! empty( $occ ) ) {
279
+ // update existing record.
280
+ $this->IncrementVisitor404( $site_id, $username, $ip );
281
+ $new = $occ->GetMetaValue( 'Attempts', 0 ) + 1;
282
+
283
+ if ( $new > $this->GetVisitor404LogLimit() ) {
284
+ $new = 'more than ' . $this->GetVisitor404LogLimit();
285
+ $msg .= ' This could possible be a scan, therefore keep an eye on the activity from this IP Address';
286
+ }
287
+
288
+ $linkFile = $this->WriteLog( $new, $ip, $username, false );
289
+
290
+ $occ->UpdateMetaValue( 'Attempts', $new );
291
+ $occ->UpdateMetaValue( 'Username', $username );
292
+ $occ->UpdateMetaValue( 'Msg', $msg );
293
+ if ( ! empty( $linkFile ) ) {
294
+ $occ->UpdateMetaValue( 'LinkFile', $linkFile );
295
+ }
296
+ $occ->created_on = null;
297
+ $occ->Save();
298
+ } else {
299
+ $linkFile = $this->WriteLog( 1, $ip, $username, false );
300
+ // create a new record.
301
+ $fields = array(
302
+ 'Attempts' => 1,
303
+ 'Username' => $username,
304
+ 'Msg' => $msg,
305
+ );
306
+ if ( ! empty( $linkFile ) ) {
307
+ $fields['LinkFile'] = $linkFile;
308
+ }
309
+ $this->plugin->alerts->Trigger( 6023, $fields );
310
  }
 
311
  }
312
  }
313
 
314
+ /**
315
+ * Triggered when a user accesses the admin area.
316
+ */
317
+ public function EventAdminInit() {
318
+
319
+ // Destroy all the session of the same user from user profile page.
320
+ if ( isset( $_REQUEST['action'] ) && ( 'destroy-sessions' == $_REQUEST['action'] ) && isset( $_REQUEST['user_id'] ) ) {
321
+ $this->plugin->alerts->Trigger( 1006, array(
322
+ 'TargetUserID' => $_REQUEST['user_id'],
323
+ ) );
324
+ }
325
+
326
+ // Make sure user can actually modify target options.
327
+ if ( ! current_user_can( 'manage_options' ) ) {
328
+ return;
329
+ }
330
  $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
331
  $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
332
  $is_option_page = $actype == 'options';
333
  $is_network_settings = $actype == 'settings';
334
  $is_permalink_page = $actype == 'options-permalink';
335
+
336
  if ($is_option_page && (get_option('users_can_register') xor isset($_POST['users_can_register']))) {
337
  $old = get_option('users_can_register') ? 'Enabled' : 'Disabled';
338
  $new = isset($_POST['users_can_register']) ? 'Enabled' : 'Disabled';
368
  ));
369
  }
370
  }
371
+
372
  if ($is_network_settings && !empty($_POST['admin_email'])) {
373
  $old = get_site_option('admin_email');
374
  $new = trim($_POST['admin_email']);
380
  ));
381
  }
382
  }
383
+
384
  if ($is_permalink_page && !empty($_REQUEST['permalink_structure'])) {
385
  $old = get_option('permalink_structure');
386
  $new = trim($_REQUEST['permalink_structure']);
392
  ));
393
  }
394
  }
395
+
396
  if ($action == 'do-core-upgrade' && isset($_REQUEST['version'])) {
397
  $oldVersion = get_bloginfo('version');
398
  $newVersion = $_REQUEST['version'];
403
  ));
404
  }
405
  }
406
+
407
  /* BBPress Forum support Setting */
408
  if ($action == 'update' && isset($_REQUEST['_bbp_default_role'])) {
409
  $oldRole = get_option('_bbp_default_role');
448
  ));
449
  }
450
  }
 
 
 
 
 
 
451
  }
452
 
453
  /**
466
  }
467
 
468
  /**
469
+ * Purge log files older than one month.
470
  */
471
+ public function LogFilesPruning() {
 
472
  if ($this->plugin->GetGlobalOption('purge-404-log', 'off') == 'on') {
473
  $upload_dir = wp_upload_dir();
474
+ $uploadsDirPath = trailingslashit($upload_dir['basedir']).'wp-security-audit-log/404s/users/';
475
  if (is_dir($uploadsDirPath)) {
476
  if ($handle = opendir($uploadsDirPath)) {
477
  while (false !== ($entry = readdir($handle))) {
489
  }
490
  }
491
  }
492
+ if ( 'on' == $this->plugin->GetGlobalOption( 'purge-visitor-404-log', 'off' ) ) {
493
+ $upload_dir = wp_upload_dir();
494
+ $uploadsDirPath = trailingslashit( $upload_dir['basedir'] ) . 'wp-security-audit-log/404s/visitors/';
495
+ if ( is_dir( $uploadsDirPath ) ) {
496
+ if ( $handle = opendir( $uploadsDirPath ) ) {
497
+ while ( false !== ( $entry = readdir( $handle ) ) ) {
498
+ if ( $entry != "." && $entry != ".." ) {
499
+ if ( file_exists( $uploadsDirPath . $entry ) ) {
500
+ $modified = filemtime( $uploadsDirPath . $entry );
501
+ if ( $modified < strtotime( '-4 weeks' ) ) {
502
+ // Delete file.
503
+ unlink( $uploadsDirPath . $entry );
504
+ }
505
+ }
506
+ }
507
+ }
508
+ closedir( $handle );
509
+ }
510
+ }
511
+ }
512
  }
513
 
514
  /**
604
  * Write a new line on 404 log file
605
  * Folder: /uploads/wp-security-audit-log/404s/
606
  */
607
+ private function WriteLog( $attempts, $ip, $username = '', $logged_in = true ) {
 
608
  $nameFile = null;
609
+
610
+ if ( $logged_in ) {
611
+ if ( 'on' == $this->plugin->GetGlobalOption( 'log-404', 'off' ) ) {
612
+ // Request URL
613
+ $url = $_SERVER["HTTP_HOST"] . $_SERVER['REQUEST_URI'];
614
+ // Create/Append to the log file
615
+ $data = 'Attempts: ' . $attempts . ' - Request URL: ' . $url;
616
+ if (!is_user_logged_in()) {
617
+ $username = '';
618
+ } else {
619
+ $username = $username . '_';
620
+ }
621
+
622
+ if ($ip == '127.0.0.1' || $ip == '::1') {
623
+ $ip = 'localhost';
624
+ }
625
+ $upload_dir = wp_upload_dir();
626
+ $uploadsDirPath = trailingslashit($upload_dir['basedir']).'wp-security-audit-log/404s/users/';
627
+ $uploadsURL = trailingslashit($upload_dir['baseurl']).'wp-security-audit-log/404s/users/';
628
+
629
+ // Check directory
630
+ if ($this->CheckDirectory($uploadsDirPath)) {
631
+ $filename = date('Ymd') . '_' . $username . $ip . '.log';
632
+ $fp = $uploadsDirPath . $filename;
633
+ $nameFile = $uploadsURL . $filename;
634
+ if (!$file = fopen($fp, 'a')) {
635
+ $i = 1;
636
+ $fileOpened = false;
637
+ do {
638
+ $fp2 = substr($fp, 0, -4) . '_' . $i . '.log';
639
+ if (!file_exists($fp2)) {
640
+ if ($file = fopen($fp2, 'a')) {
641
+ $fileOpened = true;
642
+ $nameFile = $uploadsURL . substr($nameFile, 0, -4) . '_' . $i . '.log';
643
+ }
644
+ } else {
645
+ $latestFilename = $this->GetLastModified($uploadsDirPath, $filename);
646
+ $fpLast = $uploadsDirPath . $latestFilename;
647
+ if ($file = fopen($fpLast, 'a')) {
648
+ $fileOpened = true;
649
+ $nameFile = $uploadsURL . $latestFilename;
650
+ }
651
  }
652
+ $i++;
653
+ } while (!$fileOpened);
654
+ }
655
+ fwrite($file, sprintf("%s\n", $data));
656
+ fclose($file);
657
+ }
658
+ }
659
+ } else {
660
+ if ( 'on' == $this->plugin->GetGlobalOption( 'log-visitor-404', 'off' ) ) {
661
+ // Request URL.
662
+ $url = $_SERVER["HTTP_HOST"] . $_SERVER['REQUEST_URI'];
663
+ // Create/Append to the log file.
664
+ $data = 'Attempts: ' . $attempts . ' - Request URL: ' . $url;
665
+ $username = '';
666
+
667
+ if ( '127.0.0.1' == $ip || '::1' == $ip ) {
668
+ $ip = 'localhost';
669
+ }
670
+ $upload_dir = wp_upload_dir();
671
+ $uploadsDirPath = trailingslashit( $upload_dir['basedir'] ) . 'wp-security-audit-log/404s/visitors/';
672
+ $uploadsURL = trailingslashit( $upload_dir['baseurl'] ) . 'wp-security-audit-log/404s/visitors/';
673
+
674
+ // Check directory.
675
+ if ( $this->CheckDirectory( $uploadsDirPath ) ) {
676
+ $filename = date( 'Ymd' ) . '_' . $username . $ip . '.log';
677
+ $fp = $uploadsDirPath . $filename;
678
+ $nameFile = $uploadsURL . $filename;
679
+ if ( ! $file = fopen( $fp, 'a' ) ) {
680
+ $i = 1;
681
+ $fileOpened = false;
682
+ do {
683
+ $fp2 = substr( $fp, 0, -4 ) . '_' . $i . '.log';
684
+ if ( ! file_exists( $fp2 ) ) {
685
+ if ( $file = fopen( $fp2, 'a' ) ) {
686
+ $fileOpened = true;
687
+ $nameFile = $uploadsURL . substr( $nameFile, 0, -4 ) . '_' . $i . '.log';
688
+ }
689
+ } else {
690
+ $latestFilename = $this->GetLastModified( $uploadsDirPath, $filename );
691
+ $fpLast = $uploadsDirPath . $latestFilename;
692
+ if ( $file = fopen( $fpLast, 'a' ) ) {
693
+ $fileOpened = true;
694
+ $nameFile = $uploadsURL . $latestFilename;
695
+ }
696
  }
697
+ $i++;
698
+ } while ( ! $fileOpened );
699
+ }
700
+ fwrite( $file, sprintf( "%s\n", $data ) );
701
+ fclose( $file );
702
  }
 
 
703
  }
704
  }
705
+
706
  return $nameFile;
707
  }
708
 
709
+ /**
710
+ * Get the latest file modified.
711
+ * @return string $latest_filename file name
712
+ */
713
  private function GetLastModified($uploadsDirPath, $filename)
714
  {
715
  $filename = substr($filename, 0, -4);
classes/Sensors/UserProfile.php CHANGED
@@ -1,8 +1,27 @@
1
  <?php
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
4
  {
5
-
 
 
6
  public function HookEvents()
7
  {
8
  add_action('admin_init', array($this, 'EventAdminInit'));
@@ -15,16 +34,19 @@ class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
15
 
16
  add_action('edit_user_profile', array($this, 'EventOpenProfile'), 10, 1);
17
  }
18
-
19
  protected $old_superadmins;
20
-
 
 
 
21
  public function EventAdminInit()
22
  {
23
  if ($this->IsMultisite()) {
24
  $this->old_superadmins = get_super_admins();
25
  }
26
  }
27
-
28
  public function EventUserRegister($user_id)
29
  {
30
  $user = get_userdata($user_id);
@@ -43,7 +65,7 @@ class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
43
  ),
44
  ), true);
45
  }
46
-
47
  public function EventUserRoleChanged($user_id, $role, $oldRoles)
48
  {
49
  $user = get_userdata($user_id);
@@ -109,11 +131,11 @@ class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
109
  ));
110
  }
111
  }
112
-
113
  if ($this->IsMultisite()) {
114
  $username = $user->user_login;
115
  $enabled = isset($_REQUEST['super_admin']);
116
-
117
  if ($user_id != get_current_user_id()) {
118
  // super admin enabled
119
  if ($enabled && !in_array($username, $this->old_superadmins)) {
@@ -130,11 +152,11 @@ class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
130
  'TargetUsername' => $user->user_login,
131
  ));
132
  }
133
-
134
  }
135
  }
136
  }
137
-
138
  public function EventUserDeleted($user_id)
139
  {
140
  $user = get_userdata($user_id);
@@ -151,24 +173,24 @@ class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
151
  ), array($this, 'MustNotContainCreateUser'));
152
  }
153
 
154
- public function EventOpenProfile($user)
155
- {
156
- if (!empty($user)) {
157
  $current_user = wp_get_current_user();
158
- if (!empty($current_user) && ($user->ID != $current_user->ID)) {
159
- $this->plugin->alerts->Trigger(4014, array(
 
160
  'UserChanger' => $current_user->user_login,
161
- 'TargetUsername' => $user->user_login
162
- ));
163
  }
164
  }
165
  }
166
-
167
  public function MustNotContainCreateUser(WSAL_AlertManager $mgr)
168
  {
169
  return !$mgr->WillTrigger(4012);
170
  }
171
-
172
  public function MustNotContainUserChanges(WSAL_AlertManager $mgr)
173
  {
174
  return !( $mgr->WillOrHasTriggered(4010)
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * User Profiles sensor.
6
+ *
7
+ * 4000 New user was created on WordPress
8
+ * 4001 User created another WordPress user
9
+ * 4002 The role of a user was changed by another WordPress user
10
+ * 4003 User has changed his or her password
11
+ * 4004 User changed another user's password
12
+ * 4005 User changed his or her email address
13
+ * 4006 User changed another user's email address
14
+ * 4007 User was deleted by another user
15
+ * 4008 User granted Super Admin privileges
16
+ * 4009 User revoked from Super Admin privileges
17
+ * 4013 The forum role of a user was changed by another WordPress user
18
+ * 4014 User opened the profile page of another user
19
+ */
20
  class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
21
  {
22
+ /**
23
+ * Listening to events using WP hooks.
24
+ */
25
  public function HookEvents()
26
  {
27
  add_action('admin_init', array($this, 'EventAdminInit'));
34
 
35
  add_action('edit_user_profile', array($this, 'EventOpenProfile'), 10, 1);
36
  }
37
+
38
  protected $old_superadmins;
39
+
40
+ /**
41
+ * Triggered when a user accesses the admin area.
42
+ */
43
  public function EventAdminInit()
44
  {
45
  if ($this->IsMultisite()) {
46
  $this->old_superadmins = get_super_admins();
47
  }
48
  }
49
+
50
  public function EventUserRegister($user_id)
51
  {
52
  $user = get_userdata($user_id);
65
  ),
66
  ), true);
67
  }
68
+
69
  public function EventUserRoleChanged($user_id, $role, $oldRoles)
70
  {
71
  $user = get_userdata($user_id);
131
  ));
132
  }
133
  }
134
+
135
  if ($this->IsMultisite()) {
136
  $username = $user->user_login;
137
  $enabled = isset($_REQUEST['super_admin']);
138
+
139
  if ($user_id != get_current_user_id()) {
140
  // super admin enabled
141
  if ($enabled && !in_array($username, $this->old_superadmins)) {
152
  'TargetUsername' => $user->user_login,
153
  ));
154
  }
155
+
156
  }
157
  }
158
  }
159
+
160
  public function EventUserDeleted($user_id)
161
  {
162
  $user = get_userdata($user_id);
173
  ), array($this, 'MustNotContainCreateUser'));
174
  }
175
 
176
+ public function EventOpenProfile( $user ) {
177
+ if ( ! empty( $user ) ) {
 
178
  $current_user = wp_get_current_user();
179
+ $updated = ( isset( $_GET['updated'] ) ) ? true : false;
180
+ if ( ! empty( $current_user ) && ( $user->ID !== $current_user->ID ) && empty( $updated ) ) {
181
+ $this->plugin->alerts->Trigger( 4014, array(
182
  'UserChanger' => $current_user->user_login,
183
+ 'TargetUsername' => $user->user_login,
184
+ ) );
185
  }
186
  }
187
  }
188
+
189
  public function MustNotContainCreateUser(WSAL_AlertManager $mgr)
190
  {
191
  return !$mgr->WillTrigger(4012);
192
  }
193
+
194
  public function MustNotContainUserChanges(WSAL_AlertManager $mgr)
195
  {
196
  return !( $mgr->WillOrHasTriggered(4010)
classes/Sensors/Widgets.php CHANGED
@@ -1,31 +1,48 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
4
-
5
- public function HookEvents() {
6
- if(current_user_can("edit_theme_options")) {
 
 
7
  add_action('admin_init', array($this, 'EventWidgetMove'));
8
  add_action('admin_init', array($this, 'EventWidgetPostMove'));
9
  }
10
  add_action('sidebar_admin_setup', array($this, 'EventWidgetActivity'));
11
  }
12
-
13
- protected $_WidgetMoveData = null;
14
 
15
- public function EventWidgetMove(){
16
- if(isset($_POST) && !empty($_POST['sidebars']))
17
- {
 
 
 
 
18
  $crtSidebars = $_POST['sidebars'];
19
  $sidebars = array();
20
- foreach ( $crtSidebars as $key => $val )
21
- {
22
  $sb = array();
23
- if ( !empty($val) )
24
- {
25
  $val = explode(',', $val);
26
- foreach ( $val as $k => $v )
27
- {
28
- if ( strpos($v, 'widget-') === false ) continue;
 
29
  $sb[$k] = substr($v, strpos($v, '_') + 1);
30
  }
31
  }
@@ -34,20 +51,14 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
34
  $crtSidebars = $sidebars;
35
  $dbSidebars = get_option('sidebars_widgets');
36
  $wName = $fromSidebar = $toSidebar = '';
37
- foreach($crtSidebars as $sidebarName => $values)
38
- {
39
- if(is_array($values) && ! empty($values) && isset($dbSidebars[$sidebarName]))
40
- {
41
- foreach($values as $widgetName)
42
- {
43
- if(! in_array($widgetName, $dbSidebars[$sidebarName]))
44
- {
45
  $toSidebar = $sidebarName;
46
  $wName = $widgetName;
47
- foreach($dbSidebars as $name => $v)
48
- {
49
- if(is_array($v) && !empty($v) && in_array($widgetName, $v))
50
- {
51
  $fromSidebar = $name;
52
  continue;
53
  }
@@ -57,9 +68,11 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
57
  }
58
  }
59
 
60
- if (empty($wName) || empty($fromSidebar) || empty($toSidebar)) return;
 
 
61
 
62
- if(preg_match('/^sidebar-/', $fromSidebar) || preg_match('/^sidebar-/', $toSidebar)){
63
  // This option will hold the data needed to trigger the event 2045
64
  // as at this moment the $wp_registered_sidebars variable is not yet populated
65
  // so we cannot retrieve the name for sidebar-1 || sidebar-2
@@ -76,21 +89,25 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
76
  }
77
  }
78
 
79
- public function EventWidgetPostMove() {
80
- //#!-- generates the event 2071
81
- if (isset($_REQUEST['action'])&&($_REQUEST['action']=='widgets-order'))
82
- {
 
 
 
 
83
  if (isset($_REQUEST['sidebars'])) {
84
  // Get the sidebars from $_REQUEST
85
  $requestSidebars = array();
86
  if ($_REQUEST['sidebars']) {
87
- foreach($_REQUEST['sidebars'] as $key => &$value){
88
- if(!empty($value)){
89
  // build the sidebars array
90
  $value = explode(',', $value);
91
  // Cleanup widgets' name
92
- foreach($value as $k => &$widgetName){
93
- $widgetName = preg_replace("/^([a-z]+-[0-9]+)+?_/i",'', $widgetName);
94
  }
95
  $requestSidebars[$key] = $value;
96
  }
@@ -128,25 +145,28 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
128
  }
129
  }
130
  }
131
- //#!--
132
 
133
- if($this->_WidgetMoveData){
134
  $wName = $this->_WidgetMoveData['widget'];
135
  $fromSidebar = $this->_WidgetMoveData['from'];
136
  $toSidebar = $this->_WidgetMoveData['to'];
137
 
138
  global $wp_registered_sidebars;
139
 
140
- if(preg_match('/^sidebar-/', $fromSidebar))
141
  $fromSidebar = isset($wp_registered_sidebars[$fromSidebar])
142
  ? $wp_registered_sidebars[$fromSidebar]['name']
143
  : $fromSidebar
144
  ;
145
- if(preg_match('/^sidebar-/', $toSidebar))
 
 
146
  $toSidebar = isset($wp_registered_sidebars[$toSidebar])
147
  ? $wp_registered_sidebars[$toSidebar]['name']
148
  : $toSidebar
149
  ;
 
150
 
151
  $this->plugin->alerts->Trigger(2045, array(
152
  'WidgetName' => $wName,
@@ -156,8 +176,12 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
156
  }
157
  }
158
 
159
- public function EventWidgetActivity(){
160
- if(!isset($_POST) || !isset($_POST['widget-id']) || empty($_POST['widget-id'])){
 
 
 
 
161
  return;
162
  }
163
 
@@ -165,12 +189,11 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
165
  global $wp_registered_sidebars;
166
  $canCheckSidebar = (empty($wp_registered_sidebars) ? false : true);
167
 
168
- switch(true){
169
-
170
  // added widget
171
  case isset($postData['add_new']) && $postData['add_new'] == 'multi':
172
  $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
173
- if($canCheckSidebar && preg_match('/^sidebar-/', $sidebar)){
174
  $sidebar = $wp_registered_sidebars[$sidebar]['name'];
175
  }
176
  $this->plugin->alerts->Trigger(2042, array(
@@ -178,11 +201,10 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
178
  'Sidebar' => $sidebar,
179
  ));
180
  break;
181
-
182
  // deleted widget
183
  case isset($postData['delete_widget']) && intval($postData['delete_widget']) == 1:
184
  $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
185
- if($canCheckSidebar && preg_match('/^sidebar-/',$sidebar)){
186
  $sidebar = $wp_registered_sidebars[$sidebar]['name'];
187
  }
188
  $this->plugin->alerts->Trigger(2044, array(
@@ -190,16 +212,17 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
190
  'Sidebar' => $sidebar,
191
  ));
192
  break;
193
-
194
  // modified widget
195
  case isset($postData['id_base']) && !empty($postData['id_base']):
196
  $wId = 0;
197
- if(!empty($postData['multi_number'])){
198
  $wId = intval($postData['multi_number']);
199
- }elseif(!empty($postData['widget_number'])){
200
  $wId = intval($postData['widget_number']);
201
  }
202
- if(empty($wId))return;
 
 
203
 
204
  $wName = $postData['id_base'];
205
  $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
@@ -207,20 +230,27 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
207
  ? $postData["widget-$wName"][$wId]
208
  : null;
209
 
210
- if(empty($wData))return;
211
-
 
212
  // get info from db
213
  $wdbData = get_option("widget_".$wName);
214
- if(empty($wdbData[$wId]))return;
 
 
215
 
216
  // transform 'on' -> 1
217
- foreach($wData as $k => $v)if($v == 'on')$wData[$k] = 1;
 
 
 
 
218
 
219
  // compare - checks for any changes inside widgets
220
  $diff = array_diff_assoc($wData, $wdbData[$wId]);
221
  $count = count($diff);
222
- if($count > 0){
223
- if($canCheckSidebar && preg_match("/^sidebar-/",$sidebar)){
224
  $sidebar = $wp_registered_sidebars[$sidebar]['name'];
225
  }
226
  $this->plugin->alerts->Trigger(2043, array(
@@ -229,7 +259,6 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
229
  ));
230
  }
231
  break;
232
-
233
  }
234
  }
235
- }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Widgets sensor.
6
+ *
7
+ * 2042 User added a new widget
8
+ * 2043 User modified a widget
9
+ * 2044 User deleted widget
10
+ * 2045 User moved widget
11
+ * 2071 User changed widget position
12
+ */
13
+ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor
14
+ {
15
+ protected $_WidgetMoveData = null;
16
 
17
+ /**
18
+ * Listening to events using WP hooks.
19
+ */
20
+ public function HookEvents()
21
+ {
22
+ if (current_user_can("edit_theme_options")) {
23
  add_action('admin_init', array($this, 'EventWidgetMove'));
24
  add_action('admin_init', array($this, 'EventWidgetPostMove'));
25
  }
26
  add_action('sidebar_admin_setup', array($this, 'EventWidgetActivity'));
27
  }
 
 
28
 
29
+ /**
30
+ * Triggered when a user accesses the admin area.
31
+ * Moved widget.
32
+ */
33
+ public function EventWidgetMove()
34
+ {
35
+ if (isset($_POST) && !empty($_POST['sidebars'])) {
36
  $crtSidebars = $_POST['sidebars'];
37
  $sidebars = array();
38
+ foreach ($crtSidebars as $key => $val) {
 
39
  $sb = array();
40
+ if (!empty($val)) {
 
41
  $val = explode(',', $val);
42
+ foreach ($val as $k => $v) {
43
+ if (strpos($v, 'widget-') === false) {
44
+ continue;
45
+ }
46
  $sb[$k] = substr($v, strpos($v, '_') + 1);
47
  }
48
  }
51
  $crtSidebars = $sidebars;
52
  $dbSidebars = get_option('sidebars_widgets');
53
  $wName = $fromSidebar = $toSidebar = '';
54
+ foreach ($crtSidebars as $sidebarName => $values) {
55
+ if (is_array($values) && ! empty($values) && isset($dbSidebars[$sidebarName])) {
56
+ foreach ($values as $widgetName) {
57
+ if (! in_array($widgetName, $dbSidebars[$sidebarName])) {
 
 
 
 
58
  $toSidebar = $sidebarName;
59
  $wName = $widgetName;
60
+ foreach ($dbSidebars as $name => $v) {
61
+ if (is_array($v) && !empty($v) && in_array($widgetName, $v)) {
 
 
62
  $fromSidebar = $name;
63
  continue;
64
  }
68
  }
69
  }
70
 
71
+ if (empty($wName) || empty($fromSidebar) || empty($toSidebar)) {
72
+ return;
73
+ }
74
 
75
+ if (preg_match('/^sidebar-/', $fromSidebar) || preg_match('/^sidebar-/', $toSidebar)) {
76
  // This option will hold the data needed to trigger the event 2045
77
  // as at this moment the $wp_registered_sidebars variable is not yet populated
78
  // so we cannot retrieve the name for sidebar-1 || sidebar-2
89
  }
90
  }
91
 
92
+ /**
93
+ * Triggered when a user accesses the admin area.
94
+ * Changed widget position or moved widget.
95
+ */
96
+ public function EventWidgetPostMove()
97
+ {
98
+ // #!-- generates the event 2071
99
+ if (isset($_REQUEST['action']) && ($_REQUEST['action']=='widgets-order')) {
100
  if (isset($_REQUEST['sidebars'])) {
101
  // Get the sidebars from $_REQUEST
102
  $requestSidebars = array();
103
  if ($_REQUEST['sidebars']) {
104
+ foreach ($_REQUEST['sidebars'] as $key => &$value) {
105
+ if (!empty($value)) {
106
  // build the sidebars array
107
  $value = explode(',', $value);
108
  // Cleanup widgets' name
109
+ foreach ($value as $k => &$widgetName) {
110
+ $widgetName = preg_replace("/^([a-z]+-[0-9]+)+?_/i", '', $widgetName);
111
  }
112
  $requestSidebars[$key] = $value;
113
  }
145
  }
146
  }
147
  }
148
+ // #!--
149
 
150
+ if ($this->_WidgetMoveData) {
151
  $wName = $this->_WidgetMoveData['widget'];
152
  $fromSidebar = $this->_WidgetMoveData['from'];
153
  $toSidebar = $this->_WidgetMoveData['to'];
154
 
155
  global $wp_registered_sidebars;
156
 
157
+ if (preg_match('/^sidebar-/', $fromSidebar)) {
158
  $fromSidebar = isset($wp_registered_sidebars[$fromSidebar])
159
  ? $wp_registered_sidebars[$fromSidebar]['name']
160
  : $fromSidebar
161
  ;
162
+ }
163
+
164
+ if (preg_match('/^sidebar-/', $toSidebar)) {
165
  $toSidebar = isset($wp_registered_sidebars[$toSidebar])
166
  ? $wp_registered_sidebars[$toSidebar]['name']
167
  : $toSidebar
168
  ;
169
+ }
170
 
171
  $this->plugin->alerts->Trigger(2045, array(
172
  'WidgetName' => $wName,
176
  }
177
  }
178
 
179
+ /**
180
+ * Widgets Activity (added, modified, deleted).
181
+ */
182
+ public function EventWidgetActivity()
183
+ {
184
+ if (!isset($_POST) || !isset($_POST['widget-id']) || empty($_POST['widget-id'])) {
185
  return;
186
  }
187
 
189
  global $wp_registered_sidebars;
190
  $canCheckSidebar = (empty($wp_registered_sidebars) ? false : true);
191
 
192
+ switch (true) {
 
193
  // added widget
194
  case isset($postData['add_new']) && $postData['add_new'] == 'multi':
195
  $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
196
+ if ($canCheckSidebar && preg_match('/^sidebar-/', $sidebar)) {
197
  $sidebar = $wp_registered_sidebars[$sidebar]['name'];
198
  }
199
  $this->plugin->alerts->Trigger(2042, array(
201
  'Sidebar' => $sidebar,
202
  ));
203
  break;
 
204
  // deleted widget
205
  case isset($postData['delete_widget']) && intval($postData['delete_widget']) == 1:
206
  $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
207
+ if ($canCheckSidebar && preg_match('/^sidebar-/', $sidebar)) {
208
  $sidebar = $wp_registered_sidebars[$sidebar]['name'];
209
  }
210
  $this->plugin->alerts->Trigger(2044, array(
212
  'Sidebar' => $sidebar,
213
  ));
214
  break;
 
215
  // modified widget
216
  case isset($postData['id_base']) && !empty($postData['id_base']):
217
  $wId = 0;
218
+ if (!empty($postData['multi_number'])) {
219
  $wId = intval($postData['multi_number']);
220
+ } elseif (!empty($postData['widget_number'])) {
221
  $wId = intval($postData['widget_number']);
222
  }
223
+ if (empty($wId)) {
224
+ return;
225
+ }
226
 
227
  $wName = $postData['id_base'];
228
  $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
230
  ? $postData["widget-$wName"][$wId]
231
  : null;
232
 
233
+ if (empty($wData)) {
234
+ return;
235
+ }
236
  // get info from db
237
  $wdbData = get_option("widget_".$wName);
238
+ if (empty($wdbData[$wId])) {
239
+ return;
240
+ }
241
 
242
  // transform 'on' -> 1
243
+ foreach ($wData as $k => $v) {
244
+ if ($v == 'on') {
245
+ $wData[$k] = 1;
246
+ }
247
+ }
248
 
249
  // compare - checks for any changes inside widgets
250
  $diff = array_diff_assoc($wData, $wdbData[$wId]);
251
  $count = count($diff);
252
+ if ($count > 0) {
253
+ if ($canCheckSidebar && preg_match("/^sidebar-/", $sidebar)) {
254
  $sidebar = $wp_registered_sidebars[$sidebar]['name'];
255
  }
256
  $this->plugin->alerts->Trigger(2043, array(
259
  ));
260
  }
261
  break;
 
262
  }
263
  }
264
+ }
classes/Sensors/WooCommerce.php CHANGED
@@ -1,6 +1,43 @@
1
  <?php
2
  /**
3
- * Support for WooCommerce Plugin
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  */
5
  class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor
6
  {
@@ -12,6 +49,9 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor
12
  protected $_OldFileNames = array();
13
  protected $_OldFileUrls = array();
14
 
 
 
 
15
  public function HookEvents()
16
  {
17
  if (current_user_can("edit_posts")) {
@@ -26,6 +66,9 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor
26
  // add_action('edit_product_cat', array($this, 'EventCategoryChanged'), 10, 1);
27
  }
28
 
 
 
 
29
  public function EventAdminInit()
30
  {
31
  // load old data, if applicable
@@ -33,6 +76,10 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor
33
  $this->CheckSettingsChange();
34
  }
35
 
 
 
 
 
36
  protected function RetrieveOldData()
37
  {
38
  if (isset($_POST) && isset($_POST['post_ID'])
@@ -783,6 +830,10 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor
783
  return $fn('woocommerce_' . $option_name);
784
  }
785
 
 
 
 
 
786
  private function CheckWooCommerce($post)
787
  {
788
  switch ($post->post_type) {
@@ -793,6 +844,11 @@ class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor
793
  }
794
  }
795
 
 
 
 
 
 
796
  private function GetEditorLink($post)
797
  {
798
  $name = 'EditorLinkProduct';
1
  <?php
2
  /**
3
+ * @package Wsal
4
+ * @subpackage Sensors
5
+ * Support for WooCommerce Plugin.
6
+ *
7
+ * 9000 User created a new product
8
+ * 9001 User published a product
9
+ * 9002 User created a new product category
10
+ * 9003 User changed the category of a product
11
+ * 9004 User modified the short description of a product
12
+ * 9005 User modified the text of a product
13
+ * 9006 User changed the URL of a product
14
+ * 9007 User changed the Product Data of a product
15
+ * 9008 User changed the date of a product
16
+ * 9009 User changed the visibility of a product
17
+ * 9010 User modified the published product
18
+ * 9011 User modified the draft product
19
+ * 9012 User moved a product to trash
20
+ * 9013 User permanently deleted a product
21
+ * 9014 User restored a product from the trash
22
+ * 9015 User changed status of a product
23
+ * 9016 User changed type of a price
24
+ * 9017 User changed the SKU of a product
25
+ * 9018 User changed the stock status of a product
26
+ * 9019 User changed the stock quantity
27
+ * 9020 User set a product type
28
+ * 9021 User changed the weight of a product
29
+ * 9022 User changed the dimensions of a product
30
+ * 9023 User added the Downloadable File to a product
31
+ * 9024 User Removed the Downloadable File from a product
32
+ * 9025 User changed the name of a Downloadable File in a product
33
+ * 9026 User changed the URL of the Downloadable File in a product
34
+ * 9027 User changed the Weight Unit
35
+ * 9028 User changed the Dimensions Unit
36
+ * 9029 User changed the Base Location
37
+ * 9030 User Enabled/Disabled taxes
38
+ * 9031 User changed the currency
39
+ * 9032 User Enabled/Disabled the use of coupons during checkout
40
+ * 9033 User Enabled/Disabled guest checkout
41
  */
42
  class WSAL_Sensors_WooCommerce extends WSAL_AbstractSensor
43
  {
49
  protected $_OldFileNames = array();
50
  protected $_OldFileUrls = array();
51
 
52
+ /**
53
+ * Listening to events using WP hooks.
54
+ */
55
  public function HookEvents()
56
  {
57
  if (current_user_can("edit_posts")) {
66
  // add_action('edit_product_cat', array($this, 'EventCategoryChanged'), 10, 1);
67
  }
68
 
69
+ /**
70
+ * Triggered when a user accesses the admin area.
71
+ */
72
  public function EventAdminInit()
73
  {
74
  // load old data, if applicable
76
  $this->CheckSettingsChange();
77
  }
78
 
79
+ /**
80
+ * Retrieve Old data.
81
+ * @global mixed $_POST post data
82
+ */
83
  protected function RetrieveOldData()
84
  {
85
  if (isset($_POST) && isset($_POST['post_ID'])
830
  return $fn('woocommerce_' . $option_name);
831
  }
832
 
833
+ /**
834
+ * Check post type.
835
+ * @param stdClass $post post
836
+ */
837
  private function CheckWooCommerce($post)
838
  {
839
  switch ($post->post_type) {
844
  }
845
  }
846
 
847
+ /**
848
+ * Get editor link.
849
+ * @param stdClass $post the post
850
+ * @return array $aLink name and value link
851
+ */
852
  private function GetEditorLink($post)
853
  {
854
  $name = 'EditorLinkProduct';
classes/Settings.php CHANGED
@@ -1,13 +1,16 @@
1
  <?php
2
- class WSAL_Settings {
 
 
 
 
 
 
3
  /**
4
  * @var WpSecurityAuditLog
5
  */
6
  protected $_plugin;
7
- public function __construct(WpSecurityAuditLog $plugin) {
8
- $this->_plugin = $plugin;
9
- }
10
-
11
  // <editor-fold desc="Developer Options">
12
  const OPT_DEV_DATA_INSPECTOR = 'd';
13
  const OPT_DEV_PHP_ERRORS = 'p';
@@ -17,18 +20,57 @@ class WSAL_Settings {
17
  const ERROR_CODE_INVALID_IP = 901;
18
 
19
  protected $_devoption = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  /**
21
  * @return array Array of developer options to be enabled by default.
22
  */
23
- public function GetDefaultDevOptions(){
 
24
  return array();
25
  }
 
26
  /**
27
  * Returns whether a developer option is enabled or not.
28
  * @param string $option See self::OPT_DEV_* constants.
29
  * @return boolean If option is enabled or not.
30
  */
31
- public function IsDevOptionEnabled($option){
 
32
  if (is_null($this->_devoption)) {
33
  $this->_devoption = $this->_plugin->GetGlobalOption(
34
  'dev-options',
@@ -38,18 +80,22 @@ class WSAL_Settings {
38
  }
39
  return in_array($option, $this->_devoption);
40
  }
 
41
  /**
42
  * @return boolean Whether any developer option has been enabled or not.
43
  */
44
- public function IsAnyDevOptionEnabled(){
 
45
  return !!$this->_plugin->GetGlobalOption('dev-options', null);
46
  }
 
47
  /**
48
  * Sets whether a developer option is enabled or not.
49
  * @param string $option See self::OPT_DEV_* constants.
50
  * @param boolean $enabled If option should be enabled or not.
51
  */
52
- public function SetDevOptionEnabled($option, $enabled){
 
53
  // make sure options have been loaded
54
  $this->IsDevOptionEnabled('');
55
  // remove option if it exists
@@ -66,88 +112,112 @@ class WSAL_Settings {
66
  implode(',', $this->_devoption)
67
  );
68
  }
 
69
  /**
70
  * Remove all enabled developer options.
71
  */
72
- public function ClearDevOptions(){
 
73
  $this->_devoption = array();
74
  $this->_plugin->SetGlobalOption('dev-options', '');
75
  }
 
76
  /**
77
  * @return boolean Whether to enable data inspector or not.
78
  */
79
- public function IsDataInspectorEnabled(){
 
80
  return $this->IsDevOptionEnabled(self::OPT_DEV_DATA_INSPECTOR);
81
  }
 
82
  /**
83
  * @return boolean Whether to PHP error logging or not.
84
  */
85
- public function IsPhpErrorLoggingEnabled(){
 
86
  return $this->IsDevOptionEnabled(self::OPT_DEV_PHP_ERRORS);
87
  }
 
88
  /**
89
  * @return boolean Whether to log requests to file or not.
90
  */
91
- public function IsRequestLoggingEnabled(){
 
92
  return $this->IsDevOptionEnabled(self::OPT_DEV_REQUEST_LOG);
93
  }
 
94
  /**
95
  * @return boolean Whether to store debug backtrace for PHP alerts or not.
96
  */
97
- public function IsBacktraceLoggingEnabled(){
 
98
  return $this->IsDevOptionEnabled(self::OPT_DEV_BACKTRACE_LOG);
99
  }
100
-
101
  // </editor-fold>
 
102
  /**
103
  * @return boolean Whether dashboard widgets are enabled or not.
104
  */
105
- public function IsWidgetsEnabled(){
 
106
  return !$this->_plugin->GetGlobalOption('disable-widgets');
107
  }
 
108
  /**
109
  * @param boolean $newvalue Whether dashboard widgets are enabled or not.
110
  */
111
- public function SetWidgetsEnabled($newvalue){
 
112
  $this->_plugin->SetGlobalOption('disable-widgets', !$newvalue);
113
  }
 
114
  /**
115
  * @return boolean Whether alerts in audit log view refresh automatically or not.
116
  */
117
- public function IsRefreshAlertsEnabled(){
 
118
  return !$this->_plugin->GetGlobalOption('disable-refresh');
119
  }
 
120
  /**
121
  * @param boolean $newvalue Whether alerts in audit log view refresh automatically or not.
122
  */
123
- public function SetRefreshAlertsEnabled($newvalue){
 
124
  $this->_plugin->SetGlobalOption('disable-refresh', !$newvalue);
125
  }
 
126
  /**
127
  * @return int Maximum number of alerts to show in dashboard widget.
128
  */
129
- public function GetDashboardWidgetMaxAlerts(){
 
130
  return 5;
131
  }
132
-
133
  // <editor-fold desc="Pruning Settings">
134
  /**
135
  * @return int The maximum number of alerts allowable.
136
  */
137
- public function GetMaxAllowedAlerts(){
 
138
  return 5000;
139
  }
 
140
  /**
141
  * @return string The default pruning date.
142
  */
143
- public function GetDefaultPruningDate(){
 
144
  return '1 month';
145
  }
146
- protected $_pruning = 0;
147
  /**
148
  * @return string The current pruning date.
149
  */
150
- public function GetPruningDate(){
 
151
  if (!$this->_pruning) {
152
  $this->_pruning = $this->_plugin->GetGlobalOption('pruning-date');
153
  if (!strtotime($this->_pruning)) {
@@ -156,65 +226,85 @@ class WSAL_Settings {
156
  }
157
  return $this->_pruning;
158
  }
 
159
  /**
160
  * @param string $newvalue The new pruning date.
161
  */
162
- public function SetPruningDate($newvalue){
 
163
  if (strtotime($newvalue)) {
164
  $this->_plugin->SetGlobalOption('pruning-date', $newvalue);
165
  $this->_pruning = $newvalue;
166
  }
167
  }
 
168
  /**
169
  * @return integer Maximum number of alerts to keep.
170
  */
171
- public function GetPruningLimit(){
 
172
  $val = (int)$this->_plugin->GetGlobalOption('pruning-limit');
173
  return $val ? $val : $this->GetMaxAllowedAlerts();
174
  }
 
175
  /**
176
  * @param integer $newvalue The new maximum number of alerts.
177
  */
178
- public function SetPruningLimit($newvalue){
 
179
  $newvalue = max(/*min(*/(int)$newvalue/*, $this->GetMaxAllowedAlerts())*/, 1);
180
  $this->_plugin->SetGlobalOption('pruning-limit', $newvalue);
181
  }
182
- public function SetPruningDateEnabled($enabled){
 
 
183
  $this->_plugin->SetGlobalOption('pruning-date-e', $enabled);
184
  }
185
- public function SetPruningLimitEnabled($enabled){
 
 
186
  $this->_plugin->SetGlobalOption('pruning-limit-e', $enabled);
187
  }
 
188
  public function IsPruningDateEnabled(){
189
  return $this->_plugin->GetGlobalOption('pruning-date-e');
190
  }
191
- public function IsPruningLimitEnabled(){
 
 
192
  return $this->_plugin->GetGlobalOption('pruning-limit-e');
193
  }
194
 
195
- public function IsRestrictAdmins(){
 
196
  return $this->_plugin->GetGlobalOption('restrict-admins', false);
197
  }
 
198
  /**
199
  * @deprecated Sandbox functionality is now in an external plugin.
200
  */
201
- public function IsSandboxPageEnabled(){
 
202
  $plugins = $this->_plugin->licensing->plugins();
203
  return isset($plugins['wsal-sandbox-extensionphp']);
204
  }
205
- public function SetRestrictAdmins($enable){
 
 
206
  $this->_plugin->SetGlobalOption('restrict-admins', (bool)$enable);
207
  }
208
-
209
  // </editor-fold>
210
- protected $_disabled = null;
211
- public function GetDefaultDisabledAlerts(){
212
  return array(0000, 0001, 0002, 0003, 0004, 0005);
213
  }
 
214
  /**
215
  * @return array IDs of disabled alerts.
216
  */
217
- public function GetDisabledAlerts(){
 
218
  if (!$this->_disabled) {
219
  $this->_disabled = implode(',', $this->GetDefaultDisabledAlerts());
220
  $this->_disabled = $this->_plugin->GetGlobalOption('disabled-alerts', $this->_disabled);
@@ -223,94 +313,118 @@ class WSAL_Settings {
223
  }
224
  return $this->_disabled;
225
  }
 
226
  /**
227
  * @param array $types IDs alerts to disable.
228
  */
229
- public function SetDisabledAlerts($types){
 
230
  $this->_disabled = array_unique(array_map('intval', $types));
231
  $this->_plugin->SetGlobalOption('disabled-alerts', implode(',', $this->_disabled));
232
  }
233
- public function IsIncognito(){
 
 
234
  return $this->_plugin->GetGlobalOption('hide-plugin');
235
  }
236
- public function SetIncognito($enabled){
 
 
237
  return $this->_plugin->SetGlobalOption('hide-plugin', $enabled);
238
  }
239
 
240
  /**
241
  * Checking if Logging is enabled.
242
  */
243
- public function IsLoggingDisabled(){
 
244
  return $this->_plugin->GetGlobalOption('disable-logging');
245
  }
246
 
247
- public function SetLoggingDisabled($disabled){
 
248
  return $this->_plugin->SetGlobalOption('disable-logging', $disabled);
249
  }
250
-
251
  /**
252
  * Checking if the data will be removed.
253
  */
254
- public function IsDeleteData(){
 
255
  return $this->_plugin->GetGlobalOption('delete-data');
256
  }
257
 
258
- public function SetDeleteData($enabled){
 
259
  return $this->_plugin->SetGlobalOption('delete-data', $enabled);
260
  }
261
 
262
  // <editor-fold desc="Access Control">
263
-
264
- protected $_viewers = null;
265
- public function SetAllowedPluginViewers($usersOrRoles){
266
  $this->_viewers = $usersOrRoles;
267
  $this->_plugin->SetGlobalOption('plugin-viewers', implode(',', $this->_viewers));
268
  }
269
- public function GetAllowedPluginViewers(){
 
 
270
  if (is_null($this->_viewers)) {
271
  $this->_viewers = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-viewers'))));
272
  }
273
  return $this->_viewers;
274
  }
275
- protected $_editors = null;
276
- public function SetAllowedPluginEditors($usersOrRoles){
 
277
  $this->_editors = $usersOrRoles;
278
  $this->_plugin->SetGlobalOption('plugin-editors', implode(',', $this->_editors));
279
  }
280
- public function GetAllowedPluginEditors(){
 
 
281
  if (is_null($this->_editors)) {
282
  $this->_editors = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-editors'))));
283
  }
284
  return $this->_editors;
285
  }
286
- protected $_perpage = null;
287
- public function SetViewPerPage($newvalue){
 
288
  $this->_perpage = max($newvalue, 1);
289
  $this->_plugin->SetGlobalOption('items-per-page', $this->_perpage);
290
  }
291
- public function GetViewPerPage(){
 
 
292
  if (is_null($this->_perpage)) {
293
  $this->_perpage = (int)$this->_plugin->GetGlobalOption('items-per-page', 10);
294
  }
295
  return $this->_perpage;
296
  }
 
297
  /**
298
  * @param string $action Type of action, either 'view' or 'edit'.
299
  * @return boolean If user has access or not.
300
  */
301
- public function CurrentUserCan($action){
 
302
  return $this->UserCan(wp_get_current_user(), $action);
303
  }
 
304
  /**
305
  * @return string[] List of superadmin usernames.
306
  */
307
- protected function GetSuperAdmins(){
 
308
  return $this->_plugin->IsMultisite() ? get_super_admins() : array();
309
  }
 
310
  /**
311
  * @return string[] List of admin usernames.
312
  */
313
- protected function GetAdmins(){
 
314
  if ($this->_plugin->IsMultisite()) {
315
  // see: https://gist.github.com/1508426/65785a15b8638d43a9905effb59e4d97319ef8f8
316
  global $wpdb;
@@ -324,16 +438,20 @@ class WSAL_Settings {
324
  } else {
325
  $result = array();
326
  $query = 'role=administrator&fields[]=user_login';
327
- foreach (get_users($query) as $user) $result[] = $user->user_login;
 
 
328
  return $result;
329
  }
330
  }
 
331
  /**
332
  * Returns access tokens for a particular action.
333
  * @param string $action Type of action.
334
  * @return string[] List of tokens (usernames, roles etc).
335
  */
336
- public function GetAccessTokens($action) {
 
337
  $allowed = array();
338
  switch ($action) {
339
  case 'view':
@@ -362,12 +480,14 @@ class WSAL_Settings {
362
  }
363
  return array_unique($allowed);
364
  }
 
365
  /**
366
  * @param integer|WP_user $user User object to check.
367
  * @param string $action Type of action, either 'view' or 'edit'.
368
  * @return boolean If user has access or not.
369
  */
370
- public function UserCan($user, $action) {
 
371
  if (is_int($user)) {
372
  $user = get_userdata($user);
373
  }
@@ -380,84 +500,125 @@ class WSAL_Settings {
380
  }
381
  return false;
382
  }
383
- public function GetCurrentUserRoles($baseRoles = null){
384
- if ($baseRoles == null) $baseRoles = wp_get_current_user()->roles;
385
- if (function_exists('is_super_admin') && is_super_admin()) $baseRoles[] = 'superadmin';
 
 
 
 
 
 
386
  return $baseRoles;
387
  }
388
 
389
- public function IsLoginSuperAdmin($username){
 
390
  $userId = username_exists($username);
391
- if (function_exists('is_super_admin') && is_super_admin($userId) ) return true;
392
- else return false;
 
 
 
393
  }
394
-
395
  // </editor-fold>
396
-
397
  // <editor-fold desc="Licensing">
398
- public function GetLicenses(){
 
399
  return $this->_plugin->GetGlobalOption('licenses');
400
  }
401
- public function GetLicense($name){
 
 
402
  $data = $this->GetLicenses();
403
  $name = sanitize_key(basename($name));
404
  return isset($data[$name]) ? $data[$name] : array();
405
  }
406
- public function SetLicenses($data){
 
 
407
  $this->_plugin->SetGlobalOption('licenses', $data);
408
  }
409
- public function GetLicenseKey($name){
 
 
410
  $data = $this->GetLicense($name);
411
  return isset($data['key']) ? $data['key'] : '';
412
  }
 
413
  public function GetLicenseStatus($name){
414
  $data = $this->GetLicense($name);
415
  return isset($data['sts']) ? $data['sts'] : '';
416
  }
417
- public function GetLicenseErrors($name){
 
 
418
  $data = $this->GetLicense($name);
419
  return isset($data['err']) ? $data['err'] : '';
420
  }
421
- public function SetLicenseKey($name, $key){
 
 
422
  $data = $this->GetLicenses();
423
- if (!isset($data[$name])) $data[$name] = array();
 
 
424
  $data[$name]['key'] = $key;
425
  $this->SetLicenses($data);
426
  }
427
- public function SetLicenseStatus($name, $status){
 
 
428
  $data = $this->GetLicenses();
429
- if (!isset($data[$name])) $data[$name] = array();
 
 
430
  $data[$name]['sts'] = $status;
431
  $this->SetLicenses($data);
432
  }
433
- public function SetLicenseErrors($name, $errors){
 
 
434
  $data = $this->GetLicenses();
435
- if (!isset($data[$name])) $data[$name] = array();
 
 
436
  $data[$name]['err'] = $errors;
437
  $this->SetLicenses($data);
438
  }
439
- public function ClearLicenses(){
 
 
440
  $this->SetLicenses(array());
441
  }
442
-
443
  // </editor-fold>
444
  // <editor-fold desc="Client IP Retrieval">
445
-
446
- public function IsMainIPFromProxy(){
 
447
  return $this->_plugin->GetGlobalOption('use-proxy-ip');
448
  }
449
- public function SetMainIPFromProxy($enabled){
 
 
450
  return $this->_plugin->SetGlobalOption('use-proxy-ip', $enabled);
451
  }
452
-
453
- public function IsInternalIPsFiltered(){
 
454
  return $this->_plugin->GetGlobalOption('filter-internal-ip');
455
  }
456
- public function SetInternalIPsFiltering($enabled){
 
 
457
  return $this->_plugin->SetGlobalOption('filter-internal-ip', $enabled);
458
  }
459
-
460
- public function GetMainClientIP(){
 
461
  $result = null;
462
  if ($this->IsMainIPFromProxy()) {
463
  // TODO the algorithm below just gets the first IP in the list...we might want to make this more intelligent somehow
@@ -472,8 +633,9 @@ class WSAL_Settings {
472
  }
473
  return $result;
474
  }
475
-
476
- public function GetClientIPs(){
 
477
  $ips = array();
478
  foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
479
  if (isset($_SERVER[$key])) {
@@ -487,8 +649,9 @@ class WSAL_Settings {
487
  }
488
  return $ips;
489
  }
490
-
491
- protected function NormalizeIP($ip){
 
492
  $ip = trim($ip);
493
  if (strpos($ip, ':') !== false && substr_count($ip, '.') == 3 && strpos($ip, '[') === false) {
494
  // IPv4 with a port (eg: 11.22.33.44:80)
@@ -501,16 +664,23 @@ class WSAL_Settings {
501
  }
502
  return $ip;
503
  }
504
-
505
- protected function ValidateIP($ip){
 
506
  $opts = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6;
507
- if ($this->IsInternalIPsFiltered()) $opts = $opts | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
 
 
508
  $filteredIP = filter_var($ip, FILTER_VALIDATE_IP, $opts);
509
  if (!$filteredIP || empty($filteredIP)) {
510
  //Regex IPV4
511
- if (preg_match("/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/", $ip)) return $ip;
 
 
512
  //Regex IPV6
513
- elseif (preg_match("/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/", $ip)) return $ip;
 
 
514
  if (!$this->IsLoggingDisabled) {
515
  error_log("Invalid IP in ValidateIP function: ".$ip);
516
  }
@@ -523,12 +693,12 @@ class WSAL_Settings {
523
  /**
524
  * Users excluded from monitoring
525
  */
526
- protected $_excluded_users = array();
527
  public function SetExcludedMonitoringUsers($users)
528
  {
529
  $this->_excluded_users = $users;
530
  $this->_plugin->SetGlobalOption('excluded-users', esc_html(implode(',', $this->_excluded_users)));
531
  }
 
532
  public function GetExcludedMonitoringUsers()
533
  {
534
  if (empty($this->_excluded_users)) {
@@ -540,12 +710,14 @@ class WSAL_Settings {
540
  /**
541
  * Roles excluded from monitoring
542
  */
543
- protected $_excluded_roles = array();
544
- public function SetExcludedMonitoringRoles($roles){
545
  $this->_excluded_roles = $roles;
546
  $this->_plugin->SetGlobalOption('excluded-roles', esc_html(implode(',', $this->_excluded_roles)));
547
  }
548
- public function GetExcludedMonitoringRoles(){
 
 
549
  if (empty($this->_excluded_roles)) {
550
  $this->_excluded_roles = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-roles'))));
551
  }
@@ -555,12 +727,14 @@ class WSAL_Settings {
555
  /**
556
  * Custom fields excluded from monitoring
557
  */
558
- protected $_excluded_custom = array();
559
- public function SetExcludedMonitoringCustom($custom){
560
  $this->_excluded_custom = $custom;
561
  $this->_plugin->SetGlobalOption('excluded-custom', esc_html(implode(',', $this->_excluded_custom)));
562
  }
563
- public function GetExcludedMonitoringCustom(){
 
 
564
  if (empty($this->_excluded_custom)) {
565
  $this->_excluded_custom = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-custom'))));
566
  asort($this->_excluded_custom);
@@ -571,12 +745,14 @@ class WSAL_Settings {
571
  /**
572
  * IP excluded from monitoring
573
  */
574
- protected $_excluded_ip = array();
575
- public function SetExcludedMonitoringIP($ip){
576
  $this->_excluded_ip = $ip;
577
  $this->_plugin->SetGlobalOption('excluded-ip', esc_html(implode(',', $this->_excluded_ip)));
578
  }
579
- public function GetExcludedMonitoringIP(){
 
 
580
  if (empty($this->_excluded_ip)) {
581
  $this->_excluded_ip = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-ip'))));
582
  }
@@ -586,7 +762,8 @@ class WSAL_Settings {
586
  /**
587
  * Datetime used in the Alerts.
588
  */
589
- public function GetDatetimeFormat($lineBreak = true) {
 
590
  if ($lineBreak) {
591
  $date_time_format = $this->GetDateFormat() . '<\b\r>' . $this->GetTimeFormat();
592
  } else {
@@ -605,7 +782,8 @@ class WSAL_Settings {
605
  /**
606
  * Date Format from WordPress General Settings.
607
  */
608
- public function GetDateFormat() {
 
609
  $wp_date_format = get_option('date_format');
610
  $search = array('F', 'M', 'n', 'j', ' ', '/', 'y', 'S', ',', 'l', 'D');
611
  $replace = array('m', 'm', 'm', 'd', '-', '-', 'Y', '', '', '', '');
@@ -616,7 +794,8 @@ class WSAL_Settings {
616
  /**
617
  * Time Format from WordPress General Settings.
618
  */
619
- public function GetTimeFormat() {
 
620
  $wp_time_format = get_option('time_format');
621
  $search = array('a', 'A', 'T', ' ');
622
  $replace = array('', '', '', '');
@@ -628,23 +807,28 @@ class WSAL_Settings {
628
  * Alerts Timestamp
629
  * Server's timezone or WordPress' timezone
630
  */
631
- public function GetTimezone(){
 
632
  return $this->_plugin->GetGlobalOption('timezone', 0);
633
  }
634
 
635
- public function SetTimezone($newvalue){
 
636
  return $this->_plugin->SetGlobalOption('timezone', $newvalue);
637
  }
638
 
639
- public function GetAdapterConfig($name_field){
 
640
  return $this->_plugin->GetGlobalOption($name_field);
641
  }
642
 
643
- public function SetAdapterConfig($name_field, $newvalue){
 
644
  return $this->_plugin->SetGlobalOption($name_field, trim($newvalue));
645
  }
646
 
647
- public function GetColumns(){
 
648
  $columns = array('alert_code' => '1', 'type' => '1', 'date' => '1', 'username' => '1', 'source_ip' => '1', 'message' => '1');
649
  if ($this->_plugin->IsMultisite()) {
650
  $columns = array_slice($columns, 0, 5, true) + array('site' => '1') + array_slice($columns, 5, null, true);
@@ -663,49 +847,79 @@ class WSAL_Settings {
663
  }
664
  }
665
 
666
- public function GetColumnsSelected(){
 
667
  return $this->_plugin->GetGlobalOption('columns');
668
  }
669
 
670
- public function SetColumns($columns){
 
671
  return $this->_plugin->SetGlobalOption('columns', json_encode($columns));
672
  }
673
-
674
- public function IsWPBackend(){
 
675
  return $this->_plugin->GetGlobalOption('wp-backend');
676
  }
677
 
678
- public function SetWPBackend($enabled){
 
679
  return $this->_plugin->SetGlobalOption('wp-backend', $enabled);
680
  }
681
 
682
- public function SetFromEmail($email_address){
 
683
  return $this->_plugin->SetGlobalOption('from-email', trim($email_address));
684
  }
685
 
686
- public function GetFromEmail(){
 
687
  return $this->_plugin->GetGlobalOption('from-email');
688
  }
689
 
690
- public function SetDisplayName($display_name){
 
691
  return $this->_plugin->SetGlobalOption('display-name', trim($display_name));
692
  }
693
 
694
- public function GetDisplayName(){
 
695
  return $this->_plugin->GetGlobalOption('display-name');
696
  }
697
 
698
- public function Set404LogLimit($value){
 
699
  return $this->_plugin->SetGlobalOption('log-404-limit', abs($value));
700
  }
701
 
702
- public function Get404LogLimit(){
 
703
  return $this->_plugin->GetGlobalOption('log-404-limit', 99);
704
  }
705
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
706
  /*============================== Support Archive Database ==============================*/
707
 
708
- public function IsArchivingEnabled(){
 
709
  return $this->_plugin->GetGlobalOption('archiving-e');
710
  }
711
 
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * This class is the actual controller of the Settings Page.
6
+ */
7
+ class WSAL_Settings
8
+ {
9
  /**
10
  * @var WpSecurityAuditLog
11
  */
12
  protected $_plugin;
13
+
 
 
 
14
  // <editor-fold desc="Developer Options">
15
  const OPT_DEV_DATA_INSPECTOR = 'd';
16
  const OPT_DEV_PHP_ERRORS = 'p';
20
  const ERROR_CODE_INVALID_IP = 901;
21
 
22
  protected $_devoption = null;
23
+
24
+ protected $_pruning = 0;
25
+
26
+ protected $_disabled = null;
27
+
28
+ protected $_viewers = null;
29
+
30
+ protected $_editors = null;
31
+
32
+ protected $_perpage = null;
33
+
34
+ /**
35
+ * Users excluded from monitoring
36
+ */
37
+ protected $_excluded_users = array();
38
+
39
+ /**
40
+ * Roles excluded from monitoring
41
+ */
42
+ protected $_excluded_roles = array();
43
+
44
+ /**
45
+ * Custom fields excluded from monitoring
46
+ */
47
+ protected $_excluded_custom = array();
48
+
49
+ /**
50
+ * IP excluded from monitoring
51
+ */
52
+ protected $_excluded_ip = array();
53
+
54
+ public function __construct(WpSecurityAuditLog $plugin)
55
+ {
56
+ $this->_plugin = $plugin;
57
+ }
58
+
59
  /**
60
  * @return array Array of developer options to be enabled by default.
61
  */
62
+ public function GetDefaultDevOptions()
63
+ {
64
  return array();
65
  }
66
+
67
  /**
68
  * Returns whether a developer option is enabled or not.
69
  * @param string $option See self::OPT_DEV_* constants.
70
  * @return boolean If option is enabled or not.
71
  */
72
+ public function IsDevOptionEnabled($option)
73
+ {
74
  if (is_null($this->_devoption)) {
75
  $this->_devoption = $this->_plugin->GetGlobalOption(
76
  'dev-options',
80
  }
81
  return in_array($option, $this->_devoption);
82
  }
83
+
84
  /**
85
  * @return boolean Whether any developer option has been enabled or not.
86
  */
87
+ public function IsAnyDevOptionEnabled()
88
+ {
89
  return !!$this->_plugin->GetGlobalOption('dev-options', null);
90
  }
91
+
92
  /**
93
  * Sets whether a developer option is enabled or not.
94
  * @param string $option See self::OPT_DEV_* constants.
95
  * @param boolean $enabled If option should be enabled or not.
96
  */
97
+ public function SetDevOptionEnabled($option, $enabled)
98
+ {
99
  // make sure options have been loaded
100
  $this->IsDevOptionEnabled('');
101
  // remove option if it exists
112
  implode(',', $this->_devoption)
113
  );
114
  }
115
+
116
  /**
117
  * Remove all enabled developer options.
118
  */
119
+ public function ClearDevOptions()
120
+ {
121
  $this->_devoption = array();
122
  $this->_plugin->SetGlobalOption('dev-options', '');
123
  }
124
+
125
  /**
126
  * @return boolean Whether to enable data inspector or not.
127
  */
128
+ public function IsDataInspectorEnabled()
129
+ {
130
  return $this->IsDevOptionEnabled(self::OPT_DEV_DATA_INSPECTOR);
131
  }
132
+
133
  /**
134
  * @return boolean Whether to PHP error logging or not.
135
  */
136
+ public function IsPhpErrorLoggingEnabled()
137
+ {
138
  return $this->IsDevOptionEnabled(self::OPT_DEV_PHP_ERRORS);
139
  }
140
+
141
  /**
142
  * @return boolean Whether to log requests to file or not.
143
  */
144
+ public function IsRequestLoggingEnabled()
145
+ {
146
  return $this->IsDevOptionEnabled(self::OPT_DEV_REQUEST_LOG);
147
  }
148
+
149
  /**
150
  * @return boolean Whether to store debug backtrace for PHP alerts or not.
151
  */
152
+ public function IsBacktraceLoggingEnabled()
153
+ {
154
  return $this->IsDevOptionEnabled(self::OPT_DEV_BACKTRACE_LOG);
155
  }
156
+
157
  // </editor-fold>
158
+
159
  /**
160
  * @return boolean Whether dashboard widgets are enabled or not.
161
  */
162
+ public function IsWidgetsEnabled()
163
+ {
164
  return !$this->_plugin->GetGlobalOption('disable-widgets');
165
  }
166
+
167
  /**
168
  * @param boolean $newvalue Whether dashboard widgets are enabled or not.
169
  */
170
+ public function SetWidgetsEnabled($newvalue)
171
+ {
172
  $this->_plugin->SetGlobalOption('disable-widgets', !$newvalue);
173
  }
174
+
175
  /**
176
  * @return boolean Whether alerts in audit log view refresh automatically or not.
177
  */
178
+ public function IsRefreshAlertsEnabled()
179
+ {
180
  return !$this->_plugin->GetGlobalOption('disable-refresh');
181
  }
182
+
183
  /**
184
  * @param boolean $newvalue Whether alerts in audit log view refresh automatically or not.
185
  */
186
+ public function SetRefreshAlertsEnabled($newvalue)
187
+ {
188
  $this->_plugin->SetGlobalOption('disable-refresh', !$newvalue);
189
  }
190
+
191
  /**
192
  * @return int Maximum number of alerts to show in dashboard widget.
193
  */
194
+ public function GetDashboardWidgetMaxAlerts()
195
+ {
196
  return 5;
197
  }
198
+
199
  // <editor-fold desc="Pruning Settings">
200
  /**
201
  * @return int The maximum number of alerts allowable.
202
  */
203
+ public function GetMaxAllowedAlerts()
204
+ {
205
  return 5000;
206
  }
207
+
208
  /**
209
  * @return string The default pruning date.
210
  */
211
+ public function GetDefaultPruningDate()
212
+ {
213
  return '1 month';
214
  }
215
+
216
  /**
217
  * @return string The current pruning date.
218
  */
219
+ public function GetPruningDate()
220
+ {
221
  if (!$this->_pruning) {
222
  $this->_pruning = $this->_plugin->GetGlobalOption('pruning-date');
223
  if (!strtotime($this->_pruning)) {
226
  }
227
  return $this->_pruning;
228
  }
229
+
230
  /**
231
  * @param string $newvalue The new pruning date.
232
  */
233
+ public function SetPruningDate($newvalue)
234
+ {
235
  if (strtotime($newvalue)) {
236
  $this->_plugin->SetGlobalOption('pruning-date', $newvalue);
237
  $this->_pruning = $newvalue;
238
  }
239
  }
240
+
241
  /**
242
  * @return integer Maximum number of alerts to keep.
243
  */
244
+ public function GetPruningLimit()
245
+ {
246
  $val = (int)$this->_plugin->GetGlobalOption('pruning-limit');
247
  return $val ? $val : $this->GetMaxAllowedAlerts();
248
  }
249
+
250
  /**
251
  * @param integer $newvalue The new maximum number of alerts.
252
  */
253
+ public function SetPruningLimit($newvalue)
254
+ {
255
  $newvalue = max(/*min(*/(int)$newvalue/*, $this->GetMaxAllowedAlerts())*/, 1);
256
  $this->_plugin->SetGlobalOption('pruning-limit', $newvalue);
257
  }
258
+
259
+ public function SetPruningDateEnabled($enabled)
260
+ {
261
  $this->_plugin->SetGlobalOption('pruning-date-e', $enabled);
262
  }
263
+
264
+ public function SetPruningLimitEnabled($enabled)
265
+ {
266
  $this->_plugin->SetGlobalOption('pruning-limit-e', $enabled);
267
  }
268
+
269
  public function IsPruningDateEnabled(){
270
  return $this->_plugin->GetGlobalOption('pruning-date-e');
271
  }
272
+
273
+ public function IsPruningLimitEnabled()
274
+ {
275
  return $this->_plugin->GetGlobalOption('pruning-limit-e');
276
  }
277
 
278
+ public function IsRestrictAdmins()
279
+ {
280
  return $this->_plugin->GetGlobalOption('restrict-admins', false);
281
  }
282
+
283
  /**
284
  * @deprecated Sandbox functionality is now in an external plugin.
285
  */
286
+ public function IsSandboxPageEnabled()
287
+ {
288
  $plugins = $this->_plugin->licensing->plugins();
289
  return isset($plugins['wsal-sandbox-extensionphp']);
290
  }
291
+
292
+ public function SetRestrictAdmins($enable)
293
+ {
294
  $this->_plugin->SetGlobalOption('restrict-admins', (bool)$enable);
295
  }
296
+
297
  // </editor-fold>
298
+ public function GetDefaultDisabledAlerts()
299
+ {
300
  return array(0000, 0001, 0002, 0003, 0004, 0005);
301
  }
302
+
303
  /**
304
  * @return array IDs of disabled alerts.
305
  */
306
+ public function GetDisabledAlerts()
307
+ {
308
  if (!$this->_disabled) {
309
  $this->_disabled = implode(',', $this->GetDefaultDisabledAlerts());
310
  $this->_disabled = $this->_plugin->GetGlobalOption('disabled-alerts', $this->_disabled);
313
  }
314
  return $this->_disabled;
315
  }
316
+
317
  /**
318
  * @param array $types IDs alerts to disable.
319
  */
320
+ public function SetDisabledAlerts($types)
321
+ {
322
  $this->_disabled = array_unique(array_map('intval', $types));
323
  $this->_plugin->SetGlobalOption('disabled-alerts', implode(',', $this->_disabled));
324
  }
325
+
326
+ public function IsIncognito()
327
+ {
328
  return $this->_plugin->GetGlobalOption('hide-plugin');
329
  }
330
+
331
+ public function SetIncognito($enabled)
332
+ {
333
  return $this->_plugin->SetGlobalOption('hide-plugin', $enabled);
334
  }
335
 
336
  /**
337
  * Checking if Logging is enabled.
338
  */
339
+ public function IsLoggingDisabled()
340
+ {
341
  return $this->_plugin->GetGlobalOption('disable-logging');
342
  }
343
 
344
+ public function SetLoggingDisabled($disabled)
345
+ {
346
  return $this->_plugin->SetGlobalOption('disable-logging', $disabled);
347
  }
348
+
349
  /**
350
  * Checking if the data will be removed.
351
  */
352
+ public function IsDeleteData()
353
+ {
354
  return $this->_plugin->GetGlobalOption('delete-data');
355
  }
356
 
357
+ public function SetDeleteData($enabled)
358
+ {
359
  return $this->_plugin->SetGlobalOption('delete-data', $enabled);
360
  }
361
 
362
  // <editor-fold desc="Access Control">
363
+
364
+ public function SetAllowedPluginViewers($usersOrRoles)
365
+ {
366
  $this->_viewers = $usersOrRoles;
367
  $this->_plugin->SetGlobalOption('plugin-viewers', implode(',', $this->_viewers));
368
  }
369
+
370
+ public function GetAllowedPluginViewers()
371
+ {
372
  if (is_null($this->_viewers)) {
373
  $this->_viewers = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-viewers'))));
374
  }
375
  return $this->_viewers;
376
  }
377
+
378
+ public function SetAllowedPluginEditors($usersOrRoles)
379
+ {
380
  $this->_editors = $usersOrRoles;
381
  $this->_plugin->SetGlobalOption('plugin-editors', implode(',', $this->_editors));
382
  }
383
+
384
+ public function GetAllowedPluginEditors()
385
+ {
386
  if (is_null($this->_editors)) {
387
  $this->_editors = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-editors'))));
388
  }
389
  return $this->_editors;
390
  }
391
+
392
+ public function SetViewPerPage($newvalue)
393
+ {
394
  $this->_perpage = max($newvalue, 1);
395
  $this->_plugin->SetGlobalOption('items-per-page', $this->_perpage);
396
  }
397
+
398
+ public function GetViewPerPage()
399
+ {
400
  if (is_null($this->_perpage)) {
401
  $this->_perpage = (int)$this->_plugin->GetGlobalOption('items-per-page', 10);
402
  }
403
  return $this->_perpage;
404
  }
405
+
406
  /**
407
  * @param string $action Type of action, either 'view' or 'edit'.
408
  * @return boolean If user has access or not.
409
  */
410
+ public function CurrentUserCan($action)
411
+ {
412
  return $this->UserCan(wp_get_current_user(), $action);
413
  }
414
+
415
  /**
416
  * @return string[] List of superadmin usernames.
417
  */
418
+ protected function GetSuperAdmins()
419
+ {
420
  return $this->_plugin->IsMultisite() ? get_super_admins() : array();
421
  }
422
+
423
  /**
424
  * @return string[] List of admin usernames.
425
  */
426
+ protected function GetAdmins()
427
+ {
428
  if ($this->_plugin->IsMultisite()) {
429
  // see: https://gist.github.com/1508426/65785a15b8638d43a9905effb59e4d97319ef8f8
430
  global $wpdb;
438
  } else {
439
  $result = array();
440
  $query = 'role=administrator&fields[]=user_login';
441
+ foreach (get_users($query) as $user) {
442
+ $result[] = $user->user_login;
443
+ }
444
  return $result;
445
  }
446
  }
447
+
448
  /**
449
  * Returns access tokens for a particular action.
450
  * @param string $action Type of action.
451
  * @return string[] List of tokens (usernames, roles etc).
452
  */
453
+ public function GetAccessTokens($action)
454
+ {
455
  $allowed = array();
456
  switch ($action) {
457
  case 'view':
480
  }
481
  return array_unique($allowed);
482
  }
483
+
484
  /**
485
  * @param integer|WP_user $user User object to check.
486
  * @param string $action Type of action, either 'view' or 'edit'.
487
  * @return boolean If user has access or not.
488
  */
489
+ public function UserCan($user, $action)
490
+ {
491
  if (is_int($user)) {
492
  $user = get_userdata($user);
493
  }
500
  }
501
  return false;
502
  }
503
+
504
+ public function GetCurrentUserRoles($baseRoles = null)
505
+ {
506
+ if ($baseRoles == null) {
507
+ $baseRoles = wp_get_current_user()->roles;
508
+ }
509
+ if (function_exists('is_super_admin') && is_super_admin()) {
510
+ $baseRoles[] = 'superadmin';
511
+ }
512
  return $baseRoles;
513
  }
514
 
515
+ public function IsLoginSuperAdmin($username)
516
+ {
517
  $userId = username_exists($username);
518
+ if (function_exists('is_super_admin') && is_super_admin($userId)) {
519
+ return true;
520
+ } else {
521
+ return false;
522
+ }
523
  }
524
+
525
  // </editor-fold>
526
+
527
  // <editor-fold desc="Licensing">
528
+ public function GetLicenses()
529
+ {
530
  return $this->_plugin->GetGlobalOption('licenses');
531
  }
532
+
533
+ public function GetLicense($name)
534
+ {
535
  $data = $this->GetLicenses();
536
  $name = sanitize_key(basename($name));
537
  return isset($data[$name]) ? $data[$name] : array();
538
  }
539
+
540
+ public function SetLicenses($data)
541
+ {
542
  $this->_plugin->SetGlobalOption('licenses', $data);
543
  }
544
+
545
+ public function GetLicenseKey($name)
546
+ {
547
  $data = $this->GetLicense($name);
548
  return isset($data['key']) ? $data['key'] : '';
549
  }
550
+
551
  public function GetLicenseStatus($name){
552
  $data = $this->GetLicense($name);
553
  return isset($data['sts']) ? $data['sts'] : '';
554
  }
555
+
556
+ public function GetLicenseErrors($name)
557
+ {
558
  $data = $this->GetLicense($name);
559
  return isset($data['err']) ? $data['err'] : '';
560
  }
561
+
562
+ public function SetLicenseKey($name, $key)
563
+ {
564
  $data = $this->GetLicenses();
565
+ if (!isset($data[$name])) {
566
+ $data[$name] = array();
567
+ }
568
  $data[$name]['key'] = $key;
569
  $this->SetLicenses($data);
570
  }
571
+
572
+ public function SetLicenseStatus($name, $status)
573
+ {
574
  $data = $this->GetLicenses();
575
+ if (!isset($data[$name])) {
576
+ $data[$name] = array();
577
+ }
578
  $data[$name]['sts'] = $status;
579
  $this->SetLicenses($data);
580
  }
581
+
582
+ public function SetLicenseErrors($name, $errors)
583
+ {
584
  $data = $this->GetLicenses();
585
+ if (!isset($data[$name])) {
586
+ $data[$name] = array();
587
+ }
588
  $data[$name]['err'] = $errors;
589
  $this->SetLicenses($data);
590
  }
591
+
592
+ public function ClearLicenses()
593
+ {
594
  $this->SetLicenses(array());
595
  }
596
+
597
  // </editor-fold>
598
  // <editor-fold desc="Client IP Retrieval">
599
+
600
+ public function IsMainIPFromProxy()
601
+ {
602
  return $this->_plugin->GetGlobalOption('use-proxy-ip');
603
  }
604
+
605
+ public function SetMainIPFromProxy($enabled)
606
+ {
607
  return $this->_plugin->SetGlobalOption('use-proxy-ip', $enabled);
608
  }
609
+
610
+ public function IsInternalIPsFiltered()
611
+ {
612
  return $this->_plugin->GetGlobalOption('filter-internal-ip');
613
  }
614
+
615
+ public function SetInternalIPsFiltering($enabled)
616
+ {
617
  return $this->_plugin->SetGlobalOption('filter-internal-ip', $enabled);
618
  }
619
+
620
+ public function GetMainClientIP()
621
+ {
622
  $result = null;
623
  if ($this->IsMainIPFromProxy()) {
624
  // TODO the algorithm below just gets the first IP in the list...we might want to make this more intelligent somehow
633
  }
634
  return $result;
635
  }
636
+
637
+ public function GetClientIPs()
638
+ {
639
  $ips = array();
640
  foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
641
  if (isset($_SERVER[$key])) {
649
  }
650
  return $ips;
651
  }
652
+
653
+ protected function NormalizeIP($ip)
654
+ {
655
  $ip = trim($ip);
656
  if (strpos($ip, ':') !== false && substr_count($ip, '.') == 3 && strpos($ip, '[') === false) {
657
  // IPv4 with a port (eg: 11.22.33.44:80)
664
  }
665
  return $ip;
666
  }
667
+
668
+ protected function ValidateIP($ip)
669
+ {
670
  $opts = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6;
671
+ if ($this->IsInternalIPsFiltered()) {
672
+ $opts = $opts | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
673
+ }
674
  $filteredIP = filter_var($ip, FILTER_VALIDATE_IP, $opts);
675
  if (!$filteredIP || empty($filteredIP)) {
676
  //Regex IPV4
677
+ if (preg_match("/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/", $ip)) {
678
+ return $ip;
679
+ }
680
  //Regex IPV6
681
+ elseif (preg_match("/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/", $ip)) {
682
+ return $ip;
683
+ }
684
  if (!$this->IsLoggingDisabled) {
685
  error_log("Invalid IP in ValidateIP function: ".$ip);
686
  }
693
  /**
694
  * Users excluded from monitoring
695
  */
 
696
  public function SetExcludedMonitoringUsers($users)
697
  {
698
  $this->_excluded_users = $users;
699
  $this->_plugin->SetGlobalOption('excluded-users', esc_html(implode(',', $this->_excluded_users)));
700
  }
701
+
702
  public function GetExcludedMonitoringUsers()
703
  {
704
  if (empty($this->_excluded_users)) {
710
  /**
711
  * Roles excluded from monitoring
712
  */
713
+ public function SetExcludedMonitoringRoles($roles)
714
+ {
715
  $this->_excluded_roles = $roles;
716
  $this->_plugin->SetGlobalOption('excluded-roles', esc_html(implode(',', $this->_excluded_roles)));
717
  }
718
+
719
+ public function GetExcludedMonitoringRoles()
720
+ {
721
  if (empty($this->_excluded_roles)) {
722
  $this->_excluded_roles = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-roles'))));
723
  }
727
  /**
728
  * Custom fields excluded from monitoring
729
  */
730
+ public function SetExcludedMonitoringCustom($custom)
731
+ {
732
  $this->_excluded_custom = $custom;
733
  $this->_plugin->SetGlobalOption('excluded-custom', esc_html(implode(',', $this->_excluded_custom)));
734
  }
735
+
736
+ public function GetExcludedMonitoringCustom()
737
+ {
738
  if (empty($this->_excluded_custom)) {
739
  $this->_excluded_custom = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-custom'))));
740
  asort($this->_excluded_custom);
745
  /**
746
  * IP excluded from monitoring
747
  */
748
+ public function SetExcludedMonitoringIP($ip)
749
+ {
750
  $this->_excluded_ip = $ip;
751
  $this->_plugin->SetGlobalOption('excluded-ip', esc_html(implode(',', $this->_excluded_ip)));
752
  }
753
+
754
+ public function GetExcludedMonitoringIP()
755
+ {
756
  if (empty($this->_excluded_ip)) {
757
  $this->_excluded_ip = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-ip'))));
758
  }
762
  /**
763
  * Datetime used in the Alerts.
764
  */
765
+ public function GetDatetimeFormat($lineBreak = true)
766
+ {
767
  if ($lineBreak) {
768
  $date_time_format = $this->GetDateFormat() . '<\b\r>' . $this->GetTimeFormat();
769
  } else {
782
  /**
783
  * Date Format from WordPress General Settings.
784
  */
785
+ public function GetDateFormat()
786
+ {
787
  $wp_date_format = get_option('date_format');
788
  $search = array('F', 'M', 'n', 'j', ' ', '/', 'y', 'S', ',', 'l', 'D');
789
  $replace = array('m', 'm', 'm', 'd', '-', '-', 'Y', '', '', '', '');
794
  /**
795
  * Time Format from WordPress General Settings.
796
  */
797
+ public function GetTimeFormat()
798
+ {
799
  $wp_time_format = get_option('time_format');
800
  $search = array('a', 'A', 'T', ' ');
801
  $replace = array('', '', '', '');
807
  * Alerts Timestamp
808
  * Server's timezone or WordPress' timezone
809
  */
810
+ public function GetTimezone()
811
+ {
812
  return $this->_plugin->GetGlobalOption('timezone', 0);
813
  }
814
 
815
+ public function SetTimezone($newvalue)
816
+ {
817
  return $this->_plugin->SetGlobalOption('timezone', $newvalue);
818
  }
819
 
820
+ public function GetAdapterConfig($name_field)
821
+ {
822
  return $this->_plugin->GetGlobalOption($name_field);
823
  }
824
 
825
+ public function SetAdapterConfig($name_field, $newvalue)
826
+ {
827
  return $this->_plugin->SetGlobalOption($name_field, trim($newvalue));
828
  }
829
 
830
+ public function GetColumns()
831
+ {
832
  $columns = array('alert_code' => '1', 'type' => '1', 'date' => '1', 'username' => '1', 'source_ip' => '1', 'message' => '1');
833
  if ($this->_plugin->IsMultisite()) {
834
  $columns = array_slice($columns, 0, 5, true) + array('site' => '1') + array_slice($columns, 5, null, true);
847
  }
848
  }
849
 
850
+ public function GetColumnsSelected()
851
+ {
852
  return $this->_plugin->GetGlobalOption('columns');
853
  }
854
 
855
+ public function SetColumns($columns)
856
+ {
857
  return $this->_plugin->SetGlobalOption('columns', json_encode($columns));
858
  }
859
+
860
+ public function IsWPBackend()
861
+ {
862
  return $this->_plugin->GetGlobalOption('wp-backend');
863
  }
864
 
865
+ public function SetWPBackend($enabled)
866
+ {
867
  return $this->_plugin->SetGlobalOption('wp-backend', $enabled);
868
  }
869
 
870
+ public function SetFromEmail($email_address)
871
+ {
872
  return $this->_plugin->SetGlobalOption('from-email', trim($email_address));
873
  }
874
 
875
+ public function GetFromEmail()
876
+ {
877
  return $this->_plugin->GetGlobalOption('from-email');
878
  }
879
 
880
+ public function SetDisplayName($display_name)
881
+ {
882
  return $this->_plugin->SetGlobalOption('display-name', trim($display_name));
883
  }
884
 
885
+ public function GetDisplayName()
886
+ {
887
  return $this->_plugin->GetGlobalOption('display-name');
888
  }
889
 
890
+ public function Set404LogLimit($value)
891
+ {
892
  return $this->_plugin->SetGlobalOption('log-404-limit', abs($value));
893
  }
894
 
895
+ public function Get404LogLimit()
896
+ {
897
  return $this->_plugin->GetGlobalOption('log-404-limit', 99);
898
  }
899
 
900
+ /**
901
+ * Sets the 404 log limit for visitor.
902
+ *
903
+ * @param int $value - 404 log limit.
904
+ * @since 2.6.3
905
+ */
906
+ public function SetVisitor404LogLimit( $value ) {
907
+ return $this->_plugin->SetGlobalOption( 'log-visitor-404-limit', abs( $value ) );
908
+ }
909
+
910
+ /**
911
+ * Get the 404 log limit for visitor.
912
+ *
913
+ * @since 2.6.3
914
+ */
915
+ public function GetVisitor404LogLimit() {
916
+ return $this->_plugin->GetGlobalOption( 'log-visitor-404-limit', 99 );
917
+ }
918
+
919
  /*============================== Support Archive Database ==============================*/
920
 
921
+ public function IsArchivingEnabled()
922
+ {
923
  return $this->_plugin->GetGlobalOption('archiving-e');
924
  }
925
 
classes/SimpleProfiler.php CHANGED
@@ -1,44 +1,54 @@
1
  <?php
2
-
3
- class WSAL_SimpleProfiler {
4
- protected $_items = array();
5
-
6
- public function Start($name) {
7
- $item = new WSAL_SimpleProfiler_Item($name);
8
- $this->_items[] = $item;
9
- return $item;
10
- }
11
-
12
- public function AsComment(){
13
- echo '<!-- ' . PHP_EOL;
14
- foreach($this->_items as $item){
15
- echo ' ' . $item . PHP_EOL;
16
- }
17
- echo '-->' . PHP_EOL;
18
- }
19
-
20
- public function GetItems(){
21
- return $this->_items;
22
- }
 
 
 
 
 
 
23
  }
24
 
25
- class WSAL_SimpleProfiler_Item{
26
- public function __construct($name){
27
- $this->name = $name;
28
- $this->t_bgn = microtime(true);
29
- $this->m_bgn = memory_get_usage();
30
- }
31
-
32
- public function Stop(){
33
- $this->t_end = microtime(true);
34
- $this->m_end = memory_get_usage();
35
- }
36
-
37
- public function __toString(){
38
- $t_diff = $this->t_end - $this->t_bgn;
39
- $m_diff = $this->m_end - $this->m_bgn;
40
- return number_format($t_diff, 6) . 's '
41
- . str_pad(number_format($m_diff, 0), 12, ' ', STR_PAD_LEFT) . 'b '
42
- . $this->name;
43
- }
44
- }
 
 
 
 
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ */
5
+ class WSAL_SimpleProfiler
6
+ {
7
+ protected $_items = array();
8
+
9
+ public function Start($name)
10
+ {
11
+ $item = new WSAL_SimpleProfiler_Item($name);
12
+ $this->_items[] = $item;
13
+ return $item;
14
+ }
15
+
16
+ public function AsComment()
17
+ {
18
+ echo '<!-- ' . PHP_EOL;
19
+ foreach ($this->_items as $item) {
20
+ echo ' ' . $item . PHP_EOL;
21
+ }
22
+ echo '-->' . PHP_EOL;
23
+ }
24
+
25
+ public function GetItems()
26
+ {
27
+ return $this->_items;
28
+ }
29
  }
30
 
31
+ class WSAL_SimpleProfiler_Item
32
+ {
33
+ public function __construct($name)
34
+ {
35
+ $this->name = $name;
36
+ $this->t_bgn = microtime(true);
37
+ $this->m_bgn = memory_get_usage();
38
+ }
39
+
40
+ public function Stop()
41
+ {
42
+ $this->t_end = microtime(true);
43
+ $this->m_end = memory_get_usage();
44
+ }
45
+
46
+ public function __toString()
47
+ {
48
+ $t_diff = $this->t_end - $this->t_bgn;
49
+ $m_diff = $this->m_end - $this->m_bgn;
50
+ return number_format($t_diff, 6) . 's '
51
+ . str_pad(number_format($m_diff, 0), 12, ' ', STR_PAD_LEFT) . 'b '
52
+ . $this->name;
53
+ }
54
+ }
classes/ViewManager.php CHANGED
@@ -1,79 +1,96 @@
1
  <?php
2
-
3
- class WSAL_ViewManager {
4
-
 
 
 
 
 
5
  /**
6
- * @var WSAL_AbstractView[]
7
  */
8
  public $views = array();
9
-
10
  /**
11
  * @var WpSecurityAuditLog
12
  */
13
  protected $_plugin;
14
 
15
- public function __construct(WpSecurityAuditLog $plugin){
 
 
 
 
 
 
16
  $this->_plugin = $plugin;
17
-
18
  // load views
19
- foreach(glob(dirname(__FILE__) . '/Views/*.php') as $file)
20
  $this->AddFromFile($file);
21
-
 
22
  // add menus
23
  add_action('admin_menu', array($this, 'AddAdminMenus'));
24
  add_action('network_admin_menu', array($this, 'AddAdminMenus'));
25
-
26
  // add plugin shortcut links
27
  add_filter('plugin_action_links_' . $plugin->GetBaseName(), array($this, 'AddPluginShortcuts'));
28
-
29
  // render header
30
  add_action('admin_enqueue_scripts', array($this, 'RenderViewHeader'));
31
-
32
  // render footer
33
  add_action('admin_footer', array($this, 'RenderViewFooter'));
34
  }
35
-
36
  /**
37
  * Add new view from file inside autoloader path.
38
  * @param string $file Path to file.
39
  */
40
- public function AddFromFile($file){
 
41
  $this->AddFromClass($this->_plugin->GetClassFileClassName($file));
42
  }
43
-
44
  /**
45
  * Add new view given class name.
46
  * @param string $class Class name.
47
  */
48
- public function AddFromClass($class){
 
49
  $this->AddInstance(new $class($this->_plugin));
50
  }
51
-
52
  /**
53
  * Add newly created view to list.
54
  * @param WSAL_AbstractView $view The new view.
55
  */
56
- public function AddInstance(WSAL_AbstractView $view){
 
57
  $this->views[] = $view;
58
  }
59
-
60
  /**
61
  * Order views by their declared weight.
62
  */
63
- public function ReorderViews(){
 
64
  usort($this->views, array($this, 'OrderByWeight'));
65
  }
66
-
67
  /**
68
  * @internal This has to be public for PHP to call it.
69
  * @param WSAL_AbstractView $a
70
  * @param WSAL_AbstractView $b
71
  * @return int
72
  */
73
- public function OrderByWeight(WSAL_AbstractView $a, WSAL_AbstractView $b){
 
74
  $wa = $a->GetWeight();
75
  $wb = $b->GetWeight();
76
- switch(true){
77
  case $wa < $wb:
78
  return -1;
79
  case $wa > $wb:
@@ -82,14 +99,15 @@ class WSAL_ViewManager {
82
  return 0;
83
  }
84
  }
85
-
86
  /**
87
  * Wordpress Action
88
  */
89
- public function AddAdminMenus(){
 
90
  $this->ReorderViews();
91
-
92
- if($this->_plugin->settings->CurrentUserCan('view') && count($this->views)){
93
  // add main menu
94
  $this->views[0]->hook_suffix = add_menu_page(
95
  'WP Security Audit Log',
@@ -120,81 +138,91 @@ class WSAL_ViewManager {
120
  }
121
  }
122
  }
123
-
124
  /**
125
  * Wordpress Filter
126
  */
127
- public function AddPluginShortcuts($old_links){
 
128
  $this->ReorderViews();
129
-
130
  $new_links = array();
131
- foreach($this->views as $view){
132
- if($view->HasPluginShortcutLink()){
133
  $new_links[] =
134
  '<a href="'
135
- . admin_url('admin.php?page='
136
- . $view->GetSafeViewName()
137
- ) . '">'
138
  . $view->GetName()
139
  . '</a>';
140
  }
141
  }
142
  return array_merge($new_links, $old_links);
143
  }
144
-
145
  /**
146
  * @return int Returns page id of current page (or false on error).
147
  */
148
- protected function GetBackendPageIndex(){
149
- if(isset($_REQUEST['page']))
150
- foreach($this->views as $i => $view)
151
- if($_REQUEST['page'] == $view->GetSafeViewName())
 
152
  return $i;
 
 
 
153
  return false;
154
  }
155
-
156
- /**
157
- *
158
- * @var WSAL_AbstractView|null
159
- */
160
- protected $_active_view = false;
161
-
162
  /**
163
  * @return WSAL_AbstractView|null Returns the current active view or null if none.
164
  */
165
- public function GetActiveView(){
166
- if($this->_active_view === false){
 
167
  $this->_active_view = null;
168
-
169
- if(isset($_REQUEST['page']))
170
- foreach($this->views as $view)
171
- if($_REQUEST['page'] == $view->GetSafeViewName())
172
  $this->_active_view = $view;
173
-
174
- if($this->_active_view)
 
 
 
175
  $this->_active_view->is_active = true;
 
176
  }
177
  return $this->_active_view;
178
  }
179
-
180
  /**
181
  * Render header of the current view.
182
  */
183
- public function RenderViewHeader(){
184
- if (!!($view = $this->GetActiveView())) $view->Header();
 
 
 
185
  }
186
-
187
  /**
188
  * Render footer of the current view.
189
  */
190
- public function RenderViewFooter(){
191
- if (!!($view = $this->GetActiveView())) $view->Footer();
 
 
 
192
  }
193
-
194
  /**
195
  * Render content of the current view.
196
  */
197
- public function RenderViewBody(){
 
198
  $view = $this->GetActiveView();
199
  ?><div class="wrap"><?php
200
  $view->RenderIcon();
@@ -202,16 +230,19 @@ class WSAL_ViewManager {
202
  $view->RenderContent();
203
  ?></div><?php
204
  }
205
-
206
  /**
207
  * Returns view instance corresponding to its class name.
208
  * @param string $className View class name.
209
  * @return WSAL_AbstractView The view or false on failure.
210
  */
211
- public function FindByClassName($className){
212
- foreach($this->views as $view)
213
- if($view instanceof $className)
 
214
  return $view;
 
 
215
  return false;
216
  }
217
 
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * This Class load all the views, initialize them and shows the active one.
6
+ * It creates also the menu items.
7
+ */
8
+ class WSAL_ViewManager
9
+ {
10
  /**
11
+ * @var WSAL_AbstractView[]
12
  */
13
  public $views = array();
14
+
15
  /**
16
  * @var WpSecurityAuditLog
17
  */
18
  protected $_plugin;
19
 
20
+ /**
21
+ * @var WSAL_AbstractView|null
22
+ */
23
+ protected $_active_view = false;
24
+
25
+ public function __construct(WpSecurityAuditLog $plugin)
26
+ {
27
  $this->_plugin = $plugin;
28
+
29
  // load views
30
+ foreach (glob(dirname(__FILE__) . '/Views/*.php') as $file) {
31
  $this->AddFromFile($file);
32
+ }
33
+
34
  // add menus
35
  add_action('admin_menu', array($this, 'AddAdminMenus'));
36
  add_action('network_admin_menu', array($this, 'AddAdminMenus'));
37
+
38
  // add plugin shortcut links
39
  add_filter('plugin_action_links_' . $plugin->GetBaseName(), array($this, 'AddPluginShortcuts'));
40
+
41
  // render header
42
  add_action('admin_enqueue_scripts', array($this, 'RenderViewHeader'));
43
+
44
  // render footer
45
  add_action('admin_footer', array($this, 'RenderViewFooter'));
46
  }
47
+
48
  /**
49
  * Add new view from file inside autoloader path.
50
  * @param string $file Path to file.
51
  */
52
+ public function AddFromFile($file)
53
+ {
54
  $this->AddFromClass($this->_plugin->GetClassFileClassName($file));
55
  }
56
+
57
  /**
58
  * Add new view given class name.
59
  * @param string $class Class name.
60
  */
61
+ public function AddFromClass($class)
62
+ {
63
  $this->AddInstance(new $class($this->_plugin));
64
  }
65
+
66
  /**
67
  * Add newly created view to list.
68
  * @param WSAL_AbstractView $view The new view.
69
  */
70
+ public function AddInstance(WSAL_AbstractView $view)
71
+ {
72
  $this->views[] = $view;
73
  }
74
+
75
  /**
76
  * Order views by their declared weight.
77
  */
78
+ public function ReorderViews()
79
+ {
80
  usort($this->views, array($this, 'OrderByWeight'));
81
  }
82
+
83
  /**
84
  * @internal This has to be public for PHP to call it.
85
  * @param WSAL_AbstractView $a
86
  * @param WSAL_AbstractView $b
87
  * @return int
88
  */
89
+ public function OrderByWeight(WSAL_AbstractView $a, WSAL_AbstractView $b)
90
+ {
91
  $wa = $a->GetWeight();
92
  $wb = $b->GetWeight();
93
+ switch (true) {
94
  case $wa < $wb:
95
  return -1;
96
  case $wa > $wb:
99
  return 0;
100
  }
101
  }
102
+
103
  /**
104
  * Wordpress Action
105
  */
106
+ public function AddAdminMenus()
107
+ {
108
  $this->ReorderViews();
109
+
110
+ if ($this->_plugin->settings->CurrentUserCan('view') && count($this->views)) {
111
  // add main menu
112
  $this->views[0]->hook_suffix = add_menu_page(
113
  'WP Security Audit Log',
138
  }
139
  }
140
  }
141
+
142
  /**
143
  * Wordpress Filter
144
  */
145
+ public function AddPluginShortcuts($old_links)
146
+ {
147
  $this->ReorderViews();
148
+
149
  $new_links = array();
150
+ foreach ($this->views as $view) {
151
+ if ($view->HasPluginShortcutLink()) {
152
  $new_links[] =
153
  '<a href="'
154
+ . admin_url('admin.php?page=' . $view->GetSafeViewName())
155
+ . '">'
 
156
  . $view->GetName()
157
  . '</a>';
158
  }
159
  }
160
  return array_merge($new_links, $old_links);
161
  }
162
+
163
  /**
164
  * @return int Returns page id of current page (or false on error).
165
  */
166
+ protected function GetBackendPageIndex()
167
+ {
168
+ if (isset($_REQUEST['page'])) {
169
+ foreach ($this->views as $i => $view) {
170
+ if ($_REQUEST['page'] == $view->GetSafeViewName()) {
171
  return $i;
172
+ }
173
+ }
174
+ }
175
  return false;
176
  }
177
+
 
 
 
 
 
 
178
  /**
179
  * @return WSAL_AbstractView|null Returns the current active view or null if none.
180
  */
181
+ public function GetActiveView()
182
+ {
183
+ if ($this->_active_view === false) {
184
  $this->_active_view = null;
185
+
186
+ if (isset($_REQUEST['page'])) {
187
+ foreach ($this->views as $view) {
188
+ if ($_REQUEST['page'] == $view->GetSafeViewName()) {
189
  $this->_active_view = $view;
190
+ }
191
+ }
192
+ }
193
+
194
+ if ($this->_active_view) {
195
  $this->_active_view->is_active = true;
196
+ }
197
  }
198
  return $this->_active_view;
199
  }
200
+
201
  /**
202
  * Render header of the current view.
203
  */
204
+ public function RenderViewHeader()
205
+ {
206
+ if (!!($view = $this->GetActiveView())) {
207
+ $view->Header();
208
+ }
209
  }
210
+
211
  /**
212
  * Render footer of the current view.
213
  */
214
+ public function RenderViewFooter()
215
+ {
216
+ if (!!($view = $this->GetActiveView())) {
217
+ $view->Footer();
218
+ }
219
  }
220
+
221
  /**
222
  * Render content of the current view.
223
  */
224
+ public function RenderViewBody()
225
+ {
226
  $view = $this->GetActiveView();
227
  ?><div class="wrap"><?php
228
  $view->RenderIcon();
230
  $view->RenderContent();
231
  ?></div><?php
232
  }
233
+
234
  /**
235
  * Returns view instance corresponding to its class name.
236
  * @param string $className View class name.
237
  * @return WSAL_AbstractView The view or false on failure.
238
  */
239
+ public function FindByClassName($className)
240
+ {
241
+ foreach ($this->views as $view) {
242
+ if ($view instanceof $className) {
243
  return $view;
244
+ }
245
+ }
246
  return false;
247
  }
248
 
classes/Views/About.php CHANGED
@@ -1,86 +1,94 @@
1
  <?php
2
-
3
- class WSAL_Views_About extends WSAL_AbstractView {
4
-
5
- public function GetTitle() {
6
- return __('About WP Security Audit Log', 'wp-security-audit-log');
7
- }
8
-
9
- public function GetIcon() {
10
- return 'dashicons-editor-help';
11
- }
12
-
13
- public function GetName() {
14
- return __('About', 'wp-security-audit-log');
15
- }
16
-
17
- public function GetWeight(){
18
- return 6;
19
- }
20
-
21
- public function Render(){
22
- ?><div class="metabox-holder" style="position: relative;">
23
-
24
- <div class="postbox" style="margin-right: 270px;">
25
- <!--h3 class="hndl"><span>About WP Security Audit Log</span></h3-->
26
- <div class="inside">
27
- <div class="activity-block">
28
- <?php _e('WP Security Audit Log enables WordPress administrators and owners to identify WordPress security issues before they become a security problem by keeping a security audit log. WP Security Audit Log is developed by WordPress security professionals WP White Security.', 'wp-security-audit-log'); ?>
29
-
30
- <h2><?php _e('Keep A WordPress Security Audit Log & Identify WordPress Security Issues', 'wp-security-audit-log'); ?></h2>
31
- <p>
32
- <?php _e('WP Security Audit Log logs everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A WordPress security alert is generated by the plugin when:', 'wp-security-audit-log'); ?>
33
- </p>
34
- <ul style="list-style-type: disc; margin-left: 2.5em; list-style-position: outside;">
35
- <li><?php _e('User creates a new user or a new user is registered', 'wp-security-audit-log'); ?></li>
36
- <li><?php _e('Existing user changes the role, password or other properties of another user', 'wp-security-audit-log'); ?></li>
37
- <li><?php _e('Existing user on a WordPress multisite network is added to a site', 'wp-security-audit-log'); ?></li>
38
- <li><?php _e('User uploads or deletes a file, changes a password or email address', 'wp-security-audit-log'); ?></li>
39
- <li><?php _e('User installs, activates, deactivates, upgrades or uninstalls a plugin', 'wp-security-audit-log'); ?></li>
40
- <li><?php _e('User creates, modifies or deletes a new post, page, category or a custom post type', 'wp-security-audit-log'); ?></li>
41
- <li><?php _e('User installs or activates a WordPress theme', 'wp-security-audit-log'); ?></li>
42
- <li><?php _e('User adds, modifies or deletes a widget', 'wp-security-audit-log'); ?></li>
43
- <li><?php _e('User uses the dashboard file editor', 'wp-security-audit-log'); ?></li>
44
- <li><?php _e('WordPress settings are changed', 'wp-security-audit-log'); ?></li>
45
- <li><?php _e('Failed login attempts', 'wp-security-audit-log'); ?></li>
46
- <li><?php _e('and much more&hellip;', 'wp-security-audit-log'); ?></li>
47
- </ul>
48
- <br/>
49
- Refer to the complete list of <a href="http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/?utm_source=wsalabt&utm_medium=txtlink&utm_campaign=wsal" target="_blank">WordPress Security Alerts</a> for more information.
50
- </div>
51
- </div>
52
- </div>
53
-
54
- <div style="position: absolute; right: 70px; width: 180px; top: 10px;">
55
- <div class="postbox">
56
- <h3 class="hndl"><span><?php _e('Extend the Functionality & Get More Value from WP Security Audit Log', 'wp-security-audit-log'); ?></span></h3>
57
- <div class="inside">
58
- <p>
59
- <?php _e('Get more value out of WP Security Audit Log by extending the functionality of WP Security Audit Log with the premium Add-Ons.'); ?>
60
- </p>
61
- <a class="button button-primary" href="http://www.wpsecurityauditlog.com/plugin-extensions/" target="_blank"><?php _e('See Add-Ons', 'wp-security-audit-log'); ?></a>
62
- </div>
63
- </div>
64
- <div class="postbox">
65
- <h3 class="hndl"><span><?php _e('WP Security Audit Log in your Language!', 'wp-security-audit-log'); ?></span></h3>
66
- <div class="inside">
67
- <?php _e('If you are interested in translating our plugin please drop us an email on', 'wp-security-audit-log'); ?>
68
- <a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
69
- </div>
70
- </div>
71
- <div class="postbox">
72
- <h3 class="hndl"><span><?php _e('WordPress Security Services', 'wp-security-audit-log'); ?></span></h3>
73
- <div class="inside">
74
- <?php _e('Professional WordPress security services provided by WP White Security', 'wp-security-audit-log'); ?>
75
- <ul>
76
- <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-hardening/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Hardening</a></li>
77
- <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-audit/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Audit</a></li>
78
- <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-plugins-security-code-audit-review/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Plugin Security Code Audit</a></li>
79
- </ul>
80
- </div>
81
- </div>
82
- </div>
83
- </div><?php
84
- }
85
-
86
- }
 
 
 
 
 
 
 
 
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * About Page.
6
+ */
7
+ class WSAL_Views_About extends WSAL_AbstractView
8
+ {
9
+ public function GetTitle()
10
+ {
11
+ return __('About WP Security Audit Log', 'wp-security-audit-log');
12
+ }
13
+
14
+ public function GetIcon()
15
+ {
16
+ return 'dashicons-editor-help';
17
+ }
18
+
19
+ public function GetName()
20
+ {
21
+ return __('About', 'wp-security-audit-log');
22
+ }
23
+
24
+ public function GetWeight()
25
+ {
26
+ return 6;
27
+ }
28
+
29
+ public function Render()
30
+ {
31
+ ?><div class="metabox-holder" style="position: relative;">
32
+
33
+ <div class="postbox" style="margin-right: 270px;">
34
+ <!--h3 class="hndl"><span>About WP Security Audit Log</span></h3-->
35
+ <div class="inside">
36
+ <div class="activity-block">
37
+ <?php _e('WP Security Audit Log enables WordPress administrators and owners to identify WordPress security issues before they become a security problem by keeping a security audit log. WP Security Audit Log is developed by WordPress security professionals WP White Security.', 'wp-security-audit-log'); ?>
38
+
39
+ <h2><?php _e('Keep A WordPress Security Audit Log & Identify WordPress Security Issues', 'wp-security-audit-log'); ?></h2>
40
+ <p>
41
+ <?php _e('WP Security Audit Log logs everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A WordPress security alert is generated by the plugin when:', 'wp-security-audit-log'); ?>
42
+ </p>
43
+ <ul style="list-style-type: disc; margin-left: 2.5em; list-style-position: outside;">
44
+ <li><?php _e('User creates a new user or a new user is registered', 'wp-security-audit-log'); ?></li>
45
+ <li><?php _e('Existing user changes the role, password or other properties of another user', 'wp-security-audit-log'); ?></li>
46
+ <li><?php _e('Existing user on a WordPress multisite network is added to a site', 'wp-security-audit-log'); ?></li>
47
+ <li><?php _e('User uploads or deletes a file, changes a password or email address', 'wp-security-audit-log'); ?></li>
48
+ <li><?php _e('User installs, activates, deactivates, upgrades or uninstalls a plugin', 'wp-security-audit-log'); ?></li>
49
+ <li><?php _e('User creates, modifies or deletes a new post, page, category or a custom post type', 'wp-security-audit-log'); ?></li>
50
+ <li><?php _e('User installs or activates a WordPress theme', 'wp-security-audit-log'); ?></li>
51
+ <li><?php _e('User adds, modifies or deletes a widget', 'wp-security-audit-log'); ?></li>
52
+ <li><?php _e('User uses the dashboard file editor', 'wp-security-audit-log'); ?></li>
53
+ <li><?php _e('WordPress settings are changed', 'wp-security-audit-log'); ?></li>
54
+ <li><?php _e('Failed login attempts', 'wp-security-audit-log'); ?></li>
55
+ <li><?php _e('and much more&hellip;', 'wp-security-audit-log'); ?></li>
56
+ </ul>
57
+ <br/>
58
+ Refer to the complete list of <a href="http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/?utm_source=wsalabt&utm_medium=txtlink&utm_campaign=wsal" target="_blank">WordPress Security Alerts</a> for more information.
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <div style="position: absolute; right: 70px; width: 180px; top: 10px;">
64
+ <div class="postbox">
65
+ <h3 class="hndl"><span><?php _e('Extend the Functionality & Get More Value from WP Security Audit Log', 'wp-security-audit-log'); ?></span></h3>
66
+ <div class="inside">
67
+ <p>
68
+ <?php _e('Get more value out of WP Security Audit Log by extending the functionality of WP Security Audit Log with the premium Add-Ons.'); ?>
69
+ </p>
70
+ <a class="button button-primary" href="http://www.wpsecurityauditlog.com/plugin-extensions/" target="_blank"><?php _e('See Add-Ons', 'wp-security-audit-log'); ?></a>
71
+ </div>
72
+ </div>
73
+ <div class="postbox">
74
+ <h3 class="hndl"><span><?php _e('WP Security Audit Log in your Language!', 'wp-security-audit-log'); ?></span></h3>
75
+ <div class="inside">
76
+ <?php _e('If you are interested in translating our plugin please drop us an email on', 'wp-security-audit-log'); ?>
77
+ <a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
78
+ </div>
79
+ </div>
80
+ <div class="postbox">
81
+ <h3 class="hndl"><span><?php _e('WordPress Security Services', 'wp-security-audit-log'); ?></span></h3>
82
+ <div class="inside">
83
+ <?php _e('Professional WordPress security services provided by WP White Security', 'wp-security-audit-log'); ?>
84
+ <ul>
85
+ <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-hardening/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Hardening</a></li>
86
+ <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-audit/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Audit</a></li>
87
+ <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-plugins-security-code-audit-review/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Plugin Security Code Audit</a></li>
88
+ </ul>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div><?php
93
+ }
94
+ }
classes/Views/AuditLog.php CHANGED
@@ -1,7 +1,12 @@
1
  <?php
2
  require_once(ABSPATH . 'wp-admin/includes/plugin.php');
3
-
4
- class WSAL_Views_AuditLog extends WSAL_AbstractView {
 
 
 
 
 
5
  /**
6
  * @var WSAL_AuditLogListView
7
  */
@@ -9,7 +14,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
9
 
10
  protected $_version;
11
 
12
- public function __construct(WpSecurityAuditLog $plugin) {
 
13
  parent::__construct($plugin);
14
  add_action('wp_ajax_AjaxInspector', array($this, 'AjaxInspector'));
15
  add_action('wp_ajax_AjaxRefresh', array($this, 'AjaxRefresh'));
@@ -43,36 +49,43 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
43
  }
44
  }
45
 
46
- public function HasPluginShortcutLink() {
 
47
  return true;
48
  }
49
 
50
- public function GetTitle() {
 
51
  return __('Audit Log Viewer', 'wp-security-audit-log');
52
  }
53
 
54
- public function GetIcon() {
 
55
  return $this->_wpversion < 3.8
56
  ? $this->_plugin->GetBaseUrl() . '/img/logo-main-menu.png'
57
  : 'dashicons-welcome-view-site';
58
  }
59
 
60
- public function GetName() {
 
61
  return __('Audit Log Viewer', 'wp-security-audit-log');
62
  }
63
 
64
- public function GetWeight() {
 
65
  return 1;
66
  }
67
 
68
- protected function GetListView() {
 
69
  if (is_null($this->_listview)) {
70
  $this->_listview = new WSAL_AuditLogListView($this->_plugin);
71
  }
72
  return $this->_listview;
73
  }
74
 
75
- public function Render() {
 
76
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
77
  wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
78
  }
@@ -108,7 +121,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
108
  </script><?php
109
  }
110
 
111
- public function AjaxInspector() {
 
112
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
113
  die('Access Denied.');
114
  }
@@ -133,7 +147,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
133
  die;
134
  }
135
 
136
- public function AjaxRefresh() {
 
137
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
138
  die('Access Denied.');
139
  }
@@ -145,9 +160,11 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
145
  $max = 40; // 40*500msec = 20sec
146
 
147
  $is_archive = false;
148
- $wp_session = WP_Session::get_instance();
149
- if (isset($wp_session['selected_db']) && $wp_session['selected_db'] == 'archive') {
150
- $is_archive = true;
 
 
151
  }
152
 
153
  do {
@@ -164,7 +181,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
164
  die;
165
  }
166
 
167
- public function AjaxSetIpp() {
 
168
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
169
  die('Access Denied.');
170
  }
@@ -175,7 +193,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
175
  die;
176
  }
177
 
178
- public function AjaxSearchSite() {
 
179
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
180
  die('Access Denied.');
181
  }
@@ -197,14 +216,15 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
197
  die(json_encode(array_slice($grp1 + $grp2, 0, 7)));
198
  }
199
 
200
- public function AjaxSwitchDB() {
 
201
  if (isset($_REQUEST['selected_db'])) {
202
- $wp_session = WP_Session::get_instance();
203
- $wp_session['selected_db'] = $_REQUEST['selected_db'];
204
  }
205
  }
206
 
207
- public function Header() {
 
208
  add_thickbox();
209
  wp_enqueue_style('darktooltip', $this->_plugin->GetBaseUrl() . '/css/darktooltip.css', array(), '');
210
  wp_enqueue_style(
@@ -215,7 +235,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
215
  );
216
  }
217
 
218
- public function Footer() {
 
219
  wp_enqueue_script('jquery');
220
  wp_enqueue_script('darktooltip', $this->_plugin->GetBaseUrl() . '/js/jquery.darktooltip.js', array('jquery'), '');
221
  wp_enqueue_script('suggest');
1
  <?php
2
  require_once(ABSPATH . 'wp-admin/includes/plugin.php');
3
+ /**
4
+ * @package Wsal
5
+ *
6
+ * Audit Log Viewer Page
7
+ */
8
+ class WSAL_Views_AuditLog extends WSAL_AbstractView
9
+ {
10
  /**
11
  * @var WSAL_AuditLogListView
12
  */
14
 
15
  protected $_version;
16
 
17
+ public function __construct(WpSecurityAuditLog $plugin)
18
+ {
19
  parent::__construct($plugin);
20
  add_action('wp_ajax_AjaxInspector', array($this, 'AjaxInspector'));
21
  add_action('wp_ajax_AjaxRefresh', array($this, 'AjaxRefresh'));
49
  }
50
  }
51
 
52
+ public function HasPluginShortcutLink()
53
+ {
54
  return true;
55
  }
56
 
57
+ public function GetTitle()
58
+ {
59
  return __('Audit Log Viewer', 'wp-security-audit-log');
60
  }
61
 
62
+ public function GetIcon()
63
+ {
64
  return $this->_wpversion < 3.8
65
  ? $this->_plugin->GetBaseUrl() . '/img/logo-main-menu.png'
66
  : 'dashicons-welcome-view-site';
67
  }
68
 
69
+ public function GetName()
70
+ {
71
  return __('Audit Log Viewer', 'wp-security-audit-log');
72
  }
73
 
74
+ public function GetWeight()
75
+ {
76
  return 1;
77
  }
78
 
79
+ protected function GetListView()
80
+ {
81
  if (is_null($this->_listview)) {
82
  $this->_listview = new WSAL_AuditLogListView($this->_plugin);
83
  }
84
  return $this->_listview;
85
  }
86
 
87
+ public function Render()
88
+ {
89
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
90
  wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
91
  }
121
  </script><?php
122
  }
123
 
124
+ public function AjaxInspector()
125
+ {
126
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
127
  die('Access Denied.');
128
  }
147
  die;
148
  }
149
 
150
+ public function AjaxRefresh()
151
+ {
152
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
153
  die('Access Denied.');
154
  }
160
  $max = 40; // 40*500msec = 20sec
161
 
162
  $is_archive = false;
163
+ if ($this->_plugin->settings->IsArchivingEnabled()) {
164
+ $selected_db = get_transient('wsal_wp_selected_db');
165
+ if ($selected_db && $selected_db == 'archive') {
166
+ $is_archive = true;
167
+ }
168
  }
169
 
170
  do {
181
  die;
182
  }
183
 
184
+ public function AjaxSetIpp()
185
+ {
186
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
187
  die('Access Denied.');
188
  }
193
  die;
194
  }
195
 
196
+ public function AjaxSearchSite()
197
+ {
198
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
199
  die('Access Denied.');
200
  }
216
  die(json_encode(array_slice($grp1 + $grp2, 0, 7)));
217
  }
218
 
219
+ public function AjaxSwitchDB()
220
+ {
221
  if (isset($_REQUEST['selected_db'])) {
222
+ set_transient('wsal_wp_selected_db', $_REQUEST['selected_db'], HOUR_IN_SECONDS);
 
223
  }
224
  }
225
 
226
+ public function Header()
227
+ {
228
  add_thickbox();
229
  wp_enqueue_style('darktooltip', $this->_plugin->GetBaseUrl() . '/css/darktooltip.css', array(), '');
230
  wp_enqueue_style(
235
  );
236
  }
237
 
238
+ public function Footer()
239
+ {
240
  wp_enqueue_script('jquery');
241
  wp_enqueue_script('darktooltip', $this->_plugin->GetBaseUrl() . '/js/jquery.darktooltip.js', array('jquery'), '');
242
  wp_enqueue_script('suggest');
classes/Views/EmailNotifications.php CHANGED
@@ -1,6 +1,12 @@
1
  <?php
2
-
3
- class WSAL_Views_EmailNotifications extends WSAL_AbstractView {
 
 
 
 
 
 
4
 
5
  public function GetTitle()
6
  {
@@ -22,7 +28,8 @@ class WSAL_Views_EmailNotifications extends WSAL_AbstractView {
22
  return 7;
23
  }
24
 
25
- public function Header() {
 
26
  wp_enqueue_style(
27
  'extensions',
28
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Email Notifications Add-On promo Page.
6
+ * Used only if the plugin is not activated.
7
+ */
8
+ class WSAL_Views_EmailNotifications extends WSAL_AbstractView
9
+ {
10
 
11
  public function GetTitle()
12
  {
28
  return 7;
29
  }
30
 
31
+ public function Header()
32
+ {
33
  wp_enqueue_style(
34
  'extensions',
35
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
classes/Views/Extensions.php CHANGED
@@ -1,26 +1,35 @@
1
  <?php
2
-
3
-
 
 
 
 
4
  class WSAL_Views_Extensions extends WSAL_AbstractView
5
  {
6
 
7
- public function GetTitle() {
 
8
  return __('WP Security Audit Log Add-Ons', 'wp-security-audit-log');
9
  }
10
 
11
- public function GetIcon() {
 
12
  return 'dashicons-external';
13
  }
14
 
15
- public function GetName() {
 
16
  return __(' Add Functionality', 'wp-security-audit-log');
17
  }
18
 
19
- public function GetWeight() {
 
20
  return 3.5;
21
  }
22
 
23
- public function Header() {
 
24
  wp_enqueue_style(
25
  'extensions',
26
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * All Add-Ons promo Page.
6
+ * Used only if no plugins are activated.
7
+ */
8
  class WSAL_Views_Extensions extends WSAL_AbstractView
9
  {
10
 
11
+ public function GetTitle()
12
+ {
13
  return __('WP Security Audit Log Add-Ons', 'wp-security-audit-log');
14
  }
15
 
16
+ public function GetIcon()
17
+ {
18
  return 'dashicons-external';
19
  }
20
 
21
+ public function GetName()
22
+ {
23
  return __(' Add Functionality', 'wp-security-audit-log');
24
  }
25
 
26
+ public function GetWeight()
27
+ {
28
  return 3.5;
29
  }
30
 
31
+ public function Header()
32
+ {
33
  wp_enqueue_style(
34
  'extensions',
35
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
classes/Views/ExternalDB.php CHANGED
@@ -1,6 +1,12 @@
1
  <?php
2
-
3
- class WSAL_Views_ExternalDB extends WSAL_AbstractView {
 
 
 
 
 
 
4
 
5
  public function GetTitle()
6
  {
@@ -22,7 +28,8 @@ class WSAL_Views_ExternalDB extends WSAL_AbstractView {
22
  return 10;
23
  }
24
 
25
- public function Header() {
 
26
  wp_enqueue_style(
27
  'extensions',
28
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * External DB Add-On promo Page.
6
+ * Used only if the plugin is not activated.
7
+ */
8
+ class WSAL_Views_ExternalDB extends WSAL_AbstractView
9
+ {
10
 
11
  public function GetTitle()
12
  {
28
  return 10;
29
  }
30
 
31
+ public function Header()
32
+ {
33
  wp_enqueue_style(
34
  'extensions',
35
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
classes/Views/Help.php CHANGED
@@ -1,24 +1,35 @@
1
  <?php
2
-
3
- class WSAL_Views_Help extends WSAL_AbstractView {
4
-
5
- public function GetTitle() {
 
 
 
 
 
 
 
6
  return __('Help', 'wp-security-audit-log');
7
  }
8
 
9
- public function GetIcon() {
 
10
  return 'dashicons-sos';
11
  }
12
 
13
- public function GetName() {
 
14
  return __('Help', 'wp-security-audit-log');
15
  }
16
 
17
- public function GetWeight() {
 
18
  return 5;
19
  }
20
 
21
- public function Render(){
 
22
  ?><div class="metabox-holder" style="position: relative;">
23
 
24
  <div class="postbox" style="margin-right: 270px;">
@@ -75,5 +86,4 @@ class WSAL_Views_Help extends WSAL_AbstractView {
75
 
76
  </div><?php
77
  }
78
-
79
- }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Help Page.
6
+ * - Plugin support
7
+ * - Plugin Documentation
8
+ */
9
+ class WSAL_Views_Help extends WSAL_AbstractView
10
+ {
11
+ public function GetTitle()
12
+ {
13
  return __('Help', 'wp-security-audit-log');
14
  }
15
 
16
+ public function GetIcon()
17
+ {
18
  return 'dashicons-sos';
19
  }
20
 
21
+ public function GetName()
22
+ {
23
  return __('Help', 'wp-security-audit-log');
24
  }
25
 
26
+ public function GetWeight()
27
+ {
28
  return 5;
29
  }
30
 
31
+ public function Render()
32
+ {
33
  ?><div class="metabox-holder" style="position: relative;">
34
 
35
  <div class="postbox" style="margin-right: 270px;">
86
 
87
  </div><?php
88
  }
89
+ }
 
classes/Views/Licensing.php CHANGED
@@ -1,88 +1,100 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- class WSAL_Views_Licensing extends WSAL_AbstractView {
4
-
5
- public function GetTitle() {
6
- return __('Licensing', 'wp-security-audit-log');
7
- }
8
-
9
- public function GetIcon() {
10
- return 'dashicons-cart';
11
- }
12
-
13
- public function GetName() {
14
- return __('Licensing', 'wp-security-audit-log');
15
- }
16
-
17
- public function GetWeight() {
18
- return 4;
19
- }
20
-
21
- public function IsAccessible(){
22
- return !!$this->_plugin->licensing->CountPlugins();
23
- }
24
-
25
- protected function Save(){
26
- $this->_plugin->settings->ClearLicenses();
27
- if (isset($_REQUEST['license']))
28
- foreach ($_REQUEST['license'] as $name => $key)
29
- $this->_plugin->licensing->ActivateLicense($name, $key);
30
- }
31
-
32
- public function Render(){
33
- if(!$this->_plugin->settings->CurrentUserCan('edit')){
34
- wp_die( __( 'You do not have sufficient permissions to access this page.' , 'wp-security-audit-log') );
35
- }
36
- if(isset($_POST['submit'])){
37
- try {
38
- $this->Save();
39
- ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
40
- }catch(Exception $ex){
41
- ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
42
- }
43
- }
44
- ?><form id="audit-log-licensing" method="post">
45
- <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
46
-
47
- <table class="wp-list-table widefat fixed">
48
- <thead>
49
- <tr><th>Plugin</th><th>License</th><th></th></tr>
50
- </thead><tbody>
51
- <?php $counter = 0; ?>
52
- <?php foreach($this->_plugin->licensing->Plugins() as $name => $plugin){ ?>
53
- <?php $licenseKey = trim($this->_plugin->settings->GetLicenseKey($name)); ?>
54
- <?php $licenseStatus = trim($this->_plugin->settings->GetLicenseStatus($name)); ?>
55
- <?php $licenseErrors = trim($this->_plugin->settings->GetLicenseErrors($name)); ?>
56
- <tr class="<?php echo ($counter++ % 2 === 0) ? 'alternate' : ''; ?>">
57
- <td>
58
- <a href="<?php echo esc_attr($plugin['PluginData']['PluginURI']); ?>" target="_blank">
59
- <?php echo esc_html($plugin['PluginData']['Name']); ?>
60
- </a><br/><small><b>
61
- <?php _e('Version', 'wp-security-audit-log'); ?>
62
- <?php echo esc_html($plugin['PluginData']['Version']); ?>
63
- </b></small>
64
- </td><td>
65
- <input type="text" style="width: 360px; margin: 6px 0;"
66
- name="license[<?php echo esc_attr($name); ?>]"
67
- value="<?php echo esc_attr($licenseKey); ?>"/>
68
- </td><td style="vertical-align: middle;">
69
- <?php if($licenseKey){ ?>
70
- <?php if($licenseStatus === 'valid'){ ?>
71
- <?php _e('Active', 'wp-security-audit-log'); ?>
72
- <?php }else{ ?>
73
- <?php _e('Inactive', 'wp-security-audit-log'); ?><br/>
74
- <small><?php echo esc_html($licenseErrors); ?></small>
75
- <?php } ?>
76
- <?php } ?>
77
- </td>
78
- </tr>
79
- <?php } ?>
80
- </tbody><tfoot>
81
- <tr><th>Plugin</th><th>License</th><th></th></tr>
82
- </tfoot>
83
- </table>
84
- <?php submit_button(); ?>
85
- </form><?php
86
- }
87
-
88
- }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Licensing Page for all the Add-Ons enabled.
6
+ */
7
+ class WSAL_Views_Licensing extends WSAL_AbstractView
8
+ {
9
+ public function GetTitle()
10
+ {
11
+ return __('Licensing', 'wp-security-audit-log');
12
+ }
13
+
14
+ public function GetIcon()
15
+ {
16
+ return 'dashicons-cart';
17
+ }
18
+
19
+ public function GetName()
20
+ {
21
+ return __('Licensing', 'wp-security-audit-log');
22
+ }
23
+
24
+ public function GetWeight()
25
+ {
26
+ return 4;
27
+ }
28
+
29
+ public function IsAccessible()
30
+ {
31
+ return !!$this->_plugin->licensing->CountPlugins();
32
+ }
33
 
34
+ protected function Save()
35
+ {
36
+ $this->_plugin->settings->ClearLicenses();
37
+ if (isset($_REQUEST['license'])) {
38
+ foreach ($_REQUEST['license'] as $name => $key) {
39
+ $this->_plugin->licensing->ActivateLicense($name, $key);
40
+ }
41
+ }
42
+ }
43
+
44
+ public function Render()
45
+ {
46
+ if (!$this->_plugin->settings->CurrentUserCan('edit')) {
47
+ wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
48
+ }
49
+ if (isset($_POST['submit'])) {
50
+ try {
51
+ $this->Save();
52
+ ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
53
+ } catch (Exception $ex) {
54
+ ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
55
+ }
56
+ }
57
+ ?><form id="audit-log-licensing" method="post">
58
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
59
+
60
+ <table class="wp-list-table widefat fixed">
61
+ <thead>
62
+ <tr><th>Plugin</th><th>License</th><th></th></tr>
63
+ </thead><tbody>
64
+ <?php $counter = 0; ?>
65
+ <?php foreach ($this->_plugin->licensing->Plugins() as $name => $plugin) { ?>
66
+ <?php $licenseKey = trim($this->_plugin->settings->GetLicenseKey($name)); ?>
67
+ <?php $licenseStatus = trim($this->_plugin->settings->GetLicenseStatus($name)); ?>
68
+ <?php $licenseErrors = trim($this->_plugin->settings->GetLicenseErrors($name)); ?>
69
+ <tr class="<?php echo ($counter++ % 2 === 0) ? 'alternate' : ''; ?>">
70
+ <td>
71
+ <a href="<?php echo esc_attr($plugin['PluginData']['PluginURI']); ?>" target="_blank">
72
+ <?php echo esc_html($plugin['PluginData']['Name']); ?>
73
+ </a><br/><small><b>
74
+ <?php _e('Version', 'wp-security-audit-log'); ?>
75
+ <?php echo esc_html($plugin['PluginData']['Version']); ?>
76
+ </b></small>
77
+ </td><td>
78
+ <input type="text" style="width: 360px; margin: 6px 0;"
79
+ name="license[<?php echo esc_attr($name); ?>]"
80
+ value="<?php echo esc_attr($licenseKey); ?>"/>
81
+ </td><td style="vertical-align: middle;">
82
+ <?php if ($licenseKey) { ?>
83
+ <?php if ($licenseStatus === 'valid') { ?>
84
+ <?php _e('Active', 'wp-security-audit-log'); ?>
85
+ <?php } else { ?>
86
+ <?php _e('Inactive', 'wp-security-audit-log'); ?><br/>
87
+ <small><?php echo esc_html($licenseErrors); ?></small>
88
+ <?php } ?>
89
+ <?php } ?>
90
+ </td>
91
+ </tr>
92
+ <?php } ?>
93
+ </tbody><tfoot>
94
+ <tr><th>Plugin</th><th>License</th><th></th></tr>
95
+ </tfoot>
96
+ </table>
97
+ <?php submit_button(); ?>
98
+ </form><?php
99
+ }
100
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/Views/LogInUsers.php CHANGED
@@ -1,7 +1,12 @@
1
  <?php
2
-
3
- class WSAL_Views_LogInUsers extends WSAL_AbstractView {
4
-
 
 
 
 
 
5
  public function GetTitle()
6
  {
7
  return __('User Sessions Management Add-On', 'wp-security-audit-log');
@@ -22,7 +27,8 @@ class WSAL_Views_LogInUsers extends WSAL_AbstractView {
22
  return 8;
23
  }
24
 
25
- public function Header() {
 
26
  wp_enqueue_style(
27
  'extensions',
28
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * User Sessions Management Add-On promo Page.
6
+ * Used only if the plugin is not activated.
7
+ */
8
+ class WSAL_Views_LogInUsers extends WSAL_AbstractView
9
+ {
10
  public function GetTitle()
11
  {
12
  return __('User Sessions Management Add-On', 'wp-security-audit-log');
27
  return 8;
28
  }
29
 
30
+ public function Header()
31
+ {
32
  wp_enqueue_style(
33
  'extensions',
34
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
classes/Views/Reports.php CHANGED
@@ -1,7 +1,12 @@
1
  <?php
2
-
3
- class WSAL_Views_Reports extends WSAL_AbstractView {
4
-
 
 
 
 
 
5
  public function GetTitle()
6
  {
7
  return __('Reports Add-On', 'wp-security-audit-log');
@@ -22,7 +27,8 @@ class WSAL_Views_Reports extends WSAL_AbstractView {
22
  return 9;
23
  }
24
 
25
- public function Header() {
 
26
  wp_enqueue_style(
27
  'extensions',
28
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Reports Add-On promo Page.
6
+ * Used only if the plugin is not activated.
7
+ */
8
+ class WSAL_Views_Reports extends WSAL_AbstractView
9
+ {
10
  public function GetTitle()
11
  {
12
  return __('Reports Add-On', 'wp-security-audit-log');
27
  return 9;
28
  }
29
 
30
+ public function Header()
31
+ {
32
  wp_enqueue_style(
33
  'extensions',
34
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
classes/Views/Search.php CHANGED
@@ -1,7 +1,12 @@
1
  <?php
2
-
3
- class WSAL_Views_Search extends WSAL_AbstractView {
4
-
 
 
 
 
 
5
  public function GetTitle()
6
  {
7
  return __('Search Add-On', 'wp-security-audit-log');
@@ -22,7 +27,8 @@ class WSAL_Views_Search extends WSAL_AbstractView {
22
  return 9;
23
  }
24
 
25
- public function Header() {
 
26
  wp_enqueue_style(
27
  'extensions',
28
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Search Add-On promo Page.
6
+ * Used only if the plugin is not activated.
7
+ */
8
+ class WSAL_Views_Search extends WSAL_AbstractView
9
+ {
10
  public function GetTitle()
11
  {
12
  return __('Search Add-On', 'wp-security-audit-log');
27
  return 9;
28
  }
29
 
30
+ public function Header()
31
+ {
32
  wp_enqueue_style(
33
  'extensions',
34
  $this->_plugin->GetBaseUrl() . '/css/extensions.css',
classes/Views/Settings.php CHANGED
@@ -1,9 +1,13 @@
1
  <?php
 
 
 
 
 
2
  class WSAL_Views_Settings extends WSAL_AbstractView
3
  {
4
-
5
  public $adapterMsg = '';
6
-
7
  public function __construct(WpSecurityAuditLog $plugin)
8
  {
9
  parent::__construct($plugin);
@@ -13,38 +17,49 @@ class WSAL_Views_Settings extends WSAL_AbstractView
13
  add_action('wp_ajax_AjaxGetAllUsers', array($this, 'AjaxGetAllUsers'));
14
  add_action('wp_ajax_AjaxGetAllRoles', array($this, 'AjaxGetAllRoles'));
15
  }
16
-
17
- public function HasPluginShortcutLink(){
 
18
  return true;
19
  }
20
-
21
- public function GetTitle() {
 
22
  return __('Settings', 'wp-security-audit-log');
23
  }
24
-
25
- public function GetIcon() {
 
26
  return 'dashicons-admin-generic';
27
  }
28
-
29
- public function GetName() {
 
30
  return __('Settings', 'wp-security-audit-log');
31
  }
32
-
33
- public function GetWeight() {
 
34
  return 3;
35
  }
36
-
37
- protected function GetTokenType($token){
 
38
  $users = array();
39
- foreach (get_users('blog_id=0&fields[]=user_login') as $obj)
40
  $users[] = $obj->user_login;
 
41
  $roles = array_keys(get_editable_roles());
42
-
43
- if(in_array($token, $users))return 'user';
44
- if(in_array($token, $roles))return 'role';
 
 
 
 
45
  return 'other';
46
  }
47
-
48
  protected function Save()
49
  {
50
  check_admin_referer('wsal-settings');
@@ -84,27 +99,29 @@ class WSAL_Views_Settings extends WSAL_AbstractView
84
  $this->_plugin->settings->SetDevOptionEnabled($opt, true);
85
  }
86
  }
87
- $this->_plugin->settings->Set404LogLimit($_REQUEST['404Limit']);
88
  }
89
-
90
  public function AjaxCheckSecurityToken()
91
  {
92
- if (!$this->_plugin->settings->CurrentUserCan('view'))
93
  die('Access Denied.');
94
- if (!isset($_REQUEST['token']))
 
95
  die('Token parameter expected.');
 
96
  die($this->GetTokenType($_REQUEST['token']));
97
  }
98
-
99
  public function AjaxRunCleanup()
100
  {
101
- if (!$this->_plugin->settings->CurrentUserCan('view'))
102
  die('Access Denied.');
 
103
  $this->_plugin->CleanUp();
104
  wp_redirect($this->GetUrl());
105
  exit;
106
  }
107
-
108
  public function Render()
109
  {
110
  if (!$this->_plugin->settings->CurrentUserCan('edit')) {
@@ -131,7 +148,7 @@ class WSAL_Views_Settings extends WSAL_AbstractView
131
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
132
  <input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
133
  <?php wp_nonce_field('wsal-settings'); ?>
134
-
135
  <div id="audit-log-adverts">
136
  </div>
137
  <div class="nav-tabs">
@@ -203,7 +220,7 @@ class WSAL_Views_Settings extends WSAL_AbstractView
203
  ?>/> <?php _e('Filter Internal IP Addresses', 'wp-security-audit-log'); ?>
204
  </label>
205
  <br/>
206
- <span class="description"><?php _e('Enable this option to filter internal IP addresses from the proxy headers.', 'wp-security-audit-log'); ?></span>
207
  </fieldset>
208
  </td>
209
  </tr>
@@ -512,19 +529,6 @@ class WSAL_Views_Settings extends WSAL_AbstractView
512
  </fieldset>
513
  </td>
514
  </tr>
515
- <!-- Number of 404 Requests to Log -->
516
- <tr>
517
- <th><label for="404Limit"><?php _e('Number of 404 Requests to Log', 'wp-security-audit-log'); ?></label></th>
518
- <td>
519
- <fieldset>
520
- <input type="number" id="404Limit" name="404Limit" value="<?php echo $this->_plugin->settings->Get404LogLimit(); ?>" />
521
- </fieldset>
522
- <p class="description">
523
- <?php _e('By default the plugin keeps up to 99 requests to non-existing pages from the same IP address. Increase the value in this setting to the desired amount to keep a log of more or less requests.', 'wp-security-audit-log'); ?><br />
524
- <?php _e('Note that by increasing this value to a high number, should your website be scanned the plugin will consume more resources to log all the requests.', 'wp-security-audit-log'); ?>
525
- </p>
526
- </td>
527
- </tr>
528
  </tbody>
529
  </table>
530
  <!-- Third tab -->
@@ -642,11 +646,11 @@ class WSAL_Views_Settings extends WSAL_AbstractView
642
  {
643
  if ( window.confirm('Do you want remove all data when the plugin is deleted?') == false )
644
  elementRef.checked = false;
645
- }
646
  }
647
 
648
  jQuery(document).ready(function() {
649
- var statusConfig = <?php if ($this->_plugin->settings->IsLoggingDisabled()) { echo 1; } else { echo 0; } ?>;
650
  var logging_status = jQuery('#logging_status');
651
  var txtNot = jQuery('#logging_status_text');
652
 
@@ -663,14 +667,14 @@ class WSAL_Views_Settings extends WSAL_AbstractView
663
  }
664
  wsalUpdateLoggingStatus(logging_status, txtNot);
665
 
666
- logging_status.on('change', function() {
667
- wsalUpdateLoggingStatus(logging_status, txtNot);
668
  });
669
  });
670
  // -->
671
  </script><?php
672
  }
673
-
674
  public function Header()
675
  {
676
  wp_enqueue_style(
@@ -691,7 +695,7 @@ class WSAL_Views_Settings extends WSAL_AbstractView
691
  }
692
  </style><?php
693
  }
694
-
695
  public function Footer()
696
  {
697
  wp_enqueue_script(
@@ -722,13 +726,13 @@ class WSAL_Views_Settings extends WSAL_AbstractView
722
  if(this.checked) notChecked = 0;
723
  })
724
  if(notChecked == 1){
725
- alert("You have to select at least one column!");
726
  }
727
  });
728
  });
729
  </script><?php
730
  }
731
-
732
  public function AjaxGetAllUsers()
733
  {
734
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Settings Page.
6
+ */
7
  class WSAL_Views_Settings extends WSAL_AbstractView
8
  {
 
9
  public $adapterMsg = '';
10
+
11
  public function __construct(WpSecurityAuditLog $plugin)
12
  {
13
  parent::__construct($plugin);
17
  add_action('wp_ajax_AjaxGetAllUsers', array($this, 'AjaxGetAllUsers'));
18
  add_action('wp_ajax_AjaxGetAllRoles', array($this, 'AjaxGetAllRoles'));
19
  }
20
+
21
+ public function HasPluginShortcutLink()
22
+ {
23
  return true;
24
  }
25
+
26
+ public function GetTitle()
27
+ {
28
  return __('Settings', 'wp-security-audit-log');
29
  }
30
+
31
+ public function GetIcon()
32
+ {
33
  return 'dashicons-admin-generic';
34
  }
35
+
36
+ public function GetName()
37
+ {
38
  return __('Settings', 'wp-security-audit-log');
39
  }
40
+
41
+ public function GetWeight()
42
+ {
43
  return 3;
44
  }
45
+
46
+ protected function GetTokenType($token)
47
+ {
48
  $users = array();
49
+ foreach (get_users('blog_id=0&fields[]=user_login') as $obj) {
50
  $users[] = $obj->user_login;
51
+ }
52
  $roles = array_keys(get_editable_roles());
53
+
54
+ if (in_array($token, $users)) {
55
+ return 'user';
56
+ }
57
+ if (in_array($token, $roles)) {
58
+ return 'role';
59
+ }
60
  return 'other';
61
  }
62
+
63
  protected function Save()
64
  {
65
  check_admin_referer('wsal-settings');
99
  $this->_plugin->settings->SetDevOptionEnabled($opt, true);
100
  }
101
  }
 
102
  }
103
+
104
  public function AjaxCheckSecurityToken()
105
  {
106
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
107
  die('Access Denied.');
108
+ }
109
+ if (!isset($_REQUEST['token'])) {
110
  die('Token parameter expected.');
111
+ }
112
  die($this->GetTokenType($_REQUEST['token']));
113
  }
114
+
115
  public function AjaxRunCleanup()
116
  {
117
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
118
  die('Access Denied.');
119
+ }
120
  $this->_plugin->CleanUp();
121
  wp_redirect($this->GetUrl());
122
  exit;
123
  }
124
+
125
  public function Render()
126
  {
127
  if (!$this->_plugin->settings->CurrentUserCan('edit')) {
148
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
149
  <input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
150
  <?php wp_nonce_field('wsal-settings'); ?>
151
+
152
  <div id="audit-log-adverts">
153
  </div>
154
  <div class="nav-tabs">
220
  ?>/> <?php _e('Filter Internal IP Addresses', 'wp-security-audit-log'); ?>
221
  </label>
222
  <br/>
223
+ <span class="description"><?php _e('Enable this option to filter internal IP addresses from the proxy headers.', 'wp-security-audit-log'); ?></span>
224
  </fieldset>
225
  </td>
226
  </tr>
529
  </fieldset>
530
  </td>
531
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
532
  </tbody>
533
  </table>
534
  <!-- Third tab -->
646
  {
647
  if ( window.confirm('Do you want remove all data when the plugin is deleted?') == false )
648
  elementRef.checked = false;
649
+ }
650
  }
651
 
652
  jQuery(document).ready(function() {
653
+ var statusConfig = <?php if ($this->_plugin->settings->IsLoggingDisabled()) { echo 1; } else { echo 0; } ?>;
654
  var logging_status = jQuery('#logging_status');
655
  var txtNot = jQuery('#logging_status_text');
656
 
667
  }
668
  wsalUpdateLoggingStatus(logging_status, txtNot);
669
 
670
+ logging_status.on('change', function() {
671
+ wsalUpdateLoggingStatus(logging_status, txtNot);
672
  });
673
  });
674
  // -->
675
  </script><?php
676
  }
677
+
678
  public function Header()
679
  {
680
  wp_enqueue_style(
695
  }
696
  </style><?php
697
  }
698
+
699
  public function Footer()
700
  {
701
  wp_enqueue_script(
726
  if(this.checked) notChecked = 0;
727
  })
728
  if(notChecked == 1){
729
+ alert("You have to select at least one column!");
730
  }
731
  });
732
  });
733
  </script><?php
734
  }
735
+
736
  public function AjaxGetAllUsers()
737
  {
738
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
classes/Views/ToggleAlerts.php CHANGED
@@ -1,29 +1,38 @@
1
  <?php
2
- class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
 
 
 
 
 
3
  {
4
-
5
- public function GetTitle() {
6
  return __('Enable/Disable Alerts', 'wp-security-audit-log');
7
  }
8
-
9
- public function GetIcon() {
 
10
  return 'dashicons-forms';
11
  }
12
-
13
- public function GetName() {
 
14
  return __('Enable/Disable Alerts', 'wp-security-audit-log');
15
  }
16
-
17
- public function GetWeight() {
 
18
  return 2;
19
  }
20
-
21
- protected function GetSafeCatgName($name) {
 
22
  return strtolower(
23
  preg_replace('/[^A-Za-z0-9\-]/', '-', $name)
24
  );
25
  }
26
-
27
  public function Render()
28
  {
29
  if (!$this->_plugin->settings->CurrentUserCan('edit')) {
@@ -38,9 +47,11 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
38
  try {
39
  $enabled = array_map('intval', $_POST['alert']);
40
  $disabled = array();
41
- foreach ($this->_plugin->alerts->GetAlerts() as $alert)
42
- if (!in_array($alert->type, $enabled))
43
  $disabled[] = $alert->type;
 
 
44
  $this->_plugin->alerts->SetDisabledAlerts($disabled);
45
  ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
46
  } catch (Exception $ex) {
@@ -48,6 +59,12 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
48
  }
49
  $this->_plugin->SetGlobalOption('log-404', isset($_REQUEST['log_404']) ? 'on' : 'off');
50
  $this->_plugin->SetGlobalOption('purge-404-log', isset($_REQUEST['purge_log']) ? 'on' : 'off');
 
 
 
 
 
 
51
  }
52
  ?><h2 id="wsal-tabs" class="nav-tab-wrapper"><?php
53
  foreach ($safeNames as $name => $safe) {
@@ -57,7 +74,7 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
57
  <form id="audit-log-viewer" method="post">
58
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
59
  <?php wp_nonce_field('wsal-togglealerts'); ?>
60
-
61
  <div class="nav-tabs"><?php
62
  foreach ($groupedAlerts as $name => $group) { ?>
63
  <div class="wsal-tab" id="tab-<?php echo $safeNames[$name]; ?>">
@@ -74,10 +91,16 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
74
  $active = array();
75
  $allactive = true;
76
  foreach ($alerts as $alert) {
77
- if ($alert->type <= 0006) continue; // <- ignore php alerts
78
- if ($alert->type == 9999) continue; // <- ignore promo alerts
 
 
 
 
79
  $active[$alert->type] = $this->_plugin->alerts->IsEnabled($alert->type);
80
- if (!$active[$alert->type]) $allactive = false;
 
 
81
  }
82
  ?><table class="wp-list-table wsal-tab widefat fixed wsal-sub-tab" cellspacing="0" id="tab-<?php echo $this->GetSafeCatgName($subname); ?>">
83
  <thead>
@@ -90,8 +113,12 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
90
  </thead>
91
  <tbody><?php
92
  foreach ($alerts as $alert) {
93
- if ($alert->type <= 0006) continue; // <- ignore php alerts
94
- if ($alert->type == 9999) continue; // <- ignore promo alerts
 
 
 
 
95
  $attrs = '';
96
  switch (true) {
97
  case !$alert->mesg:
@@ -119,10 +146,51 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
119
  <td></td>
120
  <td><input name="purge_log" type="checkbox" class="check_log" value="1" <?php if ($purge_log == 'on') echo 'checked="checked"'; ?>></td>
121
  <td colspan="2"><?php _e('Purge log files older than one month', 'wp-security-audit-log'); ?></td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  </tr><?php
123
  }
124
  }
125
- ?></tbody>
 
126
  </table><?php
127
  }
128
  ?>
@@ -132,7 +200,7 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
132
  <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php echo esc_attr(__('Save Changes', 'wp-security-audit-log')); ?>"></p>
133
  </form><?php
134
  }
135
-
136
  public function Header()
137
  {
138
  ?><style type="text/css">
@@ -152,9 +220,13 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
152
  background-color: #fff;
153
  border-bottom: 1px solid #fff;
154
  }
 
 
 
 
155
  </style><?php
156
  }
157
-
158
  public function Footer()
159
  {
160
  ?><script type="text/javascript">
@@ -187,7 +259,7 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
187
  var allchecked = jQuery(this).parents('tbody:first').find('th>:checkbox:not(:checked)').length === 0;
188
  jQuery(this).parents('table:first').find('thead>tr>th:first>:checkbox:first').attr('checked', allchecked);
189
  });
190
-
191
  var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
192
  var hashsublink = jQuery('.wsal-sub-tabs>a[href="' + location.hash + '"]');
193
  if (hashlink.length) {
@@ -201,7 +273,7 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
201
  jQuery('#wsal-tabs>a:first').click();
202
  jQuery('.wsal-sub-tabs>a:first').click();
203
  }
204
-
205
  // Specific for alert 6007
206
  jQuery("input[value=6007]").on("change", function(){
207
  var check = jQuery("input[value=6007]").is(":checked");
@@ -210,7 +282,17 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
210
  } else {
211
  jQuery(".check_log").removeAttr('checked');
212
  }
213
- });
 
 
 
 
 
 
 
 
 
 
214
  });
215
  </script><?php
216
  }
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Enable/Disable Alerts Page.
6
+ */
7
+ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
8
  {
9
+ public function GetTitle()
10
+ {
11
  return __('Enable/Disable Alerts', 'wp-security-audit-log');
12
  }
13
+
14
+ public function GetIcon()
15
+ {
16
  return 'dashicons-forms';
17
  }
18
+
19
+ public function GetName()
20
+ {
21
  return __('Enable/Disable Alerts', 'wp-security-audit-log');
22
  }
23
+
24
+ public function GetWeight()
25
+ {
26
  return 2;
27
  }
28
+
29
+ protected function GetSafeCatgName($name)
30
+ {
31
  return strtolower(
32
  preg_replace('/[^A-Za-z0-9\-]/', '-', $name)
33
  );
34
  }
35
+
36
  public function Render()
37
  {
38
  if (!$this->_plugin->settings->CurrentUserCan('edit')) {
47
  try {
48
  $enabled = array_map('intval', $_POST['alert']);
49
  $disabled = array();
50
+ foreach ($this->_plugin->alerts->GetAlerts() as $alert) {
51
+ if (!in_array($alert->type, $enabled)) {
52
  $disabled[] = $alert->type;
53
+ }
54
+ }
55
  $this->_plugin->alerts->SetDisabledAlerts($disabled);
56
  ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
57
  } catch (Exception $ex) {
59
  }
60
  $this->_plugin->SetGlobalOption('log-404', isset($_REQUEST['log_404']) ? 'on' : 'off');
61
  $this->_plugin->SetGlobalOption('purge-404-log', isset($_REQUEST['purge_log']) ? 'on' : 'off');
62
+
63
+ $this->_plugin->SetGlobalOption( 'log-visitor-404', isset( $_REQUEST['log_visitor_404'] ) ? 'on' : 'off' );
64
+ $this->_plugin->SetGlobalOption( 'purge-visitor-404-log', isset( $_REQUEST['purge_visitor_log'] ) ? 'on' : 'off' );
65
+
66
+ $this->_plugin->settings->Set404LogLimit( $_REQUEST['user_404Limit'] );
67
+ $this->_plugin->settings->SetVisitor404LogLimit( $_REQUEST['visitor_404Limit'] );
68
  }
69
  ?><h2 id="wsal-tabs" class="nav-tab-wrapper"><?php
70
  foreach ($safeNames as $name => $safe) {
74
  <form id="audit-log-viewer" method="post">
75
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
76
  <?php wp_nonce_field('wsal-togglealerts'); ?>
77
+
78
  <div class="nav-tabs"><?php
79
  foreach ($groupedAlerts as $name => $group) { ?>
80
  <div class="wsal-tab" id="tab-<?php echo $safeNames[$name]; ?>">
91
  $active = array();
92
  $allactive = true;
93
  foreach ($alerts as $alert) {
94
+ if ($alert->type <= 0006) {
95
+ continue; // <- ignore php alerts
96
+ }
97
+ if ($alert->type == 9999) {
98
+ continue; // <- ignore promo alerts
99
+ }
100
  $active[$alert->type] = $this->_plugin->alerts->IsEnabled($alert->type);
101
+ if (!$active[$alert->type]) {
102
+ $allactive = false;
103
+ }
104
  }
105
  ?><table class="wp-list-table wsal-tab widefat fixed wsal-sub-tab" cellspacing="0" id="tab-<?php echo $this->GetSafeCatgName($subname); ?>">
106
  <thead>
113
  </thead>
114
  <tbody><?php
115
  foreach ($alerts as $alert) {
116
+ if ($alert->type <= 0006) {
117
+ continue; // <- ignore php alerts
118
+ }
119
+ if ($alert->type == 9999) {
120
+ continue; // <- ignore promo alerts
121
+ }
122
  $attrs = '';
123
  switch (true) {
124
  case !$alert->mesg:
146
  <td></td>
147
  <td><input name="purge_log" type="checkbox" class="check_log" value="1" <?php if ($purge_log == 'on') echo 'checked="checked"'; ?>></td>
148
  <td colspan="2"><?php _e('Purge log files older than one month', 'wp-security-audit-log'); ?></td>
149
+ </tr>
150
+ <tr>
151
+ <td></td>
152
+ <td colspan="1"><input type="number" id="user_404Limit" name="user_404Limit" value="<?php echo $this->_plugin->settings->Get404LogLimit(); ?>" /></td>
153
+ <td colspan="2"><?php esc_html_e( 'Number of 404 Requests to Log', 'wp-security-audit-log' ); ?></td>
154
+ </tr>
155
+ <tr>
156
+ <td></td>
157
+ <td></td>
158
+ <td colspan="2">
159
+ <?php esc_html_e( 'By default the plugin keeps up to 99 requests to non-existing pages from the same IP address. Increase the value in this setting to the desired amount to keep a log of more or less requests.', 'wp-security-audit-log' ); ?><br />
160
+ <?php esc_html_e( 'Note that by increasing this value to a high number, should your website be scanned the plugin will consume more resources to log all the requests.', 'wp-security-audit-log' ); ?>
161
+ </td>
162
+ </tr><?php
163
+ }
164
+ if ( 6023 == $alert->type ) {
165
+ $log_visitor_404 = $this->_plugin->GetGlobalOption( 'log-visitor-404' );
166
+ $purge_visitor_log = $this->_plugin->GetGlobalOption( 'purge-visitor-404-log' );
167
+ ?><tr>
168
+ <td></td>
169
+ <td><input name="log_visitor_404" type="checkbox" class="check_visitor_log" value="1" <?php if ( 'on' == $log_visitor_404 ) echo 'checked="checked"'; ?>></td>
170
+ <td colspan="2"><?php esc_html_e( 'Capture 404 requests to file (the log file are created in the /wp-content/uploads/wp-security-audit-log/404s/ directory)', 'wp-security-audit-log' ); ?></td>
171
+ </tr>
172
+ <tr>
173
+ <td></td>
174
+ <td><input name="purge_visitor_log" type="checkbox" class="check_visitor_log" value="1" <?php if ( 'on' == $purge_visitor_log ) echo 'checked="checked"'; ?>></td>
175
+ <td colspan="2"><?php esc_html_e( 'Purge log files older than one month', 'wp-security-audit-log' ); ?></td>
176
+ </tr>
177
+ <tr>
178
+ <td></td>
179
+ <td colspan="1"><input type="number" id="visitor_404Limit" name="visitor_404Limit" value="<?php echo esc_attr( $this->_plugin->settings->GetVisitor404LogLimit() ); ?>" /></td>
180
+ <td colspan="2"><?php esc_html_e( 'Number of 404 Requests to Log', 'wp-security-audit-log' ); ?></td>
181
+ </tr>
182
+ <tr>
183
+ <td></td>
184
+ <td></td>
185
+ <td colspan="2">
186
+ <?php esc_html_e( 'By default the plugin keeps up to 99 requests to non-existing pages from the same IP address. Increase the value in this setting to the desired amount to keep a log of more or less requests.', 'wp-security-audit-log' ); ?><br />
187
+ <?php esc_html_e( 'Note that by increasing this value to a high number, should your website be scanned the plugin will consume more resources to log all the requests.', 'wp-security-audit-log' ); ?>
188
+ </td>
189
  </tr><?php
190
  }
191
  }
192
+ ?>
193
+ </tbody>
194
  </table><?php
195
  }
196
  ?>
200
  <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php echo esc_attr(__('Save Changes', 'wp-security-audit-log')); ?>"></p>
201
  </form><?php
202
  }
203
+
204
  public function Header()
205
  {
206
  ?><style type="text/css">
220
  background-color: #fff;
221
  border-bottom: 1px solid #fff;
222
  }
223
+ #user_404Limit,
224
+ #visitor_404Limit {
225
+ width: 100%;
226
+ }
227
  </style><?php
228
  }
229
+
230
  public function Footer()
231
  {
232
  ?><script type="text/javascript">
259
  var allchecked = jQuery(this).parents('tbody:first').find('th>:checkbox:not(:checked)').length === 0;
260
  jQuery(this).parents('table:first').find('thead>tr>th:first>:checkbox:first').attr('checked', allchecked);
261
  });
262
+
263
  var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
264
  var hashsublink = jQuery('.wsal-sub-tabs>a[href="' + location.hash + '"]');
265
  if (hashlink.length) {
273
  jQuery('#wsal-tabs>a:first').click();
274
  jQuery('.wsal-sub-tabs>a:first').click();
275
  }
276
+
277
  // Specific for alert 6007
278
  jQuery("input[value=6007]").on("change", function(){
279
  var check = jQuery("input[value=6007]").is(":checked");
282
  } else {
283
  jQuery(".check_log").removeAttr('checked');
284
  }
285
+ });
286
+
287
+ // Specific for alert 6023
288
+ jQuery("input[value=6023]").on("change", function(){
289
+ var check = jQuery("input[value=6023]").is(":checked");
290
+ if(check) {
291
+ jQuery(".check_visitor_log").attr ( "checked" ,"checked" );
292
+ } else {
293
+ jQuery(".check_visitor_log").removeAttr('checked');
294
+ }
295
+ });
296
  });
297
  </script><?php
298
  }
classes/WidgetManager.php CHANGED
@@ -1,5 +1,9 @@
1
  <?php
2
-
 
 
 
 
3
  class WSAL_WidgetManager
4
  {
5
  /**
1
  <?php
2
+ /**
3
+ * @package Wsal
4
+ *
5
+ * Plugin Widget used in the Wordpress Dashboard.
6
+ */
7
  class WSAL_WidgetManager
8
  {
9
  /**
defaults.php CHANGED
@@ -223,6 +223,7 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
223
  array(6004, E_CRITICAL, __('WordPress was updated', 'wp-security-audit-log'), __('Updated WordPress from version %OldVersion% to %NewVersion%.', 'wp-security-audit-log')),
224
  array(6005, E_CRITICAL, __('User changes the WordPress Permalinks', 'wp-security-audit-log'), __('Changed the WordPress permalinks from %OldPattern% to %NewPattern%.', 'wp-security-audit-log')),
225
  array(6007, E_CRITICAL, __('User requests non-existing pages (404 Error Pages)', 'wp-security-audit-log'), __('Has requested a non existing page (404 Error Pages) %Attempts% %Msg%. %LinkFile%.', 'wp-security-audit-log')),
 
226
  array(9999, E_CRITICAL, __('Advertising Add-ons.', 'wp-security-audit-log'), __('%PromoName% %PromoMessage%', 'wp-security-audit-log'))
227
  ),
228
  __('Menus', 'wp-security-audit-log') => array(
@@ -266,6 +267,7 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
266
  array(1004, E_WARNING, __('Login blocked', 'wp-security-audit-log'), __('Blocked from logging in because the same WordPress user is logged in from %ClientIP%.', 'wp-security-audit-log')),
267
  array(1005, E_WARNING, __('User logged in with existing session(s)', 'wp-security-audit-log'), __('Successfully logged in. Another session from %IPAddress% for this user already exist.', 'wp-security-audit-log')),
268
  array(1006, E_CRITICAL, __('User logged out all other sessions with the same username', 'wp-security-audit-log'), __('Logged out all other sessions with the same username.', 'wp-security-audit-log')),
 
269
  array(2010, E_NOTICE, __('User uploaded file from Uploads directory', 'wp-security-audit-log'), __('Uploaded the file %FileName% in %FilePath%.', 'wp-security-audit-log')),
270
  array(2011, E_WARNING, __('User deleted file from Uploads directory', 'wp-security-audit-log'), __('Deleted the file %FileName% from %FilePath%.', 'wp-security-audit-log'))
271
  ),
223
  array(6004, E_CRITICAL, __('WordPress was updated', 'wp-security-audit-log'), __('Updated WordPress from version %OldVersion% to %NewVersion%.', 'wp-security-audit-log')),
224
  array(6005, E_CRITICAL, __('User changes the WordPress Permalinks', 'wp-security-audit-log'), __('Changed the WordPress permalinks from %OldPattern% to %NewPattern%.', 'wp-security-audit-log')),
225
  array(6007, E_CRITICAL, __('User requests non-existing pages (404 Error Pages)', 'wp-security-audit-log'), __('Has requested a non existing page (404 Error Pages) %Attempts% %Msg%. %LinkFile%.', 'wp-security-audit-log')),
226
+ array( 6023, E_CRITICAL, __( 'Website Visitor User requests non-existing pages (404 Error Pages)', 'wp-security-audit-log' ), __( 'Website Visitor Has requested a non existing page (404 Error Pages) %Attempts% %Msg%. %LinkFile%.', 'wp-security-audit-log' ) ),
227
  array(9999, E_CRITICAL, __('Advertising Add-ons.', 'wp-security-audit-log'), __('%PromoName% %PromoMessage%', 'wp-security-audit-log'))
228
  ),
229
  __('Menus', 'wp-security-audit-log') => array(
267
  array(1004, E_WARNING, __('Login blocked', 'wp-security-audit-log'), __('Blocked from logging in because the same WordPress user is logged in from %ClientIP%.', 'wp-security-audit-log')),
268
  array(1005, E_WARNING, __('User logged in with existing session(s)', 'wp-security-audit-log'), __('Successfully logged in. Another session from %IPAddress% for this user already exist.', 'wp-security-audit-log')),
269
  array(1006, E_CRITICAL, __('User logged out all other sessions with the same username', 'wp-security-audit-log'), __('Logged out all other sessions with the same username.', 'wp-security-audit-log')),
270
+ array( 1007, E_CRITICAL, __( 'User session destroyed and logged out.', 'wp-security-audit-log' ), __( 'Logged out session %TargetSessionID% which belonged to %TargetUserName%', 'wp-security-audit-log' ) ),
271
  array(2010, E_NOTICE, __('User uploaded file from Uploads directory', 'wp-security-audit-log'), __('Uploaded the file %FileName% in %FilePath%.', 'wp-security-audit-log')),
272
  array(2011, E_WARNING, __('User deleted file from Uploads directory', 'wp-security-audit-log'), __('Deleted the file %FileName% from %FilePath%.', 'wp-security-audit-log'))
273
  ),
readme.txt CHANGED
@@ -7,7 +7,7 @@ License URI: http://www.gnu.org/licenses/gpl.html
7
  Tags: wordpress security plugin, wordpress security audit log, audit log, wordpress log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, security audit trail, wordpress security alerts, wordpress monitor, wordpress security monitor, wordpress admin, wordpress admin monitoring, analytics, activity, admin, multisite, wordpress multisite, actions, dashboard, log, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report, wordpress audit trail
8
  Requires at least: 3.6
9
  Tested up to: 4.8
10
- Stable tag: 2.6.4
11
 
12
  Keep an audit trail of all changes and under the hood WordPress activity to ensure productivity and thwart possible WordPress hacker attacks.
13
 
@@ -118,6 +118,7 @@ WP Security Audit Log plugin also has a number of features that make WordPress a
118
  * [WPLift](http://wplift.com/audit-wordpress-security-logs) - Review by Ahmad Awais
119
  * [WP SmackDown](https://wpsmackdown.com/wp-plugins/wp-security-audit-log/)
120
  * [WPKube](http://www.wpkube.com/improve-wordpress-security-wp-security-audit-log/)
 
121
  * [ManageWP Plugins of the month](https://managewp.com/free-wordpress-plugins-june-2014)
122
  * [MyWPExpert](http://www.mywpexpert.com/wp-security-audit-log/)
123
  * [BlogVault](https://blogvault.net/wp-security-audit-log-plugin-review/)
@@ -186,6 +187,18 @@ Please refer to the [FAQs page](https://www.wpsecurityauditlog.com/documentation
186
 
187
  == Changelog ==
188
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  = 2.6.4 (2017-06-01) =
190
 
191
  * **New Features**
7
  Tags: wordpress security plugin, wordpress security audit log, audit log, wordpress log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, security audit trail, wordpress security alerts, wordpress monitor, wordpress security monitor, wordpress admin, wordpress admin monitoring, analytics, activity, admin, multisite, wordpress multisite, actions, dashboard, log, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report, wordpress audit trail
8
  Requires at least: 3.6
9
  Tested up to: 4.8
10
+ Stable tag: 2.6.5
11
 
12
  Keep an audit trail of all changes and under the hood WordPress activity to ensure productivity and thwart possible WordPress hacker attacks.
13
 
118
  * [WPLift](http://wplift.com/audit-wordpress-security-logs) - Review by Ahmad Awais
119
  * [WP SmackDown](https://wpsmackdown.com/wp-plugins/wp-security-audit-log/)
120
  * [WPKube](http://www.wpkube.com/improve-wordpress-security-wp-security-audit-log/)
121
+ * [Cloudways](https://www.cloudways.com/blog/monitor-wordpress-with-wp-security-audit-log-plugin/)
122
  * [ManageWP Plugins of the month](https://managewp.com/free-wordpress-plugins-june-2014)
123
  * [MyWPExpert](http://www.mywpexpert.com/wp-security-audit-log/)
124
  * [BlogVault](https://blogvault.net/wp-security-audit-log-plugin-review/)
187
 
188
  == Changelog ==
189
 
190
+ = 2.6.5 (2017-07-18) =
191
+
192
+ * **New Audit Trail Alerts**
193
+ * Alert 1007 for when an administrator terminate's a logged in session using the Users Sessions Management Add-On
194
+ * Alert 6023 to log 404 HTTP errors (requests to non-existing pages) by website visitors (non WordPress users)
195
+
196
+ * **Improvements**
197
+ * Seggregated the logging of 404 HTTP Errors by who generates them. Alert 6007 for logged in users, 6023 for anonymous website visitors.
198
+ * Improved the logging of Alert 4014 so it is not reported every time a user's profile page is reloaded with a refresh or when a change is applied.
199
+ * Removed the wsal_wp_session cookie, which was used to store the selected database when [archiving of audit trail alerts is enabled](https://www.wpsecurityauditlog.com/wordpress-user-monitoring-plugin-documentation/faq-archiving-wordpress-audit-trail/). Using LocalStorage instead.
200
+ * Replaced mcrypt (deprecated in PHP 7) with OpenSSL. Mcrypt still used temporarily to convert configured password. Will be removed completely in future updates. [Support Ticket](https://wordpress.org/support/topic/php-issues-9/)
201
+
202
  = 2.6.4 (2017-06-01) =
203
 
204
  * **New Features**
wp-security-audit-log.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: WP Security Audit Log
4
  Plugin URI: http://www.wpsecurityauditlog.com/
5
  Description: Identify WordPress security issues before they become a problem. Keep track of everything happening on your WordPress including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log generates a security alert for everything that happens on your WordPress blogs and websites. Use the Audit Log Viewer included in the plugin to see all the security alerts.
6
  Author: WP White Security
7
- Version: 2.6.4
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpsecurityauditlog.com/
10
  License: GPL2
@@ -26,58 +26,61 @@ License: GPL2
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
 
 
 
29
  class WpSecurityAuditLog {
30
-
31
  // <editor-fold desc="Properties & Constants">
32
-
33
  const PLG_CLS_PRFX = 'WSAL_';
34
-
35
  const MIN_PHP_VERSION = '5.3.0';
36
-
37
  const OPT_PRFX = 'wsal-';
38
-
39
  /**
40
  * Views supervisor.
41
  * @var WSAL_ViewManager
42
  */
43
  public $views;
44
-
45
  /**
46
  * Logger supervisor.
47
  * @var WSAL_AlertManager
48
  */
49
  public $alerts;
50
-
51
  /**
52
  * Sensors supervisor.
53
  * @var WSAL_SensorManager
54
  */
55
  public $sensors;
56
-
57
  /**
58
  * Settings manager.
59
  * @var WSAL_Settings
60
  */
61
  public $settings;
62
-
63
  /**
64
  * Class loading manager.
65
  * @var WSAL_Autoloader
66
  */
67
  public $autoloader;
68
-
69
  /**
70
  * Constants manager.
71
  * @var WSAL_ConstantManager
72
  */
73
  public $constants;
74
-
75
  /**
76
  * Licenses manager.
77
  * @var WSAL_LicenseManager
78
  */
79
  public $licensing;
80
-
81
  /**
82
  * Simple profiler.
83
  * @var WSAL_SimpleProfiler
@@ -89,34 +92,37 @@ class WpSecurityAuditLog {
89
  * @var WSAL_DB_Option
90
  */
91
  public $options;
92
-
93
  /**
94
  * Contains a list of cleanup callbacks.
95
  * @var callable[]
96
  */
97
  protected $_cleanup_hooks = array();
98
-
99
  // </editor-fold>
100
-
101
  // <editor-fold desc="Entry Points">
102
-
103
  /**
104
  * Standard singleton pattern.
105
  * WARNING! To ensure the system always works as expected, AVOID using this method.
106
  * Instead, make use of the plugin instance provided by 'wsal_init' action.
107
  * @return WpSecurityAuditLog Returns the current plugin instance.
108
  */
109
- public static function GetInstance(){
 
110
  static $instance = null;
111
- if(!$instance)$instance = new self();
 
 
112
  return $instance;
113
  }
114
-
115
  /**
116
  * Initialize plugin.
117
  */
118
- public function __construct(){
119
-
120
  require_once('classes/Helpers/DataHelper.php');
121
  // profiler has to be loaded manually
122
  require_once('classes/SimpleProfiler.php');
@@ -127,28 +133,11 @@ class WpSecurityAuditLog {
127
  require_once('classes/Models/Option.php');
128
  require_once('classes/Models/TmpUser.php');
129
 
130
- // Use WP_Session (default)
131
- if (!defined('WP_SESSION_COOKIE')) {
132
- define('WP_SESSION_COOKIE', 'wsal_wp_session');
133
- }
134
- if (!class_exists('Recursive_ArrayAccess')) {
135
- require_once('classes/Lib/class-recursive-arrayaccess.php');
136
- }
137
- if (!class_exists('WP_Session')) {
138
- require_once('classes/Lib/class-wp-session.php');
139
- require_once('classes/Lib/wp-session.php');
140
- }
141
-
142
- if (!class_exists('WP_Session_Utils')) {
143
- require_once('classes/Lib/class-wp-session-utils.php');
144
- }
145
-
146
-
147
  // load autoloader and register base paths
148
  require_once('classes/Autoloader.php');
149
  $this->autoloader = new WSAL_Autoloader($this);
150
  $this->autoloader->Register(self::PLG_CLS_PRFX, $this->GetBaseDir() . 'classes' . DIRECTORY_SEPARATOR);
151
-
152
  // load dependencies
153
  $this->views = new WSAL_ViewManager($this);
154
  $this->alerts = new WSAL_AlertManager($this);
@@ -157,19 +146,19 @@ class WpSecurityAuditLog {
157
  $this->constants = new WSAL_ConstantManager($this);
158
  $this->licensing = new WSAL_LicenseManager($this);
159
  $this->widgets = new WSAL_WidgetManager($this);
160
-
161
- // listen for installation event
162
- register_activation_hook(__FILE__, array($this, 'Install'));
163
 
164
  // listen for init event
165
  add_action('init', array($this, 'Init'));
166
-
167
  // listen for cleanup event
168
  add_action('wsal_cleanup', array($this, 'CleanUp'));
169
-
170
  // render wsal header
171
  add_action('admin_enqueue_scripts', array($this, 'RenderHeader'));
172
-
173
  // render wsal footer
174
  add_action('admin_footer', array($this, 'RenderFooter'));
175
 
@@ -183,15 +172,29 @@ class WpSecurityAuditLog {
183
  /**
184
  * @internal Start to trigger the events after installation.
185
  */
186
- public function Init(){
 
 
187
  WpSecurityAuditLog::GetInstance()->sensors->HookEvents();
 
 
 
 
 
 
 
 
 
 
 
188
  }
189
 
190
-
191
  /**
192
  * @internal Render plugin stuff in page header.
193
  */
194
- public function RenderHeader(){
 
195
  // common.css?
196
  }
197
 
@@ -199,7 +202,8 @@ class WpSecurityAuditLog {
199
  * Disable Custom Field through ajax.
200
  * @internal
201
  */
202
- public function AjaxDisableCustomField(){
 
203
  $fields = $this->GetGlobalOption('excluded-custom');
204
  if (isset($fields) && $fields != "") {
205
  $fields .= "," . esc_html($_POST['notice']);
@@ -215,7 +219,8 @@ class WpSecurityAuditLog {
215
  * Disable Alert through ajax.
216
  * @internal
217
  */
218
- public function AjaxDisableByCode(){
 
219
  $sAlerts = $this->GetGlobalOption('disabled-alerts');
220
  if (isset($sAlerts) && $sAlerts != "") {
221
  $sAlerts .= "," . esc_html($_POST['code']);
@@ -227,11 +232,12 @@ class WpSecurityAuditLog {
227
  echo 'You can enable this alert again from the Enable/Disable Alerts node in the plugin menu.</p>';
228
  die;
229
  }
230
-
231
  /**
232
  * @internal Render plugin stuff in page footer.
233
  */
234
- public function RenderFooter(){
 
235
  wp_enqueue_script(
236
  'wsal-common',
237
  $this->GetBaseUrl() . '/js/common.js',
@@ -239,12 +245,12 @@ class WpSecurityAuditLog {
239
  filemtime($this->GetBaseDir() . '/js/common.js')
240
  );
241
  }
242
-
243
  /**
244
  * @internal Load the rest of the system.
245
  */
246
- public function Load(){
247
-
248
  $optionsTable = new WSAL_Models_Option();
249
  if (!$optionsTable->IsInstalled()) {
250
  $optionsTable->Install();
@@ -281,12 +287,20 @@ class WpSecurityAuditLog {
281
  if ($this->settings->IsIncognito()) {
282
  add_action('admin_head', array($this, 'HidePlugin'));
283
  }
 
 
 
 
 
 
 
284
  }
285
-
286
  /**
287
  * Install all assets required for a useable system.
288
  */
289
- public function Install(){
 
290
  if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION) < 0) {
291
  ?><html>
292
  <head>
@@ -302,16 +316,19 @@ class WpSecurityAuditLog {
302
  </html><?php
303
  die(1);
304
  }
305
-
306
  // ensure that the system is installed and schema is correct
307
  self::getConnector()->installAll();
308
-
309
  $PreInstalled = $this->IsInstalled();
310
-
311
  // if system already installed, do updates now (if any)
312
  $OldVersion = $this->GetOldVersion();
313
  $NewVersion = $this->GetNewVersion();
314
- if ($PreInstalled && $OldVersion != $NewVersion) $this->Update($OldVersion, $NewVersion);
 
 
 
315
 
316
  // Load options from wp_options table or wp_sitemeta in multisite enviroment
317
  $data = $this->read_options_prefixed("wsal-");
@@ -319,9 +336,11 @@ class WpSecurityAuditLog {
319
  $this->SetOptions($data);
320
  }
321
  $this->deleteAllOptions();
322
-
323
  // if system wasn't installed, try migration now
324
- if (!$PreInstalled && $this->CanMigrate()) $this->Migrate();
 
 
325
 
326
  // setting the prunig date with the old value or the default value
327
  $pruningDate = $this->settings->GetPruningDate();
@@ -350,34 +369,86 @@ class WpSecurityAuditLog {
350
  if ($purge_log_404 === false) {
351
  $this->SetGlobalOption('purge-404-log', 'on');
352
  }
353
-
354
  // install cleanup hook (remove older one if it exists)
355
  wp_clear_scheduled_hook('wsal_cleanup');
356
  wp_schedule_event(current_time('timestamp') + 600, 'hourly', 'wsal_cleanup');
357
  }
358
-
359
  /**
360
  * Run some code that updates critical components required for a newwer version.
 
361
  * @param string $old_version The old version.
362
  * @param string $new_version The new version.
363
  */
364
- public function Update($old_version, $new_version){
365
- // update version in db
366
- $this->GetGlobalOption('version', $new_version);
367
-
368
- // disable all developer options
369
  //$this->settings->ClearDevOptions();
370
-
371
- // do version-to-version specific changes
372
- if(version_compare($old_version, '1.2.3') == -1){
373
- // ... an example
374
  }
375
  }
376
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
  /**
378
  * Uninstall plugin.
379
  */
380
- public function Uninstall(){
 
381
  if ($this->GetGlobalOption("delete-data") == 1) {
382
  self::getConnector()->uninstallAll();
383
  $this->deleteAllOptions();
@@ -385,40 +456,60 @@ class WpSecurityAuditLog {
385
  wp_clear_scheduled_hook('wsal_cleanup');
386
  }
387
 
388
- public function delete_options_prefixed( $prefix ) {
 
 
 
 
 
 
389
  global $wpdb;
390
-
391
- if ( $this->IsMultisite() ) {
392
  $table_name = $wpdb->prefix .'sitemeta';
393
- $result = $wpdb->query( "DELETE FROM {$table_name} WHERE meta_key LIKE '{$prefix}%'" );
394
  } else {
395
- $result = $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '{$prefix}%'" );
396
  }
397
  return ($result) ? true : false;
398
  }
399
 
400
- private function deleteAllOptions() {
 
 
 
 
401
  $flag = true;
402
- while ( $flag ) {
403
- $flag = $this->delete_options_prefixed( 'wsal-' );
404
  }
405
  }
406
-
407
- public function read_options_prefixed( $prefix ) {
 
 
 
 
 
 
408
  global $wpdb;
409
- if ( $this->IsMultisite() ) {
410
  $table_name = $wpdb->prefix .'sitemeta';
411
- $results = $wpdb->get_results( "SELECT site_id,meta_key,meta_value FROM {$table_name} WHERE meta_key LIKE '{$prefix}%'", ARRAY_A );
412
  } else {
413
- $results = $wpdb->get_results( "SELECT option_name,option_value FROM {$wpdb->options} WHERE option_name LIKE '{$prefix}%'", ARRAY_A );
414
  }
415
  return $results;
416
  }
417
 
418
- public function SetOptions($data){
419
- foreach($data as $key => $option) {
 
 
 
 
 
420
  $this->options = new WSAL_Models_Option();
421
- if ( $this->IsMultisite() ) {
422
  $this->options->SetOptionValue($option['meta_key'], $option['meta_value']);
423
  } else {
424
  $this->options->SetOptionValue($option['option_name'], $option['option_value']);
@@ -429,49 +520,57 @@ class WpSecurityAuditLog {
429
  /**
430
  * Migrate data from old plugin.
431
  */
432
- public function Migrate(){
 
433
  global $wpdb;
434
  static $migTypes = array(
435
  3000 => 5006
436
  );
437
-
438
  // load data
439
  $sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog_events';
440
  $events = array();
441
- foreach($wpdb->get_results($sql, ARRAY_A) as $item)
442
  $events[$item['EventID']] = $item;
 
443
  $sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog';
444
  $auditlog = $wpdb->get_results($sql, ARRAY_A);
445
-
446
  // migrate using db logger
447
- foreach($auditlog as $entry){
448
  $data = array(
449
  'ClientIP' => $entry['UserIP'],
450
  'UserAgent' => '',
451
  'CurrentUserID' => $entry['UserID'],
452
  );
453
- if($entry['UserName'])
454
  $data['Username'] = base64_decode($entry['UserName']);
 
455
  $mesg = $events[$entry['EventID']]['EventDescription'];
456
  $date = strtotime($entry['EventDate']);
457
  $type = $entry['EventID'];
458
- if(isset($migTypes[$type]))$type = $migTypes[$type];
 
 
459
  // convert message from '<strong>%s</strong>' to '%Arg1%' format
460
- $c = 0; $n = '<strong>%s</strong>'; $l = strlen($n);
461
- while(($pos = strpos($mesg, $n)) !== false){
 
 
462
  $mesg = substr_replace($mesg, '%MigratedArg' . ($c++) .'%', $pos, $l);
463
  }
464
  $data['MigratedMesg'] = $mesg;
465
  // generate new meta data args
466
  $temp = unserialize(base64_decode($entry['EventData']));
467
- foreach((array)$temp as $i => $item)
468
  $data['MigratedArg' . $i] = $item;
 
469
  // send event data to logger!
470
- foreach($this->alerts->GetLoggers() as $logger){
471
  $logger->Log($type, $data, $date, $entry['BlogId'], true);
472
  }
473
  }
474
-
475
  // migrate settings
476
  $this->settings->SetAllowedPluginEditors(
477
  get_option('WPPH_PLUGIN_ALLOW_CHANGE')
@@ -485,30 +584,33 @@ class WpSecurityAuditLog {
485
  $this->settings->SetViewPerPage(max($s->showEventsViewList, 5));
486
  $this->settings->SetWidgetsEnabled(!!$s->showDW);
487
  }
488
-
489
  // </editor-fold>
490
-
491
  // <editor-fold desc="Utility Methods">
492
-
493
  /**
494
  * @return string The current plugin version (according to plugin file metadata).
495
  */
496
- public function GetNewVersion(){
 
497
  $version = get_plugin_data(__FILE__, false, false);
498
  return isset($version['Version']) ? $version['Version'] : '0.0.0';
499
  }
500
-
501
  /**
502
  * @return string The plugin version as stored in DB (will be the old version during an update/install).
503
  */
504
- public function GetOldVersion(){
 
505
  return $this->GetGlobalOption('version', '0.0.0');
506
  }
507
-
508
  /**
509
  * @internal To be called in admin header for hiding plugin form Plugins list.
510
  */
511
- public function HidePlugin() {
 
512
  $selectr = '';
513
  $plugins = array('wp-security-audit-log');
514
  foreach ($this->licensing->Plugins() as $plugin) {
@@ -519,24 +621,26 @@ class WpSecurityAuditLog {
519
  }
520
  ?><style type="text/css"> <?php echo rtrim($selectr, ", "); ?> { display: none; }</style><?php
521
  }
522
-
523
  /**
524
  * Returns the class name of a particular file that contains the class.
525
  * @param string $file File name.
526
  * @return string Class name.
527
  * @deprecated since 1.2.5 Use autoloader->GetClassFileClassName() instead.
528
  */
529
- public function GetClassFileClassName($file){
 
530
  return $this->autoloader->GetClassFileClassName($file);
531
  }
532
-
533
  /**
534
  * @return boolean Whether we are running on multisite or not.
535
  */
536
- public function IsMultisite(){
 
537
  return function_exists('is_multisite') && is_multisite();
538
  }
539
-
540
  /**
541
  * Get a global option.
542
  * @param string $option Option name.
@@ -544,27 +648,24 @@ class WpSecurityAuditLog {
544
  * @param string $prefix (Optional) A prefix used before option name.
545
  * @return mixed Option's value or $default if option not set.
546
  */
547
- public function GetGlobalOption($option, $default = false, $prefix = self::OPT_PRFX){
548
- //$fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
549
- //var_dump($fn($prefix . $option, $default));
550
- //return $fn($prefix . $option, $default);
551
  $this->options = new WSAL_Models_Option();
552
- return $this->options->GetOptionValue($prefix . $option, $default);
553
  }
554
-
555
  /**
556
  * Set a global option.
557
  * @param string $option Option name.
558
  * @param mixed $value New value for option.
559
  * @param string $prefix (Optional) A prefix used before option name.
560
  */
561
- public function SetGlobalOption($option, $value, $prefix = self::OPT_PRFX){
562
- //$fn = $this->IsMultisite() ? 'update_site_option' : 'update_option';
563
- //$fn($prefix . $option, $value);
564
  $this->options = new WSAL_Models_Option();
565
  $this->options->SetOptionValue($prefix . $option, $value);
566
  }
567
-
568
  /**
569
  * Get a user-specific option.
570
  * @param string $option Option name.
@@ -572,93 +673,111 @@ class WpSecurityAuditLog {
572
  * @param string $prefix (Optional) A prefix used before option name.
573
  * @return mixed Option's value or $default if option not set.
574
  */
575
- public function GetUserOption($option, $default = false, $prefix = self::OPT_PRFX){
 
576
  $result = get_user_option($prefix . $option, get_current_user_id());
577
  return $result === false ? $default : $result;
578
  }
579
-
580
  /**
581
  * Set a user-specific option.
582
  * @param string $option Option name.
583
  * @param mixed $value New value for option.
584
  * @param string $prefix (Optional) A prefix used before option name.
585
  */
586
- public function SetUserOption($option, $value, $prefix = self::OPT_PRFX){
 
587
  update_user_option(get_current_user_id(), $prefix . $option, $value, false);
588
  }
589
-
590
  /**
591
  * Run cleanup routines.
592
  */
593
- public function CleanUp(){
 
594
  $s = $this->profiler->Start('Clean Up');
595
- foreach($this->_cleanup_hooks as $hook)
596
  call_user_func($hook);
 
597
  $s->Stop();
598
  }
599
-
600
  /**
601
  * Add callback to be called when a cleanup operation is required.
602
  * @param callable $hook
603
  */
604
- public function AddCleanupHook($hook){
 
605
  $this->_cleanup_hooks[] = $hook;
606
  }
607
-
608
  /**
609
  * Remove a callback from the cleanup callbacks list.
610
  * @param callable $hook
611
  */
612
- public function RemoveCleanupHook($hook){
613
- while(($pos = array_search($hook, $this->_cleanup_hooks)) !== false)
 
614
  unset($this->_cleanup_hooks[$pos]);
 
615
  }
616
 
 
 
 
 
 
617
  public static function getConnector($config = null, $reset = false)
618
  {
619
  return WSAL_Connector_ConnectorFactory::getConnector($config, $reset);
620
  }
621
-
622
  /**
623
  * Do we have an existing installation? This only applies for version 1.0 onwards.
624
  * @return boolean
625
  */
626
- public function IsInstalled(){
 
627
  return self::getConnector()->isInstalled();
628
  }
629
-
630
  /**
631
  * @return boolean Whether the old plugin was present or not.
632
  */
633
- public function CanMigrate(){
 
634
  return self::getConnector()->canMigrate();
635
  }
636
-
637
  /**
638
  * @return string Absolute URL to plugin directory WITHOUT final slash.
639
  */
640
- public function GetBaseUrl(){
 
641
  return plugins_url('', __FILE__);
642
  }
643
-
644
  /**
645
  * @return string Full path to plugin directory WITH final slash.
646
  */
647
- public function GetBaseDir(){
 
648
  return plugin_dir_path(__FILE__);
649
  }
650
-
651
  /**
652
  * @return string Plugin directory name.
653
  */
654
- public function GetBaseName(){
 
655
  return plugin_basename(__FILE__);
656
  }
657
-
658
  /**
659
  * Load default configuration / data.
660
  */
661
- public function LoadDefaults(){
 
662
  $s = $this->profiler->Start('Load Defaults');
663
  require_once('defaults.php');
664
  $s->Stop();
4
  Plugin URI: http://www.wpsecurityauditlog.com/
5
  Description: Identify WordPress security issues before they become a problem. Keep track of everything happening on your WordPress including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log generates a security alert for everything that happens on your WordPress blogs and websites. Use the Audit Log Viewer included in the plugin to see all the security alerts.
6
  Author: WP White Security
7
+ Version: 2.6.5
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpsecurityauditlog.com/
10
  License: GPL2
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
+ /**
30
+ * @package Wsal
31
+ */
32
  class WpSecurityAuditLog {
33
+
34
  // <editor-fold desc="Properties & Constants">
35
+
36
  const PLG_CLS_PRFX = 'WSAL_';
37
+
38
  const MIN_PHP_VERSION = '5.3.0';
39
+
40
  const OPT_PRFX = 'wsal-';
41
+
42
  /**
43
  * Views supervisor.
44
  * @var WSAL_ViewManager
45
  */
46
  public $views;
47
+
48
  /**
49
  * Logger supervisor.
50
  * @var WSAL_AlertManager
51
  */
52
  public $alerts;
53
+
54
  /**
55
  * Sensors supervisor.
56
  * @var WSAL_SensorManager
57
  */
58
  public $sensors;
59
+
60
  /**
61
  * Settings manager.
62
  * @var WSAL_Settings
63
  */
64
  public $settings;
65
+
66
  /**
67
  * Class loading manager.
68
  * @var WSAL_Autoloader
69
  */
70
  public $autoloader;
71
+
72
  /**
73
  * Constants manager.
74
  * @var WSAL_ConstantManager
75
  */
76
  public $constants;
77
+
78
  /**
79
  * Licenses manager.
80
  * @var WSAL_LicenseManager
81
  */
82
  public $licensing;
83
+
84
  /**
85
  * Simple profiler.
86
  * @var WSAL_SimpleProfiler
92
  * @var WSAL_DB_Option
93
  */
94
  public $options;
95
+
96
  /**
97
  * Contains a list of cleanup callbacks.
98
  * @var callable[]
99
  */
100
  protected $_cleanup_hooks = array();
101
+
102
  // </editor-fold>
103
+
104
  // <editor-fold desc="Entry Points">
105
+
106
  /**
107
  * Standard singleton pattern.
108
  * WARNING! To ensure the system always works as expected, AVOID using this method.
109
  * Instead, make use of the plugin instance provided by 'wsal_init' action.
110
  * @return WpSecurityAuditLog Returns the current plugin instance.
111
  */
112
+ public static function GetInstance()
113
+ {
114
  static $instance = null;
115
+ if (!$instance) {
116
+ $instance = new self();
117
+ }
118
  return $instance;
119
  }
120
+
121
  /**
122
  * Initialize plugin.
123
  */
124
+ public function __construct()
125
+ {
126
  require_once('classes/Helpers/DataHelper.php');
127
  // profiler has to be loaded manually
128
  require_once('classes/SimpleProfiler.php');
133
  require_once('classes/Models/Option.php');
134
  require_once('classes/Models/TmpUser.php');
135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  // load autoloader and register base paths
137
  require_once('classes/Autoloader.php');
138
  $this->autoloader = new WSAL_Autoloader($this);
139
  $this->autoloader->Register(self::PLG_CLS_PRFX, $this->GetBaseDir() . 'classes' . DIRECTORY_SEPARATOR);
140
+
141
  // load dependencies
142
  $this->views = new WSAL_ViewManager($this);
143
  $this->alerts = new WSAL_AlertManager($this);
146
  $this->constants = new WSAL_ConstantManager($this);
147
  $this->licensing = new WSAL_LicenseManager($this);
148
  $this->widgets = new WSAL_WidgetManager($this);
149
+
150
+ // Listen for installation event.
151
+ register_activation_hook( __FILE__, array( $this, 'Install' ) );
152
 
153
  // listen for init event
154
  add_action('init', array($this, 'Init'));
155
+
156
  // listen for cleanup event
157
  add_action('wsal_cleanup', array($this, 'CleanUp'));
158
+
159
  // render wsal header
160
  add_action('admin_enqueue_scripts', array($this, 'RenderHeader'));
161
+
162
  // render wsal footer
163
  add_action('admin_footer', array($this, 'RenderFooter'));
164
 
172
  /**
173
  * @internal Start to trigger the events after installation.
174
  */
175
+ public function Init()
176
+ {
177
+ // Start listening to events
178
  WpSecurityAuditLog::GetInstance()->sensors->HookEvents();
179
+
180
+ if ($this->settings->IsArchivingEnabled()) {
181
+ // Check the current page
182
+ if ((!isset($_REQUEST['page']) || $_REQUEST['page'] != 'wsal-auditlog') && (!defined('DOING_AJAX') || !DOING_AJAX)) {
183
+ $selected_db = get_transient('wsal_wp_selected_db');
184
+ if ($selected_db) {
185
+ // Delete the transient
186
+ delete_transient('wsal_wp_selected_db');
187
+ }
188
+ }
189
+ }
190
  }
191
 
192
+
193
  /**
194
  * @internal Render plugin stuff in page header.
195
  */
196
+ public function RenderHeader()
197
+ {
198
  // common.css?
199
  }
200
 
202
  * Disable Custom Field through ajax.
203
  * @internal
204
  */
205
+ public function AjaxDisableCustomField()
206
+ {
207
  $fields = $this->GetGlobalOption('excluded-custom');
208
  if (isset($fields) && $fields != "") {
209
  $fields .= "," . esc_html($_POST['notice']);
219
  * Disable Alert through ajax.
220
  * @internal
221
  */
222
+ public function AjaxDisableByCode()
223
+ {
224
  $sAlerts = $this->GetGlobalOption('disabled-alerts');
225
  if (isset($sAlerts) && $sAlerts != "") {
226
  $sAlerts .= "," . esc_html($_POST['code']);
232
  echo 'You can enable this alert again from the Enable/Disable Alerts node in the plugin menu.</p>';
233
  die;
234
  }
235
+
236
  /**
237
  * @internal Render plugin stuff in page footer.
238
  */
239
+ public function RenderFooter()
240
+ {
241
  wp_enqueue_script(
242
  'wsal-common',
243
  $this->GetBaseUrl() . '/js/common.js',
245
  filemtime($this->GetBaseDir() . '/js/common.js')
246
  );
247
  }
248
+
249
  /**
250
  * @internal Load the rest of the system.
251
  */
252
+ public function Load()
253
+ {
254
  $optionsTable = new WSAL_Models_Option();
255
  if (!$optionsTable->IsInstalled()) {
256
  $optionsTable->Install();
287
  if ($this->settings->IsIncognito()) {
288
  add_action('admin_head', array($this, 'HidePlugin'));
289
  }
290
+
291
+ // Update routine.
292
+ $old_version = $this->GetOldVersion();
293
+ $new_version = $this->GetNewVersion();
294
+ if ( $old_version !== $new_version ) {
295
+ $this->Update( $old_version, $new_version );
296
+ }
297
  }
298
+
299
  /**
300
  * Install all assets required for a useable system.
301
  */
302
+ public function Install()
303
+ {
304
  if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION) < 0) {
305
  ?><html>
306
  <head>
316
  </html><?php
317
  die(1);
318
  }
319
+
320
  // ensure that the system is installed and schema is correct
321
  self::getConnector()->installAll();
322
+
323
  $PreInstalled = $this->IsInstalled();
324
+
325
  // if system already installed, do updates now (if any)
326
  $OldVersion = $this->GetOldVersion();
327
  $NewVersion = $this->GetNewVersion();
328
+
329
+ if ( $PreInstalled && $OldVersion != $NewVersion ) {
330
+ $this->Update( $OldVersion, $NewVersion );
331
+ }
332
 
333
  // Load options from wp_options table or wp_sitemeta in multisite enviroment
334
  $data = $this->read_options_prefixed("wsal-");
336
  $this->SetOptions($data);
337
  }
338
  $this->deleteAllOptions();
339
+
340
  // if system wasn't installed, try migration now
341
+ if (!$PreInstalled && $this->CanMigrate()) {
342
+ $this->Migrate();
343
+ }
344
 
345
  // setting the prunig date with the old value or the default value
346
  $pruningDate = $this->settings->GetPruningDate();
369
  if ($purge_log_404 === false) {
370
  $this->SetGlobalOption('purge-404-log', 'on');
371
  }
372
+
373
  // install cleanup hook (remove older one if it exists)
374
  wp_clear_scheduled_hook('wsal_cleanup');
375
  wp_schedule_event(current_time('timestamp') + 600, 'hourly', 'wsal_cleanup');
376
  }
377
+
378
  /**
379
  * Run some code that updates critical components required for a newwer version.
380
+ *
381
  * @param string $old_version The old version.
382
  * @param string $new_version The new version.
383
  */
384
+ public function Update( $old_version, $new_version ) {
385
+ // Update version in db.
386
+ $this->SetGlobalOption( 'version', $new_version );
387
+
388
+ // Disable all developer options.
389
  //$this->settings->ClearDevOptions();
390
+
391
+ // Do version-to-version specific changes.
392
+ if ( -1 === version_compare( $old_version, $new_version ) ) {
393
+ $this->update_external_db_password();
394
  }
395
  }
396
 
397
+ /**
398
+ * Method: Update external DB password.
399
+ *
400
+ * @since 2.6.3
401
+ */
402
+ public function update_external_db_password() {
403
+
404
+ // Get the passwords.
405
+ $external_password = $this->settings->GetAdapterConfig( 'adapter-password' );
406
+ $mirror_password = $this->settings->GetAdapterConfig( 'mirror-password' );
407
+ $archive_password = $this->settings->GetAdapterConfig( 'archive-password' );
408
+
409
+ // Update external db password.
410
+ if ( ! empty( $external_password ) ) {
411
+ // Decrypt the password using fallback method.
412
+ $password = $this->getConnector()->decryptString_fallback( $external_password );
413
+
414
+ // Encrypt the password with latest encryption method.
415
+ $encrypted_password = $this->getConnector()->encryptString( $password );
416
+
417
+ // Store the new password.
418
+ $this->settings->SetAdapterConfig( 'adapter-password', $encrypted_password );
419
+ }
420
+
421
+ // Update mirror db password.
422
+ if ( ! empty( $mirror_password ) ) {
423
+ // Decrypt the password using fallback method.
424
+ $password = $this->getConnector()->decryptString_fallback( $mirror_password );
425
+
426
+ // Encrypt the password with latest encryption method.
427
+ $encrypted_password = $this->getConnector()->encryptString( $password );
428
+
429
+ // Store the new password.
430
+ $this->settings->SetAdapterConfig( 'mirror-password', $encrypted_password );
431
+ }
432
+
433
+ // Update archive db password.
434
+ if ( ! empty( $archive_password ) ) {
435
+ // Decrypt the password using fallback method.
436
+ $password = $this->getConnector()->decryptString_fallback( $archive_password );
437
+
438
+ // Encrypt the password with latest encryption method.
439
+ $encrypted_password = $this->getConnector()->encryptString( $password );
440
+
441
+ // Store the new password.
442
+ $this->settings->SetAdapterConfig( 'archive-password', $encrypted_password );
443
+ }
444
+
445
+ }
446
+
447
  /**
448
  * Uninstall plugin.
449
  */
450
+ public function Uninstall()
451
+ {
452
  if ($this->GetGlobalOption("delete-data") == 1) {
453
  self::getConnector()->uninstallAll();
454
  $this->deleteAllOptions();
456
  wp_clear_scheduled_hook('wsal_cleanup');
457
  }
458
 
459
+ /**
460
+ * Delete from the options table of WP.
461
+ * @param string $prefix table prefix
462
+ * @return boolean query result
463
+ */
464
+ public function delete_options_prefixed($prefix)
465
+ {
466
  global $wpdb;
467
+ if ($this->IsMultisite()) {
 
468
  $table_name = $wpdb->prefix .'sitemeta';
469
+ $result = $wpdb->query("DELETE FROM {$table_name} WHERE meta_key LIKE '{$prefix}%'");
470
  } else {
471
+ $result = $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '{$prefix}%'");
472
  }
473
  return ($result) ? true : false;
474
  }
475
 
476
+ /**
477
+ * Delete all the Wsal options from the options table of WP.
478
+ */
479
+ private function deleteAllOptions()
480
+ {
481
  $flag = true;
482
+ while ($flag) {
483
+ $flag = $this->delete_options_prefixed(self::OPT_PRFX);
484
  }
485
  }
486
+
487
+ /**
488
+ * Read options from the options table of WP.
489
+ * @param string $prefix table prefix
490
+ * @return boolean query result
491
+ */
492
+ public function read_options_prefixed($prefix)
493
+ {
494
  global $wpdb;
495
+ if ($this->IsMultisite()) {
496
  $table_name = $wpdb->prefix .'sitemeta';
497
+ $results = $wpdb->get_results("SELECT site_id,meta_key,meta_value FROM {$table_name} WHERE meta_key LIKE '{$prefix}%'", ARRAY_A);
498
  } else {
499
+ $results = $wpdb->get_results("SELECT option_name,option_value FROM {$wpdb->options} WHERE option_name LIKE '{$prefix}%'", ARRAY_A);
500
  }
501
  return $results;
502
  }
503
 
504
+ /**
505
+ * Set options in the Wsal options table.
506
+ * @param array $data table prefix
507
+ */
508
+ public function SetOptions($data)
509
+ {
510
+ foreach ($data as $key => $option) {
511
  $this->options = new WSAL_Models_Option();
512
+ if ($this->IsMultisite()) {
513
  $this->options->SetOptionValue($option['meta_key'], $option['meta_value']);
514
  } else {
515
  $this->options->SetOptionValue($option['option_name'], $option['option_value']);
520
  /**
521
  * Migrate data from old plugin.
522
  */
523
+ public function Migrate()
524
+ {
525
  global $wpdb;
526
  static $migTypes = array(
527
  3000 => 5006
528
  );
529
+
530
  // load data
531
  $sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog_events';
532
  $events = array();
533
+ foreach ($wpdb->get_results($sql, ARRAY_A) as $item) {
534
  $events[$item['EventID']] = $item;
535
+ }
536
  $sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog';
537
  $auditlog = $wpdb->get_results($sql, ARRAY_A);
538
+
539
  // migrate using db logger
540
+ foreach ($auditlog as $entry) {
541
  $data = array(
542
  'ClientIP' => $entry['UserIP'],
543
  'UserAgent' => '',
544
  'CurrentUserID' => $entry['UserID'],
545
  );
546
+ if ($entry['UserName']) {
547
  $data['Username'] = base64_decode($entry['UserName']);
548
+ }
549
  $mesg = $events[$entry['EventID']]['EventDescription'];
550
  $date = strtotime($entry['EventDate']);
551
  $type = $entry['EventID'];
552
+ if (isset($migTypes[$type])) {
553
+ $type = $migTypes[$type];
554
+ }
555
  // convert message from '<strong>%s</strong>' to '%Arg1%' format
556
+ $c = 0;
557
+ $n = '<strong>%s</strong>';
558
+ $l = strlen($n);
559
+ while (($pos = strpos($mesg, $n)) !== false) {
560
  $mesg = substr_replace($mesg, '%MigratedArg' . ($c++) .'%', $pos, $l);
561
  }
562
  $data['MigratedMesg'] = $mesg;
563
  // generate new meta data args
564
  $temp = unserialize(base64_decode($entry['EventData']));
565
+ foreach ((array)$temp as $i => $item) {
566
  $data['MigratedArg' . $i] = $item;
567
+ }
568
  // send event data to logger!
569
+ foreach ($this->alerts->GetLoggers() as $logger) {
570
  $logger->Log($type, $data, $date, $entry['BlogId'], true);
571
  }
572
  }
573
+
574
  // migrate settings
575
  $this->settings->SetAllowedPluginEditors(
576
  get_option('WPPH_PLUGIN_ALLOW_CHANGE')
584
  $this->settings->SetViewPerPage(max($s->showEventsViewList, 5));
585
  $this->settings->SetWidgetsEnabled(!!$s->showDW);
586
  }
587
+
588
  // </editor-fold>
589
+
590
  // <editor-fold desc="Utility Methods">
591
+
592
  /**
593
  * @return string The current plugin version (according to plugin file metadata).
594
  */
595
+ public function GetNewVersion()
596
+ {
597
  $version = get_plugin_data(__FILE__, false, false);
598
  return isset($version['Version']) ? $version['Version'] : '0.0.0';
599
  }
600
+
601
  /**
602
  * @return string The plugin version as stored in DB (will be the old version during an update/install).
603
  */
604
+ public function GetOldVersion()
605
+ {
606
  return $this->GetGlobalOption('version', '0.0.0');
607
  }
608
+
609
  /**
610
  * @internal To be called in admin header for hiding plugin form Plugins list.
611
  */
612
+ public function HidePlugin()
613
+ {
614
  $selectr = '';
615
  $plugins = array('wp-security-audit-log');
616
  foreach ($this->licensing->Plugins() as $plugin) {
621
  }
622
  ?><style type="text/css"> <?php echo rtrim($selectr, ", "); ?> { display: none; }</style><?php
623
  }
624
+
625
  /**
626
  * Returns the class name of a particular file that contains the class.
627
  * @param string $file File name.
628
  * @return string Class name.
629
  * @deprecated since 1.2.5 Use autoloader->GetClassFileClassName() instead.
630
  */
631
+ public function GetClassFileClassName($file)
632
+ {
633
  return $this->autoloader->GetClassFileClassName($file);
634
  }
635
+
636
  /**
637
  * @return boolean Whether we are running on multisite or not.
638
  */
639
+ public function IsMultisite()
640
+ {
641
  return function_exists('is_multisite') && is_multisite();
642
  }
643
+
644
  /**
645
  * Get a global option.
646
  * @param string $option Option name.
648
  * @param string $prefix (Optional) A prefix used before option name.
649
  * @return mixed Option's value or $default if option not set.
650
  */
651
+ public function GetGlobalOption($option, $default = false, $prefix = self::OPT_PRFX)
652
+ {
 
 
653
  $this->options = new WSAL_Models_Option();
654
+ return $this->options->GetOptionValue($prefix . $option, $default);
655
  }
656
+
657
  /**
658
  * Set a global option.
659
  * @param string $option Option name.
660
  * @param mixed $value New value for option.
661
  * @param string $prefix (Optional) A prefix used before option name.
662
  */
663
+ public function SetGlobalOption($option, $value, $prefix = self::OPT_PRFX)
664
+ {
 
665
  $this->options = new WSAL_Models_Option();
666
  $this->options->SetOptionValue($prefix . $option, $value);
667
  }
668
+
669
  /**
670
  * Get a user-specific option.
671
  * @param string $option Option name.
673
  * @param string $prefix (Optional) A prefix used before option name.
674
  * @return mixed Option's value or $default if option not set.
675
  */
676
+ public function GetUserOption($option, $default = false, $prefix = self::OPT_PRFX)
677
+ {
678
  $result = get_user_option($prefix . $option, get_current_user_id());
679
  return $result === false ? $default : $result;
680
  }
681
+
682
  /**
683
  * Set a user-specific option.
684
  * @param string $option Option name.
685
  * @param mixed $value New value for option.
686
  * @param string $prefix (Optional) A prefix used before option name.
687
  */
688
+ public function SetUserOption($option, $value, $prefix = self::OPT_PRFX)
689
+ {
690
  update_user_option(get_current_user_id(), $prefix . $option, $value, false);
691
  }
692
+
693
  /**
694
  * Run cleanup routines.
695
  */
696
+ public function CleanUp()
697
+ {
698
  $s = $this->profiler->Start('Clean Up');
699
+ foreach ($this->_cleanup_hooks as $hook) {
700
  call_user_func($hook);
701
+ }
702
  $s->Stop();
703
  }
704
+
705
  /**
706
  * Add callback to be called when a cleanup operation is required.
707
  * @param callable $hook
708
  */
709
+ public function AddCleanupHook($hook)
710
+ {
711
  $this->_cleanup_hooks[] = $hook;
712
  }
713
+
714
  /**
715
  * Remove a callback from the cleanup callbacks list.
716
  * @param callable $hook
717
  */
718
+ public function RemoveCleanupHook($hook)
719
+ {
720
+ while (($pos = array_search($hook, $this->_cleanup_hooks)) !== false) {
721
  unset($this->_cleanup_hooks[$pos]);
722
+ }
723
  }
724
 
725
+ /**
726
+ * DB connection.
727
+ * @param mixed $config DB configuration.
728
+ * @return WSAL_Connector_ConnectorInterface
729
+ */
730
  public static function getConnector($config = null, $reset = false)
731
  {
732
  return WSAL_Connector_ConnectorFactory::getConnector($config, $reset);
733
  }
734
+
735
  /**
736
  * Do we have an existing installation? This only applies for version 1.0 onwards.
737
  * @return boolean
738
  */
739
+ public function IsInstalled()
740
+ {
741
  return self::getConnector()->isInstalled();
742
  }
743
+
744
  /**
745
  * @return boolean Whether the old plugin was present or not.
746
  */
747
+ public function CanMigrate()
748
+ {
749
  return self::getConnector()->canMigrate();
750
  }
751
+
752
  /**
753
  * @return string Absolute URL to plugin directory WITHOUT final slash.
754
  */
755
+ public function GetBaseUrl()
756
+ {
757
  return plugins_url('', __FILE__);
758
  }
759
+
760
  /**
761
  * @return string Full path to plugin directory WITH final slash.
762
  */
763
+ public function GetBaseDir()
764
+ {
765
  return plugin_dir_path(__FILE__);
766
  }
767
+
768
  /**
769
  * @return string Plugin directory name.
770
  */
771
+ public function GetBaseName()
772
+ {
773
  return plugin_basename(__FILE__);
774
  }
775
+
776
  /**
777
  * Load default configuration / data.
778
  */
779
+ public function LoadDefaults()
780
+ {
781
  $s = $this->profiler->Start('Load Defaults');
782
  require_once('defaults.php');
783
  $s->Stop();