Version Description
(2015-07-16) = * New Features * New database connector allowing faster and more efficient plugin to WordPress database communication * Added new option to switch the display time of alerts between 24 hour or 12 hour format * Sorting functionality in Audit Log Viewer (sort WordPress security alerts by date & time, code or username)
-
Bug Fixes
- Fixed issue where super admin roles was not reported when logging in to "sub sites" in WordPress multisite
- Fixed several formatting issues in the Audit Log Viewer (UI)
- Fixed issue where multiple plugins were upgraded via the drop down menu and no alerts were being reported
- Fixed: When unrestricting plugin access from a single admin was not working properly
Download this release
Release Info
Developer | WPWhiteSecurity |
Plugin | WP Security Audit Log |
Version | 2.0.0 |
Comparing to | |
See all releases |
Code changes from version 1.6.1 to 2.0.0
- classes/Alert.php +1 -1
- classes/AlertManager.php +1 -1
- classes/AuditLogListView.php +58 -31
- classes/Connector/AbstractConnector.php +36 -0
- classes/Connector/ConnectorFactory.php +77 -0
- classes/Connector/ConnectorInterface.php +11 -0
- classes/Connector/MySQLDBConnector.php +134 -0
- classes/DB/ActiveRecord.php +0 -472
- classes/DB/Meta.php +0 -17
- classes/DB/Occurrence.php +0 -211
- classes/DB/OccurrenceQuery.php +0 -96
- classes/DB/Option.php +0 -36
- classes/DB/Query.php +0 -162
- classes/Helpers/DataHelper.php +23 -0
- classes/Loggers/Database.php +18 -18
- classes/Models/ActiveRecord.php +267 -0
- classes/Models/Adapters/ActiveRecordInterface.php +15 -0
- classes/Models/Adapters/MetaInterface.php +13 -0
- classes/Models/Adapters/MySQL/ActiveRecordAdapter.php +460 -0
- classes/Models/Adapters/MySQL/MetaAdapter.php +49 -0
- classes/Models/Adapters/MySQL/OccurrenceAdapter.php +170 -0
- classes/Models/Adapters/MySQL/OptionAdapter.php +80 -0
- classes/Models/Adapters/MySQL/QueryAdapter.php +216 -0
- classes/Models/Adapters/OccurrenceInterface.php +11 -0
- classes/Models/Adapters/QueryInterface.php +8 -0
- classes/Models/Meta.php +34 -0
- classes/Models/Occurrence.php +193 -0
- classes/Models/OccurrenceQuery.php +29 -0
- classes/Models/Option.php +80 -0
- classes/Models/Query.php +187 -0
- classes/Sensors/LogInOut.php +18 -31
- classes/Sensors/UserProfile.php +11 -9
- classes/Settings.php +29 -3
- classes/Views/AuditLog.php +5 -3
- classes/Views/Settings.php +137 -6
- classes/WidgetManager.php +5 -4
- css/auditlog.css +1 -1
- js/settings.js +2 -0
- readme.txt +18 -6
- wp-security-audit-log.php +59 -16
classes/Alert.php
CHANGED
@@ -66,7 +66,7 @@ final class WSAL_Alert {
|
|
66 |
* @param string $afterMeta (Optional) Some text to put after meta values.
|
67 |
* @return string The expanded message.
|
68 |
*/
|
69 |
-
protected function GetFormattedMesg($origMesg, $metaData = array(), $metaFormatter = null){
|
70 |
// tokenize message with regex
|
71 |
$mesg = preg_split('/(%.*?%)/', (string)$origMesg, -1, PREG_SPLIT_DELIM_CAPTURE);
|
72 |
if(!is_array($mesg))return (string)$origMesg;
|
66 |
* @param string $afterMeta (Optional) Some text to put after meta values.
|
67 |
* @return string The expanded message.
|
68 |
*/
|
69 |
+
protected function GetFormattedMesg($origMesg, $metaData = array(), $metaFormatter = null){
|
70 |
// tokenize message with regex
|
71 |
$mesg = preg_split('/(%.*?%)/', (string)$origMesg, -1, PREG_SPLIT_DELIM_CAPTURE);
|
72 |
if(!is_array($mesg))return (string)$origMesg;
|
classes/AlertManager.php
CHANGED
@@ -80,7 +80,7 @@ final class WSAL_AlertManager {
|
|
80 |
* @param integer $type Alert type.
|
81 |
* @param array $data Alert data.
|
82 |
*/
|
83 |
-
public function Trigger($type, $data = array(), $delayed = false){
|
84 |
$username = wp_get_current_user()->user_login;
|
85 |
if (empty($username) && !empty($data["Username"])) {
|
86 |
$username = $data['Username'];
|
80 |
* @param integer $type Alert type.
|
81 |
* @param array $data Alert data.
|
82 |
*/
|
83 |
+
public function Trigger($type, $data = array(), $delayed = false){
|
84 |
$username = wp_get_current_user()->user_login;
|
85 |
if (empty($username) && !empty($data["Username"])) {
|
86 |
$username = $data['Username'];
|
classes/AuditLogListView.php
CHANGED
@@ -134,16 +134,19 @@ class WSAL_AuditLogListView extends WP_List_Table {
|
|
134 |
public function get_sortable_columns(){
|
135 |
return array(
|
136 |
'read' => array('is_read', false),
|
137 |
-
'code' => array('code', false),
|
138 |
'type' => array('alert_id', false),
|
139 |
'crtd' => array('created_on', true),
|
140 |
-
'user' => array('user',
|
141 |
-
'scip' => array('scip', false)
|
142 |
-
'site' => array('site', false),
|
143 |
);
|
144 |
}
|
145 |
|
146 |
public function column_default($item, $column_name){
|
|
|
|
|
|
|
|
|
147 |
switch($column_name){
|
148 |
case 'read':
|
149 |
return '<span class="log-read log-read-'
|
@@ -163,20 +166,24 @@ class WSAL_AuditLogListView extends WP_List_Table {
|
|
163 |
str_replace(
|
164 |
'$$$',
|
165 |
substr(number_format(fmod($item->created_on + $this->_gmt_offset_sec, 1), 3), 2),
|
166 |
-
date('Y-m-d<\b\r>
|
167 |
)
|
168 |
) : '<i>unknown</i>';
|
169 |
case 'user':
|
170 |
$username = $item->GetUsername();
|
171 |
-
if($username && ($user = get_user_by('login', $username))){
|
172 |
$image = get_avatar($user->ID, 32);
|
173 |
$uhtml = '<a href="' . admin_url('user-edit.php?user_id=' . $user->ID)
|
174 |
. '" target="_blank">' . esc_html($user->display_name) . '</a>';
|
175 |
$roles = $item->GetUserRoles();
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
|
|
180 |
$image = get_avatar(0, 32);
|
181 |
$uhtml = '<i>' . __('Unknown', 'wp-security-audit-log') . '</i>';
|
182 |
$roles = '<i>' . __('System', 'wp-security-audit-log') . '</i>';
|
@@ -184,6 +191,9 @@ class WSAL_AuditLogListView extends WP_List_Table {
|
|
184 |
return $image . $uhtml . '<br/>' . $roles;
|
185 |
case 'scip':
|
186 |
$scip = $item->GetSourceIP();
|
|
|
|
|
|
|
187 |
$oips = array(); //$item->GetOtherIPs();
|
188 |
// if there's no IP...
|
189 |
if (is_null($scip) || $scip == '') return '<i>unknown</i>';
|
@@ -301,38 +311,55 @@ class WSAL_AuditLogListView extends WP_List_Table {
|
|
301 |
|
302 |
//$this->process_bulk_action();
|
303 |
|
304 |
-
|
|
|
|
|
305 |
$bid = (int)$this->get_view_site_id();
|
306 |
-
if ($bid)
|
307 |
-
|
|
|
308 |
|
309 |
$query = apply_filters('wsal_auditlog_query', $query);
|
310 |
|
311 |
-
$total_items = $query->Count();
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
$
|
319 |
-
$
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
}
|
327 |
}
|
328 |
|
329 |
/** @todo Modify $query instead */
|
330 |
/** @deprecated */
|
331 |
//$data = array_slice($data, ($this->get_pagenum() - 1) * $per_page, $per_page);
|
332 |
-
$query->
|
333 |
-
$query->
|
334 |
|
335 |
-
$this->items = $query->Execute();
|
336 |
|
337 |
$this->set_pagination_args( array(
|
338 |
'total_items' => $total_items,
|
134 |
public function get_sortable_columns(){
|
135 |
return array(
|
136 |
'read' => array('is_read', false),
|
137 |
+
//'code' => array('code', false),
|
138 |
'type' => array('alert_id', false),
|
139 |
'crtd' => array('created_on', true),
|
140 |
+
'user' => array('user', true),
|
141 |
+
'scip' => array('scip', false)
|
|
|
142 |
);
|
143 |
}
|
144 |
|
145 |
public function column_default($item, $column_name){
|
146 |
+
//example: $item->getMetaValue('CurrentUserID')
|
147 |
+
|
148 |
+
if (!$this->_plugin->settings->GetDatetimeFormat()) $datetimeFormat = 'h:i:s.$$$&\n\b\s\p;A';
|
149 |
+
else $datetimeFormat = 'H:i:s.$$$';
|
150 |
switch($column_name){
|
151 |
case 'read':
|
152 |
return '<span class="log-read log-read-'
|
166 |
str_replace(
|
167 |
'$$$',
|
168 |
substr(number_format(fmod($item->created_on + $this->_gmt_offset_sec, 1), 3), 2),
|
169 |
+
date('Y-m-d<\b\r>'.$datetimeFormat, $item->created_on + $this->_gmt_offset_sec)
|
170 |
)
|
171 |
) : '<i>unknown</i>';
|
172 |
case 'user':
|
173 |
$username = $item->GetUsername();
|
174 |
+
if ($username && ($user = get_user_by('login', $username))) {
|
175 |
$image = get_avatar($user->ID, 32);
|
176 |
$uhtml = '<a href="' . admin_url('user-edit.php?user_id=' . $user->ID)
|
177 |
. '" target="_blank">' . esc_html($user->display_name) . '</a>';
|
178 |
$roles = $item->GetUserRoles();
|
179 |
+
if (is_array($roles) && count($roles)) {
|
180 |
+
$roles = __(esc_html(ucwords(implode(', ', $roles))));
|
181 |
+
} else if (is_string($roles) && $roles != '') {
|
182 |
+
$roles = __(esc_html(ucwords(str_replace(array("\"", "[", "]"), " ", $roles))));
|
183 |
+
} else {
|
184 |
+
$roles = '<i>' . __('Unknown', 'wp-security-audit-log') . '</i>';
|
185 |
+
}
|
186 |
+
} else {
|
187 |
$image = get_avatar(0, 32);
|
188 |
$uhtml = '<i>' . __('Unknown', 'wp-security-audit-log') . '</i>';
|
189 |
$roles = '<i>' . __('System', 'wp-security-audit-log') . '</i>';
|
191 |
return $image . $uhtml . '<br/>' . $roles;
|
192 |
case 'scip':
|
193 |
$scip = $item->GetSourceIP();
|
194 |
+
if (is_string($scip)) {
|
195 |
+
$scip = str_replace(array("\"", "[", "]"), "", $scip);
|
196 |
+
}
|
197 |
$oips = array(); //$item->GetOtherIPs();
|
198 |
// if there's no IP...
|
199 |
if (is_null($scip) || $scip == '') return '<i>unknown</i>';
|
311 |
|
312 |
//$this->process_bulk_action();
|
313 |
|
314 |
+
//TO DO: Get rid of OccurrenceQuery and use the Occurence Model
|
315 |
+
$query = new WSAL_Models_OccurrenceQuery();
|
316 |
+
|
317 |
$bid = (int)$this->get_view_site_id();
|
318 |
+
if ($bid) {
|
319 |
+
$query->addCondition("site_id = %s ", $bid);
|
320 |
+
}
|
321 |
|
322 |
$query = apply_filters('wsal_auditlog_query', $query);
|
323 |
|
324 |
+
$total_items = $query->getAdapter()->Count($query);
|
325 |
+
|
326 |
+
if (empty($_REQUEST["orderby"])) {
|
327 |
+
$query->addOrderBy("created_on", true);
|
328 |
+
} else {
|
329 |
+
$orderByField = $_REQUEST["orderby"];
|
330 |
+
|
331 |
+
$isDescending = true;
|
332 |
+
if (!empty($_REQUEST['order']) && $_REQUEST["order"] == "asc") {
|
333 |
+
$isDescending = false;
|
334 |
+
}
|
335 |
+
|
336 |
+
//TO DO: Allow order by meta values
|
337 |
+
if ($orderByField == "scip") {
|
338 |
+
$query->addMetaJoin();
|
339 |
+
$query->addOrderBy('CASE WHEN meta.name = "ClientIP" THEN meta.value END', $isDescending);
|
340 |
+
} else if ($orderByField == "user") {
|
341 |
+
$query->addMetaJoin();
|
342 |
+
$query->addOrderBy('CASE WHEN meta.name = "CurrentUserID" THEN meta.value END', $isDescending);
|
343 |
+
} else {
|
344 |
+
$tmp = new WSAL_Models_Occurrence();
|
345 |
+
//Making sure the field exists to order by
|
346 |
+
if (isset($tmp->{$orderByField})) {
|
347 |
+
// TODO we used to use a custom comparator ... is it safe to let MySQL do the ordering now?
|
348 |
+
$query->addOrderBy($_REQUEST["orderby"], $isDescending);
|
349 |
+
|
350 |
+
} else {
|
351 |
+
$query->addOrderBy("created_on", true);
|
352 |
+
}
|
353 |
}
|
354 |
}
|
355 |
|
356 |
/** @todo Modify $query instead */
|
357 |
/** @deprecated */
|
358 |
//$data = array_slice($data, ($this->get_pagenum() - 1) * $per_page, $per_page);
|
359 |
+
$query->setOffset(($this->get_pagenum() - 1) * $per_page);
|
360 |
+
$query->setLimit($per_page);
|
361 |
|
362 |
+
$this->items = $query->getAdapter()->Execute($query);
|
363 |
|
364 |
$this->set_pagination_args( array(
|
365 |
'total_items' => $total_items,
|
classes/Connector/AbstractConnector.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once('ConnectorInterface.php');
|
3 |
+
|
4 |
+
abstract class WSAL_Connector_AbstractConnector
|
5 |
+
{
|
6 |
+
protected $connection = null;
|
7 |
+
protected $adaptersBasePath = null;
|
8 |
+
protected $adaptersDirName = null;
|
9 |
+
|
10 |
+
public function __construct($adaptersDirName = null)
|
11 |
+
{
|
12 |
+
$this->adaptersBasePath = __DIR__ . DIRECTORY_SEPARATOR .'..'. DIRECTORY_SEPARATOR .'Models'. DIRECTORY_SEPARATOR .'Adapters'. DIRECTORY_SEPARATOR;
|
13 |
+
|
14 |
+
require_once($this->adaptersBasePath . 'ActiveRecordInterface.php');
|
15 |
+
require_once($this->adaptersBasePath . 'MetaInterface.php');
|
16 |
+
require_once($this->adaptersBasePath . 'OccurrenceInterface.php');
|
17 |
+
require_once($this->adaptersBasePath . 'QueryInterface.php');
|
18 |
+
|
19 |
+
if (!empty($adaptersDirName)) {
|
20 |
+
$this->adaptersDirName = $adaptersDirName;
|
21 |
+
require_once($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . 'ActiveRecordAdapter.php');
|
22 |
+
require_once($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . 'MetaAdapter.php');
|
23 |
+
require_once($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . 'OccurrenceAdapter.php');
|
24 |
+
require_once($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . 'QueryAdapter.php');
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getAdaptersDirectory()
|
29 |
+
{
|
30 |
+
if (!empty($this->adaptersBasePath) && !empty($this->adaptersDirName)) {
|
31 |
+
return $this->adaptersBasePath . $this->adaptersDirName;
|
32 |
+
} else {
|
33 |
+
return false;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
}
|
classes/Connector/ConnectorFactory.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once(__DIR__ . DIRECTORY_SEPARATOR .'..'. DIRECTORY_SEPARATOR .'Settings.php');
|
3 |
+
require_once('MySQLDBConnector.php');
|
4 |
+
|
5 |
+
abstract class WSAL_Connector_ConnectorFactory
|
6 |
+
{
|
7 |
+
public static $connector;
|
8 |
+
public static $defaultConnector;
|
9 |
+
public static $adapter;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Returns the a default WPDB connector for saving options
|
13 |
+
*/
|
14 |
+
public static function GetDefaultConnector()
|
15 |
+
{
|
16 |
+
return new WSAL_Connector_MySQLDB();
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Returns a connector singleton
|
21 |
+
* @return WSAL_Connector_ConnectorInterface
|
22 |
+
*/
|
23 |
+
public static function GetConnector()
|
24 |
+
{
|
25 |
+
$connectionConfig = self::GetConfig();
|
26 |
+
//TO DO: Load connection config
|
27 |
+
|
28 |
+
if (self::$connector == null) {
|
29 |
+
switch (strtolower($connectionConfig['type'])) {
|
30 |
+
//TO DO: Add other connectors
|
31 |
+
case 'mysql':
|
32 |
+
default:
|
33 |
+
//use config
|
34 |
+
self::$connector = new WSAL_Connector_MySQLDB($connectionConfig);
|
35 |
+
}
|
36 |
+
}
|
37 |
+
return self::$connector;
|
38 |
+
}
|
39 |
+
|
40 |
+
public static function GetConfig()
|
41 |
+
{
|
42 |
+
$conf = new WSAL_Settings(new WpSecurityAuditLog());
|
43 |
+
$type = $conf->GetAdapterConfig('adapter-type');
|
44 |
+
if (empty($type)) {
|
45 |
+
return null;
|
46 |
+
} else {
|
47 |
+
return array(
|
48 |
+
'type' => $conf->GetAdapterConfig('adapter-type'),
|
49 |
+
'user' => $conf->GetAdapterConfig('adapter-user'),
|
50 |
+
'password' => $conf->GetAdapterConfig('adapter-password'),
|
51 |
+
'name' => $conf->GetAdapterConfig('adapter-name'),
|
52 |
+
'hostname' => $conf->GetAdapterConfig('adapter-hostname'),
|
53 |
+
'base_prefix' => $conf->GetAdapterConfig('adapter-base-prefix')
|
54 |
+
);
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
public static function CheckConfig($type, $user, $password, $name, $hostname, $base_prefix)
|
59 |
+
{
|
60 |
+
$result = false;
|
61 |
+
$config = array(
|
62 |
+
'user' => $user,
|
63 |
+
'password' => $password,
|
64 |
+
'name' => $name,
|
65 |
+
'hostname' => $hostname,
|
66 |
+
'base_prefix' => $base_prefix
|
67 |
+
);
|
68 |
+
switch (strtolower($type)) {
|
69 |
+
//TO DO: Add other connectors
|
70 |
+
case 'mysql':
|
71 |
+
default:
|
72 |
+
$test = new WSAL_Connector_MySQLDB($config);
|
73 |
+
$result = $test->TestConnection();
|
74 |
+
}
|
75 |
+
return $result;
|
76 |
+
}
|
77 |
+
}
|
classes/Connector/ConnectorInterface.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
interface WSAL_Connector_ConnectorInterface
|
4 |
+
{
|
5 |
+
public function getAdapter($class_name);
|
6 |
+
public function getConnection();
|
7 |
+
public function isInstalled();
|
8 |
+
public function canMigrate();
|
9 |
+
public function installAll();
|
10 |
+
public function uninstallAll();
|
11 |
+
}
|
classes/Connector/MySQLDBConnector.php
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once('ConnectorInterface.php');
|
3 |
+
require_once('AbstractConnector.php');
|
4 |
+
|
5 |
+
|
6 |
+
class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements WSAL_Connector_ConnectorInterface
|
7 |
+
{
|
8 |
+
protected $connectionConfig = null;
|
9 |
+
public function __construct($connectionConfig = null)
|
10 |
+
{
|
11 |
+
$this->connectionConfig = $connectionConfig;
|
12 |
+
parent::__construct("MySQL");
|
13 |
+
require_once($this->getAdaptersDirectory() . '/OptionAdapter.php');
|
14 |
+
}
|
15 |
+
|
16 |
+
function test_wp_die_callback() {
|
17 |
+
return array( $this, 'test_die_handler' );
|
18 |
+
}
|
19 |
+
|
20 |
+
function test_die_handler( $message, $title = '', $args = array() ) {
|
21 |
+
throw new Exception("DB Connection failed");
|
22 |
+
}
|
23 |
+
|
24 |
+
public function TestConnection()
|
25 |
+
{
|
26 |
+
error_reporting(E_ALL ^ E_WARNING);
|
27 |
+
add_filter( 'wp_die_handler', array( $this, 'test_wp_die_callback' ) );
|
28 |
+
$connection = $this->createConnection();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Creates a connection and returns it
|
33 |
+
* @return Instance of WPDB
|
34 |
+
*/
|
35 |
+
private function createConnection()
|
36 |
+
{
|
37 |
+
if (!empty($this->connectionConfig)) {
|
38 |
+
//TO DO: Use the provided connection config
|
39 |
+
$connectionConfig = $this->connectionConfig;
|
40 |
+
$newWpdb = new wpdb($connectionConfig['user'], $connectionConfig['password'], $connectionConfig['name'], $connectionConfig['hostname']);
|
41 |
+
$newWpdb->set_prefix($connectionConfig['base_prefix']);
|
42 |
+
return $newWpdb;
|
43 |
+
} else {
|
44 |
+
global $wpdb;
|
45 |
+
return $wpdb;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Returns a wpdb instance
|
51 |
+
*/
|
52 |
+
public function getConnection()
|
53 |
+
{
|
54 |
+
if (!empty($this->connection)) {
|
55 |
+
return $this->connection;
|
56 |
+
} else {
|
57 |
+
$this->connection = $this->createConnection();
|
58 |
+
return $this->connection;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Gets an adapter for the specified model
|
64 |
+
*/
|
65 |
+
public function getAdapter($class_name)
|
66 |
+
{
|
67 |
+
$objName = $this->getAdapterClassName($class_name);
|
68 |
+
return new $objName($this->getConnection());
|
69 |
+
}
|
70 |
+
|
71 |
+
protected function getAdapterClassName($class_name)
|
72 |
+
{
|
73 |
+
return 'WSAL_Adapters_MySQL_'.$class_name;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Checks if the necessary tables are available
|
78 |
+
*/
|
79 |
+
public function isInstalled()
|
80 |
+
{
|
81 |
+
$wpdb = $this->getConnection();
|
82 |
+
$table = $wpdb->base_prefix . 'wsal_occurrences';
|
83 |
+
return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Checks if old version tables are available
|
88 |
+
*/
|
89 |
+
public function canMigrate()
|
90 |
+
{
|
91 |
+
$wpdb = $this->getConnection();
|
92 |
+
$table = $wpdb->base_prefix . 'wordpress_auditlog_events';
|
93 |
+
return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Install all DB tables.
|
98 |
+
*/
|
99 |
+
public function installAll()
|
100 |
+
{
|
101 |
+
$plugin = WpSecurityAuditLog::GetInstance();
|
102 |
+
|
103 |
+
foreach (glob($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . '*.php') as $file) {
|
104 |
+
$filePath = explode(DIRECTORY_SEPARATOR, $file);
|
105 |
+
$fileName = $filePath[count($filePath) - 1];
|
106 |
+
$className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
|
107 |
+
|
108 |
+
$class = new $className($this->getConnection());
|
109 |
+
if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
|
110 |
+
$class->Install();
|
111 |
+
}
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Uninstall all DB tables.
|
117 |
+
*/
|
118 |
+
public function uninstallAll()
|
119 |
+
{
|
120 |
+
$plugin = WpSecurityAuditLog::GetInstance();
|
121 |
+
|
122 |
+
foreach (glob($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . '*.php') as $file) {
|
123 |
+
$filePath = explode(DIRECTORY_SEPARATOR, $file);
|
124 |
+
$fileName = $filePath[count($filePath) - 1];
|
125 |
+
$className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
|
126 |
+
|
127 |
+
$class = new $className($this->getConnection());
|
128 |
+
if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
|
129 |
+
$class->Uninstall();
|
130 |
+
}
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
}
|
classes/DB/ActiveRecord.php
DELETED
@@ -1,472 +0,0 @@
|
|
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 |
-
$class = get_class($this);
|
43 |
-
$copy = new $class();
|
44 |
-
|
45 |
-
$sql = 'CREATE TABLE ' . $this->GetTable() . ' (' . PHP_EOL;
|
46 |
-
|
47 |
-
foreach($this->GetColumns() as $key) {
|
48 |
-
$sql .= ' ';
|
49 |
-
switch(true) {
|
50 |
-
case $key == $copy->_idkey:
|
51 |
-
$sql .= $key . ' BIGINT NOT NULL AUTO_INCREMENT,' . PHP_EOL;
|
52 |
-
break;
|
53 |
-
case is_integer($copy->$key):
|
54 |
-
$sql .= $key . ' BIGINT NOT NULL,' . PHP_EOL;
|
55 |
-
break;
|
56 |
-
case is_float($copy->$key):
|
57 |
-
$sql .= $key . ' DOUBLE NOT NULL,' . PHP_EOL;
|
58 |
-
break;
|
59 |
-
case is_string($copy->$key):
|
60 |
-
$maxlength = $key . '_maxlength';
|
61 |
-
if(property_exists($class, $maxlength)){
|
62 |
-
$sql .= $key . ' VARCHAR(' . intval($class::$$maxlength) . ') NOT NULL,' . PHP_EOL;
|
63 |
-
}else{
|
64 |
-
$sql .= $key . ' TEXT NOT NULL,' . PHP_EOL;
|
65 |
-
}
|
66 |
-
break;
|
67 |
-
case is_bool($copy->$key):
|
68 |
-
$sql .= $key . ' BIT NOT NULL,' . PHP_EOL;
|
69 |
-
break;
|
70 |
-
case is_array($copy->$key):
|
71 |
-
case is_object($copy->$key):
|
72 |
-
$sql .= $key . ' LONGTEXT NOT NULL,' . PHP_EOL;
|
73 |
-
break;
|
74 |
-
}
|
75 |
-
}
|
76 |
-
|
77 |
-
$sql .= $this->GetTableOptions() . PHP_EOL;
|
78 |
-
|
79 |
-
$sql .= ')';
|
80 |
-
|
81 |
-
if ( ! empty($wpdb->charset) )
|
82 |
-
$sql .= ' DEFAULT CHARACTER SET ' . $wpdb->charset;
|
83 |
-
if ( ! empty($wpdb->collate) )
|
84 |
-
$sql .= ' COLLATE ' . $wpdb->collate;
|
85 |
-
|
86 |
-
return $sql;
|
87 |
-
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* @return string Must return SQL for removing table (at a minimum, it should be ` 'DROP TABLE ' . $this->_table `).
|
92 |
-
*/
|
93 |
-
protected function _GetUninstallQuery(){
|
94 |
-
return 'DROP TABLE ' . $this->GetTable();
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* A wrapper for JSON encoding that fixes potential issues.
|
99 |
-
* @param mixed $data The data to encode.
|
100 |
-
* @return string JSON string.
|
101 |
-
*/
|
102 |
-
protected function _JsonEncode($data){
|
103 |
-
return @json_encode($data);
|
104 |
-
}
|
105 |
-
|
106 |
-
/**
|
107 |
-
* A wrapper for JSON encoding that fixes potential issues.
|
108 |
-
* @param string $data The JSON string to decode.
|
109 |
-
* @return mixed Decoded data.
|
110 |
-
*/
|
111 |
-
protected function _JsonDecode($data){
|
112 |
-
return @json_decode($data);
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* @return string Returns table name.
|
117 |
-
*/
|
118 |
-
public function GetTable(){
|
119 |
-
global $wpdb;
|
120 |
-
return $wpdb->base_prefix . $this->_table;
|
121 |
-
}
|
122 |
-
|
123 |
-
/**
|
124 |
-
* @return string SQL table options (constraints, foreign keys, indexes etc).
|
125 |
-
*/
|
126 |
-
protected function GetTableOptions(){
|
127 |
-
return ' PRIMARY KEY (' . $this->_idkey . ')';
|
128 |
-
}
|
129 |
-
|
130 |
-
/**
|
131 |
-
* @return array Returns this records' columns.
|
132 |
-
*/
|
133 |
-
public function GetColumns(){
|
134 |
-
if(!isset($this->_column_cache)){
|
135 |
-
$this->_column_cache = array();
|
136 |
-
foreach(array_keys(get_object_vars($this)) as $col)
|
137 |
-
if(trim($col) && $col[0] != '_')
|
138 |
-
$this->_column_cache[] = $col;
|
139 |
-
}
|
140 |
-
return $this->_column_cache;
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* @deprecated
|
145 |
-
* @return boolean Returns whether table structure is installed or not.
|
146 |
-
*/
|
147 |
-
public function IsInstalled(){
|
148 |
-
global $wpdb;
|
149 |
-
$sql = 'SHOW TABLES LIKE "' . $this->GetTable() . '"';
|
150 |
-
return $wpdb->get_var($sql) == $this->GetTable();
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Install this ActiveRecord structure into DB.
|
155 |
-
*/
|
156 |
-
public function Install(){
|
157 |
-
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
158 |
-
dbDelta($this->_GetInstallQuery());
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Remove this ActiveRecord structure into DB.
|
163 |
-
*/
|
164 |
-
public function Uninstall()
|
165 |
-
{
|
166 |
-
global $wpdb;
|
167 |
-
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
168 |
-
$wpdb->query($this->_GetUninstallQuery());
|
169 |
-
}
|
170 |
-
|
171 |
-
/**
|
172 |
-
* Save record to DB.
|
173 |
-
* @return integer|boolean Either the number of modified/inserted rows or false on failure.
|
174 |
-
*/
|
175 |
-
public function Save(){
|
176 |
-
$this->_state = self::STATE_UNKNOWN;
|
177 |
-
global $wpdb;
|
178 |
-
$copy = get_class($this);
|
179 |
-
$copy = new $copy;
|
180 |
-
$data = array();
|
181 |
-
$format = array();
|
182 |
-
foreach($this->GetColumns() as $key){
|
183 |
-
$val = $this->$key;
|
184 |
-
$deffmt = '%s';
|
185 |
-
if(is_int($copy->$key))$deffmt = '%d';
|
186 |
-
if(is_float($copy->$key))$deffmt = '%f';
|
187 |
-
if(is_array($copy->$key) || is_object($copy->$key)){
|
188 |
-
$data[$key] = $this->_JsonEncode($val);
|
189 |
-
}else{
|
190 |
-
$data[$key] = $val;
|
191 |
-
}
|
192 |
-
$format[] = $deffmt;
|
193 |
-
}
|
194 |
-
$result = $wpdb->replace($this->GetTable(), $data, $format);
|
195 |
-
if($wpdb->insert_id){
|
196 |
-
$this->{$this->_idkey} = $wpdb->insert_id;
|
197 |
-
if($result !== false)
|
198 |
-
$this->_state = self::STATE_CREATED;
|
199 |
-
}else{
|
200 |
-
if($result !== false)
|
201 |
-
$this->_state = self::STATE_UPDATED;
|
202 |
-
}
|
203 |
-
return $result;
|
204 |
-
}
|
205 |
-
|
206 |
-
/**
|
207 |
-
* Load record from DB.
|
208 |
-
* @param string $cond (Optional) Load condition.
|
209 |
-
* @param array $args (Optional) Load condition arguments.
|
210 |
-
*/
|
211 |
-
public function Load($cond = '%d', $args = array(1)){
|
212 |
-
global $wpdb;
|
213 |
-
|
214 |
-
$this->_state = self::STATE_UNKNOWN;
|
215 |
-
|
216 |
-
$sql = $wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '.$cond, $args);
|
217 |
-
$data = $wpdb->get_row($sql, ARRAY_A);
|
218 |
-
|
219 |
-
if(!is_null($data)){
|
220 |
-
$this->LoadData($data);
|
221 |
-
$this->_state = self::STATE_LOADED;
|
222 |
-
}
|
223 |
-
}
|
224 |
-
|
225 |
-
/**
|
226 |
-
* Load object data from variable.
|
227 |
-
* @param array|object $data Data array or object.
|
228 |
-
*/
|
229 |
-
public function LoadData($data){
|
230 |
-
$copy = get_class($this);
|
231 |
-
$copy = new $copy;
|
232 |
-
foreach((array)$data as $key => $val){
|
233 |
-
if(isset($copy->$key)){
|
234 |
-
switch(true){
|
235 |
-
case is_array($copy->$key):
|
236 |
-
case is_object($copy->$key):
|
237 |
-
$this->$key = $this->_JsonDecode($val);
|
238 |
-
break;
|
239 |
-
case is_int($copy->$key):
|
240 |
-
$this->$key = (int)$val;
|
241 |
-
break;
|
242 |
-
case is_float($copy->$key):
|
243 |
-
$this->$key = (float)$val;
|
244 |
-
break;
|
245 |
-
case is_bool($copy->$key):
|
246 |
-
$this->$key = (bool)$val;
|
247 |
-
break;
|
248 |
-
case is_string($copy->$key):
|
249 |
-
$this->$key = (string)$val;
|
250 |
-
break;
|
251 |
-
default:
|
252 |
-
throw new Exception('Unsupported type "'.gettype($copy->$key).'"');
|
253 |
-
}
|
254 |
-
}
|
255 |
-
}
|
256 |
-
}
|
257 |
-
|
258 |
-
/**
|
259 |
-
* Delete DB record.
|
260 |
-
* @return int|boolean Either the amount of deleted rows or False on error.
|
261 |
-
*/
|
262 |
-
public function Delete(){
|
263 |
-
global $wpdb;
|
264 |
-
|
265 |
-
$this->_state = self::STATE_UNKNOWN;
|
266 |
-
|
267 |
-
$result = $wpdb->delete(
|
268 |
-
$this->GetTable(),
|
269 |
-
array($this->_idkey => $this->{$this->_idkey})
|
270 |
-
);
|
271 |
-
|
272 |
-
if($result !== false)
|
273 |
-
$this->_state = self::STATE_DELETED;
|
274 |
-
|
275 |
-
return $result;
|
276 |
-
}
|
277 |
-
|
278 |
-
/**
|
279 |
-
* Delete records in DB matching a query.
|
280 |
-
* @param string $query Full SQL query.
|
281 |
-
* @param array $args (Optional) Query arguments.
|
282 |
-
*/
|
283 |
-
public static function DeleteQuery($query, $args = array()){
|
284 |
-
global $wpdb;
|
285 |
-
$sql = count($args) ? $wpdb->prepare($query, $args) : $query;
|
286 |
-
$wpdb->query($sql);
|
287 |
-
}
|
288 |
-
|
289 |
-
/**
|
290 |
-
* Load multiple records from DB.
|
291 |
-
* @param string $cond (Optional) Load condition (eg: 'some_id = %d' ).
|
292 |
-
* @param array $args (Optional) Load condition arguments (rg: array(45) ).
|
293 |
-
* @return self[] List of loaded records.
|
294 |
-
*/
|
295 |
-
public static function LoadMulti($cond, $args = array()){
|
296 |
-
global $wpdb;
|
297 |
-
$class = get_called_class();
|
298 |
-
$result = array();
|
299 |
-
$temp = new $class();
|
300 |
-
$sql = (!is_array($args) || !count($args)) // do we really need to prepare() or not?
|
301 |
-
? ('SELECT * FROM ' . $temp->GetTable() . ' WHERE ' . $cond)
|
302 |
-
: $wpdb->prepare('SELECT * FROM ' . $temp->GetTable() . ' WHERE ' . $cond, $args)
|
303 |
-
;
|
304 |
-
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
305 |
-
$result[] = new $class($data);
|
306 |
-
}
|
307 |
-
return $result;
|
308 |
-
}
|
309 |
-
|
310 |
-
/**
|
311 |
-
* Load multiple records from DB and call a callback for each record.
|
312 |
-
* This function is very memory-efficient, it doesn't load records in bulk.
|
313 |
-
* @param callable $callback The callback to invoke.
|
314 |
-
* @param string $cond (Optional) Load condition.
|
315 |
-
* @param array $args (Optional) Load condition arguments.
|
316 |
-
*/
|
317 |
-
public static function LoadAndCallForEach($callback, $cond = '%d', $args = array(1)){
|
318 |
-
global $wpdb;
|
319 |
-
$class = get_called_class();
|
320 |
-
$temp = new $class();
|
321 |
-
$sql = $wpdb->prepare('SELECT * FROM ' . $temp->GetTable() . ' WHERE '.$cond, $args);
|
322 |
-
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
323 |
-
call_user_func($callback, new $class($data));
|
324 |
-
}
|
325 |
-
}
|
326 |
-
|
327 |
-
/**
|
328 |
-
* Count records in the DB matching a condition.
|
329 |
-
* If no parameters are given, this counts the number of records in the DB table.
|
330 |
-
* @param string $cond (Optional) Query condition.
|
331 |
-
* @param array $args (Optional) Condition arguments.
|
332 |
-
* @return int Number of matching records.
|
333 |
-
*/
|
334 |
-
public static function Count($cond = '%d', $args = array(1)){
|
335 |
-
global $wpdb;
|
336 |
-
$class = get_called_class();
|
337 |
-
$temp = new $class();
|
338 |
-
$sql = $wpdb->prepare('SELECT COUNT(*) FROM ' . $temp->GetTable() . ' WHERE ' . $cond, $args);
|
339 |
-
return (int)$wpdb->get_var($sql);
|
340 |
-
}
|
341 |
-
|
342 |
-
/**
|
343 |
-
* Count records in the DB matching a query.
|
344 |
-
* @param string $query Full SQL query.
|
345 |
-
* @param array $args (Optional) Query arguments.
|
346 |
-
* @return int Number of matching records.
|
347 |
-
*/
|
348 |
-
public static function CountQuery($query, $args = array()){
|
349 |
-
global $wpdb;
|
350 |
-
$sql = count($args) ? $wpdb->prepare($query, $args) : $query;
|
351 |
-
return (int)$wpdb->get_var($sql);
|
352 |
-
}
|
353 |
-
|
354 |
-
/**
|
355 |
-
* Similar to LoadMulti but allows the use of a full SQL query.
|
356 |
-
* @param string $query Full SQL query.
|
357 |
-
* @param array $args (Optional) Query arguments.
|
358 |
-
* @return self[] List of loaded records.
|
359 |
-
*/
|
360 |
-
public static function LoadMultiQuery($query, $args = array()){
|
361 |
-
global $wpdb;
|
362 |
-
$class = get_called_class();
|
363 |
-
$result = array();
|
364 |
-
$sql = count($args) ? $wpdb->prepare($query, $args) : $query;
|
365 |
-
foreach($wpdb->get_results($sql, ARRAY_A) as $data){
|
366 |
-
$result[] = new $class($data);
|
367 |
-
}
|
368 |
-
return $result;
|
369 |
-
}
|
370 |
-
|
371 |
-
/**
|
372 |
-
* Install all DB tables.
|
373 |
-
*/
|
374 |
-
public static function InstallAll(){
|
375 |
-
$plugin = WpSecurityAuditLog::GetInstance();
|
376 |
-
foreach(glob(dirname(__FILE__) . '/*.php') as $file){
|
377 |
-
$class = $plugin->GetClassFileClassName($file);
|
378 |
-
if(is_subclass_of($class, __CLASS__)){
|
379 |
-
$class = new $class();
|
380 |
-
$class->Install();
|
381 |
-
}
|
382 |
-
}
|
383 |
-
}
|
384 |
-
|
385 |
-
/**
|
386 |
-
* Uninstall all DB tables.
|
387 |
-
*/
|
388 |
-
public static function UninstallAll(){
|
389 |
-
$plugin = WpSecurityAuditLog::GetInstance();
|
390 |
-
foreach(glob(dirname(__FILE__) . '/*.php') as $file){
|
391 |
-
$class = $plugin->GetClassFileClassName($file);
|
392 |
-
if(is_subclass_of($class, __CLASS__)) {
|
393 |
-
$class = new $class();
|
394 |
-
$class->Uninstall();
|
395 |
-
}
|
396 |
-
}
|
397 |
-
}
|
398 |
-
|
399 |
-
/**
|
400 |
-
* @return boolean
|
401 |
-
*/
|
402 |
-
public function IsLoaded(){
|
403 |
-
return $this->_state == self::STATE_LOADED;
|
404 |
-
}
|
405 |
-
|
406 |
-
/**
|
407 |
-
* @return boolean
|
408 |
-
*/
|
409 |
-
public function IsSaved(){
|
410 |
-
return $this->_state == self::STATE_CREATED
|
411 |
-
|| $this->_state == self::STATE_UPDATED;
|
412 |
-
}
|
413 |
-
|
414 |
-
/**
|
415 |
-
* @return boolean
|
416 |
-
*/
|
417 |
-
public function IsCreated(){
|
418 |
-
return $this->_state == self::STATE_CREATED;
|
419 |
-
}
|
420 |
-
|
421 |
-
/**
|
422 |
-
* @return boolean
|
423 |
-
*/
|
424 |
-
public function IsUpdated(){
|
425 |
-
return $this->_state == self::STATE_UPDATED;
|
426 |
-
}
|
427 |
-
|
428 |
-
/**
|
429 |
-
* @return boolean
|
430 |
-
*/
|
431 |
-
public function IsDeleted(){
|
432 |
-
return $this->_state == self::STATE_DELETED;
|
433 |
-
}
|
434 |
-
|
435 |
-
protected static $_cache = array();
|
436 |
-
|
437 |
-
/**
|
438 |
-
* Load ActiveRecord from DB or cache.
|
439 |
-
* @param string $target ActiveRecord class name.
|
440 |
-
* @param string $query Load condition.
|
441 |
-
* @param array $args Arguments used in condition.
|
442 |
-
* @return WSAL_DB_ActiveRecord
|
443 |
-
*/
|
444 |
-
protected static function CacheLoad($target, $query, $args){
|
445 |
-
$index = $target . '::' . vsprintf($query, $args);
|
446 |
-
if(!isset(self::$_cache[$index])){
|
447 |
-
self::$_cache[$index] = new $target();
|
448 |
-
self::$_cache[$index]->Load($query, $args);
|
449 |
-
}
|
450 |
-
return self::$_cache[$index];
|
451 |
-
}
|
452 |
-
|
453 |
-
/**
|
454 |
-
* Remove ActiveRecord cache.
|
455 |
-
* @param string $target ActiveRecord class name.
|
456 |
-
* @param string $query Load condition.
|
457 |
-
* @param array $args Arguments used in condition.
|
458 |
-
*/
|
459 |
-
protected static function CacheRemove($target, $query, $args){
|
460 |
-
$index = $target . '::' . sprintf($query, $args);
|
461 |
-
if(!isset(self::$_cache[$index])){
|
462 |
-
unset(self::$_cache[$index]);
|
463 |
-
}
|
464 |
-
}
|
465 |
-
|
466 |
-
/**
|
467 |
-
* Clear the cache.
|
468 |
-
*/
|
469 |
-
protected static function CacheClear(){
|
470 |
-
self::$_cache = array();
|
471 |
-
}
|
472 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/DB/Meta.php
DELETED
@@ -1,17 +0,0 @@
|
|
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 static $name_maxlength = 100;
|
11 |
-
public $value = array(); // force mixed type
|
12 |
-
|
13 |
-
protected function GetTableOptions(){
|
14 |
-
return parent::GetTableOptions() . ',' . PHP_EOL
|
15 |
-
. ' KEY occurrence_name (occurrence_id,name)';
|
16 |
-
}
|
17 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/DB/Occurrence.php
DELETED
@@ -1,211 +0,0 @@
|
|
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.0;
|
11 |
-
public $is_read = false;
|
12 |
-
public $is_migrated = false;
|
13 |
-
|
14 |
-
protected function GetTableOptions(){
|
15 |
-
return parent::GetTableOptions() . ',' . PHP_EOL
|
16 |
-
. ' KEY site_alert_created (site_id,alert_id,created_on)';
|
17 |
-
}
|
18 |
-
|
19 |
-
protected $_meta;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Returns all meta data related to this event.
|
23 |
-
* @return WSAL_DB_Meta[]
|
24 |
-
*/
|
25 |
-
public function GetMeta(){
|
26 |
-
if(!isset($this->_meta)){
|
27 |
-
$this->_meta = WSAL_DB_Meta::LoadMulti('occurrence_id = %d', array($this->id));
|
28 |
-
}
|
29 |
-
return $this->_meta;
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Loads a meta item given its name.
|
34 |
-
* @param string $name Meta name.
|
35 |
-
* @return WSAL_DB_Meta The meta item, be sure to checked if it was loaded successfully.
|
36 |
-
*/
|
37 |
-
public function GetNamedMeta($name){
|
38 |
-
$meta = new WSAL_DB_Meta();
|
39 |
-
$meta->Load('occurrence_id = %d AND name = %s', array($this->id, $name));
|
40 |
-
return $meta;
|
41 |
-
}
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Returns the first meta value from a given set of names. Useful when you have a mix of items that could provide a particular detail.
|
45 |
-
* @param array $names List of meta names.
|
46 |
-
* @return WSAL_DB_Meta The first meta item that exists.
|
47 |
-
*/
|
48 |
-
public function GetFirstNamedMeta($names){
|
49 |
-
$meta = new WSAL_DB_Meta();
|
50 |
-
$query = '(' . str_repeat('name = %s OR ', count($names)).'0)';
|
51 |
-
$query = 'occurrence_id = %d AND ' . $query . ' ORDER BY name DESC LIMIT 1';
|
52 |
-
array_unshift($names, $this->id); // prepend args with occurrence id
|
53 |
-
$meta->Load($query, $names);
|
54 |
-
return $meta->IsLoaded() ? $meta : null;
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Returns the alert related to this occurrence.
|
59 |
-
* @return WSAL_Alert
|
60 |
-
*/
|
61 |
-
public function GetAlert(){
|
62 |
-
return WpSecurityAuditLog::GetInstance()->alerts->GetAlert($this->alert_id);
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Returns the value of a meta item.
|
67 |
-
* @param string $name Name of meta item.
|
68 |
-
* @param mixed $default Default value returned when meta does not exist.
|
69 |
-
* @return mixed The value, if meta item does not exist $default returned.
|
70 |
-
*/
|
71 |
-
public function GetMetaValue($name, $default = array()){
|
72 |
-
$meta = $this->GetNamedMeta($name);
|
73 |
-
return $meta->IsLoaded() ? $meta->value : $default;
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Set the value of a meta item (creates or updates meta item).
|
78 |
-
* @param string $name Meta name.
|
79 |
-
* @param mixed $value Meta value.
|
80 |
-
*/
|
81 |
-
public function SetMetaValue($name, $value){
|
82 |
-
$meta = $this->GetNamedMeta($name);
|
83 |
-
$meta->occurrence_id = $this->id;
|
84 |
-
$meta->name = $name;
|
85 |
-
$meta->value = $value;
|
86 |
-
$meta->Save();
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Returns a key-value pair of meta data.
|
91 |
-
* @return array
|
92 |
-
*/
|
93 |
-
public function GetMetaArray(){
|
94 |
-
$result = array();
|
95 |
-
foreach($this->GetMeta() as $meta)
|
96 |
-
$result[$meta->name] = $meta->value;
|
97 |
-
return $result;
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Creates or updates all meta data passed as an array of meta-key/meta-value pairs.
|
102 |
-
* @param array $data New meta data.
|
103 |
-
*/
|
104 |
-
public function SetMeta($data){
|
105 |
-
foreach((array)$data as $key => $val)
|
106 |
-
$this->SetMetaValue($key, $val);
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* @param callable|null $metaFormatter (Optional) Meta formatter callback.
|
111 |
-
* @return string Full-formatted message.
|
112 |
-
*/
|
113 |
-
public function GetMessage($metaFormatter = null){
|
114 |
-
if(!isset($this->_cachedmessage)){
|
115 |
-
// get correct message entry
|
116 |
-
if($this->is_migrated){
|
117 |
-
$this->_cachedmessage = $this->GetMetaValue('MigratedMesg', false);
|
118 |
-
}
|
119 |
-
if(!$this->is_migrated || !$this->_cachedmessage){
|
120 |
-
$this->_cachedmessage = $this->GetAlert()->mesg;
|
121 |
-
}
|
122 |
-
// fill variables in message
|
123 |
-
$this->_cachedmessage = $this->GetAlert()->GetMessage($this->GetMetaArray(), $metaFormatter, $this->_cachedmessage);
|
124 |
-
}
|
125 |
-
return $this->_cachedmessage;
|
126 |
-
}
|
127 |
-
|
128 |
-
/**
|
129 |
-
* Returns newest unique occurrences.
|
130 |
-
* @param integer $limit Maximum limit.
|
131 |
-
* @return WSAL_DB_Occurrence[]
|
132 |
-
*/
|
133 |
-
public static function GetNewestUnique($limit = PHP_INT_MAX){
|
134 |
-
$temp = new self();
|
135 |
-
return self::LoadMultiQuery('
|
136 |
-
SELECT *, COUNT(alert_id) as count
|
137 |
-
FROM (
|
138 |
-
SELECT *
|
139 |
-
FROM ' . $temp->GetTable() . '
|
140 |
-
ORDER BY created_on DESC
|
141 |
-
) AS temp_table
|
142 |
-
GROUP BY alert_id
|
143 |
-
LIMIT %d
|
144 |
-
', array($limit));
|
145 |
-
}
|
146 |
-
|
147 |
-
/**
|
148 |
-
* Delete occurrence as well as associated meta data.
|
149 |
-
* @return boolean True on success, false on failure.
|
150 |
-
*/
|
151 |
-
public function Delete(){
|
152 |
-
foreach($this->GetMeta() as $meta) $meta->Delete();
|
153 |
-
return parent::Delete();
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* @return string User's username.
|
158 |
-
*/
|
159 |
-
public function GetUsername(){
|
160 |
-
$meta = $this->GetFirstNamedMeta(array('Username', 'CurrentUserID'));
|
161 |
-
if($meta){
|
162 |
-
switch(true){
|
163 |
-
case $meta->name == 'Username':
|
164 |
-
return $meta->value;
|
165 |
-
case $meta->name == 'CurrentUserID':
|
166 |
-
return ($data = get_userdata($meta->value)) ? $data->user_login : null;
|
167 |
-
}
|
168 |
-
}
|
169 |
-
return null;
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* @return string IP address of request.
|
174 |
-
*/
|
175 |
-
public function GetSourceIP(){
|
176 |
-
return $this->GetMetaValue('ClientIP', '');
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* @return string IP address of request (from proxies etc).
|
181 |
-
*/
|
182 |
-
public function GetOtherIPs(){
|
183 |
-
$result = array();
|
184 |
-
$data = (array)$this->GetMetaValue('OtherIPs', array());
|
185 |
-
foreach ($data as $ips) foreach($ips as $ip) $result[] = $ip;
|
186 |
-
return array_unique($result);
|
187 |
-
}
|
188 |
-
|
189 |
-
/**
|
190 |
-
* @return array Array of user roles.
|
191 |
-
*/
|
192 |
-
public function GetUserRoles(){
|
193 |
-
return $this->GetMetaValue('CurrentUserRoles', array());
|
194 |
-
}
|
195 |
-
|
196 |
-
/**
|
197 |
-
* @return float Number of seconds (and microseconds as fraction) since unix Day 0.
|
198 |
-
* @todo This needs some caching.
|
199 |
-
*/
|
200 |
-
protected function GetMicrotime(){
|
201 |
-
return microtime(true);// + get_option('gmt_offset') * HOUR_IN_SECONDS;
|
202 |
-
}
|
203 |
-
|
204 |
-
public function Save(){
|
205 |
-
// use today's date if not set up
|
206 |
-
if(is_null($this->created_on))
|
207 |
-
$this->created_on = $this->GetMicrotime();
|
208 |
-
|
209 |
-
return parent::Save();
|
210 |
-
}
|
211 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/DB/OccurrenceQuery.php
DELETED
@@ -1,96 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class WSAL_DB_OccurrenceQuery extends WSAL_DB_Query {
|
4 |
-
const LIKE_LEFT = 'l';
|
5 |
-
const LIKE_RIGHT = 'r';
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Contains meta-specific arguments to be AND'ed together
|
9 |
-
* @var array
|
10 |
-
*/
|
11 |
-
public $meta_where = array();
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Contains arguments to be used in meta conditions.
|
15 |
-
* @var array
|
16 |
-
*/
|
17 |
-
public $meta_args = array();
|
18 |
-
|
19 |
-
public function GetCond(){
|
20 |
-
$cond = parent::GetCond();
|
21 |
-
if (count($this->meta_where)) {
|
22 |
-
$tmp = new WSAL_DB_Meta();
|
23 |
-
$cond[] = 'id IN (
|
24 |
-
SELECT DISTINCT occurrence_id
|
25 |
-
FROM ' . $tmp->GetTable() . '
|
26 |
-
WHERE ' . implode(' AND ', $this->meta_where) . '
|
27 |
-
)';
|
28 |
-
}
|
29 |
-
return $cond;
|
30 |
-
}
|
31 |
-
|
32 |
-
public function GetArgs(){
|
33 |
-
$args = parent::GetArgs();
|
34 |
-
foreach ($this->meta_args as $arg) $args[] = $arg;
|
35 |
-
return $args;
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Find occurrences matching an exact named meta value.
|
40 |
-
* @param string $name Meta name.
|
41 |
-
* @param string $value Meta value.
|
42 |
-
*/
|
43 |
-
public function WhereMetaIs($name, $value){
|
44 |
-
$this->meta_where[] = 'name = %s AND value = %s';
|
45 |
-
$this->meta_args[] = $name;
|
46 |
-
$this->meta_args[] = $value;
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Find occurrences matching a named meta containing a value.
|
51 |
-
* @param string $name Meta name.
|
52 |
-
* @param string $value Meta value.
|
53 |
-
* @param string $type Where to check for (left, right, both or none) see LIKE_* constants
|
54 |
-
*/
|
55 |
-
public function WhereMetaLike($name, $value, $type){
|
56 |
-
$this->meta_where[] = 'name = %s AND value LIKE %s';
|
57 |
-
$this->meta_args[] = $name;
|
58 |
-
$value = esc_sql($value);
|
59 |
-
if (strpos($type, self::LIKE_LEFT) !== false) $value = '%' . $value;
|
60 |
-
if (strpos($type, self::LIKE_RIGHT) !== false) $value = $value . '%';
|
61 |
-
$this->meta_args[] = $value;
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Find occurrences matching a meta condition.
|
66 |
-
* @param string $cond Meta condition.
|
67 |
-
* @param array $args Condition arguments.
|
68 |
-
*/
|
69 |
-
public function WhereMeta($cond, $args){
|
70 |
-
$this->meta_where[] = $cond;
|
71 |
-
foreach ($args as $arg) $this->meta_args[] = $arg;
|
72 |
-
}
|
73 |
-
|
74 |
-
public function Delete(){
|
75 |
-
global $wpdb;
|
76 |
-
// get relevant occurrence ids
|
77 |
-
$occids = $wpdb->get_col($this->GetSql('select'));
|
78 |
-
|
79 |
-
if (count($occids)) {
|
80 |
-
// delete meta data: back up columns, remove them for DELETE and generate sql
|
81 |
-
$cols = $this->columns;
|
82 |
-
$this->columns = array('occurrence_id');
|
83 |
-
$tmp = new WSAL_DB_Meta();
|
84 |
-
$sql = 'DELETE FROM ' . $tmp->GetTable() . ' WHERE occurrence_id IN (' . implode(',', $occids) . ')';
|
85 |
-
|
86 |
-
// restore columns
|
87 |
-
$this->columns = $cols;
|
88 |
-
|
89 |
-
// execute query
|
90 |
-
call_user_func(array($this->ar_cls, 'DeleteQuery'), $sql, $this->GetArgs());
|
91 |
-
}
|
92 |
-
|
93 |
-
// delete occurrences
|
94 |
-
parent::Delete();
|
95 |
-
}
|
96 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/DB/Option.php
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class WSAL_DB_Option extends WSAL_DB_ActiveRecord
|
4 |
-
{
|
5 |
-
protected $_table = 'wsal_options';
|
6 |
-
protected $_idkey = 'id';
|
7 |
-
|
8 |
-
public $id = 0;
|
9 |
-
public $option_name = '';
|
10 |
-
public static $option_name_maxlength = 100;
|
11 |
-
public $option_value = '';
|
12 |
-
|
13 |
-
public function SetOptionValue($name, $value)
|
14 |
-
{
|
15 |
-
$this->GetNamedOption($name);
|
16 |
-
$this->option_name = $name;
|
17 |
-
// Serialize if $value is array or object
|
18 |
-
$value = maybe_serialize($value);
|
19 |
-
$this->option_value = $value;
|
20 |
-
$this->Save();
|
21 |
-
}
|
22 |
-
|
23 |
-
public function GetOptionValue($name, $default = array())
|
24 |
-
{
|
25 |
-
$this->GetNamedOption($name);
|
26 |
-
// Unerialize if $value is array or object
|
27 |
-
$this->option_value = maybe_unserialize($this->option_value);
|
28 |
-
return $this->IsLoaded() ? $this->option_value : $default;
|
29 |
-
}
|
30 |
-
|
31 |
-
public function GetNamedOption($name)
|
32 |
-
{
|
33 |
-
return $this->Load('option_name = %s', array($name));
|
34 |
-
}
|
35 |
-
|
36 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/DB/Query.php
DELETED
@@ -1,162 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* @todo Add group-by support
|
5 |
-
*/
|
6 |
-
class WSAL_DB_Query {
|
7 |
-
/**
|
8 |
-
* @var string
|
9 |
-
*/
|
10 |
-
protected $ar_cls;
|
11 |
-
|
12 |
-
/**
|
13 |
-
* @var WSAL_DB_ActiveRecord
|
14 |
-
*/
|
15 |
-
protected $ar_obj;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Array of table names to read from.
|
19 |
-
* @var array
|
20 |
-
*/
|
21 |
-
public $from = array();
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Array of columns to select.
|
25 |
-
* @var array
|
26 |
-
*/
|
27 |
-
public $columns = array('*');
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Array of conditions AND'ed together.
|
31 |
-
* @var array
|
32 |
-
*/
|
33 |
-
public $where = array();
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Use for ordering the result set. First items count most.
|
37 |
-
* @var array
|
38 |
-
*/
|
39 |
-
public $order = array();
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Array of join components.
|
43 |
-
* @var array
|
44 |
-
*/
|
45 |
-
public $joins = array();
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Array of values to be substituted in query.
|
49 |
-
* @var array
|
50 |
-
*/
|
51 |
-
public $args = array();
|
52 |
-
|
53 |
-
/**
|
54 |
-
* The amount of records to skip in result.
|
55 |
-
* @var int
|
56 |
-
*/
|
57 |
-
public $offset = 0;
|
58 |
-
|
59 |
-
/**
|
60 |
-
* The maximum number of records in result.
|
61 |
-
* @var int
|
62 |
-
*/
|
63 |
-
public $length = 0;
|
64 |
-
|
65 |
-
/**
|
66 |
-
* @param string $ar_class Name of class that extends ActiveRecord class.
|
67 |
-
*/
|
68 |
-
public function __construct($ar_class) {
|
69 |
-
$this->ar_cls = $ar_class;
|
70 |
-
$this->ar_obj = new $ar_class();
|
71 |
-
$this->from = array($this->ar_obj->GetTable());
|
72 |
-
}
|
73 |
-
|
74 |
-
public function GetDbType(){
|
75 |
-
global $wpdb;
|
76 |
-
return $wpdb->is_mysql ? 'mysql' : 'unknown';
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* @return string Generated sql.
|
81 |
-
*/
|
82 |
-
public function GetSql($verb = 'select'){
|
83 |
-
$where = $this->GetCond();
|
84 |
-
switch($this->GetDbType()){
|
85 |
-
case 'mysql':
|
86 |
-
return strtoupper($verb) . ' ' . implode(',', $this->columns)
|
87 |
-
. ' FROM ' . implode(',', $this->from)
|
88 |
-
. (count($this->joins) ? implode(' ', $this->where) : '')
|
89 |
-
. (count($where) ? (' WHERE ' . implode(' AND ', $where)) : '')
|
90 |
-
// @todo GROUP BY goes here
|
91 |
-
// @todo HAVING goes here
|
92 |
-
. (count($this->order) ? (' ORDER BY ' . implode(', ', $this->order)) : '')
|
93 |
-
. ($this->length ? (' LIMIT ' . ($this->offset ? ($this->offset . ', ') : '') . ' ' . $this->length) : '')
|
94 |
-
;
|
95 |
-
default:
|
96 |
-
throw new Exception('SQL generation for "' . $this->GetDbType() . '" databases is not supported.');
|
97 |
-
}
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* @return array Array of conditions.
|
102 |
-
*/
|
103 |
-
public function GetCond(){
|
104 |
-
return $this->where;
|
105 |
-
}
|
106 |
-
|
107 |
-
/**
|
108 |
-
* @return array Arguments used in query.
|
109 |
-
*/
|
110 |
-
public function GetArgs(){
|
111 |
-
return $this->args;
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* @return WSAL_DB_ActiveRecord[] Execute query and return data as $ar_cls objects.
|
116 |
-
*/
|
117 |
-
public function Execute(){
|
118 |
-
return call_user_func(array($this->ar_cls, 'LoadMultiQuery'), $this->GetSql(), $this->GetArgs());
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* @return int Use query for counting records.
|
123 |
-
*/
|
124 |
-
public function Count(){
|
125 |
-
// back up columns, use COUNT as default column and generate sql
|
126 |
-
$cols = $this->columns;
|
127 |
-
$this->columns = array('COUNT(*)');
|
128 |
-
$sql = $this->GetSql();
|
129 |
-
|
130 |
-
// restore columns
|
131 |
-
$this->columns = $cols;
|
132 |
-
|
133 |
-
// execute query and return result
|
134 |
-
return call_user_func(array($this->ar_cls, 'CountQuery'), $sql, $this->GetArgs());
|
135 |
-
}
|
136 |
-
|
137 |
-
/**
|
138 |
-
* Find occurrences matching a condition.
|
139 |
-
* @param string $cond The condition.
|
140 |
-
* @param array $args Condition arguments.
|
141 |
-
*/
|
142 |
-
public function Where($cond, $args){
|
143 |
-
$this->where[] = $cond;
|
144 |
-
foreach ($args as $arg) $this->args[] = $arg;
|
145 |
-
}
|
146 |
-
|
147 |
-
/**
|
148 |
-
* Use query for deleting records.
|
149 |
-
*/
|
150 |
-
public function Delete(){
|
151 |
-
// back up columns, remove them for DELETE and generate sql
|
152 |
-
$cols = $this->columns;
|
153 |
-
$this->columns = array();
|
154 |
-
$sql = $this->GetSql('delete');
|
155 |
-
|
156 |
-
// restore columns
|
157 |
-
$this->columns = $cols;
|
158 |
-
|
159 |
-
// execute query
|
160 |
-
call_user_func(array($this->ar_cls, 'DeleteQuery'), $sql, $this->GetArgs());
|
161 |
-
}
|
162 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
classes/Helpers/DataHelper.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Helpers_DataHelper
|
4 |
+
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* A wrapper for JSON encoding that fixes potential issues.
|
8 |
+
* @param mixed $data The data to encode.
|
9 |
+
* @return string JSON string.
|
10 |
+
*/
|
11 |
+
public static function JsonEncode($data){
|
12 |
+
return @json_encode($data);
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
* A wrapper for JSON encoding that fixes potential issues.
|
17 |
+
* @param string $data The JSON string to decode.
|
18 |
+
* @return mixed Decoded data.
|
19 |
+
*/
|
20 |
+
public static function JsonDecode($data){
|
21 |
+
return @json_decode($data);
|
22 |
+
}
|
23 |
+
}
|
classes/Loggers/Database.php
CHANGED
@@ -7,12 +7,12 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger {
|
|
7 |
$plugin->AddCleanupHook(array($this, 'CleanUp'));
|
8 |
}
|
9 |
|
10 |
-
public function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false) {
|
11 |
// is this a php alert, and if so, are we logging such alerts?
|
12 |
if ($type < 0010 && !$this->plugin->settings->IsPhpErrorLoggingEnabled()) return;
|
13 |
|
14 |
// create new occurrence
|
15 |
-
$occ = new
|
16 |
$occ->is_migrated = $migrated;
|
17 |
$occ->created_on = $date;
|
18 |
$occ->alert_id = $type;
|
@@ -28,14 +28,14 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger {
|
|
28 |
$now = current_time('timestamp');
|
29 |
$max_sdate = $this->plugin->settings->GetPruningDate();
|
30 |
$max_count = $this->plugin->settings->GetPruningLimit();
|
31 |
-
$is_date_e = $this->plugin->settings->IsPruningDateEnabled();
|
32 |
$is_limt_e = $this->plugin->settings->IsPruningLimitEnabled();
|
33 |
|
34 |
if (!$is_date_e && !$is_limt_e) {
|
35 |
return;
|
36 |
} // pruning disabled
|
37 |
-
|
38 |
-
$cnt_items =
|
39 |
|
40 |
// Check if there is something to delete
|
41 |
if($is_limt_e && ($cnt_items < $max_count)){
|
@@ -43,29 +43,29 @@ class WSAL_Loggers_Database extends WSAL_AbstractLogger {
|
|
43 |
}
|
44 |
|
45 |
$max_stamp = $now - (strtotime($max_sdate) - $now);
|
46 |
-
$max_items = max(($cnt_items - $max_count) + 1, 0);
|
47 |
-
|
48 |
-
$query = new WSAL_DB_OccurrenceQuery('WSAL_DB_Occurrence');
|
49 |
-
$query->order[] = 'created_on ASC';
|
50 |
|
51 |
-
|
52 |
-
|
|
|
|
|
|
|
53 |
|
54 |
-
$
|
55 |
-
if (!$count) return; // nothing to delete
|
56 |
|
57 |
-
|
58 |
-
$query->Delete();
|
59 |
|
|
|
60 |
// keep track of what we're doing
|
61 |
$this->plugin->alerts->Trigger(0003, array(
|
62 |
'Message' => 'Running system cleanup.',
|
63 |
-
'Query SQL' => $
|
64 |
-
'Query Args' => $
|
65 |
), true);
|
66 |
|
67 |
// notify system
|
68 |
-
do_action('wsal_prune', $
|
69 |
}
|
70 |
|
71 |
}
|
7 |
$plugin->AddCleanupHook(array($this, 'CleanUp'));
|
8 |
}
|
9 |
|
10 |
+
public function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false) {
|
11 |
// is this a php alert, and if so, are we logging such alerts?
|
12 |
if ($type < 0010 && !$this->plugin->settings->IsPhpErrorLoggingEnabled()) return;
|
13 |
|
14 |
// create new occurrence
|
15 |
+
$occ = new WSAL_Models_Occurrence();
|
16 |
$occ->is_migrated = $migrated;
|
17 |
$occ->created_on = $date;
|
18 |
$occ->alert_id = $type;
|
28 |
$now = current_time('timestamp');
|
29 |
$max_sdate = $this->plugin->settings->GetPruningDate();
|
30 |
$max_count = $this->plugin->settings->GetPruningLimit();
|
31 |
+
$is_date_e = $this->plugin->settings->IsPruningDateEnabled();
|
32 |
$is_limt_e = $this->plugin->settings->IsPruningLimitEnabled();
|
33 |
|
34 |
if (!$is_date_e && !$is_limt_e) {
|
35 |
return;
|
36 |
} // pruning disabled
|
37 |
+
$occ = new WSAL_Models_Occurrence();
|
38 |
+
$cnt_items = $occ->Count();
|
39 |
|
40 |
// Check if there is something to delete
|
41 |
if($is_limt_e && ($cnt_items < $max_count)){
|
43 |
}
|
44 |
|
45 |
$max_stamp = $now - (strtotime($max_sdate) - $now);
|
46 |
+
$max_items = (int)max(($cnt_items - $max_count) + 1, 0);
|
|
|
|
|
|
|
47 |
|
48 |
+
$query = new WSAL_Models_OccurrenceQuery();
|
49 |
+
$query->addOrderBy("created_on", false);
|
50 |
+
// TO DO Fixing data
|
51 |
+
if ($is_date_e) $query->addCondition('created_on <= %s', intval($max_stamp));
|
52 |
+
if ($is_limt_e) $query->setLimit($max_items);
|
53 |
|
54 |
+
if (($max_items-1) == 0) return; // nothing to delete
|
|
|
55 |
|
56 |
+
$result = $query->getAdapter()->GetSqlDelete($query);
|
57 |
+
$deletedCount = $query->getAdapter()->Delete($query);
|
58 |
|
59 |
+
if ($deletedCount == 0) return; // nothing to delete
|
60 |
// keep track of what we're doing
|
61 |
$this->plugin->alerts->Trigger(0003, array(
|
62 |
'Message' => 'Running system cleanup.',
|
63 |
+
'Query SQL' => $result['sql'],
|
64 |
+
'Query Args' => $result['args'],
|
65 |
), true);
|
66 |
|
67 |
// notify system
|
68 |
+
do_action('wsal_prune', $deletedCount, vsprintf($result['sql'], $result['args']));
|
69 |
}
|
70 |
|
71 |
}
|
classes/Models/ActiveRecord.php
ADDED
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once(__DIR__ . '/../Connector/ConnectorFactory.php');
|
3 |
+
|
4 |
+
abstract class WSAL_Models_ActiveRecord
|
5 |
+
{
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @var_$connector Data connector;
|
9 |
+
*/
|
10 |
+
protected $connector;
|
11 |
+
|
12 |
+
protected $id = false;
|
13 |
+
|
14 |
+
protected $adapterName = null;
|
15 |
+
|
16 |
+
protected $useDefaultAdapter = false;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @return array Returns this records' fields.
|
20 |
+
*/
|
21 |
+
public function GetFields()
|
22 |
+
{
|
23 |
+
if(!isset($this->_column_cache)){
|
24 |
+
$this->_column_cache = array();
|
25 |
+
foreach(array_keys(get_object_vars($this)) as $col)
|
26 |
+
if(trim($col) && $col[0] != '_')
|
27 |
+
$this->_column_cache[] = $col;
|
28 |
+
}
|
29 |
+
return $this->_column_cache;
|
30 |
+
}
|
31 |
+
|
32 |
+
public function setId($id)
|
33 |
+
{
|
34 |
+
$this->id = $id;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getId()
|
38 |
+
{
|
39 |
+
return $this->id;
|
40 |
+
}
|
41 |
+
|
42 |
+
const STATE_UNKNOWN = 'unknown';
|
43 |
+
const STATE_CREATED = 'created';
|
44 |
+
const STATE_UPDATED = 'updated';
|
45 |
+
const STATE_DELETED = 'deleted';
|
46 |
+
const STATE_LOADED = 'loaded';
|
47 |
+
|
48 |
+
protected $_state = self::STATE_UNKNOWN;
|
49 |
+
|
50 |
+
public function __construct($data = null)
|
51 |
+
{
|
52 |
+
if (!$this->adapterName) {
|
53 |
+
throw new Exception('Class "' . __CLASS__ . '" requires "adapterName" to be set.');
|
54 |
+
}
|
55 |
+
if (!is_null($data)) {
|
56 |
+
$this->LoadData($data);
|
57 |
+
$this->_state = self::STATE_LOADED;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
protected function getConnector()
|
62 |
+
{
|
63 |
+
if (!empty($this->connector)) {
|
64 |
+
return $this->connector;
|
65 |
+
}
|
66 |
+
if ($this->useDefaultAdapter) {
|
67 |
+
$this->connector = WSAL_Connector_ConnectorFactory::GetDefaultConnector();
|
68 |
+
} else {
|
69 |
+
$this->connector = WSAL_Connector_ConnectorFactory::GetConnector();
|
70 |
+
}
|
71 |
+
return $this->connector;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function getAdapter()
|
75 |
+
{
|
76 |
+
return $this->getConnector()->getAdapter($this->adapterName);
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Load record from DB.
|
82 |
+
* @param string $cond (Optional) Load condition.
|
83 |
+
* @param array $args (Optional) Load condition arguments.
|
84 |
+
*/
|
85 |
+
public function Load($cond = '%d', $args = array(1)){
|
86 |
+
$this->_state = self::STATE_UNKNOWN;
|
87 |
+
|
88 |
+
$data = $this->getAdapter()->Load($cond, $args);
|
89 |
+
if(!is_null($data)){
|
90 |
+
$this->LoadData($data);
|
91 |
+
$this->_state = self::STATE_LOADED;
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Load object data from variable.
|
97 |
+
* @param array|object $data Data array or object.
|
98 |
+
*/
|
99 |
+
public function LoadData($data){
|
100 |
+
$copy = get_class($this);
|
101 |
+
$copy = new $copy;
|
102 |
+
foreach((array)$data as $key => $val){
|
103 |
+
if(isset($copy->$key)){
|
104 |
+
switch(true){
|
105 |
+
case is_array($copy->$key):
|
106 |
+
case is_object($copy->$key):
|
107 |
+
$jsonDecodedVal = WSAL_Helpers_DataHelper::JsonDecode($val);
|
108 |
+
$this->$key = ($jsonDecodedVal == null) ? $val : $jsonDecodedVal;
|
109 |
+
break;
|
110 |
+
case is_int($copy->$key):
|
111 |
+
$this->$key = (int)$val;
|
112 |
+
break;
|
113 |
+
case is_float($copy->$key):
|
114 |
+
$this->$key = (float)$val;
|
115 |
+
break;
|
116 |
+
case is_bool($copy->$key):
|
117 |
+
$this->$key = (bool)$val;
|
118 |
+
break;
|
119 |
+
case is_string($copy->$key):
|
120 |
+
$this->$key = (string)$val;
|
121 |
+
break;
|
122 |
+
default:
|
123 |
+
throw new Exception('Unsupported type "'.gettype($copy->$key).'"');
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}
|
127 |
+
return $this;
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Save this active record
|
132 |
+
* @return integer|boolean Either the number of modified/inserted rows or false on failure.
|
133 |
+
*/
|
134 |
+
public function Save()
|
135 |
+
{
|
136 |
+
$this->_state = self::STATE_UNKNOWN;
|
137 |
+
|
138 |
+
// use today's date if not set up
|
139 |
+
if (is_null($this->created_on)) {
|
140 |
+
$this->created_on = $this->GetMicrotime();
|
141 |
+
}
|
142 |
+
$updateId = $this->getId();
|
143 |
+
$result = $this->getAdapter()->Save($this);
|
144 |
+
|
145 |
+
if ($result !== false) {
|
146 |
+
$this->_state = (!empty($updateId))?self::STATE_UPDATED:self::STATE_CREATED;
|
147 |
+
}
|
148 |
+
return $result;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Deletes this active record
|
153 |
+
*/
|
154 |
+
public function Delete()
|
155 |
+
{
|
156 |
+
$this->_state = self::STATE_UNKNOWN;
|
157 |
+
$result = $this->getAdapter()->Delete($this);
|
158 |
+
if($result !== false)
|
159 |
+
$this->_state = self::STATE_DELETED;
|
160 |
+
|
161 |
+
return $result;
|
162 |
+
}
|
163 |
+
|
164 |
+
public function Count($cond = '%d', $args = array(1)) {
|
165 |
+
$result = $this->getAdapter()->Count($cond, $args);
|
166 |
+
return $result;
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* @return boolean
|
171 |
+
*/
|
172 |
+
public function IsLoaded(){
|
173 |
+
return $this->_state == self::STATE_LOADED;
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* @return boolean
|
178 |
+
*/
|
179 |
+
public function IsSaved(){
|
180 |
+
return $this->_state == self::STATE_CREATED
|
181 |
+
|| $this->_state == self::STATE_UPDATED;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* @return boolean
|
186 |
+
*/
|
187 |
+
public function IsCreated(){
|
188 |
+
return $this->_state == self::STATE_CREATED;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* @return boolean
|
193 |
+
*/
|
194 |
+
public function IsUpdated()
|
195 |
+
{
|
196 |
+
return $this->_state == self::STATE_UPDATED;
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* @return boolean
|
201 |
+
*/
|
202 |
+
public function IsInstalled()
|
203 |
+
{
|
204 |
+
return $this->getAdapter()->IsInstalled();
|
205 |
+
}
|
206 |
+
|
207 |
+
public function Install()
|
208 |
+
{
|
209 |
+
return $this->getAdapter()->Install();
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* @return boolean
|
214 |
+
*/
|
215 |
+
public function IsDeleted()
|
216 |
+
{
|
217 |
+
return $this->_state == self::STATE_DELETED;
|
218 |
+
}
|
219 |
+
|
220 |
+
protected static $_cache = array();
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Load ActiveRecord from DB or cache.
|
224 |
+
* @param string $target ActiveRecord class name.
|
225 |
+
* @param string $query Load condition.
|
226 |
+
* @param array $args Arguments used in condition.
|
227 |
+
* @return WSAL_Models_ActiveRecord
|
228 |
+
*/
|
229 |
+
protected static function CacheLoad($target, $query, $args){
|
230 |
+
$index = $target . '::' . vsprintf($query, $args);
|
231 |
+
if(!isset(self::$_cache[$index])){
|
232 |
+
self::$_cache[$index] = new $target();
|
233 |
+
self::$_cache[$index]->Load($query, $args);
|
234 |
+
}
|
235 |
+
return self::$_cache[$index];
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Remove ActiveRecord cache.
|
240 |
+
* @param string $target ActiveRecord class name.
|
241 |
+
* @param string $query Load condition.
|
242 |
+
* @param array $args Arguments used in condition.
|
243 |
+
*/
|
244 |
+
protected static function CacheRemove($target, $query, $args){
|
245 |
+
$index = $target . '::' . sprintf($query, $args);
|
246 |
+
if(!isset(self::$_cache[$index])){
|
247 |
+
unset(self::$_cache[$index]);
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Clear the cache.
|
253 |
+
*/
|
254 |
+
protected static function CacheClear()
|
255 |
+
{
|
256 |
+
self::$_cache = array();
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Function used in WSAL reporting extension
|
261 |
+
*/
|
262 |
+
public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp)
|
263 |
+
{
|
264 |
+
return $this->getAdapter()->GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp);
|
265 |
+
}
|
266 |
+
|
267 |
+
}
|
classes/Models/Adapters/ActiveRecordInterface.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
interface WSAL_Adapters_ActiveRecordInterface {
|
4 |
+
|
5 |
+
public function IsInstalled();
|
6 |
+
public function Install();
|
7 |
+
public function Uninstall();
|
8 |
+
public function Load($cond = '%d', $args = array(1));
|
9 |
+
public function Save($activeRecord);
|
10 |
+
public function Delete($activeRecord);
|
11 |
+
public function LoadMulti($cond, $args = array());
|
12 |
+
public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1));
|
13 |
+
public function Count($cond = '%d', $args = array(1));
|
14 |
+
public function LoadMultiQuery($query, $args = array());
|
15 |
+
}
|
classes/Models/Adapters/MetaInterface.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
interface WSAL_Adapters_MetaInterface {
|
4 |
+
/**
|
5 |
+
* Create a meta object
|
6 |
+
* @param $metaData Array of meta data
|
7 |
+
* @return int ID of the new meta data
|
8 |
+
*/
|
9 |
+
public function deleteByOccurenceIds($occurenceIds);
|
10 |
+
|
11 |
+
public function loadByNameAndOccurenceId($metaName, $occurenceId);
|
12 |
+
|
13 |
+
}
|
classes/Models/Adapters/MySQL/ActiveRecordAdapter.php
ADDED
@@ -0,0 +1,460 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_ActiveRecordInterface {
|
4 |
+
|
5 |
+
protected $connection;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Contains the table name
|
9 |
+
* @var string
|
10 |
+
*/
|
11 |
+
protected $_table;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Contains primary key column name, override as required.
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
protected $_idkey = '';
|
18 |
+
|
19 |
+
public function __construct($conn)
|
20 |
+
{
|
21 |
+
$this->connection = $conn;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function GetModel()
|
25 |
+
{
|
26 |
+
return new WSAL_Models_ActiveRecord();
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return string Returns table name.
|
31 |
+
*/
|
32 |
+
public function GetTable()
|
33 |
+
{
|
34 |
+
//global $wpdb;
|
35 |
+
$_wpdb = $this->connection;
|
36 |
+
return $_wpdb->base_prefix . $this->_table;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @return string SQL table options (constraints, foreign keys, indexes etc).
|
41 |
+
*/
|
42 |
+
protected function GetTableOptions()
|
43 |
+
{
|
44 |
+
return ' PRIMARY KEY (' . $this->_idkey . ')';
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @return array Returns this records' columns.
|
49 |
+
*/
|
50 |
+
public function GetColumns()
|
51 |
+
{
|
52 |
+
$model = $this->GetModel();
|
53 |
+
|
54 |
+
if(!isset($this->_column_cache)){
|
55 |
+
$this->_column_cache = array();
|
56 |
+
foreach(array_keys(get_object_vars($model)) as $col)
|
57 |
+
if(trim($col) && $col[0] != '_')
|
58 |
+
$this->_column_cache[] = $col;
|
59 |
+
}
|
60 |
+
return $this->_column_cache;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @deprecated
|
65 |
+
* @return boolean Returns whether table structure is installed or not.
|
66 |
+
*/
|
67 |
+
public function IsInstalled(){
|
68 |
+
//global $wpdb;
|
69 |
+
$_wpdb = $this->connection;
|
70 |
+
$sql = 'SHOW TABLES LIKE "' . $this->GetTable() . '"';
|
71 |
+
return $_wpdb->get_var($sql) == $this->GetTable();
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Install this ActiveRecord structure into DB.
|
76 |
+
*/
|
77 |
+
public function Install(){
|
78 |
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
79 |
+
dbDelta($this->_GetInstallQuery());
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Remove this ActiveRecord structure into DB.
|
84 |
+
*/
|
85 |
+
public function Uninstall()
|
86 |
+
{
|
87 |
+
//global $wpdb;
|
88 |
+
$_wpdb = $this->connection;
|
89 |
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
90 |
+
$_wpdb->query($this->_GetUninstallQuery());
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Save an active record to DB.
|
95 |
+
* @return integer|boolean Either the number of modified/inserted rows or false on failure.
|
96 |
+
*/
|
97 |
+
public function Save($activeRecord)
|
98 |
+
{
|
99 |
+
//global $wpdb;
|
100 |
+
$_wpdb = $this->connection;
|
101 |
+
$copy = $activeRecord;
|
102 |
+
$data = array();
|
103 |
+
$format = array();
|
104 |
+
foreach ($this->GetColumns() as $key) {
|
105 |
+
|
106 |
+
$val = $copy->$key;
|
107 |
+
$deffmt = '%s';
|
108 |
+
if (is_int($copy->$key)) {
|
109 |
+
$deffmt = '%d';
|
110 |
+
}
|
111 |
+
if (is_float($copy->$key)) {
|
112 |
+
$deffmt = '%f';
|
113 |
+
}
|
114 |
+
if (is_array($copy->$key) || is_object($copy->$key)) {
|
115 |
+
$data[$key] = WSAL_Helpers_DataHelper::JsonEncode($val);
|
116 |
+
} else {
|
117 |
+
$data[$key] = $val;
|
118 |
+
}
|
119 |
+
$format[] = $deffmt;
|
120 |
+
}
|
121 |
+
$result = $_wpdb->replace($this->GetTable(), $data, $format);
|
122 |
+
|
123 |
+
if ($result !== false) {
|
124 |
+
if ($_wpdb->insert_id) {
|
125 |
+
$copy->setId($_wpdb->insert_id);
|
126 |
+
}
|
127 |
+
}
|
128 |
+
return $result;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Load record from DB.
|
133 |
+
* @param string $cond (Optional) Load condition.
|
134 |
+
* @param array $args (Optional) Load condition arguments.
|
135 |
+
*/
|
136 |
+
public function Load($cond = '%d', $args = array(1))
|
137 |
+
{
|
138 |
+
//global $wpdb;
|
139 |
+
$_wpdb = $this->connection;
|
140 |
+
|
141 |
+
$sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
|
142 |
+
$data = $_wpdb->get_row($sql, ARRAY_A);
|
143 |
+
|
144 |
+
return $data;
|
145 |
+
}
|
146 |
+
|
147 |
+
public function LoadArray($cond, $args = array())
|
148 |
+
{
|
149 |
+
//global $wpdb;
|
150 |
+
$_wpdb = $this->connection;
|
151 |
+
$result = array();
|
152 |
+
$sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
|
153 |
+
foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
|
154 |
+
$result[] = $this->getModel()->LoadData($data);
|
155 |
+
}
|
156 |
+
return $result;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Delete DB record.
|
161 |
+
* @return int|boolean Either the amount of deleted rows or False on error.
|
162 |
+
*/
|
163 |
+
public function Delete($activeRecord)
|
164 |
+
{
|
165 |
+
//global $wpdb;
|
166 |
+
$_wpdb = $this->connection;
|
167 |
+
$result = $_wpdb->delete(
|
168 |
+
$this->GetTable(),
|
169 |
+
$activeRecord->getId()
|
170 |
+
);
|
171 |
+
return $result;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Delete records in DB matching a query.
|
176 |
+
* @param string $query Full SQL query.
|
177 |
+
* @param array $args (Optional) Query arguments.
|
178 |
+
*/
|
179 |
+
public function DeleteQuery($query, $args = array())
|
180 |
+
{
|
181 |
+
$_wpdb = $this->connection;
|
182 |
+
$sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
|
183 |
+
$result = $_wpdb->query($sql);
|
184 |
+
return $result;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Load multiple records from DB.
|
189 |
+
* @param string $cond (Optional) Load condition (eg: 'some_id = %d' ).
|
190 |
+
* @param array $args (Optional) Load condition arguments (rg: array(45) ).
|
191 |
+
* @return self[] List of loaded records.
|
192 |
+
*/
|
193 |
+
public function LoadMulti($cond, $args = array())
|
194 |
+
{
|
195 |
+
//global $wpdb;
|
196 |
+
$_wpdb = $this->connection;
|
197 |
+
$result = array();
|
198 |
+
$sql = (!is_array($args) || !count($args)) // do we really need to prepare() or not?
|
199 |
+
? ($cond)
|
200 |
+
: $_wpdb->prepare($cond, $args)
|
201 |
+
;
|
202 |
+
foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
|
203 |
+
$result[] = $this->getModel()->LoadData($data);
|
204 |
+
}
|
205 |
+
return $result;
|
206 |
+
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Load multiple records from DB and call a callback for each record.
|
211 |
+
* This function is very memory-efficient, it doesn't load records in bulk.
|
212 |
+
* @param callable $callback The callback to invoke.
|
213 |
+
* @param string $cond (Optional) Load condition.
|
214 |
+
* @param array $args (Optional) Load condition arguments.
|
215 |
+
*/
|
216 |
+
public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1))
|
217 |
+
{
|
218 |
+
//global $wpdb;
|
219 |
+
$_wpdb = $this->connection;
|
220 |
+
$class = get_called_class();
|
221 |
+
$sql = $_wpdb->prepare('SELECT * FROM ' . $this->GetTable() . ' WHERE '.$cond, $args);
|
222 |
+
foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
|
223 |
+
call_user_func($callback, new $class($data));
|
224 |
+
}
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Count records in the DB matching a condition.
|
229 |
+
* If no parameters are given, this counts the number of records in the DB table.
|
230 |
+
* @param string $cond (Optional) Query condition.
|
231 |
+
* @param array $args (Optional) Condition arguments.
|
232 |
+
* @return int Number of matching records.
|
233 |
+
*/
|
234 |
+
public function Count($cond = '%d', $args = array(1))
|
235 |
+
{
|
236 |
+
//global $wpdb;
|
237 |
+
$_wpdb = $this->connection;
|
238 |
+
$class = get_called_class();
|
239 |
+
$sql = $_wpdb->prepare('SELECT COUNT(*) FROM ' . $this->GetTable() . ' WHERE ' . $cond, $args);
|
240 |
+
return (int)$_wpdb->get_var($sql);
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Count records in the DB matching a query.
|
245 |
+
* @param string $query Full SQL query.
|
246 |
+
* @param array $args (Optional) Query arguments.
|
247 |
+
* @return int Number of matching records.
|
248 |
+
*/
|
249 |
+
public function CountQuery($query, $args = array())
|
250 |
+
{
|
251 |
+
//global $wpdb;
|
252 |
+
$_wpdb = $this->connection;
|
253 |
+
$sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
|
254 |
+
return (int)$_wpdb->get_var($sql);
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Similar to LoadMulti but allows the use of a full SQL query.
|
259 |
+
* @param string $query Full SQL query.
|
260 |
+
* @param array $args (Optional) Query arguments.
|
261 |
+
* @return self[] List of loaded records.
|
262 |
+
*/
|
263 |
+
public function LoadMultiQuery($query, $args = array())
|
264 |
+
{
|
265 |
+
//global $wpdb;
|
266 |
+
$_wpdb = $this->connection;
|
267 |
+
$class = get_called_class();
|
268 |
+
$result = array();
|
269 |
+
$sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
|
270 |
+
foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
|
271 |
+
$result[] = $this->getModel()->LoadData($data);
|
272 |
+
}
|
273 |
+
return $result;
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* @return string Must return SQL for creating table.
|
278 |
+
*/
|
279 |
+
protected function _GetInstallQuery()
|
280 |
+
{
|
281 |
+
$_wpdb = $this->connection;
|
282 |
+
|
283 |
+
$class = get_class($this);
|
284 |
+
$copy = new $class($this->connection);
|
285 |
+
|
286 |
+
$sql = 'CREATE TABLE ' . $this->GetTable() . ' (' . PHP_EOL;
|
287 |
+
|
288 |
+
foreach ($this->GetColumns() as $key) {
|
289 |
+
$sql .= ' ';
|
290 |
+
switch(true) {
|
291 |
+
case $key == $copy->_idkey:
|
292 |
+
$sql .= $key . ' BIGINT NOT NULL AUTO_INCREMENT,' . PHP_EOL;
|
293 |
+
break;
|
294 |
+
case is_integer($copy->$key):
|
295 |
+
$sql .= $key . ' BIGINT NOT NULL,' . PHP_EOL;
|
296 |
+
break;
|
297 |
+
case is_float($copy->$key):
|
298 |
+
$sql .= $key . ' DOUBLE NOT NULL,' . PHP_EOL;
|
299 |
+
break;
|
300 |
+
case is_string($copy->$key):
|
301 |
+
$maxlength = $key . '_maxlength';
|
302 |
+
if (property_exists($class, $maxlength)) {
|
303 |
+
$sql .= $key . ' VARCHAR(' . intval($class::$$maxlength) . ') NOT NULL,' . PHP_EOL;
|
304 |
+
} else {
|
305 |
+
$sql .= $key . ' TEXT NOT NULL,' . PHP_EOL;
|
306 |
+
}
|
307 |
+
break;
|
308 |
+
case is_bool($copy->$key):
|
309 |
+
$sql .= $key . ' BIT NOT NULL,' . PHP_EOL;
|
310 |
+
break;
|
311 |
+
case is_array($copy->$key):
|
312 |
+
case is_object($copy->$key):
|
313 |
+
$sql .= $key . ' LONGTEXT NOT NULL,' . PHP_EOL;
|
314 |
+
break;
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
$sql .= $this->GetTableOptions() . PHP_EOL;
|
319 |
+
|
320 |
+
$sql .= ')';
|
321 |
+
|
322 |
+
if (! empty($_wpdb->charset)) {
|
323 |
+
$sql .= ' DEFAULT CHARACTER SET ' . $_wpdb->charset;
|
324 |
+
}
|
325 |
+
|
326 |
+
return $sql;
|
327 |
+
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* @return string Must return SQL for removing table (at a minimum, it should be ` 'DROP TABLE ' . $this->_table `).
|
332 |
+
*/
|
333 |
+
protected function _GetUninstallQuery(){
|
334 |
+
return 'DROP TABLE ' . $this->GetTable();
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Function used in WSAL reporting extension
|
339 |
+
*/
|
340 |
+
public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp)
|
341 |
+
{
|
342 |
+
global $wpdb;
|
343 |
+
$tableUsers = $wpdb->users;
|
344 |
+
$_wpdb = $this->connection;
|
345 |
+
// tables
|
346 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
347 |
+
$tableMeta = $meta->GetTable(); // metadata
|
348 |
+
$occurrence = new WSAL_Adapters_MySQL_Occurrence($this->connection);
|
349 |
+
$tableOcc = $occurrence->GetTable(); // occurrences
|
350 |
+
|
351 |
+
$ids = '0';
|
352 |
+
if (!empty($_userId) && $_userId != "null") {
|
353 |
+
$sql = 'SELECT ID FROM '.$tableUsers.' WHERE find_in_set(ID, @userId) > 0';
|
354 |
+
$wpdb->query("SET @userId = $_userId");
|
355 |
+
$result = $wpdb->get_results($sql, ARRAY_A);
|
356 |
+
$arrayIds = array();
|
357 |
+
foreach ($result as $item) {
|
358 |
+
$arrayIds[] = $item['ID'];
|
359 |
+
}
|
360 |
+
$ids = implode(', ', $arrayIds);
|
361 |
+
}
|
362 |
+
|
363 |
+
$sql = "SELECT DISTINCT
|
364 |
+
occ.id,
|
365 |
+
occ.alert_id,
|
366 |
+
occ.site_id,
|
367 |
+
occ.created_on,
|
368 |
+
replace(replace(replace((
|
369 |
+
SELECT t1.value FROM $tableMeta AS t1 WHERE t1.name = 'CurrentUserRoles' AND t1.occurrence_id = occ.id), '[', ''), ']', ''), '\\'', '') AS roles,
|
370 |
+
(SELECT replace(t2.value, '\"','') FROM $tableMeta as t2 WHERE t2.name = 'ClientIP' AND t2.occurrence_id = occ.id) AS ip,
|
371 |
+
(SELECT replace(t3.value, '\"', '') FROM $tableMeta as t3 WHERE t3.name = 'UserAgent' AND t3.occurrence_id = occ.id) AS ua,
|
372 |
+
COALESCE(
|
373 |
+
(SELECT replace(t4.value, '\"', '') FROM $tableMeta as t4 WHERE t4.name = 'Username' AND t4.occurrence_id = occ.id),
|
374 |
+
(SELECT replace(t5.value, '\"', '') FROM $tableMeta as t5 WHERE t5.name = 'CurrentUserID' AND t5.occurrence_id = occ.id)
|
375 |
+
) as user_id
|
376 |
+
FROM $tableOcc AS occ
|
377 |
+
JOIN $tableMeta AS meta ON meta.occurrence_id = occ.id
|
378 |
+
WHERE
|
379 |
+
(@siteId is NULL OR find_in_set(occ.site_id, @siteId) > 0)
|
380 |
+
AND (@userId is NULL OR (
|
381 |
+
(meta.name = 'CurrentUserID' AND find_in_set(meta.value, @userId) > 0)
|
382 |
+
OR (meta.name = 'Username' AND replace(meta.value, '\"', '') IN ($ids))
|
383 |
+
))
|
384 |
+
AND (@roleName is NULL OR (meta.name = 'CurrentUserRoles'
|
385 |
+
AND replace(replace(replace(meta.value, ']', ''), '[', ''), '\\'', '') REGEXP @roleName
|
386 |
+
))
|
387 |
+
AND (@alertCode is NULL OR find_in_set(occ.alert_id, @alertCode) > 0)
|
388 |
+
AND (@startTimestamp is NULL OR occ.created_on >= @startTimestamp)
|
389 |
+
AND (@endTimestamp is NULL OR occ.created_on <= @endTimestamp)
|
390 |
+
ORDER BY
|
391 |
+
site_id, created_on DESC
|
392 |
+
";
|
393 |
+
$_wpdb->query("SET @siteId = $_siteId");
|
394 |
+
$_wpdb->query("SET @userId = $_userId");
|
395 |
+
$_wpdb->query("SET @roleName = $_roleName");
|
396 |
+
$_wpdb->query("SET @alertCode = $_alertCode");
|
397 |
+
$_wpdb->query("SET @startTimestamp = $_startTimestamp");
|
398 |
+
$_wpdb->query("SET @endTimestamp = $_endTimestamp");
|
399 |
+
$results = $_wpdb->get_results($sql);
|
400 |
+
|
401 |
+
foreach ($results as $row) {
|
402 |
+
$sql = "SELECT t6.ID FROM $tableUsers AS t6 WHERE t6.user_login = \"$row->user_id\"";
|
403 |
+
$userId = $wpdb->get_var($sql);
|
404 |
+
if ($userId == null) {
|
405 |
+
$sql = "SELECT t4.ID FROM $tableUsers AS t4 WHERE t4.ID = \"$row->user_id\"";
|
406 |
+
$userId = $wpdb->get_var($sql);
|
407 |
+
}
|
408 |
+
$row->user_id = $userId;
|
409 |
+
}
|
410 |
+
return $results;
|
411 |
+
/*
|
412 |
+
$query = <<<query
|
413 |
+
SELECT DISTINCT
|
414 |
+
occ.id,
|
415 |
+
occ.alert_id,
|
416 |
+
occ.site_id,
|
417 |
+
occ.created_on,
|
418 |
+
replace(replace(replace(replace((select t1.value from $tableMeta as t1 where t1.name = 'CurrentUserRoles' and t1.occurrence_id = occ.id), '[', ''), ']', ''), '"', ''), '\\'', '') as roles,
|
419 |
+
(select replace(t2.value, '"','') from $tableMeta as t2 where t2.name = 'ClientIP' and t2.occurrence_id = occ.id) as ip,
|
420 |
+
(select replace(t3.value, '"', '') from $tableMeta as t3 where t3.name = 'UserAgent' and t3.occurrence_id = occ.id) as ua,
|
421 |
+
|
422 |
+
COALESCE(
|
423 |
+
(select t6.ID from $tableUsers as t6 where t6.user_login = (select replace(t7.value, '"', '') from $tableMeta as t7 where t7.name = 'Username' and t7.occurrence_id = occ.id)),
|
424 |
+
(select t4.ID from $tableUsers as t4 where t4.ID = (select t5.value from $tableMeta as t5 where t5.name = 'CurrentUserID' and t5.occurrence_id = occ.id))
|
425 |
+
) as user_id
|
426 |
+
FROM
|
427 |
+
$tableOcc as occ
|
428 |
+
JOIN
|
429 |
+
$tableMeta as meta on meta.occurrence_id = occ.id
|
430 |
+
WHERE
|
431 |
+
(@siteId is null or find_in_set(occ.site_id, @siteId) > 0)
|
432 |
+
and (@userId is null or (
|
433 |
+
(meta.name = 'CurrentUserID' and find_in_set(meta.value, @userId) > 0)
|
434 |
+
or (meta.name = 'Username' and replace(meta.value, '"', '') in (select user_login from $tableUsers where find_in_set(ID, @userId) > 0))
|
435 |
+
))
|
436 |
+
and (@roleName is null or (meta.name = 'CurrentUserRoles'
|
437 |
+
and replace(replace(replace(replace(meta.value, '"', ''), ']', ''), '[', ''), '\\'', '') REGEXP @roleName
|
438 |
+
))
|
439 |
+
and (@alertCode is null or find_in_set(occ.alert_id, @alertCode) > 0)
|
440 |
+
and (@startTimestamp is null or occ.created_on >= @startTimestamp)
|
441 |
+
and (@endTimestamp is null or occ.created_on <= @endTimestamp)
|
442 |
+
order by
|
443 |
+
site_id, created_on DESC;
|
444 |
+
query;
|
445 |
+
//#! Set variables first
|
446 |
+
$_wpdb->query("SET @siteId = $_siteId");
|
447 |
+
$_wpdb->query("SET @userId = $_userId");
|
448 |
+
$_wpdb->query("SET @roleName = $_roleName");
|
449 |
+
$_wpdb->query("SET @alertCode = $_alertCode");
|
450 |
+
$_wpdb->query("SET @startTimestamp = $_startTimestamp");
|
451 |
+
$_wpdb->query("SET @endTimestamp = $_endTimestamp");
|
452 |
+
|
453 |
+
//#! Then run query
|
454 |
+
return $_wpdb->get_results($query);
|
455 |
+
*/
|
456 |
+
}
|
457 |
+
|
458 |
+
|
459 |
+
|
460 |
+
}
|
classes/Models/Adapters/MySQL/MetaAdapter.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Adapters_MySQL_Meta extends WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_MetaInterface {
|
4 |
+
|
5 |
+
protected $_table = 'wsal_metadata';
|
6 |
+
protected $_idkey = 'id';
|
7 |
+
|
8 |
+
public $id = 0;
|
9 |
+
public $occurrence_id = 0;
|
10 |
+
public $name = '';
|
11 |
+
public static $name_maxlength = 100;
|
12 |
+
public $value = array(); // force mixed type
|
13 |
+
|
14 |
+
public function GetModel()
|
15 |
+
{
|
16 |
+
return new WSAL_Models_Meta();
|
17 |
+
}
|
18 |
+
|
19 |
+
public function __construct($conn) {
|
20 |
+
parent::__construct($conn);
|
21 |
+
}
|
22 |
+
|
23 |
+
protected function GetTableOptions(){
|
24 |
+
return parent::GetTableOptions() . ',' . PHP_EOL
|
25 |
+
. ' KEY occurrence_name (occurrence_id,name)';
|
26 |
+
}
|
27 |
+
|
28 |
+
public function DeleteByOccurenceIds($occurenceIds)
|
29 |
+
{
|
30 |
+
if (!empty($occurenceIds)) {
|
31 |
+
$sql = 'DELETE FROM ' . $this->GetTable() . ' WHERE occurrence_id IN (' . implode(',', $occurenceIds) . ')';
|
32 |
+
// execute query
|
33 |
+
parent::DeleteQuery($sql);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
public function LoadByNameAndOccurenceId($metaName, $occurenceId)
|
38 |
+
{
|
39 |
+
return $this->Load('occurrence_id = %d AND name = %s', array($occurenceId, $metaName));
|
40 |
+
}
|
41 |
+
|
42 |
+
public function GetMatchingIPs()
|
43 |
+
{
|
44 |
+
$_wpdb = $this->connection;
|
45 |
+
$ips = $_wpdb->get_col("SELECT DISTINCT value FROM {$this->GetTable()} WHERE name = \"ClientIP\"");
|
46 |
+
return $ips;
|
47 |
+
}
|
48 |
+
|
49 |
+
}
|
classes/Models/Adapters/MySQL/OccurrenceAdapter.php
ADDED
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Adapters_MySQL_Occurrence extends WSAL_Adapters_MySQL_ActiveRecord implements WSAL_Adapters_OccurrenceInterface {
|
4 |
+
|
5 |
+
protected $_table = 'wsal_occurrences';
|
6 |
+
protected $_idkey = 'id';
|
7 |
+
protected $_meta;
|
8 |
+
|
9 |
+
public $id = 0;
|
10 |
+
public $site_id = 0;
|
11 |
+
public $alert_id = 0;
|
12 |
+
public $created_on = 0.0;
|
13 |
+
public $is_read = false;
|
14 |
+
public $is_migrated = false;
|
15 |
+
|
16 |
+
public function __construct($conn) {
|
17 |
+
parent::__construct($conn);
|
18 |
+
}
|
19 |
+
|
20 |
+
protected function GetTableOptions(){
|
21 |
+
return parent::GetTableOptions() . ',' . PHP_EOL
|
22 |
+
. ' KEY site_alert_created (site_id,alert_id,created_on)';
|
23 |
+
}
|
24 |
+
|
25 |
+
public function GetModel()
|
26 |
+
{
|
27 |
+
return new WSAL_Models_Occurrence();
|
28 |
+
}
|
29 |
+
/**
|
30 |
+
* Returns all meta data related to this event.
|
31 |
+
* @return WSAL_Meta[]
|
32 |
+
*/
|
33 |
+
public function GetMeta($occurence){
|
34 |
+
if(!isset($this->_meta)){
|
35 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
36 |
+
$this->_meta = $meta->Load('occurrence_id = %d', array($occurence->id));
|
37 |
+
}
|
38 |
+
return $this->_meta;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function GetMultiMeta($occurence){
|
42 |
+
if(!isset($this->_meta)){
|
43 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
44 |
+
$this->_meta = $meta->LoadArray('occurrence_id = %d', array($occurence->id));
|
45 |
+
}
|
46 |
+
return $this->_meta;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Loads a meta item given its name.
|
51 |
+
* @param string $name Meta name.
|
52 |
+
* @return WSAL_Meta The meta item, be sure to checked if it was loaded successfully.
|
53 |
+
*/
|
54 |
+
public function GetNamedMeta($occurence, $name){
|
55 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
56 |
+
$this->_meta = $meta->Load('occurrence_id = %d AND name = %s', array($occurence->id, $name));
|
57 |
+
|
58 |
+
return $this->_meta;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* 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.
|
63 |
+
* @param array $names List of meta names.
|
64 |
+
* @return WSAL_Meta The first meta item that exists.
|
65 |
+
*/
|
66 |
+
public function GetFirstNamedMeta($occurence, $names){
|
67 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
68 |
+
$query = '(' . str_repeat('name = %s OR ', count($names)).'0)';
|
69 |
+
$query = 'occurrence_id = %d AND ' . $query . ' ORDER BY name DESC LIMIT 1';
|
70 |
+
array_unshift($names, $occurence->id); // prepend args with occurrence id
|
71 |
+
|
72 |
+
$this->_meta = $meta->Load($query, $names);
|
73 |
+
return $meta->getModel()->LoadData($this->_meta);
|
74 |
+
|
75 |
+
//TO DO: Do we want to reintroduce is loaded check/logic?
|
76 |
+
//return $meta->IsLoaded() ? $meta : null;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Returns newest unique occurrences.
|
81 |
+
* @param integer $limit Maximum limit.
|
82 |
+
* @return WSAL_Occurrence[]
|
83 |
+
*/
|
84 |
+
public static function GetNewestUnique($limit = PHP_INT_MAX){
|
85 |
+
$temp = new self();
|
86 |
+
return self::LoadMultiQuery('
|
87 |
+
SELECT *, COUNT(alert_id) as count
|
88 |
+
FROM (
|
89 |
+
SELECT *
|
90 |
+
FROM ' . $temp->GetTable() . '
|
91 |
+
ORDER BY created_on DESC
|
92 |
+
) AS temp_table
|
93 |
+
GROUP BY alert_id
|
94 |
+
LIMIT %d
|
95 |
+
', array($limit));
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Gets occurences of the same type by IP and Username within specified time frame
|
100 |
+
* @param string $ipAddress
|
101 |
+
* @param string $username
|
102 |
+
* @param int $alertId Alert type we are lookign for
|
103 |
+
* @param int $siteId
|
104 |
+
* @param $startTime mktime
|
105 |
+
* @param $endTime mktime
|
106 |
+
*/
|
107 |
+
public function CheckKnownUsers($args = array())
|
108 |
+
{
|
109 |
+
$tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
|
110 |
+
return self::LoadMultiQuery(
|
111 |
+
'SELECT occurrence.* FROM `' . $this->GetTable() . '` occurrence
|
112 |
+
INNER JOIN `' . $tt2->GetTable() . '` ipMeta on ipMeta.occurrence_id = occurrence.id
|
113 |
+
and ipMeta.name = "ClientIP"
|
114 |
+
and ipMeta.value = %s
|
115 |
+
INNER JOIN `' . $tt2->GetTable() . '` usernameMeta on usernameMeta.occurrence_id = occurrence.id
|
116 |
+
and usernameMeta.name = "Username"
|
117 |
+
and usernameMeta.value = %s
|
118 |
+
WHERE occurrence.alert_id = %d AND occurrence.site_id = %d
|
119 |
+
AND (created_on BETWEEN %d AND %d)
|
120 |
+
GROUP BY occurrence.id',
|
121 |
+
$args
|
122 |
+
);
|
123 |
+
}
|
124 |
+
|
125 |
+
public function CheckUnKnownUsers($args = array())
|
126 |
+
{
|
127 |
+
$tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
|
128 |
+
return self::LoadMultiQuery('
|
129 |
+
SELECT occurrence.* FROM `' . $this->GetTable() . '` occurrence
|
130 |
+
INNER JOIN `' . $tt2->GetTable() . '` ipMeta on ipMeta.occurrence_id = occurrence.id
|
131 |
+
and ipMeta.name = "ClientIP" and ipMeta.value = %s
|
132 |
+
WHERE occurrence.alert_id = %d AND occurrence.site_id = %d
|
133 |
+
AND (created_on BETWEEN %d AND %d)
|
134 |
+
GROUP BY occurrence.id',
|
135 |
+
$args
|
136 |
+
);
|
137 |
+
}
|
138 |
+
|
139 |
+
protected function prepareOccurrenceQuery($query)
|
140 |
+
{
|
141 |
+
$searchQueryParameters = array();
|
142 |
+
$searchConditions = array();
|
143 |
+
$conditions = $query->getConditions();
|
144 |
+
|
145 |
+
//BUG: not all conditions are occurence related. maybe it's just a field site_id. need seperate arrays
|
146 |
+
if (!empty($conditions)) {
|
147 |
+
$tmp = new WSAL_Adapters_MySQL_Meta($this->connection);
|
148 |
+
$sWhereClause = "";
|
149 |
+
foreach ($conditions as $field => $value) {
|
150 |
+
if (!empty($sWhereClause)) {
|
151 |
+
$sWhereClause .= " AND ";
|
152 |
+
}
|
153 |
+
$sWhereClause .= "name = %s AND value = %s";
|
154 |
+
$searchQueryParameters[] = $field;
|
155 |
+
$searchQueryParameters[] = $value;
|
156 |
+
}
|
157 |
+
|
158 |
+
$searchConditions[] = 'id IN (
|
159 |
+
SELECT DISTINCT occurrence_id
|
160 |
+
FROM ' . $tmp->GetTable() . '
|
161 |
+
WHERE ' . $sWhereClause . '
|
162 |
+
)';
|
163 |
+
}
|
164 |
+
|
165 |
+
//do something with search query parameters and search conditions - give them to the query adapter?
|
166 |
+
return $searchConditions;
|
167 |
+
}
|
168 |
+
|
169 |
+
|
170 |
+
}
|
classes/Models/Adapters/MySQL/OptionAdapter.php
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Adapters_MySQL_Option extends WSAL_Adapters_MySQL_ActiveRecord
|
4 |
+
{
|
5 |
+
|
6 |
+
protected $_table = 'wsal_options';
|
7 |
+
protected $_idkey = 'id';
|
8 |
+
|
9 |
+
public $id = 0;
|
10 |
+
public $option_name = '';
|
11 |
+
public static $option_name_maxlength = 100;
|
12 |
+
public $option_value = '';
|
13 |
+
|
14 |
+
public function __construct($conn)
|
15 |
+
{
|
16 |
+
parent::__construct($conn);
|
17 |
+
}
|
18 |
+
|
19 |
+
|
20 |
+
public function GetModel()
|
21 |
+
{
|
22 |
+
return new WSAL_Models_Option();
|
23 |
+
}
|
24 |
+
|
25 |
+
public function GetNamedOption($name)
|
26 |
+
{ if ($this->IsInstalled()) {
|
27 |
+
return $this->Load('option_name = %s', array($name));
|
28 |
+
} else {
|
29 |
+
return null;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
public function GetNotificationsSetting($opt_prefix)
|
34 |
+
{
|
35 |
+
if ($this->IsInstalled()) {
|
36 |
+
return $this->LoadArray('option_name LIKE %s', array($opt_prefix."%"));
|
37 |
+
} else {
|
38 |
+
return null;
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
public function GetNotification($id)
|
43 |
+
{
|
44 |
+
if ($this->IsInstalled()) {
|
45 |
+
return $this->Load('id = %d', array($id));
|
46 |
+
} else {
|
47 |
+
return null;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
public function DeleteByName($name)
|
52 |
+
{
|
53 |
+
if (!empty($name)) {
|
54 |
+
$sql = "DELETE FROM " . $this->GetTable() . " WHERE option_name = '". $name ."'";
|
55 |
+
// execute query
|
56 |
+
return parent::DeleteQuery($sql);
|
57 |
+
} else {
|
58 |
+
return false;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
public function DeleteByPrefix($opt_prefix)
|
63 |
+
{
|
64 |
+
if (!empty($opt_prefix)) {
|
65 |
+
$sql = "DELETE FROM " . $this->GetTable() . "WHERE option_name LIKE '". $opt_prefix ."%'";
|
66 |
+
// execute query
|
67 |
+
return parent::DeleteQuery($sql);
|
68 |
+
} else {
|
69 |
+
return false;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
public function CountNotifications($opt_prefix)
|
74 |
+
{
|
75 |
+
$_wpdb = $this->connection;
|
76 |
+
$sql = "SELECT COUNT(id) FROM " . $this->GetTable() . " WHERE option_name LIKE '". $opt_prefix ."%'";
|
77 |
+
return (int)$_wpdb->get_var($sql);
|
78 |
+
}
|
79 |
+
|
80 |
+
}
|
classes/Models/Adapters/MySQL/QueryAdapter.php
ADDED
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Adapters_MySQL_Query implements WSAL_Adapters_QueryInterface
|
4 |
+
{
|
5 |
+
protected $connection;
|
6 |
+
|
7 |
+
public function __construct($conn)
|
8 |
+
{
|
9 |
+
$this->connection = $conn;
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @return string Generated sql.
|
14 |
+
*/
|
15 |
+
protected function GetSql($query, &$args = array())
|
16 |
+
{
|
17 |
+
$conditions = $query->getConditions();
|
18 |
+
$searchCondition = $this->SearchCondition($query);
|
19 |
+
|
20 |
+
$sWhereClause = "";
|
21 |
+
foreach ($conditions as $fieldName => $fieldValue) {
|
22 |
+
if (empty($sWhereClause)) {
|
23 |
+
$sWhereClause .= " WHERE ";
|
24 |
+
} else {
|
25 |
+
$sWhereClause .= " AND ";
|
26 |
+
}
|
27 |
+
|
28 |
+
if (is_array($fieldValue)) {
|
29 |
+
$subWhereClause = "(";
|
30 |
+
foreach($fieldValue as $orFieldName => $orFieldValue) {
|
31 |
+
if ($subWhereClause != '(') {
|
32 |
+
$subWhereClause .= " OR ";
|
33 |
+
}
|
34 |
+
$subWhereClause .= $orFieldName;
|
35 |
+
$args[] = $orFieldValue;
|
36 |
+
}
|
37 |
+
$subWhereClause .= ")";
|
38 |
+
$sWhereClause .= $subWhereClause;
|
39 |
+
} else {
|
40 |
+
$sWhereClause .= $fieldName;
|
41 |
+
$args[] = $fieldValue;
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
$fromDataSets = $query->getFrom();
|
46 |
+
$columns = $query->getColumns();
|
47 |
+
$orderBys = $query->getOrderBy();
|
48 |
+
|
49 |
+
$sLimitClause = "";
|
50 |
+
if ($query->getLimit()) {
|
51 |
+
$sLimitClause .= " LIMIT ";
|
52 |
+
if ($query->getOffset()) {
|
53 |
+
$sLimitClause .= $query->getOffset() . ", ";
|
54 |
+
}
|
55 |
+
$sLimitClause .= $query->getLimit();
|
56 |
+
}
|
57 |
+
$joinClause = '';
|
58 |
+
if ($query->hasMetaJoin()) {
|
59 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
60 |
+
$occurrence = new WSAL_Adapters_MySQL_Occurrence($this->connection);
|
61 |
+
$joinClause = ' LEFT JOIN '. $meta->GetTable() .' AS meta ON meta.occurrence_id = '. $occurrence->GetTable() .'.id ';
|
62 |
+
}
|
63 |
+
$fields = (empty($columns))? $fromDataSets[0] . '.*' : implode(',', $columns);
|
64 |
+
if (!empty($searchCondition)) {
|
65 |
+
$args[] = $searchCondition['args'];
|
66 |
+
}
|
67 |
+
return 'SELECT ' . $fields
|
68 |
+
. ' FROM ' . implode(',', $fromDataSets)
|
69 |
+
. $joinClause
|
70 |
+
. $sWhereClause
|
71 |
+
. (!empty($searchCondition) ? (empty($sWhereClause) ? " WHERE ".$searchCondition['sql'] : " AND ".$searchCondition['sql']) : '')
|
72 |
+
// @todo GROUP BY goes here
|
73 |
+
. (!empty($orderBys) ? (' ORDER BY ' . implode(', ', array_keys($orderBys)) . ' ' . implode(', ', array_values($orderBys))) : '')
|
74 |
+
. $sLimitClause;
|
75 |
+
}
|
76 |
+
|
77 |
+
protected function getActiveRecordAdapter()
|
78 |
+
{
|
79 |
+
return new WSAL_Adapters_MySQL_ActiveRecord($this->connection);
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* @return WSAL_Models_ActiveRecord[] Execute query and return data as $ar_cls objects.
|
84 |
+
*/
|
85 |
+
public function Execute($query)
|
86 |
+
{
|
87 |
+
$args = array();
|
88 |
+
$sql = $this->GetSql($query, $args);
|
89 |
+
|
90 |
+
$occurenceAdapter = $query->getConnector()->getAdapter("Occurrence");
|
91 |
+
|
92 |
+
if (in_array($occurenceAdapter->GetTable(), $query->getFrom())) {
|
93 |
+
return $occurenceAdapter->LoadMulti($sql, $args);
|
94 |
+
} else {
|
95 |
+
return $this->getActiveRecordAdapter()->LoadMulti($sql, $args);
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @return int Use query for counting records.
|
101 |
+
*/
|
102 |
+
public function Count($query)
|
103 |
+
{
|
104 |
+
// back up columns, use COUNT as default column and generate sql
|
105 |
+
$cols = $query->getColumns();
|
106 |
+
$query->clearColumns();
|
107 |
+
$query->addColumn('COUNT(*)');
|
108 |
+
|
109 |
+
$args = array();
|
110 |
+
$sql = $this->GetSql($query, $args);
|
111 |
+
|
112 |
+
// restore columns
|
113 |
+
$query->setColumns($cols);
|
114 |
+
// execute query and return result
|
115 |
+
return $this->getActiveRecordAdapter()->CountQuery($sql, $args);
|
116 |
+
}
|
117 |
+
|
118 |
+
public function CountDelete($query)
|
119 |
+
{
|
120 |
+
$result = $this->GetSqlDelete($query, true);
|
121 |
+
// execute query and return result
|
122 |
+
return $this->getActiveRecordAdapter()->CountQuery($result['sql'], $result['args']);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Use query for deleting records.
|
127 |
+
*/
|
128 |
+
public function Delete($query)
|
129 |
+
{
|
130 |
+
$result = $this->GetSqlDelete($query);
|
131 |
+
$this->DeleteMetas($query, $result['args']);
|
132 |
+
return $this->getActiveRecordAdapter()->DeleteQuery($result['sql'], $result['args']);
|
133 |
+
}
|
134 |
+
|
135 |
+
public function DeleteMetas($query, $args)
|
136 |
+
{
|
137 |
+
// back up columns, use COUNT as default column and generate sql
|
138 |
+
$cols = $query->getColumns();
|
139 |
+
$query->clearColumns();
|
140 |
+
$query->addColumn('id');
|
141 |
+
$sql = $this->GetSql($query);
|
142 |
+
// restore columns
|
143 |
+
$query->setColumns($cols);
|
144 |
+
|
145 |
+
$_wpdb = $this->connection;
|
146 |
+
$occ_ids = array();
|
147 |
+
$sql = (!empty($args) ? $_wpdb->prepare($sql, $args) : $sql);
|
148 |
+
foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
|
149 |
+
$occ_ids[] = $data['id'];
|
150 |
+
}
|
151 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
152 |
+
$meta->DeleteByOccurenceIds($occ_ids);
|
153 |
+
}
|
154 |
+
|
155 |
+
public function GetSqlDelete($query, $getCount = false)
|
156 |
+
{
|
157 |
+
$result = array();
|
158 |
+
$args = array();
|
159 |
+
// back up columns, remove them for DELETE and generate sql
|
160 |
+
$cols = $query->getColumns();
|
161 |
+
$query->clearColumns();
|
162 |
+
|
163 |
+
$conditions = $query->getConditions();
|
164 |
+
|
165 |
+
$sWhereClause = "";
|
166 |
+
foreach ($conditions as $fieldName => $fieldValue) {
|
167 |
+
if (empty($sWhereClause)) {
|
168 |
+
$sWhereClause .= " WHERE ";
|
169 |
+
} else {
|
170 |
+
$sWhereClause .= " AND ";
|
171 |
+
}
|
172 |
+
$sWhereClause .= $fieldName;
|
173 |
+
$args[] = $fieldValue;
|
174 |
+
}
|
175 |
+
|
176 |
+
$fromDataSets = $query->getFrom();
|
177 |
+
$orderBys = $query->getOrderBy();
|
178 |
+
|
179 |
+
$sLimitClause = "";
|
180 |
+
if ($query->getLimit()) {
|
181 |
+
$sLimitClause .= " LIMIT ";
|
182 |
+
if ($query->getOffset()) {
|
183 |
+
$sLimitClause .= $query->getOffset() . ", ";
|
184 |
+
}
|
185 |
+
$sLimitClause .= $query->getLimit();
|
186 |
+
}
|
187 |
+
$result['sql'] = ($getCount ? 'SELECT COUNT(*) FROM ' : 'DELETE FROM ')
|
188 |
+
. implode(',', $fromDataSets)
|
189 |
+
. $sWhereClause
|
190 |
+
. (!empty($orderBys) ? (' ORDER BY ' . implode(', ', array_keys($orderBys)) . ' ' . implode(', ', array_values($orderBys))) : '')
|
191 |
+
. $sLimitClause;
|
192 |
+
$result['args'] = $args;
|
193 |
+
//restore columns
|
194 |
+
$query->setColumns($cols);
|
195 |
+
|
196 |
+
return $result;
|
197 |
+
}
|
198 |
+
|
199 |
+
public function SearchCondition($query)
|
200 |
+
{
|
201 |
+
$condition = $query->getSearchCondition();
|
202 |
+
if (empty($condition)) return null;
|
203 |
+
$searchConditions = array();
|
204 |
+
$meta = new WSAL_Adapters_MySQL_Meta($this->connection);
|
205 |
+
$occurrence = new WSAL_Adapters_MySQL_Occurrence($this->connection);
|
206 |
+
|
207 |
+
$searchConditions['sql'] = $occurrence->GetTable() .'.id IN (
|
208 |
+
SELECT DISTINCT occurrence_id
|
209 |
+
FROM ' . $meta->GetTable() . '
|
210 |
+
WHERE TRIM(BOTH "\"" FROM value) LIKE %s
|
211 |
+
)';
|
212 |
+
$searchConditions['args'] = "%". $condition. "%";
|
213 |
+
return $searchConditions;
|
214 |
+
}
|
215 |
+
|
216 |
+
}
|
classes/Models/Adapters/OccurrenceInterface.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
interface WSAL_Adapters_OccurrenceInterface
|
4 |
+
{
|
5 |
+
public function GetMeta($occurence);
|
6 |
+
public function GetNamedMeta($occurence, $name);
|
7 |
+
public function GetFirstNamedMeta($occurence, $names);
|
8 |
+
public static function GetNewestUnique($limit = PHP_INT_MAX);
|
9 |
+
public function CheckKnownUsers($args = array());
|
10 |
+
public function CheckUnKnownUsers($args = array());
|
11 |
+
}
|
classes/Models/Adapters/QueryInterface.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
interface WSAL_Adapters_QueryInterface
|
4 |
+
{
|
5 |
+
public function Execute($query);
|
6 |
+
public function Count($query);
|
7 |
+
public function Delete($query);
|
8 |
+
}
|
classes/Models/Meta.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Models_Meta extends WSAL_Models_ActiveRecord {
|
4 |
+
|
5 |
+
protected $adapterName = "Meta";
|
6 |
+
|
7 |
+
public $id = 0;
|
8 |
+
public $occurrence_id = 0;
|
9 |
+
public $name = '';
|
10 |
+
public $value = array(); // force mixed type
|
11 |
+
|
12 |
+
public function SaveMeta()
|
13 |
+
{
|
14 |
+
$this->_state = self::STATE_UNKNOWN;
|
15 |
+
$updateId = $this->getId();
|
16 |
+
$result = $this->getAdapter()->Save($this);
|
17 |
+
|
18 |
+
if ($result !== false) {
|
19 |
+
$this->_state = (!empty($updateId))?self::STATE_UPDATED:self::STATE_CREATED;
|
20 |
+
}
|
21 |
+
return $result;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function UpdateByNameAndOccurenceId($name, $value, $occurrenceId)
|
25 |
+
{
|
26 |
+
$meta = $this->getAdapter()->LoadByNameAndOccurenceId($name, $occurrenceId);
|
27 |
+
$this->id = $meta['id'];
|
28 |
+
$this->occurrence_id = $meta['occurrence_id'];
|
29 |
+
$this->name = $meta['name'];
|
30 |
+
$this->value = $value;
|
31 |
+
$this->saveMeta();
|
32 |
+
}
|
33 |
+
|
34 |
+
}
|
classes/Models/Occurrence.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
|
4 |
+
{
|
5 |
+
|
6 |
+
public $id = 0;
|
7 |
+
public $site_id = 0;
|
8 |
+
public $alert_id = 0;
|
9 |
+
public $created_on = 0.0;
|
10 |
+
public $is_read = false;
|
11 |
+
public $is_migrated = false;
|
12 |
+
protected $adapterName = "Occurrence";
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Returns the alert related to this occurrence.
|
16 |
+
* @return WSAL_Alert
|
17 |
+
*/
|
18 |
+
public function GetAlert()
|
19 |
+
{
|
20 |
+
return WpSecurityAuditLog::GetInstance()->alerts->GetAlert($this->alert_id);
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Returns the value of a meta item.
|
25 |
+
* @param string $name Name of meta item.
|
26 |
+
* @param mixed $default Default value returned when meta does not exist.
|
27 |
+
* @return mixed The value, if meta item does not exist $default returned.
|
28 |
+
*/
|
29 |
+
public function GetMetaValue($name, $default = array())
|
30 |
+
{
|
31 |
+
//get meta adapter
|
32 |
+
//call the function ($name, $this->getId())
|
33 |
+
$meta = $this->getAdapter()->GetNamedMeta($this, $name);
|
34 |
+
return maybe_unserialize($meta['value']);
|
35 |
+
|
36 |
+
//TO DO: re-introduce add is loaded check before running query
|
37 |
+
//return $meta->IsLoaded() ? $meta->value : $default;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Set the value of a meta item (creates or updates meta item).
|
42 |
+
* @param string $name Meta name.
|
43 |
+
* @param mixed $value Meta value.
|
44 |
+
*/
|
45 |
+
public function SetMetaValue($name, $value)
|
46 |
+
{
|
47 |
+
//get meta adapter
|
48 |
+
$model = new WSAL_Models_Meta();
|
49 |
+
$model->occurrence_id = $this->getId();
|
50 |
+
$model->name = $name;
|
51 |
+
$model->value = maybe_serialize($value);
|
52 |
+
$model->SaveMeta();
|
53 |
+
}
|
54 |
+
|
55 |
+
public function UpdateMetaValue($name, $value)
|
56 |
+
{
|
57 |
+
$model = new WSAL_Models_Meta();
|
58 |
+
$model->UpdateByNameAndOccurenceId($name, $value, $this->getId());
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Returns a key-value pair of meta data.
|
63 |
+
* @return array
|
64 |
+
*/
|
65 |
+
public function GetMetaArray()
|
66 |
+
{
|
67 |
+
$result = array();
|
68 |
+
$metas = $this->getAdapter()->GetMultiMeta($this);
|
69 |
+
foreach ($metas as $meta) {
|
70 |
+
$result[$meta->name] = maybe_unserialize($meta->value);
|
71 |
+
}
|
72 |
+
return $result;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Creates or updates all meta data passed as an array of meta-key/meta-value pairs.
|
77 |
+
* @param array $data New meta data.
|
78 |
+
*/
|
79 |
+
public function SetMeta($data)
|
80 |
+
{
|
81 |
+
foreach ((array)$data as $key => $val) {
|
82 |
+
$this->SetMetaValue($key, $val);
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* @param callable|null $metaFormatter (Optional) Meta formatter callback.
|
88 |
+
* @return string Full-formatted message.
|
89 |
+
*/
|
90 |
+
public function GetMessage($metaFormatter = null)
|
91 |
+
{
|
92 |
+
if (!isset($this->_cachedmessage)) {
|
93 |
+
// get correct message entry
|
94 |
+
if ($this->is_migrated) {
|
95 |
+
$this->_cachedmessage = $this->GetMetaValue('MigratedMesg', false);
|
96 |
+
}
|
97 |
+
if (!$this->is_migrated || !$this->_cachedmessage) {
|
98 |
+
$this->_cachedmessage = $this->GetAlert()->mesg;
|
99 |
+
}
|
100 |
+
// fill variables in message
|
101 |
+
$this->_cachedmessage = $this->GetAlert()->GetMessage($this->GetMetaArray(), $metaFormatter, $this->_cachedmessage);
|
102 |
+
}
|
103 |
+
return $this->_cachedmessage;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Delete occurrence as well as associated meta data.
|
108 |
+
* @return boolean True on success, false on failure.
|
109 |
+
*/
|
110 |
+
public function Delete()
|
111 |
+
{
|
112 |
+
foreach ($this->getAdapter()->GetMeta() as $meta) {
|
113 |
+
$meta->Delete();
|
114 |
+
}
|
115 |
+
return parent::Delete();
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* @return string User's username.
|
120 |
+
*/
|
121 |
+
public function GetUsername()
|
122 |
+
{
|
123 |
+
$meta = $this->getAdapter()->GetFirstNamedMeta($this, array('Username', 'CurrentUserID'));
|
124 |
+
if ($meta) {
|
125 |
+
switch(true){
|
126 |
+
case $meta->name == 'Username':
|
127 |
+
return $meta->value;
|
128 |
+
case $meta->name == 'CurrentUserID':
|
129 |
+
return ($data = get_userdata($meta->value)) ? $data->user_login : null;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
return null;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* @return string IP address of request.
|
137 |
+
*/
|
138 |
+
public function GetSourceIP()
|
139 |
+
{
|
140 |
+
return $this->GetMetaValue('ClientIP', '');
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* @return string IP address of request (from proxies etc).
|
145 |
+
*/
|
146 |
+
public function GetOtherIPs()
|
147 |
+
{
|
148 |
+
$result = array();
|
149 |
+
$data = (array)$this->GetMetaValue('OtherIPs', array());
|
150 |
+
foreach ($data as $ips) {
|
151 |
+
foreach ($ips as $ip) {
|
152 |
+
$result[] = $ip;
|
153 |
+
}
|
154 |
+
}
|
155 |
+
return array_unique($result);
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* @return array Array of user roles.
|
160 |
+
*/
|
161 |
+
public function GetUserRoles()
|
162 |
+
{
|
163 |
+
return $this->GetMetaValue('CurrentUserRoles', array());
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @return float Number of seconds (and microseconds as fraction) since unix Day 0.
|
168 |
+
* @todo This needs some caching.
|
169 |
+
*/
|
170 |
+
protected function GetMicrotime()
|
171 |
+
{
|
172 |
+
return microtime(true);// + get_option('gmt_offset') * HOUR_IN_SECONDS;
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Finds occurences of the same type by IP and Username within specified time frame
|
177 |
+
* @param string $ipAddress
|
178 |
+
* @param string $username
|
179 |
+
* @param int $alertId Alert type we are lookign for
|
180 |
+
* @param int $siteId
|
181 |
+
* @param $startTime mktime
|
182 |
+
* @param $endTime mktime
|
183 |
+
*/
|
184 |
+
public function CheckKnownUsers($args = array())
|
185 |
+
{
|
186 |
+
return $this->getAdapter()->CheckKnownUsers($args);
|
187 |
+
}
|
188 |
+
|
189 |
+
public function CheckUnKnownUsers($args = array())
|
190 |
+
{
|
191 |
+
return $this->getAdapter()->CheckUnKnownUsers($args);
|
192 |
+
}
|
193 |
+
}
|
classes/Models/OccurrenceQuery.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Models_OccurrenceQuery extends WSAL_Models_Query
|
4 |
+
{
|
5 |
+
protected $arguments = array();
|
6 |
+
|
7 |
+
public function addArgument($field, $value)
|
8 |
+
{
|
9 |
+
$this->arguments[$field] = $value;
|
10 |
+
return $this;
|
11 |
+
}
|
12 |
+
|
13 |
+
public function clearArguments()
|
14 |
+
{
|
15 |
+
$this->arguments = array();
|
16 |
+
return $this;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function __construct()
|
20 |
+
{
|
21 |
+
parent::__construct();
|
22 |
+
|
23 |
+
//TO DO: Consider if Get Table is the right method to call given that this is mysql specific
|
24 |
+
$this->addFrom(
|
25 |
+
$this->getConnector()->getAdapter("Occurrence")->GetTable()
|
26 |
+
);
|
27 |
+
}
|
28 |
+
|
29 |
+
}
|
classes/Models/Option.php
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Wordpress options are always loaded from the default wordpress database.
|
5 |
+
*/
|
6 |
+
class WSAL_Models_Option extends WSAL_Models_ActiveRecord
|
7 |
+
{
|
8 |
+
|
9 |
+
protected $adapterName = "Option";
|
10 |
+
public $id = '';
|
11 |
+
public $option_name = '';
|
12 |
+
public $option_value = '';
|
13 |
+
/**
|
14 |
+
* Options are always stored in WPDB. This setting ensures that
|
15 |
+
*/
|
16 |
+
protected $useDefaultAdapter = true;
|
17 |
+
|
18 |
+
public function SetOptionValue($name, $value)
|
19 |
+
{
|
20 |
+
$option = $this->getAdapter()->GetNamedOption($name);
|
21 |
+
$this->id = $option['id'];
|
22 |
+
$this->option_name = $name;
|
23 |
+
// Serialize if $value is array or object
|
24 |
+
$value = maybe_serialize($value);
|
25 |
+
$this->option_value = $value;
|
26 |
+
return $this->Save();
|
27 |
+
}
|
28 |
+
|
29 |
+
public function GetOptionValue($name, $default = array())
|
30 |
+
{
|
31 |
+
$option = $this->getAdapter()->GetNamedOption($name);
|
32 |
+
$this->option_value = (!empty($option)) ? $option['option_value'] : null;
|
33 |
+
if (!empty($this->option_value)) {
|
34 |
+
$this->_state = self::STATE_LOADED;
|
35 |
+
}
|
36 |
+
// Unerialize if $value is array or object
|
37 |
+
$this->option_value = maybe_unserialize($this->option_value);
|
38 |
+
return $this->IsLoaded() ? $this->option_value : $default;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function Save()
|
42 |
+
{
|
43 |
+
$this->_state = self::STATE_UNKNOWN;
|
44 |
+
|
45 |
+
$updateId = $this->getId();
|
46 |
+
$result = $this->getAdapter()->Save($this);
|
47 |
+
|
48 |
+
if ($result !== false) {
|
49 |
+
$this->_state = (!empty($updateId))?self::STATE_UPDATED:self::STATE_CREATED;
|
50 |
+
}
|
51 |
+
return $result;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function GetNotificationsSetting($opt_prefix)
|
55 |
+
{
|
56 |
+
return $this->getAdapter()->GetNotificationsSetting($opt_prefix);
|
57 |
+
}
|
58 |
+
|
59 |
+
public function GetNotification($id)
|
60 |
+
{
|
61 |
+
return $this->LoadData(
|
62 |
+
$this->getAdapter()->GetNotification($id)
|
63 |
+
);
|
64 |
+
}
|
65 |
+
|
66 |
+
public function DeleteByName($name)
|
67 |
+
{
|
68 |
+
return $this->getAdapter()->DeleteByName($name);
|
69 |
+
}
|
70 |
+
|
71 |
+
public function DeleteByPrefix($opt_prefix)
|
72 |
+
{
|
73 |
+
return $this->getAdapter()->DeleteByPrefix($opt_prefix);
|
74 |
+
}
|
75 |
+
|
76 |
+
public function CountNotifications($opt_prefix)
|
77 |
+
{
|
78 |
+
return $this->getAdapter()->CountNotifications($opt_prefix);
|
79 |
+
}
|
80 |
+
}
|
classes/Models/Query.php
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WSAL_Models_Query
|
4 |
+
{
|
5 |
+
protected $columns = array();
|
6 |
+
protected $conditions = array();
|
7 |
+
protected $orderBy = array();
|
8 |
+
protected $offset = null;
|
9 |
+
protected $limit = null;
|
10 |
+
protected $from = array();
|
11 |
+
protected $meta_join = false;
|
12 |
+
protected $searchCondition = null;
|
13 |
+
protected $useDefaultAdapter = false;
|
14 |
+
|
15 |
+
public function __construct()
|
16 |
+
{
|
17 |
+
|
18 |
+
}
|
19 |
+
|
20 |
+
public function getConnector()
|
21 |
+
{
|
22 |
+
if (!empty($this->connector)) {
|
23 |
+
return $this->connector;
|
24 |
+
}
|
25 |
+
if ($this->useDefaultAdapter) {
|
26 |
+
$this->connector = WSAL_Connector_ConnectorFactory::GetDefaultConnector();
|
27 |
+
} else {
|
28 |
+
$this->connector = WSAL_Connector_ConnectorFactory::GetConnector();
|
29 |
+
}
|
30 |
+
return $this->connector;
|
31 |
+
}
|
32 |
+
|
33 |
+
public function getAdapter()
|
34 |
+
{
|
35 |
+
return $this->getConnector()->getAdapter('Query');
|
36 |
+
}
|
37 |
+
|
38 |
+
public function addColumn($column)
|
39 |
+
{
|
40 |
+
$this->columns[] = $column;
|
41 |
+
return $this;
|
42 |
+
}
|
43 |
+
|
44 |
+
public function clearColumns()
|
45 |
+
{
|
46 |
+
$this->columns = array();
|
47 |
+
return $this;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function getColumns()
|
51 |
+
{
|
52 |
+
return $this->columns;
|
53 |
+
}
|
54 |
+
|
55 |
+
public function setColumns($columns)
|
56 |
+
{
|
57 |
+
$this->columns = $columns;
|
58 |
+
return $this;
|
59 |
+
}
|
60 |
+
|
61 |
+
public function addCondition($field, $value)
|
62 |
+
{
|
63 |
+
$this->conditions[$field] = $value;
|
64 |
+
return $this;
|
65 |
+
}
|
66 |
+
|
67 |
+
public function addORCondition($aConditions)
|
68 |
+
{
|
69 |
+
$this->conditions[] = $aConditions;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function clearConditions()
|
73 |
+
{
|
74 |
+
$this->conditions = array();
|
75 |
+
return $this;
|
76 |
+
}
|
77 |
+
|
78 |
+
public function getConditions()
|
79 |
+
{
|
80 |
+
return $this->conditions;
|
81 |
+
}
|
82 |
+
|
83 |
+
public function addOrderBy($field, $isDescending = false)
|
84 |
+
{
|
85 |
+
$order = ($isDescending) ? 'DESC' : 'ASC';
|
86 |
+
$this->orderBy[$field] = $order;
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
|
90 |
+
public function clearOrderBy()
|
91 |
+
{
|
92 |
+
$this->orderBy = array();
|
93 |
+
return $this;
|
94 |
+
}
|
95 |
+
|
96 |
+
public function getOrderBy()
|
97 |
+
{
|
98 |
+
return $this->orderBy;
|
99 |
+
}
|
100 |
+
|
101 |
+
public function addFrom($fromDataSet)
|
102 |
+
{
|
103 |
+
$this->from[] = $fromDataSet;
|
104 |
+
return $this;
|
105 |
+
}
|
106 |
+
|
107 |
+
public function clearFrom()
|
108 |
+
{
|
109 |
+
$this->from = array();
|
110 |
+
return $this;
|
111 |
+
}
|
112 |
+
|
113 |
+
public function getFrom()
|
114 |
+
{
|
115 |
+
return $this->from;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Gets the value of limit.
|
120 |
+
*
|
121 |
+
* @return mixed
|
122 |
+
*/
|
123 |
+
public function getLimit()
|
124 |
+
{
|
125 |
+
return $this->limit;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Sets the value of limit.
|
130 |
+
*
|
131 |
+
* @param mixed $limit the limit
|
132 |
+
*
|
133 |
+
* @return self
|
134 |
+
*/
|
135 |
+
public function setLimit($limit)
|
136 |
+
{
|
137 |
+
$this->limit = $limit;
|
138 |
+
|
139 |
+
return $this;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Gets the value of offset.
|
144 |
+
*
|
145 |
+
* @return mixed
|
146 |
+
*/
|
147 |
+
public function getOffset()
|
148 |
+
{
|
149 |
+
return $this->offset;
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Sets the value of offset.
|
154 |
+
*
|
155 |
+
* @param mixed $offset the offset
|
156 |
+
*
|
157 |
+
* @return self
|
158 |
+
*/
|
159 |
+
public function setOffset($offset)
|
160 |
+
{
|
161 |
+
$this->offset = $offset;
|
162 |
+
|
163 |
+
return $this;
|
164 |
+
}
|
165 |
+
|
166 |
+
public function addSearchCondition($value)
|
167 |
+
{
|
168 |
+
$this->searchCondition = $value;
|
169 |
+
return $this;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function getSearchCondition()
|
173 |
+
{
|
174 |
+
return $this->searchCondition;
|
175 |
+
}
|
176 |
+
|
177 |
+
public function hasMetaJoin()
|
178 |
+
{
|
179 |
+
return $this->meta_join;
|
180 |
+
}
|
181 |
+
|
182 |
+
public function addMetaJoin()
|
183 |
+
{
|
184 |
+
$this->meta_join = true;
|
185 |
+
return $this;
|
186 |
+
}
|
187 |
+
}
|
classes/Sensors/LogInOut.php
CHANGED
@@ -16,9 +16,11 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
|
16 |
}
|
17 |
|
18 |
public function EventLogin($user_login, $user){
|
|
|
|
|
19 |
$this->plugin->alerts->Trigger(1000, array(
|
20 |
'Username' => $user_login,
|
21 |
-
'CurrentUserRoles' => $
|
22 |
), true);
|
23 |
}
|
24 |
|
@@ -83,45 +85,36 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
|
83 |
list($y, $m, $d) = explode('-', date('Y-m-d'));
|
84 |
|
85 |
$ip = $this->plugin->settings->GetMainClientIP();
|
86 |
-
$tt1 = new WSAL_DB_Occurrence();
|
87 |
-
$tt2 = new WSAL_DB_Meta();
|
88 |
|
89 |
$username = $_POST["log"];
|
90 |
$newAlertCode = 1003;
|
91 |
$user = get_user_by('login', $username);
|
92 |
$site_id = (function_exists('get_current_blog_id') ? get_current_blog_id() : 0);
|
93 |
if ($user) {
|
94 |
-
$newAlertCode = 1002;
|
95 |
$userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
|
|
|
96 |
}
|
97 |
|
98 |
if($this->IsPastLoginFailureLimit($ip, $site_id, $user))return;
|
99 |
|
|
|
|
|
100 |
if ($newAlertCode == 1002) {
|
101 |
if (!$this->plugin->alerts->CheckEnableUserRoles($username, $userRoles))return;
|
102 |
-
$occ =
|
103 |
-
SELECT occurrence.* FROM `' . $tt1->GetTable() . '` occurrence
|
104 |
-
INNER JOIN `' . $tt2->GetTable() . '` ipMeta on ipMeta.occurrence_id = occurrence.id
|
105 |
-
and ipMeta.name = "ClientIP"
|
106 |
-
and ipMeta.value = %s
|
107 |
-
INNER JOIN `' . $tt2->GetTable() . '` usernameMeta on usernameMeta.occurrence_id = occurrence.id
|
108 |
-
and usernameMeta.name = "Username"
|
109 |
-
and usernameMeta.value = %s
|
110 |
-
WHERE occurrence.alert_id = %d AND occurrence.site_id = %d
|
111 |
-
AND (created_on BETWEEN %d AND %d)
|
112 |
-
GROUP BY occurrence.id',
|
113 |
array(
|
114 |
-
|
115 |
-
|
116 |
1002,
|
117 |
$site_id,
|
118 |
mktime(0, 0, 0, $m, $d, $y),
|
119 |
mktime(0, 0, 0, $m, $d + 1, $y) - 1
|
120 |
)
|
121 |
);
|
122 |
-
|
123 |
$occ = count($occ) ? $occ[0] : null;
|
124 |
-
|
|
|
125 |
// update existing record exists user
|
126 |
$this->IncrementLoginFailure($ip, $site_id, $user);
|
127 |
$new = $occ->GetMetaValue('Attempts', 0) + 1;
|
@@ -129,8 +122,8 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
|
129 |
if($new > $this->GetLoginFailureLogLimit())
|
130 |
$new = $this->GetLoginFailureLogLimit() . '+';
|
131 |
|
132 |
-
$occ->
|
133 |
-
$occ->
|
134 |
//$occ->SetMetaValue('CurrentUserRoles', $userRoles);
|
135 |
$occ->created_on = null;
|
136 |
$occ->Save();
|
@@ -143,15 +136,9 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
|
143 |
));
|
144 |
}
|
145 |
} else {
|
146 |
-
$occUnknown =
|
147 |
-
SELECT occurrence.* FROM `' . $tt1->GetTable() . '` occurrence
|
148 |
-
INNER JOIN `' . $tt2->GetTable() . '` ipMeta on ipMeta.occurrence_id = occurrence.id
|
149 |
-
and ipMeta.name = "ClientIP" and ipMeta.value = %s
|
150 |
-
WHERE occurrence.alert_id = %d AND occurrence.site_id = %d
|
151 |
-
AND (created_on BETWEEN %d AND %d)
|
152 |
-
GROUP BY occurrence.id',
|
153 |
array(
|
154 |
-
|
155 |
1003,
|
156 |
$site_id,
|
157 |
mktime(0, 0, 0, $m, $d, $y),
|
@@ -160,7 +147,7 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
|
160 |
);
|
161 |
|
162 |
$occUnknown = count($occUnknown) ? $occUnknown[0] : null;
|
163 |
-
if($occUnknown
|
164 |
// update existing record not exists user
|
165 |
$this->IncrementLoginFailure($ip, $site_id, false);
|
166 |
$new = $occUnknown->GetMetaValue('Attempts', 0) + 1;
|
@@ -168,7 +155,7 @@ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
|
|
168 |
if($new > $this->GetLoginFailureLogLimit())
|
169 |
$new = $this->GetLoginFailureLogLimit() . '+';
|
170 |
|
171 |
-
$occUnknown->
|
172 |
$occUnknown->created_on = null;
|
173 |
$occUnknown->Save();
|
174 |
} else {
|
16 |
}
|
17 |
|
18 |
public function EventLogin($user_login, $user){
|
19 |
+
$userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
|
20 |
+
if ( $this->plugin->settings->IsLoginSuperAdmin($user_login) ) $userRoles[] = 'superadmin';
|
21 |
$this->plugin->alerts->Trigger(1000, array(
|
22 |
'Username' => $user_login,
|
23 |
+
'CurrentUserRoles' => $userRoles,
|
24 |
), true);
|
25 |
}
|
26 |
|
85 |
list($y, $m, $d) = explode('-', date('Y-m-d'));
|
86 |
|
87 |
$ip = $this->plugin->settings->GetMainClientIP();
|
|
|
|
|
88 |
|
89 |
$username = $_POST["log"];
|
90 |
$newAlertCode = 1003;
|
91 |
$user = get_user_by('login', $username);
|
92 |
$site_id = (function_exists('get_current_blog_id') ? get_current_blog_id() : 0);
|
93 |
if ($user) {
|
94 |
+
$newAlertCode = 1002;
|
95 |
$userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
|
96 |
+
if ( $this->plugin->settings->IsLoginSuperAdmin($username) ) $userRoles[] = 'superadmin';
|
97 |
}
|
98 |
|
99 |
if($this->IsPastLoginFailureLimit($ip, $site_id, $user))return;
|
100 |
|
101 |
+
$objOcc = new WSAL_Models_Occurrence();
|
102 |
+
|
103 |
if ($newAlertCode == 1002) {
|
104 |
if (!$this->plugin->alerts->CheckEnableUserRoles($username, $userRoles))return;
|
105 |
+
$occ = $objOcc->CheckKnownUsers(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
array(
|
107 |
+
$ip,
|
108 |
+
$username,
|
109 |
1002,
|
110 |
$site_id,
|
111 |
mktime(0, 0, 0, $m, $d, $y),
|
112 |
mktime(0, 0, 0, $m, $d + 1, $y) - 1
|
113 |
)
|
114 |
);
|
|
|
115 |
$occ = count($occ) ? $occ[0] : null;
|
116 |
+
|
117 |
+
if(!empty($occ)){
|
118 |
// update existing record exists user
|
119 |
$this->IncrementLoginFailure($ip, $site_id, $user);
|
120 |
$new = $occ->GetMetaValue('Attempts', 0) + 1;
|
122 |
if($new > $this->GetLoginFailureLogLimit())
|
123 |
$new = $this->GetLoginFailureLogLimit() . '+';
|
124 |
|
125 |
+
$occ->UpdateMetaValue('Attempts', $new);
|
126 |
+
$occ->UpdateMetaValue('Username', $username);
|
127 |
//$occ->SetMetaValue('CurrentUserRoles', $userRoles);
|
128 |
$occ->created_on = null;
|
129 |
$occ->Save();
|
136 |
));
|
137 |
}
|
138 |
} else {
|
139 |
+
$occUnknown = $objOcc->CheckUnKnownUsers(
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
array(
|
141 |
+
$ip,
|
142 |
1003,
|
143 |
$site_id,
|
144 |
mktime(0, 0, 0, $m, $d, $y),
|
147 |
);
|
148 |
|
149 |
$occUnknown = count($occUnknown) ? $occUnknown[0] : null;
|
150 |
+
if(!empty($occUnknown)) {
|
151 |
// update existing record not exists user
|
152 |
$this->IncrementLoginFailure($ip, $site_id, false);
|
153 |
$new = $occUnknown->GetMetaValue('Attempts', 0) + 1;
|
155 |
if($new > $this->GetLoginFailureLogLimit())
|
156 |
$new = $this->GetLoginFailureLogLimit() . '+';
|
157 |
|
158 |
+
$occUnknown->UpdateMetaValue('Attempts', $new);
|
159 |
$occUnknown->created_on = null;
|
160 |
$occUnknown->Save();
|
161 |
} else {
|
classes/Sensors/UserProfile.php
CHANGED
@@ -73,15 +73,17 @@ class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor {
|
|
73 |
}*/
|
74 |
|
75 |
// password changed
|
76 |
-
if(!empty($_REQUEST['pass1'])){
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
'
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
85 |
}
|
86 |
|
87 |
// email changed
|
73 |
}*/
|
74 |
|
75 |
// password changed
|
76 |
+
if(!empty($_REQUEST['pass1']) && !empty($_REQUEST['pass2'])){
|
77 |
+
if (trim($_REQUEST['pass1']) == trim($_REQUEST['pass2'])) {
|
78 |
+
$event = $user_id == get_current_user_id() ? 4003 : 4004;
|
79 |
+
$this->plugin->alerts->Trigger($event, array(
|
80 |
+
'TargetUserID' => $user_id,
|
81 |
+
'TargetUserData' => (object)array(
|
82 |
+
'Username' => $user->user_login,
|
83 |
+
'Roles' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
|
84 |
+
),
|
85 |
+
));
|
86 |
+
}
|
87 |
}
|
88 |
|
89 |
// email changed
|
classes/Settings.php
CHANGED
@@ -183,10 +183,10 @@ class WSAL_Settings {
|
|
183 |
$this->_plugin->SetGlobalOption('pruning-limit-e', $enabled);
|
184 |
}
|
185 |
public function IsPruningDateEnabled(){
|
186 |
-
return $this->_plugin->GetGlobalOption('pruning-date-e'
|
187 |
}
|
188 |
public function IsPruningLimitEnabled(){
|
189 |
-
return $this->_plugin->GetGlobalOption('pruning-limit-e'
|
190 |
}
|
191 |
public function IsRestrictAdmins(){
|
192 |
return $this->_plugin->GetGlobalOption('restrict-admins', false);
|
@@ -368,11 +368,17 @@ class WSAL_Settings {
|
|
368 |
}
|
369 |
return false;
|
370 |
}
|
371 |
-
public function GetCurrentUserRoles($baseRoles = null){
|
372 |
if ($baseRoles == null) $baseRoles = wp_get_current_user()->roles;
|
373 |
if (function_exists('is_super_admin') && is_super_admin()) $baseRoles[] = 'superadmin';
|
374 |
return $baseRoles;
|
375 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
|
377 |
// </editor-fold>
|
378 |
|
@@ -547,6 +553,26 @@ class WSAL_Settings {
|
|
547 |
}
|
548 |
return $this->_excluded_custom;
|
549 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
550 |
|
551 |
// </editor-fold>
|
552 |
}
|
183 |
$this->_plugin->SetGlobalOption('pruning-limit-e', $enabled);
|
184 |
}
|
185 |
public function IsPruningDateEnabled(){
|
186 |
+
return $this->_plugin->GetGlobalOption('pruning-date-e');
|
187 |
}
|
188 |
public function IsPruningLimitEnabled(){
|
189 |
+
return $this->_plugin->GetGlobalOption('pruning-limit-e');
|
190 |
}
|
191 |
public function IsRestrictAdmins(){
|
192 |
return $this->_plugin->GetGlobalOption('restrict-admins', false);
|
368 |
}
|
369 |
return false;
|
370 |
}
|
371 |
+
public function GetCurrentUserRoles($baseRoles = null){
|
372 |
if ($baseRoles == null) $baseRoles = wp_get_current_user()->roles;
|
373 |
if (function_exists('is_super_admin') && is_super_admin()) $baseRoles[] = 'superadmin';
|
374 |
return $baseRoles;
|
375 |
}
|
376 |
+
|
377 |
+
public function IsLoginSuperAdmin($username){
|
378 |
+
$userId = username_exists($username);
|
379 |
+
if ( function_exists('is_super_admin') && is_super_admin($userId) ) return true;
|
380 |
+
else return false;
|
381 |
+
}
|
382 |
|
383 |
// </editor-fold>
|
384 |
|
553 |
}
|
554 |
return $this->_excluded_custom;
|
555 |
}
|
556 |
+
|
557 |
+
/**
|
558 |
+
* Datetime format.
|
559 |
+
* 24 hours or AM/PM
|
560 |
+
*/
|
561 |
+
public function GetDatetimeFormat(){
|
562 |
+
return $this->_plugin->GetGlobalOption('datetime-format', 0);
|
563 |
+
}
|
564 |
+
|
565 |
+
public function SetDatetimeFormat($newvalue){
|
566 |
+
return $this->_plugin->SetGlobalOption('datetime-format', $newvalue);
|
567 |
+
}
|
568 |
+
|
569 |
+
public function GetAdapterConfig($name_field){
|
570 |
+
return $this->_plugin->GetGlobalOption($name_field);
|
571 |
+
}
|
572 |
+
|
573 |
+
public function SetAdapterConfig($name_field, $newvalue){
|
574 |
+
return $this->_plugin->SetGlobalOption($name_field, trim($newvalue));
|
575 |
+
}
|
576 |
|
577 |
// </editor-fold>
|
578 |
}
|
classes/Views/AuditLog.php
CHANGED
@@ -65,6 +65,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
65 |
}
|
66 |
|
67 |
$this->GetListView()->prepare_items();
|
|
|
68 |
|
69 |
?><form id="audit-log-viewer" method="post">
|
70 |
<div id="audit-log-viewer-content">
|
@@ -87,7 +88,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
87 |
),
|
88 |
'autorefresh' => array(
|
89 |
'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
|
90 |
-
'token' => (int)
|
91 |
),
|
92 |
)); ?>);
|
93 |
});
|
@@ -99,7 +100,7 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
99 |
die('Access Denied.');
|
100 |
if(!isset($_REQUEST['occurrence']))
|
101 |
die('Occurrence parameter expected.');
|
102 |
-
$occ = new
|
103 |
$occ->Load('id = %d', array((int)$_REQUEST['occurrence']));
|
104 |
|
105 |
echo '<!DOCTYPE html><html><head>';
|
@@ -129,7 +130,8 @@ class WSAL_Views_AuditLog extends WSAL_AbstractView {
|
|
129 |
session_write_close(); // fixes session lock issue
|
130 |
|
131 |
do{
|
132 |
-
$
|
|
|
133 |
usleep(500000); // 500msec
|
134 |
}while(($old == $new) && (--$max > 0));
|
135 |
|
65 |
}
|
66 |
|
67 |
$this->GetListView()->prepare_items();
|
68 |
+
$occ = new WSAL_Models_Occurrence();
|
69 |
|
70 |
?><form id="audit-log-viewer" method="post">
|
71 |
<div id="audit-log-viewer-content">
|
88 |
),
|
89 |
'autorefresh' => array(
|
90 |
'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
|
91 |
+
'token' => (int)$occ->Count(),
|
92 |
),
|
93 |
)); ?>);
|
94 |
});
|
100 |
die('Access Denied.');
|
101 |
if(!isset($_REQUEST['occurrence']))
|
102 |
die('Occurrence parameter expected.');
|
103 |
+
$occ = new WSAL_Models_Occurrence();
|
104 |
$occ->Load('id = %d', array((int)$_REQUEST['occurrence']));
|
105 |
|
106 |
echo '<!DOCTYPE html><html><head>';
|
130 |
session_write_close(); // fixes session lock issue
|
131 |
|
132 |
do{
|
133 |
+
$occ = new WSAL_Models_Occurrence();
|
134 |
+
$new = $occ->Count();
|
135 |
usleep(500000); // 500msec
|
136 |
}while(($old == $new) && (--$max > 0));
|
137 |
|
classes/Views/Settings.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
<?php
|
2 |
class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
|
|
|
3 |
|
4 |
public function __construct(WpSecurityAuditLog $plugin) {
|
5 |
parent::__construct($plugin);
|
@@ -61,10 +63,38 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
61 |
$this->_plugin->settings->SetInternalIPsFiltering(isset($_REQUEST['EnableIpFiltering']));
|
62 |
$this->_plugin->settings->SetIncognito(isset($_REQUEST['Incognito']));
|
63 |
$this->_plugin->settings->SetDeleteData(isset($_REQUEST['DeleteData']));
|
|
|
64 |
$this->_plugin->settings->ClearDevOptions();
|
65 |
-
|
66 |
-
|
|
|
67 |
$this->_plugin->settings->SetDevOptionEnabled($opt, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
}
|
69 |
|
70 |
public function AjaxCheckSecurityToken(){
|
@@ -90,14 +120,20 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
90 |
if(isset($_POST['submit'])){
|
91 |
try {
|
92 |
$this->Save();
|
93 |
-
?><div class="updated"
|
|
|
|
|
94 |
}catch(Exception $ex){
|
95 |
?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
|
96 |
}
|
97 |
}
|
98 |
?>
|
99 |
-
<h2 id="wsal-tabs" class="nav-tab-wrapper"
|
100 |
-
|
|
|
|
|
|
|
|
|
101 |
<form id="audit-log-settings" method="post">
|
102 |
<input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
|
103 |
<input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
|
@@ -288,6 +324,24 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
288 |
</fieldset>
|
289 |
</td>
|
290 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
<tr>
|
292 |
<th><label><?php _e('Developer Options', 'wp-security-audit-log'); ?></label></th>
|
293 |
<td>
|
@@ -361,6 +415,7 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
361 |
</tr>
|
362 |
</tbody>
|
363 |
</table>
|
|
|
364 |
<table class="form-table wsal-tab widefat" id="tab-exclude">
|
365 |
<tbody>
|
366 |
<tr>
|
@@ -434,8 +489,84 @@ class WSAL_Views_Settings extends WSAL_AbstractView {
|
|
434 |
</tr>
|
435 |
</tbody>
|
436 |
</table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
437 |
</div>
|
438 |
-
<p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"></p>
|
439 |
</form>
|
440 |
<script type="text/javascript">
|
441 |
<!--
|
1 |
<?php
|
2 |
class WSAL_Views_Settings extends WSAL_AbstractView {
|
3 |
+
|
4 |
+
public $adapterMsg = '';
|
5 |
|
6 |
public function __construct(WpSecurityAuditLog $plugin) {
|
7 |
parent::__construct($plugin);
|
63 |
$this->_plugin->settings->SetInternalIPsFiltering(isset($_REQUEST['EnableIpFiltering']));
|
64 |
$this->_plugin->settings->SetIncognito(isset($_REQUEST['Incognito']));
|
65 |
$this->_plugin->settings->SetDeleteData(isset($_REQUEST['DeleteData']));
|
66 |
+
$this->_plugin->settings->SetDatetimeFormat($_REQUEST['DatetimeFormat']);
|
67 |
$this->_plugin->settings->ClearDevOptions();
|
68 |
+
|
69 |
+
if(isset($_REQUEST['DevOptions'])) {
|
70 |
+
foreach($_REQUEST['DevOptions'] as $opt) {
|
71 |
$this->_plugin->settings->SetDevOptionEnabled($opt, true);
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
//
|
76 |
+
// Database Adapter Settings
|
77 |
+
// Temporarily not used
|
78 |
+
//
|
79 |
+
/* Check Adapter config */
|
80 |
+
if (!empty($_REQUEST["AdapterUser"]) && ($_REQUEST['AdapterUser'] != '') && ($_REQUEST['AdapterName'] != '') && ($_REQUEST['AdapterHostname'] != '') ) {
|
81 |
+
WSAL_Connector_ConnectorFactory::CheckConfig(
|
82 |
+
trim($_REQUEST['AdapterType']),
|
83 |
+
trim($_REQUEST['AdapterUser']),
|
84 |
+
trim($_REQUEST['AdapterPassword']),
|
85 |
+
trim($_REQUEST['AdapterName']),
|
86 |
+
trim($_REQUEST['AdapterHostname']),
|
87 |
+
trim($_REQUEST['AdapterBasePrefix'])
|
88 |
+
);
|
89 |
+
|
90 |
+
/* Setting Adapter config */
|
91 |
+
$this->_plugin->settings->SetAdapterConfig('adapter-type', $_REQUEST['AdapterType']);
|
92 |
+
$this->_plugin->settings->SetAdapterConfig('adapter-user', $_REQUEST['AdapterUser']);
|
93 |
+
$this->_plugin->settings->SetAdapterConfig('adapter-password', $_REQUEST['AdapterPassword']);
|
94 |
+
$this->_plugin->settings->SetAdapterConfig('adapter-name', $_REQUEST['AdapterName']);
|
95 |
+
$this->_plugin->settings->SetAdapterConfig('adapter-hostname', $_REQUEST['AdapterHostname']);
|
96 |
+
$this->_plugin->settings->SetAdapterConfig('adapter-base-prefix', $_REQUEST['AdapterBasePrefix']);
|
97 |
+
}
|
98 |
}
|
99 |
|
100 |
public function AjaxCheckSecurityToken(){
|
120 |
if(isset($_POST['submit'])){
|
121 |
try {
|
122 |
$this->Save();
|
123 |
+
?><div class="updated">
|
124 |
+
<p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p>
|
125 |
+
</div><?php
|
126 |
}catch(Exception $ex){
|
127 |
?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
|
128 |
}
|
129 |
}
|
130 |
?>
|
131 |
+
<h2 id="wsal-tabs" class="nav-tab-wrapper">
|
132 |
+
<a href="#tab-general" class="nav-tab">General</a>
|
133 |
+
<a href="#tab-exclude" class="nav-tab">Exclude Objects</a>
|
134 |
+
<!--<a href="#adapter" class="nav-tab">Data Storage Adapter</a>-->
|
135 |
+
</h2>
|
136 |
+
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"/></script>
|
137 |
<form id="audit-log-settings" method="post">
|
138 |
<input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
|
139 |
<input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
|
324 |
</fieldset>
|
325 |
</td>
|
326 |
</tr>
|
327 |
+
<tr>
|
328 |
+
<th><label for="datetime_format_24"><?php _e('Alerts Time Format', 'wp-security-audit-log'); ?></label></th>
|
329 |
+
<td>
|
330 |
+
<fieldset>
|
331 |
+
<?php $datetime = $this->_plugin->settings->GetDatetimeFormat(); ?>
|
332 |
+
<label for="datetime_format_24">
|
333 |
+
<input type="radio" name="DatetimeFormat" id="datetime_format_24" style="margin-top: 2px;" <?php if($datetime)echo 'checked="checked"'; ?> value="1">
|
334 |
+
<span><?php _e('24 hours', 'wp-security-audit-log'); ?></span>
|
335 |
+
</label>
|
336 |
+
<br/>
|
337 |
+
<label for="datetime_format_default">
|
338 |
+
<input type="radio" name="DatetimeFormat" id="datetime_format_default" style="margin-top: 2px;" <?php if(!$datetime)echo 'checked="checked"'; ?> value="0">
|
339 |
+
<span><?php _e('AM/PM', 'wp-security-audit-log'); ?></span>
|
340 |
+
</label>
|
341 |
+
<br/>
|
342 |
+
</fieldset>
|
343 |
+
</td>
|
344 |
+
</tr>
|
345 |
<tr>
|
346 |
<th><label><?php _e('Developer Options', 'wp-security-audit-log'); ?></label></th>
|
347 |
<td>
|
415 |
</tr>
|
416 |
</tbody>
|
417 |
</table>
|
418 |
+
<!-- End general Tab-->
|
419 |
<table class="form-table wsal-tab widefat" id="tab-exclude">
|
420 |
<tbody>
|
421 |
<tr>
|
489 |
</tr>
|
490 |
</tbody>
|
491 |
</table>
|
492 |
+
<?php
|
493 |
+
//
|
494 |
+
// Temporarily disabling this
|
495 |
+
//
|
496 |
+
/*
|
497 |
+
<!-- End exclude objects Tab-->
|
498 |
+
<table class="form-table wsal-tab widefat" id="adapter">
|
499 |
+
<tbody>
|
500 |
+
<tr>
|
501 |
+
<th><h2>Type</h2></th>
|
502 |
+
</tr>
|
503 |
+
<tr>
|
504 |
+
<th><label for="AdapterType"><?php _e('Adapter Type', 'wp-security-audit-log'); ?></label></th>
|
505 |
+
<td>
|
506 |
+
<fieldset>
|
507 |
+
<?php $adapterType = strtolower($this->_plugin->settings->GetAdapterConfig('adapter-type')); ?>
|
508 |
+
<select name="AdapterType" id="AdapterType">
|
509 |
+
<option value="MySQL" <?=($adapterType == 'mysql')? 'selected="selected"' : '';?>>DB MySQL</option>
|
510 |
+
|
511 |
+
</select>
|
512 |
+
</fieldset>
|
513 |
+
</td>
|
514 |
+
</tr>
|
515 |
+
<tr>
|
516 |
+
<th><h2>Config</h2></th>
|
517 |
+
</tr>
|
518 |
+
<tr>
|
519 |
+
<th><label for="AdapterUser"><?php _e('Database User', 'wp-security-audit-log'); ?></label></th>
|
520 |
+
<td>
|
521 |
+
<fieldset>
|
522 |
+
<?php $adapterUser = $this->_plugin->settings->GetAdapterConfig('adapter-user'); ?>
|
523 |
+
<input type="text" id="AdapterUser" name="AdapterUser" value="<?=$adapterUser?>" style="float: left; display: block; width: 250px;">
|
524 |
+
</fieldset>
|
525 |
+
</td>
|
526 |
+
</tr>
|
527 |
+
<tr>
|
528 |
+
<th><label for="AdapterPassword"><?php _e('Database Password', 'wp-security-audit-log'); ?></label></th>
|
529 |
+
<td>
|
530 |
+
<fieldset>
|
531 |
+
<?php $adapterPassword = $this->_plugin->settings->GetAdapterConfig('adapter-password'); ?>
|
532 |
+
<input type="password" id="AdapterPassword" name="AdapterPassword" value="<?=$adapterPassword?>" style="float: left; display: block; width: 250px;">
|
533 |
+
</fieldset>
|
534 |
+
</td>
|
535 |
+
</tr>
|
536 |
+
<tr>
|
537 |
+
<th><label for="AdapterName"><?php _e('Database Name', 'wp-security-audit-log'); ?></label></th>
|
538 |
+
<td>
|
539 |
+
<fieldset>
|
540 |
+
<?php $adapterName = $this->_plugin->settings->GetAdapterConfig('adapter-name'); ?>
|
541 |
+
<input type="text" id="AdapterName" name="AdapterName" value="<?=$adapterName?>" style="float: left; display: block; width: 250px;">
|
542 |
+
</fieldset>
|
543 |
+
</td>
|
544 |
+
</tr>
|
545 |
+
<tr>
|
546 |
+
<th><label for="AdapterHostname"><?php _e('Database Hostname', 'wp-security-audit-log'); ?></label></th>
|
547 |
+
<td>
|
548 |
+
<fieldset>
|
549 |
+
<?php $adapterHostname = $this->_plugin->settings->GetAdapterConfig('adapter-hostname'); ?>
|
550 |
+
<input type="text" id="AdapterHostname" name="AdapterHostname" value="<?=$adapterHostname?>" style="float: left; display: block; width: 250px;">
|
551 |
+
</fieldset>
|
552 |
+
</td>
|
553 |
+
</tr>
|
554 |
+
<tr>
|
555 |
+
<th><label for="AdapterBasePrefix"><?php _e('Database Base prefix', 'wp-security-audit-log'); ?></label></th>
|
556 |
+
<td>
|
557 |
+
<fieldset>
|
558 |
+
<?php $adapterBasePrefix = $this->_plugin->settings->GetAdapterConfig('adapter-base-prefix'); ?>
|
559 |
+
<input type="text" id="AdapterBasePrefix" name="AdapterBasePrefix" value="<?=$adapterBasePrefix?>" style="float: left; display: block; width: 250px;">
|
560 |
+
</fieldset>
|
561 |
+
</td>
|
562 |
+
</tr>
|
563 |
+
</tbody>
|
564 |
+
</table>
|
565 |
+
*/
|
566 |
+
?>
|
567 |
+
<!-- End Adapter Tab-->
|
568 |
</div>
|
569 |
+
<p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save & Test Changes"></p>
|
570 |
</form>
|
571 |
<script type="text/javascript">
|
572 |
<!--
|
classes/WidgetManager.php
CHANGED
@@ -23,10 +23,11 @@ class WSAL_WidgetManager {
|
|
23 |
}
|
24 |
|
25 |
public function RenderWidget(){
|
26 |
-
$
|
27 |
-
|
28 |
-
|
29 |
-
);
|
|
|
30 |
?><div><?php
|
31 |
if(!count($results)){
|
32 |
?><p><?php _e('No alerts found.', 'wp-security-audit-log'); ?></p><?php
|
23 |
}
|
24 |
|
25 |
public function RenderWidget(){
|
26 |
+
$query = new WSAL_Models_OccurrenceQuery();
|
27 |
+
$query->addOrderBy("created_on", true);
|
28 |
+
$query->setLimit($this->_plugin->settings->GetDashboardWidgetMaxAlerts());
|
29 |
+
$results = $query->getAdapter()->Execute($query);
|
30 |
+
|
31 |
?><div><?php
|
32 |
if(!count($results)){
|
33 |
?><p><?php _e('No alerts found.', 'wp-security-audit-log'); ?></p><?php
|
css/auditlog.css
CHANGED
@@ -27,7 +27,7 @@
|
|
27 |
}
|
28 |
|
29 |
.column-crtd {
|
30 |
-
width:
|
31 |
}
|
32 |
|
33 |
.column-user {
|
27 |
}
|
28 |
|
29 |
.column-crtd {
|
30 |
+
width: 125px;
|
31 |
}
|
32 |
|
33 |
.column-user {
|
js/settings.js
CHANGED
@@ -50,6 +50,8 @@ jQuery(document).ready(function(){
|
|
50 |
.prepend(jQuery('<input type="hidden" name="Editors[]"/>').val(user))
|
51 |
.append(jQuery('<a href="javascript:;" title="Remove">×</a>').click(RemoveSecToken))
|
52 |
);
|
|
|
|
|
53 |
}
|
54 |
});
|
55 |
|
50 |
.prepend(jQuery('<input type="hidden" name="Editors[]"/>').val(user))
|
51 |
.append(jQuery('<a href="javascript:;" title="Remove">×</a>').click(RemoveSecToken))
|
52 |
);
|
53 |
+
} else {
|
54 |
+
jQuery('#EditorList').children().remove();
|
55 |
}
|
56 |
});
|
57 |
|
readme.txt
CHANGED
@@ -6,10 +6,10 @@ License: GPLv3
|
|
6 |
License URI: http://www.gnu.org/licenses/gpl.html
|
7 |
Tags: wordpress security plugin, wordpress security audit log, audit log, wordpress log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, security audit trail, wordpress security alerts, wordpress monitor, wordpress security monitor, wordpress admin, wordpress admin monitoring, analytics, activity, admin, multisite, wordpress multisite, actions, dashboard, log, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report
|
8 |
Requires at least: 3.6
|
9 |
-
Tested up to: 4.2.
|
10 |
-
Stable tag:
|
11 |
|
12 |
-
Keep
|
13 |
|
14 |
== Description ==
|
15 |
Keep an audit log of everything that is happening on your WordPress and [WordPress multisite](http://www.wpwhitesecurity.com/wordpress-plugins/wp-security-audit-log-plugin-features-wordpress-multisite/) with WP Security Audit Log to ensure user productivity and identify WordPress security issues before they become a security problem. WP Security Audit Log, WordPress' most comprehensive user monitoring and audit log plugin already helps thousands of WordPress administrators, owners and security professionals ensure the security of their websites and blogs. Ensure the security of your WordPress too by installing WP Security Audit Log. The community's favourite WordPress user monitoring monitoring and security auditing plugin is developed by WordPress Security Consultants and Professionals [WP White Security](http://www.wpwhitesecurity.com/).
|
@@ -93,9 +93,9 @@ NOTE: Developer options should NEVER be enabled on Live websites. They should on
|
|
93 |
WP Security Audit Log plugin also has a number of features that make WordPress and WordPress multisite monitoring and auditing easier, such as:
|
94 |
|
95 |
* Realtime Audit Log viewer to watch user activity as it happens without any delays
|
96 |
-
*
|
97 |
-
* Limit who can view the security alerts by users
|
98 |
-
* Limit who can manage the plugin by users
|
99 |
* Configurable WordPress dashboard widget highlighting the most recent critical activity
|
100 |
* Configurable WordPress security alerts pruning rules
|
101 |
* User role is reported in alerts for a complete overview of what is happening
|
@@ -180,6 +180,18 @@ Yes it is possible to exclude custom fields from being monitored. To exclude a c
|
|
180 |
|
181 |
== Changelog ==
|
182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
= 1.6.1 (2015-05-04) =
|
184 |
* **Bug Fixes**
|
185 |
* Fixed the monitoring of plugin updates for WordPress 4.2 [Support Ticket](https://wordpress.org/support/topic/not-logging-plugin-updates-in-42)
|
6 |
License URI: http://www.gnu.org/licenses/gpl.html
|
7 |
Tags: wordpress security plugin, wordpress security audit log, audit log, wordpress log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, security audit trail, wordpress security alerts, wordpress monitor, wordpress security monitor, wordpress admin, wordpress admin monitoring, analytics, activity, admin, multisite, wordpress multisite, actions, dashboard, log, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report
|
8 |
Requires at least: 3.6
|
9 |
+
Tested up to: 4.2.3
|
10 |
+
Stable tag: 2.0.0
|
11 |
|
12 |
+
Keep a WordPress audit log of all users' changes and under the hood WordPress activity - Identify WordPress issues before they become security problems.
|
13 |
|
14 |
== Description ==
|
15 |
Keep an audit log of everything that is happening on your WordPress and [WordPress multisite](http://www.wpwhitesecurity.com/wordpress-plugins/wp-security-audit-log-plugin-features-wordpress-multisite/) with WP Security Audit Log to ensure user productivity and identify WordPress security issues before they become a security problem. WP Security Audit Log, WordPress' most comprehensive user monitoring and audit log plugin already helps thousands of WordPress administrators, owners and security professionals ensure the security of their websites and blogs. Ensure the security of your WordPress too by installing WP Security Audit Log. The community's favourite WordPress user monitoring monitoring and security auditing plugin is developed by WordPress Security Consultants and Professionals [WP White Security](http://www.wpwhitesecurity.com/).
|
93 |
WP Security Audit Log plugin also has a number of features that make WordPress and WordPress multisite monitoring and auditing easier, such as:
|
94 |
|
95 |
* Realtime Audit Log viewer to watch user activity as it happens without any delays
|
96 |
+
* Built-in support for reverse proxies and web application firewalls [more information](http://www.wpwhitesecurity.com/wordpress-plugins/wordpress-user-monitoring-plugin/wp-security-audit-log-plugin-retrieves-originating-wordpress-user-ip-address/)
|
97 |
+
* Limit who can view the security alerts by users and roles
|
98 |
+
* Limit who can manage the plugin by users and roles
|
99 |
* Configurable WordPress dashboard widget highlighting the most recent critical activity
|
100 |
* Configurable WordPress security alerts pruning rules
|
101 |
* User role is reported in alerts for a complete overview of what is happening
|
180 |
|
181 |
== Changelog ==
|
182 |
|
183 |
+
= 2.0.0 (2015-07-16) =
|
184 |
+
* **New Features**
|
185 |
+
* New database connector allowing faster and more efficient plugin to WordPress database communication
|
186 |
+
* Added new option to switch the display time of alerts between 24 hour or 12 hour format
|
187 |
+
* Sorting functionality in Audit Log Viewer (sort WordPress security alerts by date & time, code or username)
|
188 |
+
|
189 |
+
* **Bug Fixes**
|
190 |
+
* Fixed issue where super admin roles was not reported when logging in to "sub sites" in WordPress multisite
|
191 |
+
* Fixed several formatting issues in the Audit Log Viewer (UI)
|
192 |
+
* Fixed issue where multiple plugins were upgraded via the drop down menu and no alerts were being reported
|
193 |
+
* Fixed: When unrestricting plugin access from a single admin was not working properly
|
194 |
+
|
195 |
= 1.6.1 (2015-05-04) =
|
196 |
* **Bug Fixes**
|
197 |
* Fixed the monitoring of plugin updates for WordPress 4.2 [Support Ticket](https://wordpress.org/support/topic/not-logging-plugin-updates-in-42)
|
wp-security-audit-log.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: WP Security Audit Log
|
|
4 |
Plugin URI: http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/
|
5 |
Description: Identify WordPress security issues before they become a problem. Keep track of everything happening on your WordPress including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log generates a security alert for everything that happens on your WordPress blogs and websites. Use the Audit Log Viewer included in the plugin to see all the security alerts.
|
6 |
Author: WP White Security
|
7 |
-
Version:
|
8 |
Text Domain: wp-security-audit-log
|
9 |
Author URI: http://www.wpwhitesecurity.com/
|
10 |
License: GPL2
|
@@ -117,12 +117,14 @@ class WpSecurityAuditLog {
|
|
117 |
*/
|
118 |
public function __construct(){
|
119 |
|
|
|
120 |
// profiler has to be loaded manually
|
121 |
require_once('classes/SimpleProfiler.php');
|
122 |
$this->profiler = new WSAL_SimpleProfiler();
|
123 |
-
|
124 |
-
require_once('classes/
|
125 |
-
require_once('classes/
|
|
|
126 |
|
127 |
// load autoloader and register base paths
|
128 |
require_once('classes/Autoloader.php');
|
@@ -205,7 +207,7 @@ class WpSecurityAuditLog {
|
|
205 |
*/
|
206 |
public function Load(){
|
207 |
|
208 |
-
$optionsTable = new
|
209 |
if (!$optionsTable->IsInstalled()) {
|
210 |
$optionsTable->Install();
|
211 |
//setting the prunig date with the old value or the default value
|
@@ -252,7 +254,7 @@ class WpSecurityAuditLog {
|
|
252 |
}
|
253 |
|
254 |
// ensure that the system is installed and schema is correct
|
255 |
-
|
256 |
|
257 |
$PreInstalled = $this->IsInstalled();
|
258 |
|
@@ -309,7 +311,7 @@ class WpSecurityAuditLog {
|
|
309 |
*/
|
310 |
public function Uninstall(){
|
311 |
if ($this->GetGlobalOption("delete-data") == 1) {
|
312 |
-
|
313 |
$this->deleteAllOptions();
|
314 |
}
|
315 |
wp_clear_scheduled_hook('wsal_cleanup');
|
@@ -347,7 +349,7 @@ class WpSecurityAuditLog {
|
|
347 |
|
348 |
public function SetOptions($data){
|
349 |
foreach($data as $key => $option) {
|
350 |
-
$this->options = new
|
351 |
if ( $this->IsMultisite() ) {
|
352 |
$this->options->SetOptionValue($option['meta_key'], $option['meta_value']);
|
353 |
} else {
|
@@ -474,7 +476,7 @@ class WpSecurityAuditLog {
|
|
474 |
//$fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
|
475 |
//var_dump($fn($prefix . $option, $default));
|
476 |
//return $fn($prefix . $option, $default);
|
477 |
-
$this->options = new
|
478 |
return $this->options->GetOptionValue($prefix . $option, $default);
|
479 |
}
|
480 |
|
@@ -487,7 +489,7 @@ class WpSecurityAuditLog {
|
|
487 |
public function SetGlobalOption($option, $value, $prefix = self::OPT_PRFX){
|
488 |
//$fn = $this->IsMultisite() ? 'update_site_option' : 'update_option';
|
489 |
//$fn($prefix . $option, $value);
|
490 |
-
$this->options = new
|
491 |
$this->options->SetOptionValue($prefix . $option, $value);
|
492 |
}
|
493 |
|
@@ -539,24 +541,26 @@ class WpSecurityAuditLog {
|
|
539 |
while(($pos = array_search($hook, $this->_cleanup_hooks)) !== false)
|
540 |
unset($this->_cleanup_hooks[$pos]);
|
541 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
542 |
|
543 |
/**
|
544 |
* Do we have an existing installation? This only applies for version 1.0 onwards.
|
545 |
* @return boolean
|
546 |
*/
|
547 |
public function IsInstalled(){
|
548 |
-
|
549 |
-
$table = $wpdb->base_prefix . 'wsal_occurrences';
|
550 |
-
return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
|
551 |
}
|
552 |
|
553 |
/**
|
554 |
* @return boolean Whether the old plugin was present or not.
|
555 |
*/
|
556 |
public function CanMigrate(){
|
557 |
-
|
558 |
-
$table = $wpdb->base_prefix . 'wordpress_auditlog_events';
|
559 |
-
return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
|
560 |
}
|
561 |
|
562 |
/**
|
@@ -588,6 +592,45 @@ class WpSecurityAuditLog {
|
|
588 |
require_once('defaults.php');
|
589 |
$s->Stop();
|
590 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
591 |
|
592 |
// </editor-fold>
|
593 |
}
|
4 |
Plugin URI: http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/
|
5 |
Description: Identify WordPress security issues before they become a problem. Keep track of everything happening on your WordPress including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log generates a security alert for everything that happens on your WordPress blogs and websites. Use the Audit Log Viewer included in the plugin to see all the security alerts.
|
6 |
Author: WP White Security
|
7 |
+
Version: 2.0.0
|
8 |
Text Domain: wp-security-audit-log
|
9 |
Author URI: http://www.wpwhitesecurity.com/
|
10 |
License: GPL2
|
117 |
*/
|
118 |
public function __construct(){
|
119 |
|
120 |
+
require_once('classes/Helpers/DataHelper.php');
|
121 |
// profiler has to be loaded manually
|
122 |
require_once('classes/SimpleProfiler.php');
|
123 |
$this->profiler = new WSAL_SimpleProfiler();
|
124 |
+
require_once('classes/Models/ActiveRecord.php');
|
125 |
+
require_once('classes/Models/Query.php');
|
126 |
+
require_once('classes/Models/OccurrenceQuery.php');
|
127 |
+
require_once('classes/Models/Option.php');
|
128 |
|
129 |
// load autoloader and register base paths
|
130 |
require_once('classes/Autoloader.php');
|
207 |
*/
|
208 |
public function Load(){
|
209 |
|
210 |
+
$optionsTable = new WSAL_Models_Option();
|
211 |
if (!$optionsTable->IsInstalled()) {
|
212 |
$optionsTable->Install();
|
213 |
//setting the prunig date with the old value or the default value
|
254 |
}
|
255 |
|
256 |
// ensure that the system is installed and schema is correct
|
257 |
+
self::getConnector()->installAll();
|
258 |
|
259 |
$PreInstalled = $this->IsInstalled();
|
260 |
|
311 |
*/
|
312 |
public function Uninstall(){
|
313 |
if ($this->GetGlobalOption("delete-data") == 1) {
|
314 |
+
self::getConnector()->uninstallAll();
|
315 |
$this->deleteAllOptions();
|
316 |
}
|
317 |
wp_clear_scheduled_hook('wsal_cleanup');
|
349 |
|
350 |
public function SetOptions($data){
|
351 |
foreach($data as $key => $option) {
|
352 |
+
$this->options = new WSAL_Models_Option();
|
353 |
if ( $this->IsMultisite() ) {
|
354 |
$this->options->SetOptionValue($option['meta_key'], $option['meta_value']);
|
355 |
} else {
|
476 |
//$fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
|
477 |
//var_dump($fn($prefix . $option, $default));
|
478 |
//return $fn($prefix . $option, $default);
|
479 |
+
$this->options = new WSAL_Models_Option();
|
480 |
return $this->options->GetOptionValue($prefix . $option, $default);
|
481 |
}
|
482 |
|
489 |
public function SetGlobalOption($option, $value, $prefix = self::OPT_PRFX){
|
490 |
//$fn = $this->IsMultisite() ? 'update_site_option' : 'update_option';
|
491 |
//$fn($prefix . $option, $value);
|
492 |
+
$this->options = new WSAL_Models_Option();
|
493 |
$this->options->SetOptionValue($prefix . $option, $value);
|
494 |
}
|
495 |
|
541 |
while(($pos = array_search($hook, $this->_cleanup_hooks)) !== false)
|
542 |
unset($this->_cleanup_hooks[$pos]);
|
543 |
}
|
544 |
+
|
545 |
+
public static function getConnector()
|
546 |
+
{
|
547 |
+
require_once('classes/Connector/ConnectorFactory.php');
|
548 |
+
return WSAL_Connector_ConnectorFactory::getConnector();
|
549 |
+
}
|
550 |
|
551 |
/**
|
552 |
* Do we have an existing installation? This only applies for version 1.0 onwards.
|
553 |
* @return boolean
|
554 |
*/
|
555 |
public function IsInstalled(){
|
556 |
+
return self::getConnector()->isInstalled();
|
|
|
|
|
557 |
}
|
558 |
|
559 |
/**
|
560 |
* @return boolean Whether the old plugin was present or not.
|
561 |
*/
|
562 |
public function CanMigrate(){
|
563 |
+
return self::getConnector()->canMigrate();
|
|
|
|
|
564 |
}
|
565 |
|
566 |
/**
|
592 |
require_once('defaults.php');
|
593 |
$s->Stop();
|
594 |
}
|
595 |
+
|
596 |
+
/**
|
597 |
+
* WSAL-Notifications-Extension Functions.
|
598 |
+
*/
|
599 |
+
public function GetNotificationsSetting($opt_prefix)
|
600 |
+
{
|
601 |
+
$this->options = new WSAL_Models_Option();
|
602 |
+
return $this->options->GetNotificationsSetting(self::OPT_PRFX . $opt_prefix);
|
603 |
+
}
|
604 |
+
|
605 |
+
public function GetNotification($id)
|
606 |
+
{
|
607 |
+
$this->options = new WSAL_Models_Option();
|
608 |
+
return $this->options->GetNotification($id);
|
609 |
+
}
|
610 |
+
|
611 |
+
public function DeleteByName($name)
|
612 |
+
{
|
613 |
+
$this->options = new WSAL_Models_Option();
|
614 |
+
return $this->options->DeleteByName($name);
|
615 |
+
}
|
616 |
+
|
617 |
+
public function DeleteByPrefix($opt_prefix)
|
618 |
+
{
|
619 |
+
$this->options = new WSAL_Models_Option();
|
620 |
+
return $this->options->DeleteByPrefix(self::OPT_PRFX . $opt_prefix);
|
621 |
+
}
|
622 |
+
|
623 |
+
public function CountNotifications($opt_prefix)
|
624 |
+
{
|
625 |
+
$this->options = new WSAL_Models_Option();
|
626 |
+
return $this->options->CountNotifications(self::OPT_PRFX . $opt_prefix);
|
627 |
+
}
|
628 |
+
|
629 |
+
public function UpdateGlobalOption($option, $value)
|
630 |
+
{
|
631 |
+
$this->options = new WSAL_Models_Option();
|
632 |
+
return $this->options->SetOptionValue($option, $value);
|
633 |
+
}
|
634 |
|
635 |
// </editor-fold>
|
636 |
}
|