MalCare WordPress Security Plugin – Malware Scanner, Cleaner, Security Firewall - 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 MalCare WordPress Security Plugin – Malware Scanner, Cleaner, Security Firewall
Version 4.54
Comparing to
See all releases

Code changes from version 4.53 to 4.54

admin/registration.php CHANGED
@@ -1,7 +1,7 @@
1
  <div class="malcare9">
2
  <section id="malcare-1">
3
  <div class="malcare-logo-img text-center">
4
- <img height="70" width="240" src="<?php echo plugins_url("/../img/mc-top-logo.png", __FILE__); ?>" alt="">
5
  </div>
6
  <div class="container-malcare" id="">
7
  <div class="row">
@@ -13,7 +13,7 @@
13
  <input type='hidden' name='bvsrc' value='wpplugin' />
14
  <input type='hidden' name='origin' value='protect' />
15
  <?php echo $this->siteInfoTags(); ?>
16
- <input type="text" placeholder="Enter your email address to continue" id="email" name="email" class="search" value="<?php echo get_option('admin_email');?>" required>
17
  <h5 class="check-box-text mt-2"><input type="checkbox" class="check-box" name="consent" value="1">
18
  <label>I agree to MalCare <a href="https://www.malcare.com/tos" target="_blank" rel="noopener noreferrer">Terms of Service</a> and <a href="https://www.malcare.com/privacy" target="_blank" rel="noopener noreferrer">Privacy Policy</a></label></h5>
19
  <button id="get-started" type="submit" class="e-mail-button"><span class="text-white">Submit</span></button>
1
  <div class="malcare9">
2
  <section id="malcare-1">
3
  <div class="malcare-logo-img text-center">
4
+ <img height="70" width="240" src="<?php echo plugins_url("/../img/mc-top-logo.svg", __FILE__); ?>" alt="">
5
  </div>
6
  <div class="container-malcare" id="">
7
  <div class="row">
13
  <input type='hidden' name='bvsrc' value='wpplugin' />
14
  <input type='hidden' name='origin' value='protect' />
15
  <?php echo $this->siteInfoTags(); ?>
16
+ <input type="text" placeholder="Enter your email address to continue" id="email" name="email" class="search" required>
17
  <h5 class="check-box-text mt-2"><input type="checkbox" class="check-box" name="consent" value="1">
18
  <label>I agree to MalCare <a href="https://www.malcare.com/tos" target="_blank" rel="noopener noreferrer">Terms of Service</a> and <a href="https://www.malcare.com/privacy" target="_blank" rel="noopener noreferrer">Privacy Policy</a></label></h5>
19
  <button id="get-started" type="submit" class="e-mail-button"><span class="text-white">Submit</span></button>
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/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
@@ -65,6 +65,60 @@ class BVDBCallback extends BVCallbackBase {
65
  return $result;
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  public function process($request) {
69
  $db = $this->db;
70
  $params = $request->params;
@@ -100,6 +154,31 @@ class BVDBCallback extends BVCallbackBase {
100
  $table = urldecode($params['table']);
101
  $resp = array("create" => $db->showTableCreate($table));
102
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  case "getrowscount":
104
  $table = urldecode($params['table']);
105
  $resp = array("count" => $db->rowsCount($table));
@@ -174,4 +253,4 @@ class BVDBCallback extends BVCallbackBase {
174
  return $resp;
175
  }
176
  }
177
- endif;
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;
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/info.php CHANGED
@@ -211,6 +211,7 @@ class BVInfoCallback extends BVCallbackBase {
211
  $data['protect'] = $settings->getOption('bvptconf');
212
  $data['brand'] = $settings->getOption($this->bvinfo->brand_option);
213
  $data['badgeinfo'] = $settings->getOption($this->bvinfo->badgeinfo);
 
214
  }
215
 
216
  public function dbconf(&$info) {
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
@@ -105,6 +105,10 @@ class BVMiscCallback extends BVCallbackBase {
105
  case "setbvss":
106
  $resp = array("status" => $settings->updateOption('bv_site_settings', $params['bv_site_settings']));
107
  break;
 
 
 
 
108
  default:
109
  $resp = false;
110
  }
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":
css/bvnew.min.css CHANGED
@@ -1 +1 @@
1
- @import url(https://fonts.googleapis.com/css?family=Roboto:400,500);@import url(https://fonts.googleapis.com/css2?family=Noto+Serif&display=swap);.text-center{text-align:center}.text-right{text-align:right}.d-flex{display:flex}.testimonial_subtitle{color:#0aaa7a;font-size:12px}.testimonial_btn{background-color:#373d4b!important;color:#fff!important}.seprator{height:2px;width:56px;background-color:#0aaa7a;margin:7px 0 10px 0}.center-align-dflex{align-items:center;display:flex;justify-content:center;flex-direction:column}.card-title img{height:100px;width:125px}.h-100{height:100%}.mb-2{margin-bottom:20px}.mr-1{margin-right:10px}.mt-1{margin-top:10px}.float-right{float:right}.fw-600{font-weight:600}.malcare-logo-img{margin-top:72px}.search-container label>a{color:red;text-decoration:underline}#malcare-1{padding-top:20px;padding-bottom:70px;background-color:#f6f6ff;height:100%;position:relative}.container-malcare{max-width:1440px;margin:auto}#malcare-1 a:hover{color:red}.text-white{color:#fff!important}a.malcare-top{font-size:14px;line-height:20px;letter-spacing:.25px;font-weight:600;text-decoration-line:underline!important;color:#fff;mix-blend-mode:normal;opacity:.73}#malcare-1 .e-mail-button{background:#7b7afe;border:1px solid #e5e5e5;box-sizing:border-box;padding:25px;max-width:600px;width:100%;border-radius:8px;font-style:normal;font-weight:600;font-size:17px;line-height:1px;text-align:center;letter-spacing:.333333px;color:#4a4a4a}#malcare-1 .heading{font-family:Roboto;font-style:normal;font-weight:500}#malcare-1 .e-mail-button:hover,#malcare-5 .premium-subscription a:hover{color:#3a3a3a}#malcare-1 h4{line-height:24px;font-size:24px}#malcare-1 h2{line-height:28px;font-size:20px}#malcare-1 form img{margin-left:-20px;position:absolute;bottom:-98px;width:100%;max-width:225px}#malcare-1 input.search{background:#fff;border:1px solid rgba(101,99,255,.5);box-sizing:border-box;box-shadow:0 2px 10px rgba(204,203,203,.4);border-radius:8px;padding:25px;max-width:600px;width:100%;font-family:Roboto;font-weight:400;font-size:16px;line-height:10px;letter-spacing:.319444px;color:#a6a6a6;height:52px}#malcare-1 h5.check-box-text{font-style:normal;font-weight:400;font-size:14px;line-height:17px;text-align:center;letter-spacing:.291667px;color:#4a4a4a;margin:15px 5px}#malcare-2 h6.card-subtitle{margin:20px 0 0 0}#malcare-3 .heading-malcare{padding-bottom:20px}#malcare-3 .container-malcare .main-image{margin:10px 10px 100px 10px;padding:10px 10px 10px 10px}.heading-malcare h4{font-family:Roboto;font-weight:500;font-style:normal;font-size:24px;line-height:28px;text-align:center;letter-spacing:.416667px;color:#4a4a4a}.heading-malcare h5{font-family:Roboto;font-weight:400;font-style:normal;font-size:12px;line-height:28px;text-align:center;letter-spacing:.8px;color:#ee5151}input[type="checkbox"]:checked::before{width:2.3rem}input[type="checkbox"]:focus{outline:unset!important}#malcare-1 h5.check-box-text input.check-box{position:relative;width:20px;height:20px;margin:0 0 5px 0}#malcare-2 h1.number-malcare{margin:0;position:absolute;font-size:50px;color:#7683ad;top:110px;left:25px}#malcare-2,#malcare-3,#malcare-4{padding:5px 0;margin:50px 0 50px 0}#malcare-5{padding:30px 0}#malcare-2{padding-top:30px}#malcare-2 h6{font-style:normal;font-weight:700;font-size:20px;line-height:26px;text-align:center;letter-spacing:.333333px;color:#4a4a4a}#malcare-2 p{font-style:normal;font-weight:400;font-size:18px;line-height:22px;text-align:center;letter-spacing:.25px;color:#7683ad}#malcare-3 .embed-responsive{border-radius:10px}#malcare-5 .malcare-testimonial h4{font-size:22px;line-height:36px;margin-top:50px;text-align:center;color:#4a4a4a}#malcare-5 .malcare-testimonial h5.testimonial_subtitle{font-style:normal;font-weight:400;font-size:18px;line-height:36px;text-align:center;color:#4d50a7}#malcare-5 .malcare-testimonial p.testimonial_para{font-style:normal;font-weight:400;font-size:18px;line-height:27px;text-align:center;letter-spacing:.2px;color:#7683ad}.heading-malcare{margin-bottom:30px}#malcare-4 .brand{justify-content:center}#malcare-4 .brand img{margin:0 15px}#malcare-5 ul li{list-style:none}#malcare-5 ul li{font-style:normal;font-weight:400;font-size:18px;line-height:36px;text-align:initial;color:#4d50a7}#malcare-5 h6{font-size:22px;line-height:36px;text-align:center;font-family:AvenirNextLTPro-Regular,sans-serif;color:#4a4a4a}#malcare-5 ul{padding:0}#malcare-5 .premium-subscription a{background:#50e3c2;border:2px solid #17abff;box-sizing:border-box;border-radius:60px;font-style:normal;text-decoration:none;font-weight:600;font-size:24px;outline:0;line-height:31px;text-align:center;letter-spacing:.333333px;padding:20px;color:#4a4a4a}#malcare-5 .subscription{align-items:center;background:#fff;border:1px solid rgba(97,120,238,.487177);box-sizing:border-box;box-shadow:0 17px 40px rgba(217,223,252,.539883);border-radius:19px;overflow:hidden;height:330px}#malcare-5 .premium-subscription{align-items:center;display:flex}.bg-light-green{background-color:rgba(80,227,194,.18)}body.malcare9 a,body.malcare9 h1,body.malcare9 h2,body.malcare9 h3,body.malcare9 h4{font-family:Roboto,sans-serif}body.malcare9 button,body.malcare9 h5,body.malcare9 h6,body.malcare9 p,body.malcare9 ul li a{font-family:Roboto,sans-serif}#malcare-2-1{padding-top:80px;padding-bottom:350px;background:url(../img/malcare-heading-2.svg) no-repeat center;height:100%;background-size:cover;background-position:bottom}#malcare-2-3 .progress.custom-progress .progress-bar{background-color:#777}#malcare-2-3 .progress-heading p{font-size:12px;line-height:41px;text-align:center;color:#4a4a4a}.malcare-3 #malcare-1{padding-top:80px;padding-bottom:130px;background-color:#f6f6ff;height:100%}.color-grey{color:#4a4a4a!important}.color-blue{color:#7683ad!important}#wpcontent{padding:0!important}.malcare-video{padding:10px 35px;background:rgba(255,255,255,.25);border:1px solid #e3ebfd;box-sizing:border-box;border-radius:8px;max-width:40%;font-family:Lato;font-weight:400;font-style:normal;font-size:14px;line-height:17px;color:#7683ad}#malcare-3 #accordion input{display:none}#malcare-3 #accordion{background:#fff;font-family:Roboto;font-style:normal}#malcare-3 #accordion h4{color:#333;font-weight:500;font-size:18px;line-height:24px}#malcare-3 #accordion h5{color:#ff6459;font-weight:400;font-size:11px;line-height:22px;letter-spacing:.5px}#malcare-3 #accordion label{border-radius:8px;display:block;margin-bottom:.125em;padding:.25em 1em;z-index:20}#malcare-3 #accordion label:hover{text-decoration:underline}#malcare-3 #accordion .article{display:none;overflow:hidden;z-index:10;font-weight:400;font-size:14px;line-height:22px;padding:.25em 1em;color:#888}#malcare-3 #accordion input:checked~.acc-card{border:1px solid rgba(101,99,255,.3);box-sizing:border-box;box-shadow:0 2px 8px rgba(229,229,229,.25);border-radius:8px}#malcare-3 #accordion input:checked~.acc-card .article{display:block}#malcare-9{overflow:hidden}#malcare-9 .carousel{padding-top:80px;text-align:center;height:auto;width:100%;margin:auto;position:relative}#malcare-9 .slide h1{font-family:"Noto Serif";font-style:normal;font-weight:400;font-size:144px;line-height:51px;text-align:center;letter-spacing:.9px;color:#7b7afe;margin:20px}#malcare-9 .slide h4{font-family:Roboto;font-style:normal;font-weight:400;font-size:28px;line-height:46px;text-align:center;letter-spacing:.2px;color:#fff;margin:20px}#malcare-9 .slide h5{font-family:Roboto;font-style:normal;font-weight:400;font-size:18px;line-height:21px;text-align:center;letter-spacing:.15px;color:#fff;mix-blend-mode:normal;opacity:.58;margin:20px}#malcare-9 .carousel .slides{width:400%;left:0;padding-left:0;padding-top:1em;list-style:none;position:relative;-webkit-transition:transform 0.5s;-moz-transition:transform 0.5s;-o-transition:transform 0.5s;transition:transform 0.5s}#malcare-9 .carousel .slide .user{position:relative;top:-90px;border-radius:50%;height:140px;width:140px}#malcare-9 .carousel .slide-div{background:#2d3a67;width:100%}#malcare-9 .carousel .slides li{width:25%;position:relative;float:left}#malcare-9 .carousel li p{margin-top:0}#malcare-9 .carousel .slidesNavigation{display:inline-block;list-style:none;margin:40px}#malcare-9 .carousel input{display:none}#malcare-9 .carousel .slidesNavigation label{float:left;margin:6px;display:block;height:10px;width:10px;-webkit-border-radius:50%;border-radius:50%;border:solid 1px #fff;background:#fff;opacity:.4;font-size:0}#radio-1:checked~.slides{transform:translateX(0)}#radio-2:checked~.slides{transform:translateX(-25%)}#radio-3:checked~.slides{transform:translateX(-50%)}#radio-4:checked~.slides{transform:translateX(-75%)}#malcare-9 .carousel #radio-1:checked~.slidesNavigation label#dotForRadio-1,#malcare-9 .carousel #radio-2:checked~.slidesNavigation label#dotForRadio-2,#malcare-9 .carousel #radio-3:checked~.slidesNavigation label#dotForRadio-3,#malcare-9 .carousel #radio-4:checked~.slidesNavigation label#dotForRadio-4{opacity:1}@media (max-width:624px){#malcare-1 h5.check-box-text{font-size:11px!important}#get-started span{display:none}#get-started:before{font-size:13px;content:"Submit"}#malcare-1 h2{font-size:22px}#malcare-1 h4{font-size:20px}.malcare-logo-img img{height:47px;width:161px}#malcare-4 .brand{justify-content:center}#malcare-4 .brand img{margin:20px;display:inline-block}#malcare-1 .search-container{margin-top:20px}#malcare-3 .container-malcare .main-image{margin:10px 10px 100px 10px;padding:10px 10px 10px 10px;width:550px}.malcare-video{max-width:100%}}@media (max-width:1024px){.man-img{display:none}.d-flex{display:inline-block}.malcare-video{margin:auto;margin-bottom:70px}#malcare-1 .e-mail-button{width:80%!important}#malcare-1 input.search{width:80%!important}.malcare-1-container h2{margin-top:70px!important}}@media (min-width:1024px) and (max-width:1367px){#get-started span{display:none}#get-started:before{content:"Submit"}}@media (min-width:768px){.justify-content-center{justify-content:center}}@media (max-width:1440px){.row{margin-left:0!important;margin-right:0!important}}@media (min-width:1440px){.malcare-video{margin:auto}.malcare-testimonial{width:100%;margin-left:auto;margin-right:auto}}
1
+ @import url(https://fonts.googleapis.com/css?family=Roboto:400,500);@import url(https://fonts.googleapis.com/css2?family=Noto+Serif&display=swap);.text-center{text-align:center}.text-right{text-align:right}.d-flex{display:flex}.testimonial_subtitle{color:#0aaa7a;font-size:12px}.testimonial_btn{background-color:#373d4b!important;color:#fff!important}.seprator{height:2px;width:56px;background-color:#0aaa7a;margin:7px 0 10px 0}.center-align-dflex{align-items:center;display:flex;justify-content:center;flex-direction:column}.card-title img{height:100px;width:125px}.h-100{height:100%}.mb-2{margin-bottom:20px}.mr-1{margin-right:10px}.mt-1{margin-top:10px}.float-right{float:right}.fw-600{font-weight:600}.malcare-logo-img{margin-top:72px}.search-container label>a{color:red;text-decoration:underline}#malcare-1{padding-top:20px;padding-bottom:70px;background-color:#f6f6ff;height:100%;position:relative}.container-malcare{max-width:1440px;margin:auto}#malcare-1 a:hover{color:red}.text-white{color:#fff!important}a.malcare-top{font-size:14px;line-height:20px;letter-spacing:.25px;font-weight:600;text-decoration-line:underline!important;color:#fff;mix-blend-mode:normal;opacity:.73}#malcare-1 .e-mail-button{background:#7b7afe;border:1px solid #e5e5e5;box-sizing:border-box;padding:25px;max-width:600px;width:100%;border-radius:8px;font-style:normal;font-weight:600;font-size:17px;line-height:1px;text-align:center;letter-spacing:.333333px;color:#4a4a4a}#malcare-1 .heading{font-family:Roboto;font-style:normal;font-weight:500}#malcare-1 .e-mail-button:hover,#malcare-5 .premium-subscription a:hover{color:#3a3a3a}#malcare-1 h4{line-height:24px;font-size:24px}#malcare-1 h2{line-height:28px;font-size:20px}#malcare-1 form img{margin-left:-20px;position:absolute;bottom:-98px;width:100%;max-width:225px}#malcare-1 input.search{background:#fff;border:1px solid rgba(101,99,255,.5);box-sizing:border-box;box-shadow:0 2px 10px rgba(204,203,203,.4);border-radius:8px;padding:25px;max-width:600px;width:100%;font-family:Roboto;font-weight:400;font-size:16px;line-height:10px;letter-spacing:.319444px;height:52px}#malcare-1 h5.check-box-text{font-style:normal;font-weight:400;font-size:14px;line-height:17px;text-align:center;letter-spacing:.291667px;color:#4a4a4a;margin:15px 5px}#malcare-2 h6.card-subtitle{margin:20px 0 0 0}#malcare-3 .heading-malcare{padding-bottom:20px}#malcare-3 .container-malcare .main-image{margin:5px 10px 100px 10px;padding:0px 10px 10px 10px}.heading-malcare h4{font-family:Roboto;font-weight:500;font-style:normal;font-size:24px;line-height:28px;text-align:center;letter-spacing:.416667px;color:#4a4a4a}.heading-malcare h5{font-family:Roboto;font-weight:400;font-style:normal;font-size:12px;line-height:28px;text-align:center;letter-spacing:.8px;color:#ee5151}input[type="checkbox"]:checked::before{width:2.3rem}input[type="checkbox"]:focus{outline:unset!important}#malcare-1 h5.check-box-text input.check-box{position:relative;width:20px;height:20px;margin:0 0 5px 0}#malcare-2 h1.number-malcare{margin:0;position:absolute;font-size:50px;color:#7683ad;top:110px;left:25px}#malcare-2,#malcare-3,#malcare-4{padding:5px 0;margin:50px 0 50px 0}#malcare-5{padding:30px 0}#malcare-2{padding-top:30px}#malcare-2 h6{font-style:normal;font-weight:700;font-size:20px;line-height:26px;text-align:center;letter-spacing:.333333px;color:#4a4a4a}#malcare-2 p{font-style:normal;font-weight:400;font-size:18px;line-height:22px;text-align:center;letter-spacing:.25px;color:#7683ad}#malcare-3 .embed-responsive{border-radius:10px}#malcare-5 .malcare-testimonial h4{font-size:22px;line-height:36px;margin-top:50px;text-align:center;color:#4a4a4a}#malcare-5 .malcare-testimonial h5.testimonial_subtitle{font-style:normal;font-weight:400;font-size:18px;line-height:36px;text-align:center;color:#4d50a7}#malcare-5 .malcare-testimonial p.testimonial_para{font-style:normal;font-weight:400;font-size:18px;line-height:27px;text-align:center;letter-spacing:.2px;color:#7683ad}.heading-malcare{margin-bottom:30px}#malcare-4 .brand{justify-content:center}#malcare-4 .brand img{margin:0 15px}#malcare-5 ul li{list-style:none}#malcare-5 ul li{font-style:normal;font-weight:400;font-size:18px;line-height:36px;text-align:initial;color:#4d50a7}#malcare-5 h6{font-size:22px;line-height:36px;text-align:center;font-family:AvenirNextLTPro-Regular,sans-serif;color:#4a4a4a}#malcare-5 ul{padding:0}#malcare-5 .premium-subscription a{background:#50e3c2;border:2px solid #17abff;box-sizing:border-box;border-radius:60px;font-style:normal;text-decoration:none;font-weight:600;font-size:24px;outline:0;line-height:31px;text-align:center;letter-spacing:.333333px;padding:20px;color:#4a4a4a}#malcare-5 .subscription{align-items:center;background:#fff;border:1px solid rgba(97,120,238,.487177);box-sizing:border-box;box-shadow:0 17px 40px rgba(217,223,252,.539883);border-radius:19px;overflow:hidden;height:330px}#malcare-5 .premium-subscription{align-items:center;display:flex}.bg-light-green{background-color:rgba(80,227,194,.18)}body.malcare9 a,body.malcare9 h1,body.malcare9 h2,body.malcare9 h3,body.malcare9 h4{font-family:Roboto,sans-serif}body.malcare9 button,body.malcare9 h5,body.malcare9 h6,body.malcare9 p,body.malcare9 ul li a{font-family:Roboto,sans-serif}#malcare-2-1{padding-top:80px;padding-bottom:350px;background:url(../img/malcare-heading-2.svg) no-repeat center;height:100%;background-size:cover;background-position:bottom}#malcare-2-3 .progress.custom-progress .progress-bar{background-color:#777}#malcare-2-3 .progress-heading p{font-size:12px;line-height:41px;text-align:center;color:#4a4a4a}.malcare-3 #malcare-1{padding-top:80px;padding-bottom:130px;background-color:#f6f6ff;height:100%}.color-grey{color:#4a4a4a!important}.color-blue{color:#7683ad!important}#wpcontent{padding:0!important}.malcare-video{padding:10px 35px;background:rgba(255,255,255,.25);border:1px solid #e3ebfd;box-sizing:border-box;border-radius:8px;max-width:40%;font-family:Lato;font-weight:400;font-style:normal;font-size:14px;line-height:17px;color:#7683ad}#malcare-3 #accordion input{display:none}#malcare-3 #accordion{background:#fff;font-family:Roboto;font-style:normal}#malcare-3 #accordion h4{color:#333;font-weight:500;font-size:18px;line-height:24px}#malcare-3 #accordion h5{color:#ff6459;font-weight:400;font-size:11px;line-height:22px;letter-spacing:.5px}#malcare-3 #accordion label{border-radius:8px;display:block;margin-bottom:.125em;padding:.25em 1em;z-index:20}#malcare-3 #accordion label:hover{text-decoration:underline}#malcare-3 #accordion .article{display:none;overflow:hidden;z-index:10;font-weight:400;font-size:14px;line-height:22px;padding:.25em 1em;color:#888}#malcare-3 #accordion input:checked~.acc-card{border:1px solid rgba(101,99,255,.3);box-sizing:border-box;box-shadow:0 2px 8px rgba(229,229,229,.25);border-radius:8px}#malcare-3 #accordion input:checked~.acc-card .article{display:block}#malcare-9{overflow:hidden}#malcare-9 .carousel{padding-top:80px;text-align:center;height:auto;width:100%;margin:auto;position:relative}#malcare-9 .slide h1{font-family:"Noto Serif";font-style:normal;font-weight:400;font-size:144px;line-height:51px;text-align:center;letter-spacing:.9px;color:#7b7afe;margin:20px}#malcare-9 .slide h4{font-family:Roboto;font-style:normal;font-weight:400;font-size:28px;line-height:46px;text-align:center;letter-spacing:.2px;color:#fff;margin:20px}#malcare-9 .slide h5{font-family:Roboto;font-style:normal;font-weight:400;font-size:18px;line-height:21px;text-align:center;letter-spacing:.15px;color:#fff;mix-blend-mode:normal;opacity:.58;margin:20px}#malcare-9 .carousel .slides{width:400%;left:0;padding-left:0;padding-top:1em;list-style:none;position:relative;-webkit-transition:transform 0.5s;-moz-transition:transform 0.5s;-o-transition:transform 0.5s;transition:transform 0.5s}#malcare-9 .carousel .slide .user{position:relative;top:-90px;border-radius:50%;height:140px;width:140px}#malcare-9 .carousel .slide-div{background:#2d3a67;width:100%}#malcare-9 .carousel .slides li{width:25%;position:relative;float:left}#malcare-9 .carousel li p{margin-top:0}#malcare-9 .carousel .slidesNavigation{display:inline-block;list-style:none;margin:40px}#malcare-9 .carousel input{display:none}#malcare-9 .carousel .slidesNavigation label{float:left;margin:6px;display:block;height:10px;width:10px;-webkit-border-radius:50%;border-radius:50%;border:solid 1px #fff;background:#fff;opacity:.4;font-size:0}#radio-1:checked~.slides{transform:translateX(0)}#radio-2:checked~.slides{transform:translateX(-25%)}#radio-3:checked~.slides{transform:translateX(-50%)}#radio-4:checked~.slides{transform:translateX(-75%)}#malcare-9 .carousel #radio-1:checked~.slidesNavigation label#dotForRadio-1,#malcare-9 .carousel #radio-2:checked~.slidesNavigation label#dotForRadio-2,#malcare-9 .carousel #radio-3:checked~.slidesNavigation label#dotForRadio-3,#malcare-9 .carousel #radio-4:checked~.slidesNavigation label#dotForRadio-4{opacity:1}@media (max-width:624px){#malcare-1 h5.check-box-text{font-size:11px!important}#get-started span{display:none}#get-started:before{font-size:13px;content:"Submit"}#malcare-1 h2{font-size:22px}#malcare-1 h4{font-size:20px}.malcare-logo-img img{height:47px;width:161px}#malcare-4 .brand{justify-content:center}#malcare-4 .brand img{margin:20px;display:inline-block}#malcare-1 .search-container{margin-top:20px}#malcare-3 .container-malcare .main-image{margin:5px 10px 100px 10px;padding:0px 10px 10px 10px;width:550px}.malcare-video{max-width:100%}}@media (max-width:1024px){.man-img{display:none}.d-flex{display:inline-block}.malcare-video{margin:auto;margin-bottom:70px}#malcare-1 .e-mail-button{width:80%!important}#malcare-1 input.search{width:80%!important}.malcare-1-container h2{margin-top:70px!important}}@media (min-width:1024px) and (max-width:1367px){#get-started span{display:none}#get-started:before{content:"Submit"}}@media (min-width:768px){.justify-content-center{justify-content:center}}@media (max-width:1440px){.row{margin-left:0!important;margin-right:0!important}}@media (min-width:1440px){.malcare-video{margin:auto}.malcare-testimonial{width:100%;margin-left:auto;margin-right:auto}}
img/mc-top-logo.png DELETED
Binary file
img/mc-top-logo.svg ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svg width="161" height="47" viewBox="0 0 161 47" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M34.0477 29.4566H12.2984C10.6274 29.4566 9.2697 28.0678 9.2697 26.3556C9.2697 24.6437 10.6274 23.2552 12.2984 23.2552H34.0477C35.7211 23.2552 37.0788 24.6437 37.0788 26.3556C37.0788 28.0678 35.7211 29.4566 34.0477 29.4566Z" fill="#2D3A67"/>
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M0 25.9682C0 27.4661 1.21077 28.6814 2.70351 28.6814C4.19562 28.6814 5.40732 27.4661 5.40732 25.9682C5.40732 24.4696 4.19562 23.2552 2.70351 23.2552C1.21077 23.2552 0 24.4696 0 25.9682Z" fill="#FF6459"/>
4
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M34.0477 37.9835H12.2984C10.6274 37.9835 9.2697 36.5945 9.2697 34.8821C9.2697 33.1714 10.6274 31.7821 12.2984 31.7821H34.0477C35.7211 31.7821 37.0788 33.1714 37.0788 34.8821C37.0788 36.5945 35.7211 37.9835 34.0477 37.9835Z" fill="#2D3A67"/>
5
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M0 34.4952C0 35.9933 1.21077 37.2083 2.70351 37.2083C4.19562 37.2083 5.40732 35.9933 5.40732 34.4952C5.40732 32.9972 4.19562 31.7821 2.70351 31.7821C1.21077 31.7821 0 32.9972 0 34.4952Z" fill="#FF6459"/>
6
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M34.0477 46.5104H12.2984C10.6274 46.5104 9.2697 45.1229 9.2697 43.4097C9.2697 41.6973 10.6274 40.309 12.2984 40.309H34.0477C35.7211 40.309 37.0788 41.6973 37.0788 43.4097C37.0788 45.1229 35.7211 46.5104 34.0477 46.5104Z" fill="#2D3A67"/>
7
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M0 43.7959C0 45.296 1.21077 46.5104 2.70351 46.5104C4.19562 46.5104 5.40732 45.296 5.40732 43.7959C5.40732 42.2986 4.19562 41.0842 2.70351 41.0842C1.21077 41.0842 0 42.2986 0 43.7959Z" fill="#FF6459"/>
8
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M33.4285 20.9297C31.8373 20.9297 30.5473 19.6484 30.5473 18.0645C30.5473 11.2643 24.9877 5.72997 18.1532 5.72997C11.3166 5.72997 5.75866 11.2643 5.75866 18.0645C5.75866 19.6484 4.47041 20.9297 2.8795 20.9297C1.28825 20.9297 0 19.6484 0 18.0645C0 8.1037 8.14228 0 18.1532 0C28.1637 0 36.3063 8.1037 36.3063 18.0645C36.3063 19.6484 35.0163 20.9297 33.4285 20.9297Z" fill="#2D3A67"/>
9
+ <path d="M64.766 32C64.9319 32.32 65.0831 32.655 65.2197 33.005C65.3661 33.345 65.5076 33.69 65.6442 34.04C65.7808 33.68 65.9223 33.325 66.0687 32.975C66.215 32.625 66.3711 32.29 66.537 31.97L72.8014 19.955C72.8794 19.805 72.9575 19.685 73.0356 19.595C73.1234 19.505 73.2161 19.44 73.3137 19.4C73.421 19.36 73.5381 19.335 73.6649 19.325C73.7918 19.315 73.943 19.31 74.1187 19.31H77.0898V41H73.621V26.99C73.621 26.73 73.6259 26.445 73.6357 26.135C73.6552 25.825 73.6796 25.51 73.7088 25.19L67.3127 37.49C67.1664 37.77 66.9761 37.99 66.7419 38.15C66.5077 38.3 66.2345 38.375 65.9223 38.375H65.3807C65.0685 38.375 64.7953 38.3 64.5611 38.15C64.3269 37.99 64.1367 37.77 63.9903 37.49L57.5064 25.145C57.5454 25.475 57.5698 25.8 57.5796 26.12C57.5991 26.43 57.6088 26.72 57.6088 26.99V41H54.14V19.31H57.1112C57.2868 19.31 57.4381 19.315 57.5649 19.325C57.6918 19.335 57.804 19.36 57.9016 19.4C58.0089 19.44 58.1065 19.505 58.1943 19.595C58.2821 19.685 58.3651 19.805 58.4431 19.955L64.766 32Z" fill="#2D3A67"/>
10
+ <path d="M93.3075 41H91.6829C91.3414 41 91.0731 40.95 90.8779 40.85C90.6828 40.74 90.5364 40.525 90.4388 40.205L90.1168 39.11C89.7363 39.46 89.3606 39.77 88.9898 40.04C88.6288 40.3 88.2531 40.52 87.8628 40.7C87.4725 40.88 87.0578 41.015 86.6187 41.105C86.1796 41.195 85.6918 41.24 85.1551 41.24C84.5208 41.24 83.9354 41.155 83.3987 40.985C82.8621 40.805 82.3986 40.54 82.0083 40.19C81.6277 39.84 81.3301 39.405 81.1154 38.885C80.9008 38.365 80.7934 37.76 80.7934 37.07C80.7934 36.49 80.9398 35.92 81.2325 35.36C81.535 34.79 82.0327 34.28 82.7254 33.83C83.4182 33.37 84.3403 32.99 85.4917 32.69C86.6431 32.39 88.0726 32.22 89.7802 32.18V31.28C89.7802 30.25 89.5655 29.49 89.1362 29C88.7166 28.5 88.1019 28.25 87.292 28.25C86.7065 28.25 86.2187 28.32 85.8284 28.46C85.4381 28.6 85.0965 28.76 84.8038 28.94C84.5208 29.11 84.2574 29.265 84.0134 29.405C83.7695 29.545 83.5012 29.615 83.2084 29.615C82.9645 29.615 82.7547 29.55 82.5791 29.42C82.4034 29.29 82.262 29.13 82.1546 28.94L81.496 27.755C83.2231 26.135 85.3063 25.325 87.7457 25.325C88.6239 25.325 89.4045 25.475 90.0875 25.775C90.7803 26.065 91.3658 26.475 91.8439 27.005C92.322 27.525 92.6831 28.15 92.927 28.88C93.1807 29.61 93.3075 30.41 93.3075 31.28V41ZM86.2821 38.69C86.6529 38.69 86.9944 38.655 87.3066 38.585C87.6189 38.515 87.9116 38.41 88.1848 38.27C88.4678 38.13 88.7361 37.96 88.9898 37.76C89.2533 37.55 89.5167 37.305 89.7802 37.025V34.43C88.7264 34.48 87.8433 34.575 87.131 34.715C86.4284 34.845 85.8625 35.015 85.4332 35.225C85.0038 35.435 84.6965 35.68 84.5111 35.96C84.3354 36.24 84.2476 36.545 84.2476 36.875C84.2476 37.525 84.433 37.99 84.8038 38.27C85.1844 38.55 85.6771 38.69 86.2821 38.69Z" fill="#2D3A67"/>
11
+ <path d="M101.102 18.71V41H97.4868V18.71H101.102Z" fill="#2D3A67"/>
12
+ <path d="M116.143 28.865C116.036 29.005 115.928 29.115 115.821 29.195C115.723 29.275 115.577 29.315 115.382 29.315C115.196 29.315 115.016 29.26 114.84 29.15C114.665 29.03 114.455 28.9 114.211 28.76C113.967 28.61 113.674 28.48 113.333 28.37C113.001 28.25 112.586 28.19 112.089 28.19C111.454 28.19 110.898 28.31 110.42 28.55C109.942 28.78 109.542 29.115 109.22 29.555C108.908 29.995 108.673 30.53 108.517 31.16C108.361 31.78 108.283 32.485 108.283 33.275C108.283 34.095 108.366 34.825 108.532 35.465C108.708 36.105 108.956 36.645 109.278 37.085C109.6 37.515 109.991 37.845 110.449 38.075C110.908 38.295 111.425 38.405 112.001 38.405C112.576 38.405 113.04 38.335 113.391 38.195C113.752 38.045 114.055 37.885 114.299 37.715C114.543 37.535 114.752 37.375 114.928 37.235C115.113 37.085 115.318 37.01 115.543 37.01C115.835 37.01 116.055 37.125 116.201 37.355L117.241 38.705C116.841 39.185 116.406 39.59 115.938 39.92C115.47 40.24 114.982 40.5 114.474 40.7C113.977 40.89 113.46 41.025 112.923 41.105C112.386 41.185 111.854 41.225 111.327 41.225C110.401 41.225 109.527 41.05 108.708 40.7C107.888 40.34 107.171 39.82 106.556 39.14C105.951 38.46 105.468 37.63 105.107 36.65C104.756 35.66 104.58 34.535 104.58 33.275C104.58 32.145 104.736 31.1 105.048 30.14C105.37 29.17 105.839 28.335 106.454 27.635C107.068 26.925 107.829 26.37 108.737 25.97C109.644 25.57 110.688 25.37 111.869 25.37C112.991 25.37 113.972 25.555 114.811 25.925C115.66 26.295 116.421 26.825 117.094 27.515L116.143 28.865Z" fill="#2D3A67"/>
13
+ <path d="M131.698 41H130.074C129.732 41 129.464 40.95 129.269 40.85C129.073 40.74 128.927 40.525 128.83 40.205L128.508 39.11C128.127 39.46 127.751 39.77 127.381 40.04C127.02 40.3 126.644 40.52 126.254 40.7C125.863 40.88 125.449 41.015 125.009 41.105C124.57 41.195 124.082 41.24 123.546 41.24C122.912 41.24 122.326 41.155 121.789 40.985C121.253 40.805 120.789 40.54 120.399 40.19C120.018 39.84 119.721 39.405 119.506 38.885C119.291 38.365 119.184 37.76 119.184 37.07C119.184 36.49 119.331 35.92 119.623 35.36C119.926 34.79 120.423 34.28 121.116 33.83C121.809 33.37 122.731 32.99 123.882 32.69C125.034 32.39 126.463 32.22 128.171 32.18V31.28C128.171 30.25 127.956 29.49 127.527 29C127.107 28.5 126.493 28.25 125.683 28.25C125.097 28.25 124.609 28.32 124.219 28.46C123.829 28.6 123.487 28.76 123.195 28.94C122.912 29.11 122.648 29.265 122.404 29.405C122.16 29.545 121.892 29.615 121.599 29.615C121.355 29.615 121.145 29.55 120.97 29.42C120.794 29.29 120.653 29.13 120.545 28.94L119.887 27.755C121.614 26.135 123.697 25.325 126.136 25.325C127.015 25.325 127.795 25.475 128.478 25.775C129.171 26.065 129.757 26.475 130.235 27.005C130.713 27.525 131.074 28.15 131.318 28.88C131.571 29.61 131.698 30.41 131.698 31.28V41ZM124.673 38.69C125.044 38.69 125.385 38.655 125.697 38.585C126.01 38.515 126.302 38.41 126.576 38.27C126.859 38.13 127.127 37.96 127.381 37.76C127.644 37.55 127.907 37.305 128.171 37.025V34.43C127.117 34.48 126.234 34.575 125.522 34.715C124.819 34.845 124.253 35.015 123.824 35.225C123.395 35.435 123.087 35.68 122.902 35.96C122.726 36.24 122.638 36.545 122.638 36.875C122.638 37.525 122.824 37.99 123.195 38.27C123.575 38.55 124.068 38.69 124.673 38.69Z" fill="#2D3A67"/>
14
+ <path d="M135.643 41V25.61H137.766C138.136 25.61 138.395 25.68 138.541 25.82C138.688 25.96 138.785 26.2 138.834 26.54L139.054 28.4C139.59 27.45 140.22 26.7 140.942 26.15C141.664 25.6 142.474 25.325 143.371 25.325C144.113 25.325 144.728 25.5 145.216 25.85L144.747 28.625C144.718 28.805 144.654 28.935 144.557 29.015C144.459 29.085 144.328 29.12 144.162 29.12C144.015 29.12 143.815 29.085 143.562 29.015C143.308 28.945 142.971 28.91 142.552 28.91C141.8 28.91 141.156 29.125 140.62 29.555C140.083 29.975 139.629 30.595 139.259 31.415V41H135.643Z" fill="#2D3A67"/>
15
+ <path d="M154.189 25.37C155.135 25.37 156.004 25.525 156.794 25.835C157.594 26.145 158.282 26.6 158.858 27.2C159.433 27.79 159.882 28.52 160.204 29.39C160.526 30.25 160.687 31.235 160.687 32.345C160.687 32.625 160.673 32.86 160.643 33.05C160.624 33.23 160.58 33.375 160.512 33.485C160.453 33.585 160.37 33.66 160.263 33.71C160.155 33.75 160.019 33.77 159.853 33.77H150.574C150.681 35.35 151.096 36.51 151.818 37.25C152.54 37.99 153.496 38.36 154.686 38.36C155.272 38.36 155.774 38.29 156.194 38.15C156.623 38.01 156.994 37.855 157.306 37.685C157.628 37.515 157.906 37.36 158.141 37.22C158.384 37.08 158.619 37.01 158.843 37.01C158.989 37.01 159.116 37.04 159.224 37.1C159.331 37.16 159.424 37.245 159.502 37.355L160.556 38.705C160.155 39.185 159.707 39.59 159.209 39.92C158.711 40.24 158.189 40.5 157.643 40.7C157.106 40.89 156.555 41.025 155.989 41.105C155.433 41.185 154.891 41.225 154.364 41.225C153.32 41.225 152.349 41.05 151.452 40.7C150.554 40.34 149.773 39.815 149.11 39.125C148.446 38.425 147.924 37.565 147.544 36.545C147.163 35.515 146.973 34.325 146.973 32.975C146.973 31.925 147.139 30.94 147.471 30.02C147.802 29.09 148.276 28.285 148.89 27.605C149.515 26.915 150.271 26.37 151.159 25.97C152.057 25.57 153.067 25.37 154.189 25.37ZM154.262 28.025C153.208 28.025 152.384 28.33 151.788 28.94C151.193 29.55 150.813 30.415 150.647 31.535H157.438C157.438 31.055 157.375 30.605 157.248 30.185C157.121 29.755 156.926 29.38 156.662 29.06C156.399 28.74 156.067 28.49 155.667 28.31C155.267 28.12 154.799 28.025 154.262 28.025Z" fill="#2D3A67"/>
16
+ </svg>
info.php CHANGED
@@ -4,21 +4,24 @@ if (!defined('ABSPATH')) exit;
4
  if (!class_exists('MCInfo')) :
5
  class MCInfo {
6
  public $settings;
 
7
  public $plugname = 'malcare';
8
  public $brandname = 'MalCare';
9
  public $badgeinfo = 'mcbadge';
10
  public $ip_header_option = 'mcipheader';
11
  public $brand_option = 'mcbrand';
12
- public $version = '4.53';
13
  public $webpage = 'https://www.malcare.com';
14
  public $appurl = 'https://app.malcare.com';
15
  public $slug = 'malcare-security/malcare.php';
16
  public $plug_redirect = 'mcredirect';
17
  public $logo = '../img/logo.png';
18
  public $brand_icon = '/img/icon.png';
 
19
 
20
  public function __construct($settings) {
21
  $this->settings = $settings;
 
22
  }
23
 
24
  public function canSetCWBranding() {
@@ -93,6 +96,14 @@ if ($bvinfo->canSetCWBranding()) {
93
  $this->isActivePlugin();
94
  }
95
 
 
 
 
 
 
 
 
 
96
  public function isActivateRedirectSet() {
97
  return ($this->settings->getOption($this->plug_redirect) === 'yes') ? true : false;
98
  }
4
  if (!class_exists('MCInfo')) :
5
  class MCInfo {
6
  public $settings;
7
+ public $config;
8
  public $plugname = 'malcare';
9
  public $brandname = 'MalCare';
10
  public $badgeinfo = 'mcbadge';
11
  public $ip_header_option = 'mcipheader';
12
  public $brand_option = 'mcbrand';
13
+ public $version = '4.54';
14
  public $webpage = 'https://www.malcare.com';
15
  public $appurl = 'https://app.malcare.com';
16
  public $slug = 'malcare-security/malcare.php';
17
  public $plug_redirect = 'mcredirect';
18
  public $logo = '../img/logo.png';
19
  public $brand_icon = '/img/icon.png';
20
+ public $services_option_name = 'mcconfig';
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() {
96
  $this->isActivePlugin();
97
  }
98
 
99
+ public function isServiceActive($service) {
100
+ $bvconfig = $this->config;
101
+ if ($bvconfig && array_key_exists('services', $bvconfig)) {
102
+ return in_array($service, $bvconfig['services']) && $this->isActivePlugin();
103
+ }
104
+ return false;
105
+ }
106
+
107
  public function isActivateRedirectSet() {
108
  return ($this->settings->getOption($this->plug_redirect) === 'yes') ? true : false;
109
  }
malcare.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: https://www.malcare.com
5
  Description: MalCare Security - Free Malware Scanner, Protection & Security for WordPress
6
  Author: MalCare Security
7
  Author URI: https://www.malcare.com
8
- Version: 4.53
9
  Network: True
10
  */
11
 
@@ -146,5 +146,12 @@ if ((array_key_exists('bvplugname', $_REQUEST)) && ($_REQUEST['bvplugname'] == "
146
  }
147
 
148
  ##DYNSYNCMODULE##
 
 
 
 
 
 
 
149
  ##WPAUTOUPDATEBLOCKMODULE##
150
  }
5
  Description: MalCare Security - Free Malware Scanner, Protection & Security for WordPress
6
  Author: MalCare Security
7
  Author URI: https://www.malcare.com
8
+ Version: 4.54
9
  Network: True
10
  */
11
 
146
  }
147
 
148
  ##DYNSYNCMODULE##
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
  ##WPAUTOUPDATEBLOCKMODULE##
157
  }
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) {
@@ -216,12 +224,12 @@ class BVFW {
216
 
217
  if ($this->request->getMethod() === 'POST' &&
218
  preg_match('/(admin-ajax.php|admin-post.php)$/', $this->request->getPath())) {
219
- $result += $this->profileRequestInfo(array("action" => $this->request->getBody('action')),
220
  true, 'BODY[');
221
  }
222
- $result += $this->profileRequestInfo($this->request->getBody(),
223
  $this->config->isReqProfilingModeDebug(), 'BODY[');
224
- $result += $this->profileRequestInfo($this->request->getQueryString(),
225
  true, 'GET[');
226
  $result += $this->profileRequestInfo($this->request->getFiles(),
227
  true, 'FILES[');
@@ -234,6 +242,13 @@ class BVFW {
234
  if ($this->isBlacklistedIP()) {
235
  $this->terminateRequest(BVWPRequest::BLACKLISTED);
236
  }
 
 
 
 
 
 
 
237
  }
238
  }
239
 
@@ -344,13 +359,69 @@ class BVFW {
344
  $result[$key]["file"] = true;
345
  }
346
 
347
- if ($this->matchCount(BVFW::SQLIREGEX, $value) >= 2) {
348
  $result[$key]["sql"] = true;
349
  }
 
 
 
 
 
 
 
 
350
  }
351
  }
352
  }
353
  return $result;
354
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
  }
356
  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) {
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
 
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
@@ -40,7 +40,8 @@ class BVProtect {
40
  $fwLogger = new BVLogger($this->db, BVFWConfig::$requests_table);
41
 
42
  $fwConfHash = array_key_exists('fw', $config) ? $config['fw'] : array();
43
- $fw = new BVFW($fwLogger, $fwConfHash, $ip, $bvinfo, $bvipstore);
 
44
 
45
  if ($fw->isActive()) {
46
 
@@ -147,5 +148,13 @@ class BVProtect {
147
  public function get_contdir() {
148
  return defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR . "/" : ABSPATH . "wp-content/";
149
  }
 
 
 
 
 
 
 
 
150
  }
151
  endif;
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
 
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://www.malcare.com
6
  Requires at least: 4.0
7
  Tested up to: 5.6
8
  Requires PHP: 5.4.0
9
- Stable tag: 4.53
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
 
@@ -397,6 +397,13 @@ These are available on our website: [Terms of Service](https://www.malcare.com/t
397
  8. MalCare’s Uptime Monitoring notifies if a website goes down so that you can handle the situation before starting to lose visitors.
398
 
399
  == CHANGELOG ==
 
 
 
 
 
 
 
400
  = 4.53 =
401
  * New UI for registration page
402
  * Bug Fixes
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
 
397
  8. MalCare’s Uptime Monitoring notifies if a website goes down so that you can handle the situation before starting to lose visitors.
398
 
399
  == CHANGELOG ==
400
+ = 4.54 =
401
+ * Added Support For Multi Table Callbacks
402
+ * Added Firewall Rule Evaluator
403
+ * Added Activity Logs feature
404
+ * Minor Improvements
405
+
406
+
407
  = 4.53 =
408
  * New UI for registration page
409
  * Bug Fixes
wp_actions.php CHANGED
@@ -38,7 +38,7 @@ if (!class_exists('MCWPAction')) :
38
  public static function uninstall() {
39
  do_action('clear_pt_config');
40
  do_action('clear_ip_store');
41
- ##CLEARDYNSYNCCONFIG##
42
  }
43
 
44
  public function footerHandler() {
38
  public static function uninstall() {
39
  do_action('clear_pt_config');
40
  do_action('clear_ip_store');
41
+ ##CLEARDYNSYNCCONFIG##
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 = MCAccount::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;