WP Security Audit Log - Version 2.4.3

Version Description

(2016-06-01) =

  • New Add-On Support

    • Included code to support the new Users Sessions Management Add-On, which allows you to see who is logged in to your WordPress and WordPress multisite networks.
  • New Alerts in the WordPress Audit Trail

    • 1004: A login attempt was blocked because a session with the same username already exists
    • 1005: Multiple logged-in sessions for the same WordPress username has been detected
  • Improvement

    • Plugin reports changes when an object is moved as a sub object in a menu.
  • Bug fixes

    • Fixed a problem where wrong permissions were assigned to the reports directory in the uploads directory for the Reports Add-On.
    • Fixed an issue where multiple incorrect changes were reported when changing the structure of a menu Support ticket.
    • Fixed a bug in the settings sensor support ticket.
Download this release

Release Info

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

Code changes from version 2.4.2 to 2.4.3

Files changed (71) hide show
  1. classes/AbstractLogger.php +13 -13
  2. classes/AbstractSandboxTask.php +68 -68
  3. classes/AbstractSensor.php +42 -42
  4. classes/AbstractView.php +180 -180
  5. classes/Alert.php +98 -98
  6. classes/AlertManager.php +382 -382
  7. classes/AuditLogListView.php +452 -445
  8. classes/Autoloader.php +69 -69
  9. classes/Connector/AbstractConnector.php +36 -36
  10. classes/Connector/ConnectorFactory.php +87 -87
  11. classes/Connector/ConnectorInterface.php +11 -11
  12. classes/Connector/MySQLDBConnector.php +337 -337
  13. classes/Connector/wp-db-custom.php +36 -36
  14. classes/ConstantManager.php +88 -88
  15. classes/EDD_SL_Plugin_Updater.php +170 -170
  16. classes/Helpers/DataHelper.php +22 -22
  17. classes/LicenseManager.php +171 -171
  18. classes/Models/ActiveRecord.php +280 -267
  19. classes/Models/Adapters/ActiveRecordInterface.php +15 -15
  20. classes/Models/Adapters/MetaInterface.php +13 -13
  21. classes/Models/Adapters/MySQL/ActiveRecordAdapter.php +448 -448
  22. classes/Models/Adapters/MySQL/MetaAdapter.php +53 -53
  23. classes/Models/Adapters/MySQL/OccurrenceAdapter.php +187 -187
  24. classes/Models/Adapters/MySQL/OptionAdapter.php +79 -79
  25. classes/Models/Adapters/MySQL/QueryAdapter.php +219 -219
  26. classes/Models/Adapters/OccurrenceInterface.php +11 -11
  27. classes/Models/Adapters/QueryInterface.php +8 -8
  28. classes/Models/Meta.php +34 -34
  29. classes/Models/Occurrence.php +199 -199
  30. classes/Models/OccurrenceQuery.php +29 -29
  31. classes/Models/Option.php +80 -80
  32. classes/Models/Query.php +187 -187
  33. classes/Nicer.php +289 -289
  34. classes/SensorManager.php +49 -49
  35. classes/Sensors/BBPress.php +412 -412
  36. classes/Sensors/Content.php +635 -635
  37. classes/Sensors/CustomHooks.php +49 -49
  38. classes/Sensors/Database.php +132 -132
  39. classes/Sensors/Files.php +55 -55
  40. classes/Sensors/LogInOut.php +215 -182
  41. classes/Sensors/Menus.php +416 -416
  42. classes/Sensors/MetaData.php +208 -208
  43. classes/Sensors/Multisite.php +129 -129
  44. classes/Sensors/PhpErrors.php +104 -104
  45. classes/Sensors/PluginsThemes.php +215 -215
  46. classes/Sensors/Request.php +40 -40
  47. classes/Sensors/System.php +168 -168
  48. classes/Sensors/UserProfile.php +164 -164
  49. classes/Sensors/Widgets.php +234 -234
  50. classes/Settings.php +639 -639
  51. classes/SimpleProfiler.php +43 -43
  52. classes/ViewManager.php +214 -214
  53. classes/Views/About.php +85 -85
  54. classes/Views/AuditLog.php +177 -177
  55. classes/Views/Help.php +78 -76
  56. classes/Views/Licensing.php +87 -87
  57. classes/Views/Settings.php +682 -682
  58. classes/Views/ToggleAlerts.php +150 -150
  59. classes/WidgetManager.php +79 -79
  60. css/auditlog.css +180 -180
  61. css/install-error.css +41 -41
  62. css/nice_r.css +92 -92
  63. css/settings.css +70 -70
  64. defaults.php +3 -0
  65. js/auditlog.js +149 -149
  66. js/common.js +17 -17
  67. js/nice_r.js +11 -11
  68. js/settings.js +73 -73
  69. readme.txt +55 -42
  70. uninstall.php +6 -6
  71. wp-security-audit-log.php +1 -1
classes/AbstractLogger.php CHANGED
@@ -1,14 +1,14 @@
1
- <?php
2
-
3
- abstract class WSAL_AbstractLogger {
4
- /**
5
- * @var WpSecurityAuditLog
6
- */
7
- protected $plugin;
8
-
9
- public function __construct(WpSecurityAuditLog $plugin){
10
- $this->plugin = $plugin;
11
- }
12
-
13
- public abstract function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false);
14
  }
1
+ <?php
2
+
3
+ abstract class WSAL_AbstractLogger {
4
+ /**
5
+ * @var WpSecurityAuditLog
6
+ */
7
+ protected $plugin;
8
+
9
+ public function __construct(WpSecurityAuditLog $plugin){
10
+ $this->plugin = $plugin;
11
+ }
12
+
13
+ public abstract function Log($type, $data = array(), $date = null, $siteid = null, $migrated = false);
14
  }
classes/AbstractSandboxTask.php CHANGED
@@ -1,68 +1,68 @@
1
- <?php
2
-
3
- abstract class WSAL_AbstractSandboxTask {
4
- public function __construct() {
5
- // remove time limit and clear output buffers
6
- set_time_limit(0);
7
- ob_implicit_flush(true);
8
- while(ob_get_level())ob_end_flush();
9
-
10
- // set up shutdown handler
11
- register_shutdown_function(array($this, 'Shutdown'));
12
-
13
- // run event sequence
14
- $this->Header();
15
- try{
16
- $this->Execute();
17
- }catch(Exception $ex){
18
- $this->Message(get_class($ex) . ' [' . basename($ex->getFile()) . ':' . $ex->getLine() . ']: ' . $ex->getMessage());
19
- $this->Message($ex->getTraceAsString(), true);
20
- }
21
- $this->Footer();
22
-
23
- // shutdown
24
- die();
25
- }
26
-
27
- protected function Header(){
28
- echo '<!DOCTYPE html><html><body style="margin: 0; padding: 8px; font: 12px Arial; color: #333;">';
29
- echo '<div style="position: fixed; top: 0; left: 0; right: 0; padding: 8px; background: #F0F0F0;">';
30
- echo ' <div id="bar" style=" border-top: 2px solid #0AE; top: 20px; height: 0; width: 0%;"> </div>';
31
- echo ' <span id="msg"></span> <span id="prg"></span>';
32
- echo '</div>';
33
- echo '<div id="msgs" style="font-family: Consolas; margin-top: 30px; white-space: pre;"></div>';
34
- echo '<script>';
35
- echo ' var bar = document.getElementById("bar");';
36
- echo ' var msg = document.getElementById("msg");';
37
- echo ' var prg = document.getElementById("prg");';
38
- echo ' var msgs = document.getElementById("msgs");';
39
- echo '</script>';
40
- flush();
41
- }
42
-
43
- protected function Footer(){
44
- echo '<div style="display: none;">';
45
- flush();
46
- }
47
-
48
- protected abstract function Execute();
49
-
50
- public function Shutdown(){
51
- echo '</div></body></html>';
52
- flush();
53
- }
54
-
55
- protected function Progress($percent){
56
- echo '<script>bar.style.width=prg.innerHTML="' . number_format($percent, 2) . '%";</script>';
57
- flush();
58
- }
59
-
60
- protected function Message($message, $sticky = false){
61
- if($sticky){
62
- echo '<script>msgs.appendChild(document.createTextNode(' . json_encode($message . PHP_EOL) . ')); window.scroll(0, document.body.scrollHeight);</script>';
63
- }else{
64
- echo '<script>msg.innerHTML=' . json_encode($message) . ';</script>';
65
- }
66
- flush();
67
- }
68
- }
1
+ <?php
2
+
3
+ abstract class WSAL_AbstractSandboxTask {
4
+ public function __construct() {
5
+ // remove time limit and clear output buffers
6
+ set_time_limit(0);
7
+ ob_implicit_flush(true);
8
+ while(ob_get_level())ob_end_flush();
9
+
10
+ // set up shutdown handler
11
+ register_shutdown_function(array($this, 'Shutdown'));
12
+
13
+ // run event sequence
14
+ $this->Header();
15
+ try{
16
+ $this->Execute();
17
+ }catch(Exception $ex){
18
+ $this->Message(get_class($ex) . ' [' . basename($ex->getFile()) . ':' . $ex->getLine() . ']: ' . $ex->getMessage());
19
+ $this->Message($ex->getTraceAsString(), true);
20
+ }
21
+ $this->Footer();
22
+
23
+ // shutdown
24
+ die();
25
+ }
26
+
27
+ protected function Header(){
28
+ echo '<!DOCTYPE html><html><body style="margin: 0; padding: 8px; font: 12px Arial; color: #333;">';
29
+ echo '<div style="position: fixed; top: 0; left: 0; right: 0; padding: 8px; background: #F0F0F0;">';
30
+ echo ' <div id="bar" style=" border-top: 2px solid #0AE; top: 20px; height: 0; width: 0%;"> </div>';
31
+ echo ' <span id="msg"></span> <span id="prg"></span>';
32
+ echo '</div>';
33
+ echo '<div id="msgs" style="font-family: Consolas; margin-top: 30px; white-space: pre;"></div>';
34
+ echo '<script>';
35
+ echo ' var bar = document.getElementById("bar");';
36
+ echo ' var msg = document.getElementById("msg");';
37
+ echo ' var prg = document.getElementById("prg");';
38
+ echo ' var msgs = document.getElementById("msgs");';
39
+ echo '</script>';
40
+ flush();
41
+ }
42
+
43
+ protected function Footer(){
44
+ echo '<div style="display: none;">';
45
+ flush();
46
+ }
47
+
48
+ protected abstract function Execute();
49
+
50
+ public function Shutdown(){
51
+ echo '</div></body></html>';
52
+ flush();
53
+ }
54
+
55
+ protected function Progress($percent){
56
+ echo '<script>bar.style.width=prg.innerHTML="' . number_format($percent, 2) . '%";</script>';
57
+ flush();
58
+ }
59
+
60
+ protected function Message($message, $sticky = false){
61
+ if($sticky){
62
+ echo '<script>msgs.appendChild(document.createTextNode(' . json_encode($message . PHP_EOL) . ')); window.scroll(0, document.body.scrollHeight);</script>';
63
+ }else{
64
+ echo '<script>msg.innerHTML=' . json_encode($message) . ';</script>';
65
+ }
66
+ flush();
67
+ }
68
+ }
classes/AbstractSensor.php CHANGED
@@ -1,43 +1,43 @@
1
- <?php
2
-
3
- abstract class WSAL_AbstractSensor {
4
- /**
5
- * @var WpSecurityAuditLog
6
- */
7
- protected $plugin;
8
-
9
- public function __construct(WpSecurityAuditLog $plugin){
10
- $this->plugin = $plugin;
11
- }
12
-
13
- /**
14
- * @return boolean Whether we are running on multisite or not.
15
- */
16
- protected function IsMultisite()
17
- {
18
- return function_exists('is_multisite') && is_multisite();
19
- }
20
-
21
- abstract function HookEvents();
22
-
23
- protected function Log($type, $message, $args){
24
- $this->plugin->alerts->Trigger($type, array(
25
- 'Message' => $message,
26
- 'Context' => $args,
27
- 'Trace' => debug_backtrace(),
28
- ));
29
- }
30
-
31
- protected function LogError($message, $args){
32
- $this->Log(0001, $message, $args);
33
- }
34
-
35
- protected function LogWarn($message, $args){
36
- $this->Log(0002, $message, $args);
37
- }
38
-
39
- protected function LogInfo($message, $args){
40
- $this->Log(0003, $message, $args);
41
- }
42
-
43
  }
1
+ <?php
2
+
3
+ abstract class WSAL_AbstractSensor {
4
+ /**
5
+ * @var WpSecurityAuditLog
6
+ */
7
+ protected $plugin;
8
+
9
+ public function __construct(WpSecurityAuditLog $plugin){
10
+ $this->plugin = $plugin;
11
+ }
12
+
13
+ /**
14
+ * @return boolean Whether we are running on multisite or not.
15
+ */
16
+ protected function IsMultisite()
17
+ {
18
+ return function_exists('is_multisite') && is_multisite();
19
+ }
20
+
21
+ abstract function HookEvents();
22
+
23
+ protected function Log($type, $message, $args){
24
+ $this->plugin->alerts->Trigger($type, array(
25
+ 'Message' => $message,
26
+ 'Context' => $args,
27
+ 'Trace' => debug_backtrace(),
28
+ ));
29
+ }
30
+
31
+ protected function LogError($message, $args){
32
+ $this->Log(0001, $message, $args);
33
+ }
34
+
35
+ protected function LogWarn($message, $args){
36
+ $this->Log(0002, $message, $args);
37
+ }
38
+
39
+ protected function LogInfo($message, $args){
40
+ $this->Log(0003, $message, $args);
41
+ }
42
+
43
  }
classes/AbstractView.php CHANGED
@@ -1,181 +1,181 @@
1
- <?php
2
-
3
- abstract class WSAL_AbstractView {
4
-
5
- /**
6
- * @var WpSecurityAuditLog
7
- */
8
- protected $_plugin;
9
-
10
- protected $_wpversion;
11
-
12
- /**
13
- * Contains the result to a call to add_submenu_page().
14
- * @var string
15
- */
16
- public $hook_suffix = '';
17
-
18
- /**
19
- * Tells us whether this view is currently being displayed or not.
20
- * @var boolean
21
- */
22
- public $is_active = false;
23
-
24
- /**
25
- * @param WpSecurityAuditLog $plugin
26
- */
27
- public function __construct(WpSecurityAuditLog $plugin){
28
- $this->_plugin = $plugin;
29
-
30
- // get and store wordpress version
31
- global $wp_version;
32
- if(!isset($wp_version))
33
- $wp_version = get_bloginfo('version');
34
- $this->_wpversion = floatval($wp_version);
35
-
36
- // handle admin notices
37
- add_action('wp_ajax_AjaxDismissNotice', array($this, 'AjaxDismissNotice'));
38
- }
39
-
40
- public static $AllowedNoticeNames = array();
41
-
42
- /**
43
- * Dismiss an admin notice through ajax.
44
- * @internal
45
- */
46
- public function AjaxDismissNotice(){
47
- if(!$this->_plugin->settings->CurrentUserCan('view'))
48
- die('Access Denied.');
49
-
50
- if(!isset($_REQUEST['notice']))
51
- die('Notice name expected as "notice" parameter.');
52
-
53
- $this->DismissNotice($_REQUEST['notice']);
54
- }
55
-
56
- /**
57
- * @param string $name Name of notice.
58
- * @return boolean Whether notice got dismissed or not.
59
- */
60
- public function IsNoticeDismissed($name){
61
- $user_id = get_current_user_id();
62
- $meta_key = 'wsal-notice-' . $name;
63
- self::$AllowedNoticeNames[] = $name;
64
- return !!get_user_meta($user_id, $meta_key, true);
65
- }
66
-
67
- /**
68
- * @param string $name Name of notice to dismiss.
69
- */
70
- public function DismissNotice($name){
71
- $user_id = get_current_user_id();
72
- $meta_key = 'wsal-notice-' . $name;
73
- $old_value = get_user_meta($user_id, $meta_key, true);
74
- if (in_array($name, self::$AllowedNoticeNames) || $old_value === false)
75
- update_user_meta($user_id, $meta_key, '1');
76
- }
77
-
78
- /**
79
- * @param string $name Makes this notice available.
80
- */
81
- public function RegisterNotice($name){
82
- self::$AllowedNoticeNames[] = $name;
83
- }
84
-
85
- /**
86
- * @return string Return page name (for menu etc).
87
- */
88
- abstract public function GetName();
89
-
90
- /**
91
- * @return string Return page title.
92
- */
93
- abstract public function GetTitle();
94
-
95
- /**
96
- * @return string Page icon name.
97
- */
98
- abstract public function GetIcon();
99
-
100
- /**
101
- * @return int Menu weight, the higher this is, the lower it goes.
102
- */
103
- abstract public function GetWeight();
104
-
105
- /**
106
- * Renders and outputs the view directly.
107
- */
108
- abstract public function Render();
109
-
110
- /**
111
- * Renders the view icon (this has been deprecated in newwer WP versions).
112
- */
113
- public function RenderIcon(){
114
- ?><div id="icon-plugins" class="icon32"><br></div><?php
115
- }
116
-
117
- /**
118
- * Renders the view title.
119
- */
120
- public function RenderTitle(){
121
- ?><h2><?php echo esc_html($this->GetTitle()); ?></h2><?php
122
- }
123
-
124
- /**
125
- * @link self::Render()
126
- */
127
- public function RenderContent(){
128
- $this->Render();
129
- }
130
-
131
- /**
132
- * @return boolean Whether page should appear in menu or not.
133
- */
134
- public function IsVisible(){ return true; }
135
-
136
- /**
137
- * @return boolean Whether page should be accessible or not.
138
- */
139
- public function IsAccessible(){ return true; }
140
-
141
- /**
142
- * Used for rendering stuff into head tag.
143
- */
144
- public function Header(){}
145
-
146
- /**
147
- * Used for rendering stuff in page fotoer.
148
- */
149
- public function Footer(){}
150
-
151
- /**
152
- * @return string Safe view menu name.
153
- */
154
- public function GetSafeViewName(){
155
- return 'wsal-' . preg_replace('/[^A-Za-z0-9\-]/', '-', $this->GetViewName());
156
- }
157
-
158
- /**
159
- * Override this and make it return true to create a shortcut link in plugin page to the view.
160
- * @return boolean
161
- */
162
- public function HasPluginShortcutLink(){
163
- return false;
164
- }
165
-
166
- /**
167
- * @return string URL to backend page for displaying view.
168
- */
169
- public function GetUrl(){
170
- $fn = function_exists('network_admin_url') ? 'network_admin_url' : 'admin_url';
171
- return $fn('admin.php?page=' . $this->GetSafeViewName());
172
- }
173
-
174
- /**
175
- * @return string Generates view name out of class name.
176
- */
177
- public function GetViewName(){
178
- return strtolower(str_replace(array('WSAL_Views_', 'WSAL_'), '', get_class($this)));
179
- }
180
-
181
  }
1
+ <?php
2
+
3
+ abstract class WSAL_AbstractView {
4
+
5
+ /**
6
+ * @var WpSecurityAuditLog
7
+ */
8
+ protected $_plugin;
9
+
10
+ protected $_wpversion;
11
+
12
+ /**
13
+ * Contains the result to a call to add_submenu_page().
14
+ * @var string
15
+ */
16
+ public $hook_suffix = '';
17
+
18
+ /**
19
+ * Tells us whether this view is currently being displayed or not.
20
+ * @var boolean
21
+ */
22
+ public $is_active = false;
23
+
24
+ /**
25
+ * @param WpSecurityAuditLog $plugin
26
+ */
27
+ public function __construct(WpSecurityAuditLog $plugin){
28
+ $this->_plugin = $plugin;
29
+
30
+ // get and store wordpress version
31
+ global $wp_version;
32
+ if(!isset($wp_version))
33
+ $wp_version = get_bloginfo('version');
34
+ $this->_wpversion = floatval($wp_version);
35
+
36
+ // handle admin notices
37
+ add_action('wp_ajax_AjaxDismissNotice', array($this, 'AjaxDismissNotice'));
38
+ }
39
+
40
+ public static $AllowedNoticeNames = array();
41
+
42
+ /**
43
+ * Dismiss an admin notice through ajax.
44
+ * @internal
45
+ */
46
+ public function AjaxDismissNotice(){
47
+ if(!$this->_plugin->settings->CurrentUserCan('view'))
48
+ die('Access Denied.');
49
+
50
+ if(!isset($_REQUEST['notice']))
51
+ die('Notice name expected as "notice" parameter.');
52
+
53
+ $this->DismissNotice($_REQUEST['notice']);
54
+ }
55
+
56
+ /**
57
+ * @param string $name Name of notice.
58
+ * @return boolean Whether notice got dismissed or not.
59
+ */
60
+ public function IsNoticeDismissed($name){
61
+ $user_id = get_current_user_id();
62
+ $meta_key = 'wsal-notice-' . $name;
63
+ self::$AllowedNoticeNames[] = $name;
64
+ return !!get_user_meta($user_id, $meta_key, true);
65
+ }
66
+
67
+ /**
68
+ * @param string $name Name of notice to dismiss.
69
+ */
70
+ public function DismissNotice($name){
71
+ $user_id = get_current_user_id();
72
+ $meta_key = 'wsal-notice-' . $name;
73
+ $old_value = get_user_meta($user_id, $meta_key, true);
74
+ if (in_array($name, self::$AllowedNoticeNames) || $old_value === false)
75
+ update_user_meta($user_id, $meta_key, '1');
76
+ }
77
+
78
+ /**
79
+ * @param string $name Makes this notice available.
80
+ */
81
+ public function RegisterNotice($name){
82
+ self::$AllowedNoticeNames[] = $name;
83
+ }
84
+
85
+ /**
86
+ * @return string Return page name (for menu etc).
87
+ */
88
+ abstract public function GetName();
89
+
90
+ /**
91
+ * @return string Return page title.
92
+ */
93
+ abstract public function GetTitle();
94
+
95
+ /**
96
+ * @return string Page icon name.
97
+ */
98
+ abstract public function GetIcon();
99
+
100
+ /**
101
+ * @return int Menu weight, the higher this is, the lower it goes.
102
+ */
103
+ abstract public function GetWeight();
104
+
105
+ /**
106
+ * Renders and outputs the view directly.
107
+ */
108
+ abstract public function Render();
109
+
110
+ /**
111
+ * Renders the view icon (this has been deprecated in newwer WP versions).
112
+ */
113
+ public function RenderIcon(){
114
+ ?><div id="icon-plugins" class="icon32"><br></div><?php
115
+ }
116
+
117
+ /**
118
+ * Renders the view title.
119
+ */
120
+ public function RenderTitle(){
121
+ ?><h2><?php echo esc_html($this->GetTitle()); ?></h2><?php
122
+ }
123
+
124
+ /**
125
+ * @link self::Render()
126
+ */
127
+ public function RenderContent(){
128
+ $this->Render();
129
+ }
130
+
131
+ /**
132
+ * @return boolean Whether page should appear in menu or not.
133
+ */
134
+ public function IsVisible(){ return true; }
135
+
136
+ /**
137
+ * @return boolean Whether page should be accessible or not.
138
+ */
139
+ public function IsAccessible(){ return true; }
140
+
141
+ /**
142
+ * Used for rendering stuff into head tag.
143
+ */
144
+ public function Header(){}
145
+
146
+ /**
147
+ * Used for rendering stuff in page fotoer.
148
+ */
149
+ public function Footer(){}
150
+
151
+ /**
152
+ * @return string Safe view menu name.
153
+ */
154
+ public function GetSafeViewName(){
155
+ return 'wsal-' . preg_replace('/[^A-Za-z0-9\-]/', '-', $this->GetViewName());
156
+ }
157
+
158
+ /**
159
+ * Override this and make it return true to create a shortcut link in plugin page to the view.
160
+ * @return boolean
161
+ */
162
+ public function HasPluginShortcutLink(){
163
+ return false;
164
+ }
165
+
166
+ /**
167
+ * @return string URL to backend page for displaying view.
168
+ */
169
+ public function GetUrl(){
170
+ $fn = function_exists('network_admin_url') ? 'network_admin_url' : 'admin_url';
171
+ return $fn('admin.php?page=' . $this->GetSafeViewName());
172
+ }
173
+
174
+ /**
175
+ * @return string Generates view name out of class name.
176
+ */
177
+ public function GetViewName(){
178
+ return strtolower(str_replace(array('WSAL_Views_', 'WSAL_'), '', get_class($this)));
179
+ }
180
+
181
  }
classes/Alert.php CHANGED
@@ -1,98 +1,98 @@
1
- <?php
2
-
3
- final class WSAL_Alert {
4
-
5
- /**
6
- * Alert type (used when triggering an alert etc).
7
- * @var integer
8
- */
9
- public $type = 0;
10
-
11
- /**
12
- * Alert error level (E_* constant).
13
- * @var integer
14
- */
15
- public $code = 0;
16
-
17
- /**
18
- * Alert category (alerts are grouped by matching categories).
19
- * @var string
20
- */
21
- public $catg = '';
22
-
23
- /**
24
- * Alert description (ie, describes what happens when alert is triggered).
25
- * @var string
26
- */
27
- public $desc = '';
28
-
29
- /**
30
- * Alert message (variables between '%' are expanded to values).
31
- * @var string
32
- */
33
- public $mesg = '';
34
-
35
- public function __construct($type = 0, $code = 0, $catg = '', $desc = '', $mesg = '') {
36
- $this->type = $type;
37
- $this->code = $code;
38
- $this->catg = $catg;
39
- $this->desc = $desc;
40
- $this->mesg = $mesg;
41
- }
42
-
43
- /**
44
- * Retrieves a value for a particular meta variable expression.
45
- * @param string $expr Expression, eg: User->Name looks for a Name property for meta named User.
46
- * @param array $metaData (Optional) Meta data relevant to expression.
47
- * @return mixed The value nearest to the expression.
48
- */
49
- protected function GetMetaExprValue($expr, $metaData = array()){
50
- // TODO Handle function calls (and methods?)
51
- $expr = explode('->', $expr);
52
- $meta = array_shift($expr);
53
- $meta = isset($metaData[$meta]) ? $metaData[$meta] : null;
54
- foreach($expr as $part){
55
- if(is_scalar($meta) || is_null($meta))return $meta; // this isn't 100% correct
56
- $meta = is_array($meta) ? $meta[$part] : $meta->$part;
57
- }
58
- return is_scalar($meta) ? (string)$meta : var_export($meta, true);
59
- }
60
-
61
- /**
62
- * Expands a message with variables by replacing variables with meta data values.
63
- * @param string $mesg The original message.
64
- * @param array $metaData (Optional) Meta data relevant to message.
65
- * @param callable|null $metaFormatter (Optional) Callback for formatting meta values.
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;
73
- // handle tokenized message
74
- foreach($mesg as $i => $token){
75
- // handle escaped percent sign
76
- if($token == '%%'){
77
- $mesg[$i] = '%';
78
- }else
79
- // handle complex expressions
80
- if(substr($token, 0, 1) == '%' && substr($token, -1, 1) == '%'){
81
- $mesg[$i] = $this->GetMetaExprValue(substr($token, 1, -1), $metaData);
82
- if($metaFormatter)$mesg[$i] = call_user_func($metaFormatter, $token, $mesg[$i]);
83
- }
84
- }
85
- // compact message and return
86
- return implode('', $mesg);
87
- }
88
-
89
- /**
90
- * @param array $metaData (Optional) Meta data relevant to message.
91
- * @param callable|null $metaFormatter (Optional) Meta formatter callback.
92
- * @param string|null $mesg (Optional) Override message template to use.
93
- * @return string Fully formatted message.
94
- */
95
- public function GetMessage($metaData = array(), $metaFormatter = null, $mesg = null){
96
- return $this->GetFormattedMesg(is_null($mesg) ? $this->mesg : $mesg, $metaData, $metaFormatter);
97
- }
98
- }
1
+ <?php
2
+
3
+ final class WSAL_Alert {
4
+
5
+ /**
6
+ * Alert type (used when triggering an alert etc).
7
+ * @var integer
8
+ */
9
+ public $type = 0;
10
+
11
+ /**
12
+ * Alert error level (E_* constant).
13
+ * @var integer
14
+ */
15
+ public $code = 0;
16
+
17
+ /**
18
+ * Alert category (alerts are grouped by matching categories).
19
+ * @var string
20
+ */
21
+ public $catg = '';
22
+
23
+ /**
24
+ * Alert description (ie, describes what happens when alert is triggered).
25
+ * @var string
26
+ */
27
+ public $desc = '';
28
+
29
+ /**
30
+ * Alert message (variables between '%' are expanded to values).
31
+ * @var string
32
+ */
33
+ public $mesg = '';
34
+
35
+ public function __construct($type = 0, $code = 0, $catg = '', $desc = '', $mesg = '') {
36
+ $this->type = $type;
37
+ $this->code = $code;
38
+ $this->catg = $catg;
39
+ $this->desc = $desc;
40
+ $this->mesg = $mesg;
41
+ }
42
+
43
+ /**
44
+ * Retrieves a value for a particular meta variable expression.
45
+ * @param string $expr Expression, eg: User->Name looks for a Name property for meta named User.
46
+ * @param array $metaData (Optional) Meta data relevant to expression.
47
+ * @return mixed The value nearest to the expression.
48
+ */
49
+ protected function GetMetaExprValue($expr, $metaData = array()){
50
+ // TODO Handle function calls (and methods?)
51
+ $expr = explode('->', $expr);
52
+ $meta = array_shift($expr);
53
+ $meta = isset($metaData[$meta]) ? $metaData[$meta] : null;
54
+ foreach($expr as $part){
55
+ if(is_scalar($meta) || is_null($meta))return $meta; // this isn't 100% correct
56
+ $meta = is_array($meta) ? $meta[$part] : $meta->$part;
57
+ }
58
+ return is_scalar($meta) ? (string)$meta : var_export($meta, true);
59
+ }
60
+
61
+ /**
62
+ * Expands a message with variables by replacing variables with meta data values.
63
+ * @param string $mesg The original message.
64
+ * @param array $metaData (Optional) Meta data relevant to message.
65
+ * @param callable|null $metaFormatter (Optional) Callback for formatting meta values.
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;
73
+ // handle tokenized message
74
+ foreach($mesg as $i => $token){
75
+ // handle escaped percent sign
76
+ if($token == '%%'){
77
+ $mesg[$i] = '%';
78
+ }else
79
+ // handle complex expressions
80
+ if(substr($token, 0, 1) == '%' && substr($token, -1, 1) == '%'){
81
+ $mesg[$i] = $this->GetMetaExprValue(substr($token, 1, -1), $metaData);
82
+ if($metaFormatter)$mesg[$i] = call_user_func($metaFormatter, $token, $mesg[$i]);
83
+ }
84
+ }
85
+ // compact message and return
86
+ return implode('', $mesg);
87
+ }
88
+
89
+ /**
90
+ * @param array $metaData (Optional) Meta data relevant to message.
91
+ * @param callable|null $metaFormatter (Optional) Meta formatter callback.
92
+ * @param string|null $mesg (Optional) Override message template to use.
93
+ * @return string Fully formatted message.
94
+ */
95
+ public function GetMessage($metaData = array(), $metaFormatter = null, $mesg = null){
96
+ return $this->GetFormattedMesg(is_null($mesg) ? $this->mesg : $mesg, $metaData, $metaFormatter);
97
+ }
98
+ }
classes/AlertManager.php CHANGED
@@ -1,382 +1,382 @@
1
- <?php
2
-
3
- final class WSAL_AlertManager {
4
-
5
- /**
6
- * @var WSAL_Alert[]
7
- */
8
- protected $_alerts = array();
9
-
10
- /**
11
- * @var WSAL_AbstractLogger[]
12
- */
13
- protected $_loggers = array();
14
-
15
- /**
16
- * @var WpSecurityAuditLog
17
- */
18
- protected $plugin;
19
-
20
- /**
21
- * Create new AlertManager instance.
22
- * @param WpSecurityAuditLog $plugin
23
- */
24
- public function __construct(WpSecurityAuditLog $plugin){
25
- $this->plugin = $plugin;
26
- foreach(glob(dirname(__FILE__) . '/Loggers/*.php') as $file)
27
- $this->AddFromFile($file);
28
-
29
- add_action('shutdown', array($this, '_CommitPipeline'));
30
- }
31
-
32
- /**
33
- * Add new logger from file inside autoloader path.
34
- * @param string $file Path to file.
35
- */
36
- public function AddFromFile($file){
37
- $this->AddFromClass($this->plugin->GetClassFileClassName($file));
38
- }
39
-
40
- /**
41
- * Add new logger given class name.
42
- * @param string $class Class name.
43
- */
44
- public function AddFromClass($class){
45
- $this->AddInstance(new $class($this->plugin));
46
- }
47
-
48
- /**
49
- * Add newly created logger to list.
50
- * @param WSAL_AbstractLogger $logger The new logger.
51
- */
52
- public function AddInstance(WSAL_AbstractLogger $logger){
53
- $this->_loggers[] = $logger;
54
- }
55
-
56
- /**
57
- * Remove logger by class name.
58
- * @param string $class The class name.
59
- */
60
- public function RemoveByClass($class){
61
- foreach($this->_loggers as $i => $inst)
62
- if(get_class($inst) == $class)
63
- unset($this->_loggers[$i]);
64
- }
65
-
66
- /**
67
- * Contains a list of alerts to trigger.
68
- * @var array
69
- */
70
- protected $_pipeline = array();
71
-
72
- /**
73
- * Contains an array of alerts that have been triggered for this request.
74
- * @var int[]
75
- */
76
- protected $_triggered_types = array();
77
-
78
- /**
79
- * Trigger an alert.
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'];
87
- }
88
- $roles = $this->plugin->settings->GetCurrentUserRoles();
89
- if (empty($roles) && !empty($data["CurrentUserRoles"])) {
90
- $roles = $data['CurrentUserRoles'];
91
- }
92
- if ($this->IsDisabledIP()) {
93
- return;
94
- }
95
- if ($this->CheckEnableUserRoles($username, $roles)) {
96
- if ($delayed) {
97
- $this->TriggerIf($type, $data, null);
98
- } else {
99
- $this->_CommitItem($type, $data, null);
100
- }
101
- }
102
- }
103
-
104
- /**
105
- * Check enable user and roles.
106
- * @param string user
107
- * @param array roles
108
- * @return boolean True if enable false otherwise.
109
- */
110
- public function CheckEnableUserRoles($user, $roles) {
111
- $is_enable = true;
112
- if ( $user != "" && $this->IsDisabledUser($user) ) { $is_enable = false; }
113
- if ( $roles != "" && $this->IsDisabledRole($roles) ) { $is_enable = false; }
114
- return $is_enable;
115
- }
116
-
117
- /**
118
- * Trigger only if a condition is met at the end of request.
119
- * @param integer $type Alert type ID.
120
- * @param array $data Alert data.
121
- * @param callable $cond A future condition callback (receives an object of type WSAL_AlertManager as parameter).
122
- */
123
- public function TriggerIf($type, $data, $cond = null) {
124
- $username = wp_get_current_user()->user_login;
125
- $roles = $this->plugin->settings->GetCurrentUserRoles();
126
-
127
- if ($this->CheckEnableUserRoles($username, $roles)) {
128
- $this->_pipeline[] = array(
129
- 'type' => $type,
130
- 'data' => $data,
131
- 'cond' => $cond,
132
- );
133
- }
134
- }
135
-
136
- /**
137
- * @internal Commit an alert now.
138
- */
139
- protected function _CommitItem($type, $data, $cond, $_retry = true)
140
- {
141
- if(!$cond || !!call_user_func($cond, $this)){
142
- if($this->IsEnabled($type)) {
143
- if(isset($this->_alerts[$type])){
144
- // ok, convert alert to a log entry
145
- $this->_triggered_types[] = $type;
146
- $this->Log($type, $data);
147
- }elseif($_retry){
148
- // this is the last attempt at loading alerts from default file
149
- $this->plugin->LoadDefaults();
150
- return $this->_CommitItem($type, $data, $cond, false);
151
- }else{
152
- // in general this shouldn't happen, but it could, so we handle it here :)
153
- throw new Exception('Alert with code "' . $type . '" has not be registered.');
154
- }
155
- }
156
- }
157
- }
158
-
159
- /**
160
- * @internal Runs over triggered alerts in pipeline and passes them to loggers.
161
- */
162
- public function _CommitPipeline(){
163
- foreach($this->_pipeline as $item)
164
- $this->_CommitItem($item['type'], $item['data'], $item['cond']);
165
- }
166
-
167
- /**
168
- * @param integer $type Alert type ID.
169
- * @return boolean True if at the end of request an alert of this type will be triggered.
170
- */
171
- public function WillTrigger($type){
172
- foreach($this->_pipeline as $item)
173
- if($item['type'] == $type)
174
- return true;
175
- return false;
176
- }
177
-
178
- /**
179
- * @param int $type Alert type ID.
180
- * @return boolean True if an alert has been or will be triggered in this request, false otherwise.
181
- */
182
- public function WillOrHasTriggered($type){
183
- return in_array($type, $this->_triggered_types)
184
- || $this->WillTrigger($type);
185
- }
186
-
187
- /**
188
- * Register an alert type.
189
- * @param array $info Array of [type, code, category, description, message] respectively.
190
- */
191
- public function Register($info){
192
- if(func_num_args() == 1){
193
- // handle single item
194
- list($type, $code, $catg, $desc, $mesg) = $info;
195
- if(isset($this->_alerts[$type]))
196
- throw new Exception("Alert $type already registered with Alert Manager.");
197
- $this->_alerts[$type] = new WSAL_Alert($type, $code, $catg, $desc, $mesg);
198
- }else{
199
- // handle multiple items
200
- foreach(func_get_args() as $arg)
201
- $this->Register($arg);
202
- }
203
- }
204
-
205
- /**
206
- * Register a whole group of items.
207
- * @param array $groups An array with group name as the index and an array of group items as the value.
208
- * Item values is an array of [type, code, description, message] respectively.
209
- */
210
- public function RegisterGroup($groups){
211
- foreach($groups as $name => $group){
212
- foreach($group as $item){
213
- list($type, $code, $desc, $mesg) = $item;
214
- $this->Register(array($type, $code, $name, $desc, $mesg));
215
- }
216
- }
217
- }
218
-
219
- /**
220
- * Returns whether alert of type $type is enabled or not.
221
- * @param integer $type Alert type.
222
- * @return boolean True if enabled, false otherwise.
223
- */
224
- public function IsEnabled($type){
225
- return !in_array($type, $this->GetDisabledAlerts());
226
- }
227
-
228
- /**
229
- * Disables a set of alerts by type.
230
- * @param int[] $types Alert type codes to be disabled.
231
- */
232
- public function SetDisabledAlerts($types){
233
- $this->plugin->settings->SetDisabledAlerts($types);
234
- }
235
-
236
- /**
237
- * @return int[] Returns an array of disabled alerts' type code.
238
- */
239
- public function GetDisabledAlerts(){
240
- return $this->plugin->settings->GetDisabledAlerts();
241
- }
242
-
243
- /**
244
- * @return WSAL_AbstractLogger[] Returns an array of loaded loggers.
245
- */
246
- public function GetLoggers(){
247
- return $this->_loggers;
248
- }
249
-
250
- /**
251
- * Converts an Alert into a Log entry (by invoking loggers).
252
- * You should not call this method directly.
253
- * @param integer $type Alert type.
254
- * @param array $data Misc alert data.
255
- */
256
- protected function Log($type, $data = array())
257
- {
258
- if (!isset($data['ClientIP'])) {
259
- $clientIP = $this->plugin->settings->GetMainClientIP();
260
- if (!empty($clientIP)) {
261
- $data['ClientIP'] = $clientIP;
262
- }
263
- }
264
- if (!isset($data['OtherIPs']) && $this->plugin->settings->IsMainIPFromProxy()) {
265
- $otherIPs = $this->plugin->settings->GetClientIPs();
266
- if (!empty($otherIPs)) {
267
- $data['OtherIPs'] = $otherIPs;
268
- }
269
- }
270
- if (!isset($data['UserAgent'])) {
271
- if (isset($_SERVER['HTTP_USER_AGENT'])) {
272
- $data['UserAgent'] = $_SERVER['HTTP_USER_AGENT'];
273
- }
274
- }
275
- if (!isset($data['Username']) && !isset($data['CurrentUserID'])) {
276
- if (function_exists('get_current_user_id')) {
277
- $data['CurrentUserID'] = get_current_user_id();
278
- }
279
- }
280
- if (!isset($data['CurrentUserRoles']) && function_exists('is_user_logged_in') && is_user_logged_in()) {
281
- $currentUserRoles = $this->plugin->settings->GetCurrentUserRoles();
282
- if (!empty($currentUserRoles)) {
283
- $data['CurrentUserRoles'] = $currentUserRoles;
284
- }
285
- }
286
- //if(isset($_SERVER['REMOTE_HOST']) && $_SERVER['REMOTE_HOST'] != $data['ClientIP'])
287
- // $data['ClientHost'] = $_SERVER['REMOTE_HOST'];
288
- //$data['OtherIPs'] = $_SERVER['REMOTE_HOST'];
289
-
290
- foreach ($this->_loggers as $logger) {
291
- $logger->Log($type, $data);
292
- }
293
- }
294
-
295
- /**
296
- * Return alert given alert type.
297
- * @param integer $type Alert type.
298
- * @param mixed $default Returned if alert is not found.
299
- * @return WSAL_Alert
300
- */
301
- public function GetAlert($type, $default = null){
302
- foreach($this->_alerts as $alert)
303
- if($alert->type == $type)
304
- return $alert;
305
- return $default;
306
- }
307
-
308
- /**
309
- * Returns all supported alerts.
310
- * @return WSAL_Alert[]
311
- */
312
- public function GetAlerts(){
313
- return $this->_alerts;
314
- }
315
-
316
- /**
317
- * Returns all supported alerts.
318
- * @return array
319
- */
320
- public function GetCategorizedAlerts(){
321
- $result = array();
322
- foreach($this->_alerts as $alert){
323
- if(!isset($result[$alert->catg]))
324
- $result[$alert->catg] = array();
325
- $result[$alert->catg][] = $alert;
326
- }
327
- ksort($result);
328
- return $result;
329
- }
330
-
331
- /**
332
- * Returns whether user is enabled or not.
333
- * @param string user.
334
- * @return boolean True if disabled, false otherwise.
335
- */
336
- public function IsDisabledUser($user)
337
- {
338
- return (in_array($user, $this->GetDisabledUsers())) ? true : false;
339
- }
340
-
341
- /**
342
- * @return Returns an array of disabled users.
343
- */
344
- public function GetDisabledUsers()
345
- {
346
- return $this->plugin->settings->GetExcludedMonitoringUsers();
347
- }
348
-
349
- /**
350
- * Returns whether user is enabled or not.
351
- * @param array roles.
352
- * @return boolean True if disabled, false otherwise.
353
- */
354
- public function IsDisabledRole($roles)
355
- {
356
- $is_disabled = false;
357
- foreach ($roles as $role) {
358
- if(in_array($role, $this->GetDisabledRoles())) $is_disabled = true;
359
- }
360
- return $is_disabled;
361
- }
362
-
363
- /**
364
- * @return Returns an array of disabled users.
365
- */
366
- public function GetDisabledRoles()
367
- {
368
- return $this->plugin->settings->GetExcludedMonitoringRoles();
369
- }
370
-
371
- private function IsDisabledIP()
372
- {
373
- $is_disabled = false;
374
- $ip = $this->plugin->settings->GetMainClientIP();
375
- $excluded_ips = $this->plugin->settings->GetExcludedMonitoringIP();
376
- if (in_array($ip, $excluded_ips)) {
377
- $is_disabled = true;
378
- }
379
- return $is_disabled;
380
- }
381
-
382
- }
1
+ <?php
2
+
3
+ final class WSAL_AlertManager {
4
+
5
+ /**
6
+ * @var WSAL_Alert[]
7
+ */
8
+ protected $_alerts = array();
9
+
10
+ /**
11
+ * @var WSAL_AbstractLogger[]
12
+ */
13
+ protected $_loggers = array();
14
+
15
+ /**
16
+ * @var WpSecurityAuditLog
17
+ */
18
+ protected $plugin;
19
+
20
+ /**
21
+ * Create new AlertManager instance.
22
+ * @param WpSecurityAuditLog $plugin
23
+ */
24
+ public function __construct(WpSecurityAuditLog $plugin){
25
+ $this->plugin = $plugin;
26
+ foreach(glob(dirname(__FILE__) . '/Loggers/*.php') as $file)
27
+ $this->AddFromFile($file);
28
+
29
+ add_action('shutdown', array($this, '_CommitPipeline'));
30
+ }
31
+
32
+ /**
33
+ * Add new logger from file inside autoloader path.
34
+ * @param string $file Path to file.
35
+ */
36
+ public function AddFromFile($file){
37
+ $this->AddFromClass($this->plugin->GetClassFileClassName($file));
38
+ }
39
+
40
+ /**
41
+ * Add new logger given class name.
42
+ * @param string $class Class name.
43
+ */
44
+ public function AddFromClass($class){
45
+ $this->AddInstance(new $class($this->plugin));
46
+ }
47
+
48
+ /**
49
+ * Add newly created logger to list.
50
+ * @param WSAL_AbstractLogger $logger The new logger.
51
+ */
52
+ public function AddInstance(WSAL_AbstractLogger $logger){
53
+ $this->_loggers[] = $logger;
54
+ }
55
+
56
+ /**
57
+ * Remove logger by class name.
58
+ * @param string $class The class name.
59
+ */
60
+ public function RemoveByClass($class){
61
+ foreach($this->_loggers as $i => $inst)
62
+ if(get_class($inst) == $class)
63
+ unset($this->_loggers[$i]);
64
+ }
65
+
66
+ /**
67
+ * Contains a list of alerts to trigger.
68
+ * @var array
69
+ */
70
+ protected $_pipeline = array();
71
+
72
+ /**
73
+ * Contains an array of alerts that have been triggered for this request.
74
+ * @var int[]
75
+ */
76
+ protected $_triggered_types = array();
77
+
78
+ /**
79
+ * Trigger an alert.
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'];
87
+ }
88
+ $roles = $this->plugin->settings->GetCurrentUserRoles();
89
+ if (empty($roles) && !empty($data["CurrentUserRoles"])) {
90
+ $roles = $data['CurrentUserRoles'];
91
+ }
92
+ if ($this->IsDisabledIP()) {
93
+ return;
94
+ }
95
+ if ($this->CheckEnableUserRoles($username, $roles)) {
96
+ if ($delayed) {
97
+ $this->TriggerIf($type, $data, null);
98
+ } else {
99
+ $this->_CommitItem($type, $data, null);
100
+ }
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Check enable user and roles.
106
+ * @param string user
107
+ * @param array roles
108
+ * @return boolean True if enable false otherwise.
109
+ */
110
+ public function CheckEnableUserRoles($user, $roles) {
111
+ $is_enable = true;
112
+ if ( $user != "" && $this->IsDisabledUser($user) ) { $is_enable = false; }
113
+ if ( $roles != "" && $this->IsDisabledRole($roles) ) { $is_enable = false; }
114
+ return $is_enable;
115
+ }
116
+
117
+ /**
118
+ * Trigger only if a condition is met at the end of request.
119
+ * @param integer $type Alert type ID.
120
+ * @param array $data Alert data.
121
+ * @param callable $cond A future condition callback (receives an object of type WSAL_AlertManager as parameter).
122
+ */
123
+ public function TriggerIf($type, $data, $cond = null) {
124
+ $username = wp_get_current_user()->user_login;
125
+ $roles = $this->plugin->settings->GetCurrentUserRoles();
126
+
127
+ if ($this->CheckEnableUserRoles($username, $roles)) {
128
+ $this->_pipeline[] = array(
129
+ 'type' => $type,
130
+ 'data' => $data,
131
+ 'cond' => $cond,
132
+ );
133
+ }
134
+ }
135
+
136
+ /**
137
+ * @internal Commit an alert now.
138
+ */
139
+ protected function _CommitItem($type, $data, $cond, $_retry = true)
140
+ {
141
+ if(!$cond || !!call_user_func($cond, $this)){
142
+ if($this->IsEnabled($type)) {
143
+ if(isset($this->_alerts[$type])){
144
+ // ok, convert alert to a log entry
145
+ $this->_triggered_types[] = $type;
146
+ $this->Log($type, $data);
147
+ }elseif($_retry){
148
+ // this is the last attempt at loading alerts from default file
149
+ $this->plugin->LoadDefaults();
150
+ return $this->_CommitItem($type, $data, $cond, false);
151
+ }else{
152
+ // in general this shouldn't happen, but it could, so we handle it here :)
153
+ throw new Exception('Alert with code "' . $type . '" has not be registered.');
154
+ }
155
+ }
156
+ }
157
+ }
158
+
159
+ /**
160
+ * @internal Runs over triggered alerts in pipeline and passes them to loggers.
161
+ */
162
+ public function _CommitPipeline(){
163
+ foreach($this->_pipeline as $item)
164
+ $this->_CommitItem($item['type'], $item['data'], $item['cond']);
165
+ }
166
+
167
+ /**
168
+ * @param integer $type Alert type ID.
169
+ * @return boolean True if at the end of request an alert of this type will be triggered.
170
+ */
171
+ public function WillTrigger($type){
172
+ foreach($this->_pipeline as $item)
173
+ if($item['type'] == $type)
174
+ return true;
175
+ return false;
176
+ }
177
+
178
+ /**
179
+ * @param int $type Alert type ID.
180
+ * @return boolean True if an alert has been or will be triggered in this request, false otherwise.
181
+ */
182
+ public function WillOrHasTriggered($type){
183
+ return in_array($type, $this->_triggered_types)
184
+ || $this->WillTrigger($type);
185
+ }
186
+
187
+ /**
188
+ * Register an alert type.
189
+ * @param array $info Array of [type, code, category, description, message] respectively.
190
+ */
191
+ public function Register($info){
192
+ if(func_num_args() == 1){
193
+ // handle single item
194
+ list($type, $code, $catg, $desc, $mesg) = $info;
195
+ if(isset($this->_alerts[$type]))
196
+ throw new Exception("Alert $type already registered with Alert Manager.");
197
+ $this->_alerts[$type] = new WSAL_Alert($type, $code, $catg, $desc, $mesg);
198
+ }else{
199
+ // handle multiple items
200
+ foreach(func_get_args() as $arg)
201
+ $this->Register($arg);
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Register a whole group of items.
207
+ * @param array $groups An array with group name as the index and an array of group items as the value.
208
+ * Item values is an array of [type, code, description, message] respectively.
209
+ */
210
+ public function RegisterGroup($groups){
211
+ foreach($groups as $name => $group){
212
+ foreach($group as $item){
213
+ list($type, $code, $desc, $mesg) = $item;
214
+ $this->Register(array($type, $code, $name, $desc, $mesg));
215
+ }
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Returns whether alert of type $type is enabled or not.
221
+ * @param integer $type Alert type.
222
+ * @return boolean True if enabled, false otherwise.
223
+ */
224
+ public function IsEnabled($type){
225
+ return !in_array($type, $this->GetDisabledAlerts());
226
+ }
227
+
228
+ /**
229
+ * Disables a set of alerts by type.
230
+ * @param int[] $types Alert type codes to be disabled.
231
+ */
232
+ public function SetDisabledAlerts($types){
233
+ $this->plugin->settings->SetDisabledAlerts($types);
234
+ }
235
+
236
+ /**
237
+ * @return int[] Returns an array of disabled alerts' type code.
238
+ */
239
+ public function GetDisabledAlerts(){
240
+ return $this->plugin->settings->GetDisabledAlerts();
241
+ }
242
+
243
+ /**
244
+ * @return WSAL_AbstractLogger[] Returns an array of loaded loggers.
245
+ */
246
+ public function GetLoggers(){
247
+ return $this->_loggers;
248
+ }
249
+
250
+ /**
251
+ * Converts an Alert into a Log entry (by invoking loggers).
252
+ * You should not call this method directly.
253
+ * @param integer $type Alert type.
254
+ * @param array $data Misc alert data.
255
+ */
256
+ protected function Log($type, $data = array())
257
+ {
258
+ if (!isset($data['ClientIP'])) {
259
+ $clientIP = $this->plugin->settings->GetMainClientIP();
260
+ if (!empty($clientIP)) {
261
+ $data['ClientIP'] = $clientIP;
262
+ }
263
+ }
264
+ if (!isset($data['OtherIPs']) && $this->plugin->settings->IsMainIPFromProxy()) {
265
+ $otherIPs = $this->plugin->settings->GetClientIPs();
266
+ if (!empty($otherIPs)) {
267
+ $data['OtherIPs'] = $otherIPs;
268
+ }
269
+ }
270
+ if (!isset($data['UserAgent'])) {
271
+ if (isset($_SERVER['HTTP_USER_AGENT'])) {
272
+ $data['UserAgent'] = $_SERVER['HTTP_USER_AGENT'];
273
+ }
274
+ }
275
+ if (!isset($data['Username']) && !isset($data['CurrentUserID'])) {
276
+ if (function_exists('get_current_user_id')) {
277
+ $data['CurrentUserID'] = get_current_user_id();
278
+ }
279
+ }
280
+ if (!isset($data['CurrentUserRoles']) && function_exists('is_user_logged_in') && is_user_logged_in()) {
281
+ $currentUserRoles = $this->plugin->settings->GetCurrentUserRoles();
282
+ if (!empty($currentUserRoles)) {
283
+ $data['CurrentUserRoles'] = $currentUserRoles;
284
+ }
285
+ }
286
+ //if(isset($_SERVER['REMOTE_HOST']) && $_SERVER['REMOTE_HOST'] != $data['ClientIP'])
287
+ // $data['ClientHost'] = $_SERVER['REMOTE_HOST'];
288
+ //$data['OtherIPs'] = $_SERVER['REMOTE_HOST'];
289
+
290
+ foreach ($this->_loggers as $logger) {
291
+ $logger->Log($type, $data);
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Return alert given alert type.
297
+ * @param integer $type Alert type.
298
+ * @param mixed $default Returned if alert is not found.
299
+ * @return WSAL_Alert
300
+ */
301
+ public function GetAlert($type, $default = null){
302
+ foreach($this->_alerts as $alert)
303
+ if($alert->type == $type)
304
+ return $alert;
305
+ return $default;
306
+ }
307
+
308
+ /**
309
+ * Returns all supported alerts.
310
+ * @return WSAL_Alert[]
311
+ */
312
+ public function GetAlerts(){
313
+ return $this->_alerts;
314
+ }
315
+
316
+ /**
317
+ * Returns all supported alerts.
318
+ * @return array
319
+ */
320
+ public function GetCategorizedAlerts(){
321
+ $result = array();
322
+ foreach($this->_alerts as $alert){
323
+ if(!isset($result[$alert->catg]))
324
+ $result[$alert->catg] = array();
325
+ $result[$alert->catg][] = $alert;
326
+ }
327
+ ksort($result);
328
+ return $result;
329
+ }
330
+
331
+ /**
332
+ * Returns whether user is enabled or not.
333
+ * @param string user.
334
+ * @return boolean True if disabled, false otherwise.
335
+ */
336
+ public function IsDisabledUser($user)
337
+ {
338
+ return (in_array($user, $this->GetDisabledUsers())) ? true : false;
339
+ }
340
+
341
+ /**
342
+ * @return Returns an array of disabled users.
343
+ */
344
+ public function GetDisabledUsers()
345
+ {
346
+ return $this->plugin->settings->GetExcludedMonitoringUsers();
347
+ }
348
+
349
+ /**
350
+ * Returns whether user is enabled or not.
351
+ * @param array roles.
352
+ * @return boolean True if disabled, false otherwise.
353
+ */
354
+ public function IsDisabledRole($roles)
355
+ {
356
+ $is_disabled = false;
357
+ foreach ($roles as $role) {
358
+ if(in_array($role, $this->GetDisabledRoles())) $is_disabled = true;
359
+ }
360
+ return $is_disabled;
361
+ }
362
+
363
+ /**
364
+ * @return Returns an array of disabled users.
365
+ */
366
+ public function GetDisabledRoles()
367
+ {
368
+ return $this->plugin->settings->GetExcludedMonitoringRoles();
369
+ }
370
+
371
+ private function IsDisabledIP()
372
+ {
373
+ $is_disabled = false;
374
+ $ip = $this->plugin->settings->GetMainClientIP();
375
+ $excluded_ips = $this->plugin->settings->GetExcludedMonitoringIP();
376
+ if (in_array($ip, $excluded_ips)) {
377
+ $is_disabled = true;
378
+ }
379
+ return $is_disabled;
380
+ }
381
+
382
+ }
classes/AuditLogListView.php CHANGED
@@ -1,445 +1,452 @@
1
- <?php
2
-
3
- require_once(ABSPATH . 'wp-admin/includes/admin.php');
4
- require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
5
-
6
- class WSAL_AuditLogListView extends WP_List_Table
7
- {
8
-
9
- /**
10
- * @var WpSecurityAuditLog
11
- */
12
- protected $_plugin;
13
- protected $_gmt_offset_sec = 0;
14
-
15
- public function __construct($plugin)
16
- {
17
- $this->_plugin = $plugin;
18
-
19
- $timezone = $this->_plugin->settings->GetTimezone();
20
- if ($timezone) {
21
- $this->_gmt_offset_sec = get_option('gmt_offset') * HOUR_IN_SECONDS;
22
- } else {
23
- $this->_gmt_offset_sec = date('Z');
24
- }
25
-
26
- parent::__construct(array(
27
- 'singular' => 'log',
28
- 'plural' => 'logs',
29
- 'ajax' => true,
30
- 'screen' => 'interval-list',
31
- ));
32
- }
33
-
34
- public function no_items()
35
- {
36
- _e('No events so far.', 'wp-security-audit-log');
37
- }
38
-
39
- public function extra_tablenav($which)
40
- {
41
- // items-per-page widget
42
- $o = __('Other', 'wp-security-audit-log');
43
- $p = $this->_plugin->settings->GetViewPerPage();
44
- $items = array($o, 5, 10, 15, 30, 50);
45
- if (!in_array($p, $items)) $items[] = $p;
46
- if ($p == $o || $p == 0) $p = $o[1]; // a sane default if things goes bust
47
-
48
- ?><div class="wsal-ipp wsal-ipp-<?php echo $which; ?>">
49
- <?php _e('Show ', 'wp-security-audit-log'); ?>
50
- <select class="wsal-ipps" onfocus="WsalIppsFocus(value);" onchange="WsalIppsChange(value);">
51
- <?php foreach ($items as $item) { ?>
52
- <option
53
- value="<?php echo is_string($item) ? '' : $item; ?>"
54
- <?php if ($item == $p) echo 'selected="selected"'; ?>><?php
55
- echo $item;
56
- ?></option>
57
- <?php } ?>
58
- </select>
59
- <?php _e(' Items', 'wp-security-audit-log'); ?>
60
- </div><?php
61
-
62
- // show site alerts widget
63
- if ($this->is_multisite() && $this->is_main_blog()) {
64
- $curr = $this->get_view_site_id();
65
- ?><div class="wsal-ssa wsal-ssa-<?php echo $which; ?>">
66
- <?php if ($this->get_site_count() > 15) { ?>
67
- <?php $curr = $curr ? get_blog_details($curr) : null; ?>
68
- <?php $curr = $curr ? ($curr->blogname . ' (' . $curr->domain . ')') : 'All Sites'; ?>
69
- <input type="text" class="wsal-ssas" value="<?php echo esc_attr($curr); ?>"/>
70
- <?php } else { ?>
71
- <select class="wsal-ssas" onchange="WsalSsasChange(value);">
72
- <option value="0"><?php _e('All Sites', 'wp-security-audit-log'); ?></option>
73
- <?php foreach ($this->get_sites() as $info) { ?>
74
- <option value="<?php echo $info->blog_id; ?>"
75
- <?php if ($info->blog_id == $curr) echo 'selected="selected"'; ?>><?php
76
- echo esc_html($info->blogname) . ' (' . esc_html($info->domain) . ')';
77
- ?></option>
78
- <?php } ?>
79
- </select>
80
- <?php } ?>
81
- </div><?php
82
- }
83
- }
84
-
85
- /**
86
- * @param int|null $limit Maximum number of sites to return (null = no limit).
87
- * @return object Object with keys: blog_id, blogname, domain
88
- */
89
- public function get_sites($limit = null)
90
- {
91
- global $wpdb;
92
-
93
- // build query
94
- $sql = 'SELECT blog_id, domain FROM ' . $wpdb->blogs;
95
- if (!is_null($limit)) $sql .= ' LIMIT ' . $limit;
96
-
97
- // execute query
98
- $res = $wpdb->get_results($sql);
99
-
100
- // modify result
101
- foreach ($res as $row) {
102
- $row->blogname = get_blog_option($row->blog_id, 'blogname');
103
- }
104
- // return result
105
- return $res;
106
- }
107
-
108
- /**
109
- * @return int The number of sites on the network.
110
- */
111
- public function get_site_count()
112
- {
113
- global $wpdb;
114
- $sql = 'SELECT COUNT(*) FROM ' . $wpdb->blogs;
115
- return (int)$wpdb->get_var($sql);
116
- }
117
-
118
- public function get_columns()
119
- {
120
- $cols = array(
121
- //'cb' => '<input type="checkbox" />',
122
- //'read' => __('Read', 'wp-security-audit-log'),
123
- 'type' => __('Code', 'wp-security-audit-log'),
124
- 'code' => __('Type', 'wp-security-audit-log'),
125
- 'crtd' => __('Date', 'wp-security-audit-log'),
126
- 'user' => __('Username', 'wp-security-audit-log'),
127
- 'scip' => __('Source IP', 'wp-security-audit-log'),
128
- );
129
- if ($this->is_multisite() && $this->is_main_blog() && !$this->is_specific_view()) {
130
- $cols['site'] = __('Site', 'wp-security-audit-log');
131
- }
132
- $cols['mesg'] = __('Message', 'wp-security-audit-log');
133
- if ($this->_plugin->settings->IsDataInspectorEnabled()) {
134
- $cols['data'] = '';
135
- }
136
- $sel_columns = $this->_plugin->settings->GetColumnsSelected();
137
- if (!empty($sel_columns)) {
138
- unset($cols);
139
- $sel_columns = (array)json_decode($sel_columns);
140
- foreach ($sel_columns as $key => $value) {
141
- switch ($key) {
142
- case 'alert_code':
143
- $cols['type'] = __('Code', 'wp-security-audit-log');
144
- break;
145
- case 'type':
146
- $cols['code'] = __('Type', 'wp-security-audit-log');
147
- break;
148
- case 'date':
149
- $cols['crtd'] = __('Date', 'wp-security-audit-log');
150
- break;
151
- case 'username':
152
- $cols['user'] = __('Username', 'wp-security-audit-log');
153
- break;
154
- case 'source_ip':
155
- $cols['scip'] = __('Source IP', 'wp-security-audit-log');
156
- break;
157
- case 'site':
158
- $cols['site'] = __('Site', 'wp-security-audit-log');
159
- break;
160
- case 'message':
161
- $cols['mesg'] = __('Message', 'wp-security-audit-log');
162
- break;
163
- }
164
- }
165
- }
166
- return $cols;
167
- }
168
-
169
- public function column_cb($item)
170
- {
171
- return '<input type="checkbox" value="'.$item->id.'" '
172
- . 'name="'.esc_attr($this->_args['singular']).'[]"/>';
173
- }
174
-
175
- public function get_sortable_columns()
176
- {
177
- return array(
178
- 'read' => array('is_read', false),
179
- //'code' => array('code', false),
180
- 'type' => array('alert_id', false),
181
- 'crtd' => array('created_on', true),
182
- 'user' => array('user', true),
183
- 'scip' => array('scip', false)
184
- );
185
- }
186
-
187
- public function column_default($item, $column_name)
188
- {
189
- //example: $item->getMetaValue('CurrentUserID')
190
-
191
- if (!$this->_plugin->settings->GetDatetimeFormat()) $datetimeFormat = 'h:i:s.$$$&\n\b\s\p;A';
192
- else $datetimeFormat = 'H:i:s.$$$';
193
- switch ($column_name) {
194
- case 'read':
195
- return '<span class="log-read log-read-'
196
- . ($item->is_read ? 'old' : 'new')
197
- . '" title="' . __('Click to toggle.', 'wp-security-audit-log') . '"></span>';
198
- case 'type':
199
- return str_pad($item->alert_id, 4, '0', STR_PAD_LEFT);
200
- case 'code':
201
- $code = $this->_plugin->alerts->GetAlert($item->alert_id);
202
- $code = $code ? $code->code : 0;
203
- $const = (object)array('name' => 'E_UNKNOWN', 'value' => 0, 'description' => __('Unknown error code.', 'wp-security-audit-log'));
204
- $const = $this->_plugin->constants->GetConstantBy('value', $code, $const);
205
- return '<span class="log-type log-type-' . $const->value
206
- . '" title="' . esc_html($const->name . ': ' . $const->description) . '"></span>';
207
- case 'crtd':
208
- return $item->created_on ? (
209
- str_replace(
210
- '$$$',
211
- substr(number_format(fmod($item->created_on + $this->_gmt_offset_sec, 1), 3), 2),
212
- date('Y-m-d<\b\r>'.$datetimeFormat, $item->created_on + $this->_gmt_offset_sec)
213
- )
214
- ) : '<i>unknown</i>';
215
- case 'user':
216
- $username = $item->GetUsername();
217
- if ($username && ($user = get_user_by('login', $username))) {
218
- $image = get_avatar($user->ID, 32);
219
- $uhtml = '<a href="' . admin_url('user-edit.php?user_id=' . $user->ID)
220
- . '" target="_blank">' . esc_html($user->display_name) . '</a>';
221
- $roles = $item->GetUserRoles();
222
- if (is_array($roles) && count($roles)) {
223
- $roles = __(esc_html(ucwords(implode(', ', $roles))));
224
- } else if (is_string($roles) && $roles != '') {
225
- $roles = __(esc_html(ucwords(str_replace(array("\"", "[", "]"), " ", $roles))));
226
- } else {
227
- $roles = '<i>' . __('Unknown', 'wp-security-audit-log') . '</i>';
228
- }
229
- } elseif ($username == 'Plugin') {
230
- $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/plugin-logo.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
231
- $uhtml = '<i>' . __('Plugin', 'wp-security-audit-log') . '</i>';
232
- $roles = '';
233
- } else {
234
- $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
235
- $uhtml = '<i>' . __('System', 'wp-security-audit-log') . '</i>';
236
- $roles = '';
237
- }
238
- return $image . $uhtml . '<br/>' . $roles;
239
- case 'scip':
240
- $scip = $item->GetSourceIP();
241
- if (is_string($scip)) {
242
- $scip = str_replace(array("\"", "[", "]"), "", $scip);
243
- }
244
- $oips = array(); //$item->GetOtherIPs();
245
- // if there's no IP...
246
- if (is_null($scip) || $scip == '') return '<i>unknown</i>';
247
- // if there's only one IP...
248
- $link = "http://whatismyipaddress.com/ip/" . $scip ."?utm_source=plugin&utm_medium=referral&utm_campaign=WPSAL";
249
- if (count($oips) < 2) return "<a target='_blank' href='$link'>". esc_html($scip) .'</a>';
250
- // if there are many IPs...
251
- $html = "<a target='_blank' href='http://whatismyipaddress.com/ip/$scip'>". esc_html($scip) .'</a>'.' <a href="javascript:;" onclick="jQuery(this).hide().next().show();">(more&hellip;)</a><div style="display: none;">';
252
- foreach ($oips as $ip) if($scip != $ip) $html .= '<div>' . $ip . '</div>';
253
- $html .= '</div>';
254
- return $html;
255
- case 'site':
256
- $info = get_blog_details($item->site_id, true);
257
- return !$info ? ('Unknown Site '.$item->site_id)
258
- : ('<a href="' . esc_attr($info->siteurl) . '">' . esc_html($info->blogname) . '</a>');
259
- case 'mesg':
260
- return '<div id="Event' . $item->id . '">' . $item->GetMessage(array($this, 'meta_formatter')) . '</div>';
261
- case 'data':
262
- $url = admin_url('admin-ajax.php') . '?action=AjaxInspector&amp;occurrence=' . $item->id;
263
- return '<a class="more-info thickbox" title="' . __('Alert Data Inspector', 'wp-security-audit-log') . '"'
264
- . ' href="' . $url . '&amp;TB_iframe=true&amp;width=600&amp;height=550">&hellip;</a>';
265
- default:
266
- return isset($item->$column_name)
267
- ? esc_html($item->$column_name)
268
- : 'Column "' . esc_html($column_name) . '" not found';
269
- }
270
- }
271
-
272
- public function reorder_items_str($a, $b)
273
- {
274
- $result = strcmp($a->{$this->_orderby}, $b->{$this->_orderby});
275
- return ($this->_order === 'asc') ? $result : -$result;
276
- }
277
-
278
- public function reorder_items_int($a, $b)
279
- {
280
- $result = $a->{$this->_orderby} - $b->{$this->_orderby};
281
- return ($this->_order === 'asc') ? $result : -$result;
282
- }
283
-
284
- public function meta_formatter($name, $value)
285
- {
286
- switch (true) {
287
- case $name == '%Message%':
288
- return esc_html($value);
289
-
290
- case $name == '%PromoMessage%':
291
- return '<p class="promo-alert">' . $value .'</p>';
292
-
293
- case $name == '%PromoLink%':
294
- return $value;
295
-
296
- case $name == '%MetaLink%':
297
- if (!empty($value)) {
298
- return "<a href=\"#\" onclick=\"WsalDisableCustom(this, '".$value."');\"> Exclude Custom Field from the Monitoring</a>";
299
- } else {
300
- return "";
301
- }
302
-
303
- case $name == '%RevisionLink%':
304
- if (!empty($value) && $value != 'NULL') {
305
- return ' Click <a target="_blank" href="'.$value.'">here</a> to see the content changes.';
306
- } else {
307
- return "";
308
- }
309
-
310
- case in_array($name, array('%MetaValue%', '%MetaValueOld%', '%MetaValueNew%')):
311
- return '<strong>' . (
312
- strlen($value) > 50 ? (esc_html(substr($value, 0, 50)) . '&hellip;') : esc_html($value)
313
- ) . '</strong>';
314
-
315
- case strncmp($value, 'http://', 7) === 0:
316
- case strncmp($value, 'https://', 7) === 0:
317
- return '<a href="' . esc_html($value) . '"'
318
- . ' title="' . esc_html($value) . '"'
319
- . ' target="_blank">'
320
- . esc_html(parse_url($value, PHP_URL_HOST)) . '/&hellip;/'
321
- . esc_html(basename(parse_url($value, PHP_URL_PATH)))
322
- . '</a>';
323
-
324
- default:
325
- return '<strong>' . esc_html($value) . '</strong>';
326
- }
327
- }
328
-
329
- protected function is_multisite()
330
- {
331
- return $this->_plugin->IsMultisite();
332
- }
333
-
334
- protected function is_main_blog()
335
- {
336
- return get_current_blog_id() == 1;
337
- }
338
-
339
- protected function is_specific_view()
340
- {
341
- return isset($_REQUEST['wsal-cbid']) && $_REQUEST['wsal-cbid'] != '0';
342
- }
343
-
344
- protected function get_specific_view()
345
- {
346
- return isset($_REQUEST['wsal-cbid']) ? (int)$_REQUEST['wsal-cbid'] : 0;
347
- }
348
-
349
- protected function get_view_site_id()
350
- {
351
- switch (true) {
352
- // non-multisite
353
- case !$this->is_multisite():
354
- return 0;
355
- // multisite + main site view
356
- case $this->is_main_blog() && !$this->is_specific_view():
357
- return 0;
358
- // multisite + switched site view
359
- case $this->is_main_blog() && $this->is_specific_view():
360
- return $this->get_specific_view();
361
- // multisite + local site view
362
- default:
363
- return get_current_blog_id();
364
- }
365
- }
366
-
367
- public function prepare_items()
368
- {
369
- $per_page = $this->_plugin->settings->GetViewPerPage();
370
-
371
- $columns = $this->get_columns();
372
- $hidden = array();
373
- $sortable = $this->get_sortable_columns();
374
-
375
- $this->_column_headers = array($columns, $hidden, $sortable);
376
-
377
- //$this->process_bulk_action();
378
- //TO DO: Get rid of OccurrenceQuery and use the Occurence Model
379
- $query = new WSAL_Models_OccurrenceQuery();
380
-
381
- $bid = (int)$this->get_view_site_id();
382
- if ($bid) {
383
- $query->addCondition("site_id = %s ", $bid);
384
- }
385
-
386
- $query = apply_filters('wsal_auditlog_query', $query);
387
-
388
- $total_items = $query->getAdapter()->Count($query);
389
-
390
- if (empty($_REQUEST["orderby"])) {
391
- $query->addOrderBy("created_on", true);
392
- } else {
393
- $orderByField = $_REQUEST["orderby"];
394
-
395
- $isDescending = true;
396
- if (!empty($_REQUEST['order']) && $_REQUEST["order"] == "asc") {
397
- $isDescending = false;
398
- }
399
-
400
- //TO DO: Allow order by meta values
401
- if ($orderByField == "scip") {
402
- $query->addMetaJoin();
403
- $query->addOrderBy('CASE WHEN meta.name = "ClientIP" THEN meta.value END', $isDescending);
404
- } else if ($orderByField == "user") {
405
- $query->addMetaJoin();
406
- $query->addOrderBy('CASE WHEN meta.name = "CurrentUserID" THEN meta.value END', $isDescending);
407
- } else {
408
- $tmp = new WSAL_Models_Occurrence();
409
- //Making sure the field exists to order by
410
- if (isset($tmp->{$orderByField})) {
411
- // TODO we used to use a custom comparator ... is it safe to let MySQL do the ordering now?
412
- $query->addOrderBy($_REQUEST["orderby"], $isDescending);
413
-
414
- } else {
415
- $query->addOrderBy("created_on", true);
416
- }
417
- }
418
- }
419
-
420
- /** @todo Modify $query instead */
421
- /** @deprecated */
422
- //$data = array_slice($data, ($this->get_pagenum() - 1) * $per_page, $per_page);
423
- $query->setOffset(($this->get_pagenum() - 1) * $per_page);
424
- $query->setLimit($per_page);
425
-
426
- $this->items = $query->getAdapter()->Execute($query);
427
-
428
- $this->set_pagination_args(array(
429
- 'total_items' => $total_items,
430
- 'per_page' => $per_page,
431
- 'total_pages' => ceil($total_items / $per_page)
432
- ));
433
- }
434
-
435
- public function single_row($item)
436
- {
437
- if ($item->alert_id == 9999) {
438
- echo '<tr style="background-color: #D5E46E">';
439
- $this->single_row_columns($item);
440
- echo '</tr>';
441
- } else {
442
- parent::single_row($item);
443
- }
444
- }
445
- }
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(ABSPATH . 'wp-admin/includes/admin.php');
4
+ require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
5
+
6
+ class WSAL_AuditLogListView extends WP_List_Table
7
+ {
8
+
9
+ /**
10
+ * @var WpSecurityAuditLog
11
+ */
12
+ protected $_plugin;
13
+ protected $_gmt_offset_sec = 0;
14
+
15
+ public function __construct($plugin)
16
+ {
17
+ $this->_plugin = $plugin;
18
+
19
+ $timezone = $this->_plugin->settings->GetTimezone();
20
+ if ($timezone) {
21
+ $this->_gmt_offset_sec = get_option('gmt_offset') * HOUR_IN_SECONDS;
22
+ } else {
23
+ $this->_gmt_offset_sec = date('Z');
24
+ }
25
+
26
+ parent::__construct(array(
27
+ 'singular' => 'log',
28
+ 'plural' => 'logs',
29
+ 'ajax' => true,
30
+ 'screen' => 'interval-list',
31
+ ));
32
+ }
33
+
34
+ public function no_items()
35
+ {
36
+ _e('No events so far.', 'wp-security-audit-log');
37
+ }
38
+
39
+ public function extra_tablenav($which)
40
+ {
41
+ // items-per-page widget
42
+ $o = __('Other', 'wp-security-audit-log');
43
+ $p = $this->_plugin->settings->GetViewPerPage();
44
+ $items = array($o, 5, 10, 15, 30, 50);
45
+ if (!in_array($p, $items)) $items[] = $p;
46
+ if ($p == $o || $p == 0) $p = $o[1]; // a sane default if things goes bust
47
+
48
+ ?><div class="wsal-ipp wsal-ipp-<?php echo $which; ?>">
49
+ <?php _e('Show ', 'wp-security-audit-log'); ?>
50
+ <select class="wsal-ipps" onfocus="WsalIppsFocus(value);" onchange="WsalIppsChange(value);">
51
+ <?php foreach ($items as $item) { ?>
52
+ <option
53
+ value="<?php echo is_string($item) ? '' : $item; ?>"
54
+ <?php if ($item == $p) echo 'selected="selected"'; ?>><?php
55
+ echo $item;
56
+ ?></option>
57
+ <?php } ?>
58
+ </select>
59
+ <?php _e(' Items', 'wp-security-audit-log'); ?>
60
+ </div><?php
61
+
62
+ // show site alerts widget
63
+ if ($this->is_multisite() && $this->is_main_blog()) {
64
+ $curr = $this->get_view_site_id();
65
+ ?><div class="wsal-ssa wsal-ssa-<?php echo $which; ?>">
66
+ <?php if ($this->get_site_count() > 15) { ?>
67
+ <?php $curr = $curr ? get_blog_details($curr) : null; ?>
68
+ <?php $curr = $curr ? ($curr->blogname . ' (' . $curr->domain . ')') : 'All Sites'; ?>
69
+ <input type="text" class="wsal-ssas" value="<?php echo esc_attr($curr); ?>"/>
70
+ <?php } else { ?>
71
+ <select class="wsal-ssas" onchange="WsalSsasChange(value);">
72
+ <option value="0"><?php _e('All Sites', 'wp-security-audit-log'); ?></option>
73
+ <?php foreach ($this->get_sites() as $info) { ?>
74
+ <option value="<?php echo $info->blog_id; ?>"
75
+ <?php if ($info->blog_id == $curr) echo 'selected="selected"'; ?>><?php
76
+ echo esc_html($info->blogname) . ' (' . esc_html($info->domain) . ')';
77
+ ?></option>
78
+ <?php } ?>
79
+ </select>
80
+ <?php } ?>
81
+ </div><?php
82
+ }
83
+ }
84
+
85
+ /**
86
+ * @param int|null $limit Maximum number of sites to return (null = no limit).
87
+ * @return object Object with keys: blog_id, blogname, domain
88
+ */
89
+ public function get_sites($limit = null)
90
+ {
91
+ global $wpdb;
92
+
93
+ // build query
94
+ $sql = 'SELECT blog_id, domain FROM ' . $wpdb->blogs;
95
+ if (!is_null($limit)) $sql .= ' LIMIT ' . $limit;
96
+
97
+ // execute query
98
+ $res = $wpdb->get_results($sql);
99
+
100
+ // modify result
101
+ foreach ($res as $row) {
102
+ $row->blogname = get_blog_option($row->blog_id, 'blogname');
103
+ }
104
+ // return result
105
+ return $res;
106
+ }
107
+
108
+ /**
109
+ * @return int The number of sites on the network.
110
+ */
111
+ public function get_site_count()
112
+ {
113
+ global $wpdb;
114
+ $sql = 'SELECT COUNT(*) FROM ' . $wpdb->blogs;
115
+ return (int)$wpdb->get_var($sql);
116
+ }
117
+
118
+ public function get_columns()
119
+ {
120
+ $cols = array(
121
+ //'cb' => '<input type="checkbox" />',
122
+ //'read' => __('Read', 'wp-security-audit-log'),
123
+ 'type' => __('Code', 'wp-security-audit-log'),
124
+ 'code' => __('Type', 'wp-security-audit-log'),
125
+ 'crtd' => __('Date', 'wp-security-audit-log'),
126
+ 'user' => __('Username', 'wp-security-audit-log'),
127
+ 'scip' => __('Source IP', 'wp-security-audit-log'),
128
+ );
129
+ if ($this->is_multisite() && $this->is_main_blog() && !$this->is_specific_view()) {
130
+ $cols['site'] = __('Site', 'wp-security-audit-log');
131
+ }
132
+ $cols['mesg'] = __('Message', 'wp-security-audit-log');
133
+ if ($this->_plugin->settings->IsDataInspectorEnabled()) {
134
+ $cols['data'] = '';
135
+ }
136
+ $sel_columns = $this->_plugin->settings->GetColumnsSelected();
137
+ if (!empty($sel_columns)) {
138
+ unset($cols);
139
+ $sel_columns = (array)json_decode($sel_columns);
140
+ foreach ($sel_columns as $key => $value) {
141
+ switch ($key) {
142
+ case 'alert_code':
143
+ $cols['type'] = __('Code', 'wp-security-audit-log');
144
+ break;
145
+ case 'type':
146
+ $cols['code'] = __('Type', 'wp-security-audit-log');
147
+ break;
148
+ case 'date':
149
+ $cols['crtd'] = __('Date', 'wp-security-audit-log');
150
+ break;
151
+ case 'username':
152
+ $cols['user'] = __('Username', 'wp-security-audit-log');
153
+ break;
154
+ case 'source_ip':
155
+ $cols['scip'] = __('Source IP', 'wp-security-audit-log');
156
+ break;
157
+ case 'site':
158
+ $cols['site'] = __('Site', 'wp-security-audit-log');
159
+ break;
160
+ case 'message':
161
+ $cols['mesg'] = __('Message', 'wp-security-audit-log');
162
+ break;
163
+ }
164
+ }
165
+ }
166
+ return $cols;
167
+ }
168
+
169
+ public function column_cb($item)
170
+ {
171
+ return '<input type="checkbox" value="'.$item->id.'" '
172
+ . 'name="'.esc_attr($this->_args['singular']).'[]"/>';
173
+ }
174
+
175
+ public function get_sortable_columns()
176
+ {
177
+ return array(
178
+ 'read' => array('is_read', false),
179
+ //'code' => array('code', false),
180
+ 'type' => array('alert_id', false),
181
+ 'crtd' => array('created_on', true),
182
+ 'user' => array('user', true),
183
+ 'scip' => array('scip', false)
184
+ );
185
+ }
186
+
187
+ public function column_default($item, $column_name)
188
+ {
189
+ //example: $item->getMetaValue('CurrentUserID')
190
+
191
+ if (!$this->_plugin->settings->GetDatetimeFormat()) $datetimeFormat = 'h:i:s.$$$&\n\b\s\p;A';
192
+ else $datetimeFormat = 'H:i:s.$$$';
193
+ switch ($column_name) {
194
+ case 'read':
195
+ return '<span class="log-read log-read-'
196
+ . ($item->is_read ? 'old' : 'new')
197
+ . '" title="' . __('Click to toggle.', 'wp-security-audit-log') . '"></span>';
198
+ case 'type':
199
+ return str_pad($item->alert_id, 4, '0', STR_PAD_LEFT);
200
+ case 'code':
201
+ $code = $this->_plugin->alerts->GetAlert($item->alert_id);
202
+ $code = $code ? $code->code : 0;
203
+ $const = (object)array('name' => 'E_UNKNOWN', 'value' => 0, 'description' => __('Unknown error code.', 'wp-security-audit-log'));
204
+ $const = $this->_plugin->constants->GetConstantBy('value', $code, $const);
205
+ return '<span class="log-type log-type-' . $const->value
206
+ . '" title="' . esc_html($const->name . ': ' . $const->description) . '"></span>';
207
+ case 'crtd':
208
+ return $item->created_on ? (
209
+ str_replace(
210
+ '$$$',
211
+ substr(number_format(fmod($item->created_on + $this->_gmt_offset_sec, 1), 3), 2),
212
+ date('Y-m-d<\b\r>'.$datetimeFormat, $item->created_on + $this->_gmt_offset_sec)
213
+ )
214
+ ) : '<i>unknown</i>';
215
+ case 'user':
216
+ $username = $item->GetUsername();
217
+ if ($username && ($user = get_user_by('login', $username))) {
218
+ $image = get_avatar($user->ID, 32);
219
+ $uhtml = '<a href="' . admin_url('user-edit.php?user_id=' . $user->ID)
220
+ . '" target="_blank">' . esc_html($user->display_name) . '</a>';
221
+ $roles = $item->GetUserRoles();
222
+ if (is_array($roles) && count($roles)) {
223
+ $roles = __(esc_html(ucwords(implode(', ', $roles))));
224
+ } else if (is_string($roles) && $roles != '') {
225
+ $roles = __(esc_html(ucwords(str_replace(array("\"", "[", "]"), " ", $roles))));
226
+ } else {
227
+ $roles = '<i>' . __('Unknown', 'wp-security-audit-log') . '</i>';
228
+ }
229
+ } elseif ($username == 'Plugin') {
230
+ $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/plugin-logo.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
231
+ $uhtml = '<i>' . __('Plugin', 'wp-security-audit-log') . '</i>';
232
+ $roles = '';
233
+ } else {
234
+ $image = '<img src="'. $this->_plugin->GetBaseUrl() . '/img/wordpress-logo-32.png" class="avatar avatar-32 photo" width="32" height="32" alt=""/>';
235
+ $uhtml = '<i>' . __('System', 'wp-security-audit-log') . '</i>';
236
+ $roles = '';
237
+ }
238
+ return $image . $uhtml . '<br/>' . $roles;
239
+ case 'scip':
240
+ $scip = $item->GetSourceIP();
241
+ if (is_string($scip)) {
242
+ $scip = str_replace(array("\"", "[", "]"), "", $scip);
243
+ }
244
+ $oips = array(); //$item->GetOtherIPs();
245
+ // if there's no IP...
246
+ if (is_null($scip) || $scip == '') return '<i>unknown</i>';
247
+ // if there's only one IP...
248
+ $link = "http://whatismyipaddress.com/ip/" . $scip ."?utm_source=plugin&utm_medium=referral&utm_campaign=WPSAL";
249
+ if (count($oips) < 2) return "<a target='_blank' href='$link'>". esc_html($scip) .'</a>';
250
+ // if there are many IPs...
251
+ $html = "<a target='_blank' href='http://whatismyipaddress.com/ip/$scip'>". esc_html($scip) .'</a>'.' <a href="javascript:;" onclick="jQuery(this).hide().next().show();">(more&hellip;)</a><div style="display: none;">';
252
+ foreach ($oips as $ip) if($scip != $ip) $html .= '<div>' . $ip . '</div>';
253
+ $html .= '</div>';
254
+ return $html;
255
+ case 'site':
256
+ $info = get_blog_details($item->site_id, true);
257
+ return !$info ? ('Unknown Site '.$item->site_id)
258
+ : ('<a href="' . esc_attr($info->siteurl) . '">' . esc_html($info->blogname) . '</a>');
259
+ case 'mesg':
260
+ return '<div id="Event' . $item->id . '">' . $item->GetMessage(array($this, 'meta_formatter')) . '</div>';
261
+ case 'data':
262
+ $url = admin_url('admin-ajax.php') . '?action=AjaxInspector&amp;occurrence=' . $item->id;
263
+ return '<a class="more-info thickbox" title="' . __('Alert Data Inspector', 'wp-security-audit-log') . '"'
264
+ . ' href="' . $url . '&amp;TB_iframe=true&amp;width=600&amp;height=550">&hellip;</a>';
265
+ default:
266
+ return isset($item->$column_name)
267
+ ? esc_html($item->$column_name)
268
+ : 'Column "' . esc_html($column_name) . '" not found';
269
+ }
270
+ }
271
+
272
+ public function reorder_items_str($a, $b)
273
+ {
274
+ $result = strcmp($a->{$this->_orderby}, $b->{$this->_orderby});
275
+ return ($this->_order === 'asc') ? $result : -$result;
276
+ }
277
+
278
+ public function reorder_items_int($a, $b)
279
+ {
280
+ $result = $a->{$this->_orderby} - $b->{$this->_orderby};
281
+ return ($this->_order === 'asc') ? $result : -$result;
282
+ }
283
+
284
+ public function meta_formatter($name, $value)
285
+ {
286
+ switch (true) {
287
+ case $name == '%Message%':
288
+ return esc_html($value);
289
+
290
+ case $name == '%PromoMessage%':
291
+ return '<p class="promo-alert">' . $value .'</p>';
292
+
293
+ case $name == '%PromoLink%':
294
+ return $value;
295
+
296
+ case $name == '%MetaLink%':
297
+ if (!empty($value)) {
298
+ return "<a href=\"#\" onclick=\"WsalDisableCustom(this, '".$value."');\"> Exclude Custom Field from the Monitoring</a>";
299
+ } else {
300
+ return "";
301
+ }
302
+
303
+ case $name == '%RevisionLink%':
304
+ if (!empty($value) && $value != 'NULL') {
305
+ return ' Click <a target="_blank" href="'.$value.'">here</a> to see the content changes.';
306
+ } else {
307
+ return "";
308
+ }
309
+
310
+ case in_array($name, array('%MetaValue%', '%MetaValueOld%', '%MetaValueNew%')):
311
+ return '<strong>' . (
312
+ strlen($value) > 50 ? (esc_html(substr($value, 0, 50)) . '&hellip;') : esc_html($value)
313
+ ) . '</strong>';
314
+
315
+ case $name == '%ClientIP%':
316
+ if (is_string($value)) {
317
+ return '<strong>' . str_replace(array("\"", "[", "]"), "", $value) . '</strong>';
318
+ } else {
319
+ return '<i>unknown</i>';
320
+ }
321
+
322
+ case strncmp($value, 'http://', 7) === 0:
323
+ case strncmp($value, 'https://', 7) === 0:
324
+ return '<a href="' . esc_html($value) . '"'
325
+ . ' title="' . esc_html($value) . '"'
326
+ . ' target="_blank">'
327
+ . esc_html(parse_url($value, PHP_URL_HOST)) . '/&hellip;/'
328
+ . esc_html(basename(parse_url($value, PHP_URL_PATH)))
329
+ . '</a>';
330
+
331
+ default:
332
+ return '<strong>' . esc_html($value) . '</strong>';
333
+ }
334
+ }
335
+
336
+ protected function is_multisite()
337
+ {
338
+ return $this->_plugin->IsMultisite();
339
+ }
340
+
341
+ protected function is_main_blog()
342
+ {
343
+ return get_current_blog_id() == 1;
344
+ }
345
+
346
+ protected function is_specific_view()
347
+ {
348
+ return isset($_REQUEST['wsal-cbid']) && $_REQUEST['wsal-cbid'] != '0';
349
+ }
350
+
351
+ protected function get_specific_view()
352
+ {
353
+ return isset($_REQUEST['wsal-cbid']) ? (int)$_REQUEST['wsal-cbid'] : 0;
354
+ }
355
+
356
+ protected function get_view_site_id()
357
+ {
358
+ switch (true) {
359
+ // non-multisite
360
+ case !$this->is_multisite():
361
+ return 0;
362
+ // multisite + main site view
363
+ case $this->is_main_blog() && !$this->is_specific_view():
364
+ return 0;
365
+ // multisite + switched site view
366
+ case $this->is_main_blog() && $this->is_specific_view():
367
+ return $this->get_specific_view();
368
+ // multisite + local site view
369
+ default:
370
+ return get_current_blog_id();
371
+ }
372
+ }
373
+
374
+ public function prepare_items()
375
+ {
376
+ $per_page = $this->_plugin->settings->GetViewPerPage();
377
+
378
+ $columns = $this->get_columns();
379
+ $hidden = array();
380
+ $sortable = $this->get_sortable_columns();
381
+
382
+ $this->_column_headers = array($columns, $hidden, $sortable);
383
+
384
+ //$this->process_bulk_action();
385
+ //TO DO: Get rid of OccurrenceQuery and use the Occurence Model
386
+ $query = new WSAL_Models_OccurrenceQuery();
387
+
388
+ $bid = (int)$this->get_view_site_id();
389
+ if ($bid) {
390
+ $query->addCondition("site_id = %s ", $bid);
391
+ }
392
+
393
+ $query = apply_filters('wsal_auditlog_query', $query);
394
+
395
+ $total_items = $query->getAdapter()->Count($query);
396
+
397
+ if (empty($_REQUEST["orderby"])) {
398
+ $query->addOrderBy("created_on", true);
399
+ } else {
400
+ $orderByField = $_REQUEST["orderby"];
401
+
402
+ $isDescending = true;
403
+ if (!empty($_REQUEST['order']) && $_REQUEST["order"] == "asc") {
404
+ $isDescending = false;
405
+ }
406
+
407
+ //TO DO: Allow order by meta values
408
+ if ($orderByField == "scip") {
409
+ $query->addMetaJoin();
410
+ $query->addOrderBy('CASE WHEN meta.name = "ClientIP" THEN meta.value END', $isDescending);
411
+ } else if ($orderByField == "user") {
412
+ $query->addMetaJoin();
413
+ $query->addOrderBy('CASE WHEN meta.name = "CurrentUserID" THEN meta.value END', $isDescending);
414
+ } else {
415
+ $tmp = new WSAL_Models_Occurrence();
416
+ //Making sure the field exists to order by
417
+ if (isset($tmp->{$orderByField})) {
418
+ // TODO we used to use a custom comparator ... is it safe to let MySQL do the ordering now?
419
+ $query->addOrderBy($_REQUEST["orderby"], $isDescending);
420
+
421
+ } else {
422
+ $query->addOrderBy("created_on", true);
423
+ }
424
+ }
425
+ }
426
+
427
+ /** @todo Modify $query instead */
428
+ /** @deprecated */
429
+ //$data = array_slice($data, ($this->get_pagenum() - 1) * $per_page, $per_page);
430
+ $query->setOffset(($this->get_pagenum() - 1) * $per_page);
431
+ $query->setLimit($per_page);
432
+
433
+ $this->items = $query->getAdapter()->Execute($query);
434
+
435
+ $this->set_pagination_args(array(
436
+ 'total_items' => $total_items,
437
+ 'per_page' => $per_page,
438
+ 'total_pages' => ceil($total_items / $per_page)
439
+ ));
440
+ }
441
+
442
+ public function single_row($item)
443
+ {
444
+ if ($item->alert_id == 9999) {
445
+ echo '<tr style="background-color: #D5E46E">';
446
+ $this->single_row_columns($item);
447
+ echo '</tr>';
448
+ } else {
449
+ parent::single_row($item);
450
+ }
451
+ }
452
+ }
classes/Autoloader.php CHANGED
@@ -1,69 +1,69 @@
1
- <?php
2
-
3
- class WSAL_Autoloader {
4
- /**
5
- * @var WpSecurityAuditLog
6
- */
7
- protected $plugin;
8
-
9
- protected $paths = array();
10
-
11
- public function __construct(WpSecurityAuditLog $plugin){
12
- $this->plugin = $plugin;
13
-
14
- // register autoloader
15
- spl_autoload_register(array($this, 'LoadClass'));
16
- }
17
-
18
- public function Register($prefix, $path){
19
- if(!isset($this->paths[$prefix]))
20
- $this->paths[$prefix] = array();
21
- $this->paths[$prefix][] = rtrim(str_replace('\\', '/', $path), '/') . '/';
22
- }
23
-
24
- /**
25
- * This is the class autoloader. You should not call this directly.
26
- * @param string $class Class name.
27
- * @return boolean True if class is found and loaded, false otherwise.
28
- */
29
- public function LoadClass($class){
30
- foreach($this->paths as $prefix => $paths){
31
- foreach($paths as $path){
32
- if(strstr($class, $prefix) !== false){
33
- $file = $path . str_replace('_', DIRECTORY_SEPARATOR, substr($class, strlen($prefix))) . '.php';
34
- if(file_exists($file)){
35
- $s = $this->plugin->profiler->Start('Autoload ' . basename($file));
36
- require_once($file);
37
- $s->Stop();
38
- return class_exists($class, false) || interface_exists($class, false);
39
- }
40
- }
41
- }
42
- }
43
-
44
- return false;
45
- }
46
-
47
- /**
48
- * Returns the class name of a particular file that contains the class.
49
- * @param string $file File name.
50
- * @return string|false Class name or false on error.
51
- */
52
- public function GetClassFileClassName($file){
53
- $file = str_replace('\\', '/', $file); // win/dos hotfix
54
-
55
- foreach($this->paths as $prefix => $paths){
56
- foreach($paths as $path){
57
- if(strstr($file, $path) !== false){
58
- return str_replace(
59
- array($path, '/'),
60
- array($prefix, '_'),
61
- substr($file, 0, -4) // remove '.php'
62
- );
63
- }
64
- }
65
- }
66
-
67
- return false;
68
- }
69
- }
1
+ <?php
2
+
3
+ class WSAL_Autoloader {
4
+ /**
5
+ * @var WpSecurityAuditLog
6
+ */
7
+ protected $plugin;
8
+
9
+ protected $paths = array();
10
+
11
+ public function __construct(WpSecurityAuditLog $plugin){
12
+ $this->plugin = $plugin;
13
+
14
+ // register autoloader
15
+ spl_autoload_register(array($this, 'LoadClass'));
16
+ }
17
+
18
+ public function Register($prefix, $path){
19
+ if(!isset($this->paths[$prefix]))
20
+ $this->paths[$prefix] = array();
21
+ $this->paths[$prefix][] = rtrim(str_replace('\\', '/', $path), '/') . '/';
22
+ }
23
+
24
+ /**
25
+ * This is the class autoloader. You should not call this directly.
26
+ * @param string $class Class name.
27
+ * @return boolean True if class is found and loaded, false otherwise.
28
+ */
29
+ public function LoadClass($class){
30
+ foreach($this->paths as $prefix => $paths){
31
+ foreach($paths as $path){
32
+ if(strstr($class, $prefix) !== false){
33
+ $file = $path . str_replace('_', DIRECTORY_SEPARATOR, substr($class, strlen($prefix))) . '.php';
34
+ if(file_exists($file)){
35
+ $s = $this->plugin->profiler->Start('Autoload ' . basename($file));
36
+ require_once($file);
37
+ $s->Stop();
38
+ return class_exists($class, false) || interface_exists($class, false);
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ return false;
45
+ }
46
+
47
+ /**
48
+ * Returns the class name of a particular file that contains the class.
49
+ * @param string $file File name.
50
+ * @return string|false Class name or false on error.
51
+ */
52
+ public function GetClassFileClassName($file){
53
+ $file = str_replace('\\', '/', $file); // win/dos hotfix
54
+
55
+ foreach($this->paths as $prefix => $paths){
56
+ foreach($paths as $path){
57
+ if(strstr($file, $path) !== false){
58
+ return str_replace(
59
+ array($path, '/'),
60
+ array($prefix, '_'),
61
+ substr($file, 0, -4) // remove '.php'
62
+ );
63
+ }
64
+ }
65
+ }
66
+
67
+ return false;
68
+ }
69
+ }
classes/Connector/AbstractConnector.php CHANGED
@@ -1,36 +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
- }
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 CHANGED
@@ -1,87 +1,87 @@
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($config = null)
24
- {
25
- if (!empty($config)) {
26
- $connectionConfig = $config;
27
- } else {
28
- $connectionConfig = self::GetConfig();
29
- }
30
-
31
- //TO DO: Load connection config
32
- if (self::$connector == null || !empty($config)) {
33
- switch (strtolower($connectionConfig['type'])) {
34
- //TO DO: Add other connectors
35
- case 'mysql':
36
- default:
37
- //use config
38
- self::$connector = new WSAL_Connector_MySQLDB($connectionConfig);
39
- }
40
- }
41
- return self::$connector;
42
- }
43
-
44
- public static function GetConfig()
45
- {
46
- $conf = new WSAL_Settings(WpSecurityAuditLog::GetInstance());
47
- $type = $conf->GetAdapterConfig('adapter-type');
48
- if (empty($type)) {
49
- return null;
50
- } else {
51
- return array(
52
- 'type' => $conf->GetAdapterConfig('adapter-type'),
53
- 'user' => $conf->GetAdapterConfig('adapter-user'),
54
- 'password' => $conf->GetAdapterConfig('adapter-password'),
55
- 'name' => $conf->GetAdapterConfig('adapter-name'),
56
- 'hostname' => $conf->GetAdapterConfig('adapter-hostname'),
57
- 'base_prefix' => $conf->GetAdapterConfig('adapter-base-prefix')
58
- );
59
- }
60
- }
61
-
62
- public static function CheckConfig($type, $user, $password, $name, $hostname, $base_prefix)
63
- {
64
- $result = false;
65
- $config = self::GetConfigArray($type, $user, $password, $name, $hostname, $base_prefix);
66
- switch (strtolower($type)) {
67
- //TO DO: Add other connectors
68
- case 'mysql':
69
- default:
70
- $test = new WSAL_Connector_MySQLDB($config);
71
- $result = $test->TestConnection();
72
- }
73
- return $result;
74
- }
75
-
76
- public static function GetConfigArray($type, $user, $password, $name, $hostname, $base_prefix)
77
- {
78
- return array(
79
- 'type' => $type,
80
- 'user' => $user,
81
- 'password' => $password,
82
- 'name' => $name,
83
- 'hostname' => $hostname,
84
- 'base_prefix' => $base_prefix
85
- );
86
- }
87
- }
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($config = null)
24
+ {
25
+ if (!empty($config)) {
26
+ $connectionConfig = $config;
27
+ } else {
28
+ $connectionConfig = self::GetConfig();
29
+ }
30
+
31
+ //TO DO: Load connection config
32
+ if (self::$connector == null || !empty($config)) {
33
+ switch (strtolower($connectionConfig['type'])) {
34
+ //TO DO: Add other connectors
35
+ case 'mysql':
36
+ default:
37
+ //use config
38
+ self::$connector = new WSAL_Connector_MySQLDB($connectionConfig);
39
+ }
40
+ }
41
+ return self::$connector;
42
+ }
43
+
44
+ public static function GetConfig()
45
+ {
46
+ $conf = new WSAL_Settings(WpSecurityAuditLog::GetInstance());
47
+ $type = $conf->GetAdapterConfig('adapter-type');
48
+ if (empty($type)) {
49
+ return null;
50
+ } else {
51
+ return array(
52
+ 'type' => $conf->GetAdapterConfig('adapter-type'),
53
+ 'user' => $conf->GetAdapterConfig('adapter-user'),
54
+ 'password' => $conf->GetAdapterConfig('adapter-password'),
55
+ 'name' => $conf->GetAdapterConfig('adapter-name'),
56
+ 'hostname' => $conf->GetAdapterConfig('adapter-hostname'),
57
+ 'base_prefix' => $conf->GetAdapterConfig('adapter-base-prefix')
58
+ );
59
+ }
60
+ }
61
+
62
+ public static function CheckConfig($type, $user, $password, $name, $hostname, $base_prefix)
63
+ {
64
+ $result = false;
65
+ $config = self::GetConfigArray($type, $user, $password, $name, $hostname, $base_prefix);
66
+ switch (strtolower($type)) {
67
+ //TO DO: Add other connectors
68
+ case 'mysql':
69
+ default:
70
+ $test = new WSAL_Connector_MySQLDB($config);
71
+ $result = $test->TestConnection();
72
+ }
73
+ return $result;
74
+ }
75
+
76
+ public static function GetConfigArray($type, $user, $password, $name, $hostname, $base_prefix)
77
+ {
78
+ return array(
79
+ 'type' => $type,
80
+ 'user' => $user,
81
+ 'password' => $password,
82
+ 'name' => $name,
83
+ 'hostname' => $hostname,
84
+ 'base_prefix' => $base_prefix
85
+ );
86
+ }
87
+ }
classes/Connector/ConnectorInterface.php CHANGED
@@ -1,11 +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
- }
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 CHANGED
@@ -1,337 +1,337 @@
1
- <?php
2
- require_once('ConnectorInterface.php');
3
- require_once('AbstractConnector.php');
4
- require_once('wp-db-custom.php');
5
-
6
- class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements WSAL_Connector_ConnectorInterface
7
- {
8
- protected $connectionConfig = null;
9
-
10
- public function __construct($connectionConfig = null)
11
- {
12
- $this->connectionConfig = $connectionConfig;
13
- parent::__construct("MySQL");
14
- require_once($this->getAdaptersDirectory() . '/OptionAdapter.php');
15
- }
16
-
17
- public function TestConnection()
18
- {
19
- error_reporting(E_ALL ^ E_WARNING);
20
- $connectionConfig = $this->connectionConfig;
21
- $password = $this->decryptString($connectionConfig['password']);
22
- $newWpdb = new wpdbCustom($connectionConfig['user'], $password, $connectionConfig['name'], $connectionConfig['hostname']);
23
- if (!$newWpdb->has_connected) { // Database Error
24
- throw new Exception("Connection failed. Please check your connection details.");
25
- }
26
- }
27
-
28
- /**
29
- * Creates a connection and returns it
30
- * @return Instance of WPDB
31
- */
32
- private function createConnection()
33
- {
34
- if (!empty($this->connectionConfig)) {
35
- //TO DO: Use the provided connection config
36
- $connectionConfig = $this->connectionConfig;
37
- $password = $this->decryptString($connectionConfig['password']);
38
- $newWpdb = new wpdb($connectionConfig['user'], $password, $connectionConfig['name'], $connectionConfig['hostname']);
39
- $newWpdb->set_prefix($connectionConfig['base_prefix']);
40
- return $newWpdb;
41
- } else {
42
- global $wpdb;
43
- return $wpdb;
44
- }
45
- }
46
-
47
- /**
48
- * Returns a wpdb instance
49
- */
50
- public function getConnection()
51
- {
52
- if (!empty($this->connection)) {
53
- return $this->connection;
54
- } else {
55
- $this->connection = $this->createConnection();
56
- return $this->connection;
57
- }
58
- }
59
-
60
- /**
61
- * Gets an adapter for the specified model
62
- */
63
- public function getAdapter($class_name)
64
- {
65
- $objName = $this->getAdapterClassName($class_name);
66
- return new $objName($this->getConnection());
67
- }
68
-
69
- protected function getAdapterClassName($class_name)
70
- {
71
- return 'WSAL_Adapters_MySQL_'.$class_name;
72
- }
73
-
74
- /**
75
- * Checks if the necessary tables are available
76
- */
77
- public function isInstalled()
78
- {
79
- global $wpdb;
80
- $table = $wpdb->base_prefix . 'wsal_occurrences';
81
- return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
82
- }
83
-
84
- /**
85
- * Checks if old version tables are available
86
- */
87
- public function canMigrate()
88
- {
89
- $wpdb = $this->getConnection();
90
- $table = $wpdb->base_prefix . 'wordpress_auditlog_events';
91
- return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
92
- }
93
-
94
- /**
95
- * Install all DB tables.
96
- */
97
- public function installAll($excludeOptions = false)
98
- {
99
- $plugin = WpSecurityAuditLog::GetInstance();
100
-
101
- foreach (glob($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . '*.php') as $file) {
102
- $filePath = explode(DIRECTORY_SEPARATOR, $file);
103
- $fileName = $filePath[count($filePath) - 1];
104
- $className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
105
-
106
- $class = new $className($this->getConnection());
107
- if ($excludeOptions && $class instanceof WSAL_Adapters_MySQL_Option) {
108
- continue;
109
- }
110
-
111
- if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
112
- $class->Install();
113
- }
114
- }
115
- }
116
-
117
- /**
118
- * Uninstall all DB tables.
119
- */
120
- public function uninstallAll()
121
- {
122
- $plugin = WpSecurityAuditLog::GetInstance();
123
-
124
- foreach (glob($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . '*.php') as $file) {
125
- $filePath = explode(DIRECTORY_SEPARATOR, $file);
126
- $fileName = $filePath[count($filePath) - 1];
127
- $className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
128
-
129
- $class = new $className($this->getConnection());
130
- if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
131
- $class->Uninstall();
132
- }
133
- }
134
- }
135
-
136
- private function GetIncreaseOccurrence()
137
- {
138
- $_wpdb = $this->getConnection();
139
- $occurrenceNew = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
140
- $sql = 'SELECT MAX(id) FROM ' . $occurrenceNew->GetTable();
141
- return (int)$_wpdb->get_var($sql);
142
- }
143
-
144
- public function MigrateMeta($index, $limit)
145
- {
146
- $result = null;
147
- $offset = ($index * $limit);
148
- global $wpdb;
149
- $_wpdb = $this->getConnection();
150
- // Add +1 because an alert is generated after delete the metadata table
151
- $increase_occurrence_id = $this->GetIncreaseOccurrence() + 1;
152
-
153
- // Load data Meta from WP
154
- $meta = new WSAL_Adapters_MySQL_Meta($wpdb);
155
- if (!$meta->IsInstalled()) {
156
- $result['empty'] = true;
157
- return $result;
158
- }
159
- $sql = 'SELECT * FROM ' . $meta->GetWPTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
160
- $metadata = $wpdb->get_results($sql, ARRAY_A);
161
-
162
- // Insert data to External DB
163
- if (!empty($metadata)) {
164
- $metaNew = new WSAL_Adapters_MySQL_Meta($_wpdb);
165
-
166
- $index++;
167
- $sql = 'INSERT INTO ' . $metaNew->GetTable() . ' (occurrence_id, name, value) VALUES ' ;
168
- foreach ($metadata as $entry) {
169
- $occurrence_id = intval($entry['occurrence_id']) + $increase_occurrence_id;
170
- $sql .= '('.$occurrence_id.', \''.$entry['name'].'\', \''.str_replace("'", "\'", $entry['value']).'\'), ';
171
- }
172
- $sql = rtrim($sql, ", ");
173
- $_wpdb->query($sql);
174
-
175
- $result['complete'] = false;
176
- } else {
177
- $result['complete'] = true;
178
- $this->DeleteAfterMigrate($meta);
179
- }
180
- $result['index'] = $index;
181
- return $result;
182
- }
183
-
184
- public function MigrateOccurrence($index, $limit)
185
- {
186
- $result = null;
187
- $offset = ($index * $limit);
188
- global $wpdb;
189
- $_wpdb = $this->getConnection();
190
-
191
- // Load data Occurrences from WP
192
- $occurrence = new WSAL_Adapters_MySQL_Occurrence($wpdb);
193
- if (!$occurrence->IsInstalled()) {
194
- $result['empty'] = true;
195
- return $result;
196
- }
197
- $sql = 'SELECT * FROM ' . $occurrence->GetWPTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
198
- $occurrences = $wpdb->get_results($sql, ARRAY_A);
199
-
200
- // Insert data to External DB
201
- if (!empty($occurrences)) {
202
- $occurrenceNew = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
203
-
204
- $index++;
205
- $sql = 'INSERT INTO ' . $occurrenceNew->GetTable() . ' (site_id, alert_id, created_on, is_read) VALUES ' ;
206
- foreach ($occurrences as $entry) {
207
- $sql .= '('.$entry['site_id'].', '.$entry['alert_id'].', '.$entry['created_on'].', '.$entry['is_read'].'), ';
208
- }
209
- $sql = rtrim($sql, ", ");
210
- $_wpdb->query($sql);
211
-
212
- $result['complete'] = false;
213
- } else {
214
- $result['complete'] = true;
215
- $this->DeleteAfterMigrate($occurrence);
216
- }
217
- $result['index'] = $index;
218
- return $result;
219
- }
220
-
221
- public function MigrateBackOccurrence($index, $limit)
222
- {
223
- $result = null;
224
- $offset = ($index * $limit);
225
- global $wpdb;
226
- $_wpdb = $this->getConnection();
227
-
228
- // Load data Occurrences from External DB
229
- $occurrence = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
230
- if (!$occurrence->IsInstalled()) {
231
- $result['empty'] = true;
232
- return $result;
233
- }
234
- $sql = 'SELECT * FROM ' . $occurrence->GetTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
235
- $occurrences = $_wpdb->get_results($sql, ARRAY_A);
236
-
237
- // Insert data to WP
238
- if (!empty($occurrences)) {
239
- $occurrenceWP = new WSAL_Adapters_MySQL_Occurrence($wpdb);
240
-
241
- $index++;
242
- $sql = 'INSERT INTO ' . $occurrenceWP->GetWPTable() . ' (id, site_id, alert_id, created_on, is_read) VALUES ' ;
243
- foreach ($occurrences as $entry) {
244
- $sql .= '('.$entry['id'].', '.$entry['site_id'].', '.$entry['alert_id'].', '.$entry['created_on'].', '.$entry['is_read'].'), ';
245
- }
246
- $sql = rtrim($sql, ", ");
247
- $wpdb->query($sql);
248
-
249
- $result['complete'] = false;
250
- } else {
251
- $result['complete'] = true;
252
- }
253
- $result['index'] = $index;
254
- return $result;
255
- }
256
-
257
- public function MigrateBackMeta($index, $limit)
258
- {
259
- $result = null;
260
- $offset = ($index * $limit);
261
- global $wpdb;
262
- $_wpdb = $this->getConnection();
263
-
264
- // Load data Meta from External DB
265
- $meta = new WSAL_Adapters_MySQL_Meta($_wpdb);
266
- if (!$meta->IsInstalled()) {
267
- $result['empty'] = true;
268
- return $result;
269
- }
270
- $sql = 'SELECT * FROM ' . $meta->GetTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
271
- $metadata = $_wpdb->get_results($sql, ARRAY_A);
272
-
273
- // Insert data to WP
274
- if (!empty($metadata)) {
275
- $metaWP = new WSAL_Adapters_MySQL_Meta($wpdb);
276
-
277
- $index++;
278
- $sql = 'INSERT INTO ' . $metaWP->GetWPTable() . ' (occurrence_id, name, value) VALUES ' ;
279
- foreach ($metadata as $entry) {
280
- $sql .= '('.$entry['occurrence_id'].', \''.$entry['name'].'\', \''.str_replace("'", "\'", $entry['value']).'\'), ';
281
- }
282
- $sql = rtrim($sql, ", ");
283
- $wpdb->query($sql);
284
-
285
- $result['complete'] = false;
286
- } else {
287
- $result['complete'] = true;
288
- }
289
- $result['index'] = $index;
290
- return $result;
291
- }
292
-
293
- private function DeleteAfterMigrate($record)
294
- {
295
- global $wpdb;
296
- $sql = 'DROP TABLE IF EXISTS ' . $record->GetTable();
297
- $wpdb->query($sql);
298
- }
299
-
300
- public function encryptString($plaintext)
301
- {
302
- $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
303
- $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
304
- $key = $this->truncateKey();
305
- $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
306
- $ciphertext = $iv . $ciphertext;
307
- $ciphertext_base64 = base64_encode($ciphertext);
308
-
309
- return $ciphertext_base64;
310
- }
311
-
312
- private function decryptString($ciphertext_base64)
313
- {
314
- $ciphertext_dec = base64_decode($ciphertext_base64);
315
- $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
316
-
317
- $iv_dec = substr($ciphertext_dec, 0, $iv_size);
318
- $ciphertext_dec = substr($ciphertext_dec, $iv_size);
319
- $key = $this->truncateKey();
320
- $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
321
-
322
- return rtrim($plaintext_dec, "\0");
323
- }
324
-
325
- private function truncateKey()
326
- {
327
- if (!defined('AUTH_KEY')) {
328
- return 'x4>Tg@G-Kr6a]o-eJeP^?UO)KW;LbV)I';
329
- }
330
- $key_size = strlen(AUTH_KEY);
331
- if ($key_size > 32) {
332
- return substr(AUTH_KEY, 0, 32);
333
- } else {
334
- return AUTH_KEY;
335
- }
336
- }
337
- }
1
+ <?php
2
+ require_once('ConnectorInterface.php');
3
+ require_once('AbstractConnector.php');
4
+ require_once('wp-db-custom.php');
5
+
6
+ class WSAL_Connector_MySQLDB extends WSAL_Connector_AbstractConnector implements WSAL_Connector_ConnectorInterface
7
+ {
8
+ protected $connectionConfig = null;
9
+
10
+ public function __construct($connectionConfig = null)
11
+ {
12
+ $this->connectionConfig = $connectionConfig;
13
+ parent::__construct("MySQL");
14
+ require_once($this->getAdaptersDirectory() . '/OptionAdapter.php');
15
+ }
16
+
17
+ public function TestConnection()
18
+ {
19
+ error_reporting(E_ALL ^ E_WARNING);
20
+ $connectionConfig = $this->connectionConfig;
21
+ $password = $this->decryptString($connectionConfig['password']);
22
+ $newWpdb = new wpdbCustom($connectionConfig['user'], $password, $connectionConfig['name'], $connectionConfig['hostname']);
23
+ if (!$newWpdb->has_connected) { // Database Error
24
+ throw new Exception("Connection failed. Please check your connection details.");
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Creates a connection and returns it
30
+ * @return Instance of WPDB
31
+ */
32
+ private function createConnection()
33
+ {
34
+ if (!empty($this->connectionConfig)) {
35
+ //TO DO: Use the provided connection config
36
+ $connectionConfig = $this->connectionConfig;
37
+ $password = $this->decryptString($connectionConfig['password']);
38
+ $newWpdb = new wpdb($connectionConfig['user'], $password, $connectionConfig['name'], $connectionConfig['hostname']);
39
+ $newWpdb->set_prefix($connectionConfig['base_prefix']);
40
+ return $newWpdb;
41
+ } else {
42
+ global $wpdb;
43
+ return $wpdb;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Returns a wpdb instance
49
+ */
50
+ public function getConnection()
51
+ {
52
+ if (!empty($this->connection)) {
53
+ return $this->connection;
54
+ } else {
55
+ $this->connection = $this->createConnection();
56
+ return $this->connection;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Gets an adapter for the specified model
62
+ */
63
+ public function getAdapter($class_name)
64
+ {
65
+ $objName = $this->getAdapterClassName($class_name);
66
+ return new $objName($this->getConnection());
67
+ }
68
+
69
+ protected function getAdapterClassName($class_name)
70
+ {
71
+ return 'WSAL_Adapters_MySQL_'.$class_name;
72
+ }
73
+
74
+ /**
75
+ * Checks if the necessary tables are available
76
+ */
77
+ public function isInstalled()
78
+ {
79
+ global $wpdb;
80
+ $table = $wpdb->base_prefix . 'wsal_occurrences';
81
+ return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
82
+ }
83
+
84
+ /**
85
+ * Checks if old version tables are available
86
+ */
87
+ public function canMigrate()
88
+ {
89
+ $wpdb = $this->getConnection();
90
+ $table = $wpdb->base_prefix . 'wordpress_auditlog_events';
91
+ return ($wpdb->get_var('SHOW TABLES LIKE "'.$table.'"') == $table);
92
+ }
93
+
94
+ /**
95
+ * Install all DB tables.
96
+ */
97
+ public function installAll($excludeOptions = false)
98
+ {
99
+ $plugin = WpSecurityAuditLog::GetInstance();
100
+
101
+ foreach (glob($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . '*.php') as $file) {
102
+ $filePath = explode(DIRECTORY_SEPARATOR, $file);
103
+ $fileName = $filePath[count($filePath) - 1];
104
+ $className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
105
+
106
+ $class = new $className($this->getConnection());
107
+ if ($excludeOptions && $class instanceof WSAL_Adapters_MySQL_Option) {
108
+ continue;
109
+ }
110
+
111
+ if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
112
+ $class->Install();
113
+ }
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Uninstall all DB tables.
119
+ */
120
+ public function uninstallAll()
121
+ {
122
+ $plugin = WpSecurityAuditLog::GetInstance();
123
+
124
+ foreach (glob($this->getAdaptersDirectory() . DIRECTORY_SEPARATOR . '*.php') as $file) {
125
+ $filePath = explode(DIRECTORY_SEPARATOR, $file);
126
+ $fileName = $filePath[count($filePath) - 1];
127
+ $className = $this->getAdapterClassName(str_replace("Adapter.php", "", $fileName));
128
+
129
+ $class = new $className($this->getConnection());
130
+ if (is_subclass_of($class, "WSAL_Adapters_MySQL_ActiveRecord")) {
131
+ $class->Uninstall();
132
+ }
133
+ }
134
+ }
135
+
136
+ private function GetIncreaseOccurrence()
137
+ {
138
+ $_wpdb = $this->getConnection();
139
+ $occurrenceNew = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
140
+ $sql = 'SELECT MAX(id) FROM ' . $occurrenceNew->GetTable();
141
+ return (int)$_wpdb->get_var($sql);
142
+ }
143
+
144
+ public function MigrateMeta($index, $limit)
145
+ {
146
+ $result = null;
147
+ $offset = ($index * $limit);
148
+ global $wpdb;
149
+ $_wpdb = $this->getConnection();
150
+ // Add +1 because an alert is generated after delete the metadata table
151
+ $increase_occurrence_id = $this->GetIncreaseOccurrence() + 1;
152
+
153
+ // Load data Meta from WP
154
+ $meta = new WSAL_Adapters_MySQL_Meta($wpdb);
155
+ if (!$meta->IsInstalled()) {
156
+ $result['empty'] = true;
157
+ return $result;
158
+ }
159
+ $sql = 'SELECT * FROM ' . $meta->GetWPTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
160
+ $metadata = $wpdb->get_results($sql, ARRAY_A);
161
+
162
+ // Insert data to External DB
163
+ if (!empty($metadata)) {
164
+ $metaNew = new WSAL_Adapters_MySQL_Meta($_wpdb);
165
+
166
+ $index++;
167
+ $sql = 'INSERT INTO ' . $metaNew->GetTable() . ' (occurrence_id, name, value) VALUES ' ;
168
+ foreach ($metadata as $entry) {
169
+ $occurrence_id = intval($entry['occurrence_id']) + $increase_occurrence_id;
170
+ $sql .= '('.$occurrence_id.', \''.$entry['name'].'\', \''.str_replace("'", "\'", $entry['value']).'\'), ';
171
+ }
172
+ $sql = rtrim($sql, ", ");
173
+ $_wpdb->query($sql);
174
+
175
+ $result['complete'] = false;
176
+ } else {
177
+ $result['complete'] = true;
178
+ $this->DeleteAfterMigrate($meta);
179
+ }
180
+ $result['index'] = $index;
181
+ return $result;
182
+ }
183
+
184
+ public function MigrateOccurrence($index, $limit)
185
+ {
186
+ $result = null;
187
+ $offset = ($index * $limit);
188
+ global $wpdb;
189
+ $_wpdb = $this->getConnection();
190
+
191
+ // Load data Occurrences from WP
192
+ $occurrence = new WSAL_Adapters_MySQL_Occurrence($wpdb);
193
+ if (!$occurrence->IsInstalled()) {
194
+ $result['empty'] = true;
195
+ return $result;
196
+ }
197
+ $sql = 'SELECT * FROM ' . $occurrence->GetWPTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
198
+ $occurrences = $wpdb->get_results($sql, ARRAY_A);
199
+
200
+ // Insert data to External DB
201
+ if (!empty($occurrences)) {
202
+ $occurrenceNew = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
203
+
204
+ $index++;
205
+ $sql = 'INSERT INTO ' . $occurrenceNew->GetTable() . ' (site_id, alert_id, created_on, is_read) VALUES ' ;
206
+ foreach ($occurrences as $entry) {
207
+ $sql .= '('.$entry['site_id'].', '.$entry['alert_id'].', '.$entry['created_on'].', '.$entry['is_read'].'), ';
208
+ }
209
+ $sql = rtrim($sql, ", ");
210
+ $_wpdb->query($sql);
211
+
212
+ $result['complete'] = false;
213
+ } else {
214
+ $result['complete'] = true;
215
+ $this->DeleteAfterMigrate($occurrence);
216
+ }
217
+ $result['index'] = $index;
218
+ return $result;
219
+ }
220
+
221
+ public function MigrateBackOccurrence($index, $limit)
222
+ {
223
+ $result = null;
224
+ $offset = ($index * $limit);
225
+ global $wpdb;
226
+ $_wpdb = $this->getConnection();
227
+
228
+ // Load data Occurrences from External DB
229
+ $occurrence = new WSAL_Adapters_MySQL_Occurrence($_wpdb);
230
+ if (!$occurrence->IsInstalled()) {
231
+ $result['empty'] = true;
232
+ return $result;
233
+ }
234
+ $sql = 'SELECT * FROM ' . $occurrence->GetTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
235
+ $occurrences = $_wpdb->get_results($sql, ARRAY_A);
236
+
237
+ // Insert data to WP
238
+ if (!empty($occurrences)) {
239
+ $occurrenceWP = new WSAL_Adapters_MySQL_Occurrence($wpdb);
240
+
241
+ $index++;
242
+ $sql = 'INSERT INTO ' . $occurrenceWP->GetWPTable() . ' (id, site_id, alert_id, created_on, is_read) VALUES ' ;
243
+ foreach ($occurrences as $entry) {
244
+ $sql .= '('.$entry['id'].', '.$entry['site_id'].', '.$entry['alert_id'].', '.$entry['created_on'].', '.$entry['is_read'].'), ';
245
+ }
246
+ $sql = rtrim($sql, ", ");
247
+ $wpdb->query($sql);
248
+
249
+ $result['complete'] = false;
250
+ } else {
251
+ $result['complete'] = true;
252
+ }
253
+ $result['index'] = $index;
254
+ return $result;
255
+ }
256
+
257
+ public function MigrateBackMeta($index, $limit)
258
+ {
259
+ $result = null;
260
+ $offset = ($index * $limit);
261
+ global $wpdb;
262
+ $_wpdb = $this->getConnection();
263
+
264
+ // Load data Meta from External DB
265
+ $meta = new WSAL_Adapters_MySQL_Meta($_wpdb);
266
+ if (!$meta->IsInstalled()) {
267
+ $result['empty'] = true;
268
+ return $result;
269
+ }
270
+ $sql = 'SELECT * FROM ' . $meta->GetTable() . ' LIMIT ' . $limit . ' OFFSET '. $offset;
271
+ $metadata = $_wpdb->get_results($sql, ARRAY_A);
272
+
273
+ // Insert data to WP
274
+ if (!empty($metadata)) {
275
+ $metaWP = new WSAL_Adapters_MySQL_Meta($wpdb);
276
+
277
+ $index++;
278
+ $sql = 'INSERT INTO ' . $metaWP->GetWPTable() . ' (occurrence_id, name, value) VALUES ' ;
279
+ foreach ($metadata as $entry) {
280
+ $sql .= '('.$entry['occurrence_id'].', \''.$entry['name'].'\', \''.str_replace("'", "\'", $entry['value']).'\'), ';
281
+ }
282
+ $sql = rtrim($sql, ", ");
283
+ $wpdb->query($sql);
284
+
285
+ $result['complete'] = false;
286
+ } else {
287
+ $result['complete'] = true;
288
+ }
289
+ $result['index'] = $index;
290
+ return $result;
291
+ }
292
+
293
+ private function DeleteAfterMigrate($record)
294
+ {
295
+ global $wpdb;
296
+ $sql = 'DROP TABLE IF EXISTS ' . $record->GetTable();
297
+ $wpdb->query($sql);
298
+ }
299
+
300
+ public function encryptString($plaintext)
301
+ {
302
+ $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
303
+ $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
304
+ $key = $this->truncateKey();
305
+ $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
306
+ $ciphertext = $iv . $ciphertext;
307
+ $ciphertext_base64 = base64_encode($ciphertext);
308
+
309
+ return $ciphertext_base64;
310
+ }
311
+
312
+ private function decryptString($ciphertext_base64)
313
+ {
314
+ $ciphertext_dec = base64_decode($ciphertext_base64);
315
+ $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
316
+
317
+ $iv_dec = substr($ciphertext_dec, 0, $iv_size);
318
+ $ciphertext_dec = substr($ciphertext_dec, $iv_size);
319
+ $key = $this->truncateKey();
320
+ $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
321
+
322
+ return rtrim($plaintext_dec, "\0");
323
+ }
324
+
325
+ private function truncateKey()
326
+ {
327
+ if (!defined('AUTH_KEY')) {
328
+ return 'x4>Tg@G-Kr6a]o-eJeP^?UO)KW;LbV)I';
329
+ }
330
+ $key_size = strlen(AUTH_KEY);
331
+ if ($key_size > 32) {
332
+ return substr(AUTH_KEY, 0, 32);
333
+ } else {
334
+ return AUTH_KEY;
335
+ }
336
+ }
337
+ }
classes/Connector/wp-db-custom.php CHANGED
@@ -1,36 +1,36 @@
1
- <?php
2
-
3
- class wpdbCustom extends wpdb
4
- {
5
- /*
6
- * overwrite wpdb class for set $allow_bail to false
7
- * and hide the print of the error
8
- */
9
- public function __construct($dbuser, $dbpassword, $dbname, $dbhost)
10
- {
11
- register_shutdown_function(array($this, '__destruct'));
12
- if (WP_DEBUG && WP_DEBUG_DISPLAY) {
13
- $this->show_errors();
14
- }
15
- if (function_exists('mysqli_connect')) {
16
- if (defined('WP_USE_EXT_MYSQL')) {
17
- $this->use_mysqli = ! WP_USE_EXT_MYSQL;
18
- } elseif (version_compare(phpversion(), '5.5', '>=') || !function_exists('mysql_connect')) {
19
- $this->use_mysqli = true;
20
- } elseif (false !== strpos($GLOBALS['wp_version'], '-')) {
21
- $this->use_mysqli = true;
22
- }
23
- }
24
- $this->dbuser = $dbuser;
25
- $this->dbpassword = $dbpassword;
26
- $this->dbname = $dbname;
27
- $this->dbhost = $dbhost;
28
- // wp-config.php creation will manually connect when ready.
29
- if (defined('WP_SETUP_CONFIG')) {
30
- return;
31
- }
32
-
33
- $this->db_connect(false);
34
- }
35
-
36
- }
1
+ <?php
2
+
3
+ class wpdbCustom extends wpdb
4
+ {
5
+ /*
6
+ * overwrite wpdb class for set $allow_bail to false
7
+ * and hide the print of the error
8
+ */
9
+ public function __construct($dbuser, $dbpassword, $dbname, $dbhost)
10
+ {
11
+ register_shutdown_function(array($this, '__destruct'));
12
+ if (WP_DEBUG && WP_DEBUG_DISPLAY) {
13
+ $this->show_errors();
14
+ }
15
+ if (function_exists('mysqli_connect')) {
16
+ if (defined('WP_USE_EXT_MYSQL')) {
17
+ $this->use_mysqli = ! WP_USE_EXT_MYSQL;
18
+ } elseif (version_compare(phpversion(), '5.5', '>=') || !function_exists('mysql_connect')) {
19
+ $this->use_mysqli = true;
20
+ } elseif (false !== strpos($GLOBALS['wp_version'], '-')) {
21
+ $this->use_mysqli = true;
22
+ }
23
+ }
24
+ $this->dbuser = $dbuser;
25
+ $this->dbpassword = $dbpassword;
26
+ $this->dbname = $dbname;
27
+ $this->dbhost = $dbhost;
28
+ // wp-config.php creation will manually connect when ready.
29
+ if (defined('WP_SETUP_CONFIG')) {
30
+ return;
31
+ }
32
+
33
+ $this->db_connect(false);
34
+ }
35
+
36
+ }
classes/ConstantManager.php CHANGED
@@ -1,89 +1,89 @@
1
- <?php
2
-
3
- class WSAL_ConstantManager {
4
-
5
- protected $_constants = array();
6
-
7
- /**
8
- * Use an existing PHP constant.
9
- * @param string $name Constant name.
10
- * @param string $description Constant description.
11
- */
12
- public function UseConstant($name, $description = ''){
13
- $this->_constants[] = (object)array(
14
- 'name' => $name,
15
- 'value' => constant($name),
16
- 'description' => $description,
17
- );
18
- }
19
-
20
- /**
21
- * Add new PHP constant.
22
- * @param string $name Constant name.
23
- * @param integer|string $value Constant value.
24
- * @param string $description Constant description.
25
- */
26
- public function AddConstant($name, $value, $description = ''){
27
-
28
- // check for constant conflict and define new one if required
29
- if(defined($name) && constant($name) !== $value){
30
- throw new Exception('Constant already defined with a different value.');
31
- }else{
32
- define($name, $value);
33
- }
34
-
35
- // add constant to da list.
36
- $this->UseConstant($name, $description);
37
-
38
- }
39
-
40
- /**
41
- * Add multiple constants in one go.
42
- * @param array $items Array of arrays with name, value, description pairs.
43
- */
44
- public function AddConstants($items){
45
- foreach($items as $item)
46
- $this->AddConstant(
47
- $item['name'],
48
- $item['value'],
49
- $item['description']
50
- );
51
- }
52
-
53
- /**
54
- * Use multiple constants in one go.
55
- * @param array $items Array of arrays with name, description pairs.
56
- */
57
- public function UseConstants($items){
58
- foreach($items as $item)
59
- $this->UseConstant(
60
- $item['name'],
61
- $item['description']
62
- );
63
- }
64
-
65
- /**
66
- * Get constant details by a particular detail.
67
- * @param string $what The type of detail: 'name', 'value'
68
- * @param mixed $value The detail expected value.
69
- * @return mixed Either constant details (props: name, value, description) or $default if not found.
70
- */
71
- public function GetConstantBy($what, $value, $default = null){
72
-
73
- // make sure we do have some constants...
74
- if(count($this->_constants)){
75
-
76
- // make sure that constants do have a $what property
77
- if(!isset($this->_constants[0]->$what))
78
- throw new Exception('Unexpected detail type "' . $what . '".');
79
-
80
- // return constant match the property value
81
- foreach($this->_constants as $constant)
82
- if($constant->$what == $value)
83
- return $constant;
84
-
85
- }
86
-
87
- return $default;
88
- }
89
  }
1
+ <?php
2
+
3
+ class WSAL_ConstantManager {
4
+
5
+ protected $_constants = array();
6
+
7
+ /**
8
+ * Use an existing PHP constant.
9
+ * @param string $name Constant name.
10
+ * @param string $description Constant description.
11
+ */
12
+ public function UseConstant($name, $description = ''){
13
+ $this->_constants[] = (object)array(
14
+ 'name' => $name,
15
+ 'value' => constant($name),
16
+ 'description' => $description,
17
+ );
18
+ }
19
+
20
+ /**
21
+ * Add new PHP constant.
22
+ * @param string $name Constant name.
23
+ * @param integer|string $value Constant value.
24
+ * @param string $description Constant description.
25
+ */
26
+ public function AddConstant($name, $value, $description = ''){
27
+
28
+ // check for constant conflict and define new one if required
29
+ if(defined($name) && constant($name) !== $value){
30
+ throw new Exception('Constant already defined with a different value.');
31
+ }else{
32
+ define($name, $value);
33
+ }
34
+
35
+ // add constant to da list.
36
+ $this->UseConstant($name, $description);
37
+
38
+ }
39
+
40
+ /**
41
+ * Add multiple constants in one go.
42
+ * @param array $items Array of arrays with name, value, description pairs.
43
+ */
44
+ public function AddConstants($items){
45
+ foreach($items as $item)
46
+ $this->AddConstant(
47
+ $item['name'],
48
+ $item['value'],
49
+ $item['description']
50
+ );
51
+ }
52
+
53
+ /**
54
+ * Use multiple constants in one go.
55
+ * @param array $items Array of arrays with name, description pairs.
56
+ */
57
+ public function UseConstants($items){
58
+ foreach($items as $item)
59
+ $this->UseConstant(
60
+ $item['name'],
61
+ $item['description']
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Get constant details by a particular detail.
67
+ * @param string $what The type of detail: 'name', 'value'
68
+ * @param mixed $value The detail expected value.
69
+ * @return mixed Either constant details (props: name, value, description) or $default if not found.
70
+ */
71
+ public function GetConstantBy($what, $value, $default = null){
72
+
73
+ // make sure we do have some constants...
74
+ if(count($this->_constants)){
75
+
76
+ // make sure that constants do have a $what property
77
+ if(!isset($this->_constants[0]->$what))
78
+ throw new Exception('Unexpected detail type "' . $what . '".');
79
+
80
+ // return constant match the property value
81
+ foreach($this->_constants as $constant)
82
+ if($constant->$what == $value)
83
+ return $constant;
84
+
85
+ }
86
+
87
+ return $default;
88
+ }
89
  }
classes/EDD_SL_Plugin_Updater.php CHANGED
@@ -1,170 +1,170 @@
1
- <?php
2
-
3
- // uncomment this line for testing
4
- //set_site_transient( 'update_plugins', null );
5
-
6
- /**
7
- * Allows plugins to use their own update API.
8
- *
9
- * @author Pippin Williamson
10
- * @version 1.2
11
- */
12
- class EDD_SL_Plugin_Updater {
13
- private $api_url = '';
14
- private $api_data = array();
15
- private $name = '';
16
- private $slug = '';
17
- private $do_check = false;
18
-
19
- /**
20
- * Class constructor.
21
- *
22
- * @uses plugin_basename()
23
- * @uses hook()
24
- *
25
- * @param string $_api_url The URL pointing to the custom API endpoint.
26
- * @param string $_plugin_file Path to the plugin file.
27
- * @param array $_api_data Optional data to send with API calls.
28
- * @return void
29
- */
30
- function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
31
- $this->api_url = trailingslashit( $_api_url );
32
- $this->api_data = urlencode_deep( $_api_data );
33
- $this->name = plugin_basename( $_plugin_file );
34
- $this->slug = basename( $_plugin_file, '.php');
35
- $this->version = $_api_data['version'];
36
-
37
- // Set up hooks.
38
- $this->hook();
39
- }
40
-
41
- /**
42
- * Set up WordPress filters to hook into WP's update process.
43
- *
44
- * @uses add_filter()
45
- *
46
- * @return void
47
- */
48
- private function hook() {
49
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins_filter' ) );
50
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
51
- add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
52
- }
53
-
54
- /**
55
- * Check for Updates at the defined API endpoint and modify the update array.
56
- *
57
- * This function dives into the update API just when WordPress creates its update array,
58
- * then adds a custom API call and injects the custom plugin data retrieved from the API.
59
- * It is reassembled from parts of the native WordPress plugin update code.
60
- * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
61
- *
62
- * @uses api_request()
63
- *
64
- * @param array $_transient_data Update array build by WordPress.
65
- * @return array Modified update array with custom plugin data.
66
- */
67
- function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
68
-
69
- if( empty( $_transient_data ) || ! $this->do_check ) {
70
-
71
- // This ensures that the custom API request only runs on the second time that WP fires the update check
72
- $this->do_check = true;
73
-
74
- return $_transient_data;
75
- }
76
-
77
- $to_send = array( 'slug' => $this->slug );
78
-
79
- $api_response = $this->api_request( 'plugin_latest_version', $to_send );
80
-
81
- if( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
82
-
83
- if( version_compare( $this->version, $api_response->new_version, '<' ) ) {
84
- $_transient_data->response[$this->name] = $api_response;
85
- }
86
- }
87
- return $_transient_data;
88
- }
89
-
90
-
91
- /**
92
- * Updates information on the "View version x.x details" page with custom data.
93
- *
94
- * @uses api_request()
95
- *
96
- * @param mixed $_data
97
- * @param string $_action
98
- * @param object $_args
99
- * @return object $_data
100
- */
101
- function plugins_api_filter( $_data, $_action = '', $_args = null ) {
102
- if ( ( $_action != 'plugin_information' ) || !isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) return $_data;
103
-
104
- $to_send = array( 'slug' => $this->slug );
105
-
106
- $api_response = $this->api_request( 'plugin_information', $to_send );
107
- if ( false !== $api_response ) $_data = $api_response;
108
-
109
- return $_data;
110
- }
111
-
112
-
113
- /**
114
- * Disable SSL verification in order to prevent download update failures
115
- *
116
- * @param array $args
117
- * @param string $url
118
- * @return object $array
119
- */
120
- function http_request_args( $args, $url ) {
121
- // If it is an https request and we are performing a package download, disable ssl verification
122
- if( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
123
- $args['sslverify'] = false;
124
- }
125
- return $args;
126
- }
127
-
128
- /**
129
- * Calls the API and, if successfull, returns the object delivered by the API.
130
- *
131
- * @uses get_bloginfo()
132
- * @uses wp_remote_post()
133
- * @uses is_wp_error()
134
- *
135
- * @param string $_action The requested action.
136
- * @param array $_data Parameters for the API action.
137
- * @return false||object
138
- */
139
- private function api_request( $_action, $_data ) {
140
-
141
- global $wp_version;
142
-
143
- $data = array_merge( $this->api_data, $_data );
144
-
145
- if( $data['slug'] != $this->slug )
146
- return;
147
-
148
- if( empty( $data['license'] ) )
149
- return;
150
-
151
- $api_params = array(
152
- 'edd_action' => 'get_version',
153
- 'license' => $data['license'],
154
- 'name' => $data['item_name'],
155
- 'slug' => $this->slug,
156
- 'author' => $data['author'],
157
- 'url' => home_url()
158
- );
159
- $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
160
-
161
- if ( ! is_wp_error( $request ) ):
162
- $request = json_decode( wp_remote_retrieve_body( $request ) );
163
- if( $request && isset( $request->sections ) )
164
- $request->sections = maybe_unserialize( $request->sections );
165
- return $request;
166
- else:
167
- return false;
168
- endif;
169
- }
170
- }
1
+ <?php
2
+
3
+ // uncomment this line for testing
4
+ //set_site_transient( 'update_plugins', null );
5
+
6
+ /**
7
+ * Allows plugins to use their own update API.
8
+ *
9
+ * @author Pippin Williamson
10
+ * @version 1.2
11
+ */
12
+ class EDD_SL_Plugin_Updater {
13
+ private $api_url = '';
14
+ private $api_data = array();
15
+ private $name = '';
16
+ private $slug = '';
17
+ private $do_check = false;
18
+
19
+ /**
20
+ * Class constructor.
21
+ *
22
+ * @uses plugin_basename()
23
+ * @uses hook()
24
+ *
25
+ * @param string $_api_url The URL pointing to the custom API endpoint.
26
+ * @param string $_plugin_file Path to the plugin file.
27
+ * @param array $_api_data Optional data to send with API calls.
28
+ * @return void
29
+ */
30
+ function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
31
+ $this->api_url = trailingslashit( $_api_url );
32
+ $this->api_data = urlencode_deep( $_api_data );
33
+ $this->name = plugin_basename( $_plugin_file );
34
+ $this->slug = basename( $_plugin_file, '.php');
35
+ $this->version = $_api_data['version'];
36
+
37
+ // Set up hooks.
38
+ $this->hook();
39
+ }
40
+
41
+ /**
42
+ * Set up WordPress filters to hook into WP's update process.
43
+ *
44
+ * @uses add_filter()
45
+ *
46
+ * @return void
47
+ */
48
+ private function hook() {
49
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins_filter' ) );
50
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
51
+ add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
52
+ }
53
+
54
+ /**
55
+ * Check for Updates at the defined API endpoint and modify the update array.
56
+ *
57
+ * This function dives into the update API just when WordPress creates its update array,
58
+ * then adds a custom API call and injects the custom plugin data retrieved from the API.
59
+ * It is reassembled from parts of the native WordPress plugin update code.
60
+ * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
61
+ *
62
+ * @uses api_request()
63
+ *
64
+ * @param array $_transient_data Update array build by WordPress.
65
+ * @return array Modified update array with custom plugin data.
66
+ */
67
+ function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
68
+
69
+ if( empty( $_transient_data ) || ! $this->do_check ) {
70
+
71
+ // This ensures that the custom API request only runs on the second time that WP fires the update check
72
+ $this->do_check = true;
73
+
74
+ return $_transient_data;
75
+ }
76
+
77
+ $to_send = array( 'slug' => $this->slug );
78
+
79
+ $api_response = $this->api_request( 'plugin_latest_version', $to_send );
80
+
81
+ if( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
82
+
83
+ if( version_compare( $this->version, $api_response->new_version, '<' ) ) {
84
+ $_transient_data->response[$this->name] = $api_response;
85
+ }
86
+ }
87
+ return $_transient_data;
88
+ }
89
+
90
+
91
+ /**
92
+ * Updates information on the "View version x.x details" page with custom data.
93
+ *
94
+ * @uses api_request()
95
+ *
96
+ * @param mixed $_data
97
+ * @param string $_action
98
+ * @param object $_args
99
+ * @return object $_data
100
+ */
101
+ function plugins_api_filter( $_data, $_action = '', $_args = null ) {
102
+ if ( ( $_action != 'plugin_information' ) || !isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) return $_data;
103
+
104
+ $to_send = array( 'slug' => $this->slug );
105
+
106
+ $api_response = $this->api_request( 'plugin_information', $to_send );
107
+ if ( false !== $api_response ) $_data = $api_response;
108
+
109
+ return $_data;
110
+ }
111
+
112
+
113
+ /**
114
+ * Disable SSL verification in order to prevent download update failures
115
+ *
116
+ * @param array $args
117
+ * @param string $url
118
+ * @return object $array
119
+ */
120
+ function http_request_args( $args, $url ) {
121
+ // If it is an https request and we are performing a package download, disable ssl verification
122
+ if( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
123
+ $args['sslverify'] = false;
124
+ }
125
+ return $args;
126
+ }
127
+
128
+ /**
129
+ * Calls the API and, if successfull, returns the object delivered by the API.
130
+ *
131
+ * @uses get_bloginfo()
132
+ * @uses wp_remote_post()
133
+ * @uses is_wp_error()
134
+ *
135
+ * @param string $_action The requested action.
136
+ * @param array $_data Parameters for the API action.
137
+ * @return false||object
138
+ */
139
+ private function api_request( $_action, $_data ) {
140
+
141
+ global $wp_version;
142
+
143
+ $data = array_merge( $this->api_data, $_data );
144
+
145
+ if( $data['slug'] != $this->slug )
146
+ return;
147
+
148
+ if( empty( $data['license'] ) )
149
+ return;
150
+
151
+ $api_params = array(
152
+ 'edd_action' => 'get_version',
153
+ 'license' => $data['license'],
154
+ 'name' => $data['item_name'],
155
+ 'slug' => $this->slug,
156
+ 'author' => $data['author'],
157
+ 'url' => home_url()
158
+ );
159
+ $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
160
+
161
+ if ( ! is_wp_error( $request ) ):
162
+ $request = json_decode( wp_remote_retrieve_body( $request ) );
163
+ if( $request && isset( $request->sections ) )
164
+ $request->sections = maybe_unserialize( $request->sections );
165
+ return $request;
166
+ else:
167
+ return false;
168
+ endif;
169
+ }
170
+ }
classes/Helpers/DataHelper.php CHANGED
@@ -1,23 +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
  }
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/LicenseManager.php CHANGED
@@ -1,171 +1,171 @@
1
- <?php
2
-
3
- // since other plugins might use this class
4
- if(!class_exists('EDD_SL_Plugin_Updater')){
5
- require_once('EDD_SL_Plugin_Updater.php');
6
- }
7
-
8
- class WSAL_LicenseManager {
9
- /**
10
- * @var WpSecurityAuditLog
11
- */
12
- protected $plugin;
13
-
14
- protected $plugins = array();
15
-
16
- public function __construct(WpSecurityAuditLog $plugin){
17
- $this->plugin = $plugin;
18
- add_action('plugins_loaded', array($this, 'LoadPlugins'));
19
- }
20
-
21
- protected function GetStoreUrl(){
22
- return 'http://www.wpsecurityauditlog.com/';
23
- }
24
-
25
- public function CountPlugins(){
26
- return count($this->plugins);
27
- }
28
-
29
- public function Plugins(){
30
- return $this->plugins;
31
- }
32
-
33
- public function LoadPlugins(){
34
- foreach(apply_filters('wsal_register', array()) as $pluginFile)
35
- $this->AddPremiumPlugin($pluginFile);
36
- }
37
-
38
- protected function GetPluginData($pluginFile, $license){
39
- // A hack since get_plugin_data() is not available now
40
- $pluginData = get_file_data($pluginFile, array(
41
- 'Name' => 'Plugin Name',
42
- 'PluginURI' => 'Plugin URI',
43
- 'Version' => 'Version',
44
- 'Description' => 'Description',
45
- 'Author' => 'Author',
46
- 'TextDomain' => 'Text Domain',
47
- 'DomainPath' => 'Domain Path',
48
- ), 'plugin' );
49
-
50
- $pluginUpdater = is_null($license)
51
- ? null
52
- : new EDD_SL_Plugin_Updater(
53
- $this->GetStoreUrl(),
54
- $pluginFile,
55
- array(
56
- 'license' => $license,
57
- 'item_name' => $pluginData['Name'],
58
- 'author' => $pluginData['Author'],
59
- 'version' => $pluginData['Version'],
60
- )
61
- );
62
-
63
- return array(
64
- 'PluginData' => $pluginData,
65
- 'EddUpdater' => $pluginUpdater,
66
- );
67
- }
68
-
69
- public function AddPremiumPlugin($pluginFile){
70
- $name = sanitize_key(basename($pluginFile));
71
- $license = $this->plugin->settings->GetLicenseKey($name);
72
- $this->plugins[$name] = $this->GetPluginData($pluginFile, $license);
73
- }
74
-
75
- public function AddPlugin($pluginFile){
76
- $name = sanitize_key(basename($pluginFile));
77
- $this->plugins[$name] = $this->GetPluginData($pluginFile, null);
78
- }
79
-
80
- protected function GetBlogIds(){
81
- global $wpdb;
82
- $sql = 'SELECT blog_id FROM ' . $wpdb->blogs;
83
- return $wpdb->get_col($sql);
84
- }
85
-
86
- public function ActivateLicense($name, $license){
87
- $this->plugin->settings->SetLicenseKey($name, $license);
88
-
89
- $plugins = $this->Plugins();
90
- $api_params = array(
91
- 'edd_action'=> 'activate_license',
92
- 'license' => urlencode($license),
93
- 'item_name' => urlencode($plugins[$name]['PluginData']['Name']),
94
- 'url' => urlencode(home_url()),
95
- );
96
-
97
- $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
98
-
99
- foreach($blog_ids as $blog_id){
100
-
101
- if($this->plugin->IsMultisite())
102
- $api_params['url'] = urlencode(get_home_url($blog_id));
103
-
104
- $response = wp_remote_get(
105
- esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
106
- array('timeout' => 15, 'sslverify' => false)
107
- );
108
-
109
- if (is_wp_error($response)) {
110
- $this->plugin->settings->SetLicenseErrors($name, 'Invalid Licensing Server Response: ' . $response->get_error_message());
111
- $this->DeactivateLicense($name, $license);
112
- return false;
113
- }
114
-
115
- $license_data = json_decode(wp_remote_retrieve_body($response));
116
-
117
- if(is_object($license_data)){
118
- $this->plugin->settings->SetLicenseStatus($name, $license_data->license);
119
- if($license_data->license !== 'valid'){
120
- $error = 'License Not Valid';
121
- if (isset($license_data->error)) $error .= ': ' . ucfirst(str_replace('_', ' ', $license_data->error));
122
- $this->plugin->settings->SetLicenseErrors($name, $error);
123
- $this->DeactivateLicense($name, $license);
124
- return false;
125
- }
126
- }else{
127
- $this->plugin->settings->SetLicenseErrors($name, 'Unexpected Licensing Server Response');
128
- $this->DeactivateLicense($name, $license);
129
- return false;
130
- }
131
- }
132
-
133
- return true;
134
- }
135
-
136
- public function IsLicenseValid($name){
137
- return trim(strtolower($this->plugin->settings->GetLicenseStatus($name))) === 'valid';
138
- }
139
-
140
- public function DeactivateLicense($name, $license = null){
141
- $this->plugin->settings->SetLicenseStatus($name, '');
142
-
143
- // deactivate it on the server (if license was given)
144
- if(!is_null($license)){
145
- $plugins = $this->Plugins();
146
- $api_params = array(
147
- 'edd_action'=> 'deactivate_license',
148
- 'license' => urlencode($license),
149
- 'item_name' => urlencode($plugins[$name]['PluginData']['Name']),
150
- 'url' => urlencode(home_url()),
151
- );
152
-
153
- $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
154
-
155
- foreach($blog_ids as $blog_id){
156
-
157
- if($this->plugin->IsMultisite())
158
- $api_params['url'] = urlencode(get_home_url($blog_id));
159
-
160
- $response = wp_remote_get(
161
- esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
162
- array('timeout' => 15, 'sslverify' => false)
163
- );
164
-
165
- if (is_wp_error($response)) return false;
166
-
167
- wp_remote_retrieve_body($response);
168
- }
169
- }
170
- }
171
- }
1
+ <?php
2
+
3
+ // since other plugins might use this class
4
+ if(!class_exists('EDD_SL_Plugin_Updater')){
5
+ require_once('EDD_SL_Plugin_Updater.php');
6
+ }
7
+
8
+ class WSAL_LicenseManager {
9
+ /**
10
+ * @var WpSecurityAuditLog
11
+ */
12
+ protected $plugin;
13
+
14
+ protected $plugins = array();
15
+
16
+ public function __construct(WpSecurityAuditLog $plugin){
17
+ $this->plugin = $plugin;
18
+ add_action('plugins_loaded', array($this, 'LoadPlugins'));
19
+ }
20
+
21
+ protected function GetStoreUrl(){
22
+ return 'http://www.wpsecurityauditlog.com/';
23
+ }
24
+
25
+ public function CountPlugins(){
26
+ return count($this->plugins);
27
+ }
28
+
29
+ public function Plugins(){
30
+ return $this->plugins;
31
+ }
32
+
33
+ public function LoadPlugins(){
34
+ foreach(apply_filters('wsal_register', array()) as $pluginFile)
35
+ $this->AddPremiumPlugin($pluginFile);
36
+ }
37
+
38
+ protected function GetPluginData($pluginFile, $license){
39
+ // A hack since get_plugin_data() is not available now
40
+ $pluginData = get_file_data($pluginFile, array(
41
+ 'Name' => 'Plugin Name',
42
+ 'PluginURI' => 'Plugin URI',
43
+ 'Version' => 'Version',
44
+ 'Description' => 'Description',
45
+ 'Author' => 'Author',
46
+ 'TextDomain' => 'Text Domain',
47
+ 'DomainPath' => 'Domain Path',
48
+ ), 'plugin' );
49
+
50
+ $pluginUpdater = is_null($license)
51
+ ? null
52
+ : new EDD_SL_Plugin_Updater(
53
+ $this->GetStoreUrl(),
54
+ $pluginFile,
55
+ array(
56
+ 'license' => $license,
57
+ 'item_name' => $pluginData['Name'],
58
+ 'author' => $pluginData['Author'],
59
+ 'version' => $pluginData['Version'],
60
+ )
61
+ );
62
+
63
+ return array(
64
+ 'PluginData' => $pluginData,
65
+ 'EddUpdater' => $pluginUpdater,
66
+ );
67
+ }
68
+
69
+ public function AddPremiumPlugin($pluginFile){
70
+ $name = sanitize_key(basename($pluginFile));
71
+ $license = $this->plugin->settings->GetLicenseKey($name);
72
+ $this->plugins[$name] = $this->GetPluginData($pluginFile, $license);
73
+ }
74
+
75
+ public function AddPlugin($pluginFile){
76
+ $name = sanitize_key(basename($pluginFile));
77
+ $this->plugins[$name] = $this->GetPluginData($pluginFile, null);
78
+ }
79
+
80
+ protected function GetBlogIds(){
81
+ global $wpdb;
82
+ $sql = 'SELECT blog_id FROM ' . $wpdb->blogs;
83
+ return $wpdb->get_col($sql);
84
+ }
85
+
86
+ public function ActivateLicense($name, $license){
87
+ $this->plugin->settings->SetLicenseKey($name, $license);
88
+
89
+ $plugins = $this->Plugins();
90
+ $api_params = array(
91
+ 'edd_action'=> 'activate_license',
92
+ 'license' => urlencode($license),
93
+ 'item_name' => urlencode($plugins[$name]['PluginData']['Name']),
94
+ 'url' => urlencode(home_url()),
95
+ );
96
+
97
+ $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
98
+
99
+ foreach($blog_ids as $blog_id){
100
+
101
+ if($this->plugin->IsMultisite())
102
+ $api_params['url'] = urlencode(get_home_url($blog_id));
103
+
104
+ $response = wp_remote_get(
105
+ esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
106
+ array('timeout' => 15, 'sslverify' => false)
107
+ );
108
+
109
+ if (is_wp_error($response)) {
110
+ $this->plugin->settings->SetLicenseErrors($name, 'Invalid Licensing Server Response: ' . $response->get_error_message());
111
+ $this->DeactivateLicense($name, $license);
112
+ return false;
113
+ }
114
+
115
+ $license_data = json_decode(wp_remote_retrieve_body($response));
116
+
117
+ if(is_object($license_data)){
118
+ $this->plugin->settings->SetLicenseStatus($name, $license_data->license);
119
+ if($license_data->license !== 'valid'){
120
+ $error = 'License Not Valid';
121
+ if (isset($license_data->error)) $error .= ': ' . ucfirst(str_replace('_', ' ', $license_data->error));
122
+ $this->plugin->settings->SetLicenseErrors($name, $error);
123
+ $this->DeactivateLicense($name, $license);
124
+ return false;
125
+ }
126
+ }else{
127
+ $this->plugin->settings->SetLicenseErrors($name, 'Unexpected Licensing Server Response');
128
+ $this->DeactivateLicense($name, $license);
129
+ return false;
130
+ }
131
+ }
132
+
133
+ return true;
134
+ }
135
+
136
+ public function IsLicenseValid($name){
137
+ return trim(strtolower($this->plugin->settings->GetLicenseStatus($name))) === 'valid';
138
+ }
139
+
140
+ public function DeactivateLicense($name, $license = null){
141
+ $this->plugin->settings->SetLicenseStatus($name, '');
142
+
143
+ // deactivate it on the server (if license was given)
144
+ if(!is_null($license)){
145
+ $plugins = $this->Plugins();
146
+ $api_params = array(
147
+ 'edd_action'=> 'deactivate_license',
148
+ 'license' => urlencode($license),
149
+ 'item_name' => urlencode($plugins[$name]['PluginData']['Name']),
150
+ 'url' => urlencode(home_url()),
151
+ );
152
+
153
+ $blog_ids = $this->plugin->IsMultisite() ? $this->GetBlogIds() : array(1);
154
+
155
+ foreach($blog_ids as $blog_id){
156
+
157
+ if($this->plugin->IsMultisite())
158
+ $api_params['url'] = urlencode(get_home_url($blog_id));
159
+
160
+ $response = wp_remote_get(
161
+ esc_url_raw(add_query_arg($api_params, $this->GetStoreUrl())),
162
+ array('timeout' => 15, 'sslverify' => false)
163
+ );
164
+
165
+ if (is_wp_error($response)) return false;
166
+
167
+ wp_remote_retrieve_body($response);
168
+ }
169
+ }
170
+ }
171
+ }
classes/Models/ActiveRecord.php CHANGED
@@ -1,267 +1,280 @@
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
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
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 $this->is_ip_address($val):
106
+ $this->$key = (string)$val;
107
+ break;
108
+ case is_array($copy->$key):
109
+ case is_object($copy->$key):
110
+ $jsonDecodedVal = WSAL_Helpers_DataHelper::JsonDecode($val);
111
+ $this->$key = ($jsonDecodedVal == null) ? $val : $jsonDecodedVal;
112
+ break;
113
+ case is_int($copy->$key):
114
+ $this->$key = (int)$val;
115
+ break;
116
+ case is_float($copy->$key):
117
+ $this->$key = (float)$val;
118
+ break;
119
+ case is_bool($copy->$key):
120
+ $this->$key = (bool)$val;
121
+ break;
122
+ case is_string($copy->$key):
123
+ $this->$key = (string)$val;
124
+ break;
125
+ default:
126
+ throw new Exception('Unsupported type "'.gettype($copy->$key).'"');
127
+ }
128
+ }
129
+ }
130
+ return $this;
131
+ }
132
+
133
+ /**
134
+ * Save this active record
135
+ * @return integer|boolean Either the number of modified/inserted rows or false on failure.
136
+ */
137
+ public function Save()
138
+ {
139
+ $this->_state = self::STATE_UNKNOWN;
140
+
141
+ // use today's date if not set up
142
+ if (is_null($this->created_on)) {
143
+ $this->created_on = $this->GetMicrotime();
144
+ }
145
+ $updateId = $this->getId();
146
+ $result = $this->getAdapter()->Save($this);
147
+
148
+ if ($result !== false) {
149
+ $this->_state = (!empty($updateId))?self::STATE_UPDATED:self::STATE_CREATED;
150
+ }
151
+ return $result;
152
+ }
153
+
154
+ /**
155
+ * Deletes this active record
156
+ */
157
+ public function Delete()
158
+ {
159
+ $this->_state = self::STATE_UNKNOWN;
160
+ $result = $this->getAdapter()->Delete($this);
161
+ if($result !== false)
162
+ $this->_state = self::STATE_DELETED;
163
+
164
+ return $result;
165
+ }
166
+
167
+ public function Count($cond = '%d', $args = array(1)) {
168
+ $result = $this->getAdapter()->Count($cond, $args);
169
+ return $result;
170
+ }
171
+
172
+ /**
173
+ * @return boolean
174
+ */
175
+ public function IsLoaded(){
176
+ return $this->_state == self::STATE_LOADED;
177
+ }
178
+
179
+ /**
180
+ * @return boolean
181
+ */
182
+ public function IsSaved(){
183
+ return $this->_state == self::STATE_CREATED
184
+ || $this->_state == self::STATE_UPDATED;
185
+ }
186
+
187
+ /**
188
+ * @return boolean
189
+ */
190
+ public function IsCreated(){
191
+ return $this->_state == self::STATE_CREATED;
192
+ }
193
+
194
+ /**
195
+ * @return boolean
196
+ */
197
+ public function IsUpdated()
198
+ {
199
+ return $this->_state == self::STATE_UPDATED;
200
+ }
201
+
202
+ /**
203
+ * @return boolean
204
+ */
205
+ public function IsInstalled()
206
+ {
207
+ return $this->getAdapter()->IsInstalled();
208
+ }
209
+
210
+ public function Install()
211
+ {
212
+ return $this->getAdapter()->Install();
213
+ }
214
+
215
+ /**
216
+ * @return boolean
217
+ */
218
+ public function IsDeleted()
219
+ {
220
+ return $this->_state == self::STATE_DELETED;
221
+ }
222
+
223
+ protected static $_cache = array();
224
+
225
+ /**
226
+ * Load ActiveRecord from DB or cache.
227
+ * @param string $target ActiveRecord class name.
228
+ * @param string $query Load condition.
229
+ * @param array $args Arguments used in condition.
230
+ * @return WSAL_Models_ActiveRecord
231
+ */
232
+ protected static function CacheLoad($target, $query, $args){
233
+ $index = $target . '::' . vsprintf($query, $args);
234
+ if(!isset(self::$_cache[$index])){
235
+ self::$_cache[$index] = new $target();
236
+ self::$_cache[$index]->Load($query, $args);
237
+ }
238
+ return self::$_cache[$index];
239
+ }
240
+
241
+ /**
242
+ * Remove ActiveRecord cache.
243
+ * @param string $target ActiveRecord class name.
244
+ * @param string $query Load condition.
245
+ * @param array $args Arguments used in condition.
246
+ */
247
+ protected static function CacheRemove($target, $query, $args){
248
+ $index = $target . '::' . sprintf($query, $args);
249
+ if(!isset(self::$_cache[$index])){
250
+ unset(self::$_cache[$index]);
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Clear the cache.
256
+ */
257
+ protected static function CacheClear()
258
+ {
259
+ self::$_cache = array();
260
+ }
261
+
262
+ /**
263
+ * Function used in WSAL reporting extension
264
+ */
265
+ public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp)
266
+ {
267
+ return $this->getAdapter()->GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp);
268
+ }
269
+
270
+ /**
271
+ * Check if the float is IPv4 instead
272
+ */
273
+ private function is_ip_address($ip_address)
274
+ {
275
+ if (filter_var($ip_address, FILTER_VALIDATE_IP) !== false) {
276
+ return true;
277
+ }
278
+ return false;
279
+ }
280
+ }
classes/Models/Adapters/ActiveRecordInterface.php CHANGED
@@ -1,15 +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
- }
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 CHANGED
@@ -1,13 +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
- }
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 CHANGED
@@ -1,448 +1,448 @@
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
- $_wpdb = $this->connection;
35
- return $_wpdb->base_prefix . $this->_table;
36
- }
37
-
38
- /**
39
- * Used for WordPress prefix
40
- * @return string Returns table name of WordPress.
41
- */
42
- public function GetWPTable()
43
- {
44
- global $wpdb;
45
- return $wpdb->base_prefix . $this->_table;
46
- }
47
-
48
- /**
49
- * @return string SQL table options (constraints, foreign keys, indexes etc).
50
- */
51
- protected function GetTableOptions()
52
- {
53
- return ' PRIMARY KEY (' . $this->_idkey . ')';
54
- }
55
-
56
- /**
57
- * @return array Returns this records' columns.
58
- */
59
- public function GetColumns()
60
- {
61
- $model = $this->GetModel();
62
-
63
- if (!isset($this->_column_cache)) {
64
- $this->_column_cache = array();
65
- foreach (array_keys(get_object_vars($model)) as $col)
66
- if (trim($col) && $col[0] != '_')
67
- $this->_column_cache[] = $col;
68
- }
69
- return $this->_column_cache;
70
- }
71
-
72
- /**
73
- * @deprecated
74
- * @return boolean Returns whether table structure is installed or not.
75
- */
76
- public function IsInstalled(){
77
- //global $wpdb;
78
- $_wpdb = $this->connection;
79
- $sql = 'SHOW TABLES LIKE "' . $this->GetTable() . '"';
80
- return strtolower($_wpdb->get_var($sql)) == strtolower($this->GetTable());
81
- }
82
-
83
- /**
84
- * Install this ActiveRecord structure into DB.
85
- */
86
- public function Install(){
87
- $_wpdb = $this->connection;
88
- $_wpdb->query($this->_GetInstallQuery());
89
- }
90
-
91
- /**
92
- * Install this ActiveRecord structure into DB WordPress.
93
- */
94
- public function InstallOriginal(){
95
- global $wpdb;
96
- $wpdb->query($this->_GetInstallQuery(true));
97
- }
98
-
99
- /**
100
- * Remove this ActiveRecord structure into DB.
101
- */
102
- public function Uninstall()
103
- {
104
- //global $wpdb;
105
- $_wpdb = $this->connection;
106
- $_wpdb->query($this->_GetUninstallQuery());
107
- }
108
-
109
- /**
110
- * Save an active record to DB.
111
- * @return integer|boolean Either the number of modified/inserted rows or false on failure.
112
- */
113
- public function Save($activeRecord)
114
- {
115
- //global $wpdb;
116
- $_wpdb = $this->connection;
117
- $copy = $activeRecord;
118
- $data = array();
119
- $format = array();
120
-
121
- foreach ($this->GetColumns() as $index => $key) {
122
- if ($key == $this->_idkey) {
123
- $_idIndex = $index;
124
- }
125
-
126
- $val = $copy->$key;
127
- $deffmt = '%s';
128
- if (is_int($copy->$key)) {
129
- $deffmt = '%d';
130
- }
131
- if (is_float($copy->$key)) {
132
- $deffmt = '%f';
133
- }
134
- if (is_array($copy->$key) || is_object($copy->$key)) {
135
- $data[$key] = WSAL_Helpers_DataHelper::JsonEncode($val);
136
- } else {
137
- $data[$key] = $val;
138
- }
139
- $format[] = $deffmt;
140
- }
141
-
142
- if (isset($data[$this->_idkey]) && empty($data[$this->_idkey])) {
143
- unset($data[$this->_idkey]);
144
- unset($format[$_idIndex]);
145
- }
146
-
147
- $result = $_wpdb->replace($this->GetTable(), $data, $format);
148
-
149
- if ($result !== false) {
150
- if ($_wpdb->insert_id) {
151
- $copy->setId($_wpdb->insert_id);
152
- }
153
- }
154
- return $result;
155
- }
156
-
157
- /**
158
- * Load record from DB.
159
- * @param string $cond (Optional) Load condition.
160
- * @param array $args (Optional) Load condition arguments.
161
- */
162
- public function Load($cond = '%d', $args = array(1))
163
- {
164
- //global $wpdb;
165
- $_wpdb = $this->connection;
166
-
167
- $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
168
- $data = $_wpdb->get_row($sql, ARRAY_A);
169
-
170
- return $data;
171
- }
172
-
173
- public function LoadArray($cond, $args = array())
174
- {
175
- //global $wpdb;
176
- $_wpdb = $this->connection;
177
- $result = array();
178
- $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
179
- foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
180
- $result[] = $this->getModel()->LoadData($data);
181
- }
182
- return $result;
183
- }
184
-
185
- /**
186
- * Delete DB record.
187
- * @return int|boolean Either the amount of deleted rows or False on error.
188
- */
189
- public function Delete($activeRecord)
190
- {
191
- //global $wpdb;
192
- $_wpdb = $this->connection;
193
- $result = $_wpdb->delete(
194
- $this->GetTable(),
195
- $activeRecord->getId()
196
- );
197
- return $result;
198
- }
199
-
200
- /**
201
- * Delete records in DB matching a query.
202
- * @param string $query Full SQL query.
203
- * @param array $args (Optional) Query arguments.
204
- */
205
- public function DeleteQuery($query, $args = array())
206
- {
207
- $_wpdb = $this->connection;
208
- $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
209
- $result = $_wpdb->query($sql);
210
- return $result;
211
- }
212
-
213
- /**
214
- * Load multiple records from DB.
215
- * @param string $cond (Optional) Load condition (eg: 'some_id = %d' ).
216
- * @param array $args (Optional) Load condition arguments (rg: array(45) ).
217
- * @return self[] List of loaded records.
218
- */
219
- public function LoadMulti($cond, $args = array())
220
- {
221
- //global $wpdb;
222
- $_wpdb = $this->connection;
223
- $result = array();
224
- $sql = (!is_array($args) || !count($args)) // do we really need to prepare() or not?
225
- ? ($cond)
226
- : $_wpdb->prepare($cond, $args)
227
- ;
228
- foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
229
- $result[] = $this->getModel()->LoadData($data);
230
- }
231
- return $result;
232
-
233
- }
234
-
235
- /**
236
- * Load multiple records from DB and call a callback for each record.
237
- * This function is very memory-efficient, it doesn't load records in bulk.
238
- * @param callable $callback The callback to invoke.
239
- * @param string $cond (Optional) Load condition.
240
- * @param array $args (Optional) Load condition arguments.
241
- */
242
- public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1))
243
- {
244
- //global $wpdb;
245
- $_wpdb = $this->connection;
246
- $class = get_called_class();
247
- $sql = $_wpdb->prepare('SELECT * FROM ' . $this->GetTable() . ' WHERE '.$cond, $args);
248
- foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
249
- call_user_func($callback, new $class($data));
250
- }
251
- }
252
-
253
- /**
254
- * Count records in the DB matching a condition.
255
- * If no parameters are given, this counts the number of records in the DB table.
256
- * @param string $cond (Optional) Query condition.
257
- * @param array $args (Optional) Condition arguments.
258
- * @return int Number of matching records.
259
- */
260
- public function Count($cond = '%d', $args = array(1))
261
- {
262
- //global $wpdb;
263
- $_wpdb = $this->connection;
264
- $class = get_called_class();
265
- $sql = $_wpdb->prepare('SELECT COUNT(*) FROM ' . $this->GetTable() . ' WHERE ' . $cond, $args);
266
- return (int)$_wpdb->get_var($sql);
267
- }
268
-
269
- /**
270
- * Count records in the DB matching a query.
271
- * @param string $query Full SQL query.
272
- * @param array $args (Optional) Query arguments.
273
- * @return int Number of matching records.
274
- */
275
- public function CountQuery($query, $args = array())
276
- {
277
- //global $wpdb;
278
- $_wpdb = $this->connection;
279
- $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
280
- return (int)$_wpdb->get_var($sql);
281
- }
282
-
283
- /**
284
- * Similar to LoadMulti but allows the use of a full SQL query.
285
- * @param string $query Full SQL query.
286
- * @param array $args (Optional) Query arguments.
287
- * @return self[] List of loaded records.
288
- */
289
- public function LoadMultiQuery($query, $args = array())
290
- {
291
- //global $wpdb;
292
- $_wpdb = $this->connection;
293
- $class = get_called_class();
294
- $result = array();
295
- $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
296
- foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
297
- $result[] = $this->getModel()->LoadData($data);
298
- }
299
- return $result;
300
- }
301
-
302
- /**
303
- * @return string Must return SQL for creating table.
304
- */
305
- protected function _GetInstallQuery($prefix = false)
306
- {
307
- $_wpdb = $this->connection;
308
-
309
- $class = get_class($this);
310
- $copy = new $class($this->connection);
311
- $table_name = ($prefix) ? $this->GetWPTable() : $this->GetTable();
312
- $sql = 'CREATE TABLE IF NOT EXISTS ' . $table_name . ' (' . PHP_EOL;
313
-
314
- foreach ($this->GetColumns() as $key) {
315
- $sql .= ' ';
316
- switch (true) {
317
- case $key == $copy->_idkey:
318
- $sql .= $key . ' BIGINT NOT NULL AUTO_INCREMENT,' . PHP_EOL;
319
- break;
320
- case is_integer($copy->$key):
321
- $sql .= $key . ' BIGINT NOT NULL,' . PHP_EOL;
322
- break;
323
- case is_float($copy->$key):
324
- $sql .= $key . ' DOUBLE NOT NULL,' . PHP_EOL;
325
- break;
326
- case is_string($copy->$key):
327
- $maxlength = $key . '_maxlength';
328
- if (property_exists($class, $maxlength)) {
329
- $sql .= $key . ' VARCHAR(' . intval($class::$$maxlength) . ') NOT NULL,' . PHP_EOL;
330
- } else {
331
- $sql .= $key . ' TEXT NOT NULL,' . PHP_EOL;
332
- }
333
- break;
334
- case is_bool($copy->$key):
335
- $sql .= $key . ' BIT NOT NULL,' . PHP_EOL;
336
- break;
337
- case is_array($copy->$key):
338
- case is_object($copy->$key):
339
- $sql .= $key . ' LONGTEXT NOT NULL,' . PHP_EOL;
340
- break;
341
- }
342
- }
343
-
344
- $sql .= $this->GetTableOptions() . PHP_EOL;
345
-
346
- $sql .= ')';
347
-
348
- if (! empty($_wpdb->charset)) {
349
- $sql .= ' DEFAULT CHARACTER SET ' . $_wpdb->charset;
350
- }
351
-
352
- return $sql;
353
-
354
- }
355
-
356
- /**
357
- * @return string Must return SQL for removing table (at a minimum, it should be ` 'DROP TABLE ' . $this->_table `).
358
- */
359
- protected function _GetUninstallQuery()
360
- {
361
- return 'DROP TABLE ' . $this->GetTable();
362
- }
363
-
364
- /**
365
- * Function used in WSAL reporting extension
366
- */
367
- public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp, $_nextDate = null, $_limit = 0)
368
- {
369
- global $wpdb;
370
- $tableUsers = $wpdb->users;
371
- $_wpdb = $this->connection;
372
- // tables
373
- $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
374
- $tableMeta = $meta->GetTable(); // metadata
375
- $occurrence = new WSAL_Adapters_MySQL_Occurrence($this->connection);
376
- $tableOcc = $occurrence->GetTable(); // occurrences
377
-
378
- $user_names = '0';
379
- if (!empty($_userId) && $_userId != "null") {
380
- $sql = 'SELECT user_login FROM '.$tableUsers.' WHERE find_in_set(ID, @userId) > 0';
381
- $wpdb->query("SET @userId = $_userId");
382
- $result = $wpdb->get_results($sql, ARRAY_A);
383
- $aUsers = array();
384
- foreach ($result as $item) {
385
- $aUsers[] = '"'.$item['user_login'].'"';
386
- }
387
- $user_names = implode(', ', $aUsers);
388
- }
389
- $conditionDate = !empty($_nextDate) ? ' AND occ.created_on < '.$_nextDate : '';
390
-
391
- $sql = "SELECT DISTINCT
392
- occ.id,
393
- occ.alert_id,
394
- occ.site_id,
395
- occ.created_on,
396
- replace(replace(replace((
397
- SELECT t1.value FROM $tableMeta AS t1 WHERE t1.name = 'CurrentUserRoles' AND t1.occurrence_id = occ.id), '[', ''), ']', ''), '\\'', '') AS roles,
398
- (SELECT replace(t2.value, '\"','') FROM $tableMeta as t2 WHERE t2.name = 'ClientIP' AND t2.occurrence_id = occ.id) AS ip,
399
- (SELECT replace(t3.value, '\"', '') FROM $tableMeta as t3 WHERE t3.name = 'UserAgent' AND t3.occurrence_id = occ.id) AS ua,
400
- COALESCE(
401
- (SELECT replace(t4.value, '\"', '') FROM $tableMeta as t4 WHERE t4.name = 'Username' AND t4.occurrence_id = occ.id),
402
- (SELECT replace(t5.value, '\"', '') FROM $tableMeta as t5 WHERE t5.name = 'CurrentUserID' AND t5.occurrence_id = occ.id)
403
- ) as user_id
404
- FROM $tableOcc AS occ
405
- JOIN $tableMeta AS meta ON meta.occurrence_id = occ.id
406
- WHERE
407
- (@siteId is NULL OR find_in_set(occ.site_id, @siteId) > 0)
408
- AND (@userId is NULL OR (
409
- (meta.name = 'CurrentUserID' AND find_in_set(meta.value, @userId) > 0)
410
- OR (meta.name = 'Username' AND replace(meta.value, '\"', '') IN ($user_names))
411
- ))
412
- AND (@roleName is NULL OR (meta.name = 'CurrentUserRoles'
413
- AND replace(replace(replace(meta.value, ']', ''), '[', ''), '\\'', '') REGEXP @roleName
414
- ))
415
- AND (@alertCode is NULL OR find_in_set(occ.alert_id, @alertCode) > 0)
416
- AND (@startTimestamp is NULL OR occ.created_on >= @startTimestamp)
417
- AND (@endTimestamp is NULL OR occ.created_on <= @endTimestamp)
418
- {$conditionDate}
419
- ORDER BY
420
- created_on DESC
421
- ";
422
-
423
- $_wpdb->query("SET @siteId = $_siteId");
424
- $_wpdb->query("SET @userId = $_userId");
425
- $_wpdb->query("SET @roleName = $_roleName");
426
- $_wpdb->query("SET @alertCode = $_alertCode");
427
- $_wpdb->query("SET @startTimestamp = $_startTimestamp");
428
- $_wpdb->query("SET @endTimestamp = $_endTimestamp");
429
-
430
- if (!empty($_limit)) {
431
- $sql .= " LIMIT {$_limit}";
432
- }
433
- $results = $_wpdb->get_results($sql);
434
-
435
- foreach ($results as $row) {
436
- $sql = "SELECT t6.ID FROM $tableUsers AS t6 WHERE t6.user_login = \"$row->user_id\"";
437
- $userId = $wpdb->get_var($sql);
438
- if ($userId == null) {
439
- $sql = "SELECT t4.ID FROM $tableUsers AS t4 WHERE t4.ID = \"$row->user_id\"";
440
- $userId = $wpdb->get_var($sql);
441
- }
442
- $row->user_id = $userId;
443
- $results['lastDate'] = $row->created_on;
444
- }
445
-
446
- return $results;
447
- }
448
- }
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
+ $_wpdb = $this->connection;
35
+ return $_wpdb->base_prefix . $this->_table;
36
+ }
37
+
38
+ /**
39
+ * Used for WordPress prefix
40
+ * @return string Returns table name of WordPress.
41
+ */
42
+ public function GetWPTable()
43
+ {
44
+ global $wpdb;
45
+ return $wpdb->base_prefix . $this->_table;
46
+ }
47
+
48
+ /**
49
+ * @return string SQL table options (constraints, foreign keys, indexes etc).
50
+ */
51
+ protected function GetTableOptions()
52
+ {
53
+ return ' PRIMARY KEY (' . $this->_idkey . ')';
54
+ }
55
+
56
+ /**
57
+ * @return array Returns this records' columns.
58
+ */
59
+ public function GetColumns()
60
+ {
61
+ $model = $this->GetModel();
62
+
63
+ if (!isset($this->_column_cache)) {
64
+ $this->_column_cache = array();
65
+ foreach (array_keys(get_object_vars($model)) as $col)
66
+ if (trim($col) && $col[0] != '_')
67
+ $this->_column_cache[] = $col;
68
+ }
69
+ return $this->_column_cache;
70
+ }
71
+
72
+ /**
73
+ * @deprecated
74
+ * @return boolean Returns whether table structure is installed or not.
75
+ */
76
+ public function IsInstalled(){
77
+ //global $wpdb;
78
+ $_wpdb = $this->connection;
79
+ $sql = 'SHOW TABLES LIKE "' . $this->GetTable() . '"';
80
+ return strtolower($_wpdb->get_var($sql)) == strtolower($this->GetTable());
81
+ }
82
+
83
+ /**
84
+ * Install this ActiveRecord structure into DB.
85
+ */
86
+ public function Install(){
87
+ $_wpdb = $this->connection;
88
+ $_wpdb->query($this->_GetInstallQuery());
89
+ }
90
+
91
+ /**
92
+ * Install this ActiveRecord structure into DB WordPress.
93
+ */
94
+ public function InstallOriginal(){
95
+ global $wpdb;
96
+ $wpdb->query($this->_GetInstallQuery(true));
97
+ }
98
+
99
+ /**
100
+ * Remove this ActiveRecord structure into DB.
101
+ */
102
+ public function Uninstall()
103
+ {
104
+ //global $wpdb;
105
+ $_wpdb = $this->connection;
106
+ $_wpdb->query($this->_GetUninstallQuery());
107
+ }
108
+
109
+ /**
110
+ * Save an active record to DB.
111
+ * @return integer|boolean Either the number of modified/inserted rows or false on failure.
112
+ */
113
+ public function Save($activeRecord)
114
+ {
115
+ //global $wpdb;
116
+ $_wpdb = $this->connection;
117
+ $copy = $activeRecord;
118
+ $data = array();
119
+ $format = array();
120
+
121
+ foreach ($this->GetColumns() as $index => $key) {
122
+ if ($key == $this->_idkey) {
123
+ $_idIndex = $index;
124
+ }
125
+
126
+ $val = $copy->$key;
127
+ $deffmt = '%s';
128
+ if (is_int($copy->$key)) {
129
+ $deffmt = '%d';
130
+ }
131
+ if (is_float($copy->$key)) {
132
+ $deffmt = '%f';
133
+ }
134
+ if (is_array($copy->$key) || is_object($copy->$key)) {
135
+ $data[$key] = WSAL_Helpers_DataHelper::JsonEncode($val);
136
+ } else {
137
+ $data[$key] = $val;
138
+ }
139
+ $format[] = $deffmt;
140
+ }
141
+
142
+ if (isset($data[$this->_idkey]) && empty($data[$this->_idkey])) {
143
+ unset($data[$this->_idkey]);
144
+ unset($format[$_idIndex]);
145
+ }
146
+
147
+ $result = $_wpdb->replace($this->GetTable(), $data, $format);
148
+
149
+ if ($result !== false) {
150
+ if ($_wpdb->insert_id) {
151
+ $copy->setId($_wpdb->insert_id);
152
+ }
153
+ }
154
+ return $result;
155
+ }
156
+
157
+ /**
158
+ * Load record from DB.
159
+ * @param string $cond (Optional) Load condition.
160
+ * @param array $args (Optional) Load condition arguments.
161
+ */
162
+ public function Load($cond = '%d', $args = array(1))
163
+ {
164
+ //global $wpdb;
165
+ $_wpdb = $this->connection;
166
+
167
+ $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
168
+ $data = $_wpdb->get_row($sql, ARRAY_A);
169
+
170
+ return $data;
171
+ }
172
+
173
+ public function LoadArray($cond, $args = array())
174
+ {
175
+ //global $wpdb;
176
+ $_wpdb = $this->connection;
177
+ $result = array();
178
+ $sql = $_wpdb->prepare('SELECT * FROM '.$this->GetTable().' WHERE '. $cond, $args);
179
+ foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
180
+ $result[] = $this->getModel()->LoadData($data);
181
+ }
182
+ return $result;
183
+ }
184
+
185
+ /**
186
+ * Delete DB record.
187
+ * @return int|boolean Either the amount of deleted rows or False on error.
188
+ */
189
+ public function Delete($activeRecord)
190
+ {
191
+ //global $wpdb;
192
+ $_wpdb = $this->connection;
193
+ $result = $_wpdb->delete(
194
+ $this->GetTable(),
195
+ $activeRecord->getId()
196
+ );
197
+ return $result;
198
+ }
199
+
200
+ /**
201
+ * Delete records in DB matching a query.
202
+ * @param string $query Full SQL query.
203
+ * @param array $args (Optional) Query arguments.
204
+ */
205
+ public function DeleteQuery($query, $args = array())
206
+ {
207
+ $_wpdb = $this->connection;
208
+ $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
209
+ $result = $_wpdb->query($sql);
210
+ return $result;
211
+ }
212
+
213
+ /**
214
+ * Load multiple records from DB.
215
+ * @param string $cond (Optional) Load condition (eg: 'some_id = %d' ).
216
+ * @param array $args (Optional) Load condition arguments (rg: array(45) ).
217
+ * @return self[] List of loaded records.
218
+ */
219
+ public function LoadMulti($cond, $args = array())
220
+ {
221
+ //global $wpdb;
222
+ $_wpdb = $this->connection;
223
+ $result = array();
224
+ $sql = (!is_array($args) || !count($args)) // do we really need to prepare() or not?
225
+ ? ($cond)
226
+ : $_wpdb->prepare($cond, $args)
227
+ ;
228
+ foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
229
+ $result[] = $this->getModel()->LoadData($data);
230
+ }
231
+ return $result;
232
+
233
+ }
234
+
235
+ /**
236
+ * Load multiple records from DB and call a callback for each record.
237
+ * This function is very memory-efficient, it doesn't load records in bulk.
238
+ * @param callable $callback The callback to invoke.
239
+ * @param string $cond (Optional) Load condition.
240
+ * @param array $args (Optional) Load condition arguments.
241
+ */
242
+ public function LoadAndCallForEach($callback, $cond = '%d', $args = array(1))
243
+ {
244
+ //global $wpdb;
245
+ $_wpdb = $this->connection;
246
+ $class = get_called_class();
247
+ $sql = $_wpdb->prepare('SELECT * FROM ' . $this->GetTable() . ' WHERE '.$cond, $args);
248
+ foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
249
+ call_user_func($callback, new $class($data));
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Count records in the DB matching a condition.
255
+ * If no parameters are given, this counts the number of records in the DB table.
256
+ * @param string $cond (Optional) Query condition.
257
+ * @param array $args (Optional) Condition arguments.
258
+ * @return int Number of matching records.
259
+ */
260
+ public function Count($cond = '%d', $args = array(1))
261
+ {
262
+ //global $wpdb;
263
+ $_wpdb = $this->connection;
264
+ $class = get_called_class();
265
+ $sql = $_wpdb->prepare('SELECT COUNT(*) FROM ' . $this->GetTable() . ' WHERE ' . $cond, $args);
266
+ return (int)$_wpdb->get_var($sql);
267
+ }
268
+
269
+ /**
270
+ * Count records in the DB matching a query.
271
+ * @param string $query Full SQL query.
272
+ * @param array $args (Optional) Query arguments.
273
+ * @return int Number of matching records.
274
+ */
275
+ public function CountQuery($query, $args = array())
276
+ {
277
+ //global $wpdb;
278
+ $_wpdb = $this->connection;
279
+ $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
280
+ return (int)$_wpdb->get_var($sql);
281
+ }
282
+
283
+ /**
284
+ * Similar to LoadMulti but allows the use of a full SQL query.
285
+ * @param string $query Full SQL query.
286
+ * @param array $args (Optional) Query arguments.
287
+ * @return self[] List of loaded records.
288
+ */
289
+ public function LoadMultiQuery($query, $args = array())
290
+ {
291
+ //global $wpdb;
292
+ $_wpdb = $this->connection;
293
+ $class = get_called_class();
294
+ $result = array();
295
+ $sql = count($args) ? $_wpdb->prepare($query, $args) : $query;
296
+ foreach ($_wpdb->get_results($sql, ARRAY_A) as $data) {
297
+ $result[] = $this->getModel()->LoadData($data);
298
+ }
299
+ return $result;
300
+ }
301
+
302
+ /**
303
+ * @return string Must return SQL for creating table.
304
+ */
305
+ protected function _GetInstallQuery($prefix = false)
306
+ {
307
+ $_wpdb = $this->connection;
308
+
309
+ $class = get_class($this);
310
+ $copy = new $class($this->connection);
311
+ $table_name = ($prefix) ? $this->GetWPTable() : $this->GetTable();
312
+ $sql = 'CREATE TABLE IF NOT EXISTS ' . $table_name . ' (' . PHP_EOL;
313
+
314
+ foreach ($this->GetColumns() as $key) {
315
+ $sql .= ' ';
316
+ switch (true) {
317
+ case $key == $copy->_idkey:
318
+ $sql .= $key . ' BIGINT NOT NULL AUTO_INCREMENT,' . PHP_EOL;
319
+ break;
320
+ case is_integer($copy->$key):
321
+ $sql .= $key . ' BIGINT NOT NULL,' . PHP_EOL;
322
+ break;
323
+ case is_float($copy->$key):
324
+ $sql .= $key . ' DOUBLE NOT NULL,' . PHP_EOL;
325
+ break;
326
+ case is_string($copy->$key):
327
+ $maxlength = $key . '_maxlength';
328
+ if (property_exists($class, $maxlength)) {
329
+ $sql .= $key . ' VARCHAR(' . intval($class::$$maxlength) . ') NOT NULL,' . PHP_EOL;
330
+ } else {
331
+ $sql .= $key . ' TEXT NOT NULL,' . PHP_EOL;
332
+ }
333
+ break;
334
+ case is_bool($copy->$key):
335
+ $sql .= $key . ' BIT NOT NULL,' . PHP_EOL;
336
+ break;
337
+ case is_array($copy->$key):
338
+ case is_object($copy->$key):
339
+ $sql .= $key . ' LONGTEXT NOT NULL,' . PHP_EOL;
340
+ break;
341
+ }
342
+ }
343
+
344
+ $sql .= $this->GetTableOptions() . PHP_EOL;
345
+
346
+ $sql .= ')';
347
+
348
+ if (! empty($_wpdb->charset)) {
349
+ $sql .= ' DEFAULT CHARACTER SET ' . $_wpdb->charset;
350
+ }
351
+
352
+ return $sql;
353
+
354
+ }
355
+
356
+ /**
357
+ * @return string Must return SQL for removing table (at a minimum, it should be ` 'DROP TABLE ' . $this->_table `).
358
+ */
359
+ protected function _GetUninstallQuery()
360
+ {
361
+ return 'DROP TABLE ' . $this->GetTable();
362
+ }
363
+
364
+ /**
365
+ * Function used in WSAL reporting extension
366
+ */
367
+ public function GetReporting($_siteId, $_userId, $_roleName, $_alertCode, $_startTimestamp, $_endTimestamp, $_nextDate = null, $_limit = 0)
368
+ {
369
+ global $wpdb;
370
+ $tableUsers = $wpdb->users;
371
+ $_wpdb = $this->connection;
372
+ // tables
373
+ $meta = new WSAL_Adapters_MySQL_Meta($this->connection);
374
+ $tableMeta = $meta->GetTable(); // metadata
375
+ $occurrence = new WSAL_Adapters_MySQL_Occurrence($this->connection);
376
+ $tableOcc = $occurrence->GetTable(); // occurrences
377
+
378
+ $user_names = '0';
379
+ if (!empty($_userId) && $_userId != "null") {
380
+ $sql = 'SELECT user_login FROM '.$tableUsers.' WHERE find_in_set(ID, @userId) > 0';
381
+ $wpdb->query("SET @userId = $_userId");
382
+ $result = $wpdb->get_results($sql, ARRAY_A);
383
+ $aUsers = array();
384
+ foreach ($result as $item) {
385
+ $aUsers[] = '"'.$item['user_login'].'"';
386
+ }
387
+ $user_names = implode(', ', $aUsers);
388
+ }
389
+ $conditionDate = !empty($_nextDate) ? ' AND occ.created_on < '.$_nextDate : '';
390
+
391
+ $sql = "SELECT DISTINCT
392
+ occ.id,
393
+ occ.alert_id,
394
+ occ.site_id,
395
+ occ.created_on,
396
+ replace(replace(replace((
397
+ SELECT t1.value FROM $tableMeta AS t1 WHERE t1.name = 'CurrentUserRoles' AND t1.occurrence_id = occ.id LIMIT 1), '[', ''), ']', ''), '\\'', '') AS roles,
398
+ (SELECT replace(t2.value, '\"','') FROM $tableMeta as t2 WHERE t2.name = 'ClientIP' AND t2.occurrence_id = occ.id LIMIT 1) AS ip,
399
+ (SELECT replace(t3.value, '\"', '') FROM $tableMeta as t3 WHERE t3.name = 'UserAgent' AND t3.occurrence_id = occ.id LIMIT 1) AS ua,
400
+ COALESCE(
401
+ (SELECT replace(t4.value, '\"', '') FROM $tableMeta as t4 WHERE t4.name = 'Username' AND t4.occurrence_id = occ.id LIMIT 1),
402
+ (SELECT replace(t5.value, '\"', '') FROM $tableMeta as t5 WHERE t5.name = 'CurrentUserID' AND t5.occurrence_id = occ.id LIMIT 1)
403
+ ) as user_id
404
+ FROM $tableOcc AS occ
405
+ JOIN $tableMeta AS meta ON meta.occurrence_id = occ.id
406
+ WHERE
407
+ (@siteId is NULL OR find_in_set(occ.site_id, @siteId) > 0)
408
+ AND (@userId is NULL OR (
409
+ (meta.name = 'CurrentUserID' AND find_in_set(meta.value, @userId) > 0)
410
+ OR (meta.name = 'Username' AND replace(meta.value, '\"', '') IN ($user_names))
411
+ ))
412
+ AND (@roleName is NULL OR (meta.name = 'CurrentUserRoles'
413
+ AND replace(replace(replace(meta.value, ']', ''), '[', ''), '\\'', '') REGEXP @roleName
414
+ ))
415
+ AND (@alertCode is NULL OR find_in_set(occ.alert_id, @alertCode) > 0)
416
+ AND (@startTimestamp is NULL OR occ.created_on >= @startTimestamp)
417
+ AND (@endTimestamp is NULL OR occ.created_on <= @endTimestamp)
418
+ {$conditionDate}
419
+ ORDER BY
420
+ created_on DESC
421
+ ";
422
+
423
+ $_wpdb->query("SET @siteId = $_siteId");
424
+ $_wpdb->query("SET @userId = $_userId");
425
+ $_wpdb->query("SET @roleName = $_roleName");
426
+ $_wpdb->query("SET @alertCode = $_alertCode");
427
+ $_wpdb->query("SET @startTimestamp = $_startTimestamp");
428
+ $_wpdb->query("SET @endTimestamp = $_endTimestamp");
429
+
430
+ if (!empty($_limit)) {
431
+ $sql .= " LIMIT {$_limit}";
432
+ }
433
+ $results = $_wpdb->get_results($sql);
434
+
435
+ foreach ($results as $row) {
436
+ $sql = "SELECT t6.ID FROM $tableUsers AS t6 WHERE t6.user_login = \"$row->user_id\"";
437
+ $userId = $wpdb->get_var($sql);
438
+ if ($userId == null) {
439
+ $sql = "SELECT t4.ID FROM $tableUsers AS t4 WHERE t4.ID = \"$row->user_id\"";
440
+ $userId = $wpdb->get_var($sql);
441
+ }
442
+ $row->user_id = $userId;
443
+ $results['lastDate'] = $row->created_on;
444
+ }
445
+
446
+ return $results;
447
+ }
448
+ }
classes/Models/Adapters/MySQL/MetaAdapter.php CHANGED
@@ -1,53 +1,53 @@
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
- {
21
- parent::__construct($conn);
22
- }
23
-
24
- protected function GetTableOptions(){
25
- return parent::GetTableOptions() . ',' . PHP_EOL
26
- . ' KEY occurrence_name (occurrence_id,name)';
27
- }
28
-
29
- public function DeleteByOccurenceIds($occurenceIds)
30
- {
31
- if (!empty($occurenceIds)) {
32
- $sql = 'DELETE FROM ' . $this->GetTable() . ' WHERE occurrence_id IN (' . implode(',', $occurenceIds) . ')';
33
- // execute query
34
- parent::DeleteQuery($sql);
35
- }
36
- }
37
-
38
- public function LoadByNameAndOccurenceId($metaName, $occurenceId)
39
- {
40
- return $this->Load('occurrence_id = %d AND name = %s', array($occurenceId, $metaName));
41
- }
42
-
43
- public function GetMatchingIPs()
44
- {
45
- $_wpdb = $this->connection;
46
- $ips = $_wpdb->get_col("SELECT DISTINCT value FROM {$this->GetTable()} WHERE name = \"ClientIP\"");
47
- foreach ($ips as $key => $ip) {
48
- $ips[$key] = str_replace('"', '', $ip);
49
- }
50
- return array_unique($ips);
51
- }
52
-
53
- }
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
+ {
21
+ parent::__construct($conn);
22
+ }
23
+
24
+ protected function GetTableOptions(){
25
+ return parent::GetTableOptions() . ',' . PHP_EOL
26
+ . ' KEY occurrence_name (occurrence_id,name)';
27
+ }
28
+
29
+ public function DeleteByOccurenceIds($occurenceIds)
30
+ {
31
+ if (!empty($occurenceIds)) {
32
+ $sql = 'DELETE FROM ' . $this->GetTable() . ' WHERE occurrence_id IN (' . implode(',', $occurenceIds) . ')';
33
+ // execute query
34
+ parent::DeleteQuery($sql);
35
+ }
36
+ }
37
+
38
+ public function LoadByNameAndOccurenceId($metaName, $occurenceId)
39
+ {
40
+ return $this->Load('occurrence_id = %d AND name = %s', array($occurenceId, $metaName));
41
+ }
42
+
43
+ public function GetMatchingIPs()
44
+ {
45
+ $_wpdb = $this->connection;
46
+ $ips = $_wpdb->get_col("SELECT DISTINCT value FROM {$this->GetTable()} WHERE name = \"ClientIP\"");
47
+ foreach ($ips as $key => $ip) {
48
+ $ips[$key] = str_replace('"', '', $ip);
49
+ }
50
+ return array_unique($ips);
51
+ }
52
+
53
+ }
classes/Models/Adapters/MySQL/OccurrenceAdapter.php CHANGED
@@ -1,187 +1,187 @@
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
- * Gets occurrence by Post_id
171
- * @param int $post_id
172
- */
173
- public function GetByPostID($post_id)
174
- {
175
- $tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
176
- return self::LoadMultiQuery(
177
- 'SELECT occurrence.* FROM `' . $this->GetTable() . '`AS occurrence
178
- INNER JOIN `' . $tt2->GetTable() . '`AS postMeta ON postMeta.occurrence_id = occurrence.id
179
- and postMeta.name = "PostID"
180
- and postMeta.value = %d
181
- GROUP BY occurrence.id
182
- ORDER BY created_on DESC',
183
- array($post_id)
184
- );
185
- }
186
-
187
- }
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
+ * Gets occurrence by Post_id
171
+ * @param int $post_id
172
+ */
173
+ public function GetByPostID($post_id)
174
+ {
175
+ $tt2 = new WSAL_Adapters_MySQL_Meta($this->connection);
176
+ return self::LoadMultiQuery(
177
+ 'SELECT occurrence.* FROM `' . $this->GetTable() . '`AS occurrence
178
+ INNER JOIN `' . $tt2->GetTable() . '`AS postMeta ON postMeta.occurrence_id = occurrence.id
179
+ and postMeta.name = "PostID"
180
+ and postMeta.value = %d
181
+ GROUP BY occurrence.id
182
+ ORDER BY created_on DESC',
183
+ array($post_id)
184
+ );
185
+ }
186
+
187
+ }
classes/Models/Adapters/MySQL/OptionAdapter.php CHANGED
@@ -1,79 +1,79 @@
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
- public function GetModel()
20
- {
21
- return new WSAL_Models_Option();
22
- }
23
-
24
- public function GetNamedOption($name)
25
- { if ($this->IsInstalled()) {
26
- return $this->Load('option_name = %s', array($name));
27
- } else {
28
- return null;
29
- }
30
- }
31
-
32
- public function GetNotificationsSetting($opt_prefix)
33
- {
34
- if ($this->IsInstalled()) {
35
- return $this->LoadArray('option_name LIKE %s', array($opt_prefix."%"));
36
- } else {
37
- return null;
38
- }
39
- }
40
-
41
- public function GetNotification($id)
42
- {
43
- if ($this->IsInstalled()) {
44
- return $this->Load('id = %d', array($id));
45
- } else {
46
- return null;
47
- }
48
- }
49
-
50
- public function DeleteByName($name)
51
- {
52
- if (!empty($name)) {
53
- $sql = "DELETE FROM " . $this->GetTable() . " WHERE option_name = '". $name ."'";
54
- // execute query
55
- return parent::DeleteQuery($sql);
56
- } else {
57
- return false;
58
- }
59
- }
60
-
61
- public function DeleteByPrefix($opt_prefix)
62
- {
63
- if (!empty($opt_prefix)) {
64
- $sql = "DELETE FROM " . $this->GetTable() . " WHERE option_name LIKE '". $opt_prefix ."%'";
65
- // execute query
66
- return parent::DeleteQuery($sql);
67
- } else {
68
- return false;
69
- }
70
- }
71
-
72
- public function CountNotifications($opt_prefix)
73
- {
74
- $_wpdb = $this->connection;
75
- $sql = "SELECT COUNT(id) FROM " . $this->GetTable() . " WHERE option_name LIKE '". $opt_prefix ."%'";
76
- return (int)$_wpdb->get_var($sql);
77
- }
78
-
79
- }
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
+ public function GetModel()
20
+ {
21
+ return new WSAL_Models_Option();
22
+ }
23
+
24
+ public function GetNamedOption($name)
25
+ { if ($this->IsInstalled()) {
26
+ return $this->Load('option_name = %s', array($name));
27
+ } else {
28
+ return null;
29
+ }
30
+ }
31
+
32
+ public function GetNotificationsSetting($opt_prefix)
33
+ {
34
+ if ($this->IsInstalled()) {
35
+ return $this->LoadArray('option_name LIKE %s', array($opt_prefix."%"));
36
+ } else {
37
+ return null;
38
+ }
39
+ }
40
+
41
+ public function GetNotification($id)
42
+ {
43
+ if ($this->IsInstalled()) {
44
+ return $this->Load('id = %d', array($id));
45
+ } else {
46
+ return null;
47
+ }
48
+ }
49
+
50
+ public function DeleteByName($name)
51
+ {
52
+ if (!empty($name)) {
53
+ $sql = "DELETE FROM " . $this->GetTable() . " WHERE option_name = '". $name ."'";
54
+ // execute query
55
+ return parent::DeleteQuery($sql);
56
+ } else {
57
+ return false;
58
+ }
59
+ }
60
+
61
+ public function DeleteByPrefix($opt_prefix)
62
+ {
63
+ if (!empty($opt_prefix)) {
64
+ $sql = "DELETE FROM " . $this->GetTable() . " WHERE option_name LIKE '". $opt_prefix ."%'";
65
+ // execute query
66
+ return parent::DeleteQuery($sql);
67
+ } else {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ public function CountNotifications($opt_prefix)
73
+ {
74
+ $_wpdb = $this->connection;
75
+ $sql = "SELECT COUNT(id) FROM " . $this->GetTable() . " WHERE option_name LIKE '". $opt_prefix ."%'";
76
+ return (int)$_wpdb->get_var($sql);
77
+ }
78
+
79
+ }
classes/Models/Adapters/MySQL/QueryAdapter.php CHANGED
@@ -1,219 +1,219 @@
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
- if (is_numeric($condition) && strlen($condition) == 4) {
207
- $searchConditions['sql'] = $occurrence->GetTable() .'.alert_id LIKE %s';
208
- } else {
209
- $searchConditions['sql'] = $occurrence->GetTable() .'.id IN (
210
- SELECT DISTINCT occurrence_id
211
- FROM ' . $meta->GetTable() . '
212
- WHERE TRIM(BOTH "\"" FROM value) LIKE %s
213
- )';
214
- }
215
- $searchConditions['args'] = "%". $condition. "%";
216
- return $searchConditions;
217
- }
218
-
219
- }
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
+ if (is_numeric($condition) && strlen($condition) == 4) {
207
+ $searchConditions['sql'] = $occurrence->GetTable() .'.alert_id LIKE %s';
208
+ } else {
209
+ $searchConditions['sql'] = $occurrence->GetTable() .'.id IN (
210
+ SELECT DISTINCT occurrence_id
211
+ FROM ' . $meta->GetTable() . '
212
+ WHERE TRIM(BOTH "\"" FROM value) LIKE %s
213
+ )';
214
+ }
215
+ $searchConditions['args'] = "%". $condition. "%";
216
+ return $searchConditions;
217
+ }
218
+
219
+ }
classes/Models/Adapters/OccurrenceInterface.php CHANGED
@@ -1,11 +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
- }
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 CHANGED
@@ -1,8 +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
- }
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 CHANGED
@@ -1,34 +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
- }
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 CHANGED
@@ -1,199 +1,199 @@
1
- <?php
2
-
3
- class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
4
- {
5
- public $id = 0;
6
- public $site_id = 0;
7
- public $alert_id = 0;
8
- public $created_on = 0.0;
9
- public $is_read = false;
10
- public $is_migrated = false;
11
- protected $adapterName = "Occurrence";
12
-
13
- /**
14
- * Returns the alert related to this occurrence.
15
- * @return WSAL_Alert
16
- */
17
- public function GetAlert()
18
- {
19
- return WpSecurityAuditLog::GetInstance()->alerts->GetAlert($this->alert_id);
20
- }
21
-
22
- /**
23
- * Returns the value of a meta item.
24
- * @param string $name Name of meta item.
25
- * @param mixed $default Default value returned when meta does not exist.
26
- * @return mixed The value, if meta item does not exist $default returned.
27
- */
28
- public function GetMetaValue($name, $default = array())
29
- {
30
- //get meta adapter
31
- //call the function ($name, $this->getId())
32
- $meta = $this->getAdapter()->GetNamedMeta($this, $name);
33
- return maybe_unserialize($meta['value']);
34
-
35
- //TO DO: re-introduce add is loaded check before running query
36
- //return $meta->IsLoaded() ? $meta->value : $default;
37
- }
38
-
39
- /**
40
- * Set the value of a meta item (creates or updates meta item).
41
- * @param string $name Meta name.
42
- * @param mixed $value Meta value.
43
- */
44
- public function SetMetaValue($name, $value)
45
- {
46
- if (!empty($value)) {
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
-
56
- public function UpdateMetaValue($name, $value)
57
- {
58
- $model = new WSAL_Models_Meta();
59
- $model->UpdateByNameAndOccurenceId($name, $value, $this->getId());
60
- }
61
-
62
- /**
63
- * Returns a key-value pair of meta data.
64
- * @return array
65
- */
66
- public function GetMetaArray()
67
- {
68
- $result = array();
69
- $metas = $this->getAdapter()->GetMultiMeta($this);
70
- foreach ($metas as $meta) {
71
- $result[$meta->name] = maybe_unserialize($meta->value);
72
- }
73
- return $result;
74
- }
75
-
76
- /**
77
- * Creates or updates all meta data passed as an array of meta-key/meta-value pairs.
78
- * @param array $data New meta data.
79
- */
80
- public function SetMeta($data)
81
- {
82
- foreach ((array)$data as $key => $val) {
83
- $this->SetMetaValue($key, $val);
84
- }
85
- }
86
-
87
- /**
88
- * @param callable|null $metaFormatter (Optional) Meta formatter callback.
89
- * @return string Full-formatted message.
90
- */
91
- public function GetMessage($metaFormatter = null)
92
- {
93
- if (!isset($this->_cachedmessage)) {
94
- // get correct message entry
95
- if ($this->is_migrated) {
96
- $this->_cachedmessage = $this->GetMetaValue('MigratedMesg', false);
97
- }
98
- if (!$this->is_migrated || !$this->_cachedmessage) {
99
- $this->_cachedmessage = $this->GetAlert()->mesg;
100
- }
101
- // fill variables in message
102
- $this->_cachedmessage = $this->GetAlert()->GetMessage($this->GetMetaArray(), $metaFormatter, $this->_cachedmessage);
103
- }
104
- return $this->_cachedmessage;
105
- }
106
-
107
- /**
108
- * Delete occurrence as well as associated meta data.
109
- * @return boolean True on success, false on failure.
110
- */
111
- public function Delete()
112
- {
113
- foreach ($this->getAdapter()->GetMeta() as $meta) {
114
- $meta->Delete();
115
- }
116
- return parent::Delete();
117
- }
118
-
119
- /**
120
- * @return string User's username.
121
- */
122
- public function GetUsername()
123
- {
124
- $meta = $this->getAdapter()->GetFirstNamedMeta($this, array('Username', 'CurrentUserID'));
125
- if ($meta) {
126
- switch (true) {
127
- case $meta->name == 'Username':
128
- return $meta->value;
129
- case $meta->name == 'CurrentUserID':
130
- return ($data = get_userdata($meta->value)) ? $data->user_login : null;
131
- }
132
- }
133
- return null;
134
- }
135
-
136
- /**
137
- * @return string IP address of request.
138
- */
139
- public function GetSourceIP()
140
- {
141
- return $this->GetMetaValue('ClientIP', '');
142
- }
143
-
144
- /**
145
- * @return string IP address of request (from proxies etc).
146
- */
147
- public function GetOtherIPs()
148
- {
149
- $result = array();
150
- $data = (array)$this->GetMetaValue('OtherIPs', array());
151
- foreach ($data as $ips) {
152
- foreach ($ips as $ip) {
153
- $result[] = $ip;
154
- }
155
- }
156
- return array_unique($result);
157
- }
158
-
159
- /**
160
- * @return array Array of user roles.
161
- */
162
- public function GetUserRoles()
163
- {
164
- return $this->GetMetaValue('CurrentUserRoles', array());
165
- }
166
-
167
- /**
168
- * @return float Number of seconds (and microseconds as fraction) since unix Day 0.
169
- * @todo This needs some caching.
170
- */
171
- protected function GetMicrotime()
172
- {
173
- return microtime(true);// + get_option('gmt_offset') * HOUR_IN_SECONDS;
174
- }
175
-
176
- /**
177
- * Finds occurences of the same type by IP and Username within specified time frame
178
- * @param string $ipAddress
179
- * @param string $username
180
- * @param int $alertId Alert type we are lookign for
181
- * @param int $siteId
182
- * @param $startTime mktime
183
- * @param $endTime mktime
184
- */
185
- public function CheckKnownUsers($args = array())
186
- {
187
- return $this->getAdapter()->CheckKnownUsers($args);
188
- }
189
-
190
- public function CheckUnKnownUsers($args = array())
191
- {
192
- return $this->getAdapter()->CheckUnKnownUsers($args);
193
- }
194
-
195
- public function GetByPostID($post_id)
196
- {
197
- return $this->getAdapter()->GetByPostID($post_id);
198
- }
199
- }
1
+ <?php
2
+
3
+ class WSAL_Models_Occurrence extends WSAL_Models_ActiveRecord
4
+ {
5
+ public $id = 0;
6
+ public $site_id = 0;
7
+ public $alert_id = 0;
8
+ public $created_on = 0.0;
9
+ public $is_read = false;
10
+ public $is_migrated = false;
11
+ protected $adapterName = "Occurrence";
12
+
13
+ /**
14
+ * Returns the alert related to this occurrence.
15
+ * @return WSAL_Alert
16
+ */
17
+ public function GetAlert()
18
+ {
19
+ return WpSecurityAuditLog::GetInstance()->alerts->GetAlert($this->alert_id);
20
+ }
21
+
22
+ /**
23
+ * Returns the value of a meta item.
24
+ * @param string $name Name of meta item.
25
+ * @param mixed $default Default value returned when meta does not exist.
26
+ * @return mixed The value, if meta item does not exist $default returned.
27
+ */
28
+ public function GetMetaValue($name, $default = array())
29
+ {
30
+ //get meta adapter
31
+ //call the function ($name, $this->getId())
32
+ $meta = $this->getAdapter()->GetNamedMeta($this, $name);
33
+ return maybe_unserialize($meta['value']);
34
+
35
+ //TO DO: re-introduce add is loaded check before running query
36
+ //return $meta->IsLoaded() ? $meta->value : $default;
37
+ }
38
+
39
+ /**
40
+ * Set the value of a meta item (creates or updates meta item).
41
+ * @param string $name Meta name.
42
+ * @param mixed $value Meta value.
43
+ */
44
+ public function SetMetaValue($name, $value)
45
+ {
46
+ if (!empty($value)) {
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
+
56
+ public function UpdateMetaValue($name, $value)
57
+ {
58
+ $model = new WSAL_Models_Meta();
59
+ $model->UpdateByNameAndOccurenceId($name, $value, $this->getId());
60
+ }
61
+
62
+ /**
63
+ * Returns a key-value pair of meta data.
64
+ * @return array
65
+ */
66
+ public function GetMetaArray()
67
+ {
68
+ $result = array();
69
+ $metas = $this->getAdapter()->GetMultiMeta($this);
70
+ foreach ($metas as $meta) {
71
+ $result[$meta->name] = maybe_unserialize($meta->value);
72
+ }
73
+ return $result;
74
+ }
75
+
76
+ /**
77
+ * Creates or updates all meta data passed as an array of meta-key/meta-value pairs.
78
+ * @param array $data New meta data.
79
+ */
80
+ public function SetMeta($data)
81
+ {
82
+ foreach ((array)$data as $key => $val) {
83
+ $this->SetMetaValue($key, $val);
84
+ }
85
+ }
86
+
87
+ /**
88
+ * @param callable|null $metaFormatter (Optional) Meta formatter callback.
89
+ * @return string Full-formatted message.
90
+ */
91
+ public function GetMessage($metaFormatter = null)
92
+ {
93
+ if (!isset($this->_cachedmessage)) {
94
+ // get correct message entry
95
+ if ($this->is_migrated) {
96
+ $this->_cachedmessage = $this->GetMetaValue('MigratedMesg', false);
97
+ }
98
+ if (!$this->is_migrated || !$this->_cachedmessage) {
99
+ $this->_cachedmessage = $this->GetAlert()->mesg;
100
+ }
101
+ // fill variables in message
102
+ $this->_cachedmessage = $this->GetAlert()->GetMessage($this->GetMetaArray(), $metaFormatter, $this->_cachedmessage);
103
+ }
104
+ return $this->_cachedmessage;
105
+ }
106
+
107
+ /**
108
+ * Delete occurrence as well as associated meta data.
109
+ * @return boolean True on success, false on failure.
110
+ */
111
+ public function Delete()
112
+ {
113
+ foreach ($this->getAdapter()->GetMeta() as $meta) {
114
+ $meta->Delete();
115
+ }
116
+ return parent::Delete();
117
+ }
118
+
119
+ /**
120
+ * @return string User's username.
121
+ */
122
+ public function GetUsername()
123
+ {
124
+ $meta = $this->getAdapter()->GetFirstNamedMeta($this, array('Username', 'CurrentUserID'));
125
+ if ($meta) {
126
+ switch (true) {
127
+ case $meta->name == 'Username':
128
+ return $meta->value;
129
+ case $meta->name == 'CurrentUserID':
130
+ return ($data = get_userdata($meta->value)) ? $data->user_login : null;
131
+ }
132
+ }
133
+ return null;
134
+ }
135
+
136
+ /**
137
+ * @return string IP address of request.
138
+ */
139
+ public function GetSourceIP()
140
+ {
141
+ return $this->GetMetaValue('ClientIP', '');
142
+ }
143
+
144
+ /**
145
+ * @return string IP address of request (from proxies etc).
146
+ */
147
+ public function GetOtherIPs()
148
+ {
149
+ $result = array();
150
+ $data = (array)$this->GetMetaValue('OtherIPs', array());
151
+ foreach ($data as $ips) {
152
+ foreach ($ips as $ip) {
153
+ $result[] = $ip;
154
+ }
155
+ }
156
+ return array_unique($result);
157
+ }
158
+
159
+ /**
160
+ * @return array Array of user roles.
161
+ */
162
+ public function GetUserRoles()
163
+ {
164
+ return $this->GetMetaValue('CurrentUserRoles', array());
165
+ }
166
+
167
+ /**
168
+ * @return float Number of seconds (and microseconds as fraction) since unix Day 0.
169
+ * @todo This needs some caching.
170
+ */
171
+ protected function GetMicrotime()
172
+ {
173
+ return microtime(true);// + get_option('gmt_offset') * HOUR_IN_SECONDS;
174
+ }
175
+
176
+ /**
177
+ * Finds occurences of the same type by IP and Username within specified time frame
178
+ * @param string $ipAddress
179
+ * @param string $username
180
+ * @param int $alertId Alert type we are lookign for
181
+ * @param int $siteId
182
+ * @param $startTime mktime
183
+ * @param $endTime mktime
184
+ */
185
+ public function CheckKnownUsers($args = array())
186
+ {
187
+ return $this->getAdapter()->CheckKnownUsers($args);
188
+ }
189
+
190
+ public function CheckUnKnownUsers($args = array())
191
+ {
192
+ return $this->getAdapter()->CheckUnKnownUsers($args);
193
+ }
194
+
195
+ public function GetByPostID($post_id)
196
+ {
197
+ return $this->getAdapter()->GetByPostID($post_id);
198
+ }
199
+ }
classes/Models/OccurrenceQuery.php CHANGED
@@ -1,29 +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
- }
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 CHANGED
@@ -1,80 +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
- }
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 CHANGED
@@ -1,187 +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
- }
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/Nicer.php CHANGED
@@ -1,289 +1,289 @@
1
- <?php
2
-
3
- /**
4
- * Inspects and prints out PHP values as HTML in a nicer way than print_r().
5
- * @author Christian Sciberras <christian@sciberras.me>
6
- * @copyright (c) 2013, Christian Sciberras
7
- * @license https://raw.github.com/uuf6429/nice_r/master/LICENSE MIT License
8
- * @link https://github.com/uuf6429/nice_r GitHub Repository
9
- * @version 2.0
10
- * @since 2.0
11
- */
12
- class WSAL_Nicer {
13
- protected $value;
14
-
15
- /**
16
- * Allows modification of CSS class prefix.
17
- * @var string
18
- */
19
- public $css_class = 'nice_r';
20
-
21
- /**
22
- * Allows modification of HTML id prefix.
23
- * @var string
24
- */
25
- public $html_id = 'nice_r_v';
26
-
27
- /**
28
- * Allows modification of JS function used to toggle sections.
29
- * @var string
30
- */
31
- public $js_func = 'nice_r_toggle';
32
-
33
- /**
34
- * Whether to inspect and output methods for objects or not.
35
- * @var boolean
36
- */
37
- public $inspect_methods = false;
38
-
39
- /**
40
- * Since PHP does not support private constants, we'll have to settle for private static fields.
41
- * @var string
42
- */
43
- protected static $BEEN_THERE = '__NICE_R_INFINITE_RECURSION_PROTECT__';
44
-
45
- protected $_has_reflection = null;
46
-
47
- /**
48
- * Constructs new renderer instance.
49
- * @param mixed $value The value to inspect and render.
50
- * @param boolean $inspectMethods Whether to inspect and output methods for objects or not.
51
- */
52
- public function __construct($value, $inspectMethods = false){
53
- $this->value = $value;
54
- $this->inspect_methods = $inspectMethods;
55
-
56
- if(is_null($this->_has_reflection))
57
- $this->_has_reflection = class_exists('ReflectionClass');
58
- }
59
-
60
- /**
61
- * Generates the inspector HTML and returns it as a string.
62
- * @return string Generated HTML.
63
- */
64
- public function generate(){
65
- return $this->_generate_value($this->value, $this->css_class);
66
- }
67
-
68
- /**
69
- * Renders the inspector HTML directly to the browser.
70
- */
71
- public function render(){
72
- echo $this->generate();
73
- }
74
-
75
- /**
76
- * Converts a string to HTML, encoding any special characters.
77
- * @param string $text The original string.
78
- * @return string The string as HTML.
79
- */
80
- protected function _esc_html($text){
81
- return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
82
- }
83
-
84
- protected function _inspect_array(&$html, &$var){
85
- $has_subitems = false;
86
-
87
- foreach($var as $k => $v){
88
- if($k !== self::$BEEN_THERE){
89
- $html .= $this->_generate_keyvalue($k, $v);
90
- $has_subitems = true;
91
- }
92
- }
93
-
94
- if(!$has_subitems){
95
- $html .= '<span class="'.$this->css_class.'_ni">Empty Array</span>';
96
- }
97
- }
98
-
99
- protected function _inspect_object(&$html, &$var){
100
- // render properties
101
- $has_subitems = false;
102
-
103
- foreach((array)$var as $k=>$v){
104
- if($k !== self::$BEEN_THERE){
105
- $html .= $this->_generate_keyvalue($k, $v);
106
- $has_subitems = true;
107
- }
108
- }
109
-
110
- if(!$has_subitems){
111
- $html .= '<span class="'.$this->css_class.'_ni">No Properties</span>';
112
- }
113
-
114
- // render methods (if enabled)
115
- if($this->inspect_methods){
116
- $has_subitems = false;
117
-
118
- foreach((array)get_class_methods($var) as $method){
119
- $html .= $this->_generate_callable($var, $method);
120
- $has_subitems = true;
121
- }
122
-
123
- if(!$has_subitems){
124
- $html .= '<span class="'.$this->css_class.'_ni">No Methods</span>';
125
- }
126
- }
127
- }
128
-
129
- /**
130
- * Render a single particular value.
131
- * @param mixed $var The value to render
132
- * @param string $class Parent CSS class.
133
- * @param string $id Item HTML id.
134
- */
135
- protected function _generate_value($var, $class = '', $id = ''){
136
- $BEENTHERE = self::$BEEN_THERE;
137
- $class .= ' '.$this->css_class.'_t_'.gettype($var);
138
-
139
- $html = '<div id="'.$id.'" class="'.$class.'">';
140
-
141
- switch(true){
142
-
143
- // handle arrays
144
- case is_array($var):
145
- if(isset($var[$BEENTHERE])){
146
- $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
147
- }else{
148
- $var[$BEENTHERE] = true;
149
- $this->_inspect_array($html, $var);
150
- unset($var[$BEENTHERE]);
151
- }
152
- break;
153
-
154
- // handle objects
155
- case is_object($var):
156
- if(isset($var->$BEENTHERE)){
157
- $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
158
- }else{
159
- $var->$BEENTHERE = true;
160
- $this->_inspect_object($html, $var);
161
- unset($var->$BEENTHERE);
162
- }
163
- break;
164
-
165
- // handle simple types
166
- default:
167
- $html .= $this->_generate_keyvalue('', $var);
168
- break;
169
- }
170
-
171
- return $html . '</div>';
172
- }
173
-
174
- /**
175
- * Generates a new unique ID for tagging elements.
176
- * @staticvar int $id
177
- * @return integer An ID unique per request.
178
- */
179
- protected function _generate_dropid(){
180
- static $id = 0;
181
- return ++$id;
182
- }
183
-
184
- /**
185
- * Render a key-value pair.
186
- * @staticvar int $id Specifies element id.
187
- * @param string $key Key name.
188
- * @param mixed $val Key value.
189
- */
190
- protected function _generate_keyvalue($key, $val){
191
- $id = $this->_generate_dropid();
192
- $p = ''; // preview
193
- $d = ''; // description
194
- $t = gettype($val); // get data type
195
- $is_hash = ($t=='array') || ($t=='object');
196
-
197
- switch($t){
198
- case 'boolean':
199
- $p = $val ? 'TRUE' : 'FALSE';
200
- break;
201
- case 'integer':
202
- case 'double':
203
- $p = (string)$val;
204
- break;
205
- case 'string':
206
- $d .= ', '.strlen($val).' characters';
207
- $p = $val;
208
- break;
209
- case 'resource':
210
- $d .= ', '.get_resource_type($val).' type';
211
- $p = (string)$val;
212
- break;
213
- case 'array':
214
- $d .= ', '.count($val).' elements';
215
- break;
216
- case 'object':
217
- $d .= ', '.get_class($val).', '.count(get_object_vars($val)).' properties';
218
- break;
219
- }
220
-
221
- $cls = $this->css_class;
222
- $xcls = !$is_hash ? $cls.'_ad' : '';
223
- $html = '<a '.($is_hash?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
224
- $html .= ' <span class="'.$cls.'_a '.$xcls.'" id="'.$this->html_id.'_a'.$id.'">&#9658;</span>';
225
- $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($key).'</span>';
226
- $html .= ' <span class="'.$cls.'_d">(<span>'.ucwords($t).'</span>'.$d.')</span>';
227
- $html .= ' <span class="'.$cls.'_p '.$cls.'_t_'.$t.'">'.$this->_esc_html($p).'</span>';
228
- $html .= '</a>';
229
-
230
- if($is_hash){
231
- $html .= $this->_generate_value($val, $cls.'_v', $this->html_id.'_v'.$id);
232
- }
233
-
234
- return $html;
235
- }
236
-
237
- protected function _generate_callable($context, $callback){
238
- $id = $this->_generate_dropid();
239
- $ref = null;
240
- $name = 'Anonymous';
241
- $cls = $this->css_class;
242
-
243
- if($this->_has_reflection){
244
- if(is_null($context)){
245
- $ref = new ReflectionFunction($callback);
246
- }else{
247
- $ref = new ReflectionMethod($context, $callback);
248
- }
249
- $name = $ref->getName();
250
- }elseif(is_string($callback)){
251
- $name = $callback;
252
- }
253
-
254
- if(!is_null($ref)){
255
- $doc = $ref->getDocComment();
256
- $prms = array();
257
- foreach($ref->getParameters() as $p){
258
- $prms[] = '$' . $p->getName() . (
259
- $p->isDefaultValueAvailable()
260
- ? (
261
- ' = <span class="'.$cls.'_mv">' . (
262
- $p->isDefaultValueConstant()
263
- ? $p->getDefaultValueConstantName()
264
- : var_export($p->getDefaultValue(), true)
265
- ) . '</span>'
266
- )
267
- : ''
268
- );
269
- }
270
- }else{
271
- $doc = null;
272
- $prms = array('???');
273
- }
274
-
275
- $xcls = !$doc ? $cls.'_ad' : '';
276
- $html = '<a class="'.$cls.'_c" '.($doc?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
277
- $html .= ' <span class="'.$cls.'_a '.$xcls.'">&#9658;</span>';
278
- $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($name).'<span class="'.$cls.'_ma">(<span>'.implode(', ', $prms).'</span>)</span></span>';
279
- $html .= '</a>';
280
-
281
- if($doc){
282
- $html .= '<div id="'.$this->html_id.'_v'.$id.'" class="nice_r_v '.$this->css_class.'_t_comment">';
283
- $html .= nl2br(str_replace(' ', '&nbsp;', $this->_esc_html($doc)));
284
- $html .= '</div>';
285
- }
286
-
287
- return $html;
288
- }
289
- }
1
+ <?php
2
+
3
+ /**
4
+ * Inspects and prints out PHP values as HTML in a nicer way than print_r().
5
+ * @author Christian Sciberras <christian@sciberras.me>
6
+ * @copyright (c) 2013, Christian Sciberras
7
+ * @license https://raw.github.com/uuf6429/nice_r/master/LICENSE MIT License
8
+ * @link https://github.com/uuf6429/nice_r GitHub Repository
9
+ * @version 2.0
10
+ * @since 2.0
11
+ */
12
+ class WSAL_Nicer {
13
+ protected $value;
14
+
15
+ /**
16
+ * Allows modification of CSS class prefix.
17
+ * @var string
18
+ */
19
+ public $css_class = 'nice_r';
20
+
21
+ /**
22
+ * Allows modification of HTML id prefix.
23
+ * @var string
24
+ */
25
+ public $html_id = 'nice_r_v';
26
+
27
+ /**
28
+ * Allows modification of JS function used to toggle sections.
29
+ * @var string
30
+ */
31
+ public $js_func = 'nice_r_toggle';
32
+
33
+ /**
34
+ * Whether to inspect and output methods for objects or not.
35
+ * @var boolean
36
+ */
37
+ public $inspect_methods = false;
38
+
39
+ /**
40
+ * Since PHP does not support private constants, we'll have to settle for private static fields.
41
+ * @var string
42
+ */
43
+ protected static $BEEN_THERE = '__NICE_R_INFINITE_RECURSION_PROTECT__';
44
+
45
+ protected $_has_reflection = null;
46
+
47
+ /**
48
+ * Constructs new renderer instance.
49
+ * @param mixed $value The value to inspect and render.
50
+ * @param boolean $inspectMethods Whether to inspect and output methods for objects or not.
51
+ */
52
+ public function __construct($value, $inspectMethods = false){
53
+ $this->value = $value;
54
+ $this->inspect_methods = $inspectMethods;
55
+
56
+ if(is_null($this->_has_reflection))
57
+ $this->_has_reflection = class_exists('ReflectionClass');
58
+ }
59
+
60
+ /**
61
+ * Generates the inspector HTML and returns it as a string.
62
+ * @return string Generated HTML.
63
+ */
64
+ public function generate(){
65
+ return $this->_generate_value($this->value, $this->css_class);
66
+ }
67
+
68
+ /**
69
+ * Renders the inspector HTML directly to the browser.
70
+ */
71
+ public function render(){
72
+ echo $this->generate();
73
+ }
74
+
75
+ /**
76
+ * Converts a string to HTML, encoding any special characters.
77
+ * @param string $text The original string.
78
+ * @return string The string as HTML.
79
+ */
80
+ protected function _esc_html($text){
81
+ return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
82
+ }
83
+
84
+ protected function _inspect_array(&$html, &$var){
85
+ $has_subitems = false;
86
+
87
+ foreach($var as $k => $v){
88
+ if($k !== self::$BEEN_THERE){
89
+ $html .= $this->_generate_keyvalue($k, $v);
90
+ $has_subitems = true;
91
+ }
92
+ }
93
+
94
+ if(!$has_subitems){
95
+ $html .= '<span class="'.$this->css_class.'_ni">Empty Array</span>';
96
+ }
97
+ }
98
+
99
+ protected function _inspect_object(&$html, &$var){
100
+ // render properties
101
+ $has_subitems = false;
102
+
103
+ foreach((array)$var as $k=>$v){
104
+ if($k !== self::$BEEN_THERE){
105
+ $html .= $this->_generate_keyvalue($k, $v);
106
+ $has_subitems = true;
107
+ }
108
+ }
109
+
110
+ if(!$has_subitems){
111
+ $html .= '<span class="'.$this->css_class.'_ni">No Properties</span>';
112
+ }
113
+
114
+ // render methods (if enabled)
115
+ if($this->inspect_methods){
116
+ $has_subitems = false;
117
+
118
+ foreach((array)get_class_methods($var) as $method){
119
+ $html .= $this->_generate_callable($var, $method);
120
+ $has_subitems = true;
121
+ }
122
+
123
+ if(!$has_subitems){
124
+ $html .= '<span class="'.$this->css_class.'_ni">No Methods</span>';
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Render a single particular value.
131
+ * @param mixed $var The value to render
132
+ * @param string $class Parent CSS class.
133
+ * @param string $id Item HTML id.
134
+ */
135
+ protected function _generate_value($var, $class = '', $id = ''){
136
+ $BEENTHERE = self::$BEEN_THERE;
137
+ $class .= ' '.$this->css_class.'_t_'.gettype($var);
138
+
139
+ $html = '<div id="'.$id.'" class="'.$class.'">';
140
+
141
+ switch(true){
142
+
143
+ // handle arrays
144
+ case is_array($var):
145
+ if(isset($var[$BEENTHERE])){
146
+ $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
147
+ }else{
148
+ $var[$BEENTHERE] = true;
149
+ $this->_inspect_array($html, $var);
150
+ unset($var[$BEENTHERE]);
151
+ }
152
+ break;
153
+
154
+ // handle objects
155
+ case is_object($var):
156
+ if(isset($var->$BEENTHERE)){
157
+ $html .= '<span class="'.$this->css_class.'_ir">Infinite Recursion Detected!</span>';
158
+ }else{
159
+ $var->$BEENTHERE = true;
160
+ $this->_inspect_object($html, $var);
161
+ unset($var->$BEENTHERE);
162
+ }
163
+ break;
164
+
165
+ // handle simple types
166
+ default:
167
+ $html .= $this->_generate_keyvalue('', $var);
168
+ break;
169
+ }
170
+
171
+ return $html . '</div>';
172
+ }
173
+
174
+ /**
175
+ * Generates a new unique ID for tagging elements.
176
+ * @staticvar int $id
177
+ * @return integer An ID unique per request.
178
+ */
179
+ protected function _generate_dropid(){
180
+ static $id = 0;
181
+ return ++$id;
182
+ }
183
+
184
+ /**
185
+ * Render a key-value pair.
186
+ * @staticvar int $id Specifies element id.
187
+ * @param string $key Key name.
188
+ * @param mixed $val Key value.
189
+ */
190
+ protected function _generate_keyvalue($key, $val){
191
+ $id = $this->_generate_dropid();
192
+ $p = ''; // preview
193
+ $d = ''; // description
194
+ $t = gettype($val); // get data type
195
+ $is_hash = ($t=='array') || ($t=='object');
196
+
197
+ switch($t){
198
+ case 'boolean':
199
+ $p = $val ? 'TRUE' : 'FALSE';
200
+ break;
201
+ case 'integer':
202
+ case 'double':
203
+ $p = (string)$val;
204
+ break;
205
+ case 'string':
206
+ $d .= ', '.strlen($val).' characters';
207
+ $p = $val;
208
+ break;
209
+ case 'resource':
210
+ $d .= ', '.get_resource_type($val).' type';
211
+ $p = (string)$val;
212
+ break;
213
+ case 'array':
214
+ $d .= ', '.count($val).' elements';
215
+ break;
216
+ case 'object':
217
+ $d .= ', '.get_class($val).', '.count(get_object_vars($val)).' properties';
218
+ break;
219
+ }
220
+
221
+ $cls = $this->css_class;
222
+ $xcls = !$is_hash ? $cls.'_ad' : '';
223
+ $html = '<a '.($is_hash?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
224
+ $html .= ' <span class="'.$cls.'_a '.$xcls.'" id="'.$this->html_id.'_a'.$id.'">&#9658;</span>';
225
+ $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($key).'</span>';
226
+ $html .= ' <span class="'.$cls.'_d">(<span>'.ucwords($t).'</span>'.$d.')</span>';
227
+ $html .= ' <span class="'.$cls.'_p '.$cls.'_t_'.$t.'">'.$this->_esc_html($p).'</span>';
228
+ $html .= '</a>';
229
+
230
+ if($is_hash){
231
+ $html .= $this->_generate_value($val, $cls.'_v', $this->html_id.'_v'.$id);
232
+ }
233
+
234
+ return $html;
235
+ }
236
+
237
+ protected function _generate_callable($context, $callback){
238
+ $id = $this->_generate_dropid();
239
+ $ref = null;
240
+ $name = 'Anonymous';
241
+ $cls = $this->css_class;
242
+
243
+ if($this->_has_reflection){
244
+ if(is_null($context)){
245
+ $ref = new ReflectionFunction($callback);
246
+ }else{
247
+ $ref = new ReflectionMethod($context, $callback);
248
+ }
249
+ $name = $ref->getName();
250
+ }elseif(is_string($callback)){
251
+ $name = $callback;
252
+ }
253
+
254
+ if(!is_null($ref)){
255
+ $doc = $ref->getDocComment();
256
+ $prms = array();
257
+ foreach($ref->getParameters() as $p){
258
+ $prms[] = '$' . $p->getName() . (
259
+ $p->isDefaultValueAvailable()
260
+ ? (
261
+ ' = <span class="'.$cls.'_mv">' . (
262
+ $p->isDefaultValueConstant()
263
+ ? $p->getDefaultValueConstantName()
264
+ : var_export($p->getDefaultValue(), true)
265
+ ) . '</span>'
266
+ )
267
+ : ''
268
+ );
269
+ }
270
+ }else{
271
+ $doc = null;
272
+ $prms = array('???');
273
+ }
274
+
275
+ $xcls = !$doc ? $cls.'_ad' : '';
276
+ $html = '<a class="'.$cls.'_c" '.($doc?'href="javascript:;"':'').' onclick="'.$this->js_func.'(\''.$this->html_id.'\',\''.$id.'\');">';
277
+ $html .= ' <span class="'.$cls.'_a '.$xcls.'">&#9658;</span>';
278
+ $html .= ' <span class="'.$cls.'_k">'.$this->_esc_html($name).'<span class="'.$cls.'_ma">(<span>'.implode(', ', $prms).'</span>)</span></span>';
279
+ $html .= '</a>';
280
+
281
+ if($doc){
282
+ $html .= '<div id="'.$this->html_id.'_v'.$id.'" class="nice_r_v '.$this->css_class.'_t_comment">';
283
+ $html .= nl2br(str_replace(' ', '&nbsp;', $this->_esc_html($doc)));
284
+ $html .= '</div>';
285
+ }
286
+
287
+ return $html;
288
+ }
289
+ }
classes/SensorManager.php CHANGED
@@ -1,50 +1,50 @@
1
- <?php
2
-
3
- final class WSAL_SensorManager extends WSAL_AbstractSensor {
4
-
5
- /**
6
- * @var WSAL_AbstractSensor[]
7
- */
8
- protected $sensors = array();
9
-
10
- public function __construct(WpSecurityAuditLog $plugin){
11
- parent::__construct($plugin);
12
-
13
- foreach(glob(dirname(__FILE__) . '/Sensors/*.php') as $file)
14
- $this->AddFromFile ($file);
15
- }
16
-
17
- public function HookEvents() {
18
- foreach($this->sensors as $sensor)
19
- $sensor->HookEvents();
20
- }
21
-
22
- public function GetSensors(){
23
- return $this->sensors;
24
- }
25
-
26
- /**
27
- * Add new sensor from file inside autoloader path.
28
- * @param string $file Path to file.
29
- */
30
- public function AddFromFile($file){
31
- $this->AddFromClass($this->plugin->GetClassFileClassName($file));
32
- }
33
-
34
- /**
35
- * Add new sensor given class name.
36
- * @param string $class Class name.
37
- */
38
- public function AddFromClass($class){
39
- $this->AddInstance(new $class($this->plugin));
40
- }
41
-
42
- /**
43
- * Add newly created sensor to list.
44
- * @param WSAL_AbstractSensor $sensor The new sensor.
45
- */
46
- public function AddInstance(WSAL_AbstractSensor $sensor){
47
- $this->sensors[] = $sensor;
48
- }
49
-
50
  }
1
+ <?php
2
+
3
+ final class WSAL_SensorManager extends WSAL_AbstractSensor {
4
+
5
+ /**
6
+ * @var WSAL_AbstractSensor[]
7
+ */
8
+ protected $sensors = array();
9
+
10
+ public function __construct(WpSecurityAuditLog $plugin){
11
+ parent::__construct($plugin);
12
+
13
+ foreach(glob(dirname(__FILE__) . '/Sensors/*.php') as $file)
14
+ $this->AddFromFile ($file);
15
+ }
16
+
17
+ public function HookEvents() {
18
+ foreach($this->sensors as $sensor)
19
+ $sensor->HookEvents();
20
+ }
21
+
22
+ public function GetSensors(){
23
+ return $this->sensors;
24
+ }
25
+
26
+ /**
27
+ * Add new sensor from file inside autoloader path.
28
+ * @param string $file Path to file.
29
+ */
30
+ public function AddFromFile($file){
31
+ $this->AddFromClass($this->plugin->GetClassFileClassName($file));
32
+ }
33
+
34
+ /**
35
+ * Add new sensor given class name.
36
+ * @param string $class Class name.
37
+ */
38
+ public function AddFromClass($class){
39
+ $this->AddInstance(new $class($this->plugin));
40
+ }
41
+
42
+ /**
43
+ * Add newly created sensor to list.
44
+ * @param WSAL_AbstractSensor $sensor The new sensor.
45
+ */
46
+ public function AddInstance(WSAL_AbstractSensor $sensor){
47
+ $this->sensors[] = $sensor;
48
+ }
49
+
50
  }
classes/Sensors/BBPress.php CHANGED
@@ -1,412 +1,412 @@
1
- <?php
2
- /**
3
- * Support for BBPress Forum Plugin
4
- */
5
- class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
6
- {
7
- protected $_OldPost = null;
8
- protected $_OldLink = null;
9
-
10
- public function HookEvents()
11
- {
12
- if (current_user_can("edit_posts")) {
13
- add_action('admin_init', array($this, 'EventAdminInit'));
14
- }
15
- add_action('post_updated', array($this, 'CheckForumChange'), 10, 3);
16
- add_action('delete_post', array($this, 'EventForumDeleted'), 10, 1);
17
- add_action('wp_trash_post', array($this, 'EventForumTrashed'), 10, 1);
18
- add_action('untrash_post', array($this, 'EventForumUntrashed'));
19
- }
20
-
21
- public function EventAdminInit()
22
- {
23
- // load old data, if applicable
24
- $this->RetrieveOldData();
25
- // check for Ajax changes
26
- $this->TriggerAjaxChange();
27
- }
28
-
29
- protected function RetrieveOldData()
30
- {
31
- if (isset($_POST) && isset($_POST['post_ID'])
32
- && !(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
33
- && !(isset($_POST['action']) && $_POST['action'] == 'autosave')
34
- ) {
35
- $postID = intval($_POST['post_ID']);
36
- $this->_OldPost = get_post($postID);
37
- $this->_OldLink = get_permalink($postID);
38
- }
39
- }
40
-
41
- public function CheckForumChange($post_ID, $newpost, $oldpost)
42
- {
43
- if ($this->CheckBBPress($oldpost)) {
44
- $changes = 0 + $this->EventForumCreation($oldpost, $newpost);
45
- // Change Visibility
46
- if (!$changes) {
47
- $changes = $this->EventForumChangedVisibility($oldpost);
48
- }
49
- // Change Type
50
- if (!$changes) {
51
- $changes = $this->EventForumChangedType($oldpost);
52
- }
53
- // Change status
54
- if (!$changes) {
55
- $changes = $this->EventForumChangedStatus($oldpost);
56
- }
57
- // Change Order, Parent or URL
58
- if (!$changes) {
59
- $changes = $this->EventForumChanged($oldpost, $newpost);
60
- }
61
- }
62
- }
63
-
64
- /**
65
- * Permanently deleted
66
- */
67
- public function EventForumDeleted($post_id)
68
- {
69
- $post = get_post($post_id);
70
- if ($this->CheckBBPress($post)) {
71
- switch ($post->post_type) {
72
- case 'forum':
73
- $this->EventForumByCode($post, 8006);
74
- break;
75
- case 'topic':
76
- $this->EventTopicByCode($post, 8020);
77
- break;
78
- }
79
- }
80
- }
81
-
82
- /**
83
- * Moved to Trash
84
- */
85
- public function EventForumTrashed($post_id)
86
- {
87
- $post = get_post($post_id);
88
- if ($this->CheckBBPress($post)) {
89
- switch ($post->post_type) {
90
- case 'forum':
91
- $this->EventForumByCode($post, 8005);
92
- break;
93
- case 'topic':
94
- $this->EventTopicByCode($post, 8019);
95
- break;
96
- }
97
- }
98
- }
99
-
100
- /**
101
- * Restored from Trash
102
- */
103
- public function EventForumUntrashed($post_id)
104
- {
105
- $post = get_post($post_id);
106
- if ($this->CheckBBPress($post)) {
107
- switch ($post->post_type) {
108
- case 'forum':
109
- $this->EventForumByCode($post, 8007);
110
- break;
111
- case 'topic':
112
- $this->EventTopicByCode($post, 8021);
113
- break;
114
- }
115
- }
116
- }
117
-
118
- private function CheckBBPress($post)
119
- {
120
- switch ($post->post_type) {
121
- case 'forum':
122
- case 'topic':
123
- case 'reply':
124
- return true;
125
- default:
126
- return false;
127
- }
128
- }
129
-
130
- private function EventForumCreation($old_post, $new_post)
131
- {
132
- $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
133
- if ($old_post->post_status == 'draft' || $original == 'auto-draft') {
134
- if ($new_post->post_status == 'publish') {
135
- switch ($old_post->post_type) {
136
- case 'forum':
137
- $this->plugin->alerts->Trigger(8000, array(
138
- 'ForumName' => $new_post->post_title,
139
- 'ForumURL' => get_permalink($new_post->ID)
140
- ));
141
- break;
142
- case 'topic':
143
- $this->plugin->alerts->Trigger(8014, array(
144
- 'TopicName' => $new_post->post_title,
145
- 'TopicURL' => get_permalink($new_post->ID)
146
- ));
147
- break;
148
- }
149
- return 1;
150
- }
151
- }
152
- return 0;
153
- }
154
-
155
- private function EventForumChangedVisibility($post)
156
- {
157
- $result = 0;
158
- switch ($post->post_type) {
159
- case 'forum':
160
- $oldVisibility = !empty($_REQUEST['visibility']) ? $_REQUEST['visibility'] : '';
161
- $newVisibility = !empty($_REQUEST['bbp_forum_visibility']) ? $_REQUEST['bbp_forum_visibility'] : '';
162
- $newVisibility = ($newVisibility == 'publish') ? 'public' : $newVisibility;
163
-
164
- if (!empty($newVisibility) && $oldVisibility != 'auto-draft' && $oldVisibility != $newVisibility) {
165
- $this->plugin->alerts->Trigger(8002, array(
166
- 'ForumName' => $post->post_title,
167
- 'OldVisibility' => $oldVisibility,
168
- 'NewVisibility' => $newVisibility
169
- ));
170
- $result = 1;
171
- }
172
- break;
173
- case 'topic':
174
- $oldVisibility = !empty($_REQUEST['hidden_post_visibility']) ? $_REQUEST['hidden_post_visibility'] : '';
175
- $newVisibility = !empty($_REQUEST['visibility']) ? $_REQUEST['visibility'] : '';
176
- $newVisibility = ($newVisibility == 'password') ? 'password protected' : $newVisibility;
177
-
178
- if (!empty($newVisibility) && $oldVisibility != 'auto-draft' && $oldVisibility != $newVisibility) {
179
- $this->plugin->alerts->Trigger(8022, array(
180
- 'TopicName' => $post->post_title,
181
- 'OldVisibility' => $oldVisibility,
182
- 'NewVisibility' => $newVisibility
183
- ));
184
- $result = 1;
185
- }
186
- break;
187
- }
188
- return $result;
189
- }
190
-
191
- private function EventForumChangedType($post)
192
- {
193
- $result = 0;
194
- switch ($post->post_type) {
195
- case 'forum':
196
- $bbp_forum_type = get_post_meta($post->ID, '_bbp_forum_type', true);
197
- $oldType = !empty($bbp_forum_type) ? $bbp_forum_type : 'forum';
198
- $newType = !empty($_POST['bbp_forum_type']) ? $_POST['bbp_forum_type'] : '';
199
- if (!empty($newType) && $oldType != $newType) {
200
- $this->plugin->alerts->Trigger(8011, array(
201
- 'ForumName' => $post->post_title,
202
- 'OldType' => $oldType,
203
- 'NewType' => $newType
204
- ));
205
- $result = 1;
206
- }
207
- break;
208
- case 'topic':
209
- if (!empty($_POST['parent_id'])) {
210
- $post_id = $_POST['parent_id'];
211
- } else {
212
- $post_id = $post->ID;
213
- }
214
- $bbp_sticky_topics = maybe_unserialize(get_post_meta($post_id, '_bbp_sticky_topics', true));
215
- $fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
216
- $bbp_super_sticky_topics = maybe_unserialize($fn('_bbp_super_sticky_topics'));
217
- if (!empty($bbp_sticky_topics) && in_array($post->ID, $bbp_sticky_topics)) {
218
- $oldType = 'sticky';
219
- } elseif (!empty($bbp_super_sticky_topics) && in_array($post->ID, $bbp_super_sticky_topics)) {
220
- $oldType = 'super';
221
- } else {
222
- $oldType = 'unstick';
223
- }
224
- $newType = !empty($_POST['bbp_stick_topic']) ? $_POST['bbp_stick_topic'] : '';
225
- if (!empty($newType) && $oldType != $newType) {
226
- $this->plugin->alerts->Trigger(8016, array(
227
- 'TopicName' => $post->post_title,
228
- 'OldType' => ($oldType == 'unstick') ? 'normal' : (($oldType == 'super') ? 'super sticky' : $oldType),
229
- 'NewType' => ($newType == 'unstick') ? 'normal' : (($newType == 'super') ? 'super sticky' : $newType)
230
- ));
231
- $result = 1;
232
- }
233
- break;
234
- }
235
- return $result;
236
- }
237
-
238
- private function EventForumChangedStatus($post)
239
- {
240
- $result = 0;
241
- switch ($post->post_type) {
242
- case 'forum':
243
- $bbp_status = get_post_meta($post->ID, '_bbp_status', true);
244
- $oldStatus = !empty($bbp_status) ? $bbp_status : 'open';
245
- $newStatus = !empty($_REQUEST['bbp_forum_status']) ? $_REQUEST['bbp_forum_status'] : '';
246
- if (!empty($newStatus) && $oldStatus != $newStatus) {
247
- $this->plugin->alerts->Trigger(8001, array(
248
- 'ForumName' => $post->post_title,
249
- 'OldStatus' => $oldStatus,
250
- 'NewStatus' => $newStatus
251
- ));
252
- $result = 1;
253
- }
254
- break;
255
- case 'topic':
256
- $oldStatus = !empty($_REQUEST['original_post_status']) ? $_REQUEST['original_post_status'] : '';
257
- $newStatus = !empty($_REQUEST['post_status']) ? $_REQUEST['post_status'] : '';
258
- // In case of Ajax request Spam/Not spam
259
- if (isset($_GET['action']) && $_GET['action'] == 'bbp_toggle_topic_spam') {
260
- $oldStatus = $post->post_status;
261
- $newStatus = 'spam';
262
- if (isset($_GET['post_status']) && $_GET['post_status'] == 'spam') {
263
- $newStatus = 'publish';
264
- }
265
- }
266
- // In case of Ajax request Close/Open
267
- if (isset($_GET['action']) && $_GET['action'] == 'bbp_toggle_topic_close') {
268
- $oldStatus = $post->post_status;
269
- $newStatus = 'closed';
270
- if (isset($_GET['post_status']) && $_GET['post_status'] == 'closed') {
271
- $newStatus = 'publish';
272
- }
273
- }
274
- if (!empty($newStatus) && $oldStatus != $newStatus) {
275
- $this->plugin->alerts->Trigger(8015, array(
276
- 'TopicName' => $post->post_title,
277
- 'OldStatus' => ($oldStatus == 'publish') ? 'open' : $oldStatus,
278
- 'NewStatus' => ($newStatus == 'publish') ? 'open' : $newStatus
279
- ));
280
- $result = 1;
281
- }
282
- break;
283
- }
284
- return $result;
285
- }
286
-
287
- private function EventForumChanged($old_post, $new_post)
288
- {
289
- // Changed Order
290
- if ($old_post->menu_order != $new_post->menu_order) {
291
- $this->plugin->alerts->Trigger(8004, array(
292
- 'ForumName' => $new_post->post_title,
293
- 'OldOrder' => $old_post->menu_order,
294
- 'NewOrder' => $new_post->menu_order
295
- ));
296
- return 1;
297
- }
298
- // Changed Parent
299
- if ($old_post->post_parent != $new_post->post_parent) {
300
- switch ($old_post->post_type) {
301
- case 'forum':
302
- $this->plugin->alerts->Trigger(8008, array(
303
- 'ForumName' => $new_post->post_title,
304
- 'OldParent' => $old_post->post_parent ? get_the_title($old_post->post_parent) : 'no parent',
305
- 'NewParent' => $new_post->post_parent ? get_the_title($new_post->post_parent) : 'no parent'
306
- ));
307
- break;
308
- case 'topic':
309
- $this->plugin->alerts->Trigger(8018, array(
310
- 'TopicName' => $new_post->post_title,
311
- 'OldForum' => $old_post->post_parent ? get_the_title($old_post->post_parent) : 'no parent',
312
- 'NewForum' => $new_post->post_parent ? get_the_title($new_post->post_parent) : 'no parent'
313
- ));
314
- break;
315
- }
316
- return 1;
317
- }
318
- // Changed URL
319
- $oldLink = $this->_OldLink;
320
- $newLink = get_permalink($new_post->ID);
321
- if (!empty($oldLink) && $oldLink != $newLink) {
322
- switch ($old_post->post_type) {
323
- case 'forum':
324
- $this->plugin->alerts->Trigger(8003, array(
325
- 'ForumName' => $new_post->post_title,
326
- 'OldUrl' => $oldLink,
327
- 'NewUrl' => $newLink
328
- ));
329
- break;
330
- case 'topic':
331
- $this->plugin->alerts->Trigger(8017, array(
332
- 'TopicName' => $new_post->post_title,
333
- 'OldUrl' => $oldLink,
334
- 'NewUrl' => $newLink
335
- ));
336
- break;
337
- }
338
- return 1;
339
- }
340
- return 0;
341
- }
342
-
343
- private function EventForumByCode($post, $event)
344
- {
345
- $this->plugin->alerts->Trigger($event, array(
346
- 'ForumID' => $post->ID,
347
- 'ForumName' => $post->post_title
348
- ));
349
- }
350
-
351
- private function EventTopicByCode($post, $event)
352
- {
353
- $this->plugin->alerts->Trigger($event, array(
354
- 'TopicID' => $post->ID,
355
- 'TopicName' => $post->post_title
356
- ));
357
- }
358
-
359
- /**
360
- * Trigger of ajax events generated in the Topic Grid
361
- */
362
- public function TriggerAjaxChange()
363
- {
364
- if (!empty($_GET['post_type']) && !empty($_GET['topic_id'])) {
365
- if ($_GET['post_type'] == 'topic') {
366
- $post = get_post($_GET['topic_id']);
367
-
368
- // Topic type
369
- if (isset($_GET['action']) && $_GET['action'] == 'bbp_toggle_topic_stick') {
370
- if (!empty($post->post_parent)) {
371
- $post_id = $post->post_parent;
372
- } else {
373
- $post_id = $_GET['topic_id'];
374
- }
375
-
376
- $bbp_sticky_topics = maybe_unserialize(get_post_meta($post_id, '_bbp_sticky_topics', true));
377
- $fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
378
- $bbp_super_sticky_topics = maybe_unserialize($fn('_bbp_super_sticky_topics'));
379
- if (!empty($bbp_sticky_topics) && in_array($_GET['topic_id'], $bbp_sticky_topics)) {
380
- $oldType = 'sticky';
381
- } elseif (!empty($bbp_super_sticky_topics) && in_array($_GET['topic_id'], $bbp_super_sticky_topics)) {
382
- $oldType = 'super sticky';
383
- } else {
384
- $oldType = 'normal';
385
- }
386
-
387
- switch ($oldType) {
388
- case 'sticky':
389
- case 'super sticky':
390
- $newType = 'normal';
391
- break;
392
- case 'normal':
393
- if (isset($_GET['super']) && $_GET['super'] == 1) {
394
- $newType = 'super sticky';
395
- } else {
396
- $newType = 'sticky';
397
- }
398
- break;
399
- }
400
-
401
- if (!empty($newType) && $oldType != $newType) {
402
- $this->plugin->alerts->Trigger(8016, array(
403
- 'TopicName' => $post->post_title,
404
- 'OldType' => $oldType,
405
- 'NewType' => $newType
406
- ));
407
- }
408
- }
409
- }
410
- }
411
- }
412
- }
1
+ <?php
2
+ /**
3
+ * Support for BBPress Forum Plugin
4
+ */
5
+ class WSAL_Sensors_BBPress extends WSAL_AbstractSensor
6
+ {
7
+ protected $_OldPost = null;
8
+ protected $_OldLink = null;
9
+
10
+ public function HookEvents()
11
+ {
12
+ if (current_user_can("edit_posts")) {
13
+ add_action('admin_init', array($this, 'EventAdminInit'));
14
+ }
15
+ add_action('post_updated', array($this, 'CheckForumChange'), 10, 3);
16
+ add_action('delete_post', array($this, 'EventForumDeleted'), 10, 1);
17
+ add_action('wp_trash_post', array($this, 'EventForumTrashed'), 10, 1);
18
+ add_action('untrash_post', array($this, 'EventForumUntrashed'));
19
+ }
20
+
21
+ public function EventAdminInit()
22
+ {
23
+ // load old data, if applicable
24
+ $this->RetrieveOldData();
25
+ // check for Ajax changes
26
+ $this->TriggerAjaxChange();
27
+ }
28
+
29
+ protected function RetrieveOldData()
30
+ {
31
+ if (isset($_POST) && isset($_POST['post_ID'])
32
+ && !(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
33
+ && !(isset($_POST['action']) && $_POST['action'] == 'autosave')
34
+ ) {
35
+ $postID = intval($_POST['post_ID']);
36
+ $this->_OldPost = get_post($postID);
37
+ $this->_OldLink = get_permalink($postID);
38
+ }
39
+ }
40
+
41
+ public function CheckForumChange($post_ID, $newpost, $oldpost)
42
+ {
43
+ if ($this->CheckBBPress($oldpost)) {
44
+ $changes = 0 + $this->EventForumCreation($oldpost, $newpost);
45
+ // Change Visibility
46
+ if (!$changes) {
47
+ $changes = $this->EventForumChangedVisibility($oldpost);
48
+ }
49
+ // Change Type
50
+ if (!$changes) {
51
+ $changes = $this->EventForumChangedType($oldpost);
52
+ }
53
+ // Change status
54
+ if (!$changes) {
55
+ $changes = $this->EventForumChangedStatus($oldpost);
56
+ }
57
+ // Change Order, Parent or URL
58
+ if (!$changes) {
59
+ $changes = $this->EventForumChanged($oldpost, $newpost);
60
+ }
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Permanently deleted
66
+ */
67
+ public function EventForumDeleted($post_id)
68
+ {
69
+ $post = get_post($post_id);
70
+ if ($this->CheckBBPress($post)) {
71
+ switch ($post->post_type) {
72
+ case 'forum':
73
+ $this->EventForumByCode($post, 8006);
74
+ break;
75
+ case 'topic':
76
+ $this->EventTopicByCode($post, 8020);
77
+ break;
78
+ }
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Moved to Trash
84
+ */
85
+ public function EventForumTrashed($post_id)
86
+ {
87
+ $post = get_post($post_id);
88
+ if ($this->CheckBBPress($post)) {
89
+ switch ($post->post_type) {
90
+ case 'forum':
91
+ $this->EventForumByCode($post, 8005);
92
+ break;
93
+ case 'topic':
94
+ $this->EventTopicByCode($post, 8019);
95
+ break;
96
+ }
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Restored from Trash
102
+ */
103
+ public function EventForumUntrashed($post_id)
104
+ {
105
+ $post = get_post($post_id);
106
+ if ($this->CheckBBPress($post)) {
107
+ switch ($post->post_type) {
108
+ case 'forum':
109
+ $this->EventForumByCode($post, 8007);
110
+ break;
111
+ case 'topic':
112
+ $this->EventTopicByCode($post, 8021);
113
+ break;
114
+ }
115
+ }
116
+ }
117
+
118
+ private function CheckBBPress($post)
119
+ {
120
+ switch ($post->post_type) {
121
+ case 'forum':
122
+ case 'topic':
123
+ case 'reply':
124
+ return true;
125
+ default:
126
+ return false;
127
+ }
128
+ }
129
+
130
+ private function EventForumCreation($old_post, $new_post)
131
+ {
132
+ $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
133
+ if ($old_post->post_status == 'draft' || $original == 'auto-draft') {
134
+ if ($new_post->post_status == 'publish') {
135
+ switch ($old_post->post_type) {
136
+ case 'forum':
137
+ $this->plugin->alerts->Trigger(8000, array(
138
+ 'ForumName' => $new_post->post_title,
139
+ 'ForumURL' => get_permalink($new_post->ID)
140
+ ));
141
+ break;
142
+ case 'topic':
143
+ $this->plugin->alerts->Trigger(8014, array(
144
+ 'TopicName' => $new_post->post_title,
145
+ 'TopicURL' => get_permalink($new_post->ID)
146
+ ));
147
+ break;
148
+ }
149
+ return 1;
150
+ }
151
+ }
152
+ return 0;
153
+ }
154
+
155
+ private function EventForumChangedVisibility($post)
156
+ {
157
+ $result = 0;
158
+ switch ($post->post_type) {
159
+ case 'forum':
160
+ $oldVisibility = !empty($_REQUEST['visibility']) ? $_REQUEST['visibility'] : '';
161
+ $newVisibility = !empty($_REQUEST['bbp_forum_visibility']) ? $_REQUEST['bbp_forum_visibility'] : '';
162
+ $newVisibility = ($newVisibility == 'publish') ? 'public' : $newVisibility;
163
+
164
+ if (!empty($newVisibility) && $oldVisibility != 'auto-draft' && $oldVisibility != $newVisibility) {
165
+ $this->plugin->alerts->Trigger(8002, array(
166
+ 'ForumName' => $post->post_title,
167
+ 'OldVisibility' => $oldVisibility,
168
+ 'NewVisibility' => $newVisibility
169
+ ));
170
+ $result = 1;
171
+ }
172
+ break;
173
+ case 'topic':
174
+ $oldVisibility = !empty($_REQUEST['hidden_post_visibility']) ? $_REQUEST['hidden_post_visibility'] : '';
175
+ $newVisibility = !empty($_REQUEST['visibility']) ? $_REQUEST['visibility'] : '';
176
+ $newVisibility = ($newVisibility == 'password') ? 'password protected' : $newVisibility;
177
+
178
+ if (!empty($newVisibility) && $oldVisibility != 'auto-draft' && $oldVisibility != $newVisibility) {
179
+ $this->plugin->alerts->Trigger(8022, array(
180
+ 'TopicName' => $post->post_title,
181
+ 'OldVisibility' => $oldVisibility,
182
+ 'NewVisibility' => $newVisibility
183
+ ));
184
+ $result = 1;
185
+ }
186
+ break;
187
+ }
188
+ return $result;
189
+ }
190
+
191
+ private function EventForumChangedType($post)
192
+ {
193
+ $result = 0;
194
+ switch ($post->post_type) {
195
+ case 'forum':
196
+ $bbp_forum_type = get_post_meta($post->ID, '_bbp_forum_type', true);
197
+ $oldType = !empty($bbp_forum_type) ? $bbp_forum_type : 'forum';
198
+ $newType = !empty($_POST['bbp_forum_type']) ? $_POST['bbp_forum_type'] : '';
199
+ if (!empty($newType) && $oldType != $newType) {
200
+ $this->plugin->alerts->Trigger(8011, array(
201
+ 'ForumName' => $post->post_title,
202
+ 'OldType' => $oldType,
203
+ 'NewType' => $newType
204
+ ));
205
+ $result = 1;
206
+ }
207
+ break;
208
+ case 'topic':
209
+ if (!empty($_POST['parent_id'])) {
210
+ $post_id = $_POST['parent_id'];
211
+ } else {
212
+ $post_id = $post->ID;
213
+ }
214
+ $bbp_sticky_topics = maybe_unserialize(get_post_meta($post_id, '_bbp_sticky_topics', true));
215
+ $fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
216
+ $bbp_super_sticky_topics = maybe_unserialize($fn('_bbp_super_sticky_topics'));
217
+ if (!empty($bbp_sticky_topics) && in_array($post->ID, $bbp_sticky_topics)) {
218
+ $oldType = 'sticky';
219
+ } elseif (!empty($bbp_super_sticky_topics) && in_array($post->ID, $bbp_super_sticky_topics)) {
220
+ $oldType = 'super';
221
+ } else {
222
+ $oldType = 'unstick';
223
+ }
224
+ $newType = !empty($_POST['bbp_stick_topic']) ? $_POST['bbp_stick_topic'] : '';
225
+ if (!empty($newType) && $oldType != $newType) {
226
+ $this->plugin->alerts->Trigger(8016, array(
227
+ 'TopicName' => $post->post_title,
228
+ 'OldType' => ($oldType == 'unstick') ? 'normal' : (($oldType == 'super') ? 'super sticky' : $oldType),
229
+ 'NewType' => ($newType == 'unstick') ? 'normal' : (($newType == 'super') ? 'super sticky' : $newType)
230
+ ));
231
+ $result = 1;
232
+ }
233
+ break;
234
+ }
235
+ return $result;
236
+ }
237
+
238
+ private function EventForumChangedStatus($post)
239
+ {
240
+ $result = 0;
241
+ switch ($post->post_type) {
242
+ case 'forum':
243
+ $bbp_status = get_post_meta($post->ID, '_bbp_status', true);
244
+ $oldStatus = !empty($bbp_status) ? $bbp_status : 'open';
245
+ $newStatus = !empty($_REQUEST['bbp_forum_status']) ? $_REQUEST['bbp_forum_status'] : '';
246
+ if (!empty($newStatus) && $oldStatus != $newStatus) {
247
+ $this->plugin->alerts->Trigger(8001, array(
248
+ 'ForumName' => $post->post_title,
249
+ 'OldStatus' => $oldStatus,
250
+ 'NewStatus' => $newStatus
251
+ ));
252
+ $result = 1;
253
+ }
254
+ break;
255
+ case 'topic':
256
+ $oldStatus = !empty($_REQUEST['original_post_status']) ? $_REQUEST['original_post_status'] : '';
257
+ $newStatus = !empty($_REQUEST['post_status']) ? $_REQUEST['post_status'] : '';
258
+ // In case of Ajax request Spam/Not spam
259
+ if (isset($_GET['action']) && $_GET['action'] == 'bbp_toggle_topic_spam') {
260
+ $oldStatus = $post->post_status;
261
+ $newStatus = 'spam';
262
+ if (isset($_GET['post_status']) && $_GET['post_status'] == 'spam') {
263
+ $newStatus = 'publish';
264
+ }
265
+ }
266
+ // In case of Ajax request Close/Open
267
+ if (isset($_GET['action']) && $_GET['action'] == 'bbp_toggle_topic_close') {
268
+ $oldStatus = $post->post_status;
269
+ $newStatus = 'closed';
270
+ if (isset($_GET['post_status']) && $_GET['post_status'] == 'closed') {
271
+ $newStatus = 'publish';
272
+ }
273
+ }
274
+ if (!empty($newStatus) && $oldStatus != $newStatus) {
275
+ $this->plugin->alerts->Trigger(8015, array(
276
+ 'TopicName' => $post->post_title,
277
+ 'OldStatus' => ($oldStatus == 'publish') ? 'open' : $oldStatus,
278
+ 'NewStatus' => ($newStatus == 'publish') ? 'open' : $newStatus
279
+ ));
280
+ $result = 1;
281
+ }
282
+ break;
283
+ }
284
+ return $result;
285
+ }
286
+
287
+ private function EventForumChanged($old_post, $new_post)
288
+ {
289
+ // Changed Order
290
+ if ($old_post->menu_order != $new_post->menu_order) {
291
+ $this->plugin->alerts->Trigger(8004, array(
292
+ 'ForumName' => $new_post->post_title,
293
+ 'OldOrder' => $old_post->menu_order,
294
+ 'NewOrder' => $new_post->menu_order
295
+ ));
296
+ return 1;
297
+ }
298
+ // Changed Parent
299
+ if ($old_post->post_parent != $new_post->post_parent) {
300
+ switch ($old_post->post_type) {
301
+ case 'forum':
302
+ $this->plugin->alerts->Trigger(8008, array(
303
+ 'ForumName' => $new_post->post_title,
304
+ 'OldParent' => $old_post->post_parent ? get_the_title($old_post->post_parent) : 'no parent',
305
+ 'NewParent' => $new_post->post_parent ? get_the_title($new_post->post_parent) : 'no parent'
306
+ ));
307
+ break;
308
+ case 'topic':
309
+ $this->plugin->alerts->Trigger(8018, array(
310
+ 'TopicName' => $new_post->post_title,
311
+ 'OldForum' => $old_post->post_parent ? get_the_title($old_post->post_parent) : 'no parent',
312
+ 'NewForum' => $new_post->post_parent ? get_the_title($new_post->post_parent) : 'no parent'
313
+ ));
314
+ break;
315
+ }
316
+ return 1;
317
+ }
318
+ // Changed URL
319
+ $oldLink = $this->_OldLink;
320
+ $newLink = get_permalink($new_post->ID);
321
+ if (!empty($oldLink) && $oldLink != $newLink) {
322
+ switch ($old_post->post_type) {
323
+ case 'forum':
324
+ $this->plugin->alerts->Trigger(8003, array(
325
+ 'ForumName' => $new_post->post_title,
326
+ 'OldUrl' => $oldLink,
327
+ 'NewUrl' => $newLink
328
+ ));
329
+ break;
330
+ case 'topic':
331
+ $this->plugin->alerts->Trigger(8017, array(
332
+ 'TopicName' => $new_post->post_title,
333
+ 'OldUrl' => $oldLink,
334
+ 'NewUrl' => $newLink
335
+ ));
336
+ break;
337
+ }
338
+ return 1;
339
+ }
340
+ return 0;
341
+ }
342
+
343
+ private function EventForumByCode($post, $event)
344
+ {
345
+ $this->plugin->alerts->Trigger($event, array(
346
+ 'ForumID' => $post->ID,
347
+ 'ForumName' => $post->post_title
348
+ ));
349
+ }
350
+
351
+ private function EventTopicByCode($post, $event)
352
+ {
353
+ $this->plugin->alerts->Trigger($event, array(
354
+ 'TopicID' => $post->ID,
355
+ 'TopicName' => $post->post_title
356
+ ));
357
+ }
358
+
359
+ /**
360
+ * Trigger of ajax events generated in the Topic Grid
361
+ */
362
+ public function TriggerAjaxChange()
363
+ {
364
+ if (!empty($_GET['post_type']) && !empty($_GET['topic_id'])) {
365
+ if ($_GET['post_type'] == 'topic') {
366
+ $post = get_post($_GET['topic_id']);
367
+
368
+ // Topic type
369
+ if (isset($_GET['action']) && $_GET['action'] == 'bbp_toggle_topic_stick') {
370
+ if (!empty($post->post_parent)) {
371
+ $post_id = $post->post_parent;
372
+ } else {
373
+ $post_id = $_GET['topic_id'];
374
+ }
375
+
376
+ $bbp_sticky_topics = maybe_unserialize(get_post_meta($post_id, '_bbp_sticky_topics', true));
377
+ $fn = $this->IsMultisite() ? 'get_site_option' : 'get_option';
378
+ $bbp_super_sticky_topics = maybe_unserialize($fn('_bbp_super_sticky_topics'));
379
+ if (!empty($bbp_sticky_topics) && in_array($_GET['topic_id'], $bbp_sticky_topics)) {
380
+ $oldType = 'sticky';
381
+ } elseif (!empty($bbp_super_sticky_topics) && in_array($_GET['topic_id'], $bbp_super_sticky_topics)) {
382
+ $oldType = 'super sticky';
383
+ } else {
384
+ $oldType = 'normal';
385
+ }
386
+
387
+ switch ($oldType) {
388
+ case 'sticky':
389
+ case 'super sticky':
390
+ $newType = 'normal';
391
+ break;
392
+ case 'normal':
393
+ if (isset($_GET['super']) && $_GET['super'] == 1) {
394
+ $newType = 'super sticky';
395
+ } else {
396
+ $newType = 'sticky';
397
+ }
398
+ break;
399
+ }
400
+
401
+ if (!empty($newType) && $oldType != $newType) {
402
+ $this->plugin->alerts->Trigger(8016, array(
403
+ 'TopicName' => $post->post_title,
404
+ 'OldType' => $oldType,
405
+ 'NewType' => $newType
406
+ ));
407
+ }
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
classes/Sensors/Content.php CHANGED
@@ -1,635 +1,635 @@
1
- <?php
2
-
3
- class WSAL_Sensors_Content extends WSAL_AbstractSensor
4
- {
5
-
6
- public function HookEvents()
7
- {
8
- if (current_user_can("edit_posts")) {
9
- add_action('admin_init', array($this, 'EventWordpressInit'));
10
- }
11
- add_action('transition_post_status', array($this, 'EventPostChanged'), 10, 3);
12
- add_action('delete_post', array($this, 'EventPostDeleted'), 10, 1);
13
- add_action('wp_trash_post', array($this, 'EventPostTrashed'), 10, 1);
14
- add_action('untrash_post', array($this, 'EventPostUntrashed'));
15
- add_action('edit_category', array($this, 'EventChangedCategoryParent'));
16
- add_action('save_post', array($this, 'SetRevisionLink'), 10, 3);
17
- add_action('publish_future_post', array($this, 'EventPublishFuture'), 10, 1);
18
- }
19
-
20
- protected function GetEventTypeForPostType($post, $typePost, $typePage, $typeCustom)
21
- {
22
- switch ($post->post_type) {
23
- case 'page':
24
- return $typePage;
25
- case 'post':
26
- return $typePost;
27
- default:
28
- return $typeCustom;
29
- }
30
- }
31
-
32
- protected $_OldPost = null;
33
- protected $_OldLink = null;
34
- protected $_OldCats = null;
35
- protected $_OldTmpl = null;
36
- protected $_OldStky = null;
37
-
38
- public function EventWordpressInit()
39
- {
40
- // load old data, if applicable
41
- $this->RetrieveOldData();
42
- // check for category changes
43
- $this->CheckCategoryCreation();
44
- $this->CheckCategoryDeletion();
45
- }
46
-
47
- protected function RetrieveOldData()
48
- {
49
- if (isset($_POST) && isset($_POST['post_ID'])
50
- && !(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
51
- && !(isset($_POST['action']) && $_POST['action'] == 'autosave')
52
- ) {
53
- $postID = intval($_POST['post_ID']);
54
- $this->_OldPost = get_post($postID);
55
- $this->_OldLink = get_permalink($postID);
56
- $this->_OldTmpl = $this->GetPostTemplate($this->_OldPost);
57
- $this->_OldCats = $this->GetPostCategories($this->_OldPost);
58
- $this->_OldStky = in_array($postID, get_option('sticky_posts'));
59
- }
60
- }
61
-
62
- protected function GetPostTemplate($post)
63
- {
64
- $id = $post->ID;
65
- $template = get_page_template_slug($id);
66
- $pagename = $post->post_name;
67
-
68
- $templates = array();
69
- if ($template && 0 === validate_file($template)) {
70
- $templates[] = $template;
71
- }
72
- if ($pagename) {
73
- $templates[] = "page-$pagename.php";
74
- }
75
- if ($id) {
76
- $templates[] = "page-$id.php";
77
- }
78
- $templates[] = 'page.php';
79
-
80
- return get_query_template('page', $templates);
81
- }
82
-
83
- protected function GetPostCategories($post)
84
- {
85
- return wp_get_post_categories($post->ID, array('fields' => 'names'));
86
- }
87
-
88
- public function EventPostChanged($newStatus, $oldStatus, $post)
89
- {
90
- // ignorable states
91
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
92
- return;
93
- }
94
- if (empty($post->post_type)) {
95
- return;
96
- }
97
- if ($post->post_type == 'revision') {
98
- return;
99
- }
100
-
101
- $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
102
-
103
- WSAL_Sensors_Request::SetVars(array(
104
- '$newStatus' => $newStatus,
105
- '$oldStatus' => $oldStatus,
106
- '$original' => $original,
107
- ));
108
- // run checks
109
- if ($this->_OldPost) {
110
- if ($this->CheckBBPress($this->_OldPost)) {
111
- return;
112
- }
113
- if ($oldStatus == 'auto-draft' || $original == 'auto-draft') {
114
- // Handle create post events
115
- $this->CheckPostCreation($this->_OldPost, $post);
116
- } else {
117
- // Handle update post events
118
- $changes = 0
119
- + $this->CheckAuthorChange($this->_OldPost, $post)
120
- + $this->CheckStatusChange($this->_OldPost, $post)
121
- + $this->CheckParentChange($this->_OldPost, $post)
122
- + $this->CheckStickyChange($this->_OldStky, isset($_REQUEST['sticky']), $post)
123
- + $this->CheckVisibilityChange($this->_OldPost, $post, $oldStatus, $newStatus)
124
- + $this->CheckTemplateChange($this->_OldTmpl, $this->GetPostTemplate($post), $post)
125
- + $this->CheckCategoriesChange($this->_OldCats, $this->GetPostCategories($post), $post)
126
- ;
127
- if (!$changes) {
128
- $changes = $this->CheckPermalinkChange($this->_OldLink, get_permalink($post->ID), $post);
129
- }
130
- if (!$changes) {
131
- $changes = $this->CheckModificationChange($post->ID, $this->_OldPost, $post);
132
- }
133
- }
134
- }
135
- }
136
-
137
- protected function CheckPostCreation($oldPost, $newPost)
138
- {
139
- $event = 0;
140
- $is_scheduled = false;
141
- switch ($newPost->post_status) {
142
- case 'publish':
143
- $event = $this->GetEventTypeForPostType($oldPost, 2001, 2005, 2030);
144
- break;
145
- case 'draft':
146
- $event = $this->GetEventTypeForPostType($oldPost, 2000, 2004, 2029);
147
- break;
148
- case 'future':
149
- $event = $this->GetEventTypeForPostType($oldPost, 2074, 2075, 2076);
150
- $is_scheduled = true;
151
- break;
152
- case 'pending':
153
- $event = 2073;
154
- break;
155
- }
156
- if ($event) {
157
- if ($is_scheduled) {
158
- $this->plugin->alerts->Trigger($event, array(
159
- 'PostType' => $newPost->post_type,
160
- 'PostTitle' => $newPost->post_title,
161
- 'PublishingDate' => $newPost->post_date
162
- ));
163
- } else {
164
- $this->plugin->alerts->Trigger($event, array(
165
- 'PostID' => $newPost->ID,
166
- 'PostType' => $newPost->post_type,
167
- 'PostTitle' => $newPost->post_title,
168
- 'PostUrl' => get_permalink($newPost->ID)
169
- ));
170
- }
171
- }
172
- }
173
-
174
- public function EventPublishFuture($post_id)
175
- {
176
- $post = get_post($post_id);
177
- $event = $this->GetEventTypeForPostType($post, 2001, 2005, 2030);
178
-
179
- if ($event) {
180
- $this->plugin->alerts->Trigger($event, array(
181
- 'PostID' => $post->ID,
182
- 'PostType' => $post->post_type,
183
- 'PostTitle' => $post->post_title,
184
- 'PostUrl' => get_permalink($post->ID)
185
- ));
186
- }
187
- }
188
-
189
- protected function CheckCategoryCreation()
190
- {
191
- if (empty($_POST)) {
192
- return;
193
- }
194
- $categoryName = '';
195
- if (!empty($_POST['screen']) && !empty($_POST['tag-name']) &&
196
- $_POST['screen'] == 'edit-category' &&
197
- $_POST['taxonomy'] == 'category' &&
198
- $_POST['action'] == 'add-tag') {
199
- $categoryName = $_POST['tag-name'];
200
- } elseif (!empty($_POST['newcategory']) && $_POST['action'] == 'add-category') {
201
- $categoryName = $_POST['newcategory'];
202
- }
203
-
204
- if ($categoryName) {
205
- $this->plugin->alerts->Trigger(2023, array(
206
- 'CategoryName' => $categoryName,
207
- ));
208
- }
209
- }
210
-
211
- protected function CheckCategoryDeletion()
212
- {
213
- if (empty($_POST)) {
214
- return;
215
- }
216
- $action = !empty($_POST['action']) ? $_POST['action']
217
- : (!empty($_POST['action2']) ? $_POST['action2'] : '');
218
- if (!$action) {
219
- return;
220
- }
221
-
222
- $categoryIds = array();
223
-
224
- if (isset($_POST['taxonomy'])) {
225
- if ($action == 'delete' && $_POST['taxonomy'] == 'category' && !empty($_POST['delete_tags'])) {
226
- // bulk delete
227
- $categoryIds[] = $_POST['delete_tags'];
228
- } elseif ($action == 'delete-tag' && $_POST['taxonomy'] == 'category' && !empty($_POST['tag_ID'])) {
229
- // single delete
230
- $categoryIds[] = $_POST['tag_ID'];
231
- }
232
- }
233
-
234
- foreach ($categoryIds as $categoryID) {
235
- $category = get_category($categoryID);
236
- $this->plugin->alerts->Trigger(2024, array(
237
- 'CategoryID' => $categoryID,
238
- 'CategoryName' => $category->cat_name,
239
- ));
240
- }
241
- }
242
-
243
- public function EventPostDeleted($post_id)
244
- {
245
- $post = get_post($post_id);
246
- if ($this->CheckBBPress($post)) {
247
- return;
248
- }
249
- if (!in_array($post->post_type, array('attachment', 'revision', 'nav_menu_item'))) { // ignore attachments, revisions and menu items
250
- $event = $this->GetEventTypeForPostType($post, 2008, 2009, 2033);
251
- // check WordPress backend operations
252
- if ($this->CheckAutoDraft($event, $post->post_title)) {
253
- return;
254
- }
255
- $this->plugin->alerts->Trigger($event, array(
256
- 'PostID' => $post->ID,
257
- 'PostType' => $post->post_type,
258
- 'PostTitle' => $post->post_title,
259
- ));
260
- }
261
- }
262
-
263
- public function EventPostTrashed($post_id)
264
- {
265
- $post = get_post($post_id);
266
- if ($this->CheckBBPress($post)) {
267
- return;
268
- }
269
- $event = $this->GetEventTypeForPostType($post, 2012, 2013, 2034);
270
- $this->plugin->alerts->Trigger($event, array(
271
- 'PostID' => $post->ID,
272
- 'PostType' => $post->post_type,
273
- 'PostTitle' => $post->post_title,
274
- ));
275
- }
276
-
277
- public function EventPostUntrashed($post_id)
278
- {
279
- $post = get_post($post_id);
280
- if ($this->CheckBBPress($post)) {
281
- return;
282
- }
283
- $event = $this->GetEventTypeForPostType($post, 2014, 2015, 2035);
284
- $this->plugin->alerts->Trigger($event, array(
285
- 'PostID' => $post->ID,
286
- 'PostType' => $post->post_type,
287
- 'PostTitle' => $post->post_title,
288
- ));
289
- }
290
-
291
- protected function CheckDateChange($oldpost, $newpost)
292
- {
293
- $from = strtotime($oldpost->post_date);
294
- $to = strtotime($newpost->post_date);
295
- if ($oldpost->post_status == 'draft') {
296
- return 0;
297
- }
298
- $pending = $this->CheckReviewPendingChange($oldpost, $newpost);
299
- if ($pending) {
300
- return 0;
301
- }
302
- if ($from != $to) {
303
- $event = $this->GetEventTypeForPostType($oldpost, 2027, 2028, 2041);
304
- $this->plugin->alerts->Trigger($event, array(
305
- 'PostID' => $oldpost->ID,
306
- 'PostType' => $oldpost->post_type,
307
- 'PostTitle' => $oldpost->post_title,
308
- 'OldDate' => $oldpost->post_date,
309
- 'NewDate' => $newpost->post_date,
310
- ));
311
- return 1;
312
- }
313
- }
314
-
315
- // Revision used
316
- protected function CheckReviewPendingChange($oldpost, $newpost)
317
- {
318
- if ($oldpost->post_status == 'pending') {
319
- $this->plugin->alerts->Trigger(2072, array(
320
- 'PostID' => $oldpost->ID,
321
- 'PostType' => $oldpost->post_type,
322
- 'PostTitle' => $oldpost->post_title
323
- ));
324
- return 1;
325
- }
326
- return 0;
327
- }
328
-
329
- protected function CheckCategoriesChange($oldCats, $newCats, $post)
330
- {
331
- $oldCats = implode(', ', $oldCats);
332
- $newCats = implode(', ', $newCats);
333
- if ($oldCats != $newCats) {
334
- $event = $this->GetEventTypeForPostType($post, 2016, 0, 2036);
335
- if ($event) {
336
- $this->plugin->alerts->Trigger($event, array(
337
- 'PostID' => $post->ID,
338
- 'PostType' => $post->post_type,
339
- 'PostTitle' => $post->post_title,
340
- 'OldCategories' => $oldCats ? $oldCats : 'no categories',
341
- 'NewCategories' => $newCats ? $newCats : 'no categories',
342
- ));
343
- return 1;
344
- }
345
- }
346
- }
347
-
348
- protected function CheckAuthorChange($oldpost, $newpost)
349
- {
350
- if ($oldpost->post_author != $newpost->post_author) {
351
- $event = $this->GetEventTypeForPostType($oldpost, 2019, 2020, 2038);
352
- $this->plugin->alerts->Trigger($event, array(
353
- 'PostID' => $oldpost->ID,
354
- 'PostType' => $oldpost->post_type,
355
- 'PostTitle' => $oldpost->post_title,
356
- 'OldAuthor' => get_userdata($oldpost->post_author)->user_login,
357
- 'NewAuthor' => get_userdata($newpost->post_author)->user_login,
358
- ));
359
- return 1;
360
- }
361
- }
362
-
363
- protected function CheckStatusChange($oldpost, $newpost)
364
- {
365
- if ($oldpost->post_status != $newpost->post_status) {
366
- if (isset($_REQUEST['publish'])) {
367
- // special case (publishing a post)
368
- $event = $this->GetEventTypeForPostType($oldpost, 2001, 2005, 2030);
369
- $this->plugin->alerts->Trigger($event, array(
370
- 'PostID' => $newpost->ID,
371
- 'PostType' => $newpost->post_type,
372
- 'PostTitle' => $newpost->post_title,
373
- 'PostUrl' => get_permalink($newpost->ID),
374
- ));
375
- } else {
376
- $event = $this->GetEventTypeForPostType($oldpost, 2021, 2022, 2039);
377
- $this->plugin->alerts->Trigger($event, array(
378
- 'PostID' => $oldpost->ID,
379
- 'PostType' => $oldpost->post_type,
380
- 'PostTitle' => $oldpost->post_title,
381
- 'OldStatus' => $oldpost->post_status,
382
- 'NewStatus' => $newpost->post_status,
383
- ));
384
- }
385
- return 1;
386
- }
387
- }
388
-
389
- protected function CheckParentChange($oldpost, $newpost)
390
- {
391
- if ($oldpost->post_parent != $newpost->post_parent) {
392
- $event = $this->GetEventTypeForPostType($oldpost, 0, 2047, 0);
393
- if ($event) {
394
- $this->plugin->alerts->Trigger($event, array(
395
- 'PostID' => $oldpost->ID,
396
- 'PostType' => $oldpost->post_type,
397
- 'PostTitle' => $oldpost->post_title,
398
- 'OldParent' => $oldpost->post_parent,
399
- 'NewParent' => $newpost->post_parent,
400
- 'OldParentName' => $oldpost->post_parent ? get_the_title($oldpost->post_parent) : 'no parent',
401
- 'NewParentName' => $newpost->post_parent ? get_the_title($newpost->post_parent) : 'no parent',
402
- ));
403
- return 1;
404
- }
405
- }
406
- }
407
-
408
- protected function CheckPermalinkChange($oldLink, $newLink, $post)
409
- {
410
- if ($oldLink != $newLink) {
411
- $event = $this->GetEventTypeForPostType($post, 2017, 2018, 2037);
412
- $this->plugin->alerts->Trigger($event, array(
413
- 'PostID' => $post->ID,
414
- 'PostType' => $post->post_type,
415
- 'PostTitle' => $post->post_title,
416
- 'OldUrl' => $oldLink,
417
- 'NewUrl' => $newLink,
418
- ));
419
- return 1;
420
- }
421
- }
422
-
423
- protected function CheckVisibilityChange($oldpost, $newpost, $oldStatus, $newStatus)
424
- {
425
- if ($oldStatus == 'draft' || $newStatus == 'draft') {
426
- return;
427
- }
428
-
429
- $oldVisibility = '';
430
- $newVisibility = '';
431
-
432
- if ($oldpost->post_password) {
433
- $oldVisibility = __('Password Protected', 'wp-security-audit-log');
434
- } elseif ($oldStatus == 'publish') {
435
- $oldVisibility = __('Public', 'wp-security-audit-log');
436
- } elseif ($oldStatus == 'private') {
437
- $oldVisibility = __('Private', 'wp-security-audit-log');
438
- }
439
-
440
- if ($newpost->post_password) {
441
- $newVisibility = __('Password Protected', 'wp-security-audit-log');
442
- } elseif ($newStatus == 'publish') {
443
- $newVisibility = __('Public', 'wp-security-audit-log');
444
- } elseif ($newStatus == 'private') {
445
- $newVisibility = __('Private', 'wp-security-audit-log');
446
- }
447
-
448
- if ($oldVisibility && $newVisibility && ($oldVisibility != $newVisibility)) {
449
- $event = $this->GetEventTypeForPostType($oldpost, 2025, 2026, 2040);
450
- $this->plugin->alerts->Trigger($event, array(
451
- 'PostID' => $oldpost->ID,
452
- 'PostType' => $oldpost->post_type,
453
- 'PostTitle' => $oldpost->post_title,
454
- 'OldVisibility' => $oldVisibility,
455
- 'NewVisibility' => $newVisibility,
456
- ));
457
- return 1;
458
- }
459
- }
460
-
461
- protected function CheckTemplateChange($oldTmpl, $newTmpl, $post)
462
- {
463
- if ($oldTmpl != $newTmpl) {
464
- $event = $this->GetEventTypeForPostType($post, 0, 2048, 0);
465
- if ($event) {
466
- $this->plugin->alerts->Trigger($event, array(
467
- 'PostID' => $post->ID,
468
- 'PostType' => $post->post_type,
469
- 'PostTitle' => $post->post_title,
470
- 'OldTemplate' => ucwords(str_replace(array('-' , '_'), ' ', basename($oldTmpl, '.php'))),
471
- 'NewTemplate' => ucwords(str_replace(array('-' , '_'), ' ', basename($newTmpl, '.php'))),
472
- 'OldTemplatePath' => $oldTmpl,
473
- 'NewTemplatePath' => $newTmpl,
474
- ));
475
- return 1;
476
- }
477
- }
478
- }
479
-
480
- protected function CheckStickyChange($oldStky, $newStky, $post)
481
- {
482
- if ($oldStky != $newStky) {
483
- $event = $newStky ? 2049 : 2050;
484
- $this->plugin->alerts->Trigger($event, array(
485
- 'PostID' => $post->ID,
486
- 'PostType' => $post->post_type,
487
- 'PostTitle' => $post->post_title,
488
- ));
489
- return 1;
490
- }
491
- }
492
-
493
- public function CheckModificationChange($post_ID, $oldpost, $newpost)
494
- {
495
- if ($this->CheckBBPress($oldpost)) {
496
- return;
497
- }
498
- $changes = 0 + $this->CheckDateChange($oldpost, $newpost)
499
- + $this->CheckTitleChange($oldpost, $newpost);
500
- if (!$changes) {
501
- $contentChanged = $oldpost->post_content != $newpost->post_content; // TODO what about excerpts?
502
-
503
- if ($oldpost->post_modified != $newpost->post_modified) {
504
- $event = 0;
505
- // @see http://codex.wordpress.org/Class_Reference/WP_Query#Status_Parameters
506
- switch ($oldpost->post_status) { // TODO or should this be $newpost?
507
- case 'draft':
508
- if ($contentChanged) {
509
- $event = $this->GetEventTypeForPostType($newpost, 2068, 2069, 2070);
510
- } else {
511
- $event = $this->GetEventTypeForPostType($newpost, 2003, 2007, 2032);
512
- }
513
- break;
514
- case 'publish':
515
- if ($contentChanged) {
516
- $event = $this->GetEventTypeForPostType($newpost, 2065, 2066, 2067);
517
- } else {
518
- $event = $this->GetEventTypeForPostType($newpost, 2002, 2006, 2031);
519
- }
520
- break;
521
- }
522
- if ($event) {
523
- $this->plugin->alerts->Trigger($event, array(
524
- 'PostID' => $post_ID,
525
- 'PostType' => $oldpost->post_type,
526
- 'PostTitle' => $oldpost->post_title,
527
- 'PostUrl' => get_permalink($post_ID) // TODO or should this be $newpost?
528
- ));
529
- return 1;
530
- }
531
- }
532
- }
533
- }
534
-
535
- public function EventChangedCategoryParent()
536
- {
537
- if (empty($_POST)) {
538
- return;
539
- }
540
- if (!current_user_can("manage_categories")) {
541
- return;
542
- }
543
- if (isset($_POST['name'])) {
544
- $category = get_category($_POST['tag_ID']);
545
- if ($category->parent != 0) {
546
- $oldParent = get_category($category->parent);
547
- $oldParentName = (empty($oldParent))? 'no parent' : $oldParent->name;
548
- } else {
549
- $oldParentName = 'no parent';
550
- }
551
- if (isset($_POST['parent'])) {
552
- $newParent = get_category($_POST['parent']);
553
- $newParentName = (empty($newParent))? 'no parent' : $newParent->name;
554
- }
555
- $this->plugin->alerts->Trigger(2052, array(
556
- 'CategoryName' => $category->name,
557
- 'OldParent' => $oldParentName,
558
- 'NewParent' => $newParentName,
559
- ));
560
- }
561
- }
562
-
563
- private function CheckAutoDraft($code, $title)
564
- {
565
- if ($code == 2008 && $title == "auto-draft") {
566
- // to do check setting else return false
567
- if ($this->plugin->settings->IsWPBackend() == 1) {
568
- return true;
569
- } else {
570
- return false;
571
- }
572
- } else {
573
- return false;
574
- }
575
- }
576
-
577
- private function getRevisionLink($revision_id)
578
- {
579
- if (!empty($revision_id)) {
580
- return admin_url('revision.php?revision='.$revision_id);
581
- } else {
582
- return null;
583
- }
584
- }
585
-
586
- /**
587
- * Ignore post from BBPress Plugin,
588
- * Triggered on the BBPress Sensor
589
- */
590
- private function CheckBBPress($post)
591
- {
592
- switch ($post->post_type) {
593
- case 'forum':
594
- case 'topic':
595
- case 'reply':
596
- return true;
597
- default:
598
- return false;
599
- }
600
- }
601
-
602
- /**
603
- * Triggered after save post for add revision link
604
- */
605
- public function SetRevisionLink($post_id, $post, $update)
606
- {
607
- $revisions = wp_get_post_revisions($post_id);
608
- if (!empty($revisions)) {
609
- $revision = array_shift($revisions);
610
-
611
- $objOcc = new WSAL_Models_Occurrence();
612
- $occ = $objOcc->GetByPostID($post_id);
613
- $occ = count($occ) ? $occ[0] : null;
614
- if (!empty($occ)) {
615
- $revisionLink = $this->getRevisionLink($revision->ID);
616
- if (!empty($revisionLink)) {
617
- $occ->SetMetaValue('RevisionLink', $revisionLink);
618
- }
619
- }
620
- }
621
- }
622
-
623
- private function CheckTitleChange($oldpost, $newpost)
624
- {
625
- if ($oldpost->post_title != $newpost->post_title) {
626
- $event = $this->GetEventTypeForPostType($newpost, 2086, 2087, 2088);
627
- $this->plugin->alerts->Trigger($event, array(
628
- 'OldTitle' => $oldpost->post_title,
629
- 'NewTitle' => $newpost->post_title,
630
- ));
631
- return 1;
632
- }
633
- return 0;
634
- }
635
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_Content extends WSAL_AbstractSensor
4
+ {
5
+
6
+ public function HookEvents()
7
+ {
8
+ if (current_user_can("edit_posts")) {
9
+ add_action('admin_init', array($this, 'EventWordpressInit'));
10
+ }
11
+ add_action('transition_post_status', array($this, 'EventPostChanged'), 10, 3);
12
+ add_action('delete_post', array($this, 'EventPostDeleted'), 10, 1);
13
+ add_action('wp_trash_post', array($this, 'EventPostTrashed'), 10, 1);
14
+ add_action('untrash_post', array($this, 'EventPostUntrashed'));
15
+ add_action('edit_category', array($this, 'EventChangedCategoryParent'));
16
+ add_action('save_post', array($this, 'SetRevisionLink'), 10, 3);
17
+ add_action('publish_future_post', array($this, 'EventPublishFuture'), 10, 1);
18
+ }
19
+
20
+ protected function GetEventTypeForPostType($post, $typePost, $typePage, $typeCustom)
21
+ {
22
+ switch ($post->post_type) {
23
+ case 'page':
24
+ return $typePage;
25
+ case 'post':
26
+ return $typePost;
27
+ default:
28
+ return $typeCustom;
29
+ }
30
+ }
31
+
32
+ protected $_OldPost = null;
33
+ protected $_OldLink = null;
34
+ protected $_OldCats = null;
35
+ protected $_OldTmpl = null;
36
+ protected $_OldStky = null;
37
+
38
+ public function EventWordpressInit()
39
+ {
40
+ // load old data, if applicable
41
+ $this->RetrieveOldData();
42
+ // check for category changes
43
+ $this->CheckCategoryCreation();
44
+ $this->CheckCategoryDeletion();
45
+ }
46
+
47
+ protected function RetrieveOldData()
48
+ {
49
+ if (isset($_POST) && isset($_POST['post_ID'])
50
+ && !(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
51
+ && !(isset($_POST['action']) && $_POST['action'] == 'autosave')
52
+ ) {
53
+ $postID = intval($_POST['post_ID']);
54
+ $this->_OldPost = get_post($postID);
55
+ $this->_OldLink = get_permalink($postID);
56
+ $this->_OldTmpl = $this->GetPostTemplate($this->_OldPost);
57
+ $this->_OldCats = $this->GetPostCategories($this->_OldPost);
58
+ $this->_OldStky = in_array($postID, get_option('sticky_posts'));
59
+ }
60
+ }
61
+
62
+ protected function GetPostTemplate($post)
63
+ {
64
+ $id = $post->ID;
65
+ $template = get_page_template_slug($id);
66
+ $pagename = $post->post_name;
67
+
68
+ $templates = array();
69
+ if ($template && 0 === validate_file($template)) {
70
+ $templates[] = $template;
71
+ }
72
+ if ($pagename) {
73
+ $templates[] = "page-$pagename.php";
74
+ }
75
+ if ($id) {
76
+ $templates[] = "page-$id.php";
77
+ }
78
+ $templates[] = 'page.php';
79
+
80
+ return get_query_template('page', $templates);
81
+ }
82
+
83
+ protected function GetPostCategories($post)
84
+ {
85
+ return wp_get_post_categories($post->ID, array('fields' => 'names'));
86
+ }
87
+
88
+ public function EventPostChanged($newStatus, $oldStatus, $post)
89
+ {
90
+ // ignorable states
91
+ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
92
+ return;
93
+ }
94
+ if (empty($post->post_type)) {
95
+ return;
96
+ }
97
+ if ($post->post_type == 'revision') {
98
+ return;
99
+ }
100
+
101
+ $original = isset($_POST['original_post_status']) ? $_POST['original_post_status'] : '';
102
+
103
+ WSAL_Sensors_Request::SetVars(array(
104
+ '$newStatus' => $newStatus,
105
+ '$oldStatus' => $oldStatus,
106
+ '$original' => $original,
107
+ ));
108
+ // run checks
109
+ if ($this->_OldPost) {
110
+ if ($this->CheckBBPress($this->_OldPost)) {
111
+ return;
112
+ }
113
+ if ($oldStatus == 'auto-draft' || $original == 'auto-draft') {
114
+ // Handle create post events
115
+ $this->CheckPostCreation($this->_OldPost, $post);
116
+ } else {
117
+ // Handle update post events
118
+ $changes = 0
119
+ + $this->CheckAuthorChange($this->_OldPost, $post)
120
+ + $this->CheckStatusChange($this->_OldPost, $post)
121
+ + $this->CheckParentChange($this->_OldPost, $post)
122
+ + $this->CheckStickyChange($this->_OldStky, isset($_REQUEST['sticky']), $post)
123
+ + $this->CheckVisibilityChange($this->_OldPost, $post, $oldStatus, $newStatus)
124
+ + $this->CheckTemplateChange($this->_OldTmpl, $this->GetPostTemplate($post), $post)
125
+ + $this->CheckCategoriesChange($this->_OldCats, $this->GetPostCategories($post), $post)
126
+ ;
127
+ if (!$changes) {
128
+ $changes = $this->CheckPermalinkChange($this->_OldLink, get_permalink($post->ID), $post);
129
+ }
130
+ if (!$changes) {
131
+ $changes = $this->CheckModificationChange($post->ID, $this->_OldPost, $post);
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ protected function CheckPostCreation($oldPost, $newPost)
138
+ {
139
+ $event = 0;
140
+ $is_scheduled = false;
141
+ switch ($newPost->post_status) {
142
+ case 'publish':
143
+ $event = $this->GetEventTypeForPostType($oldPost, 2001, 2005, 2030);
144
+ break;
145
+ case 'draft':
146
+ $event = $this->GetEventTypeForPostType($oldPost, 2000, 2004, 2029);
147
+ break;
148
+ case 'future':
149
+ $event = $this->GetEventTypeForPostType($oldPost, 2074, 2075, 2076);
150
+ $is_scheduled = true;
151
+ break;
152
+ case 'pending':
153
+ $event = 2073;
154
+ break;
155
+ }
156
+ if ($event) {
157
+ if ($is_scheduled) {
158
+ $this->plugin->alerts->Trigger($event, array(
159
+ 'PostType' => $newPost->post_type,
160
+ 'PostTitle' => $newPost->post_title,
161
+ 'PublishingDate' => $newPost->post_date
162
+ ));
163
+ } else {
164
+ $this->plugin->alerts->Trigger($event, array(
165
+ 'PostID' => $newPost->ID,
166
+ 'PostType' => $newPost->post_type,
167
+ 'PostTitle' => $newPost->post_title,
168
+ 'PostUrl' => get_permalink($newPost->ID)
169
+ ));
170
+ }
171
+ }
172
+ }
173
+
174
+ public function EventPublishFuture($post_id)
175
+ {
176
+ $post = get_post($post_id);
177
+ $event = $this->GetEventTypeForPostType($post, 2001, 2005, 2030);
178
+
179
+ if ($event) {
180
+ $this->plugin->alerts->Trigger($event, array(
181
+ 'PostID' => $post->ID,
182
+ 'PostType' => $post->post_type,
183
+ 'PostTitle' => $post->post_title,
184
+ 'PostUrl' => get_permalink($post->ID)
185
+ ));
186
+ }
187
+ }
188
+
189
+ protected function CheckCategoryCreation()
190
+ {
191
+ if (empty($_POST)) {
192
+ return;
193
+ }
194
+ $categoryName = '';
195
+ if (!empty($_POST['screen']) && !empty($_POST['tag-name']) &&
196
+ $_POST['screen'] == 'edit-category' &&
197
+ $_POST['taxonomy'] == 'category' &&
198
+ $_POST['action'] == 'add-tag') {
199
+ $categoryName = $_POST['tag-name'];
200
+ } elseif (!empty($_POST['newcategory']) && $_POST['action'] == 'add-category') {
201
+ $categoryName = $_POST['newcategory'];
202
+ }
203
+
204
+ if ($categoryName) {
205
+ $this->plugin->alerts->Trigger(2023, array(
206
+ 'CategoryName' => $categoryName,
207
+ ));
208
+ }
209
+ }
210
+
211
+ protected function CheckCategoryDeletion()
212
+ {
213
+ if (empty($_POST)) {
214
+ return;
215
+ }
216
+ $action = !empty($_POST['action']) ? $_POST['action']
217
+ : (!empty($_POST['action2']) ? $_POST['action2'] : '');
218
+ if (!$action) {
219
+ return;
220
+ }
221
+
222
+ $categoryIds = array();
223
+
224
+ if (isset($_POST['taxonomy'])) {
225
+ if ($action == 'delete' && $_POST['taxonomy'] == 'category' && !empty($_POST['delete_tags'])) {
226
+ // bulk delete
227
+ $categoryIds[] = $_POST['delete_tags'];
228
+ } elseif ($action == 'delete-tag' && $_POST['taxonomy'] == 'category' && !empty($_POST['tag_ID'])) {
229
+ // single delete
230
+ $categoryIds[] = $_POST['tag_ID'];
231
+ }
232
+ }
233
+
234
+ foreach ($categoryIds as $categoryID) {
235
+ $category = get_category($categoryID);
236
+ $this->plugin->alerts->Trigger(2024, array(
237
+ 'CategoryID' => $categoryID,
238
+ 'CategoryName' => $category->cat_name,
239
+ ));
240
+ }
241
+ }
242
+
243
+ public function EventPostDeleted($post_id)
244
+ {
245
+ $post = get_post($post_id);
246
+ if ($this->CheckBBPress($post)) {
247
+ return;
248
+ }
249
+ if (!in_array($post->post_type, array('attachment', 'revision', 'nav_menu_item'))) { // ignore attachments, revisions and menu items
250
+ $event = $this->GetEventTypeForPostType($post, 2008, 2009, 2033);
251
+ // check WordPress backend operations
252
+ if ($this->CheckAutoDraft($event, $post->post_title)) {
253
+ return;
254
+ }
255
+ $this->plugin->alerts->Trigger($event, array(
256
+ 'PostID' => $post->ID,
257
+ 'PostType' => $post->post_type,
258
+ 'PostTitle' => $post->post_title,
259
+ ));
260
+ }
261
+ }
262
+
263
+ public function EventPostTrashed($post_id)
264
+ {
265
+ $post = get_post($post_id);
266
+ if ($this->CheckBBPress($post)) {
267
+ return;
268
+ }
269
+ $event = $this->GetEventTypeForPostType($post, 2012, 2013, 2034);
270
+ $this->plugin->alerts->Trigger($event, array(
271
+ 'PostID' => $post->ID,
272
+ 'PostType' => $post->post_type,
273
+ 'PostTitle' => $post->post_title,
274
+ ));
275
+ }
276
+
277
+ public function EventPostUntrashed($post_id)
278
+ {
279
+ $post = get_post($post_id);
280
+ if ($this->CheckBBPress($post)) {
281
+ return;
282
+ }
283
+ $event = $this->GetEventTypeForPostType($post, 2014, 2015, 2035);
284
+ $this->plugin->alerts->Trigger($event, array(
285
+ 'PostID' => $post->ID,
286
+ 'PostType' => $post->post_type,
287
+ 'PostTitle' => $post->post_title,
288
+ ));
289
+ }
290
+
291
+ protected function CheckDateChange($oldpost, $newpost)
292
+ {
293
+ $from = strtotime($oldpost->post_date);
294
+ $to = strtotime($newpost->post_date);
295
+ if ($oldpost->post_status == 'draft') {
296
+ return 0;
297
+ }
298
+ $pending = $this->CheckReviewPendingChange($oldpost, $newpost);
299
+ if ($pending) {
300
+ return 0;
301
+ }
302
+ if ($from != $to) {
303
+ $event = $this->GetEventTypeForPostType($oldpost, 2027, 2028, 2041);
304
+ $this->plugin->alerts->Trigger($event, array(
305
+ 'PostID' => $oldpost->ID,
306
+ 'PostType' => $oldpost->post_type,
307
+ 'PostTitle' => $oldpost->post_title,
308
+ 'OldDate' => $oldpost->post_date,
309
+ 'NewDate' => $newpost->post_date,
310
+ ));
311
+ return 1;
312
+ }
313
+ }
314
+
315
+ // Revision used
316
+ protected function CheckReviewPendingChange($oldpost, $newpost)
317
+ {
318
+ if ($oldpost->post_status == 'pending') {
319
+ $this->plugin->alerts->Trigger(2072, array(
320
+ 'PostID' => $oldpost->ID,
321
+ 'PostType' => $oldpost->post_type,
322
+ 'PostTitle' => $oldpost->post_title
323
+ ));
324
+ return 1;
325
+ }
326
+ return 0;
327
+ }
328
+
329
+ protected function CheckCategoriesChange($oldCats, $newCats, $post)
330
+ {
331
+ $oldCats = implode(', ', $oldCats);
332
+ $newCats = implode(', ', $newCats);
333
+ if ($oldCats != $newCats) {
334
+ $event = $this->GetEventTypeForPostType($post, 2016, 0, 2036);
335
+ if ($event) {
336
+ $this->plugin->alerts->Trigger($event, array(
337
+ 'PostID' => $post->ID,
338
+ 'PostType' => $post->post_type,
339
+ 'PostTitle' => $post->post_title,
340
+ 'OldCategories' => $oldCats ? $oldCats : 'no categories',
341
+ 'NewCategories' => $newCats ? $newCats : 'no categories',
342
+ ));
343
+ return 1;
344
+ }
345
+ }
346
+ }
347
+
348
+ protected function CheckAuthorChange($oldpost, $newpost)
349
+ {
350
+ if ($oldpost->post_author != $newpost->post_author) {
351
+ $event = $this->GetEventTypeForPostType($oldpost, 2019, 2020, 2038);
352
+ $this->plugin->alerts->Trigger($event, array(
353
+ 'PostID' => $oldpost->ID,
354
+ 'PostType' => $oldpost->post_type,
355
+ 'PostTitle' => $oldpost->post_title,
356
+ 'OldAuthor' => get_userdata($oldpost->post_author)->user_login,
357
+ 'NewAuthor' => get_userdata($newpost->post_author)->user_login,
358
+ ));
359
+ return 1;
360
+ }
361
+ }
362
+
363
+ protected function CheckStatusChange($oldpost, $newpost)
364
+ {
365
+ if ($oldpost->post_status != $newpost->post_status) {
366
+ if (isset($_REQUEST['publish'])) {
367
+ // special case (publishing a post)
368
+ $event = $this->GetEventTypeForPostType($oldpost, 2001, 2005, 2030);
369
+ $this->plugin->alerts->Trigger($event, array(
370
+ 'PostID' => $newpost->ID,
371
+ 'PostType' => $newpost->post_type,
372
+ 'PostTitle' => $newpost->post_title,
373
+ 'PostUrl' => get_permalink($newpost->ID),
374
+ ));
375
+ } else {
376
+ $event = $this->GetEventTypeForPostType($oldpost, 2021, 2022, 2039);
377
+ $this->plugin->alerts->Trigger($event, array(
378
+ 'PostID' => $oldpost->ID,
379
+ 'PostType' => $oldpost->post_type,
380
+ 'PostTitle' => $oldpost->post_title,
381
+ 'OldStatus' => $oldpost->post_status,
382
+ 'NewStatus' => $newpost->post_status,
383
+ ));
384
+ }
385
+ return 1;
386
+ }
387
+ }
388
+
389
+ protected function CheckParentChange($oldpost, $newpost)
390
+ {
391
+ if ($oldpost->post_parent != $newpost->post_parent) {
392
+ $event = $this->GetEventTypeForPostType($oldpost, 0, 2047, 0);
393
+ if ($event) {
394
+ $this->plugin->alerts->Trigger($event, array(
395
+ 'PostID' => $oldpost->ID,
396
+ 'PostType' => $oldpost->post_type,
397
+ 'PostTitle' => $oldpost->post_title,
398
+ 'OldParent' => $oldpost->post_parent,
399
+ 'NewParent' => $newpost->post_parent,
400
+ 'OldParentName' => $oldpost->post_parent ? get_the_title($oldpost->post_parent) : 'no parent',
401
+ 'NewParentName' => $newpost->post_parent ? get_the_title($newpost->post_parent) : 'no parent',
402
+ ));
403
+ return 1;
404
+ }
405
+ }
406
+ }
407
+
408
+ protected function CheckPermalinkChange($oldLink, $newLink, $post)
409
+ {
410
+ if ($oldLink != $newLink) {
411
+ $event = $this->GetEventTypeForPostType($post, 2017, 2018, 2037);
412
+ $this->plugin->alerts->Trigger($event, array(
413
+ 'PostID' => $post->ID,
414
+ 'PostType' => $post->post_type,
415
+ 'PostTitle' => $post->post_title,
416
+ 'OldUrl' => $oldLink,
417
+ 'NewUrl' => $newLink,
418
+ ));
419
+ return 1;
420
+ }
421
+ }
422
+
423
+ protected function CheckVisibilityChange($oldpost, $newpost, $oldStatus, $newStatus)
424
+ {
425
+ if ($oldStatus == 'draft' || $newStatus == 'draft') {
426
+ return;
427
+ }
428
+
429
+ $oldVisibility = '';
430
+ $newVisibility = '';
431
+
432
+ if ($oldpost->post_password) {
433
+ $oldVisibility = __('Password Protected', 'wp-security-audit-log');
434
+ } elseif ($oldStatus == 'publish') {
435
+ $oldVisibility = __('Public', 'wp-security-audit-log');
436
+ } elseif ($oldStatus == 'private') {
437
+ $oldVisibility = __('Private', 'wp-security-audit-log');
438
+ }
439
+
440
+ if ($newpost->post_password) {
441
+ $newVisibility = __('Password Protected', 'wp-security-audit-log');
442
+ } elseif ($newStatus == 'publish') {
443
+ $newVisibility = __('Public', 'wp-security-audit-log');
444
+ } elseif ($newStatus == 'private') {
445
+ $newVisibility = __('Private', 'wp-security-audit-log');
446
+ }
447
+
448
+ if ($oldVisibility && $newVisibility && ($oldVisibility != $newVisibility)) {
449
+ $event = $this->GetEventTypeForPostType($oldpost, 2025, 2026, 2040);
450
+ $this->plugin->alerts->Trigger($event, array(
451
+ 'PostID' => $oldpost->ID,
452
+ 'PostType' => $oldpost->post_type,
453
+ 'PostTitle' => $oldpost->post_title,
454
+ 'OldVisibility' => $oldVisibility,
455
+ 'NewVisibility' => $newVisibility,
456
+ ));
457
+ return 1;
458
+ }
459
+ }
460
+
461
+ protected function CheckTemplateChange($oldTmpl, $newTmpl, $post)
462
+ {
463
+ if ($oldTmpl != $newTmpl) {
464
+ $event = $this->GetEventTypeForPostType($post, 0, 2048, 0);
465
+ if ($event) {
466
+ $this->plugin->alerts->Trigger($event, array(
467
+ 'PostID' => $post->ID,
468
+ 'PostType' => $post->post_type,
469
+ 'PostTitle' => $post->post_title,
470
+ 'OldTemplate' => ucwords(str_replace(array('-' , '_'), ' ', basename($oldTmpl, '.php'))),
471
+ 'NewTemplate' => ucwords(str_replace(array('-' , '_'), ' ', basename($newTmpl, '.php'))),
472
+ 'OldTemplatePath' => $oldTmpl,
473
+ 'NewTemplatePath' => $newTmpl,
474
+ ));
475
+ return 1;
476
+ }
477
+ }
478
+ }
479
+
480
+ protected function CheckStickyChange($oldStky, $newStky, $post)
481
+ {
482
+ if ($oldStky != $newStky) {
483
+ $event = $newStky ? 2049 : 2050;
484
+ $this->plugin->alerts->Trigger($event, array(
485
+ 'PostID' => $post->ID,
486
+ 'PostType' => $post->post_type,
487
+ 'PostTitle' => $post->post_title,
488
+ ));
489
+ return 1;
490
+ }
491
+ }
492
+
493
+ public function CheckModificationChange($post_ID, $oldpost, $newpost)
494
+ {
495
+ if ($this->CheckBBPress($oldpost)) {
496
+ return;
497
+ }
498
+ $changes = 0 + $this->CheckDateChange($oldpost, $newpost)
499
+ + $this->CheckTitleChange($oldpost, $newpost);
500
+ if (!$changes) {
501
+ $contentChanged = $oldpost->post_content != $newpost->post_content; // TODO what about excerpts?
502
+
503
+ if ($oldpost->post_modified != $newpost->post_modified) {
504
+ $event = 0;
505
+ // @see http://codex.wordpress.org/Class_Reference/WP_Query#Status_Parameters
506
+ switch ($oldpost->post_status) { // TODO or should this be $newpost?
507
+ case 'draft':
508
+ if ($contentChanged) {
509
+ $event = $this->GetEventTypeForPostType($newpost, 2068, 2069, 2070);
510
+ } else {
511
+ $event = $this->GetEventTypeForPostType($newpost, 2003, 2007, 2032);
512
+ }
513
+ break;
514
+ case 'publish':
515
+ if ($contentChanged) {
516
+ $event = $this->GetEventTypeForPostType($newpost, 2065, 2066, 2067);
517
+ } else {
518
+ $event = $this->GetEventTypeForPostType($newpost, 2002, 2006, 2031);
519
+ }
520
+ break;
521
+ }
522
+ if ($event) {
523
+ $this->plugin->alerts->Trigger($event, array(
524
+ 'PostID' => $post_ID,
525
+ 'PostType' => $oldpost->post_type,
526
+ 'PostTitle' => $oldpost->post_title,
527
+ 'PostUrl' => get_permalink($post_ID) // TODO or should this be $newpost?
528
+ ));
529
+ return 1;
530
+ }
531
+ }
532
+ }
533
+ }
534
+
535
+ public function EventChangedCategoryParent()
536
+ {
537
+ if (empty($_POST)) {
538
+ return;
539
+ }
540
+ if (!current_user_can("manage_categories")) {
541
+ return;
542
+ }
543
+ if (isset($_POST['name'])) {
544
+ $category = get_category($_POST['tag_ID']);
545
+ if ($category->parent != 0) {
546
+ $oldParent = get_category($category->parent);
547
+ $oldParentName = (empty($oldParent))? 'no parent' : $oldParent->name;
548
+ } else {
549
+ $oldParentName = 'no parent';
550
+ }
551
+ if (isset($_POST['parent'])) {
552
+ $newParent = get_category($_POST['parent']);
553
+ $newParentName = (empty($newParent))? 'no parent' : $newParent->name;
554
+ }
555
+ $this->plugin->alerts->Trigger(2052, array(
556
+ 'CategoryName' => $category->name,
557
+ 'OldParent' => $oldParentName,
558
+ 'NewParent' => $newParentName,
559
+ ));
560
+ }
561
+ }
562
+
563
+ private function CheckAutoDraft($code, $title)
564
+ {
565
+ if ($code == 2008 && $title == "auto-draft") {
566
+ // to do check setting else return false
567
+ if ($this->plugin->settings->IsWPBackend() == 1) {
568
+ return true;
569
+ } else {
570
+ return false;
571
+ }
572
+ } else {
573
+ return false;
574
+ }
575
+ }
576
+
577
+ private function getRevisionLink($revision_id)
578
+ {
579
+ if (!empty($revision_id)) {
580
+ return admin_url('revision.php?revision='.$revision_id);
581
+ } else {
582
+ return null;
583
+ }
584
+ }
585
+
586
+ /**
587
+ * Ignore post from BBPress Plugin,
588
+ * Triggered on the BBPress Sensor
589
+ */
590
+ private function CheckBBPress($post)
591
+ {
592
+ switch ($post->post_type) {
593
+ case 'forum':
594
+ case 'topic':
595
+ case 'reply':
596
+ return true;
597
+ default:
598
+ return false;
599
+ }
600
+ }
601
+
602
+ /**
603
+ * Triggered after save post for add revision link
604
+ */
605
+ public function SetRevisionLink($post_id, $post, $update)
606
+ {
607
+ $revisions = wp_get_post_revisions($post_id);
608
+ if (!empty($revisions)) {
609
+ $revision = array_shift($revisions);
610
+
611
+ $objOcc = new WSAL_Models_Occurrence();
612
+ $occ = $objOcc->GetByPostID($post_id);
613
+ $occ = count($occ) ? $occ[0] : null;
614
+ if (!empty($occ)) {
615
+ $revisionLink = $this->getRevisionLink($revision->ID);
616
+ if (!empty($revisionLink)) {
617
+ $occ->SetMetaValue('RevisionLink', $revisionLink);
618
+ }
619
+ }
620
+ }
621
+ }
622
+
623
+ private function CheckTitleChange($oldpost, $newpost)
624
+ {
625
+ if ($oldpost->post_title != $newpost->post_title) {
626
+ $event = $this->GetEventTypeForPostType($newpost, 2086, 2087, 2088);
627
+ $this->plugin->alerts->Trigger($event, array(
628
+ 'OldTitle' => $oldpost->post_title,
629
+ 'NewTitle' => $newpost->post_title,
630
+ ));
631
+ return 1;
632
+ }
633
+ return 0;
634
+ }
635
+ }
classes/Sensors/CustomHooks.php CHANGED
@@ -1,49 +1,49 @@
1
- <?php
2
- /**
3
- * The Class is used to allow developers to create
4
- * custom alerts
5
- */
6
- class WSAL_Sensors_CustomHooks extends WSAL_AbstractSensor
7
- {
8
- public function HookEvents()
9
- {
10
- /**
11
- * Use add_action() for every hook and pass the following:
12
- * @param string sample_hook_name
13
- * @param string SampleFunction - the name of the function above
14
- * @param int 10 - priority (Optional)
15
- * @param int 2 - number of parameters passed to the function (Optional)(Check the hook documentation)
16
- * @see http://adambrown.info/p/wp_hooks for more information on WordPress hooks
17
- */
18
- add_action('sample_hook_name', array($this, 'SampleFunction'), 10, 2);
19
- }
20
-
21
- /**
22
- * Sample function with 0 or more parameters.
23
- * Create one function for each hook:
24
- * @param anyType $paramname (Optional)
25
- */
26
- public function SampleFunction($value_1 = null, $value_2 = null)
27
- {
28
- /**
29
- * @var int (4 digit) $alertCode Alert code (3 types of criticality level)
30
- * @example Critical 2222, Warning 3333, Notice 4444
31
- */
32
- $alertCode = 2222;
33
-
34
- /**
35
- * @var string: the alert text
36
- */
37
- $alertText = 'Sample alert text';
38
-
39
- /**
40
- * @var array $variables used in the alert (With 1 or more elements)
41
- * { @var string $alertText }
42
- */
43
- $variables = array(
44
- 'CustomAlertText' => $alertText
45
- );
46
-
47
- $this->plugin->alerts->Trigger($alertCode, $variables);
48
- }
49
- }
1
+ <?php
2
+ /**
3
+ * The Class is used to allow developers to create
4
+ * custom alerts
5
+ */
6
+ class WSAL_Sensors_CustomHooks extends WSAL_AbstractSensor
7
+ {
8
+ public function HookEvents()
9
+ {
10
+ /**
11
+ * Use add_action() for every hook and pass the following:
12
+ * @param string sample_hook_name
13
+ * @param string SampleFunction - the name of the function above
14
+ * @param int 10 - priority (Optional)
15
+ * @param int 2 - number of parameters passed to the function (Optional)(Check the hook documentation)
16
+ * @see http://adambrown.info/p/wp_hooks for more information on WordPress hooks
17
+ */
18
+ add_action('sample_hook_name', array($this, 'SampleFunction'), 10, 2);
19
+ }
20
+
21
+ /**
22
+ * Sample function with 0 or more parameters.
23
+ * Create one function for each hook:
24
+ * @param anyType $paramname (Optional)
25
+ */
26
+ public function SampleFunction($value_1 = null, $value_2 = null)
27
+ {
28
+ /**
29
+ * @var int (4 digit) $alertCode Alert code (3 types of criticality level)
30
+ * @example Critical 2222, Warning 3333, Notice 4444
31
+ */
32
+ $alertCode = 2222;
33
+
34
+ /**
35
+ * @var string: the alert text
36
+ */
37
+ $alertText = 'Sample alert text';
38
+
39
+ /**
40
+ * @var array $variables used in the alert (With 1 or more elements)
41
+ * { @var string $alertText }
42
+ */
43
+ $variables = array(
44
+ 'CustomAlertText' => $alertText
45
+ );
46
+
47
+ $this->plugin->alerts->Trigger($alertCode, $variables);
48
+ }
49
+ }
classes/Sensors/Database.php CHANGED
@@ -1,132 +1,132 @@
1
- <?php
2
-
3
- class WSAL_Sensors_Database extends WSAL_AbstractSensor
4
- {
5
- public function HookEvents()
6
- {
7
- add_action('dbdelta_queries', array($this, 'EventDBDeltaQuery'));
8
- add_action('query', array($this, 'EventDropQuery'));
9
- }
10
-
11
- public function EventDropQuery($query)
12
- {
13
- $table_names = array();
14
- $str = explode(" ", $query);
15
-
16
- if (preg_match("|DROP TABLE ([^ ]*)|", $query)) {
17
- if (!empty($str[4])) {
18
- array_push($table_names, $str[4]);
19
- } else {
20
- array_push($table_names, $str[2]);
21
- }
22
- $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
23
- $alertOptions = $this->GetActionType($actype);
24
- }
25
-
26
- if (!empty($table_names)) {
27
- $event_code = $this->GetEventQueryType($actype, "delete");
28
- $alertOptions["TableNames"] = implode(",", $table_names);
29
- $this->plugin->alerts->Trigger($event_code, $alertOptions);
30
- }
31
- return $query;
32
- }
33
-
34
- public function EventDBDeltaQuery($queries)
35
- {
36
- $typeQueries = array(
37
- "create" => array(),
38
- "update" => array(),
39
- "delete" => array()
40
- );
41
- global $wpdb;
42
-
43
- foreach ($queries as $qry) {
44
- $str = explode(" ", $qry);
45
- if (preg_match("|CREATE TABLE ([^ ]*)|", $qry)) {
46
- if ($wpdb->get_var("SHOW TABLES LIKE '" . $str[2] . "'") != $str[2]) {
47
- //some plugins keep trying to create tables even when they already exist- would result in too many alerts
48
- array_push($typeQueries['create'], $str[2]);
49
- }
50
- } else if (preg_match("|ALTER TABLE ([^ ]*)|", $qry)) {
51
- array_push($typeQueries['update'], $str[2]);
52
- } else if (preg_match("|DROP TABLE ([^ ]*)|", $qry)) {
53
- if (!empty($str[4])) {
54
- array_push($typeQueries['delete'], $str[4]);
55
- } else {
56
- array_push($typeQueries['delete'], $str[2]);
57
- }
58
- }
59
- }
60
-
61
- if (!empty($typeQueries["create"]) || !empty($typeQueries["update"]) || !empty($typeQueries["delete"])) {
62
- $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
63
- $alertOptions = $this->GetActionType($actype);
64
-
65
- foreach ($typeQueries as $queryType => $tableNames) {
66
- if (!empty($tableNames)) {
67
- $event_code = $this->GetEventQueryType($actype, $queryType);
68
- $alertOptions["TableNames"] = implode(",", $tableNames);
69
- $this->plugin->alerts->Trigger($event_code, $alertOptions);
70
- }
71
- }
72
- }
73
-
74
- return $queries;
75
- }
76
-
77
- protected function GetEventQueryType($type_action, $type_query)
78
- {
79
- switch ($type_action) {
80
- case 'plugins':
81
- if ($type_query == 'create') return 5010;
82
- else if ($type_query == 'update') return 5011;
83
- else if ($type_query == 'delete') return 5012;
84
- case 'themes':
85
- if ($type_query == 'create') return 5013;
86
- else if ($type_query == 'update') return 5014;
87
- else if ($type_query == 'delete') return 5015;
88
- default:
89
- if ($type_query == 'create') return 5016;
90
- else if ($type_query == 'update') return 5017;
91
- else if ($type_query == 'delete') return 5018;
92
- }
93
- }
94
-
95
- protected function GetActionType($actype)
96
- {
97
- $is_themes = $actype == 'themes';
98
- $is_plugins = $actype == 'plugins';
99
- //Action Plugin Component
100
- $alertOptions = array();
101
- if ($is_plugins) {
102
- if (isset($_REQUEST['plugin'])) {
103
- $pluginFile = $_REQUEST['plugin'];
104
- } else {
105
- $pluginFile = $_REQUEST['checked'][0];
106
- }
107
- $pluginName = basename($pluginFile, '.php');
108
- $pluginName = str_replace(array('_', '-', ' '), ' ', $pluginName);
109
- $pluginName = ucwords($pluginName);
110
- $alertOptions["Plugin"] = (object)array(
111
- 'Name' => $pluginName,
112
- );
113
- //Action Theme Component
114
- } else if ($is_themes) {
115
- if (isset($_REQUEST['theme'])) {
116
- $themeName = $_REQUEST['theme'];
117
- } else {
118
- $themeName = $_REQUEST['checked'][0];
119
- }
120
- $themeName = str_replace(array('_', '-', ' '), ' ', $themeName);
121
- $themeName = ucwords($themeName);
122
- $alertOptions["Theme"] = (object)array(
123
- 'Name' => $themeName,
124
- );
125
- //Action Unknown Component
126
- } else {
127
- $alertOptions["Component"] = "Unknown";
128
- }
129
-
130
- return $alertOptions;
131
- }
132
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_Database extends WSAL_AbstractSensor
4
+ {
5
+ public function HookEvents()
6
+ {
7
+ add_action('dbdelta_queries', array($this, 'EventDBDeltaQuery'));
8
+ add_action('query', array($this, 'EventDropQuery'));
9
+ }
10
+
11
+ public function EventDropQuery($query)
12
+ {
13
+ $table_names = array();
14
+ $str = explode(" ", $query);
15
+
16
+ if (preg_match("|DROP TABLE ([^ ]*)|", $query)) {
17
+ if (!empty($str[4])) {
18
+ array_push($table_names, $str[4]);
19
+ } else {
20
+ array_push($table_names, $str[2]);
21
+ }
22
+ $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
23
+ $alertOptions = $this->GetActionType($actype);
24
+ }
25
+
26
+ if (!empty($table_names)) {
27
+ $event_code = $this->GetEventQueryType($actype, "delete");
28
+ $alertOptions["TableNames"] = implode(",", $table_names);
29
+ $this->plugin->alerts->Trigger($event_code, $alertOptions);
30
+ }
31
+ return $query;
32
+ }
33
+
34
+ public function EventDBDeltaQuery($queries)
35
+ {
36
+ $typeQueries = array(
37
+ "create" => array(),
38
+ "update" => array(),
39
+ "delete" => array()
40
+ );
41
+ global $wpdb;
42
+
43
+ foreach ($queries as $qry) {
44
+ $str = explode(" ", $qry);
45
+ if (preg_match("|CREATE TABLE ([^ ]*)|", $qry)) {
46
+ if ($wpdb->get_var("SHOW TABLES LIKE '" . $str[2] . "'") != $str[2]) {
47
+ //some plugins keep trying to create tables even when they already exist- would result in too many alerts
48
+ array_push($typeQueries['create'], $str[2]);
49
+ }
50
+ } else if (preg_match("|ALTER TABLE ([^ ]*)|", $qry)) {
51
+ array_push($typeQueries['update'], $str[2]);
52
+ } else if (preg_match("|DROP TABLE ([^ ]*)|", $qry)) {
53
+ if (!empty($str[4])) {
54
+ array_push($typeQueries['delete'], $str[4]);
55
+ } else {
56
+ array_push($typeQueries['delete'], $str[2]);
57
+ }
58
+ }
59
+ }
60
+
61
+ if (!empty($typeQueries["create"]) || !empty($typeQueries["update"]) || !empty($typeQueries["delete"])) {
62
+ $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
63
+ $alertOptions = $this->GetActionType($actype);
64
+
65
+ foreach ($typeQueries as $queryType => $tableNames) {
66
+ if (!empty($tableNames)) {
67
+ $event_code = $this->GetEventQueryType($actype, $queryType);
68
+ $alertOptions["TableNames"] = implode(",", $tableNames);
69
+ $this->plugin->alerts->Trigger($event_code, $alertOptions);
70
+ }
71
+ }
72
+ }
73
+
74
+ return $queries;
75
+ }
76
+
77
+ protected function GetEventQueryType($type_action, $type_query)
78
+ {
79
+ switch ($type_action) {
80
+ case 'plugins':
81
+ if ($type_query == 'create') return 5010;
82
+ else if ($type_query == 'update') return 5011;
83
+ else if ($type_query == 'delete') return 5012;
84
+ case 'themes':
85
+ if ($type_query == 'create') return 5013;
86
+ else if ($type_query == 'update') return 5014;
87
+ else if ($type_query == 'delete') return 5015;
88
+ default:
89
+ if ($type_query == 'create') return 5016;
90
+ else if ($type_query == 'update') return 5017;
91
+ else if ($type_query == 'delete') return 5018;
92
+ }
93
+ }
94
+
95
+ protected function GetActionType($actype)
96
+ {
97
+ $is_themes = $actype == 'themes';
98
+ $is_plugins = $actype == 'plugins';
99
+ //Action Plugin Component
100
+ $alertOptions = array();
101
+ if ($is_plugins) {
102
+ if (isset($_REQUEST['plugin'])) {
103
+ $pluginFile = $_REQUEST['plugin'];
104
+ } else {
105
+ $pluginFile = $_REQUEST['checked'][0];
106
+ }
107
+ $pluginName = basename($pluginFile, '.php');
108
+ $pluginName = str_replace(array('_', '-', ' '), ' ', $pluginName);
109
+ $pluginName = ucwords($pluginName);
110
+ $alertOptions["Plugin"] = (object)array(
111
+ 'Name' => $pluginName,
112
+ );
113
+ //Action Theme Component
114
+ } else if ($is_themes) {
115
+ if (isset($_REQUEST['theme'])) {
116
+ $themeName = $_REQUEST['theme'];
117
+ } else {
118
+ $themeName = $_REQUEST['checked'][0];
119
+ }
120
+ $themeName = str_replace(array('_', '-', ' '), ' ', $themeName);
121
+ $themeName = ucwords($themeName);
122
+ $alertOptions["Theme"] = (object)array(
123
+ 'Name' => $themeName,
124
+ );
125
+ //Action Unknown Component
126
+ } else {
127
+ $alertOptions["Component"] = "Unknown";
128
+ }
129
+
130
+ return $alertOptions;
131
+ }
132
+ }
classes/Sensors/Files.php CHANGED
@@ -1,55 +1,55 @@
1
- <?php
2
-
3
- class WSAL_Sensors_Files extends WSAL_AbstractSensor {
4
-
5
- public function HookEvents() {
6
- add_action('add_attachment', array($this, 'EventFileUploaded'));
7
- add_action('delete_attachment', array($this, 'EventFileUploadedDeleted'));
8
- add_action('admin_init', array($this, 'EventAdminInit'));
9
- }
10
-
11
- protected $IsFileUploaded = false;
12
-
13
- public function EventFileUploaded($attachmentID){
14
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
15
- if($action != 'upload-theme' && $action != 'upload-plugin'){
16
- $file = get_attached_file($attachmentID);
17
- $this->plugin->alerts->Trigger(2010, array(
18
- 'AttachmentID' => $attachmentID,
19
- 'FileName' => basename($file),
20
- 'FilePath' => dirname($file),
21
- ));
22
- }
23
- $this->IsFileUploaded = true;
24
- }
25
-
26
- public function EventFileUploadedDeleted($attachmentID){
27
- if($this->IsFileUploaded)return;
28
- $file = get_attached_file($attachmentID);
29
- $this->plugin->alerts->Trigger(2011, array(
30
- 'AttachmentID' => $attachmentID,
31
- 'FileName' => basename($file),
32
- 'FilePath' => dirname($file),
33
- ));
34
- }
35
-
36
- public function EventAdminInit(){
37
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
38
- $is_theme_editor = basename($_SERVER['SCRIPT_NAME']) == 'theme-editor.php';
39
- $is_plugin_editor = basename($_SERVER['SCRIPT_NAME']) == 'plugin-editor.php';
40
-
41
- if($is_theme_editor && $action == 'update'){
42
- $this->plugin->alerts->Trigger(2046, array(
43
- 'File' => $_REQUEST['file'],
44
- 'Theme' => $_REQUEST['theme'],
45
- ));
46
- }
47
-
48
- if($is_plugin_editor && $action == 'update'){
49
- $this->plugin->alerts->Trigger(2051, array(
50
- 'File' => $_REQUEST['file'],
51
- 'Plugin' => $_REQUEST['plugin'],
52
- ));
53
- }
54
- }
55
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_Files extends WSAL_AbstractSensor {
4
+
5
+ public function HookEvents() {
6
+ add_action('add_attachment', array($this, 'EventFileUploaded'));
7
+ add_action('delete_attachment', array($this, 'EventFileUploadedDeleted'));
8
+ add_action('admin_init', array($this, 'EventAdminInit'));
9
+ }
10
+
11
+ protected $IsFileUploaded = false;
12
+
13
+ public function EventFileUploaded($attachmentID){
14
+ $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
15
+ if($action != 'upload-theme' && $action != 'upload-plugin'){
16
+ $file = get_attached_file($attachmentID);
17
+ $this->plugin->alerts->Trigger(2010, array(
18
+ 'AttachmentID' => $attachmentID,
19
+ 'FileName' => basename($file),
20
+ 'FilePath' => dirname($file),
21
+ ));
22
+ }
23
+ $this->IsFileUploaded = true;
24
+ }
25
+
26
+ public function EventFileUploadedDeleted($attachmentID){
27
+ if($this->IsFileUploaded)return;
28
+ $file = get_attached_file($attachmentID);
29
+ $this->plugin->alerts->Trigger(2011, array(
30
+ 'AttachmentID' => $attachmentID,
31
+ 'FileName' => basename($file),
32
+ 'FilePath' => dirname($file),
33
+ ));
34
+ }
35
+
36
+ public function EventAdminInit(){
37
+ $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
38
+ $is_theme_editor = basename($_SERVER['SCRIPT_NAME']) == 'theme-editor.php';
39
+ $is_plugin_editor = basename($_SERVER['SCRIPT_NAME']) == 'plugin-editor.php';
40
+
41
+ if($is_theme_editor && $action == 'update'){
42
+ $this->plugin->alerts->Trigger(2046, array(
43
+ 'File' => $_REQUEST['file'],
44
+ 'Theme' => $_REQUEST['theme'],
45
+ ));
46
+ }
47
+
48
+ if($is_plugin_editor && $action == 'update'){
49
+ $this->plugin->alerts->Trigger(2051, array(
50
+ 'File' => $_REQUEST['file'],
51
+ 'Plugin' => $_REQUEST['plugin'],
52
+ ));
53
+ }
54
+ }
55
+ }
classes/Sensors/LogInOut.php CHANGED
@@ -1,182 +1,215 @@
1
- <?php
2
-
3
- class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor {
4
-
5
- public function HookEvents() {
6
- add_action('wp_login', array($this, 'EventLogin'), 10, 2);
7
- add_action('wp_logout', array($this, 'EventLogout'));
8
- add_action('password_reset', array($this, 'EventPasswordReset'), 10, 2);
9
- add_action('wp_login_failed', array($this, 'EventLoginFailure'));
10
- add_action('clear_auth_cookie', array($this, 'GetCurrentUser'), 10);
11
- }
12
-
13
- protected $_current_user = null;
14
-
15
- public function GetCurrentUser()
16
- {
17
- $this->_current_user = wp_get_current_user();
18
- }
19
-
20
- public function EventLogin($user_login, $user = null)
21
- {
22
- if (empty($user)) {
23
- $user = get_user_by('login', $user_login);
24
- }
25
- $userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
26
- if ( $this->plugin->settings->IsLoginSuperAdmin($user_login) ) $userRoles[] = 'superadmin';
27
- $this->plugin->alerts->Trigger(1000, array(
28
- 'Username' => $user_login,
29
- 'CurrentUserRoles' => $userRoles,
30
- ), true);
31
- }
32
-
33
- public function EventLogout()
34
- {
35
- if($this->_current_user->ID != 0){
36
- $this->plugin->alerts->Trigger(1001, array(
37
- 'CurrentUserID' => $this->_current_user->ID,
38
- 'CurrentUserRoles' => $this->plugin->settings->GetCurrentUserRoles($this->_current_user->roles),
39
- ), true);
40
- }
41
- }
42
-
43
- const TRANSIENT_FAILEDLOGINS = 'wsal-failedlogins-known';
44
- const TRANSIENT_FAILEDLOGINS_UNKNOWN = 'wsal-failedlogins-unknown';
45
-
46
- protected function GetLoginFailureLogLimit()
47
- {
48
- return 10;
49
- }
50
-
51
- protected function GetLoginFailureExpiration()
52
- {
53
- return 12 * 60 * 60;
54
- }
55
-
56
- protected function IsPastLoginFailureLimit($ip, $site_id, $user)
57
- {
58
- $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
59
- if ($user) {
60
- $dataKnown = $get_fn(self::TRANSIENT_FAILEDLOGINS);
61
- return ($dataKnown !== false) && isset($dataKnown[$site_id.":".$user->ID.":".$ip]) && ($dataKnown[$site_id.":".$user->ID.":".$ip] > $this->GetLoginFailureLogLimit());
62
- } else {
63
- $dataUnknown = $get_fn(self::TRANSIENT_FAILEDLOGINS_UNKNOWN);
64
- return ($dataUnknown !== false) && isset($dataUnknown[$site_id.":".$ip]) && ($dataUnknown[$site_id.":".$ip] > $this->GetLoginFailureLogLimit());
65
- }
66
- }
67
-
68
- protected function IncrementLoginFailure($ip, $site_id, $user)
69
- {
70
- $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
71
- $set_fn = $this->IsMultisite() ? 'set_site_transient' : 'set_transient';
72
- if ($user) {
73
- $dataKnown = $get_fn(self::TRANSIENT_FAILEDLOGINS);
74
- if(!$dataKnown)$dataKnown = array();
75
- if(!isset($dataKnown[$site_id.":".$user->ID.":".$ip]))$dataKnown[$site_id.":".$user->ID.":".$ip] = 1;
76
- $dataKnown[$site_id.":".$user->ID.":".$ip]++;
77
- $set_fn(self::TRANSIENT_FAILEDLOGINS, $dataKnown, $this->GetLoginFailureExpiration());
78
- } else {
79
- $dataUnknown = $get_fn(self::TRANSIENT_FAILEDLOGINS_UNKNOWN);
80
- if(!$dataUnknown)$dataUnknown = array();
81
- if(!isset($dataUnknown[$site_id.":".$ip]))$dataUnknown[$site_id.":".$ip] = 1;
82
- $dataUnknown[$site_id.":".$ip]++;
83
- $set_fn(self::TRANSIENT_FAILEDLOGINS_UNKNOWN, $dataUnknown, $this->GetLoginFailureExpiration());
84
- }
85
- }
86
-
87
- public function EventLoginFailure($username){
88
-
89
- list($y, $m, $d) = explode('-', date('Y-m-d'));
90
-
91
- $ip = $this->plugin->settings->GetMainClientIP();
92
-
93
- $username = array_key_exists('log', $_POST) ? $_POST["log"] : $username;
94
- $newAlertCode = 1003;
95
- $user = get_user_by('login', $username);
96
- $site_id = (function_exists('get_current_blog_id') ? get_current_blog_id() : 0);
97
- if ($user) {
98
- $newAlertCode = 1002;
99
- $userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
100
- if ( $this->plugin->settings->IsLoginSuperAdmin($username) ) $userRoles[] = 'superadmin';
101
- }
102
-
103
- if($this->IsPastLoginFailureLimit($ip, $site_id, $user))return;
104
-
105
- $objOcc = new WSAL_Models_Occurrence();
106
-
107
- if ($newAlertCode == 1002) {
108
- if (!$this->plugin->alerts->CheckEnableUserRoles($username, $userRoles))return;
109
- $occ = $objOcc->CheckKnownUsers(
110
- array(
111
- $ip,
112
- $username,
113
- 1002,
114
- $site_id,
115
- mktime(0, 0, 0, $m, $d, $y),
116
- mktime(0, 0, 0, $m, $d + 1, $y) - 1
117
- )
118
- );
119
- $occ = count($occ) ? $occ[0] : null;
120
-
121
- if (!empty($occ)) {
122
- // update existing record exists user
123
- $this->IncrementLoginFailure($ip, $site_id, $user);
124
- $new = $occ->GetMetaValue('Attempts', 0) + 1;
125
-
126
- if ($new > $this->GetLoginFailureLogLimit())
127
- $new = $this->GetLoginFailureLogLimit() . '+';
128
-
129
- $occ->UpdateMetaValue('Attempts', $new);
130
- $occ->UpdateMetaValue('Username', $username);
131
- //$occ->SetMetaValue('CurrentUserRoles', $userRoles);
132
- $occ->created_on = null;
133
- $occ->Save();
134
- } else {
135
- // create a new record exists user
136
- $this->plugin->alerts->Trigger($newAlertCode, array(
137
- 'Attempts' => 1,
138
- 'Username' => $username,
139
- 'CurrentUserRoles' => $userRoles
140
- ));
141
- }
142
- } else {
143
- $occUnknown = $objOcc->CheckUnKnownUsers(
144
- array(
145
- $ip,
146
- 1003,
147
- $site_id,
148
- mktime(0, 0, 0, $m, $d, $y),
149
- mktime(0, 0, 0, $m, $d + 1, $y) - 1
150
- )
151
- );
152
-
153
- $occUnknown = count($occUnknown) ? $occUnknown[0] : null;
154
- if (!empty($occUnknown)) {
155
- // update existing record not exists user
156
- $this->IncrementLoginFailure($ip, $site_id, false);
157
- $new = $occUnknown->GetMetaValue('Attempts', 0) + 1;
158
-
159
- if ($new > $this->GetLoginFailureLogLimit())
160
- $new = $this->GetLoginFailureLogLimit() . '+';
161
-
162
- $occUnknown->UpdateMetaValue('Attempts', $new);
163
- $occUnknown->created_on = null;
164
- $occUnknown->Save();
165
- } else {
166
- // create a new record not exists user
167
- $this->plugin->alerts->Trigger($newAlertCode, array('Attempts' => 1));
168
- }
169
- }
170
- }
171
-
172
- public function EventPasswordReset($user, $new_pass)
173
- {
174
- if (!empty($user)) {
175
- $userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
176
- $this->plugin->alerts->Trigger(4003, array(
177
- 'Username' => $user->user_login,
178
- 'CurrentUserRoles' => $userRoles,
179
- ), true);
180
- }
181
- }
182
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WSAL_Sensors_LogInOut extends WSAL_AbstractSensor
4
+ {
5
+
6
+ public function HookEvents()
7
+ {
8
+ add_action('wp_login', array($this, 'EventLogin'), 10, 2);
9
+ add_action('wp_logout', array($this, 'EventLogout'));
10
+ add_action('password_reset', array($this, 'EventPasswordReset'), 10, 2);
11
+ add_action('wp_login_failed', array($this, 'EventLoginFailure'));
12
+ add_action('clear_auth_cookie', array($this, 'GetCurrentUser'), 10);
13
+ add_filter('wp_login_blocked', array($this, 'EventLoginBlocked'), 10, 1);
14
+ }
15
+
16
+ protected $_current_user = null;
17
+
18
+ public function GetCurrentUser()
19
+ {
20
+ $this->_current_user = wp_get_current_user();
21
+ }
22
+
23
+ public function EventLogin($user_login, $user = null)
24
+ {
25
+ if (empty($user)) {
26
+ $user = get_user_by('login', $user_login);
27
+ }
28
+ $userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
29
+ if ($this->plugin->settings->IsLoginSuperAdmin($user_login)) {
30
+ $userRoles[] = 'superadmin';
31
+ }
32
+ $this->plugin->alerts->Trigger(1000, array(
33
+ 'Username' => $user_login,
34
+ 'CurrentUserRoles' => $userRoles,
35
+ ), true);
36
+ }
37
+
38
+ public function EventLogout()
39
+ {
40
+ if ($this->_current_user->ID != 0) {
41
+ $this->plugin->alerts->Trigger(1001, array(
42
+ 'CurrentUserID' => $this->_current_user->ID,
43
+ 'CurrentUserRoles' => $this->plugin->settings->GetCurrentUserRoles($this->_current_user->roles),
44
+ ), true);
45
+ }
46
+ }
47
+
48
+ const TRANSIENT_FAILEDLOGINS = 'wsal-failedlogins-known';
49
+ const TRANSIENT_FAILEDLOGINS_UNKNOWN = 'wsal-failedlogins-unknown';
50
+
51
+ protected function GetLoginFailureLogLimit()
52
+ {
53
+ return 10;
54
+ }
55
+
56
+ protected function GetLoginFailureExpiration()
57
+ {
58
+ return 12 * 60 * 60;
59
+ }
60
+
61
+ protected function IsPastLoginFailureLimit($ip, $site_id, $user)
62
+ {
63
+ $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
64
+ if ($user) {
65
+ $dataKnown = $get_fn(self::TRANSIENT_FAILEDLOGINS);
66
+ return ($dataKnown !== false) && isset($dataKnown[$site_id.":".$user->ID.":".$ip]) && ($dataKnown[$site_id.":".$user->ID.":".$ip] > $this->GetLoginFailureLogLimit());
67
+ } else {
68
+ $dataUnknown = $get_fn(self::TRANSIENT_FAILEDLOGINS_UNKNOWN);
69
+ return ($dataUnknown !== false) && isset($dataUnknown[$site_id.":".$ip]) && ($dataUnknown[$site_id.":".$ip] > $this->GetLoginFailureLogLimit());
70
+ }
71
+ }
72
+
73
+ protected function IncrementLoginFailure($ip, $site_id, $user)
74
+ {
75
+ $get_fn = $this->IsMultisite() ? 'get_site_transient' : 'get_transient';
76
+ $set_fn = $this->IsMultisite() ? 'set_site_transient' : 'set_transient';
77
+ if ($user) {
78
+ $dataKnown = $get_fn(self::TRANSIENT_FAILEDLOGINS);
79
+ if (!$dataKnown) {
80
+ $dataKnown = array();
81
+ }
82
+ if (!isset($dataKnown[$site_id.":".$user->ID.":".$ip])) {
83
+ $dataKnown[$site_id.":".$user->ID.":".$ip] = 1;
84
+ }
85
+ $dataKnown[$site_id.":".$user->ID.":".$ip]++;
86
+ $set_fn(self::TRANSIENT_FAILEDLOGINS, $dataKnown, $this->GetLoginFailureExpiration());
87
+ } else {
88
+ $dataUnknown = $get_fn(self::TRANSIENT_FAILEDLOGINS_UNKNOWN);
89
+ if (!$dataUnknown) {
90
+ $dataUnknown = array();
91
+ }
92
+ if (!isset($dataUnknown[$site_id.":".$ip])) {
93
+ $dataUnknown[$site_id.":".$ip] = 1;
94
+ }
95
+ $dataUnknown[$site_id.":".$ip]++;
96
+ $set_fn(self::TRANSIENT_FAILEDLOGINS_UNKNOWN, $dataUnknown, $this->GetLoginFailureExpiration());
97
+ }
98
+ }
99
+
100
+ public function EventLoginFailure($username)
101
+ {
102
+ list($y, $m, $d) = explode('-', date('Y-m-d'));
103
+
104
+ $ip = $this->plugin->settings->GetMainClientIP();
105
+
106
+ $username = array_key_exists('log', $_POST) ? $_POST["log"] : $username;
107
+ $newAlertCode = 1003;
108
+ $user = get_user_by('login', $username);
109
+ $site_id = (function_exists('get_current_blog_id') ? get_current_blog_id() : 0);
110
+ if ($user) {
111
+ $newAlertCode = 1002;
112
+ $userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
113
+ if ($this->plugin->settings->IsLoginSuperAdmin($username)) {
114
+ $userRoles[] = 'superadmin';
115
+ }
116
+ }
117
+
118
+ if ($this->IsPastLoginFailureLimit($ip, $site_id, $user)) {
119
+ return;
120
+ }
121
+
122
+ $objOcc = new WSAL_Models_Occurrence();
123
+
124
+ if ($newAlertCode == 1002) {
125
+ if (!$this->plugin->alerts->CheckEnableUserRoles($username, $userRoles)) {
126
+ return;
127
+ }
128
+ $occ = $objOcc->CheckKnownUsers(
129
+ array(
130
+ $ip,
131
+ $username,
132
+ 1002,
133
+ $site_id,
134
+ mktime(0, 0, 0, $m, $d, $y),
135
+ mktime(0, 0, 0, $m, $d + 1, $y) - 1
136
+ )
137
+ );
138
+ $occ = count($occ) ? $occ[0] : null;
139
+
140
+ if (!empty($occ)) {
141
+ // update existing record exists user
142
+ $this->IncrementLoginFailure($ip, $site_id, $user);
143
+ $new = $occ->GetMetaValue('Attempts', 0) + 1;
144
+
145
+ if ($new > $this->GetLoginFailureLogLimit()) {
146
+ $new = $this->GetLoginFailureLogLimit() . '+';
147
+ }
148
+ $occ->UpdateMetaValue('Attempts', $new);
149
+ $occ->UpdateMetaValue('Username', $username);
150
+ //$occ->SetMetaValue('CurrentUserRoles', $userRoles);
151
+ $occ->created_on = null;
152
+ $occ->Save();
153
+ } else {
154
+ // create a new record exists user
155
+ $this->plugin->alerts->Trigger($newAlertCode, array(
156
+ 'Attempts' => 1,
157
+ 'Username' => $username,
158
+ 'CurrentUserRoles' => $userRoles
159
+ ));
160
+ }
161
+ } else {
162
+ $occUnknown = $objOcc->CheckUnKnownUsers(
163
+ array(
164
+ $ip,
165
+ 1003,
166
+ $site_id,
167
+ mktime(0, 0, 0, $m, $d, $y),
168
+ mktime(0, 0, 0, $m, $d + 1, $y) - 1
169
+ )
170
+ );
171
+
172
+ $occUnknown = count($occUnknown) ? $occUnknown[0] : null;
173
+ if (!empty($occUnknown)) {
174
+ // update existing record not exists user
175
+ $this->IncrementLoginFailure($ip, $site_id, false);
176
+ $new = $occUnknown->GetMetaValue('Attempts', 0) + 1;
177
+
178
+ if ($new > $this->GetLoginFailureLogLimit()) {
179
+ $new = $this->GetLoginFailureLogLimit() . '+';
180
+ }
181
+ $occUnknown->UpdateMetaValue('Attempts', $new);
182
+ $occUnknown->created_on = null;
183
+ $occUnknown->Save();
184
+ } else {
185
+ // create a new record not exists user
186
+ $this->plugin->alerts->Trigger($newAlertCode, array('Attempts' => 1));
187
+ }
188
+ }
189
+ }
190
+
191
+ public function EventPasswordReset($user, $new_pass)
192
+ {
193
+ if (!empty($user)) {
194
+ $userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
195
+ $this->plugin->alerts->Trigger(4003, array(
196
+ 'Username' => $user->user_login,
197
+ 'CurrentUserRoles' => $userRoles
198
+ ), true);
199
+ }
200
+ }
201
+
202
+ public function EventLoginBlocked($username)
203
+ {
204
+ $user = get_user_by('login', $username);
205
+ $userRoles = $this->plugin->settings->GetCurrentUserRoles($user->roles);
206
+
207
+ if ($this->plugin->settings->IsLoginSuperAdmin($username)) {
208
+ $userRoles[] = 'superadmin';
209
+ }
210
+ $this->plugin->alerts->Trigger(1004, array(
211
+ 'Username' => $username,
212
+ 'CurrentUserRoles' => $userRoles
213
+ ), true);
214
+ }
215
+ }
classes/Sensors/Menus.php CHANGED
@@ -1,416 +1,416 @@
1
- <?php
2
-
3
- class WSAL_Sensors_Menus extends WSAL_AbstractSensor
4
- {
5
- protected $_OldMenu = null;
6
- protected $_OldMenuTerms = array();
7
- protected $_OldMenuItems = array();
8
- protected $_OldMenuLocations = null;
9
-
10
- public function HookEvents()
11
- {
12
- add_action('wp_create_nav_menu', array($this, 'CreateMenu'), 10, 2);
13
- add_action('wp_delete_nav_menu', array($this, 'DeleteMenu'), 10, 1);
14
- add_action('wp_update_nav_menu', array($this, 'UpdateMenu'), 10, 2);
15
- add_action('admin_menu', array($this, 'ManageMenuLocations'));
16
-
17
- add_action('admin_init', array($this, 'EventAdminInit'));
18
- // Customizer trigger
19
- add_action('customize_register', array($this, 'CustomizeInit'));
20
- add_action('customize_save_after', array($this, 'CustomizeSave'));
21
- }
22
-
23
- public function CreateMenu($term_id, $menu_data)
24
- {
25
- $this->plugin->alerts->Trigger(2078, array(
26
- 'MenuName' => $menu_data['menu-name']
27
- ));
28
- }
29
-
30
- public function ManageMenuLocations()
31
- {
32
- // Manage Location tab
33
- if (isset($_POST['menu-locations'])) {
34
- $new_locations = $_POST['menu-locations'];
35
- if (isset($new_locations['primary'])) {
36
- $this->LocationSetting($new_locations['primary'], 'primary');
37
- }
38
- if (isset($new_locations['social'])) {
39
- $this->LocationSetting($new_locations['social'], 'social');
40
- }
41
- }
42
- }
43
-
44
- private function LocationSetting($new_location, $type)
45
- {
46
- $old_locations = get_nav_menu_locations();
47
- if ($new_location != 0) {
48
- $menu = wp_get_nav_menu_object($new_location);
49
- if (!empty($old_locations[$type]) && $old_locations[$type] != $new_location) {
50
- $this->EventMenuSetting($menu->name, "Enabled", "Location: ".$type." menu");
51
- }
52
- } else {
53
- if (!empty($old_locations[$type])) {
54
- $menu = wp_get_nav_menu_object($old_locations[$type]);
55
- $this->EventMenuSetting($menu->name, "Disabled", "Location: ".$type." menu");
56
- }
57
- }
58
- }
59
-
60
- public function DeleteMenu($term_id)
61
- {
62
- if ($this->_OldMenu) {
63
- $this->plugin->alerts->Trigger(2081, array(
64
- 'MenuName' => $this->_OldMenu->name
65
- ));
66
- }
67
- }
68
-
69
- public function UpdateMenu($menu_id, $menu_data = null)
70
- {
71
- if (!empty($menu_data)) {
72
- $contentNamesOld = array();
73
- $contentTypesOld = array();
74
- $contentOrderOld = array();
75
-
76
- $items = wp_get_nav_menu_items($menu_id);
77
- if (!empty($items)) {
78
- foreach ($items as $item) {
79
- array_push($contentNamesOld, $item->title);
80
- array_push($contentTypesOld, $item->object);
81
- $contentOrderOld[$item->ID] = $item->menu_order;
82
- }
83
- }
84
- // Menu changed name
85
- if (!empty($this->_OldMenuTerms) && isset($_POST['menu']) && isset($_POST['menu-name'])) {
86
- foreach ($this->_OldMenuTerms as $oldMenuTerm) {
87
- if ($oldMenuTerm['term_id'] == $_POST['menu']) {
88
- if ($oldMenuTerm['name'] != $_POST['menu-name']) {
89
- $this->EventChangeName($oldMenuTerm['name'], $_POST['menu-name']);
90
- } else {
91
- // Remove the last menu item
92
- if (count($contentNamesOld) == 1 && count($contentTypesOld) == 1) {
93
- $this->EventRemoveItems($contentTypesOld[0], $contentNamesOld[0], $_POST['menu-name']);
94
- }
95
- }
96
- }
97
- }
98
- }
99
-
100
- $is_occurred_event = false;
101
- if (isset($_POST['menu-item-title']) && isset($_POST['menu-item-object'])) {
102
- $contentNamesNew = array_values($_POST['menu-item-title']);
103
- $contentTypesNew = array_values($_POST['menu-item-object']);
104
- $contentOrderNew = $_POST['menu-item-position'];
105
-
106
- $order = array_diff_assoc($contentOrderNew, $contentOrderOld);
107
- // Changed order of the objects in a menu
108
- if ((count($contentOrderOld) == count($contentOrderNew)) && count($order) > 0) {
109
- $is_occurred_event = true;
110
- $this->EventChangeOrder($menu_data['menu-name']);
111
- }
112
- $addedNames = array_diff_assoc($contentNamesNew, $contentNamesOld);
113
- $addedTypes = array_diff_assoc($contentTypesNew, $contentTypesOld);
114
-
115
- if (!$is_occurred_event) {
116
- // Add Items to the menu
117
- if (count($addedNames) > 0 && count($addedTypes) > 0) {
118
- $is_occurred_event = true;
119
- foreach ($addedNames as $key => $contentName) {
120
- $contentType = str_replace("custom", "custom link", $contentTypesNew[$key]);
121
- if (!empty($contentType)) {
122
- $this->EventAddItems($contentType, $contentName, $menu_data['menu-name']);
123
- }
124
- }
125
- }
126
-
127
- $removedNames = array_diff_assoc($contentNamesOld, $contentNamesNew);
128
- $removedTypes = array_diff_assoc($contentTypesOld, $contentTypesNew);
129
- // Remove items from the menu
130
- if (count($removedNames) > 0 && count($removedTypes) > 0) {
131
- $is_occurred_event = true;
132
- foreach ($removedNames as $key => $contentName) {
133
- $contentType = str_replace("custom", "custom link", $contentTypesOld[$key]);
134
- if (!empty($contentType)) {
135
- $this->EventRemoveItems($contentType, $contentName, $menu_data['menu-name']);
136
- }
137
- }
138
- }
139
- }
140
-
141
- // Modified Items in the menu
142
- if (!$is_occurred_event && count($addedNames) > 0) {
143
- foreach ($addedNames as $key => $contentName) {
144
- $contentType = str_replace("custom", "custom link", $contentTypesOld[$key]);
145
- if (!empty($contentType)) {
146
- $this->EventModifiedItems($contentType, $contentName, $menu_data['menu-name']);
147
- }
148
- }
149
- }
150
- }
151
- // Enable/Disable menu setting
152
- $nav_menu_options = maybe_unserialize(get_option('nav_menu_options'));
153
- $auto_add = null;
154
- if (isset($nav_menu_options['auto_add'])) {
155
- if (in_array($menu_id, $nav_menu_options['auto_add'])) {
156
- if (empty($_POST['auto-add-pages'])) {
157
- $auto_add = "Disabled";
158
- }
159
- } else {
160
- if (isset($_POST['auto-add-pages'])) {
161
- $auto_add = "Enabled";
162
- }
163
- }
164
- } else {
165
- if (isset($_POST['auto-add-pages'])) {
166
- $auto_add = "Enabled";
167
- }
168
- }
169
- // Alert 2082 Auto add pages
170
- if (!empty($auto_add)) {
171
- $this->EventMenuSetting($menu_data['menu-name'], $auto_add, "Auto add pages");
172
- }
173
-
174
- $nav_menu_locations = get_nav_menu_locations();
175
-
176
- $locationPrimary = null;
177
- if (isset($this->_OldMenuLocations['primary']) && isset($nav_menu_locations['primary'])) {
178
- if ($nav_menu_locations['primary'] == $menu_id && $this->_OldMenuLocations['primary'] != $nav_menu_locations['primary']) {
179
- $locationPrimary = "Enabled";
180
- }
181
- } elseif (empty($this->_OldMenuLocations['primary']) && isset($nav_menu_locations['primary'])) {
182
- if ($nav_menu_locations['primary'] == $menu_id) {
183
- $locationPrimary = "Enabled";
184
- }
185
- } elseif (isset($this->_OldMenuLocations['primary']) && empty($nav_menu_locations['primary'])) {
186
- if ($this->_OldMenuLocations['primary'] == $menu_id) {
187
- $locationPrimary = "Disabled";
188
- }
189
- }
190
- // Alert 2082 Primary menu
191
- if (!empty($locationPrimary)) {
192
- $this->EventMenuSetting($menu_data['menu-name'], $locationPrimary, "Location: primary menu");
193
- }
194
-
195
- $locationSocial = null;
196
- if (isset($this->_OldMenuLocations['social']) && isset($nav_menu_locations['social'])) {
197
- if ($nav_menu_locations['social'] == $menu_id && $this->_OldMenuLocations['social'] != $nav_menu_locations['social']) {
198
- $locationSocial = "Enabled";
199
- }
200
- } elseif (empty($this->_OldMenuLocations['social']) && isset($nav_menu_locations['social'])) {
201
- if ($nav_menu_locations['social'] == $menu_id) {
202
- $locationSocial = "Enabled";
203
- }
204
- } elseif (isset($this->_OldMenuLocations['social']) && empty($nav_menu_locations['social'])) {
205
- if ($this->_OldMenuLocations['social'] == $menu_id) {
206
- $locationSocial = "Disabled";
207
- }
208
- }
209
- // Alert 2082 Social links menu
210
- if (!empty($locationSocial)) {
211
- $this->EventMenuSetting($menu_data['menu-name'], $locationSocial, "Location: social menu");
212
- }
213
- }
214
- }
215
-
216
- private function BuildOldMenuTermsAndItems()
217
- {
218
- $menus = wp_get_nav_menus();
219
- if (!empty($menus)) {
220
- foreach ($menus as $menu) {
221
- array_push($this->_OldMenuTerms, array("term_id" => $menu->term_id, "name" => $menu->name));
222
- $items = wp_get_nav_menu_items($menu->term_id);
223
- if (!empty($items)) {
224
- foreach ($items as $item) {
225
- array_push($this->_OldMenuItems, array(
226
- 'item_id' => $item->ID,
227
- 'title' => $item->title,
228
- 'object' => $item->object,
229
- 'menu_name' => $menu->name,
230
- 'menu_order' => $item->menu_order
231
- ));
232
- }
233
- }
234
- }
235
- }
236
- }
237
-
238
- public function EventAdminInit()
239
- {
240
- $is_nav_menu = basename($_SERVER['SCRIPT_NAME']) == 'nav-menus.php';
241
- if ($is_nav_menu) {
242
- if (isset($_GET['action']) && $_GET['action'] == 'delete') {
243
- if (isset($_GET['menu'])) {
244
- $this->_OldMenu = wp_get_nav_menu_object($_GET['menu']);
245
- }
246
- } else {
247
- $this->BuildOldMenuTermsAndItems();
248
- }
249
- $this->_OldMenuLocations = get_nav_menu_locations();
250
- }
251
- }
252
-
253
- public function CustomizeInit()
254
- {
255
- $this->BuildOldMenuTermsAndItems();
256
- $this->_OldMenuLocations = get_nav_menu_locations();
257
- }
258
-
259
- /**
260
- * Customize Events Function
261
- */
262
- public function CustomizeSave()
263
- {
264
- $updateMenus = array();
265
- $menus = wp_get_nav_menus();
266
- if (!empty($menus)) {
267
- foreach ($menus as $menu) {
268
- array_push($updateMenus, array("term_id" => $menu->term_id, "name" => $menu->name));
269
- }
270
- }
271
- // Deleted Menu
272
- if (isset($updateMenus) && isset($this->_OldMenuTerms)) {
273
- $terms = array_diff(array_map('serialize', $this->_OldMenuTerms), array_map('serialize', $updateMenus));
274
- $terms = array_map('unserialize', $terms);
275
-
276
- if (isset($terms) && count($terms) > 0) {
277
- foreach ($terms as $term) {
278
- $this->plugin->alerts->Trigger(2081, array(
279
- 'MenuName' => $term['name']
280
- ));
281
- }
282
- }
283
- }
284
- if (isset($_POST['action']) && $_POST['action'] == 'customize_save') {
285
- if (isset($_POST['wp_customize'], $_POST['customized'])) {
286
- $customized = json_decode(wp_unslash($_POST['customized']), true);
287
- if (is_array($customized)) {
288
- foreach ($customized as $key => $value) {
289
- if (!empty($value['nav_menu_term_id'])) {
290
- $is_occurred_event = false;
291
- $menu = wp_get_nav_menu_object($value['nav_menu_term_id']);
292
- $content_name = !empty($value['title']) ? $value['title'] : "no title";
293
- if (!empty($this->_OldMenuItems)) {
294
- foreach ($this->_OldMenuItems as $old_item) {
295
- $item_id = substr(trim($key, ']'), 14);
296
- // Modified Items in the menu
297
- if ($old_item['item_id'] == $item_id && $old_item['title'] != $content_name) {
298
- $is_occurred_event = true;
299
- $this->EventModifiedItems($value['type_label'], $content_name, $menu->name);
300
- }
301
- // Changed order of the objects in a menu
302
- if ($old_item['item_id'] == $item_id && $old_item['menu_order'] != $value['position']) {
303
- $is_occurred_event = true;
304
- $this->EventChangeOrder($menu->name);
305
- return;
306
- }
307
- }
308
- }
309
- // Add Items to the menu
310
- if (!$is_occurred_event) {
311
- $menu_name = !empty($customized['new_menu_name']) ? $customized['new_menu_name'] : $menu->name;
312
- $this->EventAddItems($value['type_label'], $content_name, $menu_name);
313
- }
314
- } else {
315
- // Menu changed name
316
- if (isset($updateMenus) && isset($this->_OldMenuTerms)) {
317
- foreach ($this->_OldMenuTerms as $old_menu) {
318
- foreach ($updateMenus as $update_menu) {
319
- if ($old_menu['term_id'] == $update_menu['term_id'] && $old_menu['name'] != $update_menu['name']) {
320
- $this->EventChangeName($old_menu['name'], $update_menu['name']);
321
- }
322
- }
323
- }
324
- }
325
- // Setting Auto add pages
326
- if (!empty($value) && isset($value['auto_add'])) {
327
- if ($value['auto_add']) {
328
- $this->EventMenuSetting($value['name'], 'Enabled', "Auto add pages");
329
- } else {
330
- $this->EventMenuSetting($value['name'], 'Disabled', "Auto add pages");
331
- }
332
- }
333
- // Setting Location
334
- if (false !== strpos($key, 'nav_menu_locations[')) {
335
- $loc = substr(trim($key, ']'), 19);
336
- if (!empty($value)) {
337
- $menu = wp_get_nav_menu_object($value);
338
- $menu_name = !empty($customized['new_menu_name']) ? $customized['new_menu_name'] : (!empty($menu) ? $menu->name : '');
339
- $this->EventMenuSetting($menu_name, "Enabled", "Location: ".$loc." menu");
340
- } else {
341
- if (!empty($this->_OldMenuLocations[$loc])) {
342
- $menu = wp_get_nav_menu_object($this->_OldMenuLocations[$loc]);
343
- $menu_name = !empty($customized['new_menu_name']) ? $customized['new_menu_name'] : (!empty($menu) ? $menu->name : '');
344
- $this->EventMenuSetting($menu_name, "Disabled", "Location: ".$loc." menu");
345
- }
346
- }
347
- }
348
- // Remove items from the menu
349
- if (false !== strpos($key, 'nav_menu_item[')) {
350
- $item_id = substr(trim($key, ']'), 14);
351
- if (!empty($this->_OldMenuItems)) {
352
- foreach ($this->_OldMenuItems as $old_item) {
353
- if ($old_item['item_id'] == $item_id) {
354
- $this->EventRemoveItems($old_item['object'], $old_item['title'], $old_item['menu_name']);
355
- }
356
- }
357
- }
358
- }
359
- }
360
- }
361
- }
362
- }
363
- }
364
- }
365
-
366
- private function EventAddItems($content_type, $content_name, $menu_name)
367
- {
368
- $this->plugin->alerts->Trigger(2079, array(
369
- 'ContentType' => $content_type,
370
- 'ContentName' => $content_name,
371
- 'MenuName' => $menu_name
372
- ));
373
- }
374
-
375
- private function EventRemoveItems($content_type, $content_name, $menu_name)
376
- {
377
- $this->plugin->alerts->Trigger(2080, array(
378
- 'ContentType' => $content_type,
379
- 'ContentName' => $content_name,
380
- 'MenuName' => $menu_name
381
- ));
382
- }
383
-
384
- private function EventMenuSetting($menu_name, $status, $menu_setting)
385
- {
386
- $this->plugin->alerts->Trigger(2082, array(
387
- 'Status' => $status,
388
- 'MenuSetting' => $menu_setting,
389
- 'MenuName' => $menu_name
390
- ));
391
- }
392
-
393
- private function EventModifiedItems($content_type, $content_name, $menu_name)
394
- {
395
- $this->plugin->alerts->Trigger(2083, array(
396
- 'ContentType' => $content_type,
397
- 'ContentName' => $content_name,
398
- 'MenuName' => $menu_name
399
- ));
400
- }
401
-
402
- private function EventChangeName($old_menu_name, $new_menu_name)
403
- {
404
- $this->plugin->alerts->Trigger(2084, array(
405
- 'OldMenuName' => $old_menu_name,
406
- 'NewMenuName' => $new_menu_name
407
- ));
408
- }
409
-
410
- private function EventChangeOrder($menu_name)
411
- {
412
- $this->plugin->alerts->Trigger(2085, array(
413
- 'MenuName' => $menu_name
414
- ));
415
- }
416
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_Menus extends WSAL_AbstractSensor
4
+ {
5
+ protected $_OldMenu = null;
6
+ protected $_OldMenuTerms = array();
7
+ protected $_OldMenuItems = array();
8
+ protected $_OldMenuLocations = null;
9
+
10
+ public function HookEvents()
11
+ {
12
+ add_action('wp_create_nav_menu', array($this, 'CreateMenu'), 10, 2);
13
+ add_action('wp_delete_nav_menu', array($this, 'DeleteMenu'), 10, 1);
14
+ add_action('wp_update_nav_menu', array($this, 'UpdateMenu'), 10, 2);
15
+ add_action('admin_menu', array($this, 'ManageMenuLocations'));
16
+
17
+ add_action('admin_init', array($this, 'EventAdminInit'));
18
+ // Customizer trigger
19
+ add_action('customize_register', array($this, 'CustomizeInit'));
20
+ add_action('customize_save_after', array($this, 'CustomizeSave'));
21
+ }
22
+
23
+ public function CreateMenu($term_id, $menu_data)
24
+ {
25
+ $this->plugin->alerts->Trigger(2078, array(
26
+ 'MenuName' => $menu_data['menu-name']
27
+ ));
28
+ }
29
+
30
+ public function ManageMenuLocations()
31
+ {
32
+ // Manage Location tab
33
+ if (isset($_POST['menu-locations'])) {
34
+ $new_locations = $_POST['menu-locations'];
35
+ if (isset($new_locations['primary'])) {
36
+ $this->LocationSetting($new_locations['primary'], 'primary');
37
+ }
38
+ if (isset($new_locations['social'])) {
39
+ $this->LocationSetting($new_locations['social'], 'social');
40
+ }
41
+ }
42
+ }
43
+
44
+ private function LocationSetting($new_location, $type)
45
+ {
46
+ $old_locations = get_nav_menu_locations();
47
+ if ($new_location != 0) {
48
+ $menu = wp_get_nav_menu_object($new_location);
49
+ if (!empty($old_locations[$type]) && $old_locations[$type] != $new_location) {
50
+ $this->EventMenuSetting($menu->name, "Enabled", "Location: ".$type." menu");
51
+ }
52
+ } else {
53
+ if (!empty($old_locations[$type])) {
54
+ $menu = wp_get_nav_menu_object($old_locations[$type]);
55
+ $this->EventMenuSetting($menu->name, "Disabled", "Location: ".$type." menu");
56
+ }
57
+ }
58
+ }
59
+
60
+ public function DeleteMenu($term_id)
61
+ {
62
+ if ($this->_OldMenu) {
63
+ $this->plugin->alerts->Trigger(2081, array(
64
+ 'MenuName' => $this->_OldMenu->name
65
+ ));
66
+ }
67
+ }
68
+
69
+ public function UpdateMenu($menu_id, $menu_data = null)
70
+ {
71
+ if (!empty($menu_data)) {
72
+ $contentNamesOld = array();
73
+ $contentTypesOld = array();
74
+ $contentOrderOld = array();
75
+
76
+ $items = wp_get_nav_menu_items($menu_id);
77
+ if (!empty($items)) {
78
+ foreach ($items as $item) {
79
+ array_push($contentNamesOld, $item->title);
80
+ array_push($contentTypesOld, $item->object);
81
+ $contentOrderOld[$item->ID] = $item->menu_order;
82
+ }
83
+ }
84
+ // Menu changed name
85
+ if (!empty($this->_OldMenuTerms) && isset($_POST['menu']) && isset($_POST['menu-name'])) {
86
+ foreach ($this->_OldMenuTerms as $oldMenuTerm) {
87
+ if ($oldMenuTerm['term_id'] == $_POST['menu']) {
88
+ if ($oldMenuTerm['name'] != $_POST['menu-name']) {
89
+ $this->EventChangeName($oldMenuTerm['name'], $_POST['menu-name']);
90
+ } else {
91
+ // Remove the last menu item
92
+ if (count($contentNamesOld) == 1 && count($contentTypesOld) == 1) {
93
+ $this->EventRemoveItems($contentTypesOld[0], $contentNamesOld[0], $_POST['menu-name']);
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ $is_occurred_event = false;
101
+ if (isset($_POST['menu-item-title']) && isset($_POST['menu-item-object'])) {
102
+ $contentNamesNew = array_values($_POST['menu-item-title']);
103
+ $contentTypesNew = array_values($_POST['menu-item-object']);
104
+ $contentOrderNew = $_POST['menu-item-position'];
105
+
106
+ $order = array_diff_assoc($contentOrderNew, $contentOrderOld);
107
+ // Changed order of the objects in a menu
108
+ if ((count($contentOrderOld) == count($contentOrderNew)) && count($order) > 0) {
109
+ $is_occurred_event = true;
110
+ $this->EventChangeOrder($menu_data['menu-name']);
111
+ }
112
+ $addedNames = array_diff_assoc($contentNamesNew, $contentNamesOld);
113
+ $addedTypes = array_diff_assoc($contentTypesNew, $contentTypesOld);
114
+
115
+ if (!$is_occurred_event) {
116
+ // Add Items to the menu
117
+ if (count($addedNames) > 0 && count($addedTypes) > 0) {
118
+ $is_occurred_event = true;
119
+ foreach ($addedNames as $key => $contentName) {
120
+ $contentType = str_replace("custom", "custom link", $contentTypesNew[$key]);
121
+ if (!empty($contentType)) {
122
+ $this->EventAddItems($contentType, $contentName, $menu_data['menu-name']);
123
+ }
124
+ }
125
+ }
126
+
127
+ $removedNames = array_diff_assoc($contentNamesOld, $contentNamesNew);
128
+ $removedTypes = array_diff_assoc($contentTypesOld, $contentTypesNew);
129
+ // Remove items from the menu
130
+ if (count($removedNames) > 0 && count($removedTypes) > 0) {
131
+ $is_occurred_event = true;
132
+ foreach ($removedNames as $key => $contentName) {
133
+ $contentType = str_replace("custom", "custom link", $contentTypesOld[$key]);
134
+ if (!empty($contentType)) {
135
+ $this->EventRemoveItems($contentType, $contentName, $menu_data['menu-name']);
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ // Modified Items in the menu
142
+ if (!$is_occurred_event && count($addedNames) > 0) {
143
+ foreach ($addedNames as $key => $contentName) {
144
+ $contentType = str_replace("custom", "custom link", $contentTypesOld[$key]);
145
+ if (!empty($contentType)) {
146
+ $this->EventModifiedItems($contentType, $contentName, $menu_data['menu-name']);
147
+ }
148
+ }
149
+ }
150
+ }
151
+ // Enable/Disable menu setting
152
+ $nav_menu_options = maybe_unserialize(get_option('nav_menu_options'));
153
+ $auto_add = null;
154
+ if (isset($nav_menu_options['auto_add'])) {
155
+ if (in_array($menu_id, $nav_menu_options['auto_add'])) {
156
+ if (empty($_POST['auto-add-pages'])) {
157
+ $auto_add = "Disabled";
158
+ }
159
+ } else {
160
+ if (isset($_POST['auto-add-pages'])) {
161
+ $auto_add = "Enabled";
162
+ }
163
+ }
164
+ } else {
165
+ if (isset($_POST['auto-add-pages'])) {
166
+ $auto_add = "Enabled";
167
+ }
168
+ }
169
+ // Alert 2082 Auto add pages
170
+ if (!empty($auto_add)) {
171
+ $this->EventMenuSetting($menu_data['menu-name'], $auto_add, "Auto add pages");
172
+ }
173
+
174
+ $nav_menu_locations = get_nav_menu_locations();
175
+
176
+ $locationPrimary = null;
177
+ if (isset($this->_OldMenuLocations['primary']) && isset($nav_menu_locations['primary'])) {
178
+ if ($nav_menu_locations['primary'] == $menu_id && $this->_OldMenuLocations['primary'] != $nav_menu_locations['primary']) {
179
+ $locationPrimary = "Enabled";
180
+ }
181
+ } elseif (empty($this->_OldMenuLocations['primary']) && isset($nav_menu_locations['primary'])) {
182
+ if ($nav_menu_locations['primary'] == $menu_id) {
183
+ $locationPrimary = "Enabled";
184
+ }
185
+ } elseif (isset($this->_OldMenuLocations['primary']) && empty($nav_menu_locations['primary'])) {
186
+ if ($this->_OldMenuLocations['primary'] == $menu_id) {
187
+ $locationPrimary = "Disabled";
188
+ }
189
+ }
190
+ // Alert 2082 Primary menu
191
+ if (!empty($locationPrimary)) {
192
+ $this->EventMenuSetting($menu_data['menu-name'], $locationPrimary, "Location: primary menu");
193
+ }
194
+
195
+ $locationSocial = null;
196
+ if (isset($this->_OldMenuLocations['social']) && isset($nav_menu_locations['social'])) {
197
+ if ($nav_menu_locations['social'] == $menu_id && $this->_OldMenuLocations['social'] != $nav_menu_locations['social']) {
198
+ $locationSocial = "Enabled";
199
+ }
200
+ } elseif (empty($this->_OldMenuLocations['social']) && isset($nav_menu_locations['social'])) {
201
+ if ($nav_menu_locations['social'] == $menu_id) {
202
+ $locationSocial = "Enabled";
203
+ }
204
+ } elseif (isset($this->_OldMenuLocations['social']) && empty($nav_menu_locations['social'])) {
205
+ if ($this->_OldMenuLocations['social'] == $menu_id) {
206
+ $locationSocial = "Disabled";
207
+ }
208
+ }
209
+ // Alert 2082 Social links menu
210
+ if (!empty($locationSocial)) {
211
+ $this->EventMenuSetting($menu_data['menu-name'], $locationSocial, "Location: social menu");
212
+ }
213
+ }
214
+ }
215
+
216
+ private function BuildOldMenuTermsAndItems()
217
+ {
218
+ $menus = wp_get_nav_menus();
219
+ if (!empty($menus)) {
220
+ foreach ($menus as $menu) {
221
+ array_push($this->_OldMenuTerms, array("term_id" => $menu->term_id, "name" => $menu->name));
222
+ $items = wp_get_nav_menu_items($menu->term_id);
223
+ if (!empty($items)) {
224
+ foreach ($items as $item) {
225
+ array_push($this->_OldMenuItems, array(
226
+ 'item_id' => $item->ID,
227
+ 'title' => $item->title,
228
+ 'object' => $item->object,
229
+ 'menu_name' => $menu->name,
230
+ 'menu_order' => $item->menu_order
231
+ ));
232
+ }
233
+ }
234
+ }
235
+ }
236
+ }
237
+
238
+ public function EventAdminInit()
239
+ {
240
+ $is_nav_menu = basename($_SERVER['SCRIPT_NAME']) == 'nav-menus.php';
241
+ if ($is_nav_menu) {
242
+ if (isset($_GET['action']) && $_GET['action'] == 'delete') {
243
+ if (isset($_GET['menu'])) {
244
+ $this->_OldMenu = wp_get_nav_menu_object($_GET['menu']);
245
+ }
246
+ } else {
247
+ $this->BuildOldMenuTermsAndItems();
248
+ }
249
+ $this->_OldMenuLocations = get_nav_menu_locations();
250
+ }
251
+ }
252
+
253
+ public function CustomizeInit()
254
+ {
255
+ $this->BuildOldMenuTermsAndItems();
256
+ $this->_OldMenuLocations = get_nav_menu_locations();
257
+ }
258
+
259
+ /**
260
+ * Customize Events Function
261
+ */
262
+ public function CustomizeSave()
263
+ {
264
+ $updateMenus = array();
265
+ $menus = wp_get_nav_menus();
266
+ if (!empty($menus)) {
267
+ foreach ($menus as $menu) {
268
+ array_push($updateMenus, array("term_id" => $menu->term_id, "name" => $menu->name));
269
+ }
270
+ }
271
+ // Deleted Menu
272
+ if (isset($updateMenus) && isset($this->_OldMenuTerms)) {
273
+ $terms = array_diff(array_map('serialize', $this->_OldMenuTerms), array_map('serialize', $updateMenus));
274
+ $terms = array_map('unserialize', $terms);
275
+
276
+ if (isset($terms) && count($terms) > 0) {
277
+ foreach ($terms as $term) {
278
+ $this->plugin->alerts->Trigger(2081, array(
279
+ 'MenuName' => $term['name']
280
+ ));
281
+ }
282
+ }
283
+ }
284
+ if (isset($_POST['action']) && $_POST['action'] == 'customize_save') {
285
+ if (isset($_POST['wp_customize'], $_POST['customized'])) {
286
+ $customized = json_decode(wp_unslash($_POST['customized']), true);
287
+ if (is_array($customized)) {
288
+ foreach ($customized as $key => $value) {
289
+ if (!empty($value['nav_menu_term_id'])) {
290
+ $is_occurred_event = false;
291
+ $menu = wp_get_nav_menu_object($value['nav_menu_term_id']);
292
+ $content_name = !empty($value['title']) ? $value['title'] : "no title";
293
+ if (!empty($this->_OldMenuItems)) {
294
+ foreach ($this->_OldMenuItems as $old_item) {
295
+ $item_id = substr(trim($key, ']'), 14);
296
+ // Modified Items in the menu
297
+ if ($old_item['item_id'] == $item_id && $old_item['title'] != $content_name) {
298
+ $is_occurred_event = true;
299
+ $this->EventModifiedItems($value['type_label'], $content_name, $menu->name);
300
+ }
301
+ // Changed order of the objects in a menu
302
+ if ($old_item['item_id'] == $item_id && $old_item['menu_order'] != $value['position']) {
303
+ $is_occurred_event = true;
304
+ $this->EventChangeOrder($menu->name);
305
+ return;
306
+ }
307
+ }
308
+ }
309
+ // Add Items to the menu
310
+ if (!$is_occurred_event) {
311
+ $menu_name = !empty($customized['new_menu_name']) ? $customized['new_menu_name'] : $menu->name;
312
+ $this->EventAddItems($value['type_label'], $content_name, $menu_name);
313
+ }
314
+ } else {
315
+ // Menu changed name
316
+ if (isset($updateMenus) && isset($this->_OldMenuTerms)) {
317
+ foreach ($this->_OldMenuTerms as $old_menu) {
318
+ foreach ($updateMenus as $update_menu) {
319
+ if ($old_menu['term_id'] == $update_menu['term_id'] && $old_menu['name'] != $update_menu['name']) {
320
+ $this->EventChangeName($old_menu['name'], $update_menu['name']);
321
+ }
322
+ }
323
+ }
324
+ }
325
+ // Setting Auto add pages
326
+ if (!empty($value) && isset($value['auto_add'])) {
327
+ if ($value['auto_add']) {
328
+ $this->EventMenuSetting($value['name'], 'Enabled', "Auto add pages");
329
+ } else {
330
+ $this->EventMenuSetting($value['name'], 'Disabled', "Auto add pages");
331
+ }
332
+ }
333
+ // Setting Location
334
+ if (false !== strpos($key, 'nav_menu_locations[')) {
335
+ $loc = substr(trim($key, ']'), 19);
336
+ if (!empty($value)) {
337
+ $menu = wp_get_nav_menu_object($value);
338
+ $menu_name = !empty($customized['new_menu_name']) ? $customized['new_menu_name'] : (!empty($menu) ? $menu->name : '');
339
+ $this->EventMenuSetting($menu_name, "Enabled", "Location: ".$loc." menu");
340
+ } else {
341
+ if (!empty($this->_OldMenuLocations[$loc])) {
342
+ $menu = wp_get_nav_menu_object($this->_OldMenuLocations[$loc]);
343
+ $menu_name = !empty($customized['new_menu_name']) ? $customized['new_menu_name'] : (!empty($menu) ? $menu->name : '');
344
+ $this->EventMenuSetting($menu_name, "Disabled", "Location: ".$loc." menu");
345
+ }
346
+ }
347
+ }
348
+ // Remove items from the menu
349
+ if (false !== strpos($key, 'nav_menu_item[')) {
350
+ $item_id = substr(trim($key, ']'), 14);
351
+ if (!empty($this->_OldMenuItems)) {
352
+ foreach ($this->_OldMenuItems as $old_item) {
353
+ if ($old_item['item_id'] == $item_id) {
354
+ $this->EventRemoveItems($old_item['object'], $old_item['title'], $old_item['menu_name']);
355
+ }
356
+ }
357
+ }
358
+ }
359
+ }
360
+ }
361
+ }
362
+ }
363
+ }
364
+ }
365
+
366
+ private function EventAddItems($content_type, $content_name, $menu_name)
367
+ {
368
+ $this->plugin->alerts->Trigger(2079, array(
369
+ 'ContentType' => $content_type,
370
+ 'ContentName' => $content_name,
371
+ 'MenuName' => $menu_name
372
+ ));
373
+ }
374
+
375
+ private function EventRemoveItems($content_type, $content_name, $menu_name)
376
+ {
377
+ $this->plugin->alerts->Trigger(2080, array(
378
+ 'ContentType' => $content_type,
379
+ 'ContentName' => $content_name,
380
+ 'MenuName' => $menu_name
381
+ ));
382
+ }
383
+
384
+ private function EventMenuSetting($menu_name, $status, $menu_setting)
385
+ {
386
+ $this->plugin->alerts->Trigger(2082, array(
387
+ 'Status' => $status,
388
+ 'MenuSetting' => $menu_setting,
389
+ 'MenuName' => $menu_name
390
+ ));
391
+ }
392
+
393
+ private function EventModifiedItems($content_type, $content_name, $menu_name)
394
+ {
395
+ $this->plugin->alerts->Trigger(2083, array(
396
+ 'ContentType' => $content_type,
397
+ 'ContentName' => $content_name,
398
+ 'MenuName' => $menu_name
399
+ ));
400
+ }
401
+
402
+ private function EventChangeName($old_menu_name, $new_menu_name)
403
+ {
404
+ $this->plugin->alerts->Trigger(2084, array(
405
+ 'OldMenuName' => $old_menu_name,
406
+ 'NewMenuName' => $new_menu_name
407
+ ));
408
+ }
409
+
410
+ private function EventChangeOrder($menu_name)
411
+ {
412
+ $this->plugin->alerts->Trigger(2085, array(
413
+ 'MenuName' => $menu_name
414
+ ));
415
+ }
416
+ }
classes/Sensors/MetaData.php CHANGED
@@ -1,208 +1,208 @@
1
- <?php
2
-
3
- class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
4
- {
5
-
6
- public function HookEvents()
7
- {
8
- add_action('add_post_meta', array($this, 'EventPostMetaCreated'), 10, 3);
9
- add_action('update_post_meta', array($this, 'EventPostMetaUpdating'), 10, 3);
10
- add_action('updated_post_meta', array($this, 'EventPostMetaUpdated'), 10, 4);
11
- add_action('deleted_post_meta', array($this, 'EventPostMetaDeleted'), 10, 4);
12
- }
13
-
14
- protected $old_meta = array();
15
-
16
- protected function CanLogPostMeta($object_id, $meta_key)
17
- {
18
- //check if excluded meta key or starts with _
19
- if (substr($meta_key, 0, 1) == '_') {
20
- return false;
21
- } else if ($this->IsExcludedCustomFields($meta_key)) {
22
- return false;
23
- } else {
24
- return true;
25
- }
26
- }
27
-
28
- public function IsExcludedCustomFields($custom)
29
- {
30
- $customFields = $this->plugin->settings->GetExcludedMonitoringCustom();
31
- return (in_array($custom, $customFields)) ? true : false;
32
- }
33
-
34
- public function EventPostMetaCreated($object_id, $meta_key, $meta_value)
35
- {
36
- $post = get_post($object_id);
37
-
38
- if (!$this->CanLogPostMeta($object_id, $meta_key)) return;
39
-
40
- switch ($post->post_type) {
41
- case 'page':
42
- $this->plugin->alerts->Trigger(2059, array(
43
- 'PostID' => $object_id,
44
- 'PostTitle' => $post->post_title,
45
- 'MetaKey' => $meta_key,
46
- 'MetaValue' => $meta_value,
47
- 'MetaLink' => $meta_key,
48
- ));
49
- break;
50
- case 'post':
51
- $this->plugin->alerts->Trigger(2053, array(
52
- 'PostID' => $object_id,
53
- 'PostTitle' => $post->post_title,
54
- 'MetaKey' => $meta_key,
55
- 'MetaValue' => $meta_value,
56
- 'MetaLink' => $meta_key,
57
- ));
58
- break;
59
- default:
60
- $this->plugin->alerts->Trigger(2056, array(
61
- 'PostID' => $object_id,
62
- 'PostTitle' => $post->post_title,
63
- 'PostType' => $post->post_type,
64
- 'MetaKey' => $meta_key,
65
- 'MetaValue' => $meta_value,
66
- 'MetaLink' => $meta_key,
67
- ));
68
- break;
69
- }
70
- }
71
-
72
- public function EventPostMetaUpdating($meta_id, $object_id, $meta_key)
73
- {
74
- static $meta_type = 'post';
75
- $this->old_meta[$meta_id] = (object)array(
76
- 'key' => ($meta = get_metadata_by_mid($meta_type, $meta_id)) ? $meta->meta_key : $meta_key,
77
- 'val' => get_metadata($meta_type, $object_id, $meta_key, true),
78
- );
79
- }
80
-
81
- public function EventPostMetaUpdated($meta_id, $object_id, $meta_key, $meta_value)
82
- {
83
- $post = get_post($object_id);
84
-
85
- if (!$this->CanLogPostMeta($object_id, $meta_key)) return;
86
-
87
- if (isset($this->old_meta[$meta_id])) {
88
- // check change in meta key
89
- if ($this->old_meta[$meta_id]->key != $meta_key) {
90
- switch ($post->post_type) {
91
- case 'page':
92
- $this->plugin->alerts->Trigger(2064, array(
93
- 'PostID' => $object_id,
94
- 'PostTitle' => $post->post_title,
95
- 'MetaID' => $meta_id,
96
- 'MetaKeyNew' => $meta_key,
97
- 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
98
- 'MetaValue' => $meta_value,
99
- 'MetaLink' => $meta_key,
100
- ));
101
- break;
102
- case 'post':
103
- $this->plugin->alerts->Trigger(2062, array(
104
- 'PostID' => $object_id,
105
- 'PostTitle' => $post->post_title,
106
- 'MetaID' => $meta_id,
107
- 'MetaKeyNew' => $meta_key,
108
- 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
109
- 'MetaValue' => $meta_value,
110
- 'MetaLink' => $meta_key,
111
- ));
112
- break;
113
- default:
114
- $this->plugin->alerts->Trigger(2063, array(
115
- 'PostID' => $object_id,
116
- 'PostTitle' => $post->post_title,
117
- 'PostType' => $post->post_type,
118
- 'MetaID' => $meta_id,
119
- 'MetaKeyNew' => $meta_key,
120
- 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
121
- 'MetaValue' => $meta_value,
122
- 'MetaLink' => $smeta_key,
123
- ));
124
- break;
125
- }
126
- } else if ($this->old_meta[$meta_id]->val != $meta_value) { // check change in meta value
127
- switch ($post->post_type) {
128
- case 'page':
129
- $this->plugin->alerts->Trigger(2060, array(
130
- 'PostID' => $object_id,
131
- 'PostTitle' => $post->post_title,
132
- 'MetaID' => $meta_id,
133
- 'MetaKey' => $meta_key,
134
- 'MetaValueNew' => $meta_value,
135
- 'MetaValueOld' => $this->old_meta[$meta_id]->val,
136
- 'MetaLink' => $meta_key,
137
- ));
138
- break;
139
- case 'post':
140
- $this->plugin->alerts->Trigger(2054, array(
141
- 'PostID' => $object_id,
142
- 'PostTitle' => $post->post_title,
143
- 'MetaID' => $meta_id,
144
- 'MetaKey' => $meta_key,
145
- 'MetaValueNew' => $meta_value,
146
- 'MetaValueOld' => $this->old_meta[$meta_id]->val,
147
- 'MetaLink' => $meta_key,
148
- ));
149
- break;
150
- default:
151
- $this->plugin->alerts->Trigger(2057, array(
152
- 'PostID' => $object_id,
153
- 'PostTitle' => $post->post_title,
154
- 'PostType' => $post->post_type,
155
- 'MetaID' => $meta_id,
156
- 'MetaKey' => $meta_key,
157
- 'MetaValueNew' => $meta_value,
158
- 'MetaValueOld' => $this->old_meta[$meta_id]->val,
159
- 'MetaLink' => $meta_key,
160
- ));
161
- break;
162
- }
163
- }
164
- // remove old meta update data
165
- unset($this->old_meta[$meta_id]);
166
- }
167
- }
168
-
169
- public function EventPostMetaDeleted($meta_ids, $object_id, $meta_key, $meta_value)
170
- {
171
- $post = get_post($object_id);
172
-
173
- foreach ($meta_ids as $meta_id) {
174
- if (!$this->CanLogPostMeta($object_id, $meta_key)) continue;
175
-
176
- switch ($post->post_type) {
177
- case 'page':
178
- $this->plugin->alerts->Trigger(2061, array(
179
- 'PostID' => $object_id,
180
- 'PostTitle' => $post->post_title,
181
- 'MetaID' => $meta_id,
182
- 'MetaKey' => $meta_key,
183
- 'MetaValue' => $meta_value,
184
- ));
185
- break;
186
- case 'post':
187
- $this->plugin->alerts->Trigger(2055, array(
188
- 'PostID' => $object_id,
189
- 'PostTitle' => $post->post_title,
190
- 'MetaID' => $meta_id,
191
- 'MetaKey' => $meta_key,
192
- 'MetaValue' => $meta_value,
193
- ));
194
- break;
195
- default:
196
- $this->plugin->alerts->Trigger(2058, array(
197
- 'PostID' => $object_id,
198
- 'PostTitle' => $post->post_title,
199
- 'PostType' => $post->post_type,
200
- 'MetaID' => $meta_id,
201
- 'MetaKey' => $meta_key,
202
- 'MetaValue' => $meta_value,
203
- ));
204
- break;
205
- }
206
- }
207
- }
208
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_MetaData extends WSAL_AbstractSensor
4
+ {
5
+
6
+ public function HookEvents()
7
+ {
8
+ add_action('add_post_meta', array($this, 'EventPostMetaCreated'), 10, 3);
9
+ add_action('update_post_meta', array($this, 'EventPostMetaUpdating'), 10, 3);
10
+ add_action('updated_post_meta', array($this, 'EventPostMetaUpdated'), 10, 4);
11
+ add_action('deleted_post_meta', array($this, 'EventPostMetaDeleted'), 10, 4);
12
+ }
13
+
14
+ protected $old_meta = array();
15
+
16
+ protected function CanLogPostMeta($object_id, $meta_key)
17
+ {
18
+ //check if excluded meta key or starts with _
19
+ if (substr($meta_key, 0, 1) == '_') {
20
+ return false;
21
+ } else if ($this->IsExcludedCustomFields($meta_key)) {
22
+ return false;
23
+ } else {
24
+ return true;
25
+ }
26
+ }
27
+
28
+ public function IsExcludedCustomFields($custom)
29
+ {
30
+ $customFields = $this->plugin->settings->GetExcludedMonitoringCustom();
31
+ return (in_array($custom, $customFields)) ? true : false;
32
+ }
33
+
34
+ public function EventPostMetaCreated($object_id, $meta_key, $meta_value)
35
+ {
36
+ $post = get_post($object_id);
37
+
38
+ if (!$this->CanLogPostMeta($object_id, $meta_key)) return;
39
+
40
+ switch ($post->post_type) {
41
+ case 'page':
42
+ $this->plugin->alerts->Trigger(2059, array(
43
+ 'PostID' => $object_id,
44
+ 'PostTitle' => $post->post_title,
45
+ 'MetaKey' => $meta_key,
46
+ 'MetaValue' => $meta_value,
47
+ 'MetaLink' => $meta_key,
48
+ ));
49
+ break;
50
+ case 'post':
51
+ $this->plugin->alerts->Trigger(2053, array(
52
+ 'PostID' => $object_id,
53
+ 'PostTitle' => $post->post_title,
54
+ 'MetaKey' => $meta_key,
55
+ 'MetaValue' => $meta_value,
56
+ 'MetaLink' => $meta_key,
57
+ ));
58
+ break;
59
+ default:
60
+ $this->plugin->alerts->Trigger(2056, array(
61
+ 'PostID' => $object_id,
62
+ 'PostTitle' => $post->post_title,
63
+ 'PostType' => $post->post_type,
64
+ 'MetaKey' => $meta_key,
65
+ 'MetaValue' => $meta_value,
66
+ 'MetaLink' => $meta_key,
67
+ ));
68
+ break;
69
+ }
70
+ }
71
+
72
+ public function EventPostMetaUpdating($meta_id, $object_id, $meta_key)
73
+ {
74
+ static $meta_type = 'post';
75
+ $this->old_meta[$meta_id] = (object)array(
76
+ 'key' => ($meta = get_metadata_by_mid($meta_type, $meta_id)) ? $meta->meta_key : $meta_key,
77
+ 'val' => get_metadata($meta_type, $object_id, $meta_key, true),
78
+ );
79
+ }
80
+
81
+ public function EventPostMetaUpdated($meta_id, $object_id, $meta_key, $meta_value)
82
+ {
83
+ $post = get_post($object_id);
84
+
85
+ if (!$this->CanLogPostMeta($object_id, $meta_key)) return;
86
+
87
+ if (isset($this->old_meta[$meta_id])) {
88
+ // check change in meta key
89
+ if ($this->old_meta[$meta_id]->key != $meta_key) {
90
+ switch ($post->post_type) {
91
+ case 'page':
92
+ $this->plugin->alerts->Trigger(2064, array(
93
+ 'PostID' => $object_id,
94
+ 'PostTitle' => $post->post_title,
95
+ 'MetaID' => $meta_id,
96
+ 'MetaKeyNew' => $meta_key,
97
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
98
+ 'MetaValue' => $meta_value,
99
+ 'MetaLink' => $meta_key,
100
+ ));
101
+ break;
102
+ case 'post':
103
+ $this->plugin->alerts->Trigger(2062, array(
104
+ 'PostID' => $object_id,
105
+ 'PostTitle' => $post->post_title,
106
+ 'MetaID' => $meta_id,
107
+ 'MetaKeyNew' => $meta_key,
108
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
109
+ 'MetaValue' => $meta_value,
110
+ 'MetaLink' => $meta_key,
111
+ ));
112
+ break;
113
+ default:
114
+ $this->plugin->alerts->Trigger(2063, array(
115
+ 'PostID' => $object_id,
116
+ 'PostTitle' => $post->post_title,
117
+ 'PostType' => $post->post_type,
118
+ 'MetaID' => $meta_id,
119
+ 'MetaKeyNew' => $meta_key,
120
+ 'MetaKeyOld' => $this->old_meta[$meta_id]->key,
121
+ 'MetaValue' => $meta_value,
122
+ 'MetaLink' => $smeta_key,
123
+ ));
124
+ break;
125
+ }
126
+ } else if ($this->old_meta[$meta_id]->val != $meta_value) { // check change in meta value
127
+ switch ($post->post_type) {
128
+ case 'page':
129
+ $this->plugin->alerts->Trigger(2060, array(
130
+ 'PostID' => $object_id,
131
+ 'PostTitle' => $post->post_title,
132
+ 'MetaID' => $meta_id,
133
+ 'MetaKey' => $meta_key,
134
+ 'MetaValueNew' => $meta_value,
135
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
136
+ 'MetaLink' => $meta_key,
137
+ ));
138
+ break;
139
+ case 'post':
140
+ $this->plugin->alerts->Trigger(2054, array(
141
+ 'PostID' => $object_id,
142
+ 'PostTitle' => $post->post_title,
143
+ 'MetaID' => $meta_id,
144
+ 'MetaKey' => $meta_key,
145
+ 'MetaValueNew' => $meta_value,
146
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
147
+ 'MetaLink' => $meta_key,
148
+ ));
149
+ break;
150
+ default:
151
+ $this->plugin->alerts->Trigger(2057, array(
152
+ 'PostID' => $object_id,
153
+ 'PostTitle' => $post->post_title,
154
+ 'PostType' => $post->post_type,
155
+ 'MetaID' => $meta_id,
156
+ 'MetaKey' => $meta_key,
157
+ 'MetaValueNew' => $meta_value,
158
+ 'MetaValueOld' => $this->old_meta[$meta_id]->val,
159
+ 'MetaLink' => $meta_key,
160
+ ));
161
+ break;
162
+ }
163
+ }
164
+ // remove old meta update data
165
+ unset($this->old_meta[$meta_id]);
166
+ }
167
+ }
168
+
169
+ public function EventPostMetaDeleted($meta_ids, $object_id, $meta_key, $meta_value)
170
+ {
171
+ $post = get_post($object_id);
172
+
173
+ foreach ($meta_ids as $meta_id) {
174
+ if (!$this->CanLogPostMeta($object_id, $meta_key)) continue;
175
+
176
+ switch ($post->post_type) {
177
+ case 'page':
178
+ $this->plugin->alerts->Trigger(2061, array(
179
+ 'PostID' => $object_id,
180
+ 'PostTitle' => $post->post_title,
181
+ 'MetaID' => $meta_id,
182
+ 'MetaKey' => $meta_key,
183
+ 'MetaValue' => $meta_value,
184
+ ));
185
+ break;
186
+ case 'post':
187
+ $this->plugin->alerts->Trigger(2055, array(
188
+ 'PostID' => $object_id,
189
+ 'PostTitle' => $post->post_title,
190
+ 'MetaID' => $meta_id,
191
+ 'MetaKey' => $meta_key,
192
+ 'MetaValue' => $meta_value,
193
+ ));
194
+ break;
195
+ default:
196
+ $this->plugin->alerts->Trigger(2058, array(
197
+ 'PostID' => $object_id,
198
+ 'PostTitle' => $post->post_title,
199
+ 'PostType' => $post->post_type,
200
+ 'MetaID' => $meta_id,
201
+ 'MetaKey' => $meta_key,
202
+ 'MetaValue' => $meta_value,
203
+ ));
204
+ break;
205
+ }
206
+ }
207
+ }
208
+ }
classes/Sensors/Multisite.php CHANGED
@@ -1,130 +1,130 @@
1
- <?php
2
-
3
- class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
4
-
5
- public function HookEvents() {
6
- if($this->plugin->IsMultisite()){
7
- add_action('admin_init', array($this, 'EventAdminInit'));
8
- if(current_user_can('switch_themes'))add_action('shutdown', array($this, 'EventAdminShutdown'));
9
- add_action('wpmu_new_blog', array($this, 'EventNewBlog'), 10, 1);
10
- add_action('archive_blog', array($this, 'EventArchiveBlog'));
11
- add_action('unarchive_blog', array($this, 'EventUnarchiveBlog'));
12
- add_action('activate_blog', array($this, 'EventActivateBlog'));
13
- add_action('deactivate_blog', array($this, 'EventDeactivateBlog'));
14
- add_action('delete_blog', array($this, 'EventDeleteBlog'));
15
- add_action('add_user_to_blog', array($this, 'EventUserAddedToBlog'), 10, 3);
16
- add_action('remove_user_from_blog', array($this, 'EventUserRemovedFromBlog'));
17
- }
18
- }
19
-
20
- protected $old_allowedthemes = null;
21
-
22
- public function EventAdminInit(){
23
- $this->old_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
24
- }
25
-
26
- public function EventAdminShutdown(){
27
- if(is_null($this->old_allowedthemes))return;
28
- $new_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
29
-
30
- // check for enabled themes
31
- foreach($new_allowedthemes as $theme)
32
- if(!in_array($theme, (array)$this->old_allowedthemes)){
33
- $theme = wp_get_theme($theme);
34
- $this->plugin->alerts->Trigger(5008, array(
35
- 'Theme' => (object)array(
36
- 'Name' => $theme->Name,
37
- 'ThemeURI' => $theme->ThemeURI,
38
- 'Description' => $theme->Description,
39
- 'Author' => $theme->Author,
40
- 'Version' => $theme->Version,
41
- 'get_template_directory' => $theme->get_template_directory(),
42
- ),
43
- ));
44
- }
45
-
46
- // check for disabled themes
47
- foreach((array)$this->old_allowedthemes as $theme)
48
- if(!in_array($theme, $new_allowedthemes)){
49
- $theme = wp_get_theme($theme);
50
- $this->plugin->alerts->Trigger(5009, array(
51
- 'Theme' => (object)array(
52
- 'Name' => $theme->Name,
53
- 'ThemeURI' => $theme->ThemeURI,
54
- 'Description' => $theme->Description,
55
- 'Author' => $theme->Author,
56
- 'Version' => $theme->Version,
57
- 'get_template_directory' => $theme->get_template_directory(),
58
- ),
59
- ));
60
- }
61
- }
62
-
63
- public function EventNewBlog($blog_id){
64
- $this->plugin->alerts->Trigger(7000, array(
65
- 'BlogID' => $blog_id,
66
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
67
- ));
68
- }
69
-
70
- public function EventArchiveBlog($blog_id){
71
- $this->plugin->alerts->Trigger(7001, array(
72
- 'BlogID' => $blog_id,
73
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
74
- ));
75
- }
76
-
77
- public function EventUnarchiveBlog($blog_id){
78
- $this->plugin->alerts->Trigger(7002, array(
79
- 'BlogID' => $blog_id,
80
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
81
- ));
82
- }
83
-
84
- public function EventActivateBlog($blog_id){
85
- $this->plugin->alerts->Trigger(7003, array(
86
- 'BlogID' => $blog_id,
87
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
88
- ));
89
- }
90
-
91
- public function EventDeactivateBlog($blog_id){
92
- $this->plugin->alerts->Trigger(7004, array(
93
- 'BlogID' => $blog_id,
94
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
95
- ));
96
- }
97
-
98
- public function EventDeleteBlog($blog_id){
99
- $this->plugin->alerts->Trigger(7005, array(
100
- 'BlogID' => $blog_id,
101
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
102
- ));
103
- }
104
-
105
- public function EventUserAddedToBlog($user_id, $role, $blog_id){
106
- $this->plugin->alerts->TriggerIf(4010, array(
107
- 'TargetUserID' => $user_id,
108
- 'TargetUsername' => get_userdata($user_id)->user_login,
109
- 'TargetUserRole' => $role,
110
- 'BlogID' => $blog_id,
111
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
112
- ), array($this, 'MustNotContainCreateUser'));
113
- }
114
-
115
- public function EventUserRemovedFromBlog($user_id){
116
- $user = get_userdata($user_id);
117
- $blog_id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : 0);
118
- $this->plugin->alerts->TriggerIf(4011, array(
119
- 'TargetUserID' => $user_id,
120
- 'TargetUsername' => $user->user_login,
121
- 'TargetUserRole' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
122
- 'BlogID' => $blog_id,
123
- 'SiteName' => get_blog_option($blog_id, 'blogname'),
124
- ), array($this, 'MustNotContainCreateUser'));
125
- }
126
-
127
- public function MustNotContainCreateUser(WSAL_AlertManager $mgr){
128
- return !$mgr->WillTrigger(4012);
129
- }
130
  }
1
+ <?php
2
+
3
+ class WSAL_Sensors_Multisite extends WSAL_AbstractSensor {
4
+
5
+ public function HookEvents() {
6
+ if($this->plugin->IsMultisite()){
7
+ add_action('admin_init', array($this, 'EventAdminInit'));
8
+ if(current_user_can('switch_themes'))add_action('shutdown', array($this, 'EventAdminShutdown'));
9
+ add_action('wpmu_new_blog', array($this, 'EventNewBlog'), 10, 1);
10
+ add_action('archive_blog', array($this, 'EventArchiveBlog'));
11
+ add_action('unarchive_blog', array($this, 'EventUnarchiveBlog'));
12
+ add_action('activate_blog', array($this, 'EventActivateBlog'));
13
+ add_action('deactivate_blog', array($this, 'EventDeactivateBlog'));
14
+ add_action('delete_blog', array($this, 'EventDeleteBlog'));
15
+ add_action('add_user_to_blog', array($this, 'EventUserAddedToBlog'), 10, 3);
16
+ add_action('remove_user_from_blog', array($this, 'EventUserRemovedFromBlog'));
17
+ }
18
+ }
19
+
20
+ protected $old_allowedthemes = null;
21
+
22
+ public function EventAdminInit(){
23
+ $this->old_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
24
+ }
25
+
26
+ public function EventAdminShutdown(){
27
+ if(is_null($this->old_allowedthemes))return;
28
+ $new_allowedthemes = array_keys((array)get_site_option('allowedthemes'));
29
+
30
+ // check for enabled themes
31
+ foreach($new_allowedthemes as $theme)
32
+ if(!in_array($theme, (array)$this->old_allowedthemes)){
33
+ $theme = wp_get_theme($theme);
34
+ $this->plugin->alerts->Trigger(5008, array(
35
+ 'Theme' => (object)array(
36
+ 'Name' => $theme->Name,
37
+ 'ThemeURI' => $theme->ThemeURI,
38
+ 'Description' => $theme->Description,
39
+ 'Author' => $theme->Author,
40
+ 'Version' => $theme->Version,
41
+ 'get_template_directory' => $theme->get_template_directory(),
42
+ ),
43
+ ));
44
+ }
45
+
46
+ // check for disabled themes
47
+ foreach((array)$this->old_allowedthemes as $theme)
48
+ if(!in_array($theme, $new_allowedthemes)){
49
+ $theme = wp_get_theme($theme);
50
+ $this->plugin->alerts->Trigger(5009, array(
51
+ 'Theme' => (object)array(
52
+ 'Name' => $theme->Name,
53
+ 'ThemeURI' => $theme->ThemeURI,
54
+ 'Description' => $theme->Description,
55
+ 'Author' => $theme->Author,
56
+ 'Version' => $theme->Version,
57
+ 'get_template_directory' => $theme->get_template_directory(),
58
+ ),
59
+ ));
60
+ }
61
+ }
62
+
63
+ public function EventNewBlog($blog_id){
64
+ $this->plugin->alerts->Trigger(7000, array(
65
+ 'BlogID' => $blog_id,
66
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
67
+ ));
68
+ }
69
+
70
+ public function EventArchiveBlog($blog_id){
71
+ $this->plugin->alerts->Trigger(7001, array(
72
+ 'BlogID' => $blog_id,
73
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
74
+ ));
75
+ }
76
+
77
+ public function EventUnarchiveBlog($blog_id){
78
+ $this->plugin->alerts->Trigger(7002, array(
79
+ 'BlogID' => $blog_id,
80
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
81
+ ));
82
+ }
83
+
84
+ public function EventActivateBlog($blog_id){
85
+ $this->plugin->alerts->Trigger(7003, array(
86
+ 'BlogID' => $blog_id,
87
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
88
+ ));
89
+ }
90
+
91
+ public function EventDeactivateBlog($blog_id){
92
+ $this->plugin->alerts->Trigger(7004, array(
93
+ 'BlogID' => $blog_id,
94
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
95
+ ));
96
+ }
97
+
98
+ public function EventDeleteBlog($blog_id){
99
+ $this->plugin->alerts->Trigger(7005, array(
100
+ 'BlogID' => $blog_id,
101
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
102
+ ));
103
+ }
104
+
105
+ public function EventUserAddedToBlog($user_id, $role, $blog_id){
106
+ $this->plugin->alerts->TriggerIf(4010, array(
107
+ 'TargetUserID' => $user_id,
108
+ 'TargetUsername' => get_userdata($user_id)->user_login,
109
+ 'TargetUserRole' => $role,
110
+ 'BlogID' => $blog_id,
111
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
112
+ ), array($this, 'MustNotContainCreateUser'));
113
+ }
114
+
115
+ public function EventUserRemovedFromBlog($user_id){
116
+ $user = get_userdata($user_id);
117
+ $blog_id = (isset($_REQUEST['id']) ? $_REQUEST['id'] : 0);
118
+ $this->plugin->alerts->TriggerIf(4011, array(
119
+ 'TargetUserID' => $user_id,
120
+ 'TargetUsername' => $user->user_login,
121
+ 'TargetUserRole' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
122
+ 'BlogID' => $blog_id,
123
+ 'SiteName' => get_blog_option($blog_id, 'blogname'),
124
+ ), array($this, 'MustNotContainCreateUser'));
125
+ }
126
+
127
+ public function MustNotContainCreateUser(WSAL_AlertManager $mgr){
128
+ return !$mgr->WillTrigger(4012);
129
+ }
130
  }
classes/Sensors/PhpErrors.php CHANGED
@@ -1,104 +1,104 @@
1
- <?php
2
-
3
- class WSAL_Sensors_PhpErrors extends WSAL_AbstractSensor {
4
-
5
- protected $_avoid_error_recursion = false;
6
-
7
- protected $_error_types = array(
8
- 0001 => array(1,4,16,64,256,4096), // errors
9
- 0002 => array(2,32,128,512), // warnings
10
- 0003 => array(8,1024,2048,8192,16384), // notices
11
- 0004 => array(), // exceptions
12
- 0005 => array(), // shutdown
13
- );
14
-
15
- protected $_maybe_last_error = null;
16
-
17
- public function HookEvents() {
18
- if($this->plugin->settings->IsPhpErrorLoggingEnabled()){
19
- set_error_handler(array($this, 'EventError'), E_ALL);
20
- set_exception_handler(array($this, 'EventException'));
21
- register_shutdown_function(array($this, 'EventShutdown'));
22
- }
23
- }
24
-
25
- protected function GetErrorHash($code, $mesg, $file, $line){
26
- return md5(implode(':', func_get_args()));
27
- }
28
-
29
- public function EventError($errno, $errstr, $errfile = 'unknown', $errline = 0, $errcontext = array()){
30
- if($this->_avoid_error_recursion)return;
31
-
32
- $errbacktrace = 'No Backtrace';
33
- if($this->plugin->settings->IsBacktraceLoggingEnabled()){
34
- ob_start();
35
- debug_print_backtrace();
36
- $errbacktrace = ob_get_clean();
37
- }
38
-
39
- $data = array(
40
- 'Code' => $errno,
41
- 'Message' => $errstr,
42
- 'File' => $errfile,
43
- 'Line' => $errline,
44
- 'Context' => $errcontext,
45
- 'Trace' => $errbacktrace,
46
- );
47
-
48
- $type = 0002; // default (middle ground)
49
- foreach($this->_error_types as $temp => $codes){
50
- if(in_array($errno, $codes)){
51
- $type = $temp;
52
- }
53
- }
54
-
55
- $this->_maybe_last_error = $this->GetErrorHash($errno, $errstr, $errfile, $errline);
56
-
57
- $this->_avoid_error_recursion = true;
58
- $this->plugin->alerts->Trigger($type, $data);
59
- $this->_avoid_error_recursion = false;
60
- }
61
-
62
- public function EventException(Exception $ex){
63
- if($this->_avoid_error_recursion)return;
64
-
65
- $errbacktrace = 'No Backtrace';
66
- if($this->plugin->settings->IsBacktraceLoggingEnabled()){
67
- $errbacktrace = $ex->getTraceAsString();
68
- }
69
-
70
- $data = array(
71
- 'Class' => get_class($ex),
72
- 'Code' => $ex->getCode(),
73
- 'Message' => $ex->getMessage(),
74
- 'File' => $ex->getFile(),
75
- 'Line' => $ex->getLine(),
76
- 'Trace' => $errbacktrace,
77
- );
78
-
79
- if(method_exists($ex, 'getContext'))
80
- $data['Context'] = $ex->getContext();
81
-
82
- $this->_avoid_error_recursion = true;
83
- $this->plugin->alerts->Trigger(0004, $data);
84
- $this->_avoid_error_recursion = false;
85
- }
86
-
87
- public function EventShutdown(){
88
- if($this->_avoid_error_recursion)return;
89
-
90
- if(!!($e = error_get_last()) && ($this->_maybe_last_error != $this->GetErrorHash($e['type'], $e['message'], $e['file'], $e['line']))){
91
- $data = array(
92
- 'Code' => $e['type'],
93
- 'Message' => $e['message'],
94
- 'File' => $e['file'],
95
- 'Line' => $e['line'],
96
- );
97
-
98
- $this->_avoid_error_recursion = true;
99
- $this->plugin->alerts->Trigger(0005, $data);
100
- $this->_avoid_error_recursion = false;
101
- }
102
- }
103
-
104
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_PhpErrors extends WSAL_AbstractSensor {
4
+
5
+ protected $_avoid_error_recursion = false;
6
+
7
+ protected $_error_types = array(
8
+ 0001 => array(1,4,16,64,256,4096), // errors
9
+ 0002 => array(2,32,128,512), // warnings
10
+ 0003 => array(8,1024,2048,8192,16384), // notices
11
+ 0004 => array(), // exceptions
12
+ 0005 => array(), // shutdown
13
+ );
14
+
15
+ protected $_maybe_last_error = null;
16
+
17
+ public function HookEvents() {
18
+ if($this->plugin->settings->IsPhpErrorLoggingEnabled()){
19
+ set_error_handler(array($this, 'EventError'), E_ALL);
20
+ set_exception_handler(array($this, 'EventException'));
21
+ register_shutdown_function(array($this, 'EventShutdown'));
22
+ }
23
+ }
24
+
25
+ protected function GetErrorHash($code, $mesg, $file, $line){
26
+ return md5(implode(':', func_get_args()));
27
+ }
28
+
29
+ public function EventError($errno, $errstr, $errfile = 'unknown', $errline = 0, $errcontext = array()){
30
+ if($this->_avoid_error_recursion)return;
31
+
32
+ $errbacktrace = 'No Backtrace';
33
+ if($this->plugin->settings->IsBacktraceLoggingEnabled()){
34
+ ob_start();
35
+ debug_print_backtrace();
36
+ $errbacktrace = ob_get_clean();
37
+ }
38
+
39
+ $data = array(
40
+ 'Code' => $errno,
41
+ 'Message' => $errstr,
42
+ 'File' => $errfile,
43
+ 'Line' => $errline,
44
+ 'Context' => $errcontext,
45
+ 'Trace' => $errbacktrace,
46
+ );
47
+
48
+ $type = 0002; // default (middle ground)
49
+ foreach($this->_error_types as $temp => $codes){
50
+ if(in_array($errno, $codes)){
51
+ $type = $temp;
52
+ }
53
+ }
54
+
55
+ $this->_maybe_last_error = $this->GetErrorHash($errno, $errstr, $errfile, $errline);
56
+
57
+ $this->_avoid_error_recursion = true;
58
+ $this->plugin->alerts->Trigger($type, $data);
59
+ $this->_avoid_error_recursion = false;
60
+ }
61
+
62
+ public function EventException(Exception $ex){
63
+ if($this->_avoid_error_recursion)return;
64
+
65
+ $errbacktrace = 'No Backtrace';
66
+ if($this->plugin->settings->IsBacktraceLoggingEnabled()){
67
+ $errbacktrace = $ex->getTraceAsString();
68
+ }
69
+
70
+ $data = array(
71
+ 'Class' => get_class($ex),
72
+ 'Code' => $ex->getCode(),
73
+ 'Message' => $ex->getMessage(),
74
+ 'File' => $ex->getFile(),
75
+ 'Line' => $ex->getLine(),
76
+ 'Trace' => $errbacktrace,
77
+ );
78
+
79
+ if(method_exists($ex, 'getContext'))
80
+ $data['Context'] = $ex->getContext();
81
+
82
+ $this->_avoid_error_recursion = true;
83
+ $this->plugin->alerts->Trigger(0004, $data);
84
+ $this->_avoid_error_recursion = false;
85
+ }
86
+
87
+ public function EventShutdown(){
88
+ if($this->_avoid_error_recursion)return;
89
+
90
+ if(!!($e = error_get_last()) && ($this->_maybe_last_error != $this->GetErrorHash($e['type'], $e['message'], $e['file'], $e['line']))){
91
+ $data = array(
92
+ 'Code' => $e['type'],
93
+ 'Message' => $e['message'],
94
+ 'File' => $e['file'],
95
+ 'Line' => $e['line'],
96
+ );
97
+
98
+ $this->_avoid_error_recursion = true;
99
+ $this->plugin->alerts->Trigger(0005, $data);
100
+ $this->_avoid_error_recursion = false;
101
+ }
102
+ }
103
+
104
+ }
classes/Sensors/PluginsThemes.php CHANGED
@@ -1,215 +1,215 @@
1
- <?php
2
-
3
- class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
4
-
5
- public function HookEvents() {
6
- $hasPermission = (current_user_can("install_plugins") || current_user_can("activate_plugins") ||
7
- current_user_can("delete_plugins") || current_user_can("update_plugins") || current_user_can("install_themes"));
8
-
9
- add_action('admin_init', array($this, 'EventAdminInit'));
10
- if($hasPermission)add_action('shutdown', array($this, 'EventAdminShutdown'));
11
- add_action('switch_theme', array($this, 'EventThemeActivated'));
12
- }
13
-
14
- protected $old_themes = array();
15
- protected $old_plugins = array();
16
-
17
- public function EventAdminInit(){
18
- $this->old_themes = wp_get_themes();
19
- $this->old_plugins = get_plugins();
20
- }
21
-
22
- public function EventAdminShutdown(){
23
- $action = (isset($_REQUEST['action']) && $_REQUEST['action'] != "-1") ? $_REQUEST['action'] : '';
24
- $action = (isset($_REQUEST['action2']) && $_REQUEST['action2'] != "-1") ? $_REQUEST['action2'] : $action;
25
- $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
26
- $is_themes = $actype == 'themes';
27
- $is_plugins = $actype == 'plugins';
28
-
29
- // install plugin
30
- if(in_array($action, array('install-plugin', 'upload-plugin')) && current_user_can("install_plugins")){
31
- $plugin = array_values(array_diff(array_keys(get_plugins()), array_keys($this->old_plugins)));
32
- if(count($plugin) != 1)
33
- return $this->LogError(
34
- 'Expected exactly one new plugin but found ' . count($plugin),
35
- array('NewPlugin' => $plugin, 'OldPlugins' => $this->old_plugins, 'NewPlugins' => get_plugins())
36
- );
37
- $pluginPath = $plugin[0];
38
- $plugin = get_plugins();
39
- $plugin = $plugin[$pluginPath];
40
- $pluginPath = plugin_dir_path(WP_PLUGIN_DIR . '/' . $pluginPath[0]);
41
- $this->plugin->alerts->Trigger(5000, array(
42
- 'Plugin' => (object)array(
43
- 'Name' => $plugin['Name'],
44
- 'PluginURI' => $plugin['PluginURI'],
45
- 'Version' => $plugin['Version'],
46
- 'Author' => $plugin['Author'],
47
- 'Network' => $plugin['Network'] ? 'True' : 'False',
48
- 'plugin_dir_path' => $pluginPath,
49
- ),
50
- ));
51
- }
52
-
53
- // activate plugin
54
- if($is_plugins && in_array($action, array('activate', 'activate-selected')) && current_user_can("activate_plugins")){
55
- if(isset($_REQUEST['plugin'])){
56
- if(!isset($_REQUEST['checked']))
57
- $_REQUEST['checked'] = array();
58
- $_REQUEST['checked'][] = $_REQUEST['plugin'];
59
- }
60
- foreach($_REQUEST['checked'] as $pluginFile){
61
- $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
62
- $pluginData = get_plugin_data($pluginFile, false, true);
63
- $this->plugin->alerts->Trigger(5001, array(
64
- 'PluginFile' => $pluginFile,
65
- 'PluginData' => (object)array(
66
- 'Name' => $pluginData['Name'],
67
- 'PluginURI' => $pluginData['PluginURI'],
68
- 'Version' => $pluginData['Version'],
69
- 'Author' => $pluginData['Author'],
70
- 'Network' => $pluginData['Network'] ? 'True' : 'False',
71
- ),
72
- ));
73
- }
74
- }
75
-
76
- // deactivate plugin
77
- if($is_plugins && in_array($action, array('deactivate', 'deactivate-selected')) && current_user_can("activate_plugins")){
78
- if(isset($_REQUEST['plugin'])){
79
- if(!isset($_REQUEST['checked']))
80
- $_REQUEST['checked'] = array();
81
- $_REQUEST['checked'][] = $_REQUEST['plugin'];
82
- }
83
- foreach($_REQUEST['checked'] as $pluginFile){
84
- $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
85
- $pluginData = get_plugin_data($pluginFile, false, true);
86
- $this->plugin->alerts->Trigger(5002, array(
87
- 'PluginFile' => $pluginFile,
88
- 'PluginData' => (object)array(
89
- 'Name' => $pluginData['Name'],
90
- 'PluginURI' => $pluginData['PluginURI'],
91
- 'Version' => $pluginData['Version'],
92
- 'Author' => $pluginData['Author'],
93
- 'Network' => $pluginData['Network'] ? 'True' : 'False',
94
- ),
95
- ));
96
- }
97
- }
98
-
99
- // uninstall plugin
100
- if($is_plugins && in_array($action, array('delete-selected')) && current_user_can("delete_plugins")){
101
- if(!isset($_REQUEST['verify-delete'])){
102
- // first step, before user approves deletion
103
- // TODO store plugin data in session here
104
- }else{
105
- // second step, after deletion approval
106
- // TODO use plugin data from session
107
- foreach($_REQUEST['checked'] as $pluginFile){
108
- $pluginName = basename($pluginFile, '.php');
109
- $pluginName = str_replace(array('_', '-', ' '), ' ', $pluginName);
110
- $pluginName = ucwords($pluginName);
111
- $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
112
- $this->plugin->alerts->Trigger(5003, array(
113
- 'PluginFile' => $pluginFile,
114
- 'PluginData' => (object)array(
115
- 'Name' => $pluginName,
116
- ),
117
- ));
118
- }
119
- }
120
- }
121
-
122
- // upgrade plugin
123
- if(in_array($action, array('upgrade-plugin', 'update-plugin', 'update-selected')) && current_user_can("update_plugins")){
124
- $plugins = array();
125
- if(isset($_REQUEST['plugins'])){
126
- $plugins = explode(",", $_REQUEST['plugins']);
127
- } else if(isset($_REQUEST['plugin'])){
128
- $plugins[] = $_REQUEST['plugin'];
129
- }
130
- if(isset($plugins)){
131
- foreach($plugins as $pluginFile){
132
- $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
133
- $pluginData = get_plugin_data($pluginFile, false, true);
134
- $this->plugin->alerts->Trigger(5004, array(
135
- 'PluginFile' => $pluginFile,
136
- 'PluginData' => (object)array(
137
- 'Name' => $pluginData['Name'],
138
- 'PluginURI' => $pluginData['PluginURI'],
139
- 'Version' => $pluginData['Version'],
140
- 'Author' => $pluginData['Author'],
141
- 'Network' => $pluginData['Network'] ? 'True' : 'False',
142
- ),
143
- ));
144
- }
145
- }
146
- }
147
-
148
- // install theme
149
- if(in_array($action, array('install-theme', 'upload-theme')) && current_user_can("install_themes")){
150
- $themes = array_diff(wp_get_themes(), $this->old_themes);
151
- foreach($themes as $theme){
152
- $this->plugin->alerts->Trigger(5005, array(
153
- 'Theme' => (object)array(
154
- 'Name' => $theme->Name,
155
- 'ThemeURI' => $theme->ThemeURI,
156
- 'Description' => $theme->Description,
157
- 'Author' => $theme->Author,
158
- 'Version' => $theme->Version,
159
- 'get_template_directory' => $theme->get_template_directory(),
160
- ),
161
- ));
162
- }
163
- }
164
-
165
- // uninstall theme
166
- if($is_themes && in_array($action, array('delete-selected', 'delete')) && current_user_can("install_themes")){
167
- foreach($this->GetRemovedThemes() as $theme){
168
- $this->plugin->alerts->Trigger(5007, array(
169
- 'Theme' => (object)array(
170
- 'Name' => $theme->Name,
171
- 'ThemeURI' => $theme->ThemeURI,
172
- 'Description' => $theme->Description,
173
- 'Author' => $theme->Author,
174
- 'Version' => $theme->Version,
175
- 'get_template_directory' => $theme->get_template_directory(),
176
- ),
177
- ));
178
- }
179
- }
180
- }
181
-
182
- public function EventThemeActivated($themeName){
183
- $theme = null;
184
- foreach(wp_get_themes() as $item){
185
- if($item->Name == $themeName){
186
- $theme = $item;
187
- break;
188
- }
189
- }
190
- if($theme == null)
191
- return $this->LogError(
192
- 'Could not locate theme named "' . $theme . '".',
193
- array('ThemeName' => $themeName, 'Themes' => wp_get_themes())
194
- );
195
- $this->plugin->alerts->Trigger(5006, array(
196
- 'Theme' => (object)array(
197
- 'Name' => $theme->Name,
198
- 'ThemeURI' => $theme->ThemeURI,
199
- 'Description' => $theme->Description,
200
- 'Author' => $theme->Author,
201
- 'Version' => $theme->Version,
202
- 'get_template_directory' => $theme->get_template_directory(),
203
- ),
204
- ));
205
- }
206
-
207
- protected function GetRemovedThemes(){
208
- $result = $this->old_themes;
209
- foreach($result as $i => $theme)
210
- if(file_exists($theme->get_template_directory()))
211
- unset($result[$i]);
212
- return array_values($result);
213
- }
214
-
215
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_PluginsThemes extends WSAL_AbstractSensor {
4
+
5
+ public function HookEvents() {
6
+ $hasPermission = (current_user_can("install_plugins") || current_user_can("activate_plugins") ||
7
+ current_user_can("delete_plugins") || current_user_can("update_plugins") || current_user_can("install_themes"));
8
+
9
+ add_action('admin_init', array($this, 'EventAdminInit'));
10
+ if($hasPermission)add_action('shutdown', array($this, 'EventAdminShutdown'));
11
+ add_action('switch_theme', array($this, 'EventThemeActivated'));
12
+ }
13
+
14
+ protected $old_themes = array();
15
+ protected $old_plugins = array();
16
+
17
+ public function EventAdminInit(){
18
+ $this->old_themes = wp_get_themes();
19
+ $this->old_plugins = get_plugins();
20
+ }
21
+
22
+ public function EventAdminShutdown(){
23
+ $action = (isset($_REQUEST['action']) && $_REQUEST['action'] != "-1") ? $_REQUEST['action'] : '';
24
+ $action = (isset($_REQUEST['action2']) && $_REQUEST['action2'] != "-1") ? $_REQUEST['action2'] : $action;
25
+ $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
26
+ $is_themes = $actype == 'themes';
27
+ $is_plugins = $actype == 'plugins';
28
+
29
+ // install plugin
30
+ if(in_array($action, array('install-plugin', 'upload-plugin')) && current_user_can("install_plugins")){
31
+ $plugin = array_values(array_diff(array_keys(get_plugins()), array_keys($this->old_plugins)));
32
+ if(count($plugin) != 1)
33
+ return $this->LogError(
34
+ 'Expected exactly one new plugin but found ' . count($plugin),
35
+ array('NewPlugin' => $plugin, 'OldPlugins' => $this->old_plugins, 'NewPlugins' => get_plugins())
36
+ );
37
+ $pluginPath = $plugin[0];
38
+ $plugin = get_plugins();
39
+ $plugin = $plugin[$pluginPath];
40
+ $pluginPath = plugin_dir_path(WP_PLUGIN_DIR . '/' . $pluginPath[0]);
41
+ $this->plugin->alerts->Trigger(5000, array(
42
+ 'Plugin' => (object)array(
43
+ 'Name' => $plugin['Name'],
44
+ 'PluginURI' => $plugin['PluginURI'],
45
+ 'Version' => $plugin['Version'],
46
+ 'Author' => $plugin['Author'],
47
+ 'Network' => $plugin['Network'] ? 'True' : 'False',
48
+ 'plugin_dir_path' => $pluginPath,
49
+ ),
50
+ ));
51
+ }
52
+
53
+ // activate plugin
54
+ if($is_plugins && in_array($action, array('activate', 'activate-selected')) && current_user_can("activate_plugins")){
55
+ if(isset($_REQUEST['plugin'])){
56
+ if(!isset($_REQUEST['checked']))
57
+ $_REQUEST['checked'] = array();
58
+ $_REQUEST['checked'][] = $_REQUEST['plugin'];
59
+ }
60
+ foreach($_REQUEST['checked'] as $pluginFile){
61
+ $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
62
+ $pluginData = get_plugin_data($pluginFile, false, true);
63
+ $this->plugin->alerts->Trigger(5001, array(
64
+ 'PluginFile' => $pluginFile,
65
+ 'PluginData' => (object)array(
66
+ 'Name' => $pluginData['Name'],
67
+ 'PluginURI' => $pluginData['PluginURI'],
68
+ 'Version' => $pluginData['Version'],
69
+ 'Author' => $pluginData['Author'],
70
+ 'Network' => $pluginData['Network'] ? 'True' : 'False',
71
+ ),
72
+ ));
73
+ }
74
+ }
75
+
76
+ // deactivate plugin
77
+ if($is_plugins && in_array($action, array('deactivate', 'deactivate-selected')) && current_user_can("activate_plugins")){
78
+ if(isset($_REQUEST['plugin'])){
79
+ if(!isset($_REQUEST['checked']))
80
+ $_REQUEST['checked'] = array();
81
+ $_REQUEST['checked'][] = $_REQUEST['plugin'];
82
+ }
83
+ foreach($_REQUEST['checked'] as $pluginFile){
84
+ $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
85
+ $pluginData = get_plugin_data($pluginFile, false, true);
86
+ $this->plugin->alerts->Trigger(5002, array(
87
+ 'PluginFile' => $pluginFile,
88
+ 'PluginData' => (object)array(
89
+ 'Name' => $pluginData['Name'],
90
+ 'PluginURI' => $pluginData['PluginURI'],
91
+ 'Version' => $pluginData['Version'],
92
+ 'Author' => $pluginData['Author'],
93
+ 'Network' => $pluginData['Network'] ? 'True' : 'False',
94
+ ),
95
+ ));
96
+ }
97
+ }
98
+
99
+ // uninstall plugin
100
+ if($is_plugins && in_array($action, array('delete-selected')) && current_user_can("delete_plugins")){
101
+ if(!isset($_REQUEST['verify-delete'])){
102
+ // first step, before user approves deletion
103
+ // TODO store plugin data in session here
104
+ }else{
105
+ // second step, after deletion approval
106
+ // TODO use plugin data from session
107
+ foreach($_REQUEST['checked'] as $pluginFile){
108
+ $pluginName = basename($pluginFile, '.php');
109
+ $pluginName = str_replace(array('_', '-', ' '), ' ', $pluginName);
110
+ $pluginName = ucwords($pluginName);
111
+ $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
112
+ $this->plugin->alerts->Trigger(5003, array(
113
+ 'PluginFile' => $pluginFile,
114
+ 'PluginData' => (object)array(
115
+ 'Name' => $pluginName,
116
+ ),
117
+ ));
118
+ }
119
+ }
120
+ }
121
+
122
+ // upgrade plugin
123
+ if(in_array($action, array('upgrade-plugin', 'update-plugin', 'update-selected')) && current_user_can("update_plugins")){
124
+ $plugins = array();
125
+ if(isset($_REQUEST['plugins'])){
126
+ $plugins = explode(",", $_REQUEST['plugins']);
127
+ } else if(isset($_REQUEST['plugin'])){
128
+ $plugins[] = $_REQUEST['plugin'];
129
+ }
130
+ if(isset($plugins)){
131
+ foreach($plugins as $pluginFile){
132
+ $pluginFile = WP_PLUGIN_DIR . '/' . $pluginFile;
133
+ $pluginData = get_plugin_data($pluginFile, false, true);
134
+ $this->plugin->alerts->Trigger(5004, array(
135
+ 'PluginFile' => $pluginFile,
136
+ 'PluginData' => (object)array(
137
+ 'Name' => $pluginData['Name'],
138
+ 'PluginURI' => $pluginData['PluginURI'],
139
+ 'Version' => $pluginData['Version'],
140
+ 'Author' => $pluginData['Author'],
141
+ 'Network' => $pluginData['Network'] ? 'True' : 'False',
142
+ ),
143
+ ));
144
+ }
145
+ }
146
+ }
147
+
148
+ // install theme
149
+ if(in_array($action, array('install-theme', 'upload-theme')) && current_user_can("install_themes")){
150
+ $themes = array_diff(wp_get_themes(), $this->old_themes);
151
+ foreach($themes as $theme){
152
+ $this->plugin->alerts->Trigger(5005, array(
153
+ 'Theme' => (object)array(
154
+ 'Name' => $theme->Name,
155
+ 'ThemeURI' => $theme->ThemeURI,
156
+ 'Description' => $theme->Description,
157
+ 'Author' => $theme->Author,
158
+ 'Version' => $theme->Version,
159
+ 'get_template_directory' => $theme->get_template_directory(),
160
+ ),
161
+ ));
162
+ }
163
+ }
164
+
165
+ // uninstall theme
166
+ if($is_themes && in_array($action, array('delete-selected', 'delete')) && current_user_can("install_themes")){
167
+ foreach($this->GetRemovedThemes() as $theme){
168
+ $this->plugin->alerts->Trigger(5007, array(
169
+ 'Theme' => (object)array(
170
+ 'Name' => $theme->Name,
171
+ 'ThemeURI' => $theme->ThemeURI,
172
+ 'Description' => $theme->Description,
173
+ 'Author' => $theme->Author,
174
+ 'Version' => $theme->Version,
175
+ 'get_template_directory' => $theme->get_template_directory(),
176
+ ),
177
+ ));
178
+ }
179
+ }
180
+ }
181
+
182
+ public function EventThemeActivated($themeName){
183
+ $theme = null;
184
+ foreach(wp_get_themes() as $item){
185
+ if($item->Name == $themeName){
186
+ $theme = $item;
187
+ break;
188
+ }
189
+ }
190
+ if($theme == null)
191
+ return $this->LogError(
192
+ 'Could not locate theme named "' . $theme . '".',
193
+ array('ThemeName' => $themeName, 'Themes' => wp_get_themes())
194
+ );
195
+ $this->plugin->alerts->Trigger(5006, array(
196
+ 'Theme' => (object)array(
197
+ 'Name' => $theme->Name,
198
+ 'ThemeURI' => $theme->ThemeURI,
199
+ 'Description' => $theme->Description,
200
+ 'Author' => $theme->Author,
201
+ 'Version' => $theme->Version,
202
+ 'get_template_directory' => $theme->get_template_directory(),
203
+ ),
204
+ ));
205
+ }
206
+
207
+ protected function GetRemovedThemes(){
208
+ $result = $this->old_themes;
209
+ foreach($result as $i => $theme)
210
+ if(file_exists($theme->get_template_directory()))
211
+ unset($result[$i]);
212
+ return array_values($result);
213
+ }
214
+
215
+ }
classes/Sensors/Request.php CHANGED
@@ -1,41 +1,41 @@
1
- <?php
2
-
3
- class WSAL_Sensors_Request extends WSAL_AbstractSensor {
4
- public function HookEvents() {
5
- if($this->plugin->settings->IsRequestLoggingEnabled()){
6
- add_action('shutdown', array($this, 'EventShutdown'));
7
- }
8
- }
9
-
10
- public function EventShutdown(){
11
- $file = $this->plugin->GetBaseDir() . 'Request.log.php';
12
-
13
- $line = '['.date('Y-m-d H:i:s').'] '
14
- . $_SERVER['REQUEST_METHOD'] . ' '
15
- . $_SERVER['REQUEST_URI'] . ' '
16
- . (!empty($_POST) ? str_pad(PHP_EOL, 24) . json_encode($_POST) : '')
17
- . (!empty(self::$envvars) ? str_pad(PHP_EOL, 24) . json_encode(self::$envvars) : '')
18
- . PHP_EOL;
19
-
20
- if(!file_exists($file) && !file_put_contents($file, '<'.'?php die(\'Access Denied\'); ?>' . PHP_EOL))
21
- return $this->LogError('Could not initialize request log file', array('file' => $file));
22
-
23
- $f = fopen($file, 'a');
24
- if($f){
25
- if(!fwrite($f, $line))
26
- $this->LogWarn('Could not write to log file', array('file' => $file));
27
- if(!fclose($f))
28
- $this->LogWarn('Could not close log file', array('file' => $file));
29
- }else $this->LogWarn('Could not open log file', array('file' => $file));
30
- }
31
-
32
- protected static $envvars = array();
33
-
34
- public static function SetVar($name, $value){
35
- self::$envvars[$name] = $value;
36
- }
37
-
38
- public static function SetVars($data){
39
- foreach($data as $name => $value)self::SetVar($name, $value);
40
- }
41
  }
1
+ <?php
2
+
3
+ class WSAL_Sensors_Request extends WSAL_AbstractSensor {
4
+ public function HookEvents() {
5
+ if($this->plugin->settings->IsRequestLoggingEnabled()){
6
+ add_action('shutdown', array($this, 'EventShutdown'));
7
+ }
8
+ }
9
+
10
+ public function EventShutdown(){
11
+ $file = $this->plugin->GetBaseDir() . 'Request.log.php';
12
+
13
+ $line = '['.date('Y-m-d H:i:s').'] '
14
+ . $_SERVER['REQUEST_METHOD'] . ' '
15
+ . $_SERVER['REQUEST_URI'] . ' '
16
+ . (!empty($_POST) ? str_pad(PHP_EOL, 24) . json_encode($_POST) : '')
17
+ . (!empty(self::$envvars) ? str_pad(PHP_EOL, 24) . json_encode(self::$envvars) : '')
18
+ . PHP_EOL;
19
+
20
+ if(!file_exists($file) && !file_put_contents($file, '<'.'?php die(\'Access Denied\'); ?>' . PHP_EOL))
21
+ return $this->LogError('Could not initialize request log file', array('file' => $file));
22
+
23
+ $f = fopen($file, 'a');
24
+ if($f){
25
+ if(!fwrite($f, $line))
26
+ $this->LogWarn('Could not write to log file', array('file' => $file));
27
+ if(!fclose($f))
28
+ $this->LogWarn('Could not close log file', array('file' => $file));
29
+ }else $this->LogWarn('Could not open log file', array('file' => $file));
30
+ }
31
+
32
+ protected static $envvars = array();
33
+
34
+ public static function SetVar($name, $value){
35
+ self::$envvars[$name] = $value;
36
+ }
37
+
38
+ public static function SetVars($data){
39
+ foreach($data as $name => $value)self::SetVar($name, $value);
40
+ }
41
  }
classes/Sensors/System.php CHANGED
@@ -1,168 +1,168 @@
1
- <?php
2
-
3
- class WSAL_Sensors_System extends WSAL_AbstractSensor
4
- {
5
-
6
- public function HookEvents()
7
- {
8
- add_action('wsal_prune', array($this, 'EventPruneEvents'), 10, 2);
9
- add_action('admin_init', array($this, 'EventAdminInit'));
10
-
11
- add_action('automatic_updates_complete', array($this, 'WPUpdate'), 10, 3);
12
- }
13
-
14
- /**
15
- * @param int $count The number of deleted events.
16
- * @param string $query Query that selected events for deletion.
17
- */
18
- public function EventPruneEvents($count, $query)
19
- {
20
- $this->plugin->alerts->Trigger(6000, array(
21
- 'EventCount' => $count,
22
- 'PruneQuery' => $query,
23
- ));
24
- }
25
-
26
- public function EventAdminInit()
27
- {
28
- // make sure user can actually modify target options
29
- if (!current_user_can('manage_options')) return;
30
-
31
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
32
- $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
33
- $is_option_page = $actype == 'options';
34
- $is_network_settings = $actype == 'settings';
35
- $is_permalink_page = $actype == 'options-permalink';
36
-
37
- if ($is_option_page && (get_option('users_can_register') xor isset($_POST['users_can_register']))) {
38
- $old = get_option('users_can_register') ? 'Enabled' : 'Disabled';
39
- $new = isset($_POST['users_can_register']) ? 'Enabled' : 'Disabled';
40
- if ($old !== $new) {
41
- $this->plugin->alerts->Trigger(6001, array(
42
- 'OldValue' => $old,
43
- 'NewValue' => $new,
44
- 'CurrentUserID' => wp_get_current_user()->ID,
45
- ));
46
- }
47
- }
48
-
49
- if ($is_option_page && !empty($_POST['default_role'])) {
50
- $old = get_option('default_role');
51
- $new = trim($_POST['default_role']);
52
- if ($old !== $new) {
53
- $this->plugin->alerts->Trigger(6002, array(
54
- 'OldRole' => $old,
55
- 'NewRole' => $new,
56
- 'CurrentUserID' => wp_get_current_user()->ID,
57
- ));
58
- }
59
- }
60
-
61
- if ($is_option_page && !empty($_POST['admin_email'])) {
62
- $old = get_option('admin_email');
63
- $new = trim($_POST['admin_email']);
64
- if ($old !== $new) {
65
- $this->plugin->alerts->Trigger(6003, array(
66
- 'OldEmail' => $old,
67
- 'NewEmail' => $new,
68
- 'CurrentUserID' => wp_get_current_user()->ID,
69
- ));
70
- }
71
- }
72
-
73
- if ($is_network_settings && !empty($_POST['admin_email'])) {
74
- $old = get_site_option('admin_email');
75
- $new = trim($_POST['admin_email']);
76
- if ($old !== $new) {
77
- $this->plugin->alerts->Trigger(6003, array(
78
- 'OldEmail' => $old,
79
- 'NewEmail' => $new,
80
- 'CurrentUserID' => wp_get_current_user()->ID,
81
- ));
82
- }
83
- }
84
-
85
- if ($is_permalink_page && !empty($_POST['permalink_structure'])) {
86
- $old = get_option('permalink_structure');
87
- $new = trim($_POST['permalink_structure']);
88
- if ($old !== $new) {
89
- $this->plugin->alerts->Trigger(6005, array(
90
- 'OldPattern' => $old,
91
- 'NewPattern' => $new,
92
- 'CurrentUserID' => wp_get_current_user()->ID,
93
- ));
94
- }
95
- }
96
-
97
- if ($action == 'do-core-upgrade' && isset($_REQUEST['version'])) {
98
- $oldVersion = get_bloginfo('version');
99
- $newVersion = $_REQUEST['version'];
100
- if ($oldVersion !== $newVersion) {
101
- $this->plugin->alerts->Trigger(6004, array(
102
- 'OldVersion' => $oldVersion,
103
- 'NewVersion' => $newVersion,
104
- ));
105
- }
106
- }
107
-
108
- /* BBPress Forum support Setting */
109
- if ($action == 'update' && isset($_REQUEST['_bbp_default_role'])) {
110
- $oldRole = get_option('_bbp_default_role');
111
- $newRole = $_REQUEST['_bbp_default_role'];
112
- if ($oldRole !== $newRole) {
113
- $this->plugin->alerts->Trigger(8009, array(
114
- 'OldRole' => $oldRole,
115
- 'NewRole' => $newRole
116
- ));
117
- }
118
- }
119
-
120
- if ($action == 'update' && isset($_REQUEST['option_page']) && ($_REQUEST['option_page'] == 'bbpress')) {
121
- // Anonymous posting
122
- $allow_anonymous = get_option('_bbp_allow_anonymous');
123
- $oldStatus = !empty($allow_anonymous) ? 1 : 0;
124
- $newStatus = !empty($_REQUEST['_bbp_allow_anonymous']) ? 1 : 0;
125
- if ($oldStatus != $newStatus) {
126
- $status = ($newStatus == 1) ? 'Enabled' : 'Disabled';
127
- $this->plugin->alerts->Trigger(8010, array(
128
- 'Status' => $status
129
- ));
130
- }
131
- // Disallow editing after
132
- $bbp_edit_lock = get_option('_bbp_edit_lock');
133
- $oldTime = !empty($bbp_edit_lock) ? $bbp_edit_lock : '';
134
- $newTime = !empty($_REQUEST['_bbp_edit_lock']) ? $_REQUEST['_bbp_edit_lock'] : '';
135
- if ($oldTime != $newTime) {
136
- $this->plugin->alerts->Trigger(8012, array(
137
- 'OldTime' => $oldTime,
138
- 'NewTime' => $newTime
139
- ));
140
- }
141
- // Throttle posting every
142
- $bbp_throttle_time = get_option('_bbp_throttle_time');
143
- $oldTime2 = !empty($bbp_throttle_time) ? $bbp_throttle_time : '';
144
- $newTime2 = !empty($_REQUEST['_bbp_throttle_time']) ? $_REQUEST['_bbp_throttle_time'] : '';
145
- if ($oldTime2 != $newTime2) {
146
- $this->plugin->alerts->Trigger(8013, array(
147
- 'OldTime' => $oldTime2,
148
- 'NewTime' => $newTime2
149
- ));
150
- }
151
- }
152
- }
153
-
154
- /**
155
- * WordPress auto core update
156
- */
157
- public function WPUpdate($automatic, $updates, $complete)
158
- {
159
- if (isset($automatic['core'][0])) {
160
- $obj = $automatic['core'][0];
161
- $oldVersion = get_bloginfo('version');
162
- $this->plugin->alerts->Trigger(6004, array(
163
- 'OldVersion' => $oldVersion,
164
- 'NewVersion' => $obj->item->version.' (auto update)'
165
- ));
166
- }
167
- }
168
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_System extends WSAL_AbstractSensor
4
+ {
5
+
6
+ public function HookEvents()
7
+ {
8
+ add_action('wsal_prune', array($this, 'EventPruneEvents'), 10, 2);
9
+ add_action('admin_init', array($this, 'EventAdminInit'));
10
+
11
+ add_action('automatic_updates_complete', array($this, 'WPUpdate'), 10, 1);
12
+ }
13
+
14
+ /**
15
+ * @param int $count The number of deleted events.
16
+ * @param string $query Query that selected events for deletion.
17
+ */
18
+ public function EventPruneEvents($count, $query)
19
+ {
20
+ $this->plugin->alerts->Trigger(6000, array(
21
+ 'EventCount' => $count,
22
+ 'PruneQuery' => $query,
23
+ ));
24
+ }
25
+
26
+ public function EventAdminInit()
27
+ {
28
+ // make sure user can actually modify target options
29
+ if (!current_user_can('manage_options')) return;
30
+
31
+ $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
32
+ $actype = basename($_SERVER['SCRIPT_NAME'], '.php');
33
+ $is_option_page = $actype == 'options';
34
+ $is_network_settings = $actype == 'settings';
35
+ $is_permalink_page = $actype == 'options-permalink';
36
+
37
+ if ($is_option_page && (get_option('users_can_register') xor isset($_POST['users_can_register']))) {
38
+ $old = get_option('users_can_register') ? 'Enabled' : 'Disabled';
39
+ $new = isset($_POST['users_can_register']) ? 'Enabled' : 'Disabled';
40
+ if ($old !== $new) {
41
+ $this->plugin->alerts->Trigger(6001, array(
42
+ 'OldValue' => $old,
43
+ 'NewValue' => $new,
44
+ 'CurrentUserID' => wp_get_current_user()->ID,
45
+ ));
46
+ }
47
+ }
48
+
49
+ if ($is_option_page && !empty($_POST['default_role'])) {
50
+ $old = get_option('default_role');
51
+ $new = trim($_POST['default_role']);
52
+ if ($old !== $new) {
53
+ $this->plugin->alerts->Trigger(6002, array(
54
+ 'OldRole' => $old,
55
+ 'NewRole' => $new,
56
+ 'CurrentUserID' => wp_get_current_user()->ID,
57
+ ));
58
+ }
59
+ }
60
+
61
+ if ($is_option_page && !empty($_POST['admin_email'])) {
62
+ $old = get_option('admin_email');
63
+ $new = trim($_POST['admin_email']);
64
+ if ($old !== $new) {
65
+ $this->plugin->alerts->Trigger(6003, array(
66
+ 'OldEmail' => $old,
67
+ 'NewEmail' => $new,
68
+ 'CurrentUserID' => wp_get_current_user()->ID,
69
+ ));
70
+ }
71
+ }
72
+
73
+ if ($is_network_settings && !empty($_POST['admin_email'])) {
74
+ $old = get_site_option('admin_email');
75
+ $new = trim($_POST['admin_email']);
76
+ if ($old !== $new) {
77
+ $this->plugin->alerts->Trigger(6003, array(
78
+ 'OldEmail' => $old,
79
+ 'NewEmail' => $new,
80
+ 'CurrentUserID' => wp_get_current_user()->ID,
81
+ ));
82
+ }
83
+ }
84
+
85
+ if ($is_permalink_page && !empty($_POST['permalink_structure'])) {
86
+ $old = get_option('permalink_structure');
87
+ $new = trim($_POST['permalink_structure']);
88
+ if ($old !== $new) {
89
+ $this->plugin->alerts->Trigger(6005, array(
90
+ 'OldPattern' => $old,
91
+ 'NewPattern' => $new,
92
+ 'CurrentUserID' => wp_get_current_user()->ID,
93
+ ));
94
+ }
95
+ }
96
+
97
+ if ($action == 'do-core-upgrade' && isset($_REQUEST['version'])) {
98
+ $oldVersion = get_bloginfo('version');
99
+ $newVersion = $_REQUEST['version'];
100
+ if ($oldVersion !== $newVersion) {
101
+ $this->plugin->alerts->Trigger(6004, array(
102
+ 'OldVersion' => $oldVersion,
103
+ 'NewVersion' => $newVersion,
104
+ ));
105
+ }
106
+ }
107
+
108
+ /* BBPress Forum support Setting */
109
+ if ($action == 'update' && isset($_REQUEST['_bbp_default_role'])) {
110
+ $oldRole = get_option('_bbp_default_role');
111
+ $newRole = $_REQUEST['_bbp_default_role'];
112
+ if ($oldRole !== $newRole) {
113
+ $this->plugin->alerts->Trigger(8009, array(
114
+ 'OldRole' => $oldRole,
115
+ 'NewRole' => $newRole
116
+ ));
117
+ }
118
+ }
119
+
120
+ if ($action == 'update' && isset($_REQUEST['option_page']) && ($_REQUEST['option_page'] == 'bbpress')) {
121
+ // Anonymous posting
122
+ $allow_anonymous = get_option('_bbp_allow_anonymous');
123
+ $oldStatus = !empty($allow_anonymous) ? 1 : 0;
124
+ $newStatus = !empty($_REQUEST['_bbp_allow_anonymous']) ? 1 : 0;
125
+ if ($oldStatus != $newStatus) {
126
+ $status = ($newStatus == 1) ? 'Enabled' : 'Disabled';
127
+ $this->plugin->alerts->Trigger(8010, array(
128
+ 'Status' => $status
129
+ ));
130
+ }
131
+ // Disallow editing after
132
+ $bbp_edit_lock = get_option('_bbp_edit_lock');
133
+ $oldTime = !empty($bbp_edit_lock) ? $bbp_edit_lock : '';
134
+ $newTime = !empty($_REQUEST['_bbp_edit_lock']) ? $_REQUEST['_bbp_edit_lock'] : '';
135
+ if ($oldTime != $newTime) {
136
+ $this->plugin->alerts->Trigger(8012, array(
137
+ 'OldTime' => $oldTime,
138
+ 'NewTime' => $newTime
139
+ ));
140
+ }
141
+ // Throttle posting every
142
+ $bbp_throttle_time = get_option('_bbp_throttle_time');
143
+ $oldTime2 = !empty($bbp_throttle_time) ? $bbp_throttle_time : '';
144
+ $newTime2 = !empty($_REQUEST['_bbp_throttle_time']) ? $_REQUEST['_bbp_throttle_time'] : '';
145
+ if ($oldTime2 != $newTime2) {
146
+ $this->plugin->alerts->Trigger(8013, array(
147
+ 'OldTime' => $oldTime2,
148
+ 'NewTime' => $newTime2
149
+ ));
150
+ }
151
+ }
152
+ }
153
+
154
+ /**
155
+ * WordPress auto core update
156
+ */
157
+ public function WPUpdate($automatic)
158
+ {
159
+ if (isset($automatic['core'][0])) {
160
+ $obj = $automatic['core'][0];
161
+ $oldVersion = get_bloginfo('version');
162
+ $this->plugin->alerts->Trigger(6004, array(
163
+ 'OldVersion' => $oldVersion,
164
+ 'NewVersion' => $obj->item->version.' (auto update)'
165
+ ));
166
+ }
167
+ }
168
+ }
classes/Sensors/UserProfile.php CHANGED
@@ -1,164 +1,164 @@
1
- <?php
2
-
3
- class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
4
- {
5
-
6
- public function HookEvents()
7
- {
8
- add_action('admin_init', array($this, 'EventAdminInit'));
9
- add_action('user_register', array($this, 'EventUserRegister'));
10
- add_action('edit_user_profile_update', array($this, 'EventUserChanged'));
11
- add_action('personal_options_update', array($this, 'EventUserChanged'));
12
- add_action('delete_user', array($this, 'EventUserDeleted'));
13
- add_action('wpmu_delete_user', array($this, 'EventUserDeleted'));
14
- add_action('set_user_role', array($this, 'EventUserRoleChanged'), 10, 3);
15
- }
16
-
17
- protected $old_superadmins;
18
-
19
- public function EventAdminInit()
20
- {
21
- if ($this->IsMultisite()) {
22
- $this->old_superadmins = get_super_admins();
23
- }
24
- }
25
-
26
- public function EventUserRegister($user_id)
27
- {
28
- $user = get_userdata($user_id);
29
- $ismu = function_exists('is_multisite') && is_multisite();
30
- $event = $ismu ? 4012 : (is_user_logged_in() ? 4001 : 4000);
31
- $this->plugin->alerts->Trigger($event, array(
32
- 'NewUserID' => $user_id,
33
- 'NewUserData' => (object)array(
34
- 'Username' => $user->user_login,
35
- 'FirstName' => $user->user_firstname,
36
- 'LastName' => $user->user_lastname,
37
- 'Email' => $user->user_email,
38
- 'Roles' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
39
- ),
40
- ), true);
41
- }
42
-
43
- public function EventUserRoleChanged($user_id, $role, $oldRoles)
44
- {
45
- $user = get_userdata($user_id);
46
- $aBbpRoles = array('bbp_spectator', 'bbp_moderator', 'bbp_participant', 'bbp_keymaster', 'bbp_blocked');
47
- // remove any BBPress roles
48
- if (is_array($oldRoles)) {
49
- foreach ($oldRoles as $value) {
50
- if (in_array($value, $aBbpRoles)) {
51
- if ($_POST['bbp-forums-role'] != $value) {
52
- $current_user = wp_get_current_user();
53
- $this->plugin->alerts->TriggerIf(4013, array(
54
- 'TargetUsername' => $user->user_login,
55
- 'OldRole' => ucfirst(substr($value, 4)),
56
- 'NewRole' => ucfirst(substr($_POST['bbp-forums-role'], 4)),
57
- 'UserChanger' => $current_user->user_login
58
- ));
59
- }
60
- }
61
- }
62
- $oldRoles = array_diff($oldRoles, $aBbpRoles);
63
- }
64
- $oldRole = count($oldRoles) ? implode(', ', $oldRoles) : '';
65
- $newRole = $role;
66
- if ($oldRole != $newRole) {
67
- $this->plugin->alerts->TriggerIf(4002, array(
68
- 'TargetUserID' => $user_id,
69
- 'TargetUsername' => $user->user_login,
70
- 'OldRole' => $oldRole,
71
- 'NewRole' => $newRole,
72
- ), array($this, 'MustNotContainUserChanges'));
73
- }
74
- }
75
-
76
- public function EventUserChanged($user_id)
77
- {
78
- $user = get_userdata($user_id);
79
-
80
- // password changed
81
- if (!empty($_REQUEST['pass1']) && !empty($_REQUEST['pass2'])) {
82
- if (trim($_REQUEST['pass1']) == trim($_REQUEST['pass2'])) {
83
- $event = $user_id == get_current_user_id() ? 4003 : 4004;
84
- $this->plugin->alerts->Trigger($event, array(
85
- 'TargetUserID' => $user_id,
86
- 'TargetUserData' => (object)array(
87
- 'Username' => $user->user_login,
88
- 'Roles' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
89
- ),
90
- ));
91
- }
92
- }
93
-
94
- // email changed
95
- if (!empty($_REQUEST['email'])) {
96
- $oldEmail = $user->user_email;
97
- $newEmail = trim($_REQUEST['email']);
98
- if ($oldEmail != $newEmail) {
99
- $event = $user_id == get_current_user_id() ? 4005 : 4006;
100
- $this->plugin->alerts->Trigger($event, array(
101
- 'TargetUserID' => $user_id,
102
- 'TargetUsername' => $user->user_login,
103
- 'OldEmail' => $oldEmail,
104
- 'NewEmail' => $newEmail,
105
- ));
106
- }
107
- }
108
-
109
- if ($this->IsMultisite()) {
110
- $username = $user->user_login;
111
- $enabled = isset($_REQUEST['super_admin']);
112
-
113
- if ($user_id != get_current_user_id()) {
114
- // super admin enabled
115
- if ($enabled && !in_array($username, $this->old_superadmins)) {
116
- $this->plugin->alerts->Trigger(4008, array(
117
- 'TargetUserID' => $user_id,
118
- 'TargetUsername' => $user->user_login,
119
- ));
120
- }
121
-
122
- // super admin disabled
123
- if (!$enabled && in_array($username, $this->old_superadmins)) {
124
- $this->plugin->alerts->Trigger(4009, array(
125
- 'TargetUserID' => $user_id,
126
- 'TargetUsername' => $user->user_login,
127
- ));
128
- }
129
-
130
- }
131
- }
132
- }
133
-
134
- public function EventUserDeleted($user_id)
135
- {
136
- $user = get_userdata($user_id);
137
- $role = is_array($user->roles) ? implode(', ', $user->roles) : $user->roles;
138
- $this->plugin->alerts->TriggerIf(4007, array(
139
- 'TargetUserID' => $user_id,
140
- 'TargetUserData' => (object)array(
141
- 'Username' => $user->user_login,
142
- 'FirstName' => $user->user_firstname,
143
- 'LastName' => $user->user_lastname,
144
- 'Email' => $user->user_email,
145
- 'Roles' => $role ? $role : 'none',
146
- ),
147
- ), array($this, 'MustNotContainCreateUser'));
148
- }
149
-
150
- public function MustNotContainCreateUser(WSAL_AlertManager $mgr)
151
- {
152
- return !$mgr->WillTrigger(4012);
153
- }
154
-
155
- public function MustNotContainUserChanges(WSAL_AlertManager $mgr)
156
- {
157
- return !( $mgr->WillOrHasTriggered(4010)
158
- || $mgr->WillOrHasTriggered(4011)
159
- || $mgr->WillOrHasTriggered(4012)
160
- || $mgr->WillOrHasTriggered(4000)
161
- || $mgr->WillOrHasTriggered(4001)
162
- );
163
- }
164
- }
1
+ <?php
2
+
3
+ class WSAL_Sensors_UserProfile extends WSAL_AbstractSensor
4
+ {
5
+
6
+ public function HookEvents()
7
+ {
8
+ add_action('admin_init', array($this, 'EventAdminInit'));
9
+ add_action('user_register', array($this, 'EventUserRegister'));
10
+ add_action('edit_user_profile_update', array($this, 'EventUserChanged'));
11
+ add_action('personal_options_update', array($this, 'EventUserChanged'));
12
+ add_action('delete_user', array($this, 'EventUserDeleted'));
13
+ add_action('wpmu_delete_user', array($this, 'EventUserDeleted'));
14
+ add_action('set_user_role', array($this, 'EventUserRoleChanged'), 10, 3);
15
+ }
16
+
17
+ protected $old_superadmins;
18
+
19
+ public function EventAdminInit()
20
+ {
21
+ if ($this->IsMultisite()) {
22
+ $this->old_superadmins = get_super_admins();
23
+ }
24
+ }
25
+
26
+ public function EventUserRegister($user_id)
27
+ {
28
+ $user = get_userdata($user_id);
29
+ $ismu = function_exists('is_multisite') && is_multisite();
30
+ $event = $ismu ? 4012 : (is_user_logged_in() ? 4001 : 4000);
31
+ $this->plugin->alerts->Trigger($event, array(
32
+ 'NewUserID' => $user_id,
33
+ 'NewUserData' => (object)array(
34
+ 'Username' => $user->user_login,
35
+ 'FirstName' => $user->user_firstname,
36
+ 'LastName' => $user->user_lastname,
37
+ 'Email' => $user->user_email,
38
+ 'Roles' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
39
+ ),
40
+ ), true);
41
+ }
42
+
43
+ public function EventUserRoleChanged($user_id, $role, $oldRoles)
44
+ {
45
+ $user = get_userdata($user_id);
46
+ $aBbpRoles = array('bbp_spectator', 'bbp_moderator', 'bbp_participant', 'bbp_keymaster', 'bbp_blocked');
47
+ // remove any BBPress roles
48
+ if (is_array($oldRoles)) {
49
+ foreach ($oldRoles as $value) {
50
+ if (in_array($value, $aBbpRoles)) {
51
+ if ($_POST['bbp-forums-role'] != $value) {
52
+ $current_user = wp_get_current_user();
53
+ $this->plugin->alerts->TriggerIf(4013, array(
54
+ 'TargetUsername' => $user->user_login,
55
+ 'OldRole' => ucfirst(substr($value, 4)),
56
+ 'NewRole' => ucfirst(substr($_POST['bbp-forums-role'], 4)),
57
+ 'UserChanger' => $current_user->user_login
58
+ ));
59
+ }
60
+ }
61
+ }
62
+ $oldRoles = array_diff($oldRoles, $aBbpRoles);
63
+ }
64
+ $oldRole = count($oldRoles) ? implode(', ', $oldRoles) : '';
65
+ $newRole = $role;
66
+ if ($oldRole != $newRole) {
67
+ $this->plugin->alerts->TriggerIf(4002, array(
68
+ 'TargetUserID' => $user_id,
69
+ 'TargetUsername' => $user->user_login,
70
+ 'OldRole' => $oldRole,
71
+ 'NewRole' => $newRole,
72
+ ), array($this, 'MustNotContainUserChanges'));
73
+ }
74
+ }
75
+
76
+ public function EventUserChanged($user_id)
77
+ {
78
+ $user = get_userdata($user_id);
79
+
80
+ // password changed
81
+ if (!empty($_REQUEST['pass1']) && !empty($_REQUEST['pass2'])) {
82
+ if (trim($_REQUEST['pass1']) == trim($_REQUEST['pass2'])) {
83
+ $event = $user_id == get_current_user_id() ? 4003 : 4004;
84
+ $this->plugin->alerts->Trigger($event, array(
85
+ 'TargetUserID' => $user_id,
86
+ 'TargetUserData' => (object)array(
87
+ 'Username' => $user->user_login,
88
+ 'Roles' => is_array($user->roles) ? implode(', ', $user->roles) : $user->roles,
89
+ ),
90
+ ));
91
+ }
92
+ }
93
+
94
+ // email changed
95
+ if (!empty($_REQUEST['email'])) {
96
+ $oldEmail = $user->user_email;
97
+ $newEmail = trim($_REQUEST['email']);
98
+ if ($oldEmail != $newEmail) {
99
+ $event = $user_id == get_current_user_id() ? 4005 : 4006;
100
+ $this->plugin->alerts->Trigger($event, array(
101
+ 'TargetUserID' => $user_id,
102
+ 'TargetUsername' => $user->user_login,
103
+ 'OldEmail' => $oldEmail,
104
+ 'NewEmail' => $newEmail,
105
+ ));
106
+ }
107
+ }
108
+
109
+ if ($this->IsMultisite()) {
110
+ $username = $user->user_login;
111
+ $enabled = isset($_REQUEST['super_admin']);
112
+
113
+ if ($user_id != get_current_user_id()) {
114
+ // super admin enabled
115
+ if ($enabled && !in_array($username, $this->old_superadmins)) {
116
+ $this->plugin->alerts->Trigger(4008, array(
117
+ 'TargetUserID' => $user_id,
118
+ 'TargetUsername' => $user->user_login,
119
+ ));
120
+ }
121
+
122
+ // super admin disabled
123
+ if (!$enabled && in_array($username, $this->old_superadmins)) {
124
+ $this->plugin->alerts->Trigger(4009, array(
125
+ 'TargetUserID' => $user_id,
126
+ 'TargetUsername' => $user->user_login,
127
+ ));
128
+ }
129
+
130
+ }
131
+ }
132
+ }
133
+
134
+ public function EventUserDeleted($user_id)
135
+ {
136
+ $user = get_userdata($user_id);
137
+ $role = is_array($user->roles) ? implode(', ', $user->roles) : $user->roles;
138
+ $this->plugin->alerts->TriggerIf(4007, array(
139
+ 'TargetUserID' => $user_id,
140
+ 'TargetUserData' => (object)array(
141
+ 'Username' => $user->user_login,
142
+ 'FirstName' => $user->user_firstname,
143
+ 'LastName' => $user->user_lastname,
144
+ 'Email' => $user->user_email,
145
+ 'Roles' => $role ? $role : 'none',
146
+ ),
147
+ ), array($this, 'MustNotContainCreateUser'));
148
+ }
149
+
150
+ public function MustNotContainCreateUser(WSAL_AlertManager $mgr)
151
+ {
152
+ return !$mgr->WillTrigger(4012);
153
+ }
154
+
155
+ public function MustNotContainUserChanges(WSAL_AlertManager $mgr)
156
+ {
157
+ return !( $mgr->WillOrHasTriggered(4010)
158
+ || $mgr->WillOrHasTriggered(4011)
159
+ || $mgr->WillOrHasTriggered(4012)
160
+ || $mgr->WillOrHasTriggered(4000)
161
+ || $mgr->WillOrHasTriggered(4001)
162
+ );
163
+ }
164
+ }
classes/Sensors/Widgets.php CHANGED
@@ -1,235 +1,235 @@
1
- <?php
2
-
3
- class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
4
-
5
- public function HookEvents() {
6
- if(current_user_can("edit_theme_options")) {
7
- add_action('admin_init', array($this, 'EventWidgetMove'));
8
- add_action('admin_init', array($this, 'EventWidgetPostMove'));
9
- }
10
- add_action('sidebar_admin_setup', array($this, 'EventWidgetActivity'));
11
- }
12
-
13
- protected $_WidgetMoveData = null;
14
-
15
- public function EventWidgetMove(){
16
- if(isset($_POST) && !empty($_POST['sidebars']))
17
- {
18
- $crtSidebars = $_POST['sidebars'];
19
- $sidebars = array();
20
- foreach ( $crtSidebars as $key => $val )
21
- {
22
- $sb = array();
23
- if ( !empty($val) )
24
- {
25
- $val = explode(',', $val);
26
- foreach ( $val as $k => $v )
27
- {
28
- if ( strpos($v, 'widget-') === false ) continue;
29
- $sb[$k] = substr($v, strpos($v, '_') + 1);
30
- }
31
- }
32
- $sidebars[$key] = $sb;
33
- }
34
- $crtSidebars = $sidebars;
35
- $dbSidebars = get_option('sidebars_widgets');
36
- $wName = $fromSidebar = $toSidebar = '';
37
- foreach($crtSidebars as $sidebarName => $values)
38
- {
39
- if(is_array($values) && ! empty($values) && isset($dbSidebars[$sidebarName]))
40
- {
41
- foreach($values as $widgetName)
42
- {
43
- if(! in_array($widgetName, $dbSidebars[$sidebarName]))
44
- {
45
- $toSidebar = $sidebarName;
46
- $wName = $widgetName;
47
- foreach($dbSidebars as $name => $v)
48
- {
49
- if(is_array($v) && !empty($v) && in_array($widgetName, $v))
50
- {
51
- $fromSidebar = $name;
52
- continue;
53
- }
54
- }
55
- }
56
- }
57
- }
58
- }
59
-
60
- if (empty($wName) || empty($fromSidebar) || empty($toSidebar)) return;
61
-
62
- if(preg_match('/^sidebar-/', $fromSidebar) || preg_match('/^sidebar-/', $toSidebar)){
63
- // This option will hold the data needed to trigger the event 2045
64
- // as at this moment the $wp_registered_sidebars variable is not yet populated
65
- // so we cannot retrieve the name for sidebar-1 || sidebar-2
66
- // we will then check for this variable in the EventWidgetPostMove() event
67
- $this->_WidgetMoveData = array('widget' => $wName, 'from' => $fromSidebar, 'to' => $toSidebar);
68
- return;
69
- }
70
-
71
- $this->plugin->alerts->Trigger(2045, array(
72
- 'WidgetName' => $wName,
73
- 'OldSidebar' => $fromSidebar,
74
- 'NewSidebar' => $toSidebar,
75
- ));
76
- }
77
- }
78
-
79
- public function EventWidgetPostMove() {
80
- //#!-- generates the event 2071
81
- if (isset($_REQUEST['action'])&&($_REQUEST['action']=='widgets-order'))
82
- {
83
- if (isset($_REQUEST['sidebars'])) {
84
- // Get the sidebars from $_REQUEST
85
- $requestSidebars = array();
86
- if ($_REQUEST['sidebars']) {
87
- foreach($_REQUEST['sidebars'] as $key => &$value){
88
- if(!empty($value)){
89
- // build the sidebars array
90
- $value = explode(',', $value);
91
- // Cleanup widgets' name
92
- foreach($value as $k => &$widgetName){
93
- $widgetName = preg_replace("/^([a-z]+-[0-9]+)+?_/i",'', $widgetName);
94
- }
95
- $requestSidebars[$key] = $value;
96
- }
97
- }
98
- }
99
-
100
- if ($requestSidebars) {
101
- // Get the sidebars from DATABASE
102
- $sidebar_widgets = wp_get_sidebars_widgets();
103
- // Get global sidebars so we can retrieve the real name of the sidebar
104
- global $wp_registered_sidebars;
105
-
106
- // Check in each array if there's any change
107
- foreach ($requestSidebars as $sidebarName => $widgets) {
108
- if (isset($sidebar_widgets[$sidebarName])) {
109
- foreach ($sidebar_widgets[$sidebarName] as $i => $widgetName) {
110
- $index = array_search($widgetName, $widgets);
111
- // check to see whether or not the widget has been moved
112
- if ($i != $index) {
113
- $sn = $sidebarName;
114
- // Try to retrieve the real name of the sidebar, otherwise fall-back to id: $sidebarName
115
- if ($wp_registered_sidebars && isset($wp_registered_sidebars[$sidebarName])) {
116
- $sn = $wp_registered_sidebars[$sidebarName]['name'];
117
- }
118
- $this->plugin->alerts->Trigger(2071, array(
119
- 'WidgetName' => $widgetName,
120
- 'OldPosition' => $i+1,
121
- 'NewPosition' => $index+1,
122
- 'Sidebar' => $sn,
123
- ));
124
- }
125
- }
126
- }
127
- }
128
- }
129
- }
130
- }
131
- //#!--
132
-
133
- if($this->_WidgetMoveData){
134
- $wName = $this->_WidgetMoveData['widget'];
135
- $fromSidebar = $this->_WidgetMoveData['from'];
136
- $toSidebar = $this->_WidgetMoveData['to'];
137
-
138
- global $wp_registered_sidebars;
139
-
140
- if(preg_match('/^sidebar-/', $fromSidebar))
141
- $fromSidebar = isset($wp_registered_sidebars[$fromSidebar])
142
- ? $wp_registered_sidebars[$fromSidebar]['name']
143
- : $fromSidebar
144
- ;
145
- if(preg_match('/^sidebar-/', $toSidebar))
146
- $toSidebar = isset($wp_registered_sidebars[$toSidebar])
147
- ? $wp_registered_sidebars[$toSidebar]['name']
148
- : $toSidebar
149
- ;
150
-
151
- $this->plugin->alerts->Trigger(2045, array(
152
- 'WidgetName' => $wName,
153
- 'OldSidebar' => $fromSidebar,
154
- 'NewSidebar' => $toSidebar,
155
- ));
156
- }
157
- }
158
-
159
- public function EventWidgetActivity(){
160
- if(!isset($_POST) || !isset($_POST['widget-id']) || empty($_POST['widget-id'])){
161
- return;
162
- }
163
-
164
- $postData = $_POST;
165
- global $wp_registered_sidebars;
166
- $canCheckSidebar = (empty($wp_registered_sidebars) ? false : true);
167
-
168
- switch(true){
169
-
170
- // added widget
171
- case isset($postData['add_new']) && $postData['add_new'] == 'multi':
172
- $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
173
- if($canCheckSidebar && preg_match('/^sidebar-/', $sidebar)){
174
- $sidebar = $wp_registered_sidebars[$sidebar]['name'];
175
- }
176
- $this->plugin->alerts->Trigger(2042, array(
177
- 'WidgetName' => $postData['id_base'],
178
- 'Sidebar' => $sidebar,
179
- ));
180
- break;
181
-
182
- // deleted widget
183
- case isset($postData['delete_widget']) && intval($postData['delete_widget']) == 1:
184
- $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
185
- if($canCheckSidebar && preg_match('/^sidebar-/',$sidebar)){
186
- $sidebar = $wp_registered_sidebars[$sidebar]['name'];
187
- }
188
- $this->plugin->alerts->Trigger(2044, array(
189
- 'WidgetName' => $postData['id_base'],
190
- 'Sidebar' => $sidebar,
191
- ));
192
- break;
193
-
194
- // modified widget
195
- case isset($postData['id_base']) && !empty($postData['id_base']):
196
- $wId = 0;
197
- if(!empty($postData['multi_number'])){
198
- $wId = intval($postData['multi_number']);
199
- }elseif(!empty($postData['widget_number'])){
200
- $wId = intval($postData['widget_number']);
201
- }
202
- if(empty($wId))return;
203
-
204
- $wName = $postData['id_base'];
205
- $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
206
- $wData = isset($postData["widget-$wName"][$wId])
207
- ? $postData["widget-$wName"][$wId]
208
- : null;
209
-
210
- if(empty($wData))return;
211
-
212
- // get info from db
213
- $wdbData = get_option("widget_".$wName);
214
- if(empty($wdbData[$wId]))return;
215
-
216
- // transform 'on' -> 1
217
- foreach($wData as $k => $v)if($v == 'on')$wData[$k] = 1;
218
-
219
- // compare - checks for any changes inside widgets
220
- $diff = array_diff_assoc($wData, $wdbData[$wId]);
221
- $count = count($diff);
222
- if($count > 0){
223
- if($canCheckSidebar && preg_match("/^sidebar-/",$sidebar)){
224
- $sidebar = $wp_registered_sidebars[$sidebar]['name'];
225
- }
226
- $this->plugin->alerts->Trigger(2043, array(
227
- 'WidgetName' => $wName,
228
- 'Sidebar' => $sidebar,
229
- ));
230
- }
231
- break;
232
-
233
- }
234
- }
235
  }
1
+ <?php
2
+
3
+ class WSAL_Sensors_Widgets extends WSAL_AbstractSensor {
4
+
5
+ public function HookEvents() {
6
+ if(current_user_can("edit_theme_options")) {
7
+ add_action('admin_init', array($this, 'EventWidgetMove'));
8
+ add_action('admin_init', array($this, 'EventWidgetPostMove'));
9
+ }
10
+ add_action('sidebar_admin_setup', array($this, 'EventWidgetActivity'));
11
+ }
12
+
13
+ protected $_WidgetMoveData = null;
14
+
15
+ public function EventWidgetMove(){
16
+ if(isset($_POST) && !empty($_POST['sidebars']))
17
+ {
18
+ $crtSidebars = $_POST['sidebars'];
19
+ $sidebars = array();
20
+ foreach ( $crtSidebars as $key => $val )
21
+ {
22
+ $sb = array();
23
+ if ( !empty($val) )
24
+ {
25
+ $val = explode(',', $val);
26
+ foreach ( $val as $k => $v )
27
+ {
28
+ if ( strpos($v, 'widget-') === false ) continue;
29
+ $sb[$k] = substr($v, strpos($v, '_') + 1);
30
+ }
31
+ }
32
+ $sidebars[$key] = $sb;
33
+ }
34
+ $crtSidebars = $sidebars;
35
+ $dbSidebars = get_option('sidebars_widgets');
36
+ $wName = $fromSidebar = $toSidebar = '';
37
+ foreach($crtSidebars as $sidebarName => $values)
38
+ {
39
+ if(is_array($values) && ! empty($values) && isset($dbSidebars[$sidebarName]))
40
+ {
41
+ foreach($values as $widgetName)
42
+ {
43
+ if(! in_array($widgetName, $dbSidebars[$sidebarName]))
44
+ {
45
+ $toSidebar = $sidebarName;
46
+ $wName = $widgetName;
47
+ foreach($dbSidebars as $name => $v)
48
+ {
49
+ if(is_array($v) && !empty($v) && in_array($widgetName, $v))
50
+ {
51
+ $fromSidebar = $name;
52
+ continue;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ if (empty($wName) || empty($fromSidebar) || empty($toSidebar)) return;
61
+
62
+ if(preg_match('/^sidebar-/', $fromSidebar) || preg_match('/^sidebar-/', $toSidebar)){
63
+ // This option will hold the data needed to trigger the event 2045
64
+ // as at this moment the $wp_registered_sidebars variable is not yet populated
65
+ // so we cannot retrieve the name for sidebar-1 || sidebar-2
66
+ // we will then check for this variable in the EventWidgetPostMove() event
67
+ $this->_WidgetMoveData = array('widget' => $wName, 'from' => $fromSidebar, 'to' => $toSidebar);
68
+ return;
69
+ }
70
+
71
+ $this->plugin->alerts->Trigger(2045, array(
72
+ 'WidgetName' => $wName,
73
+ 'OldSidebar' => $fromSidebar,
74
+ 'NewSidebar' => $toSidebar,
75
+ ));
76
+ }
77
+ }
78
+
79
+ public function EventWidgetPostMove() {
80
+ //#!-- generates the event 2071
81
+ if (isset($_REQUEST['action'])&&($_REQUEST['action']=='widgets-order'))
82
+ {
83
+ if (isset($_REQUEST['sidebars'])) {
84
+ // Get the sidebars from $_REQUEST
85
+ $requestSidebars = array();
86
+ if ($_REQUEST['sidebars']) {
87
+ foreach($_REQUEST['sidebars'] as $key => &$value){
88
+ if(!empty($value)){
89
+ // build the sidebars array
90
+ $value = explode(',', $value);
91
+ // Cleanup widgets' name
92
+ foreach($value as $k => &$widgetName){
93
+ $widgetName = preg_replace("/^([a-z]+-[0-9]+)+?_/i",'', $widgetName);
94
+ }
95
+ $requestSidebars[$key] = $value;
96
+ }
97
+ }
98
+ }
99
+
100
+ if ($requestSidebars) {
101
+ // Get the sidebars from DATABASE
102
+ $sidebar_widgets = wp_get_sidebars_widgets();
103
+ // Get global sidebars so we can retrieve the real name of the sidebar
104
+ global $wp_registered_sidebars;
105
+
106
+ // Check in each array if there's any change
107
+ foreach ($requestSidebars as $sidebarName => $widgets) {
108
+ if (isset($sidebar_widgets[$sidebarName])) {
109
+ foreach ($sidebar_widgets[$sidebarName] as $i => $widgetName) {
110
+ $index = array_search($widgetName, $widgets);
111
+ // check to see whether or not the widget has been moved
112
+ if ($i != $index) {
113
+ $sn = $sidebarName;
114
+ // Try to retrieve the real name of the sidebar, otherwise fall-back to id: $sidebarName
115
+ if ($wp_registered_sidebars && isset($wp_registered_sidebars[$sidebarName])) {
116
+ $sn = $wp_registered_sidebars[$sidebarName]['name'];
117
+ }
118
+ $this->plugin->alerts->Trigger(2071, array(
119
+ 'WidgetName' => $widgetName,
120
+ 'OldPosition' => $i+1,
121
+ 'NewPosition' => $index+1,
122
+ 'Sidebar' => $sn,
123
+ ));
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+ //#!--
132
+
133
+ if($this->_WidgetMoveData){
134
+ $wName = $this->_WidgetMoveData['widget'];
135
+ $fromSidebar = $this->_WidgetMoveData['from'];
136
+ $toSidebar = $this->_WidgetMoveData['to'];
137
+
138
+ global $wp_registered_sidebars;
139
+
140
+ if(preg_match('/^sidebar-/', $fromSidebar))
141
+ $fromSidebar = isset($wp_registered_sidebars[$fromSidebar])
142
+ ? $wp_registered_sidebars[$fromSidebar]['name']
143
+ : $fromSidebar
144
+ ;
145
+ if(preg_match('/^sidebar-/', $toSidebar))
146
+ $toSidebar = isset($wp_registered_sidebars[$toSidebar])
147
+ ? $wp_registered_sidebars[$toSidebar]['name']
148
+ : $toSidebar
149
+ ;
150
+
151
+ $this->plugin->alerts->Trigger(2045, array(
152
+ 'WidgetName' => $wName,
153
+ 'OldSidebar' => $fromSidebar,
154
+ 'NewSidebar' => $toSidebar,
155
+ ));
156
+ }
157
+ }
158
+
159
+ public function EventWidgetActivity(){
160
+ if(!isset($_POST) || !isset($_POST['widget-id']) || empty($_POST['widget-id'])){
161
+ return;
162
+ }
163
+
164
+ $postData = $_POST;
165
+ global $wp_registered_sidebars;
166
+ $canCheckSidebar = (empty($wp_registered_sidebars) ? false : true);
167
+
168
+ switch(true){
169
+
170
+ // added widget
171
+ case isset($postData['add_new']) && $postData['add_new'] == 'multi':
172
+ $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
173
+ if($canCheckSidebar && preg_match('/^sidebar-/', $sidebar)){
174
+ $sidebar = $wp_registered_sidebars[$sidebar]['name'];
175
+ }
176
+ $this->plugin->alerts->Trigger(2042, array(
177
+ 'WidgetName' => $postData['id_base'],
178
+ 'Sidebar' => $sidebar,
179
+ ));
180
+ break;
181
+
182
+ // deleted widget
183
+ case isset($postData['delete_widget']) && intval($postData['delete_widget']) == 1:
184
+ $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
185
+ if($canCheckSidebar && preg_match('/^sidebar-/',$sidebar)){
186
+ $sidebar = $wp_registered_sidebars[$sidebar]['name'];
187
+ }
188
+ $this->plugin->alerts->Trigger(2044, array(
189
+ 'WidgetName' => $postData['id_base'],
190
+ 'Sidebar' => $sidebar,
191
+ ));
192
+ break;
193
+
194
+ // modified widget
195
+ case isset($postData['id_base']) && !empty($postData['id_base']):
196
+ $wId = 0;
197
+ if(!empty($postData['multi_number'])){
198
+ $wId = intval($postData['multi_number']);
199
+ }elseif(!empty($postData['widget_number'])){
200
+ $wId = intval($postData['widget_number']);
201
+ }
202
+ if(empty($wId))return;
203
+
204
+ $wName = $postData['id_base'];
205
+ $sidebar = isset($postData['sidebar']) ? $postData['sidebar'] : null;
206
+ $wData = isset($postData["widget-$wName"][$wId])
207
+ ? $postData["widget-$wName"][$wId]
208
+ : null;
209
+
210
+ if(empty($wData))return;
211
+
212
+ // get info from db
213
+ $wdbData = get_option("widget_".$wName);
214
+ if(empty($wdbData[$wId]))return;
215
+
216
+ // transform 'on' -> 1
217
+ foreach($wData as $k => $v)if($v == 'on')$wData[$k] = 1;
218
+
219
+ // compare - checks for any changes inside widgets
220
+ $diff = array_diff_assoc($wData, $wdbData[$wId]);
221
+ $count = count($diff);
222
+ if($count > 0){
223
+ if($canCheckSidebar && preg_match("/^sidebar-/",$sidebar)){
224
+ $sidebar = $wp_registered_sidebars[$sidebar]['name'];
225
+ }
226
+ $this->plugin->alerts->Trigger(2043, array(
227
+ 'WidgetName' => $wName,
228
+ 'Sidebar' => $sidebar,
229
+ ));
230
+ }
231
+ break;
232
+
233
+ }
234
+ }
235
  }
classes/Settings.php CHANGED
@@ -1,639 +1,639 @@
1
- <?php
2
- class WSAL_Settings {
3
- /**
4
- * @var WpSecurityAuditLog
5
- */
6
- protected $_plugin;
7
- public function __construct(WpSecurityAuditLog $plugin) {
8
- $this->_plugin = $plugin;
9
- }
10
-
11
- // <editor-fold desc="Developer Options">
12
- const OPT_DEV_DATA_INSPECTOR = 'd';
13
- const OPT_DEV_PHP_ERRORS = 'p';
14
- const OPT_DEV_REQUEST_LOG = 'r';
15
- const OPT_DEV_BACKTRACE_LOG = 'b';
16
-
17
- const ERROR_CODE_INVALID_IP = 901;
18
-
19
- protected $_devoption = null;
20
- /**
21
- * @return array Array of developer options to be enabled by default.
22
- */
23
- public function GetDefaultDevOptions(){
24
- return array();
25
- }
26
- /**
27
- * Returns whether a developer option is enabled or not.
28
- * @param string $option See self::OPT_DEV_* constants.
29
- * @return boolean If option is enabled or not.
30
- */
31
- public function IsDevOptionEnabled($option){
32
- if(is_null($this->_devoption)){
33
- $this->_devoption = $this->_plugin->GetGlobalOption(
34
- 'dev-options',
35
- implode(',', $this->GetDefaultDevOptions())
36
- );
37
- $this->_devoption = explode(',', $this->_devoption);
38
- }
39
- return in_array($option, $this->_devoption);
40
- }
41
- /**
42
- * @return boolean Whether any developer option has been enabled or not.
43
- */
44
- public function IsAnyDevOptionEnabled(){
45
- return !!$this->_plugin->GetGlobalOption('dev-options', null);
46
- }
47
- /**
48
- * Sets whether a developer option is enabled or not.
49
- * @param string $option See self::OPT_DEV_* constants.
50
- * @param boolean $enabled If option should be enabled or not.
51
- */
52
- public function SetDevOptionEnabled($option, $enabled){
53
- // make sure options have been loaded
54
- $this->IsDevOptionEnabled('');
55
- // remove option if it exists
56
- while(($p = array_search($option, $this->_devoption)) !== false)
57
- unset($this->_devoption[$p]);
58
- // add option if callee wants it enabled
59
- if($enabled)
60
- $this->_devoption[] = $option;
61
- // commit option
62
- $this->_plugin->SetGlobalOption(
63
- 'dev-options',
64
- implode(',', $this->_devoption)
65
- );
66
- }
67
- /**
68
- * Remove all enabled developer options.
69
- */
70
- public function ClearDevOptions(){
71
- $this->_devoption = array();
72
- $this->_plugin->SetGlobalOption('dev-options', '');
73
- }
74
- /**
75
- * @return boolean Whether to enable data inspector or not.
76
- */
77
- public function IsDataInspectorEnabled(){
78
- return $this->IsDevOptionEnabled(self::OPT_DEV_DATA_INSPECTOR);
79
- }
80
- /**
81
- * @return boolean Whether to PHP error logging or not.
82
- */
83
- public function IsPhpErrorLoggingEnabled(){
84
- return $this->IsDevOptionEnabled(self::OPT_DEV_PHP_ERRORS);
85
- }
86
- /**
87
- * @return boolean Whether to log requests to file or not.
88
- */
89
- public function IsRequestLoggingEnabled(){
90
- return $this->IsDevOptionEnabled(self::OPT_DEV_REQUEST_LOG);
91
- }
92
- /**
93
- * @return boolean Whether to store debug backtrace for PHP alerts or not.
94
- */
95
- public function IsBacktraceLoggingEnabled(){
96
- return $this->IsDevOptionEnabled(self::OPT_DEV_BACKTRACE_LOG);
97
- }
98
-
99
- // </editor-fold>
100
- /**
101
- * @return boolean Whether dashboard widgets are enabled or not.
102
- */
103
- public function IsWidgetsEnabled(){
104
- return !$this->_plugin->GetGlobalOption('disable-widgets');
105
- }
106
- /**
107
- * @param boolean $newvalue Whether dashboard widgets are enabled or not.
108
- */
109
- public function SetWidgetsEnabled($newvalue){
110
- $this->_plugin->SetGlobalOption('disable-widgets', !$newvalue);
111
- }
112
- /**
113
- * @return boolean Whether alerts in audit log view refresh automatically or not.
114
- */
115
- public function IsRefreshAlertsEnabled(){
116
- return !$this->_plugin->GetGlobalOption('disable-refresh');
117
- }
118
- /**
119
- * @param boolean $newvalue Whether alerts in audit log view refresh automatically or not.
120
- */
121
- public function SetRefreshAlertsEnabled($newvalue){
122
- $this->_plugin->SetGlobalOption('disable-refresh', !$newvalue);
123
- }
124
- /**
125
- * @return int Maximum number of alerts to show in dashboard widget.
126
- */
127
- public function GetDashboardWidgetMaxAlerts(){
128
- return 5;
129
- }
130
-
131
- // <editor-fold desc="Pruning Settings">
132
- /**
133
- * @return int The maximum number of alerts allowable.
134
- */
135
- public function GetMaxAllowedAlerts(){
136
- return 5000;
137
- }
138
- /**
139
- * @return string The default pruning date.
140
- */
141
- public function GetDefaultPruningDate(){
142
- return '1 month';
143
- }
144
- protected $_pruning = 0;
145
- /**
146
- * @return string The current pruning date.
147
- */
148
- public function GetPruningDate(){
149
- if(!$this->_pruning){
150
- $this->_pruning = $this->_plugin->GetGlobalOption('pruning-date');
151
- if(!strtotime($this->_pruning))
152
- $this->_pruning = $this->GetDefaultPruningDate();
153
- }
154
- return $this->_pruning;
155
- }
156
- /**
157
- * @param string $newvalue The new pruning date.
158
- */
159
- public function SetPruningDate($newvalue){
160
- if(strtotime($newvalue)){
161
- $this->_plugin->SetGlobalOption('pruning-date', $newvalue);
162
- $this->_pruning = $newvalue;
163
- }
164
- }
165
- /**
166
- * @return integer Maximum number of alerts to keep.
167
- */
168
- public function GetPruningLimit(){
169
- $val = (int)$this->_plugin->GetGlobalOption('pruning-limit');
170
- return $val ? $val : $this->GetMaxAllowedAlerts();
171
- }
172
- /**
173
- * @param integer $newvalue The new maximum number of alerts.
174
- */
175
- public function SetPruningLimit($newvalue){
176
- $newvalue = max(/*min(*/(int)$newvalue/*, $this->GetMaxAllowedAlerts())*/, 1);
177
- $this->_plugin->SetGlobalOption('pruning-limit', $newvalue);
178
- }
179
- public function SetPruningDateEnabled($enabled){
180
- $this->_plugin->SetGlobalOption('pruning-date-e', $enabled);
181
- }
182
- public function SetPruningLimitEnabled($enabled){
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);
193
- }
194
- /**
195
- * @deprecated Sandbox functionality is now in an external plugin.
196
- */
197
- public function IsSandboxPageEnabled(){
198
- $plugins = $this->_plugin->licensing->plugins();
199
- return isset($plugins['wsal-sandbox-extensionphp']);
200
- }
201
- public function SetRestrictAdmins($enable){
202
- $this->_plugin->SetGlobalOption('restrict-admins', (bool)$enable);
203
- }
204
-
205
- // </editor-fold>
206
- protected $_disabled = null;
207
- public function GetDefaultDisabledAlerts(){
208
- return array(0000, 0001, 0002, 0003, 0004, 0005);
209
- }
210
- /**
211
- * @return array IDs of disabled alerts.
212
- */
213
- public function GetDisabledAlerts(){
214
- if(!$this->_disabled){
215
- $this->_disabled = implode(',', $this->GetDefaultDisabledAlerts());
216
- $this->_disabled = $this->_plugin->GetGlobalOption('disabled-alerts', $this->_disabled);
217
- $this->_disabled = ($this->_disabled == '') ? array() : explode(',', $this->_disabled);
218
- $this->_disabled = array_map('intval', $this->_disabled);
219
- }
220
- return $this->_disabled;
221
- }
222
- /**
223
- * @param array $types IDs alerts to disable.
224
- */
225
- public function SetDisabledAlerts($types){
226
- $this->_disabled = array_unique(array_map('intval', $types));
227
- $this->_plugin->SetGlobalOption('disabled-alerts', implode(',', $this->_disabled));
228
- }
229
- public function IsIncognito(){
230
- return $this->_plugin->GetGlobalOption('hide-plugin');
231
- }
232
- public function SetIncognito($enabled){
233
- return $this->_plugin->SetGlobalOption('hide-plugin', $enabled);
234
- }
235
-
236
- /**
237
- * Checking if the data will be removed.
238
- */
239
- public function IsDeleteData(){
240
- return $this->_plugin->GetGlobalOption('delete-data');
241
- }
242
-
243
- public function SetDeleteData($enabled){
244
- return $this->_plugin->SetGlobalOption('delete-data', $enabled);
245
- }
246
-
247
- // <editor-fold desc="Access Control">
248
-
249
- protected $_viewers = null;
250
- public function SetAllowedPluginViewers($usersOrRoles){
251
- $this->_viewers = $usersOrRoles;
252
- $this->_plugin->SetGlobalOption('plugin-viewers', implode(',', $this->_viewers));
253
- }
254
- public function GetAllowedPluginViewers(){
255
- if(is_null($this->_viewers)){
256
- $this->_viewers = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-viewers'))));
257
- }
258
- return $this->_viewers;
259
- }
260
- protected $_editors = null;
261
- public function SetAllowedPluginEditors($usersOrRoles){
262
- $this->_editors = $usersOrRoles;
263
- $this->_plugin->SetGlobalOption('plugin-editors', implode(',', $this->_editors));
264
- }
265
- public function GetAllowedPluginEditors(){
266
- if(is_null($this->_editors)){
267
- $this->_editors = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-editors'))));
268
- }
269
- return $this->_editors;
270
- }
271
- protected $_perpage = null;
272
- public function SetViewPerPage($newvalue){
273
- $this->_perpage = max($newvalue, 1);
274
- $this->_plugin->SetGlobalOption('items-per-page', $this->_perpage);
275
- }
276
- public function GetViewPerPage(){
277
- if(is_null($this->_perpage)){
278
- $this->_perpage = (int)$this->_plugin->GetGlobalOption('items-per-page', 10);
279
- }
280
- return $this->_perpage;
281
- }
282
- /**
283
- * @param string $action Type of action, either 'view' or 'edit'.
284
- * @return boolean If user has access or not.
285
- */
286
- public function CurrentUserCan($action){
287
- return $this->UserCan(wp_get_current_user(), $action);
288
- }
289
- /**
290
- * @return string[] List of superadmin usernames.
291
- */
292
- protected function GetSuperAdmins(){
293
- return $this->_plugin->IsMultisite() ? get_super_admins() : array();
294
- }
295
- /**
296
- * @return string[] List of admin usernames.
297
- */
298
- protected function GetAdmins(){
299
- if($this->_plugin->IsMultisite()){
300
- // see: https://gist.github.com/1508426/65785a15b8638d43a9905effb59e4d97319ef8f8
301
- global $wpdb;
302
- $cap = $wpdb->prefix."capabilities";
303
- $sql = "SELECT DISTINCT $wpdb->users.user_login"
304
- . " FROM $wpdb->users"
305
- . " INNER JOIN $wpdb->usermeta ON ($wpdb->users.ID = $wpdb->usermeta.user_id )"
306
- . " WHERE $wpdb->usermeta.meta_key = '$cap'"
307
- . " AND CAST($wpdb->usermeta.meta_value AS CHAR) LIKE '%\"administrator\"%'";
308
- return $wpdb->get_col($sql);
309
- }else{
310
- $result = array();
311
- $query = 'role=administrator&fields[]=user_login';
312
- foreach (get_users($query) as $user) $result[] = $user->user_login;
313
- return $result;
314
- }
315
- }
316
- /**
317
- * Returns access tokens for a particular action.
318
- * @param string $action Type of action.
319
- * @return string[] List of tokens (usernames, roles etc).
320
- */
321
- public function GetAccessTokens($action){
322
- $allowed = array();
323
- switch($action){
324
- case 'view':
325
- $allowed = $this->GetAllowedPluginViewers();
326
- $allowed = array_merge($allowed, $this->GetAllowedPluginEditors());
327
- if (!$this->IsRestrictAdmins()) {
328
- $allowed = array_merge($allowed, $this->GetSuperAdmins());
329
- $allowed = array_merge($allowed, $this->GetAdmins());
330
- }
331
- break;
332
- case 'edit':
333
- $allowed = $this->GetAllowedPluginEditors();
334
- if (!$this->IsRestrictAdmins()) {
335
- $allowed = array_merge($allowed, $this->_plugin->IsMultisite() ?
336
- $this->GetSuperAdmins() : $this->GetAdmins()
337
- );
338
- }
339
- break;
340
- default:
341
- throw new Exception('Unknown action "'.$action.'".');
342
- }
343
- if (!$this->IsRestrictAdmins()) {
344
- if(is_multisite()){
345
- $allowed = array_merge($allowed, get_super_admins());
346
- }else{
347
- $allowed[] = 'administrator';
348
- }
349
- }
350
- return array_unique($allowed);
351
- }
352
- /**
353
- * @param integer|WP_user $user User object to check.
354
- * @param string $action Type of action, either 'view' or 'edit'.
355
- * @return boolean If user has access or not.
356
- */
357
- public function UserCan($user, $action){
358
- if(is_int($user))$user = get_userdata($user);
359
- $allowed = $this->GetAccessTokens($action);
360
- $check = array_merge(
361
- $user->roles,
362
- array($user->user_login)
363
- );
364
- foreach($check as $item){
365
- if(in_array($item, $allowed)){
366
- return true;
367
- }
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
-
385
- // <editor-fold desc="Licensing">
386
- public function GetLicenses(){
387
- return $this->_plugin->GetGlobalOption('licenses');
388
- }
389
- public function GetLicense($name){
390
- $data = $this->GetLicenses();
391
- $name = sanitize_key(basename($name));
392
- return isset($data[$name]) ? $data[$name] : array();
393
- }
394
- public function SetLicenses($data){
395
- $this->_plugin->SetGlobalOption('licenses', $data);
396
- }
397
- public function GetLicenseKey($name){
398
- $data = $this->GetLicense($name);
399
- return isset($data['key']) ? $data['key'] : '';
400
- }
401
- public function GetLicenseStatus($name){
402
- $data = $this->GetLicense($name);
403
- return isset($data['sts']) ? $data['sts'] : '';
404
- }
405
- public function GetLicenseErrors($name){
406
- $data = $this->GetLicense($name);
407
- return isset($data['err']) ? $data['err'] : '';
408
- }
409
- public function SetLicenseKey($name, $key){
410
- $data = $this->GetLicenses();
411
- if (!isset($data[$name])) $data[$name] = array();
412
- $data[$name]['key'] = $key;
413
- $this->SetLicenses($data);
414
- }
415
- public function SetLicenseStatus($name, $status){
416
- $data = $this->GetLicenses();
417
- if (!isset($data[$name])) $data[$name] = array();
418
- $data[$name]['sts'] = $status;
419
- $this->SetLicenses($data);
420
- }
421
- public function SetLicenseErrors($name, $errors){
422
- $data = $this->GetLicenses();
423
- if (!isset($data[$name])) $data[$name] = array();
424
- $data[$name]['err'] = $errors;
425
- $this->SetLicenses($data);
426
- }
427
- public function ClearLicenses(){
428
- $this->SetLicenses(array());
429
- }
430
-
431
- // </editor-fold>
432
-
433
- // <editor-fold desc="Client IP Retrieval">
434
-
435
- public function IsMainIPFromProxy(){
436
- return $this->_plugin->GetGlobalOption('use-proxy-ip');
437
- }
438
- public function SetMainIPFromProxy($enabled){
439
- return $this->_plugin->SetGlobalOption('use-proxy-ip', $enabled);
440
- }
441
-
442
- public function IsInternalIPsFiltered(){
443
- return $this->_plugin->GetGlobalOption('filter-internal-ip');
444
- }
445
- public function SetInternalIPsFiltering($enabled){
446
- return $this->_plugin->SetGlobalOption('filter-internal-ip', $enabled);
447
- }
448
-
449
- public function GetMainClientIP(){
450
- $result = null;
451
- if ($this->IsMainIPFromProxy()) {
452
- // TODO the algorithm below just gets the first IP in the list...we might want to make this more intelligent somehow
453
- $result = $this->GetClientIPs();
454
- $result = reset($result);
455
- $result = isset($result[0]) ? $result[0] : null;
456
- } elseif (isset($_SERVER['REMOTE_ADDR'])) {
457
- $result = $this->NormalizeIP($_SERVER['REMOTE_ADDR']);
458
- if (!$this->ValidateIP($result)) {
459
- $result = "Error " . self::ERROR_CODE_INVALID_IP . ": Invalid IP Address";
460
- }
461
- }
462
- return $result;
463
- }
464
-
465
- public function GetClientIPs(){
466
- $ips = array();
467
- foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
468
- if (isset($_SERVER[$key])) {
469
- $ips[$key] = array();
470
- foreach (explode(',', $_SERVER[$key]) as $ip)
471
- if ($this->ValidateIP($ip = $this->NormalizeIP($ip)))
472
- $ips[$key][] = $ip;
473
- }
474
- }
475
- return $ips;
476
- }
477
-
478
- protected function NormalizeIP($ip){
479
- $ip = trim($ip);
480
- if(strpos($ip, ':') !== false && substr_count($ip, '.') == 3 && strpos($ip, '[') === false){
481
- // IPv4 with a port (eg: 11.22.33.44:80)
482
- $ip = explode(':', $ip);
483
- $ip = $ip[0];
484
- }else{
485
- // IPv6 with a port (eg: [::1]:80)
486
- $ip = explode(']', $ip);
487
- $ip = ltrim($ip[0], '[');
488
- }
489
- return $ip;
490
- }
491
-
492
- protected function ValidateIP($ip){
493
- $opts = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6;
494
- if ($this->IsInternalIPsFiltered()) $opts = $opts | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
495
- $filteredIP = filter_var($ip, FILTER_VALIDATE_IP, $opts);
496
- if (!$filteredIP || empty($filteredIP)) {
497
- //Regex IPV4
498
- if (preg_match("/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/", $ip)) return $ip;
499
- //Regex IPV6
500
- elseif (preg_match("/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/", $ip)) return $ip;
501
-
502
- error_log("Invalid IP in ValidateIP function: ".$ip);
503
- return false;
504
- } else {
505
- return $filteredIP;
506
- }
507
- }
508
-
509
- /**
510
- * Users excluded from monitoring
511
- */
512
- protected $_excluded_users = array();
513
- public function SetExcludedMonitoringUsers($users)
514
- {
515
- $this->_excluded_users = $users;
516
- $this->_plugin->SetGlobalOption('excluded-users', implode(',', $this->_excluded_users));
517
- }
518
- public function GetExcludedMonitoringUsers()
519
- {
520
- if(empty($this->_excluded_users)){
521
- $this->_excluded_users = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-users'))));
522
- }
523
- return $this->_excluded_users;
524
- }
525
-
526
- /**
527
- * Roles excluded from monitoring
528
- */
529
- protected $_excluded_roles = array();
530
- public function SetExcludedMonitoringRoles($roles){
531
- $this->_excluded_roles = $roles;
532
- $this->_plugin->SetGlobalOption('excluded-roles', implode(',', $this->_excluded_roles));
533
- }
534
- public function GetExcludedMonitoringRoles(){
535
- if(empty($this->_excluded_roles)){
536
- $this->_excluded_roles = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-roles'))));
537
- }
538
- return $this->_excluded_roles;
539
- }
540
-
541
- /**
542
- * Custom fields excluded from monitoring
543
- */
544
- protected $_excluded_custom = array();
545
- public function SetExcludedMonitoringCustom($custom){
546
- $this->_excluded_custom = $custom;
547
- $this->_plugin->SetGlobalOption('excluded-custom', implode(',', $this->_excluded_custom));
548
- }
549
- public function GetExcludedMonitoringCustom(){
550
- if(empty($this->_excluded_custom)){
551
- $this->_excluded_custom = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-custom'))));
552
- asort($this->_excluded_custom);
553
- }
554
- return $this->_excluded_custom;
555
- }
556
-
557
- /**
558
- * IP excluded from monitoring
559
- */
560
- protected $_excluded_ip = array();
561
- public function SetExcludedMonitoringIP($ip){
562
- $this->_excluded_ip = $ip;
563
- $this->_plugin->SetGlobalOption('excluded-ip', implode(',', $this->_excluded_ip));
564
- }
565
- public function GetExcludedMonitoringIP(){
566
- if(empty($this->_excluded_ip)){
567
- $this->_excluded_ip = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-ip'))));
568
- }
569
- return $this->_excluded_ip;
570
- }
571
-
572
- /**
573
- * Datetime format.
574
- * 24 hours or AM/PM
575
- */
576
- public function GetDatetimeFormat(){
577
- return $this->_plugin->GetGlobalOption('datetime-format', 0);
578
- }
579
-
580
- public function SetDatetimeFormat($newvalue){
581
- return $this->_plugin->SetGlobalOption('datetime-format', $newvalue);
582
- }
583
-
584
- /**
585
- * Alerts Timestamp
586
- * Server's timezone or WordPress' timezone
587
- */
588
- public function GetTimezone(){
589
- return $this->_plugin->GetGlobalOption('timezone', 0);
590
- }
591
-
592
- public function SetTimezone($newvalue){
593
- return $this->_plugin->SetGlobalOption('timezone', $newvalue);
594
- }
595
-
596
- public function GetAdapterConfig($name_field){
597
- return $this->_plugin->GetGlobalOption($name_field);
598
- }
599
-
600
- public function SetAdapterConfig($name_field, $newvalue){
601
- return $this->_plugin->SetGlobalOption($name_field, trim($newvalue));
602
- }
603
-
604
- public function GetColumns(){
605
- $columns = array('alert_code' => '1', 'type' => '1', 'date' => '1', 'username' => '1', 'source_ip' => '1', 'message' => '1');
606
- if ($this->_plugin->IsMultisite()) {
607
- $columns = array_slice($columns, 0, 5, true) + array('site' => '1') + array_slice($columns, 5, null, true);
608
- }
609
- $selected = $this->GetColumnsSelected();
610
- if (!empty($selected)) {
611
- $columns = array('alert_code' => '0', 'type' => '0', 'date' => '0', 'username' => '0', 'source_ip' => '0', 'message' => '0');
612
- if ($this->_plugin->IsMultisite()) {
613
- $columns = array_slice($columns, 0, 5, true) + array('site' => '0') + array_slice($columns, 5, null, true);
614
- }
615
- $selected = (array)json_decode($selected);
616
- $columns = array_merge($columns, $selected);
617
- return $columns;
618
- } else {
619
- return $columns;
620
- }
621
- }
622
-
623
- public function GetColumnsSelected(){
624
- return $this->_plugin->GetGlobalOption('columns');
625
- }
626
-
627
- public function SetColumns($columns){
628
- return $this->_plugin->SetGlobalOption('columns', json_encode($columns));
629
- }
630
-
631
- public function IsWPBackend(){
632
- return $this->_plugin->GetGlobalOption('wp-backend');
633
- }
634
-
635
- public function SetWPBackend($enabled){
636
- return $this->_plugin->SetGlobalOption('wp-backend', $enabled);
637
- }
638
- // </editor-fold>
639
- }
1
+ <?php
2
+ class WSAL_Settings {
3
+ /**
4
+ * @var WpSecurityAuditLog
5
+ */
6
+ protected $_plugin;
7
+ public function __construct(WpSecurityAuditLog $plugin) {
8
+ $this->_plugin = $plugin;
9
+ }
10
+
11
+ // <editor-fold desc="Developer Options">
12
+ const OPT_DEV_DATA_INSPECTOR = 'd';
13
+ const OPT_DEV_PHP_ERRORS = 'p';
14
+ const OPT_DEV_REQUEST_LOG = 'r';
15
+ const OPT_DEV_BACKTRACE_LOG = 'b';
16
+
17
+ const ERROR_CODE_INVALID_IP = 901;
18
+
19
+ protected $_devoption = null;
20
+ /**
21
+ * @return array Array of developer options to be enabled by default.
22
+ */
23
+ public function GetDefaultDevOptions(){
24
+ return array();
25
+ }
26
+ /**
27
+ * Returns whether a developer option is enabled or not.
28
+ * @param string $option See self::OPT_DEV_* constants.
29
+ * @return boolean If option is enabled or not.
30
+ */
31
+ public function IsDevOptionEnabled($option){
32
+ if(is_null($this->_devoption)){
33
+ $this->_devoption = $this->_plugin->GetGlobalOption(
34
+ 'dev-options',
35
+ implode(',', $this->GetDefaultDevOptions())
36
+ );
37
+ $this->_devoption = explode(',', $this->_devoption);
38
+ }
39
+ return in_array($option, $this->_devoption);
40
+ }
41
+ /**
42
+ * @return boolean Whether any developer option has been enabled or not.
43
+ */
44
+ public function IsAnyDevOptionEnabled(){
45
+ return !!$this->_plugin->GetGlobalOption('dev-options', null);
46
+ }
47
+ /**
48
+ * Sets whether a developer option is enabled or not.
49
+ * @param string $option See self::OPT_DEV_* constants.
50
+ * @param boolean $enabled If option should be enabled or not.
51
+ */
52
+ public function SetDevOptionEnabled($option, $enabled){
53
+ // make sure options have been loaded
54
+ $this->IsDevOptionEnabled('');
55
+ // remove option if it exists
56
+ while(($p = array_search($option, $this->_devoption)) !== false)
57
+ unset($this->_devoption[$p]);
58
+ // add option if callee wants it enabled
59
+ if($enabled)
60
+ $this->_devoption[] = $option;
61
+ // commit option
62
+ $this->_plugin->SetGlobalOption(
63
+ 'dev-options',
64
+ implode(',', $this->_devoption)
65
+ );
66
+ }
67
+ /**
68
+ * Remove all enabled developer options.
69
+ */
70
+ public function ClearDevOptions(){
71
+ $this->_devoption = array();
72
+ $this->_plugin->SetGlobalOption('dev-options', '');
73
+ }
74
+ /**
75
+ * @return boolean Whether to enable data inspector or not.
76
+ */
77
+ public function IsDataInspectorEnabled(){
78
+ return $this->IsDevOptionEnabled(self::OPT_DEV_DATA_INSPECTOR);
79
+ }
80
+ /**
81
+ * @return boolean Whether to PHP error logging or not.
82
+ */
83
+ public function IsPhpErrorLoggingEnabled(){
84
+ return $this->IsDevOptionEnabled(self::OPT_DEV_PHP_ERRORS);
85
+ }
86
+ /**
87
+ * @return boolean Whether to log requests to file or not.
88
+ */
89
+ public function IsRequestLoggingEnabled(){
90
+ return $this->IsDevOptionEnabled(self::OPT_DEV_REQUEST_LOG);
91
+ }
92
+ /**
93
+ * @return boolean Whether to store debug backtrace for PHP alerts or not.
94
+ */
95
+ public function IsBacktraceLoggingEnabled(){
96
+ return $this->IsDevOptionEnabled(self::OPT_DEV_BACKTRACE_LOG);
97
+ }
98
+
99
+ // </editor-fold>
100
+ /**
101
+ * @return boolean Whether dashboard widgets are enabled or not.
102
+ */
103
+ public function IsWidgetsEnabled(){
104
+ return !$this->_plugin->GetGlobalOption('disable-widgets');
105
+ }
106
+ /**
107
+ * @param boolean $newvalue Whether dashboard widgets are enabled or not.
108
+ */
109
+ public function SetWidgetsEnabled($newvalue){
110
+ $this->_plugin->SetGlobalOption('disable-widgets', !$newvalue);
111
+ }
112
+ /**
113
+ * @return boolean Whether alerts in audit log view refresh automatically or not.
114
+ */
115
+ public function IsRefreshAlertsEnabled(){
116
+ return !$this->_plugin->GetGlobalOption('disable-refresh');
117
+ }
118
+ /**
119
+ * @param boolean $newvalue Whether alerts in audit log view refresh automatically or not.
120
+ */
121
+ public function SetRefreshAlertsEnabled($newvalue){
122
+ $this->_plugin->SetGlobalOption('disable-refresh', !$newvalue);
123
+ }
124
+ /**
125
+ * @return int Maximum number of alerts to show in dashboard widget.
126
+ */
127
+ public function GetDashboardWidgetMaxAlerts(){
128
+ return 5;
129
+ }
130
+
131
+ // <editor-fold desc="Pruning Settings">
132
+ /**
133
+ * @return int The maximum number of alerts allowable.
134
+ */
135
+ public function GetMaxAllowedAlerts(){
136
+ return 5000;
137
+ }
138
+ /**
139
+ * @return string The default pruning date.
140
+ */
141
+ public function GetDefaultPruningDate(){
142
+ return '1 month';
143
+ }
144
+ protected $_pruning = 0;
145
+ /**
146
+ * @return string The current pruning date.
147
+ */
148
+ public function GetPruningDate(){
149
+ if(!$this->_pruning){
150
+ $this->_pruning = $this->_plugin->GetGlobalOption('pruning-date');
151
+ if(!strtotime($this->_pruning))
152
+ $this->_pruning = $this->GetDefaultPruningDate();
153
+ }
154
+ return $this->_pruning;
155
+ }
156
+ /**
157
+ * @param string $newvalue The new pruning date.
158
+ */
159
+ public function SetPruningDate($newvalue){
160
+ if(strtotime($newvalue)){
161
+ $this->_plugin->SetGlobalOption('pruning-date', $newvalue);
162
+ $this->_pruning = $newvalue;
163
+ }
164
+ }
165
+ /**
166
+ * @return integer Maximum number of alerts to keep.
167
+ */
168
+ public function GetPruningLimit(){
169
+ $val = (int)$this->_plugin->GetGlobalOption('pruning-limit');
170
+ return $val ? $val : $this->GetMaxAllowedAlerts();
171
+ }
172
+ /**
173
+ * @param integer $newvalue The new maximum number of alerts.
174
+ */
175
+ public function SetPruningLimit($newvalue){
176
+ $newvalue = max(/*min(*/(int)$newvalue/*, $this->GetMaxAllowedAlerts())*/, 1);
177
+ $this->_plugin->SetGlobalOption('pruning-limit', $newvalue);
178
+ }
179
+ public function SetPruningDateEnabled($enabled){
180
+ $this->_plugin->SetGlobalOption('pruning-date-e', $enabled);
181
+ }
182
+ public function SetPruningLimitEnabled($enabled){
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);
193
+ }
194
+ /**
195
+ * @deprecated Sandbox functionality is now in an external plugin.
196
+ */
197
+ public function IsSandboxPageEnabled(){
198
+ $plugins = $this->_plugin->licensing->plugins();
199
+ return isset($plugins['wsal-sandbox-extensionphp']);
200
+ }
201
+ public function SetRestrictAdmins($enable){
202
+ $this->_plugin->SetGlobalOption('restrict-admins', (bool)$enable);
203
+ }
204
+
205
+ // </editor-fold>
206
+ protected $_disabled = null;
207
+ public function GetDefaultDisabledAlerts(){
208
+ return array(0000, 0001, 0002, 0003, 0004, 0005);
209
+ }
210
+ /**
211
+ * @return array IDs of disabled alerts.
212
+ */
213
+ public function GetDisabledAlerts(){
214
+ if(!$this->_disabled){
215
+ $this->_disabled = implode(',', $this->GetDefaultDisabledAlerts());
216
+ $this->_disabled = $this->_plugin->GetGlobalOption('disabled-alerts', $this->_disabled);
217
+ $this->_disabled = ($this->_disabled == '') ? array() : explode(',', $this->_disabled);
218
+ $this->_disabled = array_map('intval', $this->_disabled);
219
+ }
220
+ return $this->_disabled;
221
+ }
222
+ /**
223
+ * @param array $types IDs alerts to disable.
224
+ */
225
+ public function SetDisabledAlerts($types){
226
+ $this->_disabled = array_unique(array_map('intval', $types));
227
+ $this->_plugin->SetGlobalOption('disabled-alerts', implode(',', $this->_disabled));
228
+ }
229
+ public function IsIncognito(){
230
+ return $this->_plugin->GetGlobalOption('hide-plugin');
231
+ }
232
+ public function SetIncognito($enabled){
233
+ return $this->_plugin->SetGlobalOption('hide-plugin', $enabled);
234
+ }
235
+
236
+ /**
237
+ * Checking if the data will be removed.
238
+ */
239
+ public function IsDeleteData(){
240
+ return $this->_plugin->GetGlobalOption('delete-data');
241
+ }
242
+
243
+ public function SetDeleteData($enabled){
244
+ return $this->_plugin->SetGlobalOption('delete-data', $enabled);
245
+ }
246
+
247
+ // <editor-fold desc="Access Control">
248
+
249
+ protected $_viewers = null;
250
+ public function SetAllowedPluginViewers($usersOrRoles){
251
+ $this->_viewers = $usersOrRoles;
252
+ $this->_plugin->SetGlobalOption('plugin-viewers', implode(',', $this->_viewers));
253
+ }
254
+ public function GetAllowedPluginViewers(){
255
+ if(is_null($this->_viewers)){
256
+ $this->_viewers = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-viewers'))));
257
+ }
258
+ return $this->_viewers;
259
+ }
260
+ protected $_editors = null;
261
+ public function SetAllowedPluginEditors($usersOrRoles){
262
+ $this->_editors = $usersOrRoles;
263
+ $this->_plugin->SetGlobalOption('plugin-editors', implode(',', $this->_editors));
264
+ }
265
+ public function GetAllowedPluginEditors(){
266
+ if(is_null($this->_editors)){
267
+ $this->_editors = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('plugin-editors'))));
268
+ }
269
+ return $this->_editors;
270
+ }
271
+ protected $_perpage = null;
272
+ public function SetViewPerPage($newvalue){
273
+ $this->_perpage = max($newvalue, 1);
274
+ $this->_plugin->SetGlobalOption('items-per-page', $this->_perpage);
275
+ }
276
+ public function GetViewPerPage(){
277
+ if(is_null($this->_perpage)){
278
+ $this->_perpage = (int)$this->_plugin->GetGlobalOption('items-per-page', 10);
279
+ }
280
+ return $this->_perpage;
281
+ }
282
+ /**
283
+ * @param string $action Type of action, either 'view' or 'edit'.
284
+ * @return boolean If user has access or not.
285
+ */
286
+ public function CurrentUserCan($action){
287
+ return $this->UserCan(wp_get_current_user(), $action);
288
+ }
289
+ /**
290
+ * @return string[] List of superadmin usernames.
291
+ */
292
+ protected function GetSuperAdmins(){
293
+ return $this->_plugin->IsMultisite() ? get_super_admins() : array();
294
+ }
295
+ /**
296
+ * @return string[] List of admin usernames.
297
+ */
298
+ protected function GetAdmins(){
299
+ if($this->_plugin->IsMultisite()){
300
+ // see: https://gist.github.com/1508426/65785a15b8638d43a9905effb59e4d97319ef8f8
301
+ global $wpdb;
302
+ $cap = $wpdb->prefix."capabilities";
303
+ $sql = "SELECT DISTINCT $wpdb->users.user_login"
304
+ . " FROM $wpdb->users"
305
+ . " INNER JOIN $wpdb->usermeta ON ($wpdb->users.ID = $wpdb->usermeta.user_id )"
306
+ . " WHERE $wpdb->usermeta.meta_key = '$cap'"
307
+ . " AND CAST($wpdb->usermeta.meta_value AS CHAR) LIKE '%\"administrator\"%'";
308
+ return $wpdb->get_col($sql);
309
+ }else{
310
+ $result = array();
311
+ $query = 'role=administrator&fields[]=user_login';
312
+ foreach (get_users($query) as $user) $result[] = $user->user_login;
313
+ return $result;
314
+ }
315
+ }
316
+ /**
317
+ * Returns access tokens for a particular action.
318
+ * @param string $action Type of action.
319
+ * @return string[] List of tokens (usernames, roles etc).
320
+ */
321
+ public function GetAccessTokens($action){
322
+ $allowed = array();
323
+ switch($action){
324
+ case 'view':
325
+ $allowed = $this->GetAllowedPluginViewers();
326
+ $allowed = array_merge($allowed, $this->GetAllowedPluginEditors());
327
+ if (!$this->IsRestrictAdmins()) {
328
+ $allowed = array_merge($allowed, $this->GetSuperAdmins());
329
+ $allowed = array_merge($allowed, $this->GetAdmins());
330
+ }
331
+ break;
332
+ case 'edit':
333
+ $allowed = $this->GetAllowedPluginEditors();
334
+ if (!$this->IsRestrictAdmins()) {
335
+ $allowed = array_merge($allowed, $this->_plugin->IsMultisite() ?
336
+ $this->GetSuperAdmins() : $this->GetAdmins()
337
+ );
338
+ }
339
+ break;
340
+ default:
341
+ throw new Exception('Unknown action "'.$action.'".');
342
+ }
343
+ if (!$this->IsRestrictAdmins()) {
344
+ if(is_multisite()){
345
+ $allowed = array_merge($allowed, get_super_admins());
346
+ }else{
347
+ $allowed[] = 'administrator';
348
+ }
349
+ }
350
+ return array_unique($allowed);
351
+ }
352
+ /**
353
+ * @param integer|WP_user $user User object to check.
354
+ * @param string $action Type of action, either 'view' or 'edit'.
355
+ * @return boolean If user has access or not.
356
+ */
357
+ public function UserCan($user, $action){
358
+ if(is_int($user))$user = get_userdata($user);
359
+ $allowed = $this->GetAccessTokens($action);
360
+ $check = array_merge(
361
+ $user->roles,
362
+ array($user->user_login)
363
+ );
364
+ foreach($check as $item){
365
+ if(in_array($item, $allowed)){
366
+ return true;
367
+ }
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
+
385
+ // <editor-fold desc="Licensing">
386
+ public function GetLicenses(){
387
+ return $this->_plugin->GetGlobalOption('licenses');
388
+ }
389
+ public function GetLicense($name){
390
+ $data = $this->GetLicenses();
391
+ $name = sanitize_key(basename($name));
392
+ return isset($data[$name]) ? $data[$name] : array();
393
+ }
394
+ public function SetLicenses($data){
395
+ $this->_plugin->SetGlobalOption('licenses', $data);
396
+ }
397
+ public function GetLicenseKey($name){
398
+ $data = $this->GetLicense($name);
399
+ return isset($data['key']) ? $data['key'] : '';
400
+ }
401
+ public function GetLicenseStatus($name){
402
+ $data = $this->GetLicense($name);
403
+ return isset($data['sts']) ? $data['sts'] : '';
404
+ }
405
+ public function GetLicenseErrors($name){
406
+ $data = $this->GetLicense($name);
407
+ return isset($data['err']) ? $data['err'] : '';
408
+ }
409
+ public function SetLicenseKey($name, $key){
410
+ $data = $this->GetLicenses();
411
+ if (!isset($data[$name])) $data[$name] = array();
412
+ $data[$name]['key'] = $key;
413
+ $this->SetLicenses($data);
414
+ }
415
+ public function SetLicenseStatus($name, $status){
416
+ $data = $this->GetLicenses();
417
+ if (!isset($data[$name])) $data[$name] = array();
418
+ $data[$name]['sts'] = $status;
419
+ $this->SetLicenses($data);
420
+ }
421
+ public function SetLicenseErrors($name, $errors){
422
+ $data = $this->GetLicenses();
423
+ if (!isset($data[$name])) $data[$name] = array();
424
+ $data[$name]['err'] = $errors;
425
+ $this->SetLicenses($data);
426
+ }
427
+ public function ClearLicenses(){
428
+ $this->SetLicenses(array());
429
+ }
430
+
431
+ // </editor-fold>
432
+
433
+ // <editor-fold desc="Client IP Retrieval">
434
+
435
+ public function IsMainIPFromProxy(){
436
+ return $this->_plugin->GetGlobalOption('use-proxy-ip');
437
+ }
438
+ public function SetMainIPFromProxy($enabled){
439
+ return $this->_plugin->SetGlobalOption('use-proxy-ip', $enabled);
440
+ }
441
+
442
+ public function IsInternalIPsFiltered(){
443
+ return $this->_plugin->GetGlobalOption('filter-internal-ip');
444
+ }
445
+ public function SetInternalIPsFiltering($enabled){
446
+ return $this->_plugin->SetGlobalOption('filter-internal-ip', $enabled);
447
+ }
448
+
449
+ public function GetMainClientIP(){
450
+ $result = null;
451
+ if ($this->IsMainIPFromProxy()) {
452
+ // TODO the algorithm below just gets the first IP in the list...we might want to make this more intelligent somehow
453
+ $result = $this->GetClientIPs();
454
+ $result = reset($result);
455
+ $result = isset($result[0]) ? $result[0] : null;
456
+ } elseif (isset($_SERVER['REMOTE_ADDR'])) {
457
+ $result = $this->NormalizeIP($_SERVER['REMOTE_ADDR']);
458
+ if (!$this->ValidateIP($result)) {
459
+ $result = "Error " . self::ERROR_CODE_INVALID_IP . ": Invalid IP Address";
460
+ }
461
+ }
462
+ return $result;
463
+ }
464
+
465
+ public function GetClientIPs(){
466
+ $ips = array();
467
+ foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
468
+ if (isset($_SERVER[$key])) {
469
+ $ips[$key] = array();
470
+ foreach (explode(',', $_SERVER[$key]) as $ip)
471
+ if ($this->ValidateIP($ip = $this->NormalizeIP($ip)))
472
+ $ips[$key][] = $ip;
473
+ }
474
+ }
475
+ return $ips;
476
+ }
477
+
478
+ protected function NormalizeIP($ip){
479
+ $ip = trim($ip);
480
+ if(strpos($ip, ':') !== false && substr_count($ip, '.') == 3 && strpos($ip, '[') === false){
481
+ // IPv4 with a port (eg: 11.22.33.44:80)
482
+ $ip = explode(':', $ip);
483
+ $ip = $ip[0];
484
+ }else{
485
+ // IPv6 with a port (eg: [::1]:80)
486
+ $ip = explode(']', $ip);
487
+ $ip = ltrim($ip[0], '[');
488
+ }
489
+ return $ip;
490
+ }
491
+
492
+ protected function ValidateIP($ip){
493
+ $opts = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6;
494
+ if ($this->IsInternalIPsFiltered()) $opts = $opts | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
495
+ $filteredIP = filter_var($ip, FILTER_VALIDATE_IP, $opts);
496
+ if (!$filteredIP || empty($filteredIP)) {
497
+ //Regex IPV4
498
+ if (preg_match("/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/", $ip)) return $ip;
499
+ //Regex IPV6
500
+ elseif (preg_match("/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/", $ip)) return $ip;
501
+
502
+ error_log("Invalid IP in ValidateIP function: ".$ip);
503
+ return false;
504
+ } else {
505
+ return $filteredIP;
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Users excluded from monitoring
511
+ */
512
+ protected $_excluded_users = array();
513
+ public function SetExcludedMonitoringUsers($users)
514
+ {
515
+ $this->_excluded_users = $users;
516
+ $this->_plugin->SetGlobalOption('excluded-users', implode(',', $this->_excluded_users));
517
+ }
518
+ public function GetExcludedMonitoringUsers()
519
+ {
520
+ if(empty($this->_excluded_users)){
521
+ $this->_excluded_users = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-users'))));
522
+ }
523
+ return $this->_excluded_users;
524
+ }
525
+
526
+ /**
527
+ * Roles excluded from monitoring
528
+ */
529
+ protected $_excluded_roles = array();
530
+ public function SetExcludedMonitoringRoles($roles){
531
+ $this->_excluded_roles = $roles;
532
+ $this->_plugin->SetGlobalOption('excluded-roles', implode(',', $this->_excluded_roles));
533
+ }
534
+ public function GetExcludedMonitoringRoles(){
535
+ if(empty($this->_excluded_roles)){
536
+ $this->_excluded_roles = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-roles'))));
537
+ }
538
+ return $this->_excluded_roles;
539
+ }
540
+
541
+ /**
542
+ * Custom fields excluded from monitoring
543
+ */
544
+ protected $_excluded_custom = array();
545
+ public function SetExcludedMonitoringCustom($custom){
546
+ $this->_excluded_custom = $custom;
547
+ $this->_plugin->SetGlobalOption('excluded-custom', implode(',', $this->_excluded_custom));
548
+ }
549
+ public function GetExcludedMonitoringCustom(){
550
+ if(empty($this->_excluded_custom)){
551
+ $this->_excluded_custom = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-custom'))));
552
+ asort($this->_excluded_custom);
553
+ }
554
+ return $this->_excluded_custom;
555
+ }
556
+
557
+ /**
558
+ * IP excluded from monitoring
559
+ */
560
+ protected $_excluded_ip = array();
561
+ public function SetExcludedMonitoringIP($ip){
562
+ $this->_excluded_ip = $ip;
563
+ $this->_plugin->SetGlobalOption('excluded-ip', implode(',', $this->_excluded_ip));
564
+ }
565
+ public function GetExcludedMonitoringIP(){
566
+ if(empty($this->_excluded_ip)){
567
+ $this->_excluded_ip = array_unique(array_filter(explode(',', $this->_plugin->GetGlobalOption('excluded-ip'))));
568
+ }
569
+ return $this->_excluded_ip;
570
+ }
571
+
572
+ /**
573
+ * Datetime format.
574
+ * 24 hours or AM/PM
575
+ */
576
+ public function GetDatetimeFormat(){
577
+ return $this->_plugin->GetGlobalOption('datetime-format', 0);
578
+ }
579
+
580
+ public function SetDatetimeFormat($newvalue){
581
+ return $this->_plugin->SetGlobalOption('datetime-format', $newvalue);
582
+ }
583
+
584
+ /**
585
+ * Alerts Timestamp
586
+ * Server's timezone or WordPress' timezone
587
+ */
588
+ public function GetTimezone(){
589
+ return $this->_plugin->GetGlobalOption('timezone', 0);
590
+ }
591
+
592
+ public function SetTimezone($newvalue){
593
+ return $this->_plugin->SetGlobalOption('timezone', $newvalue);
594
+ }
595
+
596
+ public function GetAdapterConfig($name_field){
597
+ return $this->_plugin->GetGlobalOption($name_field);
598
+ }
599
+
600
+ public function SetAdapterConfig($name_field, $newvalue){
601
+ return $this->_plugin->SetGlobalOption($name_field, trim($newvalue));
602
+ }
603
+
604
+ public function GetColumns(){
605
+ $columns = array('alert_code' => '1', 'type' => '1', 'date' => '1', 'username' => '1', 'source_ip' => '1', 'message' => '1');
606
+ if ($this->_plugin->IsMultisite()) {
607
+ $columns = array_slice($columns, 0, 5, true) + array('site' => '1') + array_slice($columns, 5, null, true);
608
+ }
609
+ $selected = $this->GetColumnsSelected();
610
+ if (!empty($selected)) {
611
+ $columns = array('alert_code' => '0', 'type' => '0', 'date' => '0', 'username' => '0', 'source_ip' => '0', 'message' => '0');
612
+ if ($this->_plugin->IsMultisite()) {
613
+ $columns = array_slice($columns, 0, 5, true) + array('site' => '0') + array_slice($columns, 5, null, true);
614
+ }
615
+ $selected = (array)json_decode($selected);
616
+ $columns = array_merge($columns, $selected);
617
+ return $columns;
618
+ } else {
619
+ return $columns;
620
+ }
621
+ }
622
+
623
+ public function GetColumnsSelected(){
624
+ return $this->_plugin->GetGlobalOption('columns');
625
+ }
626
+
627
+ public function SetColumns($columns){
628
+ return $this->_plugin->SetGlobalOption('columns', json_encode($columns));
629
+ }
630
+
631
+ public function IsWPBackend(){
632
+ return $this->_plugin->GetGlobalOption('wp-backend');
633
+ }
634
+
635
+ public function SetWPBackend($enabled){
636
+ return $this->_plugin->SetGlobalOption('wp-backend', $enabled);
637
+ }
638
+ // </editor-fold>
639
+ }
classes/SimpleProfiler.php CHANGED
@@ -1,44 +1,44 @@
1
- <?php
2
-
3
- class WSAL_SimpleProfiler {
4
- protected $_items = array();
5
-
6
- public function Start($name) {
7
- $item = new WSAL_SimpleProfiler_Item($name);
8
- $this->_items[] = $item;
9
- return $item;
10
- }
11
-
12
- public function AsComment(){
13
- echo '<!-- ' . PHP_EOL;
14
- foreach($this->_items as $item){
15
- echo ' ' . $item . PHP_EOL;
16
- }
17
- echo '-->' . PHP_EOL;
18
- }
19
-
20
- public function GetItems(){
21
- return $this->_items;
22
- }
23
- }
24
-
25
- class WSAL_SimpleProfiler_Item{
26
- public function __construct($name){
27
- $this->name = $name;
28
- $this->t_bgn = microtime(true);
29
- $this->m_bgn = memory_get_usage();
30
- }
31
-
32
- public function Stop(){
33
- $this->t_end = microtime(true);
34
- $this->m_end = memory_get_usage();
35
- }
36
-
37
- public function __toString(){
38
- $t_diff = $this->t_end - $this->t_bgn;
39
- $m_diff = $this->m_end - $this->m_bgn;
40
- return number_format($t_diff, 6) . 's '
41
- . str_pad(number_format($m_diff, 0), 12, ' ', STR_PAD_LEFT) . 'b '
42
- . $this->name;
43
- }
44
  }
1
+ <?php
2
+
3
+ class WSAL_SimpleProfiler {
4
+ protected $_items = array();
5
+
6
+ public function Start($name) {
7
+ $item = new WSAL_SimpleProfiler_Item($name);
8
+ $this->_items[] = $item;
9
+ return $item;
10
+ }
11
+
12
+ public function AsComment(){
13
+ echo '<!-- ' . PHP_EOL;
14
+ foreach($this->_items as $item){
15
+ echo ' ' . $item . PHP_EOL;
16
+ }
17
+ echo '-->' . PHP_EOL;
18
+ }
19
+
20
+ public function GetItems(){
21
+ return $this->_items;
22
+ }
23
+ }
24
+
25
+ class WSAL_SimpleProfiler_Item{
26
+ public function __construct($name){
27
+ $this->name = $name;
28
+ $this->t_bgn = microtime(true);
29
+ $this->m_bgn = memory_get_usage();
30
+ }
31
+
32
+ public function Stop(){
33
+ $this->t_end = microtime(true);
34
+ $this->m_end = memory_get_usage();
35
+ }
36
+
37
+ public function __toString(){
38
+ $t_diff = $this->t_end - $this->t_bgn;
39
+ $m_diff = $this->m_end - $this->m_bgn;
40
+ return number_format($t_diff, 6) . 's '
41
+ . str_pad(number_format($m_diff, 0), 12, ' ', STR_PAD_LEFT) . 'b '
42
+ . $this->name;
43
+ }
44
  }
classes/ViewManager.php CHANGED
@@ -1,215 +1,215 @@
1
- <?php
2
-
3
- class WSAL_ViewManager {
4
-
5
- /**
6
- * @var WSAL_AbstractView[]
7
- */
8
- public $views = array();
9
-
10
- /**
11
- * @var WpSecurityAuditLog
12
- */
13
- protected $_plugin;
14
-
15
- public function __construct(WpSecurityAuditLog $plugin){
16
- $this->_plugin = $plugin;
17
-
18
- // load views
19
- foreach(glob(dirname(__FILE__) . '/Views/*.php') as $file)
20
- $this->AddFromFile($file);
21
-
22
- // add menus
23
- add_action('admin_menu', array($this, 'AddAdminMenus'));
24
- add_action('network_admin_menu', array($this, 'AddAdminMenus'));
25
-
26
- // add plugin shortcut links
27
- add_filter('plugin_action_links_' . $plugin->GetBaseName(), array($this, 'AddPluginShortcuts'));
28
-
29
- // render header
30
- add_action('admin_enqueue_scripts', array($this, 'RenderViewHeader'));
31
-
32
- // render footer
33
- add_action('admin_footer', array($this, 'RenderViewFooter'));
34
- }
35
-
36
- /**
37
- * Add new view from file inside autoloader path.
38
- * @param string $file Path to file.
39
- */
40
- public function AddFromFile($file){
41
- $this->AddFromClass($this->_plugin->GetClassFileClassName($file));
42
- }
43
-
44
- /**
45
- * Add new view given class name.
46
- * @param string $class Class name.
47
- */
48
- public function AddFromClass($class){
49
- $this->AddInstance(new $class($this->_plugin));
50
- }
51
-
52
- /**
53
- * Add newly created view to list.
54
- * @param WSAL_AbstractView $view The new view.
55
- */
56
- public function AddInstance(WSAL_AbstractView $view){
57
- $this->views[] = $view;
58
- }
59
-
60
- /**
61
- * Order views by their declared weight.
62
- */
63
- public function ReorderViews(){
64
- usort($this->views, array($this, 'OrderByWeight'));
65
- }
66
-
67
- /**
68
- * @internal This has to be public for PHP to call it.
69
- * @param WSAL_AbstractView $a
70
- * @param WSAL_AbstractView $b
71
- * @return int
72
- */
73
- public function OrderByWeight(WSAL_AbstractView $a, WSAL_AbstractView $b){
74
- $wa = $a->GetWeight();
75
- $wb = $b->GetWeight();
76
- switch(true){
77
- case $wa < $wb:
78
- return -1;
79
- case $wa > $wb:
80
- return 1;
81
- default:
82
- return 0;
83
- }
84
- }
85
-
86
- /**
87
- * Wordpress Action
88
- */
89
- public function AddAdminMenus(){
90
- $this->ReorderViews();
91
-
92
- if($this->_plugin->settings->CurrentUserCan('view') && count($this->views)){
93
- // add main menu
94
- $this->views[0]->hook_suffix = add_menu_page(
95
- 'WP Security Audit Log',
96
- 'Audit Log',
97
- 'read', // no capability requirement
98
- $this->views[0]->GetSafeViewName(),
99
- array($this, 'RenderViewBody'),
100
- $this->views[0]->GetIcon(),
101
- '2.5' // right after dashboard
102
- );
103
-
104
- // add menu items
105
- foreach($this->views as $view){
106
- if($view->IsAccessible()){
107
- $view->hook_suffix = add_submenu_page(
108
- $view->IsVisible() ? $this->views[0]->GetSafeViewName() : null,
109
- $view->GetTitle(),
110
- $view->GetName(),
111
- 'read', // no capability requirement
112
- $view->GetSafeViewName(),
113
- array($this, 'RenderViewBody'),
114
- $view->GetIcon()
115
- );
116
- }
117
- }
118
- }
119
- }
120
-
121
- /**
122
- * Wordpress Filter
123
- */
124
- public function AddPluginShortcuts($old_links){
125
- $this->ReorderViews();
126
-
127
- $new_links = array();
128
- foreach($this->views as $view){
129
- if($view->HasPluginShortcutLink()){
130
- $new_links[] =
131
- '<a href="'
132
- . admin_url('admin.php?page='
133
- . $view->GetSafeViewName()
134
- ) . '">'
135
- . $view->GetName()
136
- . '</a>';
137
- }
138
- }
139
- return array_merge($new_links, $old_links);
140
- }
141
-
142
- /**
143
- * @return int Returns page id of current page (or false on error).
144
- */
145
- protected function GetBackendPageIndex(){
146
- if(isset($_REQUEST['page']))
147
- foreach($this->views as $i => $view)
148
- if($_REQUEST['page'] == $view->GetSafeViewName())
149
- return $i;
150
- return false;
151
- }
152
-
153
- /**
154
- *
155
- * @var WSAL_AbstractView|null
156
- */
157
- protected $_active_view = false;
158
-
159
- /**
160
- * @return WSAL_AbstractView|null Returns the current active view or null if none.
161
- */
162
- public function GetActiveView(){
163
- if($this->_active_view === false){
164
- $this->_active_view = null;
165
-
166
- if(isset($_REQUEST['page']))
167
- foreach($this->views as $view)
168
- if($_REQUEST['page'] == $view->GetSafeViewName())
169
- $this->_active_view = $view;
170
-
171
- if($this->_active_view)
172
- $this->_active_view->is_active = true;
173
- }
174
- return $this->_active_view;
175
- }
176
-
177
- /**
178
- * Render header of the current view.
179
- */
180
- public function RenderViewHeader(){
181
- if (!!($view = $this->GetActiveView())) $view->Header();
182
- }
183
-
184
- /**
185
- * Render footer of the current view.
186
- */
187
- public function RenderViewFooter(){
188
- if (!!($view = $this->GetActiveView())) $view->Footer();
189
- }
190
-
191
- /**
192
- * Render content of the current view.
193
- */
194
- public function RenderViewBody(){
195
- $view = $this->GetActiveView();
196
- ?><div class="wrap"><?php
197
- $view->RenderIcon();
198
- $view->RenderTitle();
199
- $view->RenderContent();
200
- ?></div><?php
201
- }
202
-
203
- /**
204
- * Returns view instance corresponding to its class name.
205
- * @param string $className View class name.
206
- * @return WSAL_AbstractView The view or false on failure.
207
- */
208
- public function FindByClassName($className){
209
- foreach($this->views as $view)
210
- if($view instanceof $className)
211
- return $view;
212
- return false;
213
- }
214
-
215
  }
1
+ <?php
2
+
3
+ class WSAL_ViewManager {
4
+
5
+ /**
6
+ * @var WSAL_AbstractView[]
7
+ */
8
+ public $views = array();
9
+
10
+ /**
11
+ * @var WpSecurityAuditLog
12
+ */
13
+ protected $_plugin;
14
+
15
+ public function __construct(WpSecurityAuditLog $plugin){
16
+ $this->_plugin = $plugin;
17
+
18
+ // load views
19
+ foreach(glob(dirname(__FILE__) . '/Views/*.php') as $file)
20
+ $this->AddFromFile($file);
21
+
22
+ // add menus
23
+ add_action('admin_menu', array($this, 'AddAdminMenus'));
24
+ add_action('network_admin_menu', array($this, 'AddAdminMenus'));
25
+
26
+ // add plugin shortcut links
27
+ add_filter('plugin_action_links_' . $plugin->GetBaseName(), array($this, 'AddPluginShortcuts'));
28
+
29
+ // render header
30
+ add_action('admin_enqueue_scripts', array($this, 'RenderViewHeader'));
31
+
32
+ // render footer
33
+ add_action('admin_footer', array($this, 'RenderViewFooter'));
34
+ }
35
+
36
+ /**
37
+ * Add new view from file inside autoloader path.
38
+ * @param string $file Path to file.
39
+ */
40
+ public function AddFromFile($file){
41
+ $this->AddFromClass($this->_plugin->GetClassFileClassName($file));
42
+ }
43
+
44
+ /**
45
+ * Add new view given class name.
46
+ * @param string $class Class name.
47
+ */
48
+ public function AddFromClass($class){
49
+ $this->AddInstance(new $class($this->_plugin));
50
+ }
51
+
52
+ /**
53
+ * Add newly created view to list.
54
+ * @param WSAL_AbstractView $view The new view.
55
+ */
56
+ public function AddInstance(WSAL_AbstractView $view){
57
+ $this->views[] = $view;
58
+ }
59
+
60
+ /**
61
+ * Order views by their declared weight.
62
+ */
63
+ public function ReorderViews(){
64
+ usort($this->views, array($this, 'OrderByWeight'));
65
+ }
66
+
67
+ /**
68
+ * @internal This has to be public for PHP to call it.
69
+ * @param WSAL_AbstractView $a
70
+ * @param WSAL_AbstractView $b
71
+ * @return int
72
+ */
73
+ public function OrderByWeight(WSAL_AbstractView $a, WSAL_AbstractView $b){
74
+ $wa = $a->GetWeight();
75
+ $wb = $b->GetWeight();
76
+ switch(true){
77
+ case $wa < $wb:
78
+ return -1;
79
+ case $wa > $wb:
80
+ return 1;
81
+ default:
82
+ return 0;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Wordpress Action
88
+ */
89
+ public function AddAdminMenus(){
90
+ $this->ReorderViews();
91
+
92
+ if($this->_plugin->settings->CurrentUserCan('view') && count($this->views)){
93
+ // add main menu
94
+ $this->views[0]->hook_suffix = add_menu_page(
95
+ 'WP Security Audit Log',
96
+ 'Audit Log',
97
+ 'read', // no capability requirement
98
+ $this->views[0]->GetSafeViewName(),
99
+ array($this, 'RenderViewBody'),
100
+ $this->views[0]->GetIcon(),
101
+ '2.5' // right after dashboard
102
+ );
103
+
104
+ // add menu items
105
+ foreach($this->views as $view){
106
+ if($view->IsAccessible()){
107
+ $view->hook_suffix = add_submenu_page(
108
+ $view->IsVisible() ? $this->views[0]->GetSafeViewName() : null,
109
+ $view->GetTitle(),
110
+ $view->GetName(),
111
+ 'read', // no capability requirement
112
+ $view->GetSafeViewName(),
113
+ array($this, 'RenderViewBody'),
114
+ $view->GetIcon()
115
+ );
116
+ }
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Wordpress Filter
123
+ */
124
+ public function AddPluginShortcuts($old_links){
125
+ $this->ReorderViews();
126
+
127
+ $new_links = array();
128
+ foreach($this->views as $view){
129
+ if($view->HasPluginShortcutLink()){
130
+ $new_links[] =
131
+ '<a href="'
132
+ . admin_url('admin.php?page='
133
+ . $view->GetSafeViewName()
134
+ ) . '">'
135
+ . $view->GetName()
136
+ . '</a>';
137
+ }
138
+ }
139
+ return array_merge($new_links, $old_links);
140
+ }
141
+
142
+ /**
143
+ * @return int Returns page id of current page (or false on error).
144
+ */
145
+ protected function GetBackendPageIndex(){
146
+ if(isset($_REQUEST['page']))
147
+ foreach($this->views as $i => $view)
148
+ if($_REQUEST['page'] == $view->GetSafeViewName())
149
+ return $i;
150
+ return false;
151
+ }
152
+
153
+ /**
154
+ *
155
+ * @var WSAL_AbstractView|null
156
+ */
157
+ protected $_active_view = false;
158
+
159
+ /**
160
+ * @return WSAL_AbstractView|null Returns the current active view or null if none.
161
+ */
162
+ public function GetActiveView(){
163
+ if($this->_active_view === false){
164
+ $this->_active_view = null;
165
+
166
+ if(isset($_REQUEST['page']))
167
+ foreach($this->views as $view)
168
+ if($_REQUEST['page'] == $view->GetSafeViewName())
169
+ $this->_active_view = $view;
170
+
171
+ if($this->_active_view)
172
+ $this->_active_view->is_active = true;
173
+ }
174
+ return $this->_active_view;
175
+ }
176
+
177
+ /**
178
+ * Render header of the current view.
179
+ */
180
+ public function RenderViewHeader(){
181
+ if (!!($view = $this->GetActiveView())) $view->Header();
182
+ }
183
+
184
+ /**
185
+ * Render footer of the current view.
186
+ */
187
+ public function RenderViewFooter(){
188
+ if (!!($view = $this->GetActiveView())) $view->Footer();
189
+ }
190
+
191
+ /**
192
+ * Render content of the current view.
193
+ */
194
+ public function RenderViewBody(){
195
+ $view = $this->GetActiveView();
196
+ ?><div class="wrap"><?php
197
+ $view->RenderIcon();
198
+ $view->RenderTitle();
199
+ $view->RenderContent();
200
+ ?></div><?php
201
+ }
202
+
203
+ /**
204
+ * Returns view instance corresponding to its class name.
205
+ * @param string $className View class name.
206
+ * @return WSAL_AbstractView The view or false on failure.
207
+ */
208
+ public function FindByClassName($className){
209
+ foreach($this->views as $view)
210
+ if($view instanceof $className)
211
+ return $view;
212
+ return false;
213
+ }
214
+
215
  }
classes/Views/About.php CHANGED
@@ -1,86 +1,86 @@
1
- <?php
2
-
3
- class WSAL_Views_About extends WSAL_AbstractView {
4
-
5
- public function GetTitle() {
6
- return __('About WP Security Audit Log', 'wp-security-audit-log');
7
- }
8
-
9
- public function GetIcon() {
10
- return 'dashicons-editor-help';
11
- }
12
-
13
- public function GetName() {
14
- return __('About', 'wp-security-audit-log');
15
- }
16
-
17
- public function GetWeight(){
18
- return 6;
19
- }
20
-
21
- public function Render(){
22
- ?><div class="metabox-holder" style="position: relative;">
23
-
24
- <div class="postbox" style="margin-right: 270px;">
25
- <!--h3 class="hndl"><span>About WP Security Audit Log</span></h3-->
26
- <div class="inside">
27
- <div class="activity-block">
28
- <?php _e('WP Security Audit Log enables WordPress administrators and owners to identify WordPress security issues before they become a security problem by keeping a security audit log. WP Security Audit Log is developed by WordPress security professionals WP White Security.', 'wp-security-audit-log'); ?>
29
-
30
- <h2><?php _e('Keep A WordPress Security Audit Log & Identify WordPress Security Issues', 'wp-security-audit-log'); ?></h2>
31
- <p>
32
- <?php _e('WP Security Audit Log logs everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A WordPress security alert is generated by the plugin when:', 'wp-security-audit-log'); ?>
33
- </p>
34
- <ul style="list-style-type: disc; margin-left: 2.5em; list-style-position: outside;">
35
- <li><?php _e('User creates a new user or a new user is registered', 'wp-security-audit-log'); ?></li>
36
- <li><?php _e('Existing user changes the role, password or other properties of another user', 'wp-security-audit-log'); ?></li>
37
- <li><?php _e('Existing user on a WordPress multisite network is added to a site', 'wp-security-audit-log'); ?></li>
38
- <li><?php _e('User uploads or deletes a file, changes a password or email address', 'wp-security-audit-log'); ?></li>
39
- <li><?php _e('User installs, activates, deactivates, upgrades or uninstalls a plugin', 'wp-security-audit-log'); ?></li>
40
- <li><?php _e('User creates, modifies or deletes a new post, page, category or a custom post type', 'wp-security-audit-log'); ?></li>
41
- <li><?php _e('User installs or activates a WordPress theme', 'wp-security-audit-log'); ?></li>
42
- <li><?php _e('User adds, modifies or deletes a widget', 'wp-security-audit-log'); ?></li>
43
- <li><?php _e('User uses the dashboard file editor', 'wp-security-audit-log'); ?></li>
44
- <li><?php _e('WordPress settings are changed', 'wp-security-audit-log'); ?></li>
45
- <li><?php _e('Failed login attempts', 'wp-security-audit-log'); ?></li>
46
- <li><?php _e('and much more&hellip;', 'wp-security-audit-log'); ?></li>
47
- </ul>
48
- <br/>
49
- Refer to the complete list of <a href="http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/?utm_source=wsalabt&utm_medium=txtlink&utm_campaign=wsal" target="_blank">WordPress Security Alerts</a> for more information.
50
- </div>
51
- </div>
52
- </div>
53
-
54
- <div style="position: absolute; right: 70px; width: 180px; top: 10px;">
55
- <div class="postbox">
56
- <h3 class="hndl"><span><?php _e('Extend the Functionality & Get More Value from WP Security Audit Log', 'wp-security-audit-log'); ?></span></h3>
57
- <div class="inside">
58
- <p>
59
- <?php _e('Get more value out of WP Security Audit Log by extending the functionality of WP Security Audit Log with the premium Add-Ons.'); ?>
60
- </p>
61
- <a class="button button-primary" href="http://www.wpsecurityauditlog.com/plugin-extensions/" target="_blank"><?php _e('See Add-Ons', 'wp-security-audit-log'); ?></a>
62
- </div>
63
- </div>
64
- <div class="postbox">
65
- <h3 class="hndl"><span><?php _e('WP Security Audit Log in your Language!', 'wp-security-audit-log'); ?></span></h3>
66
- <div class="inside">
67
- <?php _e('If you are interested in translating our plugin please drop us an email on', 'wp-security-audit-log'); ?>
68
- <a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
69
- </div>
70
- </div>
71
- <div class="postbox">
72
- <h3 class="hndl"><span><?php _e('WordPress Security Services', 'wp-security-audit-log'); ?></span></h3>
73
- <div class="inside">
74
- <?php _e('Professional WordPress security services provided by WP White Security', 'wp-security-audit-log'); ?>
75
- <ul>
76
- <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-hardening/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Hardening</a></li>
77
- <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-audit/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Audit</a></li>
78
- <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-plugins-security-code-audit-review/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Plugin Security Code Audit</a></li>
79
- </ul>
80
- </div>
81
- </div>
82
- </div>
83
- </div><?php
84
- }
85
-
86
  }
1
+ <?php
2
+
3
+ class WSAL_Views_About extends WSAL_AbstractView {
4
+
5
+ public function GetTitle() {
6
+ return __('About WP Security Audit Log', 'wp-security-audit-log');
7
+ }
8
+
9
+ public function GetIcon() {
10
+ return 'dashicons-editor-help';
11
+ }
12
+
13
+ public function GetName() {
14
+ return __('About', 'wp-security-audit-log');
15
+ }
16
+
17
+ public function GetWeight(){
18
+ return 6;
19
+ }
20
+
21
+ public function Render(){
22
+ ?><div class="metabox-holder" style="position: relative;">
23
+
24
+ <div class="postbox" style="margin-right: 270px;">
25
+ <!--h3 class="hndl"><span>About WP Security Audit Log</span></h3-->
26
+ <div class="inside">
27
+ <div class="activity-block">
28
+ <?php _e('WP Security Audit Log enables WordPress administrators and owners to identify WordPress security issues before they become a security problem by keeping a security audit log. WP Security Audit Log is developed by WordPress security professionals WP White Security.', 'wp-security-audit-log'); ?>
29
+
30
+ <h2><?php _e('Keep A WordPress Security Audit Log & Identify WordPress Security Issues', 'wp-security-audit-log'); ?></h2>
31
+ <p>
32
+ <?php _e('WP Security Audit Log logs everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A WordPress security alert is generated by the plugin when:', 'wp-security-audit-log'); ?>
33
+ </p>
34
+ <ul style="list-style-type: disc; margin-left: 2.5em; list-style-position: outside;">
35
+ <li><?php _e('User creates a new user or a new user is registered', 'wp-security-audit-log'); ?></li>
36
+ <li><?php _e('Existing user changes the role, password or other properties of another user', 'wp-security-audit-log'); ?></li>
37
+ <li><?php _e('Existing user on a WordPress multisite network is added to a site', 'wp-security-audit-log'); ?></li>
38
+ <li><?php _e('User uploads or deletes a file, changes a password or email address', 'wp-security-audit-log'); ?></li>
39
+ <li><?php _e('User installs, activates, deactivates, upgrades or uninstalls a plugin', 'wp-security-audit-log'); ?></li>
40
+ <li><?php _e('User creates, modifies or deletes a new post, page, category or a custom post type', 'wp-security-audit-log'); ?></li>
41
+ <li><?php _e('User installs or activates a WordPress theme', 'wp-security-audit-log'); ?></li>
42
+ <li><?php _e('User adds, modifies or deletes a widget', 'wp-security-audit-log'); ?></li>
43
+ <li><?php _e('User uses the dashboard file editor', 'wp-security-audit-log'); ?></li>
44
+ <li><?php _e('WordPress settings are changed', 'wp-security-audit-log'); ?></li>
45
+ <li><?php _e('Failed login attempts', 'wp-security-audit-log'); ?></li>
46
+ <li><?php _e('and much more&hellip;', 'wp-security-audit-log'); ?></li>
47
+ </ul>
48
+ <br/>
49
+ Refer to the complete list of <a href="http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/?utm_source=wsalabt&utm_medium=txtlink&utm_campaign=wsal" target="_blank">WordPress Security Alerts</a> for more information.
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ <div style="position: absolute; right: 70px; width: 180px; top: 10px;">
55
+ <div class="postbox">
56
+ <h3 class="hndl"><span><?php _e('Extend the Functionality & Get More Value from WP Security Audit Log', 'wp-security-audit-log'); ?></span></h3>
57
+ <div class="inside">
58
+ <p>
59
+ <?php _e('Get more value out of WP Security Audit Log by extending the functionality of WP Security Audit Log with the premium Add-Ons.'); ?>
60
+ </p>
61
+ <a class="button button-primary" href="http://www.wpsecurityauditlog.com/plugin-extensions/" target="_blank"><?php _e('See Add-Ons', 'wp-security-audit-log'); ?></a>
62
+ </div>
63
+ </div>
64
+ <div class="postbox">
65
+ <h3 class="hndl"><span><?php _e('WP Security Audit Log in your Language!', 'wp-security-audit-log'); ?></span></h3>
66
+ <div class="inside">
67
+ <?php _e('If you are interested in translating our plugin please drop us an email on', 'wp-security-audit-log'); ?>
68
+ <a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
69
+ </div>
70
+ </div>
71
+ <div class="postbox">
72
+ <h3 class="hndl"><span><?php _e('WordPress Security Services', 'wp-security-audit-log'); ?></span></h3>
73
+ <div class="inside">
74
+ <?php _e('Professional WordPress security services provided by WP White Security', 'wp-security-audit-log'); ?>
75
+ <ul>
76
+ <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-hardening/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Hardening</a></li>
77
+ <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-security-audit/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Security Audit</a></li>
78
+ <li><a href="http://www.wpwhitesecurity.com/wordpress-security-services/wordpress-plugins-security-code-audit-review/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank">Plugin Security Code Audit</a></li>
79
+ </ul>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </div><?php
84
+ }
85
+
86
  }
classes/Views/AuditLog.php CHANGED
@@ -1,177 +1,177 @@
1
- <?php
2
-
3
- class WSAL_Views_AuditLog extends WSAL_AbstractView {
4
- /**
5
- * @var WSAL_AuditLogListView
6
- */
7
- protected $_listview;
8
-
9
- public function __construct(WpSecurityAuditLog $plugin) {
10
- parent::__construct($plugin);
11
- add_action('wp_ajax_AjaxInspector', array($this, 'AjaxInspector'));
12
- add_action('wp_ajax_AjaxRefresh', array($this, 'AjaxRefresh'));
13
- add_action('wp_ajax_AjaxSetIpp', array($this, 'AjaxSetIpp'));
14
- add_action('wp_ajax_AjaxSearchSite', array($this, 'AjaxSearchSite'));
15
-
16
- $this->RegisterNotice('notifications-extension');
17
- }
18
-
19
- public function HasPluginShortcutLink(){
20
- return true;
21
- }
22
-
23
- public function GetTitle() {
24
- return __('Audit Log Viewer', 'wp-security-audit-log');
25
- }
26
-
27
- public function GetIcon() {
28
- return $this->_wpversion < 3.8
29
- ? $this->_plugin->GetBaseUrl() . '/img/logo-main-menu.png'
30
- : 'dashicons-welcome-view-site';
31
- }
32
-
33
- public function GetName() {
34
- return __('Audit Log Viewer', 'wp-security-audit-log');
35
- }
36
-
37
- public function GetWeight(){
38
- return 1;
39
- }
40
-
41
- protected function GetListView(){
42
- if (is_null($this->_listview)) $this->_listview = new WSAL_AuditLogListView($this->_plugin);
43
- return $this->_listview;
44
- }
45
-
46
- public function Render(){
47
- if(!$this->_plugin->settings->CurrentUserCan('view')){
48
- wp_die( __( 'You do not have sufficient permissions to access this page.' , 'wp-security-audit-log') );
49
- }
50
-
51
- $this->GetListView()->prepare_items();
52
- $occ = new WSAL_Models_Occurrence();
53
-
54
- ?><form id="audit-log-viewer" method="post">
55
- <div id="audit-log-viewer-content">
56
- <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
57
- <input type="hidden" id="wsal-cbid" name="wsal-cbid" value="<?php echo esc_attr(isset($_REQUEST['wsal-cbid']) ? $_REQUEST['wsal-cbid'] : '0'); ?>" />
58
- <?php do_action('wsal_auditlog_before_view', $this->GetListView()); ?>
59
- <?php $this->GetListView()->display(); ?>
60
- <?php do_action('wsal_auditlog_after_view', $this->GetListView()); ?>
61
- </div>
62
- </form><?php
63
-
64
- ?><script type="text/javascript">
65
- jQuery(document).ready(function(){
66
- WsalAuditLogInit(<?php echo json_encode(array(
67
- 'ajaxurl' => admin_url('admin-ajax.php'),
68
- 'tr8n' => array(
69
- 'numofitems' => __('Please enter the number of alerts you would like to see on one page:', 'wp-security-audit-log'),
70
- 'searchback' => __('All Sites', 'wp-security-audit-log'),
71
- 'searchnone' => __('No Results', 'wp-security-audit-log'),
72
- ),
73
- 'autorefresh' => array(
74
- 'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
75
- 'token' => (int)$occ->Count(),
76
- ),
77
- )); ?>);
78
- });
79
- </script><?php
80
- }
81
-
82
- public function AjaxInspector(){
83
- if(!$this->_plugin->settings->CurrentUserCan('view'))
84
- die('Access Denied.');
85
- if(!isset($_REQUEST['occurrence']))
86
- die('Occurrence parameter expected.');
87
- $occ = new WSAL_Models_Occurrence();
88
- $occ->Load('id = %d', array((int)$_REQUEST['occurrence']));
89
-
90
- echo '<!DOCTYPE html><html><head>';
91
- echo '<link rel="stylesheet" id="open-sans-css" href="' . $this->_plugin->GetBaseUrl() . '/css/nice_r.css" type="text/css" media="all">';
92
- echo '<script type="text/javascript" src="'.$this->_plugin->GetBaseUrl() . '/js/nice_r.js"></script>';
93
- echo '<style type="text/css">';
94
- echo 'html, body { margin: 0; padding: 0; }';
95
- echo '.nice_r { position: absolute; padding: 8px; }';
96
- echo '.nice_r a { overflow: visible; }';
97
- echo '</style>';
98
- echo '</head><body>';
99
- $nicer = new WSAL_Nicer($occ->GetMetaArray());
100
- $nicer->render();
101
- echo '</body></html>';
102
- die;
103
- }
104
-
105
- public function AjaxRefresh(){
106
- if(!$this->_plugin->settings->CurrentUserCan('view'))
107
- die('Access Denied.');
108
- if(!isset($_REQUEST['logcount']))
109
- die('Log count parameter expected.');
110
-
111
- $old = (int)$_REQUEST['logcount'];
112
- $max = 40; // 40*500msec = 20sec
113
-
114
- session_write_close(); // fixes session lock issue
115
-
116
- do{
117
- $occ = new WSAL_Models_Occurrence();
118
- $new = $occ->Count();
119
- usleep(500000); // 500msec
120
- }while(($old == $new) && (--$max > 0));
121
-
122
- echo $old == $new ? 'false' : $new;
123
- die;
124
- }
125
-
126
- public function AjaxSetIpp(){
127
- if(!$this->_plugin->settings->CurrentUserCan('view'))
128
- die('Access Denied.');
129
- if(!isset($_REQUEST['count']))
130
- die('Count parameter expected.');
131
- $this->_plugin->settings->SetViewPerPage((int)$_REQUEST['count']);
132
- die;
133
- }
134
-
135
- public function AjaxSearchSite(){
136
- if(!$this->_plugin->settings->CurrentUserCan('view'))
137
- die('Access Denied.');
138
- if(!isset($_REQUEST['search']))
139
- die('Search parameter expected.');
140
-
141
- $grp1 = array();
142
- $grp2 = array();
143
-
144
- $search = $_REQUEST['search'];
145
-
146
- foreach($this->GetListView()->get_sites() as $site){
147
- if(stripos($site->blogname, $search) !== false)
148
- $grp1[] = $site;
149
- else
150
- if(stripos($site->domain, $search) !== false)
151
- $grp2[] = $site;
152
- }
153
-
154
- die(json_encode(array_slice($grp1 + $grp2, 0, 7)));
155
- }
156
-
157
- public function Header(){
158
- add_thickbox();
159
- wp_enqueue_style(
160
- 'auditlog',
161
- $this->_plugin->GetBaseUrl() . '/css/auditlog.css',
162
- array(),
163
- filemtime($this->_plugin->GetBaseDir() . '/css/auditlog.css')
164
- );
165
- }
166
-
167
- public function Footer() {
168
- wp_enqueue_script('jquery');
169
- wp_enqueue_script('suggest');
170
- wp_enqueue_script(
171
- 'auditlog',
172
- $this->_plugin->GetBaseUrl() . '/js/auditlog.js',
173
- array(),
174
- filemtime($this->_plugin->GetBaseDir() . '/js/auditlog.js')
175
- );
176
- }
177
- }
1
+ <?php
2
+
3
+ class WSAL_Views_AuditLog extends WSAL_AbstractView {
4
+ /**
5
+ * @var WSAL_AuditLogListView
6
+ */
7
+ protected $_listview;
8
+
9
+ public function __construct(WpSecurityAuditLog $plugin) {
10
+ parent::__construct($plugin);
11
+ add_action('wp_ajax_AjaxInspector', array($this, 'AjaxInspector'));
12
+ add_action('wp_ajax_AjaxRefresh', array($this, 'AjaxRefresh'));
13
+ add_action('wp_ajax_AjaxSetIpp', array($this, 'AjaxSetIpp'));
14
+ add_action('wp_ajax_AjaxSearchSite', array($this, 'AjaxSearchSite'));
15
+
16
+ $this->RegisterNotice('notifications-extension');
17
+ }
18
+
19
+ public function HasPluginShortcutLink(){
20
+ return true;
21
+ }
22
+
23
+ public function GetTitle() {
24
+ return __('Audit Log Viewer', 'wp-security-audit-log');
25
+ }
26
+
27
+ public function GetIcon() {
28
+ return $this->_wpversion < 3.8
29
+ ? $this->_plugin->GetBaseUrl() . '/img/logo-main-menu.png'
30
+ : 'dashicons-welcome-view-site';
31
+ }
32
+
33
+ public function GetName() {
34
+ return __('Audit Log Viewer', 'wp-security-audit-log');
35
+ }
36
+
37
+ public function GetWeight(){
38
+ return 1;
39
+ }
40
+
41
+ protected function GetListView(){
42
+ if (is_null($this->_listview)) $this->_listview = new WSAL_AuditLogListView($this->_plugin);
43
+ return $this->_listview;
44
+ }
45
+
46
+ public function Render(){
47
+ if(!$this->_plugin->settings->CurrentUserCan('view')){
48
+ wp_die( __( 'You do not have sufficient permissions to access this page.' , 'wp-security-audit-log') );
49
+ }
50
+
51
+ $this->GetListView()->prepare_items();
52
+ $occ = new WSAL_Models_Occurrence();
53
+
54
+ ?><form id="audit-log-viewer" method="post">
55
+ <div id="audit-log-viewer-content">
56
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
57
+ <input type="hidden" id="wsal-cbid" name="wsal-cbid" value="<?php echo esc_attr(isset($_REQUEST['wsal-cbid']) ? $_REQUEST['wsal-cbid'] : '0'); ?>" />
58
+ <?php do_action('wsal_auditlog_before_view', $this->GetListView()); ?>
59
+ <?php $this->GetListView()->display(); ?>
60
+ <?php do_action('wsal_auditlog_after_view', $this->GetListView()); ?>
61
+ </div>
62
+ </form><?php
63
+
64
+ ?><script type="text/javascript">
65
+ jQuery(document).ready(function(){
66
+ WsalAuditLogInit(<?php echo json_encode(array(
67
+ 'ajaxurl' => admin_url('admin-ajax.php'),
68
+ 'tr8n' => array(
69
+ 'numofitems' => __('Please enter the number of alerts you would like to see on one page:', 'wp-security-audit-log'),
70
+ 'searchback' => __('All Sites', 'wp-security-audit-log'),
71
+ 'searchnone' => __('No Results', 'wp-security-audit-log'),
72
+ ),
73
+ 'autorefresh' => array(
74
+ 'enabled' => $this->_plugin->settings->IsRefreshAlertsEnabled(),
75
+ 'token' => (int)$occ->Count(),
76
+ ),
77
+ )); ?>);
78
+ });
79
+ </script><?php
80
+ }
81
+
82
+ public function AjaxInspector(){
83
+ if(!$this->_plugin->settings->CurrentUserCan('view'))
84
+ die('Access Denied.');
85
+ if(!isset($_REQUEST['occurrence']))
86
+ die('Occurrence parameter expected.');
87
+ $occ = new WSAL_Models_Occurrence();
88
+ $occ->Load('id = %d', array((int)$_REQUEST['occurrence']));
89
+
90
+ echo '<!DOCTYPE html><html><head>';
91
+ echo '<link rel="stylesheet" id="open-sans-css" href="' . $this->_plugin->GetBaseUrl() . '/css/nice_r.css" type="text/css" media="all">';
92
+ echo '<script type="text/javascript" src="'.$this->_plugin->GetBaseUrl() . '/js/nice_r.js"></script>';
93
+ echo '<style type="text/css">';
94
+ echo 'html, body { margin: 0; padding: 0; }';
95
+ echo '.nice_r { position: absolute; padding: 8px; }';
96
+ echo '.nice_r a { overflow: visible; }';
97
+ echo '</style>';
98
+ echo '</head><body>';
99
+ $nicer = new WSAL_Nicer($occ->GetMetaArray());
100
+ $nicer->render();
101
+ echo '</body></html>';
102
+ die;
103
+ }
104
+
105
+ public function AjaxRefresh(){
106
+ if(!$this->_plugin->settings->CurrentUserCan('view'))
107
+ die('Access Denied.');
108
+ if(!isset($_REQUEST['logcount']))
109
+ die('Log count parameter expected.');
110
+
111
+ $old = (int)$_REQUEST['logcount'];
112
+ $max = 40; // 40*500msec = 20sec
113
+
114
+ session_write_close(); // fixes session lock issue
115
+
116
+ do{
117
+ $occ = new WSAL_Models_Occurrence();
118
+ $new = $occ->Count();
119
+ usleep(500000); // 500msec
120
+ }while(($old == $new) && (--$max > 0));
121
+
122
+ echo $old == $new ? 'false' : $new;
123
+ die;
124
+ }
125
+
126
+ public function AjaxSetIpp(){
127
+ if(!$this->_plugin->settings->CurrentUserCan('view'))
128
+ die('Access Denied.');
129
+ if(!isset($_REQUEST['count']))
130
+ die('Count parameter expected.');
131
+ $this->_plugin->settings->SetViewPerPage((int)$_REQUEST['count']);
132
+ die;
133
+ }
134
+
135
+ public function AjaxSearchSite(){
136
+ if(!$this->_plugin->settings->CurrentUserCan('view'))
137
+ die('Access Denied.');
138
+ if(!isset($_REQUEST['search']))
139
+ die('Search parameter expected.');
140
+
141
+ $grp1 = array();
142
+ $grp2 = array();
143
+
144
+ $search = $_REQUEST['search'];
145
+
146
+ foreach($this->GetListView()->get_sites() as $site){
147
+ if(stripos($site->blogname, $search) !== false)
148
+ $grp1[] = $site;
149
+ else
150
+ if(stripos($site->domain, $search) !== false)
151
+ $grp2[] = $site;
152
+ }
153
+
154
+ die(json_encode(array_slice($grp1 + $grp2, 0, 7)));
155
+ }
156
+
157
+ public function Header(){
158
+ add_thickbox();
159
+ wp_enqueue_style(
160
+ 'auditlog',
161
+ $this->_plugin->GetBaseUrl() . '/css/auditlog.css',
162
+ array(),
163
+ filemtime($this->_plugin->GetBaseDir() . '/css/auditlog.css')
164
+ );
165
+ }
166
+
167
+ public function Footer() {
168
+ wp_enqueue_script('jquery');
169
+ wp_enqueue_script('suggest');
170
+ wp_enqueue_script(
171
+ 'auditlog',
172
+ $this->_plugin->GetBaseUrl() . '/js/auditlog.js',
173
+ array(),
174
+ filemtime($this->_plugin->GetBaseDir() . '/js/auditlog.js')
175
+ );
176
+ }
177
+ }
classes/Views/Help.php CHANGED
@@ -1,77 +1,79 @@
1
- <?php
2
-
3
- class WSAL_Views_Help extends WSAL_AbstractView {
4
-
5
- public function GetTitle() {
6
- return __('Help', 'wp-security-audit-log');
7
- }
8
-
9
- public function GetIcon() {
10
- return 'dashicons-sos';
11
- }
12
-
13
- public function GetName() {
14
- return __('Help', 'wp-security-audit-log');
15
- }
16
-
17
- public function GetWeight() {
18
- return 5;
19
- }
20
-
21
- public function Render(){
22
- ?><div class="metabox-holder" style="position: relative;">
23
-
24
- <div class="postbox" style="margin-right: 270px;">
25
- <div class="inside">
26
- <div class="activity-block">
27
- <h2><?php _e('Plugin Support', 'wp-security-audit-log'); ?></h2>
28
- <p>
29
- <?php _e('Have you encountered or noticed any issues while using WP Security Audit Log plugin?', 'wp-security-audit-log'); ?>
30
- <?php _e('Or you want to report something to us? Click any of the options below to post on the plugin\'s forum or contact our support directly.', 'wp-security-audit-log'); ?>
31
- </p><p>
32
- <a class="button" href="https://wordpress.org/support/plugin/wp-security-audit-log" target="_blank"><?php _e('Free Support Forum', 'wp-security-audit-log'); ?></a>
33
- &nbsp;&nbsp;&nbsp;&nbsp;
34
- <a class="button" href="http://www.wpsecurityauditlog.com/contact/" target="_blank"><?php _e('Free Support Email', 'wp-security-audit-log'); ?></a>
35
- </p>
36
- </div>
37
-
38
- <div class="activity-block">
39
- <h2><?php _e('Plugin Documentation', 'wp-security-audit-log'); ?></h2>
40
- <p>
41
- <?php _e('For more detailed information about WP Security Audit Log you can visit the plugin website.', 'wp-security-audit-log'); ?>
42
- <?php _e('You can also visit the official list of WordPress Security Alerts for more information about all of the WordPress activity and changes you can monitor with WP Security Audit Log.', 'wp-security-audit-log'); ?>
43
- </p><p>
44
- <a class="button" href="http://www.wpsecurityauditlog.com/?utm_source=wpsalabt&utm_medium=txtlink&utm_campaign=wpsal" target="_blank"><?php _e('Plugin Website', 'wp-security-audit-log'); ?></a>
45
- &nbsp;&nbsp;&nbsp;&nbsp;
46
- <a class="button" href="http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/?utm_source=wsalabt&utm_medium=txtlink&utm_campaign=wsal" target="_blank"><?php _e('List of WordPress Security Alerts', 'wp-security-audit-log'); ?></a>
47
- </p>
48
- </div>
49
-
50
- <div class="">
51
- <h2><?php _e('WordPress Security Blog', 'wp-security-audit-log'); ?></h2>
52
- <p>
53
- <?php _e('New to WordPress security?', 'wp-security-audit-log'); ?>
54
- <?php _e('Do not know from where to start or which is the best services for you?', 'wp-security-audit-log'); ?>
55
- <?php _e('Visit our WordPress security blog or the WordPress Security category directly for more information and a number of tips and tricks about WordPress security.', 'wp-security-audit-log'); ?>
56
- </p>
57
- <a class="button" href="http://www.wpwhitesecurity.com/blog/?utm_source=wsalabt&utm_medium=txtlink&utm_campaign=wsal" target="_blank"><?php _e('WP White Security Blog', 'wp-security-audit-log'); ?></a>
58
- &nbsp;&nbsp;&nbsp;&nbsp;
59
- <a class="button" href="http://www.wpwhitesecurity.com/wordpress-security/?utm_source=wsalabt&utm_medium=txtlink&utm_campaign=wsal" target="_blank"><?php _e('WordPress Security Category', 'wp-security-audit-log'); ?></a>
60
- </div>
61
- </div>
62
- </div>
63
-
64
- <div style="position: absolute; right: 70px; width: 180px; top: 10px;">
65
- <div class="postbox">
66
- <h3 class="hndl"><span><?php _e('WP Security Audit Log in your Language!', 'wp-security-audit-log'); ?></span></h3>
67
- <div class="inside">
68
- <?php _e('If you are interested in translating our plugin please drop us an email on', 'wp-security-audit-log'); ?>
69
- <a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
70
- </div>
71
- </div>
72
- </div>
73
-
74
- </div><?php
75
- }
76
-
 
 
77
  }
1
+ <?php
2
+
3
+ class WSAL_Views_Help extends WSAL_AbstractView {
4
+
5
+ public function GetTitle() {
6
+ return __('Help', 'wp-security-audit-log');
7
+ }
8
+
9
+ public function GetIcon() {
10
+ return 'dashicons-sos';
11
+ }
12
+
13
+ public function GetName() {
14
+ return __('Help', 'wp-security-audit-log');
15
+ }
16
+
17
+ public function GetWeight() {
18
+ return 5;
19
+ }
20
+
21
+ public function Render(){
22
+ ?><div class="metabox-holder" style="position: relative;">
23
+
24
+ <div class="postbox" style="margin-right: 270px;">
25
+ <div class="inside">
26
+ <div class="activity-block">
27
+ <h2><?php _e('Plugin Support', 'wp-security-audit-log'); ?></h2>
28
+ <p>
29
+ <?php _e('Have you encountered or noticed any issues while using WP Security Audit Log plugin?', 'wp-security-audit-log'); ?>
30
+ <?php _e('Or you want to report something to us? Click any of the options below to post on the plugin\'s forum or contact our support directly.', 'wp-security-audit-log'); ?>
31
+ </p><p>
32
+ <a class="button" href="https://wordpress.org/support/plugin/wp-security-audit-log" target="_blank"><?php _e('Free Support Forum', 'wp-security-audit-log'); ?></a>
33
+ &nbsp;&nbsp;&nbsp;&nbsp;
34
+ <a class="button" href="http://www.wpsecurityauditlog.com/contact/" target="_blank"><?php _e('Free Support Email', 'wp-security-audit-log'); ?></a>
35
+ </p>
36
+ </div>
37
+
38
+ <div class="activity-block">
39
+ <h2><?php _e('Plugin Documentation', 'wp-security-audit-log'); ?></h2>
40
+ <p>
41
+ <?php _e('For more detailed information about WP Security Audit Log you can visit the plugin website.', 'wp-security-audit-log'); ?>
42
+ <?php _e('You can also visit the official list of WordPress Security Alerts for more information about all of the WordPress activity and changes you can monitor with WP Security Audit Log.', 'wp-security-audit-log'); ?>
43
+ </p><p>
44
+ <a class="button" href="http://www.wpsecurityauditlog.com/?utm_source=plugin&utm_medium=helppage&utm_campaign=support" target="_blank"><?php _e('Plugin Website', 'wp-security-audit-log'); ?></a>
45
+ &nbsp;&nbsp;&nbsp;&nbsp;
46
+ <a class="button" href="https://www.wpsecurityauditlog.com/documentation/?utm_source=plugin&utm_medium=helppage&utm_campaign=support" target="_blank"><?php _e('Plugin Documenation', 'wp-security-audit-log'); ?></a>
47
+ &nbsp;&nbsp;&nbsp;&nbsp;
48
+ <a class="button" href="https://www.wpsecurityauditlog.com/documentation/frequently-asked-questions-faqs/?utm_source=plugin&utm_medium=helppage&utm_campaign=support" target="_blank"><?php _e('FAQs', 'wp-security-audit-log'); ?></a>
49
+ &nbsp;&nbsp;&nbsp;&nbsp;
50
+ <a class="button" href="http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/?utm_source=plugin&utm_medium=helppage&utm_campaign=support" target="_blank"><?php _e('List of WordPress Security Alerts', 'wp-security-audit-log'); ?></a>
51
+ </p>
52
+ </div>
53
+
54
+ <div class="">
55
+ <h2><?php _e('Keep Yourself Up-to-Date with WordPress Security', 'wp-security-audit-log'); ?></h2>
56
+ <p>
57
+ <?php _e('Keep yourself informed with what is happening in the WordPress security ecosystem, which are the new vulnerabilities, which plugins you need to update and what are the latest WordPress security hacks so you can stay one step ahead of the hackers.', 'wp-security-audit-log'); ?>
58
+ </p>
59
+ <a class="button" href="http://www.wpwhitesecurity.com/blog/" target="_blank"><?php _e('Read the WP White Security Blog', 'wp-security-audit-log'); ?></a>
60
+ &nbsp;&nbsp;&nbsp;&nbsp;
61
+ <a class="button" href="http://www.wpsecuritybloggers.com" target="_blank"><?php _e('Subscribe to WP Security Bloggers (An Aggregate of WordPress Security Blogs)', 'wp-security-audit-log'); ?></a>
62
+ </div>
63
+ </div>
64
+ </div>
65
+
66
+ <div style="position: absolute; right: 70px; width: 180px; top: 10px;">
67
+ <div class="postbox">
68
+ <h3 class="hndl"><span><?php _e('WP Security Audit Log in your Language!', 'wp-security-audit-log'); ?></span></h3>
69
+ <div class="inside">
70
+ <?php _e('If you are interested in translating our plugin please drop us an email on', 'wp-security-audit-log'); ?>
71
+ <a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>.
72
+ </div>
73
+ </div>
74
+ </div>
75
+
76
+ </div><?php
77
+ }
78
+
79
  }
classes/Views/Licensing.php CHANGED
@@ -1,88 +1,88 @@
1
- <?php
2
-
3
- class WSAL_Views_Licensing extends WSAL_AbstractView {
4
-
5
- public function GetTitle() {
6
- return __('Licensing', 'wp-security-audit-log');
7
- }
8
-
9
- public function GetIcon() {
10
- return 'dashicons-cart';
11
- }
12
-
13
- public function GetName() {
14
- return __('Licensing', 'wp-security-audit-log');
15
- }
16
-
17
- public function GetWeight() {
18
- return 4;
19
- }
20
-
21
- public function IsAccessible(){
22
- return !!$this->_plugin->licensing->CountPlugins();
23
- }
24
-
25
- protected function Save(){
26
- $this->_plugin->settings->ClearLicenses();
27
- if (isset($_REQUEST['license']))
28
- foreach ($_REQUEST['license'] as $name => $key)
29
- $this->_plugin->licensing->ActivateLicense($name, $key);
30
- }
31
-
32
- public function Render(){
33
- if(!$this->_plugin->settings->CurrentUserCan('edit')){
34
- wp_die( __( 'You do not have sufficient permissions to access this page.' , 'wp-security-audit-log') );
35
- }
36
- if(isset($_POST['submit'])){
37
- try {
38
- $this->Save();
39
- ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
40
- }catch(Exception $ex){
41
- ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
42
- }
43
- }
44
- ?><form id="audit-log-licensing" method="post">
45
- <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
46
-
47
- <table class="wp-list-table widefat fixed">
48
- <thead>
49
- <tr><th>Plugin</th><th>License</th><th></th></tr>
50
- </thead><tbody>
51
- <?php $counter = 0; ?>
52
- <?php foreach($this->_plugin->licensing->Plugins() as $name => $plugin){ ?>
53
- <?php $licenseKey = trim($this->_plugin->settings->GetLicenseKey($name)); ?>
54
- <?php $licenseStatus = trim($this->_plugin->settings->GetLicenseStatus($name)); ?>
55
- <?php $licenseErrors = trim($this->_plugin->settings->GetLicenseErrors($name)); ?>
56
- <tr class="<?php echo ($counter++ % 2 === 0) ? 'alternate' : ''; ?>">
57
- <td>
58
- <a href="<?php echo esc_attr($plugin['PluginData']['PluginURI']); ?>" target="_blank">
59
- <?php echo esc_html($plugin['PluginData']['Name']); ?>
60
- </a><br/><small><b>
61
- <?php _e('Version', 'wp-security-audit-log'); ?>
62
- <?php echo esc_html($plugin['PluginData']['Version']); ?>
63
- </b></small>
64
- </td><td>
65
- <input type="text" style="width: 360px; margin: 6px 0;"
66
- name="license[<?php echo esc_attr($name); ?>]"
67
- value="<?php echo esc_attr($licenseKey); ?>"/>
68
- </td><td style="vertical-align: middle;">
69
- <?php if($licenseKey){ ?>
70
- <?php if($licenseStatus === 'valid'){ ?>
71
- <?php _e('Active', 'wp-security-audit-log'); ?>
72
- <?php }else{ ?>
73
- <?php _e('Inactive', 'wp-security-audit-log'); ?><br/>
74
- <small><?php echo esc_html($licenseErrors); ?></small>
75
- <?php } ?>
76
- <?php } ?>
77
- </td>
78
- </tr>
79
- <?php } ?>
80
- </tbody><tfoot>
81
- <tr><th>Plugin</th><th>License</th><th></th></tr>
82
- </tfoot>
83
- </table>
84
- <?php submit_button(); ?>
85
- </form><?php
86
- }
87
-
88
  }
1
+ <?php
2
+
3
+ class WSAL_Views_Licensing extends WSAL_AbstractView {
4
+
5
+ public function GetTitle() {
6
+ return __('Licensing', 'wp-security-audit-log');
7
+ }
8
+
9
+ public function GetIcon() {
10
+ return 'dashicons-cart';
11
+ }
12
+
13
+ public function GetName() {
14
+ return __('Licensing', 'wp-security-audit-log');
15
+ }
16
+
17
+ public function GetWeight() {
18
+ return 4;
19
+ }
20
+
21
+ public function IsAccessible(){
22
+ return !!$this->_plugin->licensing->CountPlugins();
23
+ }
24
+
25
+ protected function Save(){
26
+ $this->_plugin->settings->ClearLicenses();
27
+ if (isset($_REQUEST['license']))
28
+ foreach ($_REQUEST['license'] as $name => $key)
29
+ $this->_plugin->licensing->ActivateLicense($name, $key);
30
+ }
31
+
32
+ public function Render(){
33
+ if(!$this->_plugin->settings->CurrentUserCan('edit')){
34
+ wp_die( __( 'You do not have sufficient permissions to access this page.' , 'wp-security-audit-log') );
35
+ }
36
+ if(isset($_POST['submit'])){
37
+ try {
38
+ $this->Save();
39
+ ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
40
+ }catch(Exception $ex){
41
+ ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
42
+ }
43
+ }
44
+ ?><form id="audit-log-licensing" method="post">
45
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
46
+
47
+ <table class="wp-list-table widefat fixed">
48
+ <thead>
49
+ <tr><th>Plugin</th><th>License</th><th></th></tr>
50
+ </thead><tbody>
51
+ <?php $counter = 0; ?>
52
+ <?php foreach($this->_plugin->licensing->Plugins() as $name => $plugin){ ?>
53
+ <?php $licenseKey = trim($this->_plugin->settings->GetLicenseKey($name)); ?>
54
+ <?php $licenseStatus = trim($this->_plugin->settings->GetLicenseStatus($name)); ?>
55
+ <?php $licenseErrors = trim($this->_plugin->settings->GetLicenseErrors($name)); ?>
56
+ <tr class="<?php echo ($counter++ % 2 === 0) ? 'alternate' : ''; ?>">
57
+ <td>
58
+ <a href="<?php echo esc_attr($plugin['PluginData']['PluginURI']); ?>" target="_blank">
59
+ <?php echo esc_html($plugin['PluginData']['Name']); ?>
60
+ </a><br/><small><b>
61
+ <?php _e('Version', 'wp-security-audit-log'); ?>
62
+ <?php echo esc_html($plugin['PluginData']['Version']); ?>
63
+ </b></small>
64
+ </td><td>
65
+ <input type="text" style="width: 360px; margin: 6px 0;"
66
+ name="license[<?php echo esc_attr($name); ?>]"
67
+ value="<?php echo esc_attr($licenseKey); ?>"/>
68
+ </td><td style="vertical-align: middle;">
69
+ <?php if($licenseKey){ ?>
70
+ <?php if($licenseStatus === 'valid'){ ?>
71
+ <?php _e('Active', 'wp-security-audit-log'); ?>
72
+ <?php }else{ ?>
73
+ <?php _e('Inactive', 'wp-security-audit-log'); ?><br/>
74
+ <small><?php echo esc_html($licenseErrors); ?></small>
75
+ <?php } ?>
76
+ <?php } ?>
77
+ </td>
78
+ </tr>
79
+ <?php } ?>
80
+ </tbody><tfoot>
81
+ <tr><th>Plugin</th><th>License</th><th></th></tr>
82
+ </tfoot>
83
+ </table>
84
+ <?php submit_button(); ?>
85
+ </form><?php
86
+ }
87
+
88
  }
classes/Views/Settings.php CHANGED
@@ -1,682 +1,682 @@
1
- <?php
2
- class WSAL_Views_Settings extends WSAL_AbstractView
3
- {
4
-
5
- public $adapterMsg = '';
6
-
7
- public function __construct(WpSecurityAuditLog $plugin)
8
- {
9
- parent::__construct($plugin);
10
-
11
- add_action('wp_ajax_AjaxCheckSecurityToken', array($this, 'AjaxCheckSecurityToken'));
12
- add_action('wp_ajax_AjaxRunCleanup', array($this, 'AjaxRunCleanup'));
13
- add_action('wp_ajax_AjaxGetAllUsers', array($this, 'AjaxGetAllUsers'));
14
- add_action('wp_ajax_AjaxGetAllRoles', array($this, 'AjaxGetAllRoles'));
15
- }
16
-
17
- public function HasPluginShortcutLink(){
18
- return true;
19
- }
20
-
21
- public function GetTitle() {
22
- return __('Settings', 'wp-security-audit-log');
23
- }
24
-
25
- public function GetIcon() {
26
- return 'dashicons-admin-generic';
27
- }
28
-
29
- public function GetName() {
30
- return __('Settings', 'wp-security-audit-log');
31
- }
32
-
33
- public function GetWeight() {
34
- return 3;
35
- }
36
-
37
- protected function GetTokenType($token){
38
- $users = array();
39
- foreach (get_users('blog_id=0&fields[]=user_login') as $obj)
40
- $users[] = $obj->user_login;
41
- $roles = array_keys(get_editable_roles());
42
-
43
- if(in_array($token, $users))return 'user';
44
- if(in_array($token, $roles))return 'role';
45
- return 'other';
46
- }
47
-
48
- protected function Save()
49
- {
50
- check_admin_referer('wsal-settings');
51
- $this->_plugin->settings->SetPruningDateEnabled($_REQUEST['PruneBy'] == 'date');
52
- $this->_plugin->settings->SetPruningDate($_REQUEST['PruningDate']);
53
- $this->_plugin->settings->SetPruningLimitEnabled($_REQUEST['PruneBy'] == 'limit');
54
- $this->_plugin->settings->SetPruningLimit($_REQUEST['PruningLimit']);
55
- $this->_plugin->settings->SetWidgetsEnabled($_REQUEST['EnableDashboardWidgets']);
56
- $this->_plugin->settings->SetAllowedPluginViewers(isset($_REQUEST['Viewers']) ? $_REQUEST['Viewers'] : array());
57
- $this->_plugin->settings->SetAllowedPluginEditors(isset($_REQUEST['Editors']) ? $_REQUEST['Editors'] : array());
58
-
59
- $this->_plugin->settings->SetExcludedMonitoringUsers(isset($_REQUEST['ExUsers']) ? $_REQUEST['ExUsers'] : array());
60
- $this->_plugin->settings->SetExcludedMonitoringRoles(isset($_REQUEST['ExRoles']) ? $_REQUEST['ExRoles'] : array());
61
- $this->_plugin->settings->SetExcludedMonitoringCustom(isset($_REQUEST['Customs']) ? $_REQUEST['Customs'] : array());
62
- $this->_plugin->settings->SetExcludedMonitoringIP(isset($_REQUEST['IpAddrs']) ? $_REQUEST['IpAddrs'] : array());
63
-
64
- $this->_plugin->settings->SetRestrictAdmins(isset($_REQUEST['RestrictAdmins']));
65
- $this->_plugin->settings->SetRefreshAlertsEnabled($_REQUEST['EnableAuditViewRefresh']);
66
- $this->_plugin->settings->SetMainIPFromProxy(isset($_REQUEST['EnableProxyIpCapture']));
67
- $this->_plugin->settings->SetInternalIPsFiltering(isset($_REQUEST['EnableIpFiltering']));
68
- $this->_plugin->settings->SetIncognito(isset($_REQUEST['Incognito']));
69
- $this->_plugin->settings->SetDeleteData(isset($_REQUEST['DeleteData']));
70
- $this->_plugin->settings->SetDatetimeFormat($_REQUEST['DatetimeFormat']);
71
- $this->_plugin->settings->SetTimezone($_REQUEST['Timezone']);
72
- $this->_plugin->settings->SetWPBackend(isset($_REQUEST['WPBackend']));
73
- if (!empty($_REQUEST['Columns'])) {
74
- $this->_plugin->settings->SetColumns($_REQUEST['Columns']);
75
- }
76
- $this->_plugin->settings->ClearDevOptions();
77
-
78
- if (isset($_REQUEST['DevOptions'])) {
79
- foreach ($_REQUEST['DevOptions'] as $opt) {
80
- $this->_plugin->settings->SetDevOptionEnabled($opt, true);
81
- }
82
- }
83
-
84
- // Database Adapter Settings
85
- // Temporarily not used
86
- /* Check Adapter config */
87
- if (!empty($_REQUEST["AdapterUser"]) && ($_REQUEST['AdapterUser'] != '') && ($_REQUEST['AdapterName'] != '') && ($_REQUEST['AdapterHostname'] != '')) {
88
- WSAL_Connector_ConnectorFactory::CheckConfig(
89
- trim($_REQUEST['AdapterType']),
90
- trim($_REQUEST['AdapterUser']),
91
- trim($_REQUEST['AdapterPassword']),
92
- trim($_REQUEST['AdapterName']),
93
- trim($_REQUEST['AdapterHostname']),
94
- trim($_REQUEST['AdapterBasePrefix'])
95
- );
96
-
97
- /* Setting Adapter config */
98
- $this->_plugin->settings->SetAdapterConfig('adapter-type', $_REQUEST['AdapterType']);
99
- $this->_plugin->settings->SetAdapterConfig('adapter-user', $_REQUEST['AdapterUser']);
100
- $this->_plugin->settings->SetAdapterConfig('adapter-password', $_REQUEST['AdapterPassword']);
101
- $this->_plugin->settings->SetAdapterConfig('adapter-name', $_REQUEST['AdapterName']);
102
- $this->_plugin->settings->SetAdapterConfig('adapter-hostname', $_REQUEST['AdapterHostname']);
103
- $this->_plugin->settings->SetAdapterConfig('adapter-base-prefix', $_REQUEST['AdapterBasePrefix']);
104
- }
105
- }
106
-
107
- public function AjaxCheckSecurityToken()
108
- {
109
- if (!$this->_plugin->settings->CurrentUserCan('view'))
110
- die('Access Denied.');
111
- if (!isset($_REQUEST['token']))
112
- die('Token parameter expected.');
113
- die($this->GetTokenType($_REQUEST['token']));
114
- }
115
-
116
- public function AjaxRunCleanup()
117
- {
118
- if (!$this->_plugin->settings->CurrentUserCan('view'))
119
- die('Access Denied.');
120
- $this->_plugin->CleanUp();
121
- wp_redirect($this->GetUrl());
122
- exit;
123
- }
124
-
125
- public function Render()
126
- {
127
- if (!$this->_plugin->settings->CurrentUserCan('edit')) {
128
- wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
129
- }
130
- if (isset($_POST['submit'])) {
131
- try {
132
- $this->Save();
133
- ?><div class="updated">
134
- <p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p>
135
- </div><?php
136
- } catch (Exception $ex) {
137
- ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
138
- }
139
- }
140
- ?>
141
- <h2 id="wsal-tabs" class="nav-tab-wrapper">
142
- <a href="#tab-general" class="nav-tab">General</a>
143
- <a href="#tab-exclude" class="nav-tab">Exclude Objects</a>
144
- <!--<a href="#adapter" class="nav-tab">Data Storage Adapter</a>-->
145
- </h2>
146
- <script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"/></script>
147
- <form id="audit-log-settings" method="post">
148
- <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
149
- <input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
150
- <?php wp_nonce_field('wsal-settings'); ?>
151
-
152
- <div id="audit-log-adverts">
153
- <a href="http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/?utm_source=plugin&utm_medium=settingspage&utm_campaign=notifications">
154
- <img src="<?php echo $this->_plugin->GetBaseUrl(); ?>/img/notifications_250x150.gif" width="250" height="150" alt=""/>
155
- </a>
156
- <a href="http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/?utm_source=plugin&utm_medium=settingspage&utm_campaign=search">
157
- <img src="<?php echo $this->_plugin->GetBaseUrl(); ?>/img/search_250x150.gif" width="250" height="150" alt=""/>
158
- </a>
159
- <a href="http://www.wpsecurityauditlog.com/extensions/compliance-reports-add-on-for-wordpress/?utm_source=plugin&utm_medium=settingspage&utm_campaign=reports">
160
- <img src="<?php echo $this->_plugin->GetBaseUrl(); ?>/img/reporting_250x150.gif" width="250" height="150" alt=""/>
161
- </a>
162
- </div>
163
- <div class="nav-tabs">
164
- <table class="form-table wsal-tab widefat" id="tab-general">
165
- <tbody>
166
- <tr>
167
- <th><label for="delete1"><?php _e('Security Alerts Pruning', 'wp-security-audit-log'); ?></label></th>
168
- <td>
169
- <fieldset>
170
- <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
171
- <?php $nbld = !($this->_plugin->settings->IsPruningDateEnabled() || $this->_plugin->settings->IsPruningLimitEnabled()); ?>
172
- <label for="delete0">
173
- <input type="radio" id="delete0" name="PruneBy" value="" <?php if($nbld)echo 'checked="checked"'; ?>/>
174
- <?php echo __('None', 'wp-security-audit-log'); ?>
175
- </label>
176
- </fieldset>
177
- <fieldset>
178
- <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
179
- <?php $nbld = $this->_plugin->settings->IsPruningDateEnabled(); ?>
180
- <label for="delete1">
181
- <input type="radio" id="delete1" name="PruneBy" value="date" <?php if($nbld)echo 'checked="checked"'; ?>/>
182
- <?php echo __('Delete alerts older than', 'wp-security-audit-log'); ?>
183
- </label>
184
- <input type="text" id="PruningDate" name="PruningDate" placeholder="<?php echo $text; ?>"
185
- value="<?php echo esc_attr($this->_plugin->settings->GetPruningDate()); ?>"
186
- onfocus="jQuery('#delete1').attr('checked', true);"/>
187
- <span> <?php echo $text; ?></span>
188
- </fieldset>
189
- <fieldset>
190
- <?php $text = __('(eg: 80)', 'wp-security-audit-log'); ?>
191
- <?php $nbld = $this->_plugin->settings->IsPruningLimitEnabled(); ?>
192
- <label for="delete2">
193
- <input type="radio" id="delete2" name="PruneBy" value="limit" <?php if($nbld)echo 'checked="checked"'; ?>/>
194
- <?php echo __('Keep up to', 'wp-security-audit-log'); ?>
195
- </label>
196
- <input type="text" id="PruningLimit" name="PruningLimit" placeholder="<?php echo $text;?>"
197
- value="<?php echo esc_attr($this->_plugin->settings->GetPruningLimit()); ?>"
198
- onfocus="jQuery('#delete2').attr('checked', true);"/>
199
- <?php echo __('alerts', 'wp-security-audit-log'); ?>
200
- <span><?php echo $text; ?></span>
201
- </fieldset>
202
- <p class="description"><?php
203
- echo __('Next Scheduled Cleanup is in ', 'wp-security-audit-log');
204
- echo human_time_diff(current_time('timestamp'), $next = wp_next_scheduled('wsal_cleanup'));
205
- echo '<!-- ' . date('dMy H:i:s', $next) . ' --> ';
206
- echo sprintf(
207
- __('(or %s)', 'wp-security-audit-log'),
208
- '<a href="' . admin_url('admin-ajax.php?action=AjaxRunCleanup') . '">' . __('Run Manually', 'wp-security-audit-log') . '</a>'
209
- );
210
- ?></p>
211
- </td>
212
- </tr>
213
- <tr>
214
- <th><label for="dwoption_on"><?php _e('Alerts Dashboard Widget', 'wp-security-audit-log'); ?></label></th>
215
- <td>
216
- <fieldset>
217
- <?php $dwe = $this->_plugin->settings->IsWidgetsEnabled(); ?>
218
- <label for="dwoption_on">
219
- <input type="radio" name="EnableDashboardWidgets" id="dwoption_on" style="margin-top: 2px;" <?php if($dwe)echo 'checked="checked"'; ?> value="1">
220
- <span><?php _e('On', 'wp-security-audit-log'); ?></span>
221
- </label>
222
- <br/>
223
- <label for="dwoption_off">
224
- <input type="radio" name="EnableDashboardWidgets" id="dwoption_off" style="margin-top: 2px;" <?php if(!$dwe)echo 'checked="checked"'; ?> value="0">
225
- <span><?php _e('Off', 'wp-security-audit-log'); ?></span>
226
- </label>
227
- <br/>
228
- <p class="description"><?php
229
- echo sprintf(
230
- __('Display a dashboard widget with the latest %d security alerts.', 'wp-security-audit-log'),
231
- $this->_plugin->settings->GetDashboardWidgetMaxAlerts()
232
- );
233
- ?></p>
234
- </fieldset>
235
- </td>
236
- </tr>
237
- <tr>
238
- <th><label for="pioption_on"><?php _e('Reverse Proxy / Firewall Options', 'wp-security-audit-log'); ?></label></th>
239
- <td>
240
- <fieldset>
241
- <label for="EnableProxyIpCapture">
242
- <input type="checkbox" name="EnableProxyIpCapture" value="1" id="EnableProxyIpCapture"<?php
243
- if($this->_plugin->settings->IsMainIPFromProxy())echo ' checked="checked"';
244
- ?>/> <?php _e('WordPress running behind firewall or proxy', 'wp-security-audit-log'); ?><br/>
245
- <span class="description"><?php _e('Enable this option if your WordPress is running behind a firewall or reverse proxy. When this option is enabled the plugin will retrieve the user\'s IP address from the proxy header.', 'wp-security-audit-log'); ?></span>
246
- </label>
247
- <br/>
248
- <label for="EnableIpFiltering">
249
- <input type="checkbox" name="EnableIpFiltering" value="1" id="EnableIpFiltering"<?php
250
- if($this->_plugin->settings->IsInternalIPsFiltered())echo ' checked="checked"';
251
- ?>/> <?php _e('Filter Internal IP Addresses', 'wp-security-audit-log'); ?><br/>
252
- <span class="description"><?php _e('Enable this option to filter internal IP addresses from the proxy headers.', 'wp-security-audit-log'); ?></span>
253
- </label>
254
- </fieldset>
255
- </td>
256
- </tr>
257
- <tr>
258
- <th><label for="ViewerQueryBox"><?php _e('Can View Alerts', 'wp-security-audit-log'); ?></label></th>
259
- <td>
260
- <fieldset>
261
- <input type="text" id="ViewerQueryBox" style="float: left; display: block; width: 250px;">
262
- <input type="button" id="ViewerQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
263
- <br style="clear: both;"/>
264
- <p class="description"><?php
265
- _e('Users and Roles in this list can view the security alerts', 'wp-security-audit-log');
266
- ?></p>
267
- <div id="ViewerList"><?php
268
- foreach($this->_plugin->settings->GetAllowedPluginViewers() as $item){
269
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
270
- <input type="hidden" name="Viewers[]" value="<?php echo esc_attr($item); ?>"/>
271
- <?php echo esc_html($item); ?>
272
- <a href="javascript:;" title="Remove">&times;</a>
273
- </span><?php
274
- }
275
- ?></div>
276
- </fieldset>
277
- </td>
278
- </tr>
279
- <tr>
280
- <th><label for="EditorQueryBox"><?php _e('Can Manage Plugin', 'wp-security-audit-log'); ?></label></th>
281
- <td>
282
- <fieldset>
283
- <input type="text" id="EditorQueryBox" style="float: left; display: block; width: 250px;">
284
- <input type="button" id="EditorQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
285
- <br style="clear: both;"/>
286
- <p class="description"><?php
287
- _e('Users and Roles in this list can manage the plugin settings', 'wp-security-audit-log');
288
- ?></p>
289
- <div id="EditorList"><?php
290
- foreach($this->_plugin->settings->GetAllowedPluginEditors() as $item){
291
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
292
- <input type="hidden" name="Editors[]" value="<?php echo esc_attr($item); ?>"/>
293
- <?php echo esc_html($item); ?>
294
- <a href="javascript:;" title="Remove">&times;</a>
295
- </span><?php
296
- }
297
- ?></div>
298
- </fieldset>
299
- </td>
300
- </tr>
301
- <tr>
302
- <th><label for="RestrictAdmins"><?php _e('Restrict Plugin Access', 'wp-security-audit-log'); ?></label></th>
303
- <td>
304
- <fieldset>
305
- <input type="hidden" id="RestrictAdminsDefaultUser" value="<?php echo esc_attr(wp_get_current_user()->user_login); ?>"/>
306
- <label for="RestrictAdmins">
307
- <?php $ira = $this->_plugin->settings->IsRestrictAdmins(); ?>
308
- <input type="checkbox" name="RestrictAdmins" id="RestrictAdmins"<?php if($ira)echo ' checked="checked"'; ?>/>
309
- <span class="description">
310
- <?php _e('By default all the administrators on this WordPress have access to manage this plugin.<br/>By enabling this option only the users specified in the two options above and your username will have access to view alerts and manage this plugin.', 'wp-security-audit-log'); ?>
311
- </span>
312
- </label>
313
- </fieldset>
314
- </td>
315
- </tr>
316
- <tr>
317
- <th><label for="aroption_on"><?php _e('Refresh Audit Log Viewer', 'wp-security-audit-log'); ?></label></th>
318
- <td>
319
- <fieldset>
320
- <?php $are = $this->_plugin->settings->IsRefreshAlertsEnabled(); ?>
321
- <label for="aroption_on">
322
- <input type="radio" name="EnableAuditViewRefresh" id="aroption_on" style="margin-top: 2px;" <?php if($are)echo 'checked="checked"'; ?> value="1">
323
- <span><?php _e('Automatic', 'wp-security-audit-log'); ?></span>
324
- </label>
325
- <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer as soon as there are new alerts.', 'wp-security-audit-log'); ?></span>
326
- <br/>
327
- <label for="aroption_off">
328
- <input type="radio" name="EnableAuditViewRefresh" id="aroption_off" style="margin-top: 2px;" <?php if(!$are)echo 'checked="checked"'; ?> value="0">
329
- <span><?php _e('Manual', 'wp-security-audit-log'); ?></span>
330
- </label>
331
- <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer only when the page is reloaded.', 'wp-security-audit-log'); ?></span>
332
- <br/>
333
- </fieldset>
334
- </td>
335
- </tr>
336
- <tr>
337
- <th><label for="datetime_format_24"><?php _e('Alerts Time Format', 'wp-security-audit-log'); ?></label></th>
338
- <td>
339
- <fieldset>
340
- <?php $datetime = $this->_plugin->settings->GetDatetimeFormat(); ?>
341
- <label for="datetime_format_24">
342
- <input type="radio" name="DatetimeFormat" id="datetime_format_24" style="margin-top: 2px;" <?php if($datetime)echo 'checked="checked"'; ?> value="1">
343
- <span><?php _e('24 hours', 'wp-security-audit-log'); ?></span>
344
- </label>
345
- <br/>
346
- <label for="datetime_format_default">
347
- <input type="radio" name="DatetimeFormat" id="datetime_format_default" style="margin-top: 2px;" <?php if(!$datetime)echo 'checked="checked"'; ?> value="0">
348
- <span><?php _e('AM/PM', 'wp-security-audit-log'); ?></span>
349
- </label>
350
- <br/>
351
- </fieldset>
352
- </td>
353
- </tr>
354
- <tr>
355
- <th><label for="timezone-default"><?php _e('Alerts Timestamp', 'wp-security-audit-log'); ?></label></th>
356
- <td>
357
- <fieldset>
358
- <?php $timezone = $this->_plugin->settings->GetTimezone(); ?>
359
- <label for="timezone-default">
360
- <input type="radio" name="Timezone" id="timezone-default" style="margin-top: 2px;" <?php if(!$timezone)echo 'checked="checked"'; ?> value="0">
361
- <span><?php _e('UTC', 'wp-security-audit-log'); ?></span>
362
- </label>
363
- <br/>
364
- <label for="timezone">
365
- <input type="radio" name="Timezone" id="timezone" style="margin-top: 2px;" <?php if($timezone)echo 'checked="checked"'; ?> value="1">
366
- <span><?php _e('WordPress\' timezone', 'wp-security-audit-log'); ?></span>
367
- </label>
368
- <br/>
369
- <span class="description"><?php _e('Select which timestamp should the alerts have in the Audit Log viewer. Note that the WordPress\' timezone might be different from that of the server.', 'wp-security-audit-log'); ?></span>
370
- </fieldset>
371
- </td>
372
- </tr>
373
- <tr>
374
- <th><label for="columns"><?php _e('Audit Log Columns Selection', 'wp-security-audit-log'); ?></label></th>
375
- <td>
376
- <fieldset>
377
- <?php $columns = $this->_plugin->settings->GetColumns(); ?>
378
- <?php foreach ($columns as $key => $value) { ?>
379
- <label for="columns">
380
- <input type="checkbox" name="Columns[<?php echo $key; ?>]" id="<?php echo $key; ?>" class="sel-columns" style="margin-top: 2px;" <?php if ($value == '1') echo 'checked="checked"'; ?> value="1">
381
- <span><?php echo ucwords(str_replace("_", " ", $key)); ?></span>
382
- </label>
383
- <br/>
384
- <?php } ?>
385
- <span class="description"><?php _e('When you disable any of the above such details won’t be shown in the Audit Log
386
- viewer though the plugin will still record such information in the database.', 'wp-security-audit-log'); ?></span>
387
- </fieldset>
388
- </td>
389
- </tr>
390
- <tr>
391
- <th><label><?php _e('Developer Options', 'wp-security-audit-log'); ?></label></th>
392
- <td>
393
- <fieldset>
394
- <?php $any = $this->_plugin->settings->IsAnyDevOptionEnabled(); ?>
395
- <a href="javascript:;" style="<?php if($any)echo 'display: none;'; ?>"
396
- onclick="jQuery(this).hide().next().show();">Show Developer Options</a>
397
- <div style="<?php if(!$any)echo 'display: none;'; ?>">
398
- <p style="border-left: 3px solid #FFD000; padding: 2px 8px; margin-left: 6px; margin-bottom: 16px;"><?php
399
- _e('Only enable these options on testing, staging and development websites. Enabling any of the settings below on LIVE websites may cause unintended side-effects including degraded performance.', 'wp-security-audit-log');
400
- ?></p><?php
401
- foreach (array(
402
- WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array(
403
- __('Data Inspector', 'wp-security-audit-log'),
404
- __('View data logged for each triggered alert.', 'wp-security-audit-log')
405
- ),
406
- WSAL_Settings::OPT_DEV_PHP_ERRORS => array(
407
- __('PHP Errors', 'wp-security-audit-log'),
408
- __('Enables sensor for alerts generated from PHP.', 'wp-security-audit-log')
409
- ),
410
- WSAL_Settings::OPT_DEV_REQUEST_LOG => array(
411
- __('Request Log', 'wp-security-audit-log'),
412
- __('Enables logging request to file.', 'wp-security-audit-log')
413
- ),
414
- WSAL_Settings::OPT_DEV_BACKTRACE_LOG => array(
415
- __('Backtrace', 'wp-security-audit-log'),
416
- __('Log full backtrace for PHP-generated alerts.', 'wp-security-audit-log')
417
- ),
418
- ) as $opt => $info) {
419
- ?><label for="devoption_<?php echo $opt; ?>">
420
- <input type="checkbox" name="DevOptions[]" id="devoption_<?php echo $opt; ?>" <?php
421
- if($this->_plugin->settings->IsDevOptionEnabled($opt))echo 'checked="checked"'; ?> value="<?php echo $opt; ?>">
422
- <span><?php echo $info[0]; ?></span>
423
- <?php if (isset($info[1]) && $info[1]) { ?>
424
- <span class="description"> &mdash; <?php echo $info[1]; ?></span>
425
- <?php }
426
- ?></label><br/><?php
427
- }
428
- ?></div>
429
- </fieldset>
430
- </td>
431
- </tr>
432
-
433
- <tr>
434
- <th><label for="Incognito"><?php _e('Hide Plugin in Plugins Page', 'wp-security-audit-log'); ?></label></th>
435
- <td>
436
- <fieldset>
437
- <label for="Incognito">
438
- <input type="checkbox" name="Incognito" value="1" id="Incognito"<?php
439
- if ($this->_plugin->settings->IsIncognito()) echo ' checked="checked"';
440
- ?>/> <?php _e('Hide', 'wp-security-audit-log'); ?>
441
- </label>
442
- <br/>
443
- <span class="description">
444
- <?php _e('To manually revert this setting set the value of option wsal-hide-plugin to 0 in the wp_options table.', 'wp-security-audit-log'); ?>
445
- </span>
446
- </fieldset>
447
- </td>
448
- </tr>
449
- <tr>
450
- <th><label for="DeleteData"><?php _e('Disable Alerts for WordPress Background Activity', 'wp-security-audit-log'); ?></label></th>
451
- <td>
452
- <fieldset>
453
- <label for="WPBackend">
454
- <input type="checkbox" name="WPBackend" value="1" id="WPBackend" <?php
455
- if ($this->_plugin->settings->IsWPBackend()) echo ' checked="checked"';
456
- ?>/> <?php _e('Hide activity', 'wp-security-audit-log'); ?>
457
- </label>
458
- <br/>
459
- <span class="description">
460
- <?php _e('For example do not raise an alert when WordPress deletes the auto drafts.', 'wp-security-audit-log'); ?>
461
- </span>
462
- </fieldset>
463
- </td>
464
- </tr>
465
- <tr>
466
- <th><label for="DeleteData"><?php _e('Remove Data on Uninstall', 'wp-security-audit-log'); ?></label></th>
467
- <td>
468
- <fieldset>
469
- <label for="DeleteData">
470
- <input type="checkbox" name="DeleteData" value="1" id="DeleteData" onclick="return delete_confirm(this);"<?php
471
- if ($this->_plugin->settings->IsDeleteData()) echo ' checked="checked"';
472
- ?>/> <span class="description">Check this box if you would like remove all data when the plugin is deleted.</span>
473
- </label>
474
- </fieldset>
475
- </td>
476
- </tr>
477
- </tbody>
478
- </table>
479
- <!-- End general Tab-->
480
- <table class="form-table wsal-tab widefat" id="tab-exclude">
481
- <tbody>
482
- <tr>
483
- <th><h2>Users &amp; Roles</h2></th>
484
- </tr>
485
- <tr>
486
- <td colspan="2">Any of the users and roles listed in the below options will be excluded from monitoring. This means that any change they do will not be logged.</td>
487
- </tr>
488
- <tr>
489
- <th><label for="ExUserQueryBox"><?php _e('Excluded Users', 'wp-security-audit-log'); ?></label></th>
490
- <td>
491
- <fieldset>
492
- <input type="text" id="ExUserQueryBox" style="float: left; display: block; width: 250px;">
493
- <input type="button" id="ExUserQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
494
- <br style="clear: both;"/>
495
- <div id="ExUserList"><?php
496
- foreach($this->_plugin->settings->GetExcludedMonitoringUsers() as $item){
497
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
498
- <input type="hidden" name="ExUsers[]" value="<?php echo esc_attr($item); ?>"/>
499
- <?php echo esc_html($item); ?>
500
- <a href="javascript:;" title="Remove">&times;</a>
501
- </span><?php
502
- }
503
- ?></div>
504
- </fieldset>
505
- </td>
506
- </tr>
507
- <tr>
508
- <th><label for="ExRoleQueryBox"><?php _e('Excluded Roles', 'wp-security-audit-log'); ?></label></th>
509
- <td>
510
- <fieldset>
511
- <input type="text" id="ExRoleQueryBox" style="float: left; display: block; width: 250px;">
512
- <input type="button" id="ExRoleQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
513
- <br style="clear: both;"/>
514
- <div id="ExRoleList"><?php
515
- foreach($this->_plugin->settings->GetExcludedMonitoringRoles() as $item){
516
- ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
517
- <input type="hidden" name="ExRoles[]" value="<?php echo esc_attr($item); ?>"/>
518
- <?php echo esc_html($item); ?>
519
- <a href="javascript:;" title="Remove">&times;</a>
520
- </span><?php
521
- }
522
- ?></div>
523
- </fieldset>
524
- </td>
525
- </tr>
526
- <tr>
527
- <th><h2>Custom Fields</h2></th>
528
- </tr>
529
- <tr>
530
- <td colspan="2">Any of the custom fields listed below will be excluded from monitoring. This means that if they are changed or updated the plugin will not log such activity.</td>
531
- </tr>
532
- <tr>
533
- <th><label for="CustomQueryBox"><?php _e('Excluded Custom Fields', 'wp-security-audit-log'); ?></label></th>
534
- <td>
535
- <fieldset>
536
- <input type="text" id="CustomQueryBox" style="float: left; display: block; width: 250px;">
537
- <input type="button" id="CustomQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
538
- <br style="clear: both;"/>
539
- <div id="CustomList">
540
- <?php foreach ($this->_plugin->settings->GetExcludedMonitoringCustom() as $item) { ?>
541
- <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
542
- <input type="hidden" name="Customs[]" value="<?php echo esc_attr($item); ?>"/>
543
- <?php echo esc_html($item); ?>
544
- <a href="javascript:;" title="Remove">&times;</a>
545
- </span>
546
- <?php } ?>
547
- </div>
548
- </fieldset>
549
- </td>
550
- </tr>
551
- <tr>
552
- <th><h2>IP Addresses</h2></th>
553
- </tr>
554
- <tr>
555
- <td colspan="2">Any of the IP addresses listed below will be excluded from monitoring. This means that all activity from such IP address will not be recorded.</td>
556
- </tr>
557
- <tr>
558
- <th><label for="IpAddrQueryBox"><?php _e('Excluded IP Addresses', 'wp-security-audit-log'); ?></label></th>
559
- <td>
560
- <fieldset>
561
- <input type="text" id="IpAddrQueryBox" style="float: left; display: block; width: 250px;">
562
- <input type="button" id="IpAddrQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
563
- <br style="clear: both;"/>
564
- <div id="IpAddrList">
565
- <?php foreach ($this->_plugin->settings->GetExcludedMonitoringIP() as $item) { ?>
566
- <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
567
- <input type="hidden" name="IpAddrs[]" value="<?php echo esc_attr($item); ?>"/>
568
- <?php echo esc_html($item); ?>
569
- <a href="javascript:;" title="Remove">&times;</a>
570
- </span>
571
- <?php } ?>
572
- </div>
573
- </fieldset>
574
- </td>
575
- </tr>
576
- </tbody>
577
- </table>
578
- </div>
579
- <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"></p>
580
- </form>
581
- <script type="text/javascript">
582
- <!--
583
- function delete_confirm(elementRef)
584
- {
585
- if ( elementRef.checked )
586
- {
587
- if ( window.confirm('Do you want remove all data when the plugin is deleted?') == false )
588
- elementRef.checked = false;
589
- }
590
- }
591
- // -->
592
- </script><?php
593
- }
594
-
595
- public function Header()
596
- {
597
- wp_enqueue_style(
598
- 'settings',
599
- $this->_plugin->GetBaseUrl() . '/css/settings.css',
600
- array(),
601
- filemtime($this->_plugin->GetBaseDir() . '/css/settings.css')
602
- );
603
- ?><style type="text/css">
604
- .wsal-tab {
605
- display: none;
606
- }
607
- .wsal-tab tr.alert-incomplete td {
608
- color: #9BE;
609
- }
610
- .wsal-tab tr.alert-unavailable td {
611
- color: #CCC;
612
- }
613
- </style><?php
614
- }
615
-
616
- public function Footer()
617
- {
618
- wp_enqueue_script(
619
- 'settings',
620
- $this->_plugin->GetBaseUrl() . '/js/settings.js',
621
- array(),
622
- filemtime($this->_plugin->GetBaseDir() . '/js/settings.js')
623
- );
624
- ?><script type="text/javascript">
625
- jQuery(document).ready(function(){
626
- // tab handling code
627
- jQuery('#wsal-tabs>a').click(function(){
628
- jQuery('#wsal-tabs>a').removeClass('nav-tab-active');
629
- jQuery('table.wsal-tab').hide();
630
- jQuery(jQuery(this).addClass('nav-tab-active').attr('href')).show();
631
- });
632
- // show relevant tab
633
- var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
634
- if (hashlink.length) {
635
- hashlink.click();
636
- } else {
637
- jQuery('#wsal-tabs>a:first').click();
638
- }
639
-
640
- jQuery(".sel-columns").change(function(){
641
- var notChecked = 1;
642
- jQuery(".sel-columns").each(function(){
643
- if(this.checked) notChecked = 0;
644
- })
645
- if(notChecked == 1){
646
- alert("You have to select at least one column!");
647
- }
648
- });
649
- });
650
- </script><?php
651
- }
652
-
653
- public function AjaxGetAllUsers()
654
- {
655
- if (!$this->_plugin->settings->CurrentUserCan('view')) {
656
- die('Access Denied.');
657
- }
658
- $users = array();
659
- foreach (get_users() as $user) {
660
- if (strpos($user->user_login, $_GET['term']) !== false) {
661
- array_push($users, $user->user_login);
662
- }
663
- }
664
- echo json_encode($users);
665
- exit;
666
- }
667
-
668
- public function AjaxGetAllRoles()
669
- {
670
- if (!$this->_plugin->settings->CurrentUserCan('view')) {
671
- die('Access Denied.');
672
- }
673
- $roles = array();
674
- foreach (get_editable_roles() as $role_name => $role_info) {
675
- if (strpos($role_name, $_GET['term']) !== false) {
676
- array_push($roles, $role_name);
677
- }
678
- }
679
- echo json_encode($roles);
680
- exit;
681
- }
682
- }
1
+ <?php
2
+ class WSAL_Views_Settings extends WSAL_AbstractView
3
+ {
4
+
5
+ public $adapterMsg = '';
6
+
7
+ public function __construct(WpSecurityAuditLog $plugin)
8
+ {
9
+ parent::__construct($plugin);
10
+
11
+ add_action('wp_ajax_AjaxCheckSecurityToken', array($this, 'AjaxCheckSecurityToken'));
12
+ add_action('wp_ajax_AjaxRunCleanup', array($this, 'AjaxRunCleanup'));
13
+ add_action('wp_ajax_AjaxGetAllUsers', array($this, 'AjaxGetAllUsers'));
14
+ add_action('wp_ajax_AjaxGetAllRoles', array($this, 'AjaxGetAllRoles'));
15
+ }
16
+
17
+ public function HasPluginShortcutLink(){
18
+ return true;
19
+ }
20
+
21
+ public function GetTitle() {
22
+ return __('Settings', 'wp-security-audit-log');
23
+ }
24
+
25
+ public function GetIcon() {
26
+ return 'dashicons-admin-generic';
27
+ }
28
+
29
+ public function GetName() {
30
+ return __('Settings', 'wp-security-audit-log');
31
+ }
32
+
33
+ public function GetWeight() {
34
+ return 3;
35
+ }
36
+
37
+ protected function GetTokenType($token){
38
+ $users = array();
39
+ foreach (get_users('blog_id=0&fields[]=user_login') as $obj)
40
+ $users[] = $obj->user_login;
41
+ $roles = array_keys(get_editable_roles());
42
+
43
+ if(in_array($token, $users))return 'user';
44
+ if(in_array($token, $roles))return 'role';
45
+ return 'other';
46
+ }
47
+
48
+ protected function Save()
49
+ {
50
+ check_admin_referer('wsal-settings');
51
+ $this->_plugin->settings->SetPruningDateEnabled($_REQUEST['PruneBy'] == 'date');
52
+ $this->_plugin->settings->SetPruningDate($_REQUEST['PruningDate']);
53
+ $this->_plugin->settings->SetPruningLimitEnabled($_REQUEST['PruneBy'] == 'limit');
54
+ $this->_plugin->settings->SetPruningLimit($_REQUEST['PruningLimit']);
55
+ $this->_plugin->settings->SetWidgetsEnabled($_REQUEST['EnableDashboardWidgets']);
56
+ $this->_plugin->settings->SetAllowedPluginViewers(isset($_REQUEST['Viewers']) ? $_REQUEST['Viewers'] : array());
57
+ $this->_plugin->settings->SetAllowedPluginEditors(isset($_REQUEST['Editors']) ? $_REQUEST['Editors'] : array());
58
+
59
+ $this->_plugin->settings->SetExcludedMonitoringUsers(isset($_REQUEST['ExUsers']) ? $_REQUEST['ExUsers'] : array());
60
+ $this->_plugin->settings->SetExcludedMonitoringRoles(isset($_REQUEST['ExRoles']) ? $_REQUEST['ExRoles'] : array());
61
+ $this->_plugin->settings->SetExcludedMonitoringCustom(isset($_REQUEST['Customs']) ? $_REQUEST['Customs'] : array());
62
+ $this->_plugin->settings->SetExcludedMonitoringIP(isset($_REQUEST['IpAddrs']) ? $_REQUEST['IpAddrs'] : array());
63
+
64
+ $this->_plugin->settings->SetRestrictAdmins(isset($_REQUEST['RestrictAdmins']));
65
+ $this->_plugin->settings->SetRefreshAlertsEnabled($_REQUEST['EnableAuditViewRefresh']);
66
+ $this->_plugin->settings->SetMainIPFromProxy(isset($_REQUEST['EnableProxyIpCapture']));
67
+ $this->_plugin->settings->SetInternalIPsFiltering(isset($_REQUEST['EnableIpFiltering']));
68
+ $this->_plugin->settings->SetIncognito(isset($_REQUEST['Incognito']));
69
+ $this->_plugin->settings->SetDeleteData(isset($_REQUEST['DeleteData']));
70
+ $this->_plugin->settings->SetDatetimeFormat($_REQUEST['DatetimeFormat']);
71
+ $this->_plugin->settings->SetTimezone($_REQUEST['Timezone']);
72
+ $this->_plugin->settings->SetWPBackend(isset($_REQUEST['WPBackend']));
73
+ if (!empty($_REQUEST['Columns'])) {
74
+ $this->_plugin->settings->SetColumns($_REQUEST['Columns']);
75
+ }
76
+ $this->_plugin->settings->ClearDevOptions();
77
+
78
+ if (isset($_REQUEST['DevOptions'])) {
79
+ foreach ($_REQUEST['DevOptions'] as $opt) {
80
+ $this->_plugin->settings->SetDevOptionEnabled($opt, true);
81
+ }
82
+ }
83
+
84
+ // Database Adapter Settings
85
+ // Temporarily not used
86
+ /* Check Adapter config */
87
+ if (!empty($_REQUEST["AdapterUser"]) && ($_REQUEST['AdapterUser'] != '') && ($_REQUEST['AdapterName'] != '') && ($_REQUEST['AdapterHostname'] != '')) {
88
+ WSAL_Connector_ConnectorFactory::CheckConfig(
89
+ trim($_REQUEST['AdapterType']),
90
+ trim($_REQUEST['AdapterUser']),
91
+ trim($_REQUEST['AdapterPassword']),
92
+ trim($_REQUEST['AdapterName']),
93
+ trim($_REQUEST['AdapterHostname']),
94
+ trim($_REQUEST['AdapterBasePrefix'])
95
+ );
96
+
97
+ /* Setting Adapter config */
98
+ $this->_plugin->settings->SetAdapterConfig('adapter-type', $_REQUEST['AdapterType']);
99
+ $this->_plugin->settings->SetAdapterConfig('adapter-user', $_REQUEST['AdapterUser']);
100
+ $this->_plugin->settings->SetAdapterConfig('adapter-password', $_REQUEST['AdapterPassword']);
101
+ $this->_plugin->settings->SetAdapterConfig('adapter-name', $_REQUEST['AdapterName']);
102
+ $this->_plugin->settings->SetAdapterConfig('adapter-hostname', $_REQUEST['AdapterHostname']);
103
+ $this->_plugin->settings->SetAdapterConfig('adapter-base-prefix', $_REQUEST['AdapterBasePrefix']);
104
+ }
105
+ }
106
+
107
+ public function AjaxCheckSecurityToken()
108
+ {
109
+ if (!$this->_plugin->settings->CurrentUserCan('view'))
110
+ die('Access Denied.');
111
+ if (!isset($_REQUEST['token']))
112
+ die('Token parameter expected.');
113
+ die($this->GetTokenType($_REQUEST['token']));
114
+ }
115
+
116
+ public function AjaxRunCleanup()
117
+ {
118
+ if (!$this->_plugin->settings->CurrentUserCan('view'))
119
+ die('Access Denied.');
120
+ $this->_plugin->CleanUp();
121
+ wp_redirect($this->GetUrl());
122
+ exit;
123
+ }
124
+
125
+ public function Render()
126
+ {
127
+ if (!$this->_plugin->settings->CurrentUserCan('edit')) {
128
+ wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
129
+ }
130
+ if (isset($_POST['submit'])) {
131
+ try {
132
+ $this->Save();
133
+ ?><div class="updated">
134
+ <p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p>
135
+ </div><?php
136
+ } catch (Exception $ex) {
137
+ ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
138
+ }
139
+ }
140
+ ?>
141
+ <h2 id="wsal-tabs" class="nav-tab-wrapper">
142
+ <a href="#tab-general" class="nav-tab">General</a>
143
+ <a href="#tab-exclude" class="nav-tab">Exclude Objects</a>
144
+ <!--<a href="#adapter" class="nav-tab">Data Storage Adapter</a>-->
145
+ </h2>
146
+ <script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"/></script>
147
+ <form id="audit-log-settings" method="post">
148
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
149
+ <input type="hidden" id="ajaxurl" value="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>" />
150
+ <?php wp_nonce_field('wsal-settings'); ?>
151
+
152
+ <div id="audit-log-adverts">
153
+ <a href="http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/?utm_source=plugin&utm_medium=settingspage&utm_campaign=notifications">
154
+ <img src="<?php echo $this->_plugin->GetBaseUrl(); ?>/img/notifications_250x150.gif" width="250" height="150" alt=""/>
155
+ </a>
156
+ <a href="http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/?utm_source=plugin&utm_medium=settingspage&utm_campaign=search">
157
+ <img src="<?php echo $this->_plugin->GetBaseUrl(); ?>/img/search_250x150.gif" width="250" height="150" alt=""/>
158
+ </a>
159
+ <a href="http://www.wpsecurityauditlog.com/extensions/compliance-reports-add-on-for-wordpress/?utm_source=plugin&utm_medium=settingspage&utm_campaign=reports">
160
+ <img src="<?php echo $this->_plugin->GetBaseUrl(); ?>/img/reporting_250x150.gif" width="250" height="150" alt=""/>
161
+ </a>
162
+ </div>
163
+ <div class="nav-tabs">
164
+ <table class="form-table wsal-tab widefat" id="tab-general">
165
+ <tbody>
166
+ <tr>
167
+ <th><label for="delete1"><?php _e('Security Alerts Pruning', 'wp-security-audit-log'); ?></label></th>
168
+ <td>
169
+ <fieldset>
170
+ <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
171
+ <?php $nbld = !($this->_plugin->settings->IsPruningDateEnabled() || $this->_plugin->settings->IsPruningLimitEnabled()); ?>
172
+ <label for="delete0">
173
+ <input type="radio" id="delete0" name="PruneBy" value="" <?php if($nbld)echo 'checked="checked"'; ?>/>
174
+ <?php echo __('None', 'wp-security-audit-log'); ?>
175
+ </label>
176
+ </fieldset>
177
+ <fieldset>
178
+ <?php $text = __('(eg: 1 month)', 'wp-security-audit-log'); ?>
179
+ <?php $nbld = $this->_plugin->settings->IsPruningDateEnabled(); ?>
180
+ <label for="delete1">
181
+ <input type="radio" id="delete1" name="PruneBy" value="date" <?php if($nbld)echo 'checked="checked"'; ?>/>
182
+ <?php echo __('Delete alerts older than', 'wp-security-audit-log'); ?>
183
+ </label>
184
+ <input type="text" id="PruningDate" name="PruningDate" placeholder="<?php echo $text; ?>"
185
+ value="<?php echo esc_attr($this->_plugin->settings->GetPruningDate()); ?>"
186
+ onfocus="jQuery('#delete1').attr('checked', true);"/>
187
+ <span> <?php echo $text; ?></span>
188
+ </fieldset>
189
+ <fieldset>
190
+ <?php $text = __('(eg: 80)', 'wp-security-audit-log'); ?>
191
+ <?php $nbld = $this->_plugin->settings->IsPruningLimitEnabled(); ?>
192
+ <label for="delete2">
193
+ <input type="radio" id="delete2" name="PruneBy" value="limit" <?php if($nbld)echo 'checked="checked"'; ?>/>
194
+ <?php echo __('Keep up to', 'wp-security-audit-log'); ?>
195
+ </label>
196
+ <input type="text" id="PruningLimit" name="PruningLimit" placeholder="<?php echo $text;?>"
197
+ value="<?php echo esc_attr($this->_plugin->settings->GetPruningLimit()); ?>"
198
+ onfocus="jQuery('#delete2').attr('checked', true);"/>
199
+ <?php echo __('alerts', 'wp-security-audit-log'); ?>
200
+ <span><?php echo $text; ?></span>
201
+ </fieldset>
202
+ <p class="description"><?php
203
+ echo __('Next Scheduled Cleanup is in ', 'wp-security-audit-log');
204
+ echo human_time_diff(current_time('timestamp'), $next = wp_next_scheduled('wsal_cleanup'));
205
+ echo '<!-- ' . date('dMy H:i:s', $next) . ' --> ';
206
+ echo sprintf(
207
+ __('(or %s)', 'wp-security-audit-log'),
208
+ '<a href="' . admin_url('admin-ajax.php?action=AjaxRunCleanup') . '">' . __('Run Manually', 'wp-security-audit-log') . '</a>'
209
+ );
210
+ ?></p>
211
+ </td>
212
+ </tr>
213
+ <tr>
214
+ <th><label for="dwoption_on"><?php _e('Alerts Dashboard Widget', 'wp-security-audit-log'); ?></label></th>
215
+ <td>
216
+ <fieldset>
217
+ <?php $dwe = $this->_plugin->settings->IsWidgetsEnabled(); ?>
218
+ <label for="dwoption_on">
219
+ <input type="radio" name="EnableDashboardWidgets" id="dwoption_on" style="margin-top: 2px;" <?php if($dwe)echo 'checked="checked"'; ?> value="1">
220
+ <span><?php _e('On', 'wp-security-audit-log'); ?></span>
221
+ </label>
222
+ <br/>
223
+ <label for="dwoption_off">
224
+ <input type="radio" name="EnableDashboardWidgets" id="dwoption_off" style="margin-top: 2px;" <?php if(!$dwe)echo 'checked="checked"'; ?> value="0">
225
+ <span><?php _e('Off', 'wp-security-audit-log'); ?></span>
226
+ </label>
227
+ <br/>
228
+ <p class="description"><?php
229
+ echo sprintf(
230
+ __('Display a dashboard widget with the latest %d security alerts.', 'wp-security-audit-log'),
231
+ $this->_plugin->settings->GetDashboardWidgetMaxAlerts()
232
+ );
233
+ ?></p>
234
+ </fieldset>
235
+ </td>
236
+ </tr>
237
+ <tr>
238
+ <th><label for="pioption_on"><?php _e('Reverse Proxy / Firewall Options', 'wp-security-audit-log'); ?></label></th>
239
+ <td>
240
+ <fieldset>
241
+ <label for="EnableProxyIpCapture">
242
+ <input type="checkbox" name="EnableProxyIpCapture" value="1" id="EnableProxyIpCapture"<?php
243
+ if($this->_plugin->settings->IsMainIPFromProxy())echo ' checked="checked"';
244
+ ?>/> <?php _e('WordPress running behind firewall or proxy', 'wp-security-audit-log'); ?><br/>
245
+ <span class="description"><?php _e('Enable this option if your WordPress is running behind a firewall or reverse proxy. When this option is enabled the plugin will retrieve the user\'s IP address from the proxy header.', 'wp-security-audit-log'); ?></span>
246
+ </label>
247
+ <br/>
248
+ <label for="EnableIpFiltering">
249
+ <input type="checkbox" name="EnableIpFiltering" value="1" id="EnableIpFiltering"<?php
250
+ if($this->_plugin->settings->IsInternalIPsFiltered())echo ' checked="checked"';
251
+ ?>/> <?php _e('Filter Internal IP Addresses', 'wp-security-audit-log'); ?><br/>
252
+ <span class="description"><?php _e('Enable this option to filter internal IP addresses from the proxy headers.', 'wp-security-audit-log'); ?></span>
253
+ </label>
254
+ </fieldset>
255
+ </td>
256
+ </tr>
257
+ <tr>
258
+ <th><label for="ViewerQueryBox"><?php _e('Can View Alerts', 'wp-security-audit-log'); ?></label></th>
259
+ <td>
260
+ <fieldset>
261
+ <input type="text" id="ViewerQueryBox" style="float: left; display: block; width: 250px;">
262
+ <input type="button" id="ViewerQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
263
+ <br style="clear: both;"/>
264
+ <p class="description"><?php
265
+ _e('Users and Roles in this list can view the security alerts', 'wp-security-audit-log');
266
+ ?></p>
267
+ <div id="ViewerList"><?php
268
+ foreach($this->_plugin->settings->GetAllowedPluginViewers() as $item){
269
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
270
+ <input type="hidden" name="Viewers[]" value="<?php echo esc_attr($item); ?>"/>
271
+ <?php echo esc_html($item); ?>
272
+ <a href="javascript:;" title="Remove">&times;</a>
273
+ </span><?php
274
+ }
275
+ ?></div>
276
+ </fieldset>
277
+ </td>
278
+ </tr>
279
+ <tr>
280
+ <th><label for="EditorQueryBox"><?php _e('Can Manage Plugin', 'wp-security-audit-log'); ?></label></th>
281
+ <td>
282
+ <fieldset>
283
+ <input type="text" id="EditorQueryBox" style="float: left; display: block; width: 250px;">
284
+ <input type="button" id="EditorQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
285
+ <br style="clear: both;"/>
286
+ <p class="description"><?php
287
+ _e('Users and Roles in this list can manage the plugin settings', 'wp-security-audit-log');
288
+ ?></p>
289
+ <div id="EditorList"><?php
290
+ foreach($this->_plugin->settings->GetAllowedPluginEditors() as $item){
291
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
292
+ <input type="hidden" name="Editors[]" value="<?php echo esc_attr($item); ?>"/>
293
+ <?php echo esc_html($item); ?>
294
+ <a href="javascript:;" title="Remove">&times;</a>
295
+ </span><?php
296
+ }
297
+ ?></div>
298
+ </fieldset>
299
+ </td>
300
+ </tr>
301
+ <tr>
302
+ <th><label for="RestrictAdmins"><?php _e('Restrict Plugin Access', 'wp-security-audit-log'); ?></label></th>
303
+ <td>
304
+ <fieldset>
305
+ <input type="hidden" id="RestrictAdminsDefaultUser" value="<?php echo esc_attr(wp_get_current_user()->user_login); ?>"/>
306
+ <label for="RestrictAdmins">
307
+ <?php $ira = $this->_plugin->settings->IsRestrictAdmins(); ?>
308
+ <input type="checkbox" name="RestrictAdmins" id="RestrictAdmins"<?php if($ira)echo ' checked="checked"'; ?>/>
309
+ <span class="description">
310
+ <?php _e('By default all the administrators on this WordPress have access to manage this plugin.<br/>By enabling this option only the users specified in the two options above and your username will have access to view alerts and manage this plugin.', 'wp-security-audit-log'); ?>
311
+ </span>
312
+ </label>
313
+ </fieldset>
314
+ </td>
315
+ </tr>
316
+ <tr>
317
+ <th><label for="aroption_on"><?php _e('Refresh Audit Log Viewer', 'wp-security-audit-log'); ?></label></th>
318
+ <td>
319
+ <fieldset>
320
+ <?php $are = $this->_plugin->settings->IsRefreshAlertsEnabled(); ?>
321
+ <label for="aroption_on">
322
+ <input type="radio" name="EnableAuditViewRefresh" id="aroption_on" style="margin-top: 2px;" <?php if($are)echo 'checked="checked"'; ?> value="1">
323
+ <span><?php _e('Automatic', 'wp-security-audit-log'); ?></span>
324
+ </label>
325
+ <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer as soon as there are new alerts.', 'wp-security-audit-log'); ?></span>
326
+ <br/>
327
+ <label for="aroption_off">
328
+ <input type="radio" name="EnableAuditViewRefresh" id="aroption_off" style="margin-top: 2px;" <?php if(!$are)echo 'checked="checked"'; ?> value="0">
329
+ <span><?php _e('Manual', 'wp-security-audit-log'); ?></span>
330
+ </label>
331
+ <span class="description"> &mdash; <?php _e('Refresh Audit Log Viewer only when the page is reloaded.', 'wp-security-audit-log'); ?></span>
332
+ <br/>
333
+ </fieldset>
334
+ </td>
335
+ </tr>
336
+ <tr>
337
+ <th><label for="datetime_format_24"><?php _e('Alerts Time Format', 'wp-security-audit-log'); ?></label></th>
338
+ <td>
339
+ <fieldset>
340
+ <?php $datetime = $this->_plugin->settings->GetDatetimeFormat(); ?>
341
+ <label for="datetime_format_24">
342
+ <input type="radio" name="DatetimeFormat" id="datetime_format_24" style="margin-top: 2px;" <?php if($datetime)echo 'checked="checked"'; ?> value="1">
343
+ <span><?php _e('24 hours', 'wp-security-audit-log'); ?></span>
344
+ </label>
345
+ <br/>
346
+ <label for="datetime_format_default">
347
+ <input type="radio" name="DatetimeFormat" id="datetime_format_default" style="margin-top: 2px;" <?php if(!$datetime)echo 'checked="checked"'; ?> value="0">
348
+ <span><?php _e('AM/PM', 'wp-security-audit-log'); ?></span>
349
+ </label>
350
+ <br/>
351
+ </fieldset>
352
+ </td>
353
+ </tr>
354
+ <tr>
355
+ <th><label for="timezone-default"><?php _e('Alerts Timestamp', 'wp-security-audit-log'); ?></label></th>
356
+ <td>
357
+ <fieldset>
358
+ <?php $timezone = $this->_plugin->settings->GetTimezone(); ?>
359
+ <label for="timezone-default">
360
+ <input type="radio" name="Timezone" id="timezone-default" style="margin-top: 2px;" <?php if(!$timezone)echo 'checked="checked"'; ?> value="0">
361
+ <span><?php _e('UTC', 'wp-security-audit-log'); ?></span>
362
+ </label>
363
+ <br/>
364
+ <label for="timezone">
365
+ <input type="radio" name="Timezone" id="timezone" style="margin-top: 2px;" <?php if($timezone)echo 'checked="checked"'; ?> value="1">
366
+ <span><?php _e('WordPress\' timezone', 'wp-security-audit-log'); ?></span>
367
+ </label>
368
+ <br/>
369
+ <span class="description"><?php _e('Select which timestamp should the alerts have in the Audit Log viewer. Note that the WordPress\' timezone might be different from that of the server.', 'wp-security-audit-log'); ?></span>
370
+ </fieldset>
371
+ </td>
372
+ </tr>
373
+ <tr>
374
+ <th><label for="columns"><?php _e('Audit Log Columns Selection', 'wp-security-audit-log'); ?></label></th>
375
+ <td>
376
+ <fieldset>
377
+ <?php $columns = $this->_plugin->settings->GetColumns(); ?>
378
+ <?php foreach ($columns as $key => $value) { ?>
379
+ <label for="columns">
380
+ <input type="checkbox" name="Columns[<?php echo $key; ?>]" id="<?php echo $key; ?>" class="sel-columns" style="margin-top: 2px;" <?php if ($value == '1') echo 'checked="checked"'; ?> value="1">
381
+ <span><?php echo ucwords(str_replace("_", " ", $key)); ?></span>
382
+ </label>
383
+ <br/>
384
+ <?php } ?>
385
+ <span class="description"><?php _e('When you disable any of the above such details won’t be shown in the Audit Log
386
+ viewer though the plugin will still record such information in the database.', 'wp-security-audit-log'); ?></span>
387
+ </fieldset>
388
+ </td>
389
+ </tr>
390
+ <tr>
391
+ <th><label><?php _e('Developer Options', 'wp-security-audit-log'); ?></label></th>
392
+ <td>
393
+ <fieldset>
394
+ <?php $any = $this->_plugin->settings->IsAnyDevOptionEnabled(); ?>
395
+ <a href="javascript:;" style="<?php if($any)echo 'display: none;'; ?>"
396
+ onclick="jQuery(this).hide().next().show();">Show Developer Options</a>
397
+ <div style="<?php if(!$any)echo 'display: none;'; ?>">
398
+ <p style="border-left: 3px solid #FFD000; padding: 2px 8px; margin-left: 6px; margin-bottom: 16px;"><?php
399
+ _e('Only enable these options on testing, staging and development websites. Enabling any of the settings below on LIVE websites may cause unintended side-effects including degraded performance.', 'wp-security-audit-log');
400
+ ?></p><?php
401
+ foreach (array(
402
+ WSAL_Settings::OPT_DEV_DATA_INSPECTOR => array(
403
+ __('Data Inspector', 'wp-security-audit-log'),
404
+ __('View data logged for each triggered alert.', 'wp-security-audit-log')
405
+ ),
406
+ WSAL_Settings::OPT_DEV_PHP_ERRORS => array(
407
+ __('PHP Errors', 'wp-security-audit-log'),
408
+ __('Enables sensor for alerts generated from PHP.', 'wp-security-audit-log')
409
+ ),
410
+ WSAL_Settings::OPT_DEV_REQUEST_LOG => array(
411
+ __('Request Log', 'wp-security-audit-log'),
412
+ __('Enables logging request to file.', 'wp-security-audit-log')
413
+ ),
414
+ WSAL_Settings::OPT_DEV_BACKTRACE_LOG => array(
415
+ __('Backtrace', 'wp-security-audit-log'),
416
+ __('Log full backtrace for PHP-generated alerts.', 'wp-security-audit-log')
417
+ ),
418
+ ) as $opt => $info) {
419
+ ?><label for="devoption_<?php echo $opt; ?>">
420
+ <input type="checkbox" name="DevOptions[]" id="devoption_<?php echo $opt; ?>" <?php
421
+ if($this->_plugin->settings->IsDevOptionEnabled($opt))echo 'checked="checked"'; ?> value="<?php echo $opt; ?>">
422
+ <span><?php echo $info[0]; ?></span>
423
+ <?php if (isset($info[1]) && $info[1]) { ?>
424
+ <span class="description"> &mdash; <?php echo $info[1]; ?></span>
425
+ <?php }
426
+ ?></label><br/><?php
427
+ }
428
+ ?></div>
429
+ </fieldset>
430
+ </td>
431
+ </tr>
432
+
433
+ <tr>
434
+ <th><label for="Incognito"><?php _e('Hide Plugin in Plugins Page', 'wp-security-audit-log'); ?></label></th>
435
+ <td>
436
+ <fieldset>
437
+ <label for="Incognito">
438
+ <input type="checkbox" name="Incognito" value="1" id="Incognito"<?php
439
+ if ($this->_plugin->settings->IsIncognito()) echo ' checked="checked"';
440
+ ?>/> <?php _e('Hide', 'wp-security-audit-log'); ?>
441
+ </label>
442
+ <br/>
443
+ <span class="description">
444
+ <?php _e('To manually revert this setting set the value of option wsal-hide-plugin to 0 in the wp_options table.', 'wp-security-audit-log'); ?>
445
+ </span>
446
+ </fieldset>
447
+ </td>
448
+ </tr>
449
+ <tr>
450
+ <th><label for="DeleteData"><?php _e('Disable Alerts for WordPress Background Activity', 'wp-security-audit-log'); ?></label></th>
451
+ <td>
452
+ <fieldset>
453
+ <label for="WPBackend">
454
+ <input type="checkbox" name="WPBackend" value="1" id="WPBackend" <?php
455
+ if ($this->_plugin->settings->IsWPBackend()) echo ' checked="checked"';
456
+ ?>/> <?php _e('Hide activity', 'wp-security-audit-log'); ?>
457
+ </label>
458
+ <br/>
459
+ <span class="description">
460
+ <?php _e('For example do not raise an alert when WordPress deletes the auto drafts.', 'wp-security-audit-log'); ?>
461
+ </span>
462
+ </fieldset>
463
+ </td>
464
+ </tr>
465
+ <tr>
466
+ <th><label for="DeleteData"><?php _e('Remove Data on Uninstall', 'wp-security-audit-log'); ?></label></th>
467
+ <td>
468
+ <fieldset>
469
+ <label for="DeleteData">
470
+ <input type="checkbox" name="DeleteData" value="1" id="DeleteData" onclick="return delete_confirm(this);"<?php
471
+ if ($this->_plugin->settings->IsDeleteData()) echo ' checked="checked"';
472
+ ?>/> <span class="description">Check this box if you would like remove all data when the plugin is deleted.</span>
473
+ </label>
474
+ </fieldset>
475
+ </td>
476
+ </tr>
477
+ </tbody>
478
+ </table>
479
+ <!-- End general Tab-->
480
+ <table class="form-table wsal-tab widefat" id="tab-exclude">
481
+ <tbody>
482
+ <tr>
483
+ <th><h2>Users &amp; Roles</h2></th>
484
+ </tr>
485
+ <tr>
486
+ <td colspan="2">Any of the users and roles listed in the below options will be excluded from monitoring. This means that any change they do will not be logged.</td>
487
+ </tr>
488
+ <tr>
489
+ <th><label for="ExUserQueryBox"><?php _e('Excluded Users', 'wp-security-audit-log'); ?></label></th>
490
+ <td>
491
+ <fieldset>
492
+ <input type="text" id="ExUserQueryBox" style="float: left; display: block; width: 250px;">
493
+ <input type="button" id="ExUserQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
494
+ <br style="clear: both;"/>
495
+ <div id="ExUserList"><?php
496
+ foreach($this->_plugin->settings->GetExcludedMonitoringUsers() as $item){
497
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
498
+ <input type="hidden" name="ExUsers[]" value="<?php echo esc_attr($item); ?>"/>
499
+ <?php echo esc_html($item); ?>
500
+ <a href="javascript:;" title="Remove">&times;</a>
501
+ </span><?php
502
+ }
503
+ ?></div>
504
+ </fieldset>
505
+ </td>
506
+ </tr>
507
+ <tr>
508
+ <th><label for="ExRoleQueryBox"><?php _e('Excluded Roles', 'wp-security-audit-log'); ?></label></th>
509
+ <td>
510
+ <fieldset>
511
+ <input type="text" id="ExRoleQueryBox" style="float: left; display: block; width: 250px;">
512
+ <input type="button" id="ExRoleQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
513
+ <br style="clear: both;"/>
514
+ <div id="ExRoleList"><?php
515
+ foreach($this->_plugin->settings->GetExcludedMonitoringRoles() as $item){
516
+ ?><span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
517
+ <input type="hidden" name="ExRoles[]" value="<?php echo esc_attr($item); ?>"/>
518
+ <?php echo esc_html($item); ?>
519
+ <a href="javascript:;" title="Remove">&times;</a>
520
+ </span><?php
521
+ }
522
+ ?></div>
523
+ </fieldset>
524
+ </td>
525
+ </tr>
526
+ <tr>
527
+ <th><h2>Custom Fields</h2></th>
528
+ </tr>
529
+ <tr>
530
+ <td colspan="2">Any of the custom fields listed below will be excluded from monitoring. This means that if they are changed or updated the plugin will not log such activity.</td>
531
+ </tr>
532
+ <tr>
533
+ <th><label for="CustomQueryBox"><?php _e('Excluded Custom Fields', 'wp-security-audit-log'); ?></label></th>
534
+ <td>
535
+ <fieldset>
536
+ <input type="text" id="CustomQueryBox" style="float: left; display: block; width: 250px;">
537
+ <input type="button" id="CustomQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
538
+ <br style="clear: both;"/>
539
+ <div id="CustomList">
540
+ <?php foreach ($this->_plugin->settings->GetExcludedMonitoringCustom() as $item) { ?>
541
+ <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
542
+ <input type="hidden" name="Customs[]" value="<?php echo esc_attr($item); ?>"/>
543
+ <?php echo esc_html($item); ?>
544
+ <a href="javascript:;" title="Remove">&times;</a>
545
+ </span>
546
+ <?php } ?>
547
+ </div>
548
+ </fieldset>
549
+ </td>
550
+ </tr>
551
+ <tr>
552
+ <th><h2>IP Addresses</h2></th>
553
+ </tr>
554
+ <tr>
555
+ <td colspan="2">Any of the IP addresses listed below will be excluded from monitoring. This means that all activity from such IP address will not be recorded.</td>
556
+ </tr>
557
+ <tr>
558
+ <th><label for="IpAddrQueryBox"><?php _e('Excluded IP Addresses', 'wp-security-audit-log'); ?></label></th>
559
+ <td>
560
+ <fieldset>
561
+ <input type="text" id="IpAddrQueryBox" style="float: left; display: block; width: 250px;">
562
+ <input type="button" id="IpAddrQueryAdd" style="float: left; display: block;" class="button-primary" value="Add">
563
+ <br style="clear: both;"/>
564
+ <div id="IpAddrList">
565
+ <?php foreach ($this->_plugin->settings->GetExcludedMonitoringIP() as $item) { ?>
566
+ <span class="sectoken-<?php echo $this->GetTokenType($item); ?>">
567
+ <input type="hidden" name="IpAddrs[]" value="<?php echo esc_attr($item); ?>"/>
568
+ <?php echo esc_html($item); ?>
569
+ <a href="javascript:;" title="Remove">&times;</a>
570
+ </span>
571
+ <?php } ?>
572
+ </div>
573
+ </fieldset>
574
+ </td>
575
+ </tr>
576
+ </tbody>
577
+ </table>
578
+ </div>
579
+ <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes"></p>
580
+ </form>
581
+ <script type="text/javascript">
582
+ <!--
583
+ function delete_confirm(elementRef)
584
+ {
585
+ if ( elementRef.checked )
586
+ {
587
+ if ( window.confirm('Do you want remove all data when the plugin is deleted?') == false )
588
+ elementRef.checked = false;
589
+ }
590
+ }
591
+ // -->
592
+ </script><?php
593
+ }
594
+
595
+ public function Header()
596
+ {
597
+ wp_enqueue_style(
598
+ 'settings',
599
+ $this->_plugin->GetBaseUrl() . '/css/settings.css',
600
+ array(),
601
+ filemtime($this->_plugin->GetBaseDir() . '/css/settings.css')
602
+ );
603
+ ?><style type="text/css">
604
+ .wsal-tab {
605
+ display: none;
606
+ }
607
+ .wsal-tab tr.alert-incomplete td {
608
+ color: #9BE;
609
+ }
610
+ .wsal-tab tr.alert-unavailable td {
611
+ color: #CCC;
612
+ }
613
+ </style><?php
614
+ }
615
+
616
+ public function Footer()
617
+ {
618
+ wp_enqueue_script(
619
+ 'settings',
620
+ $this->_plugin->GetBaseUrl() . '/js/settings.js',
621
+ array(),
622
+ filemtime($this->_plugin->GetBaseDir() . '/js/settings.js')
623
+ );
624
+ ?><script type="text/javascript">
625
+ jQuery(document).ready(function(){
626
+ // tab handling code
627
+ jQuery('#wsal-tabs>a').click(function(){
628
+ jQuery('#wsal-tabs>a').removeClass('nav-tab-active');
629
+ jQuery('table.wsal-tab').hide();
630
+ jQuery(jQuery(this).addClass('nav-tab-active').attr('href')).show();
631
+ });
632
+ // show relevant tab
633
+ var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
634
+ if (hashlink.length) {
635
+ hashlink.click();
636
+ } else {
637
+ jQuery('#wsal-tabs>a:first').click();
638
+ }
639
+
640
+ jQuery(".sel-columns").change(function(){
641
+ var notChecked = 1;
642
+ jQuery(".sel-columns").each(function(){
643
+ if(this.checked) notChecked = 0;
644
+ })
645
+ if(notChecked == 1){
646
+ alert("You have to select at least one column!");
647
+ }
648
+ });
649
+ });
650
+ </script><?php
651
+ }
652
+
653
+ public function AjaxGetAllUsers()
654
+ {
655
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
656
+ die('Access Denied.');
657
+ }
658
+ $users = array();
659
+ foreach (get_users() as $user) {
660
+ if (strpos($user->user_login, $_GET['term']) !== false) {
661
+ array_push($users, $user->user_login);
662
+ }
663
+ }
664
+ echo json_encode($users);
665
+ exit;
666
+ }
667
+
668
+ public function AjaxGetAllRoles()
669
+ {
670
+ if (!$this->_plugin->settings->CurrentUserCan('view')) {
671
+ die('Access Denied.');
672
+ }
673
+ $roles = array();
674
+ foreach (get_editable_roles() as $role_name => $role_info) {
675
+ if (strpos($role_name, $_GET['term']) !== false) {
676
+ array_push($roles, $role_name);
677
+ }
678
+ }
679
+ echo json_encode($roles);
680
+ exit;
681
+ }
682
+ }
classes/Views/ToggleAlerts.php CHANGED
@@ -1,150 +1,150 @@
1
- <?php
2
- class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
3
- {
4
-
5
- public function GetTitle() {
6
- return __('Enable/Disable Alerts', 'wp-security-audit-log');
7
- }
8
-
9
- public function GetIcon() {
10
- return 'dashicons-forms';
11
- }
12
-
13
- public function GetName() {
14
- return __('Enable/Disable Alerts', 'wp-security-audit-log');
15
- }
16
-
17
- public function GetWeight() {
18
- return 2;
19
- }
20
-
21
- protected function GetSafeCatgName($name) {
22
- return strtolower(
23
- preg_replace('/[^A-Za-z0-9\-]/', '-', $name)
24
- );
25
- }
26
-
27
- public function Render()
28
- {
29
- if (!$this->_plugin->settings->CurrentUserCan('edit')) {
30
- wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
31
- }
32
- $alert = new WSAL_Alert(); // IDE type hinting
33
- $groupedAlerts = $this->_plugin->alerts->GetCategorizedAlerts();
34
- $safeNames = array_map(array($this, 'GetSafeCatgName'), array_keys($groupedAlerts));
35
- $safeNames = array_combine(array_keys($groupedAlerts), $safeNames);
36
- if (isset($_POST['submit']) && isset($_POST['alert'])) {
37
- check_admin_referer('wsal-togglealerts');
38
- try {
39
- $enabled = array_map('intval', $_POST['alert']);
40
- $disabled = array();
41
- foreach ($this->_plugin->alerts->GetAlerts() as $alert)
42
- if (!in_array($alert->type, $enabled))
43
- $disabled[] = $alert->type;
44
- $this->_plugin->alerts->SetDisabledAlerts($disabled);
45
- ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
46
- } catch (Exception $ex) {
47
- ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
48
- }
49
- }
50
- ?><h2 id="wsal-tabs" class="nav-tab-wrapper"><?php
51
- foreach ($safeNames as $name => $safe) {
52
- ?><a href="#tab-<?php echo $safe; ?>" class="nav-tab"><?php echo $name; ?></a><?php
53
- }
54
- ?></h2>
55
- <form id="audit-log-viewer" method="post">
56
- <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
57
- <?php wp_nonce_field('wsal-togglealerts'); ?>
58
-
59
- <div class="nav-tabs"><?php
60
- foreach ($groupedAlerts as $name => $alerts) {
61
- $active = array();
62
- $allactive = true;
63
- foreach ($alerts as $alert) {
64
- if ($alert->type <= 0006) continue; // <- ignore php alerts
65
- if ($alert->type == 9999) continue; // <- ignore promo alerts
66
- $active[$alert->type] = $this->_plugin->alerts->IsEnabled($alert->type);
67
- if (!$active[$alert->type]) $allactive = false;
68
- }
69
- ?><table class="wp-list-table wsal-tab widefat fixed" cellspacing="0" id="tab-<?php echo $safeNames[$name]; ?>">
70
- <thead>
71
- <tr>
72
- <th width="48"><input type="checkbox"<?php if ($allactive) echo 'checked="checked"'; ?>/></th>
73
- <th width="80"><?php _e('Code', 'wp-security-audit-log'); ?></th>
74
- <th width="100"><?php _e('Type', 'wp-security-audit-log'); ?></th>
75
- <th><?php _e('Description', 'wp-security-audit-log'); ?></th>
76
- </tr>
77
- </thead>
78
- <tbody><?php
79
- foreach ($alerts as $alert) {
80
- if ($alert->type <= 0006) continue; // <- ignore php alerts
81
- if ($alert->type == 9999) continue; // <- ignore promo alerts
82
- $attrs = '';
83
- switch (true) {
84
- case !$alert->mesg:
85
- $attrs = ' title="'. __('Not Implemented', 'wp-security-audit-log') . '" class="alert-incomplete"';
86
- break;
87
- case false:
88
- $attrs = ' title="'. __('Not Available', 'wp-security-audit-log') . '" class="alert-unavailable"';
89
- break;
90
- }
91
- ?><tr<?php echo $attrs; ?>>
92
- <th><input name="alert[]" type="checkbox" <?php if ($active[$alert->type]) echo 'checked="checked"'; ?> value="<?php echo (int)$alert->type; ?>"></th>
93
- <td><?php echo str_pad($alert->type, 4, '0', STR_PAD_LEFT); ?></td>
94
- <td><?php echo $this->_plugin->constants->GetConstantBy('value', $alert->code)->name; ?></td>
95
- <td><?php echo esc_html($alert->desc); ?></td>
96
- </tr><?php
97
- }
98
- ?></tbody>
99
- </table><?php
100
- }
101
- ?></div>
102
- <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php echo esc_attr(__('Save Changes', 'wp-security-audit-log')); ?>"></p>
103
- </form><?php
104
- }
105
-
106
- public function Header()
107
- {
108
- ?><style type="text/css">
109
- .wsal-tab {
110
- display: none;
111
- }
112
- .wsal-tab tr.alert-incomplete td {
113
- color: #9BE;
114
- }
115
- .wsal-tab tr.alert-unavailable td {
116
- color: #CCC;
117
- }
118
- </style><?php
119
- }
120
-
121
- public function Footer()
122
- {
123
- ?><script type="text/javascript">
124
- jQuery(document).ready(function(){
125
- // tab handling code
126
- jQuery('#wsal-tabs>a').click(function(){
127
- jQuery('#wsal-tabs>a').removeClass('nav-tab-active');
128
- jQuery('table.wsal-tab').hide();
129
- jQuery(jQuery(this).addClass('nav-tab-active').attr('href')).show();
130
- });
131
- // checkbox handling code
132
- jQuery('table.wsal-tab>thead>tr>th>:checkbox').change(function(){
133
- jQuery(this).parents('table:first').find('tbody>tr>th>:checkbox').attr('checked', this.checked);
134
- });
135
- jQuery('table.wsal-tab>tbody>tr>th>:checkbox').change(function(){
136
- var allchecked = jQuery(this).parents('tbody:first').find('th>:checkbox:not(:checked)').length === 0;
137
- jQuery(this).parents('table:first').find('thead>tr>th:first>:checkbox:first').attr('checked', allchecked);
138
- });
139
- // show relevant tab
140
- var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
141
- if(hashlink.length){
142
- hashlink.click();
143
- }else{
144
- jQuery('#wsal-tabs>a:first').click();
145
- }
146
- });
147
- </script><?php
148
- }
149
-
150
- }
1
+ <?php
2
+ class WSAL_Views_ToggleAlerts extends WSAL_AbstractView
3
+ {
4
+
5
+ public function GetTitle() {
6
+ return __('Enable/Disable Alerts', 'wp-security-audit-log');
7
+ }
8
+
9
+ public function GetIcon() {
10
+ return 'dashicons-forms';
11
+ }
12
+
13
+ public function GetName() {
14
+ return __('Enable/Disable Alerts', 'wp-security-audit-log');
15
+ }
16
+
17
+ public function GetWeight() {
18
+ return 2;
19
+ }
20
+
21
+ protected function GetSafeCatgName($name) {
22
+ return strtolower(
23
+ preg_replace('/[^A-Za-z0-9\-]/', '-', $name)
24
+ );
25
+ }
26
+
27
+ public function Render()
28
+ {
29
+ if (!$this->_plugin->settings->CurrentUserCan('edit')) {
30
+ wp_die(__('You do not have sufficient permissions to access this page.', 'wp-security-audit-log'));
31
+ }
32
+ $alert = new WSAL_Alert(); // IDE type hinting
33
+ $groupedAlerts = $this->_plugin->alerts->GetCategorizedAlerts();
34
+ $safeNames = array_map(array($this, 'GetSafeCatgName'), array_keys($groupedAlerts));
35
+ $safeNames = array_combine(array_keys($groupedAlerts), $safeNames);
36
+ if (isset($_POST['submit']) && isset($_POST['alert'])) {
37
+ check_admin_referer('wsal-togglealerts');
38
+ try {
39
+ $enabled = array_map('intval', $_POST['alert']);
40
+ $disabled = array();
41
+ foreach ($this->_plugin->alerts->GetAlerts() as $alert)
42
+ if (!in_array($alert->type, $enabled))
43
+ $disabled[] = $alert->type;
44
+ $this->_plugin->alerts->SetDisabledAlerts($disabled);
45
+ ?><div class="updated"><p><?php _e('Settings have been saved.', 'wp-security-audit-log'); ?></p></div><?php
46
+ } catch (Exception $ex) {
47
+ ?><div class="error"><p><?php _e('Error: ', 'wp-security-audit-log'); ?><?php echo $ex->getMessage(); ?></p></div><?php
48
+ }
49
+ }
50
+ ?><h2 id="wsal-tabs" class="nav-tab-wrapper"><?php
51
+ foreach ($safeNames as $name => $safe) {
52
+ ?><a href="#tab-<?php echo $safe; ?>" class="nav-tab"><?php echo $name; ?></a><?php
53
+ }
54
+ ?></h2>
55
+ <form id="audit-log-viewer" method="post">
56
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>" />
57
+ <?php wp_nonce_field('wsal-togglealerts'); ?>
58
+
59
+ <div class="nav-tabs"><?php
60
+ foreach ($groupedAlerts as $name => $alerts) {
61
+ $active = array();
62
+ $allactive = true;
63
+ foreach ($alerts as $alert) {
64
+ if ($alert->type <= 0006) continue; // <- ignore php alerts
65
+ if ($alert->type == 9999) continue; // <- ignore promo alerts
66
+ $active[$alert->type] = $this->_plugin->alerts->IsEnabled($alert->type);
67
+ if (!$active[$alert->type]) $allactive = false;
68
+ }
69
+ ?><table class="wp-list-table wsal-tab widefat fixed" cellspacing="0" id="tab-<?php echo $safeNames[$name]; ?>">
70
+ <thead>
71
+ <tr>
72
+ <th width="48"><input type="checkbox"<?php if ($allactive) echo 'checked="checked"'; ?>/></th>
73
+ <th width="80"><?php _e('Code', 'wp-security-audit-log'); ?></th>
74
+ <th width="100"><?php _e('Type', 'wp-security-audit-log'); ?></th>
75
+ <th><?php _e('Description', 'wp-security-audit-log'); ?></th>
76
+ </tr>
77
+ </thead>
78
+ <tbody><?php
79
+ foreach ($alerts as $alert) {
80
+ if ($alert->type <= 0006) continue; // <- ignore php alerts
81
+ if ($alert->type == 9999) continue; // <- ignore promo alerts
82
+ $attrs = '';
83
+ switch (true) {
84
+ case !$alert->mesg:
85
+ $attrs = ' title="'. __('Not Implemented', 'wp-security-audit-log') . '" class="alert-incomplete"';
86
+ break;
87
+ case false:
88
+ $attrs = ' title="'. __('Not Available', 'wp-security-audit-log') . '" class="alert-unavailable"';
89
+ break;
90
+ }
91
+ ?><tr<?php echo $attrs; ?>>
92
+ <th><input name="alert[]" type="checkbox" <?php if ($active[$alert->type]) echo 'checked="checked"'; ?> value="<?php echo (int)$alert->type; ?>"></th>
93
+ <td><?php echo str_pad($alert->type, 4, '0', STR_PAD_LEFT); ?></td>
94
+ <td><?php echo $this->_plugin->constants->GetConstantBy('value', $alert->code)->name; ?></td>
95
+ <td><?php echo esc_html($alert->desc); ?></td>
96
+ </tr><?php
97
+ }
98
+ ?></tbody>
99
+ </table><?php
100
+ }
101
+ ?></div>
102
+ <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php echo esc_attr(__('Save Changes', 'wp-security-audit-log')); ?>"></p>
103
+ </form><?php
104
+ }
105
+
106
+ public function Header()
107
+ {
108
+ ?><style type="text/css">
109
+ .wsal-tab {
110
+ display: none;
111
+ }
112
+ .wsal-tab tr.alert-incomplete td {
113
+ color: #9BE;
114
+ }
115
+ .wsal-tab tr.alert-unavailable td {
116
+ color: #CCC;
117
+ }
118
+ </style><?php
119
+ }
120
+
121
+ public function Footer()
122
+ {
123
+ ?><script type="text/javascript">
124
+ jQuery(document).ready(function(){
125
+ // tab handling code
126
+ jQuery('#wsal-tabs>a').click(function(){
127
+ jQuery('#wsal-tabs>a').removeClass('nav-tab-active');
128
+ jQuery('table.wsal-tab').hide();
129
+ jQuery(jQuery(this).addClass('nav-tab-active').attr('href')).show();
130
+ });
131
+ // checkbox handling code
132
+ jQuery('table.wsal-tab>thead>tr>th>:checkbox').change(function(){
133
+ jQuery(this).parents('table:first').find('tbody>tr>th>:checkbox').attr('checked', this.checked);
134
+ });
135
+ jQuery('table.wsal-tab>tbody>tr>th>:checkbox').change(function(){
136
+ var allchecked = jQuery(this).parents('tbody:first').find('th>:checkbox:not(:checked)').length === 0;
137
+ jQuery(this).parents('table:first').find('thead>tr>th:first>:checkbox:first').attr('checked', allchecked);
138
+ });
139
+ // show relevant tab
140
+ var hashlink = jQuery('#wsal-tabs>a[href="' + location.hash + '"]');
141
+ if(hashlink.length){
142
+ hashlink.click();
143
+ }else{
144
+ jQuery('#wsal-tabs>a:first').click();
145
+ }
146
+ });
147
+ </script><?php
148
+ }
149
+
150
+ }
classes/WidgetManager.php CHANGED
@@ -1,79 +1,79 @@
1
- <?php
2
-
3
- class WSAL_WidgetManager
4
- {
5
- /**
6
- * @var WpSecurityAuditLog
7
- */
8
- protected $_plugin;
9
-
10
- public function __construct(WpSecurityAuditLog $plugin)
11
- {
12
- $this->_plugin = $plugin;
13
- add_action('wp_dashboard_setup', array($this, 'AddWidgets'));
14
- }
15
-
16
- public function AddWidgets()
17
- {
18
- if ($this->_plugin->settings->IsWidgetsEnabled()
19
- && $this->_plugin->settings->CurrentUserCan('view')) {
20
- wp_add_dashboard_widget(
21
- 'wsal',
22
- __('Latest Alerts', 'wp-security-audit-log') . ' | WP Security Audit Log',
23
- array($this, 'RenderWidget')
24
- );
25
- }
26
- }
27
-
28
- public function RenderWidget()
29
- {
30
- $query = new WSAL_Models_OccurrenceQuery();
31
-
32
- $bid = (int)$this->get_view_site_id();
33
- if ($bid) {
34
- $query->addCondition("site_id = %s ", $bid);
35
- }
36
- $query->addOrderBy("created_on", true);
37
- $query->setLimit($this->_plugin->settings->GetDashboardWidgetMaxAlerts());
38
- $results = $query->getAdapter()->Execute($query);
39
-
40
- ?><div><?php
41
- if (!count($results)) {
42
- ?><p><?php _e('No alerts found.', 'wp-security-audit-log'); ?></p><?php
43
- } else {
44
- ?><table class="wp-list-table widefat" cellspacing="0" cellpadding="0"
45
- style="display: block; overflow-x: auto;">
46
- <thead>
47
- <th class="manage-column" style="width: 15%;" scope="col"><?php _e('User', 'wp-security-audit-log'); ?></th>
48
- <th class="manage-column" style="width: 85%;" scope="col"><?php _e('Description', 'wp-security-audit-log'); ?></th>
49
- </thead>
50
- <tbody><?php
51
- $url = 'admin.php?page=' . $this->_plugin->views->views[0]->GetSafeViewName();
52
- $fmt = array(new WSAL_AuditLogListView($this->_plugin), 'meta_formatter');
53
- foreach ($results as $entry) {
54
- ?><tr>
55
- <td><?php
56
- echo ($un = $entry->GetUsername()) ? esc_html($un) : '<i>unknown</i>';
57
- ?></td>
58
- <td>
59
- <a href="<?php echo $url . '#Event' . $entry->id; ?>"><?php
60
- echo $entry->GetMessage($fmt);
61
- ?></a>
62
- </td>
63
- </tr><?php
64
- }
65
- ?></tbody>
66
- </table><?php
67
- }
68
- ?></div><?php
69
- }
70
-
71
- protected function get_view_site_id()
72
- {
73
- if (is_super_admin()) {
74
- return 0;
75
- } else {
76
- return get_current_blog_id();
77
- }
78
- }
79
- }
1
+ <?php
2
+
3
+ class WSAL_WidgetManager
4
+ {
5
+ /**
6
+ * @var WpSecurityAuditLog
7
+ */
8
+ protected $_plugin;
9
+
10
+ public function __construct(WpSecurityAuditLog $plugin)
11
+ {
12
+ $this->_plugin = $plugin;
13
+ add_action('wp_dashboard_setup', array($this, 'AddWidgets'));
14
+ }
15
+
16
+ public function AddWidgets()
17
+ {
18
+ if ($this->_plugin->settings->IsWidgetsEnabled()
19
+ && $this->_plugin->settings->CurrentUserCan('view')) {
20
+ wp_add_dashboard_widget(
21
+ 'wsal',
22
+ __('Latest Alerts', 'wp-security-audit-log') . ' | WP Security Audit Log',
23
+ array($this, 'RenderWidget')
24
+ );
25
+ }
26
+ }
27
+
28
+ public function RenderWidget()
29
+ {
30
+ $query = new WSAL_Models_OccurrenceQuery();
31
+
32
+ $bid = (int)$this->get_view_site_id();
33
+ if ($bid) {
34
+ $query->addCondition("site_id = %s ", $bid);
35
+ }
36
+ $query->addOrderBy("created_on", true);
37
+ $query->setLimit($this->_plugin->settings->GetDashboardWidgetMaxAlerts());
38
+ $results = $query->getAdapter()->Execute($query);
39
+
40
+ ?><div><?php
41
+ if (!count($results)) {
42
+ ?><p><?php _e('No alerts found.', 'wp-security-audit-log'); ?></p><?php
43
+ } else {
44
+ ?><table class="wp-list-table widefat" cellspacing="0" cellpadding="0"
45
+ style="display: block; overflow-x: auto;">
46
+ <thead>
47
+ <th class="manage-column" style="width: 15%;" scope="col"><?php _e('User', 'wp-security-audit-log'); ?></th>
48
+ <th class="manage-column" style="width: 85%;" scope="col"><?php _e('Description', 'wp-security-audit-log'); ?></th>
49
+ </thead>
50
+ <tbody><?php
51
+ $url = 'admin.php?page=' . $this->_plugin->views->views[0]->GetSafeViewName();
52
+ $fmt = array(new WSAL_AuditLogListView($this->_plugin), 'meta_formatter');
53
+ foreach ($results as $entry) {
54
+ ?><tr>
55
+ <td><?php
56
+ echo ($un = $entry->GetUsername()) ? esc_html($un) : '<i>unknown</i>';
57
+ ?></td>
58
+ <td>
59
+ <a href="<?php echo $url . '#Event' . $entry->id; ?>"><?php
60
+ echo $entry->GetMessage($fmt);
61
+ ?></a>
62
+ </td>
63
+ </tr><?php
64
+ }
65
+ ?></tbody>
66
+ </table><?php
67
+ }
68
+ ?></div><?php
69
+ }
70
+
71
+ protected function get_view_site_id()
72
+ {
73
+ if (is_super_admin()) {
74
+ return 0;
75
+ } else {
76
+ return get_current_blog_id();
77
+ }
78
+ }
79
+ }
css/auditlog.css CHANGED
@@ -1,180 +1,180 @@
1
- .wsal-ipp,
2
- .wsal-ssa {
3
- display: inline-block;
4
- color: #555;
5
- line-height: 30px;
6
- font-size: 12px;
7
- }
8
-
9
- .wsal-ipp select {
10
- margin-bottom: 6px;
11
- width: 56px;
12
- }
13
-
14
- .wsal-ssa input,
15
- .wsal-ssa select {
16
- margin-bottom: 6px;
17
- width: 120px;
18
- margin-left: 16px;
19
- }
20
-
21
- .column-read,
22
- .column-type,
23
- .column-code,
24
- .column-more,
25
- .column-data {
26
- width: 70px;
27
- }
28
-
29
- .column-crtd {
30
- width: 125px;
31
- }
32
-
33
- .column-user {
34
- width: 160px;
35
- }
36
-
37
- .column-site {
38
- width: 160px;
39
- }
40
-
41
- td.column-user {
42
- font-size: 75% !important;
43
- }
44
-
45
- .column-user img {
46
- float: left;
47
- margin-right: 4px;
48
- -webkit-border-radius: 50px;
49
- -moz-border-radius: 50px;
50
- -ms-border-radius: 50px;
51
- border-radius: 50px;
52
- }
53
-
54
- .column-scip {
55
- width: 120px;
56
- }
57
-
58
- .more-info {
59
- float: right;
60
- display: block;
61
- width: 16px;
62
- height: 16px;
63
- color: #FFF;
64
- font-weight: bold;
65
- font-size: 13px;
66
- line-height: 10px;
67
- text-align: center;
68
- border-radius: 32px;
69
- margin-left: 8px;
70
- background: #AAA;
71
- }
72
-
73
- .more-info:hover {
74
- color: #FFF;
75
- background: #333;
76
- }
77
-
78
- .log-read:after {
79
- display: block;
80
- width: 16px;
81
- height: 16px;
82
- color: #FFF;
83
- font-weight: bold;
84
- font-size: 13px;
85
- line-height: 16px;
86
- text-align: center;
87
- border-radius: 32px;
88
- margin-left: 8px;
89
- content: "\2713";
90
- background: #CCC;
91
- }
92
-
93
- .log-read-new:after {
94
- background: #290;
95
- }
96
-
97
- .log-type {
98
- cursor: help;
99
- }
100
-
101
- .log-type:after {
102
- display: block;
103
- width: 16px;
104
- height: 16px;
105
- color: #FFF;
106
- font-weight: bold;
107
- font-size: 11px;
108
- line-height: 17px;
109
- background: #CCC;
110
- text-align: center;
111
- border-radius: 32px;
112
- margin-left: 8px;
113
- }
114
-
115
- /* errors */
116
- .log-type-0:after,
117
- .log-type-1:after,
118
- .log-type-4:after,
119
- .log-type-16:after,
120
- .log-type-64:after,
121
- .log-type-256:after,
122
- .log-type-4096:after,
123
- .log-type-E_CRITICAL:after
124
- { background: #E00; content: "!"; }
125
-
126
- /* warnings */
127
- .log-type-2:after,
128
- .log-type-32:after,
129
- .log-type-128:after,
130
- .log-type-512:after
131
- { background: #EB0; content: "!"; }
132
-
133
- /* notices/strict/deprecation */
134
- .log-type-8:after,
135
- .log-type-1024:after,
136
- .log-type-2048:after,
137
- .log-type-8192:after,
138
- .log-type-16384:after,
139
- .log-type-E_DEBUG:after
140
- { background: #09E; content: "i"; }
141
-
142
- /* search box */
143
- .wsal-ssas-dd {
144
- position: absolute;
145
- border: 1px solid windowframe;
146
- background: #FFF;
147
- padding: 0;
148
- margin: -8px 16px;
149
- background: window;
150
- color: windowtext;
151
- min-width: 140px;
152
- }
153
- .wsal-ssas-dd * {
154
- cursor: default;
155
- }
156
- .wsal-ssas-dd a {
157
- padding: 2px 8px;
158
- display: block;
159
- line-height: normal;
160
- text-decoration: none;
161
- color: windowtext;
162
- }
163
- .wsal-ssas-dd a:hover,
164
- .wsal-ssas-dd .active {
165
- background: highlight;
166
- color: highlighttext;
167
- }
168
- .wsal-ssas-dd a u {
169
- text-decoration: underline;
170
- }
171
- .wsal-ssas-dd span {
172
- color: #555;
173
- font-style: italic;
174
- padding: 2px 8px;
175
- display: block;
176
- line-height: normal;
177
- }
178
- .wsal-ssas-dd .allsites {
179
- border-bottom: 1px solid windowframe;
180
- }
1
+ .wsal-ipp,
2
+ .wsal-ssa {
3
+ display: inline-block;
4
+ color: #555;
5
+ line-height: 30px;
6
+ font-size: 12px;
7
+ }
8
+
9
+ .wsal-ipp select {
10
+ margin-bottom: 6px;
11
+ width: 56px;
12
+ }
13
+
14
+ .wsal-ssa input,
15
+ .wsal-ssa select {
16
+ margin-bottom: 6px;
17
+ width: 120px;
18
+ margin-left: 16px;
19
+ }
20
+
21
+ .column-read,
22
+ .column-type,
23
+ .column-code,
24
+ .column-more,
25
+ .column-data {
26
+ width: 70px;
27
+ }
28
+
29
+ .column-crtd {
30
+ width: 125px;
31
+ }
32
+
33
+ .column-user {
34
+ width: 160px;
35
+ }
36
+
37
+ .column-site {
38
+ width: 160px;
39
+ }
40
+
41
+ td.column-user {
42
+ font-size: 75% !important;
43
+ }
44
+
45
+ .column-user img {
46
+ float: left;
47
+ margin-right: 4px;
48
+ -webkit-border-radius: 50px;
49
+ -moz-border-radius: 50px;
50
+ -ms-border-radius: 50px;
51
+ border-radius: 50px;
52
+ }
53
+
54
+ .column-scip {
55
+ width: 120px;
56
+ }
57
+
58
+ .more-info {
59
+ float: right;
60
+ display: block;
61
+ width: 16px;
62
+ height: 16px;
63
+ color: #FFF;
64
+ font-weight: bold;
65
+ font-size: 13px;
66
+ line-height: 10px;
67
+ text-align: center;
68
+ border-radius: 32px;
69
+ margin-left: 8px;
70
+ background: #AAA;
71
+ }
72
+
73
+ .more-info:hover {
74
+ color: #FFF;
75
+ background: #333;
76
+ }
77
+
78
+ .log-read:after {
79
+ display: block;
80
+ width: 16px;
81
+ height: 16px;
82
+ color: #FFF;
83
+ font-weight: bold;
84
+ font-size: 13px;
85
+ line-height: 16px;
86
+ text-align: center;
87
+ border-radius: 32px;
88
+ margin-left: 8px;
89
+ content: "\2713";
90
+ background: #CCC;
91
+ }
92
+
93
+ .log-read-new:after {
94
+ background: #290;
95
+ }
96
+
97
+ .log-type {
98
+ cursor: help;
99
+ }
100
+
101
+ .log-type:after {
102
+ display: block;
103
+ width: 16px;
104
+ height: 16px;
105
+ color: #FFF;
106
+ font-weight: bold;
107
+ font-size: 11px;
108
+ line-height: 17px;
109
+ background: #CCC;
110
+ text-align: center;
111
+ border-radius: 32px;
112
+ margin-left: 8px;
113
+ }
114
+
115
+ /* errors */
116
+ .log-type-0:after,
117
+ .log-type-1:after,
118
+ .log-type-4:after,
119
+ .log-type-16:after,
120
+ .log-type-64:after,
121
+ .log-type-256:after,
122
+ .log-type-4096:after,
123
+ .log-type-E_CRITICAL:after
124
+ { background: #E00; content: "!"; }
125
+
126
+ /* warnings */
127
+ .log-type-2:after,
128
+ .log-type-32:after,
129
+ .log-type-128:after,
130
+ .log-type-512:after
131
+ { background: #EB0; content: "!"; }
132
+
133
+ /* notices/strict/deprecation */
134
+ .log-type-8:after,
135
+ .log-type-1024:after,
136
+ .log-type-2048:after,
137
+ .log-type-8192:after,
138
+ .log-type-16384:after,
139
+ .log-type-E_DEBUG:after
140
+ { background: #09E; content: "i"; }
141
+
142
+ /* search box */
143
+ .wsal-ssas-dd {
144
+ position: absolute;
145
+ border: 1px solid windowframe;
146
+ background: #FFF;
147
+ padding: 0;
148
+ margin: -8px 16px;
149
+ background: window;
150
+ color: windowtext;
151
+ min-width: 140px;
152
+ }
153
+ .wsal-ssas-dd * {
154
+ cursor: default;
155
+ }
156
+ .wsal-ssas-dd a {
157
+ padding: 2px 8px;
158
+ display: block;
159
+ line-height: normal;
160
+ text-decoration: none;
161
+ color: windowtext;
162
+ }
163
+ .wsal-ssas-dd a:hover,
164
+ .wsal-ssas-dd .active {
165
+ background: highlight;
166
+ color: highlighttext;
167
+ }
168
+ .wsal-ssas-dd a u {
169
+ text-decoration: underline;
170
+ }
171
+ .wsal-ssas-dd span {
172
+ color: #555;
173
+ font-style: italic;
174
+ padding: 2px 8px;
175
+ display: block;
176
+ line-height: normal;
177
+ }
178
+ .wsal-ssas-dd .allsites {
179
+ border-bottom: 1px solid windowframe;
180
+ }
css/install-error.css CHANGED
@@ -1,41 +1,41 @@
1
- .warn-icon-tri {
2
- top: 5px;
3
- left: 5px;
4
- position: absolute;
5
- border-left: 16px solid #FFF;
6
- border-right: 16px solid #FFF;
7
- border-bottom: 28px solid #C33;
8
- height: 3px;
9
- width: 4px
10
- }
11
-
12
- .warn-icon-chr {
13
- top: 8px;
14
- left: 18px;
15
- position: absolute;
16
- color: #FFF;
17
- font: 26px Georgia;
18
- }
19
-
20
- .warn-icon-cir {
21
- top: 2px;
22
- left: 0px;
23
- position: absolute;
24
- overflow: hidden;
25
- border: 6px solid #FFF;
26
- border-radius: 32px;
27
- width: 34px;
28
- height: 34px;
29
- }
30
-
31
- .warn-wrap {
32
- position: relative;
33
- color: #A00;
34
- font: 14px Arial;
35
- padding: 6px 48px;
36
- }
37
-
38
- .warn-wrap a,
39
- .warn-wrap a:hover {
40
- color: #F56;
41
- }
1
+ .warn-icon-tri {
2
+ top: 5px;
3
+ left: 5px;
4
+ position: absolute;
5
+ border-left: 16px solid #FFF;
6
+ border-right: 16px solid #FFF;
7
+ border-bottom: 28px solid #C33;
8
+ height: 3px;
9
+ width: 4px
10
+ }
11
+
12
+ .warn-icon-chr {
13
+ top: 8px;
14
+ left: 18px;
15
+ position: absolute;
16
+ color: #FFF;
17
+ font: 26px Georgia;
18
+ }
19
+
20
+ .warn-icon-cir {
21
+ top: 2px;
22
+ left: 0px;
23
+ position: absolute;
24
+ overflow: hidden;
25
+ border: 6px solid #FFF;
26
+ border-radius: 32px;
27
+ width: 34px;
28
+ height: 34px;
29
+ }
30
+
31
+ .warn-wrap {
32
+ position: relative;
33
+ color: #A00;
34
+ font: 14px Arial;
35
+ padding: 6px 48px;
36
+ }
37
+
38
+ .warn-wrap a,
39
+ .warn-wrap a:hover {
40
+ color: #F56;
41
+ }
css/nice_r.css CHANGED
@@ -1,92 +1,92 @@
1
- .nice_r {
2
- font: 12px Consolas, "Lucida Console", monospace;
3
- cursor: default;
4
- }
5
-
6
- .nice_r a {
7
- display: block;
8
- text-decoration: none;
9
- color: #222;
10
- padding: 2px;
11
- white-space: nowrap;
12
- overflow: hidden;
13
- text-overflow: ellipsis;
14
- }
15
-
16
- .nice_r a:hover .nice_r_k,
17
- .nice_r a:hover .nice_r_d,
18
- .nice_r a:hover .nice_r_d span,
19
- .nice_r a:hover .nice_r_p,
20
- .nice_r a:hover .nice_r_a,
21
- .nice_r a:hover {
22
- background-color: Highlight;
23
- color: HighlightText;
24
- }
25
-
26
- .nice_r_a {
27
- color: #000;
28
- }
29
-
30
- .nice_r_ad {
31
- opacity: 0.5;
32
- }
33
-
34
- .nice_r_k {
35
- color: #060;
36
- font-weight: bold;
37
- }
38
-
39
- .nice_r_d {
40
- font-size: 11px;
41
- color: #777;
42
- }
43
-
44
- .nice_r_d span {
45
- color: #333;
46
- }
47
-
48
- .nice_r_p {
49
- color: #000;
50
- font-weight: bold;
51
- }
52
-
53
- .nice_r_v {
54
- margin-left: 6px;
55
- padding-left: 6px;
56
- border-left: 1px dotted #CCC;
57
- display: none;
58
- }
59
-
60
- .nice_r_ir {
61
- font-style: italic;
62
- }
63
-
64
- .nice_r_p.nice_r_t_integer,
65
- .nice_r_p.nice_r_t_double {
66
- color: #F0E;
67
- }
68
-
69
- .nice_r_p.nice_r_t_string {
70
- color: #E00;
71
- }
72
-
73
- .nice_r_p.nice_r_t_boolean {
74
- color: #00E;
75
- }
76
-
77
- .nice_r_t_comment {
78
- color: #080;
79
- }
80
-
81
- .nice_r a.nice_r_c .nice_r_k {
82
- color: #909;
83
- }
84
-
85
- .nice_r a.nice_r_c .nice_r_ma {
86
- font-weight: normal;
87
- color: #777;
88
- }
89
-
90
- .nice_r a.nice_r_c .nice_r_mv {
91
- color: #00E;
92
- }
1
+ .nice_r {
2
+ font: 12px Consolas, "Lucida Console", monospace;
3
+ cursor: default;
4
+ }
5
+
6
+ .nice_r a {
7
+ display: block;
8
+ text-decoration: none;
9
+ color: #222;
10
+ padding: 2px;
11
+ white-space: nowrap;
12
+ overflow: hidden;
13
+ text-overflow: ellipsis;
14
+ }
15
+
16
+ .nice_r a:hover .nice_r_k,
17
+ .nice_r a:hover .nice_r_d,
18
+ .nice_r a:hover .nice_r_d span,
19
+ .nice_r a:hover .nice_r_p,
20
+ .nice_r a:hover .nice_r_a,
21
+ .nice_r a:hover {
22
+ background-color: Highlight;
23
+ color: HighlightText;
24
+ }
25
+
26
+ .nice_r_a {
27
+ color: #000;
28
+ }
29
+
30
+ .nice_r_ad {
31
+ opacity: 0.5;
32
+ }
33
+
34
+ .nice_r_k {
35
+ color: #060;
36
+ font-weight: bold;
37
+ }
38
+
39
+ .nice_r_d {
40
+ font-size: 11px;
41
+ color: #777;
42
+ }
43
+
44
+ .nice_r_d span {
45
+ color: #333;
46
+ }
47
+
48
+ .nice_r_p {
49
+ color: #000;
50
+ font-weight: bold;
51
+ }
52
+
53
+ .nice_r_v {
54
+ margin-left: 6px;
55
+ padding-left: 6px;
56
+ border-left: 1px dotted #CCC;
57
+ display: none;
58
+ }
59
+
60
+ .nice_r_ir {
61
+ font-style: italic;
62
+ }
63
+
64
+ .nice_r_p.nice_r_t_integer,
65
+ .nice_r_p.nice_r_t_double {
66
+ color: #F0E;
67
+ }
68
+
69
+ .nice_r_p.nice_r_t_string {
70
+ color: #E00;
71
+ }
72
+
73
+ .nice_r_p.nice_r_t_boolean {
74
+ color: #00E;
75
+ }
76
+
77
+ .nice_r_t_comment {
78
+ color: #080;
79
+ }
80
+
81
+ .nice_r a.nice_r_c .nice_r_k {
82
+ color: #909;
83
+ }
84
+
85
+ .nice_r a.nice_r_c .nice_r_ma {
86
+ font-weight: normal;
87
+ color: #777;
88
+ }
89
+
90
+ .nice_r a.nice_r_c .nice_r_mv {
91
+ color: #00E;
92
+ }
css/settings.css CHANGED
@@ -1,71 +1,71 @@
1
- #audit-log-settings {
2
- padding-right: 256px;
3
- position: relative;
4
- }
5
-
6
- #audit-log-adverts {
7
- position: absolute;
8
- top: 3px;
9
- right: 3px;
10
- overflow: hidden;
11
- }
12
-
13
- #audit-log-adverts a {
14
- display: block;
15
- text-decoration: none;
16
- margin: 4px 0;
17
- }
18
-
19
- .sectoken-user,
20
- .sectoken-role,
21
- .sectoken-other {
22
- display: inline-block;
23
- border-width: 1px;
24
- border-style: solid;
25
- padding: 2px 4px;
26
- margin: 2px 0 0 2px;
27
- border-radius: 3px;
28
- cursor: default;
29
- }
30
- .sectoken-other {
31
- display: table;
32
- border-collapse: separate;
33
- }
34
-
35
- .sectoken-user a,
36
- .sectoken-role a,
37
- .sectoken-other a {
38
- text-decoration: none;
39
- font-size: 12px;
40
- font-weight: bold;
41
- color: #FFF;
42
- margin-left: 2px;
43
- background: #BBB;
44
- border-radius: 25px;
45
- height: 14px;
46
- display: inline-block;
47
- width: 14px;
48
- text-align: center;
49
- line-height: 16px;
50
- }
51
-
52
- .sectoken-user a:hover,
53
- .sectoken-role a:hover,
54
- .sectoken-other a:hover {
55
- background: #FB9;
56
- }
57
-
58
- .sectoken-user { background: #EFF; border-color: #5BE; }
59
- .sectoken-role { background: #EFE; border-color: #5B5; }
60
- .sectoken-other { background: #FFE; border-color: #ED5; }
61
- .sectoken-del { background: #FEE; border-color: #EBB; }
62
-
63
- .wsal-tab {
64
- margin-top: 0px;
65
- }
66
- .wsal-tab th {
67
- padding-left: 20px;
68
- }
69
- .wsal-tab td {
70
- padding-left: 20px;
71
  }
1
+ #audit-log-settings {
2
+ padding-right: 256px;
3
+ position: relative;
4
+ }
5
+
6
+ #audit-log-adverts {
7
+ position: absolute;
8
+ top: 3px;
9
+ right: 3px;
10
+ overflow: hidden;
11
+ }
12
+
13
+ #audit-log-adverts a {
14
+ display: block;
15
+ text-decoration: none;
16
+ margin: 4px 0;
17
+ }
18
+
19
+ .sectoken-user,
20
+ .sectoken-role,
21
+ .sectoken-other {
22
+ display: inline-block;
23
+ border-width: 1px;
24
+ border-style: solid;
25
+ padding: 2px 4px;
26
+ margin: 2px 0 0 2px;
27
+ border-radius: 3px;
28
+ cursor: default;
29
+ }
30
+ .sectoken-other {
31
+ display: table;
32
+ border-collapse: separate;
33
+ }
34
+
35
+ .sectoken-user a,
36
+ .sectoken-role a,
37
+ .sectoken-other a {
38
+ text-decoration: none;
39
+ font-size: 12px;
40
+ font-weight: bold;
41
+ color: #FFF;
42
+ margin-left: 2px;
43
+ background: #BBB;
44
+ border-radius: 25px;
45
+ height: 14px;
46
+ display: inline-block;
47
+ width: 14px;
48
+ text-align: center;
49
+ line-height: 16px;
50
+ }
51
+
52
+ .sectoken-user a:hover,
53
+ .sectoken-role a:hover,
54
+ .sectoken-other a:hover {
55
+ background: #FB9;
56
+ }
57
+
58
+ .sectoken-user { background: #EFF; border-color: #5BE; }
59
+ .sectoken-role { background: #EFE; border-color: #5B5; }
60
+ .sectoken-other { background: #FFE; border-color: #ED5; }
61
+ .sectoken-del { background: #FEE; border-color: #EBB; }
62
+
63
+ .wsal-tab {
64
+ margin-top: 0px;
65
+ }
66
+ .wsal-tab th {
67
+ padding-left: 20px;
68
+ }
69
+ .wsal-tab td {
70
+ padding-left: 20px;
71
  }
defaults.php CHANGED
@@ -40,6 +40,8 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
40
  array(1001, E_NOTICE, __('User logs out', 'wp-security-audit-log'), __('Successfully logged out', 'wp-security-audit-log')),
41
  array(1002, E_WARNING, __('Login failed', 'wp-security-audit-log'), __('%Attempts% failed login(s) detected', 'wp-security-audit-log')),
42
  array(1003, E_WARNING, __('Login failed / non existing user', 'wp-security-audit-log'), __('%Attempts% failed login(s) detected using non existing user.', 'wp-security-audit-log')),
 
 
43
  array(2010, E_NOTICE, __('User uploaded file from Uploads directory', 'wp-security-audit-log'), __('Uploaded the file %FileName% in %FilePath%', 'wp-security-audit-log')),
44
  array(2011, E_WARNING, __('User deleted file from Uploads directory', 'wp-security-audit-log'), __('Deleted the file %FileName% from %FilePath%', 'wp-security-audit-log')),
45
  array(2046, E_CRITICAL, __('User changed a file using the theme editor', 'wp-security-audit-log'), __('Modified %File% with the Theme Editor', 'wp-security-audit-log')),
@@ -163,6 +165,7 @@ function wsaldefaults_wsal_init(WpSecurityAuditLog $wsal)
163
  array(6003, E_CRITICAL, __('WordPress Administrator Notification email changed', 'wp-security-audit-log'), __('Changed the WordPress administrator notifications email address from %OldEmail% to %NewEmail%', 'wp-security-audit-log')),
164
  array(6004, E_CRITICAL, __('WordPress was updated', 'wp-security-audit-log'), __('Updated WordPress from version %OldVersion% to %NewVersion%', 'wp-security-audit-log')),
165
  array(6005, E_CRITICAL, __('User changes the WordPress Permalinks', 'wp-security-audit-log'), __('Changed the WordPress permalinks from %OldPattern% to %NewPattern%', 'wp-security-audit-log')),
 
166
  array(9999, E_CRITICAL, __('Advertising Add-ons.', 'wp-security-audit-log'), __('%PromoMessage%', 'wp-security-audit-log')),
167
  ),
168
  __('MultiSite', 'wp-security-audit-log') => array(
40
  array(1001, E_NOTICE, __('User logs out', 'wp-security-audit-log'), __('Successfully logged out', 'wp-security-audit-log')),
41
  array(1002, E_WARNING, __('Login failed', 'wp-security-audit-log'), __('%Attempts% failed login(s) detected', 'wp-security-audit-log')),
42
  array(1003, E_WARNING, __('Login failed / non existing user', 'wp-security-audit-log'), __('%Attempts% failed login(s) detected using non existing user.', 'wp-security-audit-log')),
43
+ array(1004, E_WARNING, __('Login blocked', 'wp-security-audit-log'), __('Blocked from logging in because another user is logged in from %ClientIP%', 'wp-security-audit-log')),
44
+ array(1005, E_WARNING, __('User logs in with existing session(s)', 'wp-security-audit-log'), __('Successfully logged in. Other session(s) from %IPAddress% for this username already exists', 'wp-security-audit-log')),
45
  array(2010, E_NOTICE, __('User uploaded file from Uploads directory', 'wp-security-audit-log'), __('Uploaded the file %FileName% in %FilePath%', 'wp-security-audit-log')),
46
  array(2011, E_WARNING, __('User deleted file from Uploads directory', 'wp-security-audit-log'), __('Deleted the file %FileName% from %FilePath%', 'wp-security-audit-log')),
47
  array(2046, E_CRITICAL, __('User changed a file using the theme editor', 'wp-security-audit-log'), __('Modified %File% with the Theme Editor', 'wp-security-audit-log')),
165
  array(6003, E_CRITICAL, __('WordPress Administrator Notification email changed', 'wp-security-audit-log'), __('Changed the WordPress administrator notifications email address from %OldEmail% to %NewEmail%', 'wp-security-audit-log')),
166
  array(6004, E_CRITICAL, __('WordPress was updated', 'wp-security-audit-log'), __('Updated WordPress from version %OldVersion% to %NewVersion%', 'wp-security-audit-log')),
167
  array(6005, E_CRITICAL, __('User changes the WordPress Permalinks', 'wp-security-audit-log'), __('Changed the WordPress permalinks from %OldPattern% to %NewPattern%', 'wp-security-audit-log')),
168
+ array(6007, E_CRITICAL, __('User requests non-existing pages (404 Error Pages)', 'wp-security-audit-log'), __(' Is requesting non-existing pages (404 Error Pages)', 'wp-security-audit-log')),
169
  array(9999, E_CRITICAL, __('Advertising Add-ons.', 'wp-security-audit-log'), __('%PromoMessage%', 'wp-security-audit-log')),
170
  ),
171
  __('MultiSite', 'wp-security-audit-log') => array(
js/auditlog.js CHANGED
@@ -1,150 +1,150 @@
1
- var WsalData;
2
-
3
- window['WsalAuditLogRefreshed'] = function(){
4
- // fix pagination links causing form params to get lost
5
- jQuery('span.pagination-links a').click(function(ev){
6
- ev.preventDefault();
7
- var deparam = function(url){
8
- var obj = {};
9
- var pairs = url.split('&');
10
- for(var i in pairs){
11
- var split = pairs[i].split('=');
12
- obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
13
- }
14
- return obj;
15
- };
16
- var paged = deparam(this.href).paged;
17
- if (typeof paged === 'undefined') paged = 1;
18
- jQuery('#audit-log-viewer').append(
19
- jQuery('<input type="hidden" name="paged"/>').val(paged)
20
- ).submit();
21
- });
22
- };
23
-
24
- function WsalAuditLogInit(_WsalData){
25
- WsalData = _WsalData;
26
- var WsalTkn = WsalData.autorefresh.token;
27
-
28
- // list refresher
29
- var WsalAjx = null;
30
- var WsalChk = function(){
31
- if(WsalAjx)WsalAjx.abort();
32
- WsalAjx = jQuery.post(WsalData.ajaxurl, {
33
- action: 'AjaxRefresh',
34
- logcount: WsalTkn
35
- }, function(data){
36
- WsalAjx = null;
37
- if(data && data !== 'false'){
38
- WsalTkn = data;
39
- jQuery('#audit-log-viewer').load(
40
- location.href + ' #audit-log-viewer-content',
41
- window['WsalAuditLogRefreshed']
42
- );
43
- }
44
- WsalChk();
45
- });
46
- };
47
- if(WsalData.autorefresh.enabled){
48
- setInterval(WsalChk, 40000);
49
- WsalChk();
50
- }
51
-
52
- WsalSsasInit();
53
- }
54
-
55
- var WsalIppsPrev;
56
-
57
- function WsalIppsFocus(value){
58
- WsalIppsPrev = value;
59
- }
60
-
61
- function WsalIppsChange(value){
62
- if(value === ''){
63
- value = window.prompt(WsalData.tr8n.numofitems, WsalIppsPrev);
64
- if(value === null || value === WsalIppsPrev)return this.value = WsalIppsPrev; // operation canceled
65
- }
66
- jQuery('select.wsal-ipps').attr('disabled', true);
67
- jQuery.post(WsalData.ajaxurl, {
68
- action: 'AjaxSetIpp',
69
- count: value
70
- }, function(){
71
- location.reload();
72
- });
73
- }
74
-
75
- function WsalSsasInit(){
76
- var SsasAjx = null;
77
- var SsasInps = jQuery("input.wsal-ssas");
78
- SsasInps.after('<div class="wsal-ssas-dd" style="display: none;"/>');
79
- SsasInps.click(function(){
80
- jQuery(this).select();
81
- });
82
- window['WsalAuditLogRefreshed']();
83
- SsasInps.keyup(function(){
84
- var SsasInp = jQuery(this);
85
- var SsasDiv = SsasInp.next();
86
- var SsasVal = SsasInp.val();
87
- if(SsasAjx)SsasAjx.abort();
88
- SsasInp.removeClass('loading');
89
-
90
- // do a new search
91
- if(SsasInp.attr('data-oldvalue') !== SsasVal && SsasVal.length > 2){
92
- SsasInp.addClass('loading');
93
- SsasAjx = jQuery.post(WsalData.ajaxurl, {
94
- action: 'AjaxSearchSite',
95
- search: SsasVal
96
- }, function(data){
97
- if(SsasAjx)SsasAjx = null;
98
- SsasInp.removeClass('loading');
99
- SsasDiv.hide();
100
- SsasDiv.html('');
101
- if(data && data.length){
102
- var SsasReg = new RegExp(SsasVal.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'gi');
103
- for (var i = 0; i < data.length; i++){
104
- var link = jQuery('<a href="javascript:;" onclick="WsalSsasChange(' + data[i].blog_id + ')"/>')
105
- .text(data[i].blogname + ' (' + data[i].domain + ')');
106
- link.html(link.text().replace(SsasReg, '<u>$&</u>'));
107
- SsasDiv.append(link);
108
- }
109
- }else{
110
- SsasDiv.append(jQuery('<span/>').text(WsalData.tr8n.searchnone));
111
- }
112
- SsasDiv.prepend(jQuery('<a href="javascript:;" onclick="WsalSsasChange(0)" class="allsites"/>').text(WsalData.tr8n.searchback));
113
- SsasDiv.show();
114
- }, 'json');
115
- SsasInp.attr('data-oldvalue', SsasVal);
116
- }
117
-
118
- // handle keys
119
- });
120
- SsasInps.blur(function(){
121
- setTimeout(function(){
122
- var SsasInp = jQuery(this);
123
- var SsasDiv = SsasInp.next();
124
- SsasInp.attr('data-oldvalue', '');
125
- SsasDiv.hide();
126
- }, 200);
127
- });
128
- }
129
-
130
- function WsalSsasChange(value){
131
- jQuery('div.wsal-ssas-dd').hide();
132
- jQuery('input.wsal-ssas').attr('disabled', true);
133
- jQuery('#wsal-cbid').val(value);
134
- jQuery('#audit-log-viewer').submit();
135
- }
136
-
137
- function WsalDisableCustom(link, meta_key){
138
- var nfe = jQuery(this).parents('div:first');
139
- jQuery(link).hide();
140
- jQuery.ajax({
141
- type: 'POST',
142
- url: ajaxurl,
143
- async: false,
144
- data: { action: 'AjaxDisableCustomField', notice: meta_key },
145
- success: function(data) {
146
- var notice = jQuery('<div class="updated" data-notice-name="notifications-extension"></div>').html(data);
147
- jQuery("h2:first").after(notice);
148
- }
149
- });
150
  }
1
+ var WsalData;
2
+
3
+ window['WsalAuditLogRefreshed'] = function(){
4
+ // fix pagination links causing form params to get lost
5
+ jQuery('span.pagination-links a').click(function(ev){
6
+ ev.preventDefault();
7
+ var deparam = function(url){
8
+ var obj = {};
9
+ var pairs = url.split('&');
10
+ for(var i in pairs){
11
+ var split = pairs[i].split('=');
12
+ obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
13
+ }
14
+ return obj;
15
+ };
16
+ var paged = deparam(this.href).paged;
17
+ if (typeof paged === 'undefined') paged = 1;
18
+ jQuery('#audit-log-viewer').append(
19
+ jQuery('<input type="hidden" name="paged"/>').val(paged)
20
+ ).submit();
21
+ });
22
+ };
23
+
24
+ function WsalAuditLogInit(_WsalData){
25
+ WsalData = _WsalData;
26
+ var WsalTkn = WsalData.autorefresh.token;
27
+
28
+ // list refresher
29
+ var WsalAjx = null;
30
+ var WsalChk = function(){
31
+ if(WsalAjx)WsalAjx.abort();
32
+ WsalAjx = jQuery.post(WsalData.ajaxurl, {
33
+ action: 'AjaxRefresh',
34
+ logcount: WsalTkn
35
+ }, function(data){
36
+ WsalAjx = null;
37
+ if(data && data !== 'false'){
38
+ WsalTkn = data;
39
+ jQuery('#audit-log-viewer').load(
40
+ location.href + ' #audit-log-viewer-content',
41
+ window['WsalAuditLogRefreshed']
42
+ );
43
+ }
44
+ WsalChk();
45
+ });
46
+ };
47
+ if(WsalData.autorefresh.enabled){
48
+ setInterval(WsalChk, 40000);
49
+ WsalChk();
50
+ }
51
+
52
+ WsalSsasInit();
53
+ }
54
+
55
+ var WsalIppsPrev;
56
+
57
+ function WsalIppsFocus(value){
58
+ WsalIppsPrev = value;
59
+ }
60
+
61
+ function WsalIppsChange(value){
62
+ if(value === ''){
63
+ value = window.prompt(WsalData.tr8n.numofitems, WsalIppsPrev);
64
+ if(value === null || value === WsalIppsPrev)return this.value = WsalIppsPrev; // operation canceled
65
+ }
66
+ jQuery('select.wsal-ipps').attr('disabled', true);
67
+ jQuery.post(WsalData.ajaxurl, {
68
+ action: 'AjaxSetIpp',
69
+ count: value
70
+ }, function(){
71
+ location.reload();
72
+ });
73
+ }
74
+
75
+ function WsalSsasInit(){
76
+ var SsasAjx = null;
77
+ var SsasInps = jQuery("input.wsal-ssas");
78
+ SsasInps.after('<div class="wsal-ssas-dd" style="display: none;"/>');
79
+ SsasInps.click(function(){
80
+ jQuery(this).select();
81
+ });
82
+ window['WsalAuditLogRefreshed']();
83
+ SsasInps.keyup(function(){
84
+ var SsasInp = jQuery(this);
85
+ var SsasDiv = SsasInp.next();
86
+ var SsasVal = SsasInp.val();
87
+ if(SsasAjx)SsasAjx.abort();
88
+ SsasInp.removeClass('loading');
89
+
90
+ // do a new search
91
+ if(SsasInp.attr('data-oldvalue') !== SsasVal && SsasVal.length > 2){
92
+ SsasInp.addClass('loading');
93
+ SsasAjx = jQuery.post(WsalData.ajaxurl, {
94
+ action: 'AjaxSearchSite',
95
+ search: SsasVal
96
+ }, function(data){
97
+ if(SsasAjx)SsasAjx = null;
98
+ SsasInp.removeClass('loading');
99
+ SsasDiv.hide();
100
+ SsasDiv.html('');
101
+ if(data && data.length){
102
+ var SsasReg = new RegExp(SsasVal.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'gi');
103
+ for (var i = 0; i < data.length; i++){
104
+ var link = jQuery('<a href="javascript:;" onclick="WsalSsasChange(' + data[i].blog_id + ')"/>')
105
+ .text(data[i].blogname + ' (' + data[i].domain + ')');
106
+ link.html(link.text().replace(SsasReg, '<u>$&</u>'));
107
+ SsasDiv.append(link);
108
+ }
109
+ }else{
110
+ SsasDiv.append(jQuery('<span/>').text(WsalData.tr8n.searchnone));
111
+ }
112
+ SsasDiv.prepend(jQuery('<a href="javascript:;" onclick="WsalSsasChange(0)" class="allsites"/>').text(WsalData.tr8n.searchback));
113
+ SsasDiv.show();
114
+ }, 'json');
115
+ SsasInp.attr('data-oldvalue', SsasVal);
116
+ }
117
+
118
+ // handle keys
119
+ });
120
+ SsasInps.blur(function(){
121
+ setTimeout(function(){
122
+ var SsasInp = jQuery(this);
123
+ var SsasDiv = SsasInp.next();
124
+ SsasInp.attr('data-oldvalue', '');
125
+ SsasDiv.hide();
126
+ }, 200);
127
+ });
128
+ }
129
+
130
+ function WsalSsasChange(value){
131
+ jQuery('div.wsal-ssas-dd').hide();
132
+ jQuery('input.wsal-ssas').attr('disabled', true);
133
+ jQuery('#wsal-cbid').val(value);
134
+ jQuery('#audit-log-viewer').submit();
135
+ }
136
+
137
+ function WsalDisableCustom(link, meta_key){
138
+ var nfe = jQuery(this).parents('div:first');
139
+ jQuery(link).hide();
140
+ jQuery.ajax({
141
+ type: 'POST',
142
+ url: ajaxurl,
143
+ async: false,
144
+ data: { action: 'AjaxDisableCustomField', notice: meta_key },
145
+ success: function(data) {
146
+ var notice = jQuery('<div class="updated" data-notice-name="notifications-extension"></div>').html(data);
147
+ jQuery("h2:first").after(notice);
148
+ }
149
+ });
150
  }
js/common.js CHANGED
@@ -1,17 +1,17 @@
1
-
2
- jQuery(document).ready(function(){
3
- jQuery('a.wsal-dismiss-notification').click(function(){
4
- var nfe = jQuery(this).parents('div:first');
5
- var nfn = nfe.attr('data-notice-name');
6
- jQuery.ajax({
7
- type: 'POST',
8
- url: ajaxurl,
9
- async: false,
10
- data: { action: 'AjaxDismissNotice', notice: nfn }
11
- });
12
- nfe.fadeOut();
13
- });
14
-
15
- jQuery('head').append('<style>.wp-submenu .dashicons-external:before{vertical-align: bottom;}</style>');
16
- jQuery("a[href*='page=wsal-extensions']").addClass('dashicons-before dashicons-external').css('color', '#CC4444');
17
- });
1
+
2
+ jQuery(document).ready(function(){
3
+ jQuery('a.wsal-dismiss-notification').click(function(){
4
+ var nfe = jQuery(this).parents('div:first');
5
+ var nfn = nfe.attr('data-notice-name');
6
+ jQuery.ajax({
7
+ type: 'POST',
8
+ url: ajaxurl,
9
+ async: false,
10
+ data: { action: 'AjaxDismissNotice', notice: nfn }
11
+ });
12
+ nfe.fadeOut();
13
+ });
14
+
15
+ jQuery('head').append('<style>.wp-submenu .dashicons-external:before{vertical-align: bottom;}</style>');
16
+ jQuery("a[href*='page=wsal-extensions']").addClass('dashicons-before dashicons-external').css('color', '#CC4444');
17
+ });
js/nice_r.js CHANGED
@@ -1,12 +1,12 @@
1
- function nice_r_toggle(pfx, id){
2
- var el = document.getElementById(pfx+'_v'+id);
3
- if(el){
4
- if(el.style.display==='block'){
5
- el.style.display = 'none';
6
- document.getElementById(pfx+'_a'+id).innerHTML = '&#9658;';
7
- }else{
8
- el.style.display = 'block';
9
- document.getElementById(pfx+'_a'+id).innerHTML = '&#9660;';
10
- }
11
- }
12
  }
1
+ function nice_r_toggle(pfx, id){
2
+ var el = document.getElementById(pfx+'_v'+id);
3
+ if(el){
4
+ if(el.style.display==='block'){
5
+ el.style.display = 'none';
6
+ document.getElementById(pfx+'_a'+id).innerHTML = '&#9658;';
7
+ }else{
8
+ el.style.display = 'block';
9
+ document.getElementById(pfx+'_a'+id).innerHTML = '&#9660;';
10
+ }
11
+ }
12
  }
js/settings.js CHANGED
@@ -1,73 +1,73 @@
1
- jQuery(document).ready(function(){
2
- var RemoveSecToken = function(){
3
- var $this = jQuery(this).parents('span:first');
4
- $this.addClass('sectoken-del').fadeOut('fast', function(){
5
- $this.remove();
6
- });
7
- };
8
-
9
- jQuery('#ViewerQueryBox, #EditorQueryBox, #ExRoleQueryBox, #ExUserQueryBox, #CustomQueryBox, #IpAddrQueryBox').keydown(function(event){
10
- if(event.keyCode === 13) {
11
- var type = jQuery(this).attr('id').substr(0, 6);
12
- jQuery('#'+type+'QueryAdd').click();
13
- return false;
14
- }
15
- });
16
-
17
- jQuery('#ViewerQueryAdd, #EditorQueryAdd, #ExRoleQueryAdd, #ExUserQueryAdd, #CustomQueryAdd, #IpAddrQueryAdd').click(function(){
18
- var type = jQuery(this).attr('id').substr(0, 6);
19
- var value = jQuery.trim(jQuery('#'+type+'QueryBox').val());
20
- var existing = jQuery('#'+type+'List input').filter(function() { return this.value === value; });
21
-
22
- if(!value || existing.length)return; // if value is empty or already used, stop here
23
-
24
- jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', true);
25
- jQuery.post(jQuery('#ajaxurl').val(), {action: 'AjaxCheckSecurityToken', token: value}, function(data){
26
- jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', false);
27
- if (type != 'Custom' && type != 'IpAddr') {
28
- if(data === 'other') {
29
- alert('The specified token is not a user nor a role!');
30
- jQuery('#'+type+'QueryBox').val('');
31
- return;
32
- }
33
- }
34
- jQuery('#'+type+'QueryBox').val('');
35
- jQuery('#'+type+'List').append(jQuery('<span class="sectoken-'+data+'"/>').text(value).append(
36
- jQuery('<input type="hidden" name="'+type+'s[]"/>').val(value),
37
- jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken)
38
- ));
39
- });
40
- });
41
-
42
- jQuery('#ViewerList>span>a, #EditorList>span>a, #ExRoleList>span>a, #ExUserList>span>a, #CustomList>span>a, #IpAddrList>span>a').click(RemoveSecToken);
43
-
44
- jQuery('#RestrictAdmins').change(function(){
45
- var user = jQuery('#RestrictAdminsDefaultUser').val();
46
- var fltr = function() { return this.value === user; };
47
- if (this.checked && jQuery('#EditorList input').filter(fltr).length === 0) {
48
- jQuery('#EditorList').append(
49
- jQuery('<span class="sectoken-user"/>').text(user)
50
- .prepend(jQuery('<input type="hidden" name="Editors[]"/>').val(user))
51
- .append(jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken))
52
- );
53
- } else {
54
- jQuery('#EditorList').children().remove();
55
- }
56
- });
57
-
58
-
59
- var usersUrl = ajaxurl + "?action=AjaxGetAllUsers";
60
- jQuery("#ExUserQueryBox").autocomplete({
61
- source: usersUrl,
62
- minLength:1
63
- });
64
-
65
- var rolesUrl = ajaxurl + "?action=AjaxGetAllRoles";
66
- jQuery("#ExRoleQueryBox").autocomplete({
67
- source: rolesUrl,
68
- minLength:1
69
- });
70
-
71
- });
72
-
73
-
1
+ jQuery(document).ready(function(){
2
+ var RemoveSecToken = function(){
3
+ var $this = jQuery(this).parents('span:first');
4
+ $this.addClass('sectoken-del').fadeOut('fast', function(){
5
+ $this.remove();
6
+ });
7
+ };
8
+
9
+ jQuery('#ViewerQueryBox, #EditorQueryBox, #ExRoleQueryBox, #ExUserQueryBox, #CustomQueryBox, #IpAddrQueryBox').keydown(function(event){
10
+ if(event.keyCode === 13) {
11
+ var type = jQuery(this).attr('id').substr(0, 6);
12
+ jQuery('#'+type+'QueryAdd').click();
13
+ return false;
14
+ }
15
+ });
16
+
17
+ jQuery('#ViewerQueryAdd, #EditorQueryAdd, #ExRoleQueryAdd, #ExUserQueryAdd, #CustomQueryAdd, #IpAddrQueryAdd').click(function(){
18
+ var type = jQuery(this).attr('id').substr(0, 6);
19
+ var value = jQuery.trim(jQuery('#'+type+'QueryBox').val());
20
+ var existing = jQuery('#'+type+'List input').filter(function() { return this.value === value; });
21
+
22
+ if(!value || existing.length)return; // if value is empty or already used, stop here
23
+
24
+ jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', true);
25
+ jQuery.post(jQuery('#ajaxurl').val(), {action: 'AjaxCheckSecurityToken', token: value}, function(data){
26
+ jQuery('#'+type+'QueryBox, #'+type+'QueryAdd').attr('disabled', false);
27
+ if (type != 'Custom' && type != 'IpAddr') {
28
+ if(data === 'other') {
29
+ alert('The specified token is not a user nor a role!');
30
+ jQuery('#'+type+'QueryBox').val('');
31
+ return;
32
+ }
33
+ }
34
+ jQuery('#'+type+'QueryBox').val('');
35
+ jQuery('#'+type+'List').append(jQuery('<span class="sectoken-'+data+'"/>').text(value).append(
36
+ jQuery('<input type="hidden" name="'+type+'s[]"/>').val(value),
37
+ jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken)
38
+ ));
39
+ });
40
+ });
41
+
42
+ jQuery('#ViewerList>span>a, #EditorList>span>a, #ExRoleList>span>a, #ExUserList>span>a, #CustomList>span>a, #IpAddrList>span>a').click(RemoveSecToken);
43
+
44
+ jQuery('#RestrictAdmins').change(function(){
45
+ var user = jQuery('#RestrictAdminsDefaultUser').val();
46
+ var fltr = function() { return this.value === user; };
47
+ if (this.checked && jQuery('#EditorList input').filter(fltr).length === 0) {
48
+ jQuery('#EditorList').append(
49
+ jQuery('<span class="sectoken-user"/>').text(user)
50
+ .prepend(jQuery('<input type="hidden" name="Editors[]"/>').val(user))
51
+ .append(jQuery('<a href="javascript:;" title="Remove">&times;</a>').click(RemoveSecToken))
52
+ );
53
+ } else {
54
+ jQuery('#EditorList').children().remove();
55
+ }
56
+ });
57
+
58
+
59
+ var usersUrl = ajaxurl + "?action=AjaxGetAllUsers";
60
+ jQuery("#ExUserQueryBox").autocomplete({
61
+ source: usersUrl,
62
+ minLength:1
63
+ });
64
+
65
+ var rolesUrl = ajaxurl + "?action=AjaxGetAllRoles";
66
+ jQuery("#ExRoleQueryBox").autocomplete({
67
+ source: rolesUrl,
68
+ minLength:1
69
+ });
70
+
71
+ });
72
+
73
+
readme.txt CHANGED
@@ -7,7 +7,7 @@ License URI: http://www.gnu.org/licenses/gpl.html
7
  Tags: wordpress security plugin, wordpress security audit log, audit log, wordpress log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, security audit trail, wordpress security alerts, wordpress monitor, wordpress security monitor, wordpress admin, wordpress admin monitoring, analytics, activity, admin, multisite, wordpress multisite, actions, dashboard, log, notification, wordpress monitoring, email notification, wordpress email alerts, tracking, user tracking, user activity report, wordpress audit trail
8
  Requires at least: 3.6
9
  Tested up to: 4.5
10
- Stable tag: 2.4.2
11
 
12
  Keep an audit trail of all changes and under the hood WordPress activity to ensure productivity and thwart possible WordPress hacker attacks.
13
 
@@ -18,8 +18,16 @@ Keep an audit log of everything that is happening on your WordPress and [WordPre
18
 
19
  > <strong>Free and Premium Support</strong><br>
20
  >
21
- > WP White Security provides support for WP Security Audit Log plugin on the WordPress forums for free, though please note that it is free support hence it is not always possible to answer all questions on a timely manner, although we do try.
22
- > Personalized premium support is available via email to anyone who purchases any of the [Premium Add-Ons](http://www.wpsecurityauditlog.com/plugin-extensions/), such as the [Email Notifications](http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/), [Search](http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/), [External Database](http://www.wpsecurityauditlog.com/extensions/external-database-for-wp-security-audit-log/) and [Reports](http://www.wpsecurityauditlog.com/extensions/compliance-reports-add-on-for-wordpress/) Add-Ons.
 
 
 
 
 
 
 
 
23
 
24
  = Keep A WordPress Security Audit Log & Identify WordPress Security Issues =
25
  WP Security Audit Log keeps a log of everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A security alert is generated by the plugin when:
@@ -58,25 +66,18 @@ If you own a multi user WordPress blog or website, or a WordPress multisite netw
58
 
59
  Refer to the complete list of [WordPress Security Audit Alerts](http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/) for more information on what other WordPress user activity can be monitored with the WP Security Audit Log WordPress plugin.
60
 
61
- = Get Notified Instantly of Changes on Your WordPress =
62
- <strong>Get notified instantly via email of important changes happening on your blogs and websites running on WordPress and WordPress multisite.</strong>
63
 
64
- Use the premium [Email Notifications Add-On](http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/) to configure monitoring rules and get notified via email of specific actions. For example you can setup notifications rules to be alerted via email should any WordPress user logs in to your WordPress outside office hours. The email alerts include all the details a WordPress administrator or owner might need, such as the source IP address, user, user role, date, time, details about the actual action and much more.
65
 
66
- = Use Free Text Based Searches to Search for Specific Activity on WordPress =
67
- <strong>The search functionality allows you to quickly find specific WordPress activity you are looking for.</strong>
68
 
69
- It is virtually impossible to find specific WordPress activity by manually browsing through thousands of WordPress security alerts. Now you can use the premium [Search Add-On](http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/) to do free text based searches in the WordPress audit log, allowing you to easily pin point specific WordPress user, site, plugin, theme and other activity. The Search extension also has a number of built-in filters that you can use to fine tune your search results, hence allowing you to find the WordPress security alert you are looking for easily and quickly.
70
 
71
- = Improve the Security by Storing the Audit Log in an External Database =
72
- <strong>Store the WordPress Audit Log in an external database to improve the security & Performance of your WordPress websites.</strong>
73
 
74
- By storing the WordPress Audit Log in an external database with the [External DB Add-on](http://www.wpsecurityauditlog.com/extensions/external-database-for-wp-security-audit-log/) you improve the security and perforamnce of your WordPress websites and blogs. The WordPress Audit Log contains a record of everything that has happened on your WordPress hence when stored on an external database you ensure such records are not tempered with even in case the website is hacked. You also ensure that your business WordPress website is compliant to today's strict regulatory compliance requirements.
75
-
76
- = Generate HTML and CSV WordPress Reports =
77
- <strong>Generate WordPress activity reports to ensure users' productivity and meet any legal and regulatory compliance requirements your business needs to adhere to.</strong>
78
-
79
- Use the premium [Reports Add-On](http://www.wpsecurityauditlog.com/extensions/compliance-reports-add-on-for-wordpress/) to generate any type of WordPress report. For example you can generate a WordPress user or group of users activity report, specific role activity report and also site activity report in case you are running WordPress multisite. Unlike other WordPress reports plugins, WSAL Reporting Extension does not have templates that restrict you to specific reports types, but it allows you to choose any data source for your reports.
80
 
81
  = WP Security Audit Log for WordPress Multisite =
82
  WP Security Audit Log is the first tracking and audit WordPress security monitoring plugin that supports WordPress multisite network installations and can monitor activity on such WordPress multisite network installations.
@@ -86,12 +87,6 @@ For more information about the features for WordPress Multisite network installa
86
  = Easily Create Your Own Custom Alerts =
87
  Is there something on your WordPress that the plugin does not monitor, but you would like to keep a record of it? Refer to the [Hooks for custom alerts documentation](https://www.wpsecurityauditlog.com/documentation/create-custom-alerts-wordpress-audit-trail/) to easily create your own custom alerts and keep record of any change on your WordPress, be it a change in a WordPress customization, a third party plugin and more.
88
 
89
- = WordPress Security Audit Log in your Language! =
90
- We need help translating the plugin and the WordPress Security Alerts. If you would like to translate this plugin visit the [WordPress translate Project](https://translate.wordpress.org/) for more information on how to translate the plugin. If you already know how translations work, [start translating WP Security Audit Log now](https://translate.wordpress.org/projects/wp-plugins/wp-security-audit-log) and contact us on plugins@wpwhitesecurity.com for a free license of all add-ons.
91
-
92
- * Italian translation by [Leonardo Musumeci](http://leonardomusumeci.net/)
93
- * German translation by [Mourad Louha](http://excel-translator.de)
94
-
95
  = WordPress & PHP Errors Monitoring Tools =
96
  Plugins and themes customizations are most probably the norm of the day on large WordPress websites, not to mention the installation of new plugins and components. With WP Security Audit Log now it is easier than ever before to monitor your plugins', theme's and other code behaviour, it will generate a alert when a PHP error, warning, exception or shutdown is detected. It is also possible to log all HTTP GET and POST requests that are reaching your WordPress installation to a log file with WP Security Audit Log. Simply enable the PHP Errors monitoring or logging from the plugins settings.
97
 
@@ -100,14 +95,14 @@ NOTE: Developer options should NEVER be enabled on Live websites. They should on
100
  = Other Noteworthy Features =
101
  WP Security Audit Log plugin also has a number of features that make WordPress and WordPress multisite monitoring and auditing easier, such as:
102
 
103
- * Realtime Audit Log viewer to watch user activity as it happens without any delays
104
  * Built-in support for reverse proxies and web application firewalls [more information](http://www.wpsecurityauditlog.com/documentation/automatically-retrieve-originating-wordpress-user-ip-address/)
105
- * Allows you to see what actually changed when the content of posts, pages and custom post types is changed
106
- * Integrated with WhatIsMyIpAddress.com so you to get all information about a source IP with just a mouse click
107
- * Limit who can view the security alerts by users and roles
108
- * Limit who can manage the plugin by users and roles
109
  * Configurable WordPress dashboard widget highlighting the most recent critical activity
110
- * Configurable WordPress security alerts pruning rules
111
  * User role is reported in alerts for a complete overview of what is happening
112
  * User avatar is shown in the alerts for better recognizability
113
  * Enable or disable any security alerts
@@ -141,20 +136,20 @@ We need help translating the plugin and the WordPress Security Alerts. Please vi
141
  = Related Links and Documentation =
142
  For more information and to get started with WordPress Security, check out the following:
143
 
144
- * [What is a WordPress Audit Trail?](https://www.wpsecurityauditlog.com/wordpress-user-monitoring-plugin-documentation/what-is-a-wordpress-audit-trail/]
145
  * [List of WordPress Security Alerts](http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/)
146
  * [WordPress Multisite Features](http://www.wpsecurityauditlog.com/documentation/wordpress-multisite-plugin-features-support/)
147
  * [WP Security Audit Log and Reverse Proxy and WAFs Support](http://www.wpsecurityauditlog.com/documentation/automatically-retrieve-originating-wordpress-user-ip-address/)
148
  * [WP Security Audit Log Database Documentation](http://www.wpsecurityauditlog.com/documentation/plugin-wordpress-database-documentation/)
149
  * [Official WP Security Audit Log Plugin Website](http://www.wpsecurityauditlog.com/)
150
 
151
- = WordPress Security Tips & Tricks =
152
- Even if WordPress security is not your cup of tea, the security of your WordPress is your responsibility. Keep yourself up to date with the latest WordPress Security Tips & Tricks. WP White Security frequently publishes WordPress security tips & tricks on the [WordPress Security section](http://www.wpwhitesecurity.com/wordpress-security/) of their blog.
153
 
154
- = Plugin Newsletter =
155
- To keep yourself updated with what is new and updated in our WordPress security plugins please subscribe to the [WP White Security Plugins Newsletter](http://eepurl.com/Jn9sP).
156
 
157
- **Note: This plugin requires PHP 5.3 or higher to be activated because older versions of PHP are no longer maintained by PHP themselves, which make them prone to security issues. For more information or if you need assistance with your version of PHP please get in touch with us by using our [contact form](http://www.wpsecurityauditlog.com/contact/).**
158
 
159
  == Installation ==
160
 
@@ -170,16 +165,34 @@ Please refer to the [FAQs page](https://www.wpsecurityauditlog.com/documentation
170
  == Screenshots ==
171
 
172
  1. The Audit Log Viewer from where the WordPress administrator can see all the security events generated by WP Security Audit Log WordPress plugin.
173
- 2. The WP Security Audit Log plugin options from where WordPress administrator can configure the auto pruning of security alerts and specific user access.
174
- 3. Configuring WordPress email alerts with the [Email Notifications Add-On](http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/)
175
- 4. Search and filters functionality to automatically search through the WordPress security audit log with the [Search Extension](http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/)
176
- 5. The Enable/Disable Alerts settings node from where Administrators can disable or enable WordPress security alerts.
177
- 6. The Audit Log Viewer of a Super Admin in a WordPress multisite network installation with the Site selection drop down menu.
178
- 7. If there are more than 15 sites in a multisite, an auto complete site search shows up instead of the drop down menu (see [screenshots](https://wordpress.org/plugins/wp-security-audit-log/screenshots/) for reference)
179
- 8. WP Security Audit Log is integrated with the built-in revision system of WordPress, thus allowing you to see what content changes users make on your WordPress posts, pages and custom post types. For more information read [Keep Record of All WordPress Content Changes with WP Security Audit Log Plugin](http://www.wpsecurityauditlog.com/wordpress-user-monitoring-plugin-releases/record-all-wordpress-content-changes-wp-security-audit-log-plugin/)
 
180
 
181
  == Changelog ==
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  = 2.4.2 (2016-04-26) =
184
 
185
  * **Improvement**
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, wordpress audit trail
8
  Requires at least: 3.6
9
  Tested up to: 4.5
10
+ Stable tag: 2.4.3
11
 
12
  Keep an audit trail of all changes and under the hood WordPress activity to ensure productivity and thwart possible WordPress hacker attacks.
13
 
18
 
19
  > <strong>Free and Premium Support</strong><br>
20
  >
21
+ > WP White Security provides support for the WP Security Audit Log plugin on the WordPress forums for free. Since it is free support it is not always possible to answer all questions on a timely manner, although we do try our best.
22
+ >
23
+ > Premium world-class support is available via email to anyone who purchases any of the [Premium Add-Ons](http://www.wpsecurityauditlog.com/plugin-extensions/) listed below:
24
+ >
25
+ >* [All Add-Ons Package](https://www.wpsecurityauditlog.com/extensions/all-add-ons-60-off/)
26
+ >* [Email Notifications](http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/)
27
+ >* [Users Sessions Management](http://www.wpsecurityauditlog.com/extensions/user-sessions-management-wp-security-audit-log/)
28
+ >* [Search](http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/)
29
+ >* [External Database](http://www.wpsecurityauditlog.com/extensions/external-database-for-wp-security-audit-log/)
30
+ >* [Reports](http://www.wpsecurityauditlog.com/extensions/compliance-reports-add-on-for-wordpress/)
31
 
32
  = Keep A WordPress Security Audit Log & Identify WordPress Security Issues =
33
  WP Security Audit Log keeps a log of everything happening on your WordPress blog or website and WordPress multisite network. By using WP Security Audit Log security plugin it is very easy to track suspicious user activity before it becomes a problem or a security issue. A security alert is generated by the plugin when:
66
 
67
  Refer to the complete list of [WordPress Security Audit Alerts](http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/) for more information on what other WordPress user activity can be monitored with the WP Security Audit Log WordPress plugin.
68
 
69
+ = Upgrade to Premium and Extend the Functionaly of the WP Security Audit Log Plugin =
70
+ <strong>[Upgrade to Premium](https://www.wpsecurityauditlog.com/extensions/all-add-ons-60-off/)</strong> to add Email Alerts, Search, Reports and see who is logged in to your WordPress. Else you can buy any of the add-ons listed below separately:
71
 
72
+ * <strong>[Email Notifications Add-On](http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/)</strong>: get notified via email of important changes. You can setup your own triggers to for example be alerted via email should any WordPress user log in to your WordPress outside office hours.
73
 
74
+ * <strong>[Users Sessions Management Add-On](http://www.wpsecurityauditlog.com/extensions/user-sessions-management-wp-security-audit-log/)</strong>: see who is logged in to your WordPress and WordPress multisite networks. This add-on also allows you to terminate users' sessions and either allow or deny multiple sessions for the same WordPress user.
 
75
 
76
+ * <strong>[Search Add-On](http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/)</strong>: do free-text based searches in the WordPress audit trail to easily pin-point a specific WordPress user change. The Search add-on also has built-in filters so you can fine tune your searches and find the WordPress change you are looking for easily and quickly.
77
 
78
+ * <strong>[Reports Add-On](http://www.wpsecurityauditlog.com/extensions/compliance-reports-add-on-for-wordpress/)</strong>: generate any type of HTML and CSV WordPress report. For example generate a WordPress user activity report, role activity report and also site activity report (for WordPress multisite). The Reports Add-On does not restrict you to specific reports types, it allows you to choose any data source for your reports. With this add-on you can also configure automated email summary reports.
 
79
 
80
+ * <strong>[External DB Add-on](http://www.wpsecurityauditlog.com/extensions/external-database-for-wp-security-audit-log/)</strong>: store the WordPress Audit Trail in an external database to improve the security and perforamnce of your WordPress websites and blogs by ensuring such records are not tempered with even in case the website is hacked. By storing the audit trail in an external database you also ensure that your business WordPress website is compliant with today's strict regulatory compliance requirements.
 
 
 
 
 
81
 
82
  = WP Security Audit Log for WordPress Multisite =
83
  WP Security Audit Log is the first tracking and audit WordPress security monitoring plugin that supports WordPress multisite network installations and can monitor activity on such WordPress multisite network installations.
87
  = Easily Create Your Own Custom Alerts =
88
  Is there something on your WordPress that the plugin does not monitor, but you would like to keep a record of it? Refer to the [Hooks for custom alerts documentation](https://www.wpsecurityauditlog.com/documentation/create-custom-alerts-wordpress-audit-trail/) to easily create your own custom alerts and keep record of any change on your WordPress, be it a change in a WordPress customization, a third party plugin and more.
89
 
 
 
 
 
 
 
90
  = WordPress & PHP Errors Monitoring Tools =
91
  Plugins and themes customizations are most probably the norm of the day on large WordPress websites, not to mention the installation of new plugins and components. With WP Security Audit Log now it is easier than ever before to monitor your plugins', theme's and other code behaviour, it will generate a alert when a PHP error, warning, exception or shutdown is detected. It is also possible to log all HTTP GET and POST requests that are reaching your WordPress installation to a log file with WP Security Audit Log. Simply enable the PHP Errors monitoring or logging from the plugins settings.
92
 
95
  = Other Noteworthy Features =
96
  WP Security Audit Log plugin also has a number of features that make WordPress and WordPress multisite monitoring and auditing easier, such as:
97
 
98
+ * Realtime Audit Log viewer allowing you to see the changers as they happen without any delays
99
  * Built-in support for reverse proxies and web application firewalls [more information](http://www.wpsecurityauditlog.com/documentation/automatically-retrieve-originating-wordpress-user-ip-address/)
100
+ * Detailed WordPress audit trail allowing you to see what actually changed when the content of posts, pages and custom post types is changed
101
+ * WhatIsMyIpAddress.com integration so you can get all information about an IP address with just a mouse click
102
+ * Limit who can view the WordPress audit trail by either users or roles
103
+ * Limit who can manage the plugin by either users or roles
104
  * Configurable WordPress dashboard widget highlighting the most recent critical activity
105
+ * Configurable WordPress security audit trail automatic pruning
106
  * User role is reported in alerts for a complete overview of what is happening
107
  * User avatar is shown in the alerts for better recognizability
108
  * Enable or disable any security alerts
136
  = Related Links and Documentation =
137
  For more information and to get started with WordPress Security, check out the following:
138
 
139
+ * [What is a WordPress Audit Trail?](https://www.wpsecurityauditlog.com/wordpress-user-monitoring-plugin-documentation/what-is-a-wordpress-audit-trail/)
140
  * [List of WordPress Security Alerts](http://www.wpsecurityauditlog.com/documentation/list-monitoring-wordpress-security-alerts-audit-log/)
141
  * [WordPress Multisite Features](http://www.wpsecurityauditlog.com/documentation/wordpress-multisite-plugin-features-support/)
142
  * [WP Security Audit Log and Reverse Proxy and WAFs Support](http://www.wpsecurityauditlog.com/documentation/automatically-retrieve-originating-wordpress-user-ip-address/)
143
  * [WP Security Audit Log Database Documentation](http://www.wpsecurityauditlog.com/documentation/plugin-wordpress-database-documentation/)
144
  * [Official WP Security Audit Log Plugin Website](http://www.wpsecurityauditlog.com/)
145
 
146
+ = Stay a Step Ahead of the Bad Guys - Keep Yourself Informed =
147
+ Even if WordPress security is not your cup of tea, the security of your WordPress is your responsibility. Keep yourself up to date with the latest WordPress Security Tips, Tricks and news. <strong>[Subscribe to the WP Security Bloggers newsletter](http://www.wpsecuritybloggers.com/subscribe-wordpress-security-daily-weekly-roundup), for an aggregate of posts from the most popular WordPress security blogs.
148
 
149
+ = WP Security Audit Log Plugin Newsletter =
150
+ To keep yourself updated with what is new and updated in the WP Security Audit Log plugin please [subscribe to the newsletter](https://www.wpsecurityauditlog.com/subscribe-newsletter/).
151
 
152
+ **Note: This plugin requires PHP 5.3 or higher. Older versions of PHP are no longer maintained by PHP and are prone to security issues. For more information or if you need assistance with your version of PHP please get in touch with us by using our [contact form](http://www.wpsecurityauditlog.com/contact/).**
153
 
154
  == Installation ==
155
 
165
  == Screenshots ==
166
 
167
  1. The Audit Log Viewer from where the WordPress administrator can see all the security events generated by WP Security Audit Log WordPress plugin.
168
+ 2. See who is logged in to your WordPress and manage users sessions with the [Users Sessions Management Add-On](http://www.wpsecurityauditlog.com/extensions/user-sessions-management-wp-security-audit-log/)
169
+ 3. The WP Security Audit Log plugin options from where WordPress administrator can configure the auto pruning of security alerts and specific user access.
170
+ 4. Configuring WordPress email alerts with the [Email Notifications Add-On](http://www.wpsecurityauditlog.com/extensions/wordpress-email-notifications-add-on/)
171
+ 5. Search and filters functionality to automatically search through the WordPress security audit log with the [Search Extension](http://www.wpsecurityauditlog.com/extensions/search-add-on-for-wordpress-security-audit-log/)
172
+ 6. The Enable/Disable Alerts settings node from where Administrators can disable or enable WordPress security alerts.
173
+ 7. The Audit Log Viewer of a Super Admin in a WordPress multisite network installation with the Site selection drop down menu.
174
+ 8. If there are more than 15 sites in a multisite, an auto complete site search shows up instead of the drop down menu (see [screenshots](https://wordpress.org/plugins/wp-security-audit-log/screenshots/) for reference)
175
+ 9. WP Security Audit Log is integrated with the built-in revision system of WordPress, thus allowing you to see what content changes users make on your WordPress posts, pages and custom post types. For more information read [Keep Record of All WordPress Content Changes with WP Security Audit Log Plugin](http://www.wpsecurityauditlog.com/wordpress-user-monitoring-plugin-releases/record-all-wordpress-content-changes-wp-security-audit-log-plugin/)
176
 
177
  == Changelog ==
178
 
179
+ = 2.4.3 (2016-06-01) =
180
+
181
+ * **New Add-On Support**
182
+ * Included code to support the new [Users Sessions Management Add-On](http://www.wpsecurityauditlog.com/extensions/user-sessions-management-wp-security-audit-log/), which allows you to see who is logged in to your WordPress and WordPress multisite networks.
183
+
184
+ * **New Alerts in the WordPress Audit Trail**
185
+ * 1004: A login attempt was blocked because a session with the same username already exists
186
+ * 1005: Multiple logged-in sessions for the same WordPress username has been detected
187
+
188
+ * **Improvement**
189
+ * Plugin reports changes when an object is moved as a sub object in a menu.
190
+
191
+ * **Bug fixes**
192
+ * Fixed a problem where wrong permissions were assigned to the reports directory in the uploads directory for the [Reports Add-On](https://www.wpsecurityauditlog.com/extensions/compliance-reports-add-on-for-wordpress/).
193
+ * Fixed an issue where multiple incorrect changes were reported when changing the structure of a menu [Support ticket](https://wordpress.org/support/topic/multiple-entries-when-adding-menu-item).
194
+ * Fixed a bug in the settings sensor [support ticket](https://wordpress.org/support/topic/php-warning-missing-argument-2-for-wsal_sensors_systemwpupdate?replies=1).
195
+
196
  = 2.4.2 (2016-04-26) =
197
 
198
  * **Improvement**
uninstall.php CHANGED
@@ -1,7 +1,7 @@
1
- <?php
2
-
3
- // if uninstall not called from WordPress exit
4
- if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) exit();
5
-
6
- require('wp-security-audit-log.php');
7
  WpSecurityAuditLog::GetInstance()->Uninstall();
1
+ <?php
2
+
3
+ // if uninstall not called from WordPress exit
4
+ if ( !defined( 'WP_UNINSTALL_PLUGIN' ) ) exit();
5
+
6
+ require('wp-security-audit-log.php');
7
  WpSecurityAuditLog::GetInstance()->Uninstall();
wp-security-audit-log.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: WP Security Audit Log
4
  Plugin URI: http://www.wpsecurityauditlog.com/
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.4.2
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpsecurityauditlog.com/
10
  License: GPL2
4
  Plugin URI: http://www.wpsecurityauditlog.com/
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.4.3
8
  Text Domain: wp-security-audit-log
9
  Author URI: http://www.wpsecurityauditlog.com/
10
  License: GPL2