Version Description
- Robust write callbacks
- Improved and Robust prepend in Firewall Support
- Without FTP cleanup and restore support
Download this release
Release Info
| Developer | ritesh.soni36 |
| Plugin | |
| Version | 4.2 |
| Comparing to | |
| See all releases | |
Code changes from version 3.8 to 4.2
- account.php +5 -1
- callback/handler.php +5 -1
- callback/request.php +2 -2
- callback/wings/fs.php +1 -49
- callback/wings/fs_write.php +453 -0
- callback/wings/info.php +23 -0
- callback/wings/protect.php +1 -397
- info.php +1 -1
- malcare.php +2 -2
- readme.txt +6 -1
account.php
CHANGED
|
@@ -42,6 +42,10 @@ if (!class_exists('MCAccount')) :
|
|
| 42 |
return $str;
|
| 43 |
}
|
| 44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
public static function apiPublicAccount($settings) {
|
| 46 |
$pubkey = $settings->getOption(self::$api_public_key);
|
| 47 |
return self::find($settings, $pubkey);
|
|
@@ -179,4 +183,4 @@ if (!class_exists('MCAccount')) :
|
|
| 179 |
return array_key_exists($pubkey, $accounts);
|
| 180 |
}
|
| 181 |
}
|
| 182 |
-
endif;
|
| 42 |
return $str;
|
| 43 |
}
|
| 44 |
|
| 45 |
+
public static function sanitizeKey($key) {
|
| 46 |
+
return preg_replace('/[^a-zA-Z0-9_\-]/', '', $key);
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
public static function apiPublicAccount($settings) {
|
| 50 |
$pubkey = $settings->getOption(self::$api_public_key);
|
| 51 |
return self::find($settings, $pubkey);
|
| 183 |
return array_key_exists($pubkey, $accounts);
|
| 184 |
}
|
| 185 |
}
|
| 186 |
+
endif;
|
callback/handler.php
CHANGED
|
@@ -84,6 +84,10 @@ if (!class_exists('BVCallbackHandler')) :
|
|
| 84 |
require_once dirname( __FILE__ ) . '/wings/account.php';
|
| 85 |
$module = new BVAccountCallback($this);
|
| 86 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
default:
|
| 88 |
require_once dirname( __FILE__ ) . '/wings/misc.php';
|
| 89 |
$module = new BVMiscCallback($this);
|
|
@@ -104,4 +108,4 @@ if (!class_exists('BVCallbackHandler')) :
|
|
| 104 |
return 1;
|
| 105 |
}
|
| 106 |
}
|
| 107 |
-
endif;
|
| 84 |
require_once dirname( __FILE__ ) . '/wings/account.php';
|
| 85 |
$module = new BVAccountCallback($this);
|
| 86 |
break;
|
| 87 |
+
case 'fswrt':
|
| 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);
|
| 108 |
return 1;
|
| 109 |
}
|
| 110 |
}
|
| 111 |
+
endif;
|
callback/request.php
CHANGED
|
@@ -89,7 +89,7 @@ if (!class_exists('BVCallbackRequest')) :
|
|
| 89 |
if (array_key_exists('bvprms', $in_params) && isset($in_params['bvprms']) &&
|
| 90 |
array_key_exists('bvprmsmac', $in_params) && isset($in_params['bvprmsmac'])) {
|
| 91 |
$digest_algo = 'SHA1';
|
| 92 |
-
$sent_mac = $in_params['bvprmsmac'];
|
| 93 |
|
| 94 |
if (array_key_exists('bvprmshshalgo', $in_params) && isset($in_params['bvprmshshalgo'])) {
|
| 95 |
$digest_algo = $in_params['bvprmshshalgo'];
|
|
@@ -176,4 +176,4 @@ if (!class_exists('BVCallbackRequest')) :
|
|
| 176 |
return $data;
|
| 177 |
}
|
| 178 |
}
|
| 179 |
-
endif;
|
| 89 |
if (array_key_exists('bvprms', $in_params) && isset($in_params['bvprms']) &&
|
| 90 |
array_key_exists('bvprmsmac', $in_params) && isset($in_params['bvprmsmac'])) {
|
| 91 |
$digest_algo = 'SHA1';
|
| 92 |
+
$sent_mac = MCAccount::sanitizeKey($in_params['bvprmsmac']);
|
| 93 |
|
| 94 |
if (array_key_exists('bvprmshshalgo', $in_params) && isset($in_params['bvprmshshalgo'])) {
|
| 95 |
$digest_algo = $in_params['bvprmshshalgo'];
|
| 176 |
return $data;
|
| 177 |
}
|
| 178 |
}
|
| 179 |
+
endif;
|
callback/wings/fs.php
CHANGED
|
@@ -12,8 +12,6 @@ class BVFSCallback extends BVCallbackBase {
|
|
| 12 |
|
| 13 |
public function __construct($callback_handler) {
|
| 14 |
$this->account = $callback_handler->account;
|
| 15 |
-
$this->siteinfo = $callback_handler->siteinfo;
|
| 16 |
-
$this->bvinfo = $callback_handler->bvinfo;
|
| 17 |
}
|
| 18 |
|
| 19 |
function fileStat($relfile) {
|
|
@@ -236,53 +234,11 @@ class BVFSCallback extends BVCallbackBase {
|
|
| 236 |
return $result;
|
| 237 |
}
|
| 238 |
|
| 239 |
-
function mkdir($path, $permissions) {
|
| 240 |
-
$result = array();
|
| 241 |
-
$path = ABSPATH.$path;
|
| 242 |
-
|
| 243 |
-
if (!file_exists($path)) {
|
| 244 |
-
if (!mkdir($path)) {
|
| 245 |
-
$result['status'] = 'Error';
|
| 246 |
-
$result['message'] = 'UNABLE_TO_CREATE_DIR';
|
| 247 |
-
}
|
| 248 |
-
} else {
|
| 249 |
-
$result['already_exists'] = true;
|
| 250 |
-
}
|
| 251 |
-
|
| 252 |
-
if (file_exists($path)) {
|
| 253 |
-
$result['exists'] = true;
|
| 254 |
-
|
| 255 |
-
if (chmod($path, $permissions)) {
|
| 256 |
-
$result['status'] = 'Done';
|
| 257 |
-
} else {
|
| 258 |
-
$result['status'] = 'Error';
|
| 259 |
-
$result['message'] = "UNABLE_TO_SET_PERMISSIONS";
|
| 260 |
-
}
|
| 261 |
-
}
|
| 262 |
-
|
| 263 |
-
return $result;
|
| 264 |
-
}
|
| 265 |
-
|
| 266 |
function process($request) {
|
| 267 |
$params = $request->params;
|
| 268 |
$stream_init_info = BVStream::startStream($this->account, $request);
|
| 269 |
|
| 270 |
-
|
| 271 |
-
if(array_key_exists('initdir', $params)) {
|
| 272 |
-
return $stream_init_info;
|
| 273 |
-
}
|
| 274 |
-
|
| 275 |
-
if (array_key_exists('files', $params)) {
|
| 276 |
-
$files = $params['files'];
|
| 277 |
-
|
| 278 |
-
foreach($files as $file) {
|
| 279 |
-
if (!in_array($file, BVFSCallback::$cwAllowedFiles)) {
|
| 280 |
-
return $stream_init_info;
|
| 281 |
-
}
|
| 282 |
-
}
|
| 283 |
-
}
|
| 284 |
-
}
|
| 285 |
-
|
| 286 |
|
| 287 |
if (array_key_exists('stream', $stream_init_info)) {
|
| 288 |
$this->stream = $stream_init_info['stream'];
|
|
@@ -361,10 +317,6 @@ class BVFSCallback extends BVCallbackBase {
|
|
| 361 |
$withContent = array_key_exists('withcontent', $params) ? $params['withcontent'] : true;
|
| 362 |
$resp = array("files_content" => $this->getFilesContent($files, $withContent));
|
| 363 |
break;
|
| 364 |
-
case "mkdr":
|
| 365 |
-
$permissions = array_key_exists('permissions', $params) ? $params['permissions'] : 0777;
|
| 366 |
-
$resp = array('mkdir' => $this->mkdir($params['path'], $permissions));
|
| 367 |
-
break;
|
| 368 |
default:
|
| 369 |
$resp = false;
|
| 370 |
}
|
| 12 |
|
| 13 |
public function __construct($callback_handler) {
|
| 14 |
$this->account = $callback_handler->account;
|
|
|
|
|
|
|
| 15 |
}
|
| 16 |
|
| 17 |
function fileStat($relfile) {
|
| 234 |
return $result;
|
| 235 |
}
|
| 236 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
function process($request) {
|
| 238 |
$params = $request->params;
|
| 239 |
$stream_init_info = BVStream::startStream($this->account, $request);
|
| 240 |
|
| 241 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
|
| 243 |
if (array_key_exists('stream', $stream_init_info)) {
|
| 244 |
$this->stream = $stream_init_info['stream'];
|
| 317 |
$withContent = array_key_exists('withcontent', $params) ? $params['withcontent'] : true;
|
| 318 |
$resp = array("files_content" => $this->getFilesContent($files, $withContent));
|
| 319 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
default:
|
| 321 |
$resp = false;
|
| 322 |
}
|
callback/wings/fs_write.php
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
if (!defined('ABSPATH')) exit;
|
| 4 |
+
if (!class_exists('BVFSWriteCallback')) :
|
| 5 |
+
|
| 6 |
+
class BVFSWriteCallback extends BVCallbackBase {
|
| 7 |
+
|
| 8 |
+
const MEGABYTE = 1024 * 1024;
|
| 9 |
+
|
| 10 |
+
public function __construct() {
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
public function removeFiles($files) {
|
| 14 |
+
$result = array();
|
| 15 |
+
|
| 16 |
+
foreach($files as $file) {
|
| 17 |
+
$file_result = array();
|
| 18 |
+
|
| 19 |
+
if (file_exists($file)) {
|
| 20 |
+
|
| 21 |
+
$file_result['status'] = unlink($file);
|
| 22 |
+
if ($file_result['status'] === false) {
|
| 23 |
+
$file_result['error'] = "UNLINK_FAILED";
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
} else {
|
| 27 |
+
$file_result['status'] = true;
|
| 28 |
+
$file_result['error'] = "NOT_PRESENT";
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
$result[$file] = $file_result;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
$result['status'] = true;
|
| 35 |
+
return $result;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
public function makeDirs($dirs) {
|
| 39 |
+
$result = array();
|
| 40 |
+
|
| 41 |
+
foreach($dirs as $dir) {
|
| 42 |
+
$dir_result = array();
|
| 43 |
+
|
| 44 |
+
if (file_exists($dir)) {
|
| 45 |
+
|
| 46 |
+
if (is_dir($dir)) {
|
| 47 |
+
$dir_result['status'] = true;
|
| 48 |
+
$dir_result['message'] = "DIR_ALREADY_PRESENT";
|
| 49 |
+
} else {
|
| 50 |
+
$dir_result['status'] = false;
|
| 51 |
+
$dir_result['error'] = "FILE_PRESENT_IN_PLACE_OF_DIR";
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
} else {
|
| 55 |
+
|
| 56 |
+
$dir_result['status'] = mkdir($dir);
|
| 57 |
+
if ($dir_result['status'] === false) {
|
| 58 |
+
$dir_result['error'] = "MKDIR_FAILED";
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
$result[$dir] = $dir_result;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
$result['status'] = true;
|
| 67 |
+
return $result;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public function removeDirs($dirs) {
|
| 71 |
+
$result = array();
|
| 72 |
+
|
| 73 |
+
foreach($dirs as $dir) {
|
| 74 |
+
$dir_result = array();
|
| 75 |
+
|
| 76 |
+
if (is_dir($dir) && !is_link($dir)) {
|
| 77 |
+
|
| 78 |
+
if ($this->isEmptyDir($dir)) {
|
| 79 |
+
|
| 80 |
+
$dir_result['status'] = rmdir($dir);
|
| 81 |
+
if ($dir_result['status'] === false) {
|
| 82 |
+
$dir_result['error'] = "RMDIR_FAILED";
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
} else {
|
| 86 |
+
$dir_result['status'] = false;
|
| 87 |
+
$dir_result['error'] = "NOT_EMPTY";
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
} else {
|
| 91 |
+
$dir_result['status'] = false;
|
| 92 |
+
$dir_result['error'] = "NOT_DIR";
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
$result[$dir] = $dir_result;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
$result['status'] = true;
|
| 99 |
+
return $result;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
public function isEmptyDir($dir) {
|
| 103 |
+
$handle = opendir($dir);
|
| 104 |
+
|
| 105 |
+
while (false !== ($entry = readdir($handle))) {
|
| 106 |
+
if ($entry != "." && $entry != "..") {
|
| 107 |
+
closedir($handle);
|
| 108 |
+
return false;
|
| 109 |
+
}
|
| 110 |
+
}
|
| 111 |
+
closedir($handle);
|
| 112 |
+
|
| 113 |
+
return true;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
public function doChmod($path_infos) {
|
| 117 |
+
$result = array();
|
| 118 |
+
|
| 119 |
+
foreach($path_infos as $path => $mode) {
|
| 120 |
+
$path_result = array();
|
| 121 |
+
|
| 122 |
+
if (file_exists($path)) {
|
| 123 |
+
|
| 124 |
+
$path_result['status'] = chmod($path, $mode);
|
| 125 |
+
if ($path_result['status'] === false) {
|
| 126 |
+
$path_result['error'] = "CHMOD_FAILED";
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
} else {
|
| 130 |
+
$path_result['status'] = false;
|
| 131 |
+
$path_result['error'] = "NOT_FOUND";
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
$result[$path] = $path_result;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
$result['status'] = true;
|
| 138 |
+
return $result;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
public function concatFiles($ifiles, $ofile, $bsize, $offset) {
|
| 142 |
+
if (($offset !== 0) && (!file_exists($ofile))) {
|
| 143 |
+
return array(
|
| 144 |
+
'status' => false,
|
| 145 |
+
'error' => 'OFILE_NOT_FOUND_BEFORE_CONCAT'
|
| 146 |
+
);
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
if (file_exists($ofile) && ($offset !== 0)) {
|
| 150 |
+
$handle = fopen($ofile, 'rb+');
|
| 151 |
+
} else {
|
| 152 |
+
$handle = fopen($ofile, 'wb+');
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
if ($handle === false) {
|
| 156 |
+
return array(
|
| 157 |
+
'status' => false,
|
| 158 |
+
'error' => 'FOPEN_FAILED'
|
| 159 |
+
);
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
if ($offset !== 0) {
|
| 163 |
+
if (fseek($handle, $offset, SEEK_SET) === -1) {
|
| 164 |
+
return array(
|
| 165 |
+
'status' => false,
|
| 166 |
+
'error' => 'FSEEK_FAILED'
|
| 167 |
+
);
|
| 168 |
+
}
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
$total_written = 0;
|
| 172 |
+
foreach($ifiles as $file) {
|
| 173 |
+
$fp = fopen($file, 'rb');
|
| 174 |
+
if ($fp === false) {
|
| 175 |
+
return array(
|
| 176 |
+
'status' => false,
|
| 177 |
+
'error' => "UNABLE_TO_OPEN_TMP_OFILE_FOR_READING"
|
| 178 |
+
);
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
while (!feof($fp)) {
|
| 182 |
+
$content = fread($fp, $bsize);
|
| 183 |
+
if ($content === false) {
|
| 184 |
+
return array(
|
| 185 |
+
'status' => false,
|
| 186 |
+
'error' => "UNABLE_TO_READ_INFILE",
|
| 187 |
+
'filename' => $file
|
| 188 |
+
);
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
$written = fwrite($handle, $content);
|
| 192 |
+
if ($written === false) {
|
| 193 |
+
return array(
|
| 194 |
+
'status' => false,
|
| 195 |
+
'error' => "UNABLE_TO_WRITE_TO_OFILE",
|
| 196 |
+
'filename' => $file
|
| 197 |
+
);
|
| 198 |
+
}
|
| 199 |
+
$total_written += $written;
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
fclose($fp);
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
$result = array();
|
| 206 |
+
$result['fclose'] = fclose($handle);
|
| 207 |
+
|
| 208 |
+
if (file_exists($ofile) && ($total_written != 0)) {
|
| 209 |
+
$result['status'] = true;
|
| 210 |
+
$result['fsize'] = filesize($ofile);
|
| 211 |
+
$result['total_written'] = $total_written;
|
| 212 |
+
} else {
|
| 213 |
+
$result['status'] = false;
|
| 214 |
+
$result['error'] = 'CONCATINATED_FILE_FAILED';
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
return $result;
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
public function renameFiles($path_infos) {
|
| 221 |
+
$result = array();
|
| 222 |
+
|
| 223 |
+
foreach($path_infos as $oldpath => $newpath) {
|
| 224 |
+
$action_result = array();
|
| 225 |
+
$failed = array();
|
| 226 |
+
|
| 227 |
+
if (file_exists($oldpath)) {
|
| 228 |
+
|
| 229 |
+
$action_result['status'] = rename($oldpath, $newpath);
|
| 230 |
+
if ($action_result['status'] === false) {
|
| 231 |
+
$action_result['error'] = "RENAME_FAILED";
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
} else {
|
| 235 |
+
$action_result['status'] = false;
|
| 236 |
+
$action_result['error'] = "NOT_FOUND";
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
$result[$oldpath] = $action_result;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
$result['status'] = true;
|
| 243 |
+
return $result;
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
public function curlFile($ifile_url, $ofile, $timeout) {
|
| 247 |
+
$fp = fopen($ofile, "wb+");
|
| 248 |
+
if ($fp === false) {
|
| 249 |
+
return array(
|
| 250 |
+
'error' => 'FOPEN_FAILED_FOR_TEMP_OFILE'
|
| 251 |
+
);
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
$result = array();
|
| 255 |
+
$ch = curl_init($ifile_url);
|
| 256 |
+
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
|
| 257 |
+
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
| 258 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
| 259 |
+
curl_setopt($ch, CURLOPT_FILE, $fp);
|
| 260 |
+
|
| 261 |
+
if (!curl_exec($ch)) {
|
| 262 |
+
$result['error'] = curl_error($ch);
|
| 263 |
+
$result['errorno'] = curl_errno($ch);
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
curl_close($ch);
|
| 267 |
+
fclose($fp);
|
| 268 |
+
|
| 269 |
+
return $result;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
public function wgetFile($ifile_url, $ofile) {
|
| 273 |
+
$result = array();
|
| 274 |
+
system("wget -nv -O $ofile $ifile_url 2>&1 > /dev/null", $retval);
|
| 275 |
+
|
| 276 |
+
if ($retval !== 0) {
|
| 277 |
+
$result['error'] = "WGET_ERROR";
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
return $result;
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
public function streamCopyFile($ifile_url, $ofile) {
|
| 284 |
+
$result = array();
|
| 285 |
+
$handle = fopen($ifile_url, "rb");
|
| 286 |
+
|
| 287 |
+
if ($handle === false) {
|
| 288 |
+
return array(
|
| 289 |
+
'error' => "UNABLE_TO_OPEN_REMOTE_FILE_STREAM"
|
| 290 |
+
);
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
$fp = fopen($ofile, "wb+");
|
| 294 |
+
if ($fp === false) {
|
| 295 |
+
fclose($handle);
|
| 296 |
+
|
| 297 |
+
return array(
|
| 298 |
+
'error' => 'FOPEN_FAILED_FOR_OFILE'
|
| 299 |
+
);
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
if (stream_copy_to_stream($handle, $fp) === false) {
|
| 303 |
+
$result['error'] = "UNABLE_TO_WRITE_TO_TMP_OFILE";
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
fclose($handle);
|
| 307 |
+
fclose($fp);
|
| 308 |
+
|
| 309 |
+
return $result;
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
public function writeContentToFile($content, $ofile) {
|
| 313 |
+
$result = array();
|
| 314 |
+
|
| 315 |
+
$fp = fopen($ofile, "wb+");
|
| 316 |
+
if ($fp === false) {
|
| 317 |
+
return array(
|
| 318 |
+
'error' => 'FOPEN_FAILED_FOR_TEMP_OFILE'
|
| 319 |
+
);
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
if (fwrite($fp, $content) === false) {
|
| 323 |
+
$resp['error'] = "UNABLE_TO_WRITE_TO_TMP_OFILE";
|
| 324 |
+
}
|
| 325 |
+
fclose($fp);
|
| 326 |
+
|
| 327 |
+
return $result;
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
public function moveUploadedFile($ofile) {
|
| 331 |
+
$result = array();
|
| 332 |
+
|
| 333 |
+
if (isset($_FILES['myfile'])) {
|
| 334 |
+
$myfile = $_FILES['myfile'];
|
| 335 |
+
$is_upload_ok = false;
|
| 336 |
+
|
| 337 |
+
switch ($myfile['error']) {
|
| 338 |
+
case UPLOAD_ERR_OK:
|
| 339 |
+
$is_upload_ok = true;
|
| 340 |
+
break;
|
| 341 |
+
case UPLOAD_ERR_NO_FILE:
|
| 342 |
+
$result['error'] = "UPLOADERR_NO_FILE";
|
| 343 |
+
break;
|
| 344 |
+
case UPLOAD_ERR_INI_SIZE:
|
| 345 |
+
case UPLOAD_ERR_FORM_SIZE:
|
| 346 |
+
$result['error'] = "UPLOADERR_FORM_SIZE";
|
| 347 |
+
break;
|
| 348 |
+
default:
|
| 349 |
+
$result['error'] = "UPLOAD_ERR_UNKNOWN";
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
if ($is_upload_ok && !isset($myfile['tmp_name'])) {
|
| 353 |
+
$result['error'] = "MYFILE_TMP_NAME_NOT_FOUND";
|
| 354 |
+
$is_upload_ok = false;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
if ($is_upload_ok) {
|
| 358 |
+
if (move_uploaded_file($myfile['tmp_name'], $ofile) === false) {
|
| 359 |
+
$result['error'] = 'MOVE_UPLOAD_FILE_FAILED';
|
| 360 |
+
}
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
} else {
|
| 364 |
+
$result['error'] = "FILE_NOT_PRESENT_IN_FILES";
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
return $result;
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
public function uploadFile($params) {
|
| 372 |
+
$resp = array();
|
| 373 |
+
$ofile = $params['ofile'];
|
| 374 |
+
|
| 375 |
+
switch($params['protocol']) {
|
| 376 |
+
case "curl":
|
| 377 |
+
$timeout = isset($params['timeout']) ? $params['timeout'] : 60;
|
| 378 |
+
$ifile_url = isset($params['ifileurl']) ? $params['ifileurl'] : null;
|
| 379 |
+
|
| 380 |
+
$resp = $this->curlFile($ifile_url, $ofile, $timeout);
|
| 381 |
+
break;
|
| 382 |
+
case "wget":
|
| 383 |
+
$ifile_url = isset($params['ifileurl']) ? $params['ifileurl'] : null;
|
| 384 |
+
|
| 385 |
+
$resp = $this->wgetFile($ifile_url, $ofile);
|
| 386 |
+
break;
|
| 387 |
+
case "streamcopy":
|
| 388 |
+
$ifile_url = isset($params['ifileurl']) ? $params['ifileurl'] : null;
|
| 389 |
+
|
| 390 |
+
$resp = $this->streamCopyFile($ifile_url, $ofile);
|
| 391 |
+
break;
|
| 392 |
+
case "httpcontenttransfer":
|
| 393 |
+
$resp = $this->writeContentToFile($params['content'], $ofile);
|
| 394 |
+
break;
|
| 395 |
+
case "httpfiletransfer":
|
| 396 |
+
$resp = $this->moveUploadedFile($ofile);
|
| 397 |
+
break;
|
| 398 |
+
default:
|
| 399 |
+
$resp['error'] = "INVALID_PROTOCOL";
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
if (isset($resp['error'])) {
|
| 403 |
+
$resp['status'] = false;
|
| 404 |
+
} else {
|
| 405 |
+
|
| 406 |
+
if (file_exists($ofile)) {
|
| 407 |
+
$resp['status'] = true;
|
| 408 |
+
$resp['fsize'] = filesize($ofile);
|
| 409 |
+
} else {
|
| 410 |
+
$resp['status'] = false;
|
| 411 |
+
$resp['error'] = "OFILE_NOT_FOUND";
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
}
|
| 415 |
+
|
| 416 |
+
return $resp;
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
public function process($request) {
|
| 420 |
+
$params = $request->params;
|
| 421 |
+
|
| 422 |
+
switch ($request->method) {
|
| 423 |
+
case "rmfle":
|
| 424 |
+
$resp = $this->removeFiles($params['files']);
|
| 425 |
+
break;
|
| 426 |
+
case "chmd":
|
| 427 |
+
$resp = $this->doChmod($params['pathinfos']);
|
| 428 |
+
break;
|
| 429 |
+
case "mkdr":
|
| 430 |
+
$resp = $this->makeDirs($params['dirs']);
|
| 431 |
+
break;
|
| 432 |
+
case "rmdr":
|
| 433 |
+
$resp = $this->removeDirs($params['dirs']);
|
| 434 |
+
break;
|
| 435 |
+
case "renmefle":
|
| 436 |
+
$resp = $this->renameFiles($params['pathinfos']);
|
| 437 |
+
break;
|
| 438 |
+
case "wrtfle":
|
| 439 |
+
$resp = $this->uploadFile($params);
|
| 440 |
+
break;
|
| 441 |
+
case "cncatfls":
|
| 442 |
+
$bsize = (isset($params['bsize'])) ? $params['bsize'] : (8 * BVFSWriteCallback::MEGABYTE);
|
| 443 |
+
$offset = (isset($params['offset'])) ? $params['offset'] : 0;
|
| 444 |
+
$resp = $this->concatFiles($params['infiles'], $params['ofile'], $bsize, $offset);
|
| 445 |
+
break;
|
| 446 |
+
default:
|
| 447 |
+
$resp = false;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
return $resp;
|
| 451 |
+
}
|
| 452 |
+
}
|
| 453 |
+
endif;
|
callback/wings/info.php
CHANGED
|
@@ -136,6 +136,7 @@ class BVInfoCallback extends BVCallbackBase {
|
|
| 136 |
'wpversion' => $wp_version,
|
| 137 |
'dbversion' => $wp_db_version,
|
| 138 |
'abspath' => ABSPATH,
|
|
|
|
| 139 |
'uploadpath' => $upload_dir['basedir'],
|
| 140 |
'uploaddir' => wp_upload_dir(),
|
| 141 |
'contentdir' => defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR : null,
|
|
@@ -237,6 +238,15 @@ class BVInfoCallback extends BVCallbackBase {
|
|
| 237 |
return array('actinfo' => $resp);
|
| 238 |
}
|
| 239 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
public function process($request) {
|
| 241 |
$db = $this->db;
|
| 242 |
$params = $request->params;
|
|
@@ -290,6 +300,19 @@ class BVInfoCallback extends BVCallbackBase {
|
|
| 290 |
$transient = $this->objectToArray($transient);
|
| 291 |
$resp = array("transient" => $transient);
|
| 292 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 293 |
default:
|
| 294 |
$resp = false;
|
| 295 |
}
|
| 136 |
'wpversion' => $wp_version,
|
| 137 |
'dbversion' => $wp_db_version,
|
| 138 |
'abspath' => ABSPATH,
|
| 139 |
+
'bvpluginpath' => defined('MCBASEPATH') ? MCBASEPATH : null,
|
| 140 |
'uploadpath' => $upload_dir['basedir'],
|
| 141 |
'uploaddir' => wp_upload_dir(),
|
| 142 |
'contentdir' => defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR : null,
|
| 238 |
return array('actinfo' => $resp);
|
| 239 |
}
|
| 240 |
|
| 241 |
+
public function getHostInfo() {
|
| 242 |
+
$host_info = $_SERVER;
|
| 243 |
+
$host_info['PHP_SERVER_NAME'] = php_uname('\n');
|
| 244 |
+
if (array_key_exists('IS_PRESSABLE', get_defined_constants())) {
|
| 245 |
+
$host_info['IS_PRESSABLE'] = true;
|
| 246 |
+
}
|
| 247 |
+
return array('host_info' => $host_info);
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
public function process($request) {
|
| 251 |
$db = $this->db;
|
| 252 |
$params = $request->params;
|
| 300 |
$transient = $this->objectToArray($transient);
|
| 301 |
$resp = array("transient" => $transient);
|
| 302 |
break;
|
| 303 |
+
case "gthost":
|
| 304 |
+
$resp = $this->getHostInfo();
|
| 305 |
+
break;
|
| 306 |
+
case "gtplinfo":
|
| 307 |
+
$args = array(
|
| 308 |
+
'slug' => wp_unslash($params['slug'])
|
| 309 |
+
);
|
| 310 |
+
$action = $params['action'];
|
| 311 |
+
$args = (object) $args;
|
| 312 |
+
$args = apply_filters('plugins_api_args', $args, $action);
|
| 313 |
+
$data = apply_filters('plugins_api', false, $action, $args);
|
| 314 |
+
$resp = array("plugins_info" => $data);
|
| 315 |
+
break;
|
| 316 |
default:
|
| 317 |
$resp = false;
|
| 318 |
}
|
callback/wings/protect.php
CHANGED
|
@@ -16,313 +16,6 @@ class BVProtectCallback extends BVCallbackBase {
|
|
| 16 |
$this->settings = $callback_handler->settings;
|
| 17 |
}
|
| 18 |
|
| 19 |
-
public function contentDir() {
|
| 20 |
-
return defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR : "";
|
| 21 |
-
}
|
| 22 |
-
|
| 23 |
-
public function mcDataPath() {
|
| 24 |
-
return $this->contentDir() . '/mc_data/';
|
| 25 |
-
}
|
| 26 |
-
|
| 27 |
-
public function mcIPsFilePath($confkey) {
|
| 28 |
-
return $this->mcDataPath() . $confkey. '-mc_ips.conf';
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
public function mcConfigFilePath($confkey) {
|
| 32 |
-
return $this->mcDataPath() . $confkey. '-mc.conf';
|
| 33 |
-
}
|
| 34 |
-
|
| 35 |
-
public function mcLogFilePath($confkey) {
|
| 36 |
-
return $this->mcDataPath() . $confkey. '-mc.log';
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
-
public function mcWAFFilePath() {
|
| 40 |
-
return ABSPATH . 'malcare-waf.php';
|
| 41 |
-
}
|
| 42 |
-
|
| 43 |
-
public function htAccessFilePath() {
|
| 44 |
-
return ABSPATH . '.htaccess';
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
public function useriniFilePath() {
|
| 48 |
-
return ABSPATH . '.user.ini';
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
public function writeToFile($file, $content, $permissions) {
|
| 52 |
-
$tmp_file = tmpfile();
|
| 53 |
-
$result = array();
|
| 54 |
-
|
| 55 |
-
if (!$tmp_file) {
|
| 56 |
-
$result = array('status' => 'Error', 'message' => 'UNABLE_TO_CREATE_TMPFILE');
|
| 57 |
-
} else {
|
| 58 |
-
$tmpmeta = stream_get_meta_data($tmp_file);
|
| 59 |
-
$tmpfilename = $tmpmeta['uri'];
|
| 60 |
-
|
| 61 |
-
if (file_put_contents($tmpfilename, $content)) {
|
| 62 |
-
|
| 63 |
-
$tmp_contents = file_get_contents($tmpfilename);
|
| 64 |
-
|
| 65 |
-
if ($tmp_contents !== $content) {
|
| 66 |
-
$result = array('status' => 'Error', 'message' => 'TMPFILE_CONTENT_MISMATCH');
|
| 67 |
-
} else if (!@rename($tmpfilename, $file)) {
|
| 68 |
-
$result = array('status' => 'Error', 'message' => 'UNABLE_TO_RENAME_TMPFILE');
|
| 69 |
-
} else {
|
| 70 |
-
chmod($file, $permissions);
|
| 71 |
-
$fcontent = file_get_contents($file);
|
| 72 |
-
|
| 73 |
-
if ($fcontent !== $content) {
|
| 74 |
-
$result = array(
|
| 75 |
-
'status' => 'Error',
|
| 76 |
-
'message' => 'FILE_NOT_WRITTEN_PROPERLY',
|
| 77 |
-
'content' => $fcontent
|
| 78 |
-
);
|
| 79 |
-
} else {
|
| 80 |
-
$result = array('status' => 'Done');
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
}
|
| 84 |
-
} else {
|
| 85 |
-
$result = array('status' => 'Error', 'message' => 'UNABLE_TO_WRITE_IN_TMPFILE');
|
| 86 |
-
}
|
| 87 |
-
}
|
| 88 |
-
return $result;
|
| 89 |
-
}
|
| 90 |
-
|
| 91 |
-
public function writeToMcDataFile($fname, $content, $confkey, $permissions) {
|
| 92 |
-
$result = array();
|
| 93 |
-
if (in_array($fname, BVFWConfig::$validMcDataFilenames)) {
|
| 94 |
-
|
| 95 |
-
$mcDataPath = $this->mcDataPath();
|
| 96 |
-
|
| 97 |
-
if (file_exists($mcDataPath)) {
|
| 98 |
-
$filepath = $mcDataPath . $confkey . '-' . $fname;
|
| 99 |
-
$result = $this->writeToFile($filepath, $content, $permissions);
|
| 100 |
-
} else {
|
| 101 |
-
$result['status'] = 'Error';
|
| 102 |
-
$result['message'] = 'MC_DATA_PATH_DOES_NOT_EXISTS';
|
| 103 |
-
}
|
| 104 |
-
|
| 105 |
-
} else {
|
| 106 |
-
$result['status'] = 'Error';
|
| 107 |
-
$result['message'] = 'INVALID_FILE_NAME';
|
| 108 |
-
}
|
| 109 |
-
return $result;
|
| 110 |
-
}
|
| 111 |
-
|
| 112 |
-
public function getMalcareWAFContent($confkey) {
|
| 113 |
-
return sprintf(
|
| 114 |
-
'<?php
|
| 115 |
-
// Please validate auto_prepend_file setting before removing this file
|
| 116 |
-
|
| 117 |
-
if (file_exists(%1$s)) {
|
| 118 |
-
define("MCDATAPATH", %2$s);
|
| 119 |
-
define("MCCONFKEY", %3$s);
|
| 120 |
-
include_once(%1$s);
|
| 121 |
-
}
|
| 122 |
-
?>',
|
| 123 |
-
var_export(MCBASEPATH . 'protect/prepend/ignitor.php', true),
|
| 124 |
-
var_export($this->mcDataPath(), true),
|
| 125 |
-
var_export($confkey, true)
|
| 126 |
-
);
|
| 127 |
-
}
|
| 128 |
-
|
| 129 |
-
public function configureMalcareWAF($confkey) {
|
| 130 |
-
$result = array();
|
| 131 |
-
if (!$confkey || $confkey === "") {
|
| 132 |
-
$result['status'] = 'Error';
|
| 133 |
-
$result['message'] = 'INVALID_CONFKEY';
|
| 134 |
-
} else {
|
| 135 |
-
|
| 136 |
-
$content = $this->getMalcareWAFContent($confkey);
|
| 137 |
-
$result = $this->writeToFile($this->mcWAFFilePath(), $content, 0644);
|
| 138 |
-
}
|
| 139 |
-
|
| 140 |
-
return $result;
|
| 141 |
-
}
|
| 142 |
-
|
| 143 |
-
public function addPrependToHtaccess($user_ini, $mode) {
|
| 144 |
-
$userIniHtaccessContent = '';
|
| 145 |
-
if ($user_ini) {
|
| 146 |
-
$userIniHtaccessContent = sprintf('<Files "%s">
|
| 147 |
-
<IfModule mod_authz_core.c>
|
| 148 |
-
Require all denied
|
| 149 |
-
</IfModule>
|
| 150 |
-
<IfModule !mod_authz_core.c>
|
| 151 |
-
Order deny,allow
|
| 152 |
-
Deny from all
|
| 153 |
-
</IfModule>
|
| 154 |
-
</Files>
|
| 155 |
-
', $user_ini);
|
| 156 |
-
}
|
| 157 |
-
|
| 158 |
-
switch ($mode) {
|
| 159 |
-
case BVFWConfig::MODE_APACHEMODPHP:
|
| 160 |
-
$htaccessPrependContent = sprintf("# MalCare WAF
|
| 161 |
-
<IfModule mod_php5.c>
|
| 162 |
-
php_value auto_prepend_file '%s'
|
| 163 |
-
</IfModule>
|
| 164 |
-
<IfModule mod_php7.c>
|
| 165 |
-
php_value auto_prepend_file '%s'
|
| 166 |
-
</IfModule>
|
| 167 |
-
$userIniHtaccessContent
|
| 168 |
-
# END MalCare WAF
|
| 169 |
-
", $this->mcWAFFilePath(), $this->mcWAFFilePath());
|
| 170 |
-
break;
|
| 171 |
-
|
| 172 |
-
case BVFWConfig::MODE_LITESPEED:
|
| 173 |
-
$htaccessPrependContent = sprintf("# MalCare WAF
|
| 174 |
-
<IfModule LiteSpeed>
|
| 175 |
-
php_value auto_prepend_file '%s'
|
| 176 |
-
</IfModule>
|
| 177 |
-
<IfModule lsapi_module>
|
| 178 |
-
php_value auto_prepend_file '%s'
|
| 179 |
-
</IfModule>
|
| 180 |
-
$userIniHtaccessContent
|
| 181 |
-
# END MalCare WAF
|
| 182 |
-
", $this->mcWAFFilePath(), $this->mcWAFFilePath());
|
| 183 |
-
break;
|
| 184 |
-
|
| 185 |
-
case BVFWConfig::MODE_APACHESUPHP:
|
| 186 |
-
$htaccessPrependContent = sprintf("# MalCare WAF
|
| 187 |
-
$userIniHtaccessContent
|
| 188 |
-
# END MalCare WAF
|
| 189 |
-
", ABSPATH);
|
| 190 |
-
break;
|
| 191 |
-
|
| 192 |
-
case BVFWConfig::MODE_CGI_FASTCGI:
|
| 193 |
-
if ($userIniHtaccessContent) {
|
| 194 |
-
$htaccessPrependContent = sprintf("# MalCare WAF
|
| 195 |
-
$userIniHtaccessContent
|
| 196 |
-
# END MalCare WAF
|
| 197 |
-
", ABSPATH);
|
| 198 |
-
}
|
| 199 |
-
break;
|
| 200 |
-
|
| 201 |
-
}
|
| 202 |
-
|
| 203 |
-
$result = array();
|
| 204 |
-
$htaccessPath = $this->htAccessFilePath();
|
| 205 |
-
|
| 206 |
-
if (!empty($htaccessPrependContent)) {
|
| 207 |
-
$htaccessContent = '';
|
| 208 |
-
if (file_exists($htaccessPath)) {
|
| 209 |
-
$htaccessContent = file_get_contents($htaccessPath);
|
| 210 |
-
}
|
| 211 |
-
|
| 212 |
-
if (!empty($htaccessContent)) {
|
| 213 |
-
$regex = '/# MalCare WAF.*?# END MalCare WAF/is';
|
| 214 |
-
if (preg_match($regex, $htaccessContent, $matches)) {
|
| 215 |
-
$htaccessContent = preg_replace($regex, $htaccessPrependContent, $htaccessContent);
|
| 216 |
-
} else {
|
| 217 |
-
$htaccessContent .= "\n\n" . $htaccessPrependContent;
|
| 218 |
-
}
|
| 219 |
-
} else {
|
| 220 |
-
$htaccessContent = $htaccessPrependContent;
|
| 221 |
-
}
|
| 222 |
-
|
| 223 |
-
$result = $this->writeToFile($htaccessPath, $htaccessContent, 0755);
|
| 224 |
-
|
| 225 |
-
if ($mode == BVFWConfig::MODE_LITESPEED) {
|
| 226 |
-
touch($htaccessPath);
|
| 227 |
-
}
|
| 228 |
-
|
| 229 |
-
}
|
| 230 |
-
|
| 231 |
-
if (file_exists($htaccessPath)) {
|
| 232 |
-
$result['content'] = file_get_contents($htaccessPath);
|
| 233 |
-
}
|
| 234 |
-
|
| 235 |
-
return $result;
|
| 236 |
-
}
|
| 237 |
-
|
| 238 |
-
public function removePrependFromHtaccess() {
|
| 239 |
-
$result = array();
|
| 240 |
-
$htaccessPath = $this->htAccessFilePath();
|
| 241 |
-
|
| 242 |
-
if (file_exists($htaccessPath)) {
|
| 243 |
-
$htaccessContent = file_get_contents($htaccessPath);
|
| 244 |
-
$regex = '/# MalCare WAF.*?# END MalCare WAF/is';
|
| 245 |
-
|
| 246 |
-
if (preg_match($regex, $htaccessContent, $matches)) {
|
| 247 |
-
$htaccessContent = preg_replace($regex, '', $htaccessContent);
|
| 248 |
-
|
| 249 |
-
$result = $this->writeToFile($htaccessPath, $htaccessContent, 0755);
|
| 250 |
-
}
|
| 251 |
-
}
|
| 252 |
-
|
| 253 |
-
if (file_exists($htaccessPath)) {
|
| 254 |
-
$result['content'] = file_get_contents($htaccessPath);
|
| 255 |
-
}
|
| 256 |
-
|
| 257 |
-
return $result;
|
| 258 |
-
}
|
| 259 |
-
|
| 260 |
-
public function addPrependToUserini($mode) {
|
| 261 |
-
switch ($mode) {
|
| 262 |
-
case BVFWConfig::MODE_CGI_FASTCGI:
|
| 263 |
-
case BVFWConfig::MODE_NGINX:
|
| 264 |
-
case BVFWConfig::MODE_IIS:
|
| 265 |
-
case BVFWConfig::MODE_LITESPEED:
|
| 266 |
-
case BVFWConfig::MODE_APACHESUPHP:
|
| 267 |
-
$useriniPrependContent = sprintf("; MalCare WAF
|
| 268 |
-
auto_prepend_file = '%s'
|
| 269 |
-
; END MalCare WAF
|
| 270 |
-
", $this->mcWAFFilePath());
|
| 271 |
-
break;
|
| 272 |
-
}
|
| 273 |
-
|
| 274 |
-
$result = array();
|
| 275 |
-
$useriniPath = $this->useriniFilePath();
|
| 276 |
-
|
| 277 |
-
if (!empty($useriniPrependContent)) {
|
| 278 |
-
$useriniContent = '';
|
| 279 |
-
if (file_exists($useriniPath)) {
|
| 280 |
-
$useriniContent = file_get_contents($useriniPath);
|
| 281 |
-
}
|
| 282 |
-
if (!empty($useriniContent)) {
|
| 283 |
-
$useriniContent = str_replace('auto_prepend_file', ';auto_prepend_file', $useriniContent);
|
| 284 |
-
$regex = '/; MalCare WAF.*?; END MalCare WAF/is';
|
| 285 |
-
if (preg_match($regex, $useriniContent, $matches)) {
|
| 286 |
-
$useriniContent = preg_replace($regex, $useriniPrependContent, $useriniContent);
|
| 287 |
-
} else {
|
| 288 |
-
$useriniContent .= "\n\n" . $useriniPrependContent;
|
| 289 |
-
}
|
| 290 |
-
} else {
|
| 291 |
-
$useriniContent = $useriniPrependContent;
|
| 292 |
-
}
|
| 293 |
-
|
| 294 |
-
$result = $this->writeToFile($useriniPath, $useriniContent, 0755);
|
| 295 |
-
}
|
| 296 |
-
|
| 297 |
-
if (file_exists($useriniPath)) {
|
| 298 |
-
$result['content'] = file_get_contents($useriniPath);
|
| 299 |
-
}
|
| 300 |
-
|
| 301 |
-
return $result;
|
| 302 |
-
}
|
| 303 |
-
|
| 304 |
-
public function removePrependFromUserini() {
|
| 305 |
-
$result = array();
|
| 306 |
-
$useriniPath = $this->UseriniFilePath();
|
| 307 |
-
|
| 308 |
-
if (file_exists($useriniPath)) {
|
| 309 |
-
$useriniContent = file_get_contents($useriniPath);
|
| 310 |
-
$regex = '/; MalCare WAF.*?; END MalCare WAF/is';
|
| 311 |
-
|
| 312 |
-
if (preg_match($regex, $useriniContent, $matches)) {
|
| 313 |
-
$useriniContent = preg_replace($regex, '', $useriniContent);
|
| 314 |
-
|
| 315 |
-
$result = $this->writeToFile($useriniPath, $useriniContent, 0755);
|
| 316 |
-
}
|
| 317 |
-
}
|
| 318 |
-
|
| 319 |
-
if (file_exists($useriniPath)) {
|
| 320 |
-
$result['content'] = file_get_contents($useriniPath);
|
| 321 |
-
}
|
| 322 |
-
|
| 323 |
-
return $result;
|
| 324 |
-
}
|
| 325 |
-
|
| 326 |
public function serverConfig() {
|
| 327 |
return array(
|
| 328 |
'software' => $_SERVER['SERVER_SOFTWARE'],
|
|
@@ -335,35 +28,6 @@ auto_prepend_file = '%s'
|
|
| 335 |
);
|
| 336 |
}
|
| 337 |
|
| 338 |
-
public function removeDir($dir) {
|
| 339 |
-
$result = array();
|
| 340 |
-
if (file_exists($dir)) {
|
| 341 |
-
if (rmdir($dir)) {
|
| 342 |
-
$result = array('status' => 'Done');
|
| 343 |
-
} else {
|
| 344 |
-
$result = array('status' => 'Error', 'message' => 'UNABLE_TO_REMOVE_DIR');
|
| 345 |
-
}
|
| 346 |
-
} else {
|
| 347 |
-
$result = array('status' => 'Done', 'message' => 'DIR_DOESNOT_EXISTS');
|
| 348 |
-
}
|
| 349 |
-
|
| 350 |
-
return $result;
|
| 351 |
-
}
|
| 352 |
-
|
| 353 |
-
public function removeFile($filename) {
|
| 354 |
-
$result = array();
|
| 355 |
-
if (file_exists($filename)) {
|
| 356 |
-
if (unlink($filename)) {
|
| 357 |
-
$result = array('status' => 'Done');
|
| 358 |
-
} else {
|
| 359 |
-
$result = array('status' => 'Error', 'message' => 'UNABLE_TO_REMOVE_FILE');
|
| 360 |
-
}
|
| 361 |
-
} else {
|
| 362 |
-
$result = array('status' => 'Done', 'message' => 'FILE_DOESNOT_EXISTS');
|
| 363 |
-
}
|
| 364 |
-
return $result;
|
| 365 |
-
}
|
| 366 |
-
|
| 367 |
public function unBlockLogins() {
|
| 368 |
$this->settings->deleteTransient('bvlp_block_logins');
|
| 369 |
$this->settings->setTransient('bvlp_allow_logins', 'true', 1800);
|
|
@@ -419,66 +83,6 @@ auto_prepend_file = '%s'
|
|
| 419 |
case "svrcnf":
|
| 420 |
$resp = array("serverconfig" => $this->serverConfig());
|
| 421 |
break;
|
| 422 |
-
case "gtmcwafcntent":
|
| 423 |
-
$resp = array('content' => $this->getMalcareWAFContent($params['confkey']));
|
| 424 |
-
break;
|
| 425 |
-
case "wrtmcdtafle":
|
| 426 |
-
$permissions = array_key_exists('permissions', $params) ? $params['permissions'] : 0664;
|
| 427 |
-
$confkey = $params['confkey'];
|
| 428 |
-
$fname = $params['fname'];
|
| 429 |
-
$content = $params['content'];
|
| 430 |
-
$resp = array('writetomcdatafile' => $this->writeToMcDataFile($fname, $content, $confkey, $permissions));
|
| 431 |
-
break;
|
| 432 |
-
case "cnfgrewaf":
|
| 433 |
-
$confkey = $params['confkey'];
|
| 434 |
-
$resp = array('configurewaf' => $this->configureMalcareWAF($confkey));
|
| 435 |
-
break;
|
| 436 |
-
case "rmmcdta":
|
| 437 |
-
$name = $params['name'];
|
| 438 |
-
if (in_array($name, BVFWConfig::$validDeletableFiles)) {
|
| 439 |
-
switch($name) {
|
| 440 |
-
case "mc.conf":
|
| 441 |
-
$name = $this->mcConfigFilePath($params['confkey']);
|
| 442 |
-
$resp = $this->removeFile($name);
|
| 443 |
-
break;
|
| 444 |
-
case "mc_ips.conf":
|
| 445 |
-
$name = $this->mcIPsFilePath($params['confkey']);
|
| 446 |
-
$resp = $this->removeFile($name);
|
| 447 |
-
break;
|
| 448 |
-
case "malcare-waf.php":
|
| 449 |
-
$name = $this->mcWAFFilePath();
|
| 450 |
-
$resp = $this->removeFile($name);
|
| 451 |
-
break;
|
| 452 |
-
case "mc.log":
|
| 453 |
-
$name = $this->mcLogFilePath($params['confkey']);
|
| 454 |
-
$resp = $this->removeFile($name);
|
| 455 |
-
break;
|
| 456 |
-
case "mc_data":
|
| 457 |
-
$dir = $this->mcDataPath();
|
| 458 |
-
$resp = $this->removeDir($dir);
|
| 459 |
-
break;
|
| 460 |
-
default:
|
| 461 |
-
$resp = array('status' => 'Error', 'message' => 'INCORRECT_FILENAME');
|
| 462 |
-
}
|
| 463 |
-
} else {
|
| 464 |
-
$resp = array('status' => 'Error', 'message' => 'INCORRECT_FILENAME');
|
| 465 |
-
}
|
| 466 |
-
break;
|
| 467 |
-
case "addprepndtohtacess":
|
| 468 |
-
$user_ini = $params['user_ini'];
|
| 469 |
-
$mode = intval($params['mode']);
|
| 470 |
-
$resp = array('prependtohtaccess' => $this->addPrependToHtaccess($user_ini, $mode));
|
| 471 |
-
break;
|
| 472 |
-
case "rmprepndfrmhtacess":
|
| 473 |
-
$resp = array('removefromhtaccess' => $this->removePrependFromHtaccess());
|
| 474 |
-
break;
|
| 475 |
-
case "addprepndtousrini":
|
| 476 |
-
$mode = intval($params['mode']);
|
| 477 |
-
$resp = array('prependtouserini' => $this->addPrependToUserini($mode));
|
| 478 |
-
break;
|
| 479 |
-
case "rmprepndfrmusrini":
|
| 480 |
-
$resp = array('removefromuserini' => $this->removePrependFromUserini());
|
| 481 |
-
break;
|
| 482 |
case "setptplug":
|
| 483 |
$this->settings->updateOption('bvptplug', $params['ptplug']);
|
| 484 |
$resp = array("setptplug" => $this->settings->getOption('bvptplug'));
|
|
@@ -508,4 +112,4 @@ auto_prepend_file = '%s'
|
|
| 508 |
return $resp;
|
| 509 |
}
|
| 510 |
}
|
| 511 |
-
endif;
|
| 16 |
$this->settings = $callback_handler->settings;
|
| 17 |
}
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
public function serverConfig() {
|
| 20 |
return array(
|
| 21 |
'software' => $_SERVER['SERVER_SOFTWARE'],
|
| 28 |
);
|
| 29 |
}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
public function unBlockLogins() {
|
| 32 |
$this->settings->deleteTransient('bvlp_block_logins');
|
| 33 |
$this->settings->setTransient('bvlp_allow_logins', 'true', 1800);
|
| 83 |
case "svrcnf":
|
| 84 |
$resp = array("serverconfig" => $this->serverConfig());
|
| 85 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
case "setptplug":
|
| 87 |
$this->settings->updateOption('bvptplug', $params['ptplug']);
|
| 88 |
$resp = array("setptplug" => $this->settings->getOption('bvptplug'));
|
| 112 |
return $resp;
|
| 113 |
}
|
| 114 |
}
|
| 115 |
+
endif;
|
info.php
CHANGED
|
@@ -9,7 +9,7 @@ if (!class_exists('MCInfo')) :
|
|
| 9 |
public $badgeinfo = 'mcbadge';
|
| 10 |
public $ip_header_option = 'mcipheader';
|
| 11 |
public $brand_option = 'mcbrand';
|
| 12 |
-
public $version = '
|
| 13 |
public $webpage = 'https://www.malcare.com';
|
| 14 |
public $appurl = 'https://app.malcare.com';
|
| 15 |
public $slug = 'malcare-security/malcare.php';
|
| 9 |
public $badgeinfo = 'mcbadge';
|
| 10 |
public $ip_header_option = 'mcipheader';
|
| 11 |
public $brand_option = 'mcbrand';
|
| 12 |
+
public $version = '4.2';
|
| 13 |
public $webpage = 'https://www.malcare.com';
|
| 14 |
public $appurl = 'https://app.malcare.com';
|
| 15 |
public $slug = 'malcare-security/malcare.php';
|
malcare.php
CHANGED
|
@@ -5,7 +5,7 @@ Plugin URI: https://www.malcare.com
|
|
| 5 |
Description: WordPress Security, Firewall and Malware Scanner
|
| 6 |
Author: MalCare Security
|
| 7 |
Author URI: https://www.malcare.com
|
| 8 |
-
Version:
|
| 9 |
Network: True
|
| 10 |
*/
|
| 11 |
|
|
@@ -87,7 +87,7 @@ if ((array_key_exists('bvplugname', $_REQUEST)) && ($_REQUEST['bvplugname'] == "
|
|
| 87 |
require_once dirname( __FILE__ ) . '/callback/request.php';
|
| 88 |
require_once dirname( __FILE__ ) . '/recover.php';
|
| 89 |
|
| 90 |
-
$pubkey = $_REQUEST['pubkey'];
|
| 91 |
|
| 92 |
if (array_key_exists('rcvracc', $_REQUEST)) {
|
| 93 |
$account = MCRecover::find($bvsettings, $pubkey);
|
| 5 |
Description: WordPress Security, Firewall and Malware Scanner
|
| 6 |
Author: MalCare Security
|
| 7 |
Author URI: https://www.malcare.com
|
| 8 |
+
Version: 4.2
|
| 9 |
Network: True
|
| 10 |
*/
|
| 11 |
|
| 87 |
require_once dirname( __FILE__ ) . '/callback/request.php';
|
| 88 |
require_once dirname( __FILE__ ) . '/recover.php';
|
| 89 |
|
| 90 |
+
$pubkey = MCAccount::sanitizeKey($_REQUEST['pubkey']);
|
| 91 |
|
| 92 |
if (array_key_exists('rcvracc', $_REQUEST)) {
|
| 93 |
$account = MCRecover::find($bvsettings, $pubkey);
|
readme.txt
CHANGED
|
@@ -6,7 +6,7 @@ Donate link: https://www.malcare.com
|
|
| 6 |
Requires at least: 4.0
|
| 7 |
Tested up to: 5.4
|
| 8 |
Requires PHP: 5.4.0
|
| 9 |
-
Stable tag:
|
| 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 |
|
|
@@ -218,6 +218,11 @@ FTP details input into MalCare is processed on our servers. We need your FTP cre
|
|
| 218 |
8. With BlogVault's White-Label Solution you can showcase our service under your own brilliant brand.
|
| 219 |
|
| 220 |
== CHANGELOG ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
= 3.8 =
|
| 222 |
* Updated MalCare landing page front-end
|
| 223 |
|
| 6 |
Requires at least: 4.0
|
| 7 |
Tested up to: 5.4
|
| 8 |
Requires PHP: 5.4.0
|
| 9 |
+
Stable tag: 4.2
|
| 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 |
|
| 218 |
8. With BlogVault's White-Label Solution you can showcase our service under your own brilliant brand.
|
| 219 |
|
| 220 |
== CHANGELOG ==
|
| 221 |
+
= 4.2 =
|
| 222 |
+
* Robust write callbacks
|
| 223 |
+
* Improved and Robust prepend in Firewall Support
|
| 224 |
+
* Without FTP cleanup and restore support
|
| 225 |
+
|
| 226 |
= 3.8 =
|
| 227 |
* Updated MalCare landing page front-end
|
| 228 |
|
