WP Security Audit Log - Version 0.2

Version Description

  • Restricted plugin options and WordPress Audit Log Event Viewer only to WordPress administrators
  • Improved failed logins events (events generated from the same IP, or same username will be grouped to avoid mass flooding of security events)
  • Security Events pruning now uses wp-cron functionality (improved stability and reliability of events pruning)
  • Applied several performance improvements (faster loading of events etc)
  • Added support for permalinks; now events will include page or blog post URL rather than ID
  • Added new alerts for when a page or blog post status is changed from draft, pending review or published
  • Added new alert for when a page or blog post URL or author is changed
  • Added new alert for when a blog post category is changed
  • Added new alerts for when a user creates or deletes a category
  • Added new alert for when the author of a blog post or page is changed
  • Added new plugin alerts for when a plugin is installed, uninstalled or upgraded
  • Updated navigation menu to use standard WordPress dashboard icons etc
Download this release

Release Info

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

Code changes from version 0.1 to 0.2

inc/WPPH.php CHANGED
@@ -1,31 +1,33 @@
1
  <?php
2
  /**
3
- * @kyos
4
  * Base class
5
  */
6
  class WPPH
7
  {
8
  /**
9
  * @return bool
10
- * Convenient method to check whether or not the plugin can safely run
11
  */
12
- public static function canRun() { return WPPHDatabase::canRun(); }
 
 
 
 
 
13
  /**
14
  * @return bool
15
  * Convenient method to check whether or not the plugin's resources can be loaded
16
  */
17
- public static function canLoad() {
18
- if(false === ($pos = stripos($_SERVER['REQUEST_URI'], WPPH_PLUGIN_PREFIX))){ return false; }
19
- return true;
20
- }
21
 
22
  public static function loadBaseResources()
23
  {
24
  if(self::canLoad())
25
  {
26
  wp_enqueue_style('wpph_styles_base', WPPH_PLUGIN_URL . 'res/css/styles.base.css');
27
- wp_enqueue_script('wpph-ko-js', WPPH_PLUGIN_URL . 'res/js/knockout-2.2.1.min.js' );
28
- wp_enqueue_script('wpph-alvm-js', WPPH_PLUGIN_URL . 'res/js/AuditLogViewModel.js' );
 
29
  }
30
  }
31
 
@@ -102,6 +104,114 @@ class WPPH
102
  update_option(WPPH_PLUGIN_SETTING_NAME, $settings);
103
  wpphLog('Settings saved.', $settings);
104
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
 
107
 
1
  <?php
2
  /**
 
3
  * Base class
4
  */
5
  class WPPH
6
  {
7
  /**
8
  * @return bool
9
+ * Convenient method to check whether or not the user has access rights
10
  */
11
+ public static function canRun() {
12
+ if(! WPPHUtil::isAdministrator()){ return false; }
13
+ // todo: when we add option to select individual admins...
14
+ //todo...
15
+ return true;
16
+ }
17
  /**
18
  * @return bool
19
  * Convenient method to check whether or not the plugin's resources can be loaded
20
  */
21
+ public static function canLoad() { return ((false === ($pos = stripos($_SERVER['REQUEST_URI'], WPPH_PLUGIN_PREFIX))) ? false : true); }
 
 
 
22
 
23
  public static function loadBaseResources()
24
  {
25
  if(self::canLoad())
26
  {
27
  wp_enqueue_style('wpph_styles_base', WPPH_PLUGIN_URL . 'res/css/styles.base.css');
28
+ wp_enqueue_script('wpph-ko-js', WPPH_PLUGIN_URL . 'res/js/knockout.js' );
29
+ wp_enqueue_script('wpph-alvm-js', WPPH_PLUGIN_URL . 'res/js/audit-view-model.js' );
30
+ wp_enqueue_script('wpph-jcookie-js', WPPH_PLUGIN_URL . 'res/js/jquery-ck.js' );
31
  }
32
  }
33
 
104
  update_option(WPPH_PLUGIN_SETTING_NAME, $settings);
105
  wpphLog('Settings saved.', $settings);
106
  }
107
+
108
+ public static function optionExists($optionName) { return (false === get_option($optionName, false) ? false : true); }
109
+
110
+ public static function onPluginActivate()
111
+ {
112
+ $optErrorData = array();
113
+ $canContinue = true;
114
+ // Check: MySQL, PHP - without these there's not much left for this plugin to do
115
+ if(! self::__checkMySQL()){
116
+ $optErrorData = self::__addError($optErrorData, 'e400');
117
+ $canContinue = false;
118
+ }
119
+ if(! self::__checkPHP()){
120
+ $optErrorData = self::__addError($optErrorData, 'e300');
121
+ $canContinue = false;
122
+ }
123
+ // no need for further checks, the plugin cannot run on this server...
124
+ if(! $canContinue){
125
+ $optErrorData = self::__addError($optErrorData, 'e500');
126
+ update_option(WPPH_PLUGIN_ERROR_OPTION_NAME, $optErrorData);
127
+ return false;
128
+ }
129
+
130
+ // check to see whether or not an upgrade is necessary
131
+ $v = get_option(WPPH_PLUGIN_VERSION_OPTION_NAME,false);
132
+ if($v != false)
133
+ {
134
+ $v = (float)$v;
135
+ $cv = (float)WPPH_PLUGIN_VERSION;
136
+ //#! no need for upgrade
137
+ if($v == $cv){
138
+ update_option(WPPH_PLUGIN_VERSION_OPTION_NAME, WPPH_PLUGIN_VERSION);
139
+ WPPHEvent::hookWatchPluginActivity(); //#! log self installation
140
+ return true;
141
+ }
142
+ }
143
+
144
+ if(! WPPHDatabase::v2Cleanup()){
145
+ $optErrorData = self::__addError($optErrorData, 'e600');
146
+ update_option(WPPH_PLUGIN_ERROR_OPTION_NAME, $optErrorData);
147
+ return false;
148
+ }
149
+
150
+ //#! run the upgrade / update
151
+ if(($result = WPPHDatabase::handleTables()) !== true)
152
+ {
153
+ $optErrorData = self::__addError($optErrorData, 'e'.$result);
154
+ }
155
+
156
+ if(empty($optErrorData)){
157
+ update_option(WPPH_PLUGIN_VERSION_OPTION_NAME, WPPH_PLUGIN_VERSION);
158
+ WPPHEvent::hookWatchPluginActivity(); //#! log self installation
159
+ return true;
160
+ }
161
+
162
+ update_option(WPPH_PLUGIN_ERROR_OPTION_NAME, $optErrorData);
163
+ return false;
164
+ }
165
+
166
+ /**
167
+ * triggered when the plugin is deactivated
168
+ */
169
+ public static function onPluginDeactivate()
170
+ {
171
+ if(self::optionExists(WPPH_PLUGIN_ERROR_OPTION_NAME)){ delete_option(WPPH_PLUGIN_ERROR_OPTION_NAME); }
172
+ if(self::optionExists(WPPH_PLUGIN_SETTING_NAME)){ delete_option(WPPH_PLUGIN_SETTING_NAME); }
173
+ wp_clear_scheduled_hook(WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME);
174
+ wpphLog('Plugin deactivated.');
175
+ }
176
+
177
+
178
+ public static function __addError(array $errorData, $errorCode, $arg=''){
179
+ $errorData["$errorCode"] = base64_encode($arg);
180
+ return $errorData;
181
+ }
182
+
183
+ /**
184
+ * @internal
185
+ * @static
186
+ * @var array Holds the list or errors generated during install
187
+ */
188
+ private static $_errors = array();
189
+
190
+ // must only be called in pages
191
+ public static function ready()
192
+ {
193
+ if(empty(self::$_errors)){
194
+ self::$_errors = self::getPluginErrors();
195
+ if(empty(self::$_errors)){
196
+ return true;
197
+ }
198
+ }
199
+ return false;
200
+ }
201
+
202
+ public static function isInstalled() { return self::optionExists(WPPH_PLUGIN_DB_UPDATED); }
203
+
204
+ public static function getPluginErrors() { return get_option(WPPH_PLUGIN_ERROR_OPTION_NAME,null); }
205
+
206
+ private static function __checkMySQL(){
207
+ global $wpdb;
208
+ $v = $wpdb->get_var("SELECT VERSION();");
209
+ if(empty($v)){ return false; }
210
+ $v = trim($v);
211
+ if(intval($v[0]) < 5){ return false; }
212
+ return true;
213
+ }
214
+ private static function __checkPHP(){ return (version_compare(phpversion(), '5.0.0', '>')); }
215
  }
216
 
217
 
inc/WPPHAdminNotices.php CHANGED
@@ -10,18 +10,12 @@ class WPPHAdminNotices
10
  if(is_callable(array(__CLASS__,$f))){ add_action('admin_notices',array(__CLASS__,$f)); }
11
  }
12
 
13
- public static function e100(){
14
- $m = __('Plugin cannot create tables in the WordPress database to store security audit logs. Allow write access to the WordPress database user temporarily to activate this plugin. For more information contact us on support@wpprohelp.com.');
15
- echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
16
- }
17
-
18
-
19
  public static function e0()
20
  {
21
  $tableName = WPPHDatabase::getFullTableName('events');
22
  $query = '<pre><code>'.WPPHDatabase::getCreateQueryEventsDetailsTable().'</code></pre>';
23
  $m = sprintf(
24
- __('The table <strong>%s</strong> was not found nor it could be created.<br/>Please run this query manually then reload this page: %s')
25
  , $tableName, $query);
26
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
27
  }
@@ -43,10 +37,15 @@ class WPPHAdminNotices
43
  public static function e2()
44
  {
45
  $tableName = WPPHDatabase::getFullTableName('events');
46
- $query = '<pre><code>'.WPPHDatabase::getUpgradeQueryEventsDetailsTable().'</code></pre>';
 
 
 
 
 
47
  $m = sprintf(
48
- __('The table <strong>%s</strong> could not be updated.<br/>Please run this query manually then reload this page: %s')
49
- , $tableName, $query);
50
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
51
  }
52
 
@@ -55,7 +54,7 @@ class WPPHAdminNotices
55
  $tableName = WPPHDatabase::getFullTableName('main');
56
  $query = '<pre><code>'.WPPHDatabase::getCreateQueryLogsTable().'</code></pre>';
57
  $m = sprintf(
58
- __('The table <strong>%s</strong> was not found nor it could be created.<br/>Please run this query manually then reload this page: %s')
59
  , $tableName, $query);
60
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
61
  }
@@ -65,7 +64,7 @@ class WPPHAdminNotices
65
  $tableName = WPPHDatabase::getFullTableName('main');
66
  $query = '<pre><code>'.WPPHDatabase::getUpdateQueryLogsTable().'</code></pre>';
67
  $m = sprintf(
68
- __('The table <strong>%s</strong> could not be updated.<br/>Please run this query manually then reload this page: %s')
69
  , $tableName, $query);
70
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
71
  }
@@ -73,10 +72,56 @@ class WPPHAdminNotices
73
  public static function e5()
74
  {
75
  $tableName = WPPHDatabase::getFullTableName('main');
76
- $query = '<pre><code>'.WPPHDatabase::getUpgradeQueryLogsTable().'</code></pre>';
 
 
 
 
 
77
  $m = sprintf(
78
- __('The table <strong>%s</strong> could not be updated.<br/>Please run this query manually then reload this page: %s')
79
- , $tableName, $query);
80
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
10
  if(is_callable(array(__CLASS__,$f))){ add_action('admin_notices',array(__CLASS__,$f)); }
11
  }
12
 
 
 
 
 
 
 
13
  public static function e0()
14
  {
15
  $tableName = WPPHDatabase::getFullTableName('events');
16
  $query = '<pre><code>'.WPPHDatabase::getCreateQueryEventsDetailsTable().'</code></pre>';
17
  $m = sprintf(
18
+ __('The table <strong>%s</strong> was not found nor it could be created.<br/>Please run this query manually and reactivate the plugin: %s')
19
  , $tableName, $query);
20
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
21
  }
37
  public static function e2()
38
  {
39
  $tableName = WPPHDatabase::getFullTableName('events');
40
+ $queries = WPPHDatabase::getUpgradeQueryEventsDetailsTable();
41
+ $out = '<pre>';
42
+ foreach($queries as $query){
43
+ $out .= "<code>{$query}</code><br/>";
44
+ }
45
+ $out .= '</pre>';
46
  $m = sprintf(
47
+ __('The table <strong>%s</strong> could not be updated.<br/>Please run the following queries manually and reactivate the plugin: %s')
48
+ , $tableName, $out);
49
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
50
  }
51
 
54
  $tableName = WPPHDatabase::getFullTableName('main');
55
  $query = '<pre><code>'.WPPHDatabase::getCreateQueryLogsTable().'</code></pre>';
56
  $m = sprintf(
57
+ __('The table <strong>%s</strong> was not found nor it could be created.<br/>Please run this query manually and reactivate the plugin: %s')
58
  , $tableName, $query);
59
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
60
  }
64
  $tableName = WPPHDatabase::getFullTableName('main');
65
  $query = '<pre><code>'.WPPHDatabase::getUpdateQueryLogsTable().'</code></pre>';
66
  $m = sprintf(
67
+ __('The table <strong>%s</strong> could not be updated.<br/>Please run this query manually and reactivate the plugin: %s')
68
  , $tableName, $query);
69
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
70
  }
72
  public static function e5()
73
  {
74
  $tableName = WPPHDatabase::getFullTableName('main');
75
+ $queries = WPPHDatabase::getUpgradeQueryLogsTable();
76
+ $out = '<pre>';
77
+ foreach($queries as $query){
78
+ $out .= "<code>{$query}</code><br/>";
79
+ }
80
+ $out .= '</pre>';
81
  $m = sprintf(
82
+ __('The table <strong>%s</strong> could not be updated.<br/>Please run the following queries manually and reactivate the plugin: %s')
83
+ , $tableName, $out);
84
  echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
85
  }
86
+
87
+ // MySQL < 5
88
+ public static function e6(){
89
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> Plugin could not be properly installed. MySQL version detected is lower than 5.</p></div>';
90
+ }
91
+ // PHP < 5
92
+ public static function e7(){
93
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> Plugin could not be properly installed. PHP version detected is lower than 5.</p></div>';
94
+ }
95
+
96
+
97
+ public static function e100(){
98
+ $m = __('Plugin cannot create tables in the WordPress database to store security audit logs. Allow write access to the WordPress database user temporarily to activate this plugin.
99
+ For more information contact us on support@wpprohelp.com.');
100
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> '.$m.'</p></div>';
101
+ }
102
+ public static function e200($missingRights=''){
103
+ if(! empty($missingRights)){
104
+ $missingRights = base64_decode($missingRights);
105
+ }
106
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> Plugin could not be properly installed.
107
+ The db user used to connect to the WordPress database is missing the following rights: '.$missingRights.'.</p></div>';
108
+ }
109
+ public static function e300(){
110
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> Plugin could not be properly installed.
111
+ The PHP version installed on this server is less than 5.</p></div>';
112
+ }
113
+ public static function e400(){
114
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Error').':</strong> Plugin could not be properly installed.
115
+ The MySQL version installed on this server is less than 5.</p></div>';
116
+ }
117
+ public static function e500(){
118
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Fatal Error').':</strong> Plugin could not be properly installed because the server does not meet our requirements:
119
+ MySQL and PHP version >= 5.</p></div>';
120
+ }
121
+ public static function e600(){
122
+ echo '<div class="error"><p><strong>'.WPPH_PLUGIN_NAME.' '.__('Fatal Error').':</strong> Plugin could not be properly upgraded because we could not empty the content of the following tables: ';
123
+ echo '<br/><strong>'.WPPHDatabase::getFullTableName('main').'</strong>';
124
+ echo '<br/><strong>'.WPPHDatabase::getFullTableName('events').'</strong>';
125
+ echo '</p></div>';
126
+ }
127
  }
inc/WPPHDatabase.php CHANGED
@@ -9,7 +9,9 @@ class WPPHDatabase
9
  * @var bool
10
  * Whether or not we can safely use the plugin
11
  */
12
- private static $_canRun = true;
 
 
13
 
14
  /**
15
  * @var string
@@ -17,6 +19,7 @@ class WPPHDatabase
17
  * Holds the name of the event logs table WITHOUT the db prefix!
18
  */
19
  private static $_eventsLogTableBaseName = '_wordpress_eventlog';
 
20
  /**
21
  * @var string
22
  * @private
@@ -25,41 +28,153 @@ class WPPHDatabase
25
  private static $_eventsDetailsTableBaseName = '_wordpress_eventlog_details';
26
 
27
 
28
- public static function checkTables()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  {
30
- //#! EVENT DETAILS TABLE
31
- if(! self::_createEventDetailsTable()){
32
- WPPHAdminNotices::show(0);
33
- return false;
34
  }
35
- if(! self::_updateEventsDetailsTable()){
36
- WPPHAdminNotices::show(1);
37
- return false;
38
  }
39
- if(! self::_upgradeEventDetailsTable()){
40
- WPPHAdminNotices::show(2);
41
- return false;
 
 
 
 
 
42
  }
43
 
44
- //#! EVENT LOGS MAIN TABLE
45
- if(! self::_createEventLogsTable()){
46
- WPPHAdminNotices::show(3);
47
- return false;
48
  }
49
- if(! self::_updateEventLogsTable()){
50
- WPPHAdminNotices::show(4);
51
- return false;
52
  }
53
- if(! self::_upgradeEventLogsTable()){
54
- WPPHAdminNotices::show(5);
55
- return false;
 
 
 
 
 
 
56
  }
57
 
58
- self::$_canRun = true;
 
 
 
 
 
 
59
  return true;
60
  }
61
 
62
- public static function canRun() { return self::$_canRun; }
 
 
 
 
 
 
63
 
64
  /**
65
  * Returns the full table name db_prefix + base_table_name for the requested table
@@ -80,12 +195,10 @@ class WPPHDatabase
80
  return '';
81
  }
82
 
83
-
84
-
85
  public static function getCreateQueryEventsDetailsTable()
86
  {
87
  global $wpdb;
88
- $tableName = $wpdb->prefix.self::$_eventsDetailsTableBaseName;
89
  return "CREATE TABLE IF NOT EXISTS `$tableName` (
90
  `EventID` int(8) NOT NULL,
91
  `EventType` varchar(10) DEFAULT 'NOTICE',
@@ -97,16 +210,13 @@ class WPPHDatabase
97
 
98
  public static function getUpdateQueryEventsDetailsTable()
99
  {
100
- global $wpdb;
101
- $tableName = $wpdb->prefix.self::$_eventsDetailsTableBaseName;
102
-
103
  $out = array();
104
  $entries = WPPHEvent::listEvents();
105
  if(empty($entries)){ return $out; }
106
 
107
  foreach($entries as $entry)
108
  {
109
- $q = sprintf("INSERT INTO `%s` (`EventID`,`EventType`,`EventDescription`) VALUES(%d,'%s','%s')", $tableName, $entry['id'], $entry['category'], $entry['text']);
110
  $out["{$entry['id']}"] = $q;
111
  }
112
  return $out;
@@ -115,7 +225,7 @@ class WPPHDatabase
115
  //@todo: UPDATE AS NECESSARY
116
  public static function getUpgradeQueryEventsDetailsTable()
117
  {
118
- return '';
119
  }
120
 
121
 
@@ -134,14 +244,17 @@ class WPPHDatabase
134
  UNIQUE KEY `EventNumber` (`EventNumber`)
135
  );";
136
  }
137
-
138
  public static function getUpdateQueryLogsTable()
139
  {
140
  return '';
141
  }
142
  public static function getUpgradeQueryLogsTable()
143
  {
144
- return '';
 
 
 
145
  }
146
 
147
 
@@ -150,7 +263,7 @@ class WPPHDatabase
150
  if(self::_eventDetailsTableExists()) { return true; }
151
  global $wpdb;
152
  $query = self::getCreateQueryEventsDetailsTable();
153
- if (false === $wpdb->query($wpdb->prepare($query))){ return false; }
154
  return true;
155
  }
156
 
@@ -160,12 +273,18 @@ class WPPHDatabase
160
  private static function _updateEventsDetailsTable()
161
  {
162
  global $wpdb;
 
163
  $queries = self::getUpdateQueryEventsDetailsTable();
 
 
 
 
164
  foreach($queries as $id => $query){
165
  if(! empty($query)){
166
- $var = $wpdb->get_var("SELECT EventID FROM ".self::getFullTableName('events')." WHERE EventID = $id");
167
  if(empty($var)){
168
- if(false === $wpdb->query($query)){
 
169
  return false;
170
  }
171
  }
@@ -178,6 +297,17 @@ class WPPHDatabase
178
  private static function _upgradeEventDetailsTable()
179
  {
180
  //EXECUTE THE QUERY FROM self::getUpgradeQueryEventsDetailsTable();
 
 
 
 
 
 
 
 
 
 
 
181
  return true;
182
  }
183
 
@@ -187,7 +317,7 @@ class WPPHDatabase
187
  if(self::_eventLogsTableExists()){ return true;}
188
  global $wpdb;
189
  $query = self::getCreateQueryLogsTable();
190
- if(false === $wpdb->query($wpdb->prepare($query))){return false;}
191
  return true;
192
  }
193
 
@@ -200,51 +330,34 @@ class WPPHDatabase
200
  private static function _upgradeEventLogsTable()
201
  {
202
  //EXECUTE THE QUERY FROM self::getUpgradeQueryLogsTable();
 
 
 
 
 
 
 
 
 
 
 
203
  return true;
204
  }
205
 
206
  private static function _eventLogsTableExists()
207
  {
208
  global $wpdb;
209
- $tableName = $wpdb->prefix.self::$_eventsLogTableBaseName;
210
- $result = $wpdb->get_var($wpdb->prepare('SELECT EventNumber FROM '.$tableName));
211
  return (is_null($result) ? false : true);
212
 
213
  }
214
  private static function _eventDetailsTableExists()
215
  {
216
  global $wpdb;
217
- $tableName = $wpdb->prefix.self::$_eventsDetailsTableBaseName;
218
- $result = $wpdb->get_var($wpdb->prepare('SELECT EventID FROM '.$tableName));
219
  return (is_null($result) ? false : true);
220
  }
221
 
222
- //!! TODO: CHECK
223
- public static function userHasAccessRights()
224
- {
225
- global $wpdb;
226
-
227
- $rights = $wpdb->get_results("SHOW GRANTS FOR CURRENT_USER()", ARRAY_N);
228
-
229
- if(empty($rights)) return false;
230
-
231
- foreach($rights as $right){
232
- if(!empty($right[0])){
233
- $r = strtoupper($right[0]);
234
- if (preg_match("/GRANT ALL PRIVILEGES/i", $r)) { return true; }
235
- else{
236
- if (preg_match_all("/CREATE|DELETE|ALTER|INSERT|UPDATE|SELECT|DELETE/i", $r, $matches)){
237
- if (! empty($matches[0])){
238
- $m = $matches[0];
239
- $m = array_unique($m);
240
- if (count($m) >= 5){ return true; }
241
- }
242
- }
243
- }
244
- }
245
- }
246
- return false;
247
- }
248
  }
249
 
250
  /**
@@ -269,7 +382,7 @@ class WPPHDB extends WPPHDatabase
269
  {
270
  global $wpdb;
271
 
272
- $t = $wpdb->prefix.'users';
273
 
274
  $username = $wpdb->get_var("SELECT user_login FROM $t WHERE ID=$userID");
275
  $user = new WP_User( $userID );
@@ -288,8 +401,7 @@ class WPPHDB extends WPPHDatabase
288
  public static function getEventsCount()
289
  {
290
  global $wpdb;
291
- $result = $wpdb->get_var("SELECT COUNT(EventNumber) FROM ".self::getFullTableName('main'));
292
- return intval($result);
293
  }
294
 
295
  }
9
  * @var bool
10
  * Whether or not we can safely use the plugin
11
  */
12
+ private static $_canRun = false;
13
+
14
+ private static $_canUpgrade = false;
15
 
16
  /**
17
  * @var string
19
  * Holds the name of the event logs table WITHOUT the db prefix!
20
  */
21
  private static $_eventsLogTableBaseName = '_wordpress_eventlog';
22
+
23
  /**
24
  * @var string
25
  * @private
28
  private static $_eventsDetailsTableBaseName = '_wordpress_eventlog_details';
29
 
30
 
31
+ private static $_tablesCreated = false;
32
+ private static $_tablesUpgraded = false;
33
+ private static $_tablesUpdated = false;
34
+
35
+
36
+ //================================================================================================================
37
+
38
+ /**
39
+ * @temp
40
+ * @internal
41
+ * Prepares the tables for v0.2 upgrade as there are some differencies between old & new events
42
+ */
43
+ public static function v2Cleanup()
44
+ {
45
+ global $wpdb;
46
+
47
+ // empty table 1
48
+
49
+ if(self::_eventLogsTableExists())
50
+ {
51
+ $query = "TRUNCATE ".$wpdb->prefix.self::$_eventsLogTableBaseName;
52
+
53
+ if(false === $wpdb->query($query)){
54
+ self::$_canUpgrade = false;
55
+ }
56
+ else { self::$_canUpgrade = true; }
57
+ }
58
+ else { self::$_canUpgrade = true; }
59
+
60
+ // empty table 2
61
+ if(self::_eventDetailsTableExists())
62
+ {
63
+ $query = "TRUNCATE ".$wpdb->prefix.self::$_eventsDetailsTableBaseName;
64
+
65
+ if(false === $wpdb->query($query)){
66
+ self::$_canUpgrade = false;
67
+ }
68
+ else { self::$_canUpgrade = true; }
69
+ }
70
+ else { self::$_canUpgrade = true; }
71
+
72
+ return self::$_canUpgrade;
73
+ }
74
+
75
+
76
+ public static function handleTables()
77
+ {
78
+ if(! self::$_canUpgrade){
79
+ return 6;
80
+ }
81
+
82
+ if(! self::tablesExist())
83
+ {
84
+ $result = WPPHDatabase::createTables();
85
+ if($result !== true){
86
+ return $result;
87
+ }
88
+ }
89
+
90
+ $result = self::upgradeTables();
91
+ if($result !== true){
92
+ return $result;
93
+ }
94
+
95
+ $result = self::updateTables();
96
+ if($result !== true){
97
+ return $result;
98
+ }
99
+
100
+ update_option(WPPH_PLUGIN_DB_UPDATED,1);
101
+ return true;
102
+ }
103
+
104
+ // check to see whether or not the tables exist in the database
105
+ public static function tablesExist()
106
+ {
107
+ global $wpdb;
108
+ $tables = $wpdb->get_results("SHOW TABLES;",ARRAY_N);
109
+ $t1 = self::getFullTableName('main');
110
+ $t2 = self::getFullTableName('events');
111
+ $r1 = $r2 = false;
112
+ foreach($tables as $table){
113
+ if(strcasecmp($t1, $table[0])==0){ $r1 = true; }
114
+ elseif(strcasecmp($t2, $table[0])==0){ $r2 = true; }
115
+ }
116
+ if($r1 == true && $r2 == true){
117
+ self::$_tablesCreated = true;
118
+ return true;
119
+ }
120
+ return false;
121
+ }
122
+
123
+ public static function createTables()
124
  {
125
+ global $wpdb;
126
+ if(! self::_eventDetailsTableExists()) {
127
+ $query = self::getCreateQueryEventsDetailsTable();
128
+ if (false === @$wpdb->query($query)){ return 0; }
129
  }
130
+ if(! self::_eventLogsTableExists()){
131
+ $query = self::getCreateQueryLogsTable();
132
+ if(false === @$wpdb->query($query)){return 3;}
133
  }
134
+ return true;
135
+ }
136
+
137
+ public static function upgradeTables()
138
+ {
139
+ $optData = get_option(WPPH_PLUGIN_DB_UPDATED);
140
+ if($optData !== false){
141
+ if($optData == 1){ return true; }
142
  }
143
 
144
+ if(! @self::_upgradeEventDetailsTable()){
145
+ return 2;
 
 
146
  }
147
+ if(! @self::_upgradeEventLogsTable()){
148
+ return 5;
 
149
  }
150
+ self::$_tablesUpgraded = true;
151
+ return true;
152
+ }
153
+
154
+ public static function updateTables()
155
+ {
156
+ $optData = get_option(WPPH_PLUGIN_DB_UPDATED);
157
+ if($optData !== false){
158
+ if($optData == 1){ return true; }
159
  }
160
 
161
+ if(! @self::_updateEventsDetailsTable()){
162
+ return 1;
163
+ }
164
+ if(! @self::_updateEventLogsTable()){
165
+ return 4;
166
+ }
167
+ self::$_tablesUpdated = true;
168
  return true;
169
  }
170
 
171
+ public static function canRun() {
172
+ if(self::$_tablesCreated && self::$_tablesUpgraded && self::$_tablesUpdated){
173
+ self::$_canRun = true;
174
+ }
175
+ return self::$_canRun;
176
+ }
177
+
178
 
179
  /**
180
  * Returns the full table name db_prefix + base_table_name for the requested table
195
  return '';
196
  }
197
 
 
 
198
  public static function getCreateQueryEventsDetailsTable()
199
  {
200
  global $wpdb;
201
+ $tableName = self::getFullTableName('events');
202
  return "CREATE TABLE IF NOT EXISTS `$tableName` (
203
  `EventID` int(8) NOT NULL,
204
  `EventType` varchar(10) DEFAULT 'NOTICE',
210
 
211
  public static function getUpdateQueryEventsDetailsTable()
212
  {
 
 
 
213
  $out = array();
214
  $entries = WPPHEvent::listEvents();
215
  if(empty($entries)){ return $out; }
216
 
217
  foreach($entries as $entry)
218
  {
219
+ $q = sprintf("INSERT INTO ".self::getFullTableName('events')." (`EventID`,`EventType`,`EventDescription`) VALUES(%d,'%s','%s')", $entry['id'], $entry['category'], $entry['text']);
220
  $out["{$entry['id']}"] = $q;
221
  }
222
  return $out;
225
  //@todo: UPDATE AS NECESSARY
226
  public static function getUpgradeQueryEventsDetailsTable()
227
  {
228
+ return array();
229
  }
230
 
231
 
244
  UNIQUE KEY `EventNumber` (`EventNumber`)
245
  );";
246
  }
247
+ // todo: add more events to db here
248
  public static function getUpdateQueryLogsTable()
249
  {
250
  return '';
251
  }
252
  public static function getUpgradeQueryLogsTable()
253
  {
254
+ return array(
255
+ "ALTER TABLE ".self::getFullTableName('main')." ADD COLUMN `EventCount` INT NOT NULL DEFAULT 1 AFTER `EventData`;",
256
+ "ALTER TABLE ".self::getFullTableName('main')." ADD COLUMN `UserName` VARCHAR(125) NOT NULL DEFAULT '' AFTER `EventCount`;",
257
+ );
258
  }
259
 
260
 
263
  if(self::_eventDetailsTableExists()) { return true; }
264
  global $wpdb;
265
  $query = self::getCreateQueryEventsDetailsTable();
266
+ if (false === @$wpdb->query($query)){ return false; }
267
  return true;
268
  }
269
 
273
  private static function _updateEventsDetailsTable()
274
  {
275
  global $wpdb;
276
+
277
  $queries = self::getUpdateQueryEventsDetailsTable();
278
+ if(empty($queries)){
279
+ return true;
280
+ }
281
+
282
  foreach($queries as $id => $query){
283
  if(! empty($query)){
284
+ $var = @$wpdb->get_var("SELECT EventID FROM ".self::getFullTableName('events')." WHERE EventID = $id");
285
  if(empty($var)){
286
+ if(false === @$wpdb->query($query)){
287
+ wpphLog('QUERY FAILED TO RUN: ',$query);
288
  return false;
289
  }
290
  }
297
  private static function _upgradeEventDetailsTable()
298
  {
299
  //EXECUTE THE QUERY FROM self::getUpgradeQueryEventsDetailsTable();
300
+ $optData = get_option(WPPH_PLUGIN_DB_UPDATED);
301
+ if($optData !== false){
302
+ if($optData == 1){ return true; }
303
+ }
304
+ $queries = self::getUpgradeQueryEventsDetailsTable();
305
+ if(empty($queries)){ return true; }
306
+
307
+ global $wpdb;
308
+ foreach($queries as $query){
309
+ if(false === @$wpdb->query($query)){return false;}
310
+ }
311
  return true;
312
  }
313
 
317
  if(self::_eventLogsTableExists()){ return true;}
318
  global $wpdb;
319
  $query = self::getCreateQueryLogsTable();
320
+ if(false === @$wpdb->query($query)){return false;}
321
  return true;
322
  }
323
 
330
  private static function _upgradeEventLogsTable()
331
  {
332
  //EXECUTE THE QUERY FROM self::getUpgradeQueryLogsTable();
333
+ $optData = get_option(WPPH_PLUGIN_DB_UPDATED);
334
+ if($optData !== false){
335
+ if($optData == 1){ return true; }
336
+ }
337
+ $queries = self::getUpgradeQueryLogsTable();
338
+ if(empty($queries)){ return true;}
339
+ global $wpdb;
340
+
341
+ foreach($queries as $query){
342
+ if(false === @$wpdb->query($query)){return false;}
343
+ }
344
  return true;
345
  }
346
 
347
  private static function _eventLogsTableExists()
348
  {
349
  global $wpdb;
350
+ $result = @$wpdb->get_var('SELECT EventNumber FROM '.self::getFullTableName('main'));
 
351
  return (is_null($result) ? false : true);
352
 
353
  }
354
  private static function _eventDetailsTableExists()
355
  {
356
  global $wpdb;
357
+ $result = @$wpdb->get_var('SELECT EventID FROM '.self::getFullTableName('events'));
 
358
  return (is_null($result) ? false : true);
359
  }
360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  }
362
 
363
  /**
382
  {
383
  global $wpdb;
384
 
385
+ $t = $wpdb->users;
386
 
387
  $username = $wpdb->get_var("SELECT user_login FROM $t WHERE ID=$userID");
388
  $user = new WP_User( $userID );
401
  public static function getEventsCount()
402
  {
403
  global $wpdb;
404
+ return $wpdb->get_var("SELECT COUNT(EventNumber) FROM ".self::getFullTableName('main'));
 
405
  }
406
 
407
  }
inc/WPPHEvent.php CHANGED
@@ -1,19 +1,9 @@
1
  <?php
2
  /**
3
- * Class that will handle the events management
4
- * @kyos
5
  */
6
  class WPPHEvent
7
  {
8
- public static function bindHooks(array $hooks = array())
9
- {
10
- if(empty($hooks)){ return; }
11
- foreach($hooks as $hook){
12
- if(is_callable(array(self,$hook),true)){
13
- call_user_func(array(self,$hook));
14
- }
15
- }
16
- }
17
  /**
18
  * Retrieve the list of events
19
  * @return array
@@ -24,7 +14,7 @@ class WPPHEvent
24
  // 1xxx - Login/Logout events
25
  array( 'id' => 1000, 'category' => 'NOTICE', 'text' => __('Successfully logged in.') ),
26
  array( 'id' => 1001, 'category' => 'NOTICE', 'text' => __('Successfully logged out.') ),
27
- array( 'id' => 1002, 'category' => 'WARNING', 'text' => __('Failed Login detected using <strong>%s</strong> as username.') ),
28
 
29
  // 2xxx - User activity events
30
  // Created a new blog post called %Post Title%. Blog post ID is %ID%
@@ -61,6 +51,24 @@ class WPPHEvent
61
  array( 'id' => 2014, 'category' => 'HIGH', 'text' => __('Post <strong>%s</strong> has been restored from trash.') ),
62
  // 2015 - untrashed page
63
  array( 'id' => 2015, 'category' => 'HIGH', 'text' => __('Page <strong>%s</strong> has been restored from trash.') ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  // 3xxx - Themes management
66
  // Activated the theme %themeName%
@@ -80,10 +88,16 @@ class WPPHEvent
80
  array( 'id' => 4007, 'category' => 'HIGH', 'text' => __('User <strong>%s</strong> with the role of <strong>%s</strong> was deleted by <strong>%s</strong>.') ),
81
 
82
  // 5xxx - Plugin management
 
 
83
  // Activated the plugin %plugin_name% installed in %plugin_directory%
84
- array( 'id' => 5000, 'category' => 'HIGH', 'text' => __('Activated the plugin <strong>%s</strong> installed in /<strong>%s</strong>.') ),
85
  // Deactivated the plugin %plugin_name% installed in %plugin_directory%
86
- array( 'id' => 5001, 'category' => 'HIGH', 'text' => __('Deactivated the plugin <strong>%s</strong> installed in /<strong>%s</strong>.') ),
 
 
 
 
87
 
88
  // 6xxx - System events
89
  //
@@ -104,8 +118,8 @@ class WPPHEvent
104
 
105
  // 2xxx - User activity events
106
 
107
- // 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
108
- public static function hookWatchBlogActivity() { add_action('transition_post_status', array('WPPHEventWatcher', 'WatchBlogActivity'), 10, 3); }
109
  // 2008, 2009
110
  public static function hookFileDeletion() { add_action('delete_post', array('WPPHEventWatcher', 'watchTrash'), 10, 1); }
111
  // 2010
@@ -130,6 +144,71 @@ class WPPHEvent
130
  public static function hookUntrashedPosts() { add_action('untrash_post', array('WPPHEventWatcher', 'watchTrashUndo')); }
131
  // 2015
132
  public static function hookUntrashedPages() { add_action('untrash_page', array('WPPHEventWatcher', 'watchTrashUndo')); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  // 3xxx - Themes management
135
 
@@ -143,18 +222,18 @@ class WPPHEvent
143
  public static function hookUserRegisterEvent() { add_action('user_register', array('WPPHEventWatcher', 'watchEventUserRegister')); }
144
  // 4002
145
  public static function hookUserRoleUpdated() {
146
- add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserRoleUpdated'));
147
- add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserRoleUpdated'));
148
  }
149
  // 4003, 4004
150
  public static function hookUserPasswordUpdated() {
151
- add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserPasswordUpdated'));
152
- add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserPasswordUpdated'));
153
  }
154
  // 4005, 4006
155
  public static function hookUserEmailUpdated() {
156
- add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserEmailUpdated'));
157
- add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserEmailUpdated'));
158
  }
159
  // 4007
160
  public static function hookUserDeletion() { add_action( 'delete_user', array('WPPHEventWatcher', 'watchUserDeletion') ); }
@@ -162,17 +241,14 @@ class WPPHEvent
162
 
163
  // 5xxx - Plugin management
164
 
165
- // 5000, 5001
166
  public static function hookWatchPluginActivity() {
167
- @require_once(ABSPATH.'wp-admin/includes/plugin.php');
168
- $current = get_plugins();
169
- foreach($current as $plugin_file => $plugin_data) {
170
- if ($plugin_file == WPPH_PLUGIN_BASE_NAME) {
171
- continue;
172
- }
173
- add_action('activate_' . $plugin_file, array('WPPHEventWatcher', 'watchPluginActivate'));
174
- add_action('deactivate_' . $plugin_file, array('WPPHEventWatcher', 'watchPluginDeactivate'));
175
- }
176
  }
177
 
178
 
@@ -189,22 +265,33 @@ class WPPHEvent
189
  * @param int $eventID
190
  * @param int $userID . A value of 0 means user "System". This is the ID of the user triggering the alert.
191
  * @param string $userIP
192
- * @param string $eventData Optional. If provided should be as a serialized array.
 
193
  * @return bool
194
  */
195
- public static function _addLogEvent($eventID = 1000, $userID = 0, $userIP = '', $eventData = '')
196
  {
197
  if(empty($userIP)){ $userIP = WPPHUtil::getIP(); }
 
 
 
198
 
199
  global $wpdb;
200
- $query = sprintf("INSERT INTO %s (EventID, UserID, UserIP, EventData) VALUES(%d, %d, '%s', '%s')"
201
- ,WPPHDatabase::getFullTableName('MAIN'), $eventID, $userID, $userIP, $eventData);
202
- if(false === $wpdb->query($wpdb->prepare($query)))
203
- {
204
- // mysql error
205
- return false;
 
 
 
 
 
 
 
206
  }
207
- return true;
208
  }
209
 
210
 
@@ -217,7 +304,7 @@ class WPPHEvent
217
  {
218
  global $wpdb;
219
  $table = WPPHDatabase::getFullTableName('events');
220
- return $wpdb->get_row($wpdb->prepare("SELECT EventType, EventDescription FROM $table WHERE EventID = $eventID"));
221
  }
222
 
223
  /**
@@ -254,19 +341,18 @@ class WPPHEvent
254
 
255
  $t1 = WPPHDatabase::getFullTableName('main');
256
  $t2 = WPPHDatabase::getFullTableName('events');
257
- $querySelect = "SELECT le.EventNumber, le.EventID, le.EventDate, le.UserID, le.UserIP, le.EventData,
258
- led.EventType, led.EventDescription
259
- FROM `$t1` as le
260
- INNER JOIN `$t2` as led
261
- ON le.EventID = led.EventID
262
- ORDER BY $orderBy
263
- $sort
264
- LIMIT $limit;";
265
  global $wpdb;
266
- return $wpdb->get_results($wpdb->prepare($querySelect), ARRAY_A);
 
 
 
 
 
 
 
 
267
  }
268
 
269
-
270
  }
271
 
272
  /**
@@ -317,22 +403,23 @@ class WPPHEventWatcher extends WPPHEvent
317
  $nur = ucfirst($uInfo['userRole']);
318
 
319
  // %s created new user %s with role %s
320
- $eventData = serialize(array($un, $nu, $nur));
321
 
322
  if($un == 'System')
323
  {
324
  // A new user with the username %username% has registered with the role of %user_role%
325
- $eventData = serialize(array($nu, $nur));
326
  self::_addLogEvent(4000, 0, WPPHUtil::getIP(), $eventData);
327
  }
328
  else {
329
  // %s created new user %s with role %s
330
- $eventData = serialize(array($un, $nu, $nur));
331
  self::_addLogEvent(4001, $current_user->ID, WPPHUtil::getIP(), $eventData);
332
  }
333
  }
334
 
335
  /**
 
336
  * @internal
337
  * Hooks to the events deletion event
338
  */
@@ -340,12 +427,35 @@ class WPPHEventWatcher extends WPPHEvent
340
  {
341
  wpphLog(__METHOD__.'() triggered by hook.');
342
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  // check settings and delete the events (if any)
344
  $settings = WPPH::getPluginSettings();
345
- if($settings->cleanupRan == 1){
346
- wpphLog(__METHOD__.'() Ignored. Cleanup already ran today.');
347
- return;
 
 
 
 
 
348
  }
 
349
  // check to see how we should do the cleanup (by days or by number)
350
  $cleanupType = 1; // by number by default
351
 
@@ -359,6 +469,8 @@ class WPPHEventWatcher extends WPPHEvent
359
  if(self::_deleteEventsOlderThan($settings->daysToKeep)){
360
  $settings->cleanupRan = 1;
361
  $settings->lastCleanup = time();
 
 
362
  }
363
  }
364
  // by number
@@ -367,20 +479,18 @@ class WPPHEventWatcher extends WPPHEvent
367
  if(self::_deleteEventsGreaterThan($settings->eventsToKeep)){
368
  $settings->cleanupRan = 1;
369
  $settings->lastCleanup = time();
 
 
370
  }
371
  }
372
  WPPH::updatePluginSettings($settings);
373
- if($settings->cleanupRan == 1){
374
- //#! add event success
375
- wpphLog(__METHOD__.'() Cleanup complete.');
376
- self::_addLogEvent(6000, 0);
377
- }
378
  }
 
379
  //@internal
380
  // delete by days
381
  private static function _deleteEventsOlderThan($days = 1)
382
  {
383
- $query = "DELETE FROM ".WPPHDatabase::getFullTableName('main')." WHERE EventDate > (NOW() - INTERVAL ".$days." DAY)";
384
  global $wpdb;
385
  $result = $wpdb->query($query);
386
  if($result === false){ $status = 'Error executing query'; }
@@ -405,35 +515,29 @@ class WPPHEventWatcher extends WPPHEvent
405
  {
406
  $limit = $count - $keep;
407
  $query = "DELETE FROM $tableName ORDER BY EventDate LIMIT $limit";
 
 
 
 
 
408
  }
409
  else {
410
  wpphLog(__METHOD__.'('.$number.') called. Ignored, there are not enough events to trigger this action.');
411
  return;
412
  }
413
-
414
- $result = $wpdb->query($query);
415
- if($result === false){ $status = 'Error executing query'; }
416
- else { $status = 'Query executed'; }
417
- wpphLog(__METHOD__.'('.$number.') called.', array('query'=>$query, 'status'=>$status, 'rowsAffected'=> (int)$result));
418
- return ($result !== false);
419
  }
420
 
421
  /**
422
  * @internal
423
  * Fired on login failure
424
  */
425
- public static function watchLoginFailure($username)
426
  {
427
  wpphLog(__METHOD__.'() triggered by hook.', array('username'=>$username));
428
- self::_addLogEvent(1002,0,WPPHUtil::getIP(),serialize(array($username)));
429
  }
430
 
431
- /**
432
- * @internal
433
- * @param $userID the id of the user being updated
434
- * Triggered when a user's role is updated
435
- */
436
- public static function watchUserRoleUpdated($userID)
437
  {
438
  wpphLog(__METHOD__.'() triggered by hook.');
439
 
@@ -447,96 +551,112 @@ class WPPHEventWatcher extends WPPHEvent
447
  $editedUserName = $editedUserInfo['userName'];
448
  $initialUserRole = $editedUserInfo['userRole'];
449
 
450
- if(empty($_POST['role'])){
451
- wpphLog(__METHOD__.'() Ignored. Role did not change.');
452
- return;
 
 
 
 
 
 
 
 
 
 
 
 
453
  }
454
 
455
- $updatedRole = trim($_POST['role']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
  if(strcasecmp($initialUserRole, $updatedRole)==0){
457
  wpphLog(__METHOD__.'() Ignored. Role did not change.');
458
- return;
459
  }
460
 
461
  // The role of user <strong>%s</strong> was changed from <strong>%s</strong> to <strong>%s</strong> by <strong>%s</strong>
462
- $eData = serialize(array($editedUserName, ucfirst($initialUserRole), ucfirst($updatedRole), $cName));
463
 
464
- self::_addLogEvent(4002, $cid, WPPHUtil::getIP(), $eData);
 
465
  }
466
 
467
  /**
468
  * @internal
469
- * @param $userID the id of the user being updated
470
  * Triggered when a user's role is updated
 
 
 
 
 
 
471
  */
472
- public static function watchUserPasswordUpdated($userID)
473
  {
474
- if(empty($_POST['pass1'])){
475
- wpphLog(__METHOD__.'() triggered by hook. Ignored. Password did not change.');
476
- return;
477
- }
478
  wpphLog(__METHOD__.'() triggered by hook.');
479
 
480
- // get info for the currently logged in user
481
- $current_user = wp_get_current_user();
482
- $cid = $current_user->ID;
483
- $cName = $current_user->user_login;
484
-
485
  // check to see who's who here
486
- if($userID == $cid)
487
  {
488
- self::_addLogEvent(4003, $cid);
489
- return;
490
  }
491
 
492
- // get info for the currently updated user
493
- $editedUserInfo = WPPHDB::getUserInfo($userID);
494
- $editedUserName = $editedUserInfo['userName'];
495
- $editedUserRole = $editedUserInfo['userRole'];
496
-
497
- // <strong>%s</strong> changed the password for <strong>%s</strong> with the role of <strong>%s</strong>
498
- $eData = serialize(array($cName, $editedUserName, ucfirst($editedUserRole)));
499
-
500
- self::_addLogEvent(4004, $cid, WPPHUtil::getIP(), $eData);
501
  }
502
 
503
  /**
504
  * @internal
505
- * @param $userID the id of the user being updated
506
  * Triggered when a user's email is updated
 
 
 
 
 
 
507
  */
508
- public static function watchUserEmailUpdated($userID)
509
  {
510
- if(empty($_POST['email'])){
511
- wpphLog(__METHOD__.'() triggered by hook. Ignored. Email did not change.');
512
- return;
513
- }
514
  wpphLog(__METHOD__.'() triggered by hook.');
515
 
516
- global $wpdb;
517
-
518
- // get info for the currently logged in user
519
- $current_user = wp_get_current_user();
520
- $cid = $current_user->ID;
521
- $cName = $current_user->user_login;
522
-
523
- // get current user's email
524
- $oldEmail = $wpdb->get_var("SELECT user_email FROM ".$wpdb->users." WHERE ID = $userID");
525
- // new email
526
- $newEmail = mysql_real_escape_string($_POST['email']);
527
 
528
  // check to see who's who here
529
- if($userID == $cid)
530
  {
531
-
532
- self::_addLogEvent(4005, $cid, WPPHUtil::getIP(), serialize(array($oldEmail, $newEmail)));
533
- return;
534
- }
535
-
536
- // check if email updated
537
- if($_POST['email'] == $oldEmail){
538
- wpphLog(__METHOD__.'() Ignored. Email did not change.');
539
- return;
540
  }
541
 
542
  // get info for the currently updated user
@@ -544,9 +664,10 @@ class WPPHEventWatcher extends WPPHEvent
544
  $editedUserName = $editedUserInfo['userName'];
545
 
546
  // %user_making_change% changed the email address of user account %user% from %old_email% to %new_email%
547
- $eData = serialize(array($cName, $editedUserName, $oldEmail, $newEmail));
548
 
549
- self::_addLogEvent(4006, $cid, WPPHUtil::getIP(), $eData);
 
550
  }
551
 
552
  /**
@@ -572,57 +693,221 @@ class WPPHEventWatcher extends WPPHEvent
572
  $_userName = $_userInfo['userName'];
573
  $_userRole = ucfirst($_userInfo['userRole']);
574
 
575
- self::_addLogEvent(4007, $currentUserID, WPPHUtil::getIP(), serialize(array($_userName, $_userRole, $un)));
576
- // delete transient as well
577
- delete_transient(sha1($userID));
578
  }
579
 
 
580
  public static function watchPluginActivate()
581
  {
582
  wpphLog(__METHOD__.'() triggered by hook.');
583
 
584
- // activate
585
- $a = (empty($_GET['plugin']) ? '' : $_GET['plugin']);
586
-
587
- // if active plugin edited (Using the plugin editor)
588
- if(empty($a)){
589
- $a = (empty($_GET['file']) ? '' : $_GET['file']);
590
- }
591
-
592
- $b = '';
593
- if(!empty($a)){ $b = dirname($a); }
594
-
595
  // get info for the currently logged in user
596
  $current_user = wp_get_current_user();
597
 
598
- self::_addLogEvent(5000,$current_user->ID, WPPHUtil::getIP(), serialize(array($b,$a)));
599
- wpphLog('Plugin activated.', array('plugin file'=>$a));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  }
 
601
  public static function watchPluginDeactivate()
602
  {
603
  wpphLog(__METHOD__.'() triggered by hook.');
604
 
605
- // deactivate
606
- $a = (empty($_GET['plugin']) ? '' : $_GET['plugin']);
607
- $b = '';
608
- if(!empty($a)){ $b = dirname($a); }
609
-
610
  // get info for the currently logged in user
611
  $current_user = wp_get_current_user();
612
 
613
- self::_addLogEvent(5001,$current_user->ID, WPPHUtil::getIP(), serialize(array($b,$a)));
614
- wpphLog('Plugin deactivated.', array('plugin file'=>$a));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  }
617
 
618
 
619
- public static function WatchBlogActivity($newStatus, $oldStatus, $post)
620
  {
621
- $a = func_get_args();
622
- wpphLog(__METHOD__.'() triggered by hook.', $a);
 
 
 
 
 
 
 
 
 
 
 
 
623
 
624
  $postID = $post->ID;
625
- $hPid = md5($postID);
 
 
626
  $currentUserID = wp_get_current_user()->ID;
627
  $userID = $postAuthorID = $post->post_author;
628
  if($currentUserID != $postAuthorID){
@@ -630,132 +915,226 @@ class WPPHEventWatcher extends WPPHEvent
630
  $userID = $currentUserID;
631
  }
632
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
633
  // We're dealing with posts
634
  if($post->post_type == 'post')
635
  {
636
- // if transient exists then this is an update, otherwise this is a new post
637
- $value = get_transient($hPid);
638
-
639
- if($newStatus == 'inherit' && $oldStatus == 'new')
 
640
  {
641
- if(empty($value))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
642
  {
643
- // Created a new blog post called %Post Title%. Blog post ID is %ID%
644
- self::_addLogEvent(2000, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$postID)));
645
- wpphLog('New blog post saved as draft.', array('title'=>$post->post_title));
646
- set_transient($hPid, $postID, 0);
647
- return;
648
  }
649
  }
650
 
651
- // #2000 , #2003
652
- if((($oldStatus == $newStatus) == 'draft') && $post->post_status == 'draft')
653
- {
654
- // so we skip generating multiple events
655
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; }
 
 
 
 
656
 
657
- // #2000 : new blog post [as draft]
658
- if(empty($value))
 
 
 
 
659
  {
660
- // Created a new blog post called %Post Title%. Blog post ID is %ID%
661
- self::_addLogEvent(2000, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$postID)));
662
- wpphLog('New blog post saved as draft.', array('title'=>$post->post_title));
663
- set_transient($hPid, $postID, 0);
664
- return;
665
-
666
  }
667
- // #2003 : Updated draft post
668
- else
669
  {
670
- // invalid
671
- if($value != $postID) { return; }
672
-
 
673
  // Modified the draft blog post %post_title%. Blog post ID is %ID%
674
- self::_addLogEvent(2003, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$postID)));
675
- wpphLog('Draft blog post updated.', array('title'=>$post->post_title));
676
- return;
677
-
678
  }
679
  }
680
- // #2001 : Published a blog post
681
- elseif(($oldStatus == 'draft' && $newStatus == 'publish') && $post->post_status == 'publish')
682
- {
683
  // Published a blog post called %Post_Title%. Blog post URL is %Post_URL%
684
- self::_addLogEvent(2001, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$post->guid)));
685
- wpphLog('Blog post published.', array('title'=>$post->post_title));
686
- return;
 
 
 
 
 
 
 
 
687
  }
688
- // #2002 : Updated published post
689
- elseif(($oldStatus == 'publish' && $newStatus == 'publish') && $post->post_status == 'publish')
690
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
691
  // Modified the published blog post %post_title%. Blog post URL is %post_URL%
692
- self::_addLogEvent(2002, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$post->guid)));
693
- wpphLog('Published blog post updated.', array('title'=>$post->post_title));
694
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
695
  }
696
  }
697
-
698
  // We're dealing with pages
699
  elseif($post->post_type == 'page')
700
  {
701
- // if transient exists then this is an update, otherwise this is a new page
702
- $value = get_transient($hPid);
703
-
704
- if($newStatus == 'inherit' && $oldStatus == 'new')
705
- {
706
- if(empty($value))
707
- {
708
- // Created a new page called %page_title%. Page ID is %ID%
709
- self::_addLogEvent(2004, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$postID)));
710
- set_transient($hPid, $postID, 0);
711
- wpphLog('New page saved as draft.', array('title'=>$post->post_title));
712
- return;
713
  }
714
  }
715
 
716
- // #2004 , #2007
717
- if((($oldStatus == $newStatus) == 'draft') && $post->post_status == 'draft')
 
718
  {
719
- // so we skip generating multiple events
720
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; }
721
-
722
- // #2004 : new page [as draft]
723
- if(empty($value))
724
- {
725
- // Created a new page called %page_title%. Page ID is %ID%
726
- self::_addLogEvent(2004, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$postID)));
727
- set_transient($hPid, $postID, 0);
728
- wpphLog('New page saved as draft.', array('title'=>$post->post_title));
729
- return;
730
-
731
  }
732
- // #2007 : Updated draft page
733
- else
734
- {
735
- // invalid
736
- if($value != $postID) { return; }
737
- // Modified the draft page %page_title%. Page ID is %ID%
738
- self::_addLogEvent(2007, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$postID)));
739
- wpphLog('Draft page updated.', array('title'=>$post->post_title));
740
- return;
741
-
742
  }
743
  }
744
- // #2005 : Published a page
745
- elseif(($oldStatus == 'draft' && $newStatus == 'publish') && $post->post_status == 'publish')
746
- {
 
 
 
747
  // Published a page called %page_title%. Page URL is %URL%
748
- self::_addLogEvent(2005, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$post->guid)));
749
- wpphLog('Page published.', array('title'=>$post->post_title));
750
- return;
751
  }
752
- // #2006 : Updated published page
753
- elseif(($oldStatus == 'publish' && $newStatus == 'publish') && $post->post_status == 'publish')
 
 
 
 
 
754
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
  // Modified the published page %page_title%. Page URL is %URL%
756
- self::_addLogEvent(2006, $userID, WPPHUtil::getIP(), serialize(array($post->post_title,$post->guid)));
757
- wpphLog('Published page updated.', array('title'=>$post->post_title));
758
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
759
  }
760
  }
761
  }
@@ -763,30 +1142,23 @@ class WPPHEventWatcher extends WPPHEvent
763
  public static function watchTrash($postID)
764
  {
765
  wpphLog(__METHOD__.'() triggered by hook.');
766
-
767
  $hPid = md5($postID);
768
-
769
  // get info for the currently logged in user
770
  $current_user = wp_get_current_user();
771
-
772
  global $wpdb;
773
-
774
  $postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
775
  $postTitle = $postInfo->post_title;
776
  $postType = $postInfo->post_type;
777
-
778
  if($postType == 'post')
779
  {
780
  // Deleted the blog post %Title%. Blog post ID is %ID%
781
- self::_addLogEvent(2008, $current_user->ID, WPPHUtil::getIP(), serialize(array($postTitle,$postID)));
782
- delete_transient($hPid);
783
  wpphLog('Blog post deleted.', array('title'=>$postTitle, 'id'=>$postID));
784
  }
785
  elseif($postType == 'page')
786
  {
787
  // Deleted the page %Title%. Page ID is %ID%
788
- self::_addLogEvent(2009, $current_user->ID, WPPHUtil::getIP(), serialize(array($postTitle,$postID)));
789
- delete_transient($hPid);
790
  wpphLog('Page deleted.', array('title'=>$postTitle, 'id'=>$postID));
791
  }
792
  }
@@ -795,30 +1167,24 @@ class WPPHEventWatcher extends WPPHEvent
795
  public static function watchFileUploaded($attachmentID)
796
  {
797
  global $wpdb;
798
-
799
  // get info for the currently logged in user
800
  $current_user = wp_get_current_user();
801
-
802
  $rowData = $wpdb->get_row("SELECT guid FROM ".$wpdb->posts." WHERE ID = ".$attachmentID);
803
  $fileName = basename($rowData->guid);
804
  $dirName = dirname($rowData->guid);
805
-
806
  // Uploaded the file %file name$ in %file location%
807
- self::_addLogEvent(2010, $current_user->ID, WPPHUtil::getIP(), serialize(array($fileName, $dirName)));
808
  wpphLog('File uploaded.', array('title'=>$fileName, 'url'=>$dirName));
809
  }
810
  // 2011
811
  public static function watchFileUploadedDeleted($attachmentID)
812
  {
813
  global $wpdb;
814
-
815
  // get info for the currently logged in user
816
  $current_user = wp_get_current_user();
817
-
818
  $rowData = $wpdb->get_row("SELECT post_title, guid FROM ".$wpdb->posts." WHERE ID = ".$attachmentID);
819
-
820
  // Deleted file %file name$ from %file_location%
821
- self::_addLogEvent(2011, $current_user->ID, WPPHUtil::getIP(), serialize(array($rowData->post_title,dirname($rowData->guid))));
822
  wpphLog('File deleted.', array('title'=>$rowData->post_title, 'url'=>dirname($rowData->guid)));
823
  }
824
 
@@ -826,22 +1192,19 @@ class WPPHEventWatcher extends WPPHEvent
826
  public static function watchFileDeletion($postID)
827
  {
828
  global $wpdb;
829
-
830
  $postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
831
  $postTitle = $postInfo->post_title;
832
  $postType = $postInfo->post_type;
833
-
834
  // get info for the currently logged in user
835
  $userID = wp_get_current_user()->ID;
836
-
837
  if('post' == $postType)
838
  {
839
- self::_addLogEvent(2012, $userID, WPPHUtil::getIP(), serialize(array($postTitle)));
840
  wpphLog('Post trashed.', array('name'=>$postTitle));
841
  }
842
  elseif ('page' == $postType)
843
  {
844
- self::_addLogEvent(2013, $userID, WPPHUtil::getIP(), serialize(array($postTitle)));
845
  wpphLog('Page trashed.', array('name'=>$postTitle));
846
  }
847
  }
@@ -850,35 +1213,102 @@ class WPPHEventWatcher extends WPPHEvent
850
  public static function watchTrashUndo($postID)
851
  {
852
  global $wpdb;
853
-
854
  $postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
855
  $postTitle = $postInfo->post_title;
856
  $postType = $postInfo->post_type;
857
-
858
  // get info for the currently logged in user
859
  $userID = wp_get_current_user()->ID;
860
-
861
  if('post' == $postType)
862
  {
863
- self::_addLogEvent(2014, $userID, WPPHUtil::getIP(), serialize(array($postTitle)));
864
  wpphLog('Post restored from trash.', array('name'=>$postTitle));
865
  }
866
  elseif ('page' == $postType)
867
  {
868
- self::_addLogEvent(2015, $userID, WPPHUtil::getIP(), serialize(array($postTitle)));
869
  wpphLog('Page restored from trash.', array('name'=>$postTitle));
870
  }
871
  }
872
 
873
-
874
  // 3000 - Theme activated
875
  public static function watchThemeChange($themeName)
876
  {
877
  // get info for the currently logged in user
878
  $current_user = wp_get_current_user();
879
-
880
  // // Activated the theme %themeName%
881
- self::_addLogEvent(3000, $current_user->ID, WPPHUtil::getIP(), serialize(array($themeName)));
882
  wpphLog('Theme activated.', array('name'=>$themeName));
883
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
884
  }
1
  <?php
2
  /**
3
+ * WPPHEvent
 
4
  */
5
  class WPPHEvent
6
  {
 
 
 
 
 
 
 
 
 
7
  /**
8
  * Retrieve the list of events
9
  * @return array
14
  // 1xxx - Login/Logout events
15
  array( 'id' => 1000, 'category' => 'NOTICE', 'text' => __('Successfully logged in.') ),
16
  array( 'id' => 1001, 'category' => 'NOTICE', 'text' => __('Successfully logged out.') ),
17
+ array( 'id' => 1002, 'category' => 'WARNING', 'text' => __('Failed login detected using <strong>%s</strong> as username.') ),
18
 
19
  // 2xxx - User activity events
20
  // Created a new blog post called %Post Title%. Blog post ID is %ID%
51
  array( 'id' => 2014, 'category' => 'HIGH', 'text' => __('Post <strong>%s</strong> has been restored from trash.') ),
52
  // 2015 - untrashed page
53
  array( 'id' => 2015, 'category' => 'HIGH', 'text' => __('Page <strong>%s</strong> has been restored from trash.') ),
54
+ // 2016 - Post category changed
55
+ array( 'id' => 2016, 'category' => 'NOTICE', 'text' => __('Changed the category(ies) of the post <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.') ),
56
+ // 2017 - Changed the URL of the post %post_name% from %old_url% to %new_url%
57
+ array( 'id' => 2017, 'category' => 'NOTICE', 'text' => __('Changed the URL of the post <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.') ),
58
+ // 2018 - Changed the URL of the page %page_name% from %old_url% to %new_url%
59
+ array( 'id' => 2018, 'category' => 'NOTICE', 'text' => __('Changed the URL of the page <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.') ),
60
+ // 2019 - Changed the author of %post_name% post from %old_author% to %new_author%
61
+ array( 'id' => 2019, 'category' => 'NOTICE', 'text' => __('Changed the author of <strong>%s</strong> from <strong>%s</strong> to <strong>%s</strong>.') ),
62
+ // 2020 - Changed the author of %page_name% page from %old_author% to %new_author%
63
+ array( 'id' => 2020, 'category' => 'NOTICE', 'text' => __('Changed the author of <strong>%s</strong> page from <strong>%s</strong> to <strong>%s</strong>.') ),
64
+ // 2021 - %postName% from %oldStatus% to %newStatus%
65
+ array( 'id' => 2021, 'category' => 'NOTICE', 'text' => __('Changed the status of <strong>%s</strong> post from <strong>%s</strong> to <strong>%s</strong>.') ),
66
+ // 2022 - page from published to draft
67
+ array( 'id' => 2022, 'category' => 'NOTICE', 'text' => __('Changed the status of <strong>%s</strong> page from <strong>%s</strong> to <strong>%s</strong>.') ),
68
+ // 2023 - added new category
69
+ array( 'id' => 2023, 'category' => 'NOTICE', 'text' => __('Created a new category called <strong>%s</strong>.') ),
70
+ // 2024 - deleted category
71
+ array( 'id' => 2024, 'category' => 'WARNING', 'text' => __('Deleted the <strong>%s</strong> category.') ),
72
 
73
  // 3xxx - Themes management
74
  // Activated the theme %themeName%
88
  array( 'id' => 4007, 'category' => 'HIGH', 'text' => __('User <strong>%s</strong> with the role of <strong>%s</strong> was deleted by <strong>%s</strong>.') ),
89
 
90
  // 5xxx - Plugin management
91
+ // # 5000 Installed the plugin %name%.
92
+ array( 'id' => 5000, 'category' => 'HIGH', 'text' => __('Installed the plugin <strong>%s</strong>.') ),
93
  // Activated the plugin %plugin_name% installed in %plugin_directory%
94
+ array( 'id' => 5001, 'category' => 'HIGH', 'text' => __('Activated the plugin <strong>%s</strong> installed in /<strong>%s</strong>.') ),
95
  // Deactivated the plugin %plugin_name% installed in %plugin_directory%
96
+ array( 'id' => 5002, 'category' => 'HIGH', 'text' => __('Deactivated the plugin <strong>%s</strong> installed in /<strong>%s</strong>.') ),
97
+ // # 5003 Uninstalled the plugin %plugin_name% which was installed in %path%
98
+ array( 'id' => 5003, 'category' => 'HIGH', 'text' => __('Uninstalled the plugin <strong>%s</strong> which was installed in /<strong>%s</strong>.') ),
99
+ // # 5004 Upgraded the plugin %name% installed in %path%
100
+ array( 'id' => 5004, 'category' => 'WARNING', 'text' => __('Upgraded the plugin <strong>%s</strong> installed in /<strong>%s</strong>.') ),
101
 
102
  // 6xxx - System events
103
  //
118
 
119
  // 2xxx - User activity events
120
 
121
+ // 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2021, 2022
122
+ public static function hookWatchBlogActivity() { add_action('transition_post_status', array('WPPHEventWatcher', 'watchBlogActivity'), 10, 3); }
123
  // 2008, 2009
124
  public static function hookFileDeletion() { add_action('delete_post', array('WPPHEventWatcher', 'watchTrash'), 10, 1); }
125
  // 2010
144
  public static function hookUntrashedPosts() { add_action('untrash_post', array('WPPHEventWatcher', 'watchTrashUndo')); }
145
  // 2015
146
  public static function hookUntrashedPages() { add_action('untrash_page', array('WPPHEventWatcher', 'watchTrashUndo')); }
147
+ // 2016, 2017
148
+ public static function hookWatchPostStateBefore()
149
+ {
150
+ if(isset($_POST['action']) && $_POST['action'] == 'autosave') { return; }
151
+
152
+ if(isset($GLOBALS['WPPH_DEFAULT_EDITOR_ENABLED']) || isset($GLOBALS['WPPH_SCREEN_EDITOR_ENABLED']))
153
+ {
154
+ wpphLog(__METHOD__.'() triggered by hook.');
155
+
156
+ $pid = $_POST['post_ID'];
157
+
158
+ /*
159
+ * CHECK IF POST/PAGE AUTHOR UPDATED; 2019
160
+ * ## step 1: this is where we check if author has been changed
161
+ * ## step 2: @see wpph_managePostAuthorUpdateQuickEditForm()
162
+ */
163
+ if(! empty($_POST['post_author']))
164
+ {
165
+ $GLOBALS['WPPH_POST_AUTHOR_UPDATED'] = intval($_POST['post_author']);
166
+ if(isset($GLOBALS['WPPH_SCREEN_EDITOR_ENABLED'])){
167
+ // trigger hook manually
168
+ add_filter( 'wp_insert_post_data', 'wpph_managePostAuthorUpdateQuickEditForm', '1', 2 );
169
+ }
170
+ }
171
+
172
+ // if blog post
173
+ if($_POST['post_type'] == 'post')
174
+ {
175
+ // before further checks, we have to make sure this post isn't new
176
+ global $wpdb;
177
+ $postExists = (bool)$wpdb->get_var("SELECT ID FROM ".$wpdb->posts." WHERE ID = ".$pid);
178
+ if(! $postExists){
179
+ return;
180
+ }
181
+
182
+ /*
183
+ * CHECK IF POST CATEGORY UPDATED; 2016
184
+ */
185
+ $GLOBALS['WPPH_POST_OLD_CATEGORIES'] = wp_get_post_categories($pid);
186
+
187
+ /*
188
+ * CHECK IF POST URL UPDATED; 2017
189
+ * ## step 1: this is where we retrieve the new URL
190
+ * ## step 2: @see WPPHEventWatcher::watchBlogActivity()
191
+ */
192
+ $GLOBALS['WPPH_POST_NEW_URL'] = get_permalink($pid);
193
+ }
194
+ // if page
195
+ elseif($_POST['post_type'] == 'page')
196
+ {
197
+ /*
198
+ * CHECK IF PAGE URL UPDATED; 2018
199
+ * ## step 1: this is where we retrieve the new URL
200
+ * ## step 2: @see WPPHEventWatcher::watchBlogActivity()
201
+ */
202
+ $GLOBALS['WPPH_POST_NEW_URL'] = get_permalink($pid);
203
+ }
204
+ }
205
+ }
206
+
207
+ // 2023
208
+ public static function hookWatchCategoryAdd() { WPPHEventWatcher::watchCategoryAdd($_POST); }
209
+ // 2024
210
+ public static function hookWatchCategoryDelete() { WPPHEventWatcher::watchCategoryDelete($_POST); }
211
+
212
 
213
  // 3xxx - Themes management
214
 
222
  public static function hookUserRegisterEvent() { add_action('user_register', array('WPPHEventWatcher', 'watchEventUserRegister')); }
223
  // 4002
224
  public static function hookUserRoleUpdated() {
225
+ add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
226
+ add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
227
  }
228
  // 4003, 4004
229
  public static function hookUserPasswordUpdated() {
230
+ add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
231
+ add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
232
  }
233
  // 4005, 4006
234
  public static function hookUserEmailUpdated() {
235
+ add_action('edit_user_profile_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
236
+ add_action('personal_options_update', array('WPPHEventWatcher', 'watchUserInfoUpdated'));
237
  }
238
  // 4007
239
  public static function hookUserDeletion() { add_action( 'delete_user', array('WPPHEventWatcher', 'watchUserDeletion') ); }
241
 
242
  // 5xxx - Plugin management
243
 
244
+ // 5000, 5001, 5002, 5003, 5004
245
  public static function hookWatchPluginActivity() {
246
+ @include_once(ABSPATH.'wp-admin/includes/plugin.php');
247
+ WPPHEventWatcher::watchPluginInstall(); // 5000
248
+ WPPHEventWatcher::watchPluginActivate(); // 5001
249
+ WPPHEventWatcher::watchPluginDeactivate(); // 5002
250
+ WPPHEventWatcher::watchPluginUninstall(); // 5003
251
+ WPPHEventWatcher::watchPluginUpgrade(); // 5004
 
 
 
252
  }
253
 
254
 
265
  * @param int $eventID
266
  * @param int $userID . A value of 0 means user "System". This is the ID of the user triggering the alert.
267
  * @param string $userIP
268
+ * @param array $eventData Optional. If provided should be as an array.
269
+ * @param string $failedLoginUserName The name of the user used for the failed login
270
  * @return bool
271
  */
272
+ public static function _addLogEvent($eventID = 1000, $userID = 0, $userIP = '', $eventData = array(), $failedLoginUserName='')
273
  {
274
  if(empty($userIP)){ $userIP = WPPHUtil::getIP(); }
275
+ $tableName = WPPHDB::getFullTableName('MAIN');
276
+ $eventData = base64_encode(serialize($eventData));
277
+ $query = sprintf("INSERT INTO $tableName (EventID, UserID, UserIP, EventData,UserName) VALUES(%d, %d, '%s', '%s', '%s')",$eventID, $userID, $userIP, $eventData, $failedLoginUserName);
278
 
279
  global $wpdb;
280
+ if($eventID == 1002){ // 1002 == failed login
281
+
282
+ // check if there is already an event there
283
+ $eventNumber = $wpdb->get_var("SELECT EventNumber FROM $tableName WHERE EventID = $eventID AND UserIP = '$userIP' AND UserName ='$failedLoginUserName'");
284
+ if(! empty($eventNumber))
285
+ {
286
+ // update
287
+ $query = "UPDATE $tableName
288
+ SET
289
+ EventDate = CURRENT_TIMESTAMP(),
290
+ EventCount = (EventCount + 1)
291
+ WHERE EventNumber = ".$eventNumber;
292
+ }
293
  }
294
+ return ((false === $wpdb->query($query)) ? false : true);
295
  }
296
 
297
 
304
  {
305
  global $wpdb;
306
  $table = WPPHDatabase::getFullTableName('events');
307
+ return $wpdb->get_row("SELECT EventType, EventDescription FROM $table WHERE EventID = $eventID");
308
  }
309
 
310
  /**
341
 
342
  $t1 = WPPHDatabase::getFullTableName('main');
343
  $t2 = WPPHDatabase::getFullTableName('events');
 
 
 
 
 
 
 
 
344
  global $wpdb;
345
+ $query = "SELECT le.EventNumber, le.EventID, le.EventDate, le.UserID, le.UserIP, le.EventData, le.EventCount, le.UserName,
346
+ led.EventType, led.EventDescription
347
+ FROM `$t1` as le
348
+ INNER JOIN `$t2` as led
349
+ ON le.EventID = led.EventID
350
+ ORDER BY $orderBy
351
+ $sort
352
+ LIMIT $limit;";
353
+ return $wpdb->get_results($query, ARRAY_A);
354
  }
355
 
 
356
  }
357
 
358
  /**
403
  $nur = ucfirst($uInfo['userRole']);
404
 
405
  // %s created new user %s with role %s
406
+ $eventData = array($un, $nu, $nur);
407
 
408
  if($un == 'System')
409
  {
410
  // A new user with the username %username% has registered with the role of %user_role%
411
+ $eventData = array($nu, $nur);
412
  self::_addLogEvent(4000, 0, WPPHUtil::getIP(), $eventData);
413
  }
414
  else {
415
  // %s created new user %s with role %s
416
+ $eventData = array($un, $nu, $nur);
417
  self::_addLogEvent(4001, $current_user->ID, WPPHUtil::getIP(), $eventData);
418
  }
419
  }
420
 
421
  /**
422
+ * #! 6000
423
  * @internal
424
  * Hooks to the events deletion event
425
  */
427
  {
428
  wpphLog(__METHOD__.'() triggered by hook.');
429
 
430
+ if((defined('DISABLE_WP_CRON') && 'DISABLE_WP_CRON'))
431
+ {
432
+ wpphLog('wp-cron is disabled.');
433
+ self::__deleteEvents();
434
+ }
435
+ else{
436
+ add_action(WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME, array('WPPHEventWatcher','__deleteEvents'));
437
+ if ( ! wp_next_scheduled(WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME) ) {
438
+ wp_schedule_event( time(), 'daily', WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME );
439
+ wpphLog(__METHOD__.'() scheduled by wp-cron.');
440
+ }
441
+ }
442
+ }
443
+
444
+ //@internal
445
+ public static function __deleteEvents()
446
+ {
447
  // check settings and delete the events (if any)
448
  $settings = WPPH::getPluginSettings();
449
+
450
+ //if wp-cron disabled
451
+ if((defined('DISABLE_WP_CRON') && 'DISABLE_WP_CRON'))
452
+ {
453
+ if($settings->cleanupRan == 1){
454
+ wpphLog(__METHOD__.'() Ignored. Cleanup already ran today.');
455
+ return;
456
+ }
457
  }
458
+
459
  // check to see how we should do the cleanup (by days or by number)
460
  $cleanupType = 1; // by number by default
461
 
469
  if(self::_deleteEventsOlderThan($settings->daysToKeep)){
470
  $settings->cleanupRan = 1;
471
  $settings->lastCleanup = time();
472
+ self::_addLogEvent(6000, 0);
473
+ wpphLog(__METHOD__.'() Cleanup complete.');
474
  }
475
  }
476
  // by number
479
  if(self::_deleteEventsGreaterThan($settings->eventsToKeep)){
480
  $settings->cleanupRan = 1;
481
  $settings->lastCleanup = time();
482
+ self::_addLogEvent(6000, 0);
483
+ wpphLog(__METHOD__.'() Cleanup complete.');
484
  }
485
  }
486
  WPPH::updatePluginSettings($settings);
 
 
 
 
 
487
  }
488
+
489
  //@internal
490
  // delete by days
491
  private static function _deleteEventsOlderThan($days = 1)
492
  {
493
+ $query = "DELETE FROM ".WPPHDatabase::getFullTableName('main')." WHERE EventDate < (NOW() - INTERVAL ".$days." DAY)";
494
  global $wpdb;
495
  $result = $wpdb->query($query);
496
  if($result === false){ $status = 'Error executing query'; }
515
  {
516
  $limit = $count - $keep;
517
  $query = "DELETE FROM $tableName ORDER BY EventDate LIMIT $limit";
518
+ $result = $wpdb->query($query);
519
+ if($result === false){ $status = 'Error executing query'; }
520
+ else { $status = 'Query executed'; }
521
+ wpphLog(__METHOD__.'('.$number.') called.', array('query'=>$query, 'status'=>$status, 'rowsAffected'=> (int)$result));
522
+ return ($result !== false);
523
  }
524
  else {
525
  wpphLog(__METHOD__.'('.$number.') called. Ignored, there are not enough events to trigger this action.');
526
  return;
527
  }
 
 
 
 
 
 
528
  }
529
 
530
  /**
531
  * @internal
532
  * Fired on login failure
533
  */
534
+ public static function watchLoginFailure($username='')
535
  {
536
  wpphLog(__METHOD__.'() triggered by hook.', array('username'=>$username));
537
+ self::_addLogEvent(1002,0,WPPHUtil::getIP(),array($username), base64_encode($username));
538
  }
539
 
540
+ public static function watchUserInfoUpdated($userID)
 
 
 
 
 
541
  {
542
  wpphLog(__METHOD__.'() triggered by hook.');
543
 
551
  $editedUserName = $editedUserInfo['userName'];
552
  $initialUserRole = $editedUserInfo['userRole'];
553
 
554
+ // check and see *what* has been updated...
555
+
556
+ // If a user's role has been updated
557
+ if(!empty($_POST['role'])){
558
+ $updatedRole = trim($_POST['role']);
559
+ if(self::_userRoleUpdated($cid, $initialUserRole, $updatedRole, $editedUserName, $cName)){
560
+ return;
561
+ }
562
+ }
563
+
564
+ // If a user's password has been updated
565
+ if(!empty($_POST['pass1'])){
566
+ if(self::_userPasswordUpdated($userID, $cid, $cName, $editedUserName, $initialUserRole)){
567
+ return;
568
+ }
569
  }
570
 
571
+ // if a user's email was updated
572
+ if(! empty($_POST['email'])){
573
+ global $wpdb;
574
+ // get current user's email
575
+ $oldEmail = $wpdb->get_var("SELECT user_email FROM ".$wpdb->users." WHERE ID = $userID");
576
+ // new email
577
+ $newEmailSafe = mysql_real_escape_string($_POST['email']);
578
+ self::_userEmailUpdated($userID, $cid, $cName, $oldEmail, $newEmailSafe);
579
+ }
580
+ }
581
+
582
+ /**
583
+ * @internal
584
+ * Triggered when a user's role is updated
585
+ * @param $currentUserID
586
+ * @param $initialUserRole
587
+ * @param $updatedRole
588
+ * @param $editedUserName
589
+ * @param $currentUserName
590
+ * @return bool
591
+ */
592
+ private static function _userRoleUpdated($currentUserID, $initialUserRole, $updatedRole, $editedUserName, $currentUserName)
593
+ {
594
+ wpphLog(__METHOD__.'() triggered by hook.');
595
+
596
+ //$updatedRole = trim($_POST['role']);
597
  if(strcasecmp($initialUserRole, $updatedRole)==0){
598
  wpphLog(__METHOD__.'() Ignored. Role did not change.');
599
+ return false;
600
  }
601
 
602
  // The role of user <strong>%s</strong> was changed from <strong>%s</strong> to <strong>%s</strong> by <strong>%s</strong>
603
+ $eData = array($editedUserName, ucfirst($initialUserRole), ucfirst($updatedRole), $currentUserName);
604
 
605
+ self::_addLogEvent(4002, $currentUserID, WPPHUtil::getIP(), $eData);
606
+ return true;
607
  }
608
 
609
  /**
610
  * @internal
 
611
  * Triggered when a user's role is updated
612
+ * @param $userID
613
+ * @param $currentUserID
614
+ * @param $currentUserName
615
+ * @param $editedUserName
616
+ * @param $editedUserRole
617
+ * @return bool
618
  */
619
+ private static function _userPasswordUpdated($userID, $currentUserID, $currentUserName, $editedUserName, $editedUserRole)
620
  {
 
 
 
 
621
  wpphLog(__METHOD__.'() triggered by hook.');
622
 
 
 
 
 
 
623
  // check to see who's who here
624
+ if($userID == $currentUserID)
625
  {
626
+ self::_addLogEvent(4003, $currentUserID);
627
+ return true;
628
  }
629
 
630
+ $eData = array($currentUserName, $editedUserName, ucfirst($editedUserRole));
631
+ self::_addLogEvent(4004, $currentUserID, WPPHUtil::getIP(), $eData);
632
+ return true;
 
 
 
 
 
 
633
  }
634
 
635
  /**
636
  * @internal
 
637
  * Triggered when a user's email is updated
638
+ * @param $userID The user ID triggering this hook
639
+ * @param $currentUserID The ID of the current logged in user
640
+ * @param $currentUserName
641
+ * @param $oldEmail
642
+ * @param $newEmail
643
+ * @return bool
644
  */
645
+ private static function _userEmailUpdated($userID, $currentUserID, $currentUserName, $oldEmail, $newEmail)
646
  {
 
 
 
 
647
  wpphLog(__METHOD__.'() triggered by hook.');
648
 
649
+ // check if email updated
650
+ if($newEmail == $oldEmail){
651
+ wpphLog(__METHOD__.'() Ignored. Email did not change.');
652
+ return false;
653
+ }
 
 
 
 
 
 
654
 
655
  // check to see who's who here
656
+ if($userID == $currentUserID)
657
  {
658
+ self::_addLogEvent(4005, $currentUserID, WPPHUtil::getIP(), array($oldEmail, $newEmail));
659
+ return true;
 
 
 
 
 
 
 
660
  }
661
 
662
  // get info for the currently updated user
664
  $editedUserName = $editedUserInfo['userName'];
665
 
666
  // %user_making_change% changed the email address of user account %user% from %old_email% to %new_email%
667
+ $eData = array($currentUserName, $editedUserName, $oldEmail, $newEmail);
668
 
669
+ self::_addLogEvent(4006, $currentUserID, WPPHUtil::getIP(), $eData);
670
+ return true;
671
  }
672
 
673
  /**
693
  $_userName = $_userInfo['userName'];
694
  $_userRole = ucfirst($_userInfo['userRole']);
695
 
696
+ self::_addLogEvent(4007, $currentUserID, WPPHUtil::getIP(), array($_userName, $_userRole, $un));
 
 
697
  }
698
 
699
+ // # 5001
700
  public static function watchPluginActivate()
701
  {
702
  wpphLog(__METHOD__.'() triggered by hook.');
703
 
 
 
 
 
 
 
 
 
 
 
 
704
  // get info for the currently logged in user
705
  $current_user = wp_get_current_user();
706
 
707
+ // activate one by link
708
+ if(! empty($_GET['action']) && ($_GET['action']=='activate') || !empty($_GET['action2']) && ($_GET['action2']=='activate'))
709
+ {
710
+ $pluginFile = $_GET['plugin'];
711
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
712
+ $pluginName = $pluginData['Name'];
713
+ self::_addLogEvent(5001,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
714
+ wpphLog('Plugin activated.', array('plugin file'=>$pluginFile));
715
+ }
716
+ // one by bulk
717
+ elseif(isset($_POST['action']) && ($_POST['action'] == 'activate-selected') || isset($_POST['action2']) && ($_POST['action2'] == 'activate-selected'))
718
+ {
719
+ if(! empty($_POST['checked']))
720
+ {
721
+ foreach($_POST['checked'] as $k=>$pluginFile){
722
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
723
+ $pluginName = $pluginData['Name'];
724
+ self::_addLogEvent(5001,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
725
+ wpphLog('Plugin activated.', array('plugin file'=>$pluginFile));
726
+ }
727
+ }
728
+ }
729
+ // more by bulk
730
+ elseif(isset($_POST['activate-multi']) && ($_POST['action']=='activate-selected' || $_POST['action2']=='activate-selected'))
731
+ {
732
+ if(! empty($_POST['checked']))
733
+ {
734
+ foreach($_POST['checked'] as $k=>$pluginFile){
735
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
736
+ $pluginName = $pluginData['Name'];
737
+ self::_addLogEvent(5001,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
738
+ wpphLog('Plugin activated.', array('plugin file'=>$pluginFile));
739
+ }
740
+ }
741
+ }
742
  }
743
+ // # 5002
744
  public static function watchPluginDeactivate()
745
  {
746
  wpphLog(__METHOD__.'() triggered by hook.');
747
 
 
 
 
 
 
748
  // get info for the currently logged in user
749
  $current_user = wp_get_current_user();
750
 
751
+ // activate one by link
752
+ if(isset($_GET['action']) && ($_GET['action']=='deactivate') || isset($_GET['action2']) && ($_GET['action2']=='deactivate'))
753
+ {
754
+ $pluginFile = $_GET['plugin'];
755
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
756
+ $pluginName = $pluginData['Name'];
757
+ self::_addLogEvent(5002,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
758
+ wpphLog('Plugin deactivated.', array('plugin file'=>$pluginFile));
759
+ }
760
+ // one by bulk
761
+ elseif(isset($_POST['action']) && ($_POST['action'] == 'deactivate-selected') || isset($_POST['action2']) && ($_POST['action2'] == 'deactivate-selected'))
762
+ {
763
+ if(! empty($_POST['checked']))
764
+ {
765
+ foreach($_POST['checked'] as $k=>$pluginFile){
766
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
767
+ $pluginName = $pluginData['Name'];
768
+ self::_addLogEvent(5002,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
769
+ wpphLog('Plugin deactivated.', array('plugin file'=>$pluginFile));
770
+ }
771
+ }
772
+ }
773
+ // more by bulk
774
+ elseif(isset($_GET['activate-multi']) && ($_POST['action']=='deactivate-selected' || $_POST['action2']=='deactivate-selected'))
775
+ {
776
+ if(! empty($_POST['checked']))
777
+ {
778
+ foreach($_POST['checked'] as $k=>$pluginFile){
779
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
780
+ $pluginName = $pluginData['Name'];
781
+ self::_addLogEvent(5002,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
782
+ wpphLog('Plugin deactivated.', array('plugin file'=>$pluginFile));
783
+ }
784
+ }
785
+ }
786
+ }
787
+ // # 5000
788
+ public static function watchPluginInstall()
789
+ {
790
+ if(empty($_GET)) { return; }
791
+
792
+ /**
793
+ * @internal
794
+ * @param $pluginName
795
+ */
796
+ function wpph_installPlugin($pluginName)
797
+ {
798
+ if(! empty($_GET['plugin']))
799
+ {
800
+ // get info for the currently logged in user
801
+ $current_user = wp_get_current_user();
802
+ WPPHEvent::_addLogEvent(5000,$current_user->ID, WPPHUtil::getIP(), array($pluginName));
803
+ wpphLog('Plugin installed.', array('plugin'=>$pluginName));
804
+ }
805
+ }
806
 
807
+ if(isset($_GET['action']) && $_GET['action']=='install-plugin'){
808
+ wpphLog(__METHOD__.'() triggered by hook.');
809
+ wpph_installPlugin($_GET['plugin']);
810
+ }
811
+ elseif(isset($_GET['action2']) && $_GET['action2']=='install-plugin'){
812
+ wpphLog(__METHOD__.'() triggered by hook.');
813
+ wpph_installPlugin($_GET['plugin']);
814
+ }
815
+ }
816
+ // # 5003
817
+ public static function watchPluginUninstall()
818
+ {
819
+ if(empty($_POST)) { return; }
820
+ if(! isset($_POST['verify-delete'])) { return; }
821
+ if(empty($_POST['checked'])){ return; }
822
+
823
+ $action = '';
824
+ if(! empty($_POST['action'])){ $action = $_POST['action'];}
825
+ elseif(! empty($_POST['action2'])){ $action = $_POST['action2'];}
826
+ if(empty($action) || $action != 'delete-selected') {
827
+ return;
828
+ }
829
+
830
+ wpphLog(__METHOD__.'() triggered by hook.');
831
+ // get info for the currently logged in user
832
+ $current_user = wp_get_current_user();
833
+ foreach($_POST['checked'] as $pluginFile){
834
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
835
+ $pluginName = $pluginData['Name'];
836
+ self::_addLogEvent(5003,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
837
+ wpphLog('Plugin uninstalled.', array('plugin file'=>$pluginFile));
838
+ }
839
+ }
840
+ // # 5004
841
+ public static function watchPluginUpgrade()
842
+ {
843
+ // single update/upgrade
844
+ if(! empty($_GET['action']))
845
+ {
846
+ $action = '';
847
+ if(! empty($_GET['action'])){ $action = $_GET['action'];}
848
+ elseif(! empty($_GET['action2'])){ $action = $_GET['action2'];}
849
+ if(empty($action) || $action != 'upgrade-plugin') {
850
+ return;
851
+ }
852
+ wpphLog(__METHOD__.'() triggered by hook.');
853
+
854
+ // get info for the currently logged in user
855
+ $current_user = wp_get_current_user();
856
+ $pluginFile = $_GET['plugin'];
857
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
858
+ $pluginName = $pluginData['Name'];
859
+ // Upgraded the plugin <strong>%s</strong> installed in /<strong>%s</strong>
860
+ self::_addLogEvent(5004,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
861
+ wpphLog('Plugin upgraded.', array('plugin file'=>$pluginFile));
862
+ }
863
+ // multi-update/upgrade
864
+ elseif(! empty($_POST))
865
+ {
866
+ $action = '';
867
+ if(! empty($_POST['action'])){ $action = $_POST['action'];}
868
+ elseif(! empty($_POST['action2'])){ $action = $_POST['action2'];}
869
+ if(empty($action) || $action != 'update-selected') { return; }
870
+ if(empty($_POST['checked'])){ return; }
871
+ if(empty($_POST['_wp_http_referer'])){ return; }
872
+ $referrer = $_POST['_wp_http_referer'];
873
+ if(false === ($pos = stripos($referrer, 'plugins.php'))){
874
+ return;
875
+ }
876
+ wpphLog(__METHOD__.'() triggered by hook.');
877
+
878
+ // get info for the currently logged in user
879
+ $current_user = wp_get_current_user();
880
+ foreach($_POST['checked'] as $pluginFile){
881
+ $pluginData = get_plugin_data(WP_PLUGIN_DIR.'/'.$pluginFile,false,false);
882
+ $pluginName = $pluginData['Name'];
883
+ self::_addLogEvent(5004,$current_user->ID, WPPHUtil::getIP(), array($pluginName,$pluginFile));
884
+ wpphLog('Plugin upgraded.', array('plugin file'=>$pluginFile));
885
+ }
886
+ }
887
  }
888
 
889
 
890
+ public static function watchBlogActivity($newStatus, $oldStatus, $post)
891
  {
892
+ wpphLog(__FUNCTION__.'. POST DATA', array(
893
+ '$newStatus' => $newStatus,
894
+ '$oldStatus' => $oldStatus,
895
+ '$post' => $post
896
+ ));
897
+
898
+ // IGNORE STATES
899
+ if($newStatus == 'auto-draft' || $post->post_status == 'auto-draft')
900
+ {
901
+ return;
902
+ }
903
+
904
+ // so we skip generating multiple events
905
+ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; }
906
 
907
  $postID = $post->ID;
908
+ $postTitle = $post->post_title;
909
+ $postUrl = get_permalink($postID);
910
+ $postStatus = $post->post_status;
911
  $currentUserID = wp_get_current_user()->ID;
912
  $userID = $postAuthorID = $post->post_author;
913
  if($currentUserID != $postAuthorID){
915
  $userID = $currentUserID;
916
  }
917
 
918
+ if($post->post_type == 'revision'){
919
+ return;
920
+ }
921
+
922
+ wpphLog(__FUNCTION__.' triggered by hook.');
923
+
924
+
925
+ // CHECK TO SEE IF THIS UPDATE IS FROM THE QUICK EDIT FORM or the default wp post editor
926
+ if(isset($_POST['original_post_status']))
927
+ {
928
+ $originalPostStatus = $_POST['original_post_status'];
929
+ }
930
+ else{
931
+ // quick edit form
932
+ $originalPostStatus = $_POST['_status'];
933
+ }
934
+
935
+
936
  // We're dealing with posts
937
  if($post->post_type == 'post')
938
  {
939
+ /**
940
+ * @@ 2016
941
+ * Check for category change
942
+ */
943
+ if(isset($GLOBALS['WPPH_POST_OLD_CATEGORIES']))
944
  {
945
+ $originalCats = $GLOBALS['WPPH_POST_OLD_CATEGORIES'];
946
+ $categories_1 = array();
947
+ foreach($originalCats as $catID){
948
+ $cat = get_category($catID);
949
+ array_push($categories_1, $cat->name);
950
+ }
951
+ $categories_2 = array();
952
+ $newCats = $post->post_category;
953
+ if(empty($newCats[0])){
954
+ unset($newCats[0]);
955
+ }
956
+ foreach($newCats as $catID){
957
+ $cat = get_category($catID);
958
+ array_push($categories_2, $cat->name);
959
+ }
960
+
961
+ sort($categories_1);
962
+ sort($categories_2);
963
+
964
+ // categories updated
965
+ if($categories_1 <> $categories_2)
966
  {
967
+ $c1 = implode(', ', $categories_1);
968
+ $c2 = implode(', ', $categories_2);
969
+ wpph_postCategoriesUpdated(wp_get_current_user()->ID, $postTitle, $c1, $c2);
970
+ $GLOBALS['WPPH_EVENT_2016'] = true;
 
971
  }
972
  }
973
 
974
+ // 2019
975
+ // check to see whether or not the post author was changed
976
+ if(isset($GLOBALS['WPPH_POST_AUTHOR_UPDATED'])){
977
+ $newAuthorID = (int)$GLOBALS['WPPH_POST_AUTHOR_UPDATED'];
978
+ if(wpph_postAuthorUpdated($newAuthorID, $postID, $userID, $postTitle)){
979
+ unset($GLOBALS['WPPH_POST_AUTHOR_UPDATED']);
980
+ $GLOBALS['WPPH_EVENT_2019'] = true;
981
+ }
982
+ }
983
 
984
+ // # 2000 - NEW POST AS DRAFT
985
+ // # 2003 - DRAFT UPDATED
986
+ if(($oldStatus == 'draft' || $oldStatus == 'auto-draft') && $newStatus == 'draft' && $postStatus == 'draft')
987
+ {
988
+ // # 2000 - NEW POST AS DRAFT
989
+ if($originalPostStatus == 'auto-draft')
990
  {
991
+ // New blog post saved as draft
992
+ wpph_newPostAsDraft($userID, $postID, $postTitle);
 
 
 
 
993
  }
994
+ // # 2003 - DRAFT UPDATED
995
+ elseif($originalPostStatus == 'draft')
996
  {
997
+ // only if 2016 || 2017 || 2019 were not triggered
998
+ if(isset($GLOBALS['WPPH_EVENT_2016']) || isset($GLOBALS['WPPH_EVENT_2017']) || isset($GLOBALS['WPPH_EVENT_2019'])){
999
+ return;
1000
+ }
1001
  // Modified the draft blog post %post_title%. Blog post ID is %ID%
1002
+ wpph_draftPostUpdated($userID, $postID, $postTitle);
 
 
 
1003
  }
1004
  }
1005
+ // # 2001 - DRAFT TO PUBLISHED
1006
+ elseif($oldStatus == 'draft' && $newStatus == 'publish' && $postStatus == 'publish'){
 
1007
  // Published a blog post called %Post_Title%. Blog post URL is %Post_URL%
1008
+ wpph_newPostPublished($userID, $postTitle, $postUrl);
1009
+ }
1010
+ // # 2001 - NEW POST PUBLISHED
1011
+ elseif($oldStatus == 'auto-draft' && $newStatus == 'publish' && $postStatus == 'publish'){
1012
+ // Published a blog post called %Post_Title%. Blog post URL is %Post_URL%
1013
+ wpph_newPostPublished($userID, $postTitle, $postUrl);
1014
+ }
1015
+ // # 2001 - PENDING TO PUBLISHED
1016
+ elseif($oldStatus == 'pending' && $newStatus == 'publish' && $postStatus == 'publish'){
1017
+ // Published a blog post called %Post_Title%. Blog post URL is %Post_URL%
1018
+ wpph_newPostPublished($userID, $postTitle, $postUrl);
1019
  }
1020
+ // # 2002 - PUBLISHED POST UPDATED
1021
+ elseif($oldStatus == 'publish' && $newStatus == 'publish' && $postStatus == 'publish')
1022
  {
1023
+ // CHECK IF POST URL MODIFIED
1024
+ // ## step 1: see self::hookWatchPostStateBefore()
1025
+ // ## step 2: trigger event
1026
+ // trigger: 2017 - Changed the URL of the post %post_name% from %old_url% to %new_url%
1027
+ if(isset($GLOBALS['WPPH_POST_NEW_URL']))
1028
+ {
1029
+ if(wpph_postUrlUpdated($GLOBALS['WPPH_POST_NEW_URL'], get_permalink($postID), $userID, $postTitle)){
1030
+ unset($GLOBALS['WPPH_POST_NEW_URL']);
1031
+ $GLOBALS['WPPH_EVENT_2017'] = true;
1032
+ }
1033
+ }
1034
+ // only if 2016 || 2017 || 2019 were not triggered
1035
+ if(isset($GLOBALS['WPPH_EVENT_2016']) || isset($GLOBALS['WPPH_EVENT_2017']) || isset($GLOBALS['WPPH_EVENT_2019'])){
1036
+ return;
1037
+ }
1038
  // Modified the published blog post %post_title%. Blog post URL is %post_URL%
1039
+ wpph_publishedPostUpdated($userID, $postTitle, $postUrl);
1040
+ }
1041
+ // # 2021 - PUBLISHED TO PENDING
1042
+ elseif($oldStatus == 'publish' && $newStatus == 'pending' && $postStatus == 'pending'){
1043
+ wpph_postStatusUpdated('Published', 'Pending Review', $userID, $postTitle);
1044
+ }
1045
+ // # 2021 - PENDING TO DRAFT
1046
+ elseif($oldStatus == 'pending' && $newStatus == 'draft' && $postStatus == 'draft'){
1047
+ wpph_postStatusUpdated('Pending Review', 'Draft', $userID, $postTitle);
1048
+ }
1049
+ // # 2021 - DRAFT TO PENDING
1050
+ elseif($oldStatus == 'draft' && $newStatus == 'pending' && $postStatus == 'pending'){
1051
+ wpph_postStatusUpdated('Draft', 'Pending Review', $userID, $postTitle);
1052
+ }
1053
+ // # 2021 - PUBLISHED TO DRAFT
1054
+ elseif($oldStatus == 'publish' && $newStatus == 'draft' && $postStatus == 'draft'){
1055
+ wpph_postStatusUpdated('Published', 'Draft', $userID, $postTitle);
1056
  }
1057
  }
 
1058
  // We're dealing with pages
1059
  elseif($post->post_type == 'page')
1060
  {
1061
+ // 2020
1062
+ // check to see whether or not the page author was changed
1063
+ if(isset($GLOBALS['WPPH_POST_AUTHOR_UPDATED'])){
1064
+ $newAuthorID = (int)$GLOBALS['WPPH_POST_AUTHOR_UPDATED'];
1065
+ if(wpph_pageAuthorUpdated($newAuthorID, $postID, $userID, $postTitle)){
1066
+ unset($GLOBALS['WPPH_POST_AUTHOR_UPDATED']);
1067
+ $GLOBALS['WPPH_EVENT_2020'] = true;
 
 
 
 
 
1068
  }
1069
  }
1070
 
1071
+ // # 2004 - NEW PAGE AS DRAFT
1072
+ // # 2007 - DRAFT UPDATED
1073
+ if(($oldStatus == 'draft' || $oldStatus == 'auto-draft') && $newStatus == 'draft' && $postStatus == 'draft')
1074
  {
1075
+ // # 2004 - NEW PAGE AS DRAFT
1076
+ if($originalPostStatus == 'auto-draft'){
1077
+ wpph_newPageAsDraft($userID, $postID, $postTitle);
 
 
 
 
 
 
 
 
 
1078
  }
1079
+ // # 2007 - DRAFT UPDATED
1080
+ elseif($originalPostStatus == 'draft'){
1081
+ // only if 2018 || 2020 were not triggered
1082
+ if(isset($GLOBALS['WPPH_EVENT_2018']) || isset($GLOBALS['WPPH_EVENT_2020'])){
1083
+ return;
1084
+ }
1085
+ wpph_draftPageUpdated($userID, $postID, $postTitle);
 
 
 
1086
  }
1087
  }
1088
+ // # 2005 - DRAFT TO PUBLISHED
1089
+ elseif($oldStatus == 'draft' && $newStatus == 'publish' && $postStatus == 'publish'){
1090
+ wpph_newPagePublished($userID, $postTitle, $postUrl);
1091
+ }
1092
+ // # 2005 - NEW PAGE PUBLISHED
1093
+ elseif(($oldStatus == 'draft' || $oldStatus == 'auto-draft') && $newStatus == 'publish' && $postStatus == 'publish'){
1094
  // Published a page called %page_title%. Page URL is %URL%
1095
+ wpph_newPagePublished($userID, $postTitle, $postUrl);
 
 
1096
  }
1097
+ // # 2005 - PENDING TO PUBLISHED
1098
+ elseif($oldStatus == 'pending' && $newStatus == 'publish' && $postStatus == 'publish'){
1099
+ // Published a page called %page_title%. Page URL is %URL%
1100
+ wpph_newPagePublished($userID, $postTitle, $postUrl);
1101
+ }
1102
+ // # 2006 - PUBLISHED PAGE UPDATED | 2018, 2020
1103
+ elseif($oldStatus == 'publish' && $newStatus == 'publish' && $postStatus == 'publish')
1104
  {
1105
+ // CHECK IF PAGE URL MODIFIED
1106
+ // ## step 1: see self::hookWatchPostStateBefore()
1107
+ // ## step 2: trigger event
1108
+ // trigger: 2018 - Changed the URL of the page %post_name% from %old_url% to %new_url%
1109
+ if(isset($GLOBALS['WPPH_POST_NEW_URL']))
1110
+ {
1111
+ if(wpph_pageUrlUpdated($GLOBALS['WPPH_POST_NEW_URL'], get_permalink($postID), $userID, $postTitle)){
1112
+ unset($GLOBALS['WPPH_POST_NEW_URL']);
1113
+ $GLOBALS['WPPH_EVENT_2018'] = true;
1114
+ }
1115
+ }
1116
+ // only if 2018 || 2020 were not triggered
1117
+ if(isset($GLOBALS['WPPH_EVENT_2018']) || isset($GLOBALS['WPPH_EVENT_2020'])){
1118
+ return;
1119
+ }
1120
  // Modified the published page %page_title%. Page URL is %URL%
1121
+ wpph_publishedPageUpdated($userID, $postTitle, $postUrl);
1122
+ }
1123
+ // # 2022 - PUBLISHED TO PENDING
1124
+ elseif($oldStatus == 'publish' && $newStatus == 'pending' && $postStatus == 'pending'){
1125
+ wpph_pageStatusUpdated('Published', 'Pending Review', $userID, $postTitle);
1126
+ }
1127
+ // # 2022 - PENDING TO DRAFT
1128
+ elseif($oldStatus == 'pending' && $newStatus == 'draft' && $postStatus == 'draft'){
1129
+ wpph_pageStatusUpdated('Pending Review', 'Draft', $userID, $postTitle);
1130
+ }
1131
+ // # 2022 - DRAFT TO PENDING
1132
+ elseif($oldStatus == 'draft' && $newStatus == 'pending' && $postStatus == 'pending'){
1133
+ wpph_pageStatusUpdated('Draft', 'Pending Review', $userID, $postTitle);
1134
+ }
1135
+ // # 2022 - PUBLISHED TO DRAFT
1136
+ elseif($oldStatus == 'publish' && $newStatus == 'draft' && $postStatus == 'draft'){
1137
+ wpph_pageStatusUpdated('Published', 'Draft', $userID, $postTitle);
1138
  }
1139
  }
1140
  }
1142
  public static function watchTrash($postID)
1143
  {
1144
  wpphLog(__METHOD__.'() triggered by hook.');
 
1145
  $hPid = md5($postID);
 
1146
  // get info for the currently logged in user
1147
  $current_user = wp_get_current_user();
 
1148
  global $wpdb;
 
1149
  $postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
1150
  $postTitle = $postInfo->post_title;
1151
  $postType = $postInfo->post_type;
 
1152
  if($postType == 'post')
1153
  {
1154
  // Deleted the blog post %Title%. Blog post ID is %ID%
1155
+ self::_addLogEvent(2008, $current_user->ID, WPPHUtil::getIP(), array($postTitle,$postID));
 
1156
  wpphLog('Blog post deleted.', array('title'=>$postTitle, 'id'=>$postID));
1157
  }
1158
  elseif($postType == 'page')
1159
  {
1160
  // Deleted the page %Title%. Page ID is %ID%
1161
+ self::_addLogEvent(2009, $current_user->ID, WPPHUtil::getIP(), array($postTitle,$postID));
 
1162
  wpphLog('Page deleted.', array('title'=>$postTitle, 'id'=>$postID));
1163
  }
1164
  }
1167
  public static function watchFileUploaded($attachmentID)
1168
  {
1169
  global $wpdb;
 
1170
  // get info for the currently logged in user
1171
  $current_user = wp_get_current_user();
 
1172
  $rowData = $wpdb->get_row("SELECT guid FROM ".$wpdb->posts." WHERE ID = ".$attachmentID);
1173
  $fileName = basename($rowData->guid);
1174
  $dirName = dirname($rowData->guid);
 
1175
  // Uploaded the file %file name$ in %file location%
1176
+ self::_addLogEvent(2010, $current_user->ID, WPPHUtil::getIP(), array($fileName, $dirName));
1177
  wpphLog('File uploaded.', array('title'=>$fileName, 'url'=>$dirName));
1178
  }
1179
  // 2011
1180
  public static function watchFileUploadedDeleted($attachmentID)
1181
  {
1182
  global $wpdb;
 
1183
  // get info for the currently logged in user
1184
  $current_user = wp_get_current_user();
 
1185
  $rowData = $wpdb->get_row("SELECT post_title, guid FROM ".$wpdb->posts." WHERE ID = ".$attachmentID);
 
1186
  // Deleted file %file name$ from %file_location%
1187
+ self::_addLogEvent(2011, $current_user->ID, WPPHUtil::getIP(), array($rowData->post_title,dirname($rowData->guid)));
1188
  wpphLog('File deleted.', array('title'=>$rowData->post_title, 'url'=>dirname($rowData->guid)));
1189
  }
1190
 
1192
  public static function watchFileDeletion($postID)
1193
  {
1194
  global $wpdb;
 
1195
  $postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
1196
  $postTitle = $postInfo->post_title;
1197
  $postType = $postInfo->post_type;
 
1198
  // get info for the currently logged in user
1199
  $userID = wp_get_current_user()->ID;
 
1200
  if('post' == $postType)
1201
  {
1202
+ self::_addLogEvent(2012, $userID, WPPHUtil::getIP(), array($postTitle));
1203
  wpphLog('Post trashed.', array('name'=>$postTitle));
1204
  }
1205
  elseif ('page' == $postType)
1206
  {
1207
+ self::_addLogEvent(2013, $userID, WPPHUtil::getIP(), array($postTitle));
1208
  wpphLog('Page trashed.', array('name'=>$postTitle));
1209
  }
1210
  }
1213
  public static function watchTrashUndo($postID)
1214
  {
1215
  global $wpdb;
 
1216
  $postInfo = $wpdb->get_row("SELECT post_title, post_type FROM ".$wpdb->posts." WHERE ID = ".$postID);
1217
  $postTitle = $postInfo->post_title;
1218
  $postType = $postInfo->post_type;
 
1219
  // get info for the currently logged in user
1220
  $userID = wp_get_current_user()->ID;
 
1221
  if('post' == $postType)
1222
  {
1223
+ self::_addLogEvent(2014, $userID, WPPHUtil::getIP(), array($postTitle));
1224
  wpphLog('Post restored from trash.', array('name'=>$postTitle));
1225
  }
1226
  elseif ('page' == $postType)
1227
  {
1228
+ self::_addLogEvent(2015, $userID, WPPHUtil::getIP(), array($postTitle));
1229
  wpphLog('Page restored from trash.', array('name'=>$postTitle));
1230
  }
1231
  }
1232
 
 
1233
  // 3000 - Theme activated
1234
  public static function watchThemeChange($themeName)
1235
  {
1236
  // get info for the currently logged in user
1237
  $current_user = wp_get_current_user();
 
1238
  // // Activated the theme %themeName%
1239
+ self::_addLogEvent(3000, $current_user->ID, WPPHUtil::getIP(), array($themeName));
1240
  wpphLog('Theme activated.', array('name'=>$themeName));
1241
  }
1242
+
1243
+ // 2023 - category created
1244
+ public static function watchCategoryAdd(array $postData)
1245
+ {
1246
+ wpphLog(__METHOD__.'() triggered by hook.');
1247
+
1248
+ if(!empty($_POST['screen']) && !empty($_POST['tag-name']) &&
1249
+ $_POST['screen'] == 'edit-category' &&
1250
+ $_POST['taxonomy'] == 'category' &&
1251
+ $_POST['action'] == 'add-tag')
1252
+ {
1253
+ $categoryName = sanitize_text_field($_POST['tag-name']);
1254
+
1255
+ // get info for the currently logged in user
1256
+ $current_user = wp_get_current_user();
1257
+ // Created a new category called %categoryName%
1258
+ self::_addLogEvent(2023, $current_user->ID, WPPHUtil::getIP(), array($categoryName));
1259
+ wpphLog('Category added.', array('name'=>$categoryName));
1260
+ }
1261
+ // adding the new category when writing a blog post
1262
+ elseif(! empty($_POST['newcategory']) && $_POST['action'] == 'add-category')
1263
+ {
1264
+ $categoryName = sanitize_text_field($_POST['newcategory']);
1265
+
1266
+ // get info for the currently logged in user
1267
+ $current_user = wp_get_current_user();
1268
+ // Created a new category called %categoryName%
1269
+ self::_addLogEvent(2023, $current_user->ID, WPPHUtil::getIP(), array($categoryName));
1270
+ wpphLog('Category added.', array('name'=>$categoryName));
1271
+ }
1272
+ }
1273
+
1274
+ // 2024 - category deleted
1275
+ public static function watchCategoryDelete(array $postData)
1276
+ {
1277
+ wpphLog(__METHOD__.'() triggered by hook.');
1278
+
1279
+ if(empty($postData)){ return; }
1280
+
1281
+ // get info for the currently logged in user
1282
+ $current_user = wp_get_current_user();
1283
+ $userID = $current_user->ID;
1284
+ $userIP = WPPHUtil::getIP();
1285
+
1286
+ //@internal
1287
+ function __alertDeletedCategory($userID, $userIP, $categoryID){
1288
+ $category = get_category($categoryID);
1289
+ $categoryName = $category->cat_name;
1290
+ WPPHEvent::_addLogEvent(2024, $userID, $userIP, array($categoryName));
1291
+ wpphLog('Category deleted.', array('name'=>$categoryName));
1292
+ }
1293
+
1294
+ $action = '';
1295
+ if(! empty($postData['action'])){ $action = $postData['action'];}
1296
+ elseif(! empty($postData['action2'])){ $action = $postData['action2'];}
1297
+ if(empty($action)) {
1298
+ return;
1299
+ }
1300
+
1301
+ // delete one
1302
+ if($action == 'delete-tag' && $postData['taxonomy'] == 'category' && !empty($postData['tag_ID'])){
1303
+ __alertDeletedCategory($userID, $userIP, $postData['tag_ID']);
1304
+ }
1305
+
1306
+ // bulk delete
1307
+ elseif($action == 'delete' && $postData['taxonomy'] == 'category' && !empty($postData['delete_tags'])){
1308
+ foreach($postData['delete_tags'] as $categoryID){
1309
+ __alertDeletedCategory($userID, $userIP, $categoryID);
1310
+ }
1311
+ }
1312
+ }
1313
+
1314
  }
inc/WPPHLogger.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  // custom function
3
- function wpphLog($message, array $data = array()){ WPPHLogger::write($message,$data); }
4
  /*
5
  * @internal
6
  * Debug class
@@ -15,10 +15,16 @@ class WPPHLogger
15
  public static function enableDebugLogging(){ self::$_debugLoggingEnabled = true; }
16
  public static function enableErrorLogging(){ ini_set('error_log', WPPH_PLUGIN_DIR.'error.log'); }
17
 
18
- public static function write($message, array $data = array())
19
  {
20
  if(!self::$_debugLoggingEnabled) { return; }
21
  $m = '['.@date("D, M d, Y @H:i:s").'] Debug: '.$message;
 
 
 
 
 
 
22
  if(! empty($data)) {
23
  $m .= ' Data: '.var_export($data, true);
24
  }
1
  <?php
2
  // custom function
3
+ function wpphLog($message, $data=null,$function=null,$line=null){ WPPHLogger::write($message,$data,$function,$line); }
4
  /*
5
  * @internal
6
  * Debug class
15
  public static function enableDebugLogging(){ self::$_debugLoggingEnabled = true; }
16
  public static function enableErrorLogging(){ ini_set('error_log', WPPH_PLUGIN_DIR.'error.log'); }
17
 
18
+ public static function write($message, $data=null,$function=null,$line=null)
19
  {
20
  if(!self::$_debugLoggingEnabled) { return; }
21
  $m = '['.@date("D, M d, Y @H:i:s").'] Debug: '.$message;
22
+ if(!empty($function)){
23
+ $m .= PHP_EOL.'Function: '.$function;
24
+ if(! empty($line)){
25
+ $m .= PHP_EOL.'Line: '.$line.PHP_EOL;
26
+ }
27
+ }
28
  if(! empty($data)) {
29
  $m .= ' Data: '.var_export($data, true);
30
  }
inc/WPPHUtil.php CHANGED
@@ -1,22 +1,13 @@
1
  <?php
2
- /**
3
- * @kyos
4
- * Class WPPHUtil
5
- * Contains utility methods
6
- */
7
  class WPPHUtil
8
  {
9
- public static function getIP()
10
- {
11
- if ($_SERVER['HTTP_CLIENT_IP']) $ip = $_SERVER['HTTP_CLIENT_IP'];
12
- else if($_SERVER['HTTP_X_FORWARDED_FOR']) $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
13
- else if($_SERVER['HTTP_X_FORWARDED']) $ip = $_SERVER['HTTP_X_FORWARDED'];
14
- else if($_SERVER['HTTP_FORWARDED_FOR']) $ip = $_SERVER['HTTP_FORWARDED_FOR'];
15
- else if($_SERVER['HTTP_FORWARDED']) $ip = $_SERVER['HTTP_FORWARDED'];
16
- else if($_SERVER['REMOTE_ADDR']) $ip = $_SERVER['REMOTE_ADDR'];
17
- else $ip = '0.0.0.0';
18
- return $ip;
19
- }
20
 
21
  /*
22
  * Will respond to the ajax requests getting the events
@@ -25,27 +16,19 @@ class WPPHUtil
25
  {
26
  //#! VALIDATE REQUEST
27
  $rm = strtoupper($_SERVER['REQUEST_METHOD']);
28
- if($rm != 'POST'){
29
- exit('<tr><td colspan="7"><span>'.__('Error: Invalid request').'</span></td></tr>');
30
- }
31
 
32
  // set defaults
33
  $orderBy = 'EventNumber';
34
  $sort = 'desc';
35
  $limit = array(0, 50);
36
- $orderDescending = true;
37
- $pageNumber = 0;
38
 
39
  if(!empty($_POST['orderBy'])) { $orderBy = $_POST['orderBy']; }
40
  if(!empty($_POST['sort'])) {
41
- if(0 == strcasecmp($_POST['sort'],'asc')){
42
- $sort = 'asc';
43
- $orderDescending = false;
44
- }
45
  }
46
  if(isset($_POST['offset'])) { $limit[0] = intval($_POST['offset']); }
47
  if(isset($_POST['count'])) { $limit[1] = intval($_POST['count']); }
48
- if(isset($_POST['pageNumber'])) { $pageNumber = intval($_POST['pageNumber']); }
49
 
50
  function __formatJsonOutput(array $sourceData=array(), $error=''){
51
  return json_encode(array(
@@ -55,12 +38,13 @@ class WPPHUtil
55
  };
56
 
57
  // get events
 
58
  $events = WPPHEvent::getEvents($orderBy, $sort, $limit);
 
59
  $eventsNum = count($events);
60
- $allEventsCount = WPPHDB::getEventsCount();
61
 
62
  if($eventsNum == 0){
63
- exit(__formatJsonOutput(array(),__('There are no events to display.')));
64
  }
65
 
66
  $out = array();
@@ -75,15 +59,16 @@ class WPPHUtil
75
  $EventDate = $entry->EventDate;
76
  $userIP = $entry->UserIP;
77
  $UserID = $entry->UserID;
78
- $eventData = unserialize($entry->EventData); //<< values to use for event description
79
 
 
80
  // get User Info
81
  if($UserID == 0){ $username = 'System'; }
82
  else {
83
  $user_info = get_userdata($UserID);
84
  $username = $user_info->user_login;
85
- $first_name = $user_info-> user_firstname;
86
- $last_name = $user_info-> user_lastname;
87
  $username = "$username ($first_name $last_name)";
88
  }
89
 
@@ -91,8 +76,13 @@ class WPPHUtil
91
  $eventDetails = WPPHEvent::getEventDetailsData($EventID);
92
 
93
  // format event description message
94
- if(empty($eventData)) { $evm = $eventDetails->EventDescription; }
95
- else { $evm = vsprintf($eventDetails->EventDescription, $eventData); }
 
 
 
 
 
96
 
97
  $e = array(
98
  'eventNumber' => $eventNumber,
@@ -101,13 +91,13 @@ class WPPHUtil
101
  'eventDate' => $EventDate,
102
  'ip' => $userIP,
103
  'user' => $username,
104
- 'description' => $evm
105
  );
106
  array_push($out['events'], $e);
107
  }
108
- $out['eventsCount'] = $allEventsCount;
109
 
110
- exit(__formatJsonOutput($out,''));
111
  }
112
 
113
  }
1
  <?php
 
 
 
 
 
2
  class WPPHUtil
3
  {
4
+ public static function getIP() { return(!empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0'); }
5
+
6
+ /**
7
+ * Check to see whether or not the current user is an administrator
8
+ * @return bool
9
+ */
10
+ public static function isAdministrator(){ return user_can(wp_get_current_user(),'update_core'); }
 
 
 
 
11
 
12
  /*
13
  * Will respond to the ajax requests getting the events
16
  {
17
  //#! VALIDATE REQUEST
18
  $rm = strtoupper($_SERVER['REQUEST_METHOD']);
19
+ if($rm != 'POST'){ exit('<tr><td colspan="7"><span>'.__('Error: Invalid request').'</span></td></tr>'); }
 
 
20
 
21
  // set defaults
22
  $orderBy = 'EventNumber';
23
  $sort = 'desc';
24
  $limit = array(0, 50);
 
 
25
 
26
  if(!empty($_POST['orderBy'])) { $orderBy = $_POST['orderBy']; }
27
  if(!empty($_POST['sort'])) {
28
+ if(0 == strcasecmp($_POST['sort'],'asc')){ $sort = 'asc'; }
 
 
 
29
  }
30
  if(isset($_POST['offset'])) { $limit[0] = intval($_POST['offset']); }
31
  if(isset($_POST['count'])) { $limit[1] = intval($_POST['count']); }
 
32
 
33
  function __formatJsonOutput(array $sourceData=array(), $error=''){
34
  return json_encode(array(
38
  };
39
 
40
  // get events
41
+ $eventsCount = WPPHDB::getEventsCount();
42
  $events = WPPHEvent::getEvents($orderBy, $sort, $limit);
43
+
44
  $eventsNum = count($events);
 
45
 
46
  if($eventsNum == 0){
47
+ exit( __formatJsonOutput(array(),__('There are no events to display.')) );
48
  }
49
 
50
  $out = array();
59
  $EventDate = $entry->EventDate;
60
  $userIP = $entry->UserIP;
61
  $UserID = $entry->UserID;
62
+ $eventData = ((!empty($entry->EventData)) ? unserialize(base64_decode($entry->EventData)) : ''); //<< values to use for event description
63
 
64
+ $eventCount = intval($entry->EventCount);
65
  // get User Info
66
  if($UserID == 0){ $username = 'System'; }
67
  else {
68
  $user_info = get_userdata($UserID);
69
  $username = $user_info->user_login;
70
+ $first_name = $user_info->user_firstname;
71
+ $last_name = $user_info->user_lastname;
72
  $username = "$username ($first_name $last_name)";
73
  }
74
 
76
  $eventDetails = WPPHEvent::getEventDetailsData($EventID);
77
 
78
  // format event description message
79
+ if($eventCount >=2 && $EventID == 1002){
80
+ $evm = sprintf(__('<strong>%d</strong> failed login attempts from <strong>%s</strong> using <strong>%s</strong> as username.'), $eventCount, $userIP, base64_decode($entry->UserName));
81
+ }
82
+ else {
83
+ if(empty($eventData)) { $evm = $eventDetails->EventDescription; }
84
+ else { $evm = vsprintf($eventDetails->EventDescription, $eventData); }
85
+ }
86
 
87
  $e = array(
88
  'eventNumber' => $eventNumber,
91
  'eventDate' => $EventDate,
92
  'ip' => $userIP,
93
  'user' => $username,
94
+ 'description' => stripslashes($evm)
95
  );
96
  array_push($out['events'], $e);
97
  }
98
+ $out['eventsCount'] = $eventsCount;
99
 
100
+ exit(__formatJsonOutput($out));
101
  }
102
 
103
  }
inc/wpphFunctions.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // #!-- BEGIN PAGE
3
+ //======================================================================================================================
4
+
5
+ // 2018
6
+ function wpph_pageUrlUpdated($oldUrl, $newUrl, $userID, $postTitle)
7
+ {
8
+ if($oldUrl == $newUrl) { return false; }
9
+
10
+ WPPHEvent::_addLogEvent(2018, $userID, WPPHUtil::getIP(), array($postTitle, $oldUrl, $newUrl));
11
+ wpphLog('Page URL updated.', array('from' => $oldUrl,'to' => $newUrl));
12
+ return true;
13
+ }
14
+
15
+ // 2020
16
+ function wpph_pageAuthorUpdated($newAuthorID, $postID, $userID, $postTitle, $quickFormEnabled = false)
17
+ {
18
+ global $wpdb;
19
+ $oldAuthorID = $wpdb->get_var("SELECT post_author FROM ".$wpdb->posts." WHERE ID = ".$postID);
20
+ if($newAuthorID <> $oldAuthorID){
21
+ $n = $wpdb->get_var("SELECT user_login FROM ".$wpdb->users." WHERE ID = ".$newAuthorID);
22
+ $o = $wpdb->get_var("SELECT user_login FROM ".$wpdb->users." WHERE ID = ".$oldAuthorID);
23
+
24
+ if($quickFormEnabled){
25
+ // in quick edit form the authors get switched whereas in the default post editor they don't :/
26
+ $t = $n;
27
+ $n = $o;
28
+ $o = $t;
29
+ }
30
+
31
+ WPPHEvent::_addLogEvent(2020, $userID, WPPHUtil::getIP(), array($postTitle,$n,$o));
32
+ wpphLog(__FUNCTION__.' : Page author updated.', array('from'=>$o, 'to'=>$n));
33
+ return true;
34
+ }
35
+ return false;
36
+ }
37
+
38
+ // 2004
39
+ function wpph_newPageAsDraft($userID, $postID, $postTitle)
40
+ {
41
+ WPPHEvent::_addLogEvent(2004, $userID, WPPHUtil::getIP(), array($postTitle,$postID));
42
+ wpphLog(__FUNCTION__.' : New page saved as draft.', array('title'=>$postTitle));
43
+ }
44
+
45
+ // 2005
46
+ function wpph_newPagePublished($userID, $postTitle, $postUrl)
47
+ {
48
+ WPPHEvent::_addLogEvent(2005, $userID, WPPHUtil::getIP(), array($postTitle,$postUrl));
49
+ wpphLog(__FUNCTION__.' : Page published.', array('title'=>$postTitle));
50
+ }
51
+
52
+ // 2007
53
+ function wpph_draftPageUpdated($userID, $postID, $postTitle)
54
+ {
55
+ WPPHEvent::_addLogEvent(2007, $userID, WPPHUtil::getIP(), array($postTitle,$postID));
56
+ wpphLog(__FUNCTION__.' : Draft page updated.', array('title'=>$postTitle));
57
+ }
58
+
59
+ // 2006
60
+ function wpph_publishedPageUpdated($userID, $postTitle, $postUrl)
61
+ {
62
+ WPPHEvent::_addLogEvent(2006, $userID, WPPHUtil::getIP(), array($postTitle,$postUrl));
63
+ wpphLog(__FUNCTION__.' : Published page updated.', array('title'=>$postTitle));
64
+ }
65
+
66
+ // 2022
67
+ function wpph_pageStatusUpdated($fromStatus, $toStatus, $userID, $postTitle)
68
+ {
69
+ WPPHEvent::_addLogEvent(2022, $userID, WPPHUtil::getIP(), array($postTitle, $fromStatus, $toStatus));
70
+ wpphLog(__FUNCTION__.' : Page status updated.', array('title'=>$postTitle, 'from' => $fromStatus, 'to' => $toStatus));
71
+ }
72
+
73
+ // #!-- END PAGE
74
+ //======================================================================================================================
75
+
76
+
77
+ // #!-- BEGIN POSTS
78
+ //======================================================================================================================
79
+
80
+ // 2017
81
+ function wpph_postUrlUpdated($oldUrl, $newUrl, $userID, $postTitle)
82
+ {
83
+ if($oldUrl == $newUrl) { return false; }
84
+
85
+ WPPHEvent::_addLogEvent(2017, $userID, WPPHUtil::getIP(), array($postTitle, $oldUrl, $newUrl));
86
+ wpphLog(__FUNCTION__.' : Blog post URL updated.', array('from' => $oldUrl,'to' => $newUrl));
87
+ return true;
88
+ }
89
+
90
+ // 2019
91
+ function wpph_postAuthorUpdated($newAuthorID, $postID, $userID, $postTitle, $quickFormEnabled = false)
92
+ {
93
+ global $wpdb;
94
+ $oldAuthorID = $wpdb->get_var("SELECT post_author FROM ".$wpdb->posts." WHERE ID = ".$postID);
95
+ if($newAuthorID <> $oldAuthorID){
96
+ $n = $wpdb->get_var("SELECT user_login FROM ".$wpdb->users." WHERE ID = ".$newAuthorID);
97
+ $o = $wpdb->get_var("SELECT user_login FROM ".$wpdb->users." WHERE ID = ".$oldAuthorID);
98
+
99
+ if($quickFormEnabled){
100
+ // in quick edit form the authors get switched whereas in the default post editor they don't :/
101
+ $t = $n;
102
+ $n = $o;
103
+ $o = $t;
104
+ }
105
+
106
+ WPPHEvent::_addLogEvent(2019, $userID, WPPHUtil::getIP(), array($postTitle,$n,$o));
107
+ wpphLog(__FUNCTION__.' : Blog post author updated.', array('from'=>$o, 'to'=>$n));
108
+ return true;
109
+ }
110
+ return false;
111
+ }
112
+
113
+ // 2016
114
+ function wpph_postCategoriesUpdated($userID, $postTitle, $fromCategories, $toCategories)
115
+ {
116
+ WPPHEvent::_addLogEvent(2016, $userID, WPPHUtil::getIP(), array($postTitle, $fromCategories, $toCategories));
117
+ wpphLog(__FUNCTION__.' : Blog post categories updated.', array('from'=>$fromCategories, 'to'=>$toCategories));
118
+ }
119
+
120
+ // 2000
121
+ function wpph_newPostAsDraft($userID, $postID, $postTitle)
122
+ {
123
+ WPPHEvent::_addLogEvent(2000, $userID, WPPHUtil::getIP(), array($postTitle,$postID));
124
+ wpphLog(__FUNCTION__.' : New blog post saved as draft.', array('title'=>$postTitle));
125
+ }
126
+
127
+ // 2003
128
+ function wpph_draftPostUpdated($userID, $postID, $postTitle)
129
+ {
130
+ WPPHEvent::_addLogEvent(2003, $userID, WPPHUtil::getIP(), array($postTitle,$postID));
131
+ wpphLog(__FUNCTION__.' : Draft blog post updated.', array('title'=>$postTitle));
132
+ }
133
+
134
+ // 2001
135
+ function wpph_newPostPublished($userID, $postTitle, $postUrl)
136
+ {
137
+ WPPHEvent::_addLogEvent(2001, $userID, WPPHUtil::getIP(), array($postTitle,$postUrl));
138
+ wpphLog(__FUNCTION__.' : Blog post published.', array('title'=>$postTitle));
139
+ }
140
+
141
+ // 2002
142
+ function wpph_publishedPostUpdated($userID, $postTitle, $postUrl)
143
+ {
144
+ WPPHEvent::_addLogEvent(2002, $userID, WPPHUtil::getIP(), array($postTitle,$postUrl));
145
+ wpphLog(__FUNCTION__.' : Published blog post updated.', array('title'=>$postTitle));
146
+ }
147
+
148
+ // 2021
149
+ function wpph_postStatusUpdated($fromStatus, $toStatus, $userID, $postTitle)
150
+ {
151
+ WPPHEvent::_addLogEvent(2021, $userID, WPPHUtil::getIP(), array($postTitle, $fromStatus, $toStatus));
152
+ wpphLog(__FUNCTION__.' : Post status updated.', array('title'=>$postTitle, 'from' => $fromStatus, 'to' => $toStatus));
153
+ }
154
+
155
+ // #!-- END POSTS
156
+ //======================================================================================================================
157
+
158
+ // handle author change in quick edit form
159
+ function wpph_managePostAuthorUpdateQuickEditForm($data, $postArray)
160
+ {
161
+ if($data['post_type'] == 'post'){
162
+ wpph_postAuthorUpdated($GLOBALS['WPPH_POST_AUTHOR_UPDATED'], $postArray['ID'], wp_get_current_user()->ID, $data['post_title'], true);
163
+ }
164
+ elseif($data['post_type'] == 'page'){
165
+ wpph_pageAuthorUpdated($GLOBALS['WPPH_POST_AUTHOR_UPDATED'], $postArray['ID'], wp_get_current_user()->ID, $data['post_title'], true);
166
+ }
167
+ return $data;
168
+ }
pages/about.php CHANGED
@@ -1,12 +1,22 @@
1
- <?php /**
2
- * @kyos
3
- * About us page
4
- */ if(! WPPH::canRun()){ return; } ?>
 
 
 
 
 
 
 
 
 
 
5
  <div id="wpph-pageWrapper" class="wrap">
6
  <h2 class="pageTitle pageTitle-about"><?php echo __('About us');?></h2>
7
  <div>
8
  <p><?php echo sprintf(
9
  __('WP Security Audit Log is a WordPress security plugin developed by %s.'),
10
- '<a href="http://www.wpprohelp.com">WPProHelp.com</a>');?></p>
11
  </div>
12
  </div>
1
+ <?php if(! WPPH::canRun()){ return; } ?>
2
+ <?php
3
+ if(! WPPH::ready())
4
+ {
5
+ $errors = WPPH::getPLuginErrors();
6
+ foreach($errors as $k =>$v) { call_user_func(array('WPPHAdminNotices',$k),$v); }
7
+
8
+ echo '<div id="wpph-pageWrapper" class="wrap">';
9
+ echo '<p>We have encountered some errors during the installation of the plugin which you can find above.</p>';
10
+ echo '<p>Please try to correct them and then reactivate the plugin.</p>';
11
+ echo '</div>';
12
+ return;
13
+ }
14
+ ?>
15
  <div id="wpph-pageWrapper" class="wrap">
16
  <h2 class="pageTitle pageTitle-about"><?php echo __('About us');?></h2>
17
  <div>
18
  <p><?php echo sprintf(
19
  __('WP Security Audit Log is a WordPress security plugin developed by %s.'),
20
+ '<a href="http://www.wpwhitesecurity.com">WP White Security</a>');?></p>
21
  </div>
22
  </div>
pages/dashboard.php CHANGED
@@ -1,7 +1,18 @@
1
- <?php /**
2
- * @kyos
3
- * Dashboard page
4
- */ if(! WPPH::canRun()){ return; }?>
 
 
 
 
 
 
 
 
 
 
 
5
  <div id="wpph-pageWrapper" class="wrap">
6
  <h2 class="pageTitle pageTitle-eventViewer"><?php echo __('Audit Log Viewer');?></h2>
7
  <div id="EventViewerWrapper">
@@ -19,15 +30,19 @@
19
  <select name="actionLimit1" class="actionLimit" data-bind="options: availablePageSize, value: selectedPageSize"></select>
20
  <input type="button" value="Apply" class="button action" data-bind="disable: loading, click: applyPageSize">
21
  </div>
22
- <div class="paginationWrapper" data-bind="visible: totalEventsCount">
23
- <span class="showPages"><span class="span1" data-bind="text: totalEventsCount() > 0 ? 1 + offset() : 0"></span>-
24
- <span class="span2" data-bind="text: offset() + events().length"></span> <?php echo __('of');?>
25
- <span class="span3" data-bind="text: totalEventsCount"></span></span>
26
- <div class="buttonsWrapper">
27
- <button class="pageButton buttonNext" title="Next" href="#" data-bind="disable: loading, click: nextPage, css: {wpphButtonDisabled: offset() + events().length >= totalEventsCount() - 1}"><span>&gt;</span></button>
28
- <button class="pageButton buttonPrevious" title="Previous" href="#" data-bind="disable: loading, click: prevPage, css: {wpphButtonDisabled: offset() <= 0}"><span>&lt;</span></button>
29
- </div>
 
 
 
30
  </div>
 
31
  </div>
32
  </div>
33
  <table class="wp-list-table widefat fixed" cellspacing="0" cellpadding="0">
@@ -82,14 +97,16 @@
82
  <select name="actionLimit1" class="actionLimit" data-bind="options: availablePageSize, value: selectedPageSize"></select>
83
  <input type="button" value="Apply" class="button action" data-bind="disable: loading, click: applyPageSize">
84
  </div>
85
- <div class="paginationWrapper" data-bind="visible: totalEventsCount">
86
- <span class="showPages"><span class="span1" data-bind="text: totalEventsCount() > 0 ? 1 + offset() : 0"></span>-
87
- <span class="span2" data-bind="text: offset() + events().length"></span> <?php echo __('of');?>
88
- <span class="span3" data-bind="text: totalEventsCount"></span></span>
89
- <div class="buttonsWrapper">
90
- <button class="pageButton buttonNext" title="<?php echo __('Next');?>" href="#" data-bind="disable: loading, click: nextPage, css: {wpphButtonDisabled: offset() >= totalEventsCount() - 1}"><span>&gt;</span></button>
91
- <button class="pageButton buttonPrevious" title="<?php echo __('Previous');?>" href="#" data-bind="disable: loading, click: prevPage, css: {wpphButtonDisabled: offset() <= 0}"><span>&lt;</span></button>
92
- </div>
 
 
93
  </div>
94
  </div>
95
  </div>
1
+ <?php if(! WPPH::canRun()){ return; } ?>
2
+ <?php
3
+ if(! WPPH::ready())
4
+ {
5
+ $errors = WPPH::getPLuginErrors();
6
+ foreach($errors as $k =>$v) { call_user_func(array('WPPHAdminNotices',$k),$v); }
7
+
8
+ echo '<div id="wpph-pageWrapper" class="wrap">';
9
+ echo '<p>We have encountered some errors during the installation of the plugin which you can find above.</p>';
10
+ echo '<p>Please try to correct them and then reactivate the plugin.</p>';
11
+ echo '</div>';
12
+ return;
13
+ }
14
+ ?>
15
+
16
  <div id="wpph-pageWrapper" class="wrap">
17
  <h2 class="pageTitle pageTitle-eventViewer"><?php echo __('Audit Log Viewer');?></h2>
18
  <div id="EventViewerWrapper">
30
  <select name="actionLimit1" class="actionLimit" data-bind="options: availablePageSize, value: selectedPageSize"></select>
31
  <input type="button" value="Apply" class="button action" data-bind="disable: loading, click: applyPageSize">
32
  </div>
33
+
34
+ <div class="tablenav-pages">
35
+ <span class="displaying-num" data-bind="text: totalEventsCount()+' events'"></span>
36
+ <span class="pagination-links"><a href="#" title="Go to the first page" class="first-page" data-bind="click: firstPage, css: {disabled: offset() <= 0}">«</a>
37
+ <a href="#" title="Go to the previous page" class="prev-page" data-bind="click: prevPage, disable: loading, click: prevPage, css: {disabled: offset() <= 0}">‹</a>
38
+ <span class="paging-input">
39
+ <input type="text" size="1" id="fdr" title="Current page" class="current-page"
40
+ data-bind="value: currentPage, event: {keydown: onCurrentPageInputKeyDown} "/> of <span class="total-pages" data-bind="text: pageCount"></span>
41
+ </span>
42
+ <a href="#" title="Go to the next page" class="next-page" data-bind="click: nextPage, disable: loading, click: nextPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">›</a>
43
+ <a href="#" title="Go to the last page" class="last-page" data-bind="click: lastPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">»</a></span>
44
  </div>
45
+
46
  </div>
47
  </div>
48
  <table class="wp-list-table widefat fixed" cellspacing="0" cellpadding="0">
97
  <select name="actionLimit1" class="actionLimit" data-bind="options: availablePageSize, value: selectedPageSize"></select>
98
  <input type="button" value="Apply" class="button action" data-bind="disable: loading, click: applyPageSize">
99
  </div>
100
+ <div class="tablenav-pages">
101
+ <span class="displaying-num" data-bind="text: totalEventsCount()+' events'"></span>
102
+ <span class="pagination-links"><a href="#" title="Go to the first page" class="first-page" data-bind="click: firstPage, css: {disabled: offset() <= 0}">«</a>
103
+ <a href="#" title="Go to the previous page" class="prev-page" data-bind="click: prevPage, disable: loading, click: prevPage, css: {disabled: offset() <= 0}">‹</a>
104
+ <span class="paging-input">
105
+ <input type="text" size="1" id="fdr" title="Current page" class="current-page"
106
+ data-bind="value: currentPage, event: {keydown: onCurrentPageInputKeyDown} "/> of <span class="total-pages" data-bind="text: pageCount"></span>
107
+ </span>
108
+ <a href="#" title="Go to the next page" class="next-page" data-bind="click: nextPage, disable: loading, click: nextPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">›</a>
109
+ <a href="#" title="Go to the last page" class="last-page" data-bind="click: lastPage, css: {disabled: offset() + events().length >= totalEventsCount() - 1}">»</a></span>
110
  </div>
111
  </div>
112
  </div>
pages/settings.php CHANGED
@@ -1,7 +1,18 @@
1
- <?php /**
2
- * @kyos
3
- * Options page
4
- */if(! WPPH::canRun()){ return; }
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  //#! defaults
7
  $opt = WPPH::getPluginSettings();
1
+ <?php if(! WPPH::canRun()){ return; } ?>
2
+ <?php
3
+ if(! WPPH::ready())
4
+ {
5
+ $errors = WPPH::getPLuginErrors();
6
+ foreach($errors as $k =>$v) { call_user_func(array('WPPHAdminNotices',$k),$v); }
7
+
8
+ echo '<div id="wpph-pageWrapper" class="wrap">';
9
+ echo '<p>We have encountered some errors during the installation of the plugin which you can find above.</p>';
10
+ echo '<p>Please try to correct them and then reactivate the plugin.</p>';
11
+ echo '</div>';
12
+ return;
13
+ }
14
+ ?>
15
+ <?php
16
 
17
  //#! defaults
18
  $opt = WPPH::getPluginSettings();
pages/support.php CHANGED
@@ -1,12 +1,23 @@
1
- <?php /**
2
- * @kyos
3
- * Support page
4
- */ if(! WPPH::canRun()){ return; } ?>
 
 
 
 
 
 
 
 
 
 
 
5
  <div id="wpph-pageWrapper" class="wrap">
6
  <h2 class="pageTitle pageTitle-support"><?php echo __('Support');?></h2>
7
  <div>
8
  <p><?php echo
9
- sprintf(__('If you encounter any issues running this plugin, or have suggestions, please get in touch with us on %s.'),
10
- '<a href="mailto:plugins@wpprohelp.com">plugins@wpprohelp.com</a>');?></p>
11
  </div>
12
  </div>
1
+
2
+ <?php if(! WPPH::canRun()){ return; } ?>
3
+ <?php
4
+ if(! WPPH::ready())
5
+ {
6
+ $errors = WPPH::getPLuginErrors();
7
+ foreach($errors as $k =>$v) { call_user_func(array('WPPHAdminNotices',$k),$v); }
8
+
9
+ echo '<div id="wpph-pageWrapper" class="wrap">';
10
+ echo '<p>We have encountered some errors during the installation of the plugin which you can find above.</p>';
11
+ echo '<p>Please try to correct them and then reactivate the plugin.</p>';
12
+ echo '</div>';
13
+ return;
14
+ }
15
+ ?>
16
  <div id="wpph-pageWrapper" class="wrap">
17
  <h2 class="pageTitle pageTitle-support"><?php echo __('Support');?></h2>
18
  <div>
19
  <p><?php echo
20
+ sprintf(__('Thank you for showing interest and using our plugin. If you encounter any issues running this plugin, or have suggestions or queries, please get in touch with us on %s.'),
21
+ '<a href="mailto:plugins@wpwhitesecurity.com">plugins@wpwhitesecurity.com</a>');?></p>
22
  </div>
23
  </div>
readme.txt CHANGED
@@ -2,10 +2,10 @@
2
  Contributors: WPProHelp, WPWhiteSecurity
3
  License: GPLv3
4
  License URI: http://www.gnu.org/licenses/gpl.html
5
- Tags: wordpress security plugin, wordpress security audit log, audit log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log
6
  Requires at least: 3.0
7
  Tested up to: 3.6
8
- Stable tag: 0.1
9
 
10
  Identify WordPress security issues before they become a problem. Keep an audit log of everything that happens on WordPress
11
 
@@ -15,31 +15,32 @@ Identify WordPress security issues before they become a problem by keeping an au
15
  = Keep A WordPress Security Audit Log & Identify WordPress Security Issues =
16
  WP Security Audit Log keeps track of everything that is happening on your WordPress blog or website. By using this WordPress security plugin it is very easy to track suspicious user activity before it becomes a problem. A security event is generated in each of the below cases:
17
 
18
- * New user is created via registration
19
- * New user is created by another user
20
- * Existing user changes the role of another user
21
- * Existing user changes the password of another user
22
- * User uploads a file
23
- * User changes the password
24
- * A user changes the password of another user
25
  * Failed login attempt
26
  * and much more...
27
 
 
 
28
  = Monitor WordPress Users Activity & Productivity =
29
  If you own a multi user WordPress blog or website you can use the WP Security Audit Log plugin to monitor your users' activity and productivity. With this WordPress security plugin you can monitor:
30
 
31
  * When users logged in or out
32
  * From where users are logging in
 
33
  * Users who created a blog post or a page
34
  * Users who published a blog post or a page
35
  * Users who modified published WordPress content such as a page or a blog post
36
  * and much more...
37
 
 
 
38
  = WordPress Audit Log in your Language! =
39
  We need help translating the plugin and the WordPress Security Events. If you're good at translating, please drop us an email on plugins@wpwhitesecurity.com.
40
 
41
  = WordPress Security Tips & Tricks =
42
- 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. WPWhiteSecurity.com frequently publishes WordPress security tips & tricks on the [WordPress Security section](http://www.wpwhitesecurity.com/wordpress-security/) of their blog.
43
 
44
 
45
  = Further Reading =
@@ -57,17 +58,35 @@ For more information and to get started with WordPress Security, check out the f
57
 
58
  == Frequently Asked Questions ==
59
 
60
- = What can I do to prune security events? =
61
 
62
  By default the plugin will keep up to 10,000 events. When this limit is reached, older events are deleted to make place for the new ones. You can configure the plugin to keep more events from the settings page. You can also configure the plugin to delete events which are older than a number of days.
63
 
 
 
 
64
  == Screenshots ==
65
 
66
  1. The Audit Log Viewer from where the WordPress administrator can see all the security events generated by WP Security Audit Log WordPress plugin.
67
  2. The Auto Prune Security Events settings which the WordPress administrator can configure the auto deletion of security events.
68
-
69
  == Changelog ==
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  = 0.1 =
72
 
73
  * Initial beta release of WP Security Audit Log.
2
  Contributors: WPProHelp, WPWhiteSecurity
3
  License: GPLv3
4
  License URI: http://www.gnu.org/licenses/gpl.html
5
+ Tags: wordpress security plugin, wordpress security audit log, audit log, event log wordpress, wordpress user tracking, wordpress activity log, wordpress audit, security event log, audit trail, security audit trail
6
  Requires at least: 3.0
7
  Tested up to: 3.6
8
+ Stable tag: 0.2
9
 
10
  Identify WordPress security issues before they become a problem. Keep an audit log of everything that happens on WordPress
11
 
15
  = Keep A WordPress Security Audit Log & Identify WordPress Security Issues =
16
  WP Security Audit Log keeps track of everything that is happening on your WordPress blog or website. By using this WordPress security plugin it is very easy to track suspicious user activity before it becomes a problem. A security event is generated in each of the below cases:
17
 
18
+ * New user is created via registration or created by another user
19
+ * Existing user changes the role or password of another user
20
+ * User uploads a file, changes a password or email
 
 
 
 
21
  * Failed login attempt
22
  * and much more...
23
 
24
+ Refer to the complete list of [WordPress Security Audit Events](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-event-logs/) for more information.
25
+
26
  = Monitor WordPress Users Activity & Productivity =
27
  If you own a multi user WordPress blog or website you can use the WP Security Audit Log plugin to monitor your users' activity and productivity. With this WordPress security plugin you can monitor:
28
 
29
  * When users logged in or out
30
  * From where users are logging in
31
+ * Users who created or deleted categories
32
  * Users who created a blog post or a page
33
  * Users who published a blog post or a page
34
  * Users who modified published WordPress content such as a page or a blog post
35
  * and much more...
36
 
37
+ Refer to the complete list of [WordPress Security Audit Events](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-event-logs/) for more information.
38
+
39
  = WordPress Audit Log in your Language! =
40
  We need help translating the plugin and the WordPress Security Events. If you're good at translating, please drop us an email on plugins@wpwhitesecurity.com.
41
 
42
  = WordPress Security Tips & Tricks =
43
+ 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.
44
 
45
 
46
  = Further Reading =
58
 
59
  == Frequently Asked Questions ==
60
 
61
+ = How can I prune WordPress security events? =
62
 
63
  By default the plugin will keep up to 10,000 events. When this limit is reached, older events are deleted to make place for the new ones. You can configure the plugin to keep more events from the settings page. You can also configure the plugin to delete events which are older than a number of days.
64
 
65
+ = Is there a complete list of all WordPress security audit events? =
66
+ Yes. A complete list can be found [here](http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/security-audit-event-logs/)
67
+
68
  == Screenshots ==
69
 
70
  1. The Audit Log Viewer from where the WordPress administrator can see all the security events generated by WP Security Audit Log WordPress plugin.
71
  2. The Auto Prune Security Events settings which the WordPress administrator can configure the auto deletion of security events.
72
+
73
  == Changelog ==
74
 
75
+ = 0.2 =
76
+
77
+ * Restricted plugin options and WordPress Audit Log Event Viewer only to WordPress administrators
78
+ * Improved failed logins events (events generated from the same IP, or same username will be grouped to avoid mass flooding of security events)
79
+ * Security Events pruning now uses wp-cron functionality (improved stability and reliability of events pruning)
80
+ * Applied several performance improvements (faster loading of events etc)
81
+ * Added support for permalinks; now events will include page or blog post URL rather than ID
82
+ * Added new alerts for when a page or blog post status is changed from draft, pending review or published
83
+ * Added new alert for when a page or blog post URL or author is changed
84
+ * Added new alert for when a blog post category is changed
85
+ * Added new alerts for when a user creates or deletes a category
86
+ * Added new alert for when the author of a blog post or page is changed
87
+ * Added new plugin alerts for when a plugin is installed, uninstalled or upgraded
88
+ * Updated navigation menu to use standard WordPress dashboard icons etc
89
+
90
  = 0.1 =
91
 
92
  * Initial beta release of WP Security Audit Log.
res/js/{AuditLogViewModel.js → audit-view-model.js} RENAMED
@@ -39,6 +39,12 @@ var AuditLogViewModel = (function($) {
39
  if (viewModel.totalEventsCount() < viewModel.offset()) {
40
  viewModel.offset(0);
41
  }
 
 
 
 
 
 
42
  },
43
  error: function() {
44
  viewModel.loading(false);
@@ -53,7 +59,7 @@ var AuditLogViewModel = (function($) {
53
  {columnHeader: 'ID', columnName: 'EventID', sortable: true, columnWidth: '80px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
54
  {columnHeader: 'Date', columnName: 'EventDate', sortable: true, columnWidth: '170px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
55
  {columnHeader: 'Type', columnName: 'EventType', sortable: true, columnWidth: '100px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
56
- {columnHeader: 'IP Address', columnName: 'UserIP', sortable: true, columnWidth: '100px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
57
  {columnHeader: 'User', columnName: 'UserID', sortable: true, columnWidth: '240px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
58
  {columnHeader: 'Description', columnName: 'EventDescription', sortable: false, columnWidth: 'auto', sorted: ko.observable(false), sortedDescending: ko.observable(false)}]);
59
 
@@ -61,11 +67,37 @@ var AuditLogViewModel = (function($) {
61
  this.events = ko.observableArray([]);
62
  this.totalEventsCount = ko.observable(0);
63
  this.offset = ko.observable(0);
 
64
 
65
- this.pageSize = ko.observable(50);
66
- this.selectedPageSize = ko.observable(50);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
- this.availablePageSize = ko.observableArray([25, 50, 100]);
69
  this.orderBy = ko.computed({
70
  read: function() {
71
  var columnInfo = ko.utils.arrayFirst(this.columns(), function(item) { return item.sorted(); })
@@ -84,7 +116,6 @@ var AuditLogViewModel = (function($) {
84
  }
85
  }
86
  }, this);
87
-
88
  this.orderByDescending = ko.computed({
89
  read: function() {
90
  var columnInfo = ko.utils.arrayFirst(this.columns(), function(item) { return item.sorted(); })
@@ -97,8 +128,31 @@ var AuditLogViewModel = (function($) {
97
  }, this);
98
  }
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  AuditLogViewModel.prototype.applyPageSize = function(viewModel){
101
- viewModel.pageSize(parseInt(viewModel.selectedPageSize()));
 
 
 
 
 
 
102
  viewModel.refreshEvents(viewModel, 0);
103
  };
104
 
@@ -131,6 +185,23 @@ var AuditLogViewModel = (function($) {
131
  }
132
  };
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  AuditLogViewModel.prototype.refreshEvents = function(viewModel, offset) {
135
  loadRemoteData(viewModel, offset);
136
  };
39
  if (viewModel.totalEventsCount() < viewModel.offset()) {
40
  viewModel.offset(0);
41
  }
42
+
43
+ if (viewModel.offset() == 0)
44
+ viewModel.currentPage(1);
45
+ else
46
+ viewModel.currentPage(1 + viewModel.offset() / viewModel.pageSize());
47
+
48
  },
49
  error: function() {
50
  viewModel.loading(false);
59
  {columnHeader: 'ID', columnName: 'EventID', sortable: true, columnWidth: '80px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
60
  {columnHeader: 'Date', columnName: 'EventDate', sortable: true, columnWidth: '170px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
61
  {columnHeader: 'Type', columnName: 'EventType', sortable: true, columnWidth: '100px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
62
+ {columnHeader: 'IP Address', columnName: 'UserIP', sortable: true, columnWidth: '130px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
63
  {columnHeader: 'User', columnName: 'UserID', sortable: true, columnWidth: '240px', sorted: ko.observable(false), sortedDescending: ko.observable(false)},
64
  {columnHeader: 'Description', columnName: 'EventDescription', sortable: false, columnWidth: 'auto', sorted: ko.observable(false), sortedDescending: ko.observable(false)}]);
65
 
67
  this.events = ko.observableArray([]);
68
  this.totalEventsCount = ko.observable(0);
69
  this.offset = ko.observable(0);
70
+ this.availablePageSize = ko.observableArray([25, 50, 100]);
71
 
72
+ var _initialPageSize = parseInt($.cookie('wpph_ck_page_size'));
73
+ if (this.availablePageSize.indexOf(_initialPageSize) < 0) {
74
+ _initialPageSize = this.availablePageSize()[1];
75
+ }
76
+
77
+ this.pageSize = ko.observable(_initialPageSize);
78
+ this.selectedPageSize = ko.observable(_initialPageSize);
79
+ this.pageCount = ko.computed(function() {
80
+ return Math.ceil(this.totalEventsCount() / this.pageSize());
81
+ }, this);
82
+
83
+ this. _currentPageIndex = 1;
84
+ var vm = this;
85
+ this.currentPage = ko.computed({
86
+ read: function() {
87
+ return this._currentPageIndex;
88
+ },
89
+ write: function(value) {
90
+ value = parseInt(value);
91
+ if (isNaN(value) || value < 1 || value > this.pageCount()) {
92
+ return;
93
+ }
94
+ this._currentPageIndex = value;
95
+ this.currentPage.notifySubscribers();
96
+ $('#fdr').val(this._currentPageIndex);
97
+ },
98
+ owner: vm
99
+ });
100
 
 
101
  this.orderBy = ko.computed({
102
  read: function() {
103
  var columnInfo = ko.utils.arrayFirst(this.columns(), function(item) { return item.sorted(); })
116
  }
117
  }
118
  }, this);
 
119
  this.orderByDescending = ko.computed({
120
  read: function() {
121
  var columnInfo = ko.utils.arrayFirst(this.columns(), function(item) { return item.sorted(); })
128
  }, this);
129
  }
130
 
131
+ AuditLogViewModel.prototype.onCurrentPageInputKeyDown = function(viewModel, event) {
132
+ if (event.keyCode === 13) {
133
+ var value = parseInt(event.currentTarget.value);
134
+ if (isNaN(value) || value < 1 || value > viewModel.pageCount()) {
135
+ viewModel.currentPage(viewModel._currentPageIndex);
136
+ viewModel.currentPage.notifySubscribers();
137
+ return;
138
+ }
139
+ viewModel.currentPage(value);
140
+ viewModel.refreshEvents(viewModel, ( viewModel._currentPageIndex - 1) * viewModel.pageSize());
141
+ return false;
142
+ }
143
+ return true;
144
+ };
145
+
146
+
147
+
148
  AuditLogViewModel.prototype.applyPageSize = function(viewModel){
149
+ var newPageSize = parseInt(viewModel.selectedPageSize());
150
+ viewModel.pageSize(newPageSize);
151
+ var secureCookie = false;
152
+ if (window.location.href.indexOf('https://') > -1) {
153
+ secureCookie = true;
154
+ }
155
+ $.cookie('wpph_ck_page_size', newPageSize, {secure: secureCookie});
156
  viewModel.refreshEvents(viewModel, 0);
157
  };
158
 
185
  }
186
  };
187
 
188
+ //TODO
189
+ AuditLogViewModel.prototype.firstPage = function(viewModel) {
190
+ if (viewModel.offset() > 0)
191
+ viewModel.refreshEvents(viewModel, 0);
192
+ };
193
+
194
+ //TODO
195
+ AuditLogViewModel.prototype.lastPage = function(viewModel) {
196
+ var offset = Math.min(
197
+ viewModel.totalEventsCount(),
198
+ viewModel.pageSize() * (viewModel.pageCount() - 1)
199
+ );
200
+ if (viewModel.offset() != offset)
201
+ viewModel.refreshEvents(viewModel, offset);
202
+ };
203
+
204
+
205
  AuditLogViewModel.prototype.refreshEvents = function(viewModel, offset) {
206
  loadRemoteData(viewModel, offset);
207
  };
res/js/jquery-ck.js ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery Cookie Plugin v1.3.1
3
+ * https://github.com/carhartl/jquery-cookie
4
+ *
5
+ * Copyright 2013 Klaus Hartl
6
+ * Released under the MIT license
7
+ */
8
+ (function (factory) {
9
+ if (typeof define === 'function' && define.amd) {
10
+ // AMD. Register as anonymous module.
11
+ define(['jquery'], factory);
12
+ } else {
13
+ // Browser globals.
14
+ factory(jQuery);
15
+ }
16
+ }(function ($) {
17
+
18
+ var pluses = /\+/g;
19
+
20
+ function raw(s) {
21
+ return s;
22
+ }
23
+
24
+ function decoded(s) {
25
+ return decodeURIComponent(s.replace(pluses, ' '));
26
+ }
27
+
28
+ function converted(s) {
29
+ if (s.indexOf('"') === 0) {
30
+ // This is a quoted cookie as according to RFC2068, unescape
31
+ s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
32
+ }
33
+ try {
34
+ return config.json ? JSON.parse(s) : s;
35
+ } catch(er) {}
36
+ }
37
+
38
+ var config = $.cookie = function (key, value, options) {
39
+
40
+ // write
41
+ if (value !== undefined) {
42
+ options = $.extend({}, config.defaults, options);
43
+
44
+ if (typeof options.expires === 'number') {
45
+ var days = options.expires, t = options.expires = new Date();
46
+ t.setDate(t.getDate() + days);
47
+ }
48
+
49
+ value = config.json ? JSON.stringify(value) : String(value);
50
+
51
+ return (document.cookie = [
52
+ config.raw ? key : encodeURIComponent(key),
53
+ '=',
54
+ config.raw ? value : encodeURIComponent(value),
55
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
56
+ options.path ? '; path=' + options.path : '',
57
+ options.domain ? '; domain=' + options.domain : '',
58
+ options.secure ? '; secure' : ''
59
+ ].join(''));
60
+ }
61
+
62
+ // read
63
+ var decode = config.raw ? raw : decoded;
64
+ var cookies = document.cookie.split('; ');
65
+ var result = key ? undefined : {};
66
+ for (var i = 0, l = cookies.length; i < l; i++) {
67
+ var parts = cookies[i].split('=');
68
+ var name = decode(parts.shift());
69
+ var cookie = decode(parts.join('='));
70
+
71
+ if (key && key === name) {
72
+ result = converted(cookie);
73
+ break;
74
+ }
75
+
76
+ if (!key) {
77
+ result[name] = converted(cookie);
78
+ }
79
+ }
80
+
81
+ return result;
82
+ };
83
+
84
+ config.defaults = {};
85
+
86
+ $.removeCookie = function (key, options) {
87
+ if ($.cookie(key) !== undefined) {
88
+ // Must not alter options, thus extending a fresh object...
89
+ $.cookie(key, '', $.extend({}, options, { expires: -1 }));
90
+ return true;
91
+ }
92
+ return false;
93
+ };
94
+
95
+ }));
res/js/{knockout-2.2.1.min.js → knockout.js} RENAMED
File without changes
uninstall.php DELETED
@@ -1,4 +0,0 @@
1
- <?php /**
2
- * @kyos
3
- * Uninstall plugin
4
- */
 
 
 
 
wp-security-audit-log.php CHANGED
@@ -1,12 +1,11 @@
1
  <?php
2
  /*
3
  Plugin Name: WP Security Audit Log
4
- Plugin URI: http://www.wpprohelp.com/wordpress-security-plugins/wp-security-audit-log/
5
  Description: Identify WordPress security issues before they become a problem and keep track of everything happening on your WordPress, including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log will generate an event for every action it logs. Use the Audit Log Viewer to see all the events.
6
- Author: WPProHelp
7
- Contributors: kyos
8
- Version: 0.1
9
- Author URI: http://www.wpprohelp.com/
10
  License: GPL2
11
 
12
  WP Security Audit Log
@@ -26,23 +25,44 @@ License: GPL2
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
  //#! Holds the plugin option name
 
 
 
29
  define('WPPH_PLUGIN_SETTING_NAME', 'wpph_plugin_settings');
30
  define('WPPH_PLUGIN_PREFIX', 'wpph_');
31
  define('WPPH_PLUGIN_NAME', 'WP Security Audit Log');
32
  define('WPPH_PLUGIN_URL', trailingslashit(plugins_url('', __FILE__)));
33
  define('WPPH_PLUGIN_DIR', trailingslashit(plugin_dir_path(__FILE__)));
34
- define('WPPH_PLUGIN_BASE_NAME', basename(__DIR__));
 
 
 
35
 
36
  //#! Load required files
 
37
  require('inc/WPPHLogger.php');
38
  require('inc/WPPHUtil.php');
39
  require('inc/WPPHAdminNotices.php');
40
  require('inc/WPPHDatabase.php');
41
  require('inc/WPPHEvent.php');
42
  require('inc/WPPH.php');
 
43
 
44
- //#! Create tables
45
- register_activation_hook( __FILE__, array('WPPHDatabase', 'checkTables') );
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  //#! Load resources
48
  add_action('admin_init', array('WPPH', 'loadBaseResources'));
@@ -50,9 +70,44 @@ add_action('admin_init', array('WPPH', 'loadBaseResources'));
50
  //#! Add the sidebar menu
51
  add_action('admin_menu', array('WPPH', 'createPluginWpSidebar'));
52
 
53
- //#! Bind hooks
54
- WPPHEvent::bindHooks(array('hookLoginEvent','hookLogoutEvent','hookUserRegisterEvent','hookEventsDeletion','hookUserRoleUpdated','hookUserPasswordUpdated','hookUserEmailUpdated','hookLoginFailure','hookUserDeletion','hookWatchPluginActivity','hookWatchBlogActivity','hookFileDeletion','hookFileUploaded','hookFileUploadedDeleted','hookThemeChange','hookTrashPost','hookTrashPage','hookUntrashedPosts','hookUntrashedPages'));
55
-
56
- /* Enable ajax functionality in the settings page */
57
- add_action('wp_ajax_wpph_get_events', array('WPPHUtil','get_events_html'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  //#! End wp-security-audit-log
1
  <?php
2
  /*
3
  Plugin Name: WP Security Audit Log
4
+ Plugin URI: http://www.wpwhitesecurity.com/wordpress-security-plugins/wp-security-audit-log/
5
  Description: Identify WordPress security issues before they become a problem and keep track of everything happening on your WordPress, including WordPress users activity. Similar to Windows Event Log and Linux Syslog, WP Security Audit Log will generate an event for every action it logs. Use the Audit Log Viewer to see all the events.
6
+ Author: WP White Security
7
+ Version: 0.2
8
+ Author URI: http://www.wpwhitesecurity.com/
 
9
  License: GPL2
10
 
11
  WP Security Audit Log
25
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
  */
27
  //#! Holds the plugin option name
28
+ define('WPPH_PLUGIN_VERSION','0.2');
29
+ define('WPPH_PLUGIN_VERSION_OPTION_NAME','WPPH_PLUGIN_VERSION');
30
+ define('WPPH_PLUGIN_ERROR_OPTION_NAME','WPPH_PLUGIN_ERROR');
31
  define('WPPH_PLUGIN_SETTING_NAME', 'wpph_plugin_settings');
32
  define('WPPH_PLUGIN_PREFIX', 'wpph_');
33
  define('WPPH_PLUGIN_NAME', 'WP Security Audit Log');
34
  define('WPPH_PLUGIN_URL', trailingslashit(plugins_url('', __FILE__)));
35
  define('WPPH_PLUGIN_DIR', trailingslashit(plugin_dir_path(__FILE__)));
36
+ if(defined('__DIR__')) { define('WPPH_PLUGIN_BASE_NAME', basename(__DIR__)); }
37
+ else { define('WPPH_PLUGIN_BASE_NAME', basename(dirname(__FILE__))); }
38
+ define('WPPH_PLUGIN_DB_UPDATED', 'WPPH_PLUGIN_DB_UPDATED');
39
+ define('WPPH_PLUGIN_DEL_EVENTS_CRON_TASK_NAME', 'wpph_plugin_delete_events_cron');
40
 
41
  //#! Load required files
42
+ @include_once(ABSPATH.'wp-includes/pluggable.php');
43
  require('inc/WPPHLogger.php');
44
  require('inc/WPPHUtil.php');
45
  require('inc/WPPHAdminNotices.php');
46
  require('inc/WPPHDatabase.php');
47
  require('inc/WPPHEvent.php');
48
  require('inc/WPPH.php');
49
+ require('inc/wpphFunctions.php');
50
 
51
+ /**
52
+ * triggered when the plugin is uninstalled (with option files delete: true)
53
+ */
54
+ function onPluginUninstall()
55
+ {
56
+ if(WPPH::optionExists(WPPH_PLUGIN_DB_UPDATED)){ delete_option(WPPH_PLUGIN_DB_UPDATED); }
57
+ if(WPPH::optionExists(WPPH_PLUGIN_VERSION_OPTION_NAME)){ delete_option(WPPH_PLUGIN_VERSION_OPTION_NAME); }
58
+ global $wpdb;
59
+ $wpdb->query("DROP TABLE IF EXISTS ".WPPHDatabase::getFullTableName('main'));
60
+ $wpdb->query("DROP TABLE IF EXISTS ".WPPHDatabase::getFullTableName('events'));
61
+ }
62
+ //#! register callbacks
63
+ register_activation_hook( __FILE__, array('WPPH', 'onPluginActivate') );
64
+ register_deactivation_hook( __FILE__, array('WPPH', 'onPluginDeactivate') );
65
+ register_uninstall_hook( __FILE__, 'onPluginUninstall' );
66
 
67
  //#! Load resources
68
  add_action('admin_init', array('WPPH', 'loadBaseResources'));
70
  //#! Add the sidebar menu
71
  add_action('admin_menu', array('WPPH', 'createPluginWpSidebar'));
72
 
73
+ //#! Plugin init
74
+ add_action('init', 'wpphPluginInit');
75
+ function wpphPluginInit()
76
+ {
77
+ if(is_admin())
78
+ {
79
+ // WPPHEvent::hookWatchPostStateBefore:
80
+ // # 2016 - post category updated
81
+ // # 2017 - post url updated
82
+ // # 2018 - page url updated
83
+ // # 2019 - post author changed
84
+ if(! empty($_POST['action']) && $_POST['action'] == 'editpost'){ $GLOBALS['WPPH_DEFAULT_EDITOR_ENABLED'] = true; }
85
+ elseif(! empty($_POST['screen']) && $_POST['screen'] == 'edit-post'){ $GLOBALS['WPPH_SCREEN_EDITOR_ENABLED'] = true; }
86
+ elseif(! empty($_POST['screen']) && $_POST['screen'] == 'edit-page'){ $GLOBALS['WPPH_SCREEN_EDITOR_ENABLED'] = true; }
87
+ WPPHEvent::hookWatchPostStateBefore();
88
+ WPPHEvent::hookWatchCategoryAdd();
89
+ WPPHEvent::hookWatchCategoryDelete();
90
+ WPPHEvent::hookFileDeletion();
91
+ WPPHEvent::hookFileUploaded();
92
+ WPPHEvent::hookFileUploadedDeleted();
93
+ WPPHEvent::hookTrashPost();
94
+ WPPHEvent::hookTrashPage();
95
+ WPPHEvent::hookUntrashedPosts();
96
+ WPPHEvent::hookUntrashedPages();
97
+ WPPHEvent::hookThemeChange();
98
+ WPPHEvent::hookUserRoleUpdated();
99
+ WPPHEvent::hookUserPasswordUpdated();
100
+ WPPHEvent::hookUserEmailUpdated();
101
+ WPPHEvent::hookUserDeletion();
102
+ WPPHEvent::hookEventsDeletion();
103
+ WPPHEvent::hookWatchBlogActivity();
104
+ WPPHEvent::hookWatchPluginActivity();
105
+ /* Enable ajax functionality in the dashboard page */
106
+ add_action('wp_ajax_wpph_get_events', array('WPPHUtil','get_events_html'));
107
+ }
108
+ WPPHEvent::hookLoginEvent();
109
+ WPPHEvent::hookLogoutEvent();
110
+ WPPHEvent::hookLoginFailure();
111
+ WPPHEvent::hookUserRegisterEvent();
112
+ }
113
  //#! End wp-security-audit-log