WP Security Audit Log - Version 2.6.6

Version Description

(2017-08-30 =

  • New Audit Trail Alerts

    • Alert 4015 for when a user creates a custom field in a user profile.
    • Alert 4016 for when a user updates a custom field value in a user profile.
  • New Feature

    • Logging of changes in custom fields (in posts, pages, custom post types, user profiles) created by Advanced Custom Fields (ACF) or similar plugins.
    • New option to show either the Username or Firstname and Lastname of the user in the Audit Trail.
  • Improvements

    • 404 errors logfiles are now saved in /uploads/wp-security-audit-log/404s/ directory.
    • Changed the 404 errors logfile name format to [alert]_[yyyymmdd].log. Thanks to Enable Security for PoC of vulnerability and advise.
    • Removed link to view post from Alerts about permanently deleted posts (2008, 2009, 2033).
    • Added tooltip for filter via IP address.
  • Bug Fix

    • Fixed an issue where the viewing of content was not being logged when Yoast SEO is installed.
Download this release

Release Info

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

Code changes from version 2.6.5 to 2.6.6

classes/Adapters/MySQL/QueryAdapter.php CHANGED
@@ -82,7 +82,7 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
82
  if (!empty($searchCondition)) {
83
  $args[] = $searchCondition['args'];
84
  }
85
-
86
  $sql = 'SELECT ' . $fields
87
  . ' FROM ' . implode(',', $fromDataSets)
88
  . $joinClause
@@ -93,7 +93,7 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
93
  . $sLimitClause;
94
  return $sql;
95
  }
96
-
97
  /**
98
  * Get an instance of the ActiveRecord Adapter.
99
  * @return WSAL_Adapters_MySQL_ActiveRecord
@@ -102,7 +102,7 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
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
@@ -121,7 +121,7 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
121
  return $this->getActiveRecordAdapter()->LoadMulti($sql, $args);
122
  }
123
  }
124
-
125
  /**
126
  * Count query
127
  * @param object $query query object
@@ -154,7 +154,7 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
154
  // execute query and return result
155
  return $this->getActiveRecordAdapter()->CountQuery($result['sql'], $result['args']);
156
  }
157
-
158
  /**
159
  * Query for deleting records
160
  * @param object $query query object.
@@ -237,7 +237,7 @@ class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
237
  $result['args'] = $args;
238
  // restore columns
239
  $query->setColumns($cols);
240
-
241
  return $result;
242
  }
243
 
82
  if (!empty($searchCondition)) {
83
  $args[] = $searchCondition['args'];
84
  }
85
+
86
  $sql = 'SELECT ' . $fields
87
  . ' FROM ' . implode(',', $fromDataSets)
88
  . $joinClause
93
  . $sLimitClause;
94
  return $sql;
95
  }
96
+
97
  /**
98
  * Get an instance of the ActiveRecord Adapter.
99
  * @return WSAL_Adapters_MySQL_ActiveRecord
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
121
  return $this->getActiveRecordAdapter()->LoadMulti($sql, $args);
122
  }
123
  }
124
+
125
  /**
126
  * Count query
127
  * @param object $query query object
154
  // execute query and return result
155
  return $this->getActiveRecordAdapter()->CountQuery($result['sql'], $result['args']);
156
  }
157
+
158
  /**
159
  * Query for deleting records
160
  * @param object $query query object.
237
  $result['args'] = $args;
238
  // restore columns
239
  $query->setColumns($cols);
240
+
241
  return $result;
242
  }
243
 
classes/AuditLogListView.php CHANGED
@@ -15,18 +15,18 @@ class WSAL_AuditLogListView extends WP_List_Table
15
  */
16
  protected $_plugin;
17
  protected $_gmt_offset_sec = 0;
18
-
19
  public function __construct($plugin)
20
  {
21
  $this->_plugin = $plugin;
22
-
23
  $timezone = $this->_plugin->settings->GetTimezone();
24
  if ($timezone) {
25
  $this->_gmt_offset_sec = get_option('gmt_offset') * HOUR_IN_SECONDS;
26
  } else {
27
  $this->_gmt_offset_sec = date('Z');
28
  }
29
-
30
  parent::__construct(array(
31
  'singular' => 'log',
32
  'plural' => 'logs',
@@ -39,7 +39,7 @@ class WSAL_AuditLogListView extends WP_List_Table
39
  {
40
  _e('No events so far.', 'wp-security-audit-log');
41
  }
42
-
43
  public function extra_tablenav($which)
44
  {
45
  // items-per-page widget
@@ -48,7 +48,7 @@ class WSAL_AuditLogListView extends WP_List_Table
48
  $items = array($o, 5, 10, 15, 30, 50);
49
  if (!in_array($p, $items)) $items[] = $p;
50
  if ($p == $o || $p == 0) $p = $o[1]; // a sane default if things goes bust
51
-
52
  ?><div class="wsal-ipp wsal-ipp-<?php echo $which; ?>">
53
  <?php _e('Show ', 'wp-security-audit-log'); ?>
54
  <select class="wsal-ipps" onfocus="WsalIppsFocus(value);" onchange="WsalIppsChange(value);">
@@ -62,7 +62,7 @@ class WSAL_AuditLogListView extends WP_List_Table
62
  </select>
63
  <?php _e(' Items', 'wp-security-audit-log'); ?>
64
  </div><?php
65
-
66
  // show site alerts widget
67
  if ($this->is_multisite() && $this->is_main_blog()) {
68
  $curr = $this->get_view_site_id();
@@ -100,7 +100,7 @@ class WSAL_AuditLogListView extends WP_List_Table
100
  </div><?php
101
  }
102
  }
103
-
104
  /**
105
  * @param int|null $limit Maximum number of sites to return (null = no limit).
106
  * @return object Object with keys: blog_id, blogname, domain
@@ -120,7 +120,7 @@ class WSAL_AuditLogListView extends WP_List_Table
120
  // return result
121
  return $res;
122
  }
123
-
124
  /**
125
  * @return int The number of sites on the network.
126
  */
@@ -131,52 +131,57 @@ class WSAL_AuditLogListView extends WP_List_Table
131
  return (int)$wpdb->get_var($sql);
132
  }
133
 
134
- public function get_columns()
135
- {
 
 
 
 
 
136
  $cols = array(
137
  //'cb' => '<input type="checkbox" />',
138
  //'read' => __('Read', 'wp-security-audit-log'),
139
- 'type' => __('Code', 'wp-security-audit-log'),
140
- 'code' => __('Type', 'wp-security-audit-log'),
141
- 'crtd' => __('Date', 'wp-security-audit-log'),
142
- 'user' => __('Username', 'wp-security-audit-log'),
143
- 'scip' => __('Source IP', 'wp-security-audit-log'),
144
  );
145
- if ($this->is_multisite() && $this->is_main_blog() && !$this->is_specific_view()) {
146
- $cols['site'] = __('Site', 'wp-security-audit-log');
147
  }
148
- $cols['mesg'] = __('Message', 'wp-security-audit-log');
149
  $sel_columns = $this->_plugin->settings->GetColumnsSelected();
150
- if (!empty($sel_columns)) {
151
- unset($cols);
152
- $sel_columns = (array)json_decode($sel_columns);
153
- foreach ($sel_columns as $key => $value) {
154
- switch ($key) {
155
  case 'alert_code':
156
- $cols['type'] = __('Code', 'wp-security-audit-log');
157
  break;
158
  case 'type':
159
- $cols['code'] = __('Type', 'wp-security-audit-log');
160
  break;
161
  case 'date':
162
- $cols['crtd'] = __('Date', 'wp-security-audit-log');
163
  break;
164
  case 'username':
165
- $cols['user'] = __('Username', 'wp-security-audit-log');
166
  break;
167
  case 'source_ip':
168
- $cols['scip'] = __('Source IP', 'wp-security-audit-log');
169
  break;
170
  case 'site':
171
- $cols['site'] = __('Site', 'wp-security-audit-log');
172
  break;
173
  case 'message':
174
- $cols['mesg'] = __('Message', 'wp-security-audit-log');
175
  break;
176
  }
177
  }
178
  }
179
- if ($this->_plugin->settings->IsDataInspectorEnabled()) {
180
  $cols['data'] = '';
181
  }
182
  return $cols;
@@ -199,12 +204,12 @@ class WSAL_AuditLogListView extends WP_List_Table
199
  'scip' => array('scip', false)
200
  );
201
  }
202
-
203
  public function column_default($item, $column_name)
204
  {
205
  //example: $item->getMetaValue('CurrentUserID')
206
  $datetimeFormat = $this->_plugin->settings->GetDatetimeFormat();
207
-
208
  switch ($column_name) {
209
  case 'read':
210
  return '<span class="log-read log-read-'
@@ -237,53 +242,94 @@ class WSAL_AuditLogListView extends WP_List_Table
237
  )
238
  ) : '<i>unknown</i>';
239
  case 'user':
240
- $username = $item->GetUsername();
241
- if ($username && ($user = get_user_by('login', $username))) {
242
- $image = get_avatar($user->ID, 32);
243
- $uhtml = '<a href="' . admin_url('user-edit.php?user_id=' . $user->ID)
244
- . '" target="_blank">' . esc_html($user->display_name) . '</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  $roles = $item->GetUserRoles();
246
- if (is_array($roles) && count($roles)) {
247
- $roles = __(esc_html(ucwords(implode(', ', $roles))));
248
- } else if (is_string($roles) && $roles != '') {
249
- $roles = __(esc_html(ucwords(str_replace(array("\"", "[", "]"), " ", $roles))));
250
  } else {
251
- $roles = '<i>' . __('Unknown', 'wp-security-audit-log') . '</i>';
252
  }
253
- } elseif ($username == 'Plugin') {
254
- $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/plugin-logo.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
255
- $uhtml = '<i>' . __('Plugin', 'wp-security-audit-log') . '</i>';
256
  $roles = '';
257
- } elseif ($username == 'Plugins') {
258
- $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
259
- $uhtml = '<i>' . __('Plugins', 'wp-security-audit-log') . '</i>';
260
  $roles = '';
261
- } elseif ($username == 'Website Visitor') {
262
- $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
263
- $uhtml = '<i>' . __('Website Visitor', 'wp-security-audit-log') . '</i>';
264
  $roles = '';
265
  } else {
266
- $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
267
- $uhtml = '<i>' . __('System', 'wp-security-audit-log') . '</i>';
268
  $roles = '';
269
  }
270
  return $image . $uhtml . '<br/>' . $roles;
271
  case 'scip':
272
  $scip = $item->GetSourceIP();
273
- if (is_string($scip)) {
274
- $scip = str_replace(array("\"", "[", "]"), "", $scip);
275
  }
276
- $oips = array(); //$item->GetOtherIPs();
 
 
277
  // if there's no IP...
278
- if (is_null($scip) || $scip == '') return '<i>unknown</i>';
 
 
 
279
  // if there's only one IP...
280
- $link = "http://whatismyipaddress.com/ip/" . $scip ."?utm_source=plugin&utm_medium=referral&utm_campaign=WPSAL";
281
- if (count($oips) < 2) return "<a target='_blank' href='$link'>". esc_html($scip) .'</a>';
 
 
 
 
 
 
 
 
 
 
 
282
  // if there are many IPs...
283
- $html = "<a target='_blank' href='http://whatismyipaddress.com/ip/$scip'>". esc_html($scip) .'</a>'.' <a href="javascript:;" onclick="jQuery(this).hide().next().show();">(more&hellip;)</a><div style="display: none;">';
284
- foreach ($oips as $ip) if($scip != $ip) $html .= '<div>' . $ip . '</div>';
285
- $html .= '</div>';
286
- return $html;
 
 
 
 
 
 
 
 
 
 
287
  case 'site':
288
  $info = get_blog_details($item->site_id, true);
289
  return !$info ? ('Unknown Site '.$item->site_id)
@@ -306,13 +352,13 @@ class WSAL_AuditLogListView extends WP_List_Table
306
  $result = strcmp($a->{$this->_orderby}, $b->{$this->_orderby});
307
  return ($this->_order === 'asc') ? $result : -$result;
308
  }
309
-
310
  public function reorder_items_int($a, $b)
311
  {
312
  $result = $a->{$this->_orderby} - $b->{$this->_orderby};
313
  return ($this->_order === 'asc') ? $result : -$result;
314
  }
315
-
316
  public function meta_formatter($name, $value)
317
  {
318
  switch (true) {
@@ -336,27 +382,27 @@ class WSAL_AuditLogListView extends WP_List_Table
336
 
337
  case $name == '%RevisionLink%':
338
  return ' Click <a target="_blank" href="'.esc_url($value).'">here</a> to see the content changes.';
339
-
340
  case $name == '%EditorLinkPost%':
341
  return ' <a target="_blank" href="'.esc_url($value).'">View the post</a>';
342
-
343
  case $name == '%EditorLinkPage%':
344
  return ' <a target="_blank" href="'.esc_url($value).'">View the page</a>';
345
-
346
  case $name == '%CategoryLink%':
347
  return ' <a target="_blank" href="'.esc_url($value).'">View the category</a>';
348
 
349
  case $name == '%EditorLinkForum%':
350
  return ' <a target="_blank" href="'.esc_url($value).'">View the forum</a>';
351
-
352
  case $name == '%EditorLinkTopic%':
353
  return ' <a target="_blank" href="'.esc_url($value).'">View the topic</a>';
354
-
355
  case in_array($name, array('%MetaValue%', '%MetaValueOld%', '%MetaValueNew%')):
356
  return '<strong>' . (
357
  strlen($value) > 50 ? (esc_html(substr($value, 0, 50)) . '&hellip;') : esc_html($value)
358
  ) . '</strong>';
359
-
360
  case $name == '%ClientIP%':
361
  if (is_string($value)) {
362
  return '<strong>' . str_replace(array("\"", "[", "]"), "", $value) . '</strong>';
@@ -374,32 +420,32 @@ class WSAL_AuditLogListView extends WP_List_Table
374
  case strncmp($value, 'http://', 7) === 0:
375
  case strncmp($value, 'https://', 7) === 0:
376
  return '<a href="' . esc_html($value) . '"' . ' title="' . esc_html($value) . '"' . ' target="_blank">' . esc_html($value) . '</a>';
377
-
378
  default:
379
  return '<strong>' . esc_html($value) . '</strong>';
380
  }
381
  }
382
-
383
  protected function is_multisite()
384
  {
385
  return $this->_plugin->IsMultisite();
386
  }
387
-
388
  protected function is_main_blog()
389
  {
390
  return get_current_blog_id() == 1;
391
  }
392
-
393
  protected function is_specific_view()
394
  {
395
  return isset($_REQUEST['wsal-cbid']) && $_REQUEST['wsal-cbid'] != '0';
396
  }
397
-
398
  protected function get_specific_view()
399
  {
400
  return isset($_REQUEST['wsal-cbid']) ? (int)$_REQUEST['wsal-cbid'] : 0;
401
  }
402
-
403
  protected function get_view_site_id()
404
  {
405
  switch (true) {
@@ -417,7 +463,7 @@ class WSAL_AuditLogListView extends WP_List_Table
417
  return get_current_blog_id();
418
  }
419
  }
420
-
421
  public function prepare_items()
422
  {
423
  if ($this->_plugin->settings->IsArchivingEnabled()) {
@@ -444,9 +490,9 @@ class WSAL_AuditLogListView extends WP_List_Table
444
  if ($bid) {
445
  $query->addCondition("site_id = %s ", $bid);
446
  }
447
-
448
  $query = apply_filters('wsal_auditlog_query', $query);
449
-
450
  $total_items = $query->getAdapter()->Count($query);
451
 
452
  if (empty($_REQUEST["orderby"])) {
15
  */
16
  protected $_plugin;
17
  protected $_gmt_offset_sec = 0;
18
+
19
  public function __construct($plugin)
20
  {
21
  $this->_plugin = $plugin;
22
+
23
  $timezone = $this->_plugin->settings->GetTimezone();
24
  if ($timezone) {
25
  $this->_gmt_offset_sec = get_option('gmt_offset') * HOUR_IN_SECONDS;
26
  } else {
27
  $this->_gmt_offset_sec = date('Z');
28
  }
29
+
30
  parent::__construct(array(
31
  'singular' => 'log',
32
  'plural' => 'logs',
39
  {
40
  _e('No events so far.', 'wp-security-audit-log');
41
  }
42
+
43
  public function extra_tablenav($which)
44
  {
45
  // items-per-page widget
48
  $items = array($o, 5, 10, 15, 30, 50);
49
  if (!in_array($p, $items)) $items[] = $p;
50
  if ($p == $o || $p == 0) $p = $o[1]; // a sane default if things goes bust
51
+
52
  ?><div class="wsal-ipp wsal-ipp-<?php echo $which; ?>">
53
  <?php _e('Show ', 'wp-security-audit-log'); ?>
54
  <select class="wsal-ipps" onfocus="WsalIppsFocus(value);" onchange="WsalIppsChange(value);">
62
  </select>
63
  <?php _e(' Items', 'wp-security-audit-log'); ?>
64
  </div><?php
65
+
66
  // show site alerts widget
67
  if ($this->is_multisite() && $this->is_main_blog()) {
68
  $curr = $this->get_view_site_id();
100
  </div><?php
101
  }
102
  }
103
+
104
  /**
105
  * @param int|null $limit Maximum number of sites to return (null = no limit).
106
  * @return object Object with keys: blog_id, blogname, domain
120
  // return result
121
  return $res;
122
  }
123
+
124
  /**
125
  * @return int The number of sites on the network.
126
  */
131
  return (int)$wpdb->get_var($sql);
132
  }
133
 
134
+ public function get_columns() {
135
+ $type_name = $this->_plugin->settings->get_type_username();
136
+ if ( 'display_name' === $type_name ) {
137
+ $name_column = __( 'User', 'wp-security-audit-log' );
138
+ } elseif ( 'username' === $type_name ) {
139
+ $name_column = __( 'Username', 'wp-security-audit-log' );
140
+ }
141
  $cols = array(
142
  //'cb' => '<input type="checkbox" />',
143
  //'read' => __('Read', 'wp-security-audit-log'),
144
+ 'type' => __( 'Code', 'wp-security-audit-log' ),
145
+ 'code' => __( 'Type', 'wp-security-audit-log' ),
146
+ 'crtd' => __( 'Date', 'wp-security-audit-log' ),
147
+ 'user' => $name_column,
148
+ 'scip' => __( 'Source IP', 'wp-security-audit-log' ),
149
  );
150
+ if ( $this->is_multisite() && $this->is_main_blog() && ! $this->is_specific_view() ) {
151
+ $cols['site'] = __( 'Site', 'wp-security-audit-log' );
152
  }
153
+ $cols['mesg'] = __( 'Message', 'wp-security-audit-log' );
154
  $sel_columns = $this->_plugin->settings->GetColumnsSelected();
155
+ if ( ! empty( $sel_columns ) ) {
156
+ unset( $cols );
157
+ $sel_columns = (array) json_decode( $sel_columns );
158
+ foreach ( $sel_columns as $key => $value ) {
159
+ switch ( $key ) {
160
  case 'alert_code':
161
+ $cols['type'] = __( 'Code', 'wp-security-audit-log' );
162
  break;
163
  case 'type':
164
+ $cols['code'] = __( 'Type', 'wp-security-audit-log' );
165
  break;
166
  case 'date':
167
+ $cols['crtd'] = __( 'Date', 'wp-security-audit-log' );
168
  break;
169
  case 'username':
170
+ $cols['user'] = $name_column;
171
  break;
172
  case 'source_ip':
173
+ $cols['scip'] = __( 'Source IP', 'wp-security-audit-log' );
174
  break;
175
  case 'site':
176
+ $cols['site'] = __( 'Site', 'wp-security-audit-log' );
177
  break;
178
  case 'message':
179
+ $cols['mesg'] = __( 'Message', 'wp-security-audit-log' );
180
  break;
181
  }
182
  }
183
  }
184
+ if ( $this->_plugin->settings->IsDataInspectorEnabled() ) {
185
  $cols['data'] = '';
186
  }
187
  return $cols;
204
  'scip' => array('scip', false)
205
  );
206
  }
207
+
208
  public function column_default($item, $column_name)
209
  {
210
  //example: $item->getMetaValue('CurrentUserID')
211
  $datetimeFormat = $this->_plugin->settings->GetDatetimeFormat();
212
+
213
  switch ($column_name) {
214
  case 'read':
215
  return '<span class="log-read log-read-'
242
  )
243
  ) : '<i>unknown</i>';
244
  case 'user':
245
+ $username = $item->GetUsername();
246
+ $type_name = $this->_plugin->settings->get_type_username();
247
+ if ( $username && ( $user = get_user_by( 'login', $username ) ) ) {
248
+ $image = get_avatar( $user->ID, 32 );
249
+ if ( 'display_name' == $type_name ) {
250
+ $display_name = $user->first_name . ' ' . $user->last_name;
251
+ } elseif ( 'username' == $type_name ) {
252
+ $display_name = $user->user_login;
253
+ }
254
+
255
+ if ( class_exists( 'WSAL_SearchExtension' ) ) {
256
+ $tooltip = esc_attr__( 'Show me all activity by this User', 'wp-security-audit-log' );
257
+
258
+ $uhtml = '<a class="search-user" data-tooltip="' . $tooltip . '" data-user="' . $user->user_login . '" href="' . admin_url( 'user-edit.php?user_id=' . $user->ID )
259
+ . '" target="_blank">' . esc_html( $display_name ) . '</a>';
260
+ } else {
261
+ $uhtml = '<a href="' . admin_url( 'user-edit.php?user_id=' . $user->ID )
262
+ . '" target="_blank">' . esc_html( $display_name ) . '</a>';
263
+ }
264
+
265
  $roles = $item->GetUserRoles();
266
+ if ( is_array( $roles ) && count( $roles ) ) {
267
+ $roles = esc_html( ucwords( implode( ', ', $roles ) ) );
268
+ } elseif ( is_string( $roles ) && $roles != '' ) {
269
+ $roles = esc_html( ucwords( str_replace( array( "\"", "[", "]" ), " ", $roles ) ) );
270
  } else {
271
+ $roles = '<i>' . __( 'Unknown', 'wp-security-audit-log' ) . '</i>';
272
  }
273
+ } elseif ( 'Plugin' == $username ) {
274
+ $image = '<img src="' . $this->_plugin->GetBaseUrl() . '/img/plugin-logo.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
275
+ $uhtml = '<i>' . __( 'Plugin', 'wp-security-audit-log' ) . '</i>';
276
  $roles = '';
277
+ } elseif ( 'Plugins' == $username ) {
278
+ $image = '<img src="' . $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
279
+ $uhtml = '<i>' . __( 'Plugins', 'wp-security-audit-log' ) . '</i>';
280
  $roles = '';
281
+ } elseif ( 'Website Visitor' == $username ) {
282
+ $image = '<img src="' . $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
283
+ $uhtml = '<i>' . __( 'Website Visitor', 'wp-security-audit-log' ) . '</i>';
284
  $roles = '';
285
  } else {
286
+ $image = '<img src="' . $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
287
+ $uhtml = '<i>' . __( 'System', 'wp-security-audit-log' ) . '</i>';
288
  $roles = '';
289
  }
290
  return $image . $uhtml . '<br/>' . $roles;
291
  case 'scip':
292
  $scip = $item->GetSourceIP();
293
+ if ( is_string( $scip ) ) {
294
+ $scip = str_replace( array( "\"", "[", "]" ), '', $scip );
295
  }
296
+
297
+ $oips = array(); // $item->GetOtherIPs();
298
+
299
  // if there's no IP...
300
+ if ( is_null( $scip ) || '' == $scip ) {
301
+ return '<i>unknown</i>';
302
+ }
303
+
304
  // if there's only one IP...
305
+ $link = 'http://whatismyipaddress.com/ip/' . $scip . '?utm_source=plugin&utm_medium=referral&utm_campaign=WPSAL';
306
+ if ( class_exists( 'WSAL_SearchExtension' ) ) {
307
+ $tooltip = esc_attr__( 'Show me all activity originating from this IP Address', 'wp-security-audit-log' );
308
+
309
+ if ( count( $oips ) < 2 ) {
310
+ return "<a class='search-ip' data-tooltip='$tooltip' data-ip='$scip' target='_blank' href='$link'>" . esc_html( $scip ) . '</a>';
311
+ }
312
+ } else {
313
+ if ( count( $oips ) < 2 ) {
314
+ return "<a target='_blank' href='$link'>" . esc_html( $scip ) . '</a>';
315
+ }
316
+ }
317
+
318
  // if there are many IPs...
319
+ if ( class_exists( 'WSAL_SearchExtension' ) ) {
320
+ $tooltip = esc_attr__( 'Show me all activity originating from this IP Address', 'wp-security-audit-log' );
321
+
322
+ $html = "<a class='search-ip' data-tooltip='$tooltip' data-ip='$scip' target='_blank' href='http://whatismyipaddress.com/ip/$scip'>" . esc_html( $scip ) . '</a> <a href="javascript:;" onclick="jQuery(this).hide().next().show();">(more&hellip;)</a><div style="display: none;">';
323
+ foreach ( $oips as $ip ) if ( $scip != $ip ) $html .= '<div>' . $ip . '</div>';
324
+ $html .= '</div>';
325
+ return $html;
326
+ } else {
327
+ $html = "<a target='_blank' href='http://whatismyipaddress.com/ip/$scip'>" . esc_html( $scip ) . '</a> <a href="javascript:;" onclick="jQuery(this).hide().next().show();">(more&hellip;)</a><div style="display: none;">';
328
+ foreach ( $oips as $ip ) if ( $scip != $ip ) $html .= '<div>' . $ip . '</div>';
329
+ $html .= '</div>';
330
+ return $html;
331
+ }
332
+
333
  case 'site':
334
  $info = get_blog_details($item->site_id, true);
335
  return !$info ? ('Unknown Site '.$item->site_id)
352
  $result = strcmp($a->{$this->_orderby}, $b->{$this->_orderby});
353
  return ($this->_order === 'asc') ? $result : -$result;
354
  }
355
+
356
  public function reorder_items_int($a, $b)
357
  {
358
  $result = $a->{$this->_orderby} - $b->{$this->_orderby};
359
  return ($this->_order === 'asc') ? $result : -$result;
360
  }
361
+
362
  public function meta_formatter($name, $value)
363
  {
364
  switch (true) {
382
 
383
  case $name == '%RevisionLink%':
384
  return ' Click <a target="_blank" href="'.esc_url($value).'">here</a> to see the content changes.';
385
+
386
  case $name == '%EditorLinkPost%':
387
  return ' <a target="_blank" href="'.esc_url($value).'">View the post</a>';
388
+
389
  case $name == '%EditorLinkPage%':
390
  return ' <a target="_blank" href="'.esc_url($value).'">View the page</a>';
391
+
392
  case $name == '%CategoryLink%':
393
  return ' <a target="_blank" href="'.esc_url($value).'">View the category</a>';
394
 
395
  case $name == '%EditorLinkForum%':
396
  return ' <a target="_blank" href="'.esc_url($value).'">View the forum</a>';
397
+
398
  case $name == '%EditorLinkTopic%':
399
  return ' <a target="_blank" href="'.esc_url($value).'">View the topic</a>';
400
+
401
  case in_array($name, array('%MetaValue%', '%MetaValueOld%', '%MetaValueNew%')):
402
  return '<strong>' . (
403
  strlen($value) > 50 ? (esc_html(substr($value, 0, 50)) . '&hellip;') : esc_html($value)
404
  ) . '</strong>';
405
+
406
  case $name == '%ClientIP%':
407
  if (is_string($value)) {
408
  return '<strong>' . str_replace(array("\"", "[", "]"), "", $value) . '</strong>';
420
  case strncmp($value, 'http://', 7) === 0:
421
  case strncmp($value, 'https://', 7) === 0:
422
  return '<a href="' . esc_html($value) . '"' . ' title="' . esc_html($value) . '"' . ' target="_blank">' . esc_html($value) . '</a>';
423
+
424
  default:
425
  return '<strong>' . esc_html($value) . '</strong>';
426
  }
427
  }
428
+
429
  protected function is_multisite()
430
  {
431
  return $this->_plugin->IsMultisite();
432
  }
433
+
434
  protected function is_main_blog()
435
  {
436
  return get_current_blog_id() == 1;
437
  }
438
+
439
  protected function is_specific_view()
440
  {
441
  return isset($_REQUEST['wsal-cbid']) && $_REQUEST['wsal-cbid'] != '0';
442
  }
443
+
444
  protected function get_specific_view()
445
  {
446
  return isset($_REQUEST['wsal-cbid']) ? (int)$_REQUEST['wsal-cbid'] : 0;
447
  }
448
+
449
  protected function get_view_site_id()
450
  {
451
  switch (true) {
463
  return get_current_blog_id();
464
  }
465
  }
466
+
467
  public function prepare_items()
468
  {
469
  if ($this->_plugin->settings->IsArchivingEnabled()) {
490
  if ($bid) {
491
  $query->addCondition("site_id = %s ", $bid);
492
  }
493
+
494
  $query = apply_filters('wsal_auditlog_query', $query);
495
+
496
  $total_items = $query->getAdapter()->Count($query);
497
 
498
  if (empty($_REQUEST["orderby"])) {
classes/Sensors/Content.php CHANGED
@@ -123,10 +123,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
123
  // to do change with 'create_term' instead 'create_category' for trigger Tags
124
  add_action('create_category', array($this, 'EventCategoryCreation'), 10, 1);
125
 
126
- add_filter('single_post_title', array($this, 'ViewingPost'), 10, 2);
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
@@ -146,7 +146,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
146
  return $typeCustom;
147
  }
148
  }
149
-
150
  /**
151
  * Triggered when a user accesses the admin area.
152
  */
@@ -157,7 +157,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
157
  // check for category changes
158
  $this->CheckCategoryDeletion();
159
  }
160
-
161
  /**
162
  * Retrieve Old data.
163
  * @global mixed $_POST post data
@@ -176,7 +176,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
176
  $this->_OldStky = in_array($postID, get_option('sticky_posts'));
177
  }
178
  }
179
-
180
  /**
181
  * Get the template path.
182
  * @param stdClass $post the post
@@ -231,9 +231,9 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
231
  if ($post->post_type == 'revision') {
232
  return;
233
  }
234
-
235
  $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
236
-
237
  WSAL_Sensors_Request::SetVars(array(
238
  '$newStatus' => $newStatus,
239
  '$oldStatus' => $oldStatus,
@@ -258,7 +258,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
258
  + $this->CheckTemplateChange($this->_OldTmpl, $this->GetPostTemplate($post), $post)
259
  + $this->CheckCategoriesChange($this->_OldCats, $this->GetPostCategories($post), $post)
260
  ;
261
-
262
  if (!$changes) {
263
  $changes = $this->CheckDateChange($this->_OldPost, $post);
264
  if (!$changes) {
@@ -275,7 +275,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
275
  }
276
  }
277
  }
278
-
279
  /**
280
  * Check post creation.
281
  * @global array $_POST
@@ -335,7 +335,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
335
  {
336
  $post = get_post($post_id);
337
  $event = $this->GetEventTypeForPostType($post, 2001, 2005, 2030);
338
-
339
  if ($event) {
340
  $editorLink = $this->GetEditorLink($newPost);
341
  $this->plugin->alerts->Trigger($event, array(
@@ -347,7 +347,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
347
  ));
348
  }
349
  }
350
-
351
  /**
352
  * Post permanently deleted.
353
  * @param integer $post_id post ID
@@ -371,13 +371,11 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
371
  'PostID' => $post->ID,
372
  'PostType' => $post->post_type,
373
  'PostTitle' => $post->post_title,
374
- 'PostUrl' => get_permalink($post->ID),
375
- $editorLink['name'] => $editorLink['value']
376
  ));
377
  }
378
  }
379
  }
380
-
381
  /**
382
  * Post moved to the trash.
383
  * @param integer $post_id post ID
@@ -398,7 +396,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
398
  $editorLink['name'] => $editorLink['value']
399
  ));
400
  }
401
-
402
  /**
403
  * Post restored from trash.
404
  * @param integer $post_id post ID
@@ -418,7 +416,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
418
  $editorLink['name'] => $editorLink['value']
419
  ));
420
  }
421
-
422
  /**
423
  * Post date changed.
424
  * @param stdClass $oldPost old post
@@ -470,7 +468,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
470
  }
471
  return 0;
472
  }
473
-
474
  /**
475
  * Categories changed.
476
  * @param array $oldCats old categories
@@ -497,7 +495,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
497
  }
498
  }
499
  }
500
-
501
  /**
502
  * Author changed.
503
  * @param stdClass $oldPost old post
@@ -523,7 +521,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
523
  return 1;
524
  }
525
  }
526
-
527
  /**
528
  * Status changed.
529
  * @param stdClass $oldPost old post
@@ -558,7 +556,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
558
  return 1;
559
  }
560
  }
561
-
562
  /**
563
  * Post parent changed.
564
  * @param stdClass $oldPost old post
@@ -584,7 +582,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
584
  }
585
  }
586
  }
587
-
588
  /**
589
  * Permalink changed.
590
  * @param string $oldLink old permalink
@@ -608,7 +606,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
608
  }
609
  return 0;
610
  }
611
-
612
  /**
613
  * Post visibility changed.
614
  * @param stdClass $oldPost old post
@@ -621,10 +619,10 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
621
  if ($oldStatus == 'draft' || $newStatus == 'draft') {
622
  return;
623
  }
624
-
625
  $oldVisibility = '';
626
  $newVisibility = '';
627
-
628
  if ($oldpost->post_password) {
629
  $oldVisibility = __('Password Protected', 'wp-security-audit-log');
630
  } elseif ($oldStatus == 'publish') {
@@ -632,7 +630,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
632
  } elseif ($oldStatus == 'private') {
633
  $oldVisibility = __('Private', 'wp-security-audit-log');
634
  }
635
-
636
  if ($newpost->post_password) {
637
  $newVisibility = __('Password Protected', 'wp-security-audit-log');
638
  } elseif ($newStatus == 'publish') {
@@ -640,7 +638,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
640
  } elseif ($newStatus == 'private') {
641
  $newVisibility = __('Private', 'wp-security-audit-log');
642
  }
643
-
644
  if ($oldVisibility && $newVisibility && ($oldVisibility != $newVisibility)) {
645
  $event = $this->GetEventTypeForPostType($oldpost, 2025, 2026, 2040);
646
  $editorLink = $this->GetEditorLink($oldpost);
@@ -655,7 +653,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
655
  return 1;
656
  }
657
  }
658
-
659
  /**
660
  * Post template changed.
661
  * @param string $oldTmpl old template path
@@ -682,7 +680,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
682
  }
683
  }
684
  }
685
-
686
  /**
687
  * Post sets as sticky changes.
688
  * @param string $oldTmpl old template path
@@ -704,7 +702,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
704
  return 1;
705
  }
706
  }
707
-
708
  /**
709
  * Post modified content.
710
  * @param integer $post_ID post ID
@@ -719,7 +717,7 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
719
  $changes = $this->CheckTitleChange($oldpost, $newpost);
720
  if (!$changes) {
721
  $contentChanged = $oldpost->post_content != $newpost->post_content; // TODO what about excerpts?
722
-
723
  if ($oldpost->post_modified != $newpost->post_modified) {
724
  $event = 0;
725
  // @see http://codex.wordpress.org/Class_Reference/WP_Query#Status_Parameters
@@ -891,11 +889,14 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
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
- {
898
- switch ($post->post_type) {
 
 
899
  case 'forum':
900
  case 'topic':
901
  case 'reply':
@@ -931,33 +932,32 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor
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
- {
939
- if (is_user_logged_in()) {
940
- if (!is_admin()) {
941
- if ($this->CheckOtherSensors($post)) {
942
- return $title;
 
943
  }
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)) {
951
- $event = $this->GetEventTypeForPostType($post, 2101, 2103, 2105);
952
- $this->plugin->alerts->Trigger($event, array(
953
- 'PostType' => $post->post_type,
954
  'PostTitle' => $post->post_title,
955
- 'PostUrl' => get_permalink($post->ID)
956
- ));
957
  }
958
  }
959
  }
960
- return $title;
961
  }
962
 
963
  /**
123
  // to do change with 'create_term' instead 'create_category' for trigger Tags
124
  add_action('create_category', array($this, 'EventCategoryCreation'), 10, 1);
125
 
126
+ add_action( 'wp_head', array( $this, 'ViewingPost' ), 10 );
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
146
  return $typeCustom;
147
  }
148
  }
149
+
150
  /**
151
  * Triggered when a user accesses the admin area.
152
  */
157
  // check for category changes
158
  $this->CheckCategoryDeletion();
159
  }
160
+
161
  /**
162
  * Retrieve Old data.
163
  * @global mixed $_POST post data
176
  $this->_OldStky = in_array($postID, get_option('sticky_posts'));
177
  }
178
  }
179
+
180
  /**
181
  * Get the template path.
182
  * @param stdClass $post the post
231
  if ($post->post_type == 'revision') {
232
  return;
233
  }
234
+
235
  $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
236
+
237
  WSAL_Sensors_Request::SetVars(array(
238
  '$newStatus' => $newStatus,
239
  '$oldStatus' => $oldStatus,
258
  + $this->CheckTemplateChange($this->_OldTmpl, $this->GetPostTemplate($post), $post)
259
  + $this->CheckCategoriesChange($this->_OldCats, $this->GetPostCategories($post), $post)
260
  ;
261
+
262
  if (!$changes) {
263
  $changes = $this->CheckDateChange($this->_OldPost, $post);
264
  if (!$changes) {
275
  }
276
  }
277
  }
278
+
279
  /**
280
  * Check post creation.
281
  * @global array $_POST
335
  {
336
  $post = get_post($post_id);
337
  $event = $this->GetEventTypeForPostType($post, 2001, 2005, 2030);
338
+
339
  if ($event) {
340
  $editorLink = $this->GetEditorLink($newPost);
341
  $this->plugin->alerts->Trigger($event, array(
347
  ));
348
  }
349
  }
350
+
351
  /**
352
  * Post permanently deleted.
353
  * @param integer $post_id post ID
371
  'PostID' => $post->ID,
372
  'PostType' => $post->post_type,
373
  'PostTitle' => $post->post_title,
 
 
374
  ));
375
  }
376
  }
377
  }
378
+
379
  /**
380
  * Post moved to the trash.
381
  * @param integer $post_id post ID
396
  $editorLink['name'] => $editorLink['value']
397
  ));
398
  }
399
+
400
  /**
401
  * Post restored from trash.
402
  * @param integer $post_id post ID
416
  $editorLink['name'] => $editorLink['value']
417
  ));
418
  }
419
+
420
  /**
421
  * Post date changed.
422
  * @param stdClass $oldPost old post
468
  }
469
  return 0;
470
  }
471
+
472
  /**
473
  * Categories changed.
474
  * @param array $oldCats old categories
495
  }
496
  }
497
  }
498
+
499
  /**
500
  * Author changed.
501
  * @param stdClass $oldPost old post
521
  return 1;
522
  }
523
  }
524
+
525
  /**
526
  * Status changed.
527
  * @param stdClass $oldPost old post
556
  return 1;
557
  }
558
  }
559
+
560
  /**
561
  * Post parent changed.
562
  * @param stdClass $oldPost old post
582
  }
583
  }
584
  }
585
+
586
  /**
587
  * Permalink changed.
588
  * @param string $oldLink old permalink
606
  }
607
  return 0;
608
  }
609
+
610
  /**
611
  * Post visibility changed.
612
  * @param stdClass $oldPost old post
619
  if ($oldStatus == 'draft' || $newStatus == 'draft') {
620
  return;
621
  }
622
+
623
  $oldVisibility = '';
624
  $newVisibility = '';
625
+
626
  if ($oldpost->post_password) {
627
  $oldVisibility = __('Password Protected', 'wp-security-audit-log');
628
  } elseif ($oldStatus == 'publish') {
630
  } elseif ($oldStatus == 'private') {
631
  $oldVisibility = __('Private', 'wp-security-audit-log');
632
  }
633
+
634
  if ($newpost->post_password) {
635
  $newVisibility = __('Password Protected', 'wp-security-audit-log');
636
  } elseif ($newStatus == 'publish') {
638
  } elseif ($newStatus == 'private') {
639
  $newVisibility = __('Private', 'wp-security-audit-log');
640
  }
641
+
642
  if ($oldVisibility && $newVisibility && ($oldVisibility != $newVisibility)) {
643
  $event = $this->GetEventTypeForPostType($oldpost, 2025, 2026, 2040);
644
  $editorLink = $this->GetEditorLink($oldpost);
653
  return 1;
654
  }
655
  }
656
+
657
  /**
658
  * Post template changed.
659
  * @param string $oldTmpl old template path
680
  }
681
  }
682
  }
683
+
684
  /**
685
  * Post sets as sticky changes.
686
  * @param string $oldTmpl old template path
702
  return 1;
703
  }
704
  }
705
+
706
  /**
707
  * Post modified content.
708
  * @param integer $post_ID post ID
717
  $changes = $this->CheckTitleChange($oldpost, $newpost);
718
  if (!$changes) {
719
  $contentChanged = $oldpost->post_content != $newpost->post_content; // TODO what about excerpts?
720
+
721
  if ($oldpost->post_modified != $newpost->post_modified) {
722
  $event = 0;
723
  // @see http://codex.wordpress.org/Class_Reference/WP_Query#Status_Parameters
889
  /**
890
  * Ignore post from BBPress, WooCommerce Plugin
891
  * Triggered on the Sensors
892
+ *
893
+ * @param stdClass $post the post.
894
  */
895
+ private function CheckOtherSensors( $post ) {
896
+ if ( empty( $post ) ) {
897
+ return false;
898
+ }
899
+ switch ( $post->post_type ) {
900
  case 'forum':
901
  case 'topic':
902
  case 'reply':
932
 
933
  /**
934
  * Alerts for Viewing of Posts, Pages and Custom Posts.
 
 
935
  */
936
+ public function ViewingPost() {
937
+ // Retrieve the current post object.
938
+ $post = get_queried_object();
939
+ if ( is_user_logged_in() ) {
940
+ if ( ! is_admin() ) {
941
+ if ( $this->CheckOtherSensors( $post ) ) {
942
+ return $post->post_title;
943
  }
944
+
945
+ $currentPath = $_SERVER['REQUEST_URI'];
946
+ if ( ! empty( $_SERVER['HTTP_REFERER'] )
947
+ && strpos( $_SERVER['HTTP_REFERER'], $currentPath ) !== false ) {
948
+ // Ignore this if we were on the same page so we avoid double audit entries.
949
+ return;
950
  }
951
+ if ( ! empty( $post->post_title ) ) {
952
+ $event = $this->GetEventTypeForPostType( $post, 2101, 2103, 2105 );
953
+ $this->plugin->alerts->Trigger( $event, array(
954
+ 'PostType' => $post->post_type,
955
  'PostTitle' => $post->post_title,
956
+ 'PostUrl' => get_permalink( $post->ID ),
957
+ ) );
958
  }
959
  }
960
  }
 
961
  }
962
 
963
  /**
classes/Sensors/MetaData.php CHANGED
@@ -1,8 +1,6 @@
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
@@ -16,299 +14,459 @@
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);
30
- add_action('update_post_meta', array($this, 'EventPostMetaUpdating'), 10, 3);
31
- add_action('updated_post_meta', array($this, 'EventPostMetaUpdated'), 10, 4);
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)) {
45
- return false;
46
- } else {
47
- return true;
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();
59
- if (in_array($custom, $customFields)) {
60
- return true;
61
- }
62
- foreach ($customFields as $field) {
63
- if (strpos($field, "*") !== false) {
64
- // wildcard str[any_character] when you enter (str*)
65
- if (substr($field, -1) == '*') {
66
- $field = rtrim($field, '*');
67
- if (preg_match("/^$field/", $custom)) {
68
- return true;
69
- }
70
- }
71
- // wildcard [any_character]str when you enter (*str)
72
- if (substr($field, 0, 1) == '*') {
73
- $field = ltrim($field, '*');
74
- if (preg_match("/$field$/", $custom)) {
75
- return true;
76
- }
77
- }
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)) {
96
- $editorLink = $this->GetEditorLink($post);
97
- switch ($post->post_type) {
98
- case 'page':
99
- $this->plugin->alerts->Trigger(2059, array(
100
- 'PostID' => $object_id,
101
- 'PostTitle' => $post->post_title,
102
- 'MetaKey' => $meta_key,
103
- 'MetaValue' => $meta_value,
104
- 'MetaLink' => $meta_key,
105
- $editorLink['name'] => $editorLink['value']
106
- ));
107
- break;
108
- case 'post':
109
- $this->plugin->alerts->Trigger(2053, array(
110
- 'PostID' => $object_id,
111
- 'PostTitle' => $post->post_title,
112
- 'MetaKey' => $meta_key,
113
- 'MetaValue' => $meta_value,
114
- 'MetaLink' => $meta_key,
115
- $editorLink['name'] => $editorLink['value']
116
- ));
117
- break;
118
- default:
119
- $this->plugin->alerts->Trigger(2056, array(
120
- 'PostID' => $object_id,
121
- 'PostTitle' => $post->post_title,
122
- 'PostType' => $post->post_type,
123
- 'MetaKey' => $meta_key,
124
- 'MetaValue' => $meta_value,
125
- 'MetaLink' => $meta_key,
126
- $editorLink['name'] => $editorLink['value']
127
- ));
128
- break;
129
- }
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';
139
- $this->old_meta[$meta_id] = (object)array(
140
- 'key' => ($meta = get_metadata_by_mid($meta_type, $meta_id)) ? $meta->meta_key : $meta_key,
141
- 'val' => get_metadata($meta_type, $object_id, $meta_key, true),
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)) {
157
- $editorLink = $this->GetEditorLink($post);
158
- if (isset($this->old_meta[$meta_id])) {
159
- // check change in meta key
160
- if ($this->old_meta[$meta_id]->key != $meta_key) {
161
- switch ($post->post_type) {
162
- case 'page':
163
- $this->plugin->alerts->Trigger(2064, array(
164
- 'PostID' => $object_id,
165
- 'PostTitle' => $post->post_title,
166
- 'MetaID' => $meta_id,
167
- 'MetaKeyNew' => $meta_key,
168
- 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
169
- 'MetaValue' => $meta_value,
170
- 'MetaLink' => $meta_key,
171
- $editorLink['name'] => $editorLink['value']
172
- ));
173
- break;
174
- case 'post':
175
- $this->plugin->alerts->Trigger(2062, array(
176
- 'PostID' => $object_id,
177
- 'PostTitle' => $post->post_title,
178
- 'MetaID' => $meta_id,
179
- 'MetaKeyNew' => $meta_key,
180
- 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
181
- 'MetaValue' => $meta_value,
182
- 'MetaLink' => $meta_key,
183
- $editorLink['name'] => $editorLink['value']
184
- ));
185
- break;
186
- default:
187
- $this->plugin->alerts->Trigger(2063, array(
188
- 'PostID' => $object_id,
189
- 'PostTitle' => $post->post_title,
190
- 'PostType' => $post->post_type,
191
- 'MetaID' => $meta_id,
192
- 'MetaKeyNew' => $meta_key,
193
- 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
194
- 'MetaValue' => $meta_value,
195
- 'MetaLink' => $smeta_key,
196
- $editorLink['name'] => $editorLink['value']
197
- ));
198
- break;
199
- }
200
- } else if ($this->old_meta[$meta_id]->val != $meta_value) { // check change in meta value
201
- switch ($post->post_type) {
202
- case 'page':
203
- $this->plugin->alerts->Trigger(2060, array(
204
- 'PostID' => $object_id,
205
- 'PostTitle' => $post->post_title,
206
- 'MetaID' => $meta_id,
207
- 'MetaKey' => $meta_key,
208
- 'MetaValueNew' => $meta_value,
209
- 'MetaValueOld' => $this->old_meta[$meta_id]->val,
210
- 'MetaLink' => $meta_key,
211
- $editorLink['name'] => $editorLink['value']
212
- ));
213
- break;
214
- case 'post':
215
- $this->plugin->alerts->Trigger(2054, array(
216
- 'PostID' => $object_id,
217
- 'PostTitle' => $post->post_title,
218
- 'MetaID' => $meta_id,
219
- 'MetaKey' => $meta_key,
220
- 'MetaValueNew' => $meta_value,
221
- 'MetaValueOld' => $this->old_meta[$meta_id]->val,
222
- 'MetaLink' => $meta_key,
223
- $editorLink['name'] => $editorLink['value']
224
- ));
225
- break;
226
- default:
227
- $this->plugin->alerts->Trigger(2057, array(
228
- 'PostID' => $object_id,
229
- 'PostTitle' => $post->post_title,
230
- 'PostType' => $post->post_type,
231
- 'MetaID' => $meta_id,
232
- 'MetaKey' => $meta_key,
233
- 'MetaValueNew' => $meta_value,
234
- 'MetaValueOld' => $this->old_meta[$meta_id]->val,
235
- 'MetaLink' => $meta_key,
236
- $editorLink['name'] => $editorLink['value']
237
- ));
238
- break;
239
- }
240
- }
241
- // remove old meta update data
242
- unset($this->old_meta[$meta_id]);
243
- }
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);
253
-
254
- $WPActions = array('delete-meta');
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(
264
- 'PostID' => $object_id,
265
- 'PostTitle' => $post->post_title,
266
- 'MetaID' => $meta_id,
267
- 'MetaKey' => $meta_key,
268
- 'MetaValue' => $meta_value,
269
- $editorLink['name'] => $editorLink['value']
270
- ));
271
- break;
272
- case 'post':
273
- $this->plugin->alerts->Trigger(2055, array(
274
- 'PostID' => $object_id,
275
- 'PostTitle' => $post->post_title,
276
- 'MetaID' => $meta_id,
277
- 'MetaKey' => $meta_key,
278
- 'MetaValue' => $meta_value,
279
- $editorLink['name'] => $editorLink['value']
280
- ));
281
- break;
282
- default:
283
- $this->plugin->alerts->Trigger(2058, array(
284
- 'PostID' => $object_id,
285
- 'PostTitle' => $post->post_title,
286
- 'PostType' => $post->post_type,
287
- 'MetaID' => $meta_id,
288
- 'MetaKey' => $meta_key,
289
- 'MetaValue' => $meta_value,
290
- $editorLink['name'] => $editorLink['value']
291
- ));
292
- break;
293
- }
294
- }
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';
306
- $name .= ($post->post_type == 'page') ? 'Page' : 'Post' ;
307
- $value = get_edit_post_link($post->ID);
308
- $aLink = array(
309
- 'name' => $name,
310
- 'value' => $value,
311
- );
312
- return $aLink;
313
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  }
1
  <?php
2
  /**
3
+ * Custom fields (posts, pages, custom posts and users) sensor.
 
 
4
  *
5
  * 2053 User created a custom field for a post
6
  * 2056 User created a custom field for a custom post type
14
  * 2055 User deleted a custom field from a post
15
  * 2058 User deleted a custom field from a custom post type
16
  * 2061 User deleted a custom field from a page
17
+ *
18
+ * @package Wsal
19
+ * @subpackage Sensors
20
+ * @since 1.0.0
21
  */
22
+ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
23
+
24
+ /**
25
+ * Array of meta data being updated.
26
+ *
27
+ * @var array
28
+ */
29
+ protected $old_meta = array();
30
+
31
+ /**
32
+ * Empty meta counter.
33
+ *
34
+ * @var int
35
+ */
36
+ private $null_meta_counter = 0;
37
+
38
+ /**
39
+ * Listening to events using WP hooks.
40
+ */
41
+ public function HookEvents() {
42
+ add_action( 'add_post_meta', array( $this, 'EventPostMetaCreated' ), 10, 3 );
43
+ add_action( 'update_post_meta', array( $this, 'EventPostMetaUpdating' ), 10, 3 );
44
+ add_action( 'updated_post_meta', array( $this, 'EventPostMetaUpdated' ), 10, 4 );
45
+ add_action( 'deleted_post_meta', array( $this, 'EventPostMetaDeleted' ), 10, 4 );
46
+ add_action( 'save_post', array( $this, 'reset_null_meta_counter' ), 10 );
47
+
48
+ add_action( 'add_user_meta', array( $this, 'event_user_meta_created' ), 10, 3 );
49
+ add_action( 'update_user_meta', array( $this, 'event_user_meta_updating' ), 10, 3 );
50
+ add_action( 'updated_user_meta', array( $this, 'event_user_meta_updated' ), 10, 4 );
51
+ add_action( 'user_register', array( $this, 'reset_null_meta_counter' ), 10 );
52
+ }
53
+
54
+ /**
55
+ * Check "Excluded Custom Fields" or meta keys starts with "_".
56
+ *
57
+ * @param int $object_id - Object ID.
58
+ * @param string $meta_key - Meta key.
59
+ * @return boolean can log true|false
60
+ */
61
+ protected function CanLogMetaKey( $object_id, $meta_key ) {
62
+ // Check if excluded meta key or starts with _.
63
+ if ( substr( $meta_key, 0, 1 ) == '_' ) {
64
+ return false;
65
+ } elseif ( $this->IsExcludedCustomFields( $meta_key ) ) {
66
+ return false;
67
+ } else {
68
+ return true;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Check "Excluded Custom Fields".
74
+ * Used in the above function.
75
+ *
76
+ * @param string $custom - Custom meta key.
77
+ * @return boolean is excluded from monitoring true|false
78
+ */
79
+ public function IsExcludedCustomFields( $custom ) {
80
+ $customFields = $this->plugin->settings->GetExcludedMonitoringCustom();
81
+ if ( in_array( $custom, $customFields ) ) {
82
+ return true;
83
+ }
84
+ foreach ( $customFields as $field ) {
85
+ if ( false !== strpos( $field, "*" ) ) {
86
+ // wildcard str[any_character] when you enter (str*)
87
+ if ( substr( $field, -1 ) == '*') {
88
+ $field = rtrim( $field, '*' );
89
+ if ( preg_match( "/^$field/", $custom ) ) {
90
+ return true;
91
+ }
92
+ }
93
+ // Wildcard [any_character]str when you enter (*str).
94
+ if ( '*' == substr( $field, 0, 1 ) ) {
95
+ $field = ltrim( $field, '*' );
96
+ if ( preg_match( "/$field$/", $custom ) ) {
97
+ return true;
98
+ }
99
+ }
100
+ }
101
+ }
102
+ return false;
103
+ // return (in_array($custom, $customFields)) ? true : false;
104
+ }
105
+
106
+ /**
107
+ * Created a custom field.
108
+ *
109
+ * @param int $object_id - Object ID.
110
+ * @param string $meta_key - Meta key.
111
+ * @param mix $meta_value - Meta value.
112
+ */
113
+ public function EventPostMetaCreated( $object_id, $meta_key, $meta_value ) {
114
+ $post = get_post( $object_id );
115
+ if ( ! $this->CanLogMetaKey( $object_id, $meta_key ) || is_array( $meta_value ) ) {
116
+ return;
117
+ }
118
+
119
+ if ( 'revision' == $post->post_type ) {
120
+ return;
121
+ }
122
+
123
+ if ( empty( $meta_value ) && ( $this->null_meta_counter < 1 ) ) { // Report only one NULL meta value.
124
+ $this->null_meta_counter += 1;
125
+ } else { // Do not report if NULL meta values are more than one.
126
+ return;
127
+ }
128
+
129
+ $wp_action = array( 'add-meta' );
130
+
131
+ if ( isset( $_POST['action'] ) && ( 'editpost' == $_POST['action'] || in_array( $_POST['action'], $wp_action ) ) ) {
132
+ $editorLink = $this->GetEditorLink( $post );
133
+ switch ( $post->post_type ) {
134
+ case 'page':
135
+ $this->plugin->alerts->Trigger( 2059, array(
136
+ 'PostID' => $object_id,
137
+ 'PostTitle' => $post->post_title,
138
+ 'MetaKey' => $meta_key,
139
+ 'MetaValue' => $meta_value,
140
+ 'MetaLink' => $meta_key,
141
+ $editorLink['name'] => $editorLink['value'],
142
+ ) );
143
+ break;
144
+ case 'post':
145
+ $this->plugin->alerts->Trigger( 2053, array(
146
+ 'PostID' => $object_id,
147
+ 'PostTitle' => $post->post_title,
148
+ 'MetaKey' => $meta_key,
149
+ 'MetaValue' => $meta_value,
150
+ 'MetaLink' => $meta_key,
151
+ $editorLink['name'] => $editorLink['value'],
152
+ ) );
153
+ break;
154
+ default:
155
+ $this->plugin->alerts->Trigger( 2056, array(
156
+ 'PostID' => $object_id,
157
+ 'PostTitle' => $post->post_title,
158
+ 'PostType' => $post->post_type,
159
+ 'MetaKey' => $meta_key,
160
+ 'MetaValue' => $meta_value,
161
+ 'MetaLink' => $meta_key,
162
+ $editorLink['name'] => $editorLink['value'],
163
+ ) );
164
+ break;
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Sets the old meta.
171
+ *
172
+ * @param int $meta_id - Meta ID.
173
+ * @param int $object_id - Object ID.
174
+ * @param string $meta_key - Meta key.
175
+ */
176
+ public function EventPostMetaUpdating( $meta_id, $object_id, $meta_key ) {
177
+ static $meta_type = 'post';
178
+ $this->old_meta[ $meta_id ] = (object) array(
179
+ 'key' => ( $meta = get_metadata_by_mid( $meta_type, $meta_id ) ) ? $meta->meta_key : $meta_key,
180
+ 'val' => get_metadata( $meta_type, $object_id, $meta_key, true ),
181
+ );
182
+ }
183
+
184
+ /**
185
+ * Updated a custom field name/value.
186
+ *
187
+ * @param int $meta_id - Meta ID.
188
+ * @param int $object_id - Object ID.
189
+ * @param string $meta_key - Meta key.
190
+ * @param mix $meta_value - Meta value.
191
+ */
192
+ public function EventPostMetaUpdated( $meta_id, $object_id, $meta_key, $meta_value ) {
193
+ $post = get_post( $object_id );
194
+ if ( ! $this->CanLogMetaKey( $object_id, $meta_key ) || is_array( $meta_value ) ) {
195
+ return;
196
+ }
197
+
198
+ if ( 'revision' == $post->post_type ) {
199
+ return;
200
+ }
201
+
202
+ $wp_action = array( 'add-meta' );
203
+
204
+ if ( isset( $_POST['action'] ) && ( 'editpost' == $_POST['action'] || in_array( $_POST['action'], $wp_action ) ) ) {
205
+ $editorLink = $this->GetEditorLink( $post );
206
+ if ( isset( $this->old_meta[ $meta_id ] ) ) {
207
+ // Check change in meta key.
208
+ if ( $this->old_meta[ $meta_id ]->key != $meta_key ) {
209
+ switch ( $post->post_type ) {
210
+ case 'page':
211
+ $this->plugin->alerts->Trigger( 2064, array(
212
+ 'PostID' => $object_id,
213
+ 'PostTitle' => $post->post_title,
214
+ 'MetaID' => $meta_id,
215
+ 'MetaKeyNew' => $meta_key,
216
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
217
+ 'MetaValue' => $meta_value,
218
+ 'MetaLink' => $meta_key,
219
+ $editorLink['name'] => $editorLink['value'],
220
+ ) );
221
+ break;
222
+ case 'post':
223
+ $this->plugin->alerts->Trigger( 2062, array(
224
+ 'PostID' => $object_id,
225
+ 'PostTitle' => $post->post_title,
226
+ 'MetaID' => $meta_id,
227
+ 'MetaKeyNew' => $meta_key,
228
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
229
+ 'MetaValue' => $meta_value,
230
+ 'MetaLink' => $meta_key,
231
+ $editorLink['name'] => $editorLink['value'],
232
+ ) );
233
+ break;
234
+ default:
235
+ $this->plugin->alerts->Trigger( 2063, array(
236
+ 'PostID' => $object_id,
237
+ 'PostTitle' => $post->post_title,
238
+ 'PostType' => $post->post_type,
239
+ 'MetaID' => $meta_id,
240
+ 'MetaKeyNew' => $meta_key,
241
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
242
+ 'MetaValue' => $meta_value,
243
+ 'MetaLink' => $smeta_key,
244
+ $editorLink['name'] => $editorLink['value'],
245
+ ) );
246
+ break;
247
+ }
248
+ } elseif ( $this->old_meta[ $meta_id ]->val != $meta_value ) { // Check change in meta value.
249
+ switch ( $post->post_type ) {
250
+ case 'page':
251
+ $this->plugin->alerts->Trigger( 2060, array(
252
+ 'PostID' => $object_id,
253
+ 'PostTitle' => $post->post_title,
254
+ 'MetaID' => $meta_id,
255
+ 'MetaKey' => $meta_key,
256
+ 'MetaValueNew' => $meta_value,
257
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
258
+ 'MetaLink' => $meta_key,
259
+ $editorLink['name'] => $editorLink['value'],
260
+ ) );
261
+ break;
262
+ case 'post':
263
+ $this->plugin->alerts->Trigger( 2054, array(
264
+ 'PostID' => $object_id,
265
+ 'PostTitle' => $post->post_title,
266
+ 'MetaID' => $meta_id,
267
+ 'MetaKey' => $meta_key,
268
+ 'MetaValueNew' => $meta_value,
269
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
270
+ 'MetaLink' => $meta_key,
271
+ $editorLink['name'] => $editorLink['value'],
272
+ ) );
273
+ break;
274
+ default:
275
+ $this->plugin->alerts->Trigger( 2057, array(
276
+ 'PostID' => $object_id,
277
+ 'PostTitle' => $post->post_title,
278
+ 'PostType' => $post->post_type,
279
+ 'MetaID' => $meta_id,
280
+ 'MetaKey' => $meta_key,
281
+ 'MetaValueNew' => $meta_value,
282
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
283
+ 'MetaLink' => $meta_key,
284
+ $editorLink['name'] => $editorLink['value'],
285
+ ) );
286
+ break;
287
+ }
288
+ }
289
+ // Remove old meta update data.
290
+ unset( $this->old_meta[ $meta_id ] );
291
+ }
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Deleted a custom field.
297
+ *
298
+ * @param int $meta_ids - Meta IDs.
299
+ * @param int $object_id - Object ID.
300
+ * @param string $meta_key - Meta key.
301
+ * @param mix $meta_value - Meta value.
302
+ */
303
+ public function EventPostMetaDeleted( $meta_ids, $object_id, $meta_key, $meta_value ) {
304
+
305
+ // If meta key starts with "_" then return.
306
+ if ( '_' == substr( $meta_key, 0, 1 ) ) {
307
+ return;
308
+ }
309
+
310
+ $post = get_post( $object_id );
311
+
312
+ $wp_action = array( 'delete-meta' );
313
+
314
+ if ( isset( $_POST['action'] ) && in_array( $_POST['action'], $wp_action ) ) {
315
+ $editorLink = $this->GetEditorLink( $post );
316
+ foreach ( $meta_ids as $meta_id ) {
317
+ if ( ! $this->CanLogMetaKey( $object_id, $meta_key ) ) {
318
+ continue;
319
+ }
320
+ switch ( $post->post_type ) {
321
+ case 'page':
322
+ $this->plugin->alerts->Trigger( 2061, array(
323
+ 'PostID' => $object_id,
324
+ 'PostTitle' => $post->post_title,
325
+ 'MetaID' => $meta_id,
326
+ 'MetaKey' => $meta_key,
327
+ 'MetaValue' => $meta_value,
328
+ $editorLink['name'] => $editorLink['value'],
329
+ ) );
330
+ break;
331
+ case 'post':
332
+ $this->plugin->alerts->Trigger( 2055, array(
333
+ 'PostID' => $object_id,
334
+ 'PostTitle' => $post->post_title,
335
+ 'MetaID' => $meta_id,
336
+ 'MetaKey' => $meta_key,
337
+ 'MetaValue' => $meta_value,
338
+ $editorLink['name'] => $editorLink['value'],
339
+ ) );
340
+ break;
341
+ default:
342
+ $this->plugin->alerts->Trigger( 2058, array(
343
+ 'PostID' => $object_id,
344
+ 'PostTitle' => $post->post_title,
345
+ 'PostType' => $post->post_type,
346
+ 'MetaID' => $meta_id,
347
+ 'MetaKey' => $meta_key,
348
+ 'MetaValue' => $meta_value,
349
+ $editorLink['name'] => $editorLink['value'],
350
+ ) );
351
+ break;
352
+ }
353
+ }
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Method: Reset Null Meta Counter.
359
+ *
360
+ * @since 2.6.5
361
+ */
362
+ public function reset_null_meta_counter() {
363
+ $this->null_meta_counter = 0;
364
+ }
365
+
366
+ /**
367
+ * Get editor link.
368
+ *
369
+ * @param stdClass $post the post.
370
+ * @return array $aLink name and value link
371
+ */
372
+ private function GetEditorLink( $post ) {
373
+ $name = 'EditorLink';
374
+ $name .= ( 'page' == $post->post_type ) ? 'Page' : 'Post';
375
+ $value = get_edit_post_link( $post->ID );
376
+ $aLink = array(
377
+ 'name' => $name,
378
+ 'value' => $value,
379
+ );
380
+ return $aLink;
381
+ }
382
+
383
+ /**
384
+ * Create a custom field name/value.
385
+ *
386
+ * @param int $object_id - Object ID.
387
+ * @param string $meta_key - Meta key.
388
+ * @param mix $meta_value - Meta value.
389
+ */
390
+ public function event_user_meta_created( $object_id, $meta_key, $meta_value ) {
391
+
392
+ // Get user.
393
+ $user = get_user_by( 'ID', $object_id );
394
+
395
+ // Check to see if we can log the meta key.
396
+ if ( ! $this->CanLogMetaKey( $object_id, $meta_key ) || is_array( $meta_value ) ) {
397
+ return;
398
+ }
399
+
400
+ if ( empty( $meta_value ) && ( $this->null_meta_counter < 1 ) ) { // Report only one NULL meta value.
401
+ $this->null_meta_counter += 1;
402
+ } else { // Do not report if NULL meta values are more than one.
403
+ return;
404
+ }
405
+
406
+ // Get POST array.
407
+ $post_array = $_POST;
408
+
409
+ // If update action is set then trigger the alert.
410
+ if ( isset( $post_array['action'] ) && ( 'update' == $post_array['action'] || 'createuser' == $post_array['action'] ) ) {
411
+ $this->plugin->alerts->Trigger( 4016, array(
412
+ 'TargetUsername' => $user->user_login,
413
+ 'custom_field_name' => $meta_key,
414
+ 'new_value' => $meta_value,
415
+ ) );
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Sets the old meta.
421
+ *
422
+ * @param int $meta_id - Meta ID.
423
+ * @param int $object_id - Object ID.
424
+ * @param string $meta_key - Meta key.
425
+ */
426
+ public function event_user_meta_updating( $meta_id, $object_id, $meta_key ) {
427
+ static $meta_type = 'user';
428
+ $this->old_meta[ $meta_id ] = (object) array(
429
+ 'key' => ( $meta = get_metadata_by_mid( $meta_type, $meta_id ) ) ? $meta->meta_key : $meta_key,
430
+ 'val' => get_metadata( $meta_type, $object_id, $meta_key, true ),
431
+ );
432
+ }
433
+
434
+ /**
435
+ * Updated a custom field name/value.
436
+ *
437
+ * @param int $meta_id - Meta ID.
438
+ * @param int $object_id - Object ID.
439
+ * @param string $meta_key - Meta key.
440
+ * @param mix $meta_value - Meta value.
441
+ */
442
+ public function event_user_meta_updated( $meta_id, $object_id, $meta_key, $meta_value ) {
443
+
444
+ // Get user.
445
+ $user = get_user_by( 'ID', $object_id );
446
+
447
+ // Check to see if we can log the meta key.
448
+ if ( ! $this->CanLogMetaKey( $object_id, $meta_key ) || is_array( $meta_value ) ) {
449
+ return;
450
+ }
451
+
452
+ // Get POST array.
453
+ $post_array = $_POST;
454
+
455
+ // If update action is set then trigger the alert.
456
+ if ( isset( $post_array['action'] ) && 'update' == $post_array['action'] ) {
457
+ if ( isset( $this->old_meta[ $meta_id ] ) ) {
458
+ // Check change in meta value.
459
+ if ( $this->old_meta[ $meta_id ]->val != $meta_value ) {
460
+ $this->plugin->alerts->Trigger( 4015, array(
461
+ 'TargetUsername' => $user->user_login,
462
+ 'custom_field_name' => $meta_key,
463
+ 'new_value' => $meta_value,
464
+ 'old_value' => $this->old_meta[ $meta_id ]->val,
465
+ ) );
466
+ }
467
+ // Remove old meta update data.
468
+ unset( $this->old_meta[ $meta_id ] );
469
+ }
470
+ }
471
+ }
472
  }
classes/Sensors/System.php CHANGED
@@ -609,51 +609,51 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor {
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 {
@@ -673,7 +673,7 @@ class WSAL_Sensors_System extends WSAL_AbstractSensor {
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' ) ) {
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 ( '127.0.0.1' == $ip || '::1' == $ip ) {
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 = '6007_' . date( 'Ymd' ) . '.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 {
673
 
674
  // Check directory.
675
  if ( $this->CheckDirectory( $uploadsDirPath ) ) {
676
+ $filename = '6023_' . date( 'Ymd' ) . '.log';
677
  $fp = $uploadsDirPath . $filename;
678
  $nameFile = $uploadsURL . $filename;
679
  if ( ! $file = fopen( $fp, 'a' ) ) {
classes/Settings.php CHANGED
@@ -817,6 +817,23 @@ class WSAL_Settings
817
  return $this->_plugin->SetGlobalOption('timezone', $newvalue);
818
  }
819
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
820
  public function GetAdapterConfig($name_field)
821
  {
822
  return $this->_plugin->GetGlobalOption($name_field);
817
  return $this->_plugin->SetGlobalOption('timezone', $newvalue);
818
  }
819
 
820
+ /**
821
+ * Get type of username to display
822
+ */
823
+ public function get_type_username() {
824
+ return $this->_plugin->GetGlobalOption( 'type_username', 'display_name' );
825
+ }
826
+
827
+ /**
828
+ * Set type of username to display
829
+ *
830
+ * @param string $newvalue - New value variable.
831
+ * @since 2.6.5
832
+ */
833
+ public function set_type_username( $newvalue ) {
834
+ return $this->_plugin->SetGlobalOption( 'type_username', $newvalue );
835
+ }
836
+
837
  public function GetAdapterConfig($name_field)
838
  {
839
  return $this->_plugin->GetGlobalOption($name_field);
classes/Views/AuditLog.php CHANGED
@@ -13,7 +13,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
13
  protected $_listview;
14
 
15
  protected $_version;
16
-
17
  public function __construct(WpSecurityAuditLog $plugin)
18
  {
19
  parent::__construct($plugin);
@@ -48,34 +48,34 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
48
  }
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)) {
@@ -83,44 +83,74 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
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
  }
92
-
93
  $this->GetListView()->prepare_items();
94
  $occ = new WSAL_Models_Occurrence();
95
-
96
  ?><form id="audit-log-viewer" method="post">
97
  <div id="audit-log-viewer-content">
98
- <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
99
- <input type="hidden" id="wsal-cbid" name="wsal-cbid" value="<?php echo esc_attr(isset($_REQUEST['wsal-cbid']) ? $_REQUEST['wsal-cbid'] : '0'); ?>" />
100
- <?php do_action('wsal_auditlog_before_view', $this->GetListView()); ?>
101
  <?php $this->GetListView()->display(); ?>
102
- <?php do_action('wsal_auditlog_after_view', $this->GetListView()); ?>
103
  </div>
104
- </form><?php
105
-
106
- ?><script type="text/javascript">
107
- jQuery(document).ready(function(){
108
- WsalAuditLogInit(<?php echo json_encode(array(
109
- 'ajaxurl' => admin_url('admin-ajax.php'),
110
- 'tr8n' => array(
111
- 'numofitems' => __('Please enter the number of alerts you would like to see on one page:', 'wp-security-audit-log'),
112
- 'searchback' => __('All Sites', 'wp-security-audit-log'),
113
- 'searchnone' => __('No Results', 'wp-security-audit-log'),
114
- ),
115
- 'autorefresh' => array(
116
- 'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
117
- 'token' => (int)$occ->Count(),
118
- ),
119
- )); ?>);
120
- });
121
- </script><?php
122
- }
123
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  public function AjaxInspector()
125
  {
126
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
@@ -146,7 +176,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
146
  echo '</body></html>';
147
  die;
148
  }
149
-
150
  public function AjaxRefresh()
151
  {
152
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
@@ -155,7 +185,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
155
  if (!isset($_REQUEST['logcount'])) {
156
  die('Log count parameter expected.');
157
  }
158
-
159
  $old = (int)$_REQUEST['logcount'];
160
  $max = 40; // 40*500msec = 20sec
161
 
@@ -166,13 +196,13 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
166
  $is_archive = true;
167
  }
168
  }
169
-
170
  do {
171
  $occ = new WSAL_Models_Occurrence();
172
  $new = $occ->Count();
173
  usleep(500000); // 500msec
174
  } while (($old == $new) && (--$max > 0));
175
-
176
  if ($is_archive) {
177
  echo 'false';
178
  } else {
@@ -180,7 +210,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
180
  }
181
  die;
182
  }
183
-
184
  public function AjaxSetIpp()
185
  {
186
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
@@ -192,7 +222,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
192
  $this->_plugin->settings->SetViewPerPage((int)$_REQUEST['count']);
193
  die;
194
  }
195
-
196
  public function AjaxSearchSite()
197
  {
198
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
@@ -203,9 +233,9 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
203
  }
204
  $grp1 = array();
205
  $grp2 = array();
206
-
207
  $search = $_REQUEST['search'];
208
-
209
  foreach ($this->GetListView()->get_sites() as $site) {
210
  if (stripos($site->blogname, $search) !== false) {
211
  $grp1[] = $site;
@@ -222,7 +252,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
222
  set_transient('wsal_wp_selected_db', $_REQUEST['selected_db'], HOUR_IN_SECONDS);
223
  }
224
  }
225
-
226
  public function Header()
227
  {
228
  add_thickbox();
@@ -234,7 +264,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView
234
  filemtime($this->_plugin->GetBaseDir() . '/css/auditlog.css')
235
  );
236
  }
237
-
238
  public function Footer()
239
  {
240
  wp_enqueue_script('jquery');
13
  protected $_listview;
14
 
15
  protected $_version;
16
+
17
  public function __construct(WpSecurityAuditLog $plugin)
18
  {
19
  parent::__construct($plugin);
48
  }
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)) {
83
  }
84
  return $this->_listview;
85
  }
86
+
87
+ /**
88
+ * Render view table of Audit Log.
89
+ *
90
+ * @since 1.0.0
91
+ */
92
+ public function Render() {
93
+ if ( ! $this->_plugin->settings->CurrentUserCan( 'view' ) ) {
94
+ wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wp-security-audit-log' ) );
95
  }
96
+
97
  $this->GetListView()->prepare_items();
98
  $occ = new WSAL_Models_Occurrence();
99
+
100
  ?><form id="audit-log-viewer" method="post">
101
  <div id="audit-log-viewer-content">
102
+ <input type="hidden" name="page" value="<?php echo esc_attr( $_REQUEST['page'] ); ?>" />
103
+ <input type="hidden" id="wsal-cbid" name="wsal-cbid" value="<?php echo esc_attr( isset( $_REQUEST['wsal-cbid'] ) ? $_REQUEST['wsal-cbid'] : '0' ); ?>" />
104
+ <?php do_action( 'wsal_auditlog_before_view', $this->GetListView() ); ?>
105
  <?php $this->GetListView()->display(); ?>
106
+ <?php do_action( 'wsal_auditlog_after_view', $this->GetListView() ); ?>
107
  </div>
108
+ </form>
109
+
110
+ <?php if ( class_exists( 'WSAL_SearchExtension' ) &&
111
+ ( isset( $_REQUEST['Filters'] ) || ( isset( $_REQUEST['s'] ) && trim( $_REQUEST['s'] ) ) ) ) : ?>
112
+ <script type="text/javascript">
113
+ jQuery(document).ready( function() {
114
+ WsalAuditLogInit(
115
+ <?php echo json_encode( array(
116
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
117
+ 'tr8n' => array(
118
+ 'numofitems' => __( 'Please enter the number of alerts you would like to see on one page:', 'wp-security-audit-log' ),
119
+ 'searchback' => __( 'All Sites', 'wp-security-audit-log' ),
120
+ 'searchnone' => __( 'No Results', 'wp-security-audit-log' ),
121
+ ),
122
+ 'autorefresh' => array(
123
+ 'enabled' => false,
124
+ 'token' => (int) $occ->Count(),
125
+ ),
126
+ ) );
127
+ ?>
128
+ );
129
+ } );
130
+ </script>
131
+ <?php else : ?>
132
+ <script type="text/javascript">
133
+ jQuery(document).ready( function() {
134
+ WsalAuditLogInit(
135
+ <?php echo json_encode( array(
136
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
137
+ 'tr8n' => array(
138
+ 'numofitems' => __( 'Please enter the number of alerts you would like to see on one page:', 'wp-security-audit-log' ),
139
+ 'searchback' => __( 'All Sites', 'wp-security-audit-log' ),
140
+ 'searchnone' => __( 'No Results', 'wp-security-audit-log' ),
141
+ ),
142
+ 'autorefresh' => array(
143
+ 'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
144
+ 'token' => (int) $occ->Count(),
145
+ ),
146
+ ) );
147
+ ?>
148
+ );
149
+ } );
150
+ </script>
151
+ <?php endif;
152
+ }
153
+
154
  public function AjaxInspector()
155
  {
156
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
176
  echo '</body></html>';
177
  die;
178
  }
179
+
180
  public function AjaxRefresh()
181
  {
182
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
185
  if (!isset($_REQUEST['logcount'])) {
186
  die('Log count parameter expected.');
187
  }
188
+
189
  $old = (int)$_REQUEST['logcount'];
190
  $max = 40; // 40*500msec = 20sec
191
 
196
  $is_archive = true;
197
  }
198
  }
199
+
200
  do {
201
  $occ = new WSAL_Models_Occurrence();
202
  $new = $occ->Count();
203
  usleep(500000); // 500msec
204
  } while (($old == $new) && (--$max > 0));
205
+
206
  if ($is_archive) {
207
  echo 'false';
208
  } else {
210
  }
211
  die;
212
  }
213
+
214
  public function AjaxSetIpp()
215
  {
216
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
222
  $this->_plugin->settings->SetViewPerPage((int)$_REQUEST['count']);
223
  die;
224
  }
225
+
226
  public function AjaxSearchSite()
227
  {
228
  if (!$this->_plugin->settings->CurrentUserCan('view')) {
233
  }
234
  $grp1 = array();
235
  $grp2 = array();
236
+
237
  $search = $_REQUEST['search'];
238
+
239
  foreach ($this->GetListView()->get_sites() as $site) {
240
  if (stripos($site->blogname, $search) !== false) {
241
  $grp1[] = $site;
252
  set_transient('wsal_wp_selected_db', $_REQUEST['selected_db'], HOUR_IN_SECONDS);
253
  }
254
  }
255
+
256
  public function Header()
257
  {
258
  add_thickbox();
264
  filemtime($this->_plugin->GetBaseDir() . '/css/auditlog.css')
265
  );
266
  }
267
+
268
  public function Footer()
269
  {
270
  wp_enqueue_script('jquery');
classes/Views/Settings.php CHANGED
@@ -1,765 +1,800 @@
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);
14
 
15
- add_action('wp_ajax_AjaxCheckSecurityToken', array($this, 'AjaxCheckSecurityToken'));
16
- add_action('wp_ajax_AjaxRunCleanup', array($this, 'AjaxRunCleanup'));
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');
66
- $this->_plugin->settings->SetPruningDateEnabled($_REQUEST['PruneBy'] == 'date');
67
- $this->_plugin->settings->SetPruningDate($_REQUEST['PruningDate']);
68
- $this->_plugin->settings->SetPruningLimitEnabled($_REQUEST['PruneBy'] == 'limit');
69
- $this->_plugin->settings->SetPruningLimit($_REQUEST['PruningLimit']);
 
 
 
 
70
 
71
- $this->_plugin->settings->SetFromEmail($_REQUEST['FromEmail']);
72
- $this->_plugin->settings->SetDisplayName($_REQUEST['DisplayName']);
73
 
74
- $this->_plugin->settings->SetWidgetsEnabled($_REQUEST['EnableDashboardWidgets']);
75
- $this->_plugin->settings->SetAllowedPluginViewers(isset($_REQUEST['Viewers']) ? $_REQUEST['Viewers'] : array());
76
- $this->_plugin->settings->SetAllowedPluginEditors(isset($_REQUEST['Editors']) ? $_REQUEST['Editors'] : array());
77
 
78
- $this->_plugin->settings->SetExcludedMonitoringUsers(isset($_REQUEST['ExUsers']) ? $_REQUEST['ExUsers'] : array());
79
- $this->_plugin->settings->SetExcludedMonitoringRoles(isset($_REQUEST['ExRoles']) ? $_REQUEST['ExRoles'] : array());
80
- $this->_plugin->settings->SetExcludedMonitoringCustom(isset($_REQUEST['Customs']) ? $_REQUEST['Customs'] : array());
81
- $this->_plugin->settings->SetExcludedMonitoringIP(isset($_REQUEST['IpAddrs']) ? $_REQUEST['IpAddrs'] : array());
82
 
83
- $this->_plugin->settings->SetRestrictAdmins(isset($_REQUEST['RestrictAdmins']));
84
- $this->_plugin->settings->SetRefreshAlertsEnabled($_REQUEST['EnableAuditViewRefresh']);
85
- $this->_plugin->settings->SetMainIPFromProxy(isset($_REQUEST['EnableProxyIpCapture']));
86
- $this->_plugin->settings->SetInternalIPsFiltering(isset($_REQUEST['EnableIpFiltering']));
87
- $this->_plugin->settings->SetIncognito(isset($_REQUEST['Incognito']));
88
- $this->_plugin->settings->SetLoggingDisabled(isset($_REQUEST['Logging']));
89
- $this->_plugin->settings->SetDeleteData(isset($_REQUEST['DeleteData']));
90
- $this->_plugin->settings->SetTimezone($_REQUEST['Timezone']);
91
- $this->_plugin->settings->SetWPBackend(isset($_REQUEST['WPBackend']));
92
- if (!empty($_REQUEST['Columns'])) {
93
- $this->_plugin->settings->SetColumns($_REQUEST['Columns']);
94
- }
95
- $this->_plugin->settings->ClearDevOptions();
 
96
 
97
- if (isset($_REQUEST['DevOptions'])) {
98
- foreach ($_REQUEST['DevOptions'] as $opt) {
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')) {
128
- wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
129
- }
130
- if (isset($_POST['submit'])) {
131
- try {
132
- $this->Save();
133
- ?><div class="updated">
134
- <p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p>
135
- </div><?php
136
- } catch (Exception $ex) {
137
- ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
138
- }
139
- }
140
- ?>
141
- <h2 id="wsal-tabs" class="nav-tab-wrapper">
142
- <a href="#tab-general" class="nav-tab"><?php _e('General', 'wp-security-audit-log'); ?></a>
143
- <a href="#tab-audit-log" class="nav-tab"><?php _e('Audit Log', 'wp-security-audit-log'); ?></a>
144
- <a href="#tab-exclude" class="nav-tab"><?php _e('Exclude Objects', 'wp-security-audit-log'); ?></a>
145
- </h2>
146
- <script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"/></script>
147
- <form id="audit-log-settings" method="post">
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">
155
- <!-- First tab -->
156
- <table class="form-table wsal-tab widefat" id="tab-general">
157
- <tbody>
158
- <!-- From Email & Name -->
159
- <tr>
160
- <th><label for="FromEmail"><?php _e('From Email & Name', 'wp-security-audit-log'); ?></label></th>
161
- <td>
162
- <fieldset>
163
- <label for="FromEmail"><?php _e('Email Address', 'wp-security-audit-log'); ?></label>
164
- <input type="email" id="FromEmail" name="FromEmail" value="<?php echo esc_attr($this->_plugin->settings->GetFromEmail()); ?>" />
165
- &nbsp;
166
- <label for="DisplayName"><?php _e('Display Name', 'wp-security-audit-log'); ?></label>
167
- <input type="text" id="DisplayName" name="DisplayName" value="<?php echo esc_attr($this->_plugin->settings->GetDisplayName()); ?>" />
168
- </fieldset>
169
- <p class="description">
170
- <?php
171
- echo sprintf(
172
- __('These email address and display name will be used as From details in the emails sent by the %s . Please ensure the mail server can relay emails with the domain of the specified email address.', 'wp-security-audit-log'),
173
- '<a target="_blank" href="https://www.wpsecurityauditlog.com/plugin-extensions/">' . __('(premium add-ons)', 'wp-security-audit-log') . '</a>'
174
- );
175
- ?>
176
- </p>
177
- </td>
178
- </tr>
179
- <!-- Alerts Dashboard Widget -->
180
- <tr>
181
- <th><label for="dwoption_on"><?php _e('Alerts Dashboard Widget', 'wp-security-audit-log'); ?></label></th>
182
- <td>
183
- <fieldset>
184
- <?php $dwe = $this->_plugin->settings->IsWidgetsEnabled(); ?>
185
- <label for="dwoption_on">
186
- <input type="radio" name="EnableDashboardWidgets" id="dwoption_on" style="margin-top: 2px;" <?php if($dwe)echo 'checked="checked"'; ?> value="1">
187
- <span><?php _e('On', 'wp-security-audit-log'); ?></span>
188
- </label>
189
- <br/>
190
- <label for="dwoption_off">
191
- <input type="radio" name="EnableDashboardWidgets" id="dwoption_off" style="margin-top: 2px;" <?php if(!$dwe)echo 'checked="checked"'; ?> value="0">
192
- <span><?php _e('Off', 'wp-security-audit-log'); ?></span>
193
- </label>
194
- <br/>
195
- <p class="description"><?php
196
- echo sprintf(
197
- __('Display a dashboard widget with the latest %d security alerts.', 'wp-security-audit-log'),
198
- $this->_plugin->settings->GetDashboardWidgetMaxAlerts()
199
- );
200
- ?></p>
201
- </fieldset>
202
- </td>
203
- </tr>
204
- <!-- Reverse Proxy / Firewall Options -->
205
- <tr>
206
- <th><label for="pioption_on"><?php _e('Reverse Proxy / Firewall Options', 'wp-security-audit-log'); ?></label></th>
207
- <td>
208
- <fieldset>
209
- <label for="EnableProxyIpCapture">
210
- <input type="checkbox" name="EnableProxyIpCapture" value="1" id="EnableProxyIpCapture"<?php
211
- if($this->_plugin->settings->IsMainIPFromProxy())echo ' checked="checked"';
212
- ?>/> <?php _e('WordPress running behind firewall or proxy', 'wp-security-audit-log'); ?>
213
- </label>
214
- <br/>
215
- <span class="description"><?php _e('Enable this option if your WordPress is running behind a firewall or reverse proxy. When this option is enabled the plugin will retrieve the user\'s IP address from the proxy header.', 'wp-security-audit-log'); ?></span>
216
- <br/>
217
- <label for="EnableIpFiltering">
218
- <input type="checkbox" name="EnableIpFiltering" value="1" id="EnableIpFiltering"<?php
219
- if($this->_plugin->settings->IsInternalIPsFiltered())echo ' checked="checked"';
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>
227
- <!-- Can Manage Plugin -->
228
- <tr>
229
- <th><label for="EditorQueryBox"><?php _e('Can Manage Plugin', 'wp-security-audit-log'); ?></label></th>
230
- <td>
231
- <fieldset>
232
- <input type="text" id="EditorQueryBox" style="float: left; display: block; width: 250px;">
233
- <input type="button" id="EditorQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
234
- <br style="clear: both;"/>
235
- <p class="description"><?php
236
- _e('Users and Roles in this list can manage the plugin settings', 'wp-security-audit-log');
237
- ?></p>
238
- <div id="EditorList"><?php
239
- foreach ($this->_plugin->settings->GetAllowedPluginEditors() as $item) {
240
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
241
- <input type="hidden" name="Editors[]" value="<?php echo esc_attr($item); ?>"/>
242
- <?php echo esc_html($item); ?>
243
- <?php if (wp_get_current_user()->user_login != $item) { ?>
244
- <a href="javascript:;" title="Remove">&times;</a>
245
- <?php } ?>
246
- </span><?php
247
- }
248
- ?></div>
249
- </fieldset>
250
- </td>
251
- </tr>
252
- <!-- Restrict Plugin Access -->
253
- <tr>
254
- <th><label for="RestrictAdmins"><?php _e('Restrict Plugin Access', 'wp-security-audit-log'); ?></label></th>
255
- <td>
256
- <fieldset>
257
- <input type="hidden" id="RestrictAdminsDefaultUser" value="<?php echo esc_attr(wp_get_current_user()->user_login); ?>"/>
258
- <label for="RestrictAdmins">
259
- <?php $ira = $this->_plugin->settings->IsRestrictAdmins(); ?>
260
- <input type="checkbox" name="RestrictAdmins" id="RestrictAdmins"<?php if($ira)echo ' checked="checked"'; ?>/>
261
- </label>
262
- <br/>
263
- <span class="description">
264
- <?php _e('If this option is disabled all the administrators on this WordPress have access to manage this plugin.', 'wp-security-audit-log'); ?><br/>
265
- <?php _e('By enabling this option only <strong>You</strong> and the users specified in the <strong>Can Manage Plugin</strong> and <strong>Can View Alerts</strong> can configure this plugin or view the alerts in the WordPress audit trail.', 'wp-security-audit-log'); ?>
266
- </span>
267
- </fieldset>
268
- </td>
269
- </tr>
270
- <!-- Developer Options -->
271
- <tr>
272
- <th><label><?php _e('Developer Options', 'wp-security-audit-log'); ?></label></th>
273
- <td>
274
- <fieldset>
275
- <?php $any = $this->_plugin->settings->IsAnyDevOptionEnabled(); ?>
276
- <a href="javascript:;" style="<?php if($any)echo 'display: none;'; ?>"
277
- onclick="jQuery(this).hide().next().show();">Show Developer Options</a>
278
- <div style="<?php if(!$any)echo 'display: none;'; ?>">
279
- <p style="border-left: 3px solid #FFD000; padding: 2px 8px; margin-left: 6px; margin-bottom: 16px;">
280
- <?php _e('Only enable these options on testing, staging and development websites. Enabling any of the settings below on LIVE websites may cause unintended side-effects including degraded performance.', 'wp-security-audit-log'); ?>
281
- </p>
282
- <?php
283
- foreach (array(
284
- WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array(
285
- __('Data Inspector', 'wp-security-audit-log'),
286
- __('View data logged for each triggered alert.', 'wp-security-audit-log')
287
- ),
288
- /* WSAL_Settings::OPT_DEV_PHP_ERRORS => array(
289
- __('PHP Errors', 'wp-security-audit-log'),
290
- __('Enables sensor for alerts generated from PHP.', 'wp-security-audit-log')
291
- ), */
292
- WSAL_Settings::OPT_DEV_REQUEST_LOG => array(
293
- __('Request Log', 'wp-security-audit-log'),
294
- __('Enables logging request to file.', 'wp-security-audit-log')
295
- ),
296
- /* WSAL_Settings::OPT_DEV_BACKTRACE_LOG => array(
297
- __('Backtrace', 'wp-security-audit-log'),
298
- __('Log full backtrace for PHP-generated alerts.', 'wp-security-audit-log')
299
- ), */
300
- ) as $opt => $info) {
301
- ?><label for="devoption_<?php echo $opt; ?>">
302
- <input type="checkbox" name="DevOptions[]" id="devoption_<?php echo $opt; ?>" <?php
303
- if($this->_plugin->settings->IsDevOptionEnabled($opt))echo 'checked="checked"'; ?> value="<?php echo $opt; ?>">
304
- <span><?php echo $info[0]; ?></span>
305
- <?php if (isset($info[1]) && $info[1]) { ?>
306
- <span class="description"> &mdash; <?php echo $info[1]; ?></span>
307
- <?php }
308
- ?></label><br/><?php
309
- }
310
- ?>
311
- <span class="description">
312
- <?php _e('The request log file is saved in the /wp-content/uploads/wp-security-audit-log/ directory.', 'wp-security-audit-log'); ?>
313
- </span>
314
- </div>
315
- </fieldset>
316
- </td>
317
- </tr>
318
- <!-- Hide Plugin in Plugins Page -->
319
- <tr>
320
- <th><label for="Incognito"><?php _e('Hide Plugin in Plugins Page', 'wp-security-audit-log'); ?></label></th>
321
- <td>
322
- <fieldset>
323
- <label for="Incognito">
324
- <input type="checkbox" name="Incognito" value="1" id="Incognito"<?php
325
- if ($this->_plugin->settings->IsIncognito()) echo ' checked="checked"';
326
- ?>/> <?php _e('Hide', 'wp-security-audit-log'); ?>
327
- </label>
328
- <br/>
329
- <span class="description">
330
- <?php _e('To manually revert this setting set the value of option wsal-hide-plugin to 0 in the wp_wsal_options table.', 'wp-security-audit-log'); ?>
331
- </span>
332
- </fieldset>
333
- </td>
334
- </tr>
335
- <!-- Logging -->
336
- <tr>
337
- <th><label for="Logging"><?php _e('Logging', 'wp-security-audit-log'); ?></label></th>
338
- <td>
339
- <fieldset>
340
- <label for="Logging">
341
- <span class="f-container">
342
- <span class="f-left">
343
- <input type="checkbox" name="Logging" value="1" class="switch" id="logging_status"/>
344
- <label for="logging_status"></label>
345
- </span>
346
- <span class="f-right f-text"><span id="logging_status_text"></span></span>
347
- </span>
348
- </label>
349
- <br/>
350
- <span class="description">
351
- <?php _e('Disable all plugin logging.', 'wp-security-audit-log'); ?>
352
- </span>
353
- </fieldset>
354
- </td>
355
- </tr>
356
- <!-- Remove Data on Uninstall -->
357
- <tr>
358
- <th><label for="DeleteData"><?php _e('Remove Data on Uninstall', 'wp-security-audit-log'); ?></label></th>
359
- <td>
360
- <fieldset>
361
- <label for="DeleteData">
362
- <input type="checkbox" name="DeleteData" value="1" id="DeleteData" onclick="return delete_confirm(this);"<?php
363
- if ($this->_plugin->settings->IsDeleteData()) echo ' checked="checked"';
364
- ?>/> <span class="description">Check this box if you would like remove all data when the plugin is deleted.</span>
365
- </label>
366
- </fieldset>
367
- </td>
368
- </tr>
369
- </tbody>
370
- </table>
371
- <!-- Second tab -->
372
- <table class="form-table wsal-tab widefat" id="tab-audit-log">
373
- <tbody>
374
- <!-- Security Alerts Pruning -->
375
- <?php
376
- $disabled = '';
377
- if ($this->_plugin->settings->IsArchivingEnabled()) {
378
- $disabled = 'disabled';
379
- ?>
380
- <tr>
381
- <td colspan="2">
382
- <?php _e('The options below are disabled because you enabled archiving of alerts to the archiving table from', 'wp-security-audit-log'); ?>&nbsp;<a href="<?php echo admin_url('admin.php?page=wsal-ext-settings#mirroring'); ?>" target="_blank">here</a>
383
- </td>
384
- </tr>
385
- <?php } ?>
386
- <tr>
387
- <th><label for="delete1"><?php _e('Security Alerts Pruning', 'wp-security-audit-log'); ?></label></th>
388
- <td>
389
- <fieldset>
390
- <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
391
- <?php $nbld = !($this->_plugin->settings->IsPruningDateEnabled() || $this->_plugin->settings->IsPruningLimitEnabled()); ?>
392
- <label for="delete0">
393
- <input type="radio" id="delete0" name="PruneBy" value="" <?php if ($nbld) echo 'checked="checked"'; ?> <?php echo $disabled; ?>/>
394
- <?php echo __('None', 'wp-security-audit-log'); ?>
395
- </label>
396
- </fieldset>
397
- <fieldset>
398
- <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
399
- <?php $nbld = $this->_plugin->settings->IsPruningDateEnabled(); ?>
400
- <label for="delete1">
401
- <input type="radio" id="delete1" name="PruneBy" value="date" <?php if($nbld)echo 'checked="checked"'; ?> <?php echo $disabled; ?>/>
402
- <?php echo __('Delete alerts older than', 'wp-security-audit-log'); ?>
403
- </label>
404
- <input type="text" id="PruningDate" name="PruningDate" placeholder="<?php echo $text; ?>"
405
- value="<?php echo esc_attr($this->_plugin->settings->GetPruningDate()); ?>"
406
- onfocus="jQuery('#delete1').attr('checked', true);" <?php echo $disabled; ?>/>
407
- <span> <?php echo $text; ?></span>
408
- </fieldset>
409
- <fieldset>
410
- <?php $text = __('(eg: 80)', 'wp-security-audit-log'); ?>
411
- <?php $nbld = $this->_plugin->settings->IsPruningLimitEnabled(); ?>
412
- <label for="delete2">
413
- <input type="radio" id="delete2" name="PruneBy" value="limit" <?php if($nbld)echo 'checked="checked"'; ?> <?php echo $disabled; ?>/>
414
- <?php echo __('Keep up to', 'wp-security-audit-log'); ?>
415
- </label>
416
- <input type="text" id="PruningLimit" name="PruningLimit" placeholder="<?php echo $text;?>"
417
- value="<?php echo esc_attr($this->_plugin->settings->GetPruningLimit()); ?>"
418
- onfocus="jQuery('#delete2').attr('checked', true);" <?php echo $disabled; ?>/>
419
- <?php echo __('alerts', 'wp-security-audit-log'); ?>
420
- <span><?php echo $text; ?></span>
421
- </fieldset>
422
- <p class="description"><?php
423
- echo __('Next Scheduled Cleanup is in ', 'wp-security-audit-log');
424
- echo human_time_diff(current_time('timestamp'), $next = wp_next_scheduled('wsal_cleanup'));
425
- echo '<!-- ' . date('dMy H:i:s', $next) . ' --> ';
426
- echo sprintf(
427
- __('(or %s)', 'wp-security-audit-log'),
428
- '<a class="' .$disabled.'" href="' . admin_url('admin-ajax.php?action=AjaxRunCleanup') . '">' . __('Run Manually', 'wp-security-audit-log') . '</a>'
429
- );
430
- ?></p>
431
- </td>
432
- </tr>
433
- <!-- Can View Alerts -->
434
- <tr>
435
- <th><label for="ViewerQueryBox"><?php _e('Can View Alerts', 'wp-security-audit-log'); ?></label></th>
436
- <td>
437
- <fieldset>
438
- <input type="text" id="ViewerQueryBox" style="float: left; display: block; width: 250px;">
439
- <input type="button" id="ViewerQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
440
- <br style="clear: both;"/>
441
- <p class="description"><?php
442
- _e('Users and Roles in this list can view the security alerts', 'wp-security-audit-log');
443
- ?></p>
444
- <div id="ViewerList"><?php
445
- foreach($this->_plugin->settings->GetAllowedPluginViewers() as $item){
446
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
447
- <input type="hidden" name="Viewers[]" value="<?php echo esc_attr($item); ?>"/>
448
- <?php echo esc_html($item); ?>
449
- <a href="javascript:;" title="Remove">&times;</a>
450
- </span><?php
451
- }
452
- ?></div>
453
- </fieldset>
454
- </td>
455
- </tr>
456
- <!-- Refresh Audit Log Viewer -->
457
- <tr>
458
- <th><label for="aroption_on"><?php _e('Refresh Audit Log Viewer', 'wp-security-audit-log'); ?></label></th>
459
- <td>
460
- <fieldset>
461
- <?php $are = $this->_plugin->settings->IsRefreshAlertsEnabled(); ?>
462
- <label for="aroption_on">
463
- <input type="radio" name="EnableAuditViewRefresh" id="aroption_on" style="margin-top: 2px;" <?php if($are)echo 'checked="checked"'; ?> value="1">
464
- <span><?php _e('Automatic', 'wp-security-audit-log'); ?></span>
465
- </label>
466
- <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer as soon as there are new alerts.', 'wp-security-audit-log'); ?></span>
467
- <br/>
468
- <label for="aroption_off">
469
- <input type="radio" name="EnableAuditViewRefresh" id="aroption_off" style="margin-top: 2px;" <?php if(!$are)echo 'checked="checked"'; ?> value="0">
470
- <span><?php _e('Manual', 'wp-security-audit-log'); ?></span>
471
- </label>
472
- <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer only when the page is reloaded.', 'wp-security-audit-log'); ?></span>
473
- <br/>
474
- </fieldset>
475
- </td>
476
- </tr>
477
- <!-- Alerts Timestamp -->
478
- <tr>
479
- <th><label for="timezone-default"><?php _e('Alerts Timestamp', 'wp-security-audit-log'); ?></label></th>
480
- <td>
481
- <fieldset>
482
- <?php $timezone = $this->_plugin->settings->GetTimezone(); ?>
483
- <label for="timezone-default">
484
- <input type="radio" name="Timezone" id="timezone-default" style="margin-top: 2px;" <?php if(!$timezone)echo 'checked="checked"'; ?> value="0">
485
- <span><?php _e('UTC', 'wp-security-audit-log'); ?></span>
486
- </label>
487
- <br/>
488
- <label for="timezone">
489
- <input type="radio" name="Timezone" id="timezone" style="margin-top: 2px;" <?php if($timezone)echo 'checked="checked"'; ?> value="1">
490
- <span><?php _e('WordPress\' timezone', 'wp-security-audit-log'); ?></span>
491
- </label>
492
- <br/>
493
- <span class="description"><?php _e('Select which timestamp the alerts should have in the Audit Log viewer. Note that the WordPress\' timezone might be different from that of the server.', 'wp-security-audit-log'); ?></span>
494
- </fieldset>
495
- </td>
496
- </tr>
497
- <!-- Audit Log Columns Selection -->
498
- <tr>
499
- <th><label for="columns"><?php _e('Audit Log Columns Selection', 'wp-security-audit-log'); ?></label></th>
500
- <td>
501
- <fieldset>
502
- <?php $columns = $this->_plugin->settings->GetColumns(); ?>
503
- <?php foreach ($columns as $key => $value) { ?>
504
- <label for="columns">
505
- <input type="checkbox" name="Columns[<?php echo $key; ?>]" id="<?php echo $key; ?>" class="sel-columns" style="margin-top: 2px;" <?php if ($value == '1') echo 'checked="checked"'; ?> value="1">
506
- <span><?php echo ucwords(str_replace("_", " ", $key)); ?></span>
507
- </label>
508
- <br/>
509
- <?php } ?>
510
- <span class="description"><?php _e('When you disable any of the above such details won’t be shown in the Audit Log
511
- viewer though the plugin will still record such information in the database.', 'wp-security-audit-log'); ?></span>
512
- </fieldset>
513
- </td>
514
- </tr>
515
- <!-- Disable Alerts for WordPress Background activity -->
516
- <tr>
517
- <th><label for="DeleteData"><?php _e('Disable Alerts for WordPress Background Activity', 'wp-security-audit-log'); ?></label></th>
518
- <td>
519
- <fieldset>
520
- <label for="WPBackend">
521
- <input type="checkbox" name="WPBackend" value="1" id="WPBackend" <?php
522
- if ($this->_plugin->settings->IsWPBackend()) echo ' checked="checked"';
523
- ?>/> <?php _e('Hide activity', 'wp-security-audit-log'); ?>
524
- </label>
525
- <br/>
526
- <span class="description">
527
- <?php _e('For example do not raise an alert when WordPress deletes the auto drafts.', 'wp-security-audit-log'); ?>
528
- </span>
529
- </fieldset>
530
- </td>
531
- </tr>
532
- </tbody>
533
- </table>
534
- <!-- Third tab -->
535
- <table class="form-table wsal-tab widefat" id="tab-exclude">
536
- <tbody>
537
- <tr>
538
- <th><h2>Users &amp; Roles</h2></th>
539
- </tr>
540
- <tr>
541
- <td colspan="2">Any of the users and roles listed in the below options will be excluded from monitoring. This means that any change they do will not be logged.</td>
542
- </tr>
543
- <!-- Excluded Users -->
544
- <tr>
545
- <th><label for="ExUserQueryBox"><?php _e('Excluded Users', 'wp-security-audit-log'); ?></label></th>
546
- <td>
547
- <fieldset>
548
- <input type="text" id="ExUserQueryBox" style="float: left; display: block; width: 250px;">
549
- <input type="button" id="ExUserQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
550
- <br style="clear: both;"/>
551
- <div id="ExUserList"><?php
552
- foreach($this->_plugin->settings->GetExcludedMonitoringUsers() as $item){
553
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
554
- <input type="hidden" name="ExUsers[]" value="<?php echo esc_attr($item); ?>"/>
555
- <?php echo esc_html($item); ?>
556
- <a href="javascript:;" title="Remove">&times;</a>
557
- </span><?php
558
- }
559
- ?></div>
560
- </fieldset>
561
- </td>
562
- </tr>
563
- <!-- Excluded Roles -->
564
- <tr>
565
- <th><label for="ExRoleQueryBox"><?php _e('Excluded Roles', 'wp-security-audit-log'); ?></label></th>
566
- <td>
567
- <fieldset>
568
- <input type="text" id="ExRoleQueryBox" style="float: left; display: block; width: 250px;">
569
- <input type="button" id="ExRoleQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
570
- <br style="clear: both;"/>
571
- <div id="ExRoleList"><?php
572
- foreach($this->_plugin->settings->GetExcludedMonitoringRoles() as $item){
573
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
574
- <input type="hidden" name="ExRoles[]" value="<?php echo esc_attr($item); ?>"/>
575
- <?php echo esc_html($item); ?>
576
- <a href="javascript:;" title="Remove">&times;</a>
577
- </span><?php
578
- }
579
- ?></div>
580
- </fieldset>
581
- </td>
582
- </tr>
583
- <tr>
584
- <th><h2>Custom Fields</h2></th>
585
- </tr>
586
- <tr>
587
- <td colspan="2">All of the custom fields listed below will be excluded from monitoring. This means that if they are changed or updated the plugin will not log such activity.<br>
588
- You can use the * wildcard to exclude more than one Custom Field. For example to exclude all the Custom Fields that start with wp123 specify wp123*.</td>
589
- </tr>
590
- <!-- Excluded Custom Fields -->
591
- <tr>
592
- <th><label for="CustomQueryBox"><?php _e('Excluded Custom Fields', 'wp-security-audit-log'); ?></label></th>
593
- <td>
594
- <fieldset>
595
- <input type="text" id="CustomQueryBox" style="float: left; display: block; width: 250px;">
596
- <input type="button" id="CustomQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
597
- <br style="clear: both;"/>
598
- <div id="CustomList">
599
- <?php foreach ($this->_plugin->settings->GetExcludedMonitoringCustom() as $item) { ?>
600
- <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
601
- <input type="hidden" name="Customs[]" value="<?php echo esc_attr($item); ?>"/>
602
- <?php echo esc_html($item); ?>
603
- <a href="javascript:;" title="Remove">&times;</a>
604
- </span>
605
- <?php } ?>
606
- </div>
607
- </fieldset>
608
- </td>
609
- </tr>
610
- <tr>
611
- <th><h2>IP Addresses</h2></th>
612
- </tr>
613
- <tr>
614
- <td colspan="2">Any of the IP addresses listed below will be excluded from monitoring. This means that all activity from such IP address will not be recorded.</td>
615
- </tr>
616
- <!-- Excluded IP Addresses -->
617
- <tr>
618
- <th><label for="IpAddrQueryBox"><?php _e('Excluded IP Addresses', 'wp-security-audit-log'); ?></label></th>
619
- <td>
620
- <fieldset>
621
- <input type="text" id="IpAddrQueryBox" style="float: left; display: block; width: 250px;">
622
- <input type="button" id="IpAddrQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
623
- <br style="clear: both;"/>
624
- <div id="IpAddrList">
625
- <?php foreach ($this->_plugin->settings->GetExcludedMonitoringIP() as $item) { ?>
626
- <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
627
- <input type="hidden" name="IpAddrs[]" value="<?php echo esc_attr($item); ?>"/>
628
- <?php echo esc_html($item); ?>
629
- <a href="javascript:;" title="Remove">&times;</a>
630
- </span>
631
- <?php } ?>
632
- </div>
633
- </fieldset>
634
- </td>
635
- </tr>
636
- </tbody>
637
- </table>
638
- </div>
639
- <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"></p>
640
- </form>
641
- <script type="text/javascript">
642
- <!--
643
- function delete_confirm(elementRef)
644
- {
645
- if (elementRef.checked)
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
 
657
- function wsalUpdateLoggingStatus(checkbox, label){
658
- if (checkbox.prop('checked')) {
659
- label.text('On');
660
- } else {
661
- label.text('Off');
662
- }
663
- }
664
- // Set On
665
- if (statusConfig) {
666
- logging_status.prop('checked', true);
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(
681
- 'settings',
682
- $this->_plugin->GetBaseUrl() . '/css/settings.css',
683
- array(),
684
- filemtime($this->_plugin->GetBaseDir() . '/css/settings.css')
685
- );
686
- ?><style type="text/css">
687
- .wsal-tab {
688
- display: none;
689
- }
690
- .wsal-tab tr.alert-incomplete td {
691
- color: #9BE;
692
- }
693
- .wsal-tab tr.alert-unavailable td {
694
- color: #CCC;
695
- }
696
- </style><?php
697
- }
698
 
699
- public function Footer()
700
- {
701
- wp_enqueue_script(
702
- 'settings',
703
- $this->_plugin->GetBaseUrl() . '/js/settings.js',
704
- array(),
705
- filemtime($this->_plugin->GetBaseDir() . '/js/settings.js')
706
- );
707
- ?><script type="text/javascript">
708
- jQuery(document).ready(function(){
709
- // tab handling code
710
- jQuery('#wsal-tabs>a').click(function(){
711
- jQuery('#wsal-tabs>a').removeClass('nav-tab-active');
712
- jQuery('table.wsal-tab').hide();
713
- jQuery(jQuery(this).addClass('nav-tab-active').attr('href')).show();
714
- });
715
- // show relevant tab
716
- var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
717
- if (hashlink.length) {
718
- hashlink.click();
719
- } else {
720
- jQuery('#wsal-tabs>a:first').click();
721
- }
722
 
723
- jQuery(".sel-columns").change(function(){
724
- var notChecked = 1;
725
- jQuery(".sel-columns").each(function(){
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')) {
739
- die('Access Denied.');
740
- }
741
- $users = array();
742
- foreach (get_users() as $user) {
743
- if (strpos($user->user_login, $_GET['term']) !== false) {
744
- array_push($users, $user->user_login);
745
- }
746
- }
747
- echo json_encode($users);
748
- exit;
749
- }
750
 
751
- public function AjaxGetAllRoles()
752
- {
753
- if (!$this->_plugin->settings->CurrentUserCan('view')) {
754
- die('Access Denied.');
755
- }
756
- $roles = array();
757
- foreach (get_editable_roles() as $role_name => $role_info) {
758
- if (strpos($role_name, $_GET['term']) !== false) {
759
- array_push($roles, $role_name);
760
- }
761
- }
762
- echo json_encode($roles);
763
- exit;
764
- }
765
  }
1
  <?php
2
  /**
3
+ * Settings Page
4
+ *
5
+ * Settings page of the plugin.
6
+ *
7
+ * @since 1.0.0
8
  * @package Wsal
9
+ */
10
+
11
+ /**
12
+ * Class: WSAL_Views_Settings
13
+ *
14
+ * Settings view class to handle settings page functions.
15
  *
16
+ * @since 1.0.0
17
  */
18
+ class WSAL_Views_Settings extends WSAL_AbstractView {
19
+ public $adapterMsg = '';
 
20
 
21
+ public function __construct(WpSecurityAuditLog $plugin)
22
+ {
23
+ parent::__construct($plugin);
24
 
25
+ add_action('wp_ajax_AjaxCheckSecurityToken', array($this, 'AjaxCheckSecurityToken'));
26
+ add_action('wp_ajax_AjaxRunCleanup', array($this, 'AjaxRunCleanup'));
27
+ add_action('wp_ajax_AjaxGetAllUsers', array($this, 'AjaxGetAllUsers'));
28
+ add_action('wp_ajax_AjaxGetAllRoles', array($this, 'AjaxGetAllRoles'));
29
+ }
30
 
31
+ public function HasPluginShortcutLink()
32
+ {
33
+ return true;
34
+ }
35
 
36
+ public function GetTitle()
37
+ {
38
+ return __('Settings', 'wp-security-audit-log');
39
+ }
40
 
41
+ public function GetIcon()
42
+ {
43
+ return 'dashicons-admin-generic';
44
+ }
45
 
46
+ public function GetName()
47
+ {
48
+ return __('Settings', 'wp-security-audit-log');
49
+ }
50
 
51
+ public function GetWeight()
52
+ {
53
+ return 3;
54
+ }
55
 
56
+ protected function GetTokenType($token)
57
+ {
58
+ $users = array();
59
+ foreach (get_users('blog_id=0&fields[]=user_login') as $obj) {
60
+ $users[] = $obj->user_login;
61
+ }
62
+ $roles = array_keys(get_editable_roles());
63
 
64
+ if (in_array($token, $users)) {
65
+ return 'user';
66
+ }
67
+ if (in_array($token, $roles)) {
68
+ return 'role';
69
+ }
70
+ return 'other';
71
+ }
72
 
73
+ /**
74
+ * Method: Save settings.
75
+ *
76
+ * @since 1.0.0
77
+ */
78
+ protected function Save() {
79
+ check_admin_referer( 'wsal-settings' );
80
+ $this->_plugin->settings->SetPruningDateEnabled( isset( $_REQUEST['PruneBy'] ) ? $_REQUEST['PruneBy'] == 'date' : '' );
81
+ $this->_plugin->settings->SetPruningDate( isset( $_REQUEST['PruningDate'] ) ? $_REQUEST['PruningDate'] : '' );
82
+ $this->_plugin->settings->SetPruningLimitEnabled( isset( $_REQUEST['PruneBy'] ) ? $_REQUEST['PruneBy'] == 'limit' : '' );
83
+ $this->_plugin->settings->SetPruningLimit( isset( $_REQUEST['PruningLimit'] ) ? $_REQUEST['PruningLimit'] : '' );
84
 
85
+ $this->_plugin->settings->SetFromEmail( $_REQUEST['FromEmail'] );
86
+ $this->_plugin->settings->SetDisplayName( $_REQUEST['DisplayName'] );
87
 
88
+ $this->_plugin->settings->SetWidgetsEnabled( $_REQUEST['EnableDashboardWidgets'] );
89
+ $this->_plugin->settings->SetAllowedPluginViewers( isset( $_REQUEST['Viewers'] ) ? $_REQUEST['Viewers'] : array() );
90
+ $this->_plugin->settings->SetAllowedPluginEditors( isset( $_REQUEST['Editors'] ) ? $_REQUEST['Editors'] : array() );
91
 
92
+ $this->_plugin->settings->SetExcludedMonitoringUsers( isset( $_REQUEST['ExUsers'] ) ? $_REQUEST['ExUsers'] : array() );
93
+ $this->_plugin->settings->SetExcludedMonitoringRoles( isset( $_REQUEST['ExRoles'] ) ? $_REQUEST['ExRoles'] : array() );
94
+ $this->_plugin->settings->SetExcludedMonitoringCustom( isset( $_REQUEST['Customs'] ) ? $_REQUEST['Customs'] : array() );
95
+ $this->_plugin->settings->SetExcludedMonitoringIP( isset( $_REQUEST['IpAddrs'] ) ? $_REQUEST['IpAddrs'] : array() );
96
 
97
+ $this->_plugin->settings->SetRestrictAdmins( isset( $_REQUEST['RestrictAdmins'] ) );
98
+ $this->_plugin->settings->SetRefreshAlertsEnabled( $_REQUEST['EnableAuditViewRefresh'] );
99
+ $this->_plugin->settings->SetMainIPFromProxy( isset( $_REQUEST['EnableProxyIpCapture'] ) );
100
+ $this->_plugin->settings->SetInternalIPsFiltering( isset( $_REQUEST['EnableIpFiltering'] ) );
101
+ $this->_plugin->settings->SetIncognito( isset( $_REQUEST['Incognito'] ) );
102
+ $this->_plugin->settings->SetLoggingDisabled( isset( $_REQUEST['Logging'] ) );
103
+ $this->_plugin->settings->SetDeleteData( isset( $_REQUEST['DeleteData'] ) );
104
+ $this->_plugin->settings->SetTimezone( $_REQUEST['Timezone'] );
105
+ $this->_plugin->settings->set_type_username( $_REQUEST['type_username'] );
106
+ $this->_plugin->settings->SetWPBackend( isset( $_REQUEST['WPBackend'] ) );
107
+ if ( ! empty( $_REQUEST['Columns'] ) ) {
108
+ $this->_plugin->settings->SetColumns( $_REQUEST['Columns'] );
109
+ }
110
+ $this->_plugin->settings->ClearDevOptions();
111
 
112
+ if ( isset( $_REQUEST['DevOptions'] ) ) {
113
+ foreach ( $_REQUEST['DevOptions'] as $opt ) {
114
+ $this->_plugin->settings->SetDevOptionEnabled( $opt, true );
115
+ }
116
+ }
117
+ }
118
 
119
+ public function AjaxCheckSecurityToken()
120
+ {
121
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
122
+ die('Access Denied.');
123
+ }
124
+ if (!isset($_REQUEST['token'])) {
125
+ die('Token parameter expected.');
126
+ }
127
+ die($this->GetTokenType($_REQUEST['token']));
128
+ }
129
 
130
+ public function AjaxRunCleanup()
131
+ {
132
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
133
+ die('Access Denied.');
134
+ }
135
+ $this->_plugin->CleanUp();
136
+ wp_redirect($this->GetUrl());
137
+ exit;
138
+ }
139
 
140
+ public function Render()
141
+ {
142
+ if (!$this->_plugin->settings->CurrentUserCan('edit')) {
143
+ wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
144
+ }
145
+ if (isset($_POST['submit'])) {
146
+ try {
147
+ $this->Save();
148
+ ?><div class="updated">
149
+ <p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p>
150
+ </div><?php
151
+ } catch (Exception $ex) {
152
+ ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
153
+ }
154
+ }
155
+ ?>
156
+ <h2 id="wsal-tabs" class="nav-tab-wrapper">
157
+ <a href="#tab-general" class="nav-tab"><?php _e('General', 'wp-security-audit-log'); ?></a>
158
+ <a href="#tab-audit-log" class="nav-tab"><?php _e('Audit Log', 'wp-security-audit-log'); ?></a>
159
+ <a href="#tab-exclude" class="nav-tab"><?php _e('Exclude Objects', 'wp-security-audit-log'); ?></a>
160
+ </h2>
161
+ <script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"/></script>
162
+ <form id="audit-log-settings" method="post">
163
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
164
+ <input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
165
+ <?php wp_nonce_field('wsal-settings'); ?>
166
 
167
+ <div id="audit-log-adverts">
168
+ </div>
169
+ <div class="nav-tabs">
170
+ <!-- First tab -->
171
+ <table class="form-table wsal-tab widefat" id="tab-general">
172
+ <tbody>
173
+ <!-- From Email & Name -->
174
+ <tr>
175
+ <th><label for="FromEmail"><?php _e('From Email & Name', 'wp-security-audit-log'); ?></label></th>
176
+ <td>
177
+ <fieldset>
178
+ <label for="FromEmail"><?php _e('Email Address', 'wp-security-audit-log'); ?></label>
179
+ <input type="email" id="FromEmail" name="FromEmail" value="<?php echo esc_attr($this->_plugin->settings->GetFromEmail()); ?>" />
180
+ &nbsp;
181
+ <label for="DisplayName"><?php _e('Display Name', 'wp-security-audit-log'); ?></label>
182
+ <input type="text" id="DisplayName" name="DisplayName" value="<?php echo esc_attr($this->_plugin->settings->GetDisplayName()); ?>" />
183
+ </fieldset>
184
+ <p class="description">
185
+ <?php
186
+ echo sprintf(
187
+ __('These email address and display name will be used as From details in the emails sent by the %s . Please ensure the mail server can relay emails with the domain of the specified email address.', 'wp-security-audit-log'),
188
+ '<a target="_blank" href="https://www.wpsecurityauditlog.com/plugin-extensions/">' . __('(premium add-ons)', 'wp-security-audit-log') . '</a>'
189
+ );
190
+ ?>
191
+ </p>
192
+ </td>
193
+ </tr>
194
+ <!-- Alerts Dashboard Widget -->
195
+ <tr>
196
+ <th><label for="dwoption_on"><?php _e('Alerts Dashboard Widget', 'wp-security-audit-log'); ?></label></th>
197
+ <td>
198
+ <fieldset>
199
+ <?php $dwe = $this->_plugin->settings->IsWidgetsEnabled(); ?>
200
+ <label for="dwoption_on">
201
+ <input type="radio" name="EnableDashboardWidgets" id="dwoption_on" style="margin-top: 2px;" <?php if($dwe)echo 'checked="checked"'; ?> value="1">
202
+ <span><?php _e('On', 'wp-security-audit-log'); ?></span>
203
+ </label>
204
+ <br/>
205
+ <label for="dwoption_off">
206
+ <input type="radio" name="EnableDashboardWidgets" id="dwoption_off" style="margin-top: 2px;" <?php if(!$dwe)echo 'checked="checked"'; ?> value="0">
207
+ <span><?php _e('Off', 'wp-security-audit-log'); ?></span>
208
+ </label>
209
+ <br/>
210
+ <p class="description"><?php
211
+ echo sprintf(
212
+ __('Display a dashboard widget with the latest %d security alerts.', 'wp-security-audit-log'),
213
+ $this->_plugin->settings->GetDashboardWidgetMaxAlerts()
214
+ );
215
+ ?></p>
216
+ </fieldset>
217
+ </td>
218
+ </tr>
219
+ <!-- Reverse Proxy / Firewall Options -->
220
+ <tr>
221
+ <th><label for="pioption_on"><?php _e('Reverse Proxy / Firewall Options', 'wp-security-audit-log'); ?></label></th>
222
+ <td>
223
+ <fieldset>
224
+ <label for="EnableProxyIpCapture">
225
+ <input type="checkbox" name="EnableProxyIpCapture" value="1" id="EnableProxyIpCapture"<?php
226
+ if($this->_plugin->settings->IsMainIPFromProxy())echo ' checked="checked"';
227
+ ?>/> <?php _e('WordPress running behind firewall or proxy', 'wp-security-audit-log'); ?>
228
+ </label>
229
+ <br/>
230
+ <span class="description"><?php _e('Enable this option if your WordPress is running behind a firewall or reverse proxy. When this option is enabled the plugin will retrieve the user\'s IP address from the proxy header.', 'wp-security-audit-log'); ?></span>
231
+ <br/>
232
+ <label for="EnableIpFiltering">
233
+ <input type="checkbox" name="EnableIpFiltering" value="1" id="EnableIpFiltering"<?php
234
+ if($this->_plugin->settings->IsInternalIPsFiltered())echo ' checked="checked"';
235
+ ?>/> <?php _e('Filter Internal IP Addresses', 'wp-security-audit-log'); ?>
236
+ </label>
237
+ <br/>
238
+ <span class="description"><?php _e('Enable this option to filter internal IP addresses from the proxy headers.', 'wp-security-audit-log'); ?></span>
239
+ </fieldset>
240
+ </td>
241
+ </tr>
242
+ <!-- Can Manage Plugin -->
243
+ <tr>
244
+ <th><label for="EditorQueryBox"><?php _e('Can Manage Plugin', 'wp-security-audit-log'); ?></label></th>
245
+ <td>
246
+ <fieldset>
247
+ <input type="text" id="EditorQueryBox" style="float: left; display: block; width: 250px;">
248
+ <input type="button" id="EditorQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
249
+ <br style="clear: both;"/>
250
+ <p class="description"><?php
251
+ _e('Users and Roles in this list can manage the plugin settings', 'wp-security-audit-log');
252
+ ?></p>
253
+ <div id="EditorList"><?php
254
+ foreach ($this->_plugin->settings->GetAllowedPluginEditors() as $item) {
255
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
256
+ <input type="hidden" name="Editors[]" value="<?php echo esc_attr($item); ?>"/>
257
+ <?php echo esc_html($item); ?>
258
+ <?php if (wp_get_current_user()->user_login != $item) { ?>
259
+ <a href="javascript:;" title="Remove">&times;</a>
260
+ <?php } ?>
261
+ </span><?php
262
+ }
263
+ ?></div>
264
+ </fieldset>
265
+ </td>
266
+ </tr>
267
+ <!-- Restrict Plugin Access -->
268
+ <tr>
269
+ <th><label for="RestrictAdmins"><?php _e('Restrict Plugin Access', 'wp-security-audit-log'); ?></label></th>
270
+ <td>
271
+ <fieldset>
272
+ <input type="hidden" id="RestrictAdminsDefaultUser" value="<?php echo esc_attr(wp_get_current_user()->user_login); ?>"/>
273
+ <label for="RestrictAdmins">
274
+ <?php $ira = $this->_plugin->settings->IsRestrictAdmins(); ?>
275
+ <input type="checkbox" name="RestrictAdmins" id="RestrictAdmins"<?php if($ira)echo ' checked="checked"'; ?>/>
276
+ </label>
277
+ <br/>
278
+ <span class="description">
279
+ <?php _e('If this option is disabled all the administrators on this WordPress have access to manage this plugin.', 'wp-security-audit-log'); ?><br/>
280
+ <?php _e('By enabling this option only <strong>You</strong> and the users specified in the <strong>Can Manage Plugin</strong> and <strong>Can View Alerts</strong> can configure this plugin or view the alerts in the WordPress audit trail.', 'wp-security-audit-log'); ?>
281
+ </span>
282
+ </fieldset>
283
+ </td>
284
+ </tr>
285
+ <!-- Developer Options -->
286
+ <tr>
287
+ <th><label><?php _e('Developer Options', 'wp-security-audit-log'); ?></label></th>
288
+ <td>
289
+ <fieldset>
290
+ <?php $any = $this->_plugin->settings->IsAnyDevOptionEnabled(); ?>
291
+ <a href="javascript:;" style="<?php if($any)echo 'display: none;'; ?>"
292
+ onclick="jQuery(this).hide().next().show();">Show Developer Options</a>
293
+ <div style="<?php if(!$any)echo 'display: none;'; ?>">
294
+ <p style="border-left: 3px solid #FFD000; padding: 2px 8px; margin-left: 6px; margin-bottom: 16px;">
295
+ <?php _e('Only enable these options on testing, staging and development websites. Enabling any of the settings below on LIVE websites may cause unintended side-effects including degraded performance.', 'wp-security-audit-log'); ?>
296
+ </p>
297
+ <?php
298
+ foreach (array(
299
+ WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array(
300
+ __('Data Inspector', 'wp-security-audit-log'),
301
+ __('View data logged for each triggered alert.', 'wp-security-audit-log')
302
+ ),
303
+ /* WSAL_Settings::OPT_DEV_PHP_ERRORS => array(
304
+ __('PHP Errors', 'wp-security-audit-log'),
305
+ __('Enables sensor for alerts generated from PHP.', 'wp-security-audit-log')
306
+ ), */
307
+ WSAL_Settings::OPT_DEV_REQUEST_LOG => array(
308
+ __('Request Log', 'wp-security-audit-log'),
309
+ __('Enables logging request to file.', 'wp-security-audit-log')
310
+ ),
311
+ /* WSAL_Settings::OPT_DEV_BACKTRACE_LOG => array(
312
+ __('Backtrace', 'wp-security-audit-log'),
313
+ __('Log full backtrace for PHP-generated alerts.', 'wp-security-audit-log')
314
+ ), */
315
+ ) as $opt => $info) {
316
+ ?><label for="devoption_<?php echo $opt; ?>">
317
+ <input type="checkbox" name="DevOptions[]" id="devoption_<?php echo $opt; ?>" <?php
318
+ if($this->_plugin->settings->IsDevOptionEnabled($opt))echo 'checked="checked"'; ?> value="<?php echo $opt; ?>">
319
+ <span><?php echo $info[0]; ?></span>
320
+ <?php if (isset($info[1]) && $info[1]) { ?>
321
+ <span class="description"> &mdash; <?php echo $info[1]; ?></span>
322
+ <?php }
323
+ ?></label><br/><?php
324
+ }
325
+ ?>
326
+ <span class="description">
327
+ <?php _e('The request log file is saved in the /wp-content/uploads/wp-security-audit-log/ directory.', 'wp-security-audit-log'); ?>
328
+ </span>
329
+ </div>
330
+ </fieldset>
331
+ </td>
332
+ </tr>
333
+ <!-- Hide Plugin in Plugins Page -->
334
+ <tr>
335
+ <th><label for="Incognito"><?php _e('Hide Plugin in Plugins Page', 'wp-security-audit-log'); ?></label></th>
336
+ <td>
337
+ <fieldset>
338
+ <label for="Incognito">
339
+ <input type="checkbox" name="Incognito" value="1" id="Incognito"<?php
340
+ if ($this->_plugin->settings->IsIncognito()) echo ' checked="checked"';
341
+ ?>/> <?php _e('Hide', 'wp-security-audit-log'); ?>
342
+ </label>
343
+ <br/>
344
+ <span class="description">
345
+ <?php _e('To manually revert this setting set the value of option wsal-hide-plugin to 0 in the wp_wsal_options table.', 'wp-security-audit-log'); ?>
346
+ </span>
347
+ </fieldset>
348
+ </td>
349
+ </tr>
350
+ <!-- Logging -->
351
+ <tr>
352
+ <th><label for="Logging"><?php _e('Logging', 'wp-security-audit-log'); ?></label></th>
353
+ <td>
354
+ <fieldset>
355
+ <label for="Logging">
356
+ <span class="f-container">
357
+ <span class="f-left">
358
+ <input type="checkbox" name="Logging" value="1" class="switch" id="logging_status"/>
359
+ <label for="logging_status"></label>
360
+ </span>
361
+ <span class="f-right f-text"><span id="logging_status_text"></span></span>
362
+ </span>
363
+ </label>
364
+ <br/>
365
+ <span class="description">
366
+ <?php _e('Disable all plugin logging.', 'wp-security-audit-log'); ?>
367
+ </span>
368
+ </fieldset>
369
+ </td>
370
+ </tr>
371
+ <!-- Remove Data on Uninstall -->
372
+ <tr>
373
+ <th><label for="DeleteData"><?php _e('Remove Data on Uninstall', 'wp-security-audit-log'); ?></label></th>
374
+ <td>
375
+ <fieldset>
376
+ <label for="DeleteData">
377
+ <input type="checkbox" name="DeleteData" value="1" id="DeleteData" onclick="return delete_confirm(this);"<?php
378
+ if ($this->_plugin->settings->IsDeleteData()) echo ' checked="checked"';
379
+ ?>/> <span class="description">Check this box if you would like remove all data when the plugin is deleted.</span>
380
+ </label>
381
+ </fieldset>
382
+ </td>
383
+ </tr>
384
+ </tbody>
385
+ </table>
386
+ <!-- Second tab -->
387
+ <table class="form-table wsal-tab widefat" id="tab-audit-log">
388
+ <tbody>
389
+ <!-- Security Alerts Pruning -->
390
+ <?php
391
+ $disabled = '';
392
+ if ($this->_plugin->settings->IsArchivingEnabled()) {
393
+ $disabled = 'disabled';
394
+ ?>
395
+ <tr>
396
+ <td colspan="2">
397
+ <?php _e('The options below are disabled because you enabled archiving of alerts to the archiving table from', 'wp-security-audit-log'); ?>&nbsp;<a href="<?php echo admin_url('admin.php?page=wsal-ext-settings#mirroring'); ?>" target="_blank">here</a>
398
+ </td>
399
+ </tr>
400
+ <?php } ?>
401
+ <tr>
402
+ <th><label for="delete1"><?php _e('Security Alerts Pruning', 'wp-security-audit-log'); ?></label></th>
403
+ <td>
404
+ <fieldset>
405
+ <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
406
+ <?php $nbld = !($this->_plugin->settings->IsPruningDateEnabled() || $this->_plugin->settings->IsPruningLimitEnabled()); ?>
407
+ <label for="delete0">
408
+ <input type="radio" id="delete0" name="PruneBy" value="" <?php if ($nbld) echo 'checked="checked"'; ?> <?php echo $disabled; ?>/>
409
+ <?php echo __('None', 'wp-security-audit-log'); ?>
410
+ </label>
411
+ </fieldset>
412
+ <fieldset>
413
+ <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
414
+ <?php $nbld = $this->_plugin->settings->IsPruningDateEnabled(); ?>
415
+ <label for="delete1">
416
+ <input type="radio" id="delete1" name="PruneBy" value="date" <?php if($nbld)echo 'checked="checked"'; ?> <?php echo $disabled; ?>/>
417
+ <?php echo __('Delete alerts older than', 'wp-security-audit-log'); ?>
418
+ </label>
419
+ <input type="text" id="PruningDate" name="PruningDate" placeholder="<?php echo $text; ?>"
420
+ value="<?php echo esc_attr($this->_plugin->settings->GetPruningDate()); ?>"
421
+ onfocus="jQuery('#delete1').attr('checked', true);" <?php echo $disabled; ?>/>
422
+ <span> <?php echo $text; ?></span>
423
+ </fieldset>
424
+ <fieldset>
425
+ <?php $text = __('(eg: 80)', 'wp-security-audit-log'); ?>
426
+ <?php $nbld = $this->_plugin->settings->IsPruningLimitEnabled(); ?>
427
+ <label for="delete2">
428
+ <input type="radio" id="delete2" name="PruneBy" value="limit" <?php if($nbld)echo 'checked="checked"'; ?> <?php echo $disabled; ?>/>
429
+ <?php echo __('Keep up to', 'wp-security-audit-log'); ?>
430
+ </label>
431
+ <input type="text" id="PruningLimit" name="PruningLimit" placeholder="<?php echo $text;?>"
432
+ value="<?php echo esc_attr($this->_plugin->settings->GetPruningLimit()); ?>"
433
+ onfocus="jQuery('#delete2').attr('checked', true);" <?php echo $disabled; ?>/>
434
+ <?php echo __('alerts', 'wp-security-audit-log'); ?>
435
+ <span><?php echo $text; ?></span>
436
+ </fieldset>
437
+ <p class="description"><?php
438
+ echo __('Next Scheduled Cleanup is in ', 'wp-security-audit-log');
439
+ echo human_time_diff(current_time('timestamp'), $next = wp_next_scheduled('wsal_cleanup'));
440
+ echo '<!-- ' . date('dMy H:i:s', $next) . ' --> ';
441
+ echo sprintf(
442
+ __('(or %s)', 'wp-security-audit-log'),
443
+ '<a class="' .$disabled.'" href="' . admin_url('admin-ajax.php?action=AjaxRunCleanup') . '">' . __('Run Manually', 'wp-security-audit-log') . '</a>'
444
+ );
445
+ ?></p>
446
+ </td>
447
+ </tr>
448
+ <!-- Can View Alerts -->
449
+ <tr>
450
+ <th><label for="ViewerQueryBox"><?php _e('Can View Alerts', 'wp-security-audit-log'); ?></label></th>
451
+ <td>
452
+ <fieldset>
453
+ <input type="text" id="ViewerQueryBox" style="float: left; display: block; width: 250px;">
454
+ <input type="button" id="ViewerQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
455
+ <br style="clear: both;"/>
456
+ <p class="description"><?php
457
+ _e('Users and Roles in this list can view the security alerts', 'wp-security-audit-log');
458
+ ?></p>
459
+ <div id="ViewerList"><?php
460
+ foreach($this->_plugin->settings->GetAllowedPluginViewers() as $item){
461
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
462
+ <input type="hidden" name="Viewers[]" value="<?php echo esc_attr($item); ?>"/>
463
+ <?php echo esc_html($item); ?>
464
+ <a href="javascript:;" title="Remove">&times;</a>
465
+ </span><?php
466
+ }
467
+ ?></div>
468
+ </fieldset>
469
+ </td>
470
+ </tr>
471
+ <!-- Refresh Audit Log Viewer -->
472
+ <tr>
473
+ <th><label for="aroption_on"><?php _e('Refresh Audit Log Viewer', 'wp-security-audit-log'); ?></label></th>
474
+ <td>
475
+ <fieldset>
476
+ <?php $are = $this->_plugin->settings->IsRefreshAlertsEnabled(); ?>
477
+ <label for="aroption_on">
478
+ <input type="radio" name="EnableAuditViewRefresh" id="aroption_on" style="margin-top: 2px;" <?php if($are)echo 'checked="checked"'; ?> value="1">
479
+ <span><?php _e('Automatic', 'wp-security-audit-log'); ?></span>
480
+ </label>
481
+ <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer as soon as there are new alerts.', 'wp-security-audit-log'); ?></span>
482
+ <br/>
483
+ <label for="aroption_off">
484
+ <input type="radio" name="EnableAuditViewRefresh" id="aroption_off" style="margin-top: 2px;" <?php if(!$are)echo 'checked="checked"'; ?> value="0">
485
+ <span><?php _e('Manual', 'wp-security-audit-log'); ?></span>
486
+ </label>
487
+ <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer only when the page is reloaded.', 'wp-security-audit-log'); ?></span>
488
+ <br/>
489
+ </fieldset>
490
+ </td>
491
+ </tr>
492
+ <!-- Alerts Timestamp -->
493
+ <tr>
494
+ <th><label for="timezone-default"><?php _e('Alerts Timestamp', 'wp-security-audit-log'); ?></label></th>
495
+ <td>
496
+ <fieldset>
497
+ <?php $timezone = $this->_plugin->settings->GetTimezone(); ?>
498
+ <label for="timezone-default">
499
+ <input type="radio" name="Timezone" id="timezone-default" style="margin-top: 2px;" <?php if(!$timezone)echo 'checked="checked"'; ?> value="0">
500
+ <span><?php _e('UTC', 'wp-security-audit-log'); ?></span>
501
+ </label>
502
+ <br/>
503
+ <label for="timezone">
504
+ <input type="radio" name="Timezone" id="timezone" style="margin-top: 2px;" <?php if($timezone)echo 'checked="checked"'; ?> value="1">
505
+ <span><?php _e('WordPress\' timezone', 'wp-security-audit-log'); ?></span>
506
+ </label>
507
+ <br/>
508
+ <span class="description"><?php _e('Select which timestamp the alerts should have in the Audit Log viewer. Note that the WordPress\' timezone might be different from that of the server.', 'wp-security-audit-log'); ?></span>
509
+ </fieldset>
510
+ </td>
511
+ </tr>
512
+ <!-- Select type of name -->
513
+ <tr>
514
+ <th><label for="timezone-default"><?php esc_html_e( 'User Information in Audit Log', 'wp-security-audit-log' ); ?></label></th>
515
+ <td>
516
+ <fieldset>
517
+ <?php $type_username = $this->_plugin->settings->get_type_username(); ?>
518
+ <label for="column_username">
519
+ <input type="radio" name="type_username" id="column_username" style="margin-top: 2px;" <?php echo ( 'username' == $type_username ) ? 'checked="checked"' : false; ?> value="username">
520
+ <span><?php esc_html_e( 'Username', 'wp-security-audit-log' ); ?></span>
521
+ </label>
522
+ <br/>
523
+ <label for="columns_display_name">
524
+ <input type="radio" name="type_username" id="columns_display_name" style="margin-top: 2px;" <?php echo ( 'display_name' == $type_username ) ? 'checked="checked"' : false; ?> value="display_name">
525
+ <span><?php esc_html_e( 'First Name & Last Name', 'wp-security-audit-log' ); ?></span>
526
+ </label>
527
+ <br/>
528
+ <span class="description"><?php esc_html_e( 'Select the type of user information that should be displayed in the audit log.', 'wp-security-audit-log' ); ?></span>
529
+ </fieldset>
530
+ </td>
531
+ </tr>
532
+ <!-- Audit Log Columns Selection -->
533
+ <tr>
534
+ <th><label for="columns"><?php _e('Audit Log Columns Selection', 'wp-security-audit-log'); ?></label></th>
535
+ <td>
536
+ <fieldset>
537
+ <?php $columns = $this->_plugin->settings->GetColumns(); ?>
538
+ <?php foreach ($columns as $key => $value) { ?>
539
+ <label for="columns">
540
+ <input type="checkbox" name="Columns[<?php echo $key; ?>]" id="<?php echo $key; ?>" class="sel-columns" style="margin-top: 2px;" <?php if ($value == '1') echo 'checked="checked"'; ?> value="1">
541
+ <span><?php echo ucwords(str_replace("_", " ", $key)); ?></span>
542
+ </label>
543
+ <br/>
544
+ <?php } ?>
545
+ <span class="description"><?php _e('When you disable any of the above such details won’t be shown in the Audit Log
546
+ viewer though the plugin will still record such information in the database.', 'wp-security-audit-log'); ?></span>
547
+ </fieldset>
548
+ </td>
549
+ </tr>
550
+ <!-- Disable Alerts for WordPress Background activity -->
551
+ <tr>
552
+ <th><label for="DeleteData"><?php _e('Disable Alerts for WordPress Background Activity', 'wp-security-audit-log'); ?></label></th>
553
+ <td>
554
+ <fieldset>
555
+ <label for="WPBackend">
556
+ <input type="checkbox" name="WPBackend" value="1" id="WPBackend" <?php
557
+ if ($this->_plugin->settings->IsWPBackend()) echo ' checked="checked"';
558
+ ?>/> <?php _e('Hide activity', 'wp-security-audit-log'); ?>
559
+ </label>
560
+ <br/>
561
+ <span class="description">
562
+ <?php _e('For example do not raise an alert when WordPress deletes the auto drafts.', 'wp-security-audit-log'); ?>
563
+ </span>
564
+ </fieldset>
565
+ </td>
566
+ </tr>
567
+ </tbody>
568
+ </table>
569
+ <!-- Third tab -->
570
+ <table class="form-table wsal-tab widefat" id="tab-exclude">
571
+ <tbody>
572
+ <tr>
573
+ <th><h2>Users &amp; Roles</h2></th>
574
+ </tr>
575
+ <tr>
576
+ <td colspan="2">Any of the users and roles listed in the below options will be excluded from monitoring. This means that any change they do will not be logged.</td>
577
+ </tr>
578
+ <!-- Excluded Users -->
579
+ <tr>
580
+ <th><label for="ExUserQueryBox"><?php _e('Excluded Users', 'wp-security-audit-log'); ?></label></th>
581
+ <td>
582
+ <fieldset>
583
+ <input type="text" id="ExUserQueryBox" style="float: left; display: block; width: 250px;">
584
+ <input type="button" id="ExUserQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
585
+ <br style="clear: both;"/>
586
+ <div id="ExUserList"><?php
587
+ foreach($this->_plugin->settings->GetExcludedMonitoringUsers() as $item){
588
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
589
+ <input type="hidden" name="ExUsers[]" value="<?php echo esc_attr($item); ?>"/>
590
+ <?php echo esc_html($item); ?>
591
+ <a href="javascript:;" title="Remove">&times;</a>
592
+ </span><?php
593
+ }
594
+ ?></div>
595
+ </fieldset>
596
+ </td>
597
+ </tr>
598
+ <!-- Excluded Roles -->
599
+ <tr>
600
+ <th><label for="ExRoleQueryBox"><?php _e('Excluded Roles', 'wp-security-audit-log'); ?></label></th>
601
+ <td>
602
+ <fieldset>
603
+ <input type="text" id="ExRoleQueryBox" style="float: left; display: block; width: 250px;">
604
+ <input type="button" id="ExRoleQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
605
+ <br style="clear: both;"/>
606
+ <div id="ExRoleList"><?php
607
+ foreach($this->_plugin->settings->GetExcludedMonitoringRoles() as $item){
608
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
609
+ <input type="hidden" name="ExRoles[]" value="<?php echo esc_attr($item); ?>"/>
610
+ <?php echo esc_html($item); ?>
611
+ <a href="javascript:;" title="Remove">&times;</a>
612
+ </span><?php
613
+ }
614
+ ?></div>
615
+ </fieldset>
616
+ </td>
617
+ </tr>
618
+ <tr>
619
+ <th><h2>Custom Fields</h2></th>
620
+ </tr>
621
+ <tr>
622
+ <td colspan="2">All of the custom fields listed below will be excluded from monitoring. This means that if they are changed or updated the plugin will not log such activity.<br>
623
+ You can use the * wildcard to exclude more than one Custom Field. For example to exclude all the Custom Fields that start with wp123 specify wp123*.</td>
624
+ </tr>
625
+ <!-- Excluded Custom Fields -->
626
+ <tr>
627
+ <th><label for="CustomQueryBox"><?php _e('Excluded Custom Fields', 'wp-security-audit-log'); ?></label></th>
628
+ <td>
629
+ <fieldset>
630
+ <input type="text" id="CustomQueryBox" style="float: left; display: block; width: 250px;">
631
+ <input type="button" id="CustomQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
632
+ <br style="clear: both;"/>
633
+ <div id="CustomList">
634
+ <?php foreach ($this->_plugin->settings->GetExcludedMonitoringCustom() as $item) { ?>
635
+ <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
636
+ <input type="hidden" name="Customs[]" value="<?php echo esc_attr($item); ?>"/>
637
+ <?php echo esc_html($item); ?>
638
+ <a href="javascript:;" title="Remove">&times;</a>
639
+ </span>
640
+ <?php } ?>
641
+ </div>
642
+ </fieldset>
643
+ </td>
644
+ </tr>
645
+ <tr>
646
+ <th><h2>IP Addresses</h2></th>
647
+ </tr>
648
+ <tr>
649
+ <td colspan="2">Any of the IP addresses listed below will be excluded from monitoring. This means that all activity from such IP address will not be recorded.</td>
650
+ </tr>
651
+ <!-- Excluded IP Addresses -->
652
+ <tr>
653
+ <th><label for="IpAddrQueryBox"><?php _e('Excluded IP Addresses', 'wp-security-audit-log'); ?></label></th>
654
+ <td>
655
+ <fieldset>
656
+ <input type="text" id="IpAddrQueryBox" style="float: left; display: block; width: 250px;">
657
+ <input type="button" id="IpAddrQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
658
+ <br style="clear: both;"/>
659
+ <div id="IpAddrList">
660
+ <?php foreach ($this->_plugin->settings->GetExcludedMonitoringIP() as $item) { ?>
661
+ <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
662
+ <input type="hidden" name="IpAddrs[]" value="<?php echo esc_attr($item); ?>"/>
663
+ <?php echo esc_html($item); ?>
664
+ <a href="javascript:;" title="Remove">&times;</a>
665
+ </span>
666
+ <?php } ?>
667
+ </div>
668
+ </fieldset>
669
+ </td>
670
+ </tr>
671
+ </tbody>
672
+ </table>
673
+ </div>
674
+ <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"></p>
675
+ </form>
676
+ <script type="text/javascript">
677
+ <!--
678
+ function delete_confirm(elementRef)
679
+ {
680
+ if (elementRef.checked)
681
+ {
682
+ if ( window.confirm('Do you want remove all data when the plugin is deleted?') == false )
683
+ elementRef.checked = false;
684
+ }
685
+ }
686
 
687
+ jQuery(document).ready(function() {
688
+ var statusConfig = <?php if ($this->_plugin->settings->IsLoggingDisabled()) { echo 1; } else { echo 0; } ?>;
689
+ var logging_status = jQuery('#logging_status');
690
+ var txtNot = jQuery('#logging_status_text');
691
 
692
+ function wsalUpdateLoggingStatus(checkbox, label){
693
+ if (checkbox.prop('checked')) {
694
+ label.text('On');
695
+ } else {
696
+ label.text('Off');
697
+ }
698
+ }
699
+ // Set On
700
+ if (statusConfig) {
701
+ logging_status.prop('checked', true);
702
+ }
703
+ wsalUpdateLoggingStatus(logging_status, txtNot);
704
 
705
+ logging_status.on('change', function() {
706
+ wsalUpdateLoggingStatus(logging_status, txtNot);
707
+ });
708
+ });
709
+ // -->
710
+ </script><?php
711
+ }
712
 
713
+ public function Header()
714
+ {
715
+ wp_enqueue_style(
716
+ 'settings',
717
+ $this->_plugin->GetBaseUrl() . '/css/settings.css',
718
+ array(),
719
+ filemtime($this->_plugin->GetBaseDir() . '/css/settings.css')
720
+ );
721
+ ?><style type="text/css">
722
+ .wsal-tab {
723
+ display: none;
724
+ }
725
+ .wsal-tab tr.alert-incomplete td {
726
+ color: #9BE;
727
+ }
728
+ .wsal-tab tr.alert-unavailable td {
729
+ color: #CCC;
730
+ }
731
+ </style><?php
732
+ }
733
 
734
+ public function Footer()
735
+ {
736
+ wp_enqueue_script(
737
+ 'settings',
738
+ $this->_plugin->GetBaseUrl() . '/js/settings.js',
739
+ array(),
740
+ filemtime($this->_plugin->GetBaseDir() . '/js/settings.js')
741
+ );
742
+ ?><script type="text/javascript">
743
+ jQuery(document).ready(function(){
744
+ // tab handling code
745
+ jQuery('#wsal-tabs>a').click(function(){
746
+ jQuery('#wsal-tabs>a').removeClass('nav-tab-active');
747
+ jQuery('table.wsal-tab').hide();
748
+ jQuery(jQuery(this).addClass('nav-tab-active').attr('href')).show();
749
+ });
750
+ // show relevant tab
751
+ var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
752
+ if (hashlink.length) {
753
+ hashlink.click();
754
+ } else {
755
+ jQuery('#wsal-tabs>a:first').click();
756
+ }
757
 
758
+ jQuery(".sel-columns").change(function(){
759
+ var notChecked = 1;
760
+ jQuery(".sel-columns").each(function(){
761
+ if(this.checked) notChecked = 0;
762
+ })
763
+ if(notChecked == 1){
764
+ alert("You have to select at least one column!");
765
+ }
766
+ });
767
+ });
768
+ </script><?php
769
+ }
770
 
771
+ public function AjaxGetAllUsers()
772
+ {
773
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
774
+ die('Access Denied.');
775
+ }
776
+ $users = array();
777
+ foreach (get_users() as $user) {
778
+ if (strpos($user->user_login, $_GET['term']) !== false) {
779
+ array_push($users, $user->user_login);
780
+ }
781
+ }
782
+ echo json_encode($users);
783
+ exit;
784
+ }
785
 
786
+ public function AjaxGetAllRoles()
787
+ {
788
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
789
+ die('Access Denied.');
790
+ }
791
+ $roles = array();
792
+ foreach (get_editable_roles() as $role_name => $role_info) {
793
+ if (strpos($role_name, $_GET['term']) !== false) {
794
+ array_push($roles, $role_name);
795
+ }
796
+ }
797
+ echo json_encode($roles);
798
+ exit;
799
+ }
800
  }
css/auditlog.css CHANGED
@@ -128,7 +128,7 @@ td.column-user {
128
  .log-type-64:after,
129
  .log-type-256:after,
130
  .log-type-4096:after,
131
- .log-type-E_CRITICAL:after {
132
  background: #c9302c; content: "!";
133
  }
134
 
@@ -136,7 +136,7 @@ td.column-user {
136
  .log-type-2:after,
137
  .log-type-32:after,
138
  .log-type-128:after,
139
- .log-type-512:after {
140
  background: #ec971f; content: "!";
141
  }
142
 
@@ -146,7 +146,7 @@ td.column-user {
146
  .log-type-2048:after,
147
  .log-type-8192:after,
148
  .log-type-16384:after,
149
- .log-type-E_DEBUG:after {
150
  background: #ec0; content: "i";
151
  }
152
 
@@ -201,27 +201,27 @@ td.column-user {
201
  .dashicons-dismiss:hover {
202
  color:#c00
203
  }
204
- .dark-tooltip.small{
205
  margin-left: 10px;
206
- font-size:13px;
207
- padding:5px 10px;
208
- max-width:150px;
209
- -webkit-border-radius: 3px;
210
- -moz-border-radius: 3px;
211
- border-radius: 3px;
212
- }
213
- .dark-tooltip.medium{
214
  margin-left: -15px;
215
- font-size:13px;
216
- padding:5px 10px;
217
- max-width:150px;
218
- -webkit-border-radius: 3px;
219
- -moz-border-radius: 3px;
220
- border-radius: 3px;
221
  }
222
  .dark-tooltip.west.medium .tip{ border-width: 5px 7px 5px 0; margin-left:-7px; margin-top:-5px;}
223
  .dark-tooltip ul.confirm{ list-style-type:none;margin-top:5px;display:inline-block;margin:0 auto;}
224
- .dark-tooltip ul.confirm li{
225
  padding:5px 10px;
226
  float:left;
227
  margin:5px 5px 0 0;
128
  .log-type-64:after,
129
  .log-type-256:after,
130
  .log-type-4096:after,
131
+ .log-type-E_CRITICAL:after {
132
  background: #c9302c; content: "!";
133
  }
134
 
136
  .log-type-2:after,
137
  .log-type-32:after,
138
  .log-type-128:after,
139
+ .log-type-512:after {
140
  background: #ec971f; content: "!";
141
  }
142
 
146
  .log-type-2048:after,
147
  .log-type-8192:after,
148
  .log-type-16384:after,
149
+ .log-type-E_DEBUG:after {
150
  background: #ec0; content: "i";
151
  }
152
 
201
  .dashicons-dismiss:hover {
202
  color:#c00
203
  }
204
+ .dark-tooltip.small{
205
  margin-left: 10px;
206
+ font-size:13px;
207
+ padding:5px 10px;
208
+ max-width:150px;
209
+ -webkit-border-radius: 3px;
210
+ -moz-border-radius: 3px;
211
+ border-radius: 3px;
212
+ }
213
+ .dark-tooltip.medium{
214
  margin-left: -15px;
215
+ font-size:13px;
216
+ padding:5px 10px;
217
+ max-width:150px;
218
+ -webkit-border-radius: 3px;
219
+ -moz-border-radius: 3px;
220
+ border-radius: 3px;
221
  }
222
  .dark-tooltip.west.medium .tip{ border-width: 5px 7px 5px 0; margin-left:-7px; margin-top:-5px;}
223
  .dark-tooltip ul.confirm{ list-style-type:none;margin-top:5px;display:inline-block;margin:0 auto;}
224
+ .dark-tooltip ul.confirm li{
225
  padding:5px 10px;
226
  float:left;
227
  margin:5px 5px 0 0;
defaults.php CHANGED
@@ -60,7 +60,7 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
60
  array(2001, E_NOTICE, __('User published a blog post', 'wp-security-audit-log'), __('Published a post called %PostTitle%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
61
  array(2002, E_NOTICE, __('User modified a published blog post', 'wp-security-audit-log'), __('Modified the published post %PostTitle%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
62
  array(2003, E_NOTICE, __('User modified a draft blog post', 'wp-security-audit-log'), __('Modified the draft post with the %PostTitle%. %EditorLinkPost%.', 'wp-security-audit-log')),
63
- array(2008, E_WARNING, __('User permanently deleted a blog post from the trash', 'wp-security-audit-log'), __('Permanently deleted the post %PostTitle%. Post URL was %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
64
  array(2012, E_WARNING, __('User moved a blog post to the trash', 'wp-security-audit-log'), __('Moved the post %PostTitle% to trash. Post URL is %PostUrl%.', 'wp-security-audit-log')),
65
  array(2014, E_CRITICAL, __('User restored a blog post from trash', 'wp-security-audit-log'), __('Post %PostTitle% has been restored from trash. %EditorLinkPost%.', 'wp-security-audit-log')),
66
  array(2016, E_NOTICE, __('User changed blog post category', 'wp-security-audit-log'), __('Changed the category of the post %PostTitle% from %OldCategories% to %NewCategories%. %EditorLinkPost%.', 'wp-security-audit-log')),
@@ -108,7 +108,7 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
108
  array(2030, E_NOTICE, __('User published a post with custom post type', 'wp-security-audit-log'), __('Published a custom post %PostTitle% of type %PostType%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
109
  array(2031, E_NOTICE, __('User modified a post with custom post type', 'wp-security-audit-log'), __('Modified the custom post %PostTitle% of type %PostType%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
110
  array(2032, E_NOTICE, __('User modified a draft post with custom post type', 'wp-security-audit-log'), __('Modified the draft custom post %PostTitle% of type is %PostType%. %EditorLinkPost%.', 'wp-security-audit-log')),
111
- array(2033, E_WARNING, __('User permanently deleted post with custom post type', 'wp-security-audit-log'), __('Permanently Deleted the custom post %PostTitle% of type %PostType%. The post URL was %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
112
  array(2034, E_WARNING, __('User moved post with custom post type to trash', 'wp-security-audit-log'), __('Moved the custom post %PostTitle% of type %PostType% to trash. Post URL was %PostUrl%.', 'wp-security-audit-log')),
113
  array(2035, E_CRITICAL, __('User restored post with custom post type from trash', 'wp-security-audit-log'), __('The custom post %PostTitle% of type %PostType% has been restored from trash. %EditorLinkPost%.', 'wp-security-audit-log')),
114
  array(2036, E_NOTICE, __('User changed the category of a post with custom post type', 'wp-security-audit-log'), __('Changed the category(ies) of the custom post %PostTitle% of type %PostType% from %OldCategories% to %NewCategories%. %EditorLinkPost%.', 'wp-security-audit-log')),
@@ -133,7 +133,7 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
133
  array(2005, E_NOTICE, __('User published a WordPress page', 'wp-security-audit-log'), __('Published a page called %PostTitle%. Page URL is %PostUrl%. %EditorLinkPage%.', 'wp-security-audit-log')),
134
  array(2006, E_NOTICE, __('User modified a published WordPress page', 'wp-security-audit-log'), __('Modified the published page %PostTitle%. Page URL is %PostUrl%. %EditorLinkPage%.', 'wp-security-audit-log')),
135
  array(2007, E_NOTICE, __('User modified a draft WordPress page', 'wp-security-audit-log'), __('Modified the draft page %PostTitle%. Page ID is %PostID%. %EditorLinkPage%.', 'wp-security-audit-log')),
136
- array(2009, E_WARNING, __('User permanently deleted a page from the trash', 'wp-security-audit-log'), __('Permanently deleted the page %PostTitle%. Page URL was %PostUrl%. %EditorLinkPage%.', 'wp-security-audit-log')),
137
  array(2013, E_WARNING, __('User moved WordPress page to the trash', 'wp-security-audit-log'), __('Moved the page %PostTitle% to trash. Page URL was %PostUrl%.', 'wp-security-audit-log')),
138
  array(2015, E_CRITICAL, __('User restored a WordPress page from trash', 'wp-security-audit-log'), __('Page %PostTitle% has been restored from trash. %EditorLinkPage%.', 'wp-security-audit-log')),
139
  array(2018, E_NOTICE, __('User changed page URL', 'wp-security-audit-log'), __('Changed the URL of the page %PostTitle% from %OldUrl% to %NewUrl%. %EditorLinkPage%.', 'wp-security-audit-log')),
@@ -271,7 +271,7 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
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
  ),
274
- __('User Profiles', 'wp-security-audit-log') => array(
275
  array(4000, E_CRITICAL, __('New user was created on WordPress', 'wp-security-audit-log'), __('A new user %NewUserData->Username% was created with role of %NewUserData->Roles%.', 'wp-security-audit-log')),
276
  array(4001, E_CRITICAL, __('User created another WordPress user', 'wp-security-audit-log'), __('%UserChanger% created a new user %NewUserData->Username% with the role of %NewUserData->Roles%.', 'wp-security-audit-log')),
277
  array(4002, E_CRITICAL, __('The role of a user was changed by another WordPress user', 'wp-security-audit-log'), __('Changed the role of the user %TargetUsername% from %OldRole% to %NewRole%.', 'wp-security-audit-log')),
@@ -280,8 +280,10 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
280
  array(4005, E_NOTICE, __('User changed his or her email address', 'wp-security-audit-log'), __('Changed the email address from %OldEmail% to %NewEmail%.', 'wp-security-audit-log')),
281
  array(4006, E_NOTICE, __('User changed another user\'s email address', 'wp-security-audit-log'), __('Changed the email address of the user %TargetUsername% from %OldEmail% to %NewEmail%.', 'wp-security-audit-log')),
282
  array(4007, E_CRITICAL, __('User was deleted by another user', 'wp-security-audit-log'), __('Deleted the user %TargetUserData->Username% with the role of %TargetUserData->Roles%.', 'wp-security-audit-log')),
283
- array(4014, E_NOTICE, __('User opened the profile page of another user', 'wp-security-audit-log'), __('%UserChanger% opened the profile page of the user %TargetUsername%.', 'wp-security-audit-log'))
284
- )
 
 
285
  ),
286
  __('Third Party Support', 'wp-security-audit-log') => array(
287
  __('BBPress Forum', 'wp-security-audit-log') => array(
60
  array(2001, E_NOTICE, __('User published a blog post', 'wp-security-audit-log'), __('Published a post called %PostTitle%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
61
  array(2002, E_NOTICE, __('User modified a published blog post', 'wp-security-audit-log'), __('Modified the published post %PostTitle%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
62
  array(2003, E_NOTICE, __('User modified a draft blog post', 'wp-security-audit-log'), __('Modified the draft post with the %PostTitle%. %EditorLinkPost%.', 'wp-security-audit-log')),
63
+ array(2008, E_WARNING, __('User permanently deleted a blog post from the trash', 'wp-security-audit-log'), __('Permanently deleted the post %PostTitle%.', 'wp-security-audit-log')),
64
  array(2012, E_WARNING, __('User moved a blog post to the trash', 'wp-security-audit-log'), __('Moved the post %PostTitle% to trash. Post URL is %PostUrl%.', 'wp-security-audit-log')),
65
  array(2014, E_CRITICAL, __('User restored a blog post from trash', 'wp-security-audit-log'), __('Post %PostTitle% has been restored from trash. %EditorLinkPost%.', 'wp-security-audit-log')),
66
  array(2016, E_NOTICE, __('User changed blog post category', 'wp-security-audit-log'), __('Changed the category of the post %PostTitle% from %OldCategories% to %NewCategories%. %EditorLinkPost%.', 'wp-security-audit-log')),
108
  array(2030, E_NOTICE, __('User published a post with custom post type', 'wp-security-audit-log'), __('Published a custom post %PostTitle% of type %PostType%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
109
  array(2031, E_NOTICE, __('User modified a post with custom post type', 'wp-security-audit-log'), __('Modified the custom post %PostTitle% of type %PostType%. Post URL is %PostUrl%. %EditorLinkPost%.', 'wp-security-audit-log')),
110
  array(2032, E_NOTICE, __('User modified a draft post with custom post type', 'wp-security-audit-log'), __('Modified the draft custom post %PostTitle% of type is %PostType%. %EditorLinkPost%.', 'wp-security-audit-log')),
111
+ array(2033, E_WARNING, __('User permanently deleted post with custom post type', 'wp-security-audit-log'), __('Permanently Deleted the custom post %PostTitle% of type %PostType%.', 'wp-security-audit-log')),
112
  array(2034, E_WARNING, __('User moved post with custom post type to trash', 'wp-security-audit-log'), __('Moved the custom post %PostTitle% of type %PostType% to trash. Post URL was %PostUrl%.', 'wp-security-audit-log')),
113
  array(2035, E_CRITICAL, __('User restored post with custom post type from trash', 'wp-security-audit-log'), __('The custom post %PostTitle% of type %PostType% has been restored from trash. %EditorLinkPost%.', 'wp-security-audit-log')),
114
  array(2036, E_NOTICE, __('User changed the category of a post with custom post type', 'wp-security-audit-log'), __('Changed the category(ies) of the custom post %PostTitle% of type %PostType% from %OldCategories% to %NewCategories%. %EditorLinkPost%.', 'wp-security-audit-log')),
133
  array(2005, E_NOTICE, __('User published a WordPress page', 'wp-security-audit-log'), __('Published a page called %PostTitle%. Page URL is %PostUrl%. %EditorLinkPage%.', 'wp-security-audit-log')),
134
  array(2006, E_NOTICE, __('User modified a published WordPress page', 'wp-security-audit-log'), __('Modified the published page %PostTitle%. Page URL is %PostUrl%. %EditorLinkPage%.', 'wp-security-audit-log')),
135
  array(2007, E_NOTICE, __('User modified a draft WordPress page', 'wp-security-audit-log'), __('Modified the draft page %PostTitle%. Page ID is %PostID%. %EditorLinkPage%.', 'wp-security-audit-log')),
136
+ array(2009, E_WARNING, __('User permanently deleted a page from the trash', 'wp-security-audit-log'), __('Permanently deleted the page %PostTitle%.', 'wp-security-audit-log')),
137
  array(2013, E_WARNING, __('User moved WordPress page to the trash', 'wp-security-audit-log'), __('Moved the page %PostTitle% to trash. Page URL was %PostUrl%.', 'wp-security-audit-log')),
138
  array(2015, E_CRITICAL, __('User restored a WordPress page from trash', 'wp-security-audit-log'), __('Page %PostTitle% has been restored from trash. %EditorLinkPage%.', 'wp-security-audit-log')),
139
  array(2018, E_NOTICE, __('User changed page URL', 'wp-security-audit-log'), __('Changed the URL of the page %PostTitle% from %OldUrl% to %NewUrl%. %EditorLinkPage%.', '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
  ),
274
+ __( 'User Profiles', 'wp-security-audit-log' ) => array(
275
  array(4000, E_CRITICAL, __('New user was created on WordPress', 'wp-security-audit-log'), __('A new user %NewUserData->Username% was created with role of %NewUserData->Roles%.', 'wp-security-audit-log')),
276
  array(4001, E_CRITICAL, __('User created another WordPress user', 'wp-security-audit-log'), __('%UserChanger% created a new user %NewUserData->Username% with the role of %NewUserData->Roles%.', 'wp-security-audit-log')),
277
  array(4002, E_CRITICAL, __('The role of a user was changed by another WordPress user', 'wp-security-audit-log'), __('Changed the role of the user %TargetUsername% from %OldRole% to %NewRole%.', 'wp-security-audit-log')),
280
  array(4005, E_NOTICE, __('User changed his or her email address', 'wp-security-audit-log'), __('Changed the email address from %OldEmail% to %NewEmail%.', 'wp-security-audit-log')),
281
  array(4006, E_NOTICE, __('User changed another user\'s email address', 'wp-security-audit-log'), __('Changed the email address of the user %TargetUsername% from %OldEmail% to %NewEmail%.', 'wp-security-audit-log')),
282
  array(4007, E_CRITICAL, __('User was deleted by another user', 'wp-security-audit-log'), __('Deleted the user %TargetUserData->Username% with the role of %TargetUserData->Roles%.', 'wp-security-audit-log')),
283
+ array(4014, E_NOTICE, __('User opened the profile page of another user', 'wp-security-audit-log'), __('%UserChanger% opened the profile page of the user %TargetUsername%.', 'wp-security-audit-log')),
284
+ array( 4015, E_NOTICE, __( 'User updated a custom field value for a user', 'wp-security-audit-log' ), __( 'Changed the value of the custom field %custom_field_name% from %old_value% to %new_value% for the user %TargetUsername%.', 'wp-security-audit-log' ) ),
285
+ array( 4016, E_NOTICE, __( 'User created a custom field value for a user', 'wp-security-audit-log' ), __( 'Created the value of the custom field %custom_field_name% with %new_value% for the user %TargetUsername%.', 'wp-security-audit-log' ) ),
286
+ ),
287
  ),
288
  __('Third Party Support', 'wp-security-audit-log') => array(
289
  __('BBPress Forum', 'wp-security-audit-log') => array(
readme.txt CHANGED
@@ -6,8 +6,8 @@ License: GPLv3
6
  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.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
 
@@ -115,6 +115,7 @@ WP Security Audit Log plugin also has a number of features that make WordPress a
115
 
116
  = As Featured On: =
117
 
 
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/)
@@ -187,6 +188,25 @@ Please refer to the [FAQs page](https://www.wpsecurityauditlog.com/documentation
187
 
188
  == Changelog ==
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  = 2.6.5 (2017-07-18) =
191
 
192
  * **New Audit Trail Alerts**
6
  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.1
10
+ Stable tag: 2.6.6
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
 
115
 
116
  = As Featured On: =
117
 
118
+ * [WP Couple](https://wpcouple.com/wordpress-audit-logs/)
119
  * [WPLift](http://wplift.com/audit-wordpress-security-logs) - Review by Ahmad Awais
120
  * [WP SmackDown](https://wpsmackdown.com/wp-plugins/wp-security-audit-log/)
121
  * [WPKube](http://www.wpkube.com/improve-wordpress-security-wp-security-audit-log/)
188
 
189
  == Changelog ==
190
 
191
+ = 2.6.6 (2017-08-30 =
192
+
193
+ * **New Audit Trail Alerts**
194
+ * Alert 4015 for when a user creates a custom field in a user profile.
195
+ * Alert 4016 for when a user updates a custom field value in a user profile.
196
+
197
+ * **New Feature**
198
+ * Logging of changes in custom fields (in posts, pages, custom post types, user profiles) created by Advanced Custom Fields (ACF) or similar plugins.
199
+ * New option to show either the Username or Firstname and Lastname of the user in the Audit Trail.
200
+
201
+ * **Improvements**
202
+ * 404 errors logfiles are now saved in /uploads/wp-security-audit-log/404s/ directory.
203
+ * Changed the 404 errors logfile name format to [alert]_[yyyymmdd].log. Thanks to [Enable Security](https://www.enablesecurity.com/) for PoC of vulnerability and advise.
204
+ * Removed link to view post from Alerts about permanently deleted posts (2008, 2009, 2033).
205
+ * Added tooltip for filter via IP address.
206
+
207
+ * **Bug Fix**
208
+ * Fixed an issue where the viewing of content was not being logged when Yoast SEO is installed.
209
+
210
  = 2.6.5 (2017-07-18) =
211
 
212
  * **New Audit Trail Alerts**
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.5
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpsecurityauditlog.com/
10
  License: GPL2
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.6
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpsecurityauditlog.com/
10
  License: GPL2