WP Security Audit Log - Version 1.5.1

Version Description

(2015-03-26) = * Improvements * Completely removed the user of the is_admin() function to follow better security practises

  • Bug Fixes
    • Updated the licensing mechanism to correct problem where WP Security Audit Log premium add-ons could not be activated.
    • Fixed several issues where the database tables were not being created during install or upgrade. Support ticket and Support ticket 2
    • Fixed an issue where the plugin did not monitor any activity in specific scenarios. Support ticket and Support ticket 2
    • Removed duplicate options in the settings page. Support ticket
Download this release

Release Info

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

Code changes from version 1.5.0 to 1.5.1

classes/DB/ActiveRecord.php CHANGED
@@ -23,6 +23,7 @@ abstract class WSAL_DB_ActiveRecord {
23
  protected $_state = self::STATE_UNKNOWN;
24
 
25
  public function __construct($data = null) {
 
26
  if(!$this->_table)
27
  throw new Exception('Class "' . __CLASS__ . '" requires "_table" to be set.');
28
  if(!$this->_idkey)
@@ -84,6 +85,7 @@ abstract class WSAL_DB_ActiveRecord {
84
  $sql .= ' COLLATE ' . $wpdb->collate;
85
 
86
  return $sql;
 
87
  }
88
 
89
  /**
23
  protected $_state = self::STATE_UNKNOWN;
24
 
25
  public function __construct($data = null) {
26
+ ini_set( 'error_log', WP_CONTENT_DIR . '/debug.log' );
27
  if(!$this->_table)
28
  throw new Exception('Class "' . __CLASS__ . '" requires "_table" to be set.');
29
  if(!$this->_idkey)
85
  $sql .= ' COLLATE ' . $wpdb->collate;
86
 
87
  return $sql;
88
+
89
  }
90
 
91
  /**
classes/DB/Option.php CHANGED
@@ -1,32 +1,36 @@
1
- <?php
2
-
3
- class WSAL_DB_Option extends WSAL_DB_ActiveRecord
4
- {
5
- protected $_table = 'wsal_options';
6
- protected $_idkey = 'id';
7
-
8
- public $id = 0;
9
- public $option_name = '';
10
- public static $option_name_maxlength = 100;
11
- public $option_value = '';
12
-
13
- public function SetOptionValue($name, $value)
14
- {
15
- $this->GetNamedOption($name);
16
- $this->option_name = $name;
17
- $this->option_value = $value;
18
- $this->Save();
19
- }
20
-
21
- public function GetOptionValue($name, $default = array())
22
- {
23
- $this->GetNamedOption($name);
24
- return $this->IsLoaded() ? $this->option_value : $default;
25
- }
26
-
27
- public function GetNamedOption($name)
28
- {
29
- return $this->Load('option_name = %s', array($name));
30
- }
31
-
 
 
 
 
32
  }
1
+ <?php
2
+
3
+ class WSAL_DB_Option extends WSAL_DB_ActiveRecord
4
+ {
5
+ protected $_table = 'wsal_options';
6
+ protected $_idkey = 'id';
7
+
8
+ public $id = 0;
9
+ public $option_name = '';
10
+ public static $option_name_maxlength = 100;
11
+ public $option_value = '';
12
+
13
+ public function SetOptionValue($name, $value)
14
+ {
15
+ $this->GetNamedOption($name);
16
+ $this->option_name = $name;
17
+ // Serialize if $value is array or object
18
+ $value = maybe_serialize($value);
19
+ $this->option_value = $value;
20
+ $this->Save();
21
+ }
22
+
23
+ public function GetOptionValue($name, $default = array())
24
+ {
25
+ $this->GetNamedOption($name);
26
+ // Unerialize if $value is array or object
27
+ $this->option_value = maybe_unserialize($this->option_value);
28
+ return $this->IsLoaded() ? $this->option_value : $default;
29
+ }
30
+
31
+ public function GetNamedOption($name)
32
+ {
33
+ return $this->Load('option_name = %s', array($name));
34
+ }
35
+
36
  }
classes/EDD_SL_Plugin_Updater.php CHANGED
@@ -1,170 +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
- }
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/Sensors/Content.php CHANGED
@@ -3,7 +3,7 @@
3
  class WSAL_Sensors_Content extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
6
- if(is_admin())add_action('init', array($this, 'EventWordpressInit'));
7
  add_action('transition_post_status', array($this, 'EventPostChanged'), 10, 3);
8
  add_action('delete_post', array($this, 'EventPostDeleted'), 10, 1);
9
  add_action('wp_trash_post', array($this, 'EventPostTrashed'), 10, 1);
@@ -130,7 +130,6 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor {
130
 
131
  protected function CheckCategoryCreation(){
132
  if (empty($_POST)) return;
133
- if (!current_user_can("manage_categories")) return;
134
 
135
  $categoryName = '';
136
  if(!empty($_POST['screen']) && !empty($_POST['tag-name']) &&
@@ -154,7 +153,6 @@ class WSAL_Sensors_Content extends WSAL_AbstractSensor {
154
 
155
  protected function CheckCategoryDeletion(){
156
  if (empty($_POST)) return;
157
- if (!current_user_can("manage_categories")) return;
158
 
159
  $action = !empty($_POST['action']) ? $_POST['action']
160
  : (!empty($_POST['action2']) ? $_POST['action2'] : '');
3
  class WSAL_Sensors_Content extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
6
+ if(current_user_can("manage_categories"))add_action('admin_init', array($this, 'EventWordpressInit'));
7
  add_action('transition_post_status', array($this, 'EventPostChanged'), 10, 3);
8
  add_action('delete_post', array($this, 'EventPostDeleted'), 10, 1);
9
  add_action('wp_trash_post', array($this, 'EventPostTrashed'), 10, 1);
130
 
131
  protected function CheckCategoryCreation(){
132
  if (empty($_POST)) return;
 
133
 
134
  $categoryName = '';
135
  if(!empty($_POST['screen']) && !empty($_POST['tag-name']) &&
153
 
154
  protected function CheckCategoryDeletion(){
155
  if (empty($_POST)) return;
 
156
 
157
  $action = !empty($_POST['action']) ? $_POST['action']
158
  : (!empty($_POST['action2']) ? $_POST['action2'] : '');
classes/Sensors/Multisite.php CHANGED
@@ -5,7 +5,7 @@ class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
5
  public function HookEvents() {
6
  if($this->plugin->IsMultisite()){
7
  add_action('admin_init', array($this, 'EventAdminInit'));
8
- if(is_admin())add_action('shutdown', array($this, 'EventAdminShutdown'));
9
  add_action('wpmu_new_blog', array($this, 'EventNewBlog'), 10, 1);
10
  add_action('archive_blog', array($this, 'EventArchiveBlog'));
11
  add_action('unarchive_blog', array($this, 'EventUnarchiveBlog'));
@@ -24,7 +24,6 @@ class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
24
  }
25
 
26
  public function EventAdminShutdown(){
27
- if (!current_user_can("switch_themes")) return;
28
  if(is_null($this->old_allowedthemes))return;
29
  $new_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
30
 
5
  public function HookEvents() {
6
  if($this->plugin->IsMultisite()){
7
  add_action('admin_init', array($this, 'EventAdminInit'));
8
+ if(current_user_can('switch_themes'))add_action('shutdown', array($this, 'EventAdminShutdown'));
9
  add_action('wpmu_new_blog', array($this, 'EventNewBlog'), 10, 1);
10
  add_action('archive_blog', array($this, 'EventArchiveBlog'));
11
  add_action('unarchive_blog', array($this, 'EventUnarchiveBlog'));
24
  }
25
 
26
  public function EventAdminShutdown(){
 
27
  if(is_null($this->old_allowedthemes))return;
28
  $new_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
29
 
classes/Sensors/PluginsThemes.php CHANGED
@@ -3,8 +3,11 @@
3
  class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
 
 
 
6
  add_action('admin_init', array($this, 'EventAdminInit'));
7
- if(is_admin())add_action('shutdown', array($this, 'EventAdminShutdown'));
8
  add_action('switch_theme', array($this, 'EventThemeActivated'));
9
  }
10
 
3
  class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
6
+ $hasPermission = (current_user_can("install_plugins") || current_user_can("activate_plugins") ||
7
+ current_user_can("delete_plugins") || current_user_can("update_plugins") || current_user_can("install_themes"));
8
+
9
  add_action('admin_init', array($this, 'EventAdminInit'));
10
+ if($hasPermission)add_action('shutdown', array($this, 'EventAdminShutdown'));
11
  add_action('switch_theme', array($this, 'EventThemeActivated'));
12
  }
13
 
classes/Sensors/Widgets.php CHANGED
@@ -3,11 +3,13 @@
3
  class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
6
- add_action('widgets_init', array($this, 'EventWidgetMove'));
7
- if(current_user_can("edit_dashboard"))add_action('init', array($this, 'EventWidgetPostMove'));
 
 
8
  add_action('sidebar_admin_setup', array($this, 'EventWidgetActivity'));
9
  }
10
-
11
  protected $_WidgetMoveData = null;
12
 
13
  public function EventWidgetMove(){
@@ -65,17 +67,16 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
65
  $this->_WidgetMoveData = array('widget' => $wName, 'from' => $fromSidebar, 'to' => $toSidebar);
66
  return;
67
  }
68
-
69
- $this->plugin->alerts->Trigger(2045, array(
70
  'WidgetName' => $wName,
71
  'OldSidebar' => $fromSidebar,
72
  'NewSidebar' => $toSidebar,
73
- ));
74
  }
75
  }
76
 
77
  public function EventWidgetPostMove(){
78
-
79
  //#!-- generates the event 2071
80
  if(isset($_REQUEST['action'])&&($_REQUEST['action']=='widgets-order'))
81
  {
@@ -84,7 +85,7 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
84
  $requestSidebars = array();
85
  if($_REQUEST['sidebars']){
86
  foreach($_REQUEST['sidebars'] as $key => &$value){
87
- if(preg_match('/^sidebar-/', $key) && !empty($value)){
88
  // build the sidebars array
89
  $value = explode(',', $value);
90
  // Cleanup widgets' name
@@ -99,13 +100,13 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
99
  if($requestSidebars){
100
  // Get the sidebars from DATABASE
101
  $sidebar_widgets = wp_get_sidebars_widgets();
102
-
103
  // Get global sidebars so we can retrieve the real name of the sidebar
104
  global $wp_registered_sidebars;
105
 
106
  // Check in each array if there's any change
107
  foreach($requestSidebars as $sidebarName => $widgets){
108
- if(isset($sidebar_widgets[$sidebarName])){
 
109
  foreach($sidebar_widgets[$sidebarName] as $i => $widgetName){
110
  $index = array_search($widgetName, $widgets);
111
  // check to see whether or not the widget has been moved
@@ -232,4 +233,4 @@ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
232
 
233
  }
234
  }
235
- }
3
  class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
4
 
5
  public function HookEvents() {
6
+ if(current_user_can("edit_theme_options")) {
7
+ add_action('admin_init', array($this, 'EventWidgetMove'));
8
+ add_action('admin_init', array($this, 'EventWidgetPostMove'));
9
+ }
10
  add_action('sidebar_admin_setup', array($this, 'EventWidgetActivity'));
11
  }
12
+
13
  protected $_WidgetMoveData = null;
14
 
15
  public function EventWidgetMove(){
67
  $this->_WidgetMoveData = array('widget' => $wName, 'from' => $fromSidebar, 'to' => $toSidebar);
68
  return;
69
  }
70
+
71
+ $this->plugin->alerts->Trigger(2045, array(
72
  'WidgetName' => $wName,
73
  'OldSidebar' => $fromSidebar,
74
  'NewSidebar' => $toSidebar,
75
+ ));
76
  }
77
  }
78
 
79
  public function EventWidgetPostMove(){
 
80
  //#!-- generates the event 2071
81
  if(isset($_REQUEST['action'])&&($_REQUEST['action']=='widgets-order'))
82
  {
85
  $requestSidebars = array();
86
  if($_REQUEST['sidebars']){
87
  foreach($_REQUEST['sidebars'] as $key => &$value){
88
+ if(!empty($value)){
89
  // build the sidebars array
90
  $value = explode(',', $value);
91
  // Cleanup widgets' name
100
  if($requestSidebars){
101
  // Get the sidebars from DATABASE
102
  $sidebar_widgets = wp_get_sidebars_widgets();
 
103
  // Get global sidebars so we can retrieve the real name of the sidebar
104
  global $wp_registered_sidebars;
105
 
106
  // Check in each array if there's any change
107
  foreach($requestSidebars as $sidebarName => $widgets){
108
+ if(isset($sidebar_widgets[$sidebarName])){
109
+
110
  foreach($sidebar_widgets[$sidebarName] as $i => $widgetName){
111
  $index = array_search($widgetName, $widgets);
112
  // check to see whether or not the widget has been moved
233
 
234
  }
235
  }
236
+ }
classes/Settings.php CHANGED
@@ -385,7 +385,7 @@ class WSAL_Settings {
385
  $name = sanitize_key(basename($name));
386
  return isset($data[$name]) ? $data[$name] : array();
387
  }
388
- public function SetLicenses($data){
389
  $this->_plugin->SetGlobalOption('licenses', $data);
390
  }
391
  public function GetLicenseKey($name){
@@ -419,7 +419,7 @@ class WSAL_Settings {
419
  $this->SetLicenses($data);
420
  }
421
  public function ClearLicenses(){
422
- $this->SetLicenses(array());
423
  }
424
 
425
  // </editor-fold>
385
  $name = sanitize_key(basename($name));
386
  return isset($data[$name]) ? $data[$name] : array();
387
  }
388
+ public function SetLicenses($data){
389
  $this->_plugin->SetGlobalOption('licenses', $data);
390
  }
391
  public function GetLicenseKey($name){
419
  $this->SetLicenses($data);
420
  }
421
  public function ClearLicenses(){
422
+ $this->SetLicenses(array());
423
  }
424
 
425
  // </editor-fold>
classes/Views/Licensing.php CHANGED
@@ -24,7 +24,7 @@ class WSAL_Views_Licensing extends WSAL_AbstractView {
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
  }
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
  }
classes/Views/Settings.php CHANGED
@@ -3,12 +3,11 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
3
 
4
  public function __construct(WpSecurityAuditLog $plugin) {
5
  parent::__construct($plugin);
6
- if (is_admin()) {
7
- add_action('wp_ajax_AjaxCheckSecurityToken', array($this, 'AjaxCheckSecurityToken'));
8
- add_action('wp_ajax_AjaxRunCleanup', array($this, 'AjaxRunCleanup'));
9
- add_action('wp_ajax_AjaxGetAllUsers', array($this, 'AjaxGetAllUsers'));
10
- add_action('wp_ajax_AjaxGetAllRoles', array($this, 'AjaxGetAllRoles'));
11
- }
12
  }
13
 
14
  public function HasPluginShortcutLink(){
@@ -269,85 +268,6 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
269
  </fieldset>
270
  </td>
271
  </tr>
272
- <tr>
273
- <th><label for="aroption_on"><?php _e('Refresh Audit View', 'wp-security-audit-log'); ?></label></th>
274
- <td>
275
- <fieldset>
276
- <?php $are = $this->_plugin->settings->IsRefreshAlertsEnabled(); ?>
277
- <label for="aroption_on">
278
- <input type="radio" name="EnableAuditViewRefresh" id="aroption_on" style="margin-top: 2px;" <?php if($are)echo 'checked="checked"'; ?> value="1">
279
- <span><?php _e('Automatic', 'wp-security-audit-log'); ?></span>
280
- </label>
281
- <span class="description"> &mdash; <?php _e('Refresh Audit View as soon as there are new events.', 'wp-security-audit-log'); ?></span>
282
- <br/>
283
- <label for="aroption_off">
284
- <input type="radio" name="EnableAuditViewRefresh" id="aroption_off" style="margin-top: 2px;" <?php if(!$are)echo 'checked="checked"'; ?> value="0">
285
- <span><?php _e('Manual', 'wp-security-audit-log'); ?></span>
286
- </label>
287
- <span class="description"> &mdash; <?php _e('Refresh Audit View only when page is reloaded.', 'wp-security-audit-log'); ?></span>
288
- <br/>
289
- </fieldset>
290
- </td>
291
- </tr>
292
- <tr>
293
- <th><label><?php _e('Developer Options', 'wp-security-audit-log'); ?></label></th>
294
- <td>
295
- <fieldset>
296
- <?php $any = $this->_plugin->settings->IsAnyDevOptionEnabled(); ?>
297
- <a href="javascript:;" style="<?php if($any)echo 'display: none;'; ?>"
298
- onclick="jQuery(this).hide().next().show();">Show Developer Options</a>
299
- <div style="<?php if(!$any)echo 'display: none;'; ?>">
300
- <p style="border-left: 3px solid #FFD000; padding: 2px 8px; margin-left: 6px; margin-bottom: 16px;"><?php
301
- _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');
302
- ?></p><?php
303
- foreach(array(
304
- WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array(
305
- __('Data Inspector', 'wp-security-audit-log'),
306
- __('View data logged for each triggered alert.', 'wp-security-audit-log')
307
- ),
308
- WSAL_Settings::OPT_DEV_PHP_ERRORS => array(
309
- __('PHP Errors', 'wp-security-audit-log'),
310
- __('Enables sensor for alerts generated from PHP.', 'wp-security-audit-log')
311
- ),
312
- WSAL_Settings::OPT_DEV_REQUEST_LOG => array(
313
- __('Request Log', 'wp-security-audit-log'),
314
- __('Enables logging request to file.', 'wp-security-audit-log')
315
- ),
316
- WSAL_Settings::OPT_DEV_BACKTRACE_LOG => array(
317
- __('Backtrace', 'wp-security-audit-log'),
318
- __('Log full backtrace for PHP-generated alerts.', 'wp-security-audit-log')
319
- ),
320
- ) as $opt => $info){
321
- ?><label for="devoption_<?php echo $opt; ?>">
322
- <input type="checkbox" name="DevOptions[]" id="devoption_<?php echo $opt; ?>" <?php
323
- if($this->_plugin->settings->IsDevOptionEnabled($opt))echo 'checked="checked"'; ?> value="<?php echo $opt; ?>">
324
- <span><?php echo $info[0]; ?></span>
325
- <?php if(isset($info[1]) && $info[1]){ ?>
326
- <span class="description"> &mdash; <?php echo $info[1]; ?></span>
327
- <?php }
328
- ?></label><br/><?php
329
- }
330
- ?></div>
331
- </fieldset>
332
- </td>
333
- </tr>
334
-
335
- <tr>
336
- <th><label for="Incognito"><?php _e('Hide Plugin in Plugins Page', 'wp-security-audit-log'); ?></label></th>
337
- <td>
338
- <fieldset>
339
- <label for="Incognito">
340
- <input type="checkbox" name="Incognito" value="1" id="Incognito"<?php
341
- if($this->_plugin->settings->IsIncognito())echo ' checked="checked"';
342
- ?>/> <?php _e('Hide', 'wp-security-audit-log'); ?>
343
- </label>
344
- <br/>
345
- <span class="description">
346
- <?php _e('To manually revert this setting set the value of option wsal-hide-plugin to 0 in the wp_options table.', 'wp-security-audit-log'); ?>
347
- </span>
348
- </fieldset>
349
- </td>
350
- </tr>
351
  <tr>
352
  <th><label for="aroption_on"><?php _e('Refresh Audit Log Viewer', 'wp-security-audit-log'); ?></label></th>
353
  <td>
@@ -578,6 +498,9 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
578
  }
579
 
580
  public function AjaxGetAllUsers() {
 
 
 
581
  $users = array();
582
  foreach ( get_users() as $user ) {
583
  if (strpos($user->user_login, $_GET['term']) !== false) {
@@ -589,6 +512,9 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
589
  }
590
 
591
  public function AjaxGetAllRoles() {
 
 
 
592
  $roles = array();
593
  foreach ( get_editable_roles() as $role_name => $role_info ) {
594
  if (strpos($role_name, $_GET['term']) !== false) {
3
 
4
  public function __construct(WpSecurityAuditLog $plugin) {
5
  parent::__construct($plugin);
6
+
7
+ add_action('wp_ajax_AjaxCheckSecurityToken', array($this, 'AjaxCheckSecurityToken'));
8
+ add_action('wp_ajax_AjaxRunCleanup', array($this, 'AjaxRunCleanup'));
9
+ add_action('wp_ajax_AjaxGetAllUsers', array($this, 'AjaxGetAllUsers'));
10
+ add_action('wp_ajax_AjaxGetAllRoles', array($this, 'AjaxGetAllRoles'));
 
11
  }
12
 
13
  public function HasPluginShortcutLink(){
268
  </fieldset>
269
  </td>
270
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  <tr>
272
  <th><label for="aroption_on"><?php _e('Refresh Audit Log Viewer', 'wp-security-audit-log'); ?></label></th>
273
  <td>
498
  }
499
 
500
  public function AjaxGetAllUsers() {
501
+ if(!$this->_plugin->settings->CurrentUserCan('view'))
502
+ die('Access Denied.');
503
+
504
  $users = array();
505
  foreach ( get_users() as $user ) {
506
  if (strpos($user->user_login, $_GET['term']) !== false) {
512
  }
513
 
514
  public function AjaxGetAllRoles() {
515
+ if(!$this->_plugin->settings->CurrentUserCan('view'))
516
+ die('Access Denied.');
517
+
518
  $roles = array();
519
  foreach ( get_editable_roles() as $role_name => $role_info ) {
520
  if (strpos($role_name, $_GET['term']) !== false) {
css/install-error.css CHANGED
@@ -1,41 +1,41 @@
1
- .warn-icon-tri {
2
- top: 5px;
3
- left: 5px;
4
- position: absolute;
5
- border-left: 16px solid #FFF;
6
- border-right: 16px solid #FFF;
7
- border-bottom: 28px solid #C33;
8
- height: 3px;
9
- width: 4px
10
- }
11
-
12
- .warn-icon-chr {
13
- top: 8px;
14
- left: 18px;
15
- position: absolute;
16
- color: #FFF;
17
- font: 26px Georgia;
18
- }
19
-
20
- .warn-icon-cir {
21
- top: 2px;
22
- left: 0px;
23
- position: absolute;
24
- overflow: hidden;
25
- border: 6px solid #FFF;
26
- border-radius: 32px;
27
- width: 34px;
28
- height: 34px;
29
- }
30
-
31
- .warn-wrap {
32
- position: relative;
33
- color: #A00;
34
- font: 14px Arial;
35
- padding: 6px 48px;
36
- }
37
-
38
- .warn-wrap a,
39
- .warn-wrap a:hover {
40
- color: #F56;
41
- }
1
+ .warn-icon-tri {
2
+ top: 5px;
3
+ left: 5px;
4
+ position: absolute;
5
+ border-left: 16px solid #FFF;
6
+ border-right: 16px solid #FFF;
7
+ border-bottom: 28px solid #C33;
8
+ height: 3px;
9
+ width: 4px
10
+ }
11
+
12
+ .warn-icon-chr {
13
+ top: 8px;
14
+ left: 18px;
15
+ position: absolute;
16
+ color: #FFF;
17
+ font: 26px Georgia;
18
+ }
19
+
20
+ .warn-icon-cir {
21
+ top: 2px;
22
+ left: 0px;
23
+ position: absolute;
24
+ overflow: hidden;
25
+ border: 6px solid #FFF;
26
+ border-radius: 32px;
27
+ width: 34px;
28
+ height: 34px;
29
+ }
30
+
31
+ .warn-wrap {
32
+ position: relative;
33
+ color: #A00;
34
+ font: 14px Arial;
35
+ padding: 6px 48px;
36
+ }
37
+
38
+ .warn-wrap a,
39
+ .warn-wrap a:hover {
40
+ color: #F56;
41
+ }
css/settings.css CHANGED
@@ -1,71 +1,71 @@
1
- #audit-log-settings {
2
- padding-right: 256px;
3
- position: relative;
4
- }
5
-
6
- #audit-log-adverts {
7
- position: absolute;
8
- top: 3px;
9
- right: 3px;
10
- overflow: hidden;
11
- }
12
-
13
- #audit-log-adverts a {
14
- display: block;
15
- text-decoration: none;
16
- margin: 4px 0;
17
- }
18
-
19
- .sectoken-user,
20
- .sectoken-role,
21
- .sectoken-other {
22
- display: inline-block;
23
- border-width: 1px;
24
- border-style: solid;
25
- padding: 2px 4px;
26
- margin: 2px 0 0 2px;
27
- border-radius: 3px;
28
- cursor: default;
29
- }
30
- .sectoken-other {
31
- display: table;
32
- border-collapse: separate;
33
- }
34
-
35
- .sectoken-user a,
36
- .sectoken-role a,
37
- .sectoken-other a {
38
- text-decoration: none;
39
- font-size: 12px;
40
- font-weight: bold;
41
- color: #FFF;
42
- margin-left: 2px;
43
- background: #BBB;
44
- border-radius: 25px;
45
- height: 14px;
46
- display: inline-block;
47
- width: 14px;
48
- text-align: center;
49
- line-height: 16px;
50
- }
51
-
52
- .sectoken-user a:hover,
53
- .sectoken-role a:hover,
54
- .sectoken-other a:hover {
55
- background: #FB9;
56
- }
57
-
58
- .sectoken-user { background: #EFF; border-color: #5BE; }
59
- .sectoken-role { background: #EFE; border-color: #5B5; }
60
- .sectoken-other { background: #FFE; border-color: #ED5; }
61
- .sectoken-del { background: #FEE; border-color: #EBB; }
62
-
63
- .wsal-tab {
64
- margin-top: 0px;
65
- }
66
- .wsal-tab th {
67
- padding-left: 20px;
68
- }
69
- .wsal-tab td {
70
- padding-left: 20px;
71
  }
1
+ #audit-log-settings {
2
+ padding-right: 256px;
3
+ position: relative;
4
+ }
5
+
6
+ #audit-log-adverts {
7
+ position: absolute;
8
+ top: 3px;
9
+ right: 3px;
10
+ overflow: hidden;
11
+ }
12
+
13
+ #audit-log-adverts a {
14
+ display: block;
15
+ text-decoration: none;
16
+ margin: 4px 0;
17
+ }
18
+
19
+ .sectoken-user,
20
+ .sectoken-role,
21
+ .sectoken-other {
22
+ display: inline-block;
23
+ border-width: 1px;
24
+ border-style: solid;
25
+ padding: 2px 4px;
26
+ margin: 2px 0 0 2px;
27
+ border-radius: 3px;
28
+ cursor: default;
29
+ }
30
+ .sectoken-other {
31
+ display: table;
32
+ border-collapse: separate;
33
+ }
34
+
35
+ .sectoken-user a,
36
+ .sectoken-role a,
37
+ .sectoken-other a {
38
+ text-decoration: none;
39
+ font-size: 12px;
40
+ font-weight: bold;
41
+ color: #FFF;
42
+ margin-left: 2px;
43
+ background: #BBB;
44
+ border-radius: 25px;
45
+ height: 14px;
46
+ display: inline-block;
47
+ width: 14px;
48
+ text-align: center;
49
+ line-height: 16px;
50
+ }
51
+
52
+ .sectoken-user a:hover,
53
+ .sectoken-role a:hover,
54
+ .sectoken-other a:hover {
55
+ background: #FB9;
56
+ }
57
+
58
+ .sectoken-user { background: #EFF; border-color: #5BE; }
59
+ .sectoken-role { background: #EFE; border-color: #5B5; }
60
+ .sectoken-other { background: #FFE; border-color: #ED5; }
61
+ .sectoken-del { background: #FEE; border-color: #EBB; }
62
+
63
+ .wsal-tab {
64
+ margin-top: 0px;
65
+ }
66
+ .wsal-tab th {
67
+ padding-left: 20px;
68
+ }
69
+ .wsal-tab td {
70
+ padding-left: 20px;
71
  }
js/auditlog.js CHANGED
@@ -1,150 +1,150 @@
1
- var WsalData;
2
-
3
- window['WsalAuditLogRefreshed'] = function(){
4
- // fix pagination links causing form params to get lost
5
- jQuery('span.pagination-links a').click(function(ev){
6
- ev.preventDefault();
7
- var deparam = function(url){
8
- var obj = {};
9
- var pairs = url.split('&');
10
- for(var i in pairs){
11
- var split = pairs[i].split('=');
12
- obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
13
- }
14
- return obj;
15
- };
16
- var paged = deparam(this.href).paged;
17
- if (typeof paged === 'undefined') paged = 1;
18
- jQuery('#audit-log-viewer').append(
19
- jQuery('<input type="hidden" name="paged"/>').val(paged)
20
- ).submit();
21
- });
22
- };
23
-
24
- function WsalAuditLogInit(_WsalData){
25
- WsalData = _WsalData;
26
- var WsalTkn = WsalData.autorefresh.token;
27
-
28
- // list refresher
29
- var WsalAjx = null;
30
- var WsalChk = function(){
31
- if(WsalAjx)WsalAjx.abort();
32
- WsalAjx = jQuery.post(WsalData.ajaxurl, {
33
- action: 'AjaxRefresh',
34
- logcount: WsalTkn
35
- }, function(data){
36
- WsalAjx = null;
37
- if(data && data !== 'false'){
38
- WsalTkn = data;
39
- jQuery('#audit-log-viewer').load(
40
- location.href + ' #audit-log-viewer-content',
41
- window['WsalAuditLogRefreshed']
42
- );
43
- }
44
- WsalChk();
45
- });
46
- };
47
- if(WsalData.autorefresh.enabled){
48
- setInterval(WsalChk, 40000);
49
- WsalChk();
50
- }
51
-
52
- WsalSsasInit();
53
- }
54
-
55
- var WsalIppsPrev;
56
-
57
- function WsalIppsFocus(value){
58
- WsalIppsPrev = value;
59
- }
60
-
61
- function WsalIppsChange(value){
62
- if(value === ''){
63
- value = window.prompt(WsalData.tr8n.numofitems, WsalIppsPrev);
64
- if(value === null || value === WsalIppsPrev)return this.value = WsalIppsPrev; // operation canceled
65
- }
66
- jQuery('select.wsal-ipps').attr('disabled', true);
67
- jQuery.post(WsalData.ajaxurl, {
68
- action: 'AjaxSetIpp',
69
- count: value
70
- }, function(){
71
- location.reload();
72
- });
73
- }
74
-
75
- function WsalSsasInit(){
76
- var SsasAjx = null;
77
- var SsasInps = jQuery("input.wsal-ssas");
78
- SsasInps.after('<div class="wsal-ssas-dd" style="display: none;"/>');
79
- SsasInps.click(function(){
80
- jQuery(this).select();
81
- });
82
- window['WsalAuditLogRefreshed']();
83
- SsasInps.keyup(function(){
84
- var SsasInp = jQuery(this);
85
- var SsasDiv = SsasInp.next();
86
- var SsasVal = SsasInp.val();
87
- if(SsasAjx)SsasAjx.abort();
88
- SsasInp.removeClass('loading');
89
-
90
- // do a new search
91
- if(SsasInp.attr('data-oldvalue') !== SsasVal && SsasVal.length > 2){
92
- SsasInp.addClass('loading');
93
- SsasAjx = jQuery.post(WsalData.ajaxurl, {
94
- action: 'AjaxSearchSite',
95
- search: SsasVal
96
- }, function(data){
97
- if(SsasAjx)SsasAjx = null;
98
- SsasInp.removeClass('loading');
99
- SsasDiv.hide();
100
- SsasDiv.html('');
101
- if(data && data.length){
102
- var SsasReg = new RegExp(SsasVal.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'gi');
103
- for (var i = 0; i < data.length; i++){
104
- var link = jQuery('<a href="javascript:;" onclick="WsalSsasChange(' + data[i].blog_id + ')"/>')
105
- .text(data[i].blogname + ' (' + data[i].domain + ')');
106
- link.html(link.text().replace(SsasReg, '<u>$&</u>'));
107
- SsasDiv.append(link);
108
- }
109
- }else{
110
- SsasDiv.append(jQuery('<span/>').text(WsalData.tr8n.searchnone));
111
- }
112
- SsasDiv.prepend(jQuery('<a href="javascript:;" onclick="WsalSsasChange(0)" class="allsites"/>').text(WsalData.tr8n.searchback));
113
- SsasDiv.show();
114
- }, 'json');
115
- SsasInp.attr('data-oldvalue', SsasVal);
116
- }
117
-
118
- // handle keys
119
- });
120
- SsasInps.blur(function(){
121
- setTimeout(function(){
122
- var SsasInp = jQuery(this);
123
- var SsasDiv = SsasInp.next();
124
- SsasInp.attr('data-oldvalue', '');
125
- SsasDiv.hide();
126
- }, 200);
127
- });
128
- }
129
-
130
- function WsalSsasChange(value){
131
- jQuery('div.wsal-ssas-dd').hide();
132
- jQuery('input.wsal-ssas').attr('disabled', true);
133
- jQuery('#wsal-cbid').val(value);
134
- jQuery('#audit-log-viewer').submit();
135
- }
136
-
137
- function WsalDisableCustom(link, meta_key){
138
- var nfe = jQuery(this).parents('div:first');
139
- jQuery(link).hide();
140
- jQuery.ajax({
141
- type: 'POST',
142
- url: ajaxurl,
143
- async: false,
144
- data: { action: 'AjaxDisableCustomField', notice: meta_key },
145
- success: function(data) {
146
- var notice = jQuery('<div class="updated" data-notice-name="notifications-extension"></div>').html(data);
147
- jQuery("h2:first").after(notice);
148
- }
149
- });
150
  }
1
+ var WsalData;
2
+
3
+ window['WsalAuditLogRefreshed'] = function(){
4
+ // fix pagination links causing form params to get lost
5
+ jQuery('span.pagination-links a').click(function(ev){
6
+ ev.preventDefault();
7
+ var deparam = function(url){
8
+ var obj = {};
9
+ var pairs = url.split('&');
10
+ for(var i in pairs){
11
+ var split = pairs[i].split('=');
12
+ obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
13
+ }
14
+ return obj;
15
+ };
16
+ var paged = deparam(this.href).paged;
17
+ if (typeof paged === 'undefined') paged = 1;
18
+ jQuery('#audit-log-viewer').append(
19
+ jQuery('<input type="hidden" name="paged"/>').val(paged)
20
+ ).submit();
21
+ });
22
+ };
23
+
24
+ function WsalAuditLogInit(_WsalData){
25
+ WsalData = _WsalData;
26
+ var WsalTkn = WsalData.autorefresh.token;
27
+
28
+ // list refresher
29
+ var WsalAjx = null;
30
+ var WsalChk = function(){
31
+ if(WsalAjx)WsalAjx.abort();
32
+ WsalAjx = jQuery.post(WsalData.ajaxurl, {
33
+ action: 'AjaxRefresh',
34
+ logcount: WsalTkn
35
+ }, function(data){
36
+ WsalAjx = null;
37
+ if(data && data !== 'false'){
38
+ WsalTkn = data;
39
+ jQuery('#audit-log-viewer').load(
40
+ location.href + ' #audit-log-viewer-content',
41
+ window['WsalAuditLogRefreshed']
42
+ );
43
+ }
44
+ WsalChk();
45
+ });
46
+ };
47
+ if(WsalData.autorefresh.enabled){
48
+ setInterval(WsalChk, 40000);
49
+ WsalChk();
50
+ }
51
+
52
+ WsalSsasInit();
53
+ }
54
+
55
+ var WsalIppsPrev;
56
+
57
+ function WsalIppsFocus(value){
58
+ WsalIppsPrev = value;
59
+ }
60
+
61
+ function WsalIppsChange(value){
62
+ if(value === ''){
63
+ value = window.prompt(WsalData.tr8n.numofitems, WsalIppsPrev);
64
+ if(value === null || value === WsalIppsPrev)return this.value = WsalIppsPrev; // operation canceled
65
+ }
66
+ jQuery('select.wsal-ipps').attr('disabled', true);
67
+ jQuery.post(WsalData.ajaxurl, {
68
+ action: 'AjaxSetIpp',
69
+ count: value
70
+ }, function(){
71
+ location.reload();
72
+ });
73
+ }
74
+
75
+ function WsalSsasInit(){
76
+ var SsasAjx = null;
77
+ var SsasInps = jQuery("input.wsal-ssas");
78
+ SsasInps.after('<div class="wsal-ssas-dd" style="display: none;"/>');
79
+ SsasInps.click(function(){
80
+ jQuery(this).select();
81
+ });
82
+ window['WsalAuditLogRefreshed']();
83
+ SsasInps.keyup(function(){
84
+ var SsasInp = jQuery(this);
85
+ var SsasDiv = SsasInp.next();
86
+ var SsasVal = SsasInp.val();
87
+ if(SsasAjx)SsasAjx.abort();
88
+ SsasInp.removeClass('loading');
89
+
90
+ // do a new search
91
+ if(SsasInp.attr('data-oldvalue') !== SsasVal && SsasVal.length > 2){
92
+ SsasInp.addClass('loading');
93
+ SsasAjx = jQuery.post(WsalData.ajaxurl, {
94
+ action: 'AjaxSearchSite',
95
+ search: SsasVal
96
+ }, function(data){
97
+ if(SsasAjx)SsasAjx = null;
98
+ SsasInp.removeClass('loading');
99
+ SsasDiv.hide();
100
+ SsasDiv.html('');
101
+ if(data && data.length){
102
+ var SsasReg = new RegExp(SsasVal.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'gi');
103
+ for (var i = 0; i < data.length; i++){
104
+ var link = jQuery('<a href="javascript:;" onclick="WsalSsasChange(' + data[i].blog_id + ')"/>')
105
+ .text(data[i].blogname + ' (' + data[i].domain + ')');
106
+ link.html(link.text().replace(SsasReg, '<u>$&</u>'));
107
+ SsasDiv.append(link);
108
+ }
109
+ }else{
110
+ SsasDiv.append(jQuery('<span/>').text(WsalData.tr8n.searchnone));
111
+ }
112
+ SsasDiv.prepend(jQuery('<a href="javascript:;" onclick="WsalSsasChange(0)" class="allsites"/>').text(WsalData.tr8n.searchback));
113
+ SsasDiv.show();
114
+ }, 'json');
115
+ SsasInp.attr('data-oldvalue', SsasVal);
116
+ }
117
+
118
+ // handle keys
119
+ });
120
+ SsasInps.blur(function(){
121
+ setTimeout(function(){
122
+ var SsasInp = jQuery(this);
123
+ var SsasDiv = SsasInp.next();
124
+ SsasInp.attr('data-oldvalue', '');
125
+ SsasDiv.hide();
126
+ }, 200);
127
+ });
128
+ }
129
+
130
+ function WsalSsasChange(value){
131
+ jQuery('div.wsal-ssas-dd').hide();
132
+ jQuery('input.wsal-ssas').attr('disabled', true);
133
+ jQuery('#wsal-cbid').val(value);
134
+ jQuery('#audit-log-viewer').submit();
135
+ }
136
+
137
+ function WsalDisableCustom(link, meta_key){
138
+ var nfe = jQuery(this).parents('div:first');
139
+ jQuery(link).hide();
140
+ jQuery.ajax({
141
+ type: 'POST',
142
+ url: ajaxurl,
143
+ async: false,
144
+ data: { action: 'AjaxDisableCustomField', notice: meta_key },
145
+ success: function(data) {
146
+ var notice = jQuery('<div class="updated" data-notice-name="notifications-extension"></div>').html(data);
147
+ jQuery("h2:first").after(notice);
148
+ }
149
+ });
150
  }
js/common.js CHANGED
@@ -1,14 +1,14 @@
1
-
2
- jQuery(document).ready(function(){
3
- jQuery('a.wsal-dismiss-notification').click(function(){
4
- var nfe = jQuery(this).parents('div:first');
5
- var nfn = nfe.attr('data-notice-name');
6
- jQuery.ajax({
7
- type: 'POST',
8
- url: ajaxurl,
9
- async: false,
10
- data: { action: 'AjaxDismissNotice', notice: nfn }
11
- });
12
- nfe.fadeOut();
13
- });
14
- });
1
+
2
+ jQuery(document).ready(function(){
3
+ jQuery('a.wsal-dismiss-notification').click(function(){
4
+ var nfe = jQuery(this).parents('div:first');
5
+ var nfn = nfe.attr('data-notice-name');
6
+ jQuery.ajax({
7
+ type: 'POST',
8
+ url: ajaxurl,
9
+ async: false,
10
+ data: { action: 'AjaxDismissNotice', notice: nfn }
11
+ });
12
+ nfe.fadeOut();
13
+ });
14
+ });
js/nice_r.js CHANGED
@@ -1,12 +1,12 @@
1
- function nice_r_toggle(pfx, id){
2
- var el = document.getElementById(pfx+'_v'+id);
3
- if(el){
4
- if(el.style.display==='block'){
5
- el.style.display = 'none';
6
- document.getElementById(pfx+'_a'+id).innerHTML = '&#9658;';
7
- }else{
8
- el.style.display = 'block';
9
- document.getElementById(pfx+'_a'+id).innerHTML = '&#9660;';
10
- }
11
- }
12
  }
1
+ function nice_r_toggle(pfx, id){
2
+ var el = document.getElementById(pfx+'_v'+id);
3
+ if(el){
4
+ if(el.style.display==='block'){
5
+ el.style.display = 'none';
6
+ document.getElementById(pfx+'_a'+id).innerHTML = '&#9658;';
7
+ }else{
8
+ el.style.display = 'block';
9
+ document.getElementById(pfx+'_a'+id).innerHTML = '&#9660;';
10
+ }
11
+ }
12
  }
js/settings.js CHANGED
@@ -1,71 +1,71 @@
1
- jQuery(document).ready(function(){
2
- var RemoveSecToken = function(){
3
- var $this = jQuery(this).parents('span:first');
4
- $this.addClass('sectoken-del').fadeOut('fast', function(){
5
- $this.remove();
6
- });
7
- };
8
-
9
- jQuery('#ViewerQueryBox, #EditorQueryBox, #ExRoleQueryBox, #ExUserQueryBox, #CustomQueryBox').keydown(function(event){
10
- if(event.keyCode === 13) {
11
- var type = jQuery(this).attr('id').substr(0, 6);
12
- jQuery('#'+type+'QueryAdd').click();
13
- return false;
14
- }
15
- });
16
-
17
- jQuery('#ViewerQueryAdd, #EditorQueryAdd, #ExRoleQueryAdd, #ExUserQueryAdd, #CustomQueryAdd').click(function(){
18
- var type = jQuery(this).attr('id').substr(0, 6);
19
- var value = jQuery.trim(jQuery('#'+type+'QueryBox').val());
20
- var existing = jQuery('#'+type+'List input').filter(function() { return this.value === value; });
21
-
22
- if(!value || existing.length)return; // if value is empty or already used, stop here
23
-
24
- jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', true);
25
- jQuery.post(jQuery('#ajaxurl').val(), {action: 'AjaxCheckSecurityToken', token: value}, function(data){
26
- jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', false);
27
- if (type != 'Custom') {
28
- if(data==='other') {
29
- alert('The specified token is not a user nor a role!');
30
- jQuery('#'+type+'QueryBox').val('');
31
- return;
32
- }
33
- }
34
- jQuery('#'+type+'QueryBox').val('');
35
- jQuery('#'+type+'List').append(jQuery('<span class="sectoken-'+data+'"/>').text(value).append(
36
- jQuery('<input type="hidden" name="'+type+'s[]"/>').val(value),
37
- jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken)
38
- ));
39
- });
40
- });
41
-
42
- jQuery('#ViewerList>span>a, #EditorList>span>a, #ExRoleList>span>a, #ExUserList>span>a, #CustomList>span>a').click(RemoveSecToken);
43
-
44
- jQuery('#RestrictAdmins').change(function(){
45
- var user = jQuery('#RestrictAdminsDefaultUser').val();
46
- var fltr = function() { return this.value === user; };
47
- if (this.checked && jQuery('#EditorList input').filter(fltr).length === 0) {
48
- jQuery('#EditorList').append(
49
- jQuery('<span class="sectoken-user"/>').text(user)
50
- .prepend(jQuery('<input type="hidden" name="Editors[]"/>').val(user))
51
- .append(jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken))
52
- );
53
- }
54
- });
55
-
56
-
57
- var usersUrl = ajaxurl + "?action=AjaxGetAllUsers";
58
- jQuery("#ExUserQueryBox").autocomplete({
59
- source: usersUrl,
60
- minLength:1
61
- });
62
-
63
- var rolesUrl = ajaxurl + "?action=AjaxGetAllRoles";
64
- jQuery("#ExRoleQueryBox").autocomplete({
65
- source: rolesUrl,
66
- minLength:1
67
- });
68
-
69
- });
70
-
71
-
1
+ jQuery(document).ready(function(){
2
+ var RemoveSecToken = function(){
3
+ var $this = jQuery(this).parents('span:first');
4
+ $this.addClass('sectoken-del').fadeOut('fast', function(){
5
+ $this.remove();
6
+ });
7
+ };
8
+
9
+ jQuery('#ViewerQueryBox, #EditorQueryBox, #ExRoleQueryBox, #ExUserQueryBox, #CustomQueryBox').keydown(function(event){
10
+ if(event.keyCode === 13) {
11
+ var type = jQuery(this).attr('id').substr(0, 6);
12
+ jQuery('#'+type+'QueryAdd').click();
13
+ return false;
14
+ }
15
+ });
16
+
17
+ jQuery('#ViewerQueryAdd, #EditorQueryAdd, #ExRoleQueryAdd, #ExUserQueryAdd, #CustomQueryAdd').click(function(){
18
+ var type = jQuery(this).attr('id').substr(0, 6);
19
+ var value = jQuery.trim(jQuery('#'+type+'QueryBox').val());
20
+ var existing = jQuery('#'+type+'List input').filter(function() { return this.value === value; });
21
+
22
+ if(!value || existing.length)return; // if value is empty or already used, stop here
23
+
24
+ jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', true);
25
+ jQuery.post(jQuery('#ajaxurl').val(), {action: 'AjaxCheckSecurityToken', token: value}, function(data){
26
+ jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', false);
27
+ if (type != 'Custom') {
28
+ if(data==='other') {
29
+ alert('The specified token is not a user nor a role!');
30
+ jQuery('#'+type+'QueryBox').val('');
31
+ return;
32
+ }
33
+ }
34
+ jQuery('#'+type+'QueryBox').val('');
35
+ jQuery('#'+type+'List').append(jQuery('<span class="sectoken-'+data+'"/>').text(value).append(
36
+ jQuery('<input type="hidden" name="'+type+'s[]"/>').val(value),
37
+ jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken)
38
+ ));
39
+ });
40
+ });
41
+
42
+ jQuery('#ViewerList>span>a, #EditorList>span>a, #ExRoleList>span>a, #ExUserList>span>a, #CustomList>span>a').click(RemoveSecToken);
43
+
44
+ jQuery('#RestrictAdmins').change(function(){
45
+ var user = jQuery('#RestrictAdminsDefaultUser').val();
46
+ var fltr = function() { return this.value === user; };
47
+ if (this.checked && jQuery('#EditorList input').filter(fltr).length === 0) {
48
+ jQuery('#EditorList').append(
49
+ jQuery('<span class="sectoken-user"/>').text(user)
50
+ .prepend(jQuery('<input type="hidden" name="Editors[]"/>').val(user))
51
+ .append(jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken))
52
+ );
53
+ }
54
+ });
55
+
56
+
57
+ var usersUrl = ajaxurl + "?action=AjaxGetAllUsers";
58
+ jQuery("#ExUserQueryBox").autocomplete({
59
+ source: usersUrl,
60
+ minLength:1
61
+ });
62
+
63
+ var rolesUrl = ajaxurl + "?action=AjaxGetAllRoles";
64
+ jQuery("#ExRoleQueryBox").autocomplete({
65
+ source: rolesUrl,
66
+ minLength:1
67
+ });
68
+
69
+ });
70
+
71
+
readme.txt CHANGED
@@ -7,7 +7,7 @@ License URI: http://www.gnu.org/licenses/gpl.html
7
  Tags: wordpress security plugin, wordpress security audit log, audit log, wordpress log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, security audit trail, wordpress security alerts, wordpress monitor, wordpress security monitor, wordpress admin, wordpress admin monitoring, analytics, activity, admin, multisite, wordpress multisite, actions, dashboard, log, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report
8
  Requires at least: 3.6
9
  Tested up to: 4.1.1
10
- Stable tag: 1.5.0
11
 
12
  Keep an WordPress audit log of all users' changes and other under the hood activity - Identify WordPress issues before they become security problems.
13
 
@@ -110,6 +110,7 @@ WP Security Audit Log plugin also has a number of features that make WordPress a
110
  * [Design Wall](http://www.designwall.com/blog/10-wordpress-multisite-plugins-you-shouldnt-live-without/)
111
  * [WPLift](http://wplift.com/wordpress-event-tracking)
112
  * [BlogVault](https://blogvault.net/wp-security-audit-log-plugin-review/)
 
113
 
114
  = Related Links and Documentation =
115
  For more information and to get started with WordPress Security, check out the following:
@@ -159,6 +160,12 @@ You can use the premium add-on [Security Audit Log Search](http://www.wpwhitesec
159
  = Can I generate reports from the WordPress security audit log? =
160
  Yes it is possible to do so with the premium [WSAL Reporting Extension](http://www.wpwhitesecurity.com/plugins-premium-extensions/wordpress-reports-extension/). This plugin extension allows you to generate any type of WordPress report using any type of data source. Reports can be generated in HTML and CSV format.
161
 
 
 
 
 
 
 
162
  == Screenshots ==
163
 
164
  1. The Audit Log Viewer from where the WordPress administrator can see all the security events generated by WP Security Audit Log WordPress plugin.
@@ -171,6 +178,16 @@ Yes it is possible to do so with the premium [WSAL Reporting Extension](http://w
171
 
172
  == Changelog ==
173
 
 
 
 
 
 
 
 
 
 
 
174
  = 1.5.0 (2015-03-18) =
175
  * **New Features**
176
  * Ability to exclude custom fields from monitoring (custom fields can be excluded from the Audit Log Viewer with a simple click or you can specify them in the settings)
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
8
  Requires at least: 3.6
9
  Tested up to: 4.1.1
10
+ Stable tag: 1.5.1
11
 
12
  Keep an WordPress audit log of all users' changes and other under the hood activity - Identify WordPress issues before they become security problems.
13
 
110
  * [Design Wall](http://www.designwall.com/blog/10-wordpress-multisite-plugins-you-shouldnt-live-without/)
111
  * [WPLift](http://wplift.com/wordpress-event-tracking)
112
  * [BlogVault](https://blogvault.net/wp-security-audit-log-plugin-review/)
113
+ * [MyWPExpert](http://www.mywpexpert.com/wp-security-audit-log/)
114
 
115
  = Related Links and Documentation =
116
  For more information and to get started with WordPress Security, check out the following:
160
  = Can I generate reports from the WordPress security audit log? =
161
  Yes it is possible to do so with the premium [WSAL Reporting Extension](http://www.wpwhitesecurity.com/plugins-premium-extensions/wordpress-reports-extension/). This plugin extension allows you to generate any type of WordPress report using any type of data source. Reports can be generated in HTML and CSV format.
162
 
163
+ = Can I exclude users or roles from being monitored? =
164
+ Yes it is possible to exclude both users and roles from being monitored. To exclude a user or a role specify it in the Excluded Objects section in the plugin's settings node.
165
+
166
+ = Can I exclude custom fields from being monitored? =
167
+ Yes it is possible to exclude custom fields from being monitored. To exclude a custom field you can specify it in the Excluded Objects section in the plugin's settings node, else you can click the option Exclude Custom Field from Monitoring from the alert itself.
168
+
169
  == Screenshots ==
170
 
171
  1. The Audit Log Viewer from where the WordPress administrator can see all the security events generated by WP Security Audit Log WordPress plugin.
178
 
179
  == Changelog ==
180
 
181
+ = 1.5.1 (2015-03-26) =
182
+ * **Improvements**
183
+ * Completely removed the user of the is_admin() function to follow better security practises
184
+
185
+ * **Bug Fixes**
186
+ * Updated the licensing mechanism to correct problem where [WP Security Audit Log premium add-ons](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/extensions/) could not be activated.
187
+ * Fixed several issues where the database tables were not being created during install or upgrade. [Support ticket](https://wordpress.org/support/topic/wp_wsal_options-not-created-with-plugin-update?replies=8) and [Support ticket 2](https://wordpress.org/support/topic/missing-database-tables-1?replies=9)
188
+ * Fixed an issue where the plugin did not monitor any activity in specific scenarios. [Support ticket](https://wordpress.org/support/topic/clean-install-not-reporting-when-posts-or-pages-are-creatededited?replies=4) and [Support ticket 2](https://wordpress.org/support/topic/blank-audit-log-page?replies=2)
189
+ * Removed duplicate options in the settings page. [Support ticket](https://wordpress.org/support/topic/refresh-audit-view-refresh-audit-log-viewer?replies=5)
190
+
191
  = 1.5.0 (2015-03-18) =
192
  * **New Features**
193
  * Ability to exclude custom fields from monitoring (custom fields can be excluded from the Audit Log Viewer with a simple click or you can specify them in the settings)
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. 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: 1.5.0
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpwhitesecurity.com/
10
  License: GPL2
@@ -161,7 +161,6 @@ class WpSecurityAuditLog {
161
  * @internal Start to trigger the events after installation.
162
  */
163
  public function Init(){
164
-
165
  WpSecurityAuditLog::GetInstance()->sensors->HookEvents();
166
  }
167
 
@@ -205,6 +204,20 @@ class WpSecurityAuditLog {
205
  * @internal Load the rest of the system.
206
  */
207
  public function Load(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  // load translations
209
  load_plugin_textdomain('wp-security-audit-log', false, basename( dirname( __FILE__ ) ) . '/languages/');
210
 
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. 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: 1.5.1
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpwhitesecurity.com/
10
  License: GPL2
161
  * @internal Start to trigger the events after installation.
162
  */
163
  public function Init(){
 
164
  WpSecurityAuditLog::GetInstance()->sensors->HookEvents();
165
  }
166
 
204
  * @internal Load the rest of the system.
205
  */
206
  public function Load(){
207
+
208
+ $optionsTable = new WSAL_DB_Option();
209
+ if (!$optionsTable->IsInstalled()) {
210
+ $optionsTable->Install();
211
+ //setting the prunig date with the old value or the default value
212
+ $pruningDate = $this->settings->GetPruningDate();
213
+ $this->settings->SetPruningDate($pruningDate);
214
+
215
+ $pruningEnabled = $this->settings->IsPruningLimitEnabled();
216
+ $this->settings->SetPruningLimitEnabled($pruningEnabled);
217
+ //setting the prunig limit with the old value or the default value
218
+ $pruningLimit = $this->settings->GetPruningLimit();
219
+ $this->settings->SetPruningLimit($pruningLimit);
220
+ }
221
  // load translations
222
  load_plugin_textdomain('wp-security-audit-log', false, basename( dirname( __FILE__ ) ) . '/languages/');
223