Version Description
(2014-07-2) = * New Features * Unlimited Alerts can be stored (removed the 5000 alerts limit) * Alert time now includes milliseconds for more precision (ideal for auditing and compliance) * Reported alert time is now relative to user's configured timezone * Alerts automatic pruning procedures can now be enabled / disabled * Option to hide WP Security Audit Log from plugins page in WordPress * If there are more than 15 websites in a multisite installation, an auto complete site search box is shown instead of the drop down menu
- New WordPress Security Alerts
- Alert 5007: User has uninstalled / deleted a theme
- Alert 5008: Super administrator network activated a theme on multisite
- Alert 5009: Super administrator network deactivated a theme on multisite
Download this release
Release Info
Developer | WPWhiteSecurity |
Plugin | WP Security Audit Log |
Version | 1.2.0 |
Comparing to | |
See all releases |
Code changes from version 1.1.0 to 1.2.0
- classes/AbstractSandboxTask.php +68 -0
- classes/AlertManager.php +1 -1
- classes/DB/ActiveRecord.php +10 -10
- classes/DB/Occurrence.php +17 -2
- classes/Loggers/Database.php +4 -6
- classes/Nicer.php +288 -185
- classes/Sensors/LogInOut.php +1 -1
- classes/Sensors/Multisite.php +54 -8
- classes/Sensors/PhpErrors.php +5 -0
- classes/Sensors/PluginsThemes.php +62 -60
- classes/Sensors/Request.php +2 -3
- classes/Settings.php +25 -1
- classes/Views/AuditLog.php +86 -15
- classes/Views/Sandbox.php +45 -2
- classes/Views/Settings.php +32 -11
- css/auditlog.css +43 -2
- css/nice_r.css +92 -74
- defaults.php +6 -3
- js/auditlog.js +58 -1
- readme.txt +25 -3
- wp-security-audit-log.php +19 -23
classes/AbstractSandboxTask.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class WSAL_AbstractSandboxTask {
|
4 |
+
public function __construct() {
|
5 |
+
// remove time limit and clear output buffers
|
6 |
+
set_time_limit(0);
|
7 |
+
ob_implicit_flush(true);
|
8 |
+
while(ob_get_level())ob_end_flush();
|
9 |
+
|
10 |
+
// set up shutdown handler
|
11 |
+
register_shutdown_function(array($this, 'Shutdown'));
|
12 |
+
|
13 |
+
// run event sequence
|
14 |
+
$this->Header();
|
15 |
+
try{
|
16 |
+
$this->Execute();
|
17 |
+
}catch(Exception $ex){
|
18 |
+
$this->Message(get_class($ex) . ' [' . basename($ex->getFile()) . ':' . $ex->getLine() . ']: ' . $ex->getMessage());
|
19 |
+
$this->Message($ex->getTraceAsString(), true);
|
20 |
+
}
|
21 |
+
$this->Footer();
|
22 |
+
|
23 |
+
// shutdown
|
24 |
+
die();
|
25 |
+
}
|
26 |
+
|
27 |
+
protected function Header(){
|
28 |
+
echo '<!DOCTYPE html><html><body style="margin: 0; padding: 8px; font: 12px Arial; color: #333;">';
|
29 |
+
echo '<div style="position: fixed; top: 0; left: 0; right: 0; padding: 8px; background: #F0F0F0;">';
|
30 |
+
echo ' <div id="bar" style=" border-top: 2px solid #0AE; top: 20px; height: 0; width: 0%;"> </div>';
|
31 |
+
echo ' <span id="msg"></span> <span id="prg"></span>';
|
32 |
+
echo '</div>';
|
33 |
+
echo '<div id="msgs" style="font-family: Consolas; margin-top: 30px; white-space: pre;"></div>';
|
34 |
+
echo '<script>';
|
35 |
+
echo ' var bar = document.getElementById("bar");';
|
36 |
+
echo ' var msg = document.getElementById("msg");';
|
37 |
+
echo ' var prg = document.getElementById("prg");';
|
38 |
+
echo ' var msgs = document.getElementById("msgs");';
|
39 |
+
echo '</script>';
|
40 |
+
flush();
|
41 |
+
}
|
42 |
+
|
43 |
+
protected function Footer(){
|
44 |
+
echo '<div style="display: none;">';
|
45 |
+
flush();
|
46 |
+
}
|
47 |
+
|
48 |
+
protected abstract function Execute();
|
49 |
+
|
50 |
+
public function Shutdown(){
|
51 |
+
echo '</div></body></html>';
|
52 |
+
flush();
|
53 |
+
}
|
54 |
+
|
55 |
+
protected function Progress($percent){
|
56 |
+
echo '<script>bar.style.width=prg.innerHTML="' . number_format($percent, 2) . '%";</script>';
|
57 |
+
flush();
|
58 |
+
}
|
59 |
+
|
60 |
+
protected function Message($message, $sticky = false){
|
61 |
+
if($sticky){
|
62 |
+
echo '<script>msgs.appendChild(document.createTextNode(' . json_encode($message . PHP_EOL) . ')); window.scroll(0, document.body.scrollHeight);</script>';
|
63 |
+
}else{
|
64 |
+
echo '<script>msg.innerHTML=' . json_encode($message) . ';</script>';
|
65 |
+
}
|
66 |
+
flush();
|
67 |
+
}
|
68 |
+
}
|
classes/AlertManager.php
CHANGED
@@ -186,7 +186,7 @@ final class WSAL_AlertManager {
|
|
186 |
$data['UserAgent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
187 |
if(!isset($data['CurrentUserID']))
|
188 |
$data['CurrentUserID'] = function_exists('get_current_user_id') ? get_current_user_id() : 0;
|
189 |
-
if(!isset($data['CurrentUserRoles']) && is_user_logged_in())
|
190 |
$data['CurrentUserRoles'] = wp_get_current_user()->roles;
|
191 |
|
192 |
foreach($this->_loggers as $logger)
|
186 |
$data['UserAgent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
187 |
if(!isset($data['CurrentUserID']))
|
188 |
$data['CurrentUserID'] = function_exists('get_current_user_id') ? get_current_user_id() : 0;
|
189 |
+
if(!isset($data['CurrentUserRoles']) && function_exists('is_user_logged_in') && is_user_logged_in())
|
190 |
$data['CurrentUserRoles'] = wp_get_current_user()->roles;
|
191 |
|
192 |
foreach($this->_loggers as $logger)
|
classes/DB/ActiveRecord.php
CHANGED
@@ -52,7 +52,7 @@ abstract class WSAL_DB_ActiveRecord {
|
|
52 |
$sql .= $key . ' BIGINT NOT NULL,'.PHP_EOL;
|
53 |
break;
|
54 |
case is_float($copy->$key):
|
55 |
-
$sql .= $key . '
|
56 |
break;
|
57 |
case is_string($copy->$key):
|
58 |
$sql .= $key . ' TEXT NOT NULL,'.PHP_EOL;
|
@@ -123,6 +123,7 @@ abstract class WSAL_DB_ActiveRecord {
|
|
123 |
}
|
124 |
|
125 |
/**
|
|
|
126 |
* @return boolean Returns whether table structure is installed or not.
|
127 |
*/
|
128 |
public function IsInstalled(){
|
@@ -135,20 +136,16 @@ abstract class WSAL_DB_ActiveRecord {
|
|
135 |
* Install this ActiveRecord structure into DB.
|
136 |
*/
|
137 |
public function Install(){
|
138 |
-
|
139 |
-
|
140 |
-
dbDelta($this->_GetInstallQuery());
|
141 |
-
}
|
142 |
}
|
143 |
|
144 |
/**
|
145 |
* Remove this ActiveRecord structure into DB.
|
146 |
*/
|
147 |
public function Uninstall(){
|
148 |
-
|
149 |
-
|
150 |
-
dbDelta($this->_GetUninstallQuery());
|
151 |
-
}
|
152 |
}
|
153 |
|
154 |
/**
|
@@ -269,7 +266,10 @@ abstract class WSAL_DB_ActiveRecord {
|
|
269 |
$class = get_called_class();
|
270 |
$result = array();
|
271 |
$temp = new $class();
|
272 |
-
$sql = $
|
|
|
|
|
|
|
273 |
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
274 |
$result[] = new $class($data);
|
275 |
}
|
52 |
$sql .= $key . ' BIGINT NOT NULL,'.PHP_EOL;
|
53 |
break;
|
54 |
case is_float($copy->$key):
|
55 |
+
$sql .= $key . ' DOUBLE NOT NULL,'.PHP_EOL;
|
56 |
break;
|
57 |
case is_string($copy->$key):
|
58 |
$sql .= $key . ' TEXT NOT NULL,'.PHP_EOL;
|
123 |
}
|
124 |
|
125 |
/**
|
126 |
+
* @deprecated
|
127 |
* @return boolean Returns whether table structure is installed or not.
|
128 |
*/
|
129 |
public function IsInstalled(){
|
136 |
* Install this ActiveRecord structure into DB.
|
137 |
*/
|
138 |
public function Install(){
|
139 |
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
140 |
+
dbDelta($this->_GetInstallQuery());
|
|
|
|
|
141 |
}
|
142 |
|
143 |
/**
|
144 |
* Remove this ActiveRecord structure into DB.
|
145 |
*/
|
146 |
public function Uninstall(){
|
147 |
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
148 |
+
dbDelta($this->_GetUninstallQuery());
|
|
|
|
|
149 |
}
|
150 |
|
151 |
/**
|
266 |
$class = get_called_class();
|
267 |
$result = array();
|
268 |
$temp = new $class();
|
269 |
+
$sql = (!is_array($args) || !count($args)) // do we really need to prepare() or not?
|
270 |
+
? ('SELECT * FROM ' . $temp->GetTable() . ' WHERE ' . $cond)
|
271 |
+
: $wpdb->prepare('SELECT * FROM ' . $temp->GetTable() . ' WHERE ' . $cond, $args)
|
272 |
+
;
|
273 |
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
274 |
$result[] = new $class($data);
|
275 |
}
|
classes/DB/Occurrence.php
CHANGED
@@ -7,7 +7,7 @@ class WSAL_DB_Occurrence extends WSAL_DB_ActiveRecord {
|
|
7 |
public $id = 0;
|
8 |
public $site_id = 0;
|
9 |
public $alert_id = 0;
|
10 |
-
public $created_on = 0;
|
11 |
public $is_read = false;
|
12 |
public $is_migrated = false;
|
13 |
|
@@ -222,4 +222,19 @@ class WSAL_DB_Occurrence extends WSAL_DB_ActiveRecord {
|
|
222 |
return $this->GetMetaValue('CurrentUserRoles', array());
|
223 |
}
|
224 |
|
225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
public $id = 0;
|
8 |
public $site_id = 0;
|
9 |
public $alert_id = 0;
|
10 |
+
public $created_on = 0.0;
|
11 |
public $is_read = false;
|
12 |
public $is_migrated = false;
|
13 |
|
222 |
return $this->GetMetaValue('CurrentUserRoles', array());
|
223 |
}
|
224 |
|
225 |
+
/**
|
226 |
+
* @return float Number of seconds (and microseconds as fraction) since unix Day 0.
|
227 |
+
* @todo This needs some caching.
|
228 |
+
*/
|
229 |
+
protected function GetMicrotime(){
|
230 |
+
return microtime(true);// + get_option('gmt_offset') * HOUR_IN_SECONDS;
|
231 |
+
}
|
232 |
+
|
233 |
+
public function Save(){
|
234 |
+
// use today's date if not set up
|
235 |
+
if(is_null($this->created_on))
|
236 |
+
$this->created_on = $this->GetMicrotime();
|
237 |
+
|
238 |
+
return parent::Save();
|
239 |
+
}
|
240 |
+
}
|
classes/Loggers/Database.php
CHANGED
@@ -8,10 +8,6 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger {
|
|
8 |
}
|
9 |
|
10 |
public function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false) {
|
11 |
-
|
12 |
-
// use today's date if not set up
|
13 |
-
if(is_null($date))$date = current_time('timestamp');
|
14 |
-
|
15 |
// create new occurrence
|
16 |
$occ = new WSAL_DB_Occurrence();
|
17 |
$occ->is_migrated = $migrated;
|
@@ -34,8 +30,8 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger {
|
|
34 |
if($cnt_items == $max_count)return;
|
35 |
$max_items = max(($cnt_items - $max_count) + 1, 0);
|
36 |
|
37 |
-
$is_date_e =
|
38 |
-
$is_limt_e =
|
39 |
|
40 |
switch(true){
|
41 |
case $is_date_e && $is_limt_e:
|
@@ -50,6 +46,8 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger {
|
|
50 |
$cond = '1 ORDER BY created_on ASC LIMIT %d';
|
51 |
$args = array($max_items);
|
52 |
break;
|
|
|
|
|
53 |
}
|
54 |
if(!isset($cond))return;
|
55 |
|
8 |
}
|
9 |
|
10 |
public function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false) {
|
|
|
|
|
|
|
|
|
11 |
// create new occurrence
|
12 |
$occ = new WSAL_DB_Occurrence();
|
13 |
$occ->is_migrated = $migrated;
|
30 |
if($cnt_items == $max_count)return;
|
31 |
$max_items = max(($cnt_items - $max_count) + 1, 0);
|
32 |
|
33 |
+
$is_date_e = $this->plugin->settings->IsPruningDateEnabled();
|
34 |
+
$is_limt_e = $this->plugin->settings->IsPruningLimitEnabled();
|
35 |
|
36 |
switch(true){
|
37 |
case $is_date_e && $is_limt_e:
|
46 |
$cond = '1 ORDER BY created_on ASC LIMIT %d';
|
47 |
$args = array($max_items);
|
48 |
break;
|
49 |
+
case !$is_date_e && !$is_limt_e:
|
50 |
+
return;
|
51 |
}
|
52 |
if(!isset($cond))return;
|
53 |
|
classes/Nicer.php
CHANGED
@@ -1,186 +1,289 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Inspects and prints out PHP values as HTML in a nicer way than print_r().
|
5 |
+
* @author Christian Sciberras <christian@sciberras.me>
|
6 |
+
* @copyright (c) 2013, Christian Sciberras
|
7 |
+
* @license https://raw.github.com/uuf6429/nice_r/master/LICENSE MIT License
|
8 |
+
* @link https://github.com/uuf6429/nice_r GitHub Repository
|
9 |
+
* @version 2.0
|
10 |
+
* @since 2.0
|
11 |
+
*/
|
12 |
+
class WSAL_Nicer {
|
13 |
+
protected $value;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Allows modification of CSS class prefix.
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
public $css_class = 'nice_r';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Allows modification of HTML id prefix.
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
public $html_id = 'nice_r_v';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Allows modification of JS function used to toggle sections.
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
public $js_func = 'nice_r_toggle';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Whether to inspect and output methods for objects or not.
|
35 |
+
* @var boolean
|
36 |
+
*/
|
37 |
+
public $inspect_methods = false;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Since PHP does not support private constants, we'll have to settle for private static fields.
|
41 |
+
* @var string
|
42 |
+
*/
|
43 |
+
protected static $BEEN_THERE = '__NICE_R_INFINITE_RECURSION_PROTECT__';
|
44 |
+
|
45 |
+
protected $_has_reflection = null;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Constructs new renderer instance.
|
49 |
+
* @param mixed $value The value to inspect and render.
|
50 |
+
* @param boolean $inspectMethods Whether to inspect and output methods for objects or not.
|
51 |
+
*/
|
52 |
+
public function __construct($value, $inspectMethods = false){
|
53 |
+
$this->value = $value;
|
54 |
+
$this->inspect_methods = $inspectMethods;
|
55 |
+
|
56 |
+
if(is_null($this->_has_reflection))
|
57 |
+
$this->_has_reflection = class_exists('ReflectionClass');
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Generates the inspector HTML and returns it as a string.
|
62 |
+
* @return string Generated HTML.
|
63 |
+
*/
|
64 |
+
public function generate(){
|
65 |
+
return $this->_generate_value($this->value, $this->css_class);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Renders the inspector HTML directly to the browser.
|
70 |
+
*/
|
71 |
+
public function render(){
|
72 |
+
echo $this->generate();
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Converts a string to HTML, encoding any special characters.
|
77 |
+
* @param string $text The original string.
|
78 |
+
* @return string The string as HTML.
|
79 |
+
*/
|
80 |
+
protected function _esc_html($text){
|
81 |
+
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
|
82 |
+
}
|
83 |
+
|
84 |
+
protected function _inspect_array(&$html, &$var){
|
85 |
+
$has_subitems = false;
|
86 |
+
|
87 |
+
foreach($var as $k => $v){
|
88 |
+
if($k !== self::$BEEN_THERE){
|
89 |
+
$html .= $this->_generate_keyvalue($k, $v);
|
90 |
+
$has_subitems = true;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
if(!$has_subitems){
|
95 |
+
$html .= '<span class="'.$this->css_class.'_ni">Empty Array</span>';
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
protected function _inspect_object(&$html, &$var){
|
100 |
+
// render properties
|
101 |
+
$has_subitems = false;
|
102 |
+
|
103 |
+
foreach((array)$var as $k=>$v){
|
104 |
+
if($k !== self::$BEEN_THERE){
|
105 |
+
$html .= $this->_generate_keyvalue($k, $v);
|
106 |
+
$has_subitems = true;
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
if(!$has_subitems){
|
111 |
+
$html .= '<span class="'.$this->css_class.'_ni">No Properties</span>';
|
112 |
+
}
|
113 |
+
|
114 |
+
// render methods (if enabled)
|
115 |
+
if($this->inspect_methods){
|
116 |
+
$has_subitems = false;
|
117 |
+
|
118 |
+
foreach((array)get_class_methods($var) as $method){
|
119 |
+
$html .= $this->_generate_callable($var, $method);
|
120 |
+
$has_subitems = true;
|
121 |
+
}
|
122 |
+
|
123 |
+
if(!$has_subitems){
|
124 |
+
$html .= '<span class="'.$this->css_class.'_ni">No Methods</span>';
|
125 |
+
}
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Render a single particular value.
|
131 |
+
* @param mixed $var The value to render
|
132 |
+
* @param string $class Parent CSS class.
|
133 |
+
* @param string $id Item HTML id.
|
134 |
+
*/
|
135 |
+
protected function _generate_value($var, $class = '', $id = ''){
|
136 |
+
$BEENTHERE = self::$BEEN_THERE;
|
137 |
+
$class .= ' '.$this->css_class.'_t_'.gettype($var);
|
138 |
+
|
139 |
+
$html = '<div id="'.$id.'" class="'.$class.'">';
|
140 |
+
|
141 |
+
switch(true){
|
142 |
+
|
143 |
+
// handle arrays
|
144 |
+
case is_array($var):
|
145 |
+
if(isset($var[$BEENTHERE])){
|
146 |
+
$html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
|
147 |
+
}else{
|
148 |
+
$var[$BEENTHERE] = true;
|
149 |
+
$this->_inspect_array($html, $var);
|
150 |
+
unset($var[$BEENTHERE]);
|
151 |
+
}
|
152 |
+
break;
|
153 |
+
|
154 |
+
// handle objects
|
155 |
+
case is_object($var):
|
156 |
+
if(isset($var->$BEENTHERE)){
|
157 |
+
$html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
|
158 |
+
}else{
|
159 |
+
$var->$BEENTHERE = true;
|
160 |
+
$this->_inspect_object($html, $var);
|
161 |
+
unset($var->$BEENTHERE);
|
162 |
+
}
|
163 |
+
break;
|
164 |
+
|
165 |
+
// handle simple types
|
166 |
+
default:
|
167 |
+
$html .= $this->_generate_keyvalue('', $var);
|
168 |
+
break;
|
169 |
+
}
|
170 |
+
|
171 |
+
return $html . '</div>';
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Generates a new unique ID for tagging elements.
|
176 |
+
* @staticvar int $id
|
177 |
+
* @return integer An ID unique per request.
|
178 |
+
*/
|
179 |
+
protected function _generate_dropid(){
|
180 |
+
static $id = 0;
|
181 |
+
return ++$id;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Render a key-value pair.
|
186 |
+
* @staticvar int $id Specifies element id.
|
187 |
+
* @param string $key Key name.
|
188 |
+
* @param mixed $val Key value.
|
189 |
+
*/
|
190 |
+
protected function _generate_keyvalue($key, $val){
|
191 |
+
$id = $this->_generate_dropid();
|
192 |
+
$p = ''; // preview
|
193 |
+
$d = ''; // description
|
194 |
+
$t = gettype($val); // get data type
|
195 |
+
$is_hash = ($t=='array') || ($t=='object');
|
196 |
+
|
197 |
+
switch($t){
|
198 |
+
case 'boolean':
|
199 |
+
$p = $val ? 'TRUE' : 'FALSE';
|
200 |
+
break;
|
201 |
+
case 'integer':
|
202 |
+
case 'double':
|
203 |
+
$p = (string)$val;
|
204 |
+
break;
|
205 |
+
case 'string':
|
206 |
+
$d .= ', '.strlen($val).' characters';
|
207 |
+
$p = $val;
|
208 |
+
break;
|
209 |
+
case 'resource':
|
210 |
+
$d .= ', '.get_resource_type($val).' type';
|
211 |
+
$p = (string)$val;
|
212 |
+
break;
|
213 |
+
case 'array':
|
214 |
+
$d .= ', '.count($val).' elements';
|
215 |
+
break;
|
216 |
+
case 'object':
|
217 |
+
$d .= ', '.get_class($val).', '.count(get_object_vars($val)).' properties';
|
218 |
+
break;
|
219 |
+
}
|
220 |
+
|
221 |
+
$cls = $this->css_class;
|
222 |
+
$xcls = !$is_hash ? $cls.'_ad' : '';
|
223 |
+
$html = '<a '.($is_hash?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
|
224 |
+
$html .= ' <span class="'.$cls.'_a '.$xcls.'" id="'.$this->html_id.'_a'.$id.'">►</span>';
|
225 |
+
$html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($key).'</span>';
|
226 |
+
$html .= ' <span class="'.$cls.'_d">(<span>'.ucwords($t).'</span>'.$d.')</span>';
|
227 |
+
$html .= ' <span class="'.$cls.'_p '.$cls.'_t_'.$t.'">'.$this->_esc_html($p).'</span>';
|
228 |
+
$html .= '</a>';
|
229 |
+
|
230 |
+
if($is_hash){
|
231 |
+
$html .= $this->_generate_value($val, $cls.'_v', $this->html_id.'_v'.$id);
|
232 |
+
}
|
233 |
+
|
234 |
+
return $html;
|
235 |
+
}
|
236 |
+
|
237 |
+
protected function _generate_callable($context, $callback){
|
238 |
+
$id = $this->_generate_dropid();
|
239 |
+
$ref = null;
|
240 |
+
$name = 'Anonymous';
|
241 |
+
$cls = $this->css_class;
|
242 |
+
|
243 |
+
if($this->_has_reflection){
|
244 |
+
if(is_null($context)){
|
245 |
+
$ref = new ReflectionFunction($callback);
|
246 |
+
}else{
|
247 |
+
$ref = new ReflectionMethod($context, $callback);
|
248 |
+
}
|
249 |
+
$name = $ref->getName();
|
250 |
+
}elseif(is_string($callback)){
|
251 |
+
$name = $callback;
|
252 |
+
}
|
253 |
+
|
254 |
+
if(!is_null($ref)){
|
255 |
+
$doc = $ref->getDocComment();
|
256 |
+
$prms = array();
|
257 |
+
foreach($ref->getParameters() as $p){
|
258 |
+
$prms[] = '$' . $p->getName() . (
|
259 |
+
$p->isDefaultValueAvailable()
|
260 |
+
? (
|
261 |
+
' = <span class="'.$cls.'_mv">' . (
|
262 |
+
$p->isDefaultValueConstant()
|
263 |
+
? $p->getDefaultValueConstantName()
|
264 |
+
: var_export($p->getDefaultValue(), true)
|
265 |
+
) . '</span>'
|
266 |
+
)
|
267 |
+
: ''
|
268 |
+
);
|
269 |
+
}
|
270 |
+
}else{
|
271 |
+
$doc = null;
|
272 |
+
$prms = array('???');
|
273 |
+
}
|
274 |
+
|
275 |
+
$xcls = !$doc ? $cls.'_ad' : '';
|
276 |
+
$html = '<a class="'.$cls.'_c" '.($doc?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
|
277 |
+
$html .= ' <span class="'.$cls.'_a '.$xcls.'">►</span>';
|
278 |
+
$html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($name).'<span class="'.$cls.'_ma">(<span>'.implode(', ', $prms).'</span>)</span></span>';
|
279 |
+
$html .= '</a>';
|
280 |
+
|
281 |
+
if($doc){
|
282 |
+
$html .= '<div id="'.$this->html_id.'_v'.$id.'" class="nice_r_v '.$this->css_class.'_t_comment">';
|
283 |
+
$html .= nl2br(str_replace(' ', ' ', $this->_esc_html($doc)));
|
284 |
+
$html .= '</div>';
|
285 |
+
}
|
286 |
+
|
287 |
+
return $html;
|
288 |
+
}
|
289 |
+
}
|
classes/Sensors/LogInOut.php
CHANGED
@@ -53,7 +53,7 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
|
53 |
$occ->SetMetaValue('Attempts',
|
54 |
$occ->GetMetaValue('Attempts', 0) + 1
|
55 |
);
|
56 |
-
$occ->created_on =
|
57 |
$occ->Save();
|
58 |
}else{
|
59 |
// create a new record
|
53 |
$occ->SetMetaValue('Attempts',
|
54 |
$occ->GetMetaValue('Attempts', 0) + 1
|
55 |
);
|
56 |
+
$occ->created_on = null;
|
57 |
$occ->Save();
|
58 |
}else{
|
59 |
// create a new record
|
classes/Sensors/Multisite.php
CHANGED
@@ -3,14 +3,60 @@
|
|
3 |
class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
|
4 |
|
5 |
public function HookEvents() {
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
}
|
15 |
|
16 |
public function EventNewBlog($blog_id){
|
3 |
class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
|
4 |
|
5 |
public function HookEvents() {
|
6 |
+
if($this->plugin->IsMultisite()){
|
7 |
+
add_action('admin_init', array($this, 'EventAdminInit'));
|
8 |
+
if(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'));
|
12 |
+
add_action('activate_blog', array($this, 'EventActivateBlog'));
|
13 |
+
add_action('deactivate_blog', array($this, 'EventDeactivateBlog'));
|
14 |
+
add_action('delete_blog', array($this, 'EventDeleteBlog'));
|
15 |
+
add_action('add_user_to_blog', array($this, 'EventUserAddedToBlog'), 10, 3);
|
16 |
+
add_action('remove_user_from_blog', array($this, 'EventUserRemovedFromBlog'));
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
protected $old_allowedthemes;
|
21 |
+
|
22 |
+
public function EventAdminInit(){
|
23 |
+
$this->old_allowedthemes = array_keys(get_site_option('allowedthemes'));
|
24 |
+
}
|
25 |
+
|
26 |
+
public function EventAdminShutdown(){
|
27 |
+
$new_allowedthemes = array_keys(get_site_option('allowedthemes'));
|
28 |
+
|
29 |
+
// check for enabled themes
|
30 |
+
foreach($new_allowedthemes as $theme)
|
31 |
+
if(!in_array($theme, $this->old_allowedthemes)){
|
32 |
+
$theme = wp_get_theme($theme);
|
33 |
+
$this->plugin->alerts->Trigger(5008, array(
|
34 |
+
'Theme' => (object)array(
|
35 |
+
'Name' => $theme->Name,
|
36 |
+
'ThemeURI' => $theme->ThemeURI,
|
37 |
+
'Description' => $theme->Description,
|
38 |
+
'Author' => $theme->Author,
|
39 |
+
'Version' => $theme->Version,
|
40 |
+
'get_template_directory' => $theme->get_template_directory(),
|
41 |
+
),
|
42 |
+
));
|
43 |
+
}
|
44 |
+
|
45 |
+
// check for disabled themes
|
46 |
+
foreach($this->old_allowedthemes as $theme)
|
47 |
+
if(!in_array($theme, $new_allowedthemes)){
|
48 |
+
$theme = wp_get_theme($theme);
|
49 |
+
$this->plugin->alerts->Trigger(5009, array(
|
50 |
+
'Theme' => (object)array(
|
51 |
+
'Name' => $theme->Name,
|
52 |
+
'ThemeURI' => $theme->ThemeURI,
|
53 |
+
'Description' => $theme->Description,
|
54 |
+
'Author' => $theme->Author,
|
55 |
+
'Version' => $theme->Version,
|
56 |
+
'get_template_directory' => $theme->get_template_directory(),
|
57 |
+
),
|
58 |
+
));
|
59 |
+
}
|
60 |
}
|
61 |
|
62 |
public function EventNewBlog($blog_id){
|
classes/Sensors/PhpErrors.php
CHANGED
@@ -27,12 +27,17 @@ class WSAL_Sensors_PhpErrors extends WSAL_AbstractSensor {
|
|
27 |
public function EventError($errno, $errstr, $errfile = 'unknown', $errline = 0, $errcontext = array()){
|
28 |
if($this->_avoid_error_recursion)return;
|
29 |
|
|
|
|
|
|
|
|
|
30 |
$data = array(
|
31 |
'Code' => $errno,
|
32 |
'Message' => $errstr,
|
33 |
'File' => $errfile,
|
34 |
'Line' => $errline,
|
35 |
'Context' => $errcontext,
|
|
|
36 |
);
|
37 |
|
38 |
$type = 0002; // default (middle ground)
|
27 |
public function EventError($errno, $errstr, $errfile = 'unknown', $errline = 0, $errcontext = array()){
|
28 |
if($this->_avoid_error_recursion)return;
|
29 |
|
30 |
+
ob_start();
|
31 |
+
debug_print_backtrace();
|
32 |
+
$errbacktrace = ob_get_clean();
|
33 |
+
|
34 |
$data = array(
|
35 |
'Code' => $errno,
|
36 |
'Message' => $errstr,
|
37 |
'File' => $errfile,
|
38 |
'Line' => $errline,
|
39 |
'Context' => $errcontext,
|
40 |
+
'Trace' => $errbacktrace,
|
41 |
);
|
42 |
|
43 |
$type = 0002; // default (middle ground)
|
classes/Sensors/PluginsThemes.php
CHANGED
@@ -25,24 +25,24 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
|
|
25 |
|
26 |
// install plugin
|
27 |
if(($action=='install-plugin' || $action=='upload-plugin')){
|
28 |
-
$
|
29 |
-
if(count($
|
30 |
return $this->LogError(
|
31 |
-
'Expected exactly one new plugin but found ' . count($
|
32 |
-
array('NewPlugin' => $
|
33 |
);
|
34 |
-
$
|
35 |
-
$
|
36 |
-
$
|
37 |
-
$
|
38 |
$this->plugin->alerts->Trigger(5000, array(
|
39 |
-
'
|
40 |
-
'Name' => $
|
41 |
-
'PluginURI' => $
|
42 |
-
'Version' => $
|
43 |
-
'Author' => $
|
44 |
-
'Network' => $
|
45 |
-
'plugin_dir_path' => $
|
46 |
),
|
47 |
));
|
48 |
}
|
@@ -96,7 +96,6 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
|
|
96 |
// uninstall plugin
|
97 |
if($is_plugins && in_array($action, array('delete-selected'))){
|
98 |
if(!isset($_REQUEST['verify-delete'])){
|
99 |
-
|
100 |
// first step, before user approves deletion
|
101 |
// TODO store plugin data in session here
|
102 |
}else{
|
@@ -114,7 +113,6 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
|
|
114 |
),
|
115 |
));
|
116 |
}
|
117 |
-
|
118 |
}
|
119 |
}
|
120 |
|
@@ -147,66 +145,70 @@ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
|
|
147 |
}
|
148 |
|
149 |
// install theme
|
150 |
-
if($action
|
151 |
-
$
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
'Version' => $newTheme->Version,
|
165 |
-
'get_template_directory' => $newTheme->get_template_directory(),
|
166 |
-
),
|
167 |
-
));
|
168 |
}
|
169 |
|
170 |
// uninstall theme
|
171 |
-
if($is_themes && in_array($action, array('delete-selected'))){
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
}
|
184 |
}
|
185 |
}
|
186 |
|
187 |
public function EventThemeActivated($themeName){
|
188 |
-
$
|
189 |
-
foreach(wp_get_themes() as $
|
190 |
-
if($
|
191 |
-
$
|
192 |
break;
|
193 |
}
|
194 |
}
|
195 |
-
if($
|
196 |
return $this->LogError(
|
197 |
-
'Could not locate theme named "'
|
198 |
array('ThemeName' => $themeName, 'Themes' => wp_get_themes())
|
199 |
);
|
200 |
$this->plugin->alerts->Trigger(5006, array(
|
201 |
-
'
|
202 |
-
'Name' => $
|
203 |
-
'ThemeURI' => $
|
204 |
-
'Description' => $
|
205 |
-
'Author' => $
|
206 |
-
'Version' => $
|
207 |
-
'get_template_directory' => $
|
208 |
),
|
209 |
));
|
210 |
}
|
211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
}
|
25 |
|
26 |
// install plugin
|
27 |
if(($action=='install-plugin' || $action=='upload-plugin')){
|
28 |
+
$plugin = array_values(array_diff(array_keys(get_plugins()), array_keys($this->old_plugins)));
|
29 |
+
if(count($plugin) != 1)
|
30 |
return $this->LogError(
|
31 |
+
'Expected exactly one new plugin but found ' . count($plugin),
|
32 |
+
array('NewPlugin' => $plugin, 'OldPlugins' => $this->old_plugins, 'NewPlugins' => get_plugins())
|
33 |
);
|
34 |
+
$pluginPath = $plugin[0];
|
35 |
+
$plugin = get_plugins();
|
36 |
+
$plugin = $plugin[$pluginPath];
|
37 |
+
$pluginPath = plugin_dir_path(WP_PLUGIN_DIR . '/' . $pluginPath[0]);
|
38 |
$this->plugin->alerts->Trigger(5000, array(
|
39 |
+
'Plugin' => (object)array(
|
40 |
+
'Name' => $plugin['Name'],
|
41 |
+
'PluginURI' => $plugin['PluginURI'],
|
42 |
+
'Version' => $plugin['Version'],
|
43 |
+
'Author' => $plugin['Author'],
|
44 |
+
'Network' => $plugin['Network'] ? 'True' : 'False',
|
45 |
+
'plugin_dir_path' => $pluginPath,
|
46 |
),
|
47 |
));
|
48 |
}
|
96 |
// uninstall plugin
|
97 |
if($is_plugins && in_array($action, array('delete-selected'))){
|
98 |
if(!isset($_REQUEST['verify-delete'])){
|
|
|
99 |
// first step, before user approves deletion
|
100 |
// TODO store plugin data in session here
|
101 |
}else{
|
113 |
),
|
114 |
));
|
115 |
}
|
|
|
116 |
}
|
117 |
}
|
118 |
|
145 |
}
|
146 |
|
147 |
// install theme
|
148 |
+
if(in_array($action, array('install-theme', 'upload-theme'))){
|
149 |
+
$themes = array_diff(wp_get_themes(), $this->old_themes);
|
150 |
+
foreach($themes as $theme){
|
151 |
+
$this->plugin->alerts->Trigger(5005, array(
|
152 |
+
'Theme' => (object)array(
|
153 |
+
'Name' => $theme->Name,
|
154 |
+
'ThemeURI' => $theme->ThemeURI,
|
155 |
+
'Description' => $theme->Description,
|
156 |
+
'Author' => $theme->Author,
|
157 |
+
'Version' => $theme->Version,
|
158 |
+
'get_template_directory' => $theme->get_template_directory(),
|
159 |
+
),
|
160 |
+
));
|
161 |
+
}
|
|
|
|
|
|
|
|
|
162 |
}
|
163 |
|
164 |
// uninstall theme
|
165 |
+
if($is_themes && in_array($action, array('delete-selected', 'delete'))){
|
166 |
+
foreach($this->GetRemovedThemes() as $theme){
|
167 |
+
$this->plugin->alerts->Trigger(5007, array(
|
168 |
+
'Theme' => (object)array(
|
169 |
+
'Name' => $theme->Name,
|
170 |
+
'ThemeURI' => $theme->ThemeURI,
|
171 |
+
'Description' => $theme->Description,
|
172 |
+
'Author' => $theme->Author,
|
173 |
+
'Version' => $theme->Version,
|
174 |
+
'get_template_directory' => $theme->get_template_directory(),
|
175 |
+
),
|
176 |
+
));
|
177 |
}
|
178 |
}
|
179 |
}
|
180 |
|
181 |
public function EventThemeActivated($themeName){
|
182 |
+
$theme = null;
|
183 |
+
foreach(wp_get_themes() as $item){
|
184 |
+
if($item->Name == $themeName){
|
185 |
+
$theme = $item;
|
186 |
break;
|
187 |
}
|
188 |
}
|
189 |
+
if($theme == null)
|
190 |
return $this->LogError(
|
191 |
+
'Could not locate theme named "' . $theme . '".',
|
192 |
array('ThemeName' => $themeName, 'Themes' => wp_get_themes())
|
193 |
);
|
194 |
$this->plugin->alerts->Trigger(5006, array(
|
195 |
+
'Theme' => (object)array(
|
196 |
+
'Name' => $theme->Name,
|
197 |
+
'ThemeURI' => $theme->ThemeURI,
|
198 |
+
'Description' => $theme->Description,
|
199 |
+
'Author' => $theme->Author,
|
200 |
+
'Version' => $theme->Version,
|
201 |
+
'get_template_directory' => $theme->get_template_directory(),
|
202 |
),
|
203 |
));
|
204 |
}
|
205 |
|
206 |
+
protected function GetRemovedThemes(){
|
207 |
+
$result = $this->old_themes;
|
208 |
+
foreach($result as $i => $theme)
|
209 |
+
if(file_exists($theme->get_template_directory()))
|
210 |
+
unset($result[$i]);
|
211 |
+
return array_values($result);
|
212 |
+
}
|
213 |
+
|
214 |
}
|
classes/Sensors/Request.php
CHANGED
@@ -17,9 +17,8 @@ class WSAL_Sensors_Request extends WSAL_AbstractSensor {
|
|
17 |
. (!empty(self::$envvars) ? str_pad(PHP_EOL, 24) . json_encode(self::$envvars) : '')
|
18 |
. PHP_EOL;
|
19 |
|
20 |
-
if(!file_exists($file))
|
21 |
-
|
22 |
-
return $this->LogError('Could not initialize request log file', array('file' => $file));
|
23 |
|
24 |
$f = fopen($file, 'a');
|
25 |
if($f){
|
17 |
. (!empty(self::$envvars) ? str_pad(PHP_EOL, 24) . json_encode(self::$envvars) : '')
|
18 |
. PHP_EOL;
|
19 |
|
20 |
+
if(!file_exists($file) && !file_put_contents($file, '<'.'?php die(\'Access Denied\'); ?>' . PHP_EOL))
|
21 |
+
return $this->LogError('Could not initialize request log file', array('file' => $file));
|
|
|
22 |
|
23 |
$f = fopen($file, 'a');
|
24 |
if($f){
|
classes/Settings.php
CHANGED
@@ -207,10 +207,26 @@ class WSAL_Settings {
|
|
207 |
* @param integer $newvalue The new maximum number of alerts.
|
208 |
*/
|
209 |
public function SetPruningLimit($newvalue){
|
210 |
-
$newvalue = max(min((int)$newvalue
|
211 |
$this->SetGlobalOption(self::OPT_PRFX . 'pruning-limit', $newvalue);
|
212 |
}
|
213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
protected $_disabled = null;
|
215 |
|
216 |
public function GetDefaultDisabledAlerts(){
|
@@ -363,4 +379,12 @@ class WSAL_Settings {
|
|
363 |
|
364 |
return false;
|
365 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
366 |
}
|
207 |
* @param integer $newvalue The new maximum number of alerts.
|
208 |
*/
|
209 |
public function SetPruningLimit($newvalue){
|
210 |
+
$newvalue = max(/*min(*/(int)$newvalue/*, $this->GetMaxAllowedAlerts())*/, 1);
|
211 |
$this->SetGlobalOption(self::OPT_PRFX . 'pruning-limit', $newvalue);
|
212 |
}
|
213 |
|
214 |
+
public function SetPruningDateEnabled($enabled){
|
215 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'pruning-date-e', $enabled);
|
216 |
+
}
|
217 |
+
|
218 |
+
public function SetPruningLimitEnabled($enabled){
|
219 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'pruning-limit-e', $enabled);
|
220 |
+
}
|
221 |
+
|
222 |
+
public function IsPruningDateEnabled(){
|
223 |
+
return $this->GetGlobalOption(self::OPT_PRFX . 'pruning-date-e', true);
|
224 |
+
}
|
225 |
+
|
226 |
+
public function IsPruningLimitEnabled(){
|
227 |
+
return $this->GetGlobalOption(self::OPT_PRFX . 'pruning-limit-e', true);
|
228 |
+
}
|
229 |
+
|
230 |
protected $_disabled = null;
|
231 |
|
232 |
public function GetDefaultDisabledAlerts(){
|
379 |
|
380 |
return false;
|
381 |
}
|
382 |
+
|
383 |
+
public function IsIncognito(){
|
384 |
+
return $this->GetGlobalOption(self::OPT_PRFX . 'hide-plugin');
|
385 |
+
}
|
386 |
+
|
387 |
+
public function SetIncognito($enabled){
|
388 |
+
return $this->SetGlobalOption(self::OPT_PRFX . 'hide-plugin', $enabled);
|
389 |
+
}
|
390 |
}
|
classes/Views/AuditLog.php
CHANGED
@@ -10,6 +10,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
10 |
add_action('wp_ajax_AjaxInspector', array($this, 'AjaxInspector'));
|
11 |
add_action('wp_ajax_AjaxRefresh', array($this, 'AjaxRefresh'));
|
12 |
add_action('wp_ajax_AjaxSetIpp', array($this, 'AjaxSetIpp'));
|
|
|
13 |
}
|
14 |
|
15 |
public function HasPluginShortcutLink(){
|
@@ -52,6 +53,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
52 |
'ajaxurl' => admin_url('admin-ajax.php'),
|
53 |
'tr8n' => array(
|
54 |
'numofitems' => __('Please enter the number of alerts you would like to see on one page:', 'wp-security-audit-log'),
|
|
|
|
|
55 |
),
|
56 |
'autorefresh' => array(
|
57 |
'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
|
@@ -112,6 +115,28 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
112 |
die;
|
113 |
}
|
114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
public function Header(){
|
116 |
add_thickbox();
|
117 |
wp_enqueue_style(
|
@@ -123,6 +148,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
123 |
}
|
124 |
|
125 |
public function Footer() {
|
|
|
|
|
126 |
wp_enqueue_script(
|
127 |
'auditlog',
|
128 |
$this->_plugin->GetBaseUrl() . '/js/auditlog.js',
|
@@ -146,6 +173,8 @@ class WSAL_Views_AuditLogList_Internal extends WP_List_Table {
|
|
146 |
public function __construct($plugin){
|
147 |
$this->_plugin = $plugin;
|
148 |
|
|
|
|
|
149 |
parent::__construct(array(
|
150 |
'singular' => 'log',
|
151 |
'plural' => 'logs',
|
@@ -153,6 +182,8 @@ class WSAL_Views_AuditLogList_Internal extends WP_List_Table {
|
|
153 |
'screen' => 'interval-list',
|
154 |
));
|
155 |
}
|
|
|
|
|
156 |
|
157 |
public function no_items(){
|
158 |
_e('No events so far.', 'wp-security-audit-log');
|
@@ -182,24 +213,58 @@ class WSAL_Views_AuditLogList_Internal extends WP_List_Table {
|
|
182 |
|
183 |
// show site alerts widget
|
184 |
if($this->is_multisite() && $this->is_main_blog()){
|
185 |
-
// TODO should I check wp_is_large_network()?
|
186 |
$curr = $this->get_view_site_id();
|
187 |
-
$sites = wp_get_sites();
|
188 |
?><div class="wsal-ssa wsal-ssa-<?php echo $which; ?>">
|
189 |
-
|
190 |
-
|
191 |
-
<?php
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
200 |
</div><?php
|
201 |
}
|
202 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
|
204 |
public function get_columns(){
|
205 |
$cols = array(
|
@@ -254,10 +319,16 @@ class WSAL_Views_AuditLogList_Internal extends WP_List_Table {
|
|
254 |
return '<span class="log-type log-type-' . $const->value
|
255 |
. '" title="' . esc_html($const->name . ': ' . $const->description) . '"></span>';
|
256 |
case 'crtd':
|
257 |
-
return $item->created_on ?
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
case 'user':
|
259 |
$username = $item->GetUsername();
|
260 |
-
if($username && ($user =
|
261 |
$image = get_avatar($user->ID, 32);
|
262 |
$uhtml = '<a href="' . admin_url('user-edit.php?user_id=' . $user->ID)
|
263 |
. '" target="_blank">' . esc_html($user->display_name) . '</a>';
|
10 |
add_action('wp_ajax_AjaxInspector', array($this, 'AjaxInspector'));
|
11 |
add_action('wp_ajax_AjaxRefresh', array($this, 'AjaxRefresh'));
|
12 |
add_action('wp_ajax_AjaxSetIpp', array($this, 'AjaxSetIpp'));
|
13 |
+
add_action('wp_ajax_AjaxSearchSite', array($this, 'AjaxSearchSite'));
|
14 |
}
|
15 |
|
16 |
public function HasPluginShortcutLink(){
|
53 |
'ajaxurl' => admin_url('admin-ajax.php'),
|
54 |
'tr8n' => array(
|
55 |
'numofitems' => __('Please enter the number of alerts you would like to see on one page:', 'wp-security-audit-log'),
|
56 |
+
'searchback' => __('All Sites', 'wp-security-audit-log'),
|
57 |
+
'searchnone' => __('No Results', 'wp-security-audit-log'),
|
58 |
),
|
59 |
'autorefresh' => array(
|
60 |
'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
|
115 |
die;
|
116 |
}
|
117 |
|
118 |
+
public function AjaxSearchSite(){
|
119 |
+
if(!$this->_plugin->settings->CurrentUserCan('view'))
|
120 |
+
die('Access Denied.');
|
121 |
+
if(!isset($_REQUEST['search']))
|
122 |
+
die('Search parameter expected.');
|
123 |
+
|
124 |
+
$grp1 = array();
|
125 |
+
$grp2 = array();
|
126 |
+
|
127 |
+
$search = $_REQUEST['search'];
|
128 |
+
|
129 |
+
foreach($this->_listview->get_sites() as $site){
|
130 |
+
if(stripos($site->blogname, $search) !== false)
|
131 |
+
$grp1[] = $site;
|
132 |
+
else
|
133 |
+
if(stripos($site->domain, $search) !== false)
|
134 |
+
$grp2[] = $site;
|
135 |
+
}
|
136 |
+
|
137 |
+
die(json_encode(array_slice($grp1 + $grp2, 0, 7)));
|
138 |
+
}
|
139 |
+
|
140 |
public function Header(){
|
141 |
add_thickbox();
|
142 |
wp_enqueue_style(
|
148 |
}
|
149 |
|
150 |
public function Footer() {
|
151 |
+
wp_enqueue_script('jquery');
|
152 |
+
wp_enqueue_script('suggest');
|
153 |
wp_enqueue_script(
|
154 |
'auditlog',
|
155 |
$this->_plugin->GetBaseUrl() . '/js/auditlog.js',
|
173 |
public function __construct($plugin){
|
174 |
$this->_plugin = $plugin;
|
175 |
|
176 |
+
$this->_gmt_offset_sec = get_option('gmt_offset') * HOUR_IN_SECONDS;
|
177 |
+
|
178 |
parent::__construct(array(
|
179 |
'singular' => 'log',
|
180 |
'plural' => 'logs',
|
182 |
'screen' => 'interval-list',
|
183 |
));
|
184 |
}
|
185 |
+
|
186 |
+
protected $_gmt_offset_sec = 0;
|
187 |
|
188 |
public function no_items(){
|
189 |
_e('No events so far.', 'wp-security-audit-log');
|
213 |
|
214 |
// show site alerts widget
|
215 |
if($this->is_multisite() && $this->is_main_blog()){
|
|
|
216 |
$curr = $this->get_view_site_id();
|
|
|
217 |
?><div class="wsal-ssa wsal-ssa-<?php echo $which; ?>">
|
218 |
+
<?php if($this->get_site_count() > 15){ ?>
|
219 |
+
<?php $curr = $curr ? get_blog_details($curr) : null; ?>
|
220 |
+
<?php $curr = $curr ? ($curr->blogname . ' (' . $curr->domain . ')') : 'All Sites'; ?>
|
221 |
+
<input type="text" class="wsal-ssas" value="<?php echo esc_attr($curr); ?>"/>
|
222 |
+
<?php }else{ ?>
|
223 |
+
<select class="wsal-ssas" onchange="WsalSsasChange(value);">
|
224 |
+
<option value="0"><?php _e('All Sites', 'wp-security-audit-log'); ?></option>
|
225 |
+
<?php foreach($this->get_sites() as $info){ ?>
|
226 |
+
<option value="<?php echo $info->blog_id; ?>"
|
227 |
+
<?php if($info->blog_id == $curr)echo 'selected="selected"'; ?>><?php
|
228 |
+
echo esc_html($info->blogname) . ' (' . esc_html($info->domain) . ')';
|
229 |
+
?></option>
|
230 |
+
<?php } ?>
|
231 |
+
</select>
|
232 |
+
<?php } ?>
|
233 |
</div><?php
|
234 |
}
|
235 |
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* @param int|null $limit Maximum number of sites to return (null = no limit).
|
239 |
+
* @return object Object with keys: blog_id, blogname, domain
|
240 |
+
*/
|
241 |
+
public function get_sites($limit = null){
|
242 |
+
global $wpdb;
|
243 |
+
|
244 |
+
// build query
|
245 |
+
$sql = 'SELECT blog_id, domain FROM ' . $wpdb->blogs;
|
246 |
+
if(!is_null($limit))$sql .= ' LIMIT ' . $limit;
|
247 |
+
|
248 |
+
// execute query
|
249 |
+
$res = $wpdb->get_results($sql);
|
250 |
+
|
251 |
+
// modify result
|
252 |
+
foreach($res as $row){
|
253 |
+
$row->blogname = get_blog_option($row->blog_id, 'blogname');
|
254 |
+
}
|
255 |
+
|
256 |
+
// return result
|
257 |
+
return $res;
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* @return int The number of sites on the network.
|
262 |
+
*/
|
263 |
+
public function get_site_count(){
|
264 |
+
global $wpdb;
|
265 |
+
$sql = 'SELECT COUNT(*) FROM ' . $wpdb->blogs;
|
266 |
+
return (int)$wpdb->get_var($sql);
|
267 |
+
}
|
268 |
|
269 |
public function get_columns(){
|
270 |
$cols = array(
|
319 |
return '<span class="log-type log-type-' . $const->value
|
320 |
. '" title="' . esc_html($const->name . ': ' . $const->description) . '"></span>';
|
321 |
case 'crtd':
|
322 |
+
return $item->created_on ? (
|
323 |
+
str_replace(
|
324 |
+
'$$$',
|
325 |
+
substr(number_format(fmod($item->created_on + $this->_gmt_offset_sec, 1), 3), 2),
|
326 |
+
date('Y-m-d<\b\r>h:i:s.$$$&\n\b\s\p;A', $item->created_on + $this->_gmt_offset_sec)
|
327 |
+
)
|
328 |
+
) : '<i>unknown</i>';
|
329 |
case 'user':
|
330 |
$username = $item->GetUsername();
|
331 |
+
if($username && ($user = get_user_by('login', $username))){
|
332 |
$image = get_avatar($user->ID, 32);
|
333 |
$uhtml = '<a href="' . admin_url('user-edit.php?user_id=' . $user->ID)
|
334 |
. '" target="_blank">' . esc_html($user->display_name) . '</a>';
|
classes/Views/Sandbox.php
CHANGED
@@ -34,6 +34,49 @@ class WSAL_Views_Sandbox extends WSAL_AbstractView {
|
|
34 |
protected $snippets = array(
|
35 |
'' => '',
|
36 |
'Current WP User' => 'return wp_get_current_user();',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
);
|
38 |
|
39 |
public function HandleError($code, $message, $filename = 'unknown', $lineno = 0){
|
@@ -99,11 +142,11 @@ class WSAL_Views_Sandbox extends WSAL_AbstractView {
|
|
99 |
echo '</style>';
|
100 |
echo '</head><body>';
|
101 |
|
102 |
-
if(($e = error_get_last()) && !isset($this->exec_data['Errors'])
|
103 |
$this->HandleError($e['type'], $e['message'], $e['file'], $e['line']);
|
104 |
|
105 |
if(count($this->exec_data)){
|
106 |
-
$result = new WSAL_Nicer($this->exec_data);
|
107 |
$result->render();
|
108 |
}else echo '<div class="faerror">FATAL ERROR</div>';
|
109 |
|
34 |
protected $snippets = array(
|
35 |
'' => '',
|
36 |
'Current WP User' => 'return wp_get_current_user();',
|
37 |
+
|
38 |
+
'Clean PHP Error Events' => '
|
39 |
+
class OccurrenceCleanupTask extends WSAL_AbstractSandboxTask {
|
40 |
+
|
41 |
+
protected $event_ids = array(0000, 0001, 0002, 0003, 0004, 0005);
|
42 |
+
|
43 |
+
protected function Execute(){
|
44 |
+
global $wpdb;
|
45 |
+
$occs = WSAL_DB_Occurrence::LoadMulti(\'alert_id IN (\'.implode(\',\', $this->event_ids).\')\');
|
46 |
+
$c = count($occs);
|
47 |
+
$this->Message($c ? (\'Removing \' . $c . \' events...\') : \'No events to remove!\');
|
48 |
+
foreach($occs as $i => $occ){
|
49 |
+
$this->Message(\'Removing Event \' . $occ->id . \'...\', true);
|
50 |
+
$occ->Delete();
|
51 |
+
$this->Progress(($i + 1) / $c * 100);
|
52 |
+
}
|
53 |
+
}
|
54 |
+
}
|
55 |
+
new OccurrenceCleanupTask();',
|
56 |
+
|
57 |
+
'Multisite Site Creator' => '
|
58 |
+
class DummySiteCreatorTask extends WSAL_AbstractSandboxTask {
|
59 |
+
|
60 |
+
protected $sites_to_create = 100;
|
61 |
+
protected $site_host = \'localhost\';
|
62 |
+
protected $site_path = \'/wordpress-3.8/test$i/\';
|
63 |
+
protected $site_name = \'Test $i\';
|
64 |
+
|
65 |
+
protected function Execute(){
|
66 |
+
global $wpdb;
|
67 |
+
$l = $wpdb->get_var("SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id DESC LIMIT 1") + 1;
|
68 |
+
$this->Message(\'Creating \' . $this->sites_to_create . \' new sites...\');
|
69 |
+
for($i = $l; $i <= $this->sites_to_create + $l; $i++){
|
70 |
+
$this->Progress(($i - $l) / $this->sites_to_create * 100);
|
71 |
+
wpmu_create_blog(
|
72 |
+
str_replace(\'$i\', $i, $this->site_host),
|
73 |
+
str_replace(\'$i\', $i, $this->site_path),
|
74 |
+
str_replace(\'$i\', $i, $this->site_name),
|
75 |
+
1);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
new DummySiteCreatorTask();',
|
80 |
);
|
81 |
|
82 |
public function HandleError($code, $message, $filename = 'unknown', $lineno = 0){
|
142 |
echo '</style>';
|
143 |
echo '</head><body>';
|
144 |
|
145 |
+
if(($e = error_get_last()) && (!isset($this->exec_data['Errors']) || !count($this->exec_data['Errors'])))
|
146 |
$this->HandleError($e['type'], $e['message'], $e['file'], $e['line']);
|
147 |
|
148 |
if(count($this->exec_data)){
|
149 |
+
$result = new WSAL_Nicer($this->exec_data, true);
|
150 |
$result->render();
|
151 |
}else echo '<div class="faerror">FATAL ERROR</div>';
|
152 |
|
classes/Views/Settings.php
CHANGED
@@ -39,12 +39,15 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
39 |
}
|
40 |
|
41 |
protected function Save(){
|
|
|
42 |
$this->_plugin->settings->SetPruningDate($_REQUEST['PruningDate']);
|
|
|
43 |
$this->_plugin->settings->SetPruningLimit($_REQUEST['PruningLimit']);
|
44 |
$this->_plugin->settings->SetWidgetsEnabled($_REQUEST['EnableDashboardWidgets']);
|
45 |
$this->_plugin->settings->SetAllowedPluginViewers(isset($_REQUEST['Viewers']) ? $_REQUEST['Viewers'] : array());
|
46 |
$this->_plugin->settings->SetAllowedPluginEditors(isset($_REQUEST['Editors']) ? $_REQUEST['Editors'] : array());
|
47 |
$this->_plugin->settings->SetRefreshAlertsEnabled($_REQUEST['EnableAuditViewRefresh']);
|
|
|
48 |
$this->_plugin->settings->ClearDevOptions();
|
49 |
if(isset($_REQUEST['DevOptions']))
|
50 |
foreach($_REQUEST['DevOptions'] as $opt)
|
@@ -82,9 +85,13 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
82 |
<td>
|
83 |
<fieldset>
|
84 |
<?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
|
85 |
-
|
86 |
-
<label for="delete1"
|
87 |
-
|
|
|
|
|
|
|
|
|
88 |
value="<?php echo esc_attr($this->_plugin->settings->GetPruningDate()); ?>"/>
|
89 |
<span> <?php echo $text; ?></span>
|
90 |
</fieldset>
|
@@ -94,16 +101,17 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
94 |
<th></th>
|
95 |
<td>
|
96 |
<fieldset>
|
97 |
-
<?php $
|
98 |
-
<?php $
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
|
|
|
|
102 |
value="<?php echo esc_attr($this->_plugin->settings->GetPruningLimit()); ?>"/>
|
|
|
103 |
<span><?php echo $text; ?></span>
|
104 |
-
<p class="description"><?php
|
105 |
-
echo sprintf(__('By default we keep up to %d WordPress Security Events.', 'wp-security-audit-log'), $max);
|
106 |
-
?></p>
|
107 |
</fieldset>
|
108 |
</td>
|
109 |
</tr>
|
@@ -217,6 +225,19 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
217 |
?></fieldset>
|
218 |
</td>
|
219 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
</tbody>
|
221 |
</table>
|
222 |
|
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']));
|
45 |
$this->_plugin->settings->SetPruningLimit($_REQUEST['PruningLimit']);
|
46 |
$this->_plugin->settings->SetWidgetsEnabled($_REQUEST['EnableDashboardWidgets']);
|
47 |
$this->_plugin->settings->SetAllowedPluginViewers(isset($_REQUEST['Viewers']) ? $_REQUEST['Viewers'] : array());
|
48 |
$this->_plugin->settings->SetAllowedPluginEditors(isset($_REQUEST['Editors']) ? $_REQUEST['Editors'] : array());
|
49 |
$this->_plugin->settings->SetRefreshAlertsEnabled($_REQUEST['EnableAuditViewRefresh']);
|
50 |
+
$this->_plugin->settings->SetIncognito(isset($_REQUEST['Incognito']));
|
51 |
$this->_plugin->settings->ClearDevOptions();
|
52 |
if(isset($_REQUEST['DevOptions']))
|
53 |
foreach($_REQUEST['DevOptions'] as $opt)
|
85 |
<td>
|
86 |
<fieldset>
|
87 |
<?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
|
88 |
+
<?php $nbld = $this->_plugin->settings->IsPruningDateEnabled(); ?>
|
89 |
+
<label for="delete1">
|
90 |
+
<input type="checkbox" id="delete1" name="PruneByDate" value="1" <?php if($nbld)echo 'checked="checked"'; ?>
|
91 |
+
onchange="jQuery('#PruningDate').attr('readonly', !checked);"/>
|
92 |
+
<?php echo __('Delete alerts older than', 'wp-security-audit-log'); ?>
|
93 |
+
</label>
|
94 |
+
<input type="text" id="PruningDate" name="PruningDate" placeholder="<?php echo $text; ?>" <?php if(!$nbld)echo 'readonly="readonly"'; ?>
|
95 |
value="<?php echo esc_attr($this->_plugin->settings->GetPruningDate()); ?>"/>
|
96 |
<span> <?php echo $text; ?></span>
|
97 |
</fieldset>
|
101 |
<th></th>
|
102 |
<td>
|
103 |
<fieldset>
|
104 |
+
<?php $text = __('(eg: 80)', 'wp-security-audit-log'); ?>
|
105 |
+
<?php $nbld = $this->_plugin->settings->IsPruningLimitEnabled(); ?>
|
106 |
+
<label for="delete2">
|
107 |
+
<input type="checkbox" id="delete2" name="PruneByLimit" value="1" <?php if($nbld)echo 'checked="checked"'; ?>
|
108 |
+
onchange="jQuery('#PruningLimit').attr('readonly', !checked);"/>
|
109 |
+
<?php echo __('Keep up to', 'wp-security-audit-log'); ?>
|
110 |
+
</label>
|
111 |
+
<input type="text" id="PruningLimit" name="PruningLimit" placeholder="<?php echo $text;?>" <?php if(!$nbld)echo 'readonly="readonly"'; ?>
|
112 |
value="<?php echo esc_attr($this->_plugin->settings->GetPruningLimit()); ?>"/>
|
113 |
+
<?php echo __('alerts', 'wp-security-audit-log'); ?>
|
114 |
<span><?php echo $text; ?></span>
|
|
|
|
|
|
|
115 |
</fieldset>
|
116 |
</td>
|
117 |
</tr>
|
225 |
?></fieldset>
|
226 |
</td>
|
227 |
</tr>
|
228 |
+
|
229 |
+
<tr>
|
230 |
+
<th><label for="Incognito"><?php _e('Hide Plugin from Plugins Page', 'wp-security-audit-log'); ?></label></th>
|
231 |
+
<td>
|
232 |
+
<fieldset>
|
233 |
+
<label for="Incognito">
|
234 |
+
<input type="checkbox" name="Incognito" value="1" id="Incognito"<?php
|
235 |
+
if($this->_plugin->settings->IsIncognito())echo ' checked="checked"'; ?>/>
|
236 |
+
<?php _e('Hide', 'wp-security-audit-log'); ?>
|
237 |
+
</label>
|
238 |
+
</fieldset>
|
239 |
+
</td>
|
240 |
+
</tr>
|
241 |
</tbody>
|
242 |
</table>
|
243 |
|
css/auditlog.css
CHANGED
@@ -11,6 +11,7 @@
|
|
11 |
width: 56px;
|
12 |
}
|
13 |
|
|
|
14 |
.wsal-ssa select {
|
15 |
margin-bottom: 6px;
|
16 |
width: 120px;
|
@@ -25,7 +26,7 @@
|
|
25 |
}
|
26 |
|
27 |
.column-crtd {
|
28 |
-
width:
|
29 |
}
|
30 |
|
31 |
.column-user {
|
@@ -131,4 +132,44 @@ td.column-user {
|
|
131 |
.log-type-8192:after,
|
132 |
.log-type-16384:after,
|
133 |
.log-type-E_DEBUG:after
|
134 |
-
{ background: #09E; content: "i"; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
width: 56px;
|
12 |
}
|
13 |
|
14 |
+
.wsal-ssa input,
|
15 |
.wsal-ssa select {
|
16 |
margin-bottom: 6px;
|
17 |
width: 120px;
|
26 |
}
|
27 |
|
28 |
.column-crtd {
|
29 |
+
width: 120px;
|
30 |
}
|
31 |
|
32 |
.column-user {
|
132 |
.log-type-8192:after,
|
133 |
.log-type-16384:after,
|
134 |
.log-type-E_DEBUG:after
|
135 |
+
{ background: #09E; content: "i"; }
|
136 |
+
|
137 |
+
/* search box */
|
138 |
+
.wsal-ssas-dd {
|
139 |
+
position: absolute;
|
140 |
+
border: 1px solid windowframe;
|
141 |
+
background: #FFF;
|
142 |
+
padding: 0;
|
143 |
+
margin: -8px 16px;
|
144 |
+
background: window;
|
145 |
+
color: windowtext;
|
146 |
+
min-width: 140px;
|
147 |
+
}
|
148 |
+
.wsal-ssas-dd * {
|
149 |
+
cursor: default;
|
150 |
+
}
|
151 |
+
.wsal-ssas-dd a {
|
152 |
+
padding: 2px 8px;
|
153 |
+
display: block;
|
154 |
+
line-height: normal;
|
155 |
+
text-decoration: none;
|
156 |
+
color: windowtext;
|
157 |
+
}
|
158 |
+
.wsal-ssas-dd a:hover,
|
159 |
+
.wsal-ssas-dd .active {
|
160 |
+
background: highlight;
|
161 |
+
color: highlighttext;
|
162 |
+
}
|
163 |
+
.wsal-ssas-dd a u {
|
164 |
+
text-decoration: underline;
|
165 |
+
}
|
166 |
+
.wsal-ssas-dd span {
|
167 |
+
color: #555;
|
168 |
+
font-style: italic;
|
169 |
+
padding: 2px 8px;
|
170 |
+
display: block;
|
171 |
+
line-height: normal;
|
172 |
+
}
|
173 |
+
.wsal-ssas-dd .allsites {
|
174 |
+
border-bottom: 1px solid windowframe;
|
175 |
+
}
|
css/nice_r.css
CHANGED
@@ -1,74 +1,92 @@
|
|
1 |
-
.nice_r {
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
.nice_r a:hover .
|
17 |
-
.nice_r a:hover .nice_r_d
|
18 |
-
.nice_r a:hover .
|
19 |
-
.nice_r a:hover .
|
20 |
-
.nice_r a:hover
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
.nice_r_p.
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.nice_r {
|
2 |
+
font: 12px Consolas, "Lucida Console", monospace;
|
3 |
+
cursor: default;
|
4 |
+
}
|
5 |
+
|
6 |
+
.nice_r a {
|
7 |
+
display: block;
|
8 |
+
text-decoration: none;
|
9 |
+
color: #222;
|
10 |
+
padding: 2px;
|
11 |
+
white-space: nowrap;
|
12 |
+
overflow: hidden;
|
13 |
+
text-overflow: ellipsis;
|
14 |
+
}
|
15 |
+
|
16 |
+
.nice_r a:hover .nice_r_k,
|
17 |
+
.nice_r a:hover .nice_r_d,
|
18 |
+
.nice_r a:hover .nice_r_d span,
|
19 |
+
.nice_r a:hover .nice_r_p,
|
20 |
+
.nice_r a:hover .nice_r_a,
|
21 |
+
.nice_r a:hover {
|
22 |
+
background-color: Highlight;
|
23 |
+
color: HighlightText;
|
24 |
+
}
|
25 |
+
|
26 |
+
.nice_r_a {
|
27 |
+
color: #000;
|
28 |
+
}
|
29 |
+
|
30 |
+
.nice_r_ad {
|
31 |
+
opacity: 0.5;
|
32 |
+
}
|
33 |
+
|
34 |
+
.nice_r_k {
|
35 |
+
color: #060;
|
36 |
+
font-weight: bold;
|
37 |
+
}
|
38 |
+
|
39 |
+
.nice_r_d {
|
40 |
+
font-size: 11px;
|
41 |
+
color: #777;
|
42 |
+
}
|
43 |
+
|
44 |
+
.nice_r_d span {
|
45 |
+
color: #333;
|
46 |
+
}
|
47 |
+
|
48 |
+
.nice_r_p {
|
49 |
+
color: #000;
|
50 |
+
font-weight: bold;
|
51 |
+
}
|
52 |
+
|
53 |
+
.nice_r_v {
|
54 |
+
margin-left: 6px;
|
55 |
+
padding-left: 6px;
|
56 |
+
border-left: 1px dotted #CCC;
|
57 |
+
display: none;
|
58 |
+
}
|
59 |
+
|
60 |
+
.nice_r_ir {
|
61 |
+
font-style: italic;
|
62 |
+
}
|
63 |
+
|
64 |
+
.nice_r_p.nice_r_t_integer,
|
65 |
+
.nice_r_p.nice_r_t_double {
|
66 |
+
color: #F0E;
|
67 |
+
}
|
68 |
+
|
69 |
+
.nice_r_p.nice_r_t_string {
|
70 |
+
color: #E00;
|
71 |
+
}
|
72 |
+
|
73 |
+
.nice_r_p.nice_r_t_boolean {
|
74 |
+
color: #00E;
|
75 |
+
}
|
76 |
+
|
77 |
+
.nice_r_t_comment {
|
78 |
+
color: #080;
|
79 |
+
}
|
80 |
+
|
81 |
+
.nice_r a.nice_r_c .nice_r_k {
|
82 |
+
color: #909;
|
83 |
+
}
|
84 |
+
|
85 |
+
.nice_r a.nice_r_c .nice_r_ma {
|
86 |
+
font-weight: normal;
|
87 |
+
color: #777;
|
88 |
+
}
|
89 |
+
|
90 |
+
.nice_r a.nice_r_c .nice_r_mv {
|
91 |
+
color: #00E;
|
92 |
+
}
|
defaults.php
CHANGED
@@ -111,13 +111,14 @@ WpSecurityAuditLog::GetInstance()
|
|
111 |
array(4007, E_CRITICAL, __('A user was deleted by another user', 'wp-security-audit-log'), __('Deleted User %TargetUserData->Username% with the role of %TargetUserData->Roles%', 'wp-security-audit-log')),
|
112 |
),
|
113 |
'Plugins & Themes' => array(
|
114 |
-
array(5000, E_CRITICAL, __('User installed a plugin', 'wp-security-audit-log'), __('Installed the plugin %
|
115 |
array(5001, E_CRITICAL, __('User activated a WordPress plugin', 'wp-security-audit-log'), __('Activated the plugin %PluginData->Name% installed in %PluginFile%', 'wp-security-audit-log')),
|
116 |
array(5002, E_CRITICAL, __('User deactivated a WordPress plugin', 'wp-security-audit-log'), __('Deactivated the plugin %PluginData->Name% installed in %PluginFile%', 'wp-security-audit-log')),
|
117 |
array(5003, E_CRITICAL, __('User uninstalled a plugin', 'wp-security-audit-log'), __('Uninstalled the plugin %PluginData->Name% which was installed in %PluginFile%', 'wp-security-audit-log')),
|
118 |
array(5004, E_WARNING, __('User upgraded a plugin', 'wp-security-audit-log'), __('Upgraded the plugin %PluginData->Name% installed in %PluginFile%', 'wp-security-audit-log')),
|
119 |
-
array(5005, E_CRITICAL, __('User installed a theme', 'wp-security-audit-log'), __('Installed theme "%
|
120 |
-
array(5006, E_CRITICAL, __('User activated a theme', 'wp-security-audit-log'), __('Activated theme "%
|
|
|
121 |
),
|
122 |
'System Activity' => array(
|
123 |
array(0000, E_CRITICAL, __('Unknown Error', 'wp-security-audit-log'), __('An unexpected error has occurred', 'wp-security-audit-log')),
|
@@ -145,5 +146,7 @@ WpSecurityAuditLog::GetInstance()
|
|
145 |
array(7003, E_CRITICAL, __('Deactivated site has been activated', 'wp-security-audit-log'), __('Activated site %SiteName%', 'wp-security-audit-log')),
|
146 |
array(7004, E_CRITICAL, __('Site has been deactivated', 'wp-security-audit-log'), __('Deactivated site %SiteName%', 'wp-security-audit-log')),
|
147 |
array(7005, E_CRITICAL, __('Existing site deleted from network', 'wp-security-audit-log'), __('Deleted site %SiteName%', 'wp-security-audit-log')),
|
|
|
|
|
148 |
),
|
149 |
));
|
111 |
array(4007, E_CRITICAL, __('A user was deleted by another user', 'wp-security-audit-log'), __('Deleted User %TargetUserData->Username% with the role of %TargetUserData->Roles%', 'wp-security-audit-log')),
|
112 |
),
|
113 |
'Plugins & Themes' => array(
|
114 |
+
array(5000, E_CRITICAL, __('User installed a plugin', 'wp-security-audit-log'), __('Installed the plugin %Plugin->Name% in %Plugin->plugin_dir_path%', 'wp-security-audit-log')),
|
115 |
array(5001, E_CRITICAL, __('User activated a WordPress plugin', 'wp-security-audit-log'), __('Activated the plugin %PluginData->Name% installed in %PluginFile%', 'wp-security-audit-log')),
|
116 |
array(5002, E_CRITICAL, __('User deactivated a WordPress plugin', 'wp-security-audit-log'), __('Deactivated the plugin %PluginData->Name% installed in %PluginFile%', 'wp-security-audit-log')),
|
117 |
array(5003, E_CRITICAL, __('User uninstalled a plugin', 'wp-security-audit-log'), __('Uninstalled the plugin %PluginData->Name% which was installed in %PluginFile%', 'wp-security-audit-log')),
|
118 |
array(5004, E_WARNING, __('User upgraded a plugin', 'wp-security-audit-log'), __('Upgraded the plugin %PluginData->Name% installed in %PluginFile%', 'wp-security-audit-log')),
|
119 |
+
array(5005, E_CRITICAL, __('User installed a theme', 'wp-security-audit-log'), __('Installed theme "%Theme->Name%" in %Theme->get_template_directory%', 'wp-security-audit-log')),
|
120 |
+
array(5006, E_CRITICAL, __('User activated a theme', 'wp-security-audit-log'), __('Activated theme "%Theme->Name%", installed in %Theme->get_template_directory%', 'wp-security-audit-log')),
|
121 |
+
array(5007, E_CRITICAL, __('User uninstalled a theme', 'wp-security-audit-log'), __('Deleted theme "%Theme->Name%" installed in %Theme->get_template_directory%', 'wp-security-audit-log')),
|
122 |
),
|
123 |
'System Activity' => array(
|
124 |
array(0000, E_CRITICAL, __('Unknown Error', 'wp-security-audit-log'), __('An unexpected error has occurred', 'wp-security-audit-log')),
|
146 |
array(7003, E_CRITICAL, __('Deactivated site has been activated', 'wp-security-audit-log'), __('Activated site %SiteName%', 'wp-security-audit-log')),
|
147 |
array(7004, E_CRITICAL, __('Site has been deactivated', 'wp-security-audit-log'), __('Deactivated site %SiteName%', 'wp-security-audit-log')),
|
148 |
array(7005, E_CRITICAL, __('Existing site deleted from network', 'wp-security-audit-log'), __('Deleted site %SiteName%', 'wp-security-audit-log')),
|
149 |
+
array(5008, E_CRITICAL, __('Activated theme on network', 'wp-security-audit-log'), __('Network activated %Theme->Name% theme installed in %Theme->get_template_directory%', 'wp-security-audit-log')),
|
150 |
+
array(5009, E_CRITICAL, __('Deactivated theme from network', 'wp-security-audit-log'), __('Network deactivated %Theme->Name% theme installed in %Theme->get_template_directory%', 'wp-security-audit-log')),
|
151 |
),
|
152 |
));
|
js/auditlog.js
CHANGED
@@ -24,6 +24,8 @@ function WsalAuditLogInit(_WsalData){
|
|
24 |
setInterval(WsalChk, 40000);
|
25 |
WsalChk();
|
26 |
}
|
|
|
|
|
27 |
}
|
28 |
|
29 |
var WsalIppsPrev;
|
@@ -46,8 +48,63 @@ function WsalIppsChange(value){
|
|
46 |
});
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
function WsalSsasChange(value){
|
50 |
-
jQuery('
|
|
|
51 |
jQuery('#wsal-cbid').val(value);
|
52 |
jQuery('#audit-log-viewer').submit();
|
53 |
}
|
24 |
setInterval(WsalChk, 40000);
|
25 |
WsalChk();
|
26 |
}
|
27 |
+
|
28 |
+
WsalSsasInit();
|
29 |
}
|
30 |
|
31 |
var WsalIppsPrev;
|
48 |
});
|
49 |
}
|
50 |
|
51 |
+
function WsalSsasInit(){
|
52 |
+
var SsasAjx = null;
|
53 |
+
var SsasInps = jQuery("input.wsal-ssas");
|
54 |
+
SsasInps.after('<div class="wsal-ssas-dd" style="display: none;"/>');
|
55 |
+
SsasInps.click(function(){
|
56 |
+
jQuery(this).select();
|
57 |
+
});
|
58 |
+
SsasInps.keyup(function(){
|
59 |
+
var SsasInp = jQuery(this);
|
60 |
+
var SsasDiv = SsasInp.next();
|
61 |
+
var SsasVal = SsasInp.val();
|
62 |
+
if(SsasAjx)SsasAjx.abort();
|
63 |
+
SsasInp.removeClass('loading');
|
64 |
+
|
65 |
+
// do a new search
|
66 |
+
if(SsasInp.attr('data-oldvalue') !== SsasVal && SsasVal.length > 2){
|
67 |
+
SsasInp.addClass('loading');
|
68 |
+
SsasAjx = jQuery.post(WsalData.ajaxurl, {
|
69 |
+
action: 'AjaxSearchSite',
|
70 |
+
search: SsasVal
|
71 |
+
}, function(data){
|
72 |
+
if(SsasAjx)SsasAjx = null;
|
73 |
+
SsasInp.removeClass('loading');
|
74 |
+
SsasDiv.hide();
|
75 |
+
SsasDiv.html('');
|
76 |
+
if(data && data.length){
|
77 |
+
var SsasReg = new RegExp(SsasVal.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'gi');
|
78 |
+
for (var i = 0; i < data.length; i++){
|
79 |
+
var link = jQuery('<a href="javascript:;" onclick="WsalSsasChange(' + data[i].blog_id + ')"/>')
|
80 |
+
.text(data[i].blogname + ' (' + data[i].domain + ')');
|
81 |
+
link.html(link.text().replace(SsasReg, '<u>$&</u>'));
|
82 |
+
SsasDiv.append(link);
|
83 |
+
}
|
84 |
+
}else{
|
85 |
+
SsasDiv.append(jQuery('<span/>').text(WsalData.tr8n.searchnone));
|
86 |
+
}
|
87 |
+
SsasDiv.prepend(jQuery('<a href="javascript:;" onclick="WsalSsasChange(0)" class="allsites"/>').text(WsalData.tr8n.searchback));
|
88 |
+
SsasDiv.show();
|
89 |
+
}, 'json');
|
90 |
+
SsasInp.attr('data-oldvalue', SsasVal);
|
91 |
+
}
|
92 |
+
|
93 |
+
// handle keys
|
94 |
+
});
|
95 |
+
SsasInps.blur(function(){
|
96 |
+
setTimeout(function(){
|
97 |
+
var SsasInp = jQuery(this);
|
98 |
+
var SsasDiv = SsasInp.next();
|
99 |
+
SsasInp.attr('data-oldvalue', '');
|
100 |
+
SsasDiv.hide();
|
101 |
+
}, 200);
|
102 |
+
});
|
103 |
+
}
|
104 |
+
|
105 |
function WsalSsasChange(value){
|
106 |
+
jQuery('div.wsal-ssas-dd').hide();
|
107 |
+
jQuery('input.wsal-ssas').attr('disabled', true);
|
108 |
jQuery('#wsal-cbid').val(value);
|
109 |
jQuery('#audit-log-viewer').submit();
|
110 |
}
|
readme.txt
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
=== WP Security Audit Log ===
|
2 |
-
Contributors: WPWhiteSecurity, uuf6429
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=payments%40wpwhitesecurity%2ecom&lc=US&item_name=WP%20Security%20Audit%20Log%20WordPress%20Plugin¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
|
4 |
Plugin URI: http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/
|
5 |
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.
|
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 |
|
@@ -84,6 +84,13 @@ WP Security Audit Log plugin also has a number of features that make WordPress a
|
|
84 |
* Uses who upload or delete any sort of files
|
85 |
* and much more...
|
86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
= WordPress Security Tips & Tricks =
|
88 |
Even if WordPress security is not your cup of tea, the security of your WordPress is your responsibility. Keep yourself up to date with the latest WordPress Security Tips & Tricks. WP White Security frequently publishes WordPress security tips & tricks on the [WordPress Security section](http://www.wpwhitesecurity.com/wordpress-security/) of their blog.
|
89 |
|
@@ -125,9 +132,24 @@ Yes, WP Security Audit Log works on WordPress Multisite networks, i.e. it can mo
|
|
125 |
2. The WP Security Audit Log plugin options from where WordPress administrator can configure the auto pruning of security alerts and specific user access.
|
126 |
3. The Enable/Disable Alerts settings node from where Administrators can disable or enable WordPress security alerts.
|
127 |
4. The Audit Log Viewer of a Super Admin in a WordPress multisite network installation with the Site selection drop down menu.
|
|
|
128 |
|
129 |
== Changelog ==
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
= 1.1.0 (2014-05-27) =
|
132 |
* New Features
|
133 |
* User avatar is shown in the alert to allow administrators to easily recognize users and their activity
|
1 |
=== WP Security Audit Log ===
|
2 |
+
Contributors: WPWhiteSecurity, uuf6429, robert681
|
3 |
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=payments%40wpwhitesecurity%2ecom&lc=US&item_name=WP%20Security%20Audit%20Log%20WordPress%20Plugin¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
|
4 |
Plugin URI: http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/
|
5 |
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, syslog, log, changelog, trail, history, notification, dashboard, analytics, actions,
|
8 |
Requires at least: 3.6
|
9 |
Tested up to: 3.9.1
|
10 |
+
Stable tag: 1.2.0
|
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 |
|
84 |
* Uses who upload or delete any sort of files
|
85 |
* and much more...
|
86 |
|
87 |
+
= As Featured On: =
|
88 |
+
|
89 |
+
* [WP Mayor](http://www.wpmayor.com/wp-security-audit-log-plugin-review-user-activity-logging-wordpress/)
|
90 |
+
* [ManageWP](https://managewp.com/free-wordpress-plugins-june-2014)
|
91 |
+
* [Design Wall](http://www.designwall.com/blog/10-wordpress-multisite-plugins-you-shouldnt-live-without/)
|
92 |
+
* [WPLift](http://wplift.com/wordpress-event-tracking)
|
93 |
+
|
94 |
= WordPress Security Tips & Tricks =
|
95 |
Even if WordPress security is not your cup of tea, the security of your WordPress is your responsibility. Keep yourself up to date with the latest WordPress Security Tips & Tricks. WP White Security frequently publishes WordPress security tips & tricks on the [WordPress Security section](http://www.wpwhitesecurity.com/wordpress-security/) of their blog.
|
96 |
|
132 |
2. The WP Security Audit Log plugin options from where WordPress administrator can configure the auto pruning of security alerts and specific user access.
|
133 |
3. The Enable/Disable Alerts settings node from where Administrators can disable or enable WordPress security alerts.
|
134 |
4. The Audit Log Viewer of a Super Admin in a WordPress multisite network installation with the Site selection drop down menu.
|
135 |
+
5. If there are more than 15 sites in a multisite, an auto complete site search shows up instead of the drop down menu (see [screenshots](https://wordpress.org/plugins/wp-security-audit-log/screenshots/) for reference)
|
136 |
|
137 |
== Changelog ==
|
138 |
|
139 |
+
= 1.2.0 (2014-07-2) =
|
140 |
+
* New Features
|
141 |
+
* Unlimited Alerts can be stored (removed the 5000 alerts limit)
|
142 |
+
* Alert time now includes milliseconds for more precision (ideal for auditing and compliance)
|
143 |
+
* Reported alert time is now relative to user's configured timezone
|
144 |
+
* Alerts automatic pruning procedures can now be enabled / disabled
|
145 |
+
* Option to hide WP Security Audit Log from plugins page in WordPress
|
146 |
+
* If there are more than 15 websites in a multisite installation, an auto complete site search box is shown instead of the drop down menu
|
147 |
+
|
148 |
+
* New WordPress Security Alerts
|
149 |
+
* Alert 5007: User has uninstalled / deleted a theme
|
150 |
+
* Alert 5008: Super administrator network activated a theme on multisite
|
151 |
+
* Alert 5009: Super administrator network deactivated a theme on multisite
|
152 |
+
|
153 |
= 1.1.0 (2014-05-27) =
|
154 |
* New Features
|
155 |
* User avatar is shown in the alert to allow administrators to easily recognize users and their activity
|
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.
|
8 |
Text Domain: wp-security-audit-log
|
9 |
Author URI: http://www.wpwhitesecurity.com/
|
10 |
License: GPL2
|
@@ -99,30 +99,21 @@ class WpSecurityAuditLog {
|
|
99 |
$this->constants = new WSAL_ConstantManager($this);
|
100 |
$this->widgets = new WSAL_WidgetManager($this);
|
101 |
|
102 |
-
// listen to general events
|
103 |
-
$this->sensors->HookEvents();
|
104 |
-
|
105 |
// listen for installation event
|
106 |
register_activation_hook(__FILE__, array($this, 'Install'));
|
107 |
|
108 |
-
// makes sure everything is ready
|
109 |
-
add_action('init', array($this, 'CheckInstall'));
|
110 |
-
|
111 |
// listen for cleanup event
|
112 |
add_action('wsal_cleanup', array($this, 'CleanUp'));
|
113 |
|
114 |
// internationalize plugin
|
115 |
add_action('plugins_loaded', array($this, 'LoadPluginTextdomain'));
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
}else{
|
124 |
-
$this->Update();
|
125 |
-
}
|
126 |
}
|
127 |
|
128 |
public function Install(){
|
@@ -142,7 +133,9 @@ class WpSecurityAuditLog {
|
|
142 |
die(1);
|
143 |
}
|
144 |
|
145 |
-
$this->
|
|
|
|
|
146 |
|
147 |
wp_schedule_event(0, 'hourly', 'wsal_cleanup');
|
148 |
}
|
@@ -152,10 +145,6 @@ class WpSecurityAuditLog {
|
|
152 |
wp_unschedule_event(0, 'wsal_cleanup');
|
153 |
}
|
154 |
|
155 |
-
public function Update(){
|
156 |
-
|
157 |
-
}
|
158 |
-
|
159 |
public function Upgrade(){
|
160 |
global $wpdb;
|
161 |
static $migTypes = array(
|
@@ -216,6 +205,10 @@ class WpSecurityAuditLog {
|
|
216 |
|
217 |
// <editor-fold desc="Utility Methods">
|
218 |
|
|
|
|
|
|
|
|
|
219 |
/**
|
220 |
* This is the class autoloader. You should not call this directly.
|
221 |
* @param string $class Class name.
|
@@ -252,7 +245,7 @@ class WpSecurityAuditLog {
|
|
252 |
* @return boolean Whether we are running on multisite or not.
|
253 |
*/
|
254 |
public function IsMultisite(){
|
255 |
-
return
|
256 |
}
|
257 |
|
258 |
public function CleanUp(){
|
@@ -303,5 +296,8 @@ class WpSecurityAuditLog {
|
|
303 |
// Load extra files
|
304 |
require_once('defaults.php');
|
305 |
|
|
|
|
|
|
|
306 |
// Create & Run the plugin
|
307 |
return WpSecurityAuditLog::GetInstance();
|
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.0
|
8 |
Text Domain: wp-security-audit-log
|
9 |
Author URI: http://www.wpwhitesecurity.com/
|
10 |
License: GPL2
|
99 |
$this->constants = new WSAL_ConstantManager($this);
|
100 |
$this->widgets = new WSAL_WidgetManager($this);
|
101 |
|
|
|
|
|
|
|
102 |
// listen for installation event
|
103 |
register_activation_hook(__FILE__, array($this, 'Install'));
|
104 |
|
|
|
|
|
|
|
105 |
// listen for cleanup event
|
106 |
add_action('wsal_cleanup', array($this, 'CleanUp'));
|
107 |
|
108 |
// internationalize plugin
|
109 |
add_action('plugins_loaded', array($this, 'LoadPluginTextdomain'));
|
110 |
+
|
111 |
+
// hide plugin
|
112 |
+
if($this->settings->IsIncognito())
|
113 |
+
add_action('admin_head', array($this, 'HidePlugin'));
|
114 |
+
|
115 |
+
// clean up if need be
|
116 |
+
$this->CleanUp();
|
|
|
|
|
|
|
117 |
}
|
118 |
|
119 |
public function Install(){
|
133 |
die(1);
|
134 |
}
|
135 |
|
136 |
+
$PreInstalled = $this->IsInstalled();
|
137 |
+
WSAL_DB_ActiveRecord::InstallAll();
|
138 |
+
if (!$PreInstalled && $this->CanUpgrade()) $this->Upgrade();
|
139 |
|
140 |
wp_schedule_event(0, 'hourly', 'wsal_cleanup');
|
141 |
}
|
145 |
wp_unschedule_event(0, 'wsal_cleanup');
|
146 |
}
|
147 |
|
|
|
|
|
|
|
|
|
148 |
public function Upgrade(){
|
149 |
global $wpdb;
|
150 |
static $migTypes = array(
|
205 |
|
206 |
// <editor-fold desc="Utility Methods">
|
207 |
|
208 |
+
public function HidePlugin(){
|
209 |
+
?><style type="text/css">.wp-list-table.plugins #wp-security-audit-log { display: none; }</style><?php
|
210 |
+
}
|
211 |
+
|
212 |
/**
|
213 |
* This is the class autoloader. You should not call this directly.
|
214 |
* @param string $class Class name.
|
245 |
* @return boolean Whether we are running on multisite or not.
|
246 |
*/
|
247 |
public function IsMultisite(){
|
248 |
+
return function_exists('is_multisite') && is_multisite();
|
249 |
}
|
250 |
|
251 |
public function CleanUp(){
|
296 |
// Load extra files
|
297 |
require_once('defaults.php');
|
298 |
|
299 |
+
// Start listening to events
|
300 |
+
WpSecurityAuditLog::GetInstance()->sensors->HookEvents();
|
301 |
+
|
302 |
// Create & Run the plugin
|
303 |
return WpSecurityAuditLog::GetInstance();
|