Version Description
(2014-05-20) = * Complete plugin rewrite making the new version more stable and scalable
-
New Features
- New Audit Log viewer
- Auto refresh of security alerts - WordPress administrators do not need to refresh the Audit Log Viewer page to see new alerts
- Data Inspector reports more insider information about each alert (can be enabled from settings)
- Sandbox allows developers to execute PHP code for troubleshooting (can be enabled from settings)
- Request Log that logs all HTTP GET and POST requests done on WordPress (can be enabled from settings)
- Logging of PHP Errors; ideal for developers who want to monitor WordPress for any errors (can be enabled from settings)
- New Support and About Us page that you should check out!
-
New WordPress Security Alerts for monitoring themes, WordPress settings, files and much more...
- Alert 2046: User modified a file using the editor
- Alert 2047: User changed parent of page
- Alert 2048: User changed template of page
- Alert 2049: User set post as sticky
- Alert 2050: User removed post from Sticky
- Alert 5005: User installed a new theme
- Alert 5006: User activated a theme
- Alert 6004: User upgraded WordPress
- Alert 6005: User changed the WordPress permalinks
-
New WordPress Developer Alerts
- Alert 0000: Unknown error
- Alert 0001: PHP Error
- Alert 0002: PHP Warning
- Alert 0003: PHP Notice
- Alert 0004: PHP Exception
- Alert 0005: PHP Shutdown Error
For more information about what is new and changed in this version of the plugin refer to the WP Security Audit Log release notes.
Download this release
Release Info
Developer | WPWhiteSecurity |
Plugin | WP Security Audit Log |
Version | 1.0 |
Comparing to | |
See all releases |
Code changes from version 0.6.3 to 1.0
- classes/AbstractLogger.php +14 -0
- classes/AbstractSensor.php +34 -0
- classes/AbstractView.php +82 -0
- classes/Alert.php +43 -0
- classes/AlertManager.php +213 -0
- classes/ConstantManager.php +89 -0
- classes/DB/ActiveRecord.php +428 -0
- classes/DB/Meta.php +11 -0
- classes/DB/Occurrence.php +212 -0
- classes/Loggers/Database.php +63 -0
- classes/Nicer.php +186 -0
- classes/SensorManager.php +21 -0
- classes/Sensors/Content.php +405 -0
- classes/Sensors/Files.php +47 -0
- classes/Sensors/LogInOut.php +59 -0
- classes/Sensors/Multisite.php +79 -0
- classes/Sensors/PhpErrors.php +89 -0
- classes/Sensors/PluginsThemes.php +212 -0
- classes/Sensors/Request.php +42 -0
- classes/Sensors/System.php +103 -0
- classes/Sensors/UserProfile.php +146 -0
- classes/Sensors/Widgets.php +180 -0
- classes/Settings.php +366 -0
- classes/ViewManager.php +127 -0
- classes/Views/About.php +87 -0
- classes/Views/AuditLog.php +390 -0
- classes/Views/Help.php +100 -0
- classes/Views/Sandbox.php +231 -0
- classes/Views/Settings.php +245 -0
- classes/Views/ToggleAlerts.php +139 -0
- classes/WidgetManager.php +59 -0
- css/auditlog.css +121 -0
- css/nice_r.css +74 -0
- css/settings.css +39 -0
- defaults.php +144 -0
- {res/img → img}/logo-main-menu.png +0 -0
- inc/WPPH.php +0 -513
- inc/WPPHDatabase.php +0 -385
- inc/WPPHEvent.php +0 -2213
- inc/WPPHLogger.php +0 -40
- inc/WPPHNetwork.php +0 -232
- inc/WPPHPost.php +0 -191
- inc/WPPHUtil.php +0 -371
- inc/wpphFunctions.php +0 -92
- inc/wpphSettings.php +0 -34
- js/auditlog.js +53 -0
- js/nice_r.js +12 -0
- js/settings.js +37 -0
- pages/about.php +0 -21
- pages/alerts.php +0 -190
- pages/dashboard.php +0 -165
- pages/settings.php +0 -576
- pages/support.php +0 -22
- readme.txt +65 -24
- res/css/styles.base.css +0 -122
- res/img/ajax-loader.gif +0 -0
- res/img/error-icon.png +0 -0
- res/img/page-about-logo.png +0 -0
- res/img/page-settings-logo.png +0 -0
- res/img/page-support-logo.png +0 -0
- res/img/page-viewer-logo.png +0 -0
- res/img/success-icon.png +0 -0
- res/js/audit-view-model.js +0 -314
- res/js/jquery-ck.js +0 -95
- res/js/knockout.js +0 -85
- uninstall.php +7 -0
- wp-security-audit-log.php +219 -180
classes/AbstractLogger.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class WSAL_AbstractLogger {
|
4 |
+
/**
|
5 |
+
* @var WpSecurityAuditLog
|
6 |
+
*/
|
7 |
+
protected $plugin;
|
8 |
+
|
9 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
10 |
+
$this->plugin = $plugin;
|
11 |
+
}
|
12 |
+
|
13 |
+
public abstract function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false);
|
14 |
+
}
|
classes/AbstractSensor.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class WSAL_AbstractSensor {
|
4 |
+
/**
|
5 |
+
* @var WpSecurityAuditLog
|
6 |
+
*/
|
7 |
+
protected $plugin;
|
8 |
+
|
9 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
10 |
+
$this->plugin = $plugin;
|
11 |
+
}
|
12 |
+
|
13 |
+
abstract function HookEvents();
|
14 |
+
|
15 |
+
protected function Log($type, $message, $args){
|
16 |
+
$this->plugin->alerts->Trigger($type, array(
|
17 |
+
'Message' => $message,
|
18 |
+
'Context' => $args,
|
19 |
+
'Trace' => debug_backtrace(),
|
20 |
+
));
|
21 |
+
}
|
22 |
+
|
23 |
+
protected function LogError($message, $args){
|
24 |
+
$this->Log(0001, $message, $args);
|
25 |
+
}
|
26 |
+
|
27 |
+
protected function LogWarn($message, $args){
|
28 |
+
$this->Log(0002, $message, $args);
|
29 |
+
}
|
30 |
+
|
31 |
+
protected function LogInfo($message, $args){
|
32 |
+
$this->Log(0003, $message, $args);
|
33 |
+
}
|
34 |
+
}
|
classes/AbstractView.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class WSAL_AbstractView {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @var WpSecurityAuditLog
|
7 |
+
*/
|
8 |
+
protected $_plugin;
|
9 |
+
|
10 |
+
protected $_wpversion;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @param WpSecurityAuditLog $plugin
|
14 |
+
*/
|
15 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
16 |
+
$this->_plugin = $plugin;
|
17 |
+
|
18 |
+
// get and store wordpress version
|
19 |
+
global $wp_version;
|
20 |
+
if(!isset($wp_version))
|
21 |
+
$wp_version = get_bloginfo('version');
|
22 |
+
$this->_wpversion = floatval($wp_version);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return string Return page name (for menu etc).
|
27 |
+
*/
|
28 |
+
abstract public function GetName();
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return string Return page title.
|
32 |
+
*/
|
33 |
+
abstract public function GetTitle();
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return string Page icon name.
|
37 |
+
*/
|
38 |
+
abstract public function GetIcon();
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @return int Menu weight, the higher this is, the lower it goes.
|
42 |
+
*/
|
43 |
+
abstract public function GetWeight();
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Renders and outputs the view directly.
|
47 |
+
*/
|
48 |
+
abstract public function Render();
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @return boolean Whether page should appear in menu or not.
|
52 |
+
*/
|
53 |
+
public function IsVisible(){ return true; }
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Used for rendering stuff into head tag.
|
57 |
+
*/
|
58 |
+
public function Header(){}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Used for rendering stuff in page fotoer.
|
62 |
+
*/
|
63 |
+
public function Footer(){}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @return string Safe view menu name.
|
67 |
+
*/
|
68 |
+
public function GetSafeViewName(){
|
69 |
+
return 'wsal-' . strtolower(
|
70 |
+
preg_replace('/[^A-Za-z0-9\-]/', '-', $this->GetName())
|
71 |
+
);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Override this and make it return true to create a shortcut link in plugin page to the view.
|
76 |
+
* @return boolean
|
77 |
+
*/
|
78 |
+
public function HasPluginShortcutLink(){
|
79 |
+
return false;
|
80 |
+
}
|
81 |
+
|
82 |
+
}
|
classes/Alert.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class WSAL_Alert {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Alert type (used when triggering an alert etc).
|
7 |
+
* @var integer
|
8 |
+
*/
|
9 |
+
public $type = 0;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Alert error level (E_* constant).
|
13 |
+
* @var integer
|
14 |
+
*/
|
15 |
+
public $code = 0;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Alert category (alerts are grouped by matching categories).
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
public $catg = '';
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Alert description (ie, describes what happens when alert is triggered).
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
public $desc = '';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Alert message (variables between '%' are expanded to values).
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
public $mesg = '';
|
34 |
+
|
35 |
+
public function __construct($type = 0, $code = 0, $catg = '', $desc = '', $mesg = '') {
|
36 |
+
$this->type = $type;
|
37 |
+
$this->code = $code;
|
38 |
+
$this->catg = $catg;
|
39 |
+
$this->desc = $desc;
|
40 |
+
$this->mesg = $mesg;
|
41 |
+
}
|
42 |
+
|
43 |
+
}
|
classes/AlertManager.php
ADDED
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class WSAL_AlertManager {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @var WSAL_Alert[]
|
7 |
+
*/
|
8 |
+
protected $_alerts = array();
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var WSAL_AbstractLogger[]
|
12 |
+
*/
|
13 |
+
protected $_loggers = array();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var WpSecurityAuditLog
|
17 |
+
*/
|
18 |
+
protected $plugin;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Create new AlertManager instance.
|
22 |
+
* @param WpSecurityAuditLog $plugin
|
23 |
+
*/
|
24 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
25 |
+
$this->plugin = $plugin;
|
26 |
+
foreach(glob(dirname(__FILE__) . '/Loggers/*.php') as $file){
|
27 |
+
$class = $plugin->GetClassFileClassName($file);
|
28 |
+
$this->_loggers[] = new $class($plugin);
|
29 |
+
}
|
30 |
+
|
31 |
+
add_action('shutdown', array($this, '_CommitPipeline'));
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Contains a list of alerts to trigger.
|
36 |
+
* @var array
|
37 |
+
*/
|
38 |
+
protected $_pipeline = array();
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Trigger an alert.
|
42 |
+
* @param integer $type Alert type.
|
43 |
+
* @param array $data Alert data.
|
44 |
+
*/
|
45 |
+
public function Trigger($type, $data = array(), $delayed = false){
|
46 |
+
if($delayed){
|
47 |
+
$this->TriggerIf($type, $data, null);
|
48 |
+
}else{
|
49 |
+
$this->_CommitItem($type, $data, null);
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Trigger only if a condition is met at the end of request.
|
55 |
+
* @param integer $type Alert type ID.
|
56 |
+
* @param array $data Alert data.
|
57 |
+
* @param callable $cond A future condition callback (receives an object of type WSAL_AlertManager as parameter).
|
58 |
+
*/
|
59 |
+
public function TriggerIf($type, $data, $cond = null){
|
60 |
+
$this->_pipeline[] = array(
|
61 |
+
'type' => $type,
|
62 |
+
'data' => $data,
|
63 |
+
'cond' => $cond,
|
64 |
+
);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @internal Commit an alert now.
|
69 |
+
*/
|
70 |
+
protected function _CommitItem($type, $data, $cond){
|
71 |
+
if(!$cond || !!call_user_func($cond, $this)){
|
72 |
+
if($this->IsEnabled($type)){
|
73 |
+
if(isset($this->_alerts[$type])){
|
74 |
+
// ok, convert alert to a log entry
|
75 |
+
$this->Log($type, $data);
|
76 |
+
}else{
|
77 |
+
// in general this shouldn't happen, but it could, so we handle it here :)
|
78 |
+
throw new Exception('Alert with code "' . $type . '" has not be registered.');
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @internal Runs over triggered alerts in pipeline and passes them to loggers.
|
86 |
+
*/
|
87 |
+
public function _CommitPipeline(){
|
88 |
+
foreach($this->_pipeline as $item)
|
89 |
+
$this->_CommitItem($item['type'], $item['data'], $item['cond']);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* @param integer $type Alert type ID.
|
94 |
+
* @return boolean True if at the end of request an alert of this type will be triggered.
|
95 |
+
*/
|
96 |
+
public function WillTrigger($type){
|
97 |
+
foreach($this->_pipeline as $item)
|
98 |
+
if($item['type'] == $type)
|
99 |
+
return true;
|
100 |
+
return false;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Register an alert type.
|
105 |
+
* @param array $info Array of [type, code, category, description, message] respectively.
|
106 |
+
*/
|
107 |
+
public function Register($info){
|
108 |
+
if(func_num_args() == 1){
|
109 |
+
// handle single item
|
110 |
+
list($type, $code, $catg, $desc, $mesg) = $info;
|
111 |
+
if(isset($this->_alerts[$type]))
|
112 |
+
throw new Exception("Alert $type already registered with Alert Manager.");
|
113 |
+
$this->_alerts[$type] = new WSAL_Alert($type, $code, $catg, $desc, $mesg);
|
114 |
+
}else{
|
115 |
+
// handle multiple items
|
116 |
+
foreach(func_get_args() as $arg)
|
117 |
+
$this->Register($arg);
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Register a whole group of items.
|
123 |
+
* @param array $groups An array with group name as the index and an array of group items as the value.
|
124 |
+
* Item values is an array of [type, code, description, message] respectively.
|
125 |
+
*/
|
126 |
+
public function RegisterGroup($groups){
|
127 |
+
foreach($groups as $name => $group){
|
128 |
+
foreach($group as $item){
|
129 |
+
list($type, $code, $desc, $mesg) = $item;
|
130 |
+
$this->Register(array($type, $code, $name, $desc, $mesg));
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Returns whether alert of type $type is enabled or not.
|
137 |
+
* @param integer $type Alert type.
|
138 |
+
* @return boolean True if enabled, false otherwise.
|
139 |
+
*/
|
140 |
+
public function IsEnabled($type){
|
141 |
+
return !in_array($type, $this->GetDisabledAlerts());
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Disables a set of alerts by type.
|
146 |
+
* @param int[] $types Alert type codes to be disabled.
|
147 |
+
*/
|
148 |
+
public function SetDisabledAlerts($types){
|
149 |
+
$this->plugin->settings->SetDisabledAlerts($types);
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* @return int[] Returns an array of disabled alerts' type code.
|
154 |
+
*/
|
155 |
+
public function GetDisabledAlerts(){
|
156 |
+
return $this->plugin->settings->GetDisabledAlerts();
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Converts an Alert into a Log entry (by invoking loggers).
|
161 |
+
* You should not call this method directly.
|
162 |
+
* @param integer $type Alert type.
|
163 |
+
* @param array $data Misc alert data.
|
164 |
+
*/
|
165 |
+
protected function Log($type, $data = array()){
|
166 |
+
if(!isset($data['ClientIP']))
|
167 |
+
$data['ClientIP'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
|
168 |
+
if(!isset($data['UserAgent']))
|
169 |
+
$data['UserAgent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
170 |
+
if(!isset($data['CurrentUserID']))
|
171 |
+
$data['CurrentUserID'] = function_exists('get_current_user_id') ? get_current_user_id() : 0;
|
172 |
+
|
173 |
+
foreach($this->_loggers as $logger)
|
174 |
+
$logger->Log($type, $data);
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Return alert given alert type.
|
179 |
+
* @param integer $type Alert type.
|
180 |
+
* @param mixed $default Returned if alert is not found.
|
181 |
+
* @return WSAL_Alert
|
182 |
+
*/
|
183 |
+
public function GetAlert($type, $default = null){
|
184 |
+
foreach($this->_alerts as $alert)
|
185 |
+
if($alert->type == $type)
|
186 |
+
return $alert;
|
187 |
+
return $default;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Returns all supported alerts.
|
192 |
+
* @return WSAL_Alert[]
|
193 |
+
*/
|
194 |
+
public function GetAlerts(){
|
195 |
+
return $this->_alerts;
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Returns all supported alerts.
|
200 |
+
* @return array
|
201 |
+
*/
|
202 |
+
public function GetCategorizedAlerts(){
|
203 |
+
$result = array();
|
204 |
+
foreach($this->_alerts as $alert){
|
205 |
+
if(!isset($result[$alert->catg]))
|
206 |
+
$result[$alert->catg] = array();
|
207 |
+
$result[$alert->catg][] = $alert;
|
208 |
+
}
|
209 |
+
ksort($result);
|
210 |
+
return $result;
|
211 |
+
}
|
212 |
+
|
213 |
+
}
|
classes/ConstantManager.php
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_ConstantManager {
|
4 |
+
|
5 |
+
protected $_constants = array();
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Use an existing PHP constant.
|
9 |
+
* @param string $name Constant name.
|
10 |
+
* @param string $description Constant description.
|
11 |
+
*/
|
12 |
+
public function UseConstant($name, $description = ''){
|
13 |
+
$this->_constants[] = (object)array(
|
14 |
+
'name' => $name,
|
15 |
+
'value' => constant($name),
|
16 |
+
'description' => $description,
|
17 |
+
);
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Add new PHP constant.
|
22 |
+
* @param string $name Constant name.
|
23 |
+
* @param integer|string $value Constant value.
|
24 |
+
* @param string $description Constant description.
|
25 |
+
*/
|
26 |
+
public function AddConstant($name, $value, $description = ''){
|
27 |
+
|
28 |
+
// check for constant conflict and define new one if required
|
29 |
+
if(defined($name) && constant($name) !== $value){
|
30 |
+
throw new Exception('Constant already defined with a different value.');
|
31 |
+
}else{
|
32 |
+
define($name, $value);
|
33 |
+
}
|
34 |
+
|
35 |
+
// add constant to da list.
|
36 |
+
$this->UseConstant($name, $description);
|
37 |
+
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Add multiple constants in one go.
|
42 |
+
* @param array $items Array of arrays with name, value, description pairs.
|
43 |
+
*/
|
44 |
+
public function AddConstants($items){
|
45 |
+
foreach($items as $item)
|
46 |
+
$this->AddConstant(
|
47 |
+
$item['name'],
|
48 |
+
$item['value'],
|
49 |
+
$item['description']
|
50 |
+
);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Use multiple constants in one go.
|
55 |
+
* @param array $items Array of arrays with name, description pairs.
|
56 |
+
*/
|
57 |
+
public function UseConstants($items){
|
58 |
+
foreach($items as $item)
|
59 |
+
$this->UseConstant(
|
60 |
+
$item['name'],
|
61 |
+
$item['description']
|
62 |
+
);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get constant details by a particular detail.
|
67 |
+
* @param string $what The type of detail: 'name', 'value'
|
68 |
+
* @param mixed $value The detail expected value.
|
69 |
+
* @return mixed Either constant details (props: name, value, description) or $default if not found.
|
70 |
+
*/
|
71 |
+
public function GetConstantBy($what, $value, $default = null){
|
72 |
+
|
73 |
+
// make sure we do have some constants...
|
74 |
+
if(count($this->_constants)){
|
75 |
+
|
76 |
+
// make sure that constants do have a $what property
|
77 |
+
if(!isset($this->_constants[0]->$what))
|
78 |
+
throw new Exception('Unexpected detail type "' . $what . '".');
|
79 |
+
|
80 |
+
// return constant match the property value
|
81 |
+
foreach($this->_constants as $constant)
|
82 |
+
if($constant->$what == $value)
|
83 |
+
return $constant;
|
84 |
+
|
85 |
+
}
|
86 |
+
|
87 |
+
return $default;
|
88 |
+
}
|
89 |
+
}
|
classes/DB/ActiveRecord.php
ADDED
@@ -0,0 +1,428 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class WSAL_DB_ActiveRecord {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Contains table name, override as required.
|
7 |
+
* @var string
|
8 |
+
*/
|
9 |
+
protected $_table = '';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Contains primary key column name, override as required.
|
13 |
+
* @var string
|
14 |
+
*/
|
15 |
+
protected $_idkey = '';
|
16 |
+
|
17 |
+
const STATE_UNKNOWN = 'unknown';
|
18 |
+
const STATE_CREATED = 'created';
|
19 |
+
const STATE_UPDATED = 'updated';
|
20 |
+
const STATE_DELETED = 'deleted';
|
21 |
+
const STATE_LOADED = 'loaded';
|
22 |
+
|
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)
|
29 |
+
throw new Exception('Class "' . __CLASS__ . '" requires "_idkey" to be set.');
|
30 |
+
if(!is_null($data)){
|
31 |
+
$this->LoadData($data);
|
32 |
+
$this->_state = self::STATE_LOADED;
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @return string Must return SQL for creating table.
|
38 |
+
*/
|
39 |
+
protected function _GetInstallQuery(){
|
40 |
+
global $wpdb;
|
41 |
+
|
42 |
+
$copy = get_class($this);
|
43 |
+
$copy = new $copy();
|
44 |
+
|
45 |
+
$sql = 'CREATE TABLE ' . $this->GetTable() . ' (' . PHP_EOL;
|
46 |
+
foreach($this->GetColumns() as $key) {
|
47 |
+
switch(true) {
|
48 |
+
case $key == $copy->_idkey:
|
49 |
+
$sql .= $key . ' BIGINT NOT NULL AUTO_INCREMENT,'.PHP_EOL;
|
50 |
+
break;
|
51 |
+
case is_integer($copy->$key):
|
52 |
+
$sql .= $key . ' BIGINT NOT NULL,'.PHP_EOL;
|
53 |
+
break;
|
54 |
+
case is_float($copy->$key):
|
55 |
+
$sql .= $key . ' FLOAT NOT NULL,'.PHP_EOL;
|
56 |
+
break;
|
57 |
+
case is_string($copy->$key):
|
58 |
+
$sql .= $key . ' TEXT NOT NULL,'.PHP_EOL;
|
59 |
+
break;
|
60 |
+
case is_bool($copy->$key):
|
61 |
+
$sql .= $key . ' BIT NOT NULL,'.PHP_EOL;
|
62 |
+
break;
|
63 |
+
case is_array($copy->$key):
|
64 |
+
case is_object($copy->$key):
|
65 |
+
$sql .= $key . ' LONGTEXT NOT NULL,'.PHP_EOL;
|
66 |
+
break;
|
67 |
+
}
|
68 |
+
}
|
69 |
+
$sql .= 'CONSTRAINT PK_' . $this->GetTable().'_'.$this->_idkey
|
70 |
+
. ' PRIMARY KEY (' . $this->_idkey . ')' . PHP_EOL
|
71 |
+
. ' )';
|
72 |
+
if ( ! empty($wpdb->charset) )
|
73 |
+
$sql .= ' DEFAULT CHARACTER SET ' . $wpdb->charset;
|
74 |
+
if ( ! empty($wpdb->collate) )
|
75 |
+
$sql .= ' COLLATE ' . $wpdb->collate;
|
76 |
+
return $sql;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @return string Must return SQL for removing table (at a minimum, it should be ` 'DROP TABLE ' . $this->_table `).
|
81 |
+
*/
|
82 |
+
protected function _GetUninstallQuery(){
|
83 |
+
return 'DROP TABLE ' . $this->GetTable();
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* A wrapper for JSON encoding that fixes potential issues.
|
88 |
+
* @param mixed $data The data to encode.
|
89 |
+
* @return string JSON string.
|
90 |
+
*/
|
91 |
+
protected function _JsonEncode($data){
|
92 |
+
return @json_encode($data);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* A wrapper for JSON encoding that fixes potential issues.
|
97 |
+
* @param string $data The JSON string to decode.
|
98 |
+
* @return mixed Decoded data.
|
99 |
+
*/
|
100 |
+
protected function _JsonDecode($data){
|
101 |
+
return @json_decode($data);
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @return string Returns table name.
|
106 |
+
*/
|
107 |
+
public function GetTable(){
|
108 |
+
global $wpdb;
|
109 |
+
return $wpdb->base_prefix . $this->_table;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @return array Returns this records' columns.
|
114 |
+
*/
|
115 |
+
public function GetColumns(){
|
116 |
+
if(!isset($this->_column_cache)){
|
117 |
+
$this->_column_cache = array();
|
118 |
+
foreach(array_keys(get_object_vars($this)) as $col)
|
119 |
+
if(trim($col) && $col[0] != '_')
|
120 |
+
$this->_column_cache[] = $col;
|
121 |
+
}
|
122 |
+
return $this->_column_cache;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* @return boolean Returns whether table structure is installed or not.
|
127 |
+
*/
|
128 |
+
public function IsInstalled(){
|
129 |
+
global $wpdb;
|
130 |
+
$sql = 'SHOW TABLES LIKE "' . $this->GetTable() . '"';
|
131 |
+
return $wpdb->get_var($sql) == $this->GetTable();
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Install this ActiveRecord structure into DB.
|
136 |
+
*/
|
137 |
+
public function Install(){
|
138 |
+
if(!$this->IsInstalled()) {
|
139 |
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
140 |
+
dbDelta($this->_GetInstallQuery());
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Remove this ActiveRecord structure into DB.
|
146 |
+
*/
|
147 |
+
public function Uninstall(){
|
148 |
+
if($this->IsInstalled()) {
|
149 |
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
150 |
+
dbDelta($this->_GetUninstallQuery());
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Save record to DB.
|
156 |
+
* @return integer|boolean Either the number of modified/inserted rows or false on failure.
|
157 |
+
*/
|
158 |
+
public function Save(){
|
159 |
+
$this->_state = self::STATE_UNKNOWN;
|
160 |
+
global $wpdb;
|
161 |
+
$copy = get_class($this);
|
162 |
+
$copy = new $copy;
|
163 |
+
$data = array();
|
164 |
+
$format = array();
|
165 |
+
foreach($this->GetColumns() as $key){
|
166 |
+
$val = $this->$key;
|
167 |
+
$deffmt = '%s';
|
168 |
+
if(is_int($copy->$key))$deffmt = '%d';
|
169 |
+
if(is_float($copy->$key))$deffmt = '%f';
|
170 |
+
if(is_array($copy->$key) || is_object($copy->$key)){
|
171 |
+
$data[$key] = $this->_JsonEncode($val);
|
172 |
+
}else{
|
173 |
+
$data[$key] = $val;
|
174 |
+
}
|
175 |
+
$format[] = $deffmt;
|
176 |
+
}
|
177 |
+
$result = $wpdb->replace($this->GetTable(), $data, $format);
|
178 |
+
if($wpdb->insert_id){
|
179 |
+
$this->{$this->_idkey} = $wpdb->insert_id;
|
180 |
+
if($result !== false)
|
181 |
+
$this->_state = self::STATE_CREATED;
|
182 |
+
}else{
|
183 |
+
if($result !== false)
|
184 |
+
$this->_state = self::STATE_UPDATED;
|
185 |
+
}
|
186 |
+
return $result;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Load record from DB.
|
191 |
+
* @param string $cond (Optional) Load condition.
|
192 |
+
* @param array $args (Optional) Load condition arguments.
|
193 |
+
*/
|
194 |
+
public function Load($cond = '%d', $args = array(1)){
|
195 |
+
global $wpdb;
|
196 |
+
|
197 |
+
$this->_state = self::STATE_UNKNOWN;
|
198 |
+
|
199 |
+
$sql = $wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '.$cond, $args);
|
200 |
+
$data = $wpdb->get_row($sql, ARRAY_A);
|
201 |
+
|
202 |
+
if(!is_null($data)){
|
203 |
+
$this->LoadData($data);
|
204 |
+
$this->_state = self::STATE_LOADED;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Load object data from variable.
|
210 |
+
* @param array|object $data Data array or object.
|
211 |
+
*/
|
212 |
+
public function LoadData($data){
|
213 |
+
$copy = get_class($this);
|
214 |
+
$copy = new $copy;
|
215 |
+
foreach((array)$data as $key => $val){
|
216 |
+
if(isset($copy->$key)){
|
217 |
+
switch(true){
|
218 |
+
case is_array($copy->$key):
|
219 |
+
case is_object($copy->$key):
|
220 |
+
$this->$key = $this->_JsonDecode($val);
|
221 |
+
break;
|
222 |
+
case is_int($copy->$key):
|
223 |
+
$this->$key = (int)$val;
|
224 |
+
break;
|
225 |
+
case is_float($copy->$key):
|
226 |
+
$this->$key = (float)$val;
|
227 |
+
break;
|
228 |
+
case is_bool($copy->$key):
|
229 |
+
$this->$key = (bool)$val;
|
230 |
+
break;
|
231 |
+
case is_string($copy->$key):
|
232 |
+
$this->$key = (string)$val;
|
233 |
+
break;
|
234 |
+
default:
|
235 |
+
throw new Exception('Unsupported type "'.gettype($copy->$key).'"');
|
236 |
+
}
|
237 |
+
}
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Delete DB record.
|
243 |
+
* @return int|boolean Either the amount of deleted rows or False on error.
|
244 |
+
*/
|
245 |
+
public function Delete(){
|
246 |
+
global $wpdb;
|
247 |
+
|
248 |
+
$this->_state = self::STATE_UNKNOWN;
|
249 |
+
|
250 |
+
$result = $wpdb->delete(
|
251 |
+
$this->GetTable(),
|
252 |
+
array($this->_idkey => $this->{$this->_idkey})
|
253 |
+
);
|
254 |
+
|
255 |
+
if($result !== false)
|
256 |
+
$this->_state = self::STATE_DELETED;
|
257 |
+
|
258 |
+
return $result;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Load multiple records from DB.
|
263 |
+
* @param string $cond (Optional) Load condition.
|
264 |
+
* @param array $args (Optional) Load condition arguments.
|
265 |
+
* @return self[] List of loaded records.
|
266 |
+
*/
|
267 |
+
public static function LoadMulti($cond = '%d', $args = array(1)){
|
268 |
+
global $wpdb;
|
269 |
+
$class = get_called_class();
|
270 |
+
$result = array();
|
271 |
+
$temp = new $class();
|
272 |
+
$sql = $wpdb->prepare('SELECT * FROM ' . $temp->GetTable() . ' WHERE '.$cond, $args);
|
273 |
+
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
274 |
+
$result[] = new $class($data);
|
275 |
+
}
|
276 |
+
return $result;
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Load multiple records from DB and call a callback for each record.
|
281 |
+
* This function is very memory-efficient, it doesn't load records in bulk.
|
282 |
+
* @param callable $callback The callback to invoke.
|
283 |
+
* @param string $cond (Optional) Load condition.
|
284 |
+
* @param array $args (Optional) Load condition arguments.
|
285 |
+
*/
|
286 |
+
public static function LoadAndCallForEach($callback, $cond = '%d', $args = array(1)){
|
287 |
+
global $wpdb;
|
288 |
+
$class = get_called_class();
|
289 |
+
$temp = new $class();
|
290 |
+
$sql = $wpdb->prepare('SELECT * FROM ' . $temp->GetTable() . ' WHERE '.$cond, $args);
|
291 |
+
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
292 |
+
call_user_func($callback, new $class($data));
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* Count records in the DB matching a condition.
|
298 |
+
* If no parameters are given, this counts the number of records in the DB table.
|
299 |
+
* @param string $cond (Optional) Query condition.
|
300 |
+
* @param array $args (Optional) Condition arguments.
|
301 |
+
*/
|
302 |
+
public static function Count($cond = '%d', $args = array(1)){
|
303 |
+
global $wpdb;
|
304 |
+
$class = get_called_class();
|
305 |
+
$temp = new $class();
|
306 |
+
$sql = $wpdb->prepare('SELECT COUNT(*) FROM ' . $temp->GetTable() . ' WHERE '.$cond, $args);
|
307 |
+
return (int)$wpdb->get_var($sql);
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Similar to LoadMulti but allows the use of a full SQL query.
|
312 |
+
* @param string $query Full SQL query.
|
313 |
+
* @param array $args (Optional) Query arguments.
|
314 |
+
* @return self[] List of loaded records.
|
315 |
+
*/
|
316 |
+
public static function LoadMultiQuery($query, $args = array()){
|
317 |
+
global $wpdb;
|
318 |
+
$class = get_called_class();
|
319 |
+
$result = array();
|
320 |
+
$sql = $wpdb->prepare($query, $args);
|
321 |
+
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
322 |
+
$result[] = new $class($data);
|
323 |
+
}
|
324 |
+
return $result;
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Install all DB tables.
|
329 |
+
*/
|
330 |
+
public static function InstallAll(){
|
331 |
+
$plugin = WpSecurityAuditLog::GetInstance();
|
332 |
+
foreach(glob(dirname(__FILE__) . '/*.php') as $file){
|
333 |
+
$class = $plugin->GetClassFileClassName($file);
|
334 |
+
if($class != __CLASS__){
|
335 |
+
$class = new $class();
|
336 |
+
$class->Install();
|
337 |
+
}
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Uninstall all DB tables.
|
343 |
+
*/
|
344 |
+
public static function UninstallAll(){
|
345 |
+
$plugin = WpSecurityAuditLog::GetInstance();
|
346 |
+
foreach(glob(dirname(__FILE__) . '/*.php') as $file){
|
347 |
+
$class = $plugin->GetClassFileClassName($file);
|
348 |
+
if($class != __CLASS__){
|
349 |
+
$class = new $class();
|
350 |
+
$class->Uninstall();
|
351 |
+
}
|
352 |
+
}
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* @return boolean
|
357 |
+
*/
|
358 |
+
public function IsLoaded(){
|
359 |
+
return $this->_state == self::STATE_LOADED;
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* @return boolean
|
364 |
+
*/
|
365 |
+
public function IsSaved(){
|
366 |
+
return $this->_state == self::STATE_CREATED
|
367 |
+
|| $this->_state == self::STATE_UPDATED;
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* @return boolean
|
372 |
+
*/
|
373 |
+
public function IsCreated(){
|
374 |
+
return $this->_state == self::STATE_CREATED;
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* @return boolean
|
379 |
+
*/
|
380 |
+
public function IsUpdated(){
|
381 |
+
return $this->_state == self::STATE_UPDATED;
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* @return boolean
|
386 |
+
*/
|
387 |
+
public function IsDeleted(){
|
388 |
+
return $this->_state == self::STATE_DELETED;
|
389 |
+
}
|
390 |
+
|
391 |
+
protected static $_cache = array();
|
392 |
+
|
393 |
+
/**
|
394 |
+
* Load ActiveRecord from DB or cache.
|
395 |
+
* @param string $target ActiveRecord class name.
|
396 |
+
* @param string $query Load condition.
|
397 |
+
* @param array $args Arguments used in condition.
|
398 |
+
* @return WSAL_DB_ActiveRecord
|
399 |
+
*/
|
400 |
+
protected static function CacheLoad($target, $query, $args){
|
401 |
+
$index = $target . '::' . vsprintf($query, $args);
|
402 |
+
if(!isset(self::$_cache[$index])){
|
403 |
+
self::$_cache[$index] = new $target();
|
404 |
+
self::$_cache[$index]->Load($query, $args);
|
405 |
+
}
|
406 |
+
return self::$_cache[$index];
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Remove ActiveRecord cache.
|
411 |
+
* @param string $target ActiveRecord class name.
|
412 |
+
* @param string $query Load condition.
|
413 |
+
* @param array $args Arguments used in condition.
|
414 |
+
*/
|
415 |
+
protected static function CacheRemove($target, $query, $args){
|
416 |
+
$index = $target . '::' . sprintf($query, $args);
|
417 |
+
if(!isset(self::$_cache[$index])){
|
418 |
+
unset(self::$_cache[$index]);
|
419 |
+
}
|
420 |
+
}
|
421 |
+
|
422 |
+
/**
|
423 |
+
* Clear the cache.
|
424 |
+
*/
|
425 |
+
protected static function CacheClear(){
|
426 |
+
self::$_cache = array();
|
427 |
+
}
|
428 |
+
}
|
classes/DB/Meta.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_DB_Meta extends WSAL_DB_ActiveRecord {
|
4 |
+
protected $_table = 'wsal_metadata';
|
5 |
+
protected $_idkey = 'id';
|
6 |
+
|
7 |
+
public $id = 0;
|
8 |
+
public $occurrence_id = 0;
|
9 |
+
public $name = '';
|
10 |
+
public $value = array(); // force mixed type
|
11 |
+
}
|
classes/DB/Occurrence.php
ADDED
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_DB_Occurrence extends WSAL_DB_ActiveRecord {
|
4 |
+
protected $_table = 'wsal_occurrences';
|
5 |
+
protected $_idkey = 'id';
|
6 |
+
|
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 |
+
|
14 |
+
protected $_meta;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Returns all meta data related to this event.
|
18 |
+
* @return WSAL_DB_Meta[]
|
19 |
+
*/
|
20 |
+
public function GetMeta(){
|
21 |
+
if(!isset($this->_meta)){
|
22 |
+
$this->_meta = WSAL_DB_Meta::LoadMulti('occurrence_id = %d', array($this->id));
|
23 |
+
}
|
24 |
+
return $this->_meta;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Loads a meta item given its name.
|
29 |
+
* @param string $name Meta name.
|
30 |
+
* @return \WSAL_DB_Meta The meta item, be sure to checked if it was loaded successfully.
|
31 |
+
*/
|
32 |
+
public function GetNamedMeta($name){
|
33 |
+
$meta = new WSAL_DB_Meta();
|
34 |
+
$meta->Load('occurrence_id = %d AND name = %s', array($this->id, $name));
|
35 |
+
return $meta;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Returns the first meta value from a given set of names. Useful when you have a mix of items that could provide a particular detail.
|
40 |
+
* @param array $names List of meta names.
|
41 |
+
* @return \WSAL_DB_Meta The first meta item that exists.
|
42 |
+
*/
|
43 |
+
public function GetFirstNamedMeta($names){
|
44 |
+
$meta = new WSAL_DB_Meta();
|
45 |
+
$query = '(' . str_repeat('name = %s OR ', count($names)).'0)';
|
46 |
+
$query = 'occurrence_id = %d AND ' . $query . ' LIMIT 1';
|
47 |
+
array_unshift($names, $this->id); // prepend args with occurrence id
|
48 |
+
$meta->Load($query, $names);
|
49 |
+
return $meta->IsLoaded() ? $meta : null;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Returns the alert related to this occurrence.
|
54 |
+
* @return WSAL_Alert
|
55 |
+
*/
|
56 |
+
public function GetAlert(){
|
57 |
+
return WpSecurityAuditLog::GetInstance()->alerts->GetAlert($this->alert_id);
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Returns the value of a meta item.
|
62 |
+
* @param string $name Name of meta item.
|
63 |
+
* @param mixed $default Default value returned when meta does not exist.
|
64 |
+
* @return mixed The value, if meta item does not exist $default returned.
|
65 |
+
*/
|
66 |
+
public function GetMetaValue($name, $default = array()){
|
67 |
+
$meta = $this->GetNamedMeta($name);
|
68 |
+
return $meta->IsLoaded() ? $meta->value : $default;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Set the value of a meta item (creates or updates meta item).
|
73 |
+
* @param string $name Meta name.
|
74 |
+
* @param mixed $value Meta value.
|
75 |
+
*/
|
76 |
+
public function SetMetaValue($name, $value){
|
77 |
+
$meta = $this->GetNamedMeta($name);
|
78 |
+
$meta->occurrence_id = $this->id;
|
79 |
+
$meta->name = $name;
|
80 |
+
$meta->value = $value;
|
81 |
+
$meta->Save();
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Returns a key-value pair of meta data.
|
86 |
+
* @return array
|
87 |
+
*/
|
88 |
+
public function GetMetaArray(){
|
89 |
+
$result = array();
|
90 |
+
foreach($this->GetMeta() as $meta)
|
91 |
+
$result[$meta->name] = $meta->value;
|
92 |
+
return $result;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Creates or updates all meta data passed as an array of meta-key/meta-value pairs.
|
97 |
+
* @param array $data New meta data.
|
98 |
+
*/
|
99 |
+
public function SetMeta($data){
|
100 |
+
foreach((array)$data as $key => $val)
|
101 |
+
$this->SetMetaValue($key, $val);
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Retrieves a value for a particular meta variable expression.
|
106 |
+
* @param string $expr Expression, eg: User->Name looks for a Name property for meta named User.
|
107 |
+
* @return mixed The value nearest to the expression.
|
108 |
+
*/
|
109 |
+
protected function GetMetaExprValue($expr){
|
110 |
+
// TODO Handle function calls (and methods?)
|
111 |
+
$expr = explode('->', $expr);
|
112 |
+
$meta = array_shift($expr);
|
113 |
+
$meta = $this->GetMetaValue($meta, null);
|
114 |
+
foreach($expr as $part){
|
115 |
+
if(is_scalar($meta) || is_null($meta))return $meta; // this isn't 100% correct
|
116 |
+
$meta = is_array($meta) ? $meta[$part] : $meta->$part;
|
117 |
+
}
|
118 |
+
return is_scalar($meta) ? (string)$meta : var_export($meta, true);
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Expands a message with variables by replacing variables with meta data values.
|
123 |
+
* @param string $mesg The original message.
|
124 |
+
* @param callable|null $metaFormatter (Optional) Callback for formatting meta values.
|
125 |
+
* @param string $afterMeta (Optional) Some text to put after meta values.
|
126 |
+
* @return string The expanded message.
|
127 |
+
*/
|
128 |
+
protected function GetFormattedMesg($origMesg, $metaFormatter = null){
|
129 |
+
// tokenize message with regex
|
130 |
+
$mesg = preg_split('/(%.*?%)/', (string)$origMesg, -1, PREG_SPLIT_DELIM_CAPTURE);
|
131 |
+
if(!is_array($mesg))return (string)$origMesg;
|
132 |
+
// handle tokenized message
|
133 |
+
foreach($mesg as $i=>$token){
|
134 |
+
// handle escaped percent sign
|
135 |
+
if($token == '%%'){
|
136 |
+
$mesg[$i] = '%';
|
137 |
+
}else
|
138 |
+
// handle complex expressions
|
139 |
+
if(substr($token, 0, 1) == '%' && substr($token, -1, 1) == '%'){
|
140 |
+
$mesg[$i] = $this->GetMetaExprValue(substr($token, 1, -1));
|
141 |
+
if($metaFormatter)$mesg[$i] = call_user_func($metaFormatter, $token, $mesg[$i]);
|
142 |
+
}
|
143 |
+
}
|
144 |
+
// compact message and return
|
145 |
+
return implode('', $mesg);
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* @param callable|null $metaFormatter (Optional) Meta formatter callback.
|
150 |
+
* @return string Full-formatted message.
|
151 |
+
*/
|
152 |
+
public function GetMessage($metaFormatter = null){
|
153 |
+
if(!isset($this->_cachedmessage)){
|
154 |
+
// get correct message entry
|
155 |
+
if($this->is_migrated){
|
156 |
+
$this->_cachedmessage = $this->GetMetaValue('MigratedMesg', false);
|
157 |
+
}
|
158 |
+
if(!$this->is_migrated || !$this->_cachedmessage){
|
159 |
+
$this->_cachedmessage = $this->GetAlert()->mesg;
|
160 |
+
}
|
161 |
+
// fill variables in message
|
162 |
+
$this->_cachedmessage = $this->GetFormattedMesg($this->_cachedmessage, $metaFormatter);
|
163 |
+
}
|
164 |
+
return $this->_cachedmessage;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Returns newest unique occurrences.
|
169 |
+
* @param integer $limit Maximum limit.
|
170 |
+
* @return WSAL_DB_Occurrence[]
|
171 |
+
*/
|
172 |
+
public static function GetNewestUnique($limit = PHP_INT_MAX){
|
173 |
+
$temp = new self();
|
174 |
+
return self::LoadMultiQuery('
|
175 |
+
SELECT *, COUNT(alert_id) as count
|
176 |
+
FROM (
|
177 |
+
SELECT *
|
178 |
+
FROM ' . $temp->GetTable() . '
|
179 |
+
ORDER BY created_on DESC
|
180 |
+
) AS temp_table
|
181 |
+
GROUP BY alert_id
|
182 |
+
LIMIT %d
|
183 |
+
', array($limit));
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Delete occurrence as well as associated meta data.
|
188 |
+
* @return boolean True on success, false on failure.
|
189 |
+
*/
|
190 |
+
public function Delete(){
|
191 |
+
foreach($this->GetMeta() as $meta)$meta->Delete();
|
192 |
+
return parent::Delete();
|
193 |
+
}
|
194 |
+
|
195 |
+
public function GetUsername(){
|
196 |
+
$meta = $this->GetFirstNamedMeta(array('Username', 'CurrentUserID'));
|
197 |
+
if($meta){
|
198 |
+
switch(true){
|
199 |
+
case $meta->name == 'Username':
|
200 |
+
return $meta->value;
|
201 |
+
case $meta->name == 'CurrentUserID':
|
202 |
+
return ($data = get_userdata($meta->value)) ? $data->user_login : null;
|
203 |
+
}
|
204 |
+
}
|
205 |
+
return null;
|
206 |
+
}
|
207 |
+
|
208 |
+
public function GetSourceIP(){
|
209 |
+
return $this->GetMetaValue('ClientIP', '');
|
210 |
+
}
|
211 |
+
|
212 |
+
}
|
classes/Loggers/Database.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Loggers_Database extends WSAL_AbstractLogger {
|
4 |
+
|
5 |
+
public function __construct(WpSecurityAuditLog $plugin) {
|
6 |
+
parent::__construct($plugin);
|
7 |
+
$plugin->AddCleanupHook(array($this, 'CleanUp'));
|
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;
|
18 |
+
$occ->created_on = $date;
|
19 |
+
$occ->alert_id = $type;
|
20 |
+
$occ->site_id = !is_null($siteid) ? $siteid
|
21 |
+
: (function_exists('get_current_blog_id') ? get_current_blog_id() : 0);
|
22 |
+
$occ->Save();
|
23 |
+
|
24 |
+
// set up meta data
|
25 |
+
$occ->SetMeta($data);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function CleanUp() {
|
29 |
+
$now = current_time('timestamp');
|
30 |
+
$max_count = $this->plugin->settings->GetPruningLimit();
|
31 |
+
$max_sdate = $this->plugin->settings->GetPruningDate();
|
32 |
+
$max_stamp = $now - (strtotime($max_sdate) - $now);
|
33 |
+
$cnt_items = WSAL_DB_Occurrence::Count();
|
34 |
+
if($cnt_items == $max_count)return;
|
35 |
+
$max_items = max(($cnt_items - $max_count) + 1, 0);
|
36 |
+
|
37 |
+
$is_date_e = true;
|
38 |
+
$is_limt_e = true;
|
39 |
+
|
40 |
+
switch(true){
|
41 |
+
case $is_date_e && $is_limt_e:
|
42 |
+
$cond = 'created_on < %d ORDER BY created_on ASC LIMIT %d';
|
43 |
+
$args = array($max_stamp, $max_items);
|
44 |
+
break;
|
45 |
+
case $is_date_e && !$is_limt_e:
|
46 |
+
$cond = 'created_on < %d';
|
47 |
+
$args = array($max_stamp);
|
48 |
+
break;
|
49 |
+
case !$is_date_e && $is_limt_e:
|
50 |
+
$cond = '1 ORDER BY created_on ASC LIMIT %d';
|
51 |
+
$args = array($max_items);
|
52 |
+
break;
|
53 |
+
}
|
54 |
+
if(!isset($cond))return;
|
55 |
+
|
56 |
+
$items = WSAL_DB_Occurrence::LoadMulti($cond, $args);
|
57 |
+
if(!count($items))return;
|
58 |
+
|
59 |
+
foreach($items as $item)$item->Delete();
|
60 |
+
do_action('wsal_prune', $items, vsprintf($cond, $args));
|
61 |
+
}
|
62 |
+
|
63 |
+
}
|
classes/Nicer.php
ADDED
@@ -0,0 +1,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 |
+
* Since PHP does not support private constants, we'll have to settle for private static fields.
|
35 |
+
* @var string
|
36 |
+
*/
|
37 |
+
protected static $BEEN_THERE = '__NICE_R_INFINITE_RECURSION_PROTECT__';
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Constructs new renderer instance.
|
41 |
+
* @param mixed $value The value to inspect and render.
|
42 |
+
*/
|
43 |
+
public function __construct($value){
|
44 |
+
$this->value = $value;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Generates the inspector HTML and returns it as a string.
|
49 |
+
* @return string Generated HTML.
|
50 |
+
*/
|
51 |
+
public function generate(){
|
52 |
+
return $this->_generate_value($this->value, $this->css_class);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Renders the inspector HTML directly to the browser.
|
57 |
+
*/
|
58 |
+
public function render(){
|
59 |
+
echo $this->generate();
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Converts a string to HTML, encoding any special characters.
|
64 |
+
* @param string $text The original string.
|
65 |
+
* @return string The string as HTML.
|
66 |
+
*/
|
67 |
+
protected function _esc_html($text){
|
68 |
+
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Render a single particular value.
|
73 |
+
* @param mixed $var The value to render
|
74 |
+
* @param string $class Parent CSS class.
|
75 |
+
* @param string $id Item HTML id.
|
76 |
+
*/
|
77 |
+
protected function _generate_value($var, $class = '', $id = ''){
|
78 |
+
$BEENTHERE = self::$BEEN_THERE;
|
79 |
+
$class .= ' '.$this->css_class.'_t_'.gettype($var);
|
80 |
+
|
81 |
+
$html = '<div id="'.$id.'" class="'.$class.'">';
|
82 |
+
|
83 |
+
switch(true){
|
84 |
+
|
85 |
+
// handle arrays
|
86 |
+
case is_array($var):
|
87 |
+
if(isset($var[$BEENTHERE])){
|
88 |
+
$html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
|
89 |
+
}else{
|
90 |
+
$var[$BEENTHERE] = true;
|
91 |
+
$has_subitems = false;
|
92 |
+
foreach($var as $k=>$v){
|
93 |
+
if($k!==$BEENTHERE){
|
94 |
+
$html .= $this->_generate_keyvalue($k, $v);
|
95 |
+
$has_subitems = true;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
if(!$has_subitems){
|
99 |
+
$html .= '<span class="'.$this->css_class.'_ni">Empty Array</span>';
|
100 |
+
}
|
101 |
+
unset($var[$BEENTHERE]);
|
102 |
+
}
|
103 |
+
break;
|
104 |
+
|
105 |
+
// handle objects
|
106 |
+
case is_object($var):
|
107 |
+
if(isset($var->$BEENTHERE)){
|
108 |
+
$html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
|
109 |
+
}else{
|
110 |
+
$var->$BEENTHERE = true;
|
111 |
+
$has_subitems = false;
|
112 |
+
foreach((array)$var as $k=>$v){
|
113 |
+
if($k!==$BEENTHERE){
|
114 |
+
$html .= $this->_generate_keyvalue($k, $v);
|
115 |
+
$has_subitems = true;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
if(!$has_subitems){
|
119 |
+
$html .= '<span class="'.$this->css_class.'_ni">No Properties</span>';
|
120 |
+
}
|
121 |
+
unset($var->$BEENTHERE);
|
122 |
+
}
|
123 |
+
break;
|
124 |
+
|
125 |
+
// handle simple types
|
126 |
+
default:
|
127 |
+
$html .= $this->_generate_keyvalue('', $var);
|
128 |
+
break;
|
129 |
+
}
|
130 |
+
|
131 |
+
return $html . '</div>';
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Render a key-value pair.
|
136 |
+
* @staticvar int $id Specifies element id.
|
137 |
+
* @param string $key Key name.
|
138 |
+
* @param mixed $val Key value.
|
139 |
+
*/
|
140 |
+
protected function _generate_keyvalue($key, $val){
|
141 |
+
static $id = 0; $id++; // unique (per rquest) id
|
142 |
+
$p = ''; // preview
|
143 |
+
$d = ''; // description
|
144 |
+
$t = gettype($val); // get data type
|
145 |
+
$is_hash = ($t=='array') || ($t=='object');
|
146 |
+
|
147 |
+
switch($t){
|
148 |
+
case 'boolean':
|
149 |
+
$p = $val ? 'TRUE' : 'FALSE';
|
150 |
+
break;
|
151 |
+
case 'integer':
|
152 |
+
case 'double':
|
153 |
+
$p = (string)$val;
|
154 |
+
break;
|
155 |
+
case 'string':
|
156 |
+
$d .= ', '.strlen($val).' characters';
|
157 |
+
$p = $val;
|
158 |
+
break;
|
159 |
+
case 'resource':
|
160 |
+
$d .= ', '.get_resource_type($val).' type';
|
161 |
+
$p = (string)$val;
|
162 |
+
break;
|
163 |
+
case 'array':
|
164 |
+
$d .= ', '.count($val).' elements';
|
165 |
+
break;
|
166 |
+
case 'object':
|
167 |
+
$d .= ', '.get_class($val).', '.count(get_object_vars($val)).' properties';
|
168 |
+
break;
|
169 |
+
}
|
170 |
+
|
171 |
+
$cls = $this->css_class;
|
172 |
+
$xcls = !$is_hash ? $cls.'_ad' : '';
|
173 |
+
$html = '<a href="javascript:;" onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
|
174 |
+
$html .= ' <span class="'.$cls.'_a '.$xcls.'" id="'.$this->html_id.'_a'.$id.'">►</span>';
|
175 |
+
$html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($key).'</span>';
|
176 |
+
$html .= ' <span class="'.$cls.'_d">(<span>'.ucwords($t).'</span>'.$d.')</span>';
|
177 |
+
$html .= ' <span class="'.$cls.'_p '.$cls.'_t_'.$t.'">'.$this->_esc_html($p).'</span>';
|
178 |
+
$html .= '</a>';
|
179 |
+
|
180 |
+
if($is_hash){
|
181 |
+
$html .= $this->_generate_value($val, $cls.'_v', $this->html_id.'_v'.$id);
|
182 |
+
}
|
183 |
+
|
184 |
+
return $html;
|
185 |
+
}
|
186 |
+
}
|
classes/SensorManager.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
final class WSAL_SensorManager extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
protected $sensors = array();
|
6 |
+
|
7 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
8 |
+
parent::__construct($plugin);
|
9 |
+
|
10 |
+
foreach(glob(dirname(__FILE__) . '/Sensors/*.php') as $file){
|
11 |
+
$class = $plugin->GetClassFileClassName($file);
|
12 |
+
$this->sensors[] = new $class($plugin);
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
public function HookEvents() {
|
17 |
+
foreach($this->sensors as $sensor)
|
18 |
+
$sensor->HookEvents();
|
19 |
+
}
|
20 |
+
|
21 |
+
}
|
classes/Sensors/Content.php
ADDED
@@ -0,0 +1,405 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
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);
|
10 |
+
add_action('untrash_post', array($this, 'EventPostUntrashed'));
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function GetEventTypeForPostType($post, $typePost, $typePage, $typeCustom){
|
14 |
+
switch($post->post_type){
|
15 |
+
case 'page':
|
16 |
+
return $typePage;
|
17 |
+
case 'post':
|
18 |
+
return $typePost;
|
19 |
+
default:
|
20 |
+
return $typeCustom;
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
protected $_OldPost = null;
|
25 |
+
protected $_OldLink = null;
|
26 |
+
protected $_OldCats = null;
|
27 |
+
protected $_OldTmpl = null;
|
28 |
+
protected $_OldStky = null;
|
29 |
+
|
30 |
+
public function EventWordpressInit(){
|
31 |
+
// load old data, if applicable
|
32 |
+
$this->RetrieveOldData();
|
33 |
+
// check for category changes
|
34 |
+
$this->CheckCategoryCreation();
|
35 |
+
$this->CheckCategoryDeletion();
|
36 |
+
}
|
37 |
+
|
38 |
+
protected function RetrieveOldData(){
|
39 |
+
if (isset($_POST) && isset($_POST['post_ID'])
|
40 |
+
&& !(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
|
41 |
+
&& !(isset($_POST['action']) && $_POST['action'] == 'autosave')
|
42 |
+
){
|
43 |
+
$postID = intval($_POST['post_ID']);
|
44 |
+
$this->_OldPost = get_post($postID);
|
45 |
+
$this->_OldLink = get_permalink($postID);
|
46 |
+
$this->_OldTmpl = $this->GetPostTemplate($this->_OldPost);
|
47 |
+
$this->_OldCats = $this->GetPostCategories($this->_OldPost);
|
48 |
+
$this->_OldStky = in_array($postID, get_option('sticky_posts'));
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
protected function GetPostTemplate($post){
|
53 |
+
$id = $post->ID;
|
54 |
+
$template = get_page_template_slug($id);
|
55 |
+
$pagename = $post->post_name;
|
56 |
+
|
57 |
+
$templates = array();
|
58 |
+
if ( $template && 0 === validate_file( $template ) ) $templates[] = $template;
|
59 |
+
if ( $pagename ) $templates[] = "page-$pagename.php";
|
60 |
+
if ( $id ) $templates[] = "page-$id.php";
|
61 |
+
$templates[] = 'page.php';
|
62 |
+
|
63 |
+
return get_query_template( 'page', $templates );
|
64 |
+
}
|
65 |
+
|
66 |
+
protected function GetPostCategories($post){
|
67 |
+
return wp_get_post_categories($post->ID, array('fields' => 'names'));;
|
68 |
+
}
|
69 |
+
|
70 |
+
public function EventPostChanged($newStatus, $oldStatus, $post){
|
71 |
+
// ignorable states
|
72 |
+
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
73 |
+
if (empty($post->post_type)) return;
|
74 |
+
if ($post->post_type == 'revision') return;
|
75 |
+
|
76 |
+
$original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
|
77 |
+
|
78 |
+
WSAL_Sensors_Request::SetVars(array(
|
79 |
+
'$newStatus' => $newStatus,
|
80 |
+
'$oldStatus' => $oldStatus,
|
81 |
+
'$original' => $original,
|
82 |
+
));
|
83 |
+
|
84 |
+
// run checks
|
85 |
+
if($this->_OldPost){
|
86 |
+
if ($oldStatus == 'auto-draft' || $original == 'auto-draft'){
|
87 |
+
|
88 |
+
// Handle create post events
|
89 |
+
$this->CheckPostCreation($this->_OldPost, $post);
|
90 |
+
|
91 |
+
}else{
|
92 |
+
|
93 |
+
// Handle update post events
|
94 |
+
$changes = 0
|
95 |
+
+ $this->CheckDateChange($this->_OldPost, $post)
|
96 |
+
+ $this->CheckAuthorChange($this->_OldPost, $post)
|
97 |
+
+ $this->CheckStatusChange($this->_OldPost, $post)
|
98 |
+
+ $this->CheckParentChange($this->_OldPost, $post)
|
99 |
+
+ $this->CheckStickyChange($this->_OldStky, isset($_REQUEST['sticky']), $post)
|
100 |
+
+ $this->CheckVisibilityChange($this->_OldPost, $post, $oldStatus, $newStatus)
|
101 |
+
+ $this->CheckTemplateChange($this->_OldTmpl, $this->GetPostTemplate($post), $post)
|
102 |
+
+ $this->CheckCategoriesChange($this->_OldCats, $this->GetPostCategories($post), $post)
|
103 |
+
;
|
104 |
+
if(!$changes)
|
105 |
+
$changes = $this->CheckPermalinkChange($this->_OldLink, get_permalink($post->ID), $post);
|
106 |
+
if(!$changes)
|
107 |
+
$changes = $this->CheckModificationChange($this->_OldPost, $post);
|
108 |
+
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
protected function CheckPostCreation($oldPost, $newPost){
|
114 |
+
$event = 0;
|
115 |
+
switch($newPost->post_status){
|
116 |
+
case 'publish':
|
117 |
+
$event = $this->GetEventTypeForPostType($oldPost, 2001, 2005, 2030);
|
118 |
+
break;
|
119 |
+
case 'draft':
|
120 |
+
$event = $this->GetEventTypeForPostType($oldPost, 2000, 2004, 2029);
|
121 |
+
break;
|
122 |
+
}
|
123 |
+
if($event)$this->plugin->alerts->Trigger($event, array(
|
124 |
+
'PostID' => $newPost->ID,
|
125 |
+
'PostType' => $newPost->post_type,
|
126 |
+
'PostTitle' => $newPost->post_title,
|
127 |
+
'PostUrl' => get_permalink($newPost->ID),
|
128 |
+
));
|
129 |
+
}
|
130 |
+
|
131 |
+
protected function CheckCategoryCreation(){
|
132 |
+
if (empty($_POST)) return;
|
133 |
+
|
134 |
+
$categoryName = '';
|
135 |
+
if(!empty($_POST['screen']) && !empty($_POST['tag-name']) &&
|
136 |
+
$_POST['screen'] == 'edit-category' &&
|
137 |
+
$_POST['taxonomy'] == 'category' &&
|
138 |
+
$_POST['action'] == 'add-tag')
|
139 |
+
{
|
140 |
+
$categoryName = $_POST['tag-name'];
|
141 |
+
}
|
142 |
+
elseif(!empty($_POST['newcategory']) && $_POST['action'] == 'add-category')
|
143 |
+
{
|
144 |
+
$categoryName = $_POST['newcategory'];
|
145 |
+
}
|
146 |
+
|
147 |
+
if($categoryName){
|
148 |
+
$this->plugin->alerts->Trigger(2023, array(
|
149 |
+
'CategoryName' => $categoryName,
|
150 |
+
));
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
protected function CheckCategoryDeletion(){
|
155 |
+
if (empty($_POST)) return;
|
156 |
+
$action = !empty($_POST['action']) ? $_POST['action']
|
157 |
+
: (!empty($_POST['action2']) ? $_POST['action2'] : '');
|
158 |
+
if (!$action) return;
|
159 |
+
|
160 |
+
$categoryIds = array();
|
161 |
+
|
162 |
+
if($action == 'delete' && $_POST['taxonomy'] == 'category' && !empty($_POST['delete_tags'])){
|
163 |
+
// bulk delete
|
164 |
+
$categoryIds[] = $_POST['delete_tags'];
|
165 |
+
}elseif($action == 'delete-tag' && $_POST['taxonomy'] == 'category' && !empty($_POST['tag_ID'])){
|
166 |
+
// single delete
|
167 |
+
$categoryIds[] = $_POST['tag_ID'];
|
168 |
+
}
|
169 |
+
|
170 |
+
foreach($categoryIds as $categoryID){
|
171 |
+
$category = get_category($categoryID);
|
172 |
+
$this->plugin->alerts->Trigger(2024, array(
|
173 |
+
'CategoryID' => $categoryID,
|
174 |
+
'CategoryName' => $category->cat_name,
|
175 |
+
));
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
public function EventPostDeleted($post_id){
|
180 |
+
$post = get_post($post_id);
|
181 |
+
if(!in_array($post->post_type, array('attachment', 'revision'))){ // ignore attachments and revisions
|
182 |
+
$event = $this->GetEventTypeForPostType($post, 2008, 2009, 2033);
|
183 |
+
$this->plugin->alerts->Trigger($event, array(
|
184 |
+
'PostID' => $post->ID,
|
185 |
+
'PostType' => $post->post_type,
|
186 |
+
'PostTitle' => $post->post_title,
|
187 |
+
));
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
public function EventPostTrashed($post_id){
|
192 |
+
$post = get_post($post_id);
|
193 |
+
$event = $this->GetEventTypeForPostType($post, 2012, 2013, 2034);
|
194 |
+
$this->plugin->alerts->Trigger($event, array(
|
195 |
+
'PostID' => $post->ID,
|
196 |
+
'PostType' => $post->post_type,
|
197 |
+
'PostTitle' => $post->post_title,
|
198 |
+
));
|
199 |
+
}
|
200 |
+
|
201 |
+
public function EventPostUntrashed($post_id){
|
202 |
+
$post = get_post($post_id);
|
203 |
+
$event = $this->GetEventTypeForPostType($post, 2014, 2015, 2035);
|
204 |
+
$this->plugin->alerts->Trigger($event, array(
|
205 |
+
'PostID' => $post->ID,
|
206 |
+
'PostType' => $post->post_type,
|
207 |
+
'PostTitle' => $post->post_title,
|
208 |
+
));
|
209 |
+
}
|
210 |
+
|
211 |
+
protected function CheckDateChange($oldpost, $newpost){
|
212 |
+
$from = strtotime($oldpost->post_date);
|
213 |
+
$to = strtotime($newpost->post_date);
|
214 |
+
if($oldpost->post_status == 'draft')return;
|
215 |
+
if($from != $to){
|
216 |
+
$event = $this->GetEventTypeForPostType($oldpost, 2027, 2028, 2041);
|
217 |
+
$this->plugin->alerts->Trigger($event, array(
|
218 |
+
'PostID' => $oldpost->ID,
|
219 |
+
'PostType' => $oldpost->post_type,
|
220 |
+
'PostTitle' => $oldpost->post_title,
|
221 |
+
'OldDate' => $oldpost->post_date,
|
222 |
+
'NewDate' => $newpost->post_date,
|
223 |
+
));
|
224 |
+
return 1;
|
225 |
+
}
|
226 |
+
}
|
227 |
+
|
228 |
+
protected function CheckCategoriesChange($oldCats, $newCats, $post){
|
229 |
+
$oldCats = implode(', ', $oldCats);
|
230 |
+
$newCats = implode(', ', $newCats);
|
231 |
+
if($oldCats != $newCats){
|
232 |
+
$event = $this->GetEventTypeForPostType($post, 2016, 0, 2036);
|
233 |
+
if($event){
|
234 |
+
$this->plugin->alerts->Trigger($event, array(
|
235 |
+
'PostID' => $post->ID,
|
236 |
+
'PostType' => $post->post_type,
|
237 |
+
'PostTitle' => $post->post_title,
|
238 |
+
'OldCategories' => $oldCats ? $oldCats : 'no categories',
|
239 |
+
'NewCategories' => $newCats ? $newCats : 'no categories',
|
240 |
+
));
|
241 |
+
return 1;
|
242 |
+
}
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
protected function CheckAuthorChange($oldpost, $newpost){
|
247 |
+
if($oldpost->post_author != $newpost->post_author){
|
248 |
+
$event = $this->GetEventTypeForPostType($oldpost, 2019, 2020, 2038);
|
249 |
+
$this->plugin->alerts->Trigger($event, array(
|
250 |
+
'PostID' => $oldpost->ID,
|
251 |
+
'PostType' => $oldpost->post_type,
|
252 |
+
'PostTitle' => $oldpost->post_title,
|
253 |
+
'OldAuthor' => get_userdata($oldpost->post_author)->user_login,
|
254 |
+
'NewAuthor' => get_userdata($newpost->post_author)->user_login,
|
255 |
+
));
|
256 |
+
return 1;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
|
260 |
+
protected function CheckStatusChange($oldpost, $newpost){
|
261 |
+
if($oldpost->post_status != $newpost->post_status){
|
262 |
+
if(isset($_REQUEST['publish'])){
|
263 |
+
// special case (publishing a post)
|
264 |
+
$event = $this->GetEventTypeForPostType($oldpost, 2001, 2005, 2030);
|
265 |
+
$this->plugin->alerts->Trigger($event, array(
|
266 |
+
'PostID' => $newpost->ID,
|
267 |
+
'PostType' => $newpost->post_type,
|
268 |
+
'PostTitle' => $newpost->post_title,
|
269 |
+
'PostUrl' => get_permalink($newpost->ID),
|
270 |
+
));
|
271 |
+
}else{
|
272 |
+
$event = $this->GetEventTypeForPostType($oldpost, 2021, 2022, 2039);
|
273 |
+
$this->plugin->alerts->Trigger($event, array(
|
274 |
+
'PostID' => $oldpost->ID,
|
275 |
+
'PostType' => $oldpost->post_type,
|
276 |
+
'PostTitle' => $oldpost->post_title,
|
277 |
+
'OldStatus' => $oldpost->post_status,
|
278 |
+
'NewStatus' => $newpost->post_status,
|
279 |
+
));
|
280 |
+
}
|
281 |
+
return 1;
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
protected function CheckParentChange($oldpost, $newpost){
|
286 |
+
if($oldpost->post_parent != $newpost->post_parent){
|
287 |
+
$event = $this->GetEventTypeForPostType($oldpost, 0, 2047, 0);
|
288 |
+
if($event){
|
289 |
+
$this->plugin->alerts->Trigger($event, array(
|
290 |
+
'PostID' => $oldpost->ID,
|
291 |
+
'PostType' => $oldpost->post_type,
|
292 |
+
'PostTitle' => $oldpost->post_title,
|
293 |
+
'OldParent' => $oldpost->post_parent,
|
294 |
+
'NewParent' => $newpost->post_parent,
|
295 |
+
'OldParentName' => $oldpost->post_parent ? get_the_title($oldpost->post_parent) : 'no parent',
|
296 |
+
'NewParentName' => $newpost->post_parent ? get_the_title($newpost->post_parent) : 'no parent',
|
297 |
+
));
|
298 |
+
return 1;
|
299 |
+
}
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
protected function CheckPermalinkChange($oldLink, $newLink, $post){
|
304 |
+
if($oldLink != $newLink){
|
305 |
+
$event = $this->GetEventTypeForPostType($post, 2017, 2018, 2037);
|
306 |
+
$this->plugin->alerts->Trigger($event, array(
|
307 |
+
'PostID' => $post->ID,
|
308 |
+
'PostType' => $post->post_type,
|
309 |
+
'PostTitle' => $post->post_title,
|
310 |
+
'OldUrl' => $oldLink,
|
311 |
+
'NewUrl' => $newLink,
|
312 |
+
));
|
313 |
+
return 1;
|
314 |
+
}
|
315 |
+
}
|
316 |
+
|
317 |
+
protected function CheckVisibilityChange($oldpost, $newpost, $oldStatus, $newStatus){
|
318 |
+
if($oldStatus == 'draft' || $newStatus == 'draft')return;
|
319 |
+
|
320 |
+
$oldVisibility = '';
|
321 |
+
$newVisibility = '';
|
322 |
+
|
323 |
+
if($oldpost->post_password){
|
324 |
+
$oldVisibility = __('Password Protected');
|
325 |
+
}elseif($oldStatus == 'publish'){
|
326 |
+
$oldVisibility = __('Public');
|
327 |
+
}elseif($oldStatus == 'private'){
|
328 |
+
$oldVisibility = __('Private');
|
329 |
+
}
|
330 |
+
|
331 |
+
if($newpost->post_password){
|
332 |
+
$newVisibility = __('Password Protected');
|
333 |
+
}elseif($newStatus == 'publish'){
|
334 |
+
$newVisibility = __('Public');
|
335 |
+
}elseif($newStatus == 'private'){
|
336 |
+
$newVisibility = __('Private');
|
337 |
+
}
|
338 |
+
|
339 |
+
if($oldVisibility && $newVisibility && ($oldVisibility != $newVisibility)){
|
340 |
+
$event = $this->GetEventTypeForPostType($oldpost, 2025, 2026, 2040);
|
341 |
+
$this->plugin->alerts->Trigger($event, array(
|
342 |
+
'PostID' => $oldpost->ID,
|
343 |
+
'PostType' => $oldpost->post_type,
|
344 |
+
'PostTitle' => $oldpost->post_title,
|
345 |
+
'OldVisibility' => $oldVisibility,
|
346 |
+
'NewVisibility' => $newVisibility,
|
347 |
+
));
|
348 |
+
return 1;
|
349 |
+
}
|
350 |
+
}
|
351 |
+
|
352 |
+
protected function CheckTemplateChange($oldTmpl, $newTmpl, $post){
|
353 |
+
if($oldTmpl != $newTmpl){
|
354 |
+
$event = $this->GetEventTypeForPostType($post, 0, 2048, 0);
|
355 |
+
if($event){
|
356 |
+
$this->plugin->alerts->Trigger($event, array(
|
357 |
+
'PostID' => $post->ID,
|
358 |
+
'PostType' => $post->post_type,
|
359 |
+
'PostTitle' => $post->post_title,
|
360 |
+
'OldTemplate' => ucwords(str_replace(array('-' , '_'), ' ', basename($oldTmpl, '.php'))),
|
361 |
+
'NewTemplate' => ucwords(str_replace(array('-' , '_'), ' ', basename($newTmpl, '.php'))),
|
362 |
+
'OldTemplatePath' => $oldTmpl,
|
363 |
+
'NewTemplatePath' => $newTmpl,
|
364 |
+
));
|
365 |
+
return 1;
|
366 |
+
}
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
protected function CheckStickyChange($oldStky, $newStky, $post){
|
371 |
+
if($oldStky != $newStky){
|
372 |
+
$event = $newStky ? 2049 : 2050;
|
373 |
+
$this->plugin->alerts->Trigger($event, array(
|
374 |
+
'PostID' => $post->ID,
|
375 |
+
'PostType' => $post->post_type,
|
376 |
+
'PostTitle' => $post->post_title,
|
377 |
+
));
|
378 |
+
return 1;
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
protected function CheckModificationChange($oldpost, $newpost){
|
383 |
+
if($oldpost->post_modified != $newpost->post_modified){
|
384 |
+
$event = 0;
|
385 |
+
// @see http://codex.wordpress.org/Class_Reference/WP_Query#Status_Parameters
|
386 |
+
switch($oldpost->post_status){ // TODO or should this be $newpost?
|
387 |
+
case 'draft':
|
388 |
+
$event = $this->GetEventTypeForPostType($newpost, 2003, 2007, 2032);
|
389 |
+
break;
|
390 |
+
case 'publish':
|
391 |
+
$event = $this->GetEventTypeForPostType($newpost, 2002, 2006, 2031);
|
392 |
+
break;
|
393 |
+
}
|
394 |
+
if($event){
|
395 |
+
$this->plugin->alerts->Trigger($event, array(
|
396 |
+
'PostID' => $oldpost->ID,
|
397 |
+
'PostType' => $oldpost->post_type,
|
398 |
+
'PostTitle' => $oldpost->post_title,
|
399 |
+
'PostUrl' => get_permalink($oldpost->ID), // TODO or should this be $newpost?
|
400 |
+
));
|
401 |
+
return 1;
|
402 |
+
}
|
403 |
+
}
|
404 |
+
}
|
405 |
+
}
|
classes/Sensors/Files.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_Files extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
public function HookEvents() {
|
6 |
+
add_action('add_attachment', array($this, 'EventFileUploaded'));
|
7 |
+
add_action('delete_attachment', array($this, 'EventFileUploadedDeleted'));
|
8 |
+
add_action('admin_init', array($this, 'EventAdminInit'));
|
9 |
+
}
|
10 |
+
|
11 |
+
protected $IsFileUploaded = false;
|
12 |
+
|
13 |
+
public function EventFileUploaded($attachmentID){
|
14 |
+
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
|
15 |
+
if($action != 'upload-theme' && $action != 'upload-plugin'){
|
16 |
+
$file = get_attached_file($attachmentID);
|
17 |
+
$this->plugin->alerts->Trigger(2010, array(
|
18 |
+
'AttachmentID' => $attachmentID,
|
19 |
+
'FileName' => basename($file),
|
20 |
+
'FilePath' => dirname($file),
|
21 |
+
));
|
22 |
+
}
|
23 |
+
$this->IsFileUploaded = true;
|
24 |
+
}
|
25 |
+
|
26 |
+
public function EventFileUploadedDeleted($attachmentID){
|
27 |
+
if($this->IsFileUploaded)return;
|
28 |
+
$file = get_attached_file($attachmentID);
|
29 |
+
$this->plugin->alerts->Trigger(2011, array(
|
30 |
+
'AttachmentID' => $attachmentID,
|
31 |
+
'FileName' => basename($file),
|
32 |
+
'FilePath' => dirname($file),
|
33 |
+
));
|
34 |
+
}
|
35 |
+
|
36 |
+
public function EventAdminInit(){
|
37 |
+
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
|
38 |
+
$is_theme_editor = basename($_SERVER['SCRIPT_NAME']) == 'theme-editor.php';
|
39 |
+
if($is_theme_editor && $action == 'update'){
|
40 |
+
$this->plugin->alerts->Trigger(2046, array(
|
41 |
+
'File' => $_REQUEST['file'],
|
42 |
+
'Theme' => $_REQUEST['theme'],
|
43 |
+
));
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
}
|
classes/Sensors/LogInOut.php
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
public function HookEvents() {
|
6 |
+
add_action('wp_login', array($this, 'EventLogin'), 10, 2);
|
7 |
+
add_action('wp_logout', array($this, 'EventLogout'));
|
8 |
+
add_action('wp_login_failed', array($this, 'EventLoginFailure'));
|
9 |
+
}
|
10 |
+
|
11 |
+
public function EventLogin($user_login, $user){
|
12 |
+
$this->plugin->alerts->Trigger(1000, array('Username' => $user_login));
|
13 |
+
}
|
14 |
+
|
15 |
+
public function EventLogout(){
|
16 |
+
$this->plugin->alerts->Trigger(1001);
|
17 |
+
}
|
18 |
+
|
19 |
+
public function EventLoginFailure($username){
|
20 |
+
list($y, $m, $d) = explode('-', date('Y-m-d'));
|
21 |
+
$occ = WSAL_DB_Occurrence::LoadMultiQuery('
|
22 |
+
SELECT * FROM `wp_wsal_occurrences`
|
23 |
+
WHERE alert_id = %d AND site_id = %d
|
24 |
+
AND (created_on BETWEEN %d AND %d)
|
25 |
+
AND id IN (
|
26 |
+
SELECT occurrence_id as id
|
27 |
+
FROM wp_wsal_metadata
|
28 |
+
WHERE (name = "ClientIP" AND value = %s)
|
29 |
+
OR (name = "Username" AND value = %s)
|
30 |
+
GROUP BY occurrence_id
|
31 |
+
HAVING COUNT(*) = 2
|
32 |
+
)
|
33 |
+
', array(
|
34 |
+
1002,
|
35 |
+
(function_exists('get_current_blog_id') ? get_current_blog_id() : 0),
|
36 |
+
mktime(0, 0, 0, $m, $d, $y),
|
37 |
+
mktime(0, 0, 0, $m, $d + 1, $y) - 1,
|
38 |
+
json_encode(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''),
|
39 |
+
json_encode($username),
|
40 |
+
));
|
41 |
+
$occ = count($occ) ? $occ[0] : null;
|
42 |
+
|
43 |
+
if($occ && $occ->IsLoaded()){
|
44 |
+
// update existing record
|
45 |
+
$occ->SetMetaValue('Attempts',
|
46 |
+
$occ->GetMetaValue('Attempts', 0) + 1
|
47 |
+
);
|
48 |
+
$occ->created_on = current_time('timestamp');
|
49 |
+
$occ->Save();
|
50 |
+
}else{
|
51 |
+
// create a new record
|
52 |
+
$this->plugin->alerts->Trigger(1002, array(
|
53 |
+
'Username' => $username,
|
54 |
+
'Attempts' => 1
|
55 |
+
));
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
}
|
classes/Sensors/Multisite.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
public function HookEvents() {
|
6 |
+
add_action('wpmu_new_blog', array($this, 'EventNewBlog'), 10, 1);
|
7 |
+
add_action('archive_blog', array($this, 'EventArchiveBlog'));
|
8 |
+
add_action('unarchive_blog', array($this, 'EventUnarchiveBlog'));
|
9 |
+
add_action('activate_blog', array($this, 'EventActivateBlog'));
|
10 |
+
add_action('deactivate_blog', array($this, 'EventDeactivateBlog'));
|
11 |
+
add_action('delete_blog', array($this, 'EventDeleteBlog'));
|
12 |
+
add_action('add_user_to_blog', array($this, 'EventUserAddedToBlog'), 10, 3);
|
13 |
+
add_action('remove_user_from_blog', array($this, 'EventUserRemovedFromBlog'));
|
14 |
+
}
|
15 |
+
|
16 |
+
public function EventNewBlog($blog_id){
|
17 |
+
$this->plugin->alerts->Trigger(7000, array(
|
18 |
+
'BlogID' => $blog_id,
|
19 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
20 |
+
));
|
21 |
+
}
|
22 |
+
|
23 |
+
public function EventArchiveBlog($blog_id){
|
24 |
+
$this->plugin->alerts->Trigger(7001, array(
|
25 |
+
'BlogID' => $blog_id,
|
26 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
27 |
+
));
|
28 |
+
}
|
29 |
+
|
30 |
+
public function EventUnarchiveBlog($blog_id){
|
31 |
+
$this->plugin->alerts->Trigger(7002, array(
|
32 |
+
'BlogID' => $blog_id,
|
33 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
34 |
+
));
|
35 |
+
}
|
36 |
+
|
37 |
+
public function EventActivateBlog($blog_id){
|
38 |
+
$this->plugin->alerts->Trigger(7003, array(
|
39 |
+
'BlogID' => $blog_id,
|
40 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
41 |
+
));
|
42 |
+
}
|
43 |
+
|
44 |
+
public function EventDeactivateBlog($blog_id){
|
45 |
+
$this->plugin->alerts->Trigger(7004, array(
|
46 |
+
'BlogID' => $blog_id,
|
47 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
48 |
+
));
|
49 |
+
}
|
50 |
+
|
51 |
+
public function EventDeleteBlog($blog_id){
|
52 |
+
$this->plugin->alerts->Trigger(7005, array(
|
53 |
+
'BlogID' => $blog_id,
|
54 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
55 |
+
));
|
56 |
+
}
|
57 |
+
|
58 |
+
public function EventUserAddedToBlog($user_id, $role, $blog_id){
|
59 |
+
$this->plugin->alerts->Trigger(4010, array(
|
60 |
+
'UserID' => $user_id,
|
61 |
+
'Username' => get_userdata($user_id)->user_login,
|
62 |
+
'UserRole' => $role,
|
63 |
+
'BlogID' => $blog_id,
|
64 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
65 |
+
));
|
66 |
+
}
|
67 |
+
|
68 |
+
public function EventUserRemovedFromBlog($user_id){
|
69 |
+
$user = get_userdata($user_id);
|
70 |
+
$blog_id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : 0);
|
71 |
+
$this->plugin->alerts->Trigger(4011, array(
|
72 |
+
'UserID' => $user_id,
|
73 |
+
'Username' => $user->user_login,
|
74 |
+
'UserRole' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
|
75 |
+
'BlogID' => $blog_id,
|
76 |
+
'SiteName' => get_blog_option($blog_id, 'blogname'),
|
77 |
+
));
|
78 |
+
}
|
79 |
+
}
|
classes/Sensors/PhpErrors.php
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_PhpErrors extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
protected $_avoid_error_recursion = false;
|
6 |
+
|
7 |
+
protected $_error_types = array(
|
8 |
+
0001 => array(1,4,16,64,256,4096), // errors
|
9 |
+
0002 => array(2,32,128,512), // warnings
|
10 |
+
0003 => array(8,1024,2048,8192,16384), // notices
|
11 |
+
);
|
12 |
+
|
13 |
+
protected $_maybe_last_error = null;
|
14 |
+
|
15 |
+
public function HookEvents() {
|
16 |
+
if($this->plugin->settings->IsPhpErrorLoggingEnabled()){
|
17 |
+
set_error_handler(array($this, 'EventError'), E_ALL);
|
18 |
+
set_exception_handler(array($this, 'EventException'));
|
19 |
+
register_shutdown_function(array($this, 'EventShutdown'));
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
protected function GetErrorHash($code, $mesg, $file, $line){
|
24 |
+
return md5(implode(':', func_get_args()));
|
25 |
+
}
|
26 |
+
|
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)
|
39 |
+
foreach($this->_error_types as $temp => $codes){
|
40 |
+
if(in_array($errno, $codes)){
|
41 |
+
$type = $temp;
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
$this->_maybe_last_error = $this->GetErrorHash($errno, $errstr, $errfile, $errline);
|
46 |
+
|
47 |
+
$this->_avoid_error_recursion = true;
|
48 |
+
$this->plugin->alerts->Trigger($type, $data);
|
49 |
+
$this->_avoid_error_recursion = false;
|
50 |
+
}
|
51 |
+
|
52 |
+
public function EventException(Exception $ex){
|
53 |
+
if($this->_avoid_error_recursion)return;
|
54 |
+
|
55 |
+
$data = array(
|
56 |
+
'Class' => get_class($ex),
|
57 |
+
'Code' => $ex->getCode(),
|
58 |
+
'Message' => $ex->getMessage(),
|
59 |
+
'File' => $ex->getFile(),
|
60 |
+
'Line' => $ex->getLine(),
|
61 |
+
'Trace' => $ex->getTraceAsString(),
|
62 |
+
);
|
63 |
+
|
64 |
+
if(method_exists($ex, 'getContext'))
|
65 |
+
$data['Context'] = $ex->getContext();
|
66 |
+
|
67 |
+
$this->_avoid_error_recursion = true;
|
68 |
+
$this->plugin->alerts->Trigger(0004, $data);
|
69 |
+
$this->_avoid_error_recursion = false;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function EventShutdown(){
|
73 |
+
if($this->_avoid_error_recursion)return;
|
74 |
+
|
75 |
+
if(!!($e = error_get_last()) && ($this->_maybe_last_error != $this->GetErrorHash($e['type'], $e['message'], $e['file'], $e['line']))){
|
76 |
+
$data = array(
|
77 |
+
'Code' => $e['type'],
|
78 |
+
'Message' => $e['message'],
|
79 |
+
'File' => $e['file'],
|
80 |
+
'Line' => $e['line'],
|
81 |
+
);
|
82 |
+
|
83 |
+
$this->_avoid_error_recursion = true;
|
84 |
+
$this->plugin->alerts->Trigger(0005, $data);
|
85 |
+
$this->_avoid_error_recursion = false;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
}
|
classes/Sensors/PluginsThemes.php
ADDED
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
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 |
+
|
11 |
+
protected $old_themes;
|
12 |
+
protected $old_plugins;
|
13 |
+
|
14 |
+
public function EventAdminInit(){
|
15 |
+
$this->old_themes = wp_get_themes();
|
16 |
+
$this->old_plugins = get_plugins();
|
17 |
+
}
|
18 |
+
|
19 |
+
public function EventAdminShutdown(){
|
20 |
+
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
|
21 |
+
$action = isset($_REQUEST['action2']) ? $_REQUEST['action2'] : $action;
|
22 |
+
$actype = basename($_SERVER['SCRIPT_NAME'], '.php');
|
23 |
+
$is_themes = $actype == 'themes';
|
24 |
+
$is_plugins = $actype == 'plugins';
|
25 |
+
|
26 |
+
// install plugin
|
27 |
+
if(($action=='install-plugin' || $action=='upload-plugin')){
|
28 |
+
$newPlugin = array_values(array_diff(array_keys(get_plugins()), array_keys($this->old_plugins)));
|
29 |
+
if(count($newPlugin) != 1)
|
30 |
+
return $this->LogError(
|
31 |
+
'Expected exactly one new plugin but found ' . count($newPlugin),
|
32 |
+
array('NewPlugin' => $newPlugin, 'OldPlugins' => $this->old_plugins, 'NewPlugins' => get_plugins())
|
33 |
+
);
|
34 |
+
$newPluginPath = $newPlugin[0];
|
35 |
+
$newPlugin = get_plugins();
|
36 |
+
$newPlugin = $newPlugin[$newPluginPath];
|
37 |
+
$newPluginPath = plugin_dir_path(WP_PLUGIN_DIR . '/' . $newPluginPath[0]);
|
38 |
+
$this->plugin->alerts->Trigger(5000, array(
|
39 |
+
'NewPlugin' => (object)array(
|
40 |
+
'Name' => $newPlugin['Name'],
|
41 |
+
'PluginURI' => $newPlugin['PluginURI'],
|
42 |
+
'Version' => $newPlugin['Version'],
|
43 |
+
'Author' => $newPlugin['Author'],
|
44 |
+
'Network' => $newPlugin['Network'] ? 'True' : 'False',
|
45 |
+
'plugin_dir_path' => $newPluginPath,
|
46 |
+
),
|
47 |
+
));
|
48 |
+
}
|
49 |
+
|
50 |
+
// activate plugin
|
51 |
+
if($is_plugins && in_array($action, array('activate', 'activate-selected'))){
|
52 |
+
if(isset($_REQUEST['plugin'])){
|
53 |
+
if(!isset($_REQUEST['checked']))
|
54 |
+
$_REQUEST['checked'] = array();
|
55 |
+
$_REQUEST['checked'][] = $_REQUEST['plugin'];
|
56 |
+
}
|
57 |
+
foreach($_REQUEST['checked'] as $pluginFile){
|
58 |
+
$pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
|
59 |
+
$pluginData = get_plugin_data($pluginFile, false, true);
|
60 |
+
$this->plugin->alerts->Trigger(5001, array(
|
61 |
+
'PluginFile' => $pluginFile,
|
62 |
+
'PluginData' => (object)array(
|
63 |
+
'Name' => $pluginData['Name'],
|
64 |
+
'PluginURI' => $pluginData['PluginURI'],
|
65 |
+
'Version' => $pluginData['Version'],
|
66 |
+
'Author' => $pluginData['Author'],
|
67 |
+
'Network' => $pluginData['Network'] ? 'True' : 'False',
|
68 |
+
),
|
69 |
+
));
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
// deactivate plugin
|
74 |
+
if($is_plugins && in_array($action, array('deactivate', 'deactivate-selected'))){
|
75 |
+
if(isset($_REQUEST['plugin'])){
|
76 |
+
if(!isset($_REQUEST['checked']))
|
77 |
+
$_REQUEST['checked'] = array();
|
78 |
+
$_REQUEST['checked'][] = $_REQUEST['plugin'];
|
79 |
+
}
|
80 |
+
foreach($_REQUEST['checked'] as $pluginFile){
|
81 |
+
$pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
|
82 |
+
$pluginData = get_plugin_data($pluginFile, false, true);
|
83 |
+
$this->plugin->alerts->Trigger(5002, array(
|
84 |
+
'PluginFile' => $pluginFile,
|
85 |
+
'PluginData' => (object)array(
|
86 |
+
'Name' => $pluginData['Name'],
|
87 |
+
'PluginURI' => $pluginData['PluginURI'],
|
88 |
+
'Version' => $pluginData['Version'],
|
89 |
+
'Author' => $pluginData['Author'],
|
90 |
+
'Network' => $pluginData['Network'] ? 'True' : 'False',
|
91 |
+
),
|
92 |
+
));
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
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{
|
103 |
+
// second step, after deletion approval
|
104 |
+
// TODO use plugin data from session
|
105 |
+
foreach($_REQUEST['checked'] as $pluginFile){
|
106 |
+
$pluginName = basename($pluginFile, '.php');
|
107 |
+
$pluginName = str_replace(array('_', '-', ' '), ' ', $pluginName);
|
108 |
+
$pluginName = ucwords($pluginName);
|
109 |
+
$pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
|
110 |
+
$this->plugin->alerts->Trigger(5003, array(
|
111 |
+
'PluginFile' => $pluginFile,
|
112 |
+
'PluginData' => (object)array(
|
113 |
+
'Name' => $pluginName,
|
114 |
+
),
|
115 |
+
));
|
116 |
+
}
|
117 |
+
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
// upgrade plugin
|
122 |
+
if(in_array($action, array('upgrade-plugin', 'update-selected'))){
|
123 |
+
if(isset($_REQUEST['plugin'])){
|
124 |
+
if(!isset($_REQUEST['checked']))
|
125 |
+
$_REQUEST['checked'] = array();
|
126 |
+
$_REQUEST['checked'][] = $_REQUEST['plugin'];
|
127 |
+
}
|
128 |
+
if(isset($_REQUEST['checked'])){
|
129 |
+
if(!is_array($_REQUEST['checked'])){
|
130 |
+
$_REQUEST['checked'] = array($_REQUEST['checked']);
|
131 |
+
}
|
132 |
+
foreach($_REQUEST['checked'] as $pluginFile){
|
133 |
+
$pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
|
134 |
+
$pluginData = get_plugin_data($pluginFile, false, true);
|
135 |
+
$this->plugin->alerts->Trigger(5004, array(
|
136 |
+
'PluginFile' => $pluginFile,
|
137 |
+
'PluginData' => (object)array(
|
138 |
+
'Name' => $pluginData['Name'],
|
139 |
+
'PluginURI' => $pluginData['PluginURI'],
|
140 |
+
'Version' => $pluginData['Version'],
|
141 |
+
'Author' => $pluginData['Author'],
|
142 |
+
'Network' => $pluginData['Network'] ? 'True' : 'False',
|
143 |
+
),
|
144 |
+
));
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
// install theme
|
150 |
+
if($action=='install-theme' || $action=='upload-theme'){
|
151 |
+
$newTheme = array_diff(wp_get_themes(), $this->old_themes);
|
152 |
+
if(count($newTheme) != 1)
|
153 |
+
return $this->LogError(
|
154 |
+
'Expected exactly one new theme but found ' . count($newTheme),
|
155 |
+
array('OldThemes' => $this->old_themes, 'NewThemes' => wp_get_themes())
|
156 |
+
);
|
157 |
+
$newTheme = array_shift($newTheme);
|
158 |
+
$this->plugin->alerts->Trigger(5005, array(
|
159 |
+
'NewTheme' => (object)array(
|
160 |
+
'Name' => $newTheme->Name,
|
161 |
+
'ThemeURI' => $newTheme->ThemeURI,
|
162 |
+
'Description' => $newTheme->Description,
|
163 |
+
'Author' => $newTheme->Author,
|
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 |
+
if(!isset($_REQUEST['verify-delete'])){
|
173 |
+
|
174 |
+
// first step, before user approves deletion
|
175 |
+
// TODO store plugin data in session here
|
176 |
+
}else{
|
177 |
+
// second step, after deletion approval
|
178 |
+
// TODO use plugin data from session
|
179 |
+
/*foreach($_REQUEST['checked'] as $themeFile){
|
180 |
+
|
181 |
+
}*/
|
182 |
+
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
public function EventThemeActivated($themeName){
|
188 |
+
$newTheme = null;
|
189 |
+
foreach(wp_get_themes() as $theme){
|
190 |
+
if($theme->Name == $themeName){
|
191 |
+
$newTheme = $theme;
|
192 |
+
break;
|
193 |
+
}
|
194 |
+
}
|
195 |
+
if($newTheme == null)
|
196 |
+
return $this->LogError(
|
197 |
+
'Could not locate theme named "'.$newTheme.'".',
|
198 |
+
array('ThemeName' => $themeName, 'Themes' => wp_get_themes())
|
199 |
+
);
|
200 |
+
$this->plugin->alerts->Trigger(5006, array(
|
201 |
+
'NewTheme' => (object)array(
|
202 |
+
'Name' => $newTheme->Name,
|
203 |
+
'ThemeURI' => $newTheme->ThemeURI,
|
204 |
+
'Description' => $newTheme->Description,
|
205 |
+
'Author' => $newTheme->Author,
|
206 |
+
'Version' => $newTheme->Version,
|
207 |
+
'get_template_directory' => $newTheme->get_template_directory(),
|
208 |
+
),
|
209 |
+
));
|
210 |
+
}
|
211 |
+
|
212 |
+
}
|
classes/Sensors/Request.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_Request extends WSAL_AbstractSensor {
|
4 |
+
public function HookEvents() {
|
5 |
+
if($this->plugin->settings->IsRequestLoggingEnabled()){
|
6 |
+
add_action('shutdown', array($this, 'EventShutdown'));
|
7 |
+
}
|
8 |
+
}
|
9 |
+
|
10 |
+
public function EventShutdown(){
|
11 |
+
$file = $this->plugin->GetBaseDir() . 'Request.log.php';
|
12 |
+
|
13 |
+
$line = '['.date('Y-m-d H:i:s').'] '
|
14 |
+
. $_SERVER['REQUEST_METHOD'] . ' '
|
15 |
+
. $_SERVER['REQUEST_URI'] . ' '
|
16 |
+
. (!empty($_POST) ? str_pad(PHP_EOL, 24) . json_encode($_POST) : '')
|
17 |
+
. (!empty(self::$envvars) ? str_pad(PHP_EOL, 24) . json_encode(self::$envvars) : '')
|
18 |
+
. PHP_EOL;
|
19 |
+
|
20 |
+
if(!file_exists($file))
|
21 |
+
if(!file_put_contents($file, '<'.'?php die(\'Access Denied\');' . PHP_EOL))
|
22 |
+
return $this->LogError('Could not initialize request log file', array('file' => $file));
|
23 |
+
|
24 |
+
$f = fopen($file, 'a');
|
25 |
+
if($f){
|
26 |
+
if(!fwrite($f, $line))
|
27 |
+
$this->LogWarn('Could not write to log file', array('file' => $file));
|
28 |
+
if(!fclose($f))
|
29 |
+
$this->LogWarn('Could not close log file', array('file' => $file));
|
30 |
+
}else $this->LogWarn('Could not open log file', array('file' => $file));
|
31 |
+
}
|
32 |
+
|
33 |
+
protected static $envvars = array();
|
34 |
+
|
35 |
+
public static function SetVar($name, $value){
|
36 |
+
self::$envvars[$name] = $value;
|
37 |
+
}
|
38 |
+
|
39 |
+
public static function SetVars($data){
|
40 |
+
foreach($data as $name => $value)self::SetVar($name, $value);
|
41 |
+
}
|
42 |
+
}
|
classes/Sensors/System.php
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_System extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
public function HookEvents() {
|
6 |
+
add_action('wsal_prune', array($this, 'EventPruneEvents'), 10, 2);
|
7 |
+
add_action('admin_init', array($this, 'EventAdminInit'));
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @param WSAL_DB_Occurrence[] $events The events that were deleted.
|
12 |
+
*/
|
13 |
+
public function EventPruneEvents($events, $query){
|
14 |
+
$this->plugin->alerts->Trigger(6000, array(
|
15 |
+
'EventCount' => count($events),
|
16 |
+
'PruneQuery' => $query,
|
17 |
+
));
|
18 |
+
}
|
19 |
+
|
20 |
+
public function EventAdminInit(){
|
21 |
+
|
22 |
+
// make sure user can actually modify target options
|
23 |
+
if(!current_user_can('manage_options'))return;
|
24 |
+
|
25 |
+
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
|
26 |
+
$actype = basename($_SERVER['SCRIPT_NAME'], '.php');
|
27 |
+
$is_option_page = $actype == 'options';
|
28 |
+
$is_network_settings = $actype == 'settings';
|
29 |
+
$is_permalink_page = $actype == 'options-permalink';
|
30 |
+
|
31 |
+
if($is_option_page && (get_option('users_can_register') xor isset($_POST['users_can_register']))){
|
32 |
+
$old = get_option('users_can_register') ? 'Enabled' : 'Disabled';
|
33 |
+
$new = isset($_POST['users_can_register']) ? 'Enabled' : 'Disabled';
|
34 |
+
if($old !== $new){
|
35 |
+
$this->plugin->alerts->Trigger(6001, array(
|
36 |
+
'OldValue' => $old,
|
37 |
+
'NewValue' => $new,
|
38 |
+
'CurrentUserID' => wp_get_current_user()->ID,
|
39 |
+
));
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
if($is_option_page && !empty($_POST['default_role'])){
|
44 |
+
$old = get_option('default_role');
|
45 |
+
$new = trim($_POST['default_role']);
|
46 |
+
if($old !== $new){
|
47 |
+
$this->plugin->alerts->Trigger(6002, array(
|
48 |
+
'OldRole' => $old,
|
49 |
+
'NewRole' => $new,
|
50 |
+
'CurrentUserID' => wp_get_current_user()->ID,
|
51 |
+
));
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
if($is_option_page && !empty($_POST['admin_email'])){
|
56 |
+
$old = get_option('admin_email');
|
57 |
+
$new = trim($_POST['admin_email']);
|
58 |
+
if($old !== $new){
|
59 |
+
$this->plugin->alerts->Trigger(6003, array(
|
60 |
+
'OldEmail' => $old,
|
61 |
+
'NewEmail' => $new,
|
62 |
+
'CurrentUserID' => wp_get_current_user()->ID,
|
63 |
+
));
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
if($is_network_settings && !empty($_POST['admin_email'])){
|
68 |
+
$old = get_site_option('admin_email');
|
69 |
+
$new = trim($_POST['admin_email']);
|
70 |
+
if($old !== $new){
|
71 |
+
$this->plugin->alerts->Trigger(6003, array(
|
72 |
+
'OldEmail' => $old,
|
73 |
+
'NewEmail' => $new,
|
74 |
+
'CurrentUserID' => wp_get_current_user()->ID,
|
75 |
+
));
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
if($is_permalink_page && !empty($_POST['permalink_structure'])){
|
80 |
+
$old = get_option('permalink_structure');
|
81 |
+
$new = trim($_POST['permalink_structure']);
|
82 |
+
if($old !== $new){
|
83 |
+
$this->plugin->alerts->Trigger(6005, array(
|
84 |
+
'OldPattern' => $old,
|
85 |
+
'NewPattern' => $new,
|
86 |
+
'CurrentUserID' => wp_get_current_user()->ID,
|
87 |
+
));
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
if($action == 'do-core-upgrade' && isset($_REQUEST['version'])){
|
92 |
+
$oldVersion = get_bloginfo('version');
|
93 |
+
$newVersion = $_REQUEST['version'];
|
94 |
+
if($oldVersion !== $newVersion){
|
95 |
+
$this->plugin->alerts->Trigger(6004, array(
|
96 |
+
'OldVersion' => $oldVersion,
|
97 |
+
'NewVersion' => $newVersion,
|
98 |
+
));
|
99 |
+
}
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
}
|
classes/Sensors/UserProfile.php
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
public function HookEvents() {
|
6 |
+
add_action('admin_init', array($this, 'EventAdminInit'));
|
7 |
+
add_action('user_register', array($this, 'EventUserRegister'));
|
8 |
+
add_action('edit_user_profile_update', array($this, 'EventUserChanged'));
|
9 |
+
add_action('personal_options_update', array($this, 'EventUserChanged'));
|
10 |
+
add_action('delete_user', array($this, 'EventUserDeleted'));
|
11 |
+
add_action('wpmu_delete_user', array($this, 'EventUserDeleted'));
|
12 |
+
add_action('set_user_role', array($this, 'EventUserRoleChanged'), 10, 3);
|
13 |
+
}
|
14 |
+
|
15 |
+
protected $old_superadmins;
|
16 |
+
|
17 |
+
protected function IsMultisite(){
|
18 |
+
return function_exists('is_multisite') && is_multisite();
|
19 |
+
}
|
20 |
+
|
21 |
+
public function EventAdminInit(){
|
22 |
+
if($this->IsMultisite()){
|
23 |
+
$this->old_superadmins = get_super_admins();
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
public function EventUserRegister($user_id){
|
28 |
+
$user = get_userdata($user_id);
|
29 |
+
$ismu = function_exists('is_multisite') && is_multisite();
|
30 |
+
$event = $ismu ? 4012 : (is_user_logged_in() ? 4001 : 4000);
|
31 |
+
$this->plugin->alerts->Trigger($event, array(
|
32 |
+
'NewUserID' => $user_id,
|
33 |
+
'NewUserData' => (object)array(
|
34 |
+
'Username' => $user->user_login,
|
35 |
+
'FirstName' => $user->user_firstname,
|
36 |
+
'LastName' => $user->user_lastname,
|
37 |
+
'Email' => $user->user_email,
|
38 |
+
'Roles' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
|
39 |
+
),
|
40 |
+
), true);
|
41 |
+
}
|
42 |
+
|
43 |
+
public function EventUserRoleChanged($user_id, $role, $oldRoles){
|
44 |
+
$user = get_userdata($user_id);
|
45 |
+
|
46 |
+
$oldRole = count($oldRoles) ? implode(', ', $oldRoles) : '';
|
47 |
+
$newRole = $role;
|
48 |
+
if($oldRole != $newRole){
|
49 |
+
$this->plugin->alerts->Trigger(4002, array(
|
50 |
+
'TargetUserID' => $user_id,
|
51 |
+
'TargetUsername' => $user->user_login,
|
52 |
+
'OldRole' => $oldRole,
|
53 |
+
'NewRole' => $newRole,
|
54 |
+
));
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
public function EventUserChanged($user_id){
|
59 |
+
$user = get_userdata($user_id);
|
60 |
+
|
61 |
+
// roles changed
|
62 |
+
/*if(!empty($_REQUEST['role'])){
|
63 |
+
$oldRole = count($user->roles) ? $user->roles[0] : '';
|
64 |
+
$newRole = trim($_REQUEST['role']);
|
65 |
+
if($oldRole != $newRole){
|
66 |
+
$this->plugin->alerts->Trigger(4002, array(
|
67 |
+
'TargetUserID' => $user_id,
|
68 |
+
'TargetUsername' => $user->user_login,
|
69 |
+
'OldRole' => $oldRole,
|
70 |
+
'NewRole' => $newRole,
|
71 |
+
), true);
|
72 |
+
}
|
73 |
+
}*/
|
74 |
+
|
75 |
+
// password changed
|
76 |
+
if(!empty($_REQUEST['pass1'])){
|
77 |
+
$event = $user_id == get_current_user_id() ? 4003 : 4004;
|
78 |
+
$this->plugin->alerts->Trigger($event, array(
|
79 |
+
'TargetUserID' => $user_id,
|
80 |
+
'TargetUserData' => (object)array(
|
81 |
+
'Username' => $user->user_login,
|
82 |
+
'Roles' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
|
83 |
+
),
|
84 |
+
));
|
85 |
+
}
|
86 |
+
|
87 |
+
// email changed
|
88 |
+
if(!empty($_REQUEST['email'])){
|
89 |
+
$oldEmail = $user->user_email;
|
90 |
+
$newEmail = trim($_REQUEST['email']);
|
91 |
+
if($oldEmail != $newEmail){
|
92 |
+
$event = $user_id == get_current_user_id() ? 4005 : 4006;
|
93 |
+
$this->plugin->alerts->Trigger($event, array(
|
94 |
+
'TargetUserID' => $user_id,
|
95 |
+
'TargetUsername' => $user->user_login,
|
96 |
+
'OldEmail' => $oldEmail,
|
97 |
+
'NewEmail' => $newEmail,
|
98 |
+
));
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
if($this->IsMultisite()){
|
103 |
+
$username = $user->user_login;
|
104 |
+
$enabled = isset($_REQUEST['super_admin']);
|
105 |
+
|
106 |
+
if($user_id != get_current_user_id()){
|
107 |
+
|
108 |
+
// super admin enabled
|
109 |
+
if($enabled && !in_array($username, $this->old_superadmins)){
|
110 |
+
$this->plugin->alerts->Trigger(4008, array(
|
111 |
+
'TargetUserID' => $user_id,
|
112 |
+
'TargetUsername' => $user->user_login,
|
113 |
+
));
|
114 |
+
}
|
115 |
+
|
116 |
+
// super admin disabled
|
117 |
+
if(!$enabled && in_array($username, $this->old_superadmins)){
|
118 |
+
$this->plugin->alerts->Trigger(4009, array(
|
119 |
+
'TargetUserID' => $user_id,
|
120 |
+
'TargetUsername' => $user->user_login,
|
121 |
+
));
|
122 |
+
}
|
123 |
+
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
public function EventUserDeleted($user_id){
|
129 |
+
$user = get_userdata($user_id);
|
130 |
+
$role = is_array($user->roles) ? implode(', ', $user->roles) : $user->roles;
|
131 |
+
$this->plugin->alerts->TriggerIf(4007, array(
|
132 |
+
'TargetUserID' => $user_id,
|
133 |
+
'TargetUserData' => (object)array(
|
134 |
+
'Username' => $user->user_login,
|
135 |
+
'FirstName' => $user->user_firstname,
|
136 |
+
'LastName' => $user->user_lastname,
|
137 |
+
'Email' => $user->user_email,
|
138 |
+
'Roles' => $role ? $role : 'none',
|
139 |
+
),
|
140 |
+
), array($this, 'MustNotContainCreateUser'));
|
141 |
+
}
|
142 |
+
|
143 |
+
public function MustNotContainCreateUser(WSAL_AlertManager $mgr){
|
144 |
+
return !$mgr->WillTrigger(4012);
|
145 |
+
}
|
146 |
+
}
|
classes/Sensors/Widgets.php
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
|
4 |
+
|
5 |
+
public function HookEvents() {
|
6 |
+
add_action('widgets_init', array($this, 'EventWidgetMove'));
|
7 |
+
if(is_admin())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(){
|
14 |
+
if(isset($_POST) && !empty($_POST['sidebars']))
|
15 |
+
{
|
16 |
+
$crtSidebars = $_POST['sidebars'];
|
17 |
+
$sidebars = array();
|
18 |
+
foreach ( $crtSidebars as $key => $val )
|
19 |
+
{
|
20 |
+
$sb = array();
|
21 |
+
if ( !empty($val) )
|
22 |
+
{
|
23 |
+
$val = explode(',', $val);
|
24 |
+
foreach ( $val as $k => $v )
|
25 |
+
{
|
26 |
+
if ( strpos($v, 'widget-') === false ) continue;
|
27 |
+
$sb[$k] = substr($v, strpos($v, '_') + 1);
|
28 |
+
}
|
29 |
+
}
|
30 |
+
$sidebars[$key] = $sb;
|
31 |
+
}
|
32 |
+
$crtSidebars = $sidebars;
|
33 |
+
$dbSidebars = get_option('sidebars_widgets');
|
34 |
+
$wName = $fromSidebar = $toSidebar = '';
|
35 |
+
foreach($crtSidebars as $sidebarName => $values)
|
36 |
+
{
|
37 |
+
if(is_array($values) && ! empty($values) && isset($dbSidebars[$sidebarName]))
|
38 |
+
{
|
39 |
+
foreach($values as $widgetName)
|
40 |
+
{
|
41 |
+
if(! in_array($widgetName, $dbSidebars[$sidebarName]))
|
42 |
+
{
|
43 |
+
$toSidebar = $sidebarName;
|
44 |
+
$wName = $widgetName;
|
45 |
+
foreach($dbSidebars as $name => $v)
|
46 |
+
{
|
47 |
+
if(is_array($v) && !empty($v) && in_array($widgetName, $v))
|
48 |
+
{
|
49 |
+
$fromSidebar = $name;
|
50 |
+
break;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
}
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
if (empty($wName) || empty($fromSidebar) || empty($toSidebar)) return;
|
59 |
+
|
60 |
+
if(preg_match('/^sidebar-/', $fromSidebar) || preg_match('/^sidebar-/', $toSidebar)){
|
61 |
+
// This option will hold the data needed to trigger the event 2045
|
62 |
+
// as at this moment the $wp_registered_sidebars variable is not yet populated
|
63 |
+
// so we cannot retrieve the name for sidebar-1 || sidebar-2
|
64 |
+
// we will then check for this variable in the EventWidgetPostMove() event
|
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 |
+
if($this->_WidgetMoveData){
|
79 |
+
$wName = $this->_WidgetMoveData['widget'];
|
80 |
+
$fromSidebar = $this->_WidgetMoveData['from'];
|
81 |
+
$toSidebar = $this->_WidgetMoveData['to'];
|
82 |
+
|
83 |
+
global $wp_registered_sidebars;
|
84 |
+
|
85 |
+
if(preg_match('/^sidebar-/', $fromSidebar))
|
86 |
+
$fromSidebar = isset($wp_registered_sidebars[$fromSidebar])
|
87 |
+
? $wp_registered_sidebars[$fromSidebar]['name']
|
88 |
+
: $fromSidebar
|
89 |
+
;
|
90 |
+
if(preg_match('/^sidebar-/', $toSidebar))
|
91 |
+
$toSidebar = isset($wp_registered_sidebars[$toSidebar])
|
92 |
+
? $wp_registered_sidebars[$toSidebar]['name']
|
93 |
+
: $toSidebar
|
94 |
+
;
|
95 |
+
|
96 |
+
$this->plugin->alerts->Trigger(2045, array(
|
97 |
+
'WidgetName' => $wName,
|
98 |
+
'OldSidebar' => $fromSidebar,
|
99 |
+
'NewSidebar' => $toSidebar,
|
100 |
+
));
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
public function EventWidgetActivity(){
|
105 |
+
if(!isset($_POST) || !isset($_POST['widget-id']) || empty($_POST['widget-id'])){
|
106 |
+
return;
|
107 |
+
}
|
108 |
+
|
109 |
+
$postData = $_POST;
|
110 |
+
global $wp_registered_sidebars;
|
111 |
+
$canCheckSidebar = (empty($wp_registered_sidebars) ? false : true);
|
112 |
+
|
113 |
+
switch(true){
|
114 |
+
|
115 |
+
// added widget
|
116 |
+
case isset($postData['add_new']) && $postData['add_new'] == 'multi':
|
117 |
+
$sidebar = $postData['sidebar'];
|
118 |
+
if($canCheckSidebar && preg_match('/^sidebar-/', $sidebar)){
|
119 |
+
$sidebar = $wp_registered_sidebars[$sidebar]['name'];
|
120 |
+
}
|
121 |
+
$this->plugin->alerts->Trigger(2042, array(
|
122 |
+
'WidgetName' => $postData['id_base'],
|
123 |
+
'Sidebar' => $sidebar,
|
124 |
+
));
|
125 |
+
break;
|
126 |
+
|
127 |
+
// deleted widget
|
128 |
+
case isset($postData['delete_widget']) && intval($postData['delete_widget']) == 1:
|
129 |
+
$sidebar = $postData['sidebar'];
|
130 |
+
if($canCheckSidebar && preg_match('/^sidebar-/',$sidebar)){
|
131 |
+
$sidebar = $wp_registered_sidebars[$sidebar]['name'];
|
132 |
+
}
|
133 |
+
$this->plugin->alerts->Trigger(2044, array(
|
134 |
+
'WidgetName' => $postData['id_base'],
|
135 |
+
'Sidebar' => $sidebar,
|
136 |
+
));
|
137 |
+
break;
|
138 |
+
|
139 |
+
// modified widget
|
140 |
+
case isset($postData['id_base']) && !empty($postData['id_base']):
|
141 |
+
$wId = 0;
|
142 |
+
if(!empty($postData['multi_number'])){
|
143 |
+
$wId = intval($postData['multi_number']);
|
144 |
+
}elseif(!empty($postData['widget_number'])){
|
145 |
+
$wId = intval($postData['widget_number']);
|
146 |
+
}
|
147 |
+
if(empty($wId))return;
|
148 |
+
|
149 |
+
$wName = $postData['id_base'];
|
150 |
+
$sidebar = $postData['sidebar'];
|
151 |
+
$wData = isset($postData["widget-$wName"][$wId])
|
152 |
+
? $postData["widget-$wName"][$wId]
|
153 |
+
: null;
|
154 |
+
|
155 |
+
if(empty($wData))return;
|
156 |
+
|
157 |
+
// get info from db
|
158 |
+
$wdbData = get_option("widget_".$wName);
|
159 |
+
if(empty($wdbData[$wId]))return;
|
160 |
+
|
161 |
+
// transform 'on' -> 1
|
162 |
+
foreach($wData as $k => $v)if($v == 'on')$wData[$k] = 1;
|
163 |
+
|
164 |
+
// compare - checks for any changes inside widgets
|
165 |
+
$diff = array_diff_assoc($wData, $wdbData[$wId]);
|
166 |
+
$count = count($diff);
|
167 |
+
if($count > 0){
|
168 |
+
if($canCheckSidebar && preg_match("/^sidebar-/",$sidebar)){
|
169 |
+
$sidebar = $wp_registered_sidebars[$sidebar]['name'];
|
170 |
+
}
|
171 |
+
$this->plugin->alerts->Trigger(2043, array(
|
172 |
+
'WidgetName' => $wName,
|
173 |
+
'Sidebar' => $sidebar,
|
174 |
+
));
|
175 |
+
}
|
176 |
+
break;
|
177 |
+
|
178 |
+
}
|
179 |
+
}
|
180 |
+
}
|
classes/Settings.php
ADDED
@@ -0,0 +1,366 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Settings {
|
4 |
+
/**
|
5 |
+
* @var WpSecurityAuditLog
|
6 |
+
*/
|
7 |
+
protected $_plugin;
|
8 |
+
|
9 |
+
const OPT_PRFX = 'wsal-';
|
10 |
+
|
11 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
12 |
+
$this->_plugin = $plugin;
|
13 |
+
}
|
14 |
+
|
15 |
+
protected function IsMultisite(){
|
16 |
+
return function_exists('is_multisite') && is_multisite();
|
17 |
+
}
|
18 |
+
|
19 |
+
protected function GetGlobalOption($option, $default = false){
|
20 |
+
$fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
|
21 |
+
return $fn($option, $default);
|
22 |
+
}
|
23 |
+
|
24 |
+
protected function SetGlobalOption($option, $value){
|
25 |
+
$fn = $this->IsMultisite() ? 'update_site_option' : 'update_option';
|
26 |
+
return $fn($option, $value);
|
27 |
+
}
|
28 |
+
|
29 |
+
protected function GetLocalOption($option, $default = false){
|
30 |
+
$result = get_user_option($option, get_current_user_id());
|
31 |
+
return $result === false ? $default : $result;
|
32 |
+
}
|
33 |
+
|
34 |
+
protected function SetLocalOption($option, $value){
|
35 |
+
update_user_option(get_current_user_id(), $option, $value, false);
|
36 |
+
}
|
37 |
+
|
38 |
+
const OPT_DEV_DATA_INSPECTOR = 'd';
|
39 |
+
const OPT_DEV_PHP_ERRORS = 'p';
|
40 |
+
const OPT_DEV_REQUEST_LOG = 'r';
|
41 |
+
const OPT_DEV_SANDBOX_PAGE = 's';
|
42 |
+
|
43 |
+
protected $_devoption = null;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return array Array of developer options to be enabled by default.
|
47 |
+
*/
|
48 |
+
public function GetDefaultDevOptions(){
|
49 |
+
return array();
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Returns whether a developer option is enabled or not.
|
54 |
+
* @param string $option See self::OPT_DEV_* constants.
|
55 |
+
* @return boolean If option is enabled or not.
|
56 |
+
*/
|
57 |
+
public function IsDevOptionEnabled($option){
|
58 |
+
if(is_null($this->_devoption)){
|
59 |
+
$this->_devoption = $this->GetGlobalOption(
|
60 |
+
self::OPT_PRFX . 'dev-options',
|
61 |
+
implode(',', $this->GetDefaultDevOptions())
|
62 |
+
);
|
63 |
+
$this->_devoption = explode(',', $this->_devoption);
|
64 |
+
}
|
65 |
+
return in_array($option, $this->_devoption);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Sets whether a developer option is enabled or not.
|
70 |
+
* @param string $option See self::OPT_DEV_* constants.
|
71 |
+
* @param boolean $enabled If option should be enabled or not.
|
72 |
+
*/
|
73 |
+
public function SetDevOptionEnabled($option, $enabled){
|
74 |
+
// make sure options have been loaded
|
75 |
+
$this->IsDevOptionEnabled('');
|
76 |
+
// remove option if it exists
|
77 |
+
while(($p = array_search($option, $this->_devoption)) !== false)
|
78 |
+
unset($this->_devoption[$p]);
|
79 |
+
// add option if callee wants it enabled
|
80 |
+
if($enabled)
|
81 |
+
$this->_devoption[] = $option;
|
82 |
+
// commit option
|
83 |
+
$this->SetGlobalOption(
|
84 |
+
self::OPT_PRFX . 'dev-options',
|
85 |
+
implode(',', $this->_devoption)
|
86 |
+
);
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Remove all enabled developer options.
|
91 |
+
*/
|
92 |
+
public function ClearDevOptions(){
|
93 |
+
$this->_devoption = array();
|
94 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'dev-options', '');
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* @return boolean Whether to enable data inspector or not.
|
99 |
+
*/
|
100 |
+
public function IsDataInspectorEnabled(){
|
101 |
+
return $this->IsDevOptionEnabled(self::OPT_DEV_DATA_INSPECTOR);
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @return boolean Whether to PHP error logging or not.
|
106 |
+
*/
|
107 |
+
public function IsPhpErrorLoggingEnabled(){
|
108 |
+
return $this->IsDevOptionEnabled(self::OPT_DEV_PHP_ERRORS);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* @return boolean Whether to log requests to file or not.
|
113 |
+
*/
|
114 |
+
public function IsRequestLoggingEnabled(){
|
115 |
+
return $this->IsDevOptionEnabled(self::OPT_DEV_REQUEST_LOG);
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @return boolean Whether PHP sandbox page is enabled or not.
|
120 |
+
*/
|
121 |
+
public function IsSandboxPageEnabled(){
|
122 |
+
return $this->IsDevOptionEnabled(self::OPT_DEV_SANDBOX_PAGE);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* @return boolean Whether dashboard widgets are enabled or not.
|
127 |
+
*/
|
128 |
+
public function IsWidgetsEnabled(){
|
129 |
+
return !$this->GetGlobalOption(self::OPT_PRFX . 'disable-widgets');
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @param boolean $newvalue Whether dashboard widgets are enabled or not.
|
134 |
+
*/
|
135 |
+
public function SetWidgetsEnabled($newvalue){
|
136 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'disable-widgets', !$newvalue);
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* @return boolean Whether alerts in audit log view refresh automatically or not.
|
141 |
+
*/
|
142 |
+
public function IsRefreshAlertsEnabled(){
|
143 |
+
return !$this->GetGlobalOption(self::OPT_PRFX . 'disable-refresh');
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* @param boolean $newvalue Whether alerts in audit log view refresh automatically or not.
|
148 |
+
*/
|
149 |
+
public function SetRefreshAlertsEnabled($newvalue){
|
150 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'disable-refresh', !$newvalue);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* @return int Maximum number of alerts to show in dashboard widget.
|
155 |
+
*/
|
156 |
+
public function GetDashboardWidgetMaxAlerts(){
|
157 |
+
return 5;
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* @return int The maximum number of alerts allowable.
|
162 |
+
*/
|
163 |
+
public function GetMaxAllowedAlerts(){
|
164 |
+
return 5000;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* @return string The default pruning date.
|
169 |
+
*/
|
170 |
+
public function GetDefaultPruningDate(){
|
171 |
+
return '1 month';
|
172 |
+
}
|
173 |
+
|
174 |
+
protected $_pruning = 0;
|
175 |
+
|
176 |
+
/**
|
177 |
+
* @return string The current pruning date.
|
178 |
+
*/
|
179 |
+
public function GetPruningDate(){
|
180 |
+
if(!$this->_pruning){
|
181 |
+
$this->_pruning = $this->GetGlobalOption(self::OPT_PRFX . 'pruning-date');
|
182 |
+
if(!strtotime($this->_pruning))
|
183 |
+
$this->_pruning = $this->GetDefaultPruningDate();
|
184 |
+
}
|
185 |
+
return $this->_pruning;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* @param string $newvalue The new pruning date.
|
190 |
+
*/
|
191 |
+
public function SetPruningDate($newvalue){
|
192 |
+
if(strtotime($newvalue)){
|
193 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'pruning-date', $newvalue);
|
194 |
+
$this->_pruning = $newvalue;
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* @return integer Maximum number of alerts to keep.
|
200 |
+
*/
|
201 |
+
public function GetPruningLimit(){
|
202 |
+
$val = (int)$this->GetGlobalOption(self::OPT_PRFX . 'pruning-limit');
|
203 |
+
return $val ? $val : $this->GetMaxAllowedAlerts();
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
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 |
+
protected $_disabled = null;
|
215 |
+
|
216 |
+
public function GetDefaultDisabledAlerts(){
|
217 |
+
return array(); //array(0000, 0003, 0005);
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* @return array IDs of disabled alerts.
|
222 |
+
*/
|
223 |
+
public function GetDisabledAlerts(){
|
224 |
+
if(!$this->_disabled){
|
225 |
+
$this->_disabled = implode(',', $this->GetDefaultDisabledAlerts());
|
226 |
+
$this->_disabled = $this->GetGlobalOption(self::OPT_PRFX . 'disabled-alerts', $this->_disabled);
|
227 |
+
$this->_disabled = explode(',', $this->_disabled);
|
228 |
+
$this->_disabled = array_map('intval', $this->_disabled);
|
229 |
+
}
|
230 |
+
return $this->_disabled;
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* @param array $types IDs alerts to disable.
|
235 |
+
*/
|
236 |
+
public function SetDisabledAlerts($types){
|
237 |
+
$this->_disabled = array_unique(array_map('intval', $types));
|
238 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'disabled-alerts', implode(',', $this->_disabled));
|
239 |
+
}
|
240 |
+
|
241 |
+
protected $_viewers = null;
|
242 |
+
|
243 |
+
public function SetAllowedPluginViewers($usersOrRoles){
|
244 |
+
$this->_viewers = $usersOrRoles;
|
245 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'plugin-viewers', implode(',', $this->_viewers));
|
246 |
+
}
|
247 |
+
|
248 |
+
public function GetAllowedPluginViewers(){
|
249 |
+
if(is_null($this->_viewers)){
|
250 |
+
$this->_viewers = array_unique(array_filter(explode(',', $this->GetGlobalOption(self::OPT_PRFX . 'plugin-viewers'))));
|
251 |
+
}
|
252 |
+
return $this->_viewers;
|
253 |
+
}
|
254 |
+
|
255 |
+
protected $_editors = null;
|
256 |
+
|
257 |
+
public function SetAllowedPluginEditors($usersOrRoles){
|
258 |
+
$this->_editors = $usersOrRoles;
|
259 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'plugin-editors', implode(',', $this->_editors));
|
260 |
+
}
|
261 |
+
|
262 |
+
public function GetAllowedPluginEditors(){
|
263 |
+
if(is_null($this->_editors)){
|
264 |
+
$this->_editors = array_unique(array_filter(explode(',', $this->GetGlobalOption(self::OPT_PRFX . 'plugin-editors'))));
|
265 |
+
}
|
266 |
+
return $this->_editors;
|
267 |
+
}
|
268 |
+
|
269 |
+
protected $_perpage = null;
|
270 |
+
|
271 |
+
public function SetViewPerPage($newvalue){
|
272 |
+
$this->_perpage = max($newvalue, 1);
|
273 |
+
$this->SetGlobalOption(self::OPT_PRFX . 'items-per-page', $this->_perpage);
|
274 |
+
}
|
275 |
+
|
276 |
+
public function GetViewPerPage(){
|
277 |
+
if(is_null($this->_perpage)){
|
278 |
+
$this->_perpage = (int)$this->GetGlobalOption(self::OPT_PRFX . 'items-per-page', 10);
|
279 |
+
}
|
280 |
+
return $this->_perpage;
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* @param string $action Type of action, either 'view' or 'edit'.
|
285 |
+
* @return boolean If user has access or not.
|
286 |
+
*/
|
287 |
+
public function CurrentUserCan($action){
|
288 |
+
return $this->UserCan(wp_get_current_user(), $action);
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* @return string[] List of superadmin usernames.
|
293 |
+
*/
|
294 |
+
protected function GetSuperAdmins(){
|
295 |
+
return $this->IsMultisite() ? get_super_admins() : array();
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* @return string[] List of admin usernames.
|
300 |
+
*/
|
301 |
+
protected function GetAdmins(){
|
302 |
+
if($this->IsMultisite()){
|
303 |
+
// see: https://gist.github.com/1508426/65785a15b8638d43a9905effb59e4d97319ef8f8
|
304 |
+
global $wpdb;
|
305 |
+
$cap = get_current_blog_id();
|
306 |
+
$cap = ($cap < 2) ? 'wp_capabilities' : "wp_{$cap}_capabilities";
|
307 |
+
$sql = "SELECT DISTINCT $wpdb->users.user_login"
|
308 |
+
. " FROM $wpdb->users"
|
309 |
+
. " INNER JOIN $wpdb->usermeta ON ($wpdb->users.ID = $wpdb->usermeta.user_id )"
|
310 |
+
. " WHERE $wpdb->usermeta.meta_key = '$cap'"
|
311 |
+
. " AND CAST($wpdb->usermeta.meta_value AS CHAR) LIKE '%\"administrator\"%'";
|
312 |
+
return $wpdb->get_col($sql);
|
313 |
+
}else{
|
314 |
+
$result = array();
|
315 |
+
$query = 'role=administrator&fields[]=user_login';
|
316 |
+
foreach (get_users($query) as $user) $result[] = $user->user_login;
|
317 |
+
return $result;
|
318 |
+
}
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* @param integer|WP_user $user User object to check.
|
323 |
+
* @param string $action Type of action, either 'view' or 'edit'.
|
324 |
+
* @return boolean If user has access or not.
|
325 |
+
*/
|
326 |
+
public function UserCan($user, $action){
|
327 |
+
if(is_int($user))$user = get_userdata($user);
|
328 |
+
$allowed = array();
|
329 |
+
|
330 |
+
switch($action){
|
331 |
+
case 'view':
|
332 |
+
$allowed = $this->GetAllowedPluginViewers();
|
333 |
+
$allowed = array_merge($allowed, $this->GetAllowedPluginEditors());
|
334 |
+
$allowed = array_merge($allowed, $this->GetSuperAdmins());
|
335 |
+
$allowed = array_merge($allowed, $this->GetAdmins());
|
336 |
+
break;
|
337 |
+
case 'edit':
|
338 |
+
$allowed = $this->GetAllowedPluginEditors();
|
339 |
+
$allowed = array_merge($allowed, $this->IsMultisite() ?
|
340 |
+
$this->GetSuperAdmins() : $this->GetAdmins()
|
341 |
+
);
|
342 |
+
break;
|
343 |
+
default:
|
344 |
+
throw new Exception('Unknown action "'.$action.'".');
|
345 |
+
}
|
346 |
+
|
347 |
+
$check = array_merge(
|
348 |
+
$user->roles,
|
349 |
+
array($user->user_login)
|
350 |
+
);
|
351 |
+
|
352 |
+
if(is_multisite()){
|
353 |
+
$allowed = array_merge($allowed, get_super_admins());
|
354 |
+
}else{
|
355 |
+
$allowed[] = 'administrator';
|
356 |
+
}
|
357 |
+
|
358 |
+
foreach($check as $item){
|
359 |
+
if(in_array($item, $allowed)){
|
360 |
+
return true;
|
361 |
+
}
|
362 |
+
}
|
363 |
+
|
364 |
+
return false;
|
365 |
+
}
|
366 |
+
}
|
classes/ViewManager.php
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_ViewManager {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @var WSAL_AbstractView[]
|
7 |
+
*/
|
8 |
+
public $views = array();
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var WpSecurityAuditLog
|
12 |
+
*/
|
13 |
+
protected $_plugin;
|
14 |
+
|
15 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
16 |
+
$this->_plugin = $plugin;
|
17 |
+
|
18 |
+
// load views
|
19 |
+
foreach(glob(dirname(__FILE__) . '/Views/*.php') as $file){
|
20 |
+
$class = $this->_plugin->GetClassFileClassName($file);
|
21 |
+
$tmp = new $class($this->_plugin);
|
22 |
+
$this->views[] = $tmp;
|
23 |
+
}
|
24 |
+
|
25 |
+
// order views by weight
|
26 |
+
usort($this->views, array($this, 'OrderByWeight'));
|
27 |
+
|
28 |
+
// add menus
|
29 |
+
add_action('admin_menu', array($this, 'AddAdminMenus'));
|
30 |
+
add_action('network_admin_menu', array($this, 'AddAdminMenus'));
|
31 |
+
|
32 |
+
// add plugin shortcut links
|
33 |
+
add_filter('plugin_action_links_' . $plugin->GetBaseName(), array($this, 'AddPluginShortcuts'));
|
34 |
+
|
35 |
+
// render header
|
36 |
+
add_action('admin_enqueue_scripts', array($this, 'RenderViewHeader'));
|
37 |
+
|
38 |
+
// render footer
|
39 |
+
add_action('admin_footer', array($this, 'RenderViewFooter'));
|
40 |
+
}
|
41 |
+
|
42 |
+
public function OrderByWeight(WSAL_AbstractView $a, WSAL_AbstractView $b){
|
43 |
+
$wa = $a->GetWeight();
|
44 |
+
$wb = $b->GetWeight();
|
45 |
+
switch(true){
|
46 |
+
case $wa < $wb:
|
47 |
+
return -1;
|
48 |
+
case $wa > $wb:
|
49 |
+
return 1;
|
50 |
+
default:
|
51 |
+
return 0;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
public function AddAdminMenus(){
|
56 |
+
if($this->_plugin->settings->CurrentUserCan('view') && count($this->views)){
|
57 |
+
// add main menu
|
58 |
+
add_menu_page(
|
59 |
+
'WP Security Audit Log',
|
60 |
+
'Audit Log',
|
61 |
+
'read', // no capability requirement
|
62 |
+
$this->views[0]->GetSafeViewName(),
|
63 |
+
array($this, 'RenderViewBody'),
|
64 |
+
$this->views[0]->GetIcon()
|
65 |
+
);
|
66 |
+
|
67 |
+
// add menu items
|
68 |
+
foreach($this->views as $view){
|
69 |
+
if($view->IsVisible()){
|
70 |
+
add_submenu_page(
|
71 |
+
$this->views[0]->GetSafeViewName(),
|
72 |
+
$view->GetTitle(),
|
73 |
+
$view->GetName(),
|
74 |
+
'read', // no capability requirement
|
75 |
+
$view->GetSafeViewName(),
|
76 |
+
array($this, 'RenderViewBody'),
|
77 |
+
$view->GetIcon()
|
78 |
+
);
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
public function AddPluginShortcuts($old_links){
|
85 |
+
$new_links = array();
|
86 |
+
foreach($this->views as $view){
|
87 |
+
if($view->HasPluginShortcutLink()){
|
88 |
+
$new_links[] =
|
89 |
+
'<a href="'
|
90 |
+
. admin_url('admin.php?page='
|
91 |
+
. $view->GetSafeViewName()
|
92 |
+
) . '">'
|
93 |
+
. $view->GetName()
|
94 |
+
. '</a>';
|
95 |
+
}
|
96 |
+
}
|
97 |
+
return array_merge($new_links, $old_links);
|
98 |
+
}
|
99 |
+
|
100 |
+
protected function GetBackendPageIndex(){
|
101 |
+
if(isset($_REQUEST['page']))
|
102 |
+
foreach($this->views as $i => $view)
|
103 |
+
if($_REQUEST['page'] == $view->GetSafeViewName())
|
104 |
+
return $i;
|
105 |
+
return 0;
|
106 |
+
}
|
107 |
+
|
108 |
+
public function RenderViewHeader(){
|
109 |
+
$view_id = $this->GetBackendPageIndex();
|
110 |
+
$this->views[$view_id]->Header();
|
111 |
+
}
|
112 |
+
|
113 |
+
public function RenderViewFooter(){
|
114 |
+
$view_id = $this->GetBackendPageIndex();
|
115 |
+
$this->views[$view_id]->Footer();
|
116 |
+
}
|
117 |
+
|
118 |
+
public function RenderViewBody(){
|
119 |
+
$view_id = $this->GetBackendPageIndex();
|
120 |
+
?><div class="wrap">
|
121 |
+
<div id="icon-plugins" class="icon32"><br></div>
|
122 |
+
<h2><?php _e($this->views[$view_id]->GetTitle()); ?></h2>
|
123 |
+
<?php $this->views[$view_id]->Render(); ?>
|
124 |
+
</div><?php
|
125 |
+
}
|
126 |
+
|
127 |
+
}
|
classes/Views/About.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Views_About extends WSAL_AbstractView {
|
4 |
+
|
5 |
+
public function GetTitle() {
|
6 |
+
return 'About WP Security Audit Log';
|
7 |
+
}
|
8 |
+
|
9 |
+
public function GetIcon() {
|
10 |
+
return 'dashicons-editor-help';
|
11 |
+
}
|
12 |
+
|
13 |
+
public function GetName() {
|
14 |
+
return 'About';
|
15 |
+
}
|
16 |
+
|
17 |
+
public function GetWeight(){
|
18 |
+
return 4;
|
19 |
+
}
|
20 |
+
|
21 |
+
public function Render(){
|
22 |
+
?><div class="metabox-holder" style="position: relative;">
|
23 |
+
|
24 |
+
<div class="postbox" style="margin-right: 270px;">
|
25 |
+
<!--h3 class="hndl"><span>About WP Security Audit Log</span></h3-->
|
26 |
+
<div class="inside">
|
27 |
+
<div class="activity-block">
|
28 |
+
WP Security Audit Log enables WordPress administrators and owners to identify WordPress security issues before they become a security problem by keeping a security audit log. WP Security Audit Log is developed by WordPress security professionals WP White Security.
|
29 |
+
|
30 |
+
<h2>Keep A WordPress Security Audit Log & Identify WordPress Security Issues</h2>
|
31 |
+
<p>
|
32 |
+
WP Security Audit Log logs everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A WordPress security alert is generated by the plugin when:
|
33 |
+
</p>
|
34 |
+
<ul style="list-style-type: disc; margin-left: 2.5em; list-style-position: outside;">
|
35 |
+
<li>User creates a new user or a new user is registered</li>
|
36 |
+
<li>Existing user changes the role, password or other properties of another user</li>
|
37 |
+
<li>Existing user on a WordPress multisite network is added to a site</li>
|
38 |
+
<li>User uploads or deletes a file, changes a password or email address</li>
|
39 |
+
<li>User installs, activates, deactivates, upgrades or uninstalls a plugin</li>
|
40 |
+
<li>User creates, modifies or deletes a new post, page, category or a custom post type</li>
|
41 |
+
<li>User installs or activates a WordPress theme</li>
|
42 |
+
<li>User adds, modifies or deletes a widget</li>
|
43 |
+
<li>User uses the dashboard file editor</li>
|
44 |
+
<li>WordPress settings are changed</li>
|
45 |
+
<li>Failed login attempts</li>
|
46 |
+
<li>and much more…</li>
|
47 |
+
</ul>
|
48 |
+
<br/>
|
49 |
+
Refer to the complete list of <a href="http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-alerts-logs/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">WordPress Security Alerts</a> for more information.
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
+
|
54 |
+
<div style="position: absolute; right: 70px; width: 180px; top: 10px;">
|
55 |
+
<div class="postbox">
|
56 |
+
<h3 class="hndl"><span>WP Password Policy Manager</span></h3>
|
57 |
+
<div class="inside">
|
58 |
+
<p>
|
59 |
+
Easily configure WordPress password policies and ensure users use strong passwords with our plugin WP Password Policy Manager.
|
60 |
+
</p>
|
61 |
+
<a class="button button-primary" href="http://wordpress.org/plugins/wp-password-policy-manager/" target="_blank">Download</a>
|
62 |
+
</div>
|
63 |
+
</div>
|
64 |
+
<div class="postbox">
|
65 |
+
<h3 class="hndl"><span>WP Security Audit Log in your Language!</span></h3>
|
66 |
+
<div class="inside">
|
67 |
+
If you are interested in translating our plugin please drop us an email on
|
68 |
+
<a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
|
69 |
+
</div>
|
70 |
+
</div>
|
71 |
+
<div class="postbox">
|
72 |
+
<h3 class="hndl"><span>WordPress Security Services</span></h3>
|
73 |
+
<div class="inside">
|
74 |
+
Professional WordPress security services provided by WP White Security
|
75 |
+
<ul>
|
76 |
+
<li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-hardening/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Hardening</a></li>
|
77 |
+
<li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-audit/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Audit</a></li>
|
78 |
+
<li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-hacker-attack-malware-virus-removal-services/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Hack Cleanup</a></li>
|
79 |
+
<li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-plugins-security-code-audit-review/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Plugin Security Code Audit</a></li>
|
80 |
+
</ul>
|
81 |
+
</div>
|
82 |
+
</div>
|
83 |
+
</div>
|
84 |
+
</div><?php
|
85 |
+
}
|
86 |
+
|
87 |
+
}
|
classes/Views/AuditLog.php
ADDED
@@ -0,0 +1,390 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
4 |
+
|
5 |
+
protected $_listview;
|
6 |
+
|
7 |
+
public function __construct(WpSecurityAuditLog $plugin) {
|
8 |
+
parent::__construct($plugin);
|
9 |
+
$this->_listview = new WSAL_Views_AuditLogList_Internal($plugin);
|
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(){
|
16 |
+
return true;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function GetTitle() {
|
20 |
+
return 'Audit Log Viewer';
|
21 |
+
}
|
22 |
+
|
23 |
+
public function GetIcon() {
|
24 |
+
return $this->_wpversion < 3.8
|
25 |
+
? $this->_plugin->GetBaseUrl() . '/img/logo-main-menu.png'
|
26 |
+
: 'dashicons-welcome-view-site';
|
27 |
+
}
|
28 |
+
|
29 |
+
public function GetName() {
|
30 |
+
return 'Audit Log Viewer';
|
31 |
+
}
|
32 |
+
|
33 |
+
public function GetWeight(){
|
34 |
+
return 1;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function Render(){
|
38 |
+
if(!$this->_plugin->settings->CurrentUserCan('view')){
|
39 |
+
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
40 |
+
}
|
41 |
+
|
42 |
+
?><form id="audit-log-viewer" method="post">
|
43 |
+
<input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
|
44 |
+
<input type="hidden" id="wsal-cbid" name="wsal-cbid" value="<?php echo esc_attr(isset($_REQUEST['wsal-cbid']) ? $_REQUEST['wsal-cbid'] : ''); ?>" />
|
45 |
+
<?php $this->_listview->prepare_items(); ?>
|
46 |
+
<?php $this->_listview->display(); ?>
|
47 |
+
</form><?php
|
48 |
+
|
49 |
+
?><script type="text/javascript">
|
50 |
+
jQuery(document).ready(function(){
|
51 |
+
WsalAuditLogInit(<?php echo json_encode(array(
|
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:'),
|
55 |
+
),
|
56 |
+
'autorefresh' => array(
|
57 |
+
'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
|
58 |
+
'token' => (int)WSAL_DB_Occurrence::Count(),
|
59 |
+
),
|
60 |
+
)); ?>);
|
61 |
+
});
|
62 |
+
</script><?php
|
63 |
+
}
|
64 |
+
|
65 |
+
public function AjaxInspector(){
|
66 |
+
if(!$this->_plugin->settings->CurrentUserCan('view'))
|
67 |
+
die('Access Denied.');
|
68 |
+
if(!isset($_REQUEST['occurrence']))
|
69 |
+
die('Occurrence parameter expected.');
|
70 |
+
$occ = new WSAL_DB_Occurrence();
|
71 |
+
$occ->Load('id = %d', array((int)$_REQUEST['occurrence']));
|
72 |
+
|
73 |
+
echo '<!DOCTYPE html><html><head>';
|
74 |
+
echo '<link rel="stylesheet" id="open-sans-css" href="' . $this->_plugin->GetBaseUrl() . '/css/nice_r.css" type="text/css" media="all">';
|
75 |
+
echo '<script type="text/javascript" src="'.$this->_plugin->GetBaseUrl() . '/js/nice_r.js"></script>';
|
76 |
+
echo '<style type="text/css">';
|
77 |
+
echo 'html, body { margin: 0; padding: 0; }';
|
78 |
+
echo '.nice_r { position: absolute; padding: 8px; }';
|
79 |
+
echo '.nice_r a { overflow: visible; }';
|
80 |
+
echo '</style>';
|
81 |
+
echo '</head><body>';
|
82 |
+
$nicer = new WSAL_Nicer($occ->GetMetaArray());
|
83 |
+
$nicer->render();
|
84 |
+
echo '</body></html>';
|
85 |
+
die;
|
86 |
+
}
|
87 |
+
|
88 |
+
public function AjaxRefresh(){
|
89 |
+
if(!$this->_plugin->settings->CurrentUserCan('view'))
|
90 |
+
die('Access Denied.');
|
91 |
+
if(!isset($_REQUEST['logcount']))
|
92 |
+
die('Log count parameter expected.');
|
93 |
+
|
94 |
+
$old = (int)$_REQUEST['logcount'];
|
95 |
+
$max = 40; // 40*500msec = 20sec
|
96 |
+
|
97 |
+
do{
|
98 |
+
$new = WSAL_DB_Occurrence::Count();
|
99 |
+
usleep(500000); // 500msec
|
100 |
+
}while(($old == $new) && (--$max > 0));
|
101 |
+
|
102 |
+
echo $old == $new ? 'false' : $new;
|
103 |
+
die;
|
104 |
+
}
|
105 |
+
|
106 |
+
public function AjaxSetIpp(){
|
107 |
+
if(!$this->_plugin->settings->CurrentUserCan('view'))
|
108 |
+
die('Access Denied.');
|
109 |
+
if(!isset($_REQUEST['count']))
|
110 |
+
die('Count parameter expected.');
|
111 |
+
$this->_plugin->settings->SetViewPerPage((int)$_REQUEST['count']);
|
112 |
+
die;
|
113 |
+
}
|
114 |
+
|
115 |
+
public function Header(){
|
116 |
+
add_thickbox();
|
117 |
+
wp_enqueue_style(
|
118 |
+
'auditlog',
|
119 |
+
$this->_plugin->GetBaseUrl() . '/css/auditlog.css',
|
120 |
+
array(),
|
121 |
+
filemtime($this->_plugin->GetBaseDir() . '/css/auditlog.css')
|
122 |
+
);
|
123 |
+
}
|
124 |
+
|
125 |
+
public function Footer() {
|
126 |
+
wp_enqueue_script(
|
127 |
+
'auditlog',
|
128 |
+
$this->_plugin->GetBaseUrl() . '/js/auditlog.js',
|
129 |
+
array(),
|
130 |
+
filemtime($this->_plugin->GetBaseDir() . '/js/auditlog.js')
|
131 |
+
);
|
132 |
+
}
|
133 |
+
|
134 |
+
}
|
135 |
+
|
136 |
+
require_once(ABSPATH . 'wp-admin/includes/admin.php');
|
137 |
+
require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
|
138 |
+
|
139 |
+
class WSAL_Views_AuditLogList_Internal extends WP_List_Table {
|
140 |
+
|
141 |
+
/**
|
142 |
+
* @var WpSecurityAuditLog
|
143 |
+
*/
|
144 |
+
protected $_plugin;
|
145 |
+
|
146 |
+
public function __construct($plugin){
|
147 |
+
$this->_plugin = $plugin;
|
148 |
+
|
149 |
+
parent::__construct(array(
|
150 |
+
'singular' => 'log',
|
151 |
+
'plural' => 'logs',
|
152 |
+
'ajax' => true,
|
153 |
+
'screen' => 'interval-list',
|
154 |
+
));
|
155 |
+
}
|
156 |
+
|
157 |
+
public function no_items(){
|
158 |
+
_e('No events so far.');
|
159 |
+
}
|
160 |
+
|
161 |
+
public function extra_tablenav($which){
|
162 |
+
// items-per-page widget
|
163 |
+
$o = __('Other');
|
164 |
+
$p = $this->_plugin->settings->GetViewPerPage();
|
165 |
+
$items = array($o, 5, 10, 15, 30, 50);
|
166 |
+
if (!in_array($p, $items)) $items[] = $p;
|
167 |
+
if ($p == $o || $p == 0) $p = $o[1]; // a sane default if things goes bust
|
168 |
+
|
169 |
+
?><div class="wsal-ipp wsal-ipp-<?php echo $which; ?>">
|
170 |
+
<?php _e('Show '); ?>
|
171 |
+
<select class="wsal-ipps" onfocus="WsalIppsFocus(value);" onchange="WsalIppsChange(value);">
|
172 |
+
<?php foreach($items as $item){ ?>
|
173 |
+
<option
|
174 |
+
value="<?php echo is_string($item) ? '' : $item; ?>"
|
175 |
+
<?php if($item == $p)echo 'selected="selected"'; ?>><?php
|
176 |
+
echo $item;
|
177 |
+
?></option>
|
178 |
+
<?php } ?>
|
179 |
+
</select>
|
180 |
+
<?php _e(' Items'); ?>
|
181 |
+
</div><?php
|
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 |
+
<select class="wsal-ssas" onchange="WsalSsasChange(value);">
|
190 |
+
<option value="0"><?php _e('All Sites'); ?></option>
|
191 |
+
<?php foreach($sites as $site){ ?>
|
192 |
+
<?php $info = get_blog_details($site['blog_id'], true); ?>
|
193 |
+
<option
|
194 |
+
value="<?php echo $info->blog_id; ?>"
|
195 |
+
<?php if($info->blog_id == $curr)echo 'selected="selected"'; ?>><?php
|
196 |
+
echo esc_html($info->blogname) . ' (' . esc_html($info->domain) . ')';
|
197 |
+
?></option>
|
198 |
+
<?php } ?>
|
199 |
+
</select>
|
200 |
+
</div><?php
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
public function get_columns(){
|
205 |
+
$cols = array(
|
206 |
+
//'cb' => '<input type="checkbox" />',
|
207 |
+
//'read' => 'Read',
|
208 |
+
'type' => 'Code',
|
209 |
+
'code' => 'Type',
|
210 |
+
'crtd' => 'Date',
|
211 |
+
'user' => 'Username',
|
212 |
+
'scip' => 'Source IP',
|
213 |
+
);
|
214 |
+
if($this->is_multisite() && $this->is_main_blog() && !$this->is_specific_view()){
|
215 |
+
$cols['site'] = 'Site';
|
216 |
+
}
|
217 |
+
$cols['mesg'] = 'Message';
|
218 |
+
if($this->_plugin->settings->IsDataInspectorEnabled()){
|
219 |
+
$cols['data'] = '';
|
220 |
+
}
|
221 |
+
return $cols;
|
222 |
+
}
|
223 |
+
|
224 |
+
public function column_cb(WSAL_DB_Occurrence $item){
|
225 |
+
return '<input type="checkbox" value="'.$item->id.'" '
|
226 |
+
. 'name="'.esc_attr($this->_args['singular']).'[]"/>';
|
227 |
+
}
|
228 |
+
|
229 |
+
public function get_sortable_columns(){
|
230 |
+
return array(
|
231 |
+
'read' => array('is_read', false),
|
232 |
+
'code' => array('code', false),
|
233 |
+
'type' => array('alert_id', false),
|
234 |
+
'crtd' => array('created_on', true),
|
235 |
+
'user' => array('user', false),
|
236 |
+
'scip' => array('scip', false),
|
237 |
+
'site' => array('site', false),
|
238 |
+
);
|
239 |
+
}
|
240 |
+
|
241 |
+
public function column_default(WSAL_DB_Occurrence $item, $column_name){
|
242 |
+
switch($column_name){
|
243 |
+
case 'read':
|
244 |
+
return '<span class="log-read log-read-'
|
245 |
+
. ($item->is_read ? 'old' : 'new')
|
246 |
+
. '" title="Click to toggle."></span>';
|
247 |
+
case 'type':
|
248 |
+
return str_pad($item->alert_id, 4, '0', STR_PAD_LEFT);
|
249 |
+
case 'code':
|
250 |
+
$code = $this->_plugin->alerts->GetAlert($item->alert_id);
|
251 |
+
$code = $code ? $code->code : 0;
|
252 |
+
$const = (object)array('name' => 'E_UNKNOWN', 'value' => 0, 'description' => 'Unknown error code.');
|
253 |
+
$const = $this->_plugin->constants->GetConstantBy('value', $code, $const);
|
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 ? date('Y-m-d h:i:s A', $item->created_on) : '<i>unknown</i>';
|
258 |
+
case 'user':
|
259 |
+
$user = $item->GetUsername();
|
260 |
+
$usid = get_userdatabylogin($user ? $user : 0);
|
261 |
+
$usid = $usid ? $usid->ID : 0;
|
262 |
+
$uimg = get_avatar($usid, 96);
|
263 |
+
return !is_null($user) ? esc_html($user) : '<i>unknown</i>';
|
264 |
+
case 'scip':
|
265 |
+
return !is_null($item->GetSourceIP()) ? esc_html($item->GetSourceIP()) : '<i>unknown</i>';
|
266 |
+
case 'site':
|
267 |
+
$info = get_blog_details($item->site_id, true);
|
268 |
+
return !$info ? ('Unknown Site '.$item->site_id)
|
269 |
+
: ('<a href="' . esc_attr($info->siteurl) . '">' . esc_html($info->blogname) . '</a>');
|
270 |
+
case 'mesg':
|
271 |
+
return '<div id="Event' . $item->id . '">' . $item->GetMessage(array($this, 'meta_formatter')) . '</div>';
|
272 |
+
case 'data':
|
273 |
+
$url = admin_url('admin-ajax.php') . '?action=AjaxInspector&occurrence=' . $item->id;
|
274 |
+
return '<a class="more-info thickbox" title="Alert Data Inspector"'
|
275 |
+
. ' href="' . $url . '&TB_iframe=true&width=600&height=550">…</a>';
|
276 |
+
default:
|
277 |
+
return isset($item->$column_name)
|
278 |
+
? esc_html($item->$column_name)
|
279 |
+
: 'Column "' . esc_html($column_name) . '" not found';
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
public function reorder_items_str($a, $b){
|
284 |
+
$result = strcmp($a->{$this->_orderby}, $b->{$this->_orderby});
|
285 |
+
return ($this->_order === 'asc') ? $result : -$result;
|
286 |
+
}
|
287 |
+
|
288 |
+
public function reorder_items_int($a, $b){
|
289 |
+
$result = $a->{$this->_orderby} - $b->{$this->_orderby};
|
290 |
+
return ($this->_order === 'asc') ? $result : -$result;
|
291 |
+
}
|
292 |
+
|
293 |
+
public function meta_formatter($name, $value){
|
294 |
+
switch(true){
|
295 |
+
|
296 |
+
case $name == '%Message%':
|
297 |
+
return esc_html($value);
|
298 |
+
|
299 |
+
case strncmp($value, 'http://', 7) === 0:
|
300 |
+
case strncmp($value, 'https://', 7) === 0:
|
301 |
+
return '<a href="' . esc_html($value) . '"'
|
302 |
+
. ' title="' . esc_html($value) . '"'
|
303 |
+
. ' target="_blank">'
|
304 |
+
. esc_html(parse_url($value, PHP_URL_HOST)) . '/…/'
|
305 |
+
. esc_html(basename(parse_url($value, PHP_URL_PATH)))
|
306 |
+
. '</a>';
|
307 |
+
|
308 |
+
default:
|
309 |
+
return '<strong>' . esc_html($value) . '</strong>';
|
310 |
+
}
|
311 |
+
}
|
312 |
+
|
313 |
+
protected function is_multisite(){
|
314 |
+
return function_exists('is_multisite') && is_multisite();
|
315 |
+
}
|
316 |
+
|
317 |
+
protected function is_main_blog(){
|
318 |
+
return get_current_blog_id() == 1;
|
319 |
+
}
|
320 |
+
|
321 |
+
protected function is_specific_view(){
|
322 |
+
return isset($_REQUEST['wsal-cbid']) && $_REQUEST['wsal-cbid'] != '0';
|
323 |
+
}
|
324 |
+
|
325 |
+
protected function get_specific_view(){
|
326 |
+
return isset($_REQUEST['wsal-cbid']) ? (int)$_REQUEST['wsal-cbid'] : 0;
|
327 |
+
}
|
328 |
+
|
329 |
+
protected function get_view_site_id(){
|
330 |
+
switch(true){
|
331 |
+
|
332 |
+
// non-multisite
|
333 |
+
case !function_exists('is_multisite') || !is_multisite():
|
334 |
+
return 0;
|
335 |
+
|
336 |
+
// multisite + main site view
|
337 |
+
case $this->is_main_blog() && !$this->is_specific_view():
|
338 |
+
return 0;
|
339 |
+
|
340 |
+
// multisite + switched site view
|
341 |
+
case $this->is_main_blog() && $this->is_specific_view():
|
342 |
+
return $this->get_specific_view();
|
343 |
+
|
344 |
+
// multisite + local site view
|
345 |
+
default:
|
346 |
+
return get_current_blog_id();
|
347 |
+
|
348 |
+
}
|
349 |
+
}
|
350 |
+
|
351 |
+
public function prepare_items() {
|
352 |
+
$per_page = $this->_plugin->settings->GetViewPerPage();
|
353 |
+
|
354 |
+
$columns = $this->get_columns();
|
355 |
+
$hidden = array();
|
356 |
+
$sortable = $this->get_sortable_columns();
|
357 |
+
|
358 |
+
$this->_column_headers = array($columns, $hidden, $sortable);
|
359 |
+
|
360 |
+
//$this->process_bulk_action();
|
361 |
+
|
362 |
+
$bid = (int)$this->get_view_site_id();
|
363 |
+
$sql = ($bid ? "site_id=$bid" : '1') . ' ORDER BY created_on DESC';
|
364 |
+
$data = WSAL_DB_Occurrence::LoadMulti($sql);
|
365 |
+
|
366 |
+
if(count($data)){
|
367 |
+
$this->_orderby = (!empty($_REQUEST['orderby']) && isset($sortable[$_REQUEST['orderby']])) ? $_REQUEST['orderby'] : 'created_on';
|
368 |
+
$this->_order = (!empty($_REQUEST['order']) && $_REQUEST['order']=='asc') ? 'asc' : 'desc';
|
369 |
+
if(isset($data[0]->{$this->_orderby})){
|
370 |
+
$numorder = in_array($this->_orderby, array('code', 'type', 'created_on'));
|
371 |
+
usort($data, array($this, $numorder ? 'reorder_items_int' : 'reorder_items_str'));
|
372 |
+
}
|
373 |
+
}
|
374 |
+
|
375 |
+
$current_page = $this->get_pagenum();
|
376 |
+
|
377 |
+
$total_items = count($data);
|
378 |
+
|
379 |
+
$data = array_slice($data, ($current_page - 1) * $per_page, $per_page);
|
380 |
+
|
381 |
+
$this->items = $data;
|
382 |
+
|
383 |
+
$this->set_pagination_args( array(
|
384 |
+
'total_items' => $total_items,
|
385 |
+
'per_page' => $per_page,
|
386 |
+
'total_pages' => ceil($total_items / $per_page)
|
387 |
+
) );
|
388 |
+
}
|
389 |
+
|
390 |
+
}
|
classes/Views/Help.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Views_Help extends WSAL_AbstractView {
|
4 |
+
|
5 |
+
public function GetTitle() {
|
6 |
+
return 'Help';
|
7 |
+
}
|
8 |
+
|
9 |
+
public function GetIcon() {
|
10 |
+
return 'dashicons-sos';
|
11 |
+
}
|
12 |
+
|
13 |
+
public function GetName() {
|
14 |
+
return 'Help';
|
15 |
+
}
|
16 |
+
|
17 |
+
public function GetWeight() {
|
18 |
+
return 5;
|
19 |
+
}
|
20 |
+
|
21 |
+
public function Render(){
|
22 |
+
?><div class="metabox-holder" style="position: relative;">
|
23 |
+
|
24 |
+
<div class="postbox" style="margin-right: 270px;">
|
25 |
+
<h3 class="hndl"><span>Help</span></h3>
|
26 |
+
<div class="inside">
|
27 |
+
<div class="activity-block">
|
28 |
+
<h2>Plugin Support</h2>
|
29 |
+
<p>
|
30 |
+
Have you encountered or noticed any issues while using WP Security Audit Log plugin?
|
31 |
+
Or you want to report something to us? Click any of the options below to post on the plugin's forum or contact our support directly.
|
32 |
+
</p><p>
|
33 |
+
<a class="button" href="http://wordpress.org/support/plugin/wp-security-audit-log" target="_blank">Free Support Forum</a>
|
34 |
+
|
35 |
+
<a class="button" href="mailto:plugins@wpwhitesecurity.com" target="_blank">Free Support Email</a>
|
36 |
+
</p>
|
37 |
+
</div>
|
38 |
+
|
39 |
+
<div class="activity-block">
|
40 |
+
<h2>Plugin Documentation</h2>
|
41 |
+
<p>
|
42 |
+
For more detailed information about WP Security Audit Log you can visit the official plugin page.
|
43 |
+
You can also visit the official list of WordPress Security Alerts for more information about all of the activity you can monitor with WP Security Audit Log.
|
44 |
+
</p><p>
|
45 |
+
<a class="button" href="http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Official Plugin Page</a>
|
46 |
+
|
47 |
+
<a class="button" href="http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-alerts-logs/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">List of WordPress Security Alerts</a>
|
48 |
+
</p>
|
49 |
+
</div>
|
50 |
+
|
51 |
+
<div class="activity-block">
|
52 |
+
<h2>Need Help Securing WordPress?</h2>
|
53 |
+
<p>
|
54 |
+
Is your WordPress website hackable?
|
55 |
+
If you are not sure contact our WordPress security professionals to audit your WordPress or to simply secure your WordPress website.
|
56 |
+
Click on any of the below service buttons for more information.
|
57 |
+
</p><p>
|
58 |
+
<a class="button" href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-hardening/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">WordPress Security Hardening</a>
|
59 |
+
|
60 |
+
<a class="button" href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-audit/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">WordPress Security Audit</a>
|
61 |
+
</p>
|
62 |
+
</div>
|
63 |
+
|
64 |
+
<div class="">
|
65 |
+
<h2>WordPress Security Readings</h2>
|
66 |
+
<p>
|
67 |
+
New to WordPress security?
|
68 |
+
Do not know from where to start or which is the best services for you?
|
69 |
+
Visit our WordPress security blog or the WordPress Security category directly for more information and a number of tips and tricks about WordPress security.
|
70 |
+
</p>
|
71 |
+
<a class="button" href="http://www.wpwhitesecurity.com/blog/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">WP White Security Blog</a>
|
72 |
+
|
73 |
+
<a class="button" href="http://www.wpwhitesecurity.com/wordpress-security/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">WordPress Security Category</a>
|
74 |
+
</div>
|
75 |
+
</div>
|
76 |
+
</div>
|
77 |
+
|
78 |
+
<div style="position: absolute; right: 70px; width: 180px; top: 10px;">
|
79 |
+
<div class="postbox">
|
80 |
+
<h3 class="hndl"><span>WP Password Policy Manager</span></h3>
|
81 |
+
<div class="inside">
|
82 |
+
<p>
|
83 |
+
Easily configure WordPress password policies and ensure users use strong passwords with our plugin WP Password Policy Manager.
|
84 |
+
</p>
|
85 |
+
<a class="button button-primary" href="http://wordpress.org/plugins/wp-password-policy-manager/" target="_blank">Download</a>
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
+
<div class="postbox">
|
89 |
+
<h3 class="hndl"><span>WP Security Audit Log in your Language!</span></h3>
|
90 |
+
<div class="inside">
|
91 |
+
If you are interested in translating our plugin please drop us an email on
|
92 |
+
<a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
|
93 |
+
</div>
|
94 |
+
</div>
|
95 |
+
</div>
|
96 |
+
|
97 |
+
</div><?php
|
98 |
+
}
|
99 |
+
|
100 |
+
}
|
classes/Views/Sandbox.php
ADDED
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Views_Sandbox extends WSAL_AbstractView {
|
4 |
+
|
5 |
+
public function __construct(WpSecurityAuditLog $plugin) {
|
6 |
+
parent::__construct($plugin);
|
7 |
+
if(is_admin())add_action('wp_ajax_AjaxExecute', array($this, 'AjaxExecute'));
|
8 |
+
}
|
9 |
+
|
10 |
+
public function GetTitle() {
|
11 |
+
return 'Sandbox';
|
12 |
+
}
|
13 |
+
|
14 |
+
public function GetIcon() {
|
15 |
+
return 'dashicons-admin-generic';
|
16 |
+
}
|
17 |
+
|
18 |
+
public function GetName() {
|
19 |
+
return 'Sandbox';
|
20 |
+
}
|
21 |
+
|
22 |
+
public function GetWeight() {
|
23 |
+
return 5;
|
24 |
+
}
|
25 |
+
|
26 |
+
public function IsVisible(){
|
27 |
+
return $this->_plugin->settings->CurrentUserCan('edit')
|
28 |
+
&& $this->_plugin->settings->IsSandboxPageEnabled();
|
29 |
+
}
|
30 |
+
|
31 |
+
protected $exec_data = array();
|
32 |
+
protected $exec_info = array();
|
33 |
+
|
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){
|
40 |
+
if(!isset($this->exec_data['Errors']))
|
41 |
+
$this->exec_data['Errors'] = array();
|
42 |
+
$this->exec_data['Errors'] = new ErrorException($message, $code, 0, $filename, $lineno);
|
43 |
+
return true;
|
44 |
+
}
|
45 |
+
|
46 |
+
protected function BeforeExecute(){
|
47 |
+
$this->exec_info['_Time'] = microtime(true);
|
48 |
+
$this->exec_info['_Mem'] = memory_get_usage();
|
49 |
+
}
|
50 |
+
|
51 |
+
protected function AfterExecute(){
|
52 |
+
$this->exec_info['Time'] = microtime(true) - $this->exec_info['_Time'];
|
53 |
+
$this->exec_info['Mem'] = memory_get_usage() - $this->exec_info['_Mem'];
|
54 |
+
if($this->exec_info['Time'] < 0.001){
|
55 |
+
$this->exec_info['Time'] = number_format($this->exec_info['Time'] * 1000, 3) . 'ms';
|
56 |
+
}else{
|
57 |
+
$this->exec_info['Time'] = number_format($this->exec_info['Time'], 3) . 's';
|
58 |
+
}
|
59 |
+
$this->exec_info['Mem'] = size_format($this->exec_info['Mem']);
|
60 |
+
$this->exec_info['Queries'] = get_num_queries();
|
61 |
+
}
|
62 |
+
|
63 |
+
protected function Execute($code){
|
64 |
+
try {
|
65 |
+
error_reporting(-1);
|
66 |
+
ini_set('display_errors', false);
|
67 |
+
if(function_exists('xdebug_disable'))xdebug_disable();
|
68 |
+
|
69 |
+
set_error_handler(array($this, 'HandleError'));
|
70 |
+
|
71 |
+
ob_start();
|
72 |
+
|
73 |
+
$this->BeforeExecute();
|
74 |
+
$this->exec_data['Result'] = eval($code);
|
75 |
+
$this->AfterExecute();
|
76 |
+
|
77 |
+
$this->exec_data['Output'] = ob_get_clean();
|
78 |
+
|
79 |
+
if(!$this->exec_data['Output'])
|
80 |
+
unset($this->exec_data['Output']);
|
81 |
+
|
82 |
+
restore_error_handler();
|
83 |
+
} catch (Exception $ex) {
|
84 |
+
if(!isset($this->exec_data['Errors']))
|
85 |
+
$this->exec_data['Errors'] = array();
|
86 |
+
$this->exec_data['Errors'][] = $ex;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
public function AjaxExecuteResponse(){
|
91 |
+
echo '<!DOCTYPE html><html><head>';
|
92 |
+
echo '<link rel="stylesheet" id="open-sans-css" href="' . $this->_plugin->GetBaseUrl() . '/css/nice_r.css" type="text/css" media="all">';
|
93 |
+
echo '<script type="text/javascript" src="'.$this->_plugin->GetBaseUrl() . '/js/nice_r.js"></script>';
|
94 |
+
echo '<style type="text/css">';
|
95 |
+
echo 'html, body { margin: 0; padding: 0; }';
|
96 |
+
echo '.nice_r { position: absolute; padding: 8px; }';
|
97 |
+
echo '.nice_r a { overflow: visible; }';
|
98 |
+
echo '.faerror { font: 14px Arial; background: #FCC; text-align: center; padding: 32px; }';
|
99 |
+
echo '</style>';
|
100 |
+
echo '</head><body>';
|
101 |
+
|
102 |
+
if(($e = error_get_last()) && !isset($this->exec_data['Errors']) && !count($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 |
+
|
110 |
+
if(count($this->exec_info)){
|
111 |
+
?><script type="text/javascript">
|
112 |
+
window.parent.SandboxUpdateState(<?php
|
113 |
+
$res = array();
|
114 |
+
foreach($this->exec_info as $key => $val)
|
115 |
+
if($key && $key[0] != '_')
|
116 |
+
$res[$key] = $val;
|
117 |
+
echo json_encode($res);
|
118 |
+
?>);
|
119 |
+
</script><?php
|
120 |
+
}
|
121 |
+
|
122 |
+
echo '</body></html>';
|
123 |
+
}
|
124 |
+
|
125 |
+
public function AjaxExecute(){
|
126 |
+
if(!$this->_plugin->settings->IsSandboxPageEnabled())
|
127 |
+
die('Sandbox Disabled.');
|
128 |
+
if(!$this->_plugin->settings->CurrentUserCan('edit'))
|
129 |
+
die('Access Denied.');
|
130 |
+
if(!isset($_REQUEST['code']))
|
131 |
+
die('Code parameter expected.');
|
132 |
+
|
133 |
+
register_shutdown_function(array($this, 'AjaxExecuteResponse'));
|
134 |
+
$this->Execute(stripslashes_deep($_REQUEST['code']));
|
135 |
+
die;
|
136 |
+
}
|
137 |
+
|
138 |
+
public function Render(){
|
139 |
+
$snpt = isset($_REQUEST['snippet']) ? $_REQUEST['snippet'] : '';
|
140 |
+
$code = isset($this->snippets[$snpt]) ? $this->snippets[$snpt] : '';
|
141 |
+
?><form id="sandbox" method="post" target="execframe" action="<?php echo admin_url('admin-ajax.php'); ?>">
|
142 |
+
<input type="hidden" name="action" value="AjaxExecute" />
|
143 |
+
<div id="sandbox-wrap-wrap">
|
144 |
+
<div id="sandbox-wrap">
|
145 |
+
<textarea name="code" id="sandbox-code"><?php echo esc_html($code); ?></textarea>
|
146 |
+
<iframe id="sandbox-result" name="execframe"></iframe>
|
147 |
+
</div>
|
148 |
+
<div id="sandbox-status">Ready.</div>
|
149 |
+
</div>
|
150 |
+
<label for="sandbox-snippet" style="float: left; line-height: 26px; display: inline-block; margin-right: 32px; border-right: 1px dotted #CCC; padding-right: 32px;">
|
151 |
+
Use Snippet:
|
152 |
+
<?php $code = json_encode(admin_url('admin.php?page=wsal-sandbox') . '&snippet='); ?>
|
153 |
+
<select id="sandbox-snippet" onchange="location = <?php echo esc_attr($code); ?> + encodeURIComponent(this.value);"><?php
|
154 |
+
foreach(array_keys($this->snippets) as $name){
|
155 |
+
?><option value="<?php echo esc_attr($name); ?>"<?php if($name == $snpt)echo ' selected="selected"'; ?>><?php _e($name); ?></option><?php
|
156 |
+
}
|
157 |
+
?></select>
|
158 |
+
</label>
|
159 |
+
<input type="submit" name="submit" id="sandbox-submit" class="button button-primary" value="Execute">
|
160 |
+
<img id="sandbox-loader" style="margin: 6px 12px; display: none;" src="http://cdnjs.cloudflare.com/ajax/libs/jstree/3.0.0-beta10/themes/default/throbber.gif" width="16" height="16" alt="Loading..."/>
|
161 |
+
</form><?php
|
162 |
+
}
|
163 |
+
|
164 |
+
public function Header(){
|
165 |
+
?><link rel="stylesheet" href="//cdn.jsdelivr.net/codemirror/4.0.3/codemirror.css">
|
166 |
+
<style type="text/css">
|
167 |
+
#sandbox-wrap-wrap {
|
168 |
+
resize: vertical; height: 400px; overflow: auto; margin: 16px 0; padding-bottom: 16px; position: relative; border: 1px solid #DDD;
|
169 |
+
}
|
170 |
+
#sandbox-wrap {
|
171 |
+
overflow: hidden; height: 100% !important; position: relative; box-sizing: border-box;
|
172 |
+
}
|
173 |
+
#sandbox-wrap textarea,
|
174 |
+
#sandbox-wrap .CodeMirror {
|
175 |
+
resize: none; width: 50%; height: 100%; border-bottom: 1px solid #ddd; font: 12px Consolas; box-sizing: border-box;
|
176 |
+
}
|
177 |
+
#sandbox-wrap iframe {
|
178 |
+
resize: none; width: 50%; height: 100%; border-bottom: 1px solid #ddd; background: #FFF; position: absolute; top: 0; right: 0; box-sizing: border-box; border-left: 4px solid #DDD;
|
179 |
+
}
|
180 |
+
#sandbox-status {
|
181 |
+
font: 10px Tahoma; padding: 2px; position: absolute; left: 0; right: 16px; bottom: 0;
|
182 |
+
}
|
183 |
+
#sandbox-status ul {
|
184 |
+
list-style: none; margin: 0;
|
185 |
+
}
|
186 |
+
#sandbox-status li {
|
187 |
+
float: left; padding-right: 4px; border-right: 1px solid #CCC; margin: 0 4px 0 0;
|
188 |
+
}
|
189 |
+
</style><?php
|
190 |
+
}
|
191 |
+
|
192 |
+
public function Footer(){
|
193 |
+
?><script src="//cdn.jsdelivr.net/codemirror/4.0.3/codemirror.js"></script>
|
194 |
+
<script src="//cdn.jsdelivr.net/codemirror/4.0.3/addon/edit/matchbrackets.js"></script>
|
195 |
+
<script src="//cdn.jsdelivr.net/codemirror/4.0.3/mode/clike/clike.js"></script>
|
196 |
+
<script src="//cdn.jsdelivr.net/codemirror/4.0.3/mode/php/php.js"></script>
|
197 |
+
<script type="text/javascript">
|
198 |
+
jQuery(document).ready(function(){
|
199 |
+
var ed = CodeMirror.fromTextArea(
|
200 |
+
jQuery('#sandbox-code')[0],
|
201 |
+
{
|
202 |
+
lineNumbers: true,
|
203 |
+
matchBrackets: true,
|
204 |
+
mode: "text/x-php",
|
205 |
+
indentUnit: 4,
|
206 |
+
indentWithTabs: true
|
207 |
+
}
|
208 |
+
);
|
209 |
+
|
210 |
+
jQuery('#sandbox').submit(function(){
|
211 |
+
if(!ed.isClean())jQuery('#sandbox-snippet').val('');
|
212 |
+
jQuery('#sandbox-loader').show();
|
213 |
+
});
|
214 |
+
|
215 |
+
jQuery('#sandbox-result').on('load error', function(){
|
216 |
+
jQuery('#sandbox-loader').hide();
|
217 |
+
});
|
218 |
+
|
219 |
+
//jQuery('#sandbox').submit();
|
220 |
+
});
|
221 |
+
|
222 |
+
function SandboxUpdateState(data){
|
223 |
+
var ul = jQuery('<ul/>');
|
224 |
+
for(var key in data)
|
225 |
+
ul.append(jQuery('<li/>').text(key + ': ' + data[key]));
|
226 |
+
jQuery('#sandbox-status').html('').append(ul);
|
227 |
+
}
|
228 |
+
</script><?php
|
229 |
+
}
|
230 |
+
|
231 |
+
}
|
classes/Views/Settings.php
ADDED
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Views_Settings extends WSAL_AbstractView {
|
4 |
+
|
5 |
+
public function __construct(WpSecurityAuditLog $plugin) {
|
6 |
+
parent::__construct($plugin);
|
7 |
+
add_action('wp_ajax_AjaxCheckSecurityToken', array($this, 'AjaxCheckSecurityToken'));
|
8 |
+
}
|
9 |
+
|
10 |
+
public function HasPluginShortcutLink(){
|
11 |
+
return true;
|
12 |
+
}
|
13 |
+
|
14 |
+
public function GetTitle() {
|
15 |
+
return 'Settings';
|
16 |
+
}
|
17 |
+
|
18 |
+
public function GetIcon() {
|
19 |
+
return 'dashicons-admin-generic';
|
20 |
+
}
|
21 |
+
|
22 |
+
public function GetName() {
|
23 |
+
return 'Settings';
|
24 |
+
}
|
25 |
+
|
26 |
+
public function GetWeight() {
|
27 |
+
return 3;
|
28 |
+
}
|
29 |
+
|
30 |
+
protected function GetTokenType($token){
|
31 |
+
$users = array();
|
32 |
+
foreach(get_users('blog_id=0&fields[]=user_login') as $obj)
|
33 |
+
$users[] = $obj->user_login;
|
34 |
+
$roles = array_keys(get_editable_roles());
|
35 |
+
|
36 |
+
if(in_array($token, $users))return 'user';
|
37 |
+
if(in_array($token, $roles))return 'role';
|
38 |
+
return 'other';
|
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)
|
51 |
+
$this->_plugin->settings->SetDevOptionEnabled($opt, true);
|
52 |
+
}
|
53 |
+
|
54 |
+
public function AjaxCheckSecurityToken(){
|
55 |
+
if(!$this->_plugin->settings->CurrentUserCan('view'))
|
56 |
+
die('Access Denied.');
|
57 |
+
if(!isset($_REQUEST['token']))
|
58 |
+
die('Token parameter expected.');
|
59 |
+
die($this->GetTokenType($_REQUEST['token']));
|
60 |
+
}
|
61 |
+
|
62 |
+
public function Render(){
|
63 |
+
if(!$this->_plugin->settings->CurrentUserCan('edit')){
|
64 |
+
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
65 |
+
}
|
66 |
+
if(isset($_POST['submit'])){
|
67 |
+
try {
|
68 |
+
$this->Save();
|
69 |
+
?><div class="updated"><p><?php _e('Settings have been saved.'); ?></p></div><?php
|
70 |
+
}catch(Exception $ex){
|
71 |
+
?><div class="error"><p><?php _e('Error: '); ?><?php echo $ex->getMessage(); ?></p></div><?php
|
72 |
+
}
|
73 |
+
}
|
74 |
+
?><form id="audit-log-settings" method="post">
|
75 |
+
<input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
|
76 |
+
<input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
|
77 |
+
|
78 |
+
<table class="form-table">
|
79 |
+
<tbody>
|
80 |
+
<tr>
|
81 |
+
<th><label for="delete1"><?php _e('Security Alerts Pruning'); ?></label></th>
|
82 |
+
<td>
|
83 |
+
<fieldset>
|
84 |
+
<?php $text = __('(eg: 1 month)'); ?>
|
85 |
+
<!--<input type="radio" id="delete1" style="margin-top: 2px;"/>-->
|
86 |
+
<label for="delete1"><?php echo __('Delete alerts older than'); ?></label>
|
87 |
+
<input type="text" name="PruningDate" placeholder="<?php echo $text; ?>"
|
88 |
+
value="<?php echo esc_attr($this->_plugin->settings->GetPruningDate()); ?>"/>
|
89 |
+
<span> <?php echo $text; ?></span>
|
90 |
+
</fieldset>
|
91 |
+
</td>
|
92 |
+
</tr>
|
93 |
+
<tr>
|
94 |
+
<th></th>
|
95 |
+
<td>
|
96 |
+
<fieldset>
|
97 |
+
<?php $max = $this->_plugin->settings->GetMaxAllowedAlerts(); ?>
|
98 |
+
<?php $text = sprintf(__('(1 to %d alerts)'), $max); ?>
|
99 |
+
<!--<input type="radio" id="delete2" style="margin-top: 2px;"/>-->
|
100 |
+
<label for="delete2"><?php echo __('Keep up to'); ?></label>
|
101 |
+
<input type="text" name="PruningLimit" placeholder="<?php echo $text;?>"
|
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.'), $max);
|
106 |
+
?></p>
|
107 |
+
</fieldset>
|
108 |
+
</td>
|
109 |
+
</tr>
|
110 |
+
<tr>
|
111 |
+
<th><label for="dwoption_on"><?php _e('Alerts Dashboard Widget'); ?></label></th>
|
112 |
+
<td>
|
113 |
+
<fieldset>
|
114 |
+
<?php $dwe = $this->_plugin->settings->IsWidgetsEnabled(); ?>
|
115 |
+
<label for="dwoption_on">
|
116 |
+
<input type="radio" name="EnableDashboardWidgets" id="dwoption_on" style="margin-top: 2px;" <?php if($dwe)echo 'checked="checked"'; ?> value="1">
|
117 |
+
<span><?php _e('On'); ?></span>
|
118 |
+
</label>
|
119 |
+
<br/>
|
120 |
+
<label for="dwoption_off">
|
121 |
+
<input type="radio" name="EnableDashboardWidgets" id="dwoption_off" style="margin-top: 2px;" <?php if(!$dwe)echo 'checked="checked"'; ?> value="0">
|
122 |
+
<span><?php _e('Off'); ?></span>
|
123 |
+
</label>
|
124 |
+
<br/>
|
125 |
+
<p class="description"><?php
|
126 |
+
echo sprintf(
|
127 |
+
__('Display a dashboard widget with the latest %d security alerts.'),
|
128 |
+
$this->_plugin->settings->GetDashboardWidgetMaxAlerts()
|
129 |
+
);
|
130 |
+
?></p>
|
131 |
+
</fieldset>
|
132 |
+
</td>
|
133 |
+
</tr>
|
134 |
+
<tr>
|
135 |
+
<th><label for="ViewerQueryBox"><?php _e('Can View Alerts'); ?></label></th>
|
136 |
+
<td>
|
137 |
+
<fieldset>
|
138 |
+
<input type="text" id="ViewerQueryBox" style="float: left; display: block; width: 250px;">
|
139 |
+
<input type="button" id="ViewerQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
|
140 |
+
<br style="clear: both;"/>
|
141 |
+
<p class="description"><?php
|
142 |
+
_e('Users and Roles in this list can view the security alerts');
|
143 |
+
?></p>
|
144 |
+
<div id="ViewerList"><?php
|
145 |
+
foreach($this->_plugin->settings->GetAllowedPluginViewers() as $item){
|
146 |
+
?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
|
147 |
+
<input type="hidden" name="Viewers[]" value="<?php echo esc_attr($item); ?>"/>
|
148 |
+
<?php echo esc_html($item); ?>
|
149 |
+
<a href="javascript:;" title="Remove">×</a>
|
150 |
+
</span><?php
|
151 |
+
}
|
152 |
+
?></div>
|
153 |
+
</fieldset>
|
154 |
+
</td>
|
155 |
+
</tr>
|
156 |
+
<tr>
|
157 |
+
<th><label for="EditorQueryBox"><?php _e('Can Manage Plugin'); ?></label></th>
|
158 |
+
<td>
|
159 |
+
<fieldset>
|
160 |
+
<input type="text" id="EditorQueryBox" style="float: left; display: block; width: 250px;">
|
161 |
+
<input type="button" id="EditorQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
|
162 |
+
<br style="clear: both;"/>
|
163 |
+
<p class="description"><?php
|
164 |
+
_e('Users and Roles in this list can manage the plugin settings');
|
165 |
+
?></p>
|
166 |
+
<div id="EditorList"><?php
|
167 |
+
foreach($this->_plugin->settings->GetAllowedPluginEditors() as $item){
|
168 |
+
?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
|
169 |
+
<input type="hidden" name="Editors[]" value="<?php echo esc_attr($item); ?>"/>
|
170 |
+
<?php echo esc_html($item); ?>
|
171 |
+
<a href="javascript:;" title="Remove">×</a>
|
172 |
+
</span><?php
|
173 |
+
}
|
174 |
+
?></div>
|
175 |
+
</fieldset>
|
176 |
+
</td>
|
177 |
+
</tr>
|
178 |
+
<tr>
|
179 |
+
<th><label for="aroption_on"><?php _e('Refresh Audit View'); ?></label></th>
|
180 |
+
<td>
|
181 |
+
<fieldset>
|
182 |
+
<?php $are = $this->_plugin->settings->IsRefreshAlertsEnabled(); ?>
|
183 |
+
<label for="aroption_on">
|
184 |
+
<input type="radio" name="EnableAuditViewRefresh" id="aroption_on" style="margin-top: 2px;" <?php if($are)echo 'checked="checked"'; ?> value="1">
|
185 |
+
<span><?php _e('Automatic'); ?></span>
|
186 |
+
</label>
|
187 |
+
<span class="description"> — <?php _e('Refresh Audit View as soon as there are new events.'); ?></span>
|
188 |
+
<br/>
|
189 |
+
<label for="aroption_off">
|
190 |
+
<input type="radio" name="EnableAuditViewRefresh" id="aroption_off" style="margin-top: 2px;" <?php if(!$are)echo 'checked="checked"'; ?> value="0">
|
191 |
+
<span><?php _e('Manual'); ?></span>
|
192 |
+
</label>
|
193 |
+
<span class="description"> — <?php _e('Refresh Audit View only when page is reloaded.'); ?></span>
|
194 |
+
<br/>
|
195 |
+
</fieldset>
|
196 |
+
</td>
|
197 |
+
</tr>
|
198 |
+
<tr>
|
199 |
+
<th><label><?php _e('Developer Options'); ?></label></th>
|
200 |
+
<td>
|
201 |
+
<fieldset><?php
|
202 |
+
foreach(array(
|
203 |
+
WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array('Data Inspector', 'View data logged for each triggered alert.'),
|
204 |
+
WSAL_Settings::OPT_DEV_PHP_ERRORS => array('PHP Errors', 'Enables sensor for alerts generated from PHP.'),
|
205 |
+
WSAL_Settings::OPT_DEV_REQUEST_LOG => array('Request Log', 'Enables logging request to file.'),
|
206 |
+
WSAL_Settings::OPT_DEV_SANDBOX_PAGE => array('Sandbox', 'Enables sandbox for testing PHP code.'),
|
207 |
+
) as $opt => $info){
|
208 |
+
?><label for="devoption_<?php echo $opt; ?>">
|
209 |
+
<input type="checkbox" name="DevOptions[]" id="devoption_<?php echo $opt; ?>" <?php
|
210 |
+
if($this->_plugin->settings->IsDevOptionEnabled($opt))echo 'checked="checked"'; ?> value="<?php echo $opt; ?>">
|
211 |
+
<span><?php _e($info[0]); ?></span>
|
212 |
+
<?php if(isset($info[1]) && $info[1]){ ?>
|
213 |
+
<span class="description"> — <?php _e($info[1]); ?></span>
|
214 |
+
<?php }
|
215 |
+
?></label><br/><?php
|
216 |
+
}
|
217 |
+
?></fieldset>
|
218 |
+
</td>
|
219 |
+
</tr>
|
220 |
+
</tbody>
|
221 |
+
</table>
|
222 |
+
|
223 |
+
<p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"></p>
|
224 |
+
</form><?php
|
225 |
+
}
|
226 |
+
|
227 |
+
public function Header(){
|
228 |
+
wp_enqueue_style(
|
229 |
+
'settings',
|
230 |
+
$this->_plugin->GetBaseUrl() . '/css/settings.css',
|
231 |
+
array(),
|
232 |
+
filemtime($this->_plugin->GetBaseDir() . '/css/settings.css')
|
233 |
+
);
|
234 |
+
}
|
235 |
+
|
236 |
+
public function Footer() {
|
237 |
+
wp_enqueue_script(
|
238 |
+
'settings',
|
239 |
+
$this->_plugin->GetBaseUrl() . '/js/settings.js',
|
240 |
+
array(),
|
241 |
+
filemtime($this->_plugin->GetBaseDir() . '/js/settings.js')
|
242 |
+
);
|
243 |
+
}
|
244 |
+
|
245 |
+
}
|
classes/Views/ToggleAlerts.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Views_ToggleAlerts extends WSAL_AbstractView {
|
4 |
+
|
5 |
+
public function GetTitle() {
|
6 |
+
return 'Enable/Disable Alerts';
|
7 |
+
}
|
8 |
+
|
9 |
+
public function GetIcon() {
|
10 |
+
return 'dashicons-forms';
|
11 |
+
}
|
12 |
+
|
13 |
+
public function GetName() {
|
14 |
+
return 'Enable/Disable Alerts';
|
15 |
+
}
|
16 |
+
|
17 |
+
public function GetWeight() {
|
18 |
+
return 2;
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function GetSafeCatgName($name){
|
22 |
+
return strtolower(
|
23 |
+
preg_replace('/[^A-Za-z0-9\-]/', '-', $name)
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
public function Render(){
|
28 |
+
if(!$this->_plugin->settings->CurrentUserCan('edit')){
|
29 |
+
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
30 |
+
}
|
31 |
+
$alert = new WSAL_Alert(); // IDE type hinting
|
32 |
+
$groupedAlerts = $this->_plugin->alerts->GetCategorizedAlerts();
|
33 |
+
$safeNames = array_map(array($this, 'GetSafeCatgName'), array_keys($groupedAlerts));
|
34 |
+
$safeNames = array_combine(array_keys($groupedAlerts), $safeNames);
|
35 |
+
if(isset($_POST['submit']) && isset($_POST['alert'])){
|
36 |
+
try {
|
37 |
+
$enabled = array_map('intval', $_POST['alert']);
|
38 |
+
$disabled = array();
|
39 |
+
foreach($this->_plugin->alerts->GetAlerts() as $alert)
|
40 |
+
if(!in_array($alert->type, $enabled))
|
41 |
+
$disabled[] = $alert->type;
|
42 |
+
$this->_plugin->alerts->SetDisabledAlerts($disabled);
|
43 |
+
?><div class="updated"><p><?php _e('Settings have been saved.'); ?></p></div><?php
|
44 |
+
}catch(Exception $ex){
|
45 |
+
?><div class="error"><p><?php _e('Error: '); ?><?php echo $ex->getMessage(); ?></p></div><?php
|
46 |
+
}
|
47 |
+
}
|
48 |
+
?><h2 id="wsal-tabs" class="nav-tab-wrapper"><?php
|
49 |
+
foreach($safeNames as $name => $safe){
|
50 |
+
?><a href="#tab-<?php echo $safe; ?>" class="nav-tab"><?php echo __($name); ?></a><?php
|
51 |
+
}
|
52 |
+
?></h2>
|
53 |
+
<form id="audit-log-viewer" method="post">
|
54 |
+
<input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
|
55 |
+
<div class="nav-tabs"><?php
|
56 |
+
foreach($groupedAlerts as $name => $alerts){
|
57 |
+
$active = array(); $allactive = true;
|
58 |
+
foreach($alerts as $alert){
|
59 |
+
$active[$alert->type] = $this->_plugin->alerts->IsEnabled($alert->type);
|
60 |
+
if(!$active[$alert->type])$allactive = false;
|
61 |
+
}
|
62 |
+
?><table class="wp-list-table wsal-tab widefat fixed" cellspacing="0" id="tab-<?php echo $safeNames[$name]; ?>">
|
63 |
+
<thead>
|
64 |
+
<tr>
|
65 |
+
<th width="48"><input type="checkbox"<?php if($allactive)echo 'checked="checked"'; ?>/></th>
|
66 |
+
<th width="80">Code</th>
|
67 |
+
<th width="100">Type</th>
|
68 |
+
<th>Description</th>
|
69 |
+
</tr>
|
70 |
+
</thead>
|
71 |
+
<tbody><?php
|
72 |
+
foreach($alerts as $alert){
|
73 |
+
$attrs = '';
|
74 |
+
switch(true){
|
75 |
+
case !$alert->mesg:
|
76 |
+
$attrs = ' title="Not Implemented" class="alert-incomplete"';
|
77 |
+
break;
|
78 |
+
case false:
|
79 |
+
$attrs = ' title="Not Available" class="alert-unavailable"';
|
80 |
+
break;
|
81 |
+
}
|
82 |
+
?><tr<?php echo $attrs; ?>>
|
83 |
+
<th><input name="alert[]" type="checkbox" <?php if($active[$alert->type])echo 'checked="checked"'; ?> value="<?php echo (int)$alert->type; ?>"></th>
|
84 |
+
<td><?php echo str_pad($alert->type, 4, '0', STR_PAD_LEFT); ?></td>
|
85 |
+
<td><?php echo $this->_plugin->constants->GetConstantBy('value', $alert->code)->name; ?></td>
|
86 |
+
<td><?php echo esc_html(__($alert->desc)); ?></td>
|
87 |
+
</tr><?php
|
88 |
+
}
|
89 |
+
?></tbody>
|
90 |
+
</table><?php
|
91 |
+
}
|
92 |
+
?></div>
|
93 |
+
<p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"></p>
|
94 |
+
</form><?php
|
95 |
+
}
|
96 |
+
|
97 |
+
public function Header() {
|
98 |
+
?><style type="text/css">
|
99 |
+
.wsal-tab {
|
100 |
+
display: none;
|
101 |
+
}
|
102 |
+
.wsal-tab tr.alert-incomplete td {
|
103 |
+
color: #9BE;
|
104 |
+
}
|
105 |
+
.wsal-tab tr.alert-unavailable td {
|
106 |
+
color: #CCC;
|
107 |
+
}
|
108 |
+
</style><?php
|
109 |
+
}
|
110 |
+
|
111 |
+
public function Footer() {
|
112 |
+
?><script type="text/javascript">
|
113 |
+
jQuery(document).ready(function(){
|
114 |
+
// tab handling code
|
115 |
+
jQuery('#wsal-tabs>a').click(function(){
|
116 |
+
jQuery('#wsal-tabs>a').removeClass('nav-tab-active');
|
117 |
+
jQuery('table.wsal-tab').hide();
|
118 |
+
jQuery(jQuery(this).addClass('nav-tab-active').attr('href')).show();
|
119 |
+
});
|
120 |
+
// checkbox handling code
|
121 |
+
jQuery('table.wsal-tab>thead>tr>th>:checkbox').change(function(){
|
122 |
+
jQuery(this).parents('table:first').find('tbody>tr>th>:checkbox').attr('checked', this.checked);
|
123 |
+
});
|
124 |
+
jQuery('table.wsal-tab>tbody>tr>th>:checkbox').change(function(){
|
125 |
+
var allchecked = jQuery(this).parents('tbody:first').find('th>:checkbox:not(:checked)').length === 0;
|
126 |
+
jQuery(this).parents('table:first').find('thead>tr>th:first>:checkbox:first').attr('checked', allchecked);
|
127 |
+
});
|
128 |
+
// show relevant tab
|
129 |
+
var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
|
130 |
+
if(hashlink.length){
|
131 |
+
hashlink.click();
|
132 |
+
}else{
|
133 |
+
jQuery('#wsal-tabs>a:first').click();
|
134 |
+
}
|
135 |
+
});
|
136 |
+
</script><?php
|
137 |
+
}
|
138 |
+
|
139 |
+
}
|
classes/WidgetManager.php
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_WidgetManager {
|
4 |
+
/**
|
5 |
+
* @var WpSecurityAuditLog
|
6 |
+
*/
|
7 |
+
protected $_plugin;
|
8 |
+
|
9 |
+
public function __construct(WpSecurityAuditLog $plugin){
|
10 |
+
$this->_plugin = $plugin;
|
11 |
+
add_action('wp_dashboard_setup', array($this, 'AddWidgets'));
|
12 |
+
}
|
13 |
+
|
14 |
+
public function AddWidgets(){
|
15 |
+
if($this->_plugin->settings->IsWidgetsEnabled()
|
16 |
+
&& $this->_plugin->settings->CurrentUserCan('view')){
|
17 |
+
wp_add_dashboard_widget(
|
18 |
+
'wsal',
|
19 |
+
__('Latest Alerts') . ' | WP Security Audit Log',
|
20 |
+
array($this, 'RenderWidget')
|
21 |
+
);
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
public function RenderWidget(){
|
26 |
+
$results = WSAL_DB_Occurrence::LoadMulti(
|
27 |
+
' 1 ORDER BY created_on DESC LIMIT '
|
28 |
+
. $this->_plugin->settings->GetDashboardWidgetMaxAlerts()
|
29 |
+
);
|
30 |
+
?><div><?php
|
31 |
+
if(!count($results)){
|
32 |
+
?><p><?php _e('No alerts found.'); ?></p><?php
|
33 |
+
}else{
|
34 |
+
?><table class="wp-list-table widefat" cellspacing="0" cellpadding="0">
|
35 |
+
<thead>
|
36 |
+
<th class="manage-column" style="width: 15%;" scope="col"><?php _e('User'); ?></th>
|
37 |
+
<th class="manage-column" style="width: 85%;" scope="col"><?php _e('Description'); ?></th>
|
38 |
+
</thead>
|
39 |
+
<tbody><?php
|
40 |
+
$url = 'admin.php?page=' . $this->_plugin->views->views[0]->GetSafeViewName();
|
41 |
+
$fmt = array(new WSAL_Views_AuditLogList_Internal($this->_plugin), 'meta_formatter');
|
42 |
+
foreach($results as $entry){
|
43 |
+
?><tr>
|
44 |
+
<td><?php
|
45 |
+
echo ($un = $entry->GetUsername()) ? esc_html($un) : '<i>unknown</i>';
|
46 |
+
?></td>
|
47 |
+
<td>
|
48 |
+
<a href="<?php echo $url . '#Event' . $entry->id; ?>"><?php
|
49 |
+
echo $entry->GetMessage($fmt);
|
50 |
+
?></a>
|
51 |
+
</td>
|
52 |
+
</tr><?php
|
53 |
+
}
|
54 |
+
?></tbody>
|
55 |
+
</table><?php
|
56 |
+
}
|
57 |
+
?></div><?php
|
58 |
+
}
|
59 |
+
}
|
css/auditlog.css
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wsal-ipp,
|
2 |
+
.wsal-ssa {
|
3 |
+
display: inline-block;
|
4 |
+
color: #555;
|
5 |
+
line-height: 30px;
|
6 |
+
font-size: 12px;
|
7 |
+
}
|
8 |
+
|
9 |
+
.wsal-ipp select {
|
10 |
+
margin-bottom: 6px;
|
11 |
+
width: 56px;
|
12 |
+
}
|
13 |
+
|
14 |
+
.wsal-ssa select {
|
15 |
+
margin-bottom: 6px;
|
16 |
+
width: 120px;
|
17 |
+
margin-left: 16px;
|
18 |
+
}
|
19 |
+
|
20 |
+
.column-read,
|
21 |
+
.column-type,
|
22 |
+
.column-code,
|
23 |
+
.column-more {
|
24 |
+
width: 70px;
|
25 |
+
}
|
26 |
+
|
27 |
+
.column-crtd {
|
28 |
+
width: 96px;
|
29 |
+
}
|
30 |
+
|
31 |
+
.column-user {
|
32 |
+
width: 110px;
|
33 |
+
}
|
34 |
+
|
35 |
+
.column-scip {
|
36 |
+
width: 120px;
|
37 |
+
}
|
38 |
+
|
39 |
+
.more-info {
|
40 |
+
float: right;
|
41 |
+
display: block;
|
42 |
+
width: 16px;
|
43 |
+
height: 16px;
|
44 |
+
color: #FFF;
|
45 |
+
font-weight: bold;
|
46 |
+
font-size: 13px;
|
47 |
+
line-height: 10px;
|
48 |
+
text-align: center;
|
49 |
+
border-radius: 32px;
|
50 |
+
margin-left: 8px;
|
51 |
+
background: #AAA;
|
52 |
+
}
|
53 |
+
|
54 |
+
.more-info:hover {
|
55 |
+
color: #FFF;
|
56 |
+
background: #333;
|
57 |
+
}
|
58 |
+
|
59 |
+
.log-read:after {
|
60 |
+
display: block;
|
61 |
+
width: 16px;
|
62 |
+
height: 16px;
|
63 |
+
color: #FFF;
|
64 |
+
font-weight: bold;
|
65 |
+
font-size: 13px;
|
66 |
+
line-height: 16px;
|
67 |
+
text-align: center;
|
68 |
+
border-radius: 32px;
|
69 |
+
margin-left: 8px;
|
70 |
+
content: "\2713";
|
71 |
+
background: #CCC;
|
72 |
+
}
|
73 |
+
|
74 |
+
.log-read-new:after {
|
75 |
+
background: #290;
|
76 |
+
}
|
77 |
+
|
78 |
+
.log-type {
|
79 |
+
cursor: help;
|
80 |
+
}
|
81 |
+
|
82 |
+
.log-type:after {
|
83 |
+
display: block;
|
84 |
+
width: 16px;
|
85 |
+
height: 16px;
|
86 |
+
color: #FFF;
|
87 |
+
font-weight: bold;
|
88 |
+
font-size: 11px;
|
89 |
+
line-height: 17px;
|
90 |
+
background: #CCC;
|
91 |
+
text-align: center;
|
92 |
+
border-radius: 32px;
|
93 |
+
margin-left: 8px;
|
94 |
+
}
|
95 |
+
|
96 |
+
/* errors */
|
97 |
+
.log-type-0:after,
|
98 |
+
.log-type-1:after,
|
99 |
+
.log-type-4:after,
|
100 |
+
.log-type-16:after,
|
101 |
+
.log-type-64:after,
|
102 |
+
.log-type-256:after,
|
103 |
+
.log-type-4096:after,
|
104 |
+
.log-type-E_CRITICAL:after
|
105 |
+
{ background: #E00; content: "!"; }
|
106 |
+
|
107 |
+
/* warnings */
|
108 |
+
.log-type-2:after,
|
109 |
+
.log-type-32:after,
|
110 |
+
.log-type-128:after,
|
111 |
+
.log-type-512:after
|
112 |
+
{ background: #EB0; content: "!"; }
|
113 |
+
|
114 |
+
/* notices/strict/deprecation */
|
115 |
+
.log-type-8:after,
|
116 |
+
.log-type-1024:after,
|
117 |
+
.log-type-2048:after,
|
118 |
+
.log-type-8192:after,
|
119 |
+
.log-type-16384:after,
|
120 |
+
.log-type-E_DEBUG:after
|
121 |
+
{ background: #09E; content: "i"; }
|
css/nice_r.css
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.nice_r {
|
2 |
+
font: 12px Consolas, "Lucida Console", monospace;
|
3 |
+
}
|
4 |
+
|
5 |
+
.nice_r a {
|
6 |
+
display: block;
|
7 |
+
text-decoration: none;
|
8 |
+
color: #222;
|
9 |
+
padding: 2px;
|
10 |
+
white-space: nowrap;
|
11 |
+
overflow: hidden;
|
12 |
+
text-overflow: ellipsis;
|
13 |
+
}
|
14 |
+
|
15 |
+
.nice_r a:hover .nice_r_k,
|
16 |
+
.nice_r a:hover .nice_r_d,
|
17 |
+
.nice_r a:hover .nice_r_d span,
|
18 |
+
.nice_r a:hover .nice_r_p,
|
19 |
+
.nice_r a:hover .nice_r_a,
|
20 |
+
.nice_r a:hover {
|
21 |
+
background-color: Highlight;
|
22 |
+
color: HighlightText;
|
23 |
+
}
|
24 |
+
|
25 |
+
.nice_r_a {
|
26 |
+
color: #000;
|
27 |
+
}
|
28 |
+
|
29 |
+
.nice_r_ad {
|
30 |
+
opacity: 0.5;
|
31 |
+
}
|
32 |
+
|
33 |
+
.nice_r_k {
|
34 |
+
color: #060;
|
35 |
+
font-weight: bold;
|
36 |
+
}
|
37 |
+
|
38 |
+
.nice_r_d {
|
39 |
+
font-size: 11px;
|
40 |
+
color: #777;
|
41 |
+
}
|
42 |
+
|
43 |
+
.nice_r_d span {
|
44 |
+
color: #333;
|
45 |
+
}
|
46 |
+
|
47 |
+
.nice_r_p {
|
48 |
+
color: #000;
|
49 |
+
font-weight: bold;
|
50 |
+
}
|
51 |
+
|
52 |
+
.nice_r_v {
|
53 |
+
margin-left: 6px;
|
54 |
+
padding-left: 6px;
|
55 |
+
border-left: 1px dotted #CCC;
|
56 |
+
display: none;
|
57 |
+
}
|
58 |
+
|
59 |
+
.nice_r_ir {
|
60 |
+
font-style: italic;
|
61 |
+
}
|
62 |
+
|
63 |
+
.nice_r_p.nice_r_t_integer,
|
64 |
+
.nice_r_p.nice_r_t_double {
|
65 |
+
color: #F0E;
|
66 |
+
}
|
67 |
+
|
68 |
+
.nice_r_p.nice_r_t_string {
|
69 |
+
color: #E00;
|
70 |
+
}
|
71 |
+
|
72 |
+
.nice_r_p.nice_r_t_boolean {
|
73 |
+
color: #00E;
|
74 |
+
}
|
css/settings.css
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.sectoken-user,
|
2 |
+
.sectoken-role,
|
3 |
+
.sectoken-other {
|
4 |
+
display: inline-block;
|
5 |
+
border-width: 1px;
|
6 |
+
border-style: solid;
|
7 |
+
padding: 2px 4px;
|
8 |
+
margin: 2px 0 0 2px;
|
9 |
+
border-radius: 3px;
|
10 |
+
cursor: default;
|
11 |
+
}
|
12 |
+
|
13 |
+
.sectoken-user a,
|
14 |
+
.sectoken-role a,
|
15 |
+
.sectoken-other a {
|
16 |
+
text-decoration: none;
|
17 |
+
font-size: 12px;
|
18 |
+
font-weight: bold;
|
19 |
+
color: #FFF;
|
20 |
+
margin-left: 2px;
|
21 |
+
background: #BBB;
|
22 |
+
border-radius: 25px;
|
23 |
+
height: 14px;
|
24 |
+
display: inline-block;
|
25 |
+
width: 14px;
|
26 |
+
text-align: center;
|
27 |
+
line-height: 16px;
|
28 |
+
}
|
29 |
+
|
30 |
+
.sectoken-user a:hover,
|
31 |
+
.sectoken-role a:hover,
|
32 |
+
.sectoken-other a:hover {
|
33 |
+
background: #FB9;
|
34 |
+
}
|
35 |
+
|
36 |
+
.sectoken-user { background: #EFF; border-color: #5BE; }
|
37 |
+
.sectoken-role { background: #EFE; border-color: #5B5; }
|
38 |
+
.sectoken-other { background: #FFE; border-color: #ED5; }
|
39 |
+
.sectoken-del { background: #FEE; border-color: #EBB; }
|
defaults.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// if not included correctly...
|
4 |
+
if ( !class_exists( 'WpSecurityAuditLog' ) ) exit();
|
5 |
+
|
6 |
+
defined('E_CRITICAL') || define('E_CRITICAL', 'E_CRITICAL');
|
7 |
+
defined('E_DEBUG') || define('E_DEBUG', 'E_DEBUG');
|
8 |
+
|
9 |
+
WpSecurityAuditLog::GetInstance()
|
10 |
+
->constants->UseConstants(array(
|
11 |
+
// default PHP constants
|
12 |
+
array('name' => 'E_ERROR', 'description' => 'Fatal run-time error.'),
|
13 |
+
array('name' => 'E_WARNING', 'description' => 'Run-time warning (non-fatal error).'),
|
14 |
+
array('name' => 'E_PARSE', 'description' => 'Compile-time parse error.'),
|
15 |
+
array('name' => 'E_NOTICE', 'description' => 'Run-time notice.'),
|
16 |
+
array('name' => 'E_CORE_ERROR', 'description' => 'Fatal error that occurred during startup.'),
|
17 |
+
array('name' => 'E_CORE_WARNING', 'description' => 'Warnings that occurred during startup.'),
|
18 |
+
array('name' => 'E_COMPILE_ERROR', 'description' => 'Fatal compile-time error.'),
|
19 |
+
array('name' => 'E_COMPILE_WARNING', 'description' => 'Compile-time warning.'),
|
20 |
+
array('name' => 'E_USER_ERROR', 'description' => 'User-generated error message.'),
|
21 |
+
array('name' => 'E_USER_WARNING', 'description' => 'User-generated warning message.'),
|
22 |
+
array('name' => 'E_USER_NOTICE', 'description' => 'User-generated notice message. '),
|
23 |
+
array('name' => 'E_STRICT', 'description' => 'Non-standard/optimal code warning.'),
|
24 |
+
array('name' => 'E_RECOVERABLE_ERROR', 'description' => 'Catchable fatal error.'),
|
25 |
+
array('name' => 'E_DEPRECATED', 'description' => 'Run-time deprecation notices.'),
|
26 |
+
array('name' => 'E_USER_DEPRECATED', 'description' => 'Run-time user deprecation notices.'),
|
27 |
+
// custom constants
|
28 |
+
array('name' => 'E_CRITICAL', 'description' => 'Critical, high-impact messages.'),
|
29 |
+
array('name' => 'E_DEBUG', 'description' => 'Debug informational messages.'),
|
30 |
+
));
|
31 |
+
|
32 |
+
WpSecurityAuditLog::GetInstance()
|
33 |
+
->alerts->RegisterGroup(array(
|
34 |
+
'Other User Activity' => array(
|
35 |
+
array(1000, E_NOTICE, 'User logs in', 'Successfully logged in'),
|
36 |
+
array(1001, E_NOTICE, 'User logs out', 'Successfully logged out'),
|
37 |
+
array(1002, E_WARNING, 'Login failed', '%Attempts% failed login(s) detected'),
|
38 |
+
array(2010, E_NOTICE, 'User uploaded file from Uploads directory', 'Uploaded the file %FileName% in %FilePath%'),
|
39 |
+
array(2011, E_WARNING, 'User deleted file from Uploads directory', 'Deleted the file %FileName% from %FilePath%'),
|
40 |
+
array(2046, E_CRITICAL, 'User changed a file using the editor', 'Modified %File% with the Theme Editor'),
|
41 |
+
),
|
42 |
+
'Blog Posts' => array(
|
43 |
+
array(2000, E_NOTICE, 'User created a new blog post and saved it as draft', 'Created a new blog post called %PostTitle%. Blog post ID is %PostID%'),
|
44 |
+
array(2001, E_NOTICE, 'User published a blog post', 'Published a blog post called %PostTitle%. Blog post URL is %PostUrl%'),
|
45 |
+
array(2002, E_NOTICE, 'User modified a published blog post', 'Modified the published blog post %PostTitle%. Blog post URL is %PostUrl%'),
|
46 |
+
array(2003, E_NOTICE, 'User modified a draft blog post', 'Modified the draft blog post %PostTitle%. Blog post ID is %PostID%'),
|
47 |
+
array(2008, E_NOTICE, 'User permanently deleted a blog post from the trash', 'Deleted the post %PostTitle%. Blog post ID is %PostID%'),
|
48 |
+
array(2012, E_WARNING, 'User moved a blog post to the trash', 'Moved the blog post %PostTitle% to trash'),
|
49 |
+
array(2014, E_CRITICAL, 'User restored a blog post from trash', 'Restored post %PostTitle% from trash'),
|
50 |
+
array(2016, E_NOTICE, 'User changed blog post category', 'Changed the category of the post %PostTitle% from %OldCategories% to %NewCategories%'),
|
51 |
+
array(2017, E_NOTICE, 'User changed blog post URL', 'Changed the URL of the post %PostTitle% from %OldUrl% to %NewUrl%'),
|
52 |
+
array(2019, E_NOTICE, 'User changed blog post author', 'Changed the author of %PostTitle% post from %OldAuthor% to %NewAuthor%'),
|
53 |
+
array(2021, E_NOTICE, 'User changed blog post status', 'Changed the status of %PostTitle% post from %OldStatus% to %NewStatus%'),
|
54 |
+
array(2023, E_NOTICE, 'User created new category', 'Created a new category called %CategoryName%'),
|
55 |
+
array(2024, E_WARNING, 'User deleted category', 'Deleted the %CategoryName% category'),
|
56 |
+
array(2025, E_WARNING, 'User changed the visibility of a blog post', 'Changed the visibility of %PostTitle% blog post from %OldVisibility% to %NewVisibility%'),
|
57 |
+
array(2027, E_NOTICE, 'User changed the date of a blog post', 'Changed the date of %PostTitle% blog post from %OldDate% to %NewDate%'),
|
58 |
+
array(2049, E_NOTICE, 'User sets a post as sticky', 'Set the post %PostTitle% as Sticky'),
|
59 |
+
array(2050, E_NOTICE, 'User removes post from sticky', 'Removed the post %PostTitle% from Sticky'),
|
60 |
+
),
|
61 |
+
'Pages' => array(
|
62 |
+
array(2004, E_NOTICE, 'User created a new WordPress page and saved it as draft', 'Created a new page called %PostTitle%. Page ID is %PostID%'),
|
63 |
+
array(2005, E_NOTICE, 'User published a WorPress page', 'Published a page called %PostTitle%. Page URL is %PostUrl%'),
|
64 |
+
array(2006, E_NOTICE, 'User modified a published WordPress page', 'Modified the published page %PostTitle%. Page URL is %PostUrl%'),
|
65 |
+
array(2007, E_NOTICE, 'User modified a draft WordPress page', 'Modified the draft page %PostTitle%. page ID is %PostID%'),
|
66 |
+
array(2009, E_NOTICE, 'User permanently deleted a page from the trash', 'Deleted the page %PostTitle%. Page ID is %PostID%'),
|
67 |
+
array(2013, E_WARNING, 'User moved WordPress page to the trash', 'Moved the page %PostTitle% to trash'),
|
68 |
+
array(2015, E_CRITICAL, 'User restored a WordPress page from trash', 'Restored page %PostTitle% from trash'),
|
69 |
+
array(2018, E_NOTICE, 'User changed page URL', 'Changed the URL of the page %PostTitle% from %OldUrl% to %NewUrl%'),
|
70 |
+
array(2020, E_NOTICE, 'User changed page author', 'Changed the author of %PostTitle% page from %OldAuthor% to %NewAuthor%'),
|
71 |
+
array(2022, E_NOTICE, 'User changed page status', 'Changed the status of %PostTitle% page from %OldStatus% to %NewStatus%'),
|
72 |
+
array(2026, E_WARNING, 'User changed the visibility of a page post', 'Changed the visibility of %PostTitle% page from %OldVisibility% to %NewVisibility%'),
|
73 |
+
array(2028, E_NOTICE, 'User changed the date of a page post', 'Changed the date of %PostTitle% page from %OldDate% to %NewDate%'),
|
74 |
+
array(2047, E_NOTICE, 'User changed the parent of a page', 'Changed the parent of %PostTitle% page from %OldParentName% to %NewParentName%'),
|
75 |
+
array(2048, E_CRITICAL, 'User changes the template of a page', 'Changed the template of %PostTitle% page from %OldTemplate% to %NewTemplate%'),
|
76 |
+
),
|
77 |
+
'Custom Posts' => array(
|
78 |
+
array(2029, E_NOTICE, 'User created a new post with custom post type and saved it as draft', 'Created a new custom post called %PostTitle% of type %PostType%. Post ID is %PostID%'),
|
79 |
+
array(2030, E_NOTICE, 'User published a post with custom post type', 'Published a custom post %PostTitle% of type %PostType%. Post URL is %PostUrl%'),
|
80 |
+
array(2031, E_NOTICE, 'User modified a post with custom post type', 'Modified custom post %PostTitle% of type %PostType%. Post URL is %PostUrl%'),
|
81 |
+
array(2032, E_NOTICE, 'User modified a draft post with custom post type', 'Modified draft custom post %PostTitle% of type is %PostType%. Post URL is %PostUrl%'),
|
82 |
+
array(2033, E_WARNING, 'User permanently deleted post with custom post type', 'Deleted custom post %PostTitle% of type %PostType%'),
|
83 |
+
array(2034, E_WARNING, 'User moved post with custom post type to trash', 'Moved custom post %PostTitle% to trash. Post type is %PostType%'),
|
84 |
+
array(2035, E_CRITICAL, 'User restored post with custom post type from trash', 'Restored custom post %PostTitle% of type %PostType% from trash'),
|
85 |
+
array(2036, E_NOTICE, 'User changed the category of a post with custom post type', 'Changed the category(ies) of custom post %PostTitle% of type %PostType% from %OldCategories% to %NewCategories%'),
|
86 |
+
array(2037, E_NOTICE, 'User changed the URL of a post with custom post type', 'Changed the URL of custom post %PostTitle% of type %PostType% from %OldUrl% to %NewUrl%'),
|
87 |
+
array(2038, E_NOTICE, 'User changed the author or post with custom post type', 'Changed the author of custom post %PostTitle% of type %PostType% from %OldAuthor% to %NewAuthor%'),
|
88 |
+
array(2039, E_NOTICE, 'User changed the status of post with custom post type', 'Changed the status of custom post %PostTitle% of type %PostType% from %OldStatus% to %NewStatus%'),
|
89 |
+
array(2040, E_WARNING, 'User changed the visibility of a post with custom post type', 'Changed the visibility of custom post %PostTitle% of type %PostType% from %OldVisibility% to %NewVisibility%'),
|
90 |
+
array(2041, E_NOTICE, 'User changed the date of post with custom post type', 'Changed the date of custom post %PostTitle% of type %PostType% from %OldDate% to %NewDate%'),
|
91 |
+
),
|
92 |
+
'Widgets' => array(
|
93 |
+
array(2042, E_CRITICAL, 'User added a new widget', 'Added a new %WidgetName% widget in %Sidebar%'),
|
94 |
+
array(2043, E_WARNING, 'User modified a widget', 'Modified the %WidgetName% widget in %Sidebar%'),
|
95 |
+
array(2044, E_CRITICAL, 'User deleted widget', 'Deleted the %WidgetName% widget from %Sidebar%'),
|
96 |
+
array(2045, E_NOTICE, 'User moved widget', 'Moved the %WidgetName% widget from %OldSidebar% to %NewSidebar%'),
|
97 |
+
),
|
98 |
+
'User Profiles' => array(
|
99 |
+
array(4000, E_CRITICAL, 'A new user was created on WordPress', 'User %NewUserData->Username% subscribed with a role of %NewUserData->Roles%'),
|
100 |
+
array(4001, E_CRITICAL, 'A user created another WordPress user', 'Created a new user %NewUserData->Username% with the role of %NewUserData->Roles%'),
|
101 |
+
array(4002, E_CRITICAL, 'The role of a user was changed by another WordPress user', 'Changed the role of user %TargetUsername% from %OldRole% to %NewRole%'),
|
102 |
+
array(4003, E_CRITICAL, 'User has changed his or her password', 'Changed the password'),
|
103 |
+
array(4004, E_CRITICAL, 'A user changed another user\'s password', 'Changed the password for user %TargetUserData->Username% with the role of %TargetUserData->Roles%'),
|
104 |
+
array(4005, E_NOTICE, 'User changed his or her email address', 'Changed the email address from %OldEmail% to %NewEmail%'),
|
105 |
+
array(4006, E_NOTICE, 'A user changed another user\'s email address', 'Changed the email address of user account %TargetUsername% from %OldEmail% to %NewEmail%'),
|
106 |
+
array(4007, E_CRITICAL, 'A user was deleted by another user', 'Deleted User %TargetUserData->Username% with the role of %TargetUserData->Roles%'),
|
107 |
+
),
|
108 |
+
'Plugins & Themes' => array(
|
109 |
+
array(5000, E_CRITICAL, 'User installed a plugin', 'Installed the plugin %NewPlugin->Name% in %NewPlugin->plugin_dir_path%'),
|
110 |
+
array(5001, E_CRITICAL, 'User activated a WordPress plugin', 'Activated the plugin %PluginData->Name% installed in %PluginFile%'),
|
111 |
+
array(5002, E_CRITICAL, 'User deactivated a WordPress plugin', 'Deactivated the plugin %PluginData->Name% installed in %PluginFile%'),
|
112 |
+
array(5003, E_CRITICAL, 'User uninstalled a plugin', 'Uninstalled the plugin %PluginData->Name% which was installed in %PluginFile%'),
|
113 |
+
array(5004, E_WARNING, 'User upgraded a plugin', 'Upgraded the plugin %PluginData->Name% installed in %PluginFile%'),
|
114 |
+
array(5005, E_CRITICAL, 'User installed a theme', 'Installed theme "%NewTheme->Name%" in %NewTheme->get_template_directory%'),
|
115 |
+
array(5006, E_CRITICAL, 'User activated a theme', 'Activated theme "%NewTheme->Name%", installed in %NewTheme->get_template_directory%'),
|
116 |
+
),
|
117 |
+
'System Activity' => array(
|
118 |
+
array(0000, E_CRITICAL, 'Unknown Error', 'An unexpected error has occurred'),
|
119 |
+
array(0001, E_CRITICAL, 'PHP error', '%Message%'),
|
120 |
+
array(0002, E_WARNING, 'PHP warning', '%Message%'),
|
121 |
+
array(0003, E_NOTICE, 'PHP notice', '%Message%'),
|
122 |
+
array(0004, E_CRITICAL, 'PHP exception', '%Message%'),
|
123 |
+
array(0005, E_CRITICAL, 'PHP shutdown error', '%Message%'),
|
124 |
+
array(6000, E_NOTICE, 'Events automatically pruned by system', '%EventCount% event(s) automatically deleted by system'),
|
125 |
+
array(6001, E_CRITICAL, 'Option Anyone Can Register in WordPress settings changed', '%NewValue% the option "Anyone can register"'),
|
126 |
+
array(6002, E_CRITICAL, 'New User Default Role changed', 'Changed the New User Default Role from %OldRole% to %NewRole%'),
|
127 |
+
array(6003, E_CRITICAL, 'WordPress Administrator Notification email changed', 'Changed the WordPress administrator notifications email address from %OldEmail% to %NewEmail%'),
|
128 |
+
array(6004, E_CRITICAL, 'WordPress was updated', 'Updated WordPress from version %OldVersion% to %NewVersion%'),
|
129 |
+
array(6005, E_CRITICAL, 'User changes the WordPress Permalinks', 'Changed the WordPress permalinks from %OldPattern% to %NewPattern%'),
|
130 |
+
),
|
131 |
+
'MultiSite' => array(
|
132 |
+
array(4008, E_CRITICAL, 'User granted Super Admin privileges', 'Granted Super Admin privileges to %TargetUsername%'),
|
133 |
+
array(4009, E_CRITICAL, 'User revoked from Super Admin privileges', 'Revoked Super Admin privileges from %TargetUsername%'),
|
134 |
+
array(4010, E_CRITICAL, 'Existing user added to a site', 'Added existing user %Username% with %UserRole% role to site %SiteName%'),
|
135 |
+
array(4011, E_CRITICAL, 'User removed from site', 'Removed user %Username% with role %UserRole% from %SiteName% site'),
|
136 |
+
array(4012, E_CRITICAL, 'New network user created', 'Created a new network user %NewUserData->Username%'),
|
137 |
+
array(7000, E_CRITICAL, 'New site added on network', 'Added site %SiteName% to the network'),
|
138 |
+
array(7001, E_CRITICAL, 'Existing site archived', 'Archived site %SiteName%'),
|
139 |
+
array(7002, E_CRITICAL, 'Archived site has been unarchived', 'Unarchived site %SiteName%'),
|
140 |
+
array(7003, E_CRITICAL, 'Deactivated site has been activated', 'Activated site %SiteName%'),
|
141 |
+
array(7004, E_CRITICAL, 'Site has been deactivated', 'Deactivated site %SiteName%'),
|
142 |
+
array(7005, E_CRITICAL, 'Existing site deleted from network', 'Deleted site %SiteName%'),
|
143 |
+
),
|
144 |
+
));
|
{res/img → img}/logo-main-menu.png
RENAMED
File without changes
|
inc/WPPH.php
DELETED
@@ -1,513 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Base class
|
4 |
-
*/
|
5 |
-
class WPPH
|
6 |
-
{
|
7 |
-
/**
|
8 |
-
* The required user capability to display the menu
|
9 |
-
* @since v0.5
|
10 |
-
* @var string
|
11 |
-
*/
|
12 |
-
static $requiredCapMenu = 'read';
|
13 |
-
/**
|
14 |
-
* @since v0.5
|
15 |
-
* @var string
|
16 |
-
*/
|
17 |
-
static $baseMenuSlug = WPPH_PLUGIN_PREFIX;
|
18 |
-
|
19 |
-
static function loadTextDomain()
|
20 |
-
{
|
21 |
-
load_plugin_textdomain(WPPH_PLUGIN_TEXT_DOMAIN, false, WPPH_PLUGIN_DIR.'languages/');
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @since v0.5
|
26 |
-
* Retrieve the list of all events to display in the enable/disable alerts page
|
27 |
-
* @return array
|
28 |
-
*/
|
29 |
-
static function getDefaultEvents()
|
30 |
-
{
|
31 |
-
return array(
|
32 |
-
'Other_User_Activity' => array(
|
33 |
-
1000 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User logs in',WPPH_PLUGIN_TEXT_DOMAIN)),
|
34 |
-
1001 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User Logs out',WPPH_PLUGIN_TEXT_DOMAIN)),
|
35 |
-
1002 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('Failed login detected',WPPH_PLUGIN_TEXT_DOMAIN)),
|
36 |
-
2010 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User uploaded a file to the uploads directory',WPPH_PLUGIN_TEXT_DOMAIN)),
|
37 |
-
2011 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User deleted a file from the uploads directory',WPPH_PLUGIN_TEXT_DOMAIN)),
|
38 |
-
),
|
39 |
-
'Pages' => array(
|
40 |
-
2004 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User created a new WordPress page and saved it as draft',WPPH_PLUGIN_TEXT_DOMAIN)),
|
41 |
-
2005 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User published a WorPress page',WPPH_PLUGIN_TEXT_DOMAIN)),
|
42 |
-
2006 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User modified a published WordPress page',WPPH_PLUGIN_TEXT_DOMAIN)),
|
43 |
-
2007 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User modified a draft WordPress page',WPPH_PLUGIN_TEXT_DOMAIN)),
|
44 |
-
2009 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User permanently deleted a page from the trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
45 |
-
2013 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User moved WordPress page to the trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
46 |
-
2015 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User restored a WordPress page from trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
47 |
-
2018 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed page URL',WPPH_PLUGIN_TEXT_DOMAIN)),
|
48 |
-
2020 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed page author',WPPH_PLUGIN_TEXT_DOMAIN)),
|
49 |
-
2022 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed page status',WPPH_PLUGIN_TEXT_DOMAIN)),
|
50 |
-
2026 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User changed the visibility of a page',WPPH_PLUGIN_TEXT_DOMAIN)),
|
51 |
-
2028 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed the date of a page post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
52 |
-
),
|
53 |
-
'Blog_Posts' => array(
|
54 |
-
2000 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User created a new blog post and saved it as draft',WPPH_PLUGIN_TEXT_DOMAIN)),
|
55 |
-
2001 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User published a blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
56 |
-
2002 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User modified a published blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
57 |
-
2003 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User modified a draft blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
58 |
-
2008 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User permanently deleted a blog post from the trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
59 |
-
2012 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User moved a blog post to the trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
60 |
-
2014 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User restored a blog post from trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
61 |
-
2016 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed blog post category',WPPH_PLUGIN_TEXT_DOMAIN)),
|
62 |
-
2017 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed blog post URL',WPPH_PLUGIN_TEXT_DOMAIN)),
|
63 |
-
2019 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed blog post author',WPPH_PLUGIN_TEXT_DOMAIN)),
|
64 |
-
2021 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed blog post status',WPPH_PLUGIN_TEXT_DOMAIN)),
|
65 |
-
2023 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User created new category',WPPH_PLUGIN_TEXT_DOMAIN)),
|
66 |
-
2024 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User deleted a category',WPPH_PLUGIN_TEXT_DOMAIN)),
|
67 |
-
2025 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User changed the visibility of a blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
68 |
-
2027 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed the date of a blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
69 |
-
),
|
70 |
-
'Custom_Posts' => array(
|
71 |
-
2029 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User created a new custom blog post and saved it as draft',WPPH_PLUGIN_TEXT_DOMAIN)),
|
72 |
-
2030 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User published a custom blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
73 |
-
2031 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User modified a published custom blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
74 |
-
2032 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User modified a draft custom blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
75 |
-
2033 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User permanently deleted a custom blog post from the trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
76 |
-
2034 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User moved a custom blog post to the trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
77 |
-
2035 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User restored a custom blog post from trash',WPPH_PLUGIN_TEXT_DOMAIN)),
|
78 |
-
2036 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed custom blog post category',WPPH_PLUGIN_TEXT_DOMAIN)),
|
79 |
-
2037 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed custom blog post URL',WPPH_PLUGIN_TEXT_DOMAIN)),
|
80 |
-
2038 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed custom blog post author',WPPH_PLUGIN_TEXT_DOMAIN)),
|
81 |
-
2039 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed custom blog post status',WPPH_PLUGIN_TEXT_DOMAIN)),
|
82 |
-
2040 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User changed the visibility of a custom blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
83 |
-
2041 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User changed the date of a custom blog post',WPPH_PLUGIN_TEXT_DOMAIN)),
|
84 |
-
),
|
85 |
-
'Users_Profiles' => array(
|
86 |
-
4000 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('A new user was created on WordPress',WPPH_PLUGIN_TEXT_DOMAIN)),
|
87 |
-
4001 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('A user created another WordPress user',WPPH_PLUGIN_TEXT_DOMAIN)),
|
88 |
-
4002 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('The role of a user was changed by another WordPress user',WPPH_PLUGIN_TEXT_DOMAIN)),
|
89 |
-
4003 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User has changed his or her password',WPPH_PLUGIN_TEXT_DOMAIN)),
|
90 |
-
4004 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('A user changed another user\'s password',WPPH_PLUGIN_TEXT_DOMAIN)),
|
91 |
-
4005 => array('type' => WPPH_E_NOTICE_TEXT,'text' => __('User changed his or her email address',WPPH_PLUGIN_TEXT_DOMAIN)),
|
92 |
-
4006 => array('type' => WPPH_E_NOTICE_TEXT,'text' => __('A user changed another user\'s email address',WPPH_PLUGIN_TEXT_DOMAIN)),
|
93 |
-
4007 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('A user was deleted by another user',WPPH_PLUGIN_TEXT_DOMAIN)),
|
94 |
-
),
|
95 |
-
'Widgets' => array(
|
96 |
-
2042 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User added a new widget',WPPH_PLUGIN_TEXT_DOMAIN)),
|
97 |
-
2043 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User modified a widget',WPPH_PLUGIN_TEXT_DOMAIN)),
|
98 |
-
2044 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User deleted a widget',WPPH_PLUGIN_TEXT_DOMAIN)),
|
99 |
-
2045 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User moved a widget',WPPH_PLUGIN_TEXT_DOMAIN)),
|
100 |
-
),
|
101 |
-
'Themes' => array(
|
102 |
-
3000 => array('type' => WPPH_E_NOTICE_TEXT, 'text' => __('User activated a theme.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
103 |
-
),
|
104 |
-
'Plugins' => array(
|
105 |
-
5000 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User installed a plugin',WPPH_PLUGIN_TEXT_DOMAIN)),
|
106 |
-
5001 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User activated a WordPress plugin',WPPH_PLUGIN_TEXT_DOMAIN)),
|
107 |
-
5002 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User deactivated a WordPress plugin',WPPH_PLUGIN_TEXT_DOMAIN)),
|
108 |
-
5003 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User uninstalled a plugin',WPPH_PLUGIN_TEXT_DOMAIN)),
|
109 |
-
5004 => array('type' => WPPH_E_WARNING_TEXT, 'text' => __('User upgraded a plugin',WPPH_PLUGIN_TEXT_DOMAIN)),
|
110 |
-
),
|
111 |
-
'Settings_And_System_Activity' => array(
|
112 |
-
6000 => array('type' => WPPH_E_NOTICE_TEXT,'text' => __('Security alerts automatically pruned by system',WPPH_PLUGIN_TEXT_DOMAIN)),
|
113 |
-
6001 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Option Anyone Can Register in WordPress settings changed',WPPH_PLUGIN_TEXT_DOMAIN)),
|
114 |
-
6002 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('New User Default Role changed',WPPH_PLUGIN_TEXT_DOMAIN)),
|
115 |
-
6003 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('WordPress Administrator Notification email changed',WPPH_PLUGIN_TEXT_DOMAIN))
|
116 |
-
),
|
117 |
-
'MultiSite' => array(
|
118 |
-
4008 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Granted Super Admin privileges to user',WPPH_PLUGIN_TEXT_DOMAIN)),
|
119 |
-
4009 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Revoked Super Admin privileges from user',WPPH_PLUGIN_TEXT_DOMAIN)),
|
120 |
-
4010 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Existent user added to site',WPPH_PLUGIN_TEXT_DOMAIN)),
|
121 |
-
4011 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('User removed from site',WPPH_PLUGIN_TEXT_DOMAIN)),
|
122 |
-
4012 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('New network user created',WPPH_PLUGIN_TEXT_DOMAIN)),
|
123 |
-
7000 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Site added to network',WPPH_PLUGIN_TEXT_DOMAIN)),
|
124 |
-
7001 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Site archived',WPPH_PLUGIN_TEXT_DOMAIN)),
|
125 |
-
7002 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Site unarchived',WPPH_PLUGIN_TEXT_DOMAIN)),
|
126 |
-
7003 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Site activated',WPPH_PLUGIN_TEXT_DOMAIN)),
|
127 |
-
7004 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Site deactivated',WPPH_PLUGIN_TEXT_DOMAIN)),
|
128 |
-
7005 => array('type' => WPPH_E_HIGH_TEXT, 'text' => __('Site deleted',WPPH_PLUGIN_TEXT_DOMAIN)),
|
129 |
-
),
|
130 |
-
);
|
131 |
-
}
|
132 |
-
|
133 |
-
|
134 |
-
/**
|
135 |
-
* @return bool
|
136 |
-
* Convenient method to check whether or not the plugin's resources can be loaded
|
137 |
-
*/
|
138 |
-
public static function canLoad() { return ((false === ($pos = stripos($_SERVER['REQUEST_URI'], WPPH_PLUGIN_PREFIX))) ? false : true); }
|
139 |
-
|
140 |
-
public static function loadBaseResources()
|
141 |
-
{
|
142 |
-
if(self::canLoad())
|
143 |
-
{
|
144 |
-
wp_enqueue_style('wpph_styles_base', WPPH_PLUGIN_URL . 'res/css/styles.base.css');
|
145 |
-
wp_enqueue_script('wpph-alvm-js', WPPH_PLUGIN_URL . 'res/js/audit-view-model.js', array('wpph-jcookie-js', 'wpph-ko-js'));
|
146 |
-
wp_enqueue_script('wpph-ko-js', WPPH_PLUGIN_URL . 'res/js/knockout.js', array('jquery'));
|
147 |
-
wp_enqueue_script('wpph-jcookie-js', WPPH_PLUGIN_URL . 'res/js/jquery-ck.js', array('jquery'));
|
148 |
-
}
|
149 |
-
}
|
150 |
-
|
151 |
-
public static function createPluginWpSidebar()
|
152 |
-
{
|
153 |
-
$reqCap = self::$requiredCapMenu;
|
154 |
-
|
155 |
-
if (!function_exists('add_menu_page'))
|
156 |
-
{
|
157 |
-
wpphLog('The required function "add_menu_page" to create the menu is not available on this installation.');
|
158 |
-
return;
|
159 |
-
}
|
160 |
-
|
161 |
-
if(WPPHUtil::isAdministrator(wp_get_current_user()->ID)){
|
162 |
-
self::_createMenu($reqCap, true, true, true);
|
163 |
-
}
|
164 |
-
elseif (WPPHUtil::isAllowedChange()){
|
165 |
-
self::_createMenu($reqCap, true, true);
|
166 |
-
}
|
167 |
-
elseif(WPPHUtil::isAllowedAccess()){
|
168 |
-
self::_createMenu($reqCap, true);
|
169 |
-
}
|
170 |
-
}
|
171 |
-
|
172 |
-
private static function _createMenu($reqCap, $allowedAccess = false, $allowedChange = false, $isAdministrator = false)
|
173 |
-
{
|
174 |
-
if($isAdministrator || $allowedChange){
|
175 |
-
add_menu_page('WP Security Audit Log', 'WP Security Audit Log', $reqCap, self::$baseMenuSlug, 'WPPH::pageMain', WPPH_PLUGIN_URL.'res/img/logo-main-menu.png');
|
176 |
-
add_submenu_page(self::$baseMenuSlug, 'Audit Log Viewer', 'Audit Log Viewer', $reqCap, self::$baseMenuSlug, 'WPPH::pageMain');
|
177 |
-
if(WPPHUtil::isMainSite()){
|
178 |
-
add_submenu_page(self::$baseMenuSlug, __('Settings',WPPH_PLUGIN_TEXT_DOMAIN), __('Settings',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'settings', 'WPPH::pageSettings');
|
179 |
-
add_submenu_page(self::$baseMenuSlug, __('Enable/Disable Alerts',WPPH_PLUGIN_TEXT_DOMAIN), __('Enable/Disable Alerts',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'alerts', 'WPPH::pageAlerts');
|
180 |
-
}
|
181 |
-
else {
|
182 |
-
if(WPPHUtil::isAllowedChange()){
|
183 |
-
add_submenu_page(self::$baseMenuSlug, __('Settings',WPPH_PLUGIN_TEXT_DOMAIN), __('Settings',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'settings', 'WPPH::pageSettings');
|
184 |
-
add_submenu_page(self::$baseMenuSlug, __('Enable/Disable Alerts',WPPH_PLUGIN_TEXT_DOMAIN), __('Enable/Disable Alerts',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'alerts', 'WPPH::pageAlerts');
|
185 |
-
}
|
186 |
-
}
|
187 |
-
add_submenu_page(self::$baseMenuSlug, __('About',WPPH_PLUGIN_TEXT_DOMAIN), __('About',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'about', 'WPPH::pageAbout');
|
188 |
-
add_submenu_page(self::$baseMenuSlug, __('Support',WPPH_PLUGIN_TEXT_DOMAIN), __('Support',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'support', 'WPPH::pageSupport');
|
189 |
-
}
|
190 |
-
elseif($allowedAccess){
|
191 |
-
add_menu_page('WP Security Audit Log', 'WP Security Audit Log', $reqCap, self::$baseMenuSlug, 'WPPH::pageMain', WPPH_PLUGIN_URL.'res/img/logo-main-menu.png');
|
192 |
-
add_submenu_page(self::$baseMenuSlug, 'Audit Log Viewer', 'Audit Log Viewer', $reqCap, self::$baseMenuSlug, 'WPPH::pageMain');
|
193 |
-
if(WPPHUtil::isAllowedChange()){
|
194 |
-
add_submenu_page(self::$baseMenuSlug, __('Settings',WPPH_PLUGIN_TEXT_DOMAIN), __('Settings',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'settings', 'WPPH::pageSettings');
|
195 |
-
add_submenu_page(self::$baseMenuSlug, __('Enable/Disable Alerts',WPPH_PLUGIN_TEXT_DOMAIN), __('Enable/Disable Alerts',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'alerts', 'WPPH::pageAlerts');
|
196 |
-
}
|
197 |
-
add_submenu_page(self::$baseMenuSlug, __('About',WPPH_PLUGIN_TEXT_DOMAIN), __('About',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'about', 'WPPH::pageAbout');
|
198 |
-
add_submenu_page(self::$baseMenuSlug, __('Support',WPPH_PLUGIN_TEXT_DOMAIN), __('Support',WPPH_PLUGIN_TEXT_DOMAIN), $reqCap, self::$baseMenuSlug.'support', 'WPPH::pageSupport');
|
199 |
-
}
|
200 |
-
}
|
201 |
-
|
202 |
-
public static function pageMain() { include(WPPH_PLUGIN_DIR.'pages/dashboard.php'); }
|
203 |
-
public static function pageSettings() { include(WPPH_PLUGIN_DIR.'pages/settings.php'); }
|
204 |
-
public static function pageAlerts() {
|
205 |
-
wp_enqueue_style('jquery-smoothness-ui-css', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/themes/smoothness/jquery-ui.css');
|
206 |
-
wp_enqueue_script('jquery-ui-core');
|
207 |
-
wp_enqueue_script('jquery-ui-tabs');
|
208 |
-
include(WPPH_PLUGIN_DIR.'pages/alerts.php');
|
209 |
-
}
|
210 |
-
public static function pageAbout() { include(WPPH_PLUGIN_DIR.'pages/about.php'); }
|
211 |
-
public static function pageSupport() { include(WPPH_PLUGIN_DIR.'pages/support.php'); }
|
212 |
-
|
213 |
-
/**
|
214 |
-
* @since v0.5
|
215 |
-
* Create, save and retrieve the default list of events
|
216 |
-
* @return array
|
217 |
-
*/
|
218 |
-
public static function createDefaultEventsList()
|
219 |
-
{
|
220 |
-
$alerts = array();
|
221 |
-
$events = self::getDefaultEvents();
|
222 |
-
if(!empty($events)){
|
223 |
-
foreach($events as $section => $values){
|
224 |
-
$alerts[$section] = array();
|
225 |
-
$_events = array_keys($values);
|
226 |
-
if(! empty($_events)){
|
227 |
-
foreach($_events as $k){
|
228 |
-
$alerts[$section][$k] = 1;
|
229 |
-
}
|
230 |
-
}
|
231 |
-
}
|
232 |
-
}
|
233 |
-
wpph_updatePluginEventsList($alerts);
|
234 |
-
return $alerts;
|
235 |
-
}
|
236 |
-
|
237 |
-
/**
|
238 |
-
* @since v0.5
|
239 |
-
* Retrieve the list of all events from database
|
240 |
-
* @return array
|
241 |
-
*/
|
242 |
-
static function getEvents(){
|
243 |
-
$events = wpph_getPluginEventsList();
|
244 |
-
if(false === $events){
|
245 |
-
$events = self::createDefaultEventsList();
|
246 |
-
}
|
247 |
-
return $events;
|
248 |
-
}
|
249 |
-
|
250 |
-
public static function createPluginDefaultSettings()
|
251 |
-
{
|
252 |
-
$settings = new stdClass();
|
253 |
-
$settings->daysToKeep = 0;
|
254 |
-
$settings->eventsToKeep = WPPH_KEEP_MAX_EVENTS; // default delete option
|
255 |
-
$settings->showEventsViewList = 50; // how many items to show in the event viewer by default
|
256 |
-
$settings->lastCleanup = time();
|
257 |
-
$settings->cleanupRan = 0;
|
258 |
-
$settings->showDW = 1; // whether or not to show the dashboard widget. @since v0.4
|
259 |
-
|
260 |
-
update_option(WPPH_PLUGIN_SETTING_NAME, $settings);
|
261 |
-
self::createDefaultEventsList();
|
262 |
-
wpphLog('Settings added.');
|
263 |
-
return $settings;
|
264 |
-
}
|
265 |
-
public static function getPluginSettings()
|
266 |
-
{
|
267 |
-
$settings = get_option(WPPH_PLUGIN_SETTING_NAME);
|
268 |
-
if(false == $settings){
|
269 |
-
$settings = self::createPluginDefaultSettings();
|
270 |
-
}
|
271 |
-
return $settings;
|
272 |
-
}
|
273 |
-
|
274 |
-
/**
|
275 |
-
* @param object $settings If this param is null, $settingName & $settingValue(this cannot be null) must be set
|
276 |
-
* @param string $settingName Optional. Required if $settings is null
|
277 |
-
* @param string $settingValue Optional. Required if $settings is null
|
278 |
-
* @param bool $overrideCleanupRan Whether or not to override the cleanupRan option. Defaults to false
|
279 |
-
*/
|
280 |
-
public static function updatePluginSettings($settings = null, $settingName = null, $settingValue=null, $overrideCleanupRan = false)
|
281 |
-
{
|
282 |
-
if(! is_null($settings)){
|
283 |
-
if($overrideCleanupRan){
|
284 |
-
$settings->lastCleanup = 0;
|
285 |
-
$settings->cleanupRan = 0;
|
286 |
-
}
|
287 |
-
update_option(WPPH_PLUGIN_SETTING_NAME, $settings);
|
288 |
-
return;
|
289 |
-
}
|
290 |
-
|
291 |
-
// name and value must be set!
|
292 |
-
if(is_null($settingName) || is_null($settingValue)){
|
293 |
-
return;
|
294 |
-
}
|
295 |
-
|
296 |
-
$settings = self::getPluginSettings();
|
297 |
-
$settings->$settingName = $settingValue;
|
298 |
-
if($overrideCleanupRan){
|
299 |
-
$settings->lastCleanup = 0;
|
300 |
-
$settings->cleanupRan = 0;
|
301 |
-
}
|
302 |
-
update_option(WPPH_PLUGIN_SETTING_NAME, $settings);
|
303 |
-
wpphLog('Settings saved.', $settings);
|
304 |
-
}
|
305 |
-
|
306 |
-
public static function onPluginActivate($blogId=1)
|
307 |
-
{
|
308 |
-
if($blogId > 1){
|
309 |
-
return true;
|
310 |
-
}
|
311 |
-
|
312 |
-
wpphLog(__METHOD__.'() triggered.');
|
313 |
-
|
314 |
-
$canContinue = true;
|
315 |
-
|
316 |
-
// Check: MySQL, PHP - without these there's not much left for this plugin to do
|
317 |
-
if(! self::checkMySQL()){
|
318 |
-
self::__addPluginError(__("Plugin could not be properly installed. The MySQL version installed on this server is less than 5.",WPPH_PLUGIN_TEXT_DOMAIN));
|
319 |
-
$canContinue = false;
|
320 |
-
}
|
321 |
-
if(! self::checkPHP()){
|
322 |
-
self::__addPluginError(__("Plugin could not be properly installed. The PHP version installed on this server is less than 5.",WPPH_PLUGIN_TEXT_DOMAIN));
|
323 |
-
$canContinue = false;
|
324 |
-
}
|
325 |
-
// no need for further checks, the plugin cannot run on this server...
|
326 |
-
if(! $canContinue){
|
327 |
-
$GLOBALS['WPPH_CAN_RUN'] = false;
|
328 |
-
self::__addPluginError(__("Plugin could not be properly installed because the server does not meet our requirements: MySQL and PHP version >= 5.",WPPH_PLUGIN_TEXT_DOMAIN));
|
329 |
-
return false;
|
330 |
-
}
|
331 |
-
|
332 |
-
// check to see whether or not an upgrade is necessary
|
333 |
-
global $wpdb;
|
334 |
-
$dbUpdated = get_option(WPPH_PLUGIN_DB_UPDATED);
|
335 |
-
$tablesExist = false;
|
336 |
-
$triggerInstallEvent = false; // whether or not the plugin is installed
|
337 |
-
$pluginDbVersion = get_option(WPPH_PLUGIN_VERSION_OPTION_NAME);
|
338 |
-
|
339 |
-
delete_option(WPPH_PLUGIN_ERROR_OPTION_NAME);
|
340 |
-
|
341 |
-
// first install?
|
342 |
-
if($pluginDbVersion === false){
|
343 |
-
// Check tables
|
344 |
-
if(WPPHDatabase::tableExists($wpdb, WPPHDatabase::getFullTableName('MAIN')) || WPPHDatabase::tableExists($wpdb, WPPHDatabase::getFullTableName('EVENTS'))){
|
345 |
-
$tablesExist = true;
|
346 |
-
}
|
347 |
-
else { $triggerInstallEvent = true; }
|
348 |
-
}
|
349 |
-
|
350 |
-
// if we need to install
|
351 |
-
if($triggerInstallEvent)
|
352 |
-
{
|
353 |
-
if($dbUpdated){ delete_option(WPPH_PLUGIN_DB_UPDATED); }
|
354 |
-
if(WPPHDatabase::handleDatabase()){
|
355 |
-
self::__handlePluginActivation(true);
|
356 |
-
return true;
|
357 |
-
}
|
358 |
-
else {
|
359 |
-
self::__addPluginError(__("Plugin could not be properly installed because we have encountered errors during the database update.",WPPH_PLUGIN_TEXT_DOMAIN));
|
360 |
-
return false;
|
361 |
-
}
|
362 |
-
}
|
363 |
-
// plugin already installed
|
364 |
-
else
|
365 |
-
{
|
366 |
-
// if tables exist - do update database
|
367 |
-
if($tablesExist)
|
368 |
-
{
|
369 |
-
// check plugin version
|
370 |
-
if(empty($pluginDbVersion))
|
371 |
-
{
|
372 |
-
if($dbUpdated){ delete_option(WPPH_PLUGIN_DB_UPDATED); }
|
373 |
-
// maybe version 0.1 ? empty tables
|
374 |
-
if(! WPPHDatabase::v2Cleanup()){
|
375 |
-
self::__addPluginError(__("Plugin could not be properly installed because we have encountered errors during the database update.",WPPH_PLUGIN_TEXT_DOMAIN));
|
376 |
-
return false;
|
377 |
-
}
|
378 |
-
// update database
|
379 |
-
if(WPPHDatabase::handleDatabase()){
|
380 |
-
self::__handlePluginActivation();
|
381 |
-
return true;
|
382 |
-
}
|
383 |
-
else {
|
384 |
-
self::__addPluginError(__("Plugin could not be properly installed because we have encountered errors during the database update.",WPPH_PLUGIN_TEXT_DOMAIN));
|
385 |
-
return false;
|
386 |
-
}
|
387 |
-
}
|
388 |
-
else {
|
389 |
-
$pluginDbVersion = (float)$pluginDbVersion;
|
390 |
-
$currentVersion = (float)WPPH_PLUGIN_VERSION;
|
391 |
-
// no need for upgrade
|
392 |
-
if(version_compare($pluginDbVersion, $currentVersion, '==')){
|
393 |
-
self::__handlePluginActivation();
|
394 |
-
return true;
|
395 |
-
}
|
396 |
-
}
|
397 |
-
}
|
398 |
-
// tables not found
|
399 |
-
else {
|
400 |
-
if($dbUpdated){ delete_option(WPPH_PLUGIN_DB_UPDATED); }
|
401 |
-
// create them
|
402 |
-
if(WPPHDatabase::handleDatabase()){
|
403 |
-
self::__handlePluginActivation();
|
404 |
-
return true;
|
405 |
-
}
|
406 |
-
else {
|
407 |
-
self::__addPluginError(__("Plugin could not be properly installed because we have encountered errors during the database update.",WPPH_PLUGIN_TEXT_DOMAIN));
|
408 |
-
return false;
|
409 |
-
}
|
410 |
-
}
|
411 |
-
}
|
412 |
-
return false;
|
413 |
-
}
|
414 |
-
|
415 |
-
/**
|
416 |
-
* Triggered when the plugin is deactivated
|
417 |
-
* @param int $blogId
|
418 |
-
* @return bool true
|
419 |
-
*/
|
420 |
-
public static function onPluginDeactivate($blogId=1)
|
421 |
-
{
|
422 |
-
wpphLog(__FUNCTION__.'() triggered.');
|
423 |
-
wp_clear_scheduled_hook(WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME);
|
424 |
-
delete_option(WPPH_PLUGIN_ERROR_OPTION_NAME);
|
425 |
-
update_option('WPPH_PLUGIN_ACTIVATED',0);
|
426 |
-
return true;
|
427 |
-
}
|
428 |
-
|
429 |
-
public static function __addPluginError($error)
|
430 |
-
{
|
431 |
-
$data = get_option(WPPH_PLUGIN_ERROR_OPTION_NAME);
|
432 |
-
if(empty($data)){
|
433 |
-
$data = array();
|
434 |
-
}
|
435 |
-
$data[] = base64_encode($error);
|
436 |
-
update_option(WPPH_PLUGIN_ERROR_OPTION_NAME, $data);
|
437 |
-
return true;
|
438 |
-
}
|
439 |
-
|
440 |
-
private static function __handlePluginActivation($triggerInstallEvent = false)
|
441 |
-
{
|
442 |
-
self::getPluginSettings();
|
443 |
-
|
444 |
-
$GLOBALS['WPPH_CAN_RUN'] = true;
|
445 |
-
update_option(WPPH_PLUGIN_DB_UPDATED,1);
|
446 |
-
delete_option(WPPH_PLUGIN_ERROR_OPTION_NAME);
|
447 |
-
update_option(WPPH_PLUGIN_VERSION_OPTION_NAME, WPPH_PLUGIN_VERSION);
|
448 |
-
WPPHUtil::saveInitialAccessChangeList();
|
449 |
-
if($triggerInstallEvent)
|
450 |
-
{
|
451 |
-
if(! defined('WPPH_PLUGIN_INSTALLED_OK')) {
|
452 |
-
//@see: WPPHEventWatcher::watchPluginInstall()
|
453 |
-
define('WPPH_PLUGIN_INSTALLED_OK',true);
|
454 |
-
}
|
455 |
-
// log plugin installation
|
456 |
-
wpph_installPlugin(WPPH_PLUGIN_NAME, wp_get_current_user()->ID, WPPHUtil::getIP());
|
457 |
-
}
|
458 |
-
// log plugin activation
|
459 |
-
WPPHEvent::hookWatchPluginActivity();
|
460 |
-
|
461 |
-
// register cron job for events deletion
|
462 |
-
if(defined('DISABLE_WP_CRON') && DISABLE_WP_CRON){ return true; }
|
463 |
-
else
|
464 |
-
{
|
465 |
-
if ( ! wp_next_scheduled(WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME)) {
|
466 |
-
$interval = (defined('WPPH_CLEANUP_INTERVAL') ? WPPH_CLEANUP_INTERVAL : 'hourly');
|
467 |
-
wp_schedule_event( time(), $interval, WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME );
|
468 |
-
wpphLog(__METHOD__.'() '.WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME.' task scheduled by wp-cron. Time Interval set to: '.$interval);
|
469 |
-
}
|
470 |
-
}
|
471 |
-
}
|
472 |
-
/**
|
473 |
-
* @internal
|
474 |
-
* @static
|
475 |
-
* @var array Holds the list or errors generated during install
|
476 |
-
*/
|
477 |
-
private static $_errors = array();
|
478 |
-
|
479 |
-
// must only be called in pages
|
480 |
-
public static function ready()
|
481 |
-
{
|
482 |
-
if(empty(self::$_errors)){
|
483 |
-
self::$_errors = self::getPluginErrors();
|
484 |
-
if(empty(self::$_errors)){
|
485 |
-
return true;
|
486 |
-
}
|
487 |
-
}
|
488 |
-
return false;
|
489 |
-
}
|
490 |
-
|
491 |
-
public static function getPluginErrors() { return get_option(WPPH_PLUGIN_ERROR_OPTION_NAME); }
|
492 |
-
|
493 |
-
public static function checkMySQL(){
|
494 |
-
global $wpdb;
|
495 |
-
$v = $wpdb->get_var("SELECT VERSION();");
|
496 |
-
if(empty($v)){ return false; }
|
497 |
-
$v = trim($v);
|
498 |
-
if(intval($v[0]) < 5){ return false; }
|
499 |
-
return true;
|
500 |
-
}
|
501 |
-
public static function checkPHP(){ return (version_compare(phpversion(), '5.0.0', '>=')); }
|
502 |
-
|
503 |
-
|
504 |
-
/**
|
505 |
-
* Check to see whether or not this is a multisite instance
|
506 |
-
* @since v0.6
|
507 |
-
* @return bool
|
508 |
-
*/
|
509 |
-
static function isMultisite(){ return ((function_exists('is_multisite') && is_multisite()) ? true : false); }
|
510 |
-
|
511 |
-
}
|
512 |
-
|
513 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/WPPHDatabase.php
DELETED
@@ -1,385 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Class WPPHDatabase
|
4 |
-
* Internal class handling the creation, update and upgrade of the db tables
|
5 |
-
*/
|
6 |
-
class WPPHDatabase
|
7 |
-
{
|
8 |
-
/**
|
9 |
-
* @var bool
|
10 |
-
* Whether or not we can safely use the plugin
|
11 |
-
*/
|
12 |
-
private static $_canRun = false;
|
13 |
-
|
14 |
-
private static $_canUpgrade = false;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @var string
|
18 |
-
* @private
|
19 |
-
* Holds the name of the event logs table WITHOUT the db prefix. As of version 0.6 it has been changed to: wordpress_auditlog
|
20 |
-
*/
|
21 |
-
private static $_eventsLogTableBaseName = 'wordpress_auditlog'; //old: {prefix}_wordpress_eventlog
|
22 |
-
|
23 |
-
/**
|
24 |
-
* @var string
|
25 |
-
* @private
|
26 |
-
* Holds the name of the events details table WITHOUT the db prefix. As of version 0.6 it has been changed to: wordpress_auditlog_events
|
27 |
-
*/
|
28 |
-
private static $_eventsDetailsTableBaseName = 'wordpress_auditlog_events'; //old: {prefix}_wordpress_eventlog_details
|
29 |
-
|
30 |
-
|
31 |
-
private static $_tablesCreated = false;
|
32 |
-
private static $_tablesUpgraded = false;
|
33 |
-
private static $_tablesUpdated = false;
|
34 |
-
|
35 |
-
|
36 |
-
//================================================================================================================
|
37 |
-
|
38 |
-
// since v0.6
|
39 |
-
static function dropTables()
|
40 |
-
{
|
41 |
-
$version = WPPHNetwork::getGlobalOption(WPPH_PLUGIN_VERSION_OPTION_NAME, false, true, null);
|
42 |
-
if(is_null($version)){
|
43 |
-
return;
|
44 |
-
}
|
45 |
-
if(version_compare($version,'0.6','>=')){
|
46 |
-
return;
|
47 |
-
}
|
48 |
-
|
49 |
-
global $wpdb;
|
50 |
-
if(self::tableExists($wpdb, self::getFullTableName('MAIN')) && self::tableExists($wpdb, self::getFullTableName('EVENTS'))){
|
51 |
-
return;
|
52 |
-
}
|
53 |
-
|
54 |
-
WPPHNetwork::updateGlobalOption(WPPH_PLUGIN_DB_UPDATED, 0, false, true);
|
55 |
-
$prefix = (WPPH::isMultisite() ? self::getDefaultPrefix() : $wpdb->prefix);
|
56 |
-
|
57 |
-
$tMainOld = $prefix.'_wordpress_eventlog';
|
58 |
-
$tEventsOld = $prefix.'_wordpress_eventlog_details';
|
59 |
-
|
60 |
-
if(self::tableExists($wpdb, $tMainOld)){
|
61 |
-
$q = "DROP TABLE IF EXISTS {$tMainOld}";
|
62 |
-
$r = $wpdb->query($q);
|
63 |
-
wpphLog("Old table {$tMainOld} found. Deleting table.", array('query'=>$q, 'result'=> $r===true?'success':'failed'));
|
64 |
-
}
|
65 |
-
if(self::tableExists($wpdb, $tEventsOld)){
|
66 |
-
$q = "DROP TABLE IF EXISTS {$tEventsOld}";
|
67 |
-
$r = $wpdb->query($q);
|
68 |
-
wpphLog("Old table {$tEventsOld} found. Deleting table.", array('query'=>$q, 'result'=> $r===true?'success':'failed'));
|
69 |
-
}
|
70 |
-
}
|
71 |
-
|
72 |
-
|
73 |
-
static function handleDatabase()
|
74 |
-
{
|
75 |
-
// Check database
|
76 |
-
$dbUpdated = get_option(WPPH_PLUGIN_DB_UPDATED);
|
77 |
-
if(false !== $dbUpdated){
|
78 |
-
self::$_tablesCreated = true;
|
79 |
-
self::$_tablesUpgraded = true;
|
80 |
-
self::$_tablesUpdated = true;
|
81 |
-
self::$_canRun = true;
|
82 |
-
return true;
|
83 |
-
}
|
84 |
-
|
85 |
-
global $wpdb;
|
86 |
-
$tableMain = self::getFullTableName('MAIN');
|
87 |
-
$tableEvents = self::getFullTableName('EVENTS');
|
88 |
-
|
89 |
-
// Check if tables exist
|
90 |
-
if(! self::tableExists($wpdb, $tableMain)){
|
91 |
-
if(! self::_createEventLogsTable($wpdb, $tableMain)){
|
92 |
-
WPPH::__addPluginError(__("Plugin cannot create tables in the WordPress database to store security audit logs. Allow write access to the WordPress database user temporarily to activate this plugin.
|
93 |
-
For more information contact us on support@wpprohelp.com.",WPPH_PLUGIN_TEXT_DOMAIN));
|
94 |
-
return false;
|
95 |
-
}
|
96 |
-
}
|
97 |
-
if(! self::tableExists($wpdb, $tableEvents)){
|
98 |
-
if(! self::_createEventDetailsTable($wpdb, $tableEvents)){
|
99 |
-
WPPH::__addPluginError(__("Plugin cannot create tables in the WordPress database to store security audit logs. Allow write access to the WordPress database user temporarily to activate this plugin.
|
100 |
-
For more information contact us on support@wpprohelp.com.",WPPH_PLUGIN_TEXT_DOMAIN));
|
101 |
-
return false;
|
102 |
-
}
|
103 |
-
}
|
104 |
-
// Check if tables need to be upgraded
|
105 |
-
if(! self::_upgradeEventLogsTable($wpdb, $tableMain)){
|
106 |
-
return false;
|
107 |
-
}
|
108 |
-
if(! self::_upgradeEventDetailsTable($wpdb, $tableEvents)){
|
109 |
-
return false;
|
110 |
-
}
|
111 |
-
// Check if tables need to be updated
|
112 |
-
if(! self::_updateEventsDetailsTable($wpdb, $tableEvents)){
|
113 |
-
WPPH::__addPluginError(sprintf(__("Error updating table <strong>%s</strong>.",WPPH_PLUGIN_TEXT_DOMAIN), $tableEvents));
|
114 |
-
return false;
|
115 |
-
}
|
116 |
-
if(! self::_updateEventLogsTable($wpdb, $tableMain)){
|
117 |
-
WPPH::__addPluginError(sprintf(__("Error updating table <strong>%s</strong>.",WPPH_PLUGIN_TEXT_DOMAIN), $tableMain));
|
118 |
-
return false;
|
119 |
-
}
|
120 |
-
self::$_tablesCreated = true;
|
121 |
-
self::$_tablesUpgraded = true;
|
122 |
-
self::$_tablesUpdated = true;
|
123 |
-
self::$_canRun = true;
|
124 |
-
return true;
|
125 |
-
}
|
126 |
-
|
127 |
-
static function tableExists($wpdb, $tableFullName)
|
128 |
-
{
|
129 |
-
$result = $wpdb->get_var("SHOW TABLES LIKE '$tableFullName'");
|
130 |
-
return (is_null($result) ? false : true);
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Returns the full table name db_prefix + base_table_name for the requested table
|
135 |
-
* @param string $what the table identifier. Possible values:
|
136 |
-
* main -> to retrieve : db_prefix + self::$_eventsLogTableBaseName
|
137 |
-
* events -> to retrieve: db_prefix + self::$_eventsDetailsTableBaseName
|
138 |
-
* @return string
|
139 |
-
*/
|
140 |
-
static function getFullTableName($what = 'main')
|
141 |
-
{
|
142 |
-
global $wpdb;
|
143 |
-
if(strcasecmp($what, 'MAIN') == 0){
|
144 |
-
return (WPPH::isMultisite() ? self::getDefaultPrefix() : $wpdb->prefix) . self::$_eventsLogTableBaseName;
|
145 |
-
}
|
146 |
-
elseif(strcasecmp($what, 'EVENTS') == 0){
|
147 |
-
return (WPPH::isMultisite() ? self::getDefaultPrefix() : $wpdb->prefix) . self::$_eventsDetailsTableBaseName;
|
148 |
-
}
|
149 |
-
return '';
|
150 |
-
}
|
151 |
-
|
152 |
-
static function canRun() { return self::$_canRun; }
|
153 |
-
|
154 |
-
/**
|
155 |
-
* @internal
|
156 |
-
* Prepares the tables for future upgrades from v0.1
|
157 |
-
*/
|
158 |
-
static function v2Cleanup()
|
159 |
-
{
|
160 |
-
global $wpdb;
|
161 |
-
|
162 |
-
$t1 = self::getFullTableName('MAIN');
|
163 |
-
$t2 = self::getFullTableName('EVENTS');
|
164 |
-
|
165 |
-
// empty table 1
|
166 |
-
$query = "TRUNCATE ". $wpdb->prefix.self::$_eventsLogTableBaseName;
|
167 |
-
if(false === $wpdb->query($query)){
|
168 |
-
WPPH::__addPluginError(
|
169 |
-
sprintf(
|
170 |
-
__("Plugin could not be properly upgraded because we could not empty the content of the following table: <strong>%s</strong>",WPPH_PLUGIN_TEXT_DOMAIN),$t1)
|
171 |
-
);
|
172 |
-
self::$_canUpgrade = false;
|
173 |
-
}
|
174 |
-
else { self::$_canUpgrade = true; }
|
175 |
-
|
176 |
-
// empty table 2
|
177 |
-
$query = "TRUNCATE ".$wpdb->prefix.self::$_eventsDetailsTableBaseName;
|
178 |
-
if(false === $wpdb->query($query)){
|
179 |
-
WPPH::__addPluginError(
|
180 |
-
sprintf(__("Plugin could not be properly upgraded because we could not empty the content of the following table: <strong>%s</strong>",WPPH_PLUGIN_TEXT_DOMAIN),$t2)
|
181 |
-
);
|
182 |
-
self::$_canUpgrade = false;
|
183 |
-
}
|
184 |
-
else { self::$_canUpgrade = true; }
|
185 |
-
|
186 |
-
return self::$_canUpgrade;
|
187 |
-
}
|
188 |
-
|
189 |
-
private static function _createEventLogsTable($wpdb, $tableFullName)
|
190 |
-
{
|
191 |
-
$query = "CREATE TABLE IF NOT EXISTS `$tableFullName` (
|
192 |
-
`EventNumber` bigint(40) NOT NULL AUTO_INCREMENT,
|
193 |
-
`EventID` int(8) NOT NULL,
|
194 |
-
`EventDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
195 |
-
`UserID` int(8) NOT NULL DEFAULT '0',
|
196 |
-
`UserIP` varchar(24) NOT NULL DEFAULT '0.0.0.0',
|
197 |
-
`EventData` TEXT NOT NULL,
|
198 |
-
PRIMARY KEY (`EventNumber`),
|
199 |
-
UNIQUE KEY `EventNumber` (`EventNumber`)
|
200 |
-
);";
|
201 |
-
if(false === @$wpdb->query($query)){return false;}
|
202 |
-
return true;
|
203 |
-
}
|
204 |
-
private static function _createEventDetailsTable($wpdb, $tableFullName)
|
205 |
-
{
|
206 |
-
$query = "CREATE TABLE IF NOT EXISTS `$tableFullName` (
|
207 |
-
`EventID` int(8) NOT NULL,
|
208 |
-
`EventType` varchar(10) DEFAULT 'NOTICE',
|
209 |
-
`EventDescription` text NOT NULL,
|
210 |
-
PRIMARY KEY (`EventID`),
|
211 |
-
UNIQUE KEY `EventID` (`EventID`)
|
212 |
-
);";
|
213 |
-
if (false === @$wpdb->query($query)){ return false; }
|
214 |
-
return true;
|
215 |
-
}
|
216 |
-
private static function _upgradeEventLogsTable($wpdb, $tableFullName)
|
217 |
-
{
|
218 |
-
$q = "SHOW COLUMNS FROM $tableFullName LIKE 'EventCount';";
|
219 |
-
$rowData = $wpdb->get_row($q, ARRAY_A);
|
220 |
-
if(empty($rowData['Field']))
|
221 |
-
{
|
222 |
-
$q = "ALTER TABLE $tableFullName ADD COLUMN `EventCount` INT NOT NULL DEFAULT 1 AFTER `EventData`;";
|
223 |
-
$result = @$wpdb->query($q);
|
224 |
-
if($result === false){
|
225 |
-
WPPH::__addPluginError(
|
226 |
-
sprintf(__("Plugin could not be properly installed. The db user used to connect to the WordPress database is missing the <strong>ALTER</strong> right for query: <strong>%s</strong>",WPPH_PLUGIN_TEXT_DOMAIN),$q)
|
227 |
-
);
|
228 |
-
return false;
|
229 |
-
}
|
230 |
-
$q = "ALTER TABLE $tableFullName ADD COLUMN `UserName` VARCHAR(125) NOT NULL DEFAULT '' AFTER `EventCount`;";
|
231 |
-
$result = @$wpdb->query($q);
|
232 |
-
if($result === false){
|
233 |
-
WPPH::__addPluginError(
|
234 |
-
sprintf(__("Plugin could not be properly installed. The db user used to connect to the WordPress database is missing the <strong>ALTER</strong> right for query: <strong>%s</strong>",WPPH_PLUGIN_TEXT_DOMAIN),$q)
|
235 |
-
);
|
236 |
-
return false;
|
237 |
-
}
|
238 |
-
}
|
239 |
-
$q = "SHOW COLUMNS FROM $tableFullName LIKE 'BlogId';";
|
240 |
-
$rowData = $wpdb->get_row($q, ARRAY_A);
|
241 |
-
if(empty($rowData['Field']))
|
242 |
-
{
|
243 |
-
$q = "ALTER TABLE $tableFullName ADD COLUMN `BlogId` INT NOT NULL DEFAULT 1 AFTER `UserName`;";
|
244 |
-
$result = @$wpdb->query($q);
|
245 |
-
if($result === false){
|
246 |
-
WPPH::__addPluginError(
|
247 |
-
sprintf(__("Plugin could not be properly installed. The db user used to connect to the WordPress database is missing the <strong>ALTER</strong> right for query: <strong>%s</strong>",WPPH_PLUGIN_TEXT_DOMAIN),$q)
|
248 |
-
);
|
249 |
-
return false;
|
250 |
-
}
|
251 |
-
}
|
252 |
-
return true;
|
253 |
-
}
|
254 |
-
private static function _upgradeEventDetailsTable($wpdb, $tableFullName)
|
255 |
-
{
|
256 |
-
return true;
|
257 |
-
}
|
258 |
-
/**
|
259 |
-
* This function will insert the default rows in the events details table
|
260 |
-
*/
|
261 |
-
private static function _updateEventsDetailsTable($wpdb, $tableFullName)
|
262 |
-
{
|
263 |
-
$queries = array();
|
264 |
-
$events = WPPHEvent::listEvents();
|
265 |
-
if(empty($events)){ return true; }
|
266 |
-
|
267 |
-
// check for differences
|
268 |
-
$numFileEvents = count($events);
|
269 |
-
$numDbEvents = (int)$wpdb->get_var("SELECT COUNT(EventID) FROM $tableFullName;");
|
270 |
-
|
271 |
-
// no update necessary
|
272 |
-
if($numFileEvents == $numDbEvents){
|
273 |
-
return true;
|
274 |
-
}
|
275 |
-
|
276 |
-
foreach($events as $entry)
|
277 |
-
{
|
278 |
-
$q = sprintf("INSERT INTO $tableFullName (`EventID`,`EventType`,`EventDescription`) VALUES(%d,'%s','%s')", $entry['id'], $entry['category'], $entry['text']);
|
279 |
-
$queries["{$entry['id']}"] = $q;
|
280 |
-
}
|
281 |
-
|
282 |
-
// Clear table
|
283 |
-
if($numDbEvents > 0){
|
284 |
-
$result = @$wpdb->query("TRUNCATE $tableFullName");
|
285 |
-
if($result === false){
|
286 |
-
WPPH::__addPluginError(
|
287 |
-
sprintf(
|
288 |
-
__("Could not empty table <strong>%s</strong>. Please run the following query manually: <strong>TRUNCATE %s</strong>",WPPH_PLUGIN_TEXT_DOMAIN)
|
289 |
-
,$tableFullName, $tableFullName)
|
290 |
-
);
|
291 |
-
return false;
|
292 |
-
}
|
293 |
-
}
|
294 |
-
// Insert data
|
295 |
-
foreach($queries as $id => $query){
|
296 |
-
if(! empty($query)){
|
297 |
-
if(false === @$wpdb->query($query)){
|
298 |
-
wpphLog('QUERY FAILED TO RUN: ',$query);
|
299 |
-
WPPH::__addPluginError(
|
300 |
-
sprintf(
|
301 |
-
__("Error updating table <strong>%s</strong> using query: <strong>%s</strong>",WPPH_PLUGIN_TEXT_DOMAIN)
|
302 |
-
,$tableFullName, $query)
|
303 |
-
);
|
304 |
-
return false;
|
305 |
-
}
|
306 |
-
}
|
307 |
-
}
|
308 |
-
return true;
|
309 |
-
}
|
310 |
-
|
311 |
-
private static function _updateEventLogsTable($wpdb, $tableFullName)
|
312 |
-
{
|
313 |
-
return true;
|
314 |
-
}
|
315 |
-
|
316 |
-
/**
|
317 |
-
* Retrieve the default database prefix
|
318 |
-
* @since v0.6
|
319 |
-
* @uses global var $wpdb
|
320 |
-
* @return string
|
321 |
-
*/
|
322 |
-
static function getDefaultPrefix(){
|
323 |
-
global $wpdb;
|
324 |
-
return $wpdb->base_prefix;
|
325 |
-
}
|
326 |
-
}
|
327 |
-
|
328 |
-
/**
|
329 |
-
* Class WPPHDB
|
330 |
-
* Contains utility methods to communicate with the database
|
331 |
-
*/
|
332 |
-
class WPPHDB extends WPPHDatabase
|
333 |
-
{
|
334 |
-
/**
|
335 |
-
* @return string The current logged in user's role
|
336 |
-
*/
|
337 |
-
static function getCurrentUserRole()
|
338 |
-
{
|
339 |
-
global $current_user;
|
340 |
-
get_currentuserinfo();
|
341 |
-
$user_roles = $current_user->roles;
|
342 |
-
$user_role = array_shift($user_roles);
|
343 |
-
return $user_role;
|
344 |
-
}
|
345 |
-
// returns array(userName, userRole)
|
346 |
-
static function getUserInfo($userID)
|
347 |
-
{
|
348 |
-
if(empty($userID)){
|
349 |
-
wpphLog(__METHOD__.'() called with an invalid argument $userID. Ignoring request.', array('$userID'=>$userID));
|
350 |
-
return array('userName'=>'', 'userRole'=>'');
|
351 |
-
}
|
352 |
-
wpphLog(__METHOD__.'() called.', array('$userID'=>$userID));
|
353 |
-
|
354 |
-
global $wpdb;
|
355 |
-
|
356 |
-
$t = $wpdb->users;
|
357 |
-
|
358 |
-
$username = $wpdb->get_var("SELECT user_login FROM $t WHERE ID=$userID");
|
359 |
-
$user = new WP_User( $userID );
|
360 |
-
$userRole = (empty($user->roles[0]) ? '' : $user->roles[0]);
|
361 |
-
|
362 |
-
wpphLog("Function: ".__METHOD__." User info", array('id'=>$userID, 'roles'=>$user->roles));
|
363 |
-
|
364 |
-
return array(
|
365 |
-
'userName' => $username,
|
366 |
-
'userRole' => $userRole
|
367 |
-
);
|
368 |
-
}
|
369 |
-
|
370 |
-
/**
|
371 |
-
* Retrieve the total number of events from db
|
372 |
-
* @param integer $blogId
|
373 |
-
* @return int
|
374 |
-
*/
|
375 |
-
static function getEventsCount($blogId = 1)
|
376 |
-
{
|
377 |
-
global $wpdb;
|
378 |
-
$where = '';
|
379 |
-
if(!empty($blogId)){
|
380 |
-
$where = " WHERE BlogId = ".intval($blogId);
|
381 |
-
return $wpdb->get_var("SELECT COUNT(EventNumber) FROM ".self::getFullTableName('main').$where);
|
382 |
-
}
|
383 |
-
return $wpdb->get_var("SELECT COUNT(EventNumber) FROM ".self::getFullTableName('main'));
|
384 |
-
}
|
385 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/WPPHEvent.php
DELETED
@@ -1,2213 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WPPHEvent
|
4 |
-
*/
|
5 |
-
class WPPHEvent
|
6 |
-
{
|
7 |
-
/**
|
8 |
-
* Retrieve the list of events
|
9 |
-
* @return array
|
10 |
-
*/
|
11 |
-
static function listEvents()
|
12 |
-
{
|
13 |
-
return array(
|
14 |
-
// 1xxx - Login/Logout events
|
15 |
-
array( 'id' => 1000, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Successfully logged in.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
16 |
-
array( 'id' => 1001, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Successfully logged out.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
17 |
-
array( 'id' => 1002, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Failed login detected using <strong>%s</strong> as username.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
18 |
-
|
19 |
-
// 2xxx - User activity events
|
20 |
-
// Created a new blog post called %Post Title%. Blog post ID is %ID%
|
21 |
-
array( 'id' => 2000, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Created a new draft blog post called <strong>%s</strong>. Blog post ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
22 |
-
// Published a blog post called %Post_Title%. Blog post URL is %Post_URL%
|
23 |
-
array( 'id' => 2001, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Published a blog post called <strong>%s</strong>. Blog post URL is <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
24 |
-
// Modified the published blog post %post_title%. Blog post URL is %post_URL%
|
25 |
-
array( 'id' => 2002, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Modified the published blog post <strong>%s</strong>. Blog post URL is <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
26 |
-
// Modified the draft blog post %post_title%. Blog post ID is %ID%
|
27 |
-
array( 'id' => 2003, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Modified the draft blog post <strong>%s</strong>. Blog post ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
28 |
-
|
29 |
-
// Created a new page called %page_title%. Page ID is %ID%
|
30 |
-
array( 'id' => 2004, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Created a new draft page called <strong>%s</strong>. Page ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
31 |
-
// Published a page called %page_title%. Page URL is %URL%
|
32 |
-
array( 'id' => 2005, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Published a page called <strong>%s</strong>. Page URL is <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
33 |
-
// Modified the published page %page_title%. Page URL is %URL%
|
34 |
-
array( 'id' => 2006, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Modified the published page <strong>%s</strong>. Page URL is <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
35 |
-
// Modified the draft page %page_title%. Page ID is %ID%
|
36 |
-
array( 'id' => 2007, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Modified the draft page <strong>%s</strong>. Page ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
37 |
-
// Deleted the post %Title%. Blog post ID is %ID%
|
38 |
-
array( 'id' => 2008, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Deleted the post <strong>%s</strong>. Blog post ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
39 |
-
// Deleted the page %Title%. Page ID is %ID%
|
40 |
-
array( 'id' => 2009, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Deleted the page <strong>%s</strong>. Page ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
41 |
-
|
42 |
-
// Uploaded the file %file name$ in %file location%
|
43 |
-
array( 'id' => 2010, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Uploaded the file <strong>%s</strong> in <strong>%s</strong>/.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
44 |
-
// Deleted file %file name$ from %file_location%
|
45 |
-
array( 'id' => 2011, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Deleted the file <strong>%s</strong> from <strong>%s</strong>/.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
46 |
-
// 2012 - trashed draft post
|
47 |
-
array( 'id' => 2012, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Moved the post <strong>%s</strong> to trash.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
48 |
-
// 2013 - trashed published post
|
49 |
-
array( 'id' => 2013, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Moved the page <strong>%s</strong> to trash.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
50 |
-
// 2014 - untrashed post
|
51 |
-
array( 'id' => 2014, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Post <strong>%s</strong> has been restored from trash.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
52 |
-
// 2015 - untrashed page
|
53 |
-
array( 'id' => 2015, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Page <strong>%s</strong> has been restored from trash.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
54 |
-
// 2016 - Post category changed
|
55 |
-
array( 'id' => 2016, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the category(ies) of the post <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
56 |
-
// 2017 - Changed the URL of the post %post_name% from %old_url% to %new_url%
|
57 |
-
array( 'id' => 2017, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the URL of the post <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
58 |
-
// 2018 - Changed the URL of the page %page_name% from %old_url% to %new_url%
|
59 |
-
array( 'id' => 2018, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the URL of the page <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
60 |
-
// 2019 - Changed the author of %post_name% post from %old_author% to %new_author%
|
61 |
-
array( 'id' => 2019, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the author of <strong>%s</strong> post from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
62 |
-
// 2020 - Changed the author of %page_name% page from %old_author% to %new_author%
|
63 |
-
array( 'id' => 2020, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the author of <strong>%s</strong> page from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
64 |
-
// 2021 - %postName% from %oldStatus% to %newStatus%
|
65 |
-
array( 'id' => 2021, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the status of <strong>%s</strong> post from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
66 |
-
// 2022 - page from published to draft
|
67 |
-
array( 'id' => 2022, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the status of <strong>%s</strong> page from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
68 |
-
// 2023 - added new category
|
69 |
-
array( 'id' => 2023, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Created a new category called <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
70 |
-
// 2024 - deleted category
|
71 |
-
array( 'id' => 2024, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Deleted the <strong>%s</strong> category.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
72 |
-
// 2025 - Changed the visibility of %post_name% blog post from %old_visibility% to %new_visibility%
|
73 |
-
array( 'id' => 2025, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Changed the visibility of <strong>%s</strong> blog post from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
74 |
-
// 2026 - Changed the visibility of %page_name% page from %old_visibility% to %new_visibility%
|
75 |
-
array( 'id' => 2026, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Changed the visibility of <strong>%s</strong> page from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
76 |
-
// 2027 - Changed the date of %post_name% blog post from %old_date% to %new_date%
|
77 |
-
array( 'id' => 2027, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the date of <strong>%s</strong> blog post from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
78 |
-
// 2028 - Changed the date of %post_name% page from %old_date% to %new_date%
|
79 |
-
array( 'id' => 2028, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the date of <strong>%s</strong> page from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
80 |
-
|
81 |
-
//[[ Custom Post Types
|
82 |
-
// 2029 Created a new custom post called %Post Title%. Post ID is %ID%
|
83 |
-
array( 'id' => 2029, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Created a new draft custom post <strong>%s</strong> of type <strong>%s</strong>. Post ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
84 |
-
// 2030 Published a custom post called %Post_Title%. Post URL is %Post_URL%
|
85 |
-
array( 'id' => 2030, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Published a custom post <strong>%s</strong> of type <strong>%s</strong>. Post URL is <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
86 |
-
// 2031 Modified the published custom post %post_title%. Post URL is %post_URL%
|
87 |
-
array( 'id' => 2031, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Modified the custom post <strong>%s</strong> of type <strong>%s</strong>. Post URL is <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
88 |
-
// 2032 Modified the draft custom post %post_title%. Post ID is %ID%
|
89 |
-
array( 'id' => 2032, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Modified the draft custom post <strong>%s</strong> of type <strong>%s</strong>. Post ID is <strong>%d</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
90 |
-
// 2033 Deleted the custom post %Title%. Post ID is %ID%
|
91 |
-
array( 'id' => 2033, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Deleted custom post <strong>%s</strong> of type <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
92 |
-
// 2034 - trashed draft custom post
|
93 |
-
array( 'id' => 2034, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Moved the custom post <strong>%s</strong> to trash. Post type is <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
94 |
-
// 2035 - untrashed custom post
|
95 |
-
array( 'id' => 2035, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Custom post <strong>%s</strong> of type <strong>%s</strong> has been restored from trash.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
96 |
-
// 2036 - Custom post category changed
|
97 |
-
array( 'id' => 2036, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the category(ies) of custom post <strong>%s</strong> of type <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
98 |
-
// 2037 - Changed the URL of the custom post %post_name% from %old_url% to %new_url%
|
99 |
-
array( 'id' => 2037, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the URL of the custom post <strong>%s</strong> of type <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
100 |
-
// 2038 - Changed the author of %post_name% custom post from %old_author% to %new_author%
|
101 |
-
array( 'id' => 2038, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the author of custom post <strong>%s</strong> of type <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
102 |
-
// 2039 - Changed the status of %postName% custom post from %oldStatus% to %newStatus%
|
103 |
-
array( 'id' => 2039, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the status of custom post <strong>%s</strong> of type <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
104 |
-
// 2040 - Changed the visibility of %post_name% custom post from %old_visibility% to %new_visibility%
|
105 |
-
array( 'id' => 2040, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Changed the visibility of custom post <strong>%s</strong> of type <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
106 |
-
// 2041 - Changed the date of %post_name% custom post from %old_date% to %new_date%
|
107 |
-
array( 'id' => 2041, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the date of custom post <strong>%s</strong> of type <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
108 |
-
|
109 |
-
// WIDGETS
|
110 |
-
// 2042 - Added a new %type% widget in %section%
|
111 |
-
array( 'id' => 2042, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Added a new <strong>%s</strong> widget in <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
112 |
-
// 2043 - Modified the %type% widget in %section%
|
113 |
-
array( 'id' => 2043, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Modified the <strong>%s</strong> widget in <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
114 |
-
// 2044 - Deleted the %type% widget from %section%
|
115 |
-
array( 'id' => 2044, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Deleted the <strong>%s</strong> widget from <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
116 |
-
// 2045 - Moved the %type% widget from %old_location% to %new_location%
|
117 |
-
array( 'id' => 2045, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Moved the <strong>%s</strong> widget from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
118 |
-
|
119 |
-
// 3xxx - Themes management
|
120 |
-
// Activated the theme %themeName%
|
121 |
-
array( 'id' => 3000, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Activated the theme <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
122 |
-
|
123 |
-
// 4xxx - User profile events
|
124 |
-
array( 'id' => 4000, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('A new user with the username <strong>%s</strong> has registered with the role of <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
125 |
-
array( 'id' => 4001, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('<strong>%s</strong> created a new user <strong>%s</strong> with the role of <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
126 |
-
array( 'id' => 4002, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('The role of user <strong>%s</strong> was changed from <strong>%s</strong> to <strong>%s</strong> by <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
127 |
-
array( 'id' => 4003, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Changed the account password.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
128 |
-
array( 'id' => 4004, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('<strong>%s</strong> changed the password for user <strong>%s</strong> with the role of <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
129 |
-
// Changed the email address from %old_email% to %new_email%
|
130 |
-
array( 'id' => 4005, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Changed the email address from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
131 |
-
// %user_making_change% changed the email address of user %user% from %old_email% to %new_email%
|
132 |
-
array( 'id' => 4006, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('<strong>%s</strong> changed the email address of user <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
133 |
-
// User %user% with the role of %role% was deleted by %user_deleting%
|
134 |
-
array( 'id' => 4007, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('User <strong>%s</strong> with the role of <strong>%s</strong> was deleted by <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
135 |
-
|
136 |
-
// 5xxx - Plugin management
|
137 |
-
// # 5000 Installed the plugin %name%.
|
138 |
-
array( 'id' => 5000, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Installed the plugin <strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
139 |
-
// Activated the plugin %plugin_name% installed in %plugin_directory%
|
140 |
-
array( 'id' => 5001, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Activated the plugin <strong>%s</strong> installed in /<strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
141 |
-
// Deactivated the plugin %plugin_name% installed in %plugin_directory%
|
142 |
-
array( 'id' => 5002, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Deactivated the plugin <strong>%s</strong> installed in /<strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
143 |
-
// # 5003 Uninstalled the plugin %plugin_name% which was installed in %path%
|
144 |
-
array( 'id' => 5003, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Uninstalled the plugin <strong>%s</strong> which was installed in /<strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
145 |
-
// # 5004 Upgraded the plugin %name% installed in %path%
|
146 |
-
array( 'id' => 5004, 'category' => WPPH_E_WARNING_TEXT, 'text' => __('Upgraded the plugin <strong>%s</strong> installed in /<strong>%s</strong>.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
147 |
-
|
148 |
-
// 6xxx - System events
|
149 |
-
// #6000 Events automatically deleted by system.
|
150 |
-
array( 'id' => 6000, 'category' => WPPH_E_NOTICE_TEXT, 'text' => __('Alerts automatically deleted by system.',WPPH_PLUGIN_TEXT_DOMAIN)),
|
151 |
-
// #6001 - <strong>%s</strong> the option Anyone can register
|
152 |
-
array( 'id' => 6001, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('<strong>%s</strong> the option Anyone can register',WPPH_PLUGIN_TEXT_DOMAIN)),
|
153 |
-
// #6002 - Changed the New User Default Role from <strong>%s</strong> to <strong>%s</strong>
|
154 |
-
array( 'id' => 6002, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Changed the New User Default Role from <strong>%s</strong> to <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
155 |
-
// #6003 - Changed the WordPress administrator notifications email address from %old_email% to %new_mail%
|
156 |
-
array( 'id' => 6003, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Changed the WordPress administrator notifications email address from <strong>%s</strong> to <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
157 |
-
|
158 |
-
|
159 |
-
// xxxx - MultiSite Events
|
160 |
-
|
161 |
-
// #4008 - Granted Super Admin privileges from <strong>%user%</strong>
|
162 |
-
array( 'id' => 4008, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Granted Super Admin privileges to <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
163 |
-
// #4009 - Revoked Super Admin privileges from <strong>%user%</strong>
|
164 |
-
array( 'id' => 4009, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Revoked Super Admin privileges from <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
165 |
-
// #4010 - Added existing user %user% with %role% role to site %site%
|
166 |
-
array( 'id' => 4010, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Added existing user <strong>%s</strong> with role <strong>%s</strong> to site <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
167 |
-
// #4011 - Removed user %user% with role %role% from %site% site
|
168 |
-
array( 'id' => 4011, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Removed user <strong>%s</strong> with role <strong>%s</strong> from site <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
169 |
-
// #4012 - Created a new network user %user%
|
170 |
-
array( 'id' => 4012, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Created a new network user <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
171 |
-
// #7000 - Added <strong>%site%</strong> to the network
|
172 |
-
array( 'id' => 7000, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Added site <strong>%s</strong> to the network',WPPH_PLUGIN_TEXT_DOMAIN)),
|
173 |
-
// #7001 - Archived site <strong>%site%</strong>
|
174 |
-
array( 'id' => 7001, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Archived site <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
175 |
-
// #7002 - Unarchived site <strong>%site%</strong>
|
176 |
-
array( 'id' => 7002, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Unarchived site <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
177 |
-
// #7003 - Activated site <strong>%site%</strong>
|
178 |
-
array( 'id' => 7003, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Activated site <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
179 |
-
// #7004 - Deactivated site <strong>%site%</strong>
|
180 |
-
array( 'id' => 7004, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Deactivated site <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
181 |
-
// #7005 - Deleted site <strong>%site%</strong>
|
182 |
-
array( 'id' => 7005, 'category' => WPPH_E_HIGH_TEXT, 'text' => __('Deleted site <strong>%s</strong>',WPPH_PLUGIN_TEXT_DOMAIN)),
|
183 |
-
);
|
184 |
-
}
|
185 |
-
|
186 |
-
|
187 |
-
// 1xxx - Login/Logout events
|
188 |
-
|
189 |
-
// 1000
|
190 |
-
static function hookLoginEvent() { add_action('wp_login', array('WPPHEventWatcher', 'watchEventLogin'), 10, 2); }
|
191 |
-
// 1001
|
192 |
-
static function hookLogoutEvent() { add_action('wp_logout', array('WPPHEventWatcher', 'watchEventLogout')); }
|
193 |
-
// 1002
|
194 |
-
static function hookLoginFailure() { add_action('wp_login_failed', array('WPPHEventWatcher', 'watchLoginFailure')); }
|
195 |
-
|
196 |
-
|
197 |
-
// 2xxx - User activity events
|
198 |
-
|
199 |
-
// 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2021, 2022
|
200 |
-
static function hookWatchBlogActivity() { add_action('transition_post_status', array('WPPHEventWatcher', 'watchBlogActivity'), 10, 3); }
|
201 |
-
// 2008, 2009
|
202 |
-
static function hookFileDeletion() { add_action('delete_post', array('WPPHEventWatcher', 'watchTrash'), 10, 1); }
|
203 |
-
// 2010
|
204 |
-
static function hookFileUploaded() { add_action('add_attachment', array('WPPHEventWatcher', 'watchFileUploaded')); }
|
205 |
-
// 2011
|
206 |
-
static function hookFileUploadedDeleted() { add_action('delete_attachment', array('WPPHEventWatcher', 'watchFileUploadedDeleted')); }
|
207 |
-
// 2012
|
208 |
-
static function hookTrashPost() {
|
209 |
-
if(defined('EMPTY_TRASH_DAYS') && (EMPTY_TRASH_DAYS == 0)){
|
210 |
-
add_action('delete_post', array('WPPHEventWatcher', 'watchTrash'), 10, 1);
|
211 |
-
}
|
212 |
-
else { add_action('wp_trash_post', array('WPPHEventWatcher', 'watchFileDeletion')); }
|
213 |
-
}
|
214 |
-
// 2013
|
215 |
-
static function hookTrashPage() {
|
216 |
-
if(defined('EMPTY_TRASH_DAYS') && (EMPTY_TRASH_DAYS == 0)){
|
217 |
-
add_action('delete_post', array('WPPHEventWatcher', 'watchTrash'), 10, 1);
|
218 |
-
}
|
219 |
-
else { add_action('wp_trash_page', array('WPPHEventWatcher', 'watchFileDeletion')); }
|
220 |
-
}
|
221 |
-
//2014
|
222 |
-
static function hookUntrashedPosts() { add_action('untrash_post', array('WPPHEventWatcher', 'watchTrashUndo')); }
|
223 |
-
// 2015
|
224 |
-
static function hookUntrashedPages() { add_action('untrash_page', array('WPPHEventWatcher', 'watchTrashUndo')); }
|
225 |
-
// 2016, 2017
|
226 |
-
static function hookWatchPostStateBefore()
|
227 |
-
{
|
228 |
-
if(! isset($_POST)){ wpphLog(__METHOD__.' not $_POST method'); return; }
|
229 |
-
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { wpphLog(__METHOD__.' doing autosave'); return; }
|
230 |
-
if(isset($_POST['action']) && $_POST['action'] == 'autosave') { wpphLog(__METHOD__.' $_POST action == autosave'); return; }
|
231 |
-
|
232 |
-
if(isset($GLOBALS['WPPH_DEFAULT_EDITOR_ENABLED']) || isset($GLOBALS['WPPH_SCREEN_EDITOR_ENABLED']))
|
233 |
-
{
|
234 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
235 |
-
|
236 |
-
global $wpdb;
|
237 |
-
$pid = $_POST['post_ID'];
|
238 |
-
|
239 |
-
$postType = (empty($_POST['post_type']) ? '' : $_POST['post_type']);
|
240 |
-
if(! WPPHPost::validatePostType($postType)){
|
241 |
-
wpphLog('Invalid post type.', array('post-type'=>$postType));
|
242 |
-
return;
|
243 |
-
}
|
244 |
-
|
245 |
-
$_postType = $postType;
|
246 |
-
if($_postType != 'post' && $_postType != 'page'){
|
247 |
-
$_postType = 'custom';
|
248 |
-
}
|
249 |
-
do_action('wpph_set_post_type',$_postType);
|
250 |
-
|
251 |
-
/*
|
252 |
-
* CHECK IF POST/PAGE AUTHOR UPDATED; 2019
|
253 |
-
* ## step 1: this is where we check if author has been changed
|
254 |
-
* ## step 2: @see WPPHPost::managePostAuthorUpdateQuickEditForm()
|
255 |
-
*/
|
256 |
-
if(! empty($_POST['post_author']))
|
257 |
-
{
|
258 |
-
$GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID'] = intval($_POST['post_author']);
|
259 |
-
if(isset($GLOBALS['WPPH_SCREEN_EDITOR_ENABLED'])){
|
260 |
-
// trigger hook manually
|
261 |
-
add_filter('wp_insert_post_data', array('WPPHPost','managePostAuthorUpdateQuickEditForm'), 1, 2);
|
262 |
-
}
|
263 |
-
}
|
264 |
-
|
265 |
-
// check if post exists & get aggregated data
|
266 |
-
$query = "SELECT ID, post_title, post_name, post_password, post_date FROM ".$wpdb->posts." WHERE ID = ".$pid;
|
267 |
-
$result = $wpdb->get_row($query);
|
268 |
-
$postExists = (empty($result->ID) ? false : true);
|
269 |
-
$GLOBALS['WPPH_POST_EXISTS'] = $postExists;
|
270 |
-
$GLOBALS['WPPH_POST_PWD_PROTECTED'] = (empty($result->post_password) ? false : true);
|
271 |
-
|
272 |
-
// if blog post
|
273 |
-
if($postType == 'post' || $_postType == 'custom')
|
274 |
-
{
|
275 |
-
// before further checks, we have to make sure this post isn't new
|
276 |
-
if(! $postExists){
|
277 |
-
wpphLog("POST DOES NOT EXISTS.");
|
278 |
-
return;
|
279 |
-
}
|
280 |
-
|
281 |
-
// retrieve the old post pwd to help us detect the posts' visibility transition state
|
282 |
-
$GLOBALS['WPPH_OLD_POST_PASSWORD'] = $result->post_password;
|
283 |
-
// check if post date has been changed
|
284 |
-
$GLOBALS['WPPH_POST_OLD_DATE'] = $result->post_date;
|
285 |
-
// Get the post name so we'll know if URL was updated
|
286 |
-
$GLOBALS['WPPH_POST_OLD_NAME'] = (empty($result->post_name) ? $result->post_title : $result->post_name);
|
287 |
-
// CHECK IF POST CATEGORY UPDATED; 2016
|
288 |
-
$GLOBALS['WPPH_POST_OLD_CATEGORIES'] = wp_get_post_categories($pid);
|
289 |
-
/*
|
290 |
-
* CHECK IF POST URL UPDATED; 2017
|
291 |
-
* ## step 1: this is where we retrieve the new URL
|
292 |
-
* ## step 2: @see WPPHEventWatcher::watchBlogActivity()
|
293 |
-
*/
|
294 |
-
$GLOBALS['WPPH_POST_NEW_URL'] = get_permalink($pid);
|
295 |
-
}
|
296 |
-
// if page
|
297 |
-
elseif($postType == 'page')
|
298 |
-
{
|
299 |
-
if($postExists)
|
300 |
-
{
|
301 |
-
// get the page's password if any (to trigger the 2026 event)
|
302 |
-
// retrieve the old post pwd to help us detect the posts' visibility transition state
|
303 |
-
$GLOBALS['WPPH_OLD_POST_PASSWORD'] = $result->post_password;
|
304 |
-
// check if post date has been changed
|
305 |
-
$GLOBALS['WPPH_POST_OLD_DATE'] = $result->post_date;
|
306 |
-
// Get the post name so we'll know if URL was updated
|
307 |
-
$GLOBALS['WPPH_POST_OLD_NAME'] = (empty($result->post_name) ? $result->post_title : $result->post_name);
|
308 |
-
}
|
309 |
-
|
310 |
-
/*
|
311 |
-
* CHECK IF PAGE URL UPDATED; 2018
|
312 |
-
* ## step 1: this is where we retrieve the new URL
|
313 |
-
* ## step 2: @see WPPHEventWatcher::watchBlogActivity()
|
314 |
-
*/
|
315 |
-
$GLOBALS['WPPH_POST_NEW_URL'] = get_permalink($pid);
|
316 |
-
}
|
317 |
-
wpphLog('GLOBAL VARIABLES', array(
|
318 |
-
'WPPH_POST_AUTHOR_UPDATED_ID' => $GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID'],
|
319 |
-
'WPPH_POST_EXISTS' => $GLOBALS['WPPH_POST_EXISTS'],
|
320 |
-
'WPPH_POST_PWD_PROTECTED' => $GLOBALS['WPPH_POST_PWD_PROTECTED'],
|
321 |
-
'WPPH_OLD_POST_PASSWORD' => $GLOBALS['WPPH_OLD_POST_PASSWORD'],
|
322 |
-
'WPPH_POST_OLD_DATE' => $GLOBALS['WPPH_POST_OLD_DATE'],
|
323 |
-
'WPPH_POST_OLD_NAME' => $GLOBALS['WPPH_POST_OLD_NAME'],
|
324 |
-
'WPPH_POST_OLD_CATEGORIES' => isset($GLOBALS['WPPH_POST_OLD_CATEGORIES']) ? $GLOBALS['WPPH_POST_OLD_CATEGORIES'] : '',
|
325 |
-
'WPPH_POST_NEW_URL' => $GLOBALS['WPPH_POST_NEW_URL'],
|
326 |
-
'post_type' => $postType,
|
327 |
-
'WPPH_DEFAULT_EDITOR_ENABLED' => isset($GLOBALS['WPPH_DEFAULT_EDITOR_ENABLED']) ? 'true' : 'false',
|
328 |
-
'WPPH_SCREEN_EDITOR_ENABLED' => isset($GLOBALS['WPPH_SCREEN_EDITOR_ENABLED']) ? 'true' : 'false',
|
329 |
-
)
|
330 |
-
);
|
331 |
-
}
|
332 |
-
}
|
333 |
-
|
334 |
-
// 2023
|
335 |
-
static function hookWatchCategoryAdd() { WPPHEventWatcher::watchCategoryAdd($_POST); }
|
336 |
-
// 2024
|
337 |
-
static function hookWatchCategoryDelete() { WPPHEventWatcher::watchCategoryDelete($_POST); }
|
338 |
-
|
339 |
-
// 3xxx - Themes management
|
340 |
-
|
341 |
-
// 3000
|
342 |
-
static function hookThemeChange() { add_action('switch_theme', array('WPPHEventWatcher', 'watchThemeChange'));}
|
343 |
-
|
344 |
-
|
345 |
-
// 4xxx - User profile events
|
346 |
-
|
347 |
-
// 4000, 4001, 4012
|
348 |
-
static function hookUserRegisterEvent()
|
349 |
-
{
|
350 |
-
if(WPPH::isMultisite()){
|
351 |
-
// 4012
|
352 |
-
add_action('user_register', array('WPPHEventWatcher', 'watchWpmuUserRegister'));
|
353 |
-
}
|
354 |
-
// 4000 & 4001
|
355 |
-
else { add_action('user_register', array('WPPHEventWatcher', 'watchEventUserRegister')); }
|
356 |
-
}
|
357 |
-
// 4002
|
358 |
-
static function hookUserRoleUpdated() {
|
359 |
-
add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
|
360 |
-
add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
|
361 |
-
}
|
362 |
-
// 4003, 4004
|
363 |
-
static function hookUserPasswordUpdated() {
|
364 |
-
add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
|
365 |
-
add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
|
366 |
-
}
|
367 |
-
// 4005, 4006
|
368 |
-
static function hookUserEmailUpdated() {
|
369 |
-
add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
|
370 |
-
add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
|
371 |
-
}
|
372 |
-
// 4008
|
373 |
-
static function hookUserAdminPriv() {
|
374 |
-
add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserAdminPrivUpdated'));
|
375 |
-
add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserAdminPrivUpdated'));
|
376 |
-
}
|
377 |
-
|
378 |
-
// 4007
|
379 |
-
static function hookUserDeletion() { add_action( 'delete_user', array('WPPHEventWatcher', 'watchUserDeletion') ); }
|
380 |
-
|
381 |
-
|
382 |
-
// 5xxx - Plugin management
|
383 |
-
|
384 |
-
// 5000, 5001, 5002, 5003, 5004
|
385 |
-
static function hookWatchPluginActivity() {
|
386 |
-
@include_once(ABSPATH.'wp-admin/includes/plugin.php');
|
387 |
-
WPPHEventWatcher::watchPluginInstall(); // 5000
|
388 |
-
WPPHEventWatcher::watchPluginActivate(); // 5001
|
389 |
-
WPPHEventWatcher::watchPluginDeactivate(); // 5002
|
390 |
-
WPPHEventWatcher::watchPluginUninstall(); // 5003
|
391 |
-
WPPHEventWatcher::watchPluginUpgrade(); // 5004
|
392 |
-
}
|
393 |
-
|
394 |
-
|
395 |
-
// 6xxx - System events
|
396 |
-
|
397 |
-
|
398 |
-
// Events: 6001, 6002 are not available in MultiSite.
|
399 |
-
// 6001, 6002, 6003
|
400 |
-
static function hookCheckWpGeneralSettings(){
|
401 |
-
if(WPPH::isMultisite())
|
402 |
-
{
|
403 |
-
if(isset($_POST))
|
404 |
-
{
|
405 |
-
if(isset($_POST['_wp_http_referer']) && !empty($_POST['_wp_http_referer'])){
|
406 |
-
$wp_referrer = $_POST['_wp_http_referer'];
|
407 |
-
if(false === ($pos = stripos($wp_referrer,'settings.php'))){
|
408 |
-
return;
|
409 |
-
}
|
410 |
-
// 6003
|
411 |
-
if(! empty($_POST['admin_email'])){
|
412 |
-
$from = get_option('admin_email');
|
413 |
-
$to = trim($_POST['admin_email']);
|
414 |
-
if(strcasecmp($from,$to)!=0){
|
415 |
-
wpphLog('Admin email changed',array(
|
416 |
-
'from' => $from,
|
417 |
-
'to' => $to
|
418 |
-
));
|
419 |
-
self::_addLogEvent(6003, wp_get_current_user()->ID, WPPHUtil::getIP(), array($from, $to));
|
420 |
-
}
|
421 |
-
}
|
422 |
-
}
|
423 |
-
}
|
424 |
-
return;
|
425 |
-
}
|
426 |
-
if(isset($_POST))
|
427 |
-
{
|
428 |
-
$wpphOptData = get_option(WPPH_USERS_CAN_REGISTER_OPT_NAME);
|
429 |
-
|
430 |
-
// 6001
|
431 |
-
if(!empty($_POST['option_page']) && $_POST['option_page'] == 'general')
|
432 |
-
{
|
433 |
-
if(isset($_POST['users_can_register'])){
|
434 |
-
// on
|
435 |
-
if(false === $wpphOptData || 0 == $wpphOptData){
|
436 |
-
self::_addLogEvent(6001, wp_get_current_user()->ID, WPPHUtil::getIP(), array(__('Enabled')));
|
437 |
-
update_option(WPPH_USERS_CAN_REGISTER_OPT_NAME,1);
|
438 |
-
}
|
439 |
-
}
|
440 |
-
else {
|
441 |
-
// off
|
442 |
-
if(false === $wpphOptData || 1 == $wpphOptData){
|
443 |
-
self::_addLogEvent(6001, wp_get_current_user()->ID, WPPHUtil::getIP(), array(__('Disabled')));
|
444 |
-
update_option('wpph_users_can_register',0);
|
445 |
-
}
|
446 |
-
}
|
447 |
-
|
448 |
-
// 6002
|
449 |
-
if(! empty($_POST['default_role'])){
|
450 |
-
$from = get_option('default_role');
|
451 |
-
$to = trim($_POST['default_role']);
|
452 |
-
if(strcasecmp($from,$to)!=0){
|
453 |
-
wpphLog('Default user role changed',array(
|
454 |
-
'from' => $from,
|
455 |
-
'to' => $to
|
456 |
-
));
|
457 |
-
self::_addLogEvent(6002, wp_get_current_user()->ID, WPPHUtil::getIP(), array($from, $to));
|
458 |
-
}
|
459 |
-
}
|
460 |
-
|
461 |
-
// 6003
|
462 |
-
if(! empty($_POST['admin_email'])){
|
463 |
-
$from = get_option('admin_email');
|
464 |
-
$to = trim($_POST['admin_email']);
|
465 |
-
if(strcasecmp($from,$to)!=0){
|
466 |
-
wpphLog('Admin email changed',array(
|
467 |
-
'from' => $from,
|
468 |
-
'to' => $to
|
469 |
-
));
|
470 |
-
self::_addLogEvent(6003, wp_get_current_user()->ID, WPPHUtil::getIP(), array($from, $to));
|
471 |
-
}
|
472 |
-
}
|
473 |
-
}
|
474 |
-
}
|
475 |
-
}
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
/**
|
480 |
-
* Add log event. Internal function. Do not use outside class scope.
|
481 |
-
* @internal
|
482 |
-
* @static
|
483 |
-
* @param int $eventID
|
484 |
-
* @param int $userID . A value of 0 means user "System". This is the ID of the user triggering the alert.
|
485 |
-
* @param string $userIP
|
486 |
-
* @param array $eventData Optional. If provided should be as an array.
|
487 |
-
* @param string $failedLoginUserName The name of the user used for the failed login
|
488 |
-
* @param int $blogID The blog id for which the event is triggered. If omitted, the global $blog_id variable will be used.
|
489 |
-
* @return bool
|
490 |
-
*/
|
491 |
-
static function _addLogEvent($eventID = 1000, $userID = 0, $userIP = '', $eventData = array(), $failedLoginUserName='', $blogID = null)
|
492 |
-
{
|
493 |
-
$params = func_get_args();
|
494 |
-
wpphLog(__METHOD__.'() called with params:', $params);
|
495 |
-
wpphLog(__METHOD__.'() triggered.');
|
496 |
-
if(empty($blogID)){
|
497 |
-
wpphLog('The blog ID was not provided. Trying to use the global $blog_id');
|
498 |
-
global $blog_id; // try to get the current blog id if none provided
|
499 |
-
if(empty($blog_id)){
|
500 |
-
wpphLog('The blog ID could not be determined. Ignoring request for adding the log event.');
|
501 |
-
return true;
|
502 |
-
}
|
503 |
-
}
|
504 |
-
else { $blog_id = $blogID; }
|
505 |
-
|
506 |
-
if(! wpph_isEventEnabled($eventID)){
|
507 |
-
wpphLog('Event '.$eventID.' is not enabled. Ignoring request.');
|
508 |
-
return true;
|
509 |
-
}
|
510 |
-
|
511 |
-
if(empty($userIP)){ $userIP = WPPHUtil::getIP(); }
|
512 |
-
$tableName = WPPHDB::getFullTableName('MAIN');
|
513 |
-
$eventData = base64_encode(serialize($eventData));
|
514 |
-
$query = sprintf("INSERT INTO $tableName (EventID, UserID, UserIP, EventData, UserName, BlogId) VALUES(%d, %d, '%s', '%s', '%s', %d)",$eventID, $userID, $userIP, $eventData, $failedLoginUserName,$blog_id);
|
515 |
-
|
516 |
-
global $wpdb;
|
517 |
-
if($eventID == 1002){ // 1002 == failed login
|
518 |
-
|
519 |
-
// check if there is already an event there
|
520 |
-
$eventNumber = $wpdb->get_var("SELECT EventNumber FROM $tableName WHERE EventID = $eventID AND UserIP = '$userIP' AND UserName ='$failedLoginUserName'");
|
521 |
-
if(! empty($eventNumber))
|
522 |
-
{
|
523 |
-
// update
|
524 |
-
$query = "UPDATE $tableName
|
525 |
-
SET
|
526 |
-
EventDate = CURRENT_TIMESTAMP(),
|
527 |
-
EventCount = (EventCount + 1)
|
528 |
-
WHERE EventNumber = ".$eventNumber;
|
529 |
-
}
|
530 |
-
}
|
531 |
-
return ((false === $wpdb->query($query)) ? false : true);
|
532 |
-
}
|
533 |
-
|
534 |
-
|
535 |
-
/*
|
536 |
-
* PUBLIC METHODS
|
537 |
-
* ============================================
|
538 |
-
*/
|
539 |
-
|
540 |
-
static function getEventDetailsData($eventID)
|
541 |
-
{
|
542 |
-
global $wpdb;
|
543 |
-
$table = WPPHDatabase::getFullTableName('events');
|
544 |
-
return $wpdb->get_row("SELECT EventType, EventDescription FROM $table WHERE EventID = $eventID");
|
545 |
-
}
|
546 |
-
|
547 |
-
/**
|
548 |
-
* Retrieve the events from db.
|
549 |
-
* @param string $orderBy. Must be a valid column name. Defaults to EventNumber
|
550 |
-
* @param string $sort ASC or DESC
|
551 |
-
* @param array $limit
|
552 |
-
* @param integer $blogId
|
553 |
-
* @return mixed
|
554 |
-
*/
|
555 |
-
static function getEvents($orderBy='EventNumber', $sort = 'DESC', $limit = array(0,0), $blogId = 1)
|
556 |
-
{
|
557 |
-
$validArgsSort = array('ASC', 'DESC');
|
558 |
-
$validCnTableLogDetails = array('EventID', 'EventType');
|
559 |
-
$validCnTableLog = array('EventNumber', 'EventDate', 'UserID', 'UserIP');
|
560 |
-
|
561 |
-
$l0 = 0;
|
562 |
-
$l1 = 1;
|
563 |
-
if(isset($limit[0]) && ($limit[0] >= 0)){ $l0 = intval($limit[0]); }
|
564 |
-
if(isset($limit[1]) && ($limit[1] >= 1)){ $l1 = intval($limit[1]); }
|
565 |
-
$limit = "$l0,$l1";
|
566 |
-
|
567 |
-
$sort = strtoupper($sort);
|
568 |
-
if(empty($sort) || !in_array($sort, $validArgsSort)) { $sort = $validArgsSort[1]; }
|
569 |
-
|
570 |
-
if(! empty($orderBy)){
|
571 |
-
if(in_array($orderBy, $validCnTableLog)){
|
572 |
-
$orderBy = 'le.'.$orderBy;
|
573 |
-
}
|
574 |
-
elseif(in_array($orderBy, $validCnTableLogDetails)){
|
575 |
-
$orderBy = 'led.'.$orderBy;
|
576 |
-
}
|
577 |
-
}
|
578 |
-
else { $orderBy = 'le.EventNumber'; }
|
579 |
-
|
580 |
-
$t1 = WPPHDatabase::getFullTableName('main');
|
581 |
-
$t2 = WPPHDatabase::getFullTableName('events');
|
582 |
-
global $wpdb;
|
583 |
-
$query = "SELECT le.EventNumber, le.EventID, le.EventDate, le.UserID, le.UserIP, le.EventData, le.EventCount, le.UserName, le.BlogId,
|
584 |
-
led.EventType, led.EventDescription
|
585 |
-
FROM `$t1` as le
|
586 |
-
INNER JOIN `$t2` as led
|
587 |
-
ON le.EventID = led.EventID
|
588 |
-
WHERE ($blogId = 0) OR (le.BlogId = $blogId)
|
589 |
-
ORDER BY $orderBy
|
590 |
-
$sort
|
591 |
-
LIMIT $limit;";
|
592 |
-
return $wpdb->get_results($query, ARRAY_A);
|
593 |
-
}
|
594 |
-
|
595 |
-
}
|
596 |
-
|
597 |
-
/**
|
598 |
-
* Class WPPHEventWatcher
|
599 |
-
* This class provides callable methods that are called inside the hooks registered
|
600 |
-
* in the WPPHEvent class. All methods are internal and should not be used outside
|
601 |
-
* scope.
|
602 |
-
* @static
|
603 |
-
* @internal
|
604 |
-
*/
|
605 |
-
class WPPHEventWatcher extends WPPHEvent
|
606 |
-
{
|
607 |
-
/**
|
608 |
-
* @internal
|
609 |
-
* Hooks to the login event
|
610 |
-
* @param $user_login
|
611 |
-
* @param WP_User $user
|
612 |
-
*/
|
613 |
-
static function watchEventLogin($user_login, $user)
|
614 |
-
{
|
615 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
616 |
-
self::_addLogEvent(1000, $user->ID);
|
617 |
-
}
|
618 |
-
/**
|
619 |
-
* @internal
|
620 |
-
* Hooks to the logout event
|
621 |
-
*/
|
622 |
-
static function watchEventLogout()
|
623 |
-
{
|
624 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
625 |
-
self::_addLogEvent(1001, wp_get_current_user()->ID);
|
626 |
-
}
|
627 |
-
|
628 |
-
|
629 |
-
/**
|
630 |
-
* @internal
|
631 |
-
* Hooks to the user register event
|
632 |
-
*/
|
633 |
-
static function watchEventUserRegister($user_id)
|
634 |
-
{
|
635 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
636 |
-
|
637 |
-
global $current_user;
|
638 |
-
get_currentuserinfo();
|
639 |
-
|
640 |
-
$un = (empty($current_user->user_login) ? 'System' : $current_user->user_login);
|
641 |
-
$uInfo = WPPHDB::getUserInfo($user_id);
|
642 |
-
$nu = $uInfo['userName'];
|
643 |
-
$nur = ucfirst($uInfo['userRole']);
|
644 |
-
|
645 |
-
wpphLog(__METHOD__.'() -> USER INFO', array('user_id'=>$user_id, 'current_user'=>$current_user, 'user_info'=>$uInfo));
|
646 |
-
|
647 |
-
if($un == 'System')
|
648 |
-
{
|
649 |
-
// A new user with the username %username% has registered with the role of %user_role%
|
650 |
-
$eventData = array($nu, $nur);
|
651 |
-
self::_addLogEvent(4000, 0, WPPHUtil::getIP(), $eventData);
|
652 |
-
}
|
653 |
-
else {
|
654 |
-
// %s created new user %s with role %s
|
655 |
-
$eventData = array($un, $nu, $nur);
|
656 |
-
self::_addLogEvent(4001, $current_user->ID, WPPHUtil::getIP(), $eventData);
|
657 |
-
}
|
658 |
-
}
|
659 |
-
|
660 |
-
/**
|
661 |
-
* 6000
|
662 |
-
* @internal
|
663 |
-
* Hooks to the events deletion event
|
664 |
-
*/
|
665 |
-
static function __deleteEvents()
|
666 |
-
{
|
667 |
-
wpphLog(__METHOD__.'() triggered.');
|
668 |
-
|
669 |
-
// check settings and delete the events (if any)
|
670 |
-
$settings = WPPH::getPluginSettings();
|
671 |
-
|
672 |
-
$runCleanup = ((time() - $settings->lastCleanup) < WPPH_CLEANUP_WAIT_TIME);
|
673 |
-
if(! $runCleanup){
|
674 |
-
wpphLog(__METHOD__.'() Ignored. Not enough time elapsed between deletion requests.');
|
675 |
-
return;
|
676 |
-
}
|
677 |
-
|
678 |
-
// check to see how we should do the cleanup (by days or by number)
|
679 |
-
$cleanupType = 1; // by number by default
|
680 |
-
|
681 |
-
if(!empty($settings->daysToKeep)){
|
682 |
-
$cleanupType = 0;
|
683 |
-
}
|
684 |
-
|
685 |
-
// by days
|
686 |
-
if($cleanupType == 0)
|
687 |
-
{
|
688 |
-
if(self::_deleteEventsOlderThan($settings->daysToKeep)){
|
689 |
-
$settings->cleanupRan = 1;
|
690 |
-
$settings->lastCleanup = time();
|
691 |
-
self::_addLogEvent(6000, 0);
|
692 |
-
wpphLog(__METHOD__.'() Cleanup complete.');
|
693 |
-
}
|
694 |
-
}
|
695 |
-
// by number
|
696 |
-
else
|
697 |
-
{
|
698 |
-
if(self::_deleteEventsGreaterThan($settings->eventsToKeep)){
|
699 |
-
$settings->cleanupRan = 1;
|
700 |
-
$settings->lastCleanup = time();
|
701 |
-
self::_addLogEvent(6000, 0);
|
702 |
-
wpphLog(__METHOD__.'() Cleanup complete.');
|
703 |
-
}
|
704 |
-
}
|
705 |
-
WPPH::updatePluginSettings($settings);
|
706 |
-
}
|
707 |
-
|
708 |
-
//@internal
|
709 |
-
// delete by days
|
710 |
-
private static function _deleteEventsOlderThan($days = 1)
|
711 |
-
{
|
712 |
-
global $wpdb;
|
713 |
-
|
714 |
-
// run for each blog
|
715 |
-
if(WPPH::isMultisite())
|
716 |
-
{
|
717 |
-
$old_blog = $wpdb->blogid;
|
718 |
-
$blogIds = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
719 |
-
foreach ($blogIds as $blog_id)
|
720 |
-
{
|
721 |
-
switch_to_blog($blog_id);
|
722 |
-
$query = sprintf("DELETE FROM ".WPPHDatabase::getFullTableName('main')." WHERE BlogID=%d EventDate < (NOW() - INTERVAL %d DAY)",$blog_id, $days);
|
723 |
-
$result = $wpdb->query($query);
|
724 |
-
if($result === false){ $status = 'Error executing query'; }
|
725 |
-
else { $status = 'Query executed'; }
|
726 |
-
wpphLog(__METHOD__.'('.$days.') called for blog: '.$blog_id.'.', array('query'=>$query, 'status'=>$status, 'rowsDeleted'=> (int)$result));
|
727 |
-
}
|
728 |
-
switch_to_blog($old_blog);
|
729 |
-
return true;
|
730 |
-
}
|
731 |
-
else {
|
732 |
-
$query = sprintf("DELETE FROM ".WPPHDatabase::getFullTableName('main')." WHERE EventDate < (NOW() - INTERVAL %d DAY)", $days);
|
733 |
-
$result = $wpdb->query($query);
|
734 |
-
if($result === false){ $status = 'Error executing query'; }
|
735 |
-
else { $status = 'Query executed'; }
|
736 |
-
wpphLog(__METHOD__.'('.$days.') called.', array('query'=>$query, 'status'=>$status, 'rowsDeleted'=> (int)$result));
|
737 |
-
return ($result !== false);
|
738 |
-
}
|
739 |
-
|
740 |
-
}
|
741 |
-
//@internal
|
742 |
-
// delete by number
|
743 |
-
private static function _deleteEventsGreaterThan($number = WPPH_KEEP_MAX_EVENTS)
|
744 |
-
{
|
745 |
-
global $wpdb;
|
746 |
-
if($number > WPPH_KEEP_MAX_EVENTS){ $number = WPPH_KEEP_MAX_EVENTS; }
|
747 |
-
$tableName = WPPHDatabase::getFullTableName('main');
|
748 |
-
|
749 |
-
// run for each blog
|
750 |
-
if(WPPH::isMultisite())
|
751 |
-
{
|
752 |
-
$old_blog = $wpdb->blogid;
|
753 |
-
$blogIds = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
754 |
-
foreach ($blogIds as $blog_id)
|
755 |
-
{
|
756 |
-
switch_to_blog($blog_id);
|
757 |
-
$count = $wpdb->get_var(sprintf("SELECT COUNT(0) FROM $tableName WHERE BlogID=%d",$blog_id));
|
758 |
-
if(empty($count)){
|
759 |
-
wpphLog(__METHOD__.'('.$number.') called for blog id: '.$blog_id.'. Ignored, there are no events for this blog id in the database.');
|
760 |
-
continue;
|
761 |
-
}
|
762 |
-
$keep = $number;
|
763 |
-
if($count > $keep)
|
764 |
-
{
|
765 |
-
$limit = $count - $keep;
|
766 |
-
$query = sprintf("DELETE FROM $tableName WHERE BlogID=%d ORDER BY EventDate LIMIT %d", $blog_id, $limit);
|
767 |
-
$result = $wpdb->query($query);
|
768 |
-
if($result === false){ $status = 'Error executing query'; }
|
769 |
-
else { $status = 'Query executed'; }
|
770 |
-
wpphLog(__METHOD__.'('.$number.') called for blog id: '.$blog_id.'.', array('query'=>$query, 'status'=>$status, 'rowsAffected'=> (int)$result));
|
771 |
-
return ($result !== false);
|
772 |
-
}
|
773 |
-
else {
|
774 |
-
wpphLog(__METHOD__.'('.$number.') called for blog id: '.$blog_id.'. Ignored, there are not enough events to perform this action.');
|
775 |
-
continue;
|
776 |
-
}
|
777 |
-
}
|
778 |
-
switch_to_blog($old_blog);
|
779 |
-
return true;
|
780 |
-
}
|
781 |
-
else {
|
782 |
-
$count = $wpdb->get_var("SELECT COUNT(0) FROM $tableName");
|
783 |
-
if(empty($count)){
|
784 |
-
wpphLog(__METHOD__.'('.$number.') called. Ignored, there are no events in the database');
|
785 |
-
return true;
|
786 |
-
}
|
787 |
-
$keep = $number;
|
788 |
-
if($count > $keep)
|
789 |
-
{
|
790 |
-
$limit = $count - $keep;
|
791 |
-
$query = "DELETE FROM $tableName ORDER BY EventDate LIMIT $limit";
|
792 |
-
$result = $wpdb->query($query);
|
793 |
-
if($result === false){ $status = 'Error executing query'; }
|
794 |
-
else { $status = 'Query executed'; }
|
795 |
-
wpphLog(__METHOD__.'('.$number.') called.', array('query'=>$query, 'status'=>$status, 'rowsAffected'=> (int)$result));
|
796 |
-
return ($result !== false);
|
797 |
-
}
|
798 |
-
else {
|
799 |
-
wpphLog(__METHOD__.'('.$number.') called. Ignored, there are not enough events to trigger this action.');
|
800 |
-
return true;
|
801 |
-
}
|
802 |
-
}
|
803 |
-
}
|
804 |
-
|
805 |
-
/**
|
806 |
-
* @internal
|
807 |
-
* Fired on login failure
|
808 |
-
*/
|
809 |
-
static function watchLoginFailure($username='')
|
810 |
-
{
|
811 |
-
wpphLog(__METHOD__.'() triggered by hook.', array('username'=>$username));
|
812 |
-
self::_addLogEvent(1002,0,WPPHUtil::getIP(),array($username), base64_encode($username));
|
813 |
-
}
|
814 |
-
|
815 |
-
static function watchUserInfoUpdated($userID)
|
816 |
-
{
|
817 |
-
wpphLog(__METHOD__.'() triggered by hook.', array('POST DATA'=>$_POST));
|
818 |
-
|
819 |
-
// get info for the currently logged in user
|
820 |
-
$current_user = wp_get_current_user();
|
821 |
-
$cid = $current_user->ID;
|
822 |
-
$cName = $current_user->user_login;
|
823 |
-
|
824 |
-
// get info for the currently updated user
|
825 |
-
$editedUserInfo = WPPHDB::getUserInfo($userID);
|
826 |
-
$editedUserName = $editedUserInfo['userName'];
|
827 |
-
$initialUserRole = $editedUserInfo['userRole'];
|
828 |
-
|
829 |
-
// check and see *what* has been updated...
|
830 |
-
|
831 |
-
// If a user's role has been updated
|
832 |
-
if(!empty($_POST['role'])){
|
833 |
-
$updatedRole = trim($_POST['role']);
|
834 |
-
if(self::_userRoleUpdated($cid, $initialUserRole, $updatedRole, $editedUserName, $cName)){
|
835 |
-
//return;
|
836 |
-
}
|
837 |
-
}
|
838 |
-
|
839 |
-
// If a user's password has been updated
|
840 |
-
if(!empty($_POST['pass1'])){
|
841 |
-
if(self::_userPasswordUpdated($userID, $cid, $cName, $editedUserName, $initialUserRole)){
|
842 |
-
// return;
|
843 |
-
}
|
844 |
-
}
|
845 |
-
|
846 |
-
// if a user's email was updated
|
847 |
-
if(! empty($_POST['email'])){
|
848 |
-
global $wpdb;
|
849 |
-
// get current user's email
|
850 |
-
$oldEmail = $wpdb->get_var("SELECT user_email FROM ".$wpdb->users." WHERE ID = $userID");
|
851 |
-
// new email
|
852 |
-
$newEmailSafe = mysql_real_escape_string($_POST['email']);
|
853 |
-
self::_userEmailUpdated($userID, $cid, $cName, $oldEmail, $newEmailSafe);
|
854 |
-
}
|
855 |
-
}
|
856 |
-
|
857 |
-
/**
|
858 |
-
* @internal
|
859 |
-
* Triggered when a user's role is updated
|
860 |
-
* @param $currentUserID
|
861 |
-
* @param $initialUserRole
|
862 |
-
* @param $updatedRole
|
863 |
-
* @param $editedUserName
|
864 |
-
* @param $currentUserName
|
865 |
-
* @return bool
|
866 |
-
*/
|
867 |
-
private static function _userRoleUpdated($currentUserID, $initialUserRole, $updatedRole, $editedUserName, $currentUserName)
|
868 |
-
{
|
869 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
870 |
-
|
871 |
-
if(strcasecmp($initialUserRole, $updatedRole)==0){
|
872 |
-
wpphLog(__METHOD__.'() Ignored. Role did not change.');
|
873 |
-
return false;
|
874 |
-
}
|
875 |
-
|
876 |
-
// The role of user <strong>%s</strong> was changed from <strong>%s</strong> to <strong>%s</strong> by <strong>%s</strong>
|
877 |
-
$eData = array($editedUserName, ucfirst($initialUserRole), ucfirst($updatedRole), $currentUserName);
|
878 |
-
|
879 |
-
self::_addLogEvent(4002, $currentUserID, WPPHUtil::getIP(), $eData);
|
880 |
-
return true;
|
881 |
-
}
|
882 |
-
|
883 |
-
/**
|
884 |
-
* @internal
|
885 |
-
* Triggered when a user's role is updated
|
886 |
-
* @param $userID
|
887 |
-
* @param $currentUserID
|
888 |
-
* @param $currentUserName
|
889 |
-
* @param $editedUserName
|
890 |
-
* @param $editedUserRole
|
891 |
-
* @return bool
|
892 |
-
*/
|
893 |
-
private static function _userPasswordUpdated($userID, $currentUserID, $currentUserName, $editedUserName, $editedUserRole)
|
894 |
-
{
|
895 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
896 |
-
|
897 |
-
// check to see who's who here
|
898 |
-
if($userID == $currentUserID)
|
899 |
-
{
|
900 |
-
self::_addLogEvent(4003, $currentUserID);
|
901 |
-
return true;
|
902 |
-
}
|
903 |
-
|
904 |
-
$eData = array($currentUserName, $editedUserName, ucfirst($editedUserRole));
|
905 |
-
self::_addLogEvent(4004, $currentUserID, WPPHUtil::getIP(), $eData);
|
906 |
-
return true;
|
907 |
-
}
|
908 |
-
|
909 |
-
/**
|
910 |
-
* @internal
|
911 |
-
* Triggered when a user's email is updated
|
912 |
-
* @param $userID The user ID triggering this hook
|
913 |
-
* @param $currentUserID The ID of the current logged in user
|
914 |
-
* @param $currentUserName
|
915 |
-
* @param $oldEmail
|
916 |
-
* @param $newEmail
|
917 |
-
* @return bool
|
918 |
-
*/
|
919 |
-
private static function _userEmailUpdated($userID, $currentUserID, $currentUserName, $oldEmail, $newEmail)
|
920 |
-
{
|
921 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
922 |
-
|
923 |
-
// check if email updated
|
924 |
-
if($newEmail == $oldEmail){
|
925 |
-
wpphLog(__METHOD__.'() Ignored. Email did not change.');
|
926 |
-
return false;
|
927 |
-
}
|
928 |
-
|
929 |
-
// check to see who's who here
|
930 |
-
if($userID == $currentUserID)
|
931 |
-
{
|
932 |
-
self::_addLogEvent(4005, $currentUserID, WPPHUtil::getIP(), array($oldEmail, $newEmail));
|
933 |
-
return true;
|
934 |
-
}
|
935 |
-
|
936 |
-
// get info for the currently updated user
|
937 |
-
$editedUserInfo = WPPHDB::getUserInfo($userID);
|
938 |
-
$editedUserName = $editedUserInfo['userName'];
|
939 |
-
|
940 |
-
// %user_making_change% changed the email address of user account %user% from %old_email% to %new_email%
|
941 |
-
$eData = array($currentUserName, $editedUserName, $oldEmail, $newEmail);
|
942 |
-
|
943 |
-
self::_addLogEvent(4006, $currentUserID, WPPHUtil::getIP(), $eData);
|
944 |
-
return true;
|
945 |
-
}
|
946 |
-
|
947 |
-
/**
|
948 |
-
* @internal
|
949 |
-
* @param $userID the id of the user being deleted
|
950 |
-
* Triggered when a user is deleted
|
951 |
-
*/
|
952 |
-
static function watchUserDeletion($userID)
|
953 |
-
{
|
954 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
955 |
-
|
956 |
-
global $current_user;
|
957 |
-
get_currentuserinfo();
|
958 |
-
|
959 |
-
$un = (empty($current_user->user_login) ? 'System' : $current_user->user_login);
|
960 |
-
if($un == 'System'){
|
961 |
-
$currentUserID = 0;
|
962 |
-
}
|
963 |
-
else { $currentUserID = $current_user->ID; }
|
964 |
-
|
965 |
-
// get info for the currently deleted user
|
966 |
-
$_userInfo = WPPHDB::getUserInfo($userID);
|
967 |
-
$_userName = $_userInfo['userName'];
|
968 |
-
$_userRole = ucfirst($_userInfo['userRole']);
|
969 |
-
|
970 |
-
self::_addLogEvent(4007, $currentUserID, WPPHUtil::getIP(), array($_userName, $_userRole, $un));
|
971 |
-
}
|
972 |
-
|
973 |
-
// # 5001
|
974 |
-
static function watchPluginActivate()
|
975 |
-
{
|
976 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
977 |
-
|
978 |
-
$userID = wp_get_current_user()->ID;
|
979 |
-
$userIP = WPPHUtil::getIP();
|
980 |
-
|
981 |
-
// activate one by link
|
982 |
-
if(isset($_GET['action']) && ($_GET['action']=='activate') || isset($_GET['action2']) && ($_GET['action2']=='activate'))
|
983 |
-
{
|
984 |
-
wpphLog('------------------------------- 1 ------------------------------');
|
985 |
-
$pluginFile = isset($_GET['plugin']) ? $_GET['plugin'] : null;
|
986 |
-
if(empty($pluginFile)){
|
987 |
-
wpphLog("EMPTY plugin param in GET");
|
988 |
-
return;
|
989 |
-
}
|
990 |
-
$fp = WP_PLUGIN_DIR.'/'.$pluginFile;
|
991 |
-
if(! is_file($fp)){
|
992 |
-
wpphLog("Plugin not found", array('filePath'=>$fp));
|
993 |
-
return;
|
994 |
-
}
|
995 |
-
$pluginData = get_plugin_data($fp,false,false);
|
996 |
-
self::_addLogEvent(5001, $userID, $userIP, array($pluginData['Name'],$pluginFile));
|
997 |
-
wpphLog('Plugin activated.', array('plugin file'=>$pluginFile));
|
998 |
-
return;
|
999 |
-
}
|
1000 |
-
// one by bulk
|
1001 |
-
elseif(isset($_POST['action']) && ($_POST['action'] == 'activate-selected') || (isset($_POST['action2']) && ($_POST['action2'] == 'activate-selected')))
|
1002 |
-
{
|
1003 |
-
wpphLog('------------------------------- 2 ------------------------------');
|
1004 |
-
if(! empty($_POST['checked']))
|
1005 |
-
{
|
1006 |
-
foreach($_POST['checked'] as $k=>$pluginFile)
|
1007 |
-
{
|
1008 |
-
if(empty($pluginFile)){
|
1009 |
-
wpphLog("EMPTY plugin param in POST");
|
1010 |
-
return;
|
1011 |
-
}
|
1012 |
-
$fp = WP_PLUGIN_DIR.'/'.$pluginFile;
|
1013 |
-
if(! is_file($fp)){
|
1014 |
-
wpphLog("Plugin not found", array('filePath'=>$fp));
|
1015 |
-
return;
|
1016 |
-
}
|
1017 |
-
$pluginData = get_plugin_data($fp,false,false);
|
1018 |
-
self::_addLogEvent(5001, $userID, $userIP, array($pluginData['Name'],$pluginFile));
|
1019 |
-
wpphLog('Plugin activated.', array('plugin file'=>$pluginFile));
|
1020 |
-
}
|
1021 |
-
}
|
1022 |
-
}
|
1023 |
-
// more by bulk
|
1024 |
-
elseif(isset($_POST['activate-multi']) && ($_POST['action']=='activate-selected' || (isset($_POST['action2']) && $_POST['action2']=='activate-selected')))
|
1025 |
-
{
|
1026 |
-
wpphLog('------------------------------- 3 ------------------------------');
|
1027 |
-
if(! empty($_POST['checked']))
|
1028 |
-
{
|
1029 |
-
foreach($_POST['checked'] as $k=>$pluginFile)
|
1030 |
-
{
|
1031 |
-
if(empty($pluginFile)){
|
1032 |
-
wpphLog("EMPTY plugin param in POST");
|
1033 |
-
return;
|
1034 |
-
}
|
1035 |
-
$fp = WP_PLUGIN_DIR.'/'.$pluginFile;
|
1036 |
-
if(! is_file($fp)){
|
1037 |
-
wpphLog("Plugin not found", array('filePath'=>$fp));
|
1038 |
-
return;
|
1039 |
-
}
|
1040 |
-
$pluginData = get_plugin_data($fp,false,false);
|
1041 |
-
self::_addLogEvent(5001, $userID, $userIP, array($pluginData['Name'],$pluginFile));
|
1042 |
-
wpphLog('Plugin activated.', array('plugin file'=>$pluginFile));
|
1043 |
-
}
|
1044 |
-
}
|
1045 |
-
}
|
1046 |
-
}
|
1047 |
-
// # 5002
|
1048 |
-
static function watchPluginDeactivate()
|
1049 |
-
{
|
1050 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1051 |
-
|
1052 |
-
// get info for the currently logged in user
|
1053 |
-
$userID = wp_get_current_user()->ID;
|
1054 |
-
$userIP = WPPHUtil::getIP();
|
1055 |
-
|
1056 |
-
// activate one by link
|
1057 |
-
if((isset($_GET['action']) && $_GET['action']=='deactivate') || isset($_GET['action2']) && ($_GET['action2']=='deactivate'))
|
1058 |
-
{
|
1059 |
-
wpphLog('------------------------------- 1 ------------------------------');
|
1060 |
-
$pluginFile = $_GET['plugin'];
|
1061 |
-
$pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
|
1062 |
-
$pluginName = $pluginData['Name'];
|
1063 |
-
self::_addLogEvent(5002, $userID, $userIP, array($pluginName,$pluginFile));
|
1064 |
-
wpphLog('Plugin deactivated.', array('plugin file'=>$pluginFile));
|
1065 |
-
}
|
1066 |
-
// one by bulk
|
1067 |
-
elseif((isset($_POST['action']) && $_POST['action'] == 'deactivate-selected') || isset($_POST['action2']) && ($_POST['action2'] == 'deactivate-selected'))
|
1068 |
-
{
|
1069 |
-
if(! empty($_POST['checked']))
|
1070 |
-
{
|
1071 |
-
wpphLog('------------------------------- 2 ------------------------------');
|
1072 |
-
foreach($_POST['checked'] as $k=>$pluginFile){
|
1073 |
-
$pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
|
1074 |
-
$pluginName = $pluginData['Name'];
|
1075 |
-
self::_addLogEvent(5002, $userID, $userIP, array($pluginName,$pluginFile));
|
1076 |
-
wpphLog('Plugin deactivated.', array('plugin file'=>$pluginFile));
|
1077 |
-
}
|
1078 |
-
}
|
1079 |
-
}
|
1080 |
-
// more by bulk
|
1081 |
-
elseif(isset($_GET['deactivate-multi']) && (isset($_POST['action']) && $_POST['action']=='deactivate-selected' || (isset($_POST['action2']) && $_POST['action2']=='deactivate-selected')))
|
1082 |
-
{
|
1083 |
-
if(! empty($_POST['checked']))
|
1084 |
-
{
|
1085 |
-
wpphLog('------------------------------- 3 ------------------------------');
|
1086 |
-
foreach($_POST['checked'] as $k=>$pluginFile){
|
1087 |
-
$pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
|
1088 |
-
$pluginName = $pluginData['Name'];
|
1089 |
-
self::_addLogEvent(5002, $userID, $userIP, array($pluginName,$pluginFile));
|
1090 |
-
wpphLog('Plugin deactivated.', array('plugin file'=>$pluginFile));
|
1091 |
-
}
|
1092 |
-
}
|
1093 |
-
}
|
1094 |
-
}
|
1095 |
-
|
1096 |
-
// # 5000
|
1097 |
-
static function watchPluginInstall()
|
1098 |
-
{
|
1099 |
-
if(defined('WPPH_PLUGIN_INSTALLED_OK')){ return; }
|
1100 |
-
if(empty($_GET)) { return; }
|
1101 |
-
|
1102 |
-
if(isset($_GET['action']) && $_GET['action']=='install-plugin'){
|
1103 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1104 |
-
wpph_installPlugin($_GET['plugin'], wp_get_current_user()->ID, WPPHUtil::getIP());
|
1105 |
-
}
|
1106 |
-
elseif(isset($_GET['action2']) && $_GET['action2']=='install-plugin'){
|
1107 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1108 |
-
wpph_installPlugin($_GET['plugin'], wp_get_current_user()->ID, WPPHUtil::getIP());
|
1109 |
-
}
|
1110 |
-
}
|
1111 |
-
// # 5003
|
1112 |
-
static function watchPluginUninstall()
|
1113 |
-
{
|
1114 |
-
if(empty($_POST)) { return; }
|
1115 |
-
if(! isset($_POST['verify-delete'])) { return; }
|
1116 |
-
if(empty($_POST['checked'])){ return; }
|
1117 |
-
|
1118 |
-
$action = '';
|
1119 |
-
if(! empty($_POST['action'])){ $action = $_POST['action'];}
|
1120 |
-
elseif(! empty($_POST['action2'])){ $action = $_POST['action2'];}
|
1121 |
-
if(empty($action) || $action != 'delete-selected') {
|
1122 |
-
return;
|
1123 |
-
}
|
1124 |
-
|
1125 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1126 |
-
// get info for the currently logged in user
|
1127 |
-
$current_user = wp_get_current_user();
|
1128 |
-
foreach($_POST['checked'] as $pluginFile){
|
1129 |
-
$pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
|
1130 |
-
$pluginName = $pluginData['Name'];
|
1131 |
-
self::_addLogEvent(5003,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
|
1132 |
-
wpphLog('Plugin uninstalled.', array('plugin file'=>$pluginFile));
|
1133 |
-
}
|
1134 |
-
}
|
1135 |
-
// # 5004
|
1136 |
-
static function watchPluginUpgrade()
|
1137 |
-
{
|
1138 |
-
wpphLog(__METHOD__.'() triggered.');
|
1139 |
-
|
1140 |
-
$current_user = wp_get_current_user();
|
1141 |
-
$userID = $current_user->ID;
|
1142 |
-
$ip = WPPHUtil::getIP();
|
1143 |
-
|
1144 |
-
// One by link
|
1145 |
-
if(!empty($_GET))
|
1146 |
-
{
|
1147 |
-
if(isset($_GET['action']) && !empty($_GET['action']))
|
1148 |
-
{
|
1149 |
-
$action = $_GET['action'];
|
1150 |
-
if(! in_array($action, array('upgrade-plugin', 'update-selected'))){
|
1151 |
-
return;
|
1152 |
-
}
|
1153 |
-
if(! empty($_GET['plugin'])){ $pluginFile = $_GET['plugin']; }
|
1154 |
-
if(empty($pluginFile)){
|
1155 |
-
return;
|
1156 |
-
}
|
1157 |
-
$pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
|
1158 |
-
$pluginName = $pluginData['Name'];
|
1159 |
-
// Upgraded the plugin <strong>%s</strong> installed in /<strong>%s</strong>
|
1160 |
-
self::_addLogEvent(5004,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
|
1161 |
-
wpphLog('Plugin upgraded.', array('plugin file'=>$pluginFile));
|
1162 |
-
return;
|
1163 |
-
}
|
1164 |
-
}
|
1165 |
-
elseif(isset($_POST))
|
1166 |
-
{
|
1167 |
-
$action = '';
|
1168 |
-
if(isset($_POST['action']) && !empty($_POST['action'])){
|
1169 |
-
$action = $_POST['action'];
|
1170 |
-
if(! in_array($action, array('upgrade-plugin', 'update-selected'))){
|
1171 |
-
$action = '';
|
1172 |
-
if(isset($_POST['action2']) && !empty($_POST['action2'])){
|
1173 |
-
$action = $_POST['action2'];
|
1174 |
-
if(! in_array($action, array('upgrade-plugin', 'update-selected'))){
|
1175 |
-
return;
|
1176 |
-
}
|
1177 |
-
}
|
1178 |
-
}
|
1179 |
-
}
|
1180 |
-
if(empty($action)) { return; }
|
1181 |
-
|
1182 |
-
if(! isset($_POST['checked']) || empty($_POST['checked'])){
|
1183 |
-
return;
|
1184 |
-
}
|
1185 |
-
foreach($_POST['checked'] as $i=>$pluginFile){
|
1186 |
-
$pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
|
1187 |
-
$pluginName = $pluginData['Name'];
|
1188 |
-
self::_addLogEvent(5004,$userID, $ip, array($pluginName,$pluginFile));
|
1189 |
-
wpphLog('Plugin upgraded.', array('plugin file'=>$pluginFile));
|
1190 |
-
}
|
1191 |
-
}
|
1192 |
-
}
|
1193 |
-
|
1194 |
-
|
1195 |
-
static function watchBlogActivity($newStatus, $oldStatus, $post)
|
1196 |
-
{
|
1197 |
-
wpphLog(__METHOD__.'() triggered.');
|
1198 |
-
|
1199 |
-
wpphLog(__METHOD__.'. POST STATUS DATA', array(
|
1200 |
-
'$oldStatus' => $oldStatus,
|
1201 |
-
'$newStatus' => $newStatus,
|
1202 |
-
'$postStatus' => $post->post_status,
|
1203 |
-
'$post' => $post
|
1204 |
-
));
|
1205 |
-
|
1206 |
-
// IGNORE STATES - so we skip generating multiple events
|
1207 |
-
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { wpphLog('Doing autosave'); return; }
|
1208 |
-
if(empty($post->post_type)){ wpphLog('Empty post->post_type'); return; }
|
1209 |
-
if($post->post_type == 'revision') { wpphLog('Post type == revision.'); return; }
|
1210 |
-
if($newStatus == 'auto-draft' || ($oldStatus == 'new' && $newStatus=='auto-draft')) { wpphLog('Doing draft autosave'); return; }
|
1211 |
-
|
1212 |
-
$types = WPPHPost::getPostTypes();
|
1213 |
-
if(! in_array($post->post_type, $types)){
|
1214 |
-
wpphLog('Invalid post type.', array('post-type'=>$post->post_type));
|
1215 |
-
return;
|
1216 |
-
}
|
1217 |
-
do_action('wpph_set_post_type','custom');
|
1218 |
-
|
1219 |
-
$postID = $post->ID;
|
1220 |
-
$postTitle = $post->post_title;
|
1221 |
-
$postUrl = get_permalink($postID);
|
1222 |
-
$postStatus = $post->post_status;
|
1223 |
-
$currentUserID = wp_get_current_user()->ID;
|
1224 |
-
$userID = $postAuthorID = (int)$post->post_author;
|
1225 |
-
if($currentUserID != $postAuthorID){
|
1226 |
-
// someone else is doing this
|
1227 |
-
$userID = $currentUserID;
|
1228 |
-
}
|
1229 |
-
|
1230 |
-
// CHECK TO SEE IF THIS UPDATE IS FROM THE QUICK EDIT FORM or the default wp post editor
|
1231 |
-
if(isset($_POST['original_post_status']))
|
1232 |
-
{
|
1233 |
-
$originalPostStatus = $_POST['original_post_status'];
|
1234 |
-
}
|
1235 |
-
else{
|
1236 |
-
// quick edit form
|
1237 |
-
$originalPostStatus = (isset($_POST['_status']) ? $_POST['_status'] : null);
|
1238 |
-
}
|
1239 |
-
|
1240 |
-
if(empty($originalPostStatus)){
|
1241 |
-
// wpphLog(__METHOD__.' $_POST["_status"] not found. $originalPostStatus is EMPTY - nothing to do here.');
|
1242 |
-
// wpphLog(__METHOD__.' POST DATA',$_POST);
|
1243 |
-
return;
|
1244 |
-
}
|
1245 |
-
|
1246 |
-
$postTypePost = $postTypePage = $customPostType = false;
|
1247 |
-
|
1248 |
-
if($post->post_type == 'post'){ $postTypePost = true;}
|
1249 |
-
elseif($post->post_type == 'page'){ $postTypePage = true;}
|
1250 |
-
else { $customPostType = true; }
|
1251 |
-
|
1252 |
-
if(!$postTypePost && !$postTypePage && !$customPostType){
|
1253 |
-
wpphLog('Ignored. Invalid post type', array('postType'=>$post->post_type));
|
1254 |
-
return;
|
1255 |
-
}
|
1256 |
-
|
1257 |
-
WPPHPost::$currentPostType = $post->post_type;
|
1258 |
-
|
1259 |
-
global $wpdb;
|
1260 |
-
|
1261 |
-
//## 2025 & 2026 & 2040
|
1262 |
-
if($customPostType){ self::watchPostVisibilityChange($oldStatus, $newStatus, $userID, $postTitle, $post, 2040); }
|
1263 |
-
else { self::watchPostVisibilityChange($oldStatus, $newStatus, $userID, $postTitle, $post, ($postTypePost) ? 2025 : 2026); }
|
1264 |
-
|
1265 |
-
//## 2027 & 2028 & 2041
|
1266 |
-
if(! in_array($oldStatus, array('new', 'auto-draft'))){
|
1267 |
-
if($customPostType){ self::watchPostDateChange($userID, $postTitle, $post->post_date, 2041);}
|
1268 |
-
else { self::watchPostDateChange($userID, $postTitle, $post->post_date, ($postTypePost) ? 2027 : 2028); }
|
1269 |
-
}
|
1270 |
-
|
1271 |
-
//## 2016 & 2036
|
1272 |
-
if($postTypePost){ self::watchPostCategoriesChange($post, $wpdb, $postTitle, 2016); }
|
1273 |
-
elseif($customPostType){ self::watchPostCategoriesChange($post, $wpdb, $postTitle, 2036); }
|
1274 |
-
|
1275 |
-
//## 2019 & 2020 & 2038
|
1276 |
-
$authorChanged = false;
|
1277 |
-
if(isset($GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID']))
|
1278 |
-
{
|
1279 |
-
$quickFormEnabled = isset($GLOBALS['WPPH_SCREEN_EDITOR_ENABLED']) ? true : false;
|
1280 |
-
if($customPostType){
|
1281 |
-
if(WPPHPost::postAuthorChanged((int)$GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID'], $postID, $userID, $postTitle, 2038, $quickFormEnabled)){
|
1282 |
-
$GLOBALS['WPPH_POST_AUTHOR_UPDATED'] = true;
|
1283 |
-
$authorChanged = true;
|
1284 |
-
}
|
1285 |
-
}
|
1286 |
-
else {
|
1287 |
-
if(WPPHPost::postAuthorChanged((int)$GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID'], $postID, $userID, $postTitle, ($postTypePost) ? 2019 : 2020, $quickFormEnabled)){
|
1288 |
-
$GLOBALS['WPPH_POST_AUTHOR_UPDATED'] = true;
|
1289 |
-
$authorChanged = true;
|
1290 |
-
}
|
1291 |
-
}
|
1292 |
-
unset($GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID']);
|
1293 |
-
}
|
1294 |
-
|
1295 |
-
// 2000 & 2004 & 2029
|
1296 |
-
if($newStatus != 'publish'){
|
1297 |
-
if($originalPostStatus == 'auto-draft' || ($oldStatus=='new' && $newStatus=='inherit' && $postStatus=='inherit'))
|
1298 |
-
{
|
1299 |
-
if($customPostType){ WPPHPost::newPostAsDraft($userID, $postID, $postTitle, 2029); }
|
1300 |
-
else { WPPHPost::newPostAsDraft($userID, $postID, $postTitle, ($postTypePost) ? 2000 : 2004); }
|
1301 |
-
}
|
1302 |
-
}
|
1303 |
-
|
1304 |
-
// check if post/page modified
|
1305 |
-
$postModified = self::watchPostChanged($wpdb, $postID);
|
1306 |
-
wpphLog('POST MODIFIED',array('modified'=> $postModified ? 'true' : 'false'));
|
1307 |
-
|
1308 |
-
//## 2000 & 2003 & 2004 & 2007 & 2032
|
1309 |
-
if(($oldStatus == 'draft') && ($newStatus == 'draft' && $postStatus == 'draft'))
|
1310 |
-
{
|
1311 |
-
if($originalPostStatus == 'draft')
|
1312 |
-
{
|
1313 |
-
//## 2003 - draft post updated
|
1314 |
-
if($postTypePost || $customPostType){
|
1315 |
-
// only if 2016 || 2017 || 2019 were not triggered
|
1316 |
-
if(isset($GLOBALS['WPPH_POST_CATEGORIES_UPDATED']) || isset($GLOBALS['WPPH_POST_URL_UPDATED']) || isset($GLOBALS['WPPH_POST_AUTHOR_UPDATED'])){}
|
1317 |
-
else {
|
1318 |
-
$event = ($customPostType ? 2032 : 2003);
|
1319 |
-
WPPHPost::draftPostUpdated($userID, $postID, $postTitle, $event);
|
1320 |
-
$postModified = false;
|
1321 |
-
}
|
1322 |
-
}
|
1323 |
-
//## 2007 - draft page updated
|
1324 |
-
else {
|
1325 |
-
// only if 2018 || 2020 were not triggered
|
1326 |
-
if(isset($GLOBALS['WPPH_PAGE_URL_UPDATED']) || isset($GLOBALS['WPPH_PAGE_AUTHOR_UPDATED'])){}
|
1327 |
-
else {
|
1328 |
-
WPPHPost::draftPostUpdated($userID, $postID, $postTitle, 2007);
|
1329 |
-
$postModified = false;
|
1330 |
-
}
|
1331 |
-
}
|
1332 |
-
}
|
1333 |
-
}
|
1334 |
-
|
1335 |
-
//## 2001 & 2005 & 2030 - new post/page published
|
1336 |
-
elseif(in_array($oldStatus, array('draft','auto-draft','pending')) && $newStatus == 'publish' && $postStatus == 'publish')
|
1337 |
-
{
|
1338 |
-
$event = 0;
|
1339 |
-
if($customPostType) { $event = 2030;}
|
1340 |
-
elseif($postTypePost) { $event = 2001; }
|
1341 |
-
elseif($postTypePage) { $event = 2005; }
|
1342 |
-
if(! empty($event)){
|
1343 |
-
WPPHPost::newPostPublished($userID, $postTitle, $postUrl, $event);
|
1344 |
-
return; // no need to process further
|
1345 |
-
}
|
1346 |
-
}
|
1347 |
-
|
1348 |
-
//## 2021 & 2022 & 2039 : published -> pending
|
1349 |
-
elseif($oldStatus == 'publish' && $newStatus == 'pending' && $postStatus == 'pending')
|
1350 |
-
{
|
1351 |
-
$event = 0;
|
1352 |
-
if($customPostType) { $event = 2039;}
|
1353 |
-
elseif($postTypePost) { $event = 2021; }
|
1354 |
-
elseif($postTypePage) { $event = 2022; }
|
1355 |
-
if(! empty($event)){
|
1356 |
-
WPPHPost::postStatusChanged($postTitle, __('Published'), __('Pending Review'), $userID, $event);
|
1357 |
-
}
|
1358 |
-
}
|
1359 |
-
|
1360 |
-
//## 2021 & 2022 & 2039 : pending -> draft
|
1361 |
-
elseif($oldStatus == 'pending' && $newStatus == 'draft' && $postStatus == 'draft')
|
1362 |
-
{
|
1363 |
-
$event = 0;
|
1364 |
-
if($customPostType) { $event = 2039;}
|
1365 |
-
elseif($postTypePost) { $event = 2021; }
|
1366 |
-
elseif($postTypePage) { $event = 2022; }
|
1367 |
-
if(! empty($event)){
|
1368 |
-
WPPHPost::postStatusChanged($postTitle, __('Pending Review'), __('Draft'), $userID, $event);
|
1369 |
-
}
|
1370 |
-
}
|
1371 |
-
|
1372 |
-
//## 2021 & 2022 & 2039 : draft -> pending
|
1373 |
-
elseif($oldStatus == 'draft' && $newStatus == 'pending' && $postStatus == 'pending')
|
1374 |
-
{
|
1375 |
-
$event = 0;
|
1376 |
-
if($customPostType) { $event = 2039;}
|
1377 |
-
elseif($postTypePost) { $event = 2021; }
|
1378 |
-
elseif($postTypePage) { $event = 2022; }
|
1379 |
-
if(! empty($event)){
|
1380 |
-
WPPHPost::postStatusChanged($postTitle, __('Draft'), __('Pending Review'), $userID, $event);
|
1381 |
-
}
|
1382 |
-
}
|
1383 |
-
|
1384 |
-
//## 2021 & 2022 & 2039 : published -> draft
|
1385 |
-
elseif($oldStatus == 'publish' && $newStatus == 'draft' && $postStatus == 'draft')
|
1386 |
-
{
|
1387 |
-
$event = 0;
|
1388 |
-
if($customPostType) { $event = 2039;}
|
1389 |
-
elseif($postTypePost) { $event = 2021; }
|
1390 |
-
elseif($postTypePage) { $event = 2022; }
|
1391 |
-
if(! empty($event)){
|
1392 |
-
WPPHPost::postStatusChanged($postTitle, __('Published'), __('Draft'), $userID, $event);
|
1393 |
-
}
|
1394 |
-
}
|
1395 |
-
|
1396 |
-
//## 2002 & 2006 & 2017 & 2018 & 2031 & 2037 : published post/page updated
|
1397 |
-
elseif($oldStatus == 'publish' && $newStatus == 'publish' && $postStatus == 'publish')
|
1398 |
-
{
|
1399 |
-
// trigger: 2017 & 2018 & 2037 - Changed the URL of the post %post_name% from %old_url% to %new_url%
|
1400 |
-
if(isset($GLOBALS['WPPH_POST_NEW_URL']) || $postModified)
|
1401 |
-
{
|
1402 |
-
$event = 0;
|
1403 |
-
if($customPostType) { $event = 2037;}
|
1404 |
-
elseif($postTypePost) { $event = 2017; }
|
1405 |
-
elseif($postTypePage) { $event = 2018; }
|
1406 |
-
if(! empty($event)){
|
1407 |
-
if(WPPHPost::postUrlUpdated($GLOBALS['WPPH_POST_NEW_URL'], get_permalink($postID), $userID, $postTitle, $event))
|
1408 |
-
{
|
1409 |
-
unset($GLOBALS['WPPH_POST_NEW_URL']);
|
1410 |
-
$GLOBALS['WPPH_POST_URL_UPDATED'] = $postTypePost;
|
1411 |
-
$GLOBALS['WPPH_PAGE_URL_UPDATED'] = $postTypePage;
|
1412 |
-
}
|
1413 |
-
}
|
1414 |
-
}
|
1415 |
-
// 2002 & 2031
|
1416 |
-
if($postTypePost || $customPostType)
|
1417 |
-
{
|
1418 |
-
if(isset($GLOBALS['WPPH_POST_CATEGORIES_UPDATED']) || isset($GLOBALS['WPPH_POST_URL_UPDATED'])
|
1419 |
-
|| isset($GLOBALS['WPPH_POST_AUTHOR_UPDATED']) || isset($GLOBALS['WPPH_POST_PROTECTED_TRANSITION'])
|
1420 |
-
|| isset($GLOBALS['WPPH_POST_DATE_CHANGED']) || isset($GLOBALS['WPPH_PREVENT_BUBBLE'])){}
|
1421 |
-
// Modified the published blog post %post_title%. Blog post URL is %post_URL%
|
1422 |
-
else {
|
1423 |
-
if(! $authorChanged){
|
1424 |
-
WPPHPost::publishedPostUpdated($userID, $postTitle, $postUrl, ($postTypePost) ? 2002 : 2031);
|
1425 |
-
}
|
1426 |
-
}
|
1427 |
-
}
|
1428 |
-
else
|
1429 |
-
{
|
1430 |
-
if(isset($GLOBALS['WPPH_PAGE_URL_UPDATED']) || isset($GLOBALS['WPPH_PAGE_AUTHOR_UPDATED'])
|
1431 |
-
|| isset($GLOBALS['WPPH_PAGE_PROTECTED_TRANSITION']) || isset($GLOBALS['WPPH_POST_DATE_CHANGED'])
|
1432 |
-
|| isset($GLOBALS['WPPH_PREVENT_BUBBLE'])){}
|
1433 |
-
// Modified the published page %page_title%. Page URL is %URL%
|
1434 |
-
else {
|
1435 |
-
if(! $authorChanged){
|
1436 |
-
WPPHPost::publishedPostUpdated($userID, $postTitle, $postUrl, 2006);
|
1437 |
-
}
|
1438 |
-
}
|
1439 |
-
}
|
1440 |
-
// no need to process further
|
1441 |
-
return;
|
1442 |
-
}
|
1443 |
-
|
1444 |
-
// if post name changed - we probably have a URL change here
|
1445 |
-
// 2003 & 2007 & 2032
|
1446 |
-
if($postModified){
|
1447 |
-
if( isset($GLOBALS['WPPH_PAGE_AUTHOR_UPDATED']) || isset($GLOBALS['WPPH_PAGE_AUTHOR_UPDATED'])
|
1448 |
-
|| isset($GLOBALS['WPPH_POST_CATEGORIES_UPDATED'])|| isset($GLOBALS['WPPH_POST_DATE_CHANGED'])){}
|
1449 |
-
else {
|
1450 |
-
$event = 0;
|
1451 |
-
if($customPostType) { $event = 2032;}
|
1452 |
-
elseif($postTypePost) { $event = 2003; }
|
1453 |
-
elseif($postTypePage) { $event = 2007; }
|
1454 |
-
if(! empty($event)){
|
1455 |
-
WPPHPost::draftPostUpdated($userID, $postID, $postTitle, $event);
|
1456 |
-
}
|
1457 |
-
}
|
1458 |
-
}
|
1459 |
-
}
|
1460 |
-
|
1461 |
-
static function watchTrash($postID)
|
1462 |
-
{
|
1463 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1464 |
-
// get info for the currently logged in user
|
1465 |
-
$current_user = wp_get_current_user();
|
1466 |
-
global $wpdb;
|
1467 |
-
$postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
|
1468 |
-
$postTitle = $postInfo->post_title;
|
1469 |
-
$postType = $postInfo->post_type;
|
1470 |
-
$customPostType = false;
|
1471 |
-
$postTypePost = (($postType == 'post') ? true : false);
|
1472 |
-
$postTypePage = (($postType == 'page') ? true : false);
|
1473 |
-
if(!$postTypePost && !$postTypePage){
|
1474 |
-
if(WPPHPost::validatePostType($postType)){
|
1475 |
-
$customPostType = true;
|
1476 |
-
}
|
1477 |
-
}
|
1478 |
-
$event = 0;
|
1479 |
-
if($customPostType) { $event = 2033;}
|
1480 |
-
elseif($postTypePost) { $event = 2008; }
|
1481 |
-
elseif($postTypePage) { $event = 2009; }
|
1482 |
-
if(! empty($event)){
|
1483 |
-
if($event == 2033){
|
1484 |
-
self::_addLogEvent($event, $current_user->ID, WPPHUtil::getIP(), array($postTitle, ucfirst($postType), $postID));
|
1485 |
-
}
|
1486 |
-
else { self::_addLogEvent($event, $current_user->ID, WPPHUtil::getIP(), array($postTitle,$postID)); }
|
1487 |
-
|
1488 |
-
wpphLog('Post/Page deleted.', array('title'=>$postTitle, 'id'=>$postID));
|
1489 |
-
}
|
1490 |
-
}
|
1491 |
-
|
1492 |
-
// 2010
|
1493 |
-
static function watchFileUploaded($attachmentID)
|
1494 |
-
{
|
1495 |
-
global $wpdb;
|
1496 |
-
// get info for the currently logged in user
|
1497 |
-
$current_user = wp_get_current_user();
|
1498 |
-
$rowData = $wpdb->get_row("SELECT guid FROM ".$wpdb->posts." WHERE ID = ".$attachmentID);
|
1499 |
-
$fileName = basename($rowData->guid);
|
1500 |
-
$dirName = dirname($rowData->guid);
|
1501 |
-
// Uploaded the file %file name$ in %file location%
|
1502 |
-
self::_addLogEvent(2010, $current_user->ID, WPPHUtil::getIP(), array($fileName, $dirName));
|
1503 |
-
wpphLog('File uploaded.', array('title'=>$fileName, 'url'=>$dirName));
|
1504 |
-
$GLOBALS['WPPH_PLUGIN_FILE_UPLOADED_IGNORE_DELETE'] = true;
|
1505 |
-
}
|
1506 |
-
// 2011
|
1507 |
-
static function watchFileUploadedDeleted($attachmentID)
|
1508 |
-
{
|
1509 |
-
if(isset($GLOBALS['WPPH_PLUGIN_FILE_UPLOADED_IGNORE_DELETE'])){
|
1510 |
-
// return, because if this variable is set this means this action is
|
1511 |
-
// triggered inside WP after uploading a plugin and there's no reason to log this event.
|
1512 |
-
return;
|
1513 |
-
}
|
1514 |
-
global $wpdb;
|
1515 |
-
// get info for the currently logged in user
|
1516 |
-
$current_user = wp_get_current_user();
|
1517 |
-
$rowData = $wpdb->get_row("SELECT post_title, guid FROM ".$wpdb->posts." WHERE ID = ".$attachmentID);
|
1518 |
-
// Deleted file %file name$ from %file_location%
|
1519 |
-
self::_addLogEvent(2011, $current_user->ID, WPPHUtil::getIP(), array($rowData->post_title,dirname($rowData->guid)));
|
1520 |
-
wpphLog('File deleted.', array('title'=>$rowData->post_title, 'url'=>dirname($rowData->guid)));
|
1521 |
-
}
|
1522 |
-
|
1523 |
-
// 2012, 2013, 2034
|
1524 |
-
static function watchFileDeletion($postID)
|
1525 |
-
{
|
1526 |
-
global $wpdb;
|
1527 |
-
$userID = wp_get_current_user()->ID;
|
1528 |
-
$postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
|
1529 |
-
$postTitle = $postInfo->post_title;
|
1530 |
-
$postType = $postInfo->post_type;
|
1531 |
-
$customPostType = false;
|
1532 |
-
$postTypePost = (($postType == 'post') ? true : false);
|
1533 |
-
$postTypePage = (($postType == 'page') ? true : false);
|
1534 |
-
if(!$postTypePost && !$postTypePage){
|
1535 |
-
if(WPPHPost::validatePostType($postType)){
|
1536 |
-
$customPostType = true;
|
1537 |
-
}
|
1538 |
-
}
|
1539 |
-
$event = 0;
|
1540 |
-
if($customPostType) { $event = 2034;}
|
1541 |
-
elseif($postTypePost) { $event = 2012; }
|
1542 |
-
elseif($postTypePage) { $event = 2013; }
|
1543 |
-
if(! empty($event)){
|
1544 |
-
if($event == 2034){
|
1545 |
-
self::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst($postType)));
|
1546 |
-
}
|
1547 |
-
else { self::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle)); }
|
1548 |
-
wpphLog('Post/Page trashed.', array('name'=>$postTitle));
|
1549 |
-
}
|
1550 |
-
}
|
1551 |
-
|
1552 |
-
// 2014, 2015, 2035
|
1553 |
-
static function watchTrashUndo($postID)
|
1554 |
-
{
|
1555 |
-
global $wpdb;
|
1556 |
-
$userID = wp_get_current_user()->ID;
|
1557 |
-
$postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
|
1558 |
-
$postTitle = $postInfo->post_title;
|
1559 |
-
$postType = $postInfo->post_type;
|
1560 |
-
$customPostType = false;
|
1561 |
-
$postTypePost = (($postType == 'post') ? true : false);
|
1562 |
-
$postTypePage = (($postType == 'page') ? true : false);
|
1563 |
-
if(!$postTypePost && !$postTypePage){
|
1564 |
-
if(WPPHPost::validatePostType($postType)){
|
1565 |
-
$customPostType = true;
|
1566 |
-
}
|
1567 |
-
}
|
1568 |
-
$event = 0;
|
1569 |
-
if($customPostType) { $event = 2035;}
|
1570 |
-
elseif($postTypePost) { $event = 2014; }
|
1571 |
-
elseif($postTypePage) { $event = 2015; }
|
1572 |
-
if(! empty($event)){
|
1573 |
-
if($event == 2035){
|
1574 |
-
self::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst($postType)));
|
1575 |
-
}
|
1576 |
-
else { self::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle)); }
|
1577 |
-
wpphLog('Post/Page restored from trash.', array('name'=>$postTitle));
|
1578 |
-
}
|
1579 |
-
}
|
1580 |
-
|
1581 |
-
static function watchWidgetActivity()
|
1582 |
-
{
|
1583 |
-
if ('POST' != strtoupper($_SERVER['REQUEST_METHOD']))
|
1584 |
-
{
|
1585 |
-
return;
|
1586 |
-
}
|
1587 |
-
if(!isset($_POST['widget-id']) || empty($_POST['widget-id'])){
|
1588 |
-
return;
|
1589 |
-
}
|
1590 |
-
|
1591 |
-
$postData = $_POST;
|
1592 |
-
|
1593 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1594 |
-
//wpphLog('POST DATA', $postData);
|
1595 |
-
|
1596 |
-
global $wp_registered_sidebars;
|
1597 |
-
$canCheckSidebar = (empty($wp_registered_sidebars) ? false : true);
|
1598 |
-
$userID = wp_get_current_user()->ID;
|
1599 |
-
|
1600 |
-
// if widget added
|
1601 |
-
if(isset($postData['add_new']) && $postData['add_new'] == 'multi')
|
1602 |
-
{
|
1603 |
-
$widgetType = $postData['id_base'];
|
1604 |
-
$sidebar = $postData['sidebar'];
|
1605 |
-
if($canCheckSidebar && preg_match("/^sidebar-/",$sidebar)){
|
1606 |
-
$sidebar = $wp_registered_sidebars[$sidebar]['name'];
|
1607 |
-
}
|
1608 |
-
self::_addLogEvent(2042, $userID, WPPHUtil::getIP(), array($widgetType, $sidebar));
|
1609 |
-
wpphLog('User added a widget.', array('type'=>$widgetType, 'sidebar'=>$sidebar));
|
1610 |
-
}
|
1611 |
-
// if widget deleted
|
1612 |
-
elseif(isset($postData['delete_widget']) && intval($postData['delete_widget']) == 1)
|
1613 |
-
{
|
1614 |
-
$widgetType = $postData['id_base'];
|
1615 |
-
$sidebar = $postData['sidebar'];
|
1616 |
-
if($canCheckSidebar && preg_match("/^sidebar-/",$sidebar)){
|
1617 |
-
$sidebar = $wp_registered_sidebars[$sidebar]['name'];
|
1618 |
-
}
|
1619 |
-
self::_addLogEvent(2044, $userID, WPPHUtil::getIP(), array($widgetType, $sidebar));
|
1620 |
-
wpphLog('User deleted a widget.', array('type'=>$widgetType, 'sidebar'=>$sidebar));
|
1621 |
-
}
|
1622 |
-
// if widget modified
|
1623 |
-
elseif(isset($postData['id_base']) && !empty($postData['id_base']))
|
1624 |
-
{
|
1625 |
-
wpphLog('CHECKING IF WIDGET MODIFIED....');
|
1626 |
-
// get info from $_POST
|
1627 |
-
$wId = 0;
|
1628 |
-
if(! empty($postData['multi_number'])){
|
1629 |
-
$wId = intval($postData['multi_number']);
|
1630 |
-
}
|
1631 |
-
else {
|
1632 |
-
if(! empty($postData['widget_number'])){
|
1633 |
-
$wId = intval($postData['widget_number']);
|
1634 |
-
}
|
1635 |
-
}
|
1636 |
-
if(empty($wId)){
|
1637 |
-
wpphLog('EMPTY $wId');
|
1638 |
-
return;
|
1639 |
-
}
|
1640 |
-
$wName = $postData['id_base'];
|
1641 |
-
$sidebar = $postData['sidebar'];
|
1642 |
-
$wData = isset($postData["widget-".$wName][$wId]) ? $postData["widget-".$wName][$wId] : null;
|
1643 |
-
|
1644 |
-
if(empty($wData)){
|
1645 |
-
wpphLog('EMPTY $wData');
|
1646 |
-
return;
|
1647 |
-
}
|
1648 |
-
// get info from db
|
1649 |
-
$wdbData = get_option("widget_".$wName);
|
1650 |
-
if(empty($wdbData[$wId])){
|
1651 |
-
wpphLog('EMPTY $wbData[$wId]');
|
1652 |
-
return;
|
1653 |
-
}
|
1654 |
-
// transform 'on' -> 1
|
1655 |
-
foreach($wData as $k=>&$v){
|
1656 |
-
if($v == 'on'){ $v = 1; }
|
1657 |
-
}
|
1658 |
-
// compare - checks for any changes inside widgets
|
1659 |
-
$diff = array_diff_assoc($wData, $wdbData[$wId]);
|
1660 |
-
$count = count($diff);
|
1661 |
-
if($count > 0){
|
1662 |
-
if($canCheckSidebar && preg_match("/^sidebar-/",$sidebar)){
|
1663 |
-
$sidebar = $wp_registered_sidebars[$sidebar]['name'];
|
1664 |
-
}
|
1665 |
-
//wpphLog('DIFF EXISTS.', array('wdata'=>$wData, 'wdbdata'=>$wdbData[$wId], 'diff'=>$diff));
|
1666 |
-
self::_addLogEvent(2043, $userID, WPPHUtil::getIP(), array($wName, $sidebar));
|
1667 |
-
wpphLog('User modified a widget.', array('type'=>$wName, 'sidebar'=>$sidebar));
|
1668 |
-
}
|
1669 |
-
else {wpphLog('No change.');}
|
1670 |
-
}
|
1671 |
-
}
|
1672 |
-
//@ 2045
|
1673 |
-
static function watchWidgetMove()
|
1674 |
-
{
|
1675 |
-
if(isset($_POST) && !empty($_POST['sidebars']))
|
1676 |
-
{
|
1677 |
-
wpphLog('Checking for moved widgets');
|
1678 |
-
$crtSidebars = $_POST['sidebars'];
|
1679 |
-
$sidebars = array();
|
1680 |
-
//-- WP
|
1681 |
-
foreach ( $crtSidebars as $key => $val ) {
|
1682 |
-
$sb = array();
|
1683 |
-
if ( !empty($val) ) {
|
1684 |
-
$val = explode(',', $val);
|
1685 |
-
foreach ( $val as $k => $v ) {
|
1686 |
-
if ( strpos($v, 'widget-') === false ){ continue; }
|
1687 |
-
$sb[$k] = substr($v, strpos($v, '_') + 1);
|
1688 |
-
}
|
1689 |
-
}
|
1690 |
-
$sidebars[$key] = $sb;
|
1691 |
-
}
|
1692 |
-
//-- WP
|
1693 |
-
$crtSidebars = $sidebars;
|
1694 |
-
$dbSidebars = get_option('sidebars_widgets');
|
1695 |
-
$wName = $fromSidebar = $toSidebar = '';
|
1696 |
-
foreach($crtSidebars as $sidebarName => $values)
|
1697 |
-
{
|
1698 |
-
if(is_array($values) && ! empty($values))
|
1699 |
-
{
|
1700 |
-
if(isset($dbSidebars[$sidebarName]))
|
1701 |
-
{
|
1702 |
-
foreach($values as $i => $widgetName)
|
1703 |
-
{
|
1704 |
-
if(! in_array($widgetName, $dbSidebars[$sidebarName])){
|
1705 |
-
$toSidebar = $sidebarName;
|
1706 |
-
$wName = $widgetName;
|
1707 |
-
foreach($dbSidebars as $name => $v){
|
1708 |
-
if(is_array($v) && !empty($v)){
|
1709 |
-
if(in_array($widgetName, $v)){
|
1710 |
-
$fromSidebar = $name;
|
1711 |
-
break;
|
1712 |
-
}
|
1713 |
-
}
|
1714 |
-
}
|
1715 |
-
}
|
1716 |
-
}
|
1717 |
-
}
|
1718 |
-
}
|
1719 |
-
}
|
1720 |
-
if(empty($wName) || empty($fromSidebar) || empty($toSidebar)){
|
1721 |
-
wpphLog('No change.');
|
1722 |
-
return;
|
1723 |
-
}
|
1724 |
-
|
1725 |
-
$userID = wp_get_current_user()->ID;
|
1726 |
-
$ip = WPPHUtil::getIP();
|
1727 |
-
|
1728 |
-
if(preg_match("/^sidebar-/", $fromSidebar) || preg_match("/^sidebar-/",$toSidebar)){
|
1729 |
-
// This option will hold the data needed to trigger the event 2045
|
1730 |
-
// as at this moment the $wp_registered_sidebars variable is not yet populated
|
1731 |
-
// so we cannot retrieve the name for sidebar-1 || sidebar-2
|
1732 |
-
// we will then check for this variable in the triggerWidgetMoveEvent() function
|
1733 |
-
$GLOBALS['WPPH_WIDGET_MOVE'] = array('widget'=>$wName, 'from'=>$fromSidebar, 'to'=>$toSidebar, 'user'=>$userID, 'ip', 'ip'=>$ip);
|
1734 |
-
wpphLog('Widget moved. Data saved to variable: WPPH_WIDGET_MOVE');
|
1735 |
-
return;
|
1736 |
-
}
|
1737 |
-
self::_addLogEvent(2045, $userID, $ip, array($wName, $fromSidebar, $toSidebar));
|
1738 |
-
}
|
1739 |
-
}
|
1740 |
-
|
1741 |
-
static function triggerWidgetMoveEvent()
|
1742 |
-
{
|
1743 |
-
wpphLog(__METHOD__.'() triggered.');
|
1744 |
-
$data = (isset($GLOBALS['WPPH_WIDGET_MOVE']) ? $GLOBALS['WPPH_WIDGET_MOVE'] : null);
|
1745 |
-
if(empty($data)){
|
1746 |
-
wpphLog("Global var: WPPH_WIDGET_MOVE not available yet. Nothing to do here.");
|
1747 |
-
return;
|
1748 |
-
}
|
1749 |
-
$from = $data['from'];
|
1750 |
-
$to = $data['to'];
|
1751 |
-
global $wp_registered_sidebars;
|
1752 |
-
if(preg_match("/^sidebar-/", $from)){ $from = (isset($wp_registered_sidebars[$from]) ? $wp_registered_sidebars[$from]['name'] : $from); }
|
1753 |
-
if(preg_match("/^sidebar-/", $to)){ $to = (isset($wp_registered_sidebars[$to]) ? $wp_registered_sidebars[$to]['name'] : $to); }
|
1754 |
-
self::_addLogEvent(2045, $data['user'], $data['ip'], array($data['widget'], $from, $to));
|
1755 |
-
}
|
1756 |
-
|
1757 |
-
|
1758 |
-
// 3000 - Theme activated
|
1759 |
-
static function watchThemeChange($themeName)
|
1760 |
-
{
|
1761 |
-
// get info for the currently logged in user
|
1762 |
-
$current_user = wp_get_current_user();
|
1763 |
-
// // Activated the theme %themeName%
|
1764 |
-
self::_addLogEvent(3000, $current_user->ID, WPPHUtil::getIP(), array($themeName));
|
1765 |
-
wpphLog('Theme activated.', array('name'=>$themeName));
|
1766 |
-
}
|
1767 |
-
|
1768 |
-
// 2023 - category created
|
1769 |
-
static function watchCategoryAdd(array $postData)
|
1770 |
-
{
|
1771 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1772 |
-
|
1773 |
-
if(!empty($_POST['screen']) && !empty($_POST['tag-name']) &&
|
1774 |
-
$_POST['screen'] == 'edit-category' &&
|
1775 |
-
$_POST['taxonomy'] == 'category' &&
|
1776 |
-
$_POST['action'] == 'add-tag')
|
1777 |
-
{
|
1778 |
-
$categoryName = sanitize_text_field($_POST['tag-name']);
|
1779 |
-
|
1780 |
-
// get info for the currently logged in user
|
1781 |
-
$current_user = wp_get_current_user();
|
1782 |
-
// Created a new category called %categoryName%
|
1783 |
-
self::_addLogEvent(2023, $current_user->ID, WPPHUtil::getIP(), array($categoryName));
|
1784 |
-
wpphLog('Category added.', array('name'=>$categoryName));
|
1785 |
-
}
|
1786 |
-
// adding the new category when writing a blog post
|
1787 |
-
elseif(! empty($_POST['newcategory']) && $_POST['action'] == 'add-category')
|
1788 |
-
{
|
1789 |
-
$categoryName = sanitize_text_field($_POST['newcategory']);
|
1790 |
-
|
1791 |
-
// get info for the currently logged in user
|
1792 |
-
$current_user = wp_get_current_user();
|
1793 |
-
// Created a new category called %categoryName%
|
1794 |
-
self::_addLogEvent(2023, $current_user->ID, WPPHUtil::getIP(), array($categoryName));
|
1795 |
-
wpphLog('Category added.', array('name'=>$categoryName));
|
1796 |
-
}
|
1797 |
-
}
|
1798 |
-
|
1799 |
-
// 2024 - category deleted
|
1800 |
-
static function watchCategoryDelete(array $postData)
|
1801 |
-
{
|
1802 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
1803 |
-
|
1804 |
-
if(empty($postData)){ return; }
|
1805 |
-
|
1806 |
-
// get info for the currently logged in user
|
1807 |
-
$current_user = wp_get_current_user();
|
1808 |
-
$userID = $current_user->ID;
|
1809 |
-
$userIP = WPPHUtil::getIP();
|
1810 |
-
|
1811 |
-
//@internal
|
1812 |
-
function __alertDeletedCategory($userID, $userIP, $categoryID){
|
1813 |
-
$category = get_category($categoryID);
|
1814 |
-
$categoryName = $category->cat_name;
|
1815 |
-
WPPHEvent::_addLogEvent(2024, $userID, $userIP, array($categoryName));
|
1816 |
-
wpphLog('Category deleted.', array('name'=>$categoryName));
|
1817 |
-
}
|
1818 |
-
|
1819 |
-
$action = '';
|
1820 |
-
if(! empty($postData['action'])){ $action = $postData['action'];}
|
1821 |
-
elseif(! empty($postData['action2'])){ $action = $postData['action2'];}
|
1822 |
-
if(empty($action)) {
|
1823 |
-
return;
|
1824 |
-
}
|
1825 |
-
|
1826 |
-
// delete one
|
1827 |
-
if($action == 'delete-tag' && $postData['taxonomy'] == 'category' && !empty($postData['tag_ID'])){
|
1828 |
-
__alertDeletedCategory($userID, $userIP, $postData['tag_ID']);
|
1829 |
-
}
|
1830 |
-
|
1831 |
-
// bulk delete
|
1832 |
-
elseif($action == 'delete' && $postData['taxonomy'] == 'category' && !empty($postData['delete_tags'])){
|
1833 |
-
foreach($postData['delete_tags'] as $categoryID){
|
1834 |
-
__alertDeletedCategory($userID, $userIP, $categoryID);
|
1835 |
-
}
|
1836 |
-
}
|
1837 |
-
}
|
1838 |
-
|
1839 |
-
// 2025, 2026
|
1840 |
-
static function watchPostVisibilityChange($oldStatus, $newStatus, $userID, $postTitle, $post, $event)
|
1841 |
-
{
|
1842 |
-
$args = func_get_args();
|
1843 |
-
wpphLog(__METHOD__.'() triggered.', array('params'=>$args));
|
1844 |
-
|
1845 |
-
global $wpdb;
|
1846 |
-
|
1847 |
-
$crtPostPassword = $wpdb->get_var("SELECT post_password FROM ".$wpdb->posts." WHERE ID = ".$post->ID);
|
1848 |
-
$oldPostPassword = (isset($GLOBALS['WPPH_OLD_POST_PASSWORD']) ? $GLOBALS['WPPH_OLD_POST_PASSWORD'] : null);
|
1849 |
-
|
1850 |
-
$from = $to = '';
|
1851 |
-
|
1852 |
-
// public -> pwd protected
|
1853 |
-
// pwd protected -> public
|
1854 |
-
if($oldStatus == 'publish' && $newStatus == 'publish')
|
1855 |
-
{
|
1856 |
-
if(! WPPH::isMultisite()){
|
1857 |
-
// if post is already pwd protected and there is no change, it will still be issued an event: public to pwd protected
|
1858 |
-
if(isset($GLOBALS['WPPH_POST_PWD_PROTECTED']) && $GLOBALS['WPPH_POST_PWD_PROTECTED']){
|
1859 |
-
$GLOBALS['WPPH_PREVENT_BUBBLE'] = true;
|
1860 |
-
wpphLog(__METHOD__.'() No change.');
|
1861 |
-
return;
|
1862 |
-
}
|
1863 |
-
}
|
1864 |
-
|
1865 |
-
// pwd protected -> public
|
1866 |
-
if(empty($crtPostPassword) && !empty($oldPostPassword)){
|
1867 |
-
$from = __('Password Protected');
|
1868 |
-
$to = __('Public');
|
1869 |
-
}
|
1870 |
-
// public -> pwd protected
|
1871 |
-
else {
|
1872 |
-
if(! empty($crtPostPassword)){
|
1873 |
-
$from = __('Public');
|
1874 |
-
$to = __('Password Protected');
|
1875 |
-
}
|
1876 |
-
}
|
1877 |
-
}
|
1878 |
-
// public -> private
|
1879 |
-
// pwd protected -> private
|
1880 |
-
elseif($oldStatus == 'publish' && $newStatus == 'private')
|
1881 |
-
{
|
1882 |
-
// public -> private
|
1883 |
-
if(empty($crtPostPassword) && empty($oldPostPassword)){
|
1884 |
-
$from = __('Public');
|
1885 |
-
$to = __('Private');
|
1886 |
-
}
|
1887 |
-
// pwd protected -> private
|
1888 |
-
else {
|
1889 |
-
if(!empty($oldPostPassword)){
|
1890 |
-
$from = __('Password Protected');
|
1891 |
-
$to = __('Private');
|
1892 |
-
}
|
1893 |
-
}
|
1894 |
-
}
|
1895 |
-
// private -> public
|
1896 |
-
// private -> pwd protected
|
1897 |
-
elseif($oldStatus == 'private' && $newStatus == 'publish')
|
1898 |
-
{
|
1899 |
-
// private -> public
|
1900 |
-
if(empty($oldPostPassword) && empty($crtPostPassword)){
|
1901 |
-
$from = __('Private');
|
1902 |
-
$to = __('Public');
|
1903 |
-
}
|
1904 |
-
// private -> pwd protected
|
1905 |
-
else {
|
1906 |
-
if(empty($oldPostPassword) && !empty($crtPostPassword)){
|
1907 |
-
$from = __('Private');
|
1908 |
-
$to = __('Password Protected');
|
1909 |
-
}
|
1910 |
-
}
|
1911 |
-
}
|
1912 |
-
wpphLog("Changing post visibility:",array('from'=>$from, 'to'=>$to));
|
1913 |
-
if(empty($from) || empty($to)){
|
1914 |
-
return;
|
1915 |
-
}
|
1916 |
-
|
1917 |
-
$GLOBALS['WPPH_PREVENT_BUBBLE'] = true;
|
1918 |
-
WPPHPost::postVisibilityChanged($userID, $postTitle, $from, $to, $event);
|
1919 |
-
}
|
1920 |
-
|
1921 |
-
// 2027 & 2028
|
1922 |
-
static function watchPostDateChange($userID, $postTitle, $postCurrentDate, $event)
|
1923 |
-
{
|
1924 |
-
wpphLog(__METHOD__.'() triggered.');
|
1925 |
-
|
1926 |
-
if($GLOBALS['WPPH_POST_IS_NEW']){
|
1927 |
-
wpphLog('Nothing to do. The post is brand new.');
|
1928 |
-
return;
|
1929 |
-
}
|
1930 |
-
if(empty($GLOBALS['WPPH_POST_OLD_DATE'])){
|
1931 |
-
wpphLog('Empty global WPPH_POST_OLD_DATE, nothing to do.');
|
1932 |
-
return;
|
1933 |
-
}
|
1934 |
-
|
1935 |
-
$t1 = strtotime($GLOBALS['WPPH_POST_OLD_DATE']);
|
1936 |
-
$t2 = strtotime($postCurrentDate);
|
1937 |
-
|
1938 |
-
if($t1 == $t2){
|
1939 |
-
wpphLog('No change.');
|
1940 |
-
return;
|
1941 |
-
}
|
1942 |
-
if(empty($t1) || empty($postCurrentDate)){
|
1943 |
-
wpphLog('Empty $t1 or $postCurrentDate. Nothing to do.');
|
1944 |
-
return;
|
1945 |
-
}
|
1946 |
-
|
1947 |
-
$format = get_option('date_format');
|
1948 |
-
$from = date($format, $t1);
|
1949 |
-
$to = date($format, $t2);
|
1950 |
-
if($from == $to){
|
1951 |
-
wpphLog('No date change.');
|
1952 |
-
return;
|
1953 |
-
}
|
1954 |
-
wpphLog('POST DATE CHANGED',array(
|
1955 |
-
'from' => $from . '('.$t1.')',
|
1956 |
-
'to' => $to . '('.$t2.')'
|
1957 |
-
));
|
1958 |
-
WPPHPost::postDateChanged($userID, $postTitle, $from, $to, $event);
|
1959 |
-
}
|
1960 |
-
|
1961 |
-
static function watchPostCategoriesChange($post, $wpdb, $postTitle, $event)
|
1962 |
-
{
|
1963 |
-
wpphLog(__METHOD__.'() triggered.');
|
1964 |
-
|
1965 |
-
if(! wpph_isEventEnabled($event)){
|
1966 |
-
wpphLog('Event '.$event.' is not enabled. Ignoring request.');
|
1967 |
-
return true;
|
1968 |
-
}
|
1969 |
-
|
1970 |
-
if(isset($GLOBALS['WPPH_POST_OLD_CATEGORIES']))
|
1971 |
-
{
|
1972 |
-
$originalCats = $GLOBALS['WPPH_POST_OLD_CATEGORIES'];
|
1973 |
-
$categories_1 = array();
|
1974 |
-
foreach($originalCats as $catID){
|
1975 |
-
$cat = get_category($catID);
|
1976 |
-
array_push($categories_1, $cat->name);
|
1977 |
-
}
|
1978 |
-
$categories_2 = array();
|
1979 |
-
$newCats = $post->post_category;
|
1980 |
-
if(empty($newCats)){
|
1981 |
-
wpphLog('No categories found for this post.');
|
1982 |
-
return true;
|
1983 |
-
}
|
1984 |
-
wpphLog('$newCats', $newCats);
|
1985 |
-
foreach($newCats as $catID){
|
1986 |
-
if(empty($catID)){
|
1987 |
-
wpphLog('Category is empty: '.$catID);
|
1988 |
-
continue;
|
1989 |
-
}
|
1990 |
-
$cat = get_category($catID);
|
1991 |
-
array_push($categories_2, $cat->name);
|
1992 |
-
}
|
1993 |
-
|
1994 |
-
sort($categories_1);
|
1995 |
-
sort($categories_2);
|
1996 |
-
|
1997 |
-
// categories updated
|
1998 |
-
if($categories_1 <> $categories_2)
|
1999 |
-
{
|
2000 |
-
if(empty($categories_1)){
|
2001 |
-
// get the name of the default category
|
2002 |
-
$optID = get_option('default_category');
|
2003 |
-
$query = $wpdb->prepare("SELECT wpt.name FROM ".$wpdb->terms." AS wpt
|
2004 |
-
INNER JOIN ".$wpdb->options." AS wpo
|
2005 |
-
WHERE wpo.option_id = %d
|
2006 |
-
AND wpt.term_id = %d;", $optID, $optID);
|
2007 |
-
$defaultCategoryName = $wpdb->get_var($query);
|
2008 |
-
|
2009 |
-
// if categories-2 contains only the name of the default category...
|
2010 |
-
if(count($categories_2) == 1){
|
2011 |
-
if(strcasecmp($categories_2[0], $defaultCategoryName) == 0){
|
2012 |
-
// nothing to do here...
|
2013 |
-
$GLOBALS['WPPH_POST_CATEGORIES_UPDATED'] = true;
|
2014 |
-
}
|
2015 |
-
}
|
2016 |
-
else {
|
2017 |
-
$c1 = implode(', ', $categories_1);
|
2018 |
-
$c2 = implode(', ', $categories_2);
|
2019 |
-
WPPHPost::postCategoriesUpdated(wp_get_current_user()->ID, $postTitle, $c1, $c2, $event);
|
2020 |
-
$GLOBALS['WPPH_POST_CATEGORIES_UPDATED'] = true;
|
2021 |
-
}
|
2022 |
-
}
|
2023 |
-
else {
|
2024 |
-
$c1 = implode(', ', $categories_1);
|
2025 |
-
$c2 = implode(', ', $categories_2);
|
2026 |
-
WPPHPost::postCategoriesUpdated(wp_get_current_user()->ID, $postTitle, $c1, $c2, $event);
|
2027 |
-
$GLOBALS['WPPH_POST_CATEGORIES_UPDATED'] = true;
|
2028 |
-
}
|
2029 |
-
}
|
2030 |
-
}
|
2031 |
-
}
|
2032 |
-
|
2033 |
-
// 2017 & 2018 - Post/page modified
|
2034 |
-
// convenience method to trigger a post/page modified event
|
2035 |
-
static function watchPostChanged($wpdb, $postID)
|
2036 |
-
{
|
2037 |
-
wpphLog(__METHOD__.'() triggered.');
|
2038 |
-
|
2039 |
-
if(isset($GLOBALS['WPPH_POST_OLD_NAME'])){
|
2040 |
-
// get the current post name and compare
|
2041 |
-
$result = $wpdb->get_row("SELECT post_title, post_name, post_password, post_date FROM ".$wpdb->posts." WHERE ID = $postID");
|
2042 |
-
if(empty($result)){ return false; }
|
2043 |
-
$postName = (empty($result->post_name) ? $result->post_title : $result->post_name);
|
2044 |
-
return($GLOBALS['WPPH_POST_OLD_NAME'] != $postName);
|
2045 |
-
}
|
2046 |
-
return false;
|
2047 |
-
}
|
2048 |
-
|
2049 |
-
|
2050 |
-
// 7000 new site added to network
|
2051 |
-
static function watchBlogAdded($blog_id, $user_id)
|
2052 |
-
{
|
2053 |
-
if(empty($blog_id)) { return; }
|
2054 |
-
$blogName = WPPHNetwork::getBlogName($blog_id);
|
2055 |
-
if(empty($blogName)) { return; }
|
2056 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2057 |
-
WPPHEvent::_addLogEvent(7000, wp_get_current_user()->ID, WPPHUtil::getIP(), array($blogName), null, $currentBlogID);
|
2058 |
-
wpphLog(__METHOD__.'() triggered by hook. Blog added: '.$blogName.'; user ID = '.$user_id);
|
2059 |
-
}
|
2060 |
-
|
2061 |
-
// 7001 - blog archived
|
2062 |
-
static function watchBlogArchived($blog_id)
|
2063 |
-
{
|
2064 |
-
if(empty($blog_id)) { return; }
|
2065 |
-
$blogName = WPPHNetwork::getBlogName($blog_id);
|
2066 |
-
if(empty($blogName)) { return; }
|
2067 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2068 |
-
WPPHEvent::_addLogEvent(7001, wp_get_current_user()->ID, WPPHUtil::getIP(), array($blogName), null, $currentBlogID);
|
2069 |
-
wpphLog(__METHOD__.'() triggered by hook. Blog archived: '.$blogName);
|
2070 |
-
}
|
2071 |
-
|
2072 |
-
// 7002 - blog unarchived
|
2073 |
-
static function watchBlogUnarchived($blog_id)
|
2074 |
-
{
|
2075 |
-
if(empty($blog_id)) { return; }
|
2076 |
-
$blogName = WPPHNetwork::getBlogName($blog_id);
|
2077 |
-
if(empty($blogName)) { return; }
|
2078 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2079 |
-
WPPHEvent::_addLogEvent(7002, wp_get_current_user()->ID, WPPHUtil::getIP(), array($blogName), null, $currentBlogID);
|
2080 |
-
wpphLog(__METHOD__.'() triggered by hook. Blog unarchived: '.$blogName);
|
2081 |
-
}
|
2082 |
-
|
2083 |
-
// 7003 - blog activated
|
2084 |
-
static function watchBlogActivated($blog_id)
|
2085 |
-
{
|
2086 |
-
if(empty($blog_id)) { return; }
|
2087 |
-
$blogName = WPPHNetwork::getBlogName($blog_id);
|
2088 |
-
if(empty($blogName)) { return; }
|
2089 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2090 |
-
WPPHEvent::_addLogEvent(7003, wp_get_current_user()->ID, WPPHUtil::getIP(), array($blogName), null, $currentBlogID);
|
2091 |
-
wpphLog(__METHOD__.'() triggered by hook. Blog activated: '.$blogName);
|
2092 |
-
}
|
2093 |
-
|
2094 |
-
// 7004 - blog deactivated
|
2095 |
-
static function watchBlogDeactivated($blog_id)
|
2096 |
-
{
|
2097 |
-
if(empty($blog_id)) { return; }
|
2098 |
-
$blogName = WPPHNetwork::getBlogName($blog_id);
|
2099 |
-
if(empty($blogName)) { return; }
|
2100 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2101 |
-
WPPHEvent::_addLogEvent(7004, wp_get_current_user()->ID, WPPHUtil::getIP(), array($blogName), null, $currentBlogID);
|
2102 |
-
wpphLog(__METHOD__.'() triggered by hook. Blog deactivated: '.$blogName);
|
2103 |
-
}
|
2104 |
-
|
2105 |
-
// 7005 - blog deleted
|
2106 |
-
static function watchBlogDeleted($blog_id)
|
2107 |
-
{
|
2108 |
-
if(empty($blog_id)) { return; }
|
2109 |
-
$blogName = WPPHNetwork::getBlogName($blog_id);
|
2110 |
-
if(empty($blogName)) { return; }
|
2111 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2112 |
-
WPPHEvent::_addLogEvent(7005, wp_get_current_user()->ID, WPPHUtil::getIP(), array($blogName), null, $currentBlogID);
|
2113 |
-
wpphLog(__METHOD__.'() triggered by hook. Blog deleted: ', array('id'=>$blog_id, 'name'=>$blogName));
|
2114 |
-
}
|
2115 |
-
|
2116 |
-
// 4008 && 4009
|
2117 |
-
static function watchUserAdminPrivUpdated($userID)
|
2118 |
-
{
|
2119 |
-
wpphLog(__METHOD__.'() triggered by hook.');
|
2120 |
-
wpphLog('POST DATA', $_POST);
|
2121 |
-
|
2122 |
-
// 4008
|
2123 |
-
if(isset($_POST['super_admin']) && !empty($_POST['super_admin']))
|
2124 |
-
{
|
2125 |
-
$bid = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2126 |
-
$userName = trim($_POST['display_name']);
|
2127 |
-
WPPHEvent::_addLogEvent(4008, wp_get_current_user()->ID, WPPHUtil::getIP(), array($userName), null, $bid);
|
2128 |
-
}
|
2129 |
-
// 4009
|
2130 |
-
else {
|
2131 |
-
$bid = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2132 |
-
$superAdmins = get_super_admins();
|
2133 |
-
$u = new WP_User($userID);
|
2134 |
-
$userName = $u->get('user_login');
|
2135 |
-
if(! empty($superAdmins)){
|
2136 |
-
foreach($superAdmins as $admin){
|
2137 |
-
if($admin == $userName){
|
2138 |
-
WPPHEvent::_addLogEvent(4009, wp_get_current_user()->ID, WPPHUtil::getIP(), array($userName), null, $bid);
|
2139 |
-
return;
|
2140 |
-
}
|
2141 |
-
}
|
2142 |
-
}
|
2143 |
-
}
|
2144 |
-
}
|
2145 |
-
|
2146 |
-
// 4010
|
2147 |
-
static function watchUserAddedToBlog($user_id, $role, $blog_id)
|
2148 |
-
{
|
2149 |
-
wpphLog(__METHOD__.'() triggered with params: ', array(
|
2150 |
-
'$user_id' => $user_id,
|
2151 |
-
'$role' => $role,
|
2152 |
-
'$blog_id' => $blog_id
|
2153 |
-
));
|
2154 |
-
|
2155 |
-
// current blog id
|
2156 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2157 |
-
|
2158 |
-
// get current user info
|
2159 |
-
$userInfo = WPPHDB::getUserInfo($user_id);
|
2160 |
-
$userName = $userInfo['userName'];
|
2161 |
-
$siteName = WPPHNetwork::getBlogName($blog_id);
|
2162 |
-
|
2163 |
-
WPPHEvent::_addLogEvent(4010, wp_get_current_user()->ID, WPPHUtil::getIP(), array($userName, $role, $siteName), null, $currentBlogID);
|
2164 |
-
wpphLog('User added to site.');
|
2165 |
-
}
|
2166 |
-
|
2167 |
-
// 4011
|
2168 |
-
static function watchUserRemovedFromBlog($user_id)
|
2169 |
-
{
|
2170 |
-
$blog_id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : 0);
|
2171 |
-
wpphLog(__METHOD__.'() triggered with params: ', array(
|
2172 |
-
'$user_id' => $user_id,
|
2173 |
-
'$blog_id' => $blog_id
|
2174 |
-
));
|
2175 |
-
|
2176 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2177 |
-
|
2178 |
-
// get current user info
|
2179 |
-
$userInfo = WPPHDB::getUserInfo($user_id);
|
2180 |
-
$userName = $userInfo['userName'];
|
2181 |
-
$userRole = $userInfo['userRole'];
|
2182 |
-
$siteName = WPPHNetwork::getBlogName($blog_id);
|
2183 |
-
|
2184 |
-
if(empty($currentBlogID) || empty($userName) || empty($userRole) || empty($siteName)){
|
2185 |
-
wpphLog('Cannot trigger the event 4011. One or more required variables are empty.', array(
|
2186 |
-
'$currentBlogID' => $currentBlogID,
|
2187 |
-
'$userName' => $userName,
|
2188 |
-
'$userRole' => $userRole,
|
2189 |
-
'$siteName' => $siteName,
|
2190 |
-
));
|
2191 |
-
return;
|
2192 |
-
}
|
2193 |
-
|
2194 |
-
WPPHEvent::_addLogEvent(4011, wp_get_current_user()->ID, WPPHUtil::getIP(), array($userName, $userRole, $siteName), null, $currentBlogID);
|
2195 |
-
wpphLog('User removed from site.');
|
2196 |
-
}
|
2197 |
-
|
2198 |
-
// 4012
|
2199 |
-
static function watchWpmuUserRegister($user_id)
|
2200 |
-
{
|
2201 |
-
wpphLog(__METHOD__.'() triggered with params: ', array('$user_id' => $user_id));
|
2202 |
-
|
2203 |
-
$currentBlogID = WPPHNetwork::getGlobalOption(WPPH_MAIN_SITE_ID_OPTION_NAME, false, true);
|
2204 |
-
$userInfo = WPPHDB::getUserInfo($user_id);
|
2205 |
-
$userName = $userInfo['userName'];
|
2206 |
-
|
2207 |
-
WPPHEvent::_addLogEvent(4012, wp_get_current_user()->ID, WPPHUtil::getIP(), array($userName), null, $currentBlogID);
|
2208 |
-
wpphLog('Created new network user.');
|
2209 |
-
}
|
2210 |
-
|
2211 |
-
|
2212 |
-
|
2213 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/WPPHLogger.php
DELETED
@@ -1,40 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
// custom function
|
3 |
-
function wpphLog($message, $data=null, $function=null,$line=null){ WPPHLogger::write($message,$data,$function,$line); }
|
4 |
-
/*
|
5 |
-
* @internal
|
6 |
-
* Debug class
|
7 |
-
* DO NOT enable this on live website
|
8 |
-
*/
|
9 |
-
class WPPHLogger
|
10 |
-
{
|
11 |
-
private static $_debugLoggingEnabled = false;
|
12 |
-
|
13 |
-
private static $_fileName = 'debug.log';
|
14 |
-
|
15 |
-
public static function enableDebugLogging(){ self::$_debugLoggingEnabled = true; }
|
16 |
-
public static function enableErrorLogging(){ ini_set('error_log', WPPH_PLUGIN_DIR.'error.log'); }
|
17 |
-
|
18 |
-
public static function write($message, $data=null, $function=null, $line=null)
|
19 |
-
{
|
20 |
-
if(!empty($_POST)){
|
21 |
-
if(isset($_POST['action']) && $_POST['action'] == 'heartbeat'){ return;}
|
22 |
-
}
|
23 |
-
|
24 |
-
if(!self::$_debugLoggingEnabled) { return; }
|
25 |
-
|
26 |
-
$m = '['.@date("D, M d, Y @H:i:s").'] Debug: '.$message;
|
27 |
-
if(!empty($function)){
|
28 |
-
$m .= PHP_EOL.'Function: '.$function;
|
29 |
-
if(! empty($line)){
|
30 |
-
$m .= PHP_EOL.'Line: '.$line.PHP_EOL;
|
31 |
-
}
|
32 |
-
}
|
33 |
-
if(! empty($data)) {
|
34 |
-
$m .= ' Data: '.var_export($data, true);
|
35 |
-
}
|
36 |
-
$m .= PHP_EOL;
|
37 |
-
|
38 |
-
@file_put_contents(WPPH_PLUGIN_DIR.self::$_fileName,$m,FILE_APPEND);
|
39 |
-
}
|
40 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/WPPHNetwork.php
DELETED
@@ -1,232 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Class wpphNetwork
|
4 |
-
*/
|
5 |
-
class WPPHNetwork
|
6 |
-
{
|
7 |
-
// runs per site
|
8 |
-
static function _activate($blogId=1)
|
9 |
-
{
|
10 |
-
wpphLog("Activating plugin for blog: $blogId");
|
11 |
-
|
12 |
-
// Network ID
|
13 |
-
update_option(WPPH_NETWORK_ID_OPTION_NAME, (defined('SITE_ID_CURRENT_SITE') ? SITE_ID_CURRENT_SITE : 1));
|
14 |
-
// Main Site ID
|
15 |
-
update_option(WPPH_MAIN_SITE_ID_OPTION_NAME, (defined('BLOG_ID_CURRENT_SITE') ? BLOG_ID_CURRENT_SITE : 1));
|
16 |
-
|
17 |
-
if(WPPH::isMultisite())
|
18 |
-
{
|
19 |
-
// if main site
|
20 |
-
if(WPPHUtil::isMainSite()){
|
21 |
-
WPPH::createPluginDefaultSettings();
|
22 |
-
}
|
23 |
-
// nothing to do here
|
24 |
-
else {
|
25 |
-
update_option('WPPH_PLUGIN_ACTIVATED',1);
|
26 |
-
wpphLog("Plugin activated successfully for blog: $blogId");
|
27 |
-
return true;
|
28 |
-
}
|
29 |
-
}
|
30 |
-
|
31 |
-
$ok = WPPH::onPluginActivate($blogId);
|
32 |
-
if($ok)
|
33 |
-
{
|
34 |
-
update_option('WPPH_PLUGIN_ACTIVATED',1);
|
35 |
-
wpphLog("Plugin activated successfully for blog: $blogId");
|
36 |
-
}
|
37 |
-
else { wpphLog("Plugin could not be activated for blog: $blogId"); }
|
38 |
-
}
|
39 |
-
// runs per site
|
40 |
-
static function _deactivate($blogId=1){
|
41 |
-
wpphLog("Deactivating plugin for blog: $blogId");
|
42 |
-
$ok = WPPH::onPluginDeactivate($blogId);
|
43 |
-
if($ok){
|
44 |
-
wpphLog("Plugin deactivated successfully for blog: $blogId");
|
45 |
-
}
|
46 |
-
else { wpphLog("Plugin could not be deactivated for blog: $blogId"); }
|
47 |
-
}
|
48 |
-
// runs per site
|
49 |
-
static function _uninstall($blogId=1){
|
50 |
-
wpphLog("Uninstalling plugin from blog: $blogId");
|
51 |
-
|
52 |
-
//check first for the wpph_plugin_activated for each site and if active first deactivate and then uninstall
|
53 |
-
$active = (int)get_option('WPPH_PLUGIN_ACTIVATED');
|
54 |
-
if(!empty($active)){
|
55 |
-
self::_deactivate($blogId);
|
56 |
-
}
|
57 |
-
|
58 |
-
global $wpdb;
|
59 |
-
|
60 |
-
// check if any tables created for a particular blog inside the network exist
|
61 |
-
$prefix = $wpdb->prefix;
|
62 |
-
|
63 |
-
if(empty($blogId) || $blogId == 1){}
|
64 |
-
else { $prefix .= $blogId.'_'; }
|
65 |
-
|
66 |
-
$wpdb->query("DROP TABLE IF EXISTS ".$prefix.'_wordpress_eventlog');
|
67 |
-
$wpdb->query("DROP TABLE IF EXISTS ".$prefix.'_wordpress_eventlog_details');
|
68 |
-
$wpdb->query("DROP TABLE IF EXISTS ".$prefix.'wordpress_auditlog');
|
69 |
-
$wpdb->query("DROP TABLE IF EXISTS ".$prefix.'wordpress_auditlog_events');
|
70 |
-
|
71 |
-
delete_option('WPPH_CRON_TASK_NAME');
|
72 |
-
delete_option('WPPH_NETWORK_INSTALL');
|
73 |
-
delete_option('WPPH_PLUGIN_ACTIVATED');
|
74 |
-
delete_option(WPPH_MAIN_SITE_ID_OPTION_NAME);
|
75 |
-
delete_option(WPPH_NETWORK_ID_OPTION_NAME);
|
76 |
-
delete_option(WPPH_PLUGIN_ALLOW_ACCESS_OPTION_NAME);
|
77 |
-
delete_option(WPPH_PLUGIN_ALLOW_CHANGE_OPTION_NAME);
|
78 |
-
delete_option(WPPH_PLUGIN_DB_UPDATED);
|
79 |
-
delete_option(WPPH_PLUGIN_SETTING_NAME);
|
80 |
-
delete_option(WPPH_PLUGIN_EVENTS_LIST_OPTION_NAME);
|
81 |
-
delete_option(WPPH_PLUGIN_VERSION_OPTION_NAME);
|
82 |
-
delete_option(WPPH_USERS_CAN_REGISTER_OPT_NAME);
|
83 |
-
delete_option(WPPH_PLUGIN_ERROR_OPTION_NAME);
|
84 |
-
wpphLog("Plugin successfully uninstalled.");
|
85 |
-
}
|
86 |
-
|
87 |
-
static function networkActivate(/*$networkwide=false*/)
|
88 |
-
{
|
89 |
-
global $wpdb;
|
90 |
-
if (WPPH::isMultisite()) {
|
91 |
-
$old_blog = $wpdb->blogid;
|
92 |
-
$blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
93 |
-
foreach ($blogids as $blog_id) {
|
94 |
-
switch_to_blog($blog_id);
|
95 |
-
self::_activate($blog_id);
|
96 |
-
}
|
97 |
-
switch_to_blog($old_blog);
|
98 |
-
update_option('WPPH_NETWORK_INSTALL',1);
|
99 |
-
}else{
|
100 |
-
update_option('WPPH_NETWORK_INSTALL',0);
|
101 |
-
self::_activate($wpdb->blogid);
|
102 |
-
}
|
103 |
-
/*global $wpdb;
|
104 |
-
if (WPPH::isMultisite()) {
|
105 |
-
// check if it is a network activation - if so, run the activation function for each blog id
|
106 |
-
if ($networkwide)
|
107 |
-
{
|
108 |
-
$old_blog = $wpdb->blogid;
|
109 |
-
$blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
|
110 |
-
foreach ($blogids as $blog_id) {
|
111 |
-
switch_to_blog($blog_id);
|
112 |
-
self::_activate($blog_id);
|
113 |
-
}
|
114 |
-
switch_to_blog($old_blog);
|
115 |
-
update_option('WPPH_NETWORK_INSTALL',1);
|
116 |
-
return;
|
117 |
-
}
|
118 |
-
}
|
119 |
-
update_option('WPPH_NETWORK_INSTALL',0);
|
120 |
-
self::_activate($wpdb->blogid);*/
|
121 |
-
}
|
122 |
-
|
123 |
-
static function networkDeactivate($networkwide=false){
|
124 |
-
global $wpdb;
|
125 |
-
if (WPPH::isMultisite()) {
|
126 |
-
// check if it is a network activation - if so, run the activation function
|
127 |
-
// for each blog id
|
128 |
-
if ($networkwide) {
|
129 |
-
$old_blog = $wpdb->blogid;
|
130 |
-
// Get all blog ids
|
131 |
-
$blogids = $wpdb->get_col("SELECT blog_id FROM {$wpdb->blogs}");
|
132 |
-
foreach ($blogids as $blog_id) {
|
133 |
-
switch_to_blog($blog_id);
|
134 |
-
self::_deactivate($blog_id);
|
135 |
-
}
|
136 |
-
switch_to_blog($old_blog);
|
137 |
-
return;
|
138 |
-
}
|
139 |
-
}
|
140 |
-
self::_deactivate($wpdb->blogid);
|
141 |
-
}
|
142 |
-
|
143 |
-
static function networkUninstall(){
|
144 |
-
global $wpdb;
|
145 |
-
if (WPPH::isMultisite()) {
|
146 |
-
$old_blog = $wpdb->blogid;
|
147 |
-
// Get all blog ids
|
148 |
-
$blogids = $wpdb->get_col("SELECT blog_id FROM {$wpdb->blogs}");
|
149 |
-
foreach ($blogids as $blog_id) {
|
150 |
-
switch_to_blog($blog_id);
|
151 |
-
self::_uninstall($blog_id);
|
152 |
-
}
|
153 |
-
switch_to_blog($old_blog);
|
154 |
-
return;
|
155 |
-
}
|
156 |
-
self::_uninstall();
|
157 |
-
}
|
158 |
-
|
159 |
-
/**
|
160 |
-
* Retrieve the list of all blogs in the network
|
161 |
-
* @return array( blogID => blogName )
|
162 |
-
*/
|
163 |
-
static function getBlogsList()
|
164 |
-
{
|
165 |
-
global $wpdb;
|
166 |
-
$out = array();
|
167 |
-
$results = $wpdb->get_results("SELECT blog_id FROM $wpdb->blogs WHERE public = 1 ORDER BY blog_id", ARRAY_A);
|
168 |
-
if(empty($results)){
|
169 |
-
return $out;
|
170 |
-
}
|
171 |
-
foreach($results as $entry){
|
172 |
-
$out[$entry['blog_id']] = self::getBlogName($entry['blog_id']);
|
173 |
-
}
|
174 |
-
return $out;
|
175 |
-
}
|
176 |
-
|
177 |
-
static function getBlogName($blogID)
|
178 |
-
{
|
179 |
-
return self::callOptionFunc('get', $blogID, 'blogname');
|
180 |
-
}
|
181 |
-
|
182 |
-
static function getGlobalBlogId(){
|
183 |
-
return 1; // this is the norm
|
184 |
-
}
|
185 |
-
|
186 |
-
/**
|
187 |
-
* Retrive the value of a global option
|
188 |
-
* @param $optionName
|
189 |
-
* @param bool $unserialize
|
190 |
-
* @param bool $isConstant
|
191 |
-
* @param null $default The default value to return if option not found
|
192 |
-
* @return mixed string if $unserialize = false, otherwise array
|
193 |
-
*/
|
194 |
-
static function getGlobalOption($optionName, $unserialize = false, $isConstant = false, $default = null)
|
195 |
-
{
|
196 |
-
return self::callOptionFunc('get', self::getGlobalBlogId(), $optionName, $default);
|
197 |
-
}
|
198 |
-
|
199 |
-
/**
|
200 |
-
* Update a global option
|
201 |
-
* @param string $optionName
|
202 |
-
* @param mixed $optionValue
|
203 |
-
* @param bool $serialize
|
204 |
-
* @param bool $isConstant
|
205 |
-
* @return bool
|
206 |
-
*/
|
207 |
-
static function updateGlobalOption($optionName, $optionValue, $serialize = false, $isConstant = false)
|
208 |
-
{
|
209 |
-
return self::callOptionFunc('update', self::getGlobalBlogId(), $optionName, $optionValue);
|
210 |
-
}
|
211 |
-
|
212 |
-
static function addGlobalOption($optionName, $optionValue, $serialize = false, $isConstant = false)
|
213 |
-
{
|
214 |
-
return self::callOptionFunc('add', self::getGlobalBlogId(), $optionName, $optionValue);
|
215 |
-
}
|
216 |
-
|
217 |
-
/**
|
218 |
-
* Gets, adds or updates a wordpress option.
|
219 |
-
* @param string $action An action: get, add, update
|
220 |
-
* @param integer $blogid Blog id, used on multisite only.
|
221 |
-
* @param mixed Rest of the function arguments.
|
222 |
-
* @return type
|
223 |
-
*/
|
224 |
-
static function callOptionFunc($action, $blogid){
|
225 |
-
$args = func_get_args();
|
226 |
-
$action = array_shift($args);
|
227 |
-
$musite = function_exists($action.'_blog_option');
|
228 |
-
$fnname = $musite ? "{$action}_blog_option" : "{$action}_option";
|
229 |
-
if(!$musite)$blogid = array_shift($args); // remove blogid when not multisite
|
230 |
-
return call_user_func_array($fnname, $args);
|
231 |
-
}
|
232 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/WPPHPost.php
DELETED
@@ -1,191 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class WPPHPost
|
4 |
-
{
|
5 |
-
public static $currentPostType = '';
|
6 |
-
|
7 |
-
static function getPostTypes()
|
8 |
-
{
|
9 |
-
$args = array('public' => true,'_builtin' => false);
|
10 |
-
$output = 'names'; // names or objects, note names is the default
|
11 |
-
$operator = 'and'; // 'and' or 'or'
|
12 |
-
|
13 |
-
$result = get_post_types( $args, $output, $operator );
|
14 |
-
if(! isset($result['post'])){ $result['post'] = 'post'; }
|
15 |
-
if(! isset($result['page'])){ $result['page'] = 'page'; }
|
16 |
-
return $result;
|
17 |
-
}
|
18 |
-
|
19 |
-
static function validatePostType($postType)
|
20 |
-
{
|
21 |
-
if(empty($postType)){
|
22 |
-
return false;
|
23 |
-
}
|
24 |
-
$types = self::getPostTypes();
|
25 |
-
wpphLog('POST TYPES',$types);
|
26 |
-
return (in_array($postType, $types) ? true : false);
|
27 |
-
}
|
28 |
-
|
29 |
-
// 2019 & 2020 & 2038
|
30 |
-
static function managePostAuthorUpdateQuickEditForm($data, $postArray)
|
31 |
-
{
|
32 |
-
if($data['post_type'] == 'post'){
|
33 |
-
if(self::postAuthorChanged($GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID'], $postArray['ID'], wp_get_current_user()->ID, $data['post_title'], 2019, true)){
|
34 |
-
$GLOBALS['WPPH_POST_AUTHOR_UPDATED'] = true;
|
35 |
-
}
|
36 |
-
}
|
37 |
-
elseif($data['post_type'] == 'page'){
|
38 |
-
if(self::postAuthorChanged($GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID'], $postArray['ID'], wp_get_current_user()->ID, $data['post_title'], 2020, true)){
|
39 |
-
$GLOBALS['WPPH_PAGE_AUTHOR_UPDATED'] = true;
|
40 |
-
}
|
41 |
-
}
|
42 |
-
// custom post type
|
43 |
-
else {
|
44 |
-
self::$currentPostType = $data['post_type'];
|
45 |
-
wpphLog('CURRENT POST TYPE: '.self::$currentPostType);
|
46 |
-
if(self::postAuthorChanged($GLOBALS['WPPH_POST_AUTHOR_UPDATED_ID'], $postArray['ID'], wp_get_current_user()->ID, $data['post_title'], 2038, true)){
|
47 |
-
$GLOBALS['WPPH_POST_AUTHOR_UPDATED'] = true;
|
48 |
-
}
|
49 |
-
}
|
50 |
-
return $data;
|
51 |
-
}
|
52 |
-
|
53 |
-
// 2019 & 2020 & 2038
|
54 |
-
static function postAuthorChanged($newAuthorID, $postID, $userID, $postTitle, $event, $quickFormEnabled = false)
|
55 |
-
{
|
56 |
-
$args = func_get_args();
|
57 |
-
wpphLog(__METHOD__.'() triggered.',array('params'=> $args));
|
58 |
-
if(empty($postID)){
|
59 |
-
wpphLog('Error: $postID is empty. Invalid function call.');
|
60 |
-
return false;
|
61 |
-
}
|
62 |
-
if(empty($newAuthorID)){
|
63 |
-
wpphLog('Error: $newAuthorID is empty. Invalid function call.');
|
64 |
-
return false;
|
65 |
-
}
|
66 |
-
|
67 |
-
global $wpdb;
|
68 |
-
$oldAuthorID = $wpdb->get_var("SELECT post_author FROM ".$wpdb->posts." WHERE ID = ".$postID);
|
69 |
-
|
70 |
-
wpphLog(__METHOD__.'() ',array(
|
71 |
-
'oldAuthorID' => $oldAuthorID,
|
72 |
-
'newAuthorID' => $newAuthorID
|
73 |
-
));
|
74 |
-
|
75 |
-
if($newAuthorID <> $oldAuthorID)
|
76 |
-
{
|
77 |
-
$n = $wpdb->get_var("SELECT user_login FROM ".$wpdb->users." WHERE ID = ".$newAuthorID);
|
78 |
-
$o = $wpdb->get_var("SELECT user_login FROM ".$wpdb->users." WHERE ID = ".$oldAuthorID);
|
79 |
-
|
80 |
-
if($quickFormEnabled){
|
81 |
-
// in quick edit form the authors get switched whereas in the default post editor they don't :/
|
82 |
-
$t = $n;
|
83 |
-
$n = $o;
|
84 |
-
$o = $t;
|
85 |
-
}
|
86 |
-
$userID = (int)$userID;
|
87 |
-
if(self::isCustomPost()){
|
88 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,ucfirst(self::$currentPostType),$n,$o));
|
89 |
-
}
|
90 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,$n,$o)); }
|
91 |
-
wpphLog(__METHOD__.' : Author updated.', array('from'=>$o, 'to'=>$n));
|
92 |
-
return true;
|
93 |
-
}
|
94 |
-
return false;
|
95 |
-
}
|
96 |
-
|
97 |
-
// 2001 & 2005 & 2030
|
98 |
-
static function newPostPublished($userID, $postTitle, $postUrl, $event)
|
99 |
-
{
|
100 |
-
if(self::isCustomPost()){
|
101 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst(self::$currentPostType), $postUrl));
|
102 |
-
}
|
103 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,$postUrl)); }
|
104 |
-
wpphLog(__METHOD__.'() : Post/Page published.', array('title'=>$postTitle));
|
105 |
-
}
|
106 |
-
|
107 |
-
// 2003 & 2007 & 2032
|
108 |
-
static function draftPostUpdated($userID, $postID, $postTitle, $event)
|
109 |
-
{
|
110 |
-
if(self::isCustomPost()){
|
111 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst(self::$currentPostType), $postID));
|
112 |
-
}
|
113 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,$postID)); }
|
114 |
-
wpphLog(__METHOD__.'() : Draft post/page updated.', array('title'=>$postTitle));
|
115 |
-
}
|
116 |
-
|
117 |
-
// 2000 & 2004 & 2029
|
118 |
-
static function newPostAsDraft($userID, $postID, $postTitle, $event)
|
119 |
-
{
|
120 |
-
if(self::isCustomPost()){
|
121 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst(self::$currentPostType), $postID));
|
122 |
-
}
|
123 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, $postID)); }
|
124 |
-
wpphLog(__METHOD__.'() : New post/page saved as draft.', array('title'=>$postTitle));
|
125 |
-
}
|
126 |
-
|
127 |
-
// 2017 & 2018
|
128 |
-
static function postUrlUpdated($oldUrl, $newUrl, $userID, $postTitle, $event)
|
129 |
-
{
|
130 |
-
if($oldUrl == $newUrl) { return false; }
|
131 |
-
if(self::isCustomPost()){
|
132 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst(self::$currentPostType), $oldUrl, $newUrl));
|
133 |
-
}
|
134 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, $oldUrl, $newUrl)); }
|
135 |
-
wpphLog(__METHOD__.'() : Post/Page URL updated.', array('from' => $oldUrl,'to' => $newUrl));
|
136 |
-
return true;
|
137 |
-
}
|
138 |
-
|
139 |
-
// 2002 & 2006 & 2031
|
140 |
-
static function publishedPostUpdated($userID, $postTitle, $postUrl, $event)
|
141 |
-
{
|
142 |
-
if(self::isCustomPost()){
|
143 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst(self::$currentPostType), $postUrl));
|
144 |
-
}
|
145 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,$postUrl)); }
|
146 |
-
wpphLog(__METHOD__.'() : Published post/page updated.', array('title'=>$postTitle));
|
147 |
-
}
|
148 |
-
|
149 |
-
static function postVisibilityChanged($userID, $postTitle, $fromVisibility, $toVisibility, $event)
|
150 |
-
{
|
151 |
-
if(self::isCustomPost()){
|
152 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,ucfirst(self::$currentPostType),$fromVisibility,$toVisibility));
|
153 |
-
}
|
154 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,$fromVisibility,$toVisibility)); }
|
155 |
-
wpphLog('Post visibility changed.', array('from' => $fromVisibility, 'to' => $toVisibility));
|
156 |
-
}
|
157 |
-
|
158 |
-
static function postDateChanged($userID, $postTitle, $fromDate, $toDate, $event)
|
159 |
-
{
|
160 |
-
$GLOBALS['WPPH_POST_DATE_CHANGED'] = true; // so we won't trigger the "modified post/page" event alongside the current event
|
161 |
-
if(self::isCustomPost()){
|
162 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,ucfirst(self::$currentPostType),$fromDate,$toDate));
|
163 |
-
}
|
164 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle,$fromDate,$toDate)); }
|
165 |
-
wpphLog('Post date changed.', array('from' => $fromDate . ' ('.strtotime($fromDate).')', 'to' => $toDate . ' ('.strtotime($toDate).')'));
|
166 |
-
}
|
167 |
-
|
168 |
-
static function postStatusChanged($postTitle, $fromStatus, $toStatus, $userID, $event)
|
169 |
-
{
|
170 |
-
if(self::isCustomPost()){
|
171 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst(self::$currentPostType), $fromStatus, $toStatus));
|
172 |
-
}
|
173 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, $fromStatus, $toStatus)); }
|
174 |
-
wpphLog(__METHOD__.'() : Post status updated.', array('title'=>$postTitle, 'from' => $fromStatus, 'to' => $toStatus));
|
175 |
-
}
|
176 |
-
|
177 |
-
// 2016
|
178 |
-
static function postCategoriesUpdated($userID, $postTitle, $fromCategories, $toCategories, $event)
|
179 |
-
{
|
180 |
-
if(self::isCustomPost()){
|
181 |
-
WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, ucfirst(self::$currentPostType), $fromCategories, $toCategories));
|
182 |
-
}
|
183 |
-
else { WPPHEvent::_addLogEvent($event, $userID, WPPHUtil::getIP(), array($postTitle, $fromCategories, $toCategories)); }
|
184 |
-
wpphLog(__METHOD__.' : Post categories updated.', array('from'=>$fromCategories, 'to'=>$toCategories));
|
185 |
-
}
|
186 |
-
|
187 |
-
static function isCustomPost(){
|
188 |
-
if(in_array(self::$currentPostType, array('post','page'))){ return false; }
|
189 |
-
return self::validatePostType(self::$currentPostType);
|
190 |
-
}
|
191 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/WPPHUtil.php
DELETED
@@ -1,371 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
class WPPHUtil
|
3 |
-
{
|
4 |
-
static function loadPluggable(){ @include_once(ABSPATH.'wp-includes/pluggable.php'); }
|
5 |
-
|
6 |
-
static function getIP() { return(!empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0'); }
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Check to see whether or not the current user is an administrator
|
10 |
-
* @param int $userId
|
11 |
-
* @return bool
|
12 |
-
*/
|
13 |
-
static function isAdministrator($userId=0){ if(empty($userId)){$userId = wp_get_current_user();} return user_can($userId,'administrator'); }
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Will respond to the ajax requests getting the events
|
17 |
-
*/
|
18 |
-
static function get_events_html()
|
19 |
-
{
|
20 |
-
// VALIDATE REQUEST
|
21 |
-
$rm = strtoupper($_SERVER['REQUEST_METHOD']);
|
22 |
-
if($rm != 'POST'){ exit('<tr><td colspan="7"><span>'.__('Error: Invalid request',WPPH_PLUGIN_TEXT_DOMAIN).'</span></td></tr>'); }
|
23 |
-
|
24 |
-
// set defaults
|
25 |
-
$orderBy = 'EventNumber';
|
26 |
-
$sort = 'desc';
|
27 |
-
$limit = array(0, 50);
|
28 |
-
|
29 |
-
if(!empty($_POST['orderBy'])) { $orderBy = $_POST['orderBy']; }
|
30 |
-
if(!empty($_POST['sort'])) {
|
31 |
-
if(0 == strcasecmp($_POST['sort'],'asc')){ $sort = 'asc'; }
|
32 |
-
}
|
33 |
-
if(isset($_POST['offset'])) { $limit[0] = intval($_POST['offset']); }
|
34 |
-
if(isset($_POST['count'])) { $limit[1] = intval($_POST['count']); }
|
35 |
-
|
36 |
-
global $current_user, $blog_id;
|
37 |
-
|
38 |
-
$out = array();
|
39 |
-
$out['events'] = array();
|
40 |
-
$globalBlogID = $blog_id;
|
41 |
-
$is_wpmu = WPPH::isMultisite();
|
42 |
-
$isMainSite = WPPHUtil::isMainSite();
|
43 |
-
$isSA = false;
|
44 |
-
$allSites = false;
|
45 |
-
|
46 |
-
$blogList = ($isMainSite && $is_wpmu) ? self::get_blogs() : array();
|
47 |
-
function _getBlogName($id, $blogList) {
|
48 |
-
for ($i = 0; $i < count($blogList); $i++) {
|
49 |
-
if ($blogList[$i]['blog_id'] == $id) {
|
50 |
-
return $blogList[$i]['blogname'];
|
51 |
-
}
|
52 |
-
}
|
53 |
-
}
|
54 |
-
|
55 |
-
if(!isset($_POST['blogID']) || empty($_POST['blogID'])){
|
56 |
-
if($isMainSite){
|
57 |
-
$postedBlogID = 0; // get the events for all sites by default
|
58 |
-
$allSites = true;
|
59 |
-
}
|
60 |
-
else {
|
61 |
-
$postedBlogID = $globalBlogID;
|
62 |
-
$allSites = false;
|
63 |
-
}
|
64 |
-
}
|
65 |
-
else { $postedBlogID = intval($_POST['blogID']); }
|
66 |
-
|
67 |
-
if($is_wpmu){ $isSA = is_super_admin($current_user->ID); }
|
68 |
-
else {
|
69 |
-
if(empty($postedBlogID)){
|
70 |
-
$postedBlogID = 1;
|
71 |
-
}
|
72 |
-
}
|
73 |
-
|
74 |
-
if($is_wpmu && !$isSA)
|
75 |
-
{
|
76 |
-
// Only Super Admin can view other blogs' alerts
|
77 |
-
if($globalBlogID <> $postedBlogID){
|
78 |
-
$out['blogs'] = $blogList;
|
79 |
-
exit( wpph_formatJsonOutput($out,__('There are no security alerts to display.',WPPH_PLUGIN_TEXT_DOMAIN)) );
|
80 |
-
}
|
81 |
-
}
|
82 |
-
|
83 |
-
if(! $isMainSite){ $postedBlogID = $globalBlogID; }
|
84 |
-
|
85 |
-
// get events
|
86 |
-
if($allSites){
|
87 |
-
$eventsCount = WPPHDB::getEventsCount(0);
|
88 |
-
$events = WPPHEvent::getEvents($orderBy, $sort, $limit, 0);
|
89 |
-
}
|
90 |
-
else {
|
91 |
-
$eventsCount = WPPHDB::getEventsCount($postedBlogID);
|
92 |
-
$events = WPPHEvent::getEvents($orderBy, $sort, $limit, $postedBlogID);
|
93 |
-
}
|
94 |
-
$eventsNum = count($events);
|
95 |
-
|
96 |
-
wpphLog("GETTING EVENTS FOR ".(empty($postedBlogID) ? 'ALL BLOGS' : 'BLOG: '.$postedBlogID).". Num events: $eventsNum");
|
97 |
-
|
98 |
-
if($eventsNum == 0){
|
99 |
-
if($is_wpmu){
|
100 |
-
$out['blogs'] = $blogList;
|
101 |
-
exit( wpph_formatJsonOutput($out,__('There are no security alerts to display.',WPPH_PLUGIN_TEXT_DOMAIN)) );
|
102 |
-
}
|
103 |
-
exit( wpph_formatJsonOutput(array(),__('There are no security alerts to display.',WPPH_PLUGIN_TEXT_DOMAIN)) );
|
104 |
-
}
|
105 |
-
|
106 |
-
// prepare output
|
107 |
-
foreach($events as $entry)
|
108 |
-
{
|
109 |
-
$entry = (object)$entry;
|
110 |
-
$eventNumber = $entry->EventNumber;
|
111 |
-
$EventID = $entry->EventID;
|
112 |
-
$EventDate = $entry->EventDate;
|
113 |
-
$userIP = $entry->UserIP;
|
114 |
-
$UserID = $entry->UserID;
|
115 |
-
$blogId = $entry->BlogId;
|
116 |
-
$eventData = ((!empty($entry->EventData)) ? unserialize(base64_decode($entry->EventData)) : ''); //<< values to use for event description
|
117 |
-
|
118 |
-
$eventCount = intval($entry->EventCount);
|
119 |
-
// get User Info
|
120 |
-
if($UserID == 0){ $username = 'System'; }
|
121 |
-
else {
|
122 |
-
$user_info = get_userdata($UserID);
|
123 |
-
$username = $user_info->user_login;
|
124 |
-
$first_name = $user_info->user_firstname;
|
125 |
-
$last_name = $user_info->user_lastname;
|
126 |
-
$username = "$username ($first_name $last_name)";
|
127 |
-
}
|
128 |
-
|
129 |
-
// get event details
|
130 |
-
$eventDetails = WPPHEvent::getEventDetailsData($EventID);
|
131 |
-
|
132 |
-
// format event description message
|
133 |
-
if($eventCount >=2 && $EventID == 1002){
|
134 |
-
$evm = sprintf(__('<strong>%d</strong> failed login attempts from <strong>%s</strong> using <strong>%s</strong> as username.',WPPH_PLUGIN_TEXT_DOMAIN)
|
135 |
-
, $eventCount, $userIP, base64_decode($entry->UserName));
|
136 |
-
}
|
137 |
-
else {
|
138 |
-
if(empty($eventData)) { $evm = $eventDetails->EventDescription; }
|
139 |
-
else { $evm = vsprintf($eventDetails->EventDescription, $eventData); }
|
140 |
-
}
|
141 |
-
|
142 |
-
$e = array(
|
143 |
-
'eventNumber' => $eventNumber,
|
144 |
-
'eventId' => $EventID,
|
145 |
-
'EventType' => $eventDetails->EventType,
|
146 |
-
'eventDate' => $EventDate,
|
147 |
-
'ip' => $userIP,
|
148 |
-
'user' => $username,
|
149 |
-
'siteName' => $allSites ? _getBlogName($blogId, $blogList) : '',
|
150 |
-
'description' => stripslashes($evm)
|
151 |
-
);
|
152 |
-
array_push($out['events'], $e);
|
153 |
-
}
|
154 |
-
$out['eventsCount'] = $eventsCount;
|
155 |
-
$out['blogID'] = $postedBlogID;
|
156 |
-
$out['blogs'] = $blogList;
|
157 |
-
exit(wpph_formatJsonOutput($out));
|
158 |
-
}
|
159 |
-
|
160 |
-
// @since v0.6
|
161 |
-
static function get_blogs()
|
162 |
-
{
|
163 |
-
if(wp_is_large_network()){
|
164 |
-
return get_blog_details(get_option(WPPH_MAIN_SITE_ID_OPTION_NAME),true);
|
165 |
-
}
|
166 |
-
$blogs = wp_get_sites();
|
167 |
-
$out = array();
|
168 |
-
foreach($blogs as $blog){
|
169 |
-
$entry = get_blog_details($blog['blog_id']);
|
170 |
-
array_push($out, array(
|
171 |
-
'blog_id' => $entry->blog_id,
|
172 |
-
'blogname' => $entry->blogname
|
173 |
-
));
|
174 |
-
}
|
175 |
-
array_unshift($out, array('blog_id' => 0, 'blogname' => 'All sites'));
|
176 |
-
return $out;
|
177 |
-
}
|
178 |
-
|
179 |
-
static function addDashboardWidget()
|
180 |
-
{
|
181 |
-
if(! empty(WPPH::getPluginSettings()->showDW))
|
182 |
-
{
|
183 |
-
$currentUser = wp_get_current_user();
|
184 |
-
if(WPPHUtil::isAdministrator($currentUser->ID)|| WPPHUtil::isAllowedAccess($currentUser->ID) || WPPHUtil::isAllowedChange($currentUser->ID)){
|
185 |
-
wp_add_dashboard_widget('wpphPluginDashboardWidget', __('Latest WordPress Security Alerts').' | WP Security Audit Log', array(get_class(),'createDashboardWidget'));
|
186 |
-
}
|
187 |
-
}
|
188 |
-
}
|
189 |
-
static function createDashboardWidget()
|
190 |
-
{
|
191 |
-
// get and display data
|
192 |
-
$results = WPPHEvent::getEvents('EventNumber', 'DESC', array(0,5));
|
193 |
-
echo '<div>';
|
194 |
-
if(empty($results))
|
195 |
-
{
|
196 |
-
echo '<p>'.__('No alerts found.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
197 |
-
}
|
198 |
-
else {
|
199 |
-
echo '<table class="wp-list-table widefat" cellspacing="0" cellpadding="0">';
|
200 |
-
echo '<thead>';
|
201 |
-
echo '<th class="manage-column" style="width: 15%;" scope="col">'.__('User',WPPH_PLUGIN_TEXT_DOMAIN).'</th>';
|
202 |
-
echo '<th class="manage-column" style="width: 85%;" scope="col">'.__('Description',WPPH_PLUGIN_TEXT_DOMAIN).'</th>';
|
203 |
-
echo '</thead>';
|
204 |
-
echo '<tbody>';
|
205 |
-
foreach($results as $entry)
|
206 |
-
{
|
207 |
-
$entry = (object)$entry;
|
208 |
-
$eventID = $entry->EventID;
|
209 |
-
$userID = $entry->UserID;
|
210 |
-
$eventData = ((!empty($entry->EventData)) ? unserialize(base64_decode($entry->EventData)) : ''); //<< values to use for event description
|
211 |
-
$eventCount = intval($entry->EventCount);
|
212 |
-
$userIP = $entry->UserIP;
|
213 |
-
// get User Info
|
214 |
-
if($userID == 0){ $username = 'System'; }
|
215 |
-
else {
|
216 |
-
$user_info = get_userdata($userID);
|
217 |
-
$username = $user_info->user_login;
|
218 |
-
}
|
219 |
-
// format event description message
|
220 |
-
if($eventCount >=2 && $eventID == 1002){
|
221 |
-
$evm = sprintf(__('<strong>%d</strong> failed login attempts from <strong>%s</strong> using <strong>%s</strong> as username.',WPPH_PLUGIN_TEXT_DOMAIN)
|
222 |
-
, $eventCount, $userIP, base64_decode($entry->UserName));
|
223 |
-
}
|
224 |
-
else {
|
225 |
-
$eventDetails = WPPHEvent::getEventDetailsData($eventID);
|
226 |
-
if(empty($eventData)) { $evm = $eventDetails->EventDescription; }
|
227 |
-
else { $evm = vsprintf($eventDetails->EventDescription, $eventData); }
|
228 |
-
}
|
229 |
-
|
230 |
-
echo '<tr>';
|
231 |
-
echo '<td>'.$username.'</td>';
|
232 |
-
echo '<td><a href="admin.php?page='.WPPH_PLUGIN_PREFIX.'">'.$evm.'</a></td>';
|
233 |
-
echo '</tr>';
|
234 |
-
}
|
235 |
-
echo '</tbody>';
|
236 |
-
echo '</table>';
|
237 |
-
}
|
238 |
-
echo '</div>';
|
239 |
-
}
|
240 |
-
|
241 |
-
|
242 |
-
/**
|
243 |
-
* Check to see whether or not a user has access to view any of the plugin's pages
|
244 |
-
* @since v0.5
|
245 |
-
* @return bool
|
246 |
-
*/
|
247 |
-
static function canViewPage()
|
248 |
-
{
|
249 |
-
$currentUser = wp_get_current_user();
|
250 |
-
if(WPPHUtil::isAdministrator($currentUser->ID)|| WPPHUtil::isAllowedAccess($currentUser->ID) || WPPHUtil::isAllowedChange($currentUser->ID)){
|
251 |
-
return true;
|
252 |
-
}
|
253 |
-
return false;
|
254 |
-
}
|
255 |
-
|
256 |
-
/**
|
257 |
-
* Check to see whether or not the current user is allowed to VIEW the plugin
|
258 |
-
* @since v0.5
|
259 |
-
* @return bool
|
260 |
-
*/
|
261 |
-
static function isAllowedAccess()
|
262 |
-
{
|
263 |
-
$data = WPPHNetwork::getGlobalOption(WPPH_PLUGIN_ALLOW_ACCESS_OPTION_NAME, true, true, array());
|
264 |
-
if(empty($data)){return false;}
|
265 |
-
$userID = wp_get_current_user()->ID;
|
266 |
-
$userInfo = WPPHDB::getUserInfo($userID);
|
267 |
-
return (in_array($userInfo['userName'], $data) || in_array($userInfo['userRole'], $data));
|
268 |
-
}
|
269 |
-
/**
|
270 |
-
* Check to see whether or not the current user allowed to CHANGE the plugin's settings
|
271 |
-
* @since v0.5
|
272 |
-
* @return bool
|
273 |
-
*/
|
274 |
-
static function isAllowedChange()
|
275 |
-
{
|
276 |
-
$data = WPPHNetwork::getGlobalOption(WPPH_PLUGIN_ALLOW_CHANGE_OPTION_NAME, true, true, array());
|
277 |
-
if(empty($data)){return false;}
|
278 |
-
$userID = wp_get_current_user()->ID;
|
279 |
-
$userInfo = WPPHDB::getUserInfo($userID);
|
280 |
-
return (in_array($userInfo['userName'], $data) || in_array($userInfo['userRole'], $data));
|
281 |
-
}
|
282 |
-
/**
|
283 |
-
* @param array $data
|
284 |
-
* @since v0.5
|
285 |
-
* @return bool False if value was not updated and true if value was updated.
|
286 |
-
*/
|
287 |
-
static function saveAllowAccessUserList(array $data)
|
288 |
-
{
|
289 |
-
$result = WPPHNetwork::updateGlobalOption(WPPH_PLUGIN_ALLOW_ACCESS_OPTION_NAME, $data, true, true);
|
290 |
-
wpphLog(__METHOD__.'() result:', array('data'=> $data, 'result'=>$result));
|
291 |
-
return $result;
|
292 |
-
}
|
293 |
-
/**
|
294 |
-
* @param array $data
|
295 |
-
* @since v0.5
|
296 |
-
* @return bool False if value was not updated and true if value was updated.
|
297 |
-
*/
|
298 |
-
static function saveAllowedChangeUserList(array $data)
|
299 |
-
{
|
300 |
-
$result = WPPHNetwork::updateGlobalOption(WPPH_PLUGIN_ALLOW_CHANGE_OPTION_NAME, $data, true, true);
|
301 |
-
wpphLog(__METHOD__.'() result:', array('data'=> $data, 'result'=>$result));
|
302 |
-
return $result;
|
303 |
-
}
|
304 |
-
|
305 |
-
|
306 |
-
/**
|
307 |
-
* Saves the default list of users with access to plugin
|
308 |
-
* @since v0.5
|
309 |
-
* @return bool
|
310 |
-
*/
|
311 |
-
static function saveInitialAccessChangeList()
|
312 |
-
{
|
313 |
-
if(self::isMainSite()){
|
314 |
-
WPPHNetwork::addGlobalOption(WPPH_PLUGIN_ALLOW_ACCESS_OPTION_NAME, array(), true, true);
|
315 |
-
WPPHNetwork::addGlobalOption(WPPH_PLUGIN_ALLOW_CHANGE_OPTION_NAME, array(), true, true);
|
316 |
-
}
|
317 |
-
}
|
318 |
-
|
319 |
-
// ajax
|
320 |
-
static function check_user_role()
|
321 |
-
{
|
322 |
-
// VALIDATE REQUEST
|
323 |
-
$rm = strtoupper($_SERVER['REQUEST_METHOD']);
|
324 |
-
if($rm != 'POST'){ exit(__('Error: Invalid request',WPPH_PLUGIN_TEXT_DOMAIN)); }
|
325 |
-
|
326 |
-
$value = $_POST['check_input'];
|
327 |
-
|
328 |
-
if(empty($value)){
|
329 |
-
exit(__('Error: Invalid request',WPPH_PLUGIN_TEXT_DOMAIN));
|
330 |
-
}
|
331 |
-
|
332 |
-
$value = strtolower($value);
|
333 |
-
$value = stripslashes($value);
|
334 |
-
$value = strip_tags($value);
|
335 |
-
$value = esc_sql($value);
|
336 |
-
|
337 |
-
// check user
|
338 |
-
$result = self::_userExists($value);
|
339 |
-
if ($result){
|
340 |
-
exit('1');
|
341 |
-
}
|
342 |
-
// check role
|
343 |
-
$result = self::_roleExists($value);
|
344 |
-
if ($result){
|
345 |
-
exit('1');
|
346 |
-
}
|
347 |
-
exit('0');
|
348 |
-
}
|
349 |
-
|
350 |
-
static function _userExists($username){
|
351 |
-
global $wpdb;
|
352 |
-
$result = $wpdb->get_var($wpdb->prepare("SELECT `ID` FROM {$wpdb->users} WHERE user_login = '%s' OR display_name = '%s'", $username, $username));
|
353 |
-
if ($result !== false && $result > 0){
|
354 |
-
return true;
|
355 |
-
}
|
356 |
-
return false;
|
357 |
-
}
|
358 |
-
|
359 |
-
static function _roleExists($role){
|
360 |
-
global $wp_roles;
|
361 |
-
return (isset($wp_roles->roles[$role]) ? true : false);
|
362 |
-
}
|
363 |
-
|
364 |
-
static function isMainSite(){
|
365 |
-
if (WPPH::isMultisite()) {
|
366 |
-
global $current_site, $blog_id;
|
367 |
-
return ($current_site->id == $blog_id);
|
368 |
-
}
|
369 |
-
return true;
|
370 |
-
}
|
371 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/wpphFunctions.php
DELETED
@@ -1,92 +0,0 @@
|
|
1 |
-
<?php if(! defined('WPPH_PLUGIN_NAME')) return;
|
2 |
-
|
3 |
-
/**
|
4 |
-
* @param string $error The error to display in the admin notice
|
5 |
-
* This function can be used to generate an admin notice error
|
6 |
-
*/
|
7 |
-
function wpph_adminNotice($error) { echo '<div id="errMessage" class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error',WPPH_PLUGIN_TEXT_DOMAIN).':</strong> '.$error.'</p></div>'; }
|
8 |
-
function wpph_adminUpdate($message) { echo '<div id="errMessage" class="updated"><p><strong>'.$message.'</strong></p></div>'; }
|
9 |
-
|
10 |
-
add_action('wpph_set_post_type', 'wpph_setPostType', 1, 1);
|
11 |
-
function wpph_setPostType($postType){
|
12 |
-
WPPHPost::$currentPostType = $postType;
|
13 |
-
wpphLog(__FUNCTION__.' triggered', array('postType'=>$postType));
|
14 |
-
}
|
15 |
-
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Retrieve the custom post type from the given base post type
|
19 |
-
* @since v0.4
|
20 |
-
* @param string $baseType The post's base type from which to extract the custom type
|
21 |
-
* @return string The custom post type
|
22 |
-
*/
|
23 |
-
function wpph_extractCustomPostType($baseType) { return substr($baseType, strpos($baseType,'-')+1); }
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Check to see whether or not the provided event is enabled
|
27 |
-
* @since v0.4
|
28 |
-
* @param integer $event the event to search for
|
29 |
-
* @param array $events Optional. The list of events where to search for $event to see if it's enabled or not
|
30 |
-
* @return bool
|
31 |
-
*/
|
32 |
-
function wpph_isEventEnabled($event, array $events = array())
|
33 |
-
{
|
34 |
-
if(empty($event)){ return false; }
|
35 |
-
if(empty($events)){
|
36 |
-
$events = wpph_getPluginEventsList();
|
37 |
-
if(empty($events)){
|
38 |
-
wpphLog("Error retrieving the list of events from database. option: ".WPPH_PLUGIN_EVENTS_LIST_OPTION_NAME." was either not found or empty.");
|
39 |
-
return false;
|
40 |
-
}
|
41 |
-
}
|
42 |
-
$event = (int)$event;
|
43 |
-
foreach($events as $sections){
|
44 |
-
foreach($sections as $_event => $enabled){
|
45 |
-
if(($event == (int)$_event) && (bool)$enabled){
|
46 |
-
return true;
|
47 |
-
}
|
48 |
-
}
|
49 |
-
}
|
50 |
-
return false;
|
51 |
-
}
|
52 |
-
|
53 |
-
// Add custom links on plugins page
|
54 |
-
function wpphCustomLinks($links) { return array_merge(array('<a href="admin.php?page=wpph_">Audit Log Viewer </a>', '<a href="admin.php?page=wpph_settings">'.__('Settings',WPPH_PLUGIN_TEXT_DOMAIN).'</a>'), $links); }
|
55 |
-
// Load text domain
|
56 |
-
function wpphLoadTextDomain() { load_plugin_textdomain(WPPH_PLUGIN_TEXT_DOMAIN, false, 'wp-security-audit-log/languages/'); }
|
57 |
-
|
58 |
-
|
59 |
-
/**
|
60 |
-
* @internal
|
61 |
-
* @param string $pluginName
|
62 |
-
* @param int $userID
|
63 |
-
* @param string $userIP
|
64 |
-
*/
|
65 |
-
function wpph_installPlugin($pluginName, $userID, $userIP)
|
66 |
-
{
|
67 |
-
if(! empty($_GET['plugin']))
|
68 |
-
{
|
69 |
-
WPPHEvent::_addLogEvent(5000,$userID, $userIP, array($pluginName));
|
70 |
-
wpphLog('Plugin installed.', array('plugin'=>$pluginName));
|
71 |
-
}
|
72 |
-
}
|
73 |
-
|
74 |
-
function wpph_updatePluginEventsList($data)
|
75 |
-
{
|
76 |
-
if(WPPH::isMultisite()){
|
77 |
-
update_blog_option((int)get_option(WPPH_MAIN_SITE_ID_OPTION_NAME), WPPH_PLUGIN_EVENTS_LIST_OPTION_NAME, $data);
|
78 |
-
}
|
79 |
-
else { update_option(WPPH_PLUGIN_EVENTS_LIST_OPTION_NAME, $data); }
|
80 |
-
}
|
81 |
-
|
82 |
-
function wpph_getPluginEventsList()
|
83 |
-
{
|
84 |
-
return WPPHNetwork::getGlobalOption(WPPH_PLUGIN_EVENTS_LIST_OPTION_NAME, true, true);
|
85 |
-
}
|
86 |
-
|
87 |
-
function wpph_formatJsonOutput(array $sourceData=array(), $error=''){
|
88 |
-
return json_encode(array(
|
89 |
-
'dataSource' => $sourceData,
|
90 |
-
'error' => $error
|
91 |
-
));
|
92 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/wpphSettings.php
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
define('WPPH_PLUGIN_VERSION_OPTION_NAME','WPPH_PLUGIN_VERSION');
|
3 |
-
define('WPPH_PLUGIN_ERROR_OPTION_NAME','WPPH_PLUGIN_ERROR');
|
4 |
-
define('WPPH_PLUGIN_SETTING_NAME', 'wpph_plugin_settings');
|
5 |
-
|
6 |
-
define('WPPH_PLUGIN_DB_UPDATED', 'WPPH_PLUGIN_DB_UPDATED');
|
7 |
-
define('WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME', 'wpph_plugin_delete_events_cron');
|
8 |
-
/** @since v0.3 */
|
9 |
-
define('WPPH_USERS_CAN_REGISTER_OPT_NAME', 'wpph_users_can_register');
|
10 |
-
/**
|
11 |
-
* @since v0.3
|
12 |
-
* @see WPPH::onPluginActivate()
|
13 |
-
*/
|
14 |
-
$GLOBALS['WPPH_CAN_RUN'] = true;
|
15 |
-
/**@since 0.4*/
|
16 |
-
define('WPPH_PLUGIN_TEXT_DOMAIN', 'wp-security-audit-log');
|
17 |
-
/**@since 0.4*/
|
18 |
-
define('WPPH_E_NOTICE_TEXT', __('NOTICE',WPPH_PLUGIN_TEXT_DOMAIN));
|
19 |
-
/**@since 0.4*/
|
20 |
-
define('WPPH_E_HIGH_TEXT', __('HIGH',WPPH_PLUGIN_TEXT_DOMAIN));
|
21 |
-
/**@since 0.4*/
|
22 |
-
define('WPPH_E_WARNING_TEXT', __('WARNING',WPPH_PLUGIN_TEXT_DOMAIN));
|
23 |
-
|
24 |
-
/**@since 0.4*/
|
25 |
-
define('WPPH_KEEP_MAX_EVENTS', 5000);
|
26 |
-
|
27 |
-
//since v0.5
|
28 |
-
define('WPPH_PLUGIN_ALLOW_ACCESS_OPTION_NAME','WPPH_PLUGIN_ALLOW_ACCESS');
|
29 |
-
define('WPPH_PLUGIN_ALLOW_CHANGE_OPTION_NAME','WPPH_PLUGIN_ALLOW_CHANGE');
|
30 |
-
define('WPPH_PLUGIN_EVENTS_LIST_OPTION_NAME', 'WPPH_PLUGIN_EVENTS_LIST');
|
31 |
-
|
32 |
-
//since v0.6
|
33 |
-
define('WPPH_NETWORK_ID_OPTION_NAME','WPPH_NETWORK_ID');
|
34 |
-
define('WPPH_MAIN_SITE_ID_OPTION_NAME','WPPH_MAIN_SITE_ID');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
js/auditlog.js
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var WsalData;
|
2 |
+
|
3 |
+
function WsalAuditLogInit(_WsalData){
|
4 |
+
WsalData = _WsalData;
|
5 |
+
var WsalTkn = WsalData.autorefresh.token;
|
6 |
+
|
7 |
+
// list refresher
|
8 |
+
var WsalAjx = null;
|
9 |
+
var WsalChk = function(){
|
10 |
+
if(WsalAjx)WsalAjx.abort();
|
11 |
+
WsalAjx = jQuery.post(WsalData.ajaxurl, {
|
12 |
+
action: 'AjaxRefresh',
|
13 |
+
logcount: WsalTkn
|
14 |
+
}, function(data){
|
15 |
+
WsalAjx = null;
|
16 |
+
if(data && data !== 'false'){
|
17 |
+
WsalTkn = data;
|
18 |
+
jQuery('#audit-log-viewer').load(location.href + ' #audit-log-viewer');
|
19 |
+
}
|
20 |
+
WsalChk();
|
21 |
+
});
|
22 |
+
};
|
23 |
+
if(WsalData.autorefresh.enabled){
|
24 |
+
setInterval(WsalChk, 40000);
|
25 |
+
WsalChk();
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
var WsalIppsPrev;
|
30 |
+
|
31 |
+
function WsalIppsFocus(value){
|
32 |
+
WsalIppsPrev = value;
|
33 |
+
}
|
34 |
+
|
35 |
+
function WsalIppsChange(value){
|
36 |
+
if(value === ''){
|
37 |
+
value = window.prompt(WsalData.tr8n.numofitems, WsalIppsPrev);
|
38 |
+
if(value === null || value === WsalIppsPrev)return this.value = WsalIppsPrev; // operation canceled
|
39 |
+
}
|
40 |
+
jQuery('select.wsal-ipps').attr('disabled', true);
|
41 |
+
jQuery.post(WsalData.ajaxurl, {
|
42 |
+
action: 'AjaxSetIpp',
|
43 |
+
count: value
|
44 |
+
}, function(){
|
45 |
+
location.reload();
|
46 |
+
});
|
47 |
+
}
|
48 |
+
|
49 |
+
function WsalSsasChange(value){
|
50 |
+
jQuery('select.wsal-ssas').attr('disabled', true);
|
51 |
+
jQuery('#wsal-cbid').val(value);
|
52 |
+
jQuery('#audit-log-viewer').submit();
|
53 |
+
}
|
js/nice_r.js
ADDED
@@ -0,0 +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 = '►';
|
7 |
+
}else{
|
8 |
+
el.style.display = 'block';
|
9 |
+
document.getElementById(pfx+'_a'+id).innerHTML = '▼';
|
10 |
+
}
|
11 |
+
}
|
12 |
+
}
|
js/settings.js
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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').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').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(data==='other' && !confirm('The specified token is not a user nor a role, do you still want to add it?'))return;
|
28 |
+
jQuery('#'+type+'QueryBox').val('');
|
29 |
+
jQuery('#'+type+'List').append(jQuery('<span class="sectoken-'+data+'"/>').text(value).append(
|
30 |
+
jQuery('<input type="hidden" name="'+type+'s[]"/>').val(value),
|
31 |
+
jQuery('<a href="javascript:;" title="Remove">×</a>').click(RemoveSecToken)
|
32 |
+
));
|
33 |
+
});
|
34 |
+
});
|
35 |
+
|
36 |
+
jQuery('#ViewerList>span>a, #EditorList>span>a').click(RemoveSecToken);
|
37 |
+
});
|
pages/about.php
DELETED
@@ -1,21 +0,0 @@
|
|
1 |
-
<?php if(! WPPHUtil::canViewPage()){ return; } ?>
|
2 |
-
<?php
|
3 |
-
if(! WPPH::ready())
|
4 |
-
{
|
5 |
-
$errors = WPPH::getPluginErrors();
|
6 |
-
foreach($errors as $error) {
|
7 |
-
wpph_adminNotice(base64_decode($error));
|
8 |
-
}
|
9 |
-
echo '<div id="wpph-pageWrapper" class="wrap">';
|
10 |
-
echo '<p>'.__('We have encountered some errors during the installation of the plugin which you can find above.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
11 |
-
echo '<p>'.__('Please try to correct them and then reactivate the plugin.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
12 |
-
echo '</div>';
|
13 |
-
return;
|
14 |
-
}
|
15 |
-
?>
|
16 |
-
<div id="wpph-pageWrapper" class="wrap">
|
17 |
-
<h2 class="pageTitle pageTitle-about"><?php echo __('About us',WPPH_PLUGIN_TEXT_DOMAIN);?></h2>
|
18 |
-
<div>
|
19 |
-
<p><?php echo sprintf(__('WP Security Audit Log is a WordPress security plugin developed by %s.',WPPH_PLUGIN_TEXT_DOMAIN), '<a href="http://www.wpwhitesecurity.com">WP White Security</a>');?></p>
|
20 |
-
</div>
|
21 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/alerts.php
DELETED
@@ -1,190 +0,0 @@
|
|
1 |
-
<?php if(! WPPHUtil::canViewPage()){ return; } ?>
|
2 |
-
<?php
|
3 |
-
if(! WPPH::ready())
|
4 |
-
{
|
5 |
-
$errors = WPPH::getPluginErrors();
|
6 |
-
foreach($errors as $error) {
|
7 |
-
wpph_adminNotice($error);
|
8 |
-
}
|
9 |
-
echo '<div id="wpph-pageWrapper" class="wrap">';
|
10 |
-
echo '<p>'.__('We have encountered some errors during the installation of the plugin which you can find above.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
11 |
-
echo '<p>'.__('Please try to correct them and then reactivate the plugin.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
12 |
-
echo '</div>';
|
13 |
-
return;
|
14 |
-
}
|
15 |
-
?>
|
16 |
-
<?php
|
17 |
-
// defaults
|
18 |
-
$defaultEvents = WPPH::getDefaultEvents();
|
19 |
-
$logEvents = WPPH::getEvents();
|
20 |
-
$validationMessage = array();
|
21 |
-
$sectionNames = (empty($logEvents)) ? array(): array_keys($logEvents);
|
22 |
-
$activeTab = 0;
|
23 |
-
$rm = strtoupper($_SERVER['REQUEST_METHOD']);
|
24 |
-
if('POST' == $rm)
|
25 |
-
{
|
26 |
-
// Check nonce
|
27 |
-
if(isset($_POST['wpph_update_settings_field_nonce'])){
|
28 |
-
if(!wp_verify_nonce($_POST['wpph_update_settings_field_nonce'],'wpph_update_settings')){
|
29 |
-
wp_die('Invalid request');
|
30 |
-
}
|
31 |
-
}
|
32 |
-
else {wp_die('Invalid request');}
|
33 |
-
|
34 |
-
$hasErrors = false;
|
35 |
-
$activeTab = intval($_POST['activeTab']);
|
36 |
-
$inputEvents = $_POST['inputEvents'];
|
37 |
-
$inputEvents = str_replace("\\", "",$inputEvents);
|
38 |
-
$inputEvents = json_decode($inputEvents, true);
|
39 |
-
if(is_null($inputEvents)){
|
40 |
-
$validationMessage['error'] = __('JSON Decode Error: ',WPPH_PLUGIN_TEXT_DOMAIN).json_last_error();
|
41 |
-
$hasErrors = true;
|
42 |
-
}
|
43 |
-
|
44 |
-
// save options
|
45 |
-
if(!$hasErrors)
|
46 |
-
{
|
47 |
-
$logEvents = array();
|
48 |
-
$wpphEvents = WPPH::getEvents();
|
49 |
-
foreach($wpphEvents as $category=>$entries){
|
50 |
-
$logEvents[$category] = array();
|
51 |
-
foreach($entries as $event=>$entry){
|
52 |
-
$logEvents[$category][$event] = 1;
|
53 |
-
}
|
54 |
-
}
|
55 |
-
foreach($inputEvents as $category=>$entries){
|
56 |
-
foreach($entries as $entry){
|
57 |
-
$event = (int)$entry['e'];
|
58 |
-
// validate event before insert
|
59 |
-
if(isset($wpphEvents[$category][$event])){
|
60 |
-
$logEvents[$category][$event] = 0;
|
61 |
-
}
|
62 |
-
}
|
63 |
-
}
|
64 |
-
wpph_updatePluginEventsList($logEvents);
|
65 |
-
$validationMessage['success'] = __('Your settings have been saved.',WPPH_PLUGIN_TEXT_DOMAIN);
|
66 |
-
}
|
67 |
-
}
|
68 |
-
// end $post
|
69 |
-
?>
|
70 |
-
<div id="wpph-pageWrapper" class="wrap">
|
71 |
-
<h2 class="pageTitle pageTitle-settings"><?php echo __('Enable/Disable Alerts',WPPH_PLUGIN_TEXT_DOMAIN);?></h2>
|
72 |
-
|
73 |
-
<div id="optionsDescription">
|
74 |
-
<p id="description" style="background: none repeat scroll 0 0 #EEEEEE;border: 1px solid #AAAAAA;border-radius: 4px 4px 4px 4px;box-shadow: 2px 2px 3px #DDDDDD;">
|
75 |
-
<?php
|
76 |
-
echo __('From this page you can enable or disable WordPress security alerts. If a security alert is disabled, an alert will not be generated in the Audit Log Viewer once such action happens.',WPPH_PLUGIN_TEXT_DOMAIN);
|
77 |
-
echo '<br/>'.__('To disable a security alert, select the category tab and untick the alert. Click Save Settings when ready.',WPPH_PLUGIN_TEXT_DOMAIN);
|
78 |
-
?>
|
79 |
-
</p>
|
80 |
-
</div>
|
81 |
-
|
82 |
-
<?php if(! empty($validationMessage)) : ?>
|
83 |
-
<?php
|
84 |
-
if(!empty($validationMessage['error'])){ wpph_adminNotice($validationMessage['error']); }
|
85 |
-
else { wpph_adminUpdate($validationMessage['success']); }
|
86 |
-
?>
|
87 |
-
<?php endif;?>
|
88 |
-
|
89 |
-
<?php if(!empty($sectionNames)) : ?>
|
90 |
-
<div id="logEventsTabControl" style="margin: 20px 0; opacity: 0;">
|
91 |
-
<form id="updateSettingsForm" method="post">
|
92 |
-
<?php wp_nonce_field('wpph_update_settings','wpph_update_settings_field_nonce'); ?>
|
93 |
-
<?php
|
94 |
-
echo '<ul id="tabControlNavBar">';
|
95 |
-
foreach($sectionNames as $item){
|
96 |
-
echo '<li data-id="'.$item.'"><a href="#'.$item.'"/>'.str_replace('_',' ', $item).'</a></li>';
|
97 |
-
}
|
98 |
-
echo '</ul>';
|
99 |
-
|
100 |
-
foreach($logEvents as $sectionName => $items){
|
101 |
-
echo '<div id="'.$sectionName.'">';
|
102 |
-
echo '<table class="wp-list-table widefat" cellspacing="0" cellpadding="0">';
|
103 |
-
echo '<thead>';
|
104 |
-
echo '<th class="manage-column column-cb check-column item-cb item-cb_h" scope="col"><input type="checkbox" class="js-select-all"/></th>';
|
105 |
-
echo '<th class="manage-column item-event" scope="col">'.__('Event',WPPH_PLUGIN_TEXT_DOMAIN).'</th>';
|
106 |
-
echo '<th class="manage-column item-type" scope="col">'.__('Type',WPPH_PLUGIN_TEXT_DOMAIN).'</th>';
|
107 |
-
echo '<th class="manage-column item-description" scope="col">'.__('Description',WPPH_PLUGIN_TEXT_DOMAIN).'</th>';
|
108 |
-
echo '</thead>';
|
109 |
-
echo '<tbody>';
|
110 |
-
$disabledEvents = array(6001,6002);
|
111 |
-
foreach($items as $item => $enabled){
|
112 |
-
if(in_array((int)$item, $disabledEvents)){
|
113 |
-
$t = sprintf(__('Event %s is not available in MultiSite.',WPPH_PLUGIN_TEXT_DOMAIN), $item);
|
114 |
-
echo '<tr class="row" title="'.$t.'">';
|
115 |
-
echo '<th class="manage-column column-cb check-column item-cb_h" scope="row"><input class="item_cb" type="checkbox" disabled="disabled"/></th>';
|
116 |
-
echo '<td class="wpph-text-disabled">'.$item.'</td>';
|
117 |
-
echo '<td class="wpph-text-disabled">'.(isset($defaultEvents[$sectionName][$item]['type']) ? $defaultEvents[$sectionName][$item]['type'] : '').'</td>';
|
118 |
-
echo '<td class="wpph-text-disabled">'.(isset($defaultEvents[$sectionName][$item]['text']) ? $defaultEvents[$sectionName][$item]['text'] : '').'</td>';
|
119 |
-
echo '</tr>';
|
120 |
-
}
|
121 |
-
else {
|
122 |
-
echo '<tr class="row">';
|
123 |
-
echo '<th class="manage-column column-cb check-column item-cb_h" scope="row"><input class="item_cb" type="checkbox" '.($enabled ? 'checked="checked"' : '').' value="'.$item.'"/></th>';
|
124 |
-
echo '<td>'.$item.'</td>';
|
125 |
-
echo '<td>'.(isset($defaultEvents[$sectionName][$item]['type']) ? $defaultEvents[$sectionName][$item]['type'] : '').'</td>';
|
126 |
-
echo '<td>'.(isset($defaultEvents[$sectionName][$item]['text']) ? $defaultEvents[$sectionName][$item]['text'] : '').'</td>';
|
127 |
-
echo '</tr>';
|
128 |
-
|
129 |
-
}
|
130 |
-
}
|
131 |
-
echo '</tbody>';
|
132 |
-
echo '</table>';
|
133 |
-
echo '</div>';
|
134 |
-
}
|
135 |
-
?>
|
136 |
-
<input type="submit" id="submitButton" class="button button-primary" style="margin: 0 0 12px 19px;" value="<?php echo __('Save settings',WPPH_PLUGIN_TEXT_DOMAIN);?>"/>
|
137 |
-
<input type="hidden" id="inputEvents" name="inputEvents" value=""/>
|
138 |
-
<input type="hidden" id="activeTab" name="activeTab" value=""/>
|
139 |
-
</form>
|
140 |
-
</div>
|
141 |
-
<?php else : ?>
|
142 |
-
<div class="error"><p><?php echo __('Error retrieving the list of events from database. Please inform the plugin author about this.',WPPH_PLUGIN_TEXT_DOMAIN);?></p></div>
|
143 |
-
<?php endif; ?>
|
144 |
-
</div>
|
145 |
-
<br class="clear"/>
|
146 |
-
|
147 |
-
<script type="text/javascript">
|
148 |
-
jQuery(document).ready(function($){
|
149 |
-
var tabControl = $('#logEventsTabControl');
|
150 |
-
var activeTab = $('#activeTab');
|
151 |
-
tabControl.tabs();
|
152 |
-
tabControl.tabs("option", "active", <?php echo $activeTab;?>);
|
153 |
-
tabControl.css('opacity',1);
|
154 |
-
// update select all checkbox
|
155 |
-
$('#tabControlNavBar li').each(function(){
|
156 |
-
var sectionName = $(this).data('id');
|
157 |
-
if(sectionName.length > 0){
|
158 |
-
$('#'+sectionName+' input:checkbox.item_cb').each(function() {
|
159 |
-
var self = $(this);
|
160 |
-
if (self.prop('checked')) {
|
161 |
-
$('#'+sectionName+' input:checkbox.js-select-all').attr('checked','checked');
|
162 |
-
}
|
163 |
-
});
|
164 |
-
}
|
165 |
-
});
|
166 |
-
//
|
167 |
-
// form submit
|
168 |
-
$('#submitButton').on('click',function()
|
169 |
-
{
|
170 |
-
activeTab.val(tabControl.tabs("option","active"));
|
171 |
-
// build options
|
172 |
-
var e = $('#inputEvents')
|
173 |
-
,catList = $('#tabControlNavBar li')
|
174 |
-
,outData = {};
|
175 |
-
catList.each(function(){
|
176 |
-
var sectionName = $(this).data('id');
|
177 |
-
if(sectionName.length > 0){
|
178 |
-
outData[sectionName] = [];
|
179 |
-
$('#'+sectionName+' input:checkbox.item_cb').each(function() {
|
180 |
-
var self = $(this);
|
181 |
-
if (!self.prop('checked')) {
|
182 |
-
outData[sectionName].push({"e": self.val()});
|
183 |
-
}
|
184 |
-
});
|
185 |
-
}
|
186 |
-
});
|
187 |
-
e.val(JSON.stringify(outData));
|
188 |
-
});
|
189 |
-
});
|
190 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/dashboard.php
DELETED
@@ -1,165 +0,0 @@
|
|
1 |
-
<?php if(! WPPHUtil::canViewPage()){ return; } ?>
|
2 |
-
<?php
|
3 |
-
if(! WPPH::ready())
|
4 |
-
{
|
5 |
-
$errors = WPPH::getPluginErrors();
|
6 |
-
foreach($errors as $error) {
|
7 |
-
wpph_adminNotice($error);
|
8 |
-
}
|
9 |
-
echo '<div id="wpph-pageWrapper" class="wrap">';
|
10 |
-
echo '<p>'.__('We have encountered some errors during the installation of the plugin which you can find above.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
11 |
-
echo '<p>'.__('Please try to correct them and then reactivate the plugin.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
12 |
-
echo '</div>';
|
13 |
-
return;
|
14 |
-
}
|
15 |
-
?>
|
16 |
-
<div id="wpph-pageWrapper" class="wrap">
|
17 |
-
<h2 class="pageTitle pageTitle-eventViewer">Audit Log Viewer</h2>
|
18 |
-
<div id="EventViewerWrapper">
|
19 |
-
<div style="overflow: hidden; display: block; clear: both;">
|
20 |
-
<div class="tablenav top" style="overflow: hidden; padding: 4px 0;">
|
21 |
-
<div class="alignleft">
|
22 |
-
<div style="overflow: hidden;">
|
23 |
-
<input type="button" class="buttonRefreshEventsList button" value="<?php echo __('Refresh Security Alerts List',WPPH_PLUGIN_TEXT_DOMAIN);?>"
|
24 |
-
style="float: left; display: block;" data-bind="disable: loading, click: $root.onRefreshEvents"/>
|
25 |
-
<span class="ajaxLoaderWrapper" style="float: left; display: block; width: 20px; height: 20px; padding: 7px 7px;"><img/></span>
|
26 |
-
</div>
|
27 |
-
</div>
|
28 |
-
<div class="alignleft actions" style="overflow: hidden;">
|
29 |
-
<label class="alignleft" style="margin: 5px 5px 0 0;"><?php echo __('Number of security alerts per page:',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
30 |
-
<select name="actionLimit1" class="actionLimit" data-bind="options: availablePageSize, value: selectedPageSize, disable: loading"></select>
|
31 |
-
<input type="button" value="Apply" class="button action" data-bind="disable: loading, click: $root.onApplyPageSize">
|
32 |
-
</div>
|
33 |
-
|
34 |
-
<?php if(WPPH::isMultisite()): ?>
|
35 |
-
<!-- ko if: isMainSite -->
|
36 |
-
<div class="alignleft" style="padding: 2px 0;">
|
37 |
-
<select id="ntwkBlogs" data-bind="disable: loading, options: blogList, optionsText: 'blogname', optionsValue: 'blog_id', value: blogId"></select>
|
38 |
-
</div>
|
39 |
-
<!-- /ko -->
|
40 |
-
<?php endif;?>
|
41 |
-
|
42 |
-
<div class="tablenav-pages">
|
43 |
-
<span class="displaying-num" data-bind="text: totalEventsCount()+' security alerts'"></span>
|
44 |
-
<span class="pagination-links"><a href="#" title="Go to the first page" class="first-page" data-bind="click: firstPage, css: {disabled: offset() <= 0}">«</a>
|
45 |
-
<a href="#" title="Go to the previous page" class="prev-page" data-bind="click: prevPage, disable: loading, click: prevPage, css: {disabled: offset() <= 0}">‹</a>
|
46 |
-
<span class="paging-input">
|
47 |
-
<input type="text" size="1" id="fdr" title="Current page" class="current-page"
|
48 |
-
data-bind="value: currentPage, event: {keydown: onCurrentPageInputKeyDown} "/> of <span class="total-pages" data-bind="text: pageCount"></span>
|
49 |
-
</span>
|
50 |
-
<a href="#" title="Go to the next page" class="next-page" data-bind="click: nextPage, disable: loading, click: nextPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">›</a>
|
51 |
-
<a href="#" title="Go to the last page" class="last-page" data-bind="click: lastPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">»</a></span>
|
52 |
-
</div>
|
53 |
-
|
54 |
-
</div>
|
55 |
-
</div>
|
56 |
-
<table class="wp-list-table widefat fixed" cellspacing="0" cellpadding="0">
|
57 |
-
<thead>
|
58 |
-
<tr data-bind="foreach: { data: columns, as: 'columnItem' }">
|
59 |
-
<!-- ko if: columnItem.visible -->
|
60 |
-
<th class="manage-column column-left-align" scope="col"
|
61 |
-
data-bind="style: {width: columnItem.columnWidth}, css: { sortable: columnItem.sortable, sorted: columnItem.sorted, desc: columnItem.sortable && columnItem.sortedDescending(), asc: columnItem.sortable && !columnItem.sortedDescending()}">
|
62 |
-
<a href="#" data-bind="disable: $root.loading, click: columnItem.sortable ? $root.onApplySorting : function() { return false; }">
|
63 |
-
<span data-bind="text: columnItem.columnHeader"></span>
|
64 |
-
<span class="sorting-indicator"></span>
|
65 |
-
</a>
|
66 |
-
</th>
|
67 |
-
<!-- /ko -->
|
68 |
-
</tr>
|
69 |
-
</thead>
|
70 |
-
<tfoot>
|
71 |
-
<tr data-bind="foreach: { data: columns, as: 'columnItem' }">
|
72 |
-
<!-- ko if: columnItem.visible -->
|
73 |
-
<th class="manage-column column-left-align" scope="col"
|
74 |
-
data-bind="style: {width: columnItem.columnWidth}, css: { sortable: columnItem.sortable, sorted: columnItem.sorted, desc: columnItem.sortable && columnItem.sortedDescending(), asc: columnItem.sortable && !columnItem.sortedDescending()}">
|
75 |
-
<a href="#" data-bind="disable: $root.loading, click: columnItem.sortable ? $root.onApplySorting : function() { return false; }">
|
76 |
-
<span data-bind="text: columnItem.columnHeader"></span>
|
77 |
-
<span class="sorting-indicator"></span>
|
78 |
-
</a>
|
79 |
-
</th>
|
80 |
-
<!-- /ko -->
|
81 |
-
</tr>
|
82 |
-
</tfoot>
|
83 |
-
<tbody id="the-list">
|
84 |
-
<!-- ko if: events().length == 0 -->
|
85 |
-
<tr>
|
86 |
-
<!-- ko ifnot: error -->
|
87 |
-
<td id="wpph_ew" style="padding: 4px !important;" colspan="8"><?php echo __('No security alerts',WPPH_PLUGIN_TEXT_DOMAIN);?></td>
|
88 |
-
<!-- /ko -->
|
89 |
-
|
90 |
-
<!-- ko if: error -->
|
91 |
-
<td id="wpph_ew" style="padding: 4px !important;" colspan="8">
|
92 |
-
<strong data-bind="text: error"></strong>
|
93 |
-
</td>
|
94 |
-
<!-- /ko -->
|
95 |
-
</tr>
|
96 |
-
<!-- /ko -->
|
97 |
-
|
98 |
-
<!-- ko foreach: events -->
|
99 |
-
<tr data-bind="css: {'row-0': ($index() % 2) == 0, 'row-1': ($index() % 2) != 0}">
|
100 |
-
<td class="column-event_number"><span data-bind="text: eventNumber"></span></td>
|
101 |
-
<td class="column-event_id"><span data-bind="text: eventId"></span></td>
|
102 |
-
<td class="column-event_date"><span data-bind="text: eventDate"></span></td>
|
103 |
-
<td class="column-event_category"><span data-bind="text: EventType"></span></td>
|
104 |
-
<td class="column-ip"><span data-bind="text: ip"></span></td>
|
105 |
-
<td class="column-user"><span data-bind="text: user"></span></td>
|
106 |
-
<!-- ko if: $root.blogId() === 0 -->
|
107 |
-
<td class="column-site"><span data-bind="text: $data.siteName"></span></td>
|
108 |
-
<!-- /ko -->
|
109 |
-
<td class="column-description"><span data-bind="html: description"></span></td>
|
110 |
-
</tr>
|
111 |
-
<!-- /ko -->
|
112 |
-
</tbody>
|
113 |
-
</table>
|
114 |
-
<div style="overflow: hidden; display: block; clear: both;">
|
115 |
-
<div class="tablenav top" style="overflow: hidden; padding: 4px 0;">
|
116 |
-
<div class="alignleft">
|
117 |
-
<div style="overflow: hidden;">
|
118 |
-
<input type="button" class="buttonRefreshEventsList button" value="<?php echo __('Refresh security alerts List',WPPH_PLUGIN_TEXT_DOMAIN);?>"
|
119 |
-
style="float: left; display: block;" data-bind="disable: loading, click: $root.onRefreshEvents"/>
|
120 |
-
<span class="ajaxLoaderWrapper" style="float: left; display: block; width: 20px; height: 20px; padding: 7px 7px;"><img/></span>
|
121 |
-
</div>
|
122 |
-
</div>
|
123 |
-
<div class="alignleft actions" style="overflow: hidden;">
|
124 |
-
<label class="alignleft" style="margin: 5px 5px 0 0;"><?php echo __('Number of security alerts per page:',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
125 |
-
<select name="actionLimit1" class="actionLimit" data-bind="options: availablePageSize, value: selectedPageSize, disable: loading"></select>
|
126 |
-
<input type="button" value="Apply" class="button action" data-bind="disable: loading, click: $root.onApplyPageSize">
|
127 |
-
</div>
|
128 |
-
<div class="tablenav-pages">
|
129 |
-
<span class="displaying-num" data-bind="text: totalEventsCount()+' security alerts'"></span>
|
130 |
-
<span class="pagination-links"><a href="#" title="Go to the first page" class="first-page" data-bind="click: firstPage, css: {disabled: offset() <= 0}">«</a>
|
131 |
-
<a href="#" title="Go to the previous page" class="prev-page" data-bind="click: prevPage, disable: loading, click: prevPage, css: {disabled: offset() <= 0}">‹</a>
|
132 |
-
<span class="paging-input">
|
133 |
-
<input type="text" size="1" id="fdr" title="Current page" class="current-page"
|
134 |
-
data-bind="value: currentPage, event: {keydown: onCurrentPageInputKeyDown} "/> of <span class="total-pages" data-bind="text: pageCount"></span>
|
135 |
-
</span>
|
136 |
-
<a href="#" title="Go to the next page" class="next-page" data-bind="click: nextPage, disable: loading, click: nextPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">›</a>
|
137 |
-
<a href="#" title="Go to the last page" class="last-page" data-bind="click: lastPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">»</a></span>
|
138 |
-
</div>
|
139 |
-
</div>
|
140 |
-
</div>
|
141 |
-
|
142 |
-
</div>
|
143 |
-
</div>
|
144 |
-
<?php global $blog_id; ?>
|
145 |
-
<script type="text/javascript">
|
146 |
-
jQuery.WPPH_CRT_BLOG_ID = <?php echo WPPHUtil::isMainSite() ? 0 : $blog_id;?>;
|
147 |
-
// configure ajax loader
|
148 |
-
var __ajaxLoaderTargetElement__ = jQuery('.ajaxLoaderWrapper img');
|
149 |
-
var AjaxLoaderCreate = function(e){
|
150 |
-
var imgPath = "<?php echo WPPH_PLUGIN_URL.'res/img/ajax-loader.gif';?>";
|
151 |
-
e.attr('src',imgPath);
|
152 |
-
}(__ajaxLoaderTargetElement__);
|
153 |
-
var AjaxLoaderShow = function(e){ e.show(); };
|
154 |
-
var AjaxLoaderHide = function(e){ e.hide(); };
|
155 |
-
jQuery(document).ready(function($) {
|
156 |
-
var myViewModel = AuditLogViewModel;
|
157 |
-
myViewModel.isMainSite(!!<?php echo WPPHUtil::isMainSite() ? '1': '0';?>);
|
158 |
-
myViewModel.orderBy('EventNumber');
|
159 |
-
myViewModel.orderByDescending(true);
|
160 |
-
ko.applyBindings(myViewModel, $('#wpph-pageWrapper').get(0));
|
161 |
-
setTimeout(function() {
|
162 |
-
myViewModel.refreshEvents(0, jQuery.WPPH_CRT_BLOG_ID);
|
163 |
-
});
|
164 |
-
});
|
165 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/settings.php
DELETED
@@ -1,576 +0,0 @@
|
|
1 |
-
<?php //if(! WPPHUtil::canViewPage()){ return; } ?>
|
2 |
-
<?php
|
3 |
-
if(! WPPH::ready())
|
4 |
-
{
|
5 |
-
$errors = WPPH::getPluginErrors();
|
6 |
-
foreach($errors as $error) {
|
7 |
-
wpph_adminNotice($error);
|
8 |
-
}
|
9 |
-
echo '<div id="wpph-pageWrapper" class="wrap">';
|
10 |
-
echo '<p>'.__('We have encountered some errors during the installation of the plugin which you can find above.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
11 |
-
echo '<p>'.__('Please try to correct them and then reactivate the plugin.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
12 |
-
echo '</div>';
|
13 |
-
return;
|
14 |
-
}
|
15 |
-
?>
|
16 |
-
<?php
|
17 |
-
// defaults
|
18 |
-
$opt = WPPH::getPluginSettings();
|
19 |
-
$daysInput = 0;
|
20 |
-
$eventsNumber = 0;
|
21 |
-
$validationMessage = array();
|
22 |
-
$hasErrors = false;
|
23 |
-
$showDW = (empty($opt->showDW) ? false : true);
|
24 |
-
// active delete option for events
|
25 |
-
if(!empty($opt->daysToKeep)){ $daysInput = $opt->daysToKeep; $activeOption = 1; }
|
26 |
-
if(! empty($opt->eventsToKeep)){ $eventsNumber = $opt->eventsToKeep; $activeOption = 2; }
|
27 |
-
$allowedAccess = WPPHNetwork::getGlobalOption(WPPH_PLUGIN_ALLOW_ACCESS_OPTION_NAME, true, true, array());
|
28 |
-
$allowedChange = WPPHNetwork::getGlobalOption(WPPH_PLUGIN_ALLOW_CHANGE_OPTION_NAME, true, true, array());
|
29 |
-
if(! isset($activeOption)){ $activeOption = 2; }
|
30 |
-
// end defaults
|
31 |
-
|
32 |
-
$rm = strtoupper($_SERVER['REQUEST_METHOD']);
|
33 |
-
if('POST' == $rm)
|
34 |
-
{
|
35 |
-
// Check nonce
|
36 |
-
if(isset($_POST['wpph_update_settings_field_nonce'])){
|
37 |
-
if(!wp_verify_nonce($_POST['wpph_update_settings_field_nonce'],'wpph_update_settings')){
|
38 |
-
wp_die('Invalid request');
|
39 |
-
}
|
40 |
-
}
|
41 |
-
else {wp_die('Invalid request');}
|
42 |
-
|
43 |
-
// method to use
|
44 |
-
if(! isset($_POST['deleteEventsBy'])){ wp_die('Invalid request'); }
|
45 |
-
// value to use
|
46 |
-
if(! isset($_POST['deleteEventsValue'])){ wp_die('Invalid request'); }
|
47 |
-
$deleteEventsBy = intval($_POST['deleteEventsBy']);
|
48 |
-
$deleteEventsValue = intval($_POST['deleteEventsValue']);
|
49 |
-
|
50 |
-
$pac = (isset($_POST['accessListInput']) ? trim($_POST['accessListInput']) : null);
|
51 |
-
$pcc = (isset($_POST['changeListInput']) ? trim($_POST['changeListInput']) : null);
|
52 |
-
|
53 |
-
// pre-validate access rules if any
|
54 |
-
if(! empty($pac) && strlen($pac)>4){
|
55 |
-
$pac = str_replace('\\','', $pac);
|
56 |
-
$allowedAccess = json_decode($pac);
|
57 |
-
if(is_null($allowedAccess)){
|
58 |
-
wpphLog('Error decoding json input $pac.', array('pac'=>$pac));
|
59 |
-
$validationMessage['error'] = __('UAL: Error decoding json input', WPPH_PLUGIN_TEXT_DOMAIN);
|
60 |
-
$hasErrors = true;
|
61 |
-
}
|
62 |
-
else {
|
63 |
-
wpphLog('accessListInput is not empty.', array('pac'=>$pac,'data'=>$allowedAccess));
|
64 |
-
WPPHUtil::saveAllowAccessUserList($allowedAccess);
|
65 |
-
}
|
66 |
-
}
|
67 |
-
else {
|
68 |
-
wpphLog('accessListInput is empty. Resetting the user access list.');
|
69 |
-
WPPHUtil::saveAllowAccessUserList(array());
|
70 |
-
}
|
71 |
-
|
72 |
-
// pre-validate change rules if any
|
73 |
-
if(! empty($pcc) && strlen($pcc)>4){
|
74 |
-
$pcc = str_replace('\\','', $pcc);
|
75 |
-
$allowedChange = json_decode($pcc);
|
76 |
-
if(is_null($allowedChange)){
|
77 |
-
wpphLog('Error decoding json input $pcc.', array('pcc'=>$pcc));
|
78 |
-
$validationMessage['error'] = __('UCL: Error decoding json input: '.$pcc.' '.var_export($allowedChange,true), WPPH_PLUGIN_TEXT_DOMAIN);
|
79 |
-
$hasErrors = true;
|
80 |
-
}
|
81 |
-
else {
|
82 |
-
wpphLog('changeListInput is not empty.', array('pcc'=>$pcc,'data'=>$allowedChange));
|
83 |
-
WPPHUtil::saveAllowedChangeUserList($allowedChange);
|
84 |
-
}
|
85 |
-
}
|
86 |
-
else {
|
87 |
-
wpphLog('changeListInput is empty. Resetting the user access list.');
|
88 |
-
WPPHUtil::saveAllowedChangeUserList(array());
|
89 |
-
}
|
90 |
-
|
91 |
-
// if Delete events older than ... days
|
92 |
-
if($deleteEventsBy == 1)
|
93 |
-
{
|
94 |
-
$activeOption = 1;
|
95 |
-
$daysInput = $deleteEventsValue;
|
96 |
-
|
97 |
-
// Validate
|
98 |
-
if(!preg_match('/^\d+$/',$deleteEventsValue)){
|
99 |
-
$validationMessage['error'] = __('Incorrect number of days. Please specify a value between 1 and 365.',WPPH_PLUGIN_TEXT_DOMAIN);
|
100 |
-
$hasErrors = true;
|
101 |
-
}
|
102 |
-
elseif($deleteEventsValue < 1 || $deleteEventsValue > 365){
|
103 |
-
$validationMessage['error'] = __('Incorrect number of days. Please specify a value between 1 and 365.',WPPH_PLUGIN_TEXT_DOMAIN);
|
104 |
-
$hasErrors = true;
|
105 |
-
}
|
106 |
-
else {
|
107 |
-
if(! $hasErrors){
|
108 |
-
// reset events number
|
109 |
-
if(isset($opt->eventsToKeep)){
|
110 |
-
$opt->eventsToKeep = 0;
|
111 |
-
}
|
112 |
-
$opt->daysToKeep = $deleteEventsValue;
|
113 |
-
}
|
114 |
-
}
|
115 |
-
}
|
116 |
-
elseif($deleteEventsBy == 2)
|
117 |
-
{
|
118 |
-
$activeOption = 2;
|
119 |
-
$eventsNumber = $deleteEventsValue;
|
120 |
-
|
121 |
-
// Validate
|
122 |
-
if(!preg_match('/^\d+$/',$deleteEventsValue)){
|
123 |
-
$validationMessage['error'] = sprintf(__('Incorrect number of security alerts. Please specify a value between 1 and %d.',WPPH_PLUGIN_TEXT_DOMAIN), WPPH_KEEP_MAX_EVENTS);
|
124 |
-
$hasErrors = true;
|
125 |
-
}
|
126 |
-
elseif($deleteEventsValue < 1 || $deleteEventsValue > WPPH_KEEP_MAX_EVENTS){
|
127 |
-
$validationMessage['error'] = sprintf(__('Incorrect number of security alerts. Please specify a value between 1 and %d.',WPPH_PLUGIN_TEXT_DOMAIN), WPPH_KEEP_MAX_EVENTS);
|
128 |
-
$hasErrors = true;
|
129 |
-
}
|
130 |
-
else {
|
131 |
-
// reset days
|
132 |
-
if(isset($opt->daysToKeep)){
|
133 |
-
$opt->daysToKeep = 0;
|
134 |
-
}
|
135 |
-
$opt->eventsToKeep = $deleteEventsValue;
|
136 |
-
}
|
137 |
-
}
|
138 |
-
|
139 |
-
// dashboard widget
|
140 |
-
if(isset($_POST['optionDW'])){
|
141 |
-
$showDW = intval($_POST['optionDW']);
|
142 |
-
}
|
143 |
-
|
144 |
-
// save options
|
145 |
-
if(!$hasErrors)
|
146 |
-
{
|
147 |
-
$opt->showDW = (empty($showDW) ? 0 : 1);
|
148 |
-
$opt->cleanupRan = 0;
|
149 |
-
WPPH::updatePluginSettings($opt,null,null,true);
|
150 |
-
$validationMessage['success'] = __('Your settings have been saved.',WPPH_PLUGIN_TEXT_DOMAIN);
|
151 |
-
}
|
152 |
-
}
|
153 |
-
// end $post
|
154 |
-
?>
|
155 |
-
<style type="text/css">
|
156 |
-
.widefat td p { margin: 13px 0 0.8em !important; }
|
157 |
-
.message {
|
158 |
-
background-color: #FFFFE0 !important;
|
159 |
-
border-radius: 3px 3px 3px 3px;
|
160 |
-
border-style: solid;
|
161 |
-
border-width: 1px;
|
162 |
-
border-color: #E6DB55;
|
163 |
-
margin: 5px 0 15px !important;
|
164 |
-
padding: 0 0.6em !important;
|
165 |
-
}
|
166 |
-
.message p { margin: 0 0; padding: 7px 0; font-style: italic; }
|
167 |
-
p.description span { text-decoration: underline;}
|
168 |
-
.the-list th, .the-list tr td {padding: 7px 0 0 0 !important;}
|
169 |
-
.the-list th p, .the-list tr td p {padding: 0 0 !important; margin: 0 0 !important;}
|
170 |
-
.the-list td.column-username p,
|
171 |
-
.the-list td.column-name p,
|
172 |
-
.the-list td.column-role p { padding-left: 7px !important;}
|
173 |
-
.form-table td { vertical-align: top !important; }
|
174 |
-
.section-left label { margin-top: 3px !important; display: block;}
|
175 |
-
</style>
|
176 |
-
<div id="wpph-pageWrapper" class="wrap">
|
177 |
-
<h2 class="pageTitle pageTitle-settings"><?php echo __('WP Security Audit Log Settings',WPPH_PLUGIN_TEXT_DOMAIN);?></h2>
|
178 |
-
|
179 |
-
<?php if(! empty($validationMessage)) : ?>
|
180 |
-
<?php
|
181 |
-
if(!empty($validationMessage['error'])){ wpph_adminNotice($validationMessage['error']); }
|
182 |
-
else { wpph_adminUpdate($validationMessage['success']); }
|
183 |
-
?>
|
184 |
-
<?php else : ?>
|
185 |
-
<div id="errMessage" style="display: none;"></div>
|
186 |
-
<?php endif;?>
|
187 |
-
<div style="margin: 20px 0;">
|
188 |
-
<form id="updateSettingsForm" method="post">
|
189 |
-
<?php wp_nonce_field('wpph_update_settings','wpph_update_settings_field_nonce'); ?>
|
190 |
-
<div id="eventsDeletion">
|
191 |
-
<div id="section-holder">
|
192 |
-
|
193 |
-
<table cellspacing="0" cellpadding="0" class="form-table">
|
194 |
-
<tbody>
|
195 |
-
<tr valign="top">
|
196 |
-
<td rowspan="3" class="section-left">
|
197 |
-
<label style="display:block;margin: 0 0;" for="eventsNumberInput"><?php echo __('Security Alerts Pruning',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
198 |
-
</td>
|
199 |
-
</tr>
|
200 |
-
<tr>
|
201 |
-
<td class="section-right">
|
202 |
-
<p>
|
203 |
-
<input type="radio" id="option1" class="radioInput" style="margin-top: 2px;"/>
|
204 |
-
<label for="option1"><?php echo __('Delete alerts older than',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
205 |
-
<input type="text" id="daysInput" maxlength="3"
|
206 |
-
placeholder="<?php echo __('(1 to 365)',WPPH_PLUGIN_TEXT_DOMAIN);?>"
|
207 |
-
value="<?php if(! empty($daysInput)) { echo $daysInput; } ;?>"/>
|
208 |
-
<span> <?php echo __('(1 to 365 days)',WPPH_PLUGIN_TEXT_DOMAIN);?></span>
|
209 |
-
</p>
|
210 |
-
</td>
|
211 |
-
</tr>
|
212 |
-
<tr>
|
213 |
-
<td class="section-right">
|
214 |
-
<p>
|
215 |
-
<?php $wpph_t1 = sprintf(__('(1 to %d alerts)',WPPH_PLUGIN_TEXT_DOMAIN),WPPH_KEEP_MAX_EVENTS); ?>
|
216 |
-
<input type="radio" id="option2" class="radioInput" style="margin-top: 2px;"/>
|
217 |
-
<label for="option2"><?php echo __('Keep up to',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
218 |
-
<input type="text" id="eventsNumberInput" maxlength="6"
|
219 |
-
placeholder="<?php echo $wpph_t1;?>"
|
220 |
-
value="<?php if(! empty($eventsNumber)) { echo $eventsNumber; } ;?>"/>
|
221 |
-
<span><?php echo $wpph_t1;?></span>
|
222 |
-
</p>
|
223 |
-
<p class="description" style="margin-top: 5px !important;"><?php echo sprintf(__('By default %s will keep up to %d WordPress Security Events.',WPPH_PLUGIN_TEXT_DOMAIN),WPPH_PLUGIN_NAME, WPPH_KEEP_MAX_EVENTS);?></p>
|
224 |
-
</td>
|
225 |
-
</tr>
|
226 |
-
<tr>
|
227 |
-
<td rowspan="2" class="section-left" style=""><label style="display:block;margin: 0 0;" for="optionDW_on"><?php echo __('Alerts Dashboard Widget',WPPH_PLUGIN_TEXT_DOMAIN);?></label></td>
|
228 |
-
</tr>
|
229 |
-
<tr>
|
230 |
-
<td class="section-right">
|
231 |
-
<input type="radio" id="optionDW_on" class="radioInput" style="margin-top: 2px;"/><label for="optionDW_on" style="padding-top: 5px; padding-left: 3px;"><?php echo __('On',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
232 |
-
<br/>
|
233 |
-
<input type="radio" id="optionDW_off" class="radioInput" style="margin-top: 2px;"/><label for="optionDW_off" style="padding-top: 5px; padding-left: 3px;"><?php echo __('Off',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
234 |
-
<br/>
|
235 |
-
<p class="description" style="margin-top: 5px !important;"><?php echo sprintf(__('Display a dashboard widget with the latest 5 security alerts',WPPH_PLUGIN_TEXT_DOMAIN),WPPH_PLUGIN_NAME, WPPH_KEEP_MAX_EVENTS);?></p>
|
236 |
-
</td>
|
237 |
-
</tr>
|
238 |
-
</tbody>
|
239 |
-
</table>
|
240 |
-
|
241 |
-
<style type="text/css">
|
242 |
-
.divTarget { padding: 10px 0;}
|
243 |
-
.tagElement { padding: 2px 4px; margin: 2px 0 0 2px; border: solid 1px #E6DB55; background: #FFFFE0; }
|
244 |
-
.tagElement .tagDelete { cursor: pointer; font-weight: 900; }
|
245 |
-
.tagElement .tagDelete:hover { color: #d00000; }
|
246 |
-
#section-holder #c-list p.description { margin-top: 0 !important; margin-bottom: 0 !important; }
|
247 |
-
</style>
|
248 |
-
<table cellspacing="0" cellpadding="0" class="form-table">
|
249 |
-
<tbody>
|
250 |
-
<tr valign="top">
|
251 |
-
<td valign="top" class="section-left">
|
252 |
-
<label style="display:block;margin: 0 0;" for="inputUser1"><?php echo __('Can view Security Alerts',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
253 |
-
</td>
|
254 |
-
<td class="section-right">
|
255 |
-
<div id="a-list">
|
256 |
-
<input type="text" id="inputUser1" style="float: left; display: block; width: 250px;"/>
|
257 |
-
<input type="button" id="inputAdd1" style="float: left; display: block;" class="button-primary" value="<?php echo __('Add',WPPH_PLUGIN_TEXT_DOMAIN);?>"/>
|
258 |
-
<p class="description" style="clear:both; padding-top: 3px;"><?php echo __('Users and Roles in this list can view the security alerts via the Audit Log Viewer (Read Only)',WPPH_PLUGIN_TEXT_DOMAIN);?></p>
|
259 |
-
<div id="accessListTarget" class="divTarget" style="float: none; clear: both;"></div>
|
260 |
-
</div>
|
261 |
-
</td>
|
262 |
-
</tr>
|
263 |
-
<tr valign="top" style="margin-top: 30px;">
|
264 |
-
<td valign="top" class="section-left">
|
265 |
-
<label style="display:block;margin: 0 0;" for="inputUser2"><?php echo __('Can Manage Plugin ',WPPH_PLUGIN_TEXT_DOMAIN);?></label>
|
266 |
-
</td>
|
267 |
-
<td class="section-right">
|
268 |
-
<div id="c-list">
|
269 |
-
<input type="text" id="inputUser2" style="float: left; display: block; width: 250px;"/>
|
270 |
-
<input type="button" id="inputAdd2" style="float: left; display: block;" class="button-primary" value="<?php echo __('Add',WPPH_PLUGIN_TEXT_DOMAIN);?>"/>
|
271 |
-
<p class="description" style="clear:both; padding-top: 3px;"><?php echo __('Users and Roles in this list can manage the plugin settings.',WPPH_PLUGIN_TEXT_DOMAIN);?></p>
|
272 |
-
<div id="changeListTarget" class="divTarget" style="float: none; clear: both;"></div>
|
273 |
-
</div>
|
274 |
-
</td>
|
275 |
-
</tr>
|
276 |
-
</tbody>
|
277 |
-
</table>
|
278 |
-
<script type="text/javascript">
|
279 |
-
jQuery(document).ready(function($)
|
280 |
-
{
|
281 |
-
var mainContainer1 = $('#a-list'),
|
282 |
-
inputUser1 = $('#inputUser1'),
|
283 |
-
inputAdd1 = $('#inputAdd1'),
|
284 |
-
divTarget1 = $('#accessListTarget'),
|
285 |
-
tagElement1 = $('.tagElement', mainContainer1),
|
286 |
-
mainContainer2 = $('#c-list'),
|
287 |
-
inputUser2 = $('#inputUser2'),
|
288 |
-
inputAdd2 = $('#inputAdd2'),
|
289 |
-
divTarget2 = $('#changeListTarget'),
|
290 |
-
tagElement2 = $('.tagElement', mainContainer2)
|
291 |
-
;
|
292 |
-
|
293 |
-
function showDefaultEntries(data, divTarget){
|
294 |
-
if(data.length > 0){
|
295 |
-
$.each(data, function(i,v){
|
296 |
-
createTag($, v, divTarget);
|
297 |
-
});
|
298 |
-
}
|
299 |
-
}
|
300 |
-
|
301 |
-
// Display the default list
|
302 |
-
<?php
|
303 |
-
if(!empty($allowedAccess)){ echo 'showDefaultEntries(["'.implode('","',$allowedAccess).'"],divTarget1);'; }
|
304 |
-
if(!empty($allowedChange)){ echo 'showDefaultEntries(["'.implode('","',$allowedChange).'"],divTarget2);'; }
|
305 |
-
?>
|
306 |
-
|
307 |
-
function _ajax(string)
|
308 |
-
{
|
309 |
-
if(string.length > 0){
|
310 |
-
var data = {
|
311 |
-
'action': 'wpph_check_user_role',
|
312 |
-
'check_input' : string
|
313 |
-
};
|
314 |
-
}
|
315 |
-
else {
|
316 |
-
alert('Please add a user name or role.');
|
317 |
-
return false;
|
318 |
-
}
|
319 |
-
var result;
|
320 |
-
$.ajax({
|
321 |
-
url: ajaxurl,
|
322 |
-
cache: false,
|
323 |
-
type: 'POST',
|
324 |
-
data: data,
|
325 |
-
async : false,
|
326 |
-
success: function(response) {
|
327 |
-
result = response;
|
328 |
-
},
|
329 |
-
error: function() {
|
330 |
-
result = 'An error occurred. Please try again in a few moments.';
|
331 |
-
}
|
332 |
-
});
|
333 |
-
return result;
|
334 |
-
}
|
335 |
-
function createTag($, value, parentElement){ parentElement.append($('<span class="tagElement"><span class="tagName">'+value+'</span> <span class="tagDelete" title="Delete">x</span></span>')); }
|
336 |
-
function isValidEntry($, value, targetDiv){
|
337 |
-
var elements = $('.tagName', targetDiv);
|
338 |
-
var result = true;
|
339 |
-
if(elements.length > 0){
|
340 |
-
$.each(elements,function(i,v){
|
341 |
-
var val = $.trim($(this).text());
|
342 |
-
if($.trim(value) == val){
|
343 |
-
result = false;
|
344 |
-
return false;
|
345 |
-
}
|
346 |
-
});
|
347 |
-
}
|
348 |
-
return result;
|
349 |
-
}
|
350 |
-
$('.tagDelete', tagElement1).live('click', function(){ $(this).parent().remove(); });
|
351 |
-
$('.tagDelete', tagElement2).live('click', function(){ $(this).parent().remove(); });
|
352 |
-
inputAdd1.on('click', function(){
|
353 |
-
var val = $.trim(inputUser1.val());
|
354 |
-
if(val.length == 0){
|
355 |
-
alert('Please add a user name or role.');
|
356 |
-
return false;
|
357 |
-
}
|
358 |
-
if( false == isValidEntry($, val, divTarget1)){
|
359 |
-
alert('The user or role has been already added.');
|
360 |
-
return false;
|
361 |
-
}
|
362 |
-
else {
|
363 |
-
var result = _ajax(val);
|
364 |
-
if(result.length > 5){
|
365 |
-
alert('Error: '+result);
|
366 |
-
return false;
|
367 |
-
}
|
368 |
-
else if (parseInt(result) == 0){
|
369 |
-
alert('user or role '+val+' was not found');
|
370 |
-
return false;
|
371 |
-
}
|
372 |
-
createTag($, val, divTarget1);
|
373 |
-
inputUser1.val('');
|
374 |
-
return true;
|
375 |
-
}
|
376 |
-
});
|
377 |
-
inputUser1.keypress(function(event){
|
378 |
-
if (event.keyCode == 10 || event.keyCode == 13) {
|
379 |
-
event.preventDefault();
|
380 |
-
inputAdd1.click();
|
381 |
-
}
|
382 |
-
});
|
383 |
-
inputAdd2.on('click', function(){
|
384 |
-
var val = $.trim(inputUser2.val());
|
385 |
-
if(val.length == 0){
|
386 |
-
alert('Please add a user name or role.');
|
387 |
-
return false;
|
388 |
-
}
|
389 |
-
if( false == isValidEntry($, val, divTarget2)){
|
390 |
-
alert('The user or role has been already added.');
|
391 |
-
return false;
|
392 |
-
}
|
393 |
-
else {
|
394 |
-
var result = _ajax(val);
|
395 |
-
if(result.length > 5){
|
396 |
-
alert('Error: '+result);
|
397 |
-
return false;
|
398 |
-
}
|
399 |
-
else if (parseInt(result) == 0){
|
400 |
-
alert('user or role '+val+' was not found');
|
401 |
-
return false;
|
402 |
-
}
|
403 |
-
createTag($, val, divTarget2);
|
404 |
-
inputUser2.val('');
|
405 |
-
return true;
|
406 |
-
}
|
407 |
-
});
|
408 |
-
inputUser2.keypress(function(event){
|
409 |
-
if (event.keyCode == 10 || event.keyCode == 13) {
|
410 |
-
event.preventDefault();
|
411 |
-
inputAdd2.click();
|
412 |
-
}
|
413 |
-
});
|
414 |
-
});
|
415 |
-
</script>
|
416 |
-
</div>
|
417 |
-
</div>
|
418 |
-
<p style="margin-top: 40px;">
|
419 |
-
<input type="submit" id="submitButton" class="button button-primary" value="<?php echo __('Save settings',WPPH_PLUGIN_TEXT_DOMAIN);?>"/>
|
420 |
-
</p>
|
421 |
-
<input type="hidden" id="deleteEventsBy" name="deleteEventsBy" value=""/>
|
422 |
-
<input type="hidden" id="deleteEventsValue" name="deleteEventsValue" value=""/>
|
423 |
-
<input type="hidden" id="optionDW" name="optionDW" value=""/>
|
424 |
-
<input type="hidden" id="accessListInput" name="accessListInput" value=""/>
|
425 |
-
<input type="hidden" id="changeListInput" name="changeListInput" value=""/>
|
426 |
-
</form>
|
427 |
-
</div>
|
428 |
-
</div>
|
429 |
-
<br class="clear"/>
|
430 |
-
|
431 |
-
<script type="text/javascript">
|
432 |
-
jQuery(document).ready(function($){
|
433 |
-
var showErrorMessage = function(msg){
|
434 |
-
$('#errMessage').removeClass('updated').addClass('error').html("<p>Error: "+msg+"</p>").show();
|
435 |
-
};
|
436 |
-
var setFocusOn = function($e){
|
437 |
-
$e.focus();
|
438 |
-
$e.select();
|
439 |
-
};
|
440 |
-
var validateDeleteOptions = function(section, $daysInput, $eventsNumberInput)
|
441 |
-
{
|
442 |
-
if(section == 0){
|
443 |
-
showErrorMessage("<?php echo __('Invalid form. Please reload the page and try again.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
444 |
-
setFocusOn($daysInput);
|
445 |
-
return false;
|
446 |
-
}
|
447 |
-
// validate fields
|
448 |
-
if(section == 1)
|
449 |
-
{
|
450 |
-
var daysInputVal = $daysInput.val();
|
451 |
-
|
452 |
-
if(daysInputVal.length == 0){
|
453 |
-
showErrorMessage("<?php echo __('Please input the number of days.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
454 |
-
setFocusOn($daysInput);
|
455 |
-
return false;
|
456 |
-
}
|
457 |
-
if(daysInputVal == 0){
|
458 |
-
showErrorMessage("<?php echo __('Please input a number greater than 0.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
459 |
-
setFocusOn($daysInput);
|
460 |
-
return false;
|
461 |
-
}
|
462 |
-
if(!/^\d+$/.test(daysInputVal)){
|
463 |
-
showErrorMessage("<?php echo __('Only numbers greater than 0 allowed.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
464 |
-
setFocusOn($daysInput);
|
465 |
-
return false;
|
466 |
-
}
|
467 |
-
if(daysInputVal > 365){
|
468 |
-
showErrorMessage("<?php echo __('Incorrect number of days. Please specify a value between 1 and 365.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
469 |
-
setFocusOn($daysInput);
|
470 |
-
return false;
|
471 |
-
}
|
472 |
-
}
|
473 |
-
else if(section == 2)
|
474 |
-
{
|
475 |
-
var eniVal = $eventsNumberInput.val();
|
476 |
-
|
477 |
-
if(eniVal.length == 0){
|
478 |
-
showErrorMessage("<?php echo __('Please input the number of alerts.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
479 |
-
setFocusOn($eventsNumberInput);
|
480 |
-
return false;
|
481 |
-
}
|
482 |
-
if(eniVal == 0){
|
483 |
-
showErrorMessage("<?php echo __('Please input a number greater than 0.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
484 |
-
setFocusOn($eventsNumberInput);
|
485 |
-
return false;
|
486 |
-
}
|
487 |
-
if(!/^\d+$/.test(eniVal)){
|
488 |
-
showErrorMessage("<?php echo __('Only numbers greater than 0 allowed.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
489 |
-
setFocusOn($eventsNumberInput);
|
490 |
-
return false;
|
491 |
-
}
|
492 |
-
if(eniVal > <?php echo WPPH_KEEP_MAX_EVENTS;?>){
|
493 |
-
showErrorMessage("<?php echo sprintf(__('Incorrect number of security alerts. Please specify a value between 1 and %d.',WPPH_PLUGIN_TEXT_DOMAIN),WPPH_KEEP_MAX_EVENTS);?>");
|
494 |
-
setFocusOn($eventsNumberInput);
|
495 |
-
return false;
|
496 |
-
}
|
497 |
-
}
|
498 |
-
return true;
|
499 |
-
};
|
500 |
-
|
501 |
-
var deb = $('#deleteEventsBy')
|
502 |
-
,debv = $('#deleteEventsValue')
|
503 |
-
,option1 = $('#option1')
|
504 |
-
,option2 = $('#option2')
|
505 |
-
,daysInput = $('#daysInput')
|
506 |
-
,eventsNumber = $('#eventsNumberInput')
|
507 |
-
,showDW = $('#optionDW_on')
|
508 |
-
,hideDW = $('#optionDW_off')
|
509 |
-
,accessListInput = $('#accessListInput')
|
510 |
-
,changeListInput = $('#changeListInput');
|
511 |
-
option1.on('click', function(){ option2.removeAttr('checked'); $(this).attr('checked','checked'); setFocusOn(daysInput); });
|
512 |
-
option2.on('click', function(){ option1.removeAttr('checked'); $(this).attr('checked','checked'); setFocusOn(eventsNumber); });
|
513 |
-
daysInput.on('click', function(){ option2.removeAttr('checked'); option1.attr('checked','checked'); });
|
514 |
-
eventsNumber.on('click', function(){ option1.removeAttr('checked'); option2.attr('checked','checked'); });
|
515 |
-
showDW.on('click', function(){ hideDW.removeAttr('checked'); $(this).attr('checked','checked'); setFocusOn($(this)); });
|
516 |
-
hideDW.on('click', function(){ showDW.removeAttr('checked'); $(this).attr('checked','checked'); setFocusOn($(this)); });
|
517 |
-
|
518 |
-
// select delete option
|
519 |
-
<?php if($activeOption == 1):?>
|
520 |
-
option1.attr('checked','checked');
|
521 |
-
eventsNumber.val("");
|
522 |
-
<?php else :?>
|
523 |
-
option2.attr('checked','checked');
|
524 |
-
daysInput.val("");
|
525 |
-
<?php endif; ?>
|
526 |
-
|
527 |
-
//select DW
|
528 |
-
<?php if($showDW):?>
|
529 |
-
showDW.attr('checked','checked');
|
530 |
-
<?php else :?>
|
531 |
-
hideDW.attr('checked','checked');
|
532 |
-
<?php endif;?>
|
533 |
-
|
534 |
-
// form submit
|
535 |
-
$('#submitButton').on('click',function()
|
536 |
-
{
|
537 |
-
var section = 0;
|
538 |
-
if ($('#option1').prop('checked')){section = 1;}
|
539 |
-
else { section = 2; }
|
540 |
-
|
541 |
-
if(section < 1){
|
542 |
-
alert("<?php echo __('Invalid form. Please refresh the page and try again.',WPPH_PLUGIN_TEXT_DOMAIN);?>");
|
543 |
-
return false;
|
544 |
-
}
|
545 |
-
if(! validateDeleteOptions(section, daysInput, eventsNumber)){
|
546 |
-
return false;
|
547 |
-
}
|
548 |
-
// alerts pruning
|
549 |
-
if(section == 1){
|
550 |
-
deb.val(1);
|
551 |
-
debv.val(daysInput.val());
|
552 |
-
}
|
553 |
-
else if(section ==2){
|
554 |
-
deb.val(2);
|
555 |
-
debv.val(eventsNumber.val());
|
556 |
-
}
|
557 |
-
// dashboard widget
|
558 |
-
if(showDW.prop('checked')){
|
559 |
-
$('#optionDW').val('1');
|
560 |
-
}
|
561 |
-
else { $('#optionDW').val('0') }
|
562 |
-
|
563 |
-
//#! build the access list
|
564 |
-
var a = [];
|
565 |
-
$('.tagName', $('#a-list')).each(function(){a.push($(this).text());});
|
566 |
-
accessListInput.val(JSON.stringify(a));
|
567 |
-
|
568 |
-
// build the change list
|
569 |
-
var b = [];
|
570 |
-
$('.tagName', $('#c-list')).each(function(){b.push($(this).text());});
|
571 |
-
changeListInput.val(JSON.stringify(b));
|
572 |
-
|
573 |
-
return true;
|
574 |
-
});
|
575 |
-
});
|
576 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/support.php
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
<?php if(! WPPHUtil::canViewPage()){ return; } ?><?php
|
2 |
-
if(! WPPH::ready())
|
3 |
-
{
|
4 |
-
$errors = WPPH::getPluginErrors();
|
5 |
-
foreach($errors as $error) {
|
6 |
-
wpph_adminNotice($error);
|
7 |
-
}
|
8 |
-
echo '<div id="wpph-pageWrapper" class="wrap">';
|
9 |
-
echo '<p>'.__('We have encountered some errors during the installation of the plugin which you can find above.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
10 |
-
echo '<p>'.__('Please try to correct them and then reactivate the plugin.',WPPH_PLUGIN_TEXT_DOMAIN).'</p>';
|
11 |
-
echo '</div>';
|
12 |
-
return;
|
13 |
-
}
|
14 |
-
?>
|
15 |
-
<div id="wpph-pageWrapper" class="wrap">
|
16 |
-
<h2 class="pageTitle pageTitle-support"><?php echo __('Support',WPPH_PLUGIN_TEXT_DOMAIN);?></h2>
|
17 |
-
<div>
|
18 |
-
<p><?php echo
|
19 |
-
sprintf(__('Thank you for showing interest and using our plugin. If you encounter any issues running this plugin, or have suggestions or queries, please get in touch with us on %s.',WPPH_PLUGIN_TEXT_DOMAIN),
|
20 |
-
'<a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>');?></p>
|
21 |
-
</div>
|
22 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -1,57 +1,65 @@
|
|
1 |
=== WP Security Audit Log ===
|
2 |
-
Contributors: WPWhiteSecurity
|
3 |
License: GPLv3
|
4 |
License URI: http://www.gnu.org/licenses/gpl.html
|
5 |
-
Tags: wordpress security plugin, wordpress security audit log, audit 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,
|
6 |
-
Requires at least: 3.
|
7 |
Tested up to: 3.9.1
|
8 |
-
Stable tag: 0.
|
9 |
|
10 |
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.
|
11 |
|
12 |
== Description ==
|
13 |
-
Identify WordPress security issues before they become a security problem by keeping a security audit log of what is happening under the hood of your WordPress blog or website or your WordPress Multisite installation. WP Security Audit Log plugin is developed by WordPress Security Consultants and Professionals [WP White Security](http://www.wpwhitesecurity.com/wordpress-security-services/) and works on both WordPress and [WordPress Multisite](http://www.wpwhitesecurity.com/wordpress-plugins/wp-security-audit-log-plugin-features-wordpress-multisite/).
|
14 |
|
15 |
= Keep A WordPress Security Audit Log & Identify WordPress Security Issues =
|
16 |
WP Security Audit Log keeps a log of everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A security alert is generated by the plugin when:
|
17 |
|
18 |
-
* New user is created via registration or
|
19 |
-
*
|
20 |
-
*
|
21 |
* User uploads or deletes a file, changes a password or email address
|
22 |
* User installs, activates, deactivates, upgrades or uninstalls a plugin
|
23 |
* User creates a new post, page, category or a custom post type
|
24 |
* User modifies an existing post, page, category or a custom post type
|
25 |
-
* User adds, modifies or deletes a widget
|
26 |
-
*
|
|
|
|
|
27 |
* Failed login attempts
|
28 |
* and much more...
|
29 |
|
30 |
-
Refer to the complete list of [WordPress Security Audit Alerts](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-alerts-logs/) for more information.
|
31 |
|
32 |
= Monitor WordPress Users Activity & Productivity =
|
33 |
-
If you own a multi user WordPress blog or website, or a WordPress multisite network installation you can use
|
34 |
|
35 |
-
* When WordPress users
|
36 |
* From where WordPress users are logging in
|
37 |
-
* Users who created or deleted categories
|
38 |
-
* Users who created a blog post or a
|
39 |
-
* Users who published a blog post or a
|
40 |
-
* Users who modified published WordPress content such as
|
|
|
41 |
* Users who modify WordPress widgets
|
42 |
-
* Uses who upload or delete files
|
43 |
* and much more...
|
44 |
|
45 |
-
Refer to the complete list of [WordPress Security Audit Alerts](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-alerts-logs/) for more information.
|
46 |
|
47 |
= WP Security Audit Log for WordPress Multisite =
|
48 |
-
WP Security Audit Log is the first
|
49 |
|
50 |
-
For more information about
|
51 |
|
52 |
= WordPress Security Audit Log in your Language! =
|
53 |
We need help translating the plugin and the WordPress Security Events. If you're good at translating, please drop us an email on plugins@wpwhitesecurity.com.
|
54 |
|
|
|
|
|
|
|
|
|
|
|
55 |
= WordPress Security Tips & Tricks =
|
56 |
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.
|
57 |
|
@@ -82,10 +90,10 @@ Yes. A complete list can be found [here](http://www.wpwhitesecurity.com/wordpres
|
|
82 |
|
83 |
= Can I disable some WordPress security alerts? =
|
84 |
|
85 |
-
Yes it is possible to disable (and re-enable
|
86 |
|
87 |
= Can WP Security Audit Log plugin work and monitor activity on WodPress Multisite? =
|
88 |
-
Yes, WP Security Audit Log works on WordPress Multisite
|
89 |
|
90 |
== Screenshots ==
|
91 |
|
@@ -96,6 +104,39 @@ Yes, WP Security Audit Log works on WordPress Multisite networkds. For more info
|
|
96 |
|
97 |
== Changelog ==
|
98 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
= 0.6.3 (2014-02-18) =
|
100 |
* Bug Fix
|
101 |
* Disabled debugging by default (left enabled by mistake)
|
@@ -111,7 +152,7 @@ Yes, WP Security Audit Log works on WordPress Multisite networkds. For more info
|
|
111 |
|
112 |
= 0.6 (2014-01-15) =
|
113 |
* New Plugin Feature
|
114 |
-
|
115 |
|
116 |
* New WordPress Security Alerts for monitoring specific multisite activity on a WordPress multisite network installation
|
117 |
* Alert 4008: User is granted super admin privileges (network)
|
1 |
=== WP Security Audit Log ===
|
2 |
+
Contributors: WPWhiteSecurity, uuf6429
|
3 |
License: GPLv3
|
4 |
License URI: http://www.gnu.org/licenses/gpl.html
|
5 |
+
Tags: wordpress security plugin, wordpress security audit log, audit 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
|
6 |
+
Requires at least: 3.6
|
7 |
Tested up to: 3.9.1
|
8 |
+
Stable tag: 1.0.0
|
9 |
|
10 |
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.
|
11 |
|
12 |
== Description ==
|
13 |
+
Identify WordPress security issues before they become a security problem by keeping a security audit log of what is happening under the hood of your WordPress blog or website or your WordPress Multisite installation. WP Security Audit Log plugin is developed by WordPress Security Consultants and Professionals [WP White Security](http://www.wpwhitesecurity.com/wordpress-security-services/) and is the only WordPress monitoring and auditing plugin that works on both WordPress single site installations and [WordPress Multisite](http://www.wpwhitesecurity.com/wordpress-plugins/wp-security-audit-log-plugin-features-wordpress-multisite/).
|
14 |
|
15 |
= Keep A WordPress Security Audit Log & Identify WordPress Security Issues =
|
16 |
WP Security Audit Log keeps a log of everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A security alert is generated by the plugin when:
|
17 |
|
18 |
+
* New user is created via registration or by another user
|
19 |
+
* User changes the role, password or other profile settings of another user
|
20 |
+
* User on a WordPress multisite network is added or removed from a site
|
21 |
* User uploads or deletes a file, changes a password or email address
|
22 |
* User installs, activates, deactivates, upgrades or uninstalls a plugin
|
23 |
* User creates a new post, page, category or a custom post type
|
24 |
* User modifies an existing post, page, category or a custom post type
|
25 |
+
* User adds, moves, modifies or deletes a widget
|
26 |
+
* User installs or activates a new WordPress theme
|
27 |
+
* User changes WordPress settings such as permalinks or administrator notification email
|
28 |
+
* WordPress is updated / upgraded
|
29 |
* Failed login attempts
|
30 |
* and much more...
|
31 |
|
32 |
+
Refer to the complete list of [WordPress Security Audit Alerts](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-alerts-logs/) for more information on what WordPress activity can be monitored with WP Security Audit Log.
|
33 |
|
34 |
= Monitor WordPress Users Activity & Productivity =
|
35 |
+
If you own a multi user WordPress blog or website, or a WordPress multisite network installation you can use WP Security Audit Log plugin to monitor your users' activity and productivity. With WP Security Audit Log WordPress plugin you can monitor:
|
36 |
|
37 |
+
* When WordPress users log in or out
|
38 |
* From where WordPress users are logging in
|
39 |
+
* Users who created. modified or deleted categories
|
40 |
+
* Users who created a blog post, page or a custom post
|
41 |
+
* Users who published a blog post, page or a custom post
|
42 |
+
* Users who modified published WordPress content such as custom posts, pages or a blog posts
|
43 |
+
* Users who moves content such as blog posts or WordPress pages to trash or permanently deletes it
|
44 |
* Users who modify WordPress widgets
|
45 |
+
* Uses who upload or delete any sort of files
|
46 |
* and much more...
|
47 |
|
48 |
+
Refer to the complete list of [WordPress Security Audit Alerts](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-alerts-logs/) for more information on what other WordPress user activity can be monitored with the WP Security Audit Log WordPress plugin.
|
49 |
|
50 |
= WP Security Audit Log for WordPress Multisite =
|
51 |
+
WP Security Audit Log is the first tracking and audit WordPress security monitoring plugin that supports WordPress multisite network installations and can monitor activity on such WordPress multisite network installations.
|
52 |
|
53 |
+
For more information about the features for WordPress Multisite network installation refer to [WP Security Audit Log Features for WordPress Multisite](http://www.wpwhitesecurity.com/wordpress-plugins/wp-security-audit-log-plugin-features-wordpress-multisite/)
|
54 |
|
55 |
= WordPress Security Audit Log in your Language! =
|
56 |
We need help translating the plugin and the WordPress Security Events. If you're good at translating, please drop us an email on plugins@wpwhitesecurity.com.
|
57 |
|
58 |
+
= WordPress & PHP Errors Monitoring Tools =
|
59 |
+
Plugins and themes customizations are most probably the norm of the day on large WordPress websites, not to mention the installation of new plugins and components. Unforunately sometimes such changes create problems and it is not always easy and possible to setup real live scenarios and replicate specific problems or bugs.
|
60 |
+
|
61 |
+
With WP Security Audit Log now it is easier than ever before to monitor your plugins', theme's and other code behaviour, it will generate a alert when a PHP error, warning, exception or shutdown is detected. It is also possible to log all HTTP GET and POST requests that are reaching your WordPress installation to a log file with WP Security Audit Log. Simply enable the PHP Errors monitoring or logging from the plugins settings.
|
62 |
+
|
63 |
= WordPress Security Tips & Tricks =
|
64 |
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.
|
65 |
|
90 |
|
91 |
= Can I disable some WordPress security alerts? =
|
92 |
|
93 |
+
Yes it is possible to disable (and re-enable) specific WordPress security alerts. To do so navigate to the "Enable/Disable Alerts" node in the plugin's menu, select the category tab and untick the WordPress security alert. Tick back the alert to re-enable it.
|
94 |
|
95 |
= Can WP Security Audit Log plugin work and monitor activity on WodPress Multisite? =
|
96 |
+
Yes, WP Security Audit Log works on WordPress Multisite networks, i.e. it can monitor user and under the hood WordPress activity on WordPress multisite installations. For more information refer to the post [WP Security Audit Log Features for WordPress Multisite installation](http://www.wpwhitesecurity.com/wordpress-plugins/wp-security-audit-log-plugin-features-wordpress-multisite/).
|
97 |
|
98 |
== Screenshots ==
|
99 |
|
104 |
|
105 |
== Changelog ==
|
106 |
|
107 |
+
= 1.0 (2014-05-20) =
|
108 |
+
* Complete plugin rewrite making the new version more stable and scalable
|
109 |
+
|
110 |
+
* New Features
|
111 |
+
* New Audit Log viewer
|
112 |
+
* Auto refresh of security alerts - WordPress administrators do not need to refresh the Audit Log Viewer page to see new alerts
|
113 |
+
* Data Inspector reports more insider information about each alert (can be enabled from settings)
|
114 |
+
* Sandbox allows developers to execute PHP code for troubleshooting (can be enabled from settings)
|
115 |
+
* Request Log that logs all HTTP GET and POST requests done on WordPress (can be enabled from settings)
|
116 |
+
* Logging of PHP Errors; ideal for developers who want to monitor WordPress for any errors (can be enabled from settings)
|
117 |
+
* New Support and About Us page that you should check out!
|
118 |
+
|
119 |
+
* New WordPress Security Alerts for monitoring themes, WordPress settings, files and much more...
|
120 |
+
* Alert 2046: User modified a file using the editor
|
121 |
+
* Alert 2047: User changed parent of page
|
122 |
+
* Alert 2048: User changed template of page
|
123 |
+
* Alert 2049: User set post as sticky
|
124 |
+
* Alert 2050: User removed post from Sticky
|
125 |
+
* Alert 5005: User installed a new theme
|
126 |
+
* Alert 5006: User activated a theme
|
127 |
+
* Alert 6004: User upgraded WordPress
|
128 |
+
* Alert 6005: User changed the WordPress permalinks
|
129 |
+
|
130 |
+
* New WordPress Developer Alerts
|
131 |
+
* Alert 0000: Unknown error
|
132 |
+
* Alert 0001: PHP Error
|
133 |
+
* Alert 0002: PHP Warning
|
134 |
+
* Alert 0003: PHP Notice
|
135 |
+
* Alert 0004: PHP Exception
|
136 |
+
* Alert 0005: PHP Shutdown Error
|
137 |
+
|
138 |
+
* For more information about what is new and changed in this version of the plugin refer to the [WP Security Audit Log release notes](http://www.wpwhitesecurity.com/wordpress-plugins/easy-wordpress-security-monitor-wp-security-audit-log-plugin).
|
139 |
+
|
140 |
= 0.6.3 (2014-02-18) =
|
141 |
* Bug Fix
|
142 |
* Disabled debugging by default (left enabled by mistake)
|
152 |
|
153 |
= 0.6 (2014-01-15) =
|
154 |
* New Plugin Feature
|
155 |
+
* WordPress Multisite Support [Read More](http://www.wpwhitesecurity.com/wordpress-plugins/wp-security-audit-log-plugin-features-wordpress-multisite/)
|
156 |
|
157 |
* New WordPress Security Alerts for monitoring specific multisite activity on a WordPress multisite network installation
|
158 |
* Alert 4008: User is granted super admin privileges (network)
|
res/css/styles.base.css
DELETED
@@ -1,122 +0,0 @@
|
|
1 |
-
#wpph-pageWrapper{ padding: 0 0; clear: both; }
|
2 |
-
|
3 |
-
h2.pageTitle { padding-left: 40px; }
|
4 |
-
h2.pageTitle-eventViewer { background: url("../img/page-viewer-logo.png") no-repeat left center; }
|
5 |
-
h2.pageTitle-settings { background: url("../img/page-settings-logo.png") no-repeat left center; }
|
6 |
-
h2.pageTitle-support { background: url("../img/page-support-logo.png") no-repeat left center; }
|
7 |
-
h2.pageTitle-about { background: url("../img/page-about-logo.png") no-repeat left center; }
|
8 |
-
|
9 |
-
#wpph-pageWrapper .button { margin-top: 1px;}
|
10 |
-
#wpph-pageWrapper .buttonRefreshEventsList { margin-top: 3px;}
|
11 |
-
|
12 |
-
.wpph-text-disabled { color: #c0c0c0 !important; }
|
13 |
-
|
14 |
-
|
15 |
-
/*
|
16 |
-
* Page: Event Viewer
|
17 |
-
*/
|
18 |
-
.column-left-align { text-align: left; }
|
19 |
-
.column-center-align { text-align: center; }
|
20 |
-
|
21 |
-
#the-list .row-0 { background-color: #FCFCFC; }
|
22 |
-
.widefat tbody th.check-column { padding: 8px 0 0 0 !important; }
|
23 |
-
.widefat .check-column { padding: 6px 0 0 0; }
|
24 |
-
|
25 |
-
#the-list th, #the-list tr, #the-list td { padding: 0 0 0 0 !important; line-height: normal !important;}
|
26 |
-
#the-list span { padding: 5px 5px; line-height: normal !important; display: block; }
|
27 |
-
|
28 |
-
/*
|
29 |
-
* Page: Settings, Alerts
|
30 |
-
*/
|
31 |
-
.error-info-icon {
|
32 |
-
padding: 5px 7px 5px 20px;
|
33 |
-
margin-left: 8px;
|
34 |
-
color: #ff0000;
|
35 |
-
background: url("../img/error-icon.png") no-repeat left center;
|
36 |
-
}
|
37 |
-
.success-info-icon {
|
38 |
-
padding: 5px 7px 5px 20px !important;
|
39 |
-
margin-left: 8px;
|
40 |
-
color: #000000;
|
41 |
-
background: url("../img/success-icon.png") no-repeat left center;
|
42 |
-
}
|
43 |
-
|
44 |
-
#section-holder { overflow: hidden; }
|
45 |
-
#section-holder p { margin: 15px 0; overflow: hidden; }
|
46 |
-
#section-holder p input[type="radio"] { float: left; margin-top: 5px !important; }
|
47 |
-
#section-holder p label, #section-holder p span { float: left; margin-top: 4px !important; margin-left: 10px !important; font-size: 12px !important; }
|
48 |
-
#section-holder p input[type="text"] { float: left; margin-left: 10px !important; }
|
49 |
-
|
50 |
-
.form-table, .form-table td { border: none 0;}
|
51 |
-
.form-table td { line-height: normal !important; }
|
52 |
-
.form-table td.section-left { width: 190px; padding: 0 0; }
|
53 |
-
.form-table td.section-right { padding: 0 0 20px 0 !important; margin: 0 0 !important; }
|
54 |
-
.form-table td.section-right p { padding: 0 0 !important; margin: 0 0 !important; }
|
55 |
-
.form-table td.section-left label { font-weight: bold; }
|
56 |
-
|
57 |
-
#errMessage { margin: 20px 0; }
|
58 |
-
#eventsDeletion #description,
|
59 |
-
#optionsDescription #description {
|
60 |
-
background: none repeat scroll 0 0 #EEEEEE;
|
61 |
-
margin: 0 0 20px 0;
|
62 |
-
padding: 10px;
|
63 |
-
}
|
64 |
-
#optionsDescription #description { margin: 20px 0; }
|
65 |
-
|
66 |
-
.widefat .item-cb_h { width: 50px !important; }
|
67 |
-
.widefat .item-event { width: 100px !important; text-align: left; padding: 8px 7px 2px 7px !important; }
|
68 |
-
.widefat .item-type { min-width: 100px !important; text-align: left; padding: 8px 7px 2px 7px !important; }
|
69 |
-
.widefat .item-description { width: auto !important; text-align: left; padding: 8px 7px 2px 7px !important; }
|
70 |
-
.widefat tbody th.check-column { padding: 11px 0 0 3px !important; }
|
71 |
-
/*
|
72 |
-
* Page: Events :: pagination
|
73 |
-
*/
|
74 |
-
.paginationWrapper{
|
75 |
-
overflow: hidden;
|
76 |
-
float: right;
|
77 |
-
display: block;
|
78 |
-
margin-right: 0;
|
79 |
-
}
|
80 |
-
.paginationWrapper .showPages {
|
81 |
-
float: left;
|
82 |
-
display: block;
|
83 |
-
margin-top:10px;
|
84 |
-
margin-right: 7px;
|
85 |
-
}
|
86 |
-
.paginationWrapper .showPages .span1,
|
87 |
-
.paginationWrapper .showPages .span2,
|
88 |
-
.paginationWrapper .showPages .span3 { font-weight: 800; }
|
89 |
-
|
90 |
-
.paginationWrapper .pageButton {
|
91 |
-
color: #B8B8B8;
|
92 |
-
background-color: transparent;
|
93 |
-
background-image: -moz-linear-gradient(center top , #F5F5F5, #F1F1F1);
|
94 |
-
border: 1px solid rgba(0, 0, 0, 0.1);
|
95 |
-
cursor: default;
|
96 |
-
outline: 0;
|
97 |
-
text-align: center;
|
98 |
-
white-space: nowrap;
|
99 |
-
display: inline-block;
|
100 |
-
padding: 0 0;
|
101 |
-
margin: 0 0;
|
102 |
-
}
|
103 |
-
.pageButton span{
|
104 |
-
display: block;
|
105 |
-
font-family: Verdana, "Arial Unicode MS", Arial;
|
106 |
-
font-weight: 800;
|
107 |
-
font-size: 18px;
|
108 |
-
color: #000;
|
109 |
-
margin-right: 0;
|
110 |
-
margin-top: -1px;
|
111 |
-
padding: 2px 7px 4px;
|
112 |
-
}
|
113 |
-
.paginationWrapper .buttonsWrapper{
|
114 |
-
overflow: hidden;
|
115 |
-
float: right;
|
116 |
-
display: block;
|
117 |
-
width: 70px;
|
118 |
-
}
|
119 |
-
.buttonsWrapper .buttonPrevious,
|
120 |
-
.buttonsWrapper .buttonNext {float: right;}
|
121 |
-
.wpphButtonDisabled { background: #ccc !important; }
|
122 |
-
.wpphButtonDisabled span { color: #808080 !important; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res/img/ajax-loader.gif
DELETED
Binary file
|
res/img/error-icon.png
DELETED
Binary file
|
res/img/page-about-logo.png
DELETED
Binary file
|
res/img/page-settings-logo.png
DELETED
Binary file
|
res/img/page-support-logo.png
DELETED
Binary file
|
res/img/page-viewer-logo.png
DELETED
Binary file
|
res/img/success-icon.png
DELETED
Binary file
|
res/js/audit-view-model.js
DELETED
@@ -1,314 +0,0 @@
|
|
1 |
-
var AuditLogViewModel = (function($, ko) {
|
2 |
-
"use strict";
|
3 |
-
/*global AjaxLoaderShow, AjaxLoaderHide, ajaxurl, __ajaxLoaderTargetElement__*/
|
4 |
-
/*jshint curly:false,devel:true*/
|
5 |
-
|
6 |
-
var error = ko.observable('');
|
7 |
-
var loading = ko.observable(false);
|
8 |
-
var events = ko.observableArray([]);
|
9 |
-
var totalEventsCount = ko.observable(0);
|
10 |
-
var offset = ko.observable(0);
|
11 |
-
var availablePageSize = ko.observableArray([25, 50, 100]);
|
12 |
-
var isMainSite = ko.observable(false);
|
13 |
-
var _blogId = ko.observable();
|
14 |
-
var blogId = ko.computed({
|
15 |
-
read: function() {
|
16 |
-
var parsedValue = parseInt(_blogId(), 10);
|
17 |
-
return isNaN(parsedValue) ? undefined : parsedValue;
|
18 |
-
},
|
19 |
-
write: function(newValue) {
|
20 |
-
newValue = parseInt(newValue, 10);
|
21 |
-
if (isNaN(newValue)) newValue = undefined;
|
22 |
-
if (_blogId() !== newValue) {
|
23 |
-
// console.warn('blogId changed from %o to %o', _blogId(), newValue);
|
24 |
-
var refresh = false;
|
25 |
-
if (_blogId() !== undefined) {
|
26 |
-
refresh = true;
|
27 |
-
}
|
28 |
-
_blogId(newValue);
|
29 |
-
if (refresh) {
|
30 |
-
refreshEvents(0, newValue);
|
31 |
-
}
|
32 |
-
}
|
33 |
-
}
|
34 |
-
});
|
35 |
-
var blogList = ko.observableArray();
|
36 |
-
|
37 |
-
var columns = ko.observableArray([
|
38 |
-
{columnHeader: 'Event', columnName: 'EventNumber', sortable: true, columnWidth: '5%', sorted: ko.observable(false), sortedDescending: ko.observable(false), visible: true },
|
39 |
-
{columnHeader: 'ID', columnName: 'EventID', sortable: true, columnWidth: '5%', sorted: ko.observable(false), sortedDescending: ko.observable(false), visible: true},
|
40 |
-
{columnHeader: 'Date', columnName: 'EventDate', sortable: true, columnWidth: '11%', sorted: ko.observable(false), sortedDescending: ko.observable(false), visible: true},
|
41 |
-
{columnHeader: 'Type', columnName: 'EventType', sortable: true, columnWidth: '6%', sorted: ko.observable(false), sortedDescending: ko.observable(false), visible: true},
|
42 |
-
{columnHeader: 'IP Address', columnName: 'UserIP', sortable: true, columnWidth: '9%', sorted: ko.observable(false), sortedDescending: ko.observable(false), visible: true},
|
43 |
-
{columnHeader: 'User', columnName: 'UserID', sortable: true, columnWidth: '10%', sorted: ko.observable(false), sortedDescending: ko.observable(false), visible: true},
|
44 |
-
{columnHeader: 'Site', columnName: 'SiteName', sortable: true, columnWidth: '10%', sorted: ko.observable(true), sortedDescending: ko.observable(false), visible: ko.computed(function() {
|
45 |
-
return blogId() === 0;
|
46 |
-
})},
|
47 |
-
{columnHeader: 'Description', columnName: 'EventDescription', sortable: false, columnWidth: 'auto', sorted: ko.observable(false), sortedDescending: ko.observable(false), visible: true}
|
48 |
-
]);
|
49 |
-
|
50 |
-
|
51 |
-
var _initialPageSize = parseInt($.cookie('wpph_ck_page_size'), 10);
|
52 |
-
if (availablePageSize.indexOf(_initialPageSize) < 0) {
|
53 |
-
_initialPageSize = availablePageSize()[1];
|
54 |
-
}
|
55 |
-
|
56 |
-
var pageSize = ko.observable(_initialPageSize);
|
57 |
-
var selectedPageSize = ko.observable(_initialPageSize);
|
58 |
-
var pageCount = ko.computed(function() {
|
59 |
-
return Math.ceil(totalEventsCount() / pageSize());
|
60 |
-
});
|
61 |
-
|
62 |
-
var _currentPageIndex = 1;
|
63 |
-
var currentPage = ko.computed({
|
64 |
-
read: function() {
|
65 |
-
return _currentPageIndex;
|
66 |
-
},
|
67 |
-
write: function(value) {
|
68 |
-
value = parseInt(value, 10);
|
69 |
-
if (isNaN(value) || value < 1 || value > pageCount()) {
|
70 |
-
return;
|
71 |
-
}
|
72 |
-
_currentPageIndex = value;
|
73 |
-
currentPage.notifySubscribers();
|
74 |
-
$('#fdr').val(_currentPageIndex);
|
75 |
-
}
|
76 |
-
});
|
77 |
-
|
78 |
-
var orderBy = ko.computed({
|
79 |
-
read: function() {
|
80 |
-
var columnInfo = ko.utils.arrayFirst(columns(), function(item) { return item.sorted(); });
|
81 |
-
return columnInfo && columnInfo.columnName || '';
|
82 |
-
},
|
83 |
-
write: function(value) {
|
84 |
-
var columnInfo = ko.utils.arrayFirst(columns(), function(item) {
|
85 |
-
return item.columnName === value;
|
86 |
-
});
|
87 |
-
if (columnInfo) {
|
88 |
-
ko.utils.arrayForEach(columns(), function(item) {
|
89 |
-
item.sorted(false);
|
90 |
-
item.sortedDescending(false);
|
91 |
-
});
|
92 |
-
columnInfo.sorted(value);
|
93 |
-
}
|
94 |
-
}
|
95 |
-
});
|
96 |
-
var orderByDescending = ko.computed({
|
97 |
-
read: function() {
|
98 |
-
var columnInfo = ko.utils.arrayFirst(columns(), function(item) { return item.sorted(); });
|
99 |
-
return !!(columnInfo && columnInfo.sortedDescending());
|
100 |
-
},
|
101 |
-
write: function(value) {
|
102 |
-
var columnInfo = ko.utils.arrayFirst(columns(), function(item) { return item.sorted(); });
|
103 |
-
if (columnInfo) columnInfo.sortedDescending(value);
|
104 |
-
}
|
105 |
-
});
|
106 |
-
|
107 |
-
|
108 |
-
function loadRemoteData(newOffset, bid) {
|
109 |
-
newOffset = newOffset || 0;
|
110 |
-
|
111 |
-
var _blogId = null;
|
112 |
-
|
113 |
-
if(bid !== null){
|
114 |
-
_blogId = bid;
|
115 |
-
}
|
116 |
-
else {
|
117 |
-
_blogId = parseInt(blogId(), 10);
|
118 |
-
if (isNaN(_blogId)) _blogId = undefined;
|
119 |
-
}
|
120 |
-
|
121 |
-
var data = {
|
122 |
-
action: 'wpph_get_events',
|
123 |
-
orderBy: orderBy(),
|
124 |
-
sort: orderByDescending() ? 'desc' : 'asc',
|
125 |
-
offset: newOffset,
|
126 |
-
count: pageSize(),
|
127 |
-
blogID: _blogId
|
128 |
-
};
|
129 |
-
|
130 |
-
// busy property possible?
|
131 |
-
AjaxLoaderShow(__ajaxLoaderTargetElement__);
|
132 |
-
loading(true);
|
133 |
-
|
134 |
-
$.ajax({ url: ajaxurl, cache: false, type: 'POST', data: data, dataType: 'json' })
|
135 |
-
.then(function (response) {
|
136 |
-
if (response.dataSource.blogs) {
|
137 |
-
blogList.removeAll();
|
138 |
-
ko.utils.arrayPushAll(blogList(), response.dataSource.blogs);
|
139 |
-
}
|
140 |
-
|
141 |
-
if (response.error.length > 0) {
|
142 |
-
error(response.error);
|
143 |
-
events.removeAll();
|
144 |
-
totalEventsCount(0);
|
145 |
-
offset(0);
|
146 |
-
$('#wpph_ew').attr('colspan', _blogId===undefined ? 8 : 7);
|
147 |
-
return;
|
148 |
-
}
|
149 |
-
events(response.dataSource.events);
|
150 |
-
totalEventsCount(response.dataSource.eventsCount);
|
151 |
-
offset(newOffset);
|
152 |
-
|
153 |
-
if (response.dataSource.blogID) {
|
154 |
-
blogId(response.dataSource.blogID);
|
155 |
-
}
|
156 |
-
|
157 |
-
if (totalEventsCount() < offset()) {
|
158 |
-
offset(0);
|
159 |
-
}
|
160 |
-
|
161 |
-
if (offset() === 0) {
|
162 |
-
currentPage(1);
|
163 |
-
}
|
164 |
-
else { currentPage(1 + offset() / pageSize()); }
|
165 |
-
})
|
166 |
-
.fail(function () {
|
167 |
-
//Report data loading error
|
168 |
-
error("An error occurred while loading data. Please try again in a few moments.");
|
169 |
-
events.removeAll();
|
170 |
-
totalEventsCount(0);
|
171 |
-
offset(0);
|
172 |
-
})
|
173 |
-
.always(function () {
|
174 |
-
loading(false);
|
175 |
-
AjaxLoaderHide(__ajaxLoaderTargetElement__);
|
176 |
-
});
|
177 |
-
}
|
178 |
-
|
179 |
-
function onCurrentPageInputKeyDown(viewModel, event) {
|
180 |
-
if (event.keyCode === 13) {
|
181 |
-
var value = parseInt(event.currentTarget.value, 10);
|
182 |
-
if (isNaN(value) || value < 1 || value > pageCount()) {
|
183 |
-
currentPage(_currentPageIndex);
|
184 |
-
currentPage.notifySubscribers();
|
185 |
-
return;
|
186 |
-
}
|
187 |
-
currentPage(value);
|
188 |
-
refreshEvents((_currentPageIndex - 1) * pageSize());
|
189 |
-
return false;
|
190 |
-
}
|
191 |
-
return true;
|
192 |
-
}
|
193 |
-
|
194 |
-
function onRefreshEvents() {
|
195 |
-
refreshEvents(0, blogId());
|
196 |
-
}
|
197 |
-
|
198 |
-
function onApplyPageSize() {
|
199 |
-
applyPageSize();
|
200 |
-
}
|
201 |
-
|
202 |
-
function onApplySorting(columnItem) {
|
203 |
-
applySorting(columnItem);
|
204 |
-
}
|
205 |
-
|
206 |
-
|
207 |
-
function applyPageSize(){
|
208 |
-
var newPageSize = parseInt(selectedPageSize(), 10);
|
209 |
-
pageSize(newPageSize);
|
210 |
-
var secureCookie = false;
|
211 |
-
if (window.location.href.indexOf('https://') > -1) {
|
212 |
-
secureCookie = true;
|
213 |
-
}
|
214 |
-
$.cookie('wpph_ck_page_size', newPageSize, {secure: secureCookie});
|
215 |
-
refreshEvents(0);
|
216 |
-
}
|
217 |
-
|
218 |
-
function applySorting(columnInfo) {
|
219 |
-
if (orderBy() === columnInfo.columnName) {
|
220 |
-
orderByDescending(! orderByDescending());
|
221 |
-
}
|
222 |
-
else {
|
223 |
-
orderBy(columnInfo.columnName);
|
224 |
-
orderByDescending(false);
|
225 |
-
}
|
226 |
-
refreshEvents(0);
|
227 |
-
}
|
228 |
-
|
229 |
-
|
230 |
-
function nextPage() {
|
231 |
-
var currentOffset = offset();
|
232 |
-
var newOffset = currentOffset + pageSize();
|
233 |
-
|
234 |
-
if (newOffset < totalEventsCount()) {
|
235 |
-
refreshEvents(newOffset);
|
236 |
-
}
|
237 |
-
}
|
238 |
-
|
239 |
-
function prevPage() {
|
240 |
-
var currentOffset = offset();
|
241 |
-
var newOffset = currentOffset - pageSize();
|
242 |
-
|
243 |
-
if (newOffset >= 0) {
|
244 |
-
refreshEvents(newOffset);
|
245 |
-
}
|
246 |
-
}
|
247 |
-
|
248 |
-
function firstPage() {
|
249 |
-
if (offset() > 0)
|
250 |
-
refreshEvents(0);
|
251 |
-
}
|
252 |
-
|
253 |
-
function lastPage() {
|
254 |
-
var offset = Math.min(
|
255 |
-
totalEventsCount(),
|
256 |
-
pageSize() * (pageCount() - 1)
|
257 |
-
);
|
258 |
-
if (offset() !== offset)
|
259 |
-
refreshEvents(offset);
|
260 |
-
}
|
261 |
-
|
262 |
-
|
263 |
-
function refreshEvents(offset, bid) {
|
264 |
-
if (loading()) {
|
265 |
-
console.warn('Cannot refresh events. Still busy!!!');
|
266 |
-
return;
|
267 |
-
}
|
268 |
-
// console.warn('refreshEvents: %d', offset);
|
269 |
-
if(bid !== null){
|
270 |
-
loadRemoteData(offset, bid);
|
271 |
-
}
|
272 |
-
else { loadRemoteData(offset); }
|
273 |
-
}
|
274 |
-
|
275 |
-
|
276 |
-
return {
|
277 |
-
columns: columns,
|
278 |
-
error: error,
|
279 |
-
loading: loading,
|
280 |
-
events: events,
|
281 |
-
totalEventsCount: totalEventsCount,
|
282 |
-
offset: offset,
|
283 |
-
availablePageSize: availablePageSize,
|
284 |
-
|
285 |
-
isMainSite: isMainSite,
|
286 |
-
blogId: blogId,
|
287 |
-
blogList: blogList,
|
288 |
-
|
289 |
-
pageSize: pageSize,
|
290 |
-
selectedPageSize: selectedPageSize,
|
291 |
-
pageCount: pageCount,
|
292 |
-
|
293 |
-
|
294 |
-
currentPage: currentPage,
|
295 |
-
orderBy: orderBy,
|
296 |
-
orderByDescending: orderByDescending,
|
297 |
-
|
298 |
-
onCurrentPageInputKeyDown: onCurrentPageInputKeyDown,
|
299 |
-
onRefreshEvents: onRefreshEvents,
|
300 |
-
onApplyPageSize: onApplyPageSize,
|
301 |
-
onApplySorting: onApplySorting,
|
302 |
-
|
303 |
-
nextPage: nextPage,
|
304 |
-
prevPage: prevPage,
|
305 |
-
firstPage: firstPage,
|
306 |
-
lastPage: lastPage,
|
307 |
-
|
308 |
-
applyPageSize: applyPageSize,
|
309 |
-
applySorting: applySorting,
|
310 |
-
refreshEvents: refreshEvents
|
311 |
-
};
|
312 |
-
|
313 |
-
})(window.jQuery, window.ko);
|
314 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res/js/jquery-ck.js
DELETED
@@ -1,95 +0,0 @@
|
|
1 |
-
/*!
|
2 |
-
* jQuery Cookie Plugin v1.3.1
|
3 |
-
* https://github.com/carhartl/jquery-cookie
|
4 |
-
*
|
5 |
-
* Copyright 2013 Klaus Hartl
|
6 |
-
* Released under the MIT license
|
7 |
-
*/
|
8 |
-
(function (factory) {
|
9 |
-
if (typeof define === 'function' && define.amd) {
|
10 |
-
// AMD. Register as anonymous module.
|
11 |
-
define(['jquery'], factory);
|
12 |
-
} else {
|
13 |
-
// Browser globals.
|
14 |
-
factory(jQuery);
|
15 |
-
}
|
16 |
-
}(function ($) {
|
17 |
-
|
18 |
-
var pluses = /\+/g;
|
19 |
-
|
20 |
-
function raw(s) {
|
21 |
-
return s;
|
22 |
-
}
|
23 |
-
|
24 |
-
function decoded(s) {
|
25 |
-
return decodeURIComponent(s.replace(pluses, ' '));
|
26 |
-
}
|
27 |
-
|
28 |
-
function converted(s) {
|
29 |
-
if (s.indexOf('"') === 0) {
|
30 |
-
// This is a quoted cookie as according to RFC2068, unescape
|
31 |
-
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
32 |
-
}
|
33 |
-
try {
|
34 |
-
return config.json ? JSON.parse(s) : s;
|
35 |
-
} catch(er) {}
|
36 |
-
}
|
37 |
-
|
38 |
-
var config = $.cookie = function (key, value, options) {
|
39 |
-
|
40 |
-
// write
|
41 |
-
if (value !== undefined) {
|
42 |
-
options = $.extend({}, config.defaults, options);
|
43 |
-
|
44 |
-
if (typeof options.expires === 'number') {
|
45 |
-
var days = options.expires, t = options.expires = new Date();
|
46 |
-
t.setDate(t.getDate() + days);
|
47 |
-
}
|
48 |
-
|
49 |
-
value = config.json ? JSON.stringify(value) : String(value);
|
50 |
-
|
51 |
-
return (document.cookie = [
|
52 |
-
config.raw ? key : encodeURIComponent(key),
|
53 |
-
'=',
|
54 |
-
config.raw ? value : encodeURIComponent(value),
|
55 |
-
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
56 |
-
options.path ? '; path=' + options.path : '',
|
57 |
-
options.domain ? '; domain=' + options.domain : '',
|
58 |
-
options.secure ? '; secure' : ''
|
59 |
-
].join(''));
|
60 |
-
}
|
61 |
-
|
62 |
-
// read
|
63 |
-
var decode = config.raw ? raw : decoded;
|
64 |
-
var cookies = document.cookie.split('; ');
|
65 |
-
var result = key ? undefined : {};
|
66 |
-
for (var i = 0, l = cookies.length; i < l; i++) {
|
67 |
-
var parts = cookies[i].split('=');
|
68 |
-
var name = decode(parts.shift());
|
69 |
-
var cookie = decode(parts.join('='));
|
70 |
-
|
71 |
-
if (key && key === name) {
|
72 |
-
result = converted(cookie);
|
73 |
-
break;
|
74 |
-
}
|
75 |
-
|
76 |
-
if (!key) {
|
77 |
-
result[name] = converted(cookie);
|
78 |
-
}
|
79 |
-
}
|
80 |
-
|
81 |
-
return result;
|
82 |
-
};
|
83 |
-
|
84 |
-
config.defaults = {};
|
85 |
-
|
86 |
-
$.removeCookie = function (key, options) {
|
87 |
-
if ($.cookie(key) !== undefined) {
|
88 |
-
// Must not alter options, thus extending a fresh object...
|
89 |
-
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
|
90 |
-
return true;
|
91 |
-
}
|
92 |
-
return false;
|
93 |
-
};
|
94 |
-
|
95 |
-
}));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res/js/knockout.js
DELETED
@@ -1,85 +0,0 @@
|
|
1 |
-
// Knockout JavaScript library v2.2.1
|
2 |
-
// (c) Steven Sanderson - http://knockoutjs.com/
|
3 |
-
// License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
4 |
-
|
5 |
-
(function() {function j(w){throw w;}var m=!0,p=null,r=!1;function u(w){return function(){return w}};var x=window,y=document,ga=navigator,F=window.jQuery,I=void 0;
|
6 |
-
function L(w){function ha(a,d,c,e,f){var g=[];a=b.j(function(){var a=d(c,f)||[];0<g.length&&(b.a.Ya(M(g),a),e&&b.r.K(e,p,[c,a,f]));g.splice(0,g.length);b.a.P(g,a)},p,{W:a,Ka:function(){return 0==g.length||!b.a.X(g[0])}});return{M:g,j:a.pa()?a:I}}function M(a){for(;a.length&&!b.a.X(a[0]);)a.splice(0,1);if(1<a.length){for(var d=a[0],c=a[a.length-1],e=[d];d!==c;){d=d.nextSibling;if(!d)return;e.push(d)}Array.prototype.splice.apply(a,[0,a.length].concat(e))}return a}function S(a,b,c,e,f){var g=Math.min,
|
7 |
-
h=Math.max,k=[],l,n=a.length,q,s=b.length,v=s-n||1,G=n+s+1,J,A,z;for(l=0;l<=n;l++){A=J;k.push(J=[]);z=g(s,l+v);for(q=h(0,l-1);q<=z;q++)J[q]=q?l?a[l-1]===b[q-1]?A[q-1]:g(A[q]||G,J[q-1]||G)+1:q+1:l+1}g=[];h=[];v=[];l=n;for(q=s;l||q;)s=k[l][q]-1,q&&s===k[l][q-1]?h.push(g[g.length]={status:c,value:b[--q],index:q}):l&&s===k[l-1][q]?v.push(g[g.length]={status:e,value:a[--l],index:l}):(g.push({status:"retained",value:b[--q]}),--l);if(h.length&&v.length){a=10*n;var t;for(b=c=0;(f||b<a)&&(t=h[c]);c++){for(e=
|
8 |
-
0;k=v[e];e++)if(t.value===k.value){t.moved=k.index;k.moved=t.index;v.splice(e,1);b=e=0;break}b+=e}}return g.reverse()}function T(a,d,c,e,f){f=f||{};var g=a&&N(a),g=g&&g.ownerDocument,h=f.templateEngine||O;b.za.vb(c,h,g);c=h.renderTemplate(c,e,f,g);("number"!=typeof c.length||0<c.length&&"number"!=typeof c[0].nodeType)&&j(Error("Template engine must return an array of DOM nodes"));g=r;switch(d){case "replaceChildren":b.e.N(a,c);g=m;break;case "replaceNode":b.a.Ya(a,c);g=m;break;case "ignoreTargetNode":break;
|
9 |
-
default:j(Error("Unknown renderMode: "+d))}g&&(U(c,e),f.afterRender&&b.r.K(f.afterRender,p,[c,e.$data]));return c}function N(a){return a.nodeType?a:0<a.length?a[0]:p}function U(a,d){if(a.length){var c=a[0],e=a[a.length-1];V(c,e,function(a){b.Da(d,a)});V(c,e,function(a){b.s.ib(a,[d])})}}function V(a,d,c){var e;for(d=b.e.nextSibling(d);a&&(e=a)!==d;)a=b.e.nextSibling(e),(1===e.nodeType||8===e.nodeType)&&c(e)}function W(a,d,c){a=b.g.aa(a);for(var e=b.g.Q,f=0;f<a.length;f++){var g=a[f].key;if(e.hasOwnProperty(g)){var h=
|
10 |
-
e[g];"function"===typeof h?(g=h(a[f].value))&&j(Error(g)):h||j(Error("This template engine does not support the '"+g+"' binding within its templates"))}}a="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+b.g.ba(a)+" } })()})";return c.createJavaScriptEvaluatorBlock(a)+d}function X(a,d,c,e){function f(a){return function(){return k[a]}}function g(){return k}var h=0,k,l;b.j(function(){var n=c&&c instanceof b.z?c:new b.z(b.a.d(c)),q=n.$data;e&&b.eb(a,n);if(k=("function"==typeof d?
|
11 |
-
d(n,a):d)||b.J.instance.getBindings(a,n)){if(0===h){h=1;for(var s in k){var v=b.c[s];v&&8===a.nodeType&&!b.e.I[s]&&j(Error("The binding '"+s+"' cannot be used with virtual elements"));if(v&&"function"==typeof v.init&&(v=(0,v.init)(a,f(s),g,q,n))&&v.controlsDescendantBindings)l!==I&&j(Error("Multiple bindings ("+l+" and "+s+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.")),l=s}h=2}if(2===h)for(s in k)(v=b.c[s])&&"function"==
|
12 |
-
typeof v.update&&(0,v.update)(a,f(s),g,q,n)}},p,{W:a});return{Nb:l===I}}function Y(a,d,c){var e=m,f=1===d.nodeType;f&&b.e.Ta(d);if(f&&c||b.J.instance.nodeHasBindings(d))e=X(d,p,a,c).Nb;e&&Z(a,d,!f)}function Z(a,d,c){for(var e=b.e.firstChild(d);d=e;)e=b.e.nextSibling(d),Y(a,d,c)}function $(a,b){var c=aa(a,b);return c?0<c.length?c[c.length-1].nextSibling:a.nextSibling:p}function aa(a,b){for(var c=a,e=1,f=[];c=c.nextSibling;){if(H(c)&&(e--,0===e))return f;f.push(c);B(c)&&e++}b||j(Error("Cannot find closing comment tag to match: "+
|
13 |
-
a.nodeValue));return p}function H(a){return 8==a.nodeType&&(K?a.text:a.nodeValue).match(ia)}function B(a){return 8==a.nodeType&&(K?a.text:a.nodeValue).match(ja)}function P(a,b){for(var c=p;a!=c;)c=a,a=a.replace(ka,function(a,c){return b[c]});return a}function la(){var a=[],d=[];this.save=function(c,e){var f=b.a.i(a,c);0<=f?d[f]=e:(a.push(c),d.push(e))};this.get=function(c){c=b.a.i(a,c);return 0<=c?d[c]:I}}function ba(a,b,c){function e(e){var g=b(a[e]);switch(typeof g){case "boolean":case "number":case "string":case "function":f[e]=
|
14 |
-
g;break;case "object":case "undefined":var h=c.get(g);f[e]=h!==I?h:ba(g,b,c)}}c=c||new la;a=b(a);if(!("object"==typeof a&&a!==p&&a!==I&&!(a instanceof Date)))return a;var f=a instanceof Array?[]:{};c.save(a,f);var g=a;if(g instanceof Array){for(var h=0;h<g.length;h++)e(h);"function"==typeof g.toJSON&&e("toJSON")}else for(h in g)e(h);return f}function ca(a,d){if(a)if(8==a.nodeType){var c=b.s.Ua(a.nodeValue);c!=p&&d.push({sb:a,Fb:c})}else if(1==a.nodeType)for(var c=0,e=a.childNodes,f=e.length;c<f;c++)ca(e[c],
|
15 |
-
d)}function Q(a,d,c,e){b.c[a]={init:function(a){b.a.f.set(a,da,{});return{controlsDescendantBindings:m}},update:function(a,g,h,k,l){h=b.a.f.get(a,da);g=b.a.d(g());k=!c!==!g;var n=!h.Za;if(n||d||k!==h.qb)n&&(h.Za=b.a.Ia(b.e.childNodes(a),m)),k?(n||b.e.N(a,b.a.Ia(h.Za)),b.Ea(e?e(l,g):l,a)):b.e.Y(a),h.qb=k}};b.g.Q[a]=r;b.e.I[a]=m}function ea(a,d,c){c&&d!==b.k.q(a)&&b.k.T(a,d);d!==b.k.q(a)&&b.r.K(b.a.Ba,p,[a,"change"])}var b="undefined"!==typeof w?w:{};b.b=function(a,d){for(var c=a.split("."),e=b,f=0;f<
|
16 |
-
c.length-1;f++)e=e[c[f]];e[c[c.length-1]]=d};b.p=function(a,b,c){a[b]=c};b.version="2.2.1";b.b("version",b.version);b.a=new function(){function a(a,d){if("input"!==b.a.u(a)||!a.type||"click"!=d.toLowerCase())return r;var c=a.type;return"checkbox"==c||"radio"==c}var d=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,c={},e={};c[/Firefox\/2/i.test(ga.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];c.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");
|
17 |
-
for(var f in c){var g=c[f];if(g.length)for(var h=0,k=g.length;h<k;h++)e[g[h]]=f}var l={propertychange:m},n,c=3;f=y.createElement("div");for(g=f.getElementsByTagName("i");f.innerHTML="\x3c!--[if gt IE "+ ++c+"]><i></i><![endif]--\x3e",g[0];);n=4<c?c:I;return{Na:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],o:function(a,b){for(var d=0,c=a.length;d<c;d++)b(a[d])},i:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var d=0,c=a.length;d<
|
18 |
-
c;d++)if(a[d]===b)return d;return-1},lb:function(a,b,d){for(var c=0,e=a.length;c<e;c++)if(b.call(d,a[c]))return a[c];return p},ga:function(a,d){var c=b.a.i(a,d);0<=c&&a.splice(c,1)},Ga:function(a){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)0>b.a.i(d,a[c])&&d.push(a[c]);return d},V:function(a,b){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)d.push(b(a[c]));return d},fa:function(a,b){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)b(a[c])&&d.push(a[c]);return d},P:function(a,b){if(b instanceof Array)a.push.apply(a,
|
19 |
-
b);else for(var d=0,c=b.length;d<c;d++)a.push(b[d]);return a},extend:function(a,b){if(b)for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);return a},ka:function(a){for(;a.firstChild;)b.removeNode(a.firstChild)},Hb:function(a){a=b.a.L(a);for(var d=y.createElement("div"),c=0,e=a.length;c<e;c++)d.appendChild(b.A(a[c]));return d},Ia:function(a,d){for(var c=0,e=a.length,g=[];c<e;c++){var f=a[c].cloneNode(m);g.push(d?b.A(f):f)}return g},N:function(a,d){b.a.ka(a);if(d)for(var c=0,e=d.length;c<e;c++)a.appendChild(d[c])},
|
20 |
-
Ya:function(a,d){var c=a.nodeType?[a]:a;if(0<c.length){for(var e=c[0],g=e.parentNode,f=0,h=d.length;f<h;f++)g.insertBefore(d[f],e);f=0;for(h=c.length;f<h;f++)b.removeNode(c[f])}},bb:function(a,b){7>n?a.setAttribute("selected",b):a.selected=b},D:function(a){return(a||"").replace(d,"")},Rb:function(a,d){for(var c=[],e=(a||"").split(d),f=0,g=e.length;f<g;f++){var h=b.a.D(e[f]);""!==h&&c.push(h)}return c},Ob:function(a,b){a=a||"";return b.length>a.length?r:a.substring(0,b.length)===b},tb:function(a,b){if(b.compareDocumentPosition)return 16==
|
21 |
-
(b.compareDocumentPosition(a)&16);for(;a!=p;){if(a==b)return m;a=a.parentNode}return r},X:function(a){return b.a.tb(a,a.ownerDocument)},u:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,d,c){var e=n&&l[d];if(!e&&"undefined"!=typeof F){if(a(b,d)){var f=c;c=function(a,b){var d=this.checked;b&&(this.checked=b.nb!==m);f.call(this,a);this.checked=d}}F(b).bind(d,c)}else!e&&"function"==typeof b.addEventListener?b.addEventListener(d,c,r):"undefined"!=typeof b.attachEvent?b.attachEvent("on"+
|
22 |
-
d,function(a){c.call(b,a)}):j(Error("Browser doesn't support addEventListener or attachEvent"))},Ba:function(b,d){(!b||!b.nodeType)&&j(Error("element must be a DOM node when calling triggerEvent"));if("undefined"!=typeof F){var c=[];a(b,d)&&c.push({nb:b.checked});F(b).trigger(d,c)}else"function"==typeof y.createEvent?"function"==typeof b.dispatchEvent?(c=y.createEvent(e[d]||"HTMLEvents"),c.initEvent(d,m,m,x,0,0,0,0,0,r,r,r,r,0,b),b.dispatchEvent(c)):j(Error("The supplied element doesn't support dispatchEvent")):
|
23 |
-
"undefined"!=typeof b.fireEvent?(a(b,d)&&(b.checked=b.checked!==m),b.fireEvent("on"+d)):j(Error("Browser doesn't support triggering events"))},d:function(a){return b.$(a)?a():a},ua:function(a){return b.$(a)?a.t():a},da:function(a,d,c){if(d){var e=/[\w-]+/g,f=a.className.match(e)||[];b.a.o(d.match(e),function(a){var d=b.a.i(f,a);0<=d?c||f.splice(d,1):c&&f.push(a)});a.className=f.join(" ")}},cb:function(a,d){var c=b.a.d(d);if(c===p||c===I)c="";if(3===a.nodeType)a.data=c;else{var e=b.e.firstChild(a);
|
24 |
-
!e||3!=e.nodeType||b.e.nextSibling(e)?b.e.N(a,[y.createTextNode(c)]):e.data=c;b.a.wb(a)}},ab:function(a,b){a.name=b;if(7>=n)try{a.mergeAttributes(y.createElement("<input name='"+a.name+"'/>"),r)}catch(d){}},wb:function(a){9<=n&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},ub:function(a){if(9<=n){var b=a.style.width;a.style.width=0;a.style.width=b}},Lb:function(a,d){a=b.a.d(a);d=b.a.d(d);for(var c=[],e=a;e<=d;e++)c.push(e);return c},L:function(a){for(var b=[],d=0,c=a.length;d<
|
25 |
-
c;d++)b.push(a[d]);return b},Pb:6===n,Qb:7===n,Z:n,Oa:function(a,d){for(var c=b.a.L(a.getElementsByTagName("input")).concat(b.a.L(a.getElementsByTagName("textarea"))),e="string"==typeof d?function(a){return a.name===d}:function(a){return d.test(a.name)},f=[],g=c.length-1;0<=g;g--)e(c[g])&&f.push(c[g]);return f},Ib:function(a){return"string"==typeof a&&(a=b.a.D(a))?x.JSON&&x.JSON.parse?x.JSON.parse(a):(new Function("return "+a))():p},xa:function(a,d,c){("undefined"==typeof JSON||"undefined"==typeof JSON.stringify)&&
|
26 |
-
j(Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"));return JSON.stringify(b.a.d(a),d,c)},Jb:function(a,d,c){c=c||{};var e=c.params||{},f=c.includeFields||this.Na,g=a;if("object"==typeof a&&"form"===b.a.u(a))for(var g=a.action,h=f.length-1;0<=h;h--)for(var k=b.a.Oa(a,f[h]),l=k.length-1;0<=l;l--)e[k[l].name]=k[l].value;d=b.a.d(d);var n=y.createElement("form");
|
27 |
-
n.style.display="none";n.action=g;n.method="post";for(var w in d)a=y.createElement("input"),a.name=w,a.value=b.a.xa(b.a.d(d[w])),n.appendChild(a);for(w in e)a=y.createElement("input"),a.name=w,a.value=e[w],n.appendChild(a);y.body.appendChild(n);c.submitter?c.submitter(n):n.submit();setTimeout(function(){n.parentNode.removeChild(n)},0)}}};b.b("utils",b.a);b.b("utils.arrayForEach",b.a.o);b.b("utils.arrayFirst",b.a.lb);b.b("utils.arrayFilter",b.a.fa);b.b("utils.arrayGetDistinctValues",b.a.Ga);b.b("utils.arrayIndexOf",
|
28 |
-
b.a.i);b.b("utils.arrayMap",b.a.V);b.b("utils.arrayPushAll",b.a.P);b.b("utils.arrayRemoveItem",b.a.ga);b.b("utils.extend",b.a.extend);b.b("utils.fieldsIncludedWithJsonPost",b.a.Na);b.b("utils.getFormFields",b.a.Oa);b.b("utils.peekObservable",b.a.ua);b.b("utils.postJson",b.a.Jb);b.b("utils.parseJson",b.a.Ib);b.b("utils.registerEventHandler",b.a.n);b.b("utils.stringifyJson",b.a.xa);b.b("utils.range",b.a.Lb);b.b("utils.toggleDomNodeCssClass",b.a.da);b.b("utils.triggerEvent",b.a.Ba);b.b("utils.unwrapObservable",
|
29 |
-
b.a.d);Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return b.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});b.a.f=new function(){var a=0,d="__ko__"+(new Date).getTime(),c={};return{get:function(a,d){var c=b.a.f.la(a,r);return c===I?I:c[d]},set:function(a,d,c){c===I&&b.a.f.la(a,r)===I||(b.a.f.la(a,m)[d]=c)},la:function(b,f){var g=b[d];if(!g||!("null"!==g&&c[g])){if(!f)return I;g=b[d]="ko"+
|
30 |
-
a++;c[g]={}}return c[g]},clear:function(a){var b=a[d];return b?(delete c[b],a[d]=p,m):r}}};b.b("utils.domData",b.a.f);b.b("utils.domData.clear",b.a.f.clear);b.a.F=new function(){function a(a,d){var e=b.a.f.get(a,c);e===I&&d&&(e=[],b.a.f.set(a,c,e));return e}function d(c){var e=a(c,r);if(e)for(var e=e.slice(0),k=0;k<e.length;k++)e[k](c);b.a.f.clear(c);"function"==typeof F&&"function"==typeof F.cleanData&&F.cleanData([c]);if(f[c.nodeType])for(e=c.firstChild;c=e;)e=c.nextSibling,8===c.nodeType&&d(c)}
|
31 |
-
var c="__ko_domNodeDisposal__"+(new Date).getTime(),e={1:m,8:m,9:m},f={1:m,9:m};return{Ca:function(b,d){"function"!=typeof d&&j(Error("Callback must be a function"));a(b,m).push(d)},Xa:function(d,e){var f=a(d,r);f&&(b.a.ga(f,e),0==f.length&&b.a.f.set(d,c,I))},A:function(a){if(e[a.nodeType]&&(d(a),f[a.nodeType])){var c=[];b.a.P(c,a.getElementsByTagName("*"));for(var k=0,l=c.length;k<l;k++)d(c[k])}return a},removeNode:function(a){b.A(a);a.parentNode&&a.parentNode.removeChild(a)}}};b.A=b.a.F.A;b.removeNode=
|
32 |
-
b.a.F.removeNode;b.b("cleanNode",b.A);b.b("removeNode",b.removeNode);b.b("utils.domNodeDisposal",b.a.F);b.b("utils.domNodeDisposal.addDisposeCallback",b.a.F.Ca);b.b("utils.domNodeDisposal.removeDisposeCallback",b.a.F.Xa);b.a.ta=function(a){var d;if("undefined"!=typeof F)if(F.parseHTML)d=F.parseHTML(a);else{if((d=F.clean([a]))&&d[0]){for(a=d[0];a.parentNode&&11!==a.parentNode.nodeType;)a=a.parentNode;a.parentNode&&a.parentNode.removeChild(a)}}else{var c=b.a.D(a).toLowerCase();d=y.createElement("div");
|
33 |
-
c=c.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!c.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!c.indexOf("<td")||!c.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];a="ignored<div>"+c[1]+a+c[2]+"</div>";for("function"==typeof x.innerShiv?d.appendChild(x.innerShiv(a)):d.innerHTML=a;c[0]--;)d=d.lastChild;d=b.a.L(d.lastChild.childNodes)}return d};b.a.ca=function(a,d){b.a.ka(a);d=b.a.d(d);if(d!==p&&d!==I)if("string"!=typeof d&&(d=d.toString()),
|
34 |
-
"undefined"!=typeof F)F(a).html(d);else for(var c=b.a.ta(d),e=0;e<c.length;e++)a.appendChild(c[e])};b.b("utils.parseHtmlFragment",b.a.ta);b.b("utils.setHtml",b.a.ca);var R={};b.s={ra:function(a){"function"!=typeof a&&j(Error("You can only pass a function to ko.memoization.memoize()"));var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);R[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},hb:function(a,b){var c=R[a];c===I&&j(Error("Couldn't find any memo with ID "+
|
35 |
-
a+". Perhaps it's already been unmemoized."));try{return c.apply(p,b||[]),m}finally{delete R[a]}},ib:function(a,d){var c=[];ca(a,c);for(var e=0,f=c.length;e<f;e++){var g=c[e].sb,h=[g];d&&b.a.P(h,d);b.s.hb(c[e].Fb,h);g.nodeValue="";g.parentNode&&g.parentNode.removeChild(g)}},Ua:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:p}};b.b("memoization",b.s);b.b("memoization.memoize",b.s.ra);b.b("memoization.unmemoize",b.s.hb);b.b("memoization.parseMemoText",b.s.Ua);b.b("memoization.unmemoizeDomNodeAndDescendants",
|
36 |
-
b.s.ib);b.Ma={throttle:function(a,d){a.throttleEvaluation=d;var c=p;return b.j({read:a,write:function(b){clearTimeout(c);c=setTimeout(function(){a(b)},d)}})},notify:function(a,d){a.equalityComparer="always"==d?u(r):b.m.fn.equalityComparer;return a}};b.b("extenders",b.Ma);b.fb=function(a,d,c){this.target=a;this.ha=d;this.rb=c;b.p(this,"dispose",this.B)};b.fb.prototype.B=function(){this.Cb=m;this.rb()};b.S=function(){this.w={};b.a.extend(this,b.S.fn);b.p(this,"subscribe",this.ya);b.p(this,"extend",
|
37 |
-
this.extend);b.p(this,"getSubscriptionsCount",this.yb)};b.S.fn={ya:function(a,d,c){c=c||"change";var e=new b.fb(this,d?a.bind(d):a,function(){b.a.ga(this.w[c],e)}.bind(this));this.w[c]||(this.w[c]=[]);this.w[c].push(e);return e},notifySubscribers:function(a,d){d=d||"change";this.w[d]&&b.r.K(function(){b.a.o(this.w[d].slice(0),function(b){b&&b.Cb!==m&&b.ha(a)})},this)},yb:function(){var a=0,b;for(b in this.w)this.w.hasOwnProperty(b)&&(a+=this.w[b].length);return a},extend:function(a){var d=this;if(a)for(var c in a){var e=
|
38 |
-
b.Ma[c];"function"==typeof e&&(d=e(d,a[c]))}return d}};b.Qa=function(a){return"function"==typeof a.ya&&"function"==typeof a.notifySubscribers};b.b("subscribable",b.S);b.b("isSubscribable",b.Qa);var C=[];b.r={mb:function(a){C.push({ha:a,La:[]})},end:function(){C.pop()},Wa:function(a){b.Qa(a)||j(Error("Only subscribable things can act as dependencies"));if(0<C.length){var d=C[C.length-1];d&&!(0<=b.a.i(d.La,a))&&(d.La.push(a),d.ha(a))}},K:function(a,b,c){try{return C.push(p),a.apply(b,c||[])}finally{C.pop()}}};
|
39 |
-
var ma={undefined:m,"boolean":m,number:m,string:m};b.m=function(a){function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Wa(d);return c}var c=a;b.S.call(d);d.t=function(){return c};d.G=function(){d.notifySubscribers(c)};d.H=function(){d.notifySubscribers(c,"beforeChange")};b.a.extend(d,b.m.fn);b.p(d,"peek",d.t);b.p(d,"valueHasMutated",d.G);b.p(d,"valueWillMutate",d.H);return d};b.m.fn={equalityComparer:function(a,
|
40 |
-
b){return a===p||typeof a in ma?a===b:r}};var E=b.m.Kb="__ko_proto__";b.m.fn[E]=b.m;b.ma=function(a,d){return a===p||a===I||a[E]===I?r:a[E]===d?m:b.ma(a[E],d)};b.$=function(a){return b.ma(a,b.m)};b.Ra=function(a){return"function"==typeof a&&a[E]===b.m||"function"==typeof a&&a[E]===b.j&&a.zb?m:r};b.b("observable",b.m);b.b("isObservable",b.$);b.b("isWriteableObservable",b.Ra);b.R=function(a){0==arguments.length&&(a=[]);a!==p&&(a!==I&&!("length"in a))&&j(Error("The argument passed when initializing an observable array must be an array, or null, or undefined."));
|
41 |
-
var d=b.m(a);b.a.extend(d,b.R.fn);return d};b.R.fn={remove:function(a){for(var b=this.t(),c=[],e="function"==typeof a?a:function(b){return b===a},f=0;f<b.length;f++){var g=b[f];e(g)&&(0===c.length&&this.H(),c.push(g),b.splice(f,1),f--)}c.length&&this.G();return c},removeAll:function(a){if(a===I){var d=this.t(),c=d.slice(0);this.H();d.splice(0,d.length);this.G();return c}return!a?[]:this.remove(function(d){return 0<=b.a.i(a,d)})},destroy:function(a){var b=this.t(),c="function"==typeof a?a:function(b){return b===
|
42 |
-
a};this.H();for(var e=b.length-1;0<=e;e--)c(b[e])&&(b[e]._destroy=m);this.G()},destroyAll:function(a){return a===I?this.destroy(u(m)):!a?[]:this.destroy(function(d){return 0<=b.a.i(a,d)})},indexOf:function(a){var d=this();return b.a.i(d,a)},replace:function(a,b){var c=this.indexOf(a);0<=c&&(this.H(),this.t()[c]=b,this.G())}};b.a.o("pop push reverse shift sort splice unshift".split(" "),function(a){b.R.fn[a]=function(){var b=this.t();this.H();b=b[a].apply(b,arguments);this.G();return b}});b.a.o(["slice"],
|
43 |
-
function(a){b.R.fn[a]=function(){var b=this();return b[a].apply(b,arguments)}});b.b("observableArray",b.R);b.j=function(a,d,c){function e(){b.a.o(z,function(a){a.B()});z=[]}function f(){var a=h.throttleEvaluation;a&&0<=a?(clearTimeout(t),t=setTimeout(g,a)):g()}function g(){if(!q)if(n&&w())A();else{q=m;try{var a=b.a.V(z,function(a){return a.target});b.r.mb(function(c){var d;0<=(d=b.a.i(a,c))?a[d]=I:z.push(c.ya(f))});for(var c=s.call(d),e=a.length-1;0<=e;e--)a[e]&&z.splice(e,1)[0].B();n=m;h.notifySubscribers(l,
|
44 |
-
"beforeChange");l=c}finally{b.r.end()}h.notifySubscribers(l);q=r;z.length||A()}}function h(){if(0<arguments.length)return"function"===typeof v?v.apply(d,arguments):j(Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.")),this;n||g();b.r.Wa(h);return l}function k(){return!n||0<z.length}var l,n=r,q=r,s=a;s&&"object"==typeof s?(c=s,s=c.read):(c=c||{},s||(s=c.read));"function"!=typeof s&&j(Error("Pass a function that returns the value of the ko.computed"));
|
45 |
-
var v=c.write,G=c.disposeWhenNodeIsRemoved||c.W||p,w=c.disposeWhen||c.Ka||u(r),A=e,z=[],t=p;d||(d=c.owner);h.t=function(){n||g();return l};h.xb=function(){return z.length};h.zb="function"===typeof c.write;h.B=function(){A()};h.pa=k;b.S.call(h);b.a.extend(h,b.j.fn);b.p(h,"peek",h.t);b.p(h,"dispose",h.B);b.p(h,"isActive",h.pa);b.p(h,"getDependenciesCount",h.xb);c.deferEvaluation!==m&&g();if(G&&k()){A=function(){b.a.F.Xa(G,arguments.callee);e()};b.a.F.Ca(G,A);var D=w,w=function(){return!b.a.X(G)||D()}}return h};
|
46 |
-
b.Bb=function(a){return b.ma(a,b.j)};w=b.m.Kb;b.j[w]=b.m;b.j.fn={};b.j.fn[w]=b.j;b.b("dependentObservable",b.j);b.b("computed",b.j);b.b("isComputed",b.Bb);b.gb=function(a){0==arguments.length&&j(Error("When calling ko.toJS, pass the object you want to convert."));return ba(a,function(a){for(var c=0;b.$(a)&&10>c;c++)a=a();return a})};b.toJSON=function(a,d,c){a=b.gb(a);return b.a.xa(a,d,c)};b.b("toJS",b.gb);b.b("toJSON",b.toJSON);b.k={q:function(a){switch(b.a.u(a)){case "option":return a.__ko__hasDomDataOptionValue__===
|
47 |
-
m?b.a.f.get(a,b.c.options.sa):7>=b.a.Z?a.getAttributeNode("value").specified?a.value:a.text:a.value;case "select":return 0<=a.selectedIndex?b.k.q(a.options[a.selectedIndex]):I;default:return a.value}},T:function(a,d){switch(b.a.u(a)){case "option":switch(typeof d){case "string":b.a.f.set(a,b.c.options.sa,I);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=d;break;default:b.a.f.set(a,b.c.options.sa,d),a.__ko__hasDomDataOptionValue__=m,a.value="number"===typeof d?
|
48 |
-
d:""}break;case "select":for(var c=a.options.length-1;0<=c;c--)if(b.k.q(a.options[c])==d){a.selectedIndex=c;break}break;default:if(d===p||d===I)d="";a.value=d}}};b.b("selectExtensions",b.k);b.b("selectExtensions.readValue",b.k.q);b.b("selectExtensions.writeValue",b.k.T);var ka=/\@ko_token_(\d+)\@/g,na=["true","false"],oa=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;b.g={Q:[],aa:function(a){var d=b.a.D(a);if(3>d.length)return[];"{"===d.charAt(0)&&(d=d.substring(1,d.length-1));a=[];for(var c=
|
49 |
-
p,e,f=0;f<d.length;f++){var g=d.charAt(f);if(c===p)switch(g){case '"':case "'":case "/":c=f,e=g}else if(g==e&&"\\"!==d.charAt(f-1)){g=d.substring(c,f+1);a.push(g);var h="@ko_token_"+(a.length-1)+"@",d=d.substring(0,c)+h+d.substring(f+1),f=f-(g.length-h.length),c=p}}e=c=p;for(var k=0,l=p,f=0;f<d.length;f++){g=d.charAt(f);if(c===p)switch(g){case "{":c=f;l=g;e="}";break;case "(":c=f;l=g;e=")";break;case "[":c=f,l=g,e="]"}g===l?k++:g===e&&(k--,0===k&&(g=d.substring(c,f+1),a.push(g),h="@ko_token_"+(a.length-
|
50 |
-
1)+"@",d=d.substring(0,c)+h+d.substring(f+1),f-=g.length-h.length,c=p))}e=[];d=d.split(",");c=0;for(f=d.length;c<f;c++)k=d[c],l=k.indexOf(":"),0<l&&l<k.length-1?(g=k.substring(l+1),e.push({key:P(k.substring(0,l),a),value:P(g,a)})):e.push({unknown:P(k,a)});return e},ba:function(a){var d="string"===typeof a?b.g.aa(a):a,c=[];a=[];for(var e,f=0;e=d[f];f++)if(0<c.length&&c.push(","),e.key){var g;a:{g=e.key;var h=b.a.D(g);switch(h.length&&h.charAt(0)){case "'":case '"':break a;default:g="'"+h+"'"}}e=e.value;
|
51 |
-
c.push(g);c.push(":");c.push(e);e=b.a.D(e);0<=b.a.i(na,b.a.D(e).toLowerCase())?e=r:(h=e.match(oa),e=h===p?r:h[1]?"Object("+h[1]+")"+h[2]:e);e&&(0<a.length&&a.push(", "),a.push(g+" : function(__ko_value) { "+e+" = __ko_value; }"))}else e.unknown&&c.push(e.unknown);d=c.join("");0<a.length&&(d=d+", '_ko_property_writers' : { "+a.join("")+" } ");return d},Eb:function(a,d){for(var c=0;c<a.length;c++)if(b.a.D(a[c].key)==d)return m;return r},ea:function(a,d,c,e,f){if(!a||!b.Ra(a)){if((a=d()._ko_property_writers)&&
|
52 |
-
a[c])a[c](e)}else(!f||a.t()!==e)&&a(e)}};b.b("expressionRewriting",b.g);b.b("expressionRewriting.bindingRewriteValidators",b.g.Q);b.b("expressionRewriting.parseObjectLiteral",b.g.aa);b.b("expressionRewriting.preProcessBindings",b.g.ba);b.b("jsonExpressionRewriting",b.g);b.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",b.g.ba);var K="\x3c!--test--\x3e"===y.createComment("test").text,ja=K?/^\x3c!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*--\x3e$/:/^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/,ia=K?/^\x3c!--\s*\/ko\s*--\x3e$/:
|
53 |
-
/^\s*\/ko\s*$/,pa={ul:m,ol:m};b.e={I:{},childNodes:function(a){return B(a)?aa(a):a.childNodes},Y:function(a){if(B(a)){a=b.e.childNodes(a);for(var d=0,c=a.length;d<c;d++)b.removeNode(a[d])}else b.a.ka(a)},N:function(a,d){if(B(a)){b.e.Y(a);for(var c=a.nextSibling,e=0,f=d.length;e<f;e++)c.parentNode.insertBefore(d[e],c)}else b.a.N(a,d)},Va:function(a,b){B(a)?a.parentNode.insertBefore(b,a.nextSibling):a.firstChild?a.insertBefore(b,a.firstChild):a.appendChild(b)},Pa:function(a,d,c){c?B(a)?a.parentNode.insertBefore(d,
|
54 |
-
c.nextSibling):c.nextSibling?a.insertBefore(d,c.nextSibling):a.appendChild(d):b.e.Va(a,d)},firstChild:function(a){return!B(a)?a.firstChild:!a.nextSibling||H(a.nextSibling)?p:a.nextSibling},nextSibling:function(a){B(a)&&(a=$(a));return a.nextSibling&&H(a.nextSibling)?p:a.nextSibling},jb:function(a){return(a=B(a))?a[1]:p},Ta:function(a){if(pa[b.a.u(a)]){var d=a.firstChild;if(d){do if(1===d.nodeType){var c;c=d.firstChild;var e=p;if(c){do if(e)e.push(c);else if(B(c)){var f=$(c,m);f?c=f:e=[c]}else H(c)&&
|
55 |
-
(e=[c]);while(c=c.nextSibling)}if(c=e){e=d.nextSibling;for(f=0;f<c.length;f++)e?a.insertBefore(c[f],e):a.appendChild(c[f])}}while(d=d.nextSibling)}}}};b.b("virtualElements",b.e);b.b("virtualElements.allowedBindings",b.e.I);b.b("virtualElements.emptyNode",b.e.Y);b.b("virtualElements.insertAfter",b.e.Pa);b.b("virtualElements.prepend",b.e.Va);b.b("virtualElements.setDomNodeChildren",b.e.N);b.J=function(){this.Ha={}};b.a.extend(b.J.prototype,{nodeHasBindings:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind")!=
|
56 |
-
p;case 8:return b.e.jb(a)!=p;default:return r}},getBindings:function(a,b){var c=this.getBindingsString(a,b);return c?this.parseBindingsString(c,b,a):p},getBindingsString:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind");case 8:return b.e.jb(a);default:return p}},parseBindingsString:function(a,d,c){try{var e;if(!(e=this.Ha[a])){var f=this.Ha,g,h="with($context){with($data||{}){return{"+b.g.ba(a)+"}}}";g=new Function("$context","$element",h);e=f[a]=g}return e(d,c)}catch(k){j(Error("Unable to parse bindings.\nMessage: "+
|
57 |
-
k+";\nBindings value: "+a))}}});b.J.instance=new b.J;b.b("bindingProvider",b.J);b.c={};b.z=function(a,d,c){d?(b.a.extend(this,d),this.$parentContext=d,this.$parent=d.$data,this.$parents=(d.$parents||[]).slice(0),this.$parents.unshift(this.$parent)):(this.$parents=[],this.$root=a,this.ko=b);this.$data=a;c&&(this[c]=a)};b.z.prototype.createChildContext=function(a,d){return new b.z(a,this,d)};b.z.prototype.extend=function(a){var d=b.a.extend(new b.z,this);return b.a.extend(d,a)};b.eb=function(a,d){if(2==
|
58 |
-
arguments.length)b.a.f.set(a,"__ko_bindingContext__",d);else return b.a.f.get(a,"__ko_bindingContext__")};b.Fa=function(a,d,c){1===a.nodeType&&b.e.Ta(a);return X(a,d,c,m)};b.Ea=function(a,b){(1===b.nodeType||8===b.nodeType)&&Z(a,b,m)};b.Da=function(a,b){b&&(1!==b.nodeType&&8!==b.nodeType)&&j(Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node"));b=b||x.document.body;Y(a,b,m)};b.ja=function(a){switch(a.nodeType){case 1:case 8:var d=b.eb(a);if(d)return d;
|
59 |
-
if(a.parentNode)return b.ja(a.parentNode)}return I};b.pb=function(a){return(a=b.ja(a))?a.$data:I};b.b("bindingHandlers",b.c);b.b("applyBindings",b.Da);b.b("applyBindingsToDescendants",b.Ea);b.b("applyBindingsToNode",b.Fa);b.b("contextFor",b.ja);b.b("dataFor",b.pb);var fa={"class":"className","for":"htmlFor"};b.c.attr={update:function(a,d){var c=b.a.d(d())||{},e;for(e in c)if("string"==typeof e){var f=b.a.d(c[e]),g=f===r||f===p||f===I;g&&a.removeAttribute(e);8>=b.a.Z&&e in fa?(e=fa[e],g?a.removeAttribute(e):
|
60 |
-
a[e]=f):g||a.setAttribute(e,f.toString());"name"===e&&b.a.ab(a,g?"":f.toString())}}};b.c.checked={init:function(a,d,c){b.a.n(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=d(),g=b.a.d(f);"checkbox"==a.type&&g instanceof Array?(e=b.a.i(g,a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):b.g.ea(f,c,"checked",e,m)});"radio"==a.type&&!a.name&&b.c.uniqueName.init(a,u(m))},update:function(a,d){var c=b.a.d(d());
|
61 |
-
"checkbox"==a.type?a.checked=c instanceof Array?0<=b.a.i(c,a.value):c:"radio"==a.type&&(a.checked=a.value==c)}};b.c.css={update:function(a,d){var c=b.a.d(d());if("object"==typeof c)for(var e in c){var f=b.a.d(c[e]);b.a.da(a,e,f)}else c=String(c||""),b.a.da(a,a.__ko__cssValue,r),a.__ko__cssValue=c,b.a.da(a,c,m)}};b.c.enable={update:function(a,d){var c=b.a.d(d());c&&a.disabled?a.removeAttribute("disabled"):!c&&!a.disabled&&(a.disabled=m)}};b.c.disable={update:function(a,d){b.c.enable.update(a,function(){return!b.a.d(d())})}};
|
62 |
-
b.c.event={init:function(a,d,c,e){var f=d()||{},g;for(g in f)(function(){var f=g;"string"==typeof f&&b.a.n(a,f,function(a){var g,n=d()[f];if(n){var q=c();try{var s=b.a.L(arguments);s.unshift(e);g=n.apply(e,s)}finally{g!==m&&(a.preventDefault?a.preventDefault():a.returnValue=r)}q[f+"Bubble"]===r&&(a.cancelBubble=m,a.stopPropagation&&a.stopPropagation())}})})()}};b.c.foreach={Sa:function(a){return function(){var d=a(),c=b.a.ua(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:b.C.oa};
|
63 |
-
b.a.d(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:b.C.oa}}},init:function(a,d){return b.c.template.init(a,b.c.foreach.Sa(d))},update:function(a,d,c,e,f){return b.c.template.update(a,b.c.foreach.Sa(d),c,e,f)}};b.g.Q.foreach=r;b.e.I.foreach=m;b.c.hasfocus={init:function(a,d,c){function e(e){a.__ko_hasfocusUpdating=m;var f=a.ownerDocument;"activeElement"in
|
64 |
-
f&&(e=f.activeElement===a);f=d();b.g.ea(f,c,"hasfocus",e,m);a.__ko_hasfocusUpdating=r}var f=e.bind(p,m),g=e.bind(p,r);b.a.n(a,"focus",f);b.a.n(a,"focusin",f);b.a.n(a,"blur",g);b.a.n(a,"focusout",g)},update:function(a,d){var c=b.a.d(d());a.__ko_hasfocusUpdating||(c?a.focus():a.blur(),b.r.K(b.a.Ba,p,[a,c?"focusin":"focusout"]))}};b.c.html={init:function(){return{controlsDescendantBindings:m}},update:function(a,d){b.a.ca(a,d())}};var da="__ko_withIfBindingData";Q("if");Q("ifnot",r,m);Q("with",m,r,function(a,
|
65 |
-
b){return a.createChildContext(b)});b.c.options={update:function(a,d,c){"select"!==b.a.u(a)&&j(Error("options binding applies only to SELECT elements"));for(var e=0==a.length,f=b.a.V(b.a.fa(a.childNodes,function(a){return a.tagName&&"option"===b.a.u(a)&&a.selected}),function(a){return b.k.q(a)||a.innerText||a.textContent}),g=a.scrollTop,h=b.a.d(d());0<a.length;)b.A(a.options[0]),a.remove(0);if(h){c=c();var k=c.optionsIncludeDestroyed;"number"!=typeof h.length&&(h=[h]);if(c.optionsCaption){var l=y.createElement("option");
|
66 |
-
b.a.ca(l,c.optionsCaption);b.k.T(l,I);a.appendChild(l)}d=0;for(var n=h.length;d<n;d++){var q=h[d];if(!q||!q._destroy||k){var l=y.createElement("option"),s=function(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c},v=s(q,c.optionsValue,q);b.k.T(l,b.a.d(v));q=s(q,c.optionsText,v);b.a.cb(l,q);a.appendChild(l)}}h=a.getElementsByTagName("option");d=k=0;for(n=h.length;d<n;d++)0<=b.a.i(f,b.k.q(h[d]))&&(b.a.bb(h[d],m),k++);a.scrollTop=g;e&&"value"in c&&ea(a,b.a.ua(c.value),m);b.a.ub(a)}}};
|
67 |
-
b.c.options.sa="__ko.optionValueDomData__";b.c.selectedOptions={init:function(a,d,c){b.a.n(a,"change",function(){var e=d(),f=[];b.a.o(a.getElementsByTagName("option"),function(a){a.selected&&f.push(b.k.q(a))});b.g.ea(e,c,"value",f)})},update:function(a,d){"select"!=b.a.u(a)&&j(Error("values binding applies only to SELECT elements"));var c=b.a.d(d());c&&"number"==typeof c.length&&b.a.o(a.getElementsByTagName("option"),function(a){var d=0<=b.a.i(c,b.k.q(a));b.a.bb(a,d)})}};b.c.style={update:function(a,
|
68 |
-
d){var c=b.a.d(d()||{}),e;for(e in c)if("string"==typeof e){var f=b.a.d(c[e]);a.style[e]=f||""}}};b.c.submit={init:function(a,d,c,e){"function"!=typeof d()&&j(Error("The value for a submit binding must be a function"));b.a.n(a,"submit",function(b){var c,h=d();try{c=h.call(e,a)}finally{c!==m&&(b.preventDefault?b.preventDefault():b.returnValue=r)}})}};b.c.text={update:function(a,d){b.a.cb(a,d())}};b.e.I.text=m;b.c.uniqueName={init:function(a,d){if(d()){var c="ko_unique_"+ ++b.c.uniqueName.ob;b.a.ab(a,
|
69 |
-
c)}}};b.c.uniqueName.ob=0;b.c.value={init:function(a,d,c){function e(){h=r;var e=d(),f=b.k.q(a);b.g.ea(e,c,"value",f)}var f=["change"],g=c().valueUpdate,h=r;g&&("string"==typeof g&&(g=[g]),b.a.P(f,g),f=b.a.Ga(f));if(b.a.Z&&("input"==a.tagName.toLowerCase()&&"text"==a.type&&"off"!=a.autocomplete&&(!a.form||"off"!=a.form.autocomplete))&&-1==b.a.i(f,"propertychange"))b.a.n(a,"propertychange",function(){h=m}),b.a.n(a,"blur",function(){h&&e()});b.a.o(f,function(c){var d=e;b.a.Ob(c,"after")&&(d=function(){setTimeout(e,
|
70 |
-
0)},c=c.substring(5));b.a.n(a,c,d)})},update:function(a,d){var c="select"===b.a.u(a),e=b.a.d(d()),f=b.k.q(a),g=e!=f;0===e&&(0!==f&&"0"!==f)&&(g=m);g&&(f=function(){b.k.T(a,e)},f(),c&&setTimeout(f,0));c&&0<a.length&&ea(a,e,r)}};b.c.visible={update:function(a,d){var c=b.a.d(d()),e="none"!=a.style.display;c&&!e?a.style.display="":!c&&e&&(a.style.display="none")}};b.c.click={init:function(a,d,c,e){return b.c.event.init.call(this,a,function(){var a={};a.click=d();return a},c,e)}};b.v=function(){};b.v.prototype.renderTemplateSource=
|
71 |
-
function(){j(Error("Override renderTemplateSource"))};b.v.prototype.createJavaScriptEvaluatorBlock=function(){j(Error("Override createJavaScriptEvaluatorBlock"))};b.v.prototype.makeTemplateSource=function(a,d){if("string"==typeof a){d=d||y;var c=d.getElementById(a);c||j(Error("Cannot find template with ID "+a));return new b.l.h(c)}if(1==a.nodeType||8==a.nodeType)return new b.l.O(a);j(Error("Unknown template type: "+a))};b.v.prototype.renderTemplate=function(a,b,c,e){a=this.makeTemplateSource(a,e);
|
72 |
-
return this.renderTemplateSource(a,b,c)};b.v.prototype.isTemplateRewritten=function(a,b){return this.allowTemplateRewriting===r?m:this.makeTemplateSource(a,b).data("isRewritten")};b.v.prototype.rewriteTemplate=function(a,b,c){a=this.makeTemplateSource(a,c);b=b(a.text());a.text(b);a.data("isRewritten",m)};b.b("templateEngine",b.v);var qa=/(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi,ra=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;b.za={vb:function(a,
|
73 |
-
d,c){d.isTemplateRewritten(a,c)||d.rewriteTemplate(a,function(a){return b.za.Gb(a,d)},c)},Gb:function(a,b){return a.replace(qa,function(a,e,f,g,h,k,l){return W(l,e,b)}).replace(ra,function(a,e){return W(e,"\x3c!-- ko --\x3e",b)})},kb:function(a){return b.s.ra(function(d,c){d.nextSibling&&b.Fa(d.nextSibling,a,c)})}};b.b("__tr_ambtns",b.za.kb);b.l={};b.l.h=function(a){this.h=a};b.l.h.prototype.text=function(){var a=b.a.u(this.h),a="script"===a?"text":"textarea"===a?"value":"innerHTML";if(0==arguments.length)return this.h[a];
|
74 |
-
var d=arguments[0];"innerHTML"===a?b.a.ca(this.h,d):this.h[a]=d};b.l.h.prototype.data=function(a){if(1===arguments.length)return b.a.f.get(this.h,"templateSourceData_"+a);b.a.f.set(this.h,"templateSourceData_"+a,arguments[1])};b.l.O=function(a){this.h=a};b.l.O.prototype=new b.l.h;b.l.O.prototype.text=function(){if(0==arguments.length){var a=b.a.f.get(this.h,"__ko_anon_template__")||{};a.Aa===I&&a.ia&&(a.Aa=a.ia.innerHTML);return a.Aa}b.a.f.set(this.h,"__ko_anon_template__",{Aa:arguments[0]})};b.l.h.prototype.nodes=
|
75 |
-
function(){if(0==arguments.length)return(b.a.f.get(this.h,"__ko_anon_template__")||{}).ia;b.a.f.set(this.h,"__ko_anon_template__",{ia:arguments[0]})};b.b("templateSources",b.l);b.b("templateSources.domElement",b.l.h);b.b("templateSources.anonymousTemplate",b.l.O);var O;b.wa=function(a){a!=I&&!(a instanceof b.v)&&j(Error("templateEngine must inherit from ko.templateEngine"));O=a};b.va=function(a,d,c,e,f){c=c||{};(c.templateEngine||O)==I&&j(Error("Set a template engine before calling renderTemplate"));
|
76 |
-
f=f||"replaceChildren";if(e){var g=N(e);return b.j(function(){var h=d&&d instanceof b.z?d:new b.z(b.a.d(d)),k="function"==typeof a?a(h.$data,h):a,h=T(e,f,k,h,c);"replaceNode"==f&&(e=h,g=N(e))},p,{Ka:function(){return!g||!b.a.X(g)},W:g&&"replaceNode"==f?g.parentNode:g})}return b.s.ra(function(e){b.va(a,d,c,e,"replaceNode")})};b.Mb=function(a,d,c,e,f){function g(a,b){U(b,k);c.afterRender&&c.afterRender(b,a)}function h(d,e){k=f.createChildContext(b.a.d(d),c.as);k.$index=e;var g="function"==typeof a?
|
77 |
-
a(d,k):a;return T(p,"ignoreTargetNode",g,k,c)}var k;return b.j(function(){var a=b.a.d(d)||[];"undefined"==typeof a.length&&(a=[a]);a=b.a.fa(a,function(a){return c.includeDestroyed||a===I||a===p||!b.a.d(a._destroy)});b.r.K(b.a.$a,p,[e,a,h,c,g])},p,{W:e})};b.c.template={init:function(a,d){var c=b.a.d(d());if("string"!=typeof c&&!c.name&&(1==a.nodeType||8==a.nodeType))c=1==a.nodeType?a.childNodes:b.e.childNodes(a),c=b.a.Hb(c),(new b.l.O(a)).nodes(c);return{controlsDescendantBindings:m}},update:function(a,
|
78 |
-
d,c,e,f){d=b.a.d(d());c={};e=m;var g,h=p;"string"!=typeof d&&(c=d,d=c.name,"if"in c&&(e=b.a.d(c["if"])),e&&"ifnot"in c&&(e=!b.a.d(c.ifnot)),g=b.a.d(c.data));"foreach"in c?h=b.Mb(d||a,e&&c.foreach||[],c,a,f):e?(f="data"in c?f.createChildContext(g,c.as):f,h=b.va(d||a,f,c,a)):b.e.Y(a);f=h;(g=b.a.f.get(a,"__ko__templateComputedDomDataKey__"))&&"function"==typeof g.B&&g.B();b.a.f.set(a,"__ko__templateComputedDomDataKey__",f&&f.pa()?f:I)}};b.g.Q.template=function(a){a=b.g.aa(a);return 1==a.length&&a[0].unknown||
|
79 |
-
b.g.Eb(a,"name")?p:"This template engine does not support anonymous templates nested within its templates"};b.e.I.template=m;b.b("setTemplateEngine",b.wa);b.b("renderTemplate",b.va);b.a.Ja=function(a,b,c){a=a||[];b=b||[];return a.length<=b.length?S(a,b,"added","deleted",c):S(b,a,"deleted","added",c)};b.b("utils.compareArrays",b.a.Ja);b.a.$a=function(a,d,c,e,f){function g(a,b){t=l[b];w!==b&&(z[a]=t);t.na(w++);M(t.M);s.push(t);A.push(t)}function h(a,c){if(a)for(var d=0,e=c.length;d<e;d++)c[d]&&b.a.o(c[d].M,
|
80 |
-
function(b){a(b,d,c[d].U)})}d=d||[];e=e||{};var k=b.a.f.get(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult")===I,l=b.a.f.get(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult")||[],n=b.a.V(l,function(a){return a.U}),q=b.a.Ja(n,d),s=[],v=0,w=0,B=[],A=[];d=[];for(var z=[],n=[],t,D=0,C,E;C=q[D];D++)switch(E=C.moved,C.status){case "deleted":E===I&&(t=l[v],t.j&&t.j.B(),B.push.apply(B,M(t.M)),e.beforeRemove&&(d[D]=t,A.push(t)));v++;break;case "retained":g(D,v++);break;case "added":E!==I?
|
81 |
-
g(D,E):(t={U:C.value,na:b.m(w++)},s.push(t),A.push(t),k||(n[D]=t))}h(e.beforeMove,z);b.a.o(B,e.beforeRemove?b.A:b.removeNode);for(var D=0,k=b.e.firstChild(a),H;t=A[D];D++){t.M||b.a.extend(t,ha(a,c,t.U,f,t.na));for(v=0;q=t.M[v];k=q.nextSibling,H=q,v++)q!==k&&b.e.Pa(a,q,H);!t.Ab&&f&&(f(t.U,t.M,t.na),t.Ab=m)}h(e.beforeRemove,d);h(e.afterMove,z);h(e.afterAdd,n);b.a.f.set(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult",s)};b.b("utils.setDomNodeChildrenFromArrayMapping",b.a.$a);b.C=function(){this.allowTemplateRewriting=
|
82 |
-
r};b.C.prototype=new b.v;b.C.prototype.renderTemplateSource=function(a){var d=!(9>b.a.Z)&&a.nodes?a.nodes():p;if(d)return b.a.L(d.cloneNode(m).childNodes);a=a.text();return b.a.ta(a)};b.C.oa=new b.C;b.wa(b.C.oa);b.b("nativeTemplateEngine",b.C);b.qa=function(){var a=this.Db=function(){if("undefined"==typeof F||!F.tmpl)return 0;try{if(0<=F.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,c,e){e=e||{};2>a&&j(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));
|
83 |
-
var f=b.data("precompiled");f||(f=b.text()||"",f=F.template(p,"{{ko_with $item.koBindingContext}}"+f+"{{/ko_with}}"),b.data("precompiled",f));b=[c.$data];c=F.extend({koBindingContext:c},e.templateOptions);c=F.tmpl(f,b,c);c.appendTo(y.createElement("div"));F.fragments={};return c};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){y.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(F.tmpl.tag.ko_code=
|
84 |
-
{open:"__.push($1 || '');"},F.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};b.qa.prototype=new b.v;w=new b.qa;0<w.Db&&b.wa(w);b.b("jqueryTmplTemplateEngine",b.qa)}"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?L(module.exports||exports):"function"===typeof define&&define.amd?define(["exports"],L):L(x.ko={});m;
|
85 |
-
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uninstall.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// if uninstall not called from WordPress exit
|
4 |
+
if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) exit();
|
5 |
+
|
6 |
+
require('wp-security-audit-log.php');
|
7 |
+
WpSecurityAuditLog::GetInstance()->Uninstall();
|
wp-security-audit-log.php
CHANGED
@@ -4,14 +4,12 @@ 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: 0.
|
8 |
Author URI: http://www.wpwhitesecurity.com/
|
9 |
License: GPL2
|
10 |
-
Text Domain: wp-security-audit-log
|
11 |
-
Domain Path: /languages
|
12 |
|
13 |
WP Security Audit Log
|
14 |
-
Copyright(c)
|
15 |
|
16 |
This program is free software; you can redistribute it and/or modify
|
17 |
it under the terms of the GNU General Public License, version 2, as
|
@@ -26,183 +24,224 @@ Domain Path: /languages
|
|
26 |
along with this program; if not, write to the Free Software
|
27 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
28 |
*/
|
29 |
-
define('WPPH_PLUGIN_VERSION','0.6.3');
|
30 |
-
define('WPPH_PLUGIN_PREFIX', 'wpph_');
|
31 |
-
define('WPPH_PLUGIN_NAME', 'WP Security Audit Log');
|
32 |
-
define('WPPH_PLUGIN_URL', trailingslashit(plugins_url('', __FILE__)));
|
33 |
-
define('WPPH_PLUGIN_DIR', trailingslashit(plugin_dir_path(__FILE__)));
|
34 |
-
if(defined('__DIR__')) { define('WPPH_PLUGIN_BASE_NAME', basename(__DIR__)); }
|
35 |
-
else { define('WPPH_PLUGIN_BASE_NAME', basename(dirname(__FILE__))); }
|
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 |
-
else add_action('admin_menu', array('WPPH','createPluginWpSidebar'));
|
85 |
-
register_activation_hook( __FILE__, array('WPPHDatabase','dropTables')); // since v0.6
|
86 |
-
register_activation_hook( __FILE__, array('wpphNetwork','networkActivate'));
|
87 |
-
register_deactivation_hook( __FILE__, array('wpphNetwork','networkDeactivate'));
|
88 |
-
register_uninstall_hook( __FILE__, array('wpphNetwork','networkUninstall'));
|
89 |
-
|
90 |
-
// Add custom links on plugins page
|
91 |
-
add_filter("plugin_action_links_".plugin_basename(__FILE__), 'wpphCustomLinks' );
|
92 |
-
// Load text domain
|
93 |
-
add_action('plugins_loaded', 'wpphLoadTextDomain');
|
94 |
-
// create dashboard widget
|
95 |
-
add_action('wp_dashboard_setup', array('WPPHUtil','addDashboardWidget'));
|
96 |
-
// activate plugin for new created websites
|
97 |
-
add_action('wpmu_new_blog', array('WPPH','onPluginActivate'));
|
98 |
-
|
99 |
-
// $GLOBALS['WPPH_CAN_RUN']
|
100 |
-
// @since v0.3
|
101 |
-
// @see WPPH::onPluginActivate()
|
102 |
-
if($GLOBALS['WPPH_CAN_RUN'])
|
103 |
-
{
|
104 |
-
// Watch widget activity
|
105 |
-
add_action('widgets_init',array('WPPHEventWatcher','watchWidgetMove'));
|
106 |
-
add_action('sidebar_admin_setup', array('WPPHEventWatcher','watchWidgetActivity'));
|
107 |
-
// Load the pluggable.php file if needed
|
108 |
-
add_action('admin_init', array('WPPHUtil','loadPluggable'));
|
109 |
-
// Load resources
|
110 |
-
add_action('admin_init', array('WPPH','loadBaseResources'));
|
111 |
-
// Add the sidebar menu
|
112 |
-
add_action('admin_menu', array('WPPH','createPluginWpSidebar'));
|
113 |
-
|
114 |
-
if(WPPH::isMultisite())
|
115 |
-
{
|
116 |
-
// 4001 && 4002 - wpmu user activated/registered
|
117 |
-
add_action('wpmu_activate_user', array('WPPHEventWatcher', 'watchEventUserRegister'));
|
118 |
-
// 4008 && 4009
|
119 |
-
WPPHEvent::hookUserAdminPriv();
|
120 |
-
// 4010 - user added to blog
|
121 |
-
add_action('add_user_to_blog', array('WPPHEventWatcher','watchUserAddedToBlog'), 10, 3);
|
122 |
-
// 4011 - user removed from blog
|
123 |
-
add_action('remove_user_from_blog', array('WPPHEventWatcher','watchUserRemovedFromBlog'));
|
124 |
-
// 7000 - new blog added
|
125 |
-
add_action('wpmu_new_blog', array('WPPHEventWatcher','watchBlogAdded'), 10, 6);
|
126 |
-
// 7001 - blog archived
|
127 |
-
add_action('archive_blog', array('WPPHEventWatcher','watchBlogArchived'));
|
128 |
-
// 7002 - blog unarchived
|
129 |
-
add_action('unarchive_blog', array('WPPHEventWatcher','watchBlogUnarchived'));
|
130 |
-
// 7003 - blog activated
|
131 |
-
add_action('activate_blog', array('WPPHEventWatcher','watchBlogActivated'));
|
132 |
-
// 7004 - blog deactivated
|
133 |
-
add_action('deactivate_blog', array('WPPHEventWatcher','watchBlogDeactivated'));
|
134 |
-
// 7005 - blog deleted
|
135 |
-
add_action('delete_blog', array('WPPHEventWatcher','watchBlogDeleted'));
|
136 |
-
}
|
137 |
-
// end wpmu events
|
138 |
|
139 |
-
|
140 |
-
|
141 |
-
WPPHEvent::hookLoginFailure();
|
142 |
-
// 4000 && 4001 && 4012
|
143 |
-
WPPHEvent::hookUserRegisterEvent();
|
144 |
-
// 4003 && 4004
|
145 |
-
WPPHEvent::hookUserPasswordUpdated();
|
146 |
-
// 4005 && 4006
|
147 |
-
WPPHEvent::hookUserEmailUpdated();
|
148 |
-
|
149 |
-
// 6000
|
150 |
-
if(defined('DISABLE_WP_CRON') && DISABLE_WP_CRON)
|
151 |
-
{
|
152 |
-
wpphLog('wp-cron is disabled.');
|
153 |
-
WPPHEventWatcher::__deleteEvents();
|
154 |
-
}
|
155 |
-
else { add_action(WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME, array('WPPHEventWatcher','__deleteEvents')); }
|
156 |
-
|
157 |
-
// Plugin init
|
158 |
-
add_action('init', 'wpphPluginInit');
|
159 |
-
function wpphPluginInit()
|
160 |
-
{
|
161 |
-
if(is_admin())
|
162 |
-
{
|
163 |
-
if(isset($_POST)){
|
164 |
-
//# 6001, 6002, 6003
|
165 |
-
WPPHEvent::hookCheckWpGeneralSettings();
|
166 |
-
if(isset($_POST)){
|
167 |
-
if(isset($_POST['action']) && $_POST['action'] == 'editpost'){
|
168 |
-
wpphLog('WPPH_DEFAULT_EDITOR_ENABLED');
|
169 |
-
$GLOBALS['WPPH_DEFAULT_EDITOR_ENABLED'] = true;
|
170 |
-
}
|
171 |
-
elseif(isset($_POST['screen'])){
|
172 |
-
if($_POST['screen'] == 'edit-post' || $_POST['screen'] == 'edit-page'){
|
173 |
-
wpphLog('WPPH_SCREEN_EDITOR_ENABLED');
|
174 |
-
$GLOBALS['WPPH_SCREEN_EDITOR_ENABLED'] = true;
|
175 |
-
}
|
176 |
-
else {// Custom Post type screen
|
177 |
-
$type = wpph_extractCustomPostType($_POST['screen']);
|
178 |
-
if(WPPHPost::validatePostType($type)){
|
179 |
-
wpphLog('WPPH_SCREEN_EDITOR_ENABLED');
|
180 |
-
$GLOBALS['WPPH_SCREEN_EDITOR_ENABLED'] = true;
|
181 |
-
}
|
182 |
-
}
|
183 |
-
}
|
184 |
-
}
|
185 |
-
}
|
186 |
-
WPPHEventWatcher::triggerWidgetMoveEvent();
|
187 |
-
WPPHEvent::hookWatchPostStateBefore();
|
188 |
-
WPPHEvent::hookWatchBlogActivity();
|
189 |
-
WPPHEvent::hookWatchCategoryAdd();
|
190 |
-
WPPHEvent::hookWatchCategoryDelete();
|
191 |
-
WPPHEvent::hookFileDeletion();
|
192 |
-
WPPHEvent::hookFileUploaded();
|
193 |
-
WPPHEvent::hookFileUploadedDeleted();
|
194 |
-
WPPHEvent::hookTrashPost();
|
195 |
-
WPPHEvent::hookTrashPage();
|
196 |
-
WPPHEvent::hookUntrashedPosts();
|
197 |
-
WPPHEvent::hookUntrashedPages();
|
198 |
-
WPPHEvent::hookThemeChange();
|
199 |
-
WPPHEvent::hookUserDeletion();
|
200 |
-
WPPHEvent::hookWatchPluginActivity();
|
201 |
-
/* Enable ajax functionality in the dashboard page */
|
202 |
-
add_action('wp_ajax_wpph_get_events', array('WPPHUtil','get_events_html'));
|
203 |
-
add_action('wp_ajax_wpph_get_blogs', array('WPPHUtil','ajax_get_blogs'));
|
204 |
-
add_action('wp_ajax_wpph_check_user_role', array('WPPHUtil','check_user_role'));
|
205 |
-
}
|
206 |
-
}
|
207 |
-
}
|
208 |
-
// End 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.0.0
|
8 |
Author URI: http://www.wpwhitesecurity.com/
|
9 |
License: GPL2
|
|
|
|
|
10 |
|
11 |
WP Security Audit Log
|
12 |
+
Copyright(c) 2014 Robert Abela (email : robert@wpwhitesecurity.com)
|
13 |
|
14 |
This program is free software; you can redistribute it and/or modify
|
15 |
it under the terms of the GNU General Public License, version 2, as
|
24 |
along with this program; if not, write to the Free Software
|
25 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
26 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
+
class WpSecurityAuditLog {
|
29 |
+
|
30 |
+
// <editor-fold desc="Properties & Constants">
|
31 |
+
|
32 |
+
const PLG_CLS_PRFX = 'WSAL_';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Views supervisor.
|
36 |
+
* @var WSAL_ViewManager
|
37 |
+
*/
|
38 |
+
public $views;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Logger supervisor.
|
42 |
+
* @var WSAL_AlertManager
|
43 |
+
*/
|
44 |
+
public $alerts;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Sensors supervisor.
|
48 |
+
* @var WSAL_SensorManager
|
49 |
+
*/
|
50 |
+
public $sensors;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Settings manager.
|
54 |
+
* @var WSAL_Settings
|
55 |
+
*/
|
56 |
+
public $settings;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Constants manager.
|
60 |
+
* @var WSAL_ConstantManager
|
61 |
+
*/
|
62 |
+
public $constants;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Contains a list of cleanup callbacks.
|
66 |
+
* @var callable[]
|
67 |
+
*/
|
68 |
+
protected $_cleanup_hooks = array();
|
69 |
+
|
70 |
+
// </editor-fold>
|
71 |
+
|
72 |
+
// <editor-fold desc="Entry Points">
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Standard singleton pattern.
|
76 |
+
* @return \self Returns the current plugin instance.
|
77 |
+
*/
|
78 |
+
public static function GetInstance(){
|
79 |
+
static $instance = null;
|
80 |
+
if(!$instance)$instance = new self();
|
81 |
+
return $instance;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Initialize plugin.
|
86 |
+
*/
|
87 |
+
public function __construct(){
|
88 |
+
spl_autoload_register(array($this, 'LoadClass'));
|
89 |
+
|
90 |
+
// load dependencies
|
91 |
+
$this->views = new WSAL_ViewManager($this);
|
92 |
+
$this->alerts = new WSAL_AlertManager($this);
|
93 |
+
$this->sensors = new WSAL_SensorManager($this);
|
94 |
+
$this->settings = new WSAL_Settings($this);
|
95 |
+
$this->constants = new WSAL_ConstantManager($this);
|
96 |
+
$this->widgets = new WSAL_WidgetManager($this);
|
97 |
+
|
98 |
+
// listen to general events
|
99 |
+
$this->sensors->HookEvents();
|
100 |
+
|
101 |
+
// listen for installation event
|
102 |
+
register_activation_hook(__FILE__, array($this, 'Install'));
|
103 |
+
|
104 |
+
// listen for cleanup event
|
105 |
+
add_action('wsal_cleanup', array($this, 'CleanUp'));
|
106 |
+
//add_action('init', array($this, 'CleanUp'));
|
107 |
+
}
|
108 |
+
|
109 |
+
public function CleanUp(){
|
110 |
+
foreach($this->_cleanup_hooks as $hook)
|
111 |
+
call_user_func($hook);
|
112 |
+
}
|
113 |
+
|
114 |
+
public function AddCleanupHook($hook){
|
115 |
+
$this->_cleanup_hooks[] = $hook;
|
116 |
+
}
|
117 |
+
|
118 |
+
public function RemoveCleanupHook($hook){
|
119 |
+
while(($pos = array_search($hook, $this->_cleanup_hooks)) !== false)
|
120 |
+
unset($this->_cleanup_hooks[$pos]);
|
121 |
+
}
|
122 |
+
|
123 |
+
public function Install(){
|
124 |
+
WSAL_DB_ActiveRecord::InstallAll();
|
125 |
+
if($this->CanUpgrade())$this->Upgrade();
|
126 |
+
wp_schedule_event(0, 'hourly', 'wsal_cleanup');
|
127 |
+
}
|
128 |
+
|
129 |
+
public function Uninstall(){
|
130 |
+
WSAL_DB_ActiveRecord::UninstallAll();
|
131 |
+
wp_unschedule_event(0, 'wsal_cleanup');
|
132 |
+
}
|
133 |
+
|
134 |
+
public function CanUpgrade(){
|
135 |
+
global $wpdb;
|
136 |
+
$table = $wpdb->base_prefix . 'wordpress_auditlog_events';
|
137 |
+
return $wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table;
|
138 |
+
}
|
139 |
+
|
140 |
+
public function Upgrade(){
|
141 |
+
global $wpdb;
|
142 |
+
static $migTypes = array(
|
143 |
+
3000 => 5006
|
144 |
+
);
|
145 |
+
|
146 |
+
// load data
|
147 |
+
$sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog_events';
|
148 |
+
$events = array();
|
149 |
+
foreach($wpdb->get_results($sql, ARRAY_A) as $item)
|
150 |
+
$events[$item['EventID']] = $item;
|
151 |
+
$sql = 'SELECT * FROM ' . $wpdb->base_prefix . 'wordpress_auditlog';
|
152 |
+
$auditlog = $wpdb->get_results($sql, ARRAY_A);
|
153 |
+
|
154 |
+
// migrate using db logger
|
155 |
+
$lgr = new WSAL_Loggers_Database($this);
|
156 |
+
foreach($auditlog as $entry){
|
157 |
+
$data = array(
|
158 |
+
'ClientIP' => $entry['UserIP'],
|
159 |
+
'UserAgent' => '',
|
160 |
+
'CurrentUserID' => $entry['UserID'],
|
161 |
+
);
|
162 |
+
if($entry['UserName'])
|
163 |
+
$data['Username'] = base64_decode($entry['UserName']);
|
164 |
+
$mesg = $events[$entry['EventID']]['EventDescription'];
|
165 |
+
$date = strtotime($entry['EventDate']);
|
166 |
+
$type = $entry['EventID'];
|
167 |
+
if(isset($migTypes[$type]))$type = $migTypes[$type];
|
168 |
+
// convert message from '<strong>%s</strong>' to '%Arg1%' format
|
169 |
+
$c = 0; $n = '<strong>%s</strong>'; $l = strlen($n);
|
170 |
+
while(($pos = strpos($mesg, $n)) !== false){
|
171 |
+
$mesg = substr_replace($mesg, '%MigratedArg' . ($c++) .'%', $pos, $l);
|
172 |
+
}
|
173 |
+
$data['MigratedMesg'] = $mesg;
|
174 |
+
// generate new meta data args
|
175 |
+
$temp = unserialize(base64_decode($entry['EventData']));
|
176 |
+
foreach((array)$temp as $i => $item)
|
177 |
+
$data['MigratedArg' . $i] = $item;
|
178 |
+
// send event data to logger!
|
179 |
+
$lgr->Log($type, $data, $date, $entry['BlogId'], true);
|
180 |
+
}
|
181 |
+
|
182 |
+
// migrate settings
|
183 |
+
$this->settings->SetAllowedPluginEditors(
|
184 |
+
get_option('WPPH_PLUGIN_ALLOW_CHANGE')
|
185 |
+
);
|
186 |
+
$this->settings->SetAllowedPluginViewers(
|
187 |
+
get_option('WPPH_PLUGIN_ALLOW_ACCESS')
|
188 |
+
);
|
189 |
+
$s = get_option('wpph_plugin_settings');
|
190 |
+
//$this->settings->SetPruningDate(($s->daysToKeep ? $s->daysToKeep : 30) . ' days');
|
191 |
+
//$this->settings->SetPruningLimit(min($s->eventsToKeep, 1));
|
192 |
+
$this->settings->SetViewPerPage(max($s->showEventsViewList, 5));
|
193 |
+
$this->settings->SetWidgetsEnabled(!!$s->showDW);
|
194 |
+
}
|
195 |
+
|
196 |
+
public function GetBaseUrl(){
|
197 |
+
return plugins_url('', __FILE__);
|
198 |
+
}
|
199 |
+
|
200 |
+
public function GetBaseDir(){
|
201 |
+
return plugin_dir_path(__FILE__);
|
202 |
+
}
|
203 |
+
|
204 |
+
public function GetBaseName(){
|
205 |
+
return plugin_basename(__FILE__);
|
206 |
+
}
|
207 |
+
|
208 |
+
// </editor-fold>
|
209 |
+
|
210 |
+
/**
|
211 |
+
* This is the class autoloader. You should not call this directly.
|
212 |
+
* @param string $class Class name.
|
213 |
+
* @return boolean True if class is found and loaded, false otherwise.
|
214 |
+
*/
|
215 |
+
public function LoadClass($class){
|
216 |
+
if(substr($class, 0, strlen(self::PLG_CLS_PRFX)) == self::PLG_CLS_PRFX){
|
217 |
+
$file = str_replace('_', DIRECTORY_SEPARATOR, substr($class, strlen(self::PLG_CLS_PRFX)));
|
218 |
+
$file = $this->GetBaseDir() . 'classes' . DIRECTORY_SEPARATOR . $file . '.php';
|
219 |
+
if(file_exists($file)){
|
220 |
+
require_once($file);
|
221 |
+
return class_exists($class, false) || interface_exists($class, false);
|
222 |
+
}
|
223 |
+
}
|
224 |
+
return false;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Returns the class name of a particular file that contains the class.
|
229 |
+
* @param string $file File name.
|
230 |
+
* @return string Class name.
|
231 |
+
*/
|
232 |
+
public function GetClassFileClassName($file){
|
233 |
+
$base = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $this->GetBaseDir() . 'classes' . DIRECTORY_SEPARATOR);
|
234 |
+
$file = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $file);
|
235 |
+
return str_replace(
|
236 |
+
array($base, '\\', '/'),
|
237 |
+
array(self::PLG_CLS_PRFX, '_', '_'),
|
238 |
+
substr($file, 0, -4)
|
239 |
+
);
|
240 |
+
}
|
241 |
}
|
242 |
|
243 |
+
// Load extra files
|
244 |
+
require_once('defaults.php');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
+
// Create & Run the plugin
|
247 |
+
return WpSecurityAuditLog::GetInstance();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|