WP Security Audit Log - Version 1.2.5

Version Description

(2014-08-12) = * New Feature * Monitoring of custom fields in WordPress posts, pages and custom post types.

  • New WordPress Security Alerts

    • Alert 2053: User created new custom field in blog post
    • Alert 2054: User modified the value of custom field in blog post
    • Alert 2055: User deleted a custom field in blog post
    • Alert 2062: User renamed custom field in blog post
    • Alert 2059: User created new custom field in page
    • Alert 2060: User modified the value of custom field in page
    • Alert 2061: User deleted custom field from page
    • Alert 2063: User renamed custom field in
    • Alert 2056: User created new custom field in custom post type
    • Alert 2057: User modified the value of custom field in custom post type
    • Alert 2058: User deleted a custom field from custom post type
    • Alert 2064: User renamed custom field in custom post type
  • Improvements

    • Improved the writing and reading of WordPress alerts from the WordPress database (plugin runs more efficiently on high traffic WordPress and WordPress multisite installations)
    • Improved the monitoring of WordPress login and logout actions
    • Applied various plugin performance tweaks
  • Bug Fixes

    • Fixed a specific issue where user and user role where not being reported (ticket)
    • Fixed an error which was being reported during user logout in specific scenarios (ticket)
    • Fixed a CSRF vulnerability reported by Kvin FALCOZ aka 0pc0deFR
Download this release

Release Info

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

Code changes from version 1.2.4 to 1.2.5

classes/AbstractView.php CHANGED
@@ -84,4 +84,12 @@ abstract class WSAL_AbstractView {
84
  return false;
85
  }
86
 
 
 
 
 
 
 
 
 
87
  }
84
  return false;
85
  }
86
 
87
+ /**
88
+ * @return string URL to backend page for displaying view.
89
+ */
90
+ public function GetUrl(){
91
+ $fn = function_exists('network_admin_url') ? 'network_admin_url' : 'admin_url';
92
+ return $fn('admin.php?page=' . $this->GetSafeViewName());
93
+ }
94
+
95
  }
classes/Alert.php CHANGED
@@ -71,7 +71,7 @@ final class WSAL_Alert {
71
  $mesg = preg_split('/(%.*?%)/', (string)$origMesg, -1, PREG_SPLIT_DELIM_CAPTURE);
72
  if(!is_array($mesg))return (string)$origMesg;
73
  // handle tokenized message
74
- foreach($mesg as $i=>$token){
75
  // handle escaped percent sign
76
  if($token == '%%'){
77
  $mesg[$i] = '%';
71
  $mesg = preg_split('/(%.*?%)/', (string)$origMesg, -1, PREG_SPLIT_DELIM_CAPTURE);
72
  if(!is_array($mesg))return (string)$origMesg;
73
  // handle tokenized message
74
+ foreach($mesg as $i => $token){
75
  // handle escaped percent sign
76
  if($token == '%%'){
77
  $mesg[$i] = '%';
classes/AlertManager.php CHANGED
@@ -212,7 +212,7 @@ final class WSAL_AlertManager {
212
  $data['ClientIP'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
213
  if(!isset($data['UserAgent']))
214
  $data['UserAgent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
215
- if(!isset($data['CurrentUserID']))
216
  $data['CurrentUserID'] = function_exists('get_current_user_id') ? get_current_user_id() : 0;
217
  if(!isset($data['CurrentUserRoles']) && function_exists('is_user_logged_in') && is_user_logged_in())
218
  $data['CurrentUserRoles'] = wp_get_current_user()->roles;
212
  $data['ClientIP'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
213
  if(!isset($data['UserAgent']))
214
  $data['UserAgent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
215
+ if(!isset($data['Username']) && !isset($data['CurrentUserID']))
216
  $data['CurrentUserID'] = function_exists('get_current_user_id') ? get_current_user_id() : 0;
217
  if(!isset($data['CurrentUserRoles']) && function_exists('is_user_logged_in') && is_user_logged_in())
218
  $data['CurrentUserRoles'] = wp_get_current_user()->roles;
classes/DB/Occurrence.php CHANGED
@@ -32,7 +32,7 @@ class WSAL_DB_Occurrence extends WSAL_DB_ActiveRecord {
32
  /**
33
  * Loads a meta item given its name.
34
  * @param string $name Meta name.
35
- * @return \WSAL_DB_Meta The meta item, be sure to checked if it was loaded successfully.
36
  */
37
  public function GetNamedMeta($name){
38
  $meta = new WSAL_DB_Meta();
@@ -43,12 +43,12 @@ class WSAL_DB_Occurrence extends WSAL_DB_ActiveRecord {
43
  /**
44
  * Returns the first meta value from a given set of names. Useful when you have a mix of items that could provide a particular detail.
45
  * @param array $names List of meta names.
46
- * @return \WSAL_DB_Meta The first meta item that exists.
47
  */
48
  public function GetFirstNamedMeta($names){
49
  $meta = new WSAL_DB_Meta();
50
  $query = '(' . str_repeat('name = %s OR ', count($names)).'0)';
51
- $query = 'occurrence_id = %d AND ' . $query . ' LIMIT 1';
52
  array_unshift($names, $this->id); // prepend args with occurrence id
53
  $meta->Load($query, $names);
54
  return $meta->IsLoaded() ? $meta : null;
32
  /**
33
  * Loads a meta item given its name.
34
  * @param string $name Meta name.
35
+ * @return WSAL_DB_Meta The meta item, be sure to checked if it was loaded successfully.
36
  */
37
  public function GetNamedMeta($name){
38
  $meta = new WSAL_DB_Meta();
43
  /**
44
  * Returns the first meta value from a given set of names. Useful when you have a mix of items that could provide a particular detail.
45
  * @param array $names List of meta names.
46
+ * @return WSAL_DB_Meta The first meta item that exists.
47
  */
48
  public function GetFirstNamedMeta($names){
49
  $meta = new WSAL_DB_Meta();
50
  $query = '(' . str_repeat('name = %s OR ', count($names)).'0)';
51
+ $query = 'occurrence_id = %d AND ' . $query . ' ORDER BY name DESC LIMIT 1';
52
  array_unshift($names, $this->id); // prepend args with occurrence id
53
  $meta->Load($query, $names);
54
  return $meta->IsLoaded() ? $meta : null;
classes/EDD_SL_Plugin_Updater.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // uncomment this line for testing
4
+ //set_site_transient( 'update_plugins', null );
5
+
6
+ /**
7
+ * Allows plugins to use their own update API.
8
+ *
9
+ * @author Pippin Williamson
10
+ * @version 1.2
11
+ */
12
+ class EDD_SL_Plugin_Updater {
13
+ private $api_url = '';
14
+ private $api_data = array();
15
+ private $name = '';
16
+ private $slug = '';
17
+ private $do_check = false;
18
+
19
+ /**
20
+ * Class constructor.
21
+ *
22
+ * @uses plugin_basename()
23
+ * @uses hook()
24
+ *
25
+ * @param string $_api_url The URL pointing to the custom API endpoint.
26
+ * @param string $_plugin_file Path to the plugin file.
27
+ * @param array $_api_data Optional data to send with API calls.
28
+ * @return void
29
+ */
30
+ function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
31
+ $this->api_url = trailingslashit( $_api_url );
32
+ $this->api_data = urlencode_deep( $_api_data );
33
+ $this->name = plugin_basename( $_plugin_file );
34
+ $this->slug = basename( $_plugin_file, '.php');
35
+ $this->version = $_api_data['version'];
36
+
37
+ // Set up hooks.
38
+ $this->hook();
39
+ }
40
+
41
+ /**
42
+ * Set up WordPress filters to hook into WP's update process.
43
+ *
44
+ * @uses add_filter()
45
+ *
46
+ * @return void
47
+ */
48
+ private function hook() {
49
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins_filter' ) );
50
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
51
+ add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
52
+ }
53
+
54
+ /**
55
+ * Check for Updates at the defined API endpoint and modify the update array.
56
+ *
57
+ * This function dives into the update API just when WordPress creates its update array,
58
+ * then adds a custom API call and injects the custom plugin data retrieved from the API.
59
+ * It is reassembled from parts of the native WordPress plugin update code.
60
+ * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
61
+ *
62
+ * @uses api_request()
63
+ *
64
+ * @param array $_transient_data Update array build by WordPress.
65
+ * @return array Modified update array with custom plugin data.
66
+ */
67
+ function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
68
+
69
+ if( empty( $_transient_data ) || ! $this->do_check ) {
70
+
71
+ // This ensures that the custom API request only runs on the second time that WP fires the update check
72
+ $this->do_check = true;
73
+
74
+ return $_transient_data;
75
+ }
76
+
77
+ $to_send = array( 'slug' => $this->slug );
78
+
79
+ $api_response = $this->api_request( 'plugin_latest_version', $to_send );
80
+
81
+ if( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
82
+
83
+ if( version_compare( $this->version, $api_response->new_version, '<' ) ) {
84
+ $_transient_data->response[$this->name] = $api_response;
85
+ }
86
+ }
87
+ return $_transient_data;
88
+ }
89
+
90
+
91
+ /**
92
+ * Updates information on the "View version x.x details" page with custom data.
93
+ *
94
+ * @uses api_request()
95
+ *
96
+ * @param mixed $_data
97
+ * @param string $_action
98
+ * @param object $_args
99
+ * @return object $_data
100
+ */
101
+ function plugins_api_filter( $_data, $_action = '', $_args = null ) {
102
+ if ( ( $_action != 'plugin_information' ) || !isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) return $_data;
103
+
104
+ $to_send = array( 'slug' => $this->slug );
105
+
106
+ $api_response = $this->api_request( 'plugin_information', $to_send );
107
+ if ( false !== $api_response ) $_data = $api_response;
108
+
109
+ return $_data;
110
+ }
111
+
112
+
113
+ /**
114
+ * Disable SSL verification in order to prevent download update failures
115
+ *
116
+ * @param array $args
117
+ * @param string $url
118
+ * @return object $array
119
+ */
120
+ function http_request_args( $args, $url ) {
121
+ // If it is an https request and we are performing a package download, disable ssl verification
122
+ if( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
123
+ $args['sslverify'] = false;
124
+ }
125
+ return $args;
126
+ }
127
+
128
+ /**
129
+ * Calls the API and, if successfull, returns the object delivered by the API.
130
+ *
131
+ * @uses get_bloginfo()
132
+ * @uses wp_remote_post()
133
+ * @uses is_wp_error()
134
+ *
135
+ * @param string $_action The requested action.
136
+ * @param array $_data Parameters for the API action.
137
+ * @return false||object
138
+ */
139
+ private function api_request( $_action, $_data ) {
140
+
141
+ global $wp_version;
142
+
143
+ $data = array_merge( $this->api_data, $_data );
144
+
145
+ if( $data['slug'] != $this->slug )
146
+ return;
147
+
148
+ if( empty( $data['license'] ) )
149
+ return;
150
+
151
+ $api_params = array(
152
+ 'edd_action' => 'get_version',
153
+ 'license' => $data['license'],
154
+ 'name' => $data['item_name'],
155
+ 'slug' => $this->slug,
156
+ 'author' => $data['author'],
157
+ 'url' => home_url()
158
+ );
159
+ $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
160
+
161
+ if ( ! is_wp_error( $request ) ):
162
+ $request = json_decode( wp_remote_retrieve_body( $request ) );
163
+ if( $request && isset( $request->sections ) )
164
+ $request->sections = maybe_unserialize( $request->sections );
165
+ return $request;
166
+ else:
167
+ return false;
168
+ endif;
169
+ }
170
+ }
classes/LicenseManager.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // since other plugins might use this class
4
+ if(!class_exists('EDD_SL_Plugin_Updater')){
5
+ require_once('EDD_SL_Plugin_Updater.php');
6
+ }
7
+
8
+ class WSAL_LicenseManager {
9
+ /**
10
+ * @var WpSecurityAuditLog
11
+ */
12
+ protected $plugin;
13
+
14
+ public $plugins = array();
15
+
16
+ public function __construct(WpSecurityAuditLog $plugin){
17
+ $this->plugin = $plugin;
18
+ }
19
+
20
+ protected function GetStoreUrl(){
21
+ return 'http://wpwhitesecurity.com/';
22
+ }
23
+
24
+ public function CountPlugins(){
25
+ return count($this->plugins);
26
+ }
27
+
28
+ public function AddPremiumPlugin($pluginFile){
29
+ $name = sanitize_key($pluginFile);
30
+ $pluginData = get_plugin_data($pluginFile);
31
+
32
+ $this->plugins[$name] = array(
33
+ 'PluginData' => $pluginData,
34
+ 'EddUpdater' => new EDD_SL_Plugin_Updater(
35
+ $this->GetStoreUrl(),
36
+ $pluginFile,
37
+ array(
38
+ 'license' => $this->plugin->settings->GetLicenseKey($name),
39
+ 'item_name' => $pluginData['Name'],
40
+ 'author' => $pluginData['Author'],
41
+ 'version' => $pluginData['Version'],
42
+ )
43
+ ),
44
+ );
45
+ }
46
+
47
+ public function ActivateLicense($name, $license){
48
+ $this->plugin->settings->SetLicenseKey($name, $license);
49
+
50
+ $api_params = array(
51
+ 'edd_action'=> 'activate_license',
52
+ 'license' => $license,
53
+ 'item_name' => urlencode($name),
54
+ 'url' => home_url()
55
+ );
56
+
57
+ $response = wp_remote_get(
58
+ add_query_arg($api_params, $this->GetStoreUrl()),
59
+ array('timeout' => 15, 'sslverify' => false)
60
+ );
61
+
62
+ if (is_wp_error($response)) {
63
+ $this->plugin->settings->SetLicenseErrors($name, 'Invalid Licensing Server Response');
64
+ return false;
65
+ }
66
+
67
+ $license_data = json_decode( wp_remote_retrieve_body( $response ) );
68
+
69
+ if(is_object($license_data)){
70
+ $this->plugin->settings->SetLicenseStatus($name, $license_data->license);
71
+ if($license_data->license !== 'valid')
72
+ $this->plugin->settings->SetLicenseErrors($name, 'License Not Valid');
73
+ }else{
74
+ $this->plugin->settings->SetLicenseErrors($name, 'Unexpected Licensing Server Response');
75
+ }
76
+
77
+ return true;
78
+ }
79
+
80
+ public function DeactivateLicense($name){
81
+ $this->plugin->settings->SetLicenseStatus($name, '');
82
+ }
83
+ }
classes/Sensors/LogInOut.php CHANGED
@@ -6,6 +6,13 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
6
  add_action('wp_login', array($this, 'EventLogin'), 10, 2);
7
  add_action('wp_logout', array($this, 'EventLogout'));
8
  add_action('wp_login_failed', array($this, 'EventLoginFailure'));
 
 
 
 
 
 
 
9
  }
10
 
11
  public function EventLogin($user_login, $user){
@@ -16,7 +23,10 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
16
  }
17
 
18
  public function EventLogout(){
19
- $this->plugin->alerts->Trigger(1001);
 
 
 
20
  }
21
 
22
  const TRANSIENT_FAILEDLOGINS = 'wsal-failedlogins';
@@ -31,7 +41,7 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
31
 
32
  protected function IsPastLoginFailureLimit($ip){
33
  $data = get_transient(self::TRANSIENT_FAILEDLOGINS);
34
- return ($data !== false) && ($data[$ip] > ($this->GetLoginFailureLogLimit()));
35
  }
36
 
37
  protected function IncrementLoginFailure($ip){
6
  add_action('wp_login', array($this, 'EventLogin'), 10, 2);
7
  add_action('wp_logout', array($this, 'EventLogout'));
8
  add_action('wp_login_failed', array($this, 'EventLoginFailure'));
9
+ add_action('clear_auth_cookie', array($this, 'GetCurrentUser'), 10);
10
+ }
11
+
12
+ protected $_current_user = null;
13
+
14
+ public function GetCurrentUser(){
15
+ $this->_current_user = wp_get_current_user();
16
  }
17
 
18
  public function EventLogin($user_login, $user){
23
  }
24
 
25
  public function EventLogout(){
26
+ $this->plugin->alerts->Trigger(1001, array(
27
+ 'CurrentUserID' => $this->_current_user->ID,
28
+ 'CurrentUserRoles' => $this->_current_user->roles,
29
+ ));
30
  }
31
 
32
  const TRANSIENT_FAILEDLOGINS = 'wsal-failedlogins';
41
 
42
  protected function IsPastLoginFailureLimit($ip){
43
  $data = get_transient(self::TRANSIENT_FAILEDLOGINS);
44
+ return ($data !== false) && isset($data[$ip]) && ($data[$ip] > $this->GetLoginFailureLogLimit());
45
  }
46
 
47
  protected function IncrementLoginFailure($ip){
classes/Sensors/MetaData.php CHANGED
@@ -3,17 +3,23 @@
3
  class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
6
- /*add_action('added_post_meta', array($this, 'EventPostMetaCreated'), 10, 4);
7
  add_action('update_post_meta', array($this, 'EventPostMetaUpdating'), 10, 3);
8
  add_action('updated_post_meta', array($this, 'EventPostMetaUpdated'), 10, 4);
9
- add_action('deleted_post_meta', array($this, 'EventPostMetaDeleted'), 10, 4);*/
10
  }
11
 
12
  protected $old_meta = array();
13
 
 
 
 
 
14
  public function EventPostMetaCreated($meta_id, $object_id, $meta_key, $_meta_value){
15
  $post = get_post($object_id);
16
 
 
 
17
  switch($post->post_type){
18
  case 'page':
19
  $this->plugin->alerts->Trigger(2059, array(
@@ -47,16 +53,22 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
47
  }
48
 
49
  public function EventPostMetaUpdating($meta_id, $object_id, $meta_key){
50
- $this->old_meta[$meta_id] = array($meta_key, get_metadata('post', $object_id, $meta_key, true));
 
 
 
 
51
  }
52
 
53
  public function EventPostMetaUpdated($meta_id, $object_id, $meta_key, $_meta_value){
54
  $post = get_post($object_id);
55
 
 
 
56
  if(isset($this->old_meta[$meta_id])){
57
 
58
  // check change in meta key
59
- if($this->old_meta[$meta_id][0] != $meta_key){
60
  switch($post->post_type){
61
  case 'page':
62
  $this->plugin->alerts->Trigger(2064, array(
@@ -64,7 +76,7 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
64
  'PostTitle' => $post->post_title,
65
  'MetaID' => $meta_id,
66
  'MetaKeyNew' => $meta_key,
67
- 'MetaKeyOld' => $this->old_meta[$meta_id][0],
68
  'MetaValue' => $_meta_value,
69
  ));
70
  break;
@@ -74,7 +86,7 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
74
  'PostTitle' => $post->post_title,
75
  'MetaID' => $meta_id,
76
  'MetaKeyNew' => $meta_key,
77
- 'MetaKeyOld' => $this->old_meta[$meta_id][0],
78
  'MetaValue' => $_meta_value,
79
  ));
80
  break;
@@ -85,15 +97,15 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
85
  'PostType' => $post->post_type,
86
  'MetaID' => $meta_id,
87
  'MetaKeyNew' => $meta_key,
88
- 'MetaKeyOld' => $this->old_meta[$meta_id][0],
89
  'MetaValue' => $_meta_value,
90
  ));
91
  break;
92
  }
93
  }
94
-
95
  // check change in meta value
96
- if($this->old_meta[$meta_id][1] != $_meta_value){
97
  switch($post->post_type){
98
  case 'page':
99
  $this->plugin->alerts->Trigger(2060, array(
@@ -102,7 +114,7 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
102
  'MetaID' => $meta_id,
103
  'MetaKey' => $meta_key,
104
  'MetaValueNew' => $_meta_value,
105
- 'MetaValueOld' => $this->old_meta[$meta_id][1],
106
  ));
107
  break;
108
  case 'post':
@@ -112,7 +124,7 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
112
  'MetaID' => $meta_id,
113
  'MetaKey' => $meta_key,
114
  'MetaValueNew' => $_meta_value,
115
- 'MetaValueOld' => $this->old_meta[$meta_id][1],
116
  ));
117
  break;
118
  default:
@@ -123,7 +135,7 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
123
  'MetaID' => $meta_id,
124
  'MetaKey' => $meta_key,
125
  'MetaValueNew' => $_meta_value,
126
- 'MetaValueOld' => $this->old_meta[$meta_id][1],
127
  ));
128
  break;
129
  }
@@ -136,7 +148,11 @@ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
136
 
137
  public function EventPostMetaDeleted($meta_ids, $object_id, $meta_key, $_meta_value){
138
  $post = get_post($object_id);
 
139
  foreach($meta_ids as $meta_id){
 
 
 
140
  switch($post->post_type){
141
  case 'page':
142
  $this->plugin->alerts->Trigger(2061, array(
3
  class WSAL_Sensors_MetaData extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
6
+ add_action('added_post_meta', array($this, 'EventPostMetaCreated'), 10, 4);
7
  add_action('update_post_meta', array($this, 'EventPostMetaUpdating'), 10, 3);
8
  add_action('updated_post_meta', array($this, 'EventPostMetaUpdated'), 10, 4);
9
+ add_action('deleted_post_meta', array($this, 'EventPostMetaDeleted'), 10, 4);
10
  }
11
 
12
  protected $old_meta = array();
13
 
14
+ protected function CanLogPostMeta($meta_id, $object_id, $meta_key){
15
+ return substr($meta_key, 0, 1) != '_';
16
+ }
17
+
18
  public function EventPostMetaCreated($meta_id, $object_id, $meta_key, $_meta_value){
19
  $post = get_post($object_id);
20
 
21
+ if(!$this->CanLogPostMeta($meta_id, $object_id, $meta_key))return;
22
+
23
  switch($post->post_type){
24
  case 'page':
25
  $this->plugin->alerts->Trigger(2059, array(
53
  }
54
 
55
  public function EventPostMetaUpdating($meta_id, $object_id, $meta_key){
56
+ static $meta_type = 'post';
57
+ $this->old_meta[$meta_id] = (object)array(
58
+ 'key' => ($meta = get_metadata_by_mid($meta_type, $meta_id)) ? $meta->meta_key : $meta_key,
59
+ 'val' => get_metadata($meta_type, $object_id, $meta_key, true),
60
+ );
61
  }
62
 
63
  public function EventPostMetaUpdated($meta_id, $object_id, $meta_key, $_meta_value){
64
  $post = get_post($object_id);
65
 
66
+ if(!$this->CanLogPostMeta($meta_id, $object_id, $meta_key))return;
67
+
68
  if(isset($this->old_meta[$meta_id])){
69
 
70
  // check change in meta key
71
+ if($this->old_meta[$meta_id]->key != $meta_key){
72
  switch($post->post_type){
73
  case 'page':
74
  $this->plugin->alerts->Trigger(2064, array(
76
  'PostTitle' => $post->post_title,
77
  'MetaID' => $meta_id,
78
  'MetaKeyNew' => $meta_key,
79
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
80
  'MetaValue' => $_meta_value,
81
  ));
82
  break;
86
  'PostTitle' => $post->post_title,
87
  'MetaID' => $meta_id,
88
  'MetaKeyNew' => $meta_key,
89
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
90
  'MetaValue' => $_meta_value,
91
  ));
92
  break;
97
  'PostType' => $post->post_type,
98
  'MetaID' => $meta_id,
99
  'MetaKeyNew' => $meta_key,
100
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
101
  'MetaValue' => $_meta_value,
102
  ));
103
  break;
104
  }
105
  }
106
+ else
107
  // check change in meta value
108
+ if($this->old_meta[$meta_id]->val != $_meta_value){
109
  switch($post->post_type){
110
  case 'page':
111
  $this->plugin->alerts->Trigger(2060, array(
114
  'MetaID' => $meta_id,
115
  'MetaKey' => $meta_key,
116
  'MetaValueNew' => $_meta_value,
117
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
118
  ));
119
  break;
120
  case 'post':
124
  'MetaID' => $meta_id,
125
  'MetaKey' => $meta_key,
126
  'MetaValueNew' => $_meta_value,
127
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
128
  ));
129
  break;
130
  default:
135
  'MetaID' => $meta_id,
136
  'MetaKey' => $meta_key,
137
  'MetaValueNew' => $_meta_value,
138
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
139
  ));
140
  break;
141
  }
148
 
149
  public function EventPostMetaDeleted($meta_ids, $object_id, $meta_key, $_meta_value){
150
  $post = get_post($object_id);
151
+
152
  foreach($meta_ids as $meta_id){
153
+
154
+ if(!$this->CanLogPostMeta($meta_id, $object_id, $meta_key))continue;
155
+
156
  switch($post->post_type){
157
  case 'page':
158
  $this->plugin->alerts->Trigger(2061, array(
classes/Settings.php CHANGED
@@ -377,4 +377,57 @@ class WSAL_Settings {
377
  public function SetIncognito($enabled){
378
  return $this->_plugin->SetGlobalOption('hide-plugin', $enabled);
379
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  }
377
  public function SetIncognito($enabled){
378
  return $this->_plugin->SetGlobalOption('hide-plugin', $enabled);
379
  }
380
+
381
+ public function GetLicenses(){
382
+ return $this->_plugin->GetGlobalOption('licenses');
383
+ }
384
+
385
+ public function GetLicense($name){
386
+ $data = $this->GetLicenses();
387
+ return isset($data[$name]) ? $data[$name] : array();
388
+ }
389
+
390
+ public function SetLicenses($data){
391
+ $this->_plugin->SetGlobalOption('licenses', $data);
392
+ }
393
+
394
+ public function GetLicenseKey($name){
395
+ $data = $this->GetLicense($name);
396
+ return isset($data['key']) ? $data['key'] : '';
397
+ }
398
+
399
+ public function GetLicenseStatus($name){
400
+ $data = $this->GetLicense($name);
401
+ return isset($data['sts']) ? $data['sts'] : '';
402
+ }
403
+
404
+ public function GetLicenseErrors($name){
405
+ $data = $this->GetLicense($name);
406
+ return isset($data['err']) ? $data['err'] : '';
407
+ }
408
+
409
+ public function SetLicenseKey($name, $key){
410
+ $data = $this->GetLicenses();
411
+ if (!isset($data[$name])) $data[$name] = array();
412
+ $data[$name]['key'] = $key;
413
+ $this->SetLicenses($data);
414
+ }
415
+
416
+ public function SetLicenseStatus($name, $status){
417
+ $data = $this->GetLicenses();
418
+ if (!isset($data[$name])) $data[$name] = array();
419
+ $data[$name]['sts'] = $status;
420
+ $this->SetLicenses($data);
421
+ }
422
+
423
+ public function SetLicenseErrors($name, $errors){
424
+ $data = $this->GetLicenses();
425
+ if (!isset($data[$name])) $data[$name] = array();
426
+ $data[$name]['err'] = $errors;
427
+ $this->SetLicenses($data);
428
+ }
429
+
430
+ public function ClearLicenses(){
431
+ $this->SetLicenses(array());
432
+ }
433
  }
classes/Views/AuditLog.php CHANGED
@@ -376,6 +376,11 @@ class WSAL_Views_AuditLogList_Internal extends WP_List_Table {
376
 
377
  case $name == '%Message%':
378
  return esc_html($value);
 
 
 
 
 
379
 
380
  case strncmp($value, 'http://', 7) === 0:
381
  case strncmp($value, 'https://', 7) === 0:
376
 
377
  case $name == '%Message%':
378
  return esc_html($value);
379
+
380
+ case in_array($name, array('%MetaValue%', '%MetaValueOld%', '%MetaValueNew%')):
381
+ return '<strong>' . (
382
+ strlen($value) > 50 ? (esc_html(substr($value, 0, 50)) . '&hellip;') : esc_html($value)
383
+ ) . '</strong>';
384
 
385
  case strncmp($value, 'http://', 7) === 0:
386
  case strncmp($value, 'https://', 7) === 0:
classes/Views/Licensing.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WSAL_Views_Licensing extends WSAL_AbstractView {
4
+
5
+ public function GetTitle() {
6
+ return __('Licensing', 'wp-security-audit-log');
7
+ }
8
+
9
+ public function GetIcon() {
10
+ return 'dashicons-cart';
11
+ }
12
+
13
+ public function GetName() {
14
+ return __('Licensing', 'wp-security-audit-log');
15
+ }
16
+
17
+ public function GetWeight() {
18
+ return 4;
19
+ }
20
+
21
+ public function IsAccessible(){
22
+ return !!$this->_plugin->licensing->CountPlugins();
23
+ }
24
+
25
+ protected function Save(){
26
+ $this->_plugin->settings->ClearLicenses();
27
+ if (isset($_REQUEST['license']))
28
+ foreach ($_REQUEST['license'] as $name => $key)
29
+ $this->_plugin->licensing->ActivateLicense($name, $key);
30
+ }
31
+
32
+ public function Render(){
33
+ if(!$this->_plugin->settings->CurrentUserCan('edit')){
34
+ wp_die( __( 'You do not have sufficient permissions to access this page.' , 'wp-security-audit-log') );
35
+ }
36
+ if(isset($_POST['submit'])){
37
+ try {
38
+ $this->Save();
39
+ ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
40
+ }catch(Exception $ex){
41
+ ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
42
+ }
43
+ }
44
+ ?><form id="audit-log-licensing" method="post">
45
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
46
+
47
+ <table class="wp-list-table widefat fixed">
48
+ <thead>
49
+ <tr><th>Plugin</th><th>License</th><th></th></tr>
50
+ </thead><tbody>
51
+ <?php $counter = 0; ?>
52
+ <?php foreach($this->_plugin->licensing->plugins as $name => $plugin){ ?>
53
+ <?php $licenseKey = trim($this->_plugin->settings->GetLicenseKey($name)); ?>
54
+ <?php $licenseStatus = trim($this->_plugin->settings->GetLicenseStatus($name)); ?>
55
+ <?php $licenseErrors = trim($this->_plugin->settings->GetLicenseErrors($name)); ?>
56
+ <tr class="<?php echo ($counter++ % 2 === 0) ? 'alternate' : ''; ?>">
57
+ <td>
58
+ <a href="<?php echo esc_attr($plugin['PluginData']['PluginURI']); ?>" target="_blank">
59
+ <?php echo esc_html($plugin['PluginData']['Name']); ?>
60
+ </a><br/><small><b>
61
+ <?php _e('Version', 'wp-security-audit-log'); ?>
62
+ <?php echo esc_html($plugin['PluginData']['Version']); ?>
63
+ </b></small>
64
+ </td><td>
65
+ <input type="text" style="width: 360px; margin: 6px 0;"
66
+ name="license[<?php echo esc_attr($name); ?>]"
67
+ value="<?php echo esc_attr($licenseKey); ?>"/>
68
+ </td><td>
69
+ <?php if($licenseKey){ ?>
70
+ <?php if($licenseStatus === 'valid'){ ?>
71
+ <?php _e('Active', 'wp-security-audit-log'); ?>
72
+ <?php }else{ ?>
73
+ <?php _e('Inactive', 'wp-security-audit-log'); ?><br/>
74
+ <small><?php echo esc_html($licenseErrors); ?></small>
75
+ <?php } ?>
76
+ <?php } ?>
77
+ </td>
78
+ </tr>
79
+ <?php } ?>
80
+ </tbody><tfoot>
81
+ <tr><th>Plugin</th><th>License</th><th></th></tr>
82
+ </tfoot>
83
+ </table>
84
+ <?php submit_button(); ?>
85
+ </form><?php
86
+ }
87
+
88
+ }
classes/Views/Settings.php CHANGED
@@ -39,6 +39,7 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
39
  }
40
 
41
  protected function Save(){
 
42
  $this->_plugin->settings->SetPruningDateEnabled(isset($_REQUEST['PruneByDate']));
43
  $this->_plugin->settings->SetPruningDate($_REQUEST['PruningDate']);
44
  $this->_plugin->settings->SetPruningLimitEnabled(isset($_REQUEST['PruneByLimit']));
@@ -77,6 +78,7 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
77
  ?><form id="audit-log-settings" method="post">
78
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
79
  <input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
 
80
 
81
  <table class="form-table">
82
  <tbody>
@@ -212,7 +214,7 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
212
  onclick="jQuery(this).hide().next().show();">Show Developer Options</a>
213
  <div style="<?php if(!$any)echo 'display: none;'; ?>">
214
  <p style="border-left: 3px solid #FFD000; padding: 2px 8px; margin-left: 6px; margin-bottom: 16px;"><?php
215
- _e('Enabling any of the settings below may cause unintended side-effects including degraded performance.<br/>Only enable these options if you know what you are doing.', 'wp-security-audit-log');
216
  ?></p><?php
217
  foreach(array(
218
  WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array(
39
  }
40
 
41
  protected function Save(){
42
+ check_admin_referer('wsal-settings');
43
  $this->_plugin->settings->SetPruningDateEnabled(isset($_REQUEST['PruneByDate']));
44
  $this->_plugin->settings->SetPruningDate($_REQUEST['PruningDate']);
45
  $this->_plugin->settings->SetPruningLimitEnabled(isset($_REQUEST['PruneByLimit']));
78
  ?><form id="audit-log-settings" method="post">
79
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
80
  <input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
81
+ <?php wp_nonce_field('wsal-settings'); ?>
82
 
83
  <table class="form-table">
84
  <tbody>
214
  onclick="jQuery(this).hide().next().show();">Show Developer Options</a>
215
  <div style="<?php if(!$any)echo 'display: none;'; ?>">
216
  <p style="border-left: 3px solid #FFD000; padding: 2px 8px; margin-left: 6px; margin-bottom: 16px;"><?php
217
+ _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');
218
  ?></p><?php
219
  foreach(array(
220
  WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array(
classes/Views/ToggleAlerts.php CHANGED
@@ -33,6 +33,7 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView {
33
  $safeNames = array_map(array($this, 'GetSafeCatgName'), array_keys($groupedAlerts));
34
  $safeNames = array_combine(array_keys($groupedAlerts), $safeNames);
35
  if(isset($_POST['submit']) && isset($_POST['alert'])){
 
36
  try {
37
  $enabled = array_map('intval', $_POST['alert']);
38
  $disabled = array();
@@ -52,6 +53,8 @@ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView {
52
  ?></h2>
53
  <form id="audit-log-viewer" method="post">
54
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
 
 
55
  <div class="nav-tabs"><?php
56
  foreach($groupedAlerts as $name => $alerts){
57
  $active = array(); $allactive = true;
33
  $safeNames = array_map(array($this, 'GetSafeCatgName'), array_keys($groupedAlerts));
34
  $safeNames = array_combine(array_keys($groupedAlerts), $safeNames);
35
  if(isset($_POST['submit']) && isset($_POST['alert'])){
36
+ check_admin_referer('wsal-togglealerts');
37
  try {
38
  $enabled = array_map('intval', $_POST['alert']);
39
  $disabled = array();
53
  ?></h2>
54
  <form id="audit-log-viewer" method="post">
55
  <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
56
+ <?php wp_nonce_field('wsal-togglealerts'); ?>
57
+
58
  <div class="nav-tabs"><?php
59
  foreach($groupedAlerts as $name => $alerts){
60
  $active = array(); $allactive = true;
languages/wp-security-audit-log-it_IT.mo CHANGED
Binary file
languages/wp-security-audit-log.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the WP Security Audit Log package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WP Security Audit Log 1.2.3\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/wp-security-audit-log\n"
7
- "POT-Creation-Date: 2014-07-23 10:21:20+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -140,8 +140,8 @@ msgstr ""
140
  msgid "Audit Log Viewer"
141
  msgstr ""
142
 
143
- #: classes/Views/AuditLog.php:40 classes/Views/Settings.php:67
144
- #: classes/Views/ToggleAlerts.php:29
145
  msgid "You do not have sufficient permissions to access this page."
146
  msgstr ""
147
 
@@ -173,11 +173,11 @@ msgstr ""
173
  msgid " Items"
174
  msgstr ""
175
 
176
- #: classes/Views/AuditLog.php:273 classes/Views/ToggleAlerts.php:66
177
  msgid "Code"
178
  msgstr ""
179
 
180
- #: classes/Views/AuditLog.php:274 classes/Views/ToggleAlerts.php:67
181
  msgid "Type"
182
  msgstr ""
183
 
@@ -328,8 +328,34 @@ msgstr ""
328
  msgid "WordPress Security Category"
329
  msgstr ""
330
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  #: classes/Views/Sandbox.php:11 classes/Views/Sandbox.php:19
332
- #: classes/Views/Settings.php:231
333
  msgid "Sandbox"
334
  msgstr ""
335
 
@@ -341,142 +367,134 @@ msgstr ""
341
  msgid "Settings"
342
  msgstr ""
343
 
344
- #: classes/Views/Settings.php:72 classes/Views/ToggleAlerts.php:43
345
- msgid "Settings have been saved."
346
- msgstr ""
347
-
348
- #: classes/Views/Settings.php:74 classes/Views/ToggleAlerts.php:45
349
- msgid "Error: "
350
- msgstr ""
351
-
352
- #: classes/Views/Settings.php:84
353
  msgid "Security Alerts Pruning"
354
  msgstr ""
355
 
356
- #: classes/Views/Settings.php:87
357
  msgid "(eg: 1 month)"
358
  msgstr ""
359
 
360
- #: classes/Views/Settings.php:92
361
  msgid "Delete alerts older than"
362
  msgstr ""
363
 
364
- #: classes/Views/Settings.php:104
365
  msgid "(eg: 80)"
366
  msgstr ""
367
 
368
- #: classes/Views/Settings.php:109
369
  msgid "Keep up to"
370
  msgstr ""
371
 
372
- #: classes/Views/Settings.php:113
373
  msgid "alerts"
374
  msgstr ""
375
 
376
- #: classes/Views/Settings.php:119
377
  msgid "Alerts Dashboard Widget"
378
  msgstr ""
379
 
380
- #: classes/Views/Settings.php:125
381
  msgid "On"
382
  msgstr ""
383
 
384
- #: classes/Views/Settings.php:130
385
  msgid "Off"
386
  msgstr ""
387
 
388
- #: classes/Views/Settings.php:135
389
  msgid "Display a dashboard widget with the latest %d security alerts."
390
  msgstr ""
391
 
392
- #: classes/Views/Settings.php:143
393
  msgid "Can View Alerts"
394
  msgstr ""
395
 
396
- #: classes/Views/Settings.php:150
397
  msgid "Users and Roles in this list can view the security alerts"
398
  msgstr ""
399
 
400
- #: classes/Views/Settings.php:165
401
  msgid "Can Manage Plugin"
402
  msgstr ""
403
 
404
- #: classes/Views/Settings.php:172
405
  msgid "Users and Roles in this list can manage the plugin settings"
406
  msgstr ""
407
 
408
- #: classes/Views/Settings.php:187
409
  msgid "Refresh Audit View"
410
  msgstr ""
411
 
412
- #: classes/Views/Settings.php:193
413
  msgid "Automatic"
414
  msgstr ""
415
 
416
- #: classes/Views/Settings.php:195
417
  msgid "Refresh Audit View as soon as there are new events."
418
  msgstr ""
419
 
420
- #: classes/Views/Settings.php:199
421
  msgid "Manual"
422
  msgstr ""
423
 
424
- #: classes/Views/Settings.php:201
425
  msgid "Refresh Audit View only when page is reloaded."
426
  msgstr ""
427
 
428
- #: classes/Views/Settings.php:207
429
  msgid "Developer Options"
430
  msgstr ""
431
 
432
- #: classes/Views/Settings.php:215
433
  msgid ""
434
- "Enabling any of the settings below may cause unintended side-effects "
435
- "including degraded performance.<br/>Only enable these options if you know "
436
- "what you are doing."
437
  msgstr ""
438
 
439
- #: classes/Views/Settings.php:219
440
  msgid "Data Inspector"
441
  msgstr ""
442
 
443
- #: classes/Views/Settings.php:220
444
  msgid "View data logged for each triggered alert."
445
  msgstr ""
446
 
447
- #: classes/Views/Settings.php:223
448
  msgid "PHP Errors"
449
  msgstr ""
450
 
451
- #: classes/Views/Settings.php:224
452
  msgid "Enables sensor for alerts generated from PHP."
453
  msgstr ""
454
 
455
- #: classes/Views/Settings.php:227
456
  msgid "Request Log"
457
  msgstr ""
458
 
459
- #: classes/Views/Settings.php:228
460
  msgid "Enables logging request to file."
461
  msgstr ""
462
 
463
- #: classes/Views/Settings.php:232
464
  msgid "Enables sandbox for testing PHP code."
465
  msgstr ""
466
 
467
- #: classes/Views/Settings.php:235
468
  msgid "Backtrace"
469
  msgstr ""
470
 
471
- #: classes/Views/Settings.php:236
472
  msgid "Log full backtrace for PHP-generated alerts."
473
  msgstr ""
474
 
475
- #: classes/Views/Settings.php:254
476
  msgid "Hide Plugin from Plugins Page"
477
  msgstr ""
478
 
479
- #: classes/Views/Settings.php:260
480
  msgid "Hide"
481
  msgstr ""
482
 
@@ -484,19 +502,19 @@ msgstr ""
484
  msgid "Enable/Disable Alerts"
485
  msgstr ""
486
 
487
- #: classes/Views/ToggleAlerts.php:68 classes/WidgetManager.php:38
488
  msgid "Description"
489
  msgstr ""
490
 
491
- #: classes/Views/ToggleAlerts.php:76
492
  msgid "Not Implemented"
493
  msgstr ""
494
 
495
- #: classes/Views/ToggleAlerts.php:79
496
  msgid "Not Available"
497
  msgstr ""
498
 
499
- #: classes/Views/ToggleAlerts.php:93
500
  msgid "Save Changes"
501
  msgstr ""
502
 
@@ -1535,7 +1553,7 @@ msgid ""
1535
  ">get_template_directory%"
1536
  msgstr ""
1537
 
1538
- #: wp-security-audit-log.php:142
1539
  msgid ""
1540
  "You are using a version of PHP that is older than %s, which is no longer "
1541
  "supported.<br/>Contact us on <a href=\"mailto:plugins@wpwhitesecurity.com"
2
  # This file is distributed under the same license as the WP Security Audit Log package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WP Security Audit Log 1.2.5\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/wp-security-audit-log\n"
7
+ "POT-Creation-Date: 2014-08-12 08:27:38+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
140
  msgid "Audit Log Viewer"
141
  msgstr ""
142
 
143
+ #: classes/Views/AuditLog.php:40 classes/Views/Licensing.php:34
144
+ #: classes/Views/Settings.php:68 classes/Views/ToggleAlerts.php:29
145
  msgid "You do not have sufficient permissions to access this page."
146
  msgstr ""
147
 
173
  msgid " Items"
174
  msgstr ""
175
 
176
+ #: classes/Views/AuditLog.php:273 classes/Views/ToggleAlerts.php:69
177
  msgid "Code"
178
  msgstr ""
179
 
180
+ #: classes/Views/AuditLog.php:274 classes/Views/ToggleAlerts.php:70
181
  msgid "Type"
182
  msgstr ""
183
 
328
  msgid "WordPress Security Category"
329
  msgstr ""
330
 
331
+ #: classes/Views/Licensing.php:6 classes/Views/Licensing.php:14
332
+ msgid "Licensing"
333
+ msgstr ""
334
+
335
+ #: classes/Views/Licensing.php:39 classes/Views/Settings.php:73
336
+ #: classes/Views/ToggleAlerts.php:44
337
+ msgid "Settings have been saved."
338
+ msgstr ""
339
+
340
+ #: classes/Views/Licensing.php:41 classes/Views/Settings.php:75
341
+ #: classes/Views/ToggleAlerts.php:46
342
+ msgid "Error: "
343
+ msgstr ""
344
+
345
+ #: classes/Views/Licensing.php:61
346
+ msgid "Version"
347
+ msgstr ""
348
+
349
+ #: classes/Views/Licensing.php:71
350
+ msgid "Active"
351
+ msgstr ""
352
+
353
+ #: classes/Views/Licensing.php:73
354
+ msgid "Inactive"
355
+ msgstr ""
356
+
357
  #: classes/Views/Sandbox.php:11 classes/Views/Sandbox.php:19
358
+ #: classes/Views/Settings.php:233
359
  msgid "Sandbox"
360
  msgstr ""
361
 
367
  msgid "Settings"
368
  msgstr ""
369
 
370
+ #: classes/Views/Settings.php:86
 
 
 
 
 
 
 
 
371
  msgid "Security Alerts Pruning"
372
  msgstr ""
373
 
374
+ #: classes/Views/Settings.php:89
375
  msgid "(eg: 1 month)"
376
  msgstr ""
377
 
378
+ #: classes/Views/Settings.php:94
379
  msgid "Delete alerts older than"
380
  msgstr ""
381
 
382
+ #: classes/Views/Settings.php:106
383
  msgid "(eg: 80)"
384
  msgstr ""
385
 
386
+ #: classes/Views/Settings.php:111
387
  msgid "Keep up to"
388
  msgstr ""
389
 
390
+ #: classes/Views/Settings.php:115
391
  msgid "alerts"
392
  msgstr ""
393
 
394
+ #: classes/Views/Settings.php:121
395
  msgid "Alerts Dashboard Widget"
396
  msgstr ""
397
 
398
+ #: classes/Views/Settings.php:127
399
  msgid "On"
400
  msgstr ""
401
 
402
+ #: classes/Views/Settings.php:132
403
  msgid "Off"
404
  msgstr ""
405
 
406
+ #: classes/Views/Settings.php:137
407
  msgid "Display a dashboard widget with the latest %d security alerts."
408
  msgstr ""
409
 
410
+ #: classes/Views/Settings.php:145
411
  msgid "Can View Alerts"
412
  msgstr ""
413
 
414
+ #: classes/Views/Settings.php:152
415
  msgid "Users and Roles in this list can view the security alerts"
416
  msgstr ""
417
 
418
+ #: classes/Views/Settings.php:167
419
  msgid "Can Manage Plugin"
420
  msgstr ""
421
 
422
+ #: classes/Views/Settings.php:174
423
  msgid "Users and Roles in this list can manage the plugin settings"
424
  msgstr ""
425
 
426
+ #: classes/Views/Settings.php:189
427
  msgid "Refresh Audit View"
428
  msgstr ""
429
 
430
+ #: classes/Views/Settings.php:195
431
  msgid "Automatic"
432
  msgstr ""
433
 
434
+ #: classes/Views/Settings.php:197
435
  msgid "Refresh Audit View as soon as there are new events."
436
  msgstr ""
437
 
438
+ #: classes/Views/Settings.php:201
439
  msgid "Manual"
440
  msgstr ""
441
 
442
+ #: classes/Views/Settings.php:203
443
  msgid "Refresh Audit View only when page is reloaded."
444
  msgstr ""
445
 
446
+ #: classes/Views/Settings.php:209
447
  msgid "Developer Options"
448
  msgstr ""
449
 
450
+ #: classes/Views/Settings.php:217
451
  msgid ""
452
+ "Only enable these options on testing, staging and development websites. "
453
+ "Enabling any of the settings below on LIVE websites may cause unintended "
454
+ "side-effects including degraded performance."
455
  msgstr ""
456
 
457
+ #: classes/Views/Settings.php:221
458
  msgid "Data Inspector"
459
  msgstr ""
460
 
461
+ #: classes/Views/Settings.php:222
462
  msgid "View data logged for each triggered alert."
463
  msgstr ""
464
 
465
+ #: classes/Views/Settings.php:225
466
  msgid "PHP Errors"
467
  msgstr ""
468
 
469
+ #: classes/Views/Settings.php:226
470
  msgid "Enables sensor for alerts generated from PHP."
471
  msgstr ""
472
 
473
+ #: classes/Views/Settings.php:229
474
  msgid "Request Log"
475
  msgstr ""
476
 
477
+ #: classes/Views/Settings.php:230
478
  msgid "Enables logging request to file."
479
  msgstr ""
480
 
481
+ #: classes/Views/Settings.php:234
482
  msgid "Enables sandbox for testing PHP code."
483
  msgstr ""
484
 
485
+ #: classes/Views/Settings.php:237
486
  msgid "Backtrace"
487
  msgstr ""
488
 
489
+ #: classes/Views/Settings.php:238
490
  msgid "Log full backtrace for PHP-generated alerts."
491
  msgstr ""
492
 
493
+ #: classes/Views/Settings.php:256
494
  msgid "Hide Plugin from Plugins Page"
495
  msgstr ""
496
 
497
+ #: classes/Views/Settings.php:262
498
  msgid "Hide"
499
  msgstr ""
500
 
502
  msgid "Enable/Disable Alerts"
503
  msgstr ""
504
 
505
+ #: classes/Views/ToggleAlerts.php:71 classes/WidgetManager.php:38
506
  msgid "Description"
507
  msgstr ""
508
 
509
+ #: classes/Views/ToggleAlerts.php:79
510
  msgid "Not Implemented"
511
  msgstr ""
512
 
513
+ #: classes/Views/ToggleAlerts.php:82
514
  msgid "Not Available"
515
  msgstr ""
516
 
517
+ #: classes/Views/ToggleAlerts.php:96
518
  msgid "Save Changes"
519
  msgstr ""
520
 
1553
  ">get_template_directory%"
1554
  msgstr ""
1555
 
1556
+ #: wp-security-audit-log.php:149
1557
  msgid ""
1558
  "You are using a version of PHP that is older than %s, which is no longer "
1559
  "supported.<br/>Contact us on <a href=\"mailto:plugins@wpwhitesecurity.com"
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
8
  Requires at least: 3.6
9
- Tested up to: 3.9.1
10
- Stable tag: 1.2.4
11
 
12
  Identify WordPress issues before they become a security problem by keeping an audit log of users and all of the under the hood WordPress activity.
13
 
@@ -24,6 +24,7 @@ WP Security Audit Log keeps a log of everything happening on your WordPress blog
24
  * User installs, activates, deactivates, upgrades or uninstalls a plugin
25
  * User creates a new post, page, category or a custom post type
26
  * User modifies an existing post, page, category or a custom post type
 
27
  * User adds, moves, modifies or deletes a widget
28
  * User installs or activates a new WordPress theme
29
  * User changes WordPress settings such as permalinks or administrator notification email
@@ -130,10 +131,38 @@ Yes, WP Security Audit Log works on WordPress Multisite networks, i.e. it can mo
130
 
131
  == Changelog ==
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  = 1.2.4 (2014-07-27) =
134
  * Improvements
135
  * Improved monitoring of failed logins, addressed issues reported [here](http://wordpress.org/support/topic/horrible-performance#post-), [here](http://wordpress.org/support/topic/much-too-much-sql-load#post-), [here](http://wordpress.org/support/topic/overload-due-to-this-plugin#post-) and [here](http://wordpress.org/support/topic/mysql-200-cpu-time-copying-to-tmp-table)
136
-
137
  = 1.2.3 (2014-07-23) =
138
  * Improvements
139
  * Improved database structure for better support of high-traffic WordPress and WordPress multisite installations
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
8
  Requires at least: 3.6
9
+ Tested up to: 3.9.2
10
+ Stable tag: 1.2.5
11
 
12
  Identify WordPress issues before they become a security problem by keeping an audit log of users and all of the under the hood WordPress activity.
13
 
24
  * User installs, activates, deactivates, upgrades or uninstalls a plugin
25
  * User creates a new post, page, category or a custom post type
26
  * User modifies an existing post, page, category or a custom post type
27
+ * User creates, modifies or deletes a custom field from a post, page or custom post type
28
  * User adds, moves, modifies or deletes a widget
29
  * User installs or activates a new WordPress theme
30
  * User changes WordPress settings such as permalinks or administrator notification email
131
 
132
  == Changelog ==
133
 
134
+ = 1.2.5 (2014-08-12) =
135
+ * New Feature
136
+ * Monitoring of custom fields in WordPress posts, pages and custom post types.
137
+
138
+ * New WordPress Security Alerts
139
+ * Alert 2053: User created new custom field in blog post
140
+ * Alert 2054: User modified the value of custom field in blog post
141
+ * Alert 2055: User deleted a custom field in blog post
142
+ * Alert 2062: User renamed custom field in blog post
143
+ * Alert 2059: User created new custom field in page
144
+ * Alert 2060: User modified the value of custom field in page
145
+ * Alert 2061: User deleted custom field from page
146
+ * Alert 2063: User renamed custom field in
147
+ * Alert 2056: User created new custom field in custom post type
148
+ * Alert 2057: User modified the value of custom field in custom post type
149
+ * Alert 2058: User deleted a custom field from custom post type
150
+ * Alert 2064: User renamed custom field in custom post type
151
+
152
+ * Improvements
153
+ * Improved the writing and reading of WordPress alerts from the WordPress database (plugin runs more efficiently on high traffic WordPress and WordPress multisite installations)
154
+ * Improved the monitoring of WordPress login and logout actions
155
+ * Applied various plugin performance tweaks
156
+
157
+ * Bug Fixes
158
+ * Fixed a specific issue where user and user role where not being reported ([ticket](http://wordpress.org/support/topic/showing-unknown-user-logged-out-but-never-logged-in?replies=11))
159
+ * Fixed an error which was being reported during user logout in specific scenarios ([ticket](http://wordpress.org/support/topic/error-at-logou?replies=3))
160
+ * Fixed a CSRF vulnerability reported by Kévin FALCOZ aka 0pc0deFR
161
+
162
  = 1.2.4 (2014-07-27) =
163
  * Improvements
164
  * Improved monitoring of failed logins, addressed issues reported [here](http://wordpress.org/support/topic/horrible-performance#post-), [here](http://wordpress.org/support/topic/much-too-much-sql-load#post-), [here](http://wordpress.org/support/topic/overload-due-to-this-plugin#post-) and [here](http://wordpress.org/support/topic/mysql-200-cpu-time-copying-to-tmp-table)
165
+
166
  = 1.2.3 (2014-07-23) =
167
  * Improvements
168
  * Improved database structure for better support of high-traffic WordPress and WordPress multisite installations
wp-security-audit-log.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: WP Security Audit Log
4
  Plugin URI: http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/
5
  Description: Identify WordPress security issues before they become a problem and keep track of everything happening on your WordPress, including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log will generate a security alert for everything that happens on your WordPress blog or website. Use the Audit Log Viewer included in the plugin to see all the security alerts.
6
  Author: WP White Security
7
- Version: 1.2.4
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpwhitesecurity.com/
10
  License: GPL2
@@ -66,6 +66,12 @@ class WpSecurityAuditLog {
66
  */
67
  public $constants;
68
 
 
 
 
 
 
 
69
  /**
70
  * Contains a list of cleanup callbacks.
71
  * @var callable[]
@@ -101,6 +107,7 @@ class WpSecurityAuditLog {
101
  $this->sensors = new WSAL_SensorManager($this);
102
  $this->settings = new WSAL_Settings($this);
103
  $this->constants = new WSAL_ConstantManager($this);
 
104
  $this->widgets = new WSAL_WidgetManager($this);
105
 
106
  // listen for installation event
4
  Plugin URI: http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/
5
  Description: Identify WordPress security issues before they become a problem and keep track of everything happening on your WordPress, including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log will generate a security alert for everything that happens on your WordPress blog or website. Use the Audit Log Viewer included in the plugin to see all the security alerts.
6
  Author: WP White Security
7
+ Version: 1.2.5
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpwhitesecurity.com/
10
  License: GPL2
66
  */
67
  public $constants;
68
 
69
+ /**
70
+ * Licenses manager.
71
+ * @var WSAL_LicenseManager
72
+ */
73
+ public $licensing;
74
+
75
  /**
76
  * Contains a list of cleanup callbacks.
77
  * @var callable[]
107
  $this->sensors = new WSAL_SensorManager($this);
108
  $this->settings = new WSAL_Settings($this);
109
  $this->constants = new WSAL_ConstantManager($this);
110
+ $this->licensing = new WSAL_LicenseManager($this);
111
  $this->widgets = new WSAL_WidgetManager($this);
112
 
113
  // listen for installation event