WordPress Backup & Security Plugin – BlogVault - Version 4.54

Version Description

  • Added Support For Multi Table Callbacks
  • Added Firewall Rule Evaluator
  • Added Activity Logs feature
  • Minor Improvements
Download this release

Release Info

Developer ritesh.soni36
Plugin Icon 128x128 WordPress Backup & Security Plugin – BlogVault
Version 4.54
Comparing to
See all releases

Code changes from version 4.36 to 4.54

account.php CHANGED
@@ -84,6 +84,39 @@ if (!class_exists('BVAccount')) :
84
  return $accountsByPlugname;
85
  }
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  public static function isConfigured($settings) {
88
  $accounts = self::accountsByPlugname($settings);
89
  return (sizeof($accounts) >= 1);
@@ -155,16 +188,22 @@ if (!class_exists('BVAccount')) :
155
  $this->settings->updateOption('bvLastRecvTime', $time);
156
  return 1;
157
  }
158
-
159
  public function updateInfo($info) {
160
  $accounts = self::allAccounts($this->settings);
161
- $plugname = self::getPlugName($this->settings);
 
162
  $pubkey = $info['pubkey'];
163
  if (!array_key_exists($pubkey, $accounts)) {
164
  $accounts[$pubkey] = array();
165
  }
 
 
 
 
166
  $accounts[$pubkey]['lastbackuptime'] = time();
167
  $accounts[$pubkey][$plugname] = true;
 
168
  $accounts[$pubkey]['url'] = $info['url'];
169
  $accounts[$pubkey]['email'] = $info['email'];
170
  self::update($this->settings, $accounts);
@@ -180,6 +219,28 @@ if (!class_exists('BVAccount')) :
180
  return false;
181
  }
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  public static function exists($settings, $pubkey) {
184
  $accounts = self::allAccounts($settings);
185
  return array_key_exists($pubkey, $accounts);
84
  return $accountsByPlugname;
85
  }
86
 
87
+ public static function accountsByType($settings, $account_type) {
88
+ $accounts = self::allAccounts($settings);
89
+ $accounts_by_type = array();
90
+ foreach ($accounts as $pubkey => $value) {
91
+ if (array_key_exists('account_type', $value) && $value['account_type'] === $account_type) {
92
+ $accounts_by_type[$pubkey] = $value;
93
+ }
94
+ }
95
+ return $accounts_by_type;
96
+ }
97
+
98
+ public static function accountsByGid($settings, $account_gid) {
99
+ $accounts = self::allAccounts($settings);
100
+ $accounts_by_gid = array();
101
+ foreach ($accounts as $pubkey => $value) {
102
+ if (array_key_exists('account_gid', $value) && $value['account_gid'] === $account_gid) {
103
+ $accounts_by_gid[$pubkey] = $value;
104
+ }
105
+ }
106
+ return $accounts_by_gid;
107
+ }
108
+
109
+ public static function accountsByPattern($settings, $search_key, $search_pattern) {
110
+ $accounts = self::allAccounts($settings);
111
+ $accounts_by_pattern = array();
112
+ foreach ($accounts as $pubkey => $value) {
113
+ if (array_key_exists($search_key, $value) && preg_match($search_pattern, $value[$search_key]) == 1) {
114
+ $accounts_by_pattern[$pubkey] = $value;
115
+ }
116
+ }
117
+ return $accounts_by_pattern;
118
+ }
119
+
120
  public static function isConfigured($settings) {
121
  $accounts = self::accountsByPlugname($settings);
122
  return (sizeof($accounts) >= 1);
188
  $this->settings->updateOption('bvLastRecvTime', $time);
189
  return 1;
190
  }
191
+
192
  public function updateInfo($info) {
193
  $accounts = self::allAccounts($this->settings);
194
+ $plugname = $info["plugname"];
195
+ $account_type = $info["account_type"];
196
  $pubkey = $info['pubkey'];
197
  if (!array_key_exists($pubkey, $accounts)) {
198
  $accounts[$pubkey] = array();
199
  }
200
+ if (array_key_exists('secret', $info)) {
201
+ $accounts[$pubkey]['secret'] = $info['secret'];
202
+ }
203
+ $accounts[$pubkey]['account_gid'] = $info['account_gid'];
204
  $accounts[$pubkey]['lastbackuptime'] = time();
205
  $accounts[$pubkey][$plugname] = true;
206
+ $accounts[$pubkey]['account_type'] = $account_type;
207
  $accounts[$pubkey]['url'] = $info['url'];
208
  $accounts[$pubkey]['email'] = $info['email'];
209
  self::update($this->settings, $accounts);
219
  return false;
220
  }
221
 
222
+ public static function removeByAccountType($settings, $account_type) {
223
+ $accounts = BVAccount::accountsByType($settings, $account_type);
224
+ if (sizeof($accounts) >= 1) {
225
+ foreach ($accounts as $pubkey => $value) {
226
+ BVAccount::remove($settings, $pubkey);
227
+ }
228
+ return true;
229
+ }
230
+ return false;
231
+ }
232
+
233
+ public static function removeByAccountGid($settings, $account_gid) {
234
+ $accounts = BVAccount::accountsByGid($settings, $account_gid);
235
+ if (sizeof($accounts) >= 1) {
236
+ foreach ($accounts as $pubkey => $value) {
237
+ BVAccount::remove($settings, $pubkey);
238
+ }
239
+ return true;
240
+ }
241
+ return false;
242
+ }
243
+
244
  public static function exists($settings, $pubkey) {
245
  $accounts = self::allAccounts($settings);
246
  return array_key_exists($pubkey, $accounts);
blogvault.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: https://blogvault.net
5
  Description: Easiest way to backup & secure your WordPress site
6
  Author: Backup by BlogVault
7
  Author URI: https://blogvault.net
8
- Version: 4.36
9
  Network: True
10
  */
11
 
@@ -69,6 +69,7 @@ if (is_admin()) {
69
  add_action('admin_head', array($wpadmin, 'removeAdminNotices'), 3);
70
  add_action('admin_notices', array($wpadmin, 'activateWarning'));
71
  ##ADMINENQUEUESCRIPTS##
 
72
  }
73
 
74
 
@@ -130,10 +131,13 @@ if ((array_key_exists('bvplugname', $_REQUEST)) && ($_REQUEST['bvplugname'] == "
130
  $response->terminate($resp);
131
  }
132
  } else {
133
- if ($bvinfo->isProtectModuleEnabled()) {
134
  require_once dirname( __FILE__ ) . '/protect/wp/protect.php';
135
  $bvprotect = new BVProtect($bvdb, $bvsettings);
136
- $bvprotect->run();
 
 
 
137
  }
138
 
139
  if ($bvinfo->isDynSyncModuleEnabled()) {
@@ -142,6 +146,13 @@ if ((array_key_exists('bvplugname', $_REQUEST)) && ($_REQUEST['bvplugname'] == "
142
  $dynsync->init();
143
  }
144
 
 
 
 
 
 
 
 
145
  $bv_site_settings = $bvsettings->getOption('bv_site_settings');
146
  if (isset($bv_site_settings)) {
147
  if (isset($bv_site_settings['wp_auto_updates'])) {
5
  Description: Easiest way to backup & secure your WordPress site
6
  Author: Backup by BlogVault
7
  Author URI: https://blogvault.net
8
+ Version: 4.54
9
  Network: True
10
  */
11
 
69
  add_action('admin_head', array($wpadmin, 'removeAdminNotices'), 3);
70
  add_action('admin_notices', array($wpadmin, 'activateWarning'));
71
  ##ADMINENQUEUESCRIPTS##
72
+ ##REMOVEDEACTIVATIONLINK##
73
  }
74
 
75
 
131
  $response->terminate($resp);
132
  }
133
  } else {
134
+ if ($bvsettings->getOption('bvptplug') === $bvinfo->plugname) {
135
  require_once dirname( __FILE__ ) . '/protect/wp/protect.php';
136
  $bvprotect = new BVProtect($bvdb, $bvsettings);
137
+ $bvprotect->init();
138
+ if ($bvinfo->isActivePlugin() && !(defined( 'WP_CLI' ) && WP_CLI)) {
139
+ $bvprotect->run();
140
+ }
141
  }
142
 
143
  if ($bvinfo->isDynSyncModuleEnabled()) {
146
  $dynsync->init();
147
  }
148
 
149
+ if ($bvinfo->isServiceActive('activity_log')) {
150
+ require_once dirname( __FILE__ ) . '/wp_actlog.php';
151
+ $bvconfig = $bvinfo->config;
152
+ $actlog = new BVWPActLog($bvdb, $bvsettings, $bvinfo, $bvconfig['activity_log']);
153
+ $actlog->init();
154
+ }
155
+
156
  $bv_site_settings = $bvsettings->getOption('bv_site_settings');
157
  if (isset($bv_site_settings)) {
158
  if (isset($bv_site_settings['wp_auto_updates'])) {
callback/handler.php CHANGED
@@ -88,6 +88,10 @@ if (!class_exists('BVCallbackHandler')) :
88
  require_once dirname( __FILE__ ) . '/wings/fs_write.php';
89
  $module = new BVFSWriteCallback();
90
  break;
 
 
 
 
91
  default:
92
  require_once dirname( __FILE__ ) . '/wings/misc.php';
93
  $module = new BVMiscCallback($this);
88
  require_once dirname( __FILE__ ) . '/wings/fs_write.php';
89
  $module = new BVFSWriteCallback();
90
  break;
91
+ case 'actlg':
92
+ require_once dirname( __FILE__ ) . '/wings/actlog.php';
93
+ $module = new BVActLogCallback($this);
94
+ break;
95
  default:
96
  require_once dirname( __FILE__ ) . '/wings/misc.php';
97
  $module = new BVMiscCallback($this);
callback/wings/account.php CHANGED
@@ -24,19 +24,15 @@ class BVAccountCallback extends BVCallbackBase {
24
  $resp = array("status" => BVAccount::remove($this->settings, $params['public']));
25
  break;
26
  case "updt":
27
- $info = array();
28
- $info['email'] = $params['email'];
29
- $info['url'] = $params['url'];
30
- $info['pubkey'] = $params['pubkey'];
31
- $account->updateInfo($info);
32
  $resp = array("status" => BVAccount::exists($this->settings, $params['pubkey']));
33
  break;
34
  case "updtapikey":
35
  BVAccount::updateApiPublicKey($this->settings, $params['pubkey']);
36
  $resp = array("status" => $this->settings->getOption(BVAccount::$api_public_key));
37
  break;
38
- case "rmdefsec":
39
- $resp = array("status" => $settings->deleteOption('bvDefaultSecret'));
40
  break;
41
  case "rmbvkeys":
42
  $resp = array("status" => $settings->deleteOption('bvKeys'));
24
  $resp = array("status" => BVAccount::remove($this->settings, $params['public']));
25
  break;
26
  case "updt":
27
+ $account->updateInfo($params);
 
 
 
 
28
  $resp = array("status" => BVAccount::exists($this->settings, $params['pubkey']));
29
  break;
30
  case "updtapikey":
31
  BVAccount::updateApiPublicKey($this->settings, $params['pubkey']);
32
  $resp = array("status" => $this->settings->getOption(BVAccount::$api_public_key));
33
  break;
34
+ case "rmbvscrt":
35
+ $resp = array("status" => $settings->deleteOption('bvSecretKey'));
36
  break;
37
  case "rmbvkeys":
38
  $resp = array("status" => $settings->deleteOption('bvKeys'));
callback/wings/actlog.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined('ABSPATH')) exit;
4
+ if (!class_exists('BVActLogCallback')) :
5
+
6
+ require_once dirname( __FILE__ ) . '/../../wp_actlog.php';
7
+
8
+ class BVActLogCallback extends BVCallbackBase {
9
+ public $db;
10
+ public $settings;
11
+
12
+ public function __construct($callback_handler) {
13
+ $this->db = $callback_handler->db;
14
+ $this->settings = $callback_handler->settings;
15
+ }
16
+
17
+ public function dropActLogTable() {
18
+ return $this->db->dropBVTable(BVWPActLog::$actlog_table);
19
+ }
20
+
21
+ public function createActLogTable($usedbdelta = false) {
22
+ $db = $this->db;
23
+ $charset_collate = $db->getCharsetCollate();
24
+ $table = $this->db->getBVTable(BVWPActLog::$actlog_table);
25
+ $query = "CREATE TABLE $table (
26
+ id bigint(20) NOT NULL AUTO_INCREMENT,
27
+ site_id int NOT NULL,
28
+ user_id int DEFAULT 0,
29
+ username text DEFAULT '',
30
+ request_id text DEFAULT '',
31
+ ip varchar(20) DEFAULT '',
32
+ event_type varchar(40) NOT NULL DEFAULT '',
33
+ event_data mediumtext NOT NULL,
34
+ time int,
35
+ PRIMARY KEY (id)
36
+ ) $charset_collate;";
37
+ return $db->createTable($query, BVWPActLog::$actlog_table, $usedbdelta);
38
+ }
39
+
40
+ public function process($request) {
41
+ $settings = $this->settings;
42
+ $params = $request->params;
43
+ switch ($request->method) {
44
+ case "truncactlogtable":
45
+ $resp = array("status" => $this->db->truncateBVTable(BVWPActLog::$actlog_table));
46
+ break;
47
+ case "dropactlogtable":
48
+ $resp = array("status" => $this->dropActLogTable());
49
+ break;
50
+ case "createactlogtable":
51
+ $usedbdelta = array_key_exists('usedbdelta', $params);
52
+ $resp = array("status" => $this->createActLogTable($usedbdelta));
53
+ break;
54
+ default:
55
+ $resp = false;
56
+ }
57
+ return $resp;
58
+ }
59
+ }
60
+ endif;
callback/wings/db.php CHANGED
@@ -15,7 +15,6 @@ class BVDBCallback extends BVCallbackBase {
15
  $this->db = $callback_handler->db;
16
  $this->account = $callback_handler->account;
17
  $this->siteinfo = $callback_handler->siteinfo;
18
- $this->bvinfo = $callback_handler->bvinfo;
19
  }
20
 
21
  public function getLastID($pkeys, $end_row) {
@@ -43,7 +42,9 @@ class BVDBCallback extends BVCallbackBase {
43
  $data = array();
44
  $data["offset"] = $offset;
45
  $data["size"] = $srows;
46
- $data["md5"] = md5(serialize($rows));
 
 
47
  array_push($tinfo, $data);
48
  if (!empty($pkeys) && $srows > 0) {
49
  $end_row = end($rows);
@@ -64,13 +65,65 @@ class BVDBCallback extends BVCallbackBase {
64
  return $result;
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  public function process($request) {
68
  $db = $this->db;
69
  $params = $request->params;
70
  $stream_init_info = BVStream::startStream($this->account, $request);
71
 
72
-
73
-
74
  if (array_key_exists('stream', $stream_init_info)) {
75
  $this->stream = $stream_init_info['stream'];
76
  switch ($request->method) {
@@ -101,6 +154,31 @@ class BVDBCallback extends BVCallbackBase {
101
  $table = urldecode($params['table']);
102
  $resp = array("create" => $db->showTableCreate($table));
103
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  case "getrowscount":
105
  $table = urldecode($params['table']);
106
  $resp = array("count" => $db->rowsCount($table));
@@ -175,4 +253,4 @@ class BVDBCallback extends BVCallbackBase {
175
  return $resp;
176
  }
177
  }
178
- endif;
15
  $this->db = $callback_handler->db;
16
  $this->account = $callback_handler->account;
17
  $this->siteinfo = $callback_handler->siteinfo;
 
18
  }
19
 
20
  public function getLastID($pkeys, $end_row) {
42
  $data = array();
43
  $data["offset"] = $offset;
44
  $data["size"] = $srows;
45
+ $serialized_rows = serialize($rows);
46
+ $data['md5'] = md5($serialized_rows);
47
+ $data['length'] = strlen($serialized_rows);
48
  array_push($tinfo, $data);
49
  if (!empty($pkeys) && $srows > 0) {
50
  $end_row = end($rows);
65
  return $result;
66
  }
67
 
68
+ public function getCreateTableQueries($tables) {
69
+ $resp = array();
70
+ foreach($tables as $table) {
71
+ $tname = urldecode($table);
72
+ $resp[$tname] = array("create" => $this->db->showTableCreate($table));
73
+ }
74
+ return $resp;
75
+ }
76
+
77
+ public function checkTables($tables, $type) {
78
+ $resp = array();
79
+ foreach($tables as $table) {
80
+ $tname = urldecode($table);
81
+ $resp[$tname] = array("status" => $this->db->checkTable($table, $type));
82
+ }
83
+ return $resp;
84
+ }
85
+
86
+ public function describeTables($tables) {
87
+ $resp = array();
88
+ foreach($tables as $table) {
89
+ $tname = urldecode($table);
90
+ $resp[$tname] = array("description" => $this->db->describeTable($table));
91
+ }
92
+ return $resp;
93
+ }
94
+
95
+ public function checkTablesExist($tables) {
96
+ $resp = array();
97
+ foreach($tables as $table) {
98
+ $tname = urldecode($table);
99
+ $resp[$tname] = array("tblexists" => $this->db->isTablePresent($table));
100
+ }
101
+ return $resp;
102
+ }
103
+
104
+ public function getTablesRowCount($tables) {
105
+ $resp = array();
106
+ foreach($tables as $table) {
107
+ $tname = urldecode($table);
108
+ $resp[$tname] = array("count" => $this->db->rowsCount($table));
109
+ }
110
+ return $resp;
111
+ }
112
+
113
+ public function getTablesKeys($tables) {
114
+ $resp = array();
115
+ foreach($tables as $table) {
116
+ $tname = urldecode($table);
117
+ $resp[$tname] = array("keys" => $this->db->tableKeys($table));
118
+ }
119
+ return $resp;
120
+ }
121
+
122
  public function process($request) {
123
  $db = $this->db;
124
  $params = $request->params;
125
  $stream_init_info = BVStream::startStream($this->account, $request);
126
 
 
 
127
  if (array_key_exists('stream', $stream_init_info)) {
128
  $this->stream = $stream_init_info['stream'];
129
  switch ($request->method) {
154
  $table = urldecode($params['table']);
155
  $resp = array("create" => $db->showTableCreate($table));
156
  break;
157
+ case "tblskys":
158
+ $tables = $params['tables'];
159
+ $resp = $this->getTablesKeys($tables);
160
+ break;
161
+ case "getmlticrt":
162
+ $tables = $params['tables'];
163
+ $resp = $this->getCreateTableQueries($tables);
164
+ break;
165
+ case "desctbls":
166
+ $tables = $params['tables'];
167
+ $resp = $this->describeTables($tables);
168
+ break;
169
+ case "mltirwscount":
170
+ $tables = $params['tables'];
171
+ $resp = $this->getTablesRowCount($tables);
172
+ break;
173
+ case "chktabls":
174
+ $tables = $params['tables'];
175
+ $type = urldecode($params['type']);
176
+ $resp = $this->checkTables($tables, $type);
177
+ break;
178
+ case "chktablsxist":
179
+ $tables = $params['tables'];
180
+ $resp = $this->checkTablesExist($tables);
181
+ break;
182
  case "getrowscount":
183
  $table = urldecode($params['table']);
184
  $resp = array("count" => $db->rowsCount($table));
253
  return $resp;
254
  }
255
  }
256
+ endif;
callback/wings/fs.php CHANGED
@@ -26,7 +26,7 @@ class BVFSCallback extends BVCallbackBase {
26
  if (is_link($absfile)) {
27
  $fdata["link"] = @readlink($absfile);
28
  }
29
- if ($md5 === true) {
30
  $fdata["md5"] = $this->calculateMd5($absfile, array(), 0, 0, 0);
31
  }
32
  } else {
@@ -196,7 +196,7 @@ class BVFSCallback extends BVCallbackBase {
196
  $result["missingfiles"][] = $file;
197
  continue;
198
  }
199
- if ($md5 === true) {
200
  $fdata["md5"] = $this->calculateMd5($absfile, $fdata, $offset, $limit, $bsize);
201
  }
202
  $result["stats"][] = $fdata;
@@ -245,8 +245,6 @@ class BVFSCallback extends BVCallbackBase {
245
  function process($request) {
246
  $params = $request->params;
247
  $stream_init_info = BVStream::startStream($this->account, $request);
248
-
249
-
250
 
251
  if (array_key_exists('stream', $stream_init_info)) {
252
  $this->stream = $stream_init_info['stream'];
26
  if (is_link($absfile)) {
27
  $fdata["link"] = @readlink($absfile);
28
  }
29
+ if ($md5 === true && !is_dir($absfile)) {
30
  $fdata["md5"] = $this->calculateMd5($absfile, array(), 0, 0, 0);
31
  }
32
  } else {
196
  $result["missingfiles"][] = $file;
197
  continue;
198
  }
199
+ if ($md5 === true && !is_dir($absfile)) {
200
  $fdata["md5"] = $this->calculateMd5($absfile, $fdata, $offset, $limit, $bsize);
201
  }
202
  $result["stats"][] = $fdata;
245
  function process($request) {
246
  $params = $request->params;
247
  $stream_init_info = BVStream::startStream($this->account, $request);
 
 
248
 
249
  if (array_key_exists('stream', $stream_init_info)) {
250
  $this->stream = $stream_init_info['stream'];
callback/wings/fs_write.php CHANGED
@@ -35,7 +35,7 @@ class BVFSWriteCallback extends BVCallbackBase {
35
  return $result;
36
  }
37
 
38
- public function makeDirs($dirs) {
39
  $result = array();
40
 
41
  foreach($dirs as $dir) {
@@ -53,7 +53,7 @@ class BVFSWriteCallback extends BVCallbackBase {
53
 
54
  } else {
55
 
56
- $dir_result['status'] = mkdir($dir);
57
  if ($dir_result['status'] === false) {
58
  $dir_result['error'] = "MKDIR_FAILED";
59
  }
@@ -411,7 +411,7 @@ class BVFSWriteCallback extends BVCallbackBase {
411
  $resp = $this->doChmod($params['pathinfos']);
412
  break;
413
  case "mkdr":
414
- $resp = $this->makeDirs($params['dirs']);
415
  break;
416
  case "rmdr":
417
  $resp = $this->removeDirs($params['dirs']);
35
  return $result;
36
  }
37
 
38
+ public function makeDirs($dirs, $permissions = 0777, $recursive = true) {
39
  $result = array();
40
 
41
  foreach($dirs as $dir) {
53
 
54
  } else {
55
 
56
+ $dir_result['status'] = mkdir($dir, $permissions, $recursive);
57
  if ($dir_result['status'] === false) {
58
  $dir_result['error'] = "MKDIR_FAILED";
59
  }
411
  $resp = $this->doChmod($params['pathinfos']);
412
  break;
413
  case "mkdr":
414
+ $resp = $this->makeDirs($params['dirs'], $params['permissions'], $params['recursive']);
415
  break;
416
  case "rmdr":
417
  $resp = $this->removeDirs($params['dirs']);
callback/wings/info.php CHANGED
@@ -129,6 +129,7 @@ class BVInfoCallback extends BVCallbackBase {
129
  'dbprefix' => $db->dbprefix(),
130
  'wpmu' => $siteinfo->isMultisite(),
131
  'mainsite' => $siteinfo->isMainSite(),
 
132
  'name' => get_bloginfo('name'),
133
  'siteurl' => $siteinfo->siteurl(),
134
  'homeurl' => $siteinfo->homeurl(),
@@ -210,6 +211,7 @@ class BVInfoCallback extends BVCallbackBase {
210
  $data['protect'] = $settings->getOption('bvptconf');
211
  $data['brand'] = $settings->getOption($this->bvinfo->brand_option);
212
  $data['badgeinfo'] = $settings->getOption($this->bvinfo->badgeinfo);
 
213
  }
214
 
215
  public function dbconf(&$info) {
129
  'dbprefix' => $db->dbprefix(),
130
  'wpmu' => $siteinfo->isMultisite(),
131
  'mainsite' => $siteinfo->isMainSite(),
132
+ 'main_site_id' => $siteinfo->getMainSiteId(),
133
  'name' => get_bloginfo('name'),
134
  'siteurl' => $siteinfo->siteurl(),
135
  'homeurl' => $siteinfo->homeurl(),
211
  $data['protect'] = $settings->getOption('bvptconf');
212
  $data['brand'] = $settings->getOption($this->bvinfo->brand_option);
213
  $data['badgeinfo'] = $settings->getOption($this->bvinfo->badgeinfo);
214
+ $data[$this->bvinfo->services_option_name] = $this->bvinfo->config;
215
  }
216
 
217
  public function dbconf(&$info) {
callback/wings/misc.php CHANGED
@@ -8,12 +8,14 @@ class BVMiscCallback extends BVCallbackBase {
8
  public $bvinfo;
9
  public $siteinfo;
10
  public $account;
 
11
 
12
  public function __construct($callback_handler) {
13
  $this->settings = $callback_handler->settings;
14
  $this->siteinfo = $callback_handler->siteinfo;
15
  $this->account = $callback_handler->account;
16
  $this->bvinfo = new BVInfo($callback_handler->settings);
 
17
  }
18
 
19
  public function refreshPluginUpdates() {
@@ -53,6 +55,12 @@ class BVMiscCallback extends BVCallbackBase {
53
  $resp = array_merge($resp, $this->account->info());
54
  $resp = array_merge($resp, $this->bvinfo->info());
55
  break;
 
 
 
 
 
 
56
  case "enablebadge":
57
  $option = $bvinfo->badgeinfo;
58
  $badgeinfo = array();
@@ -94,12 +102,13 @@ class BVMiscCallback extends BVCallbackBase {
94
  case "dlttrsnt":
95
  $resp = array("dlttrsnt" => $settings->deleteTransient($params['key']));
96
  break;
97
- case "setmanulsignup":
98
- $resp = array("setmanulsignup" => $settings->updateOption("bvmanualsignup", true));
99
- break;
100
  case "setbvss":
101
  $resp = array("status" => $settings->updateOption('bv_site_settings', $params['bv_site_settings']));
102
  break;
 
 
 
 
103
  default:
104
  $resp = false;
105
  }
8
  public $bvinfo;
9
  public $siteinfo;
10
  public $account;
11
+ public $bvapi;
12
 
13
  public function __construct($callback_handler) {
14
  $this->settings = $callback_handler->settings;
15
  $this->siteinfo = $callback_handler->siteinfo;
16
  $this->account = $callback_handler->account;
17
  $this->bvinfo = new BVInfo($callback_handler->settings);
18
+ $this->bvapi = new BVWPAPI($callback_handler->settings);
19
  }
20
 
21
  public function refreshPluginUpdates() {
55
  $resp = array_merge($resp, $this->account->info());
56
  $resp = array_merge($resp, $this->bvinfo->info());
57
  break;
58
+ case "pngbv":
59
+ $info = array();
60
+ $this->siteinfo->basic($info);
61
+ $this->bvapi->pingbv('/bvapi/pingbv', $info);
62
+ $resp = array("status" => true);
63
+ break;
64
  case "enablebadge":
65
  $option = $bvinfo->badgeinfo;
66
  $badgeinfo = array();
102
  case "dlttrsnt":
103
  $resp = array("dlttrsnt" => $settings->deleteTransient($params['key']));
104
  break;
 
 
 
105
  case "setbvss":
106
  $resp = array("status" => $settings->updateOption('bv_site_settings', $params['bv_site_settings']));
107
  break;
108
+ case "stsrvcs":
109
+ $settings->updateOption($bvinfo->services_option_name, $params['services']);
110
+ $resp = array("stsrvcs" => $settings->getOption($bvinfo->services_option_name));
111
+ break;
112
  default:
113
  $resp = false;
114
  }
callback/wings/protect.php CHANGED
@@ -76,6 +76,17 @@ class BVProtectCallback extends BVCallbackBase {
76
  $this->settings->updateOption('bvptconf', $params['conf']);
77
  $resp = array('conf' => $this->settings->getOption('bvptconf'));
78
  break;
 
 
 
 
 
 
 
 
 
 
 
79
  case "gtraddr":
80
  $raddr = array_key_exists('REMOTE_ADDR', $_SERVER) ? $_SERVER['REMOTE_ADDR'] : false;
81
  $resp = array("raddr" => $raddr);
76
  $this->settings->updateOption('bvptconf', $params['conf']);
77
  $resp = array('conf' => $this->settings->getOption('bvptconf'));
78
  break;
79
+ case "gtrulcnf":
80
+ $resp = array('conf' => $this->settings->getOption('bvruleset'));
81
+ break;
82
+ case "clrrulcnf":
83
+ $this->settings->deleteOption('bvruleset');
84
+ $resp = array("clearconfig" => true);
85
+ break;
86
+ case "dorulcnf":
87
+ $this->settings->updateOption('bvruleset', $params['conf']);
88
+ $resp = array('conf' => $this->settings->getOption('bvruleset'));
89
+ break;
90
  case "gtraddr":
91
  $raddr = array_key_exists('REMOTE_ADDR', $_SERVER) ? $_SERVER['REMOTE_ADDR'] : false;
92
  $resp = array("raddr" => $raddr);
callback/wings/watch.php CHANGED
@@ -129,6 +129,16 @@ class BVWatchCallback extends BVCallbackBase {
129
  }
130
  }
131
 
 
 
 
 
 
 
 
 
 
 
132
  $resp["status"] = "done";
133
  break;
134
  case "rmdata":
129
  }
130
  }
131
 
132
+ if (array_key_exists('actlog', $params)) {
133
+ require_once dirname( __FILE__ ) . '/../../wp_actlog.php';
134
+ $actlog_params = $params['actlog'];
135
+ $limit = intval(urldecode($actlog_params['limit']));
136
+ $filter = urldecode($actlog_params['filter']);
137
+ $db->deleteBVTableContent(BVWPActLog::$actlog_table, $actlog_params['rmfilter']);
138
+ $table = $db->getBVTable(BVWPActLog::$actlog_table);
139
+ $resp["actlogs"] = $this->getData($table, $limit, $filter);
140
+ }
141
+
142
  $resp["status"] = "done";
143
  break;
144
  case "rmdata":
info.php CHANGED
@@ -4,26 +4,39 @@ if (!defined('ABSPATH')) exit;
4
  if (!class_exists('BVInfo')) :
5
  class BVInfo {
6
  public $settings;
 
7
  public $plugname = 'bvbackup';
8
  public $brandname = 'BlogVault';
9
  public $badgeinfo = 'bvbadge';
10
  public $ip_header_option = 'bvipheader';
11
  public $brand_option = 'bvbrand';
12
- public $version = '4.36';
13
  public $webpage = 'https://blogvault.net';
14
  public $appurl = 'https://app.blogvault.net';
15
  public $slug = 'blogvault-real-time-backup/blogvault.php';
16
  public $plug_redirect = 'bvredirect';
17
  public $logo = '../img/bvlogo.png';
18
  public $brand_icon = '/img/icon.png';
 
19
 
20
  public function __construct($settings) {
21
  $this->settings = $settings;
 
22
  }
23
 
24
- public function isManualSignup() {
25
- $scanOption = $this->settings->getOption('bvmanualsignup');
26
- return (isset($scanOption) && $scanOption == 1);
 
 
 
 
 
 
 
 
 
 
27
  }
28
 
29
  public function getBrandInfo() {
@@ -79,6 +92,14 @@ if (!class_exists('BVInfo')) :
79
  $this->isActivePlugin();
80
  }
81
 
 
 
 
 
 
 
 
 
82
  public function isActivateRedirectSet() {
83
  return ($this->settings->getOption($this->plug_redirect) === 'yes') ? true : false;
84
  }
4
  if (!class_exists('BVInfo')) :
5
  class BVInfo {
6
  public $settings;
7
+ public $config;
8
  public $plugname = 'bvbackup';
9
  public $brandname = 'BlogVault';
10
  public $badgeinfo = 'bvbadge';
11
  public $ip_header_option = 'bvipheader';
12
  public $brand_option = 'bvbrand';
13
+ public $version = '4.54';
14
  public $webpage = 'https://blogvault.net';
15
  public $appurl = 'https://app.blogvault.net';
16
  public $slug = 'blogvault-real-time-backup/blogvault.php';
17
  public $plug_redirect = 'bvredirect';
18
  public $logo = '../img/bvlogo.png';
19
  public $brand_icon = '/img/icon.png';
20
+ public $services_option_name = 'bvconfig';
21
 
22
  public function __construct($settings) {
23
  $this->settings = $settings;
24
+ $this->config = $this->settings->getOption($this->services_option_name);
25
  }
26
 
27
+ public function canSetCWBranding() {
28
+ if (BVWPSiteInfo::isCWServer()) {
29
+
30
+ $bot_protect_accounts = BVAccount::accountsByType($this->settings, 'botprotect');
31
+ if (sizeof($bot_protect_accounts) >= 1)
32
+ return true;
33
+
34
+ $bot_protect_accounts = BVAccount::accountsByPattern($this->settings, 'email', '/@cw_user\.com$/');
35
+ if (sizeof($bot_protect_accounts) >= 1)
36
+ return true;
37
+ }
38
+
39
+ return false;
40
  }
41
 
42
  public function getBrandInfo() {
92
  $this->isActivePlugin();
93
  }
94
 
95
+ public function isServiceActive($service) {
96
+ $bvconfig = $this->config;
97
+ if ($bvconfig && array_key_exists('services', $bvconfig)) {
98
+ return in_array($service, $bvconfig['services']) && $this->isActivePlugin();
99
+ }
100
+ return false;
101
+ }
102
+
103
  public function isActivateRedirectSet() {
104
  return ($this->settings->getOption($this->plug_redirect) === 'yes') ? true : false;
105
  }
protect/fw/config.php CHANGED
@@ -15,6 +15,7 @@ class BVFWConfig {
15
  public $cookiePath;
16
  public $cookieDomain;
17
  public $loggingMode;
 
18
 
19
  public static $requests_table = 'fw_requests';
20
  public static $roleLevels = array(
@@ -36,6 +37,7 @@ class BVFWConfig {
36
  $this->cookieKey = array_key_exists('cookiekey', $confHash) ? $confHash['cookiekey'] : "";
37
  $this->cookiePath = array_key_exists('cookiepath', $confHash) ? $confHash['cookiepath'] : "";
38
  $this->cookieDomain = array_key_exists('cookiedomain', $confHash) ? $confHash['cookiedomain'] : "";
 
39
  }
40
 
41
  #mode
@@ -77,10 +79,9 @@ class BVFWConfig {
77
  const LOGGING_MODE_COMPLETE = 2;
78
  const LOGGING_MODE_DISABLED = 3;
79
 
80
-
81
- #Valid mc_data filenames
82
- public static $validMcDataFilenames = array('mc.conf', 'mc_ips.conf');
83
- public static $validDeletableFiles = array('mc.conf', 'mc_ips.conf', 'malcare-waf.php', 'mc.log', 'mc_data');
84
 
85
  public function isActive() {
86
  return ($this->mode !== BVFWConfig::DISABLED);
@@ -113,5 +114,9 @@ class BVFWConfig {
113
  public function isLoggingDisabled() {
114
  return ($this->loggingMode === BVFWConfig::LOGGING_MODE_DISABLED);
115
  }
 
 
 
 
116
  }
117
  endif;
15
  public $cookiePath;
16
  public $cookieDomain;
17
  public $loggingMode;
18
+ public $rulesMode;
19
 
20
  public static $requests_table = 'fw_requests';
21
  public static $roleLevels = array(
37
  $this->cookieKey = array_key_exists('cookiekey', $confHash) ? $confHash['cookiekey'] : "";
38
  $this->cookiePath = array_key_exists('cookiepath', $confHash) ? $confHash['cookiepath'] : "";
39
  $this->cookieDomain = array_key_exists('cookiedomain', $confHash) ? $confHash['cookiedomain'] : "";
40
+ $this->rulesMode = array_key_exists('rulesmode', $confHash) ? intval($confHash['rulesmode']) : BVFWConfig::DISABLED;
41
  }
42
 
43
  #mode
79
  const LOGGING_MODE_COMPLETE = 2;
80
  const LOGGING_MODE_DISABLED = 3;
81
 
82
+ #Valid mc_data filenames (not used anywhere)
83
+ public static $validMcDataFilenames = array('mc.conf', 'mc_ips.conf', 'mc_rules.json');
84
+ public static $validDeletableFiles = array('mc.conf', 'mc_ips.conf', 'malcare-waf.php', 'mc.log', 'mc_data', 'mc_rules.json');
 
85
 
86
  public function isActive() {
87
  return ($this->mode !== BVFWConfig::DISABLED);
114
  public function isLoggingDisabled() {
115
  return ($this->loggingMode === BVFWConfig::LOGGING_MODE_DISABLED);
116
  }
117
+
118
+ public function isRulesModeEnabled() {
119
+ return ($this->rulesMode === BVFWConfig::PROTECT);
120
+ }
121
  }
122
  endif;
protect/fw/fw.php CHANGED
@@ -3,6 +3,8 @@
3
  if (! (defined('ABSPATH') || defined('MCDATAPATH')) ) exit;
4
  if (!class_exists('BVFW')) :
5
 
 
 
6
  class BVFW {
7
  public $bvinfo;
8
  public $request;
@@ -10,6 +12,9 @@ class BVFW {
10
  public $ipstore;
11
  public $category;
12
  public $logger;
 
 
 
13
 
14
  const SQLIREGEX = '/(?:[^\\w<]|\\/\\*\\![0-9]*|^)(?:
15
  @@HOSTNAME|
@@ -47,12 +52,15 @@ class BVFW {
47
  const BYPASS_COOKIE = "bvfw-bypass-cookie";
48
  const IP_COOKIE = "bvfw-ip-cookie";
49
 
50
- public function __construct($logger, $confHash, $ip, $bvinfo, $ipstore) {
51
  $this->config = new BVFWConfig($confHash);
52
  $this->request = new BVWPRequest($ip);
53
  $this->bvinfo = $bvinfo;
54
  $this->ipstore = $ipstore;
55
  $this->logger = $logger;
 
 
 
56
  }
57
 
58
  public function setcookie($name, $value, $expire) {
@@ -202,18 +210,26 @@ class BVFW {
202
  return false;
203
  }
204
 
 
 
 
 
 
 
 
 
205
  public function execute() {
206
  if ($this->config->canProfileReqInfo()) {
207
  $result = array();
208
 
209
  if ($this->request->getMethod() === 'POST' &&
210
  preg_match('/(admin-ajax.php|admin-post.php)$/', $this->request->getPath())) {
211
- $result += $this->profileRequestInfo(array("action" => $this->request->getBody('action')),
212
  true, 'BODY[');
213
  }
214
- $result += $this->profileRequestInfo($this->request->getBody(),
215
  $this->config->isReqProfilingModeDebug(), 'BODY[');
216
- $result += $this->profileRequestInfo($this->request->getQueryString(),
217
  true, 'GET[');
218
  $result += $this->profileRequestInfo($this->request->getFiles(),
219
  true, 'FILES[');
@@ -226,6 +242,13 @@ class BVFW {
226
  if ($this->isBlacklistedIP()) {
227
  $this->terminateRequest(BVWPRequest::BLACKLISTED);
228
  }
 
 
 
 
 
 
 
229
  }
230
  }
231
 
@@ -258,6 +281,7 @@ class BVFW {
258
  $result = array();
259
  if (is_array($params)) {
260
  foreach ($params as $key => $value) {
 
261
  $key = $prefix . $key;
262
  if (is_array($value)) {
263
  $result = $result + $this->profileRequestInfo($value, $debug, $key . '[', $obraces + 1);
@@ -266,7 +290,7 @@ class BVFW {
266
  $result[$key] = array();
267
  $valsize = $this->getLength($value);
268
  $result[$key]["size"] = $valsize;
269
- if ($debug === true && $valsize < 256) {
270
  $result[$key]["value"] = $value;
271
  continue;
272
  }
@@ -335,13 +359,69 @@ class BVFW {
335
  $result[$key]["file"] = true;
336
  }
337
 
338
- if ($this->matchCount(BVFW::SQLIREGEX, $value) >= 2) {
339
  $result[$key]["sql"] = true;
340
  }
 
 
 
 
 
 
 
 
341
  }
342
  }
343
  }
344
  return $result;
345
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  }
347
  endif;
3
  if (! (defined('ABSPATH') || defined('MCDATAPATH')) ) exit;
4
  if (!class_exists('BVFW')) :
5
 
6
+ require_once dirname( __FILE__ ) . '/rule_evaluator.php';
7
+
8
  class BVFW {
9
  public $bvinfo;
10
  public $request;
12
  public $ipstore;
13
  public $category;
14
  public $logger;
15
+ public $ruleSet;
16
+ public $ruleEvaluator;
17
+ public $break_rule_evaluation;
18
 
19
  const SQLIREGEX = '/(?:[^\\w<]|\\/\\*\\![0-9]*|^)(?:
20
  @@HOSTNAME|
52
  const BYPASS_COOKIE = "bvfw-bypass-cookie";
53
  const IP_COOKIE = "bvfw-ip-cookie";
54
 
55
+ public function __construct($logger, $confHash, $ip, $bvinfo, $ipstore, $ruleSet) {
56
  $this->config = new BVFWConfig($confHash);
57
  $this->request = new BVWPRequest($ip);
58
  $this->bvinfo = $bvinfo;
59
  $this->ipstore = $ipstore;
60
  $this->logger = $logger;
61
+ $this->ruleSet = $ruleSet;
62
+ $this->ruleEvaluator = new BVFWRuleEvaluator($this->request);
63
+ $this->break_rule_evaluation = false;
64
  }
65
 
66
  public function setcookie($name, $value, $expire) {
210
  return false;
211
  }
212
 
213
+ public function canLogValue($key) {
214
+ $skip_keys = array('password' => true, 'passwd' => true, 'pwd' => true);
215
+ if (isset($skip_keys[$key])) {
216
+ return false;
217
+ }
218
+ return true;
219
+ }
220
+
221
  public function execute() {
222
  if ($this->config->canProfileReqInfo()) {
223
  $result = array();
224
 
225
  if ($this->request->getMethod() === 'POST' &&
226
  preg_match('/(admin-ajax.php|admin-post.php)$/', $this->request->getPath())) {
227
+ $result += $this->profileRequestInfo(array("action" => $this->request->getPostParams('action')),
228
  true, 'BODY[');
229
  }
230
+ $result += $this->profileRequestInfo($this->request->getPostParams(),
231
  $this->config->isReqProfilingModeDebug(), 'BODY[');
232
+ $result += $this->profileRequestInfo($this->request->getGetParams(),
233
  true, 'GET[');
234
  $result += $this->profileRequestInfo($this->request->getFiles(),
235
  true, 'FILES[');
242
  if ($this->isBlacklistedIP()) {
243
  $this->terminateRequest(BVWPRequest::BLACKLISTED);
244
  }
245
+ if ($this->config->isRulesModeEnabled()) {
246
+ if ($this->ruleSet) {
247
+ $this->evaluateRules($this->ruleSet);
248
+ } else {
249
+ $this->request->updateRulesInfo('errors', 'ruleset', 'Invalid RuleSet');
250
+ }
251
+ }
252
  }
253
  }
254
 
281
  $result = array();
282
  if (is_array($params)) {
283
  foreach ($params as $key => $value) {
284
+ $original_key = $key;
285
  $key = $prefix . $key;
286
  if (is_array($value)) {
287
  $result = $result + $this->profileRequestInfo($value, $debug, $key . '[', $obraces + 1);
290
  $result[$key] = array();
291
  $valsize = $this->getLength($value);
292
  $result[$key]["size"] = $valsize;
293
+ if ($debug === true && $valsize < 256 && $this->canLogValue($original_key)) {
294
  $result[$key]["value"] = $value;
295
  continue;
296
  }
359
  $result[$key]["file"] = true;
360
  }
361
 
362
+ if ($this->matchCount(BVFW::SQLIREGEX, $value) > 2) {
363
  $result[$key]["sql"] = true;
364
  }
365
+
366
+ if (preg_match('/(?:\.{2}[\/]+)/', $value)) {
367
+ $result[$key]["path_traversal"] = true;
368
+ }
369
+
370
+ if (preg_match('/\\b(?i:eval)\\s*\\(\\s*(?i:base64_decode|exec|file_get_contents|gzinflate|passthru|shell_exec|stripslashes|system)\\s*\\(/', $value)) {
371
+ $result[$key]["php_eval"] = true;
372
+ }
373
  }
374
  }
375
  }
376
  return $result;
377
  }
378
+
379
+ public function evaluateRules($ruleSet) {
380
+ foreach ($ruleSet as $rule) {
381
+ $id = $rule["id"];
382
+ $ruleLogic = $rule["rule_logic"];
383
+ $actions = $rule["actions"];
384
+ $min_rule_engine_ver = $rule["min_rule_engine_ver"];
385
+ $this->ruleEvaluator->resetErrors();
386
+
387
+ if (BVFWRuleEvaluator::VERSION >= $min_rule_engine_ver) {
388
+ if ($this->ruleEvaluator->evaluateRule($ruleLogic) && empty($this->ruleEvaluator->getErrors())) {
389
+ $this->request->updateRulesInfo('matched_rules', $id, null);
390
+ $this->executeActions($actions);
391
+ } elseif (!empty($this->ruleEvaluator->getErrors())) {
392
+ $this->request->updateRulesInfo("errors", (string) $id, $this->ruleEvaluator->getErrors());
393
+ }
394
+ }
395
+ if ($this->break_rule_evaluation) {
396
+ return;
397
+ }
398
+ }
399
+ }
400
+
401
+ function executeActions($actions){
402
+ foreach($actions as $action) {
403
+ switch ($action["type"]) {
404
+ case "ALLOW":
405
+ $this->break_rule_evaluation = true;
406
+ return;
407
+ case "BLOCK":
408
+ $this->terminateRequest(BVWPRequest::BLACKLISTED);
409
+ return;
410
+ case "INSPECT":
411
+ //TODO
412
+ //call_user_func_array(array($this, "profileRequestInfo"), $this->ruleEvaluator->getArgs($action["args"]));
413
+ break;
414
+ case "DEBUG":
415
+ //TODO
416
+ break;
417
+ case "SCRUB":
418
+ //TODO
419
+ break;
420
+ case "FILTER":
421
+ //TODO
422
+ break;
423
+ }
424
+ }
425
+ }
426
  }
427
  endif;
protect/fw/request.php CHANGED
@@ -11,10 +11,10 @@ class BVWPRequest {
11
  private $ip;
12
  private $method;
13
  private $path;
14
- private $queryString;
15
  private $timestamp;
16
  private $uri;
17
- private $body;
18
  private $cookies;
19
  private $respcode;
20
  private $status;
@@ -27,9 +27,9 @@ class BVWPRequest {
27
  const BYPASSED = 3;
28
 
29
  #category
30
- const BLACKLISTED = 1;
31
- const WHITELISTED = 2;
32
- const NORMAL = 3;
33
 
34
  public function __construct($ip) {
35
  $fileNames = array();
@@ -44,9 +44,9 @@ class BVWPRequest {
44
  $this->setCategory(BVWPRequest::NORMAL);
45
  $this->setStatus(BVWpRequest::ALLOWED);
46
  $this->setTimestamp(time());
47
- $this->setQueryString($_GET);
48
  $this->setCookies($_COOKIE);
49
- $this->setBody($_POST);
50
  $this->setFiles($_FILES);
51
  if (!empty($_FILES)) {
52
  foreach ($_FILES as $input => $file) {
@@ -103,8 +103,8 @@ class BVWPRequest {
103
  $this->category = $category;
104
  }
105
 
106
- public function setBody($body) {
107
- $this->body = $body;
108
  }
109
 
110
  public function setCookies($cookies) {
@@ -143,8 +143,8 @@ class BVWPRequest {
143
  $this->path = $path;
144
  }
145
 
146
- public function setQueryString($queryString) {
147
- $this->queryString = $queryString;
148
  }
149
 
150
  public function setTimestamp($timestamp) {
@@ -155,8 +155,10 @@ class BVWPRequest {
155
  $this->uri = $uri;
156
  }
157
 
158
- public function updateRulesInfo($key, $value) {
159
- $this->rulesInfo[$key] = $value;
 
 
160
  }
161
 
162
  public function getRulesInfo() {
@@ -227,15 +229,15 @@ class BVWPRequest {
227
  }
228
  return null;
229
  }
230
-
231
- public function getBody() {
232
  if (func_num_args() > 0) {
233
  $args = func_get_args();
234
- return $this->getKeyVal($this->body, $args);
235
  }
236
- return $this->body;
237
  }
238
-
239
  public function getCookies() {
240
  if (func_num_args() > 0) {
241
  $args = func_get_args();
@@ -244,21 +246,33 @@ class BVWPRequest {
244
  return $this->cookies;
245
  }
246
 
247
- public function getQueryString() {
248
  if (func_num_args() > 0) {
249
  $args = func_get_args();
250
- return $this->getKeyVal($this->queryString, $args);
251
  }
252
- return $this->queryString;
253
  }
254
-
 
 
 
 
255
  public function getHeader($key) {
256
  if (array_key_exists($key, $this->headers)) {
257
  return $this->headers[$key];
258
  }
259
  return null;
260
  }
261
-
 
 
 
 
 
 
 
 
262
  public function getFiles() {
263
  if (func_num_args() > 0) {
264
  $args = func_get_args();
@@ -298,5 +312,22 @@ class BVWPRequest {
298
  public function getTimestamp() {
299
  return $this->timestamp;
300
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  }
302
- endif;
11
  private $ip;
12
  private $method;
13
  private $path;
14
+ private $getParams;
15
  private $timestamp;
16
  private $uri;
17
+ private $postParams;
18
  private $cookies;
19
  private $respcode;
20
  private $status;
27
  const BYPASSED = 3;
28
 
29
  #category
30
+ const BLACKLISTED = 1;
31
+ const WHITELISTED = 2;
32
+ const NORMAL = 3;
33
 
34
  public function __construct($ip) {
35
  $fileNames = array();
44
  $this->setCategory(BVWPRequest::NORMAL);
45
  $this->setStatus(BVWpRequest::ALLOWED);
46
  $this->setTimestamp(time());
47
+ $this->setGetParams($_GET);
48
  $this->setCookies($_COOKIE);
49
+ $this->setPostParams($_POST);
50
  $this->setFiles($_FILES);
51
  if (!empty($_FILES)) {
52
  foreach ($_FILES as $input => $file) {
103
  $this->category = $category;
104
  }
105
 
106
+ public function setPostParams($postParams) {
107
+ $this->postParams = $postParams;
108
  }
109
 
110
  public function setCookies($cookies) {
143
  $this->path = $path;
144
  }
145
 
146
+ public function setGetParams($getParams) {
147
+ $this->getParams = $getParams;
148
  }
149
 
150
  public function setTimestamp($timestamp) {
155
  $this->uri = $uri;
156
  }
157
 
158
+ public function updateRulesInfo($category, $sub_category, $value) {
159
+ $rule_info = (array_key_exists($category, $this->rulesInfo)) ? $this->rulesInfo[$category] : array();
160
+ $rule_info[$sub_category] = $value;
161
+ $this->rulesInfo[$category] = $rule_info;
162
  }
163
 
164
  public function getRulesInfo() {
229
  }
230
  return null;
231
  }
232
+
233
+ public function getPostParams() {
234
  if (func_num_args() > 0) {
235
  $args = func_get_args();
236
+ return $this->getKeyVal($this->postParams, $args);
237
  }
238
+ return $this->postParams;
239
  }
240
+
241
  public function getCookies() {
242
  if (func_num_args() > 0) {
243
  $args = func_get_args();
246
  return $this->cookies;
247
  }
248
 
249
+ public function getGetParams() {
250
  if (func_num_args() > 0) {
251
  $args = func_get_args();
252
+ return $this->getKeyVal($this->getParams, $args);
253
  }
254
+ return $this->getParams;
255
  }
256
+
257
+ public function getAllParams() {
258
+ return array("getParams" => $this->getParams, "postParams" => $this->postParams);
259
+ }
260
+
261
  public function getHeader($key) {
262
  if (array_key_exists($key, $this->headers)) {
263
  return $this->headers[$key];
264
  }
265
  return null;
266
  }
267
+
268
+ public function getHeaders() {
269
+ if (func_num_args() > 0) {
270
+ $args = func_get_args();
271
+ return $this->getKeyVal($this->headers, $args);
272
+ }
273
+ return $this->headers;
274
+ }
275
+
276
  public function getFiles() {
277
  if (func_num_args() > 0) {
278
  $args = func_get_args();
312
  public function getTimestamp() {
313
  return $this->timestamp;
314
  }
315
+
316
+ public function getServerValue($key) {
317
+ if (isset($_SERVER) && array_key_exists($key, $_SERVER)) {
318
+ return $_SERVER[$key];
319
+ }
320
+ return false;
321
+ }
322
+
323
+ public function getUserRoleLevel() {
324
+ // TODO
325
+ // Handle prepend level using custom cookies.
326
+ return 0;
327
+ }
328
+
329
+ public function isUserRoleLevel($level) {
330
+ return ($level === $this->getUserRoleLevel());
331
+ }
332
  }
333
+ endif;
protect/fw/rule_evaluator.php ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!(defined('ABSPATH') || defined('MCDATAPATH'))) exit;
4
+ if (!class_exists('BVFWRuleEvaluator')) :
5
+
6
+ class BVFWRuleEvaluator {
7
+ private $request;
8
+
9
+ const VERSION = 0.2;
10
+
11
+ public function __construct($request) {
12
+ $this->request = $request;
13
+ }
14
+
15
+ function getErrors() {
16
+ return $this->errors;
17
+ }
18
+
19
+ function resetErrors() {
20
+ $this->errors = array();
21
+ }
22
+
23
+ // ================================ Functions for type checking ========================================
24
+ function isNumeric($value) {
25
+ return (preg_match('/^\d+$/', $value));
26
+ }
27
+
28
+ function isRegularWord($value) {
29
+ return (preg_match('/^\w+$/', $value));
30
+ }
31
+
32
+ function isSpecialWord($value) {
33
+ return (preg_match('/^\S+$/', $value));
34
+ }
35
+
36
+ function isRegularSentence($value) {
37
+ return (preg_match('/^[\w\s]+$/', $value));
38
+ }
39
+
40
+ function isSpecialCharsSentence($value) {
41
+ return (preg_match('/^[\w\W]+$/', $value));
42
+ }
43
+
44
+ function isLink($value) {
45
+ return (preg_match('/^(http|ftp)s?:\/\/\S+$/i', $value));
46
+ }
47
+
48
+ function isFileUpload($value) {
49
+ $file = $this->getFiles($value);
50
+ if (is_array($file) && in_array('tmp_name', $file)) {
51
+ return is_uploaded_file($file['tmp_name']);
52
+ }
53
+ return false;
54
+ }
55
+
56
+ function isIpv4($value) {
57
+ return (preg_match('/^\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b$/x', $value));
58
+ }
59
+
60
+ function isEmbededIpv4($value) {
61
+ return (preg_match('/\b((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b/x', $value));
62
+ }
63
+
64
+ function isIpv6($value) {
65
+ return (preg_match('/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/x', $value));
66
+ }
67
+
68
+ function isEmbededIpv6($value) {
69
+ return (preg_match('/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/x', $value));
70
+ }
71
+
72
+ function isEmail($value) {
73
+ return (preg_match('/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/', $value));
74
+ }
75
+
76
+ function isEmbededEmail($value) {
77
+ return (preg_match('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}/', $value));
78
+ }
79
+
80
+ function isEmbededLink($value) {
81
+ return (preg_match('/(http|ftp)s?:\/\/\S+$/i', $value));
82
+ }
83
+
84
+ function isEmbededHtml($value) {
85
+ return (preg_match('/<(html|head|title|base|link|meta|style|picture|source|img|iframe|embed|object|param|video|audio|track|map|area|form|label|input|button|select|datalist|optgroup|option|textarea|output|progress|meter|fieldset|legend|script|noscript|template|slot|canvas)/ix', $value));
86
+ }
87
+
88
+ function isFile($value) {
89
+ return (preg_match('/\.(jpg|jpeg|png|gif|ico|pdf|doc|docx|ppt|pptx|pps|ppsx|odt|xls|zip|gzip|xlsx|psd|mp3|m4a|ogg|wav|mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|php|html|phtml|js|css)/ix', $value));
90
+ }
91
+
92
+ function isPathTraversal($value) {
93
+ return (preg_match('/(?:\.{2}[\/]+)/', $value));
94
+ }
95
+
96
+ function isPhpEval($value) {
97
+ return (preg_match('/\\b(?i:eval)\\s*\\(\\s*(?i:base64_decode|exec|file_get_contents|gzinflate|passthru|shell_exec|stripslashes|system)\\s*\\(/', $value));
98
+ }
99
+
100
+ // ================================ Functions to perform operations ========================================
101
+ function contains($val, $subject) {
102
+ if (is_array($val)) {
103
+ return in_array($val, $subject);
104
+ }
105
+ return strpos((string) $subject, (string) $val) !== false;
106
+ }
107
+
108
+ function notContains($val, $subject) {
109
+ return !$this->contains($val, $subject);
110
+ }
111
+
112
+ function match($pattern, $subject) {
113
+ if (is_array($subject)) {
114
+ foreach ($subject as $k => $v) {
115
+ if ($this->match($pattern, $v)) {
116
+ return true;
117
+ }
118
+ }
119
+ return false;
120
+ }
121
+ $resp = preg_match((string) $pattern, (string) $subject);
122
+ if ($resp === false) {
123
+ array_push($this->errors, array("preg_match", $subject));
124
+ } else if ($resp > 0) {
125
+ return true;
126
+ }
127
+ return false;
128
+ }
129
+
130
+ function notMatch($pattern, $subject) {
131
+ return !$this->match($pattern, $subject);
132
+ }
133
+
134
+ function matchCount($pattern, $subject) {
135
+ $count = 0;
136
+ if (is_array($subject)) {
137
+ foreach ($subject as $val) {
138
+ $count += $this->matchCount($pattern, $val);
139
+ }
140
+ return $count;
141
+ }
142
+ $count = preg_match_all((string) $pattern, (string) $subject, $matches);
143
+ if ($count === false) {
144
+ array_push($this->errors, array("preg_match_all", $subject));
145
+ }
146
+ return $count;
147
+ }
148
+
149
+ function maxMatchCount($pattern, $subject) {
150
+ $count = 0;
151
+ if (is_array($subject)) {
152
+ foreach ($subject as $val) {
153
+ $count = max($count, $this->matchCount($pattern, $val));
154
+ }
155
+ return $count;
156
+ }
157
+ $count = preg_match_all((string) $pattern, (string) $subject, $matches);
158
+ if ($count === false) {
159
+ array_push($this->errors, array("preg_match_all", $subject));
160
+ }
161
+ return $count;
162
+ }
163
+
164
+ function equals($val, $subject) {
165
+ return ($val == $subject);
166
+ }
167
+
168
+ function notEquals($val, $subject) {
169
+ return !$this->equals($val, $subject);
170
+ }
171
+
172
+ function isIdentical($val, $subject) {
173
+ return ($val === $subject);
174
+ }
175
+
176
+ function notIdentical($val, $subject) {
177
+ return !$this->isIdentical($val, $subject);
178
+ }
179
+
180
+ function greaterThan($val, $subject) {
181
+ return ($subject > $val);
182
+ }
183
+
184
+ function greaterThanEqualTo($val, $subject) {
185
+ return ($subject >= $val);
186
+ }
187
+
188
+ function lessThan($val, $subject) {
189
+ return ($subject < $val);
190
+ }
191
+
192
+ function lessThanEqualTo($val, $subject) {
193
+ return ($subject <= $val);
194
+ }
195
+
196
+ function lengthGreaterThan($val, $subject) {
197
+ return (strlen((string) $subject) > $val);
198
+ }
199
+
200
+ function lengthLessThan($val, $subject) {
201
+ return (strlen((string) $subject) < $val);
202
+ }
203
+
204
+ function md5Equals($val, $subject) {
205
+ return (md5((string) $subject) === $val);
206
+ }
207
+
208
+ function compareMultipleSubjects($func, $args, $subjects) {
209
+ // TODO
210
+ }
211
+
212
+ // ================================ Functions to get request data ========================================
213
+ function getReqInfo($key) {
214
+ return $this->request->getReqInfo($key);
215
+ }
216
+
217
+ function getPath() {
218
+ return $this->request->getPath();
219
+ }
220
+
221
+ function getServerValue($key) {
222
+ return $this->request->getServerValue($key);
223
+ }
224
+
225
+ function getHeader($key) {
226
+ return $this->request->getHeader($key);
227
+ }
228
+
229
+ function getHeaders() {
230
+ return $this->request->getHeaders();
231
+ }
232
+
233
+ function getPostParams() {
234
+ if (func_num_args() > 0) {
235
+ $args = func_get_args();
236
+ return $this->request->getPostParams($args);
237
+ }
238
+ return $this->request->getPostParams();
239
+ }
240
+
241
+ function getReqMethod() {
242
+ return $this->request->getMethod();
243
+ }
244
+
245
+ function getGetParams() {
246
+ if (func_num_args() > 0) {
247
+ $args = func_get_args();
248
+ return $this->request->getGetParams($args);
249
+ }
250
+ return $this->request->getGetParams();
251
+ }
252
+
253
+ function getCookies() {
254
+ if (func_num_args() > 0) {
255
+ $args = func_get_args();
256
+ return $this->request->getCookies($args);
257
+ }
258
+ return $this->request->getCookies();
259
+ }
260
+
261
+ function getFiles() {
262
+ if (func_num_args() > 0) {
263
+ $args = func_get_args();
264
+ return $this->request->getFiles($args);
265
+ }
266
+ return $this->request->getFiles();
267
+ }
268
+
269
+ function getFileNames() {
270
+ if (func_num_args() > 0) {
271
+ $args = func_get_args();
272
+ return $this->request->getFileNames($args);
273
+ }
274
+ return $this->request->getFileNames();
275
+ }
276
+
277
+ function getHost() {
278
+ return $this->host;
279
+ }
280
+
281
+ function getURI() {
282
+ return $this->request->getURI();
283
+ }
284
+
285
+ function getIP() {
286
+ return $this->request->getIP();
287
+ }
288
+
289
+ function getTimestamp() {
290
+ return $this->request->getTimeStamp();
291
+ }
292
+
293
+ function getUserRoleLevel() {
294
+ return $this->request->getUserRoleLevel();
295
+ }
296
+
297
+ function isUserRoleLevel($level) {
298
+ return $this->request->isUserRoleLevel($level);
299
+ }
300
+
301
+ function getAllParams() {
302
+ return $this->request->getAllParams();
303
+ }
304
+
305
+ // ================================ Functions to evaluate rule logic ========================================
306
+ function evaluateRule($ruleLogic) {
307
+ return $this->evaluateExpression($ruleLogic);
308
+ }
309
+
310
+ function evaluateExpression($expr) {
311
+ switch ($expr["type"]) {
312
+ case "AND" :
313
+ $loperand = $this->getValue($expr["left_operand"]);
314
+ $roperand = $this->getValue($expr["right_operand"]);
315
+ return ($loperand && $roperand);
316
+ case "OR" :
317
+ $loperand = $this->getValue($expr["left_operand"]);
318
+ $roperand = $this->getValue($expr["right_operand"]);
319
+ return ($loperand || $roperand);
320
+ case "NOT" :
321
+ return !$this->getValue($expr["value"]);
322
+ case "FUNCTION" :
323
+ return $this->executeFunctionCall($expr);
324
+ default :
325
+ break;
326
+ }
327
+ }
328
+
329
+ function fetchConstantValue($name) {
330
+ $value = constant($name);
331
+ if ($value) {
332
+ return $value;
333
+ }
334
+ array_push($this->errors, array("fetch_constant_value", $name));
335
+ return false;
336
+ }
337
+
338
+ function getArgs($args) {
339
+ $_args = array();
340
+ foreach ($args as $arg) {
341
+ array_push($_args, $this->getValue($arg));
342
+ }
343
+ return $_args;
344
+ }
345
+
346
+ function executeFunctionCall($func) {
347
+ $name = $func["name"];
348
+ $handler = array($this, $name);
349
+ if (!is_callable($handler)) {
350
+ array_push($this->errors, array("execute_function_call", "function_not_allowed", $name));
351
+ return false;
352
+ }
353
+ return call_user_func_array($handler, $this->getArgs($func["args"]));
354
+ }
355
+
356
+ function getValue($expr) {
357
+ switch ($expr["type"]) {
358
+ case "NUMBER" :
359
+ return $expr["value"];
360
+ case "STRING" :
361
+ return $expr["value"];
362
+ case "STRING_WITH_QUOTES" :
363
+ $expr["value"] = preg_replace("/^('|\")/", "", $expr["value"]);
364
+ $expr["value"] = preg_replace("/('|\")$/", "", $expr["value"]);
365
+ return $expr["value"];
366
+ case "CONST" :
367
+ return $this->fetchConstantValue($expr["value"]);
368
+ case "FUNCTION" :
369
+ return $this->executeFunctionCall($expr);
370
+ default :
371
+ return $this->evaluateExpression($expr);
372
+ }
373
+ }
374
+ }
375
+ endif;
protect/prepend/protect.php CHANGED
@@ -14,10 +14,12 @@ require_once dirname( __FILE__ ) . '/logger.php';
14
  class BVPrependProtect {
15
  public $mcConfFile;
16
  public $mcIPsFile;
 
17
 
18
  function __construct() {
19
  $this->mcConfFile = MCDATAPATH . MCCONFKEY . '-' . 'mc.conf';
20
  $this->mcIPsFile = MCDATAPATH . MCCONFKEY . '-' . 'mc_ips.conf';
 
21
  }
22
 
23
  public function parseFile($fname) {
@@ -36,6 +38,7 @@ require_once dirname( __FILE__ ) . '/logger.php';
36
  public function run() {
37
  $mcConf = $this->parseFile($this->mcConfFile);
38
  $mcIPsConf = $this->parseFile($this->mcIPsFile);
 
39
 
40
  if (!array_key_exists('time', $mcConf) || !isset($mcConf['time']) || !($mcConf['time'] > time() - (48*3600))) {
41
  return false;
@@ -55,7 +58,7 @@ require_once dirname( __FILE__ ) . '/logger.php';
55
  $fwlogger = new BVPrependLogger();
56
 
57
  $fwConfHash = array_key_exists('fw', $mcConf) ? $mcConf['fw'] : array();
58
- $fw = new BVFW($fwlogger, $fwConfHash, $ip, $bvinfo, $bvipstore);
59
 
60
  if ($fw->isActive()) {
61
 
@@ -73,4 +76,4 @@ require_once dirname( __FILE__ ) . '/logger.php';
73
  }
74
 
75
  }
76
- endif;
14
  class BVPrependProtect {
15
  public $mcConfFile;
16
  public $mcIPsFile;
17
+ public $mcRulesFile;
18
 
19
  function __construct() {
20
  $this->mcConfFile = MCDATAPATH . MCCONFKEY . '-' . 'mc.conf';
21
  $this->mcIPsFile = MCDATAPATH . MCCONFKEY . '-' . 'mc_ips.conf';
22
+ $this->mcRulesFile = MCDATAPATH . MCCONFKEY . '-' . 'mc_rules.json';
23
  }
24
 
25
  public function parseFile($fname) {
38
  public function run() {
39
  $mcConf = $this->parseFile($this->mcConfFile);
40
  $mcIPsConf = $this->parseFile($this->mcIPsFile);
41
+ $mcRuleSet = $this->parseFile($this->mcRulesFile);
42
 
43
  if (!array_key_exists('time', $mcConf) || !isset($mcConf['time']) || !($mcConf['time'] > time() - (48*3600))) {
44
  return false;
58
  $fwlogger = new BVPrependLogger();
59
 
60
  $fwConfHash = array_key_exists('fw', $mcConf) ? $mcConf['fw'] : array();
61
+ $fw = new BVFW($fwlogger, $fwConfHash, $ip, $bvinfo, $bvipstore, $mcRuleSet);
62
 
63
  if ($fw->isActive()) {
64
 
76
  }
77
 
78
  }
79
+ endif;
protect/wp/lp/lp.php CHANGED
@@ -183,10 +183,12 @@ class BVWPLP {
183
  $this->setCategory(BVWPLP::UNBLOCKED);
184
  } else {
185
  $failed_attempts = $this->getLoginCount(BVWPLP::LOGINFAILURE, $this->ip);
186
- if ($this->isBlacklistedIP()) {
 
 
187
  $this->setCategory(BVWPLP::BLACKLISTED);
188
  $this->terminateLogin();
189
- } else if ($this->isKnownLogin() || $this->isWhitelistedIP()) {
190
  $this->setCategory(BVWPLP::BYPASSED);
191
  } else if ($this->isLoginBlocked()) {
192
  $this->setCategory(BVWPLP::ALLBLOCKED);
183
  $this->setCategory(BVWPLP::UNBLOCKED);
184
  } else {
185
  $failed_attempts = $this->getLoginCount(BVWPLP::LOGINFAILURE, $this->ip);
186
+ if ($this->isWhitelistedIP()) {
187
+ $this->setCategory(BVWPLP::BYPASSED);
188
+ } else if ($this->isBlacklistedIP()) {
189
  $this->setCategory(BVWPLP::BLACKLISTED);
190
  $this->terminateLogin();
191
+ } else if ($this->isKnownLogin()) {
192
  $this->setCategory(BVWPLP::BYPASSED);
193
  } else if ($this->isLoginBlocked()) {
194
  $this->setCategory(BVWPLP::ALLBLOCKED);
protect/wp/protect.php CHANGED
@@ -20,6 +20,10 @@ class BVProtect {
20
  $this->db = $db;
21
  }
22
 
 
 
 
 
23
  public function run() {
24
  $bvipstore = new BVIPStore($this->db);
25
  $bvipstore->init();
@@ -36,7 +40,8 @@ class BVProtect {
36
  $fwLogger = new BVLogger($this->db, BVFWConfig::$requests_table);
37
 
38
  $fwConfHash = array_key_exists('fw', $config) ? $config['fw'] : array();
39
- $fw = new BVFW($fwLogger, $fwConfHash, $ip, $bvinfo, $bvipstore);
 
40
 
41
  if ($fw->isActive()) {
42
 
@@ -55,8 +60,6 @@ class BVProtect {
55
  }
56
  }
57
 
58
- add_action('clear_pt_config', array($this, 'uninstall'));
59
-
60
  $lpConfHash = array_key_exists('lp', $config) ? $config['lp'] : array();
61
  $lp = new BVWPLP($this->db, $this->settings, $ip, $bvipstore, $lpConfHash);
62
  if ($lp->isActive()) {
@@ -69,7 +72,89 @@ class BVProtect {
69
  $this->db->dropBVTable(BVFWConfig::$requests_table);
70
  $this->db->dropBVTable(BVWPLPConfig::$requests_table);
71
  $this->settings->deleteOption('bvptplug');
 
 
 
72
  return true;
73
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
75
  endif;
20
  $this->db = $db;
21
  }
22
 
23
+ public function init() {
24
+ add_action('clear_pt_config', array($this, 'uninstall'));
25
+ }
26
+
27
  public function run() {
28
  $bvipstore = new BVIPStore($this->db);
29
  $bvipstore->init();
40
  $fwLogger = new BVLogger($this->db, BVFWConfig::$requests_table);
41
 
42
  $fwConfHash = array_key_exists('fw', $config) ? $config['fw'] : array();
43
+ $ruleSet = $this->getRuleSet();
44
+ $fw = new BVFW($fwLogger, $fwConfHash, $ip, $bvinfo, $bvipstore, $ruleSet);
45
 
46
  if ($fw->isActive()) {
47
 
60
  }
61
  }
62
 
 
 
63
  $lpConfHash = array_key_exists('lp', $config) ? $config['lp'] : array();
64
  $lp = new BVWPLP($this->db, $this->settings, $ip, $bvipstore, $lpConfHash);
65
  if ($lp->isActive()) {
72
  $this->db->dropBVTable(BVFWConfig::$requests_table);
73
  $this->db->dropBVTable(BVWPLPConfig::$requests_table);
74
  $this->settings->deleteOption('bvptplug');
75
+ $this->remove_wp_prepend();
76
+ $this->remove_php_prepend();
77
+ $this->remove_mcdata();
78
  return true;
79
  }
80
+
81
+ private function remove_wp_prepend() {
82
+ $wp_conf_paths = array(ABSPATH . "wp-config.php", ABSPATH . "../wp-config.php");
83
+ if (file_exists($wp_conf_paths[0])) {
84
+ $fname = $wp_conf_paths[0];
85
+ } elseif (file_exists($wp_conf_paths[1])) {
86
+ $fname = $wp_conf_paths[1];
87
+ } else {
88
+ return;
89
+ }
90
+
91
+ $content = file_get_contents($fname);
92
+ if ($content) {
93
+ $pattern = "@include '" . ABSPATH . "malcare-waf.php" . "';";
94
+ $modified_content = str_replace($pattern, "", $content);
95
+ if ($content !== $modified_content) {
96
+ file_put_contents($fname, $modified_content);
97
+ }
98
+ }
99
+ }
100
+
101
+ private function remove_php_prepend() {
102
+ $this->remove_htaccess_prepend();
103
+ $this->remove_userini_prepend();
104
+ }
105
+
106
+ private function remove_prepend($fname, $pattern) {
107
+ if (!file_exists($fname)) return;
108
+
109
+ $content = file_get_contents($fname);
110
+ if ($content) {
111
+ $modified_content = preg_replace($pattern, "", $content);
112
+ if ($content !== $modified_content) {
113
+ file_put_contents($fname, $modified_content);
114
+ }
115
+ }
116
+ }
117
+
118
+ private function remove_htaccess_prepend() {
119
+ $pattern = "/# MalCare WAF(.|\n)*# END MalCare WAF/i";
120
+ $this->remove_prepend(ABSPATH . ".htaccess", $pattern);
121
+ }
122
+
123
+ private function remove_userini_prepend() {
124
+ $pattern = "/; MalCare WAF(.|\n)*; END MalCare WAF/i";
125
+ $this->remove_prepend(ABSPATH . ".user.ini", $pattern);
126
+ }
127
+
128
+ private function remove_mcdata() {
129
+ $this->rrmdir($this->get_contdir() . "mc_data");
130
+ }
131
+
132
+ private function rrmdir($dir) {
133
+ if (is_dir($dir)) {
134
+ $objects = scandir($dir);
135
+ foreach ($objects as $object) {
136
+ if ($object != "." && $object != "..") {
137
+ if (is_dir($dir . "/" . $object) && !is_link($dir . "/" . $object)) {
138
+ rrmdir($dir . "/" . $object);
139
+ } else {
140
+ unlink($dir . "/" . $object);
141
+ }
142
+ }
143
+ }
144
+ rmdir($dir);
145
+ }
146
+ }
147
+
148
+ public function get_contdir() {
149
+ return defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR . "/" : ABSPATH . "wp-content/";
150
+ }
151
+
152
+ public function getRuleSet() {
153
+ $ruleSet = $this->settings->getOption('bvruleset');
154
+ if ($ruleSet) {
155
+ return $ruleSet;
156
+ }
157
+ return array();
158
+ }
159
  }
160
  endif;
readme.txt CHANGED
@@ -6,7 +6,7 @@ Donate link: https://app.blogvault.net/home/signup
6
  Requires at least: 4.0
7
  Tested up to: 5.6
8
  Requires PHP: 5.4.0
9
- Stable tag: 4.36
10
  License: GPLv2 or later
11
  License URI: [http://www.gnu.org/licenses/gpl-2.0.html](http://www.gnu.org/licenses/gpl-2.0.html)
12
 
@@ -247,6 +247,12 @@ These are available on our website: [Terms of Service](https://blogvault.net/tos
247
  9. We power WordPress migration for WPEngine, Pantheon, FlyWheel, LiquidWeb, Cloudways, Savvii and many more. Need we say more?
248
 
249
  == CHANGELOG ==
 
 
 
 
 
 
250
  = 4.36 =
251
  * Block WordPress auto update feature
252
  * Improved scanfiles and filelist api
6
  Requires at least: 4.0
7
  Tested up to: 5.6
8
  Requires PHP: 5.4.0
9
+ Stable tag: 4.54
10
  License: GPLv2 or later
11
  License URI: [http://www.gnu.org/licenses/gpl-2.0.html](http://www.gnu.org/licenses/gpl-2.0.html)
12
 
247
  9. We power WordPress migration for WPEngine, Pantheon, FlyWheel, LiquidWeb, Cloudways, Savvii and many more. Need we say more?
248
 
249
  == CHANGELOG ==
250
+ = 4.54 =
251
+ * Added Support For Multi Table Callbacks
252
+ * Added Firewall Rule Evaluator
253
+ * Added Activity Logs feature
254
+ * Minor Improvements
255
+
256
  = 4.36 =
257
  * Block WordPress auto update feature
258
  * Improved scanfiles and filelist api
wp_actions.php CHANGED
@@ -38,7 +38,7 @@ if (!class_exists('BVWPAction')) :
38
  public static function uninstall() {
39
  do_action('clear_pt_config');
40
  do_action('clear_ip_store');
41
- do_action('clear_dynsync_config');
42
  }
43
 
44
  public function footerHandler() {
38
  public static function uninstall() {
39
  do_action('clear_pt_config');
40
  do_action('clear_ip_store');
41
+ do_action('clear_dynsync_config');
42
  }
43
 
44
  public function footerHandler() {
wp_actlog.php ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined('ABSPATH')) exit;
4
+ if (!class_exists('BVWPActLog')) :
5
+
6
+ class BVWPActLog {
7
+
8
+ public static $actlog_table = 'activities_store';
9
+ public $db;
10
+ public $settings;
11
+ public $bvinfo;
12
+
13
+ public function __construct($db, $settings, $info, $config) {
14
+ $this->db = $db;
15
+ $this->settings = $settings;
16
+ $this->bvinfo = $info;
17
+ $this->request_id = BVAccount::randString(16);
18
+ $this->ip_header = array_key_exists('ip_header', $config) ? $config['ip_header'] : false;
19
+ }
20
+
21
+ function init() {
22
+ $this->add_actions_and_listeners();
23
+ }
24
+
25
+ function get_post($post_id) {
26
+ $post = get_post($post_id);
27
+ $data = array('id' => $post_id);
28
+ if (!empty($post)) {
29
+ $data['title'] = $post->post_title;
30
+ $data['status'] = $post->post_status;
31
+ $data['type'] = $post->post_type;
32
+ $data['url'] = get_permalink($post_id);
33
+ $data['date'] = $post->post_date;
34
+ }
35
+ return $data;
36
+ }
37
+
38
+ function get_comment($comment_id) {
39
+ $comment = get_comment($comment_id);
40
+ $data = array('id' => $comment_id);
41
+ if (!empty($comment)) {
42
+ $data['author'] = $comment->comment_author;
43
+ }
44
+ return $data;
45
+ }
46
+
47
+ function get_term($term_id) {
48
+ $term = get_term($term_id);
49
+ $data = array('id' => $term_id);
50
+ if (!empty($term)) {
51
+ $data['name'] = $term->name;
52
+ $data['slug'] = $term->slug;
53
+ $data['taxonomy'] = $term->taxonomy;
54
+ }
55
+ return $data;
56
+ }
57
+
58
+ function get_user($user_id) {
59
+ $user = get_userdata($user_id);
60
+ $data = array('id' => $user_id);
61
+ if (!empty($user)) {
62
+ $data['username'] = $user->user_login;
63
+ $data['email'] = $user->user_email;
64
+ }
65
+ return $data;
66
+ }
67
+
68
+ function get_blog($blog_id) {
69
+ $blog = get_blog_details($blog_id);
70
+ $data = array('id' => $blog_id);
71
+ if (!empty($blog)) {
72
+ $data['name'] = $blog->blogname;
73
+ $data['url'] = $blog->path;
74
+ }
75
+ return $data;
76
+ }
77
+
78
+ function add_activity($event_data) {
79
+ $user = wp_get_current_user();
80
+ $values = array();
81
+ if (!empty($user)) {
82
+ $values["user_id"] = $user->ID;
83
+ $values["username"] = $user->user_login;
84
+ }
85
+ $values["request_id"] = $this->request_id;
86
+ $values["site_id"] = get_current_blog_id();
87
+ $values["ip"] = BVProtectBase::getIP($this->ip_header);
88
+ $values["event_type"] = current_filter();
89
+ $values["event_data"] = maybe_serialize($event_data);
90
+ $values["time"] = time();
91
+ $this->db->replaceIntoBVTable(BVWPActLog::$actlog_table, $values);
92
+ }
93
+
94
+ function user_login_handler($user_login, $user) {
95
+ $event_data = array("user" => $this->get_user($user->ID));
96
+ $this->add_activity($event_data);
97
+ }
98
+
99
+ function user_logout_handler($user_id) {
100
+ $user = $this->get_user($user_id);
101
+ $event_data = array("user" => $user);
102
+ $this->add_activity($event_data);
103
+ }
104
+
105
+ function password_reset_handler($user, $new_pass) {
106
+ if (!empty($user)) {
107
+ $event_data = array("user" => $this->get_user($user->ID));
108
+ $this->add_activity($event_data);
109
+ }
110
+ }
111
+
112
+ function comment_handler($comment_id) {
113
+ $comment = $this->get_comment($comment_id);
114
+ $post = $this->get_post($comment->comment_post_ID);
115
+ $event_data = array(
116
+ "comment" => $comment,
117
+ "post" => $post
118
+ );
119
+ $this->add_activity($event_data);
120
+ }
121
+
122
+ function comment_status_changed_handler($new_status, $old_status, $comment) {
123
+ $post = $this->get_post($comment->comment_post_ID);
124
+ $event_data = array(
125
+ "comment" => $this->get_comment($comment->comment_ID),
126
+ "post" => $post,
127
+ "old_status" => $old_status,
128
+ "new_status" => $new_status
129
+ );
130
+ $this->add_activity($event_data);
131
+ }
132
+
133
+ function post_handler($post_id) {
134
+ $post = $this->get_post($post_id);
135
+ $event_data = array(
136
+ "post" => $post
137
+ );
138
+ $this->add_activity($event_data);
139
+ }
140
+
141
+ function post_saved_handler($post_id, $post, $update) {
142
+ $post = $this->get_post($post_id);
143
+ $event_data = array(
144
+ "post" => $post,
145
+ "updated" => $update
146
+ );
147
+ $this->add_activity($event_data);
148
+ }
149
+
150
+ function term_handler($term_id) {
151
+ $term = $this->get_term($term_id);
152
+ $event_data = array(
153
+ "term" => $term,
154
+ );
155
+ $this->add_activity($event_data);
156
+ }
157
+
158
+ function term_updation_handler($data, $term_id) {
159
+ $term = $this->get_term($term_id);
160
+ $event_data = array(
161
+ "old_term" => $term,
162
+ "term" => $data
163
+ );
164
+ $this->add_activity($event_data);
165
+ return $data;
166
+ }
167
+
168
+ function term_deletion_handler($term_id) {
169
+ $event_data = array(
170
+ "term" => array("id" => $term_id)
171
+ );
172
+ $this->add_activity($event_data);
173
+ }
174
+
175
+ function user_handler($user_id) {
176
+ $user = $this->get_user($user_id);
177
+ $event_data = array(
178
+ "user" => $user,
179
+ );
180
+ $this->add_activity($event_data);
181
+ }
182
+
183
+ function user_update_handler($user_id, $old_userdata) {
184
+ $new_userdata = $this->get_user($user_id);
185
+ $event_data = array(
186
+ "old_user" => $this->get_user($old_userdata->ID),
187
+ "user" => $new_userdata,
188
+ );
189
+ $this->add_activity($event_data);
190
+ }
191
+
192
+ function plugin_action_handler($plugin) {
193
+ $event_data = array("plugin" => $plugin);
194
+ $this->add_activity($event_data);
195
+ }
196
+
197
+ function theme_action_handler($theme_name) {
198
+ $event_data = array("theme" => $theme_name);
199
+ $this->add_activity($event_data);
200
+ }
201
+
202
+ function mu_handler($blog_id) {
203
+ $blog = $this->get_blog($blog_id);
204
+ $event_data = array(
205
+ "blog" => $blog
206
+ );
207
+ $this->add_activity($event_data);
208
+ }
209
+
210
+ function mu_delete_handler($blog) {
211
+ $event_data = array(
212
+ "blog" => $this->get_blog($blog->blog_id)
213
+ );
214
+ $this->add_activity($event_data);
215
+ }
216
+
217
+ /* ADDING ACTION AND LISTENERS FOR SENSING EVENTS. */
218
+ public function add_actions_and_listeners() {
219
+ /* SENSORS FOR POST AND PAGE CHANGES */
220
+ add_action('pre_post_update', array($this, 'post_handler'));
221
+ add_action('save_post', array($this, 'post_saved_handler'), 10, 3);
222
+ add_action('post_stuck', array($this, 'post_handler'));
223
+ add_action('post_unstuck', array($this, 'post_handler'));
224
+ add_action('delete_post', array($this, 'post_handler'));
225
+
226
+ /* SENSORS FOR COMMENTS */
227
+ add_action('comment_post', array($this, 'comment_handler'));
228
+ add_action('edit_comment', array($this, 'comment_handler'));
229
+ add_action('transition_comment_status', array($this, 'comment_status_changed_handler'), 10, 3);
230
+
231
+ /* SENSORS FOR TAG AND CATEGORY CHANGES */
232
+ add_action('create_term', array($this, 'term_handler'));
233
+ add_action('pre_delete_term', array($this, 'term_handler'));
234
+ add_action('delete_term', array($this, 'term_deletion_handler'));
235
+ add_filter('wp_update_term_data', array($this, 'term_updation_handler'), 10, 2);
236
+
237
+ /* SENSORS FOR USER CHANGES*/
238
+ add_action('user_register', array($this, 'user_handler'));
239
+ add_action('wpmu_new_user', array($this, 'user_handler'));
240
+ add_action('profile_update', array($this, 'user_update_handler'), 10, 2);
241
+ add_action('delete_user', array($this, 'user_handler'));
242
+ add_action('wpmu_delete_user', array($this, 'user_handler'));
243
+
244
+ /* SENSORS FOR PLUGIN AND THEME*/
245
+ add_action('activate_plugin', array($this, 'plugin_action_handler'));
246
+ add_action('deactivate_plugin', array($this, 'plugin_action_handler'));
247
+ add_action('switch_theme', array($this, 'theme_action_handler'));
248
+
249
+ /* SENSORS FOR MULTISITE CHANGES */
250
+ add_action('wpmu_new_blog', array($this, 'mu_handler'));
251
+ add_action('archive_blog', array($this, 'mu_handler'));
252
+ add_action('unarchive_blog', array( $this, 'mu_handler'));
253
+ add_action('activate_blog', array($this, 'mu_handler'));
254
+ add_action('deactivate_blog', array($this, 'mu_handler'));
255
+ add_action('wp_delete_site', array($this, 'mu_delete_handler'));
256
+
257
+ /* SENSORS USER ACTIONS AT FRONTEND */
258
+ add_action('wp_login', array($this, 'user_login_handler'), 10, 2);
259
+ add_action('wp_logout', array( $this, 'user_logout_handler'), 5, 1);
260
+ add_action('password_reset', array( $this, 'password_reset_handler'), 10, 2);
261
+ }
262
+ }
263
+ endif;
wp_site_info.php CHANGED
@@ -39,6 +39,12 @@ class BVWPSiteInfo {
39
  return is_main_site();
40
  }
41
 
 
 
 
 
 
 
42
  public function info() {
43
  $info = array();
44
  $this->basic($info);
39
  return is_main_site();
40
  }
41
 
42
+ public function getMainSiteId() {
43
+ if (!function_exists('get_main_site_id'))
44
+ return 0;
45
+ return get_main_site_id();
46
+ }
47
+
48
  public function info() {
49
  $info = array();
50
  $this->basic($info);