PluginProbe
The WP Remote WordPress Plugin / 5.47
The WP Remote WordPress Plugin v5.47
6.72 6.69 6.65 6.62 6.48 6.47 4.87 4.97 5.05 5.09 5.16 5.22 5.24 5.25 5.38 5.41 5.42 5.45 5.47 5.53 5.56 5.65 5.68 5.72 5.73 All 53 releases
wpremote / callback / wings / fs.php

fs.php in The WP Remote WordPress Plugin 5.47, at callback/wings/fs.php

407 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) exit;
4 if (!class_exists('BVFSCallback')) :
5 require_once dirname( __FILE__ ) . '/../streams.php';
6
7 class BVFSCallback extends BVCallbackBase {
8 public $stream;
9 public $account;
10
11 public static $cwAllowedFiles = array(".htaccess", ".user.ini", "malcare-waf.php");
12 const FS_WING_VERSION = 1.2;
13
14 public function __construct($callback_handler) {
15 $this->account = $callback_handler->account;
16 }
17
18 function fileStat($relfile, $md5 = false) {
19 $absfile = ABSPATH.$relfile;
20 $fdata = array();
21 $fdata["filename"] = $relfile;
22 $stats = @stat($absfile);
23 if ($stats) {
24 foreach (preg_grep('#size|uid|gid|mode|mtime#i', array_keys($stats)) as $key ) {
25 $fdata[$key] = $stats[$key];
26 }
27 if (is_link($absfile)) {
28 $fdata["link"] = @readlink($absfile);
29 }
30 if ($md5 === true && !is_dir($absfile)) {
31 $fdata["md5"] = $this->calculateMd5($absfile, array(), 0, 0, 0);
32 }
33 } else {
34 $fdata["failed"] = true;
35 }
36 return $fdata;
37 }
38
39 function scanFilesUsingGlob($initdir = "./", $offset = 0, $limit = 0, $bsize = 512, $recurse = true, $regex = '{.??,}*') {
40 $i = 0;
41 $dirs = array();
42 $dirs[] = $initdir;
43 $bfc = 0;
44 $bfa = array();
45 $current = 0;
46 $abspath = realpath(ABSPATH).'/';
47 $abslen = strlen($abspath);
48 # XNOTE: $recurse cannot be used directly here
49 while ($i < count($dirs)) {
50 $dir = $dirs[$i];
51
52 foreach (glob($abspath.$dir.$regex, GLOB_NOSORT | GLOB_BRACE) as $absfile) {
53 $relfile = substr($absfile, $abslen);
54 if (is_dir($absfile) && !is_link($absfile)) {
55 $dirs[] = $relfile."/";
56 }
57 $current++;
58 if ($offset >= $current)
59 continue;
60 if (($limit != 0) && (($current - $offset) > $limit)) {
61 $i = count($dirs);
62 break;
63 }
64 $bfa[] = $this->fileStat($relfile);
65 $bfc++;
66 if ($bfc == $bsize) {
67 $str = serialize($bfa);
68 $this->stream->writeStream($str);
69 $bfc = 0;
70 $bfa = array();
71 }
72 }
73 $regex = '{.??,}*';
74 $i++;
75 if ($recurse == false)
76 break;
77 }
78 if ($bfc != 0) {
79 $str = serialize($bfa);
80 $this->stream->writeStream($str);
81 }
82 return array("status" => "done");
83 }
84
85 function scanFiles($initdir = "./", $offset = 0, $limit = 0, $bsize = 512, $recurse = true, $md5 = false) {
86 $i = 0;
87 $links = array();
88 $dirs = array();
89 $dirs[] = $initdir;
90 $bfc = 0;
91 $bfa = array();
92 $current = 0;
93 while ($i < count($dirs)) {
94 $dir = $dirs[$i];
95 $d = @opendir(ABSPATH.$dir);
96 if ($d) {
97 while (($file = readdir($d)) !== false) {
98 if ($file == '.' || $file == '..') { continue; }
99 $relfile = $dir.$file;
100 $absfile = ABSPATH.$relfile;
101 if (is_link($absfile)) {
102 $links[] = $relfile;
103 }
104 if (is_dir($absfile) && !is_link($absfile)) {
105 $dirs[] = $relfile."/";
106 }
107 $current++;
108 if ($offset >= $current)
109 continue;
110 if (($limit != 0) && (($current - $offset) > $limit)) {
111 $i = count($dirs);
112 break;
113 }
114 $bfa[] = $this->fileStat($relfile, $md5);
115 $bfc++;
116 if ($bfc == $bsize) {
117 $str = serialize($bfa);
118 $this->stream->writeStream($str);
119 $bfc = 0;
120 $bfa = array();
121 }
122 }
123 closedir($d);
124 }
125 $i++;
126 if ($recurse == false)
127 break;
128 }
129 if ($bfc != 0) {
130 $str = serialize($bfa);
131 $this->stream->writeStream($str);
132 }
133
134 return $links;
135 }
136
137 function calculateMd5($absfile, $fdata, $offset, $limit, $bsize) {
138 if ($offset == 0 && $limit == 0) {
139 $md5 = md5_file($absfile);
140 } else {
141 if ($limit == 0)
142 $limit = $fdata["size"];
143 if ($offset + $limit < $fdata["size"])
144 $limit = $fdata["size"] - $offset;
145 $handle = fopen($absfile, "rb");
146 $ctx = hash_init('md5');
147 fseek($handle, $offset, SEEK_SET);
148 $dlen = 1;
149 while (($limit > 0) && ($dlen > 0)) {
150 if ($bsize > $limit)
151 $bsize = $limit;
152 $d = fread($handle, $bsize);
153 $dlen = strlen($d);
154 hash_update($ctx, $d);
155 $limit -= $dlen;
156 }
157 fclose($handle);
158 $md5 = hash_final($ctx);
159 }
160 return $md5;
161 }
162
163 function getFilesContent($files, $withContent = true) {
164 $result = array();
165 foreach ($files as $file) {
166 $fdata = $this->fileStat($file);
167 $absfile = ABSPATH.$file;
168
169 if (is_dir($absfile) && !is_link($absfile)) {
170 $fdata['is_dir'] = true;
171 } else {
172 if (!is_readable($absfile)) {
173 $fdata['error'] = 'file not readable';
174 } else {
175 if ($withContent === true) {
176 if ($content = file_get_contents($absfile)) {
177 $fdata['content'] = $content;
178 } else {
179 $fdata['error'] = 'unable to read file';
180 }
181 }
182 }
183 }
184
185 $result[$file] = $fdata;
186 }
187
188 return $result;
189 }
190
191 function getFilesStats($files, $offset = 0, $limit = 0, $bsize = 102400, $md5 = false) {
192 $result = array();
193 foreach ($files as $file) {
194 $fdata = $this->fileStat($file);
195 $absfile = ABSPATH.$file;
196 if (!is_readable($absfile)) {
197 $result["missingfiles"][] = $file;
198 continue;
199 }
200 if ($md5 === true && !is_dir($absfile)) {
201 $fdata["md5"] = $this->calculateMd5($absfile, $fdata, $offset, $limit, $bsize);
202 }
203 $result["stats"][] = $fdata;
204 }
205 return $result;
206 }
207
208 function uploadFiles($files, $offset = 0, $limit = 0, $bsize = 102400) {
209 $result = array();
210 foreach ($files as $file) {
211 if (!is_readable(ABSPATH.$file)) {
212 $result["missingfiles"][] = $file;
213 continue;
214 }
215 $handle = fopen(ABSPATH.$file, "rb");
216 if (($handle != null) && is_resource($handle)) {
217 $fdata = $this->fileStat($file);
218 $_limit = $limit;
219 $_bsize = $bsize;
220 if ($_limit == 0)
221 $_limit = $fdata["size"];
222 if ($offset + $_limit > $fdata["size"])
223 $_limit = $fdata["size"] - $offset;
224 $fdata["limit"] = $_limit;
225 $sfdata = serialize($fdata);
226 $this->stream->writeStream($sfdata);
227 fseek($handle, $offset, SEEK_SET);
228 $dlen = 1;
229 while (($_limit > 0) && ($dlen > 0)) {
230 if ($_bsize > $_limit)
231 $_bsize = $_limit;
232 $d = fread($handle, $_bsize);
233 $dlen = strlen($d);
234 $this->stream->writeStream($d);
235 $_limit -= $dlen;
236 }
237 fclose($handle);
238 } else {
239 $result["unreadablefiles"][] = $file;
240 }
241 }
242 $result["status"] = "done";
243 return $result;
244 }
245
246 function process($request) {
247 $params = $request->params;
248 $stream_init_info = BVStream::startStream($this->account, $request);
249
250 if (array_key_exists('stream', $stream_init_info)) {
251 $this->stream = $stream_init_info['stream'];
252 switch ($request->method) {
253 case "scanfilesglob":
254 $initdir = $params['initdir'];
255 $offset = intval($params['offset']);
256 $limit = intval($params['limit']);
257 $bsize = intval($params['bsize']);
258 $regex = $params['regex'];
259 $recurse = true;
260 if (array_key_exists('recurse', $params) && $params["recurse"] == "false") {
261 $recurse = false;
262 }
263 $resp = $this->scanFilesUsingGlob($initdir, $offset, $limit, $bsize, $recurse, $regex);
264 break;
265 case "scanfiles":
266 $links = array();
267 $dir_options = array();
268 if (array_key_exists('dir_options', $params)) {
269 $dir_options = $params['dir_options'];
270 }
271 $bsize = intval($params['bsize']);
272 foreach($dir_options as $option) {
273 $dir = $option['dir'];
274 $offset = intval($option['offset']);
275 $limit = intval($option['limit']);
276 $recurse = true;
277 if (array_key_exists('recurse', $option) && $option["recurse"] == "false") {
278 $recurse = false;
279 }
280 $md5 = true;
281 if (array_key_exists('md5', $option) && $option["md5"] == "false") {
282 $md5 = false;
283 }
284
285 $_links = $this->scanFiles($dir, $offset, $limit, $bsize, $recurse, $md5);
286 $links = array_merge($links, $_links);
287 }
288 $resp = array("status" => "done", "links" => $links);
289 break;
290 case "getfilesstats":
291 $files = $params['files'];
292 $offset = intval($params['offset']);
293 $limit = intval($params['limit']);
294 $bsize = intval($params['bsize']);
295 $md5 = false;
296 if (array_key_exists('md5', $params)) {
297 $md5 = true;
298 }
299 $resp = $this->getFilesStats($files, $offset, $limit, $bsize, $md5);
300 break;
301 case "sendmanyfiles":
302 $files = $params['files'];
303 $offset = intval($params['offset']);
304 $limit = intval($params['limit']);
305 $bsize = intval($params['bsize']);
306 $resp = $this->uploadFiles($files, $offset, $limit, $bsize);
307 break;
308 case "filelist":
309 $dir_options = array();
310 if (array_key_exists('dir_options', $params)) {
311 $dir_options = $params['dir_options'];
312 }
313 if (array_key_exists('chdir', $params)) {
314 chdir(ABSPATH);
315 }
316 $resp = array();
317 foreach($dir_options as $options) {
318 $glob_option = 0;
319 if (array_key_exists('onlydir', $options)) {
320 $glob_option = GLOB_ONLYDIR;
321 }
322
323 $regexes = array("*", ".*");
324 if (array_key_exists('regex', $options)) {
325 $regexes = array($options['regex']);
326 }
327
328 $md5 = false;
329 if (array_key_exists('md5', $options)) {
330 $md5 = $options['md5'];
331 }
332
333 $directoryList = array();
334
335 foreach($regexes as $regex) {
336 $directoryList = array_merge($directoryList, glob($options['dir'].$regex, $glob_option));
337 }
338 $resp[$options['dir']] = $this->getFilesStats($directoryList, 0, 0, 0, $md5);
339 }
340 break;
341 case "dirsexists":
342 $resp = array();
343 $dirs = $params['dirs'];
344
345 foreach ($dirs as $dir) {
346 $path = ABSPATH.$dir;
347 if (file_exists($path) && is_dir($path) && !is_link($path)) {
348 $resp[$dir] = true;
349 } else {
350 $resp[$dir] = false;
351 }
352 }
353
354 $resp["status"] = "Done";
355 break;
356 case "gtfilescntent":
357 $files = $params['files'];
358 $withContent = array_key_exists('withcontent', $params) ? $params['withcontent'] : true;
359 $resp = array("files_content" => $this->getFilesContent($files, $withContent));
360 break;
361 case "gtfls":
362 $resp = array();
363
364 if (array_key_exists('get_files_content', $params)) {
365 $args = $params['get_files_content'];
366 $with_content = array_key_exists('withcontent', $args) ? $args['withcontent'] : true;
367 $resp['get_files_content'] = $this->getFilesContent($args['files'], $with_content);
368 }
369
370 if (array_key_exists('get_files_stats', $params)) {
371 $args = $params['get_files_stats'];
372 $md5 = array_key_exists('md5', $args) ? $args['md5'] : false;
373 $stats = $this->getFilesStats(
374 $args['files'], $args['offset'], $args['limit'], $args['bsize'], $md5
375 );
376
377 $result = array();
378
379 if (array_key_exists('stats', $stats)) {
380 $result['stats'] = array();
381 foreach ($stats['stats'] as $stat) {
382 $result['stats'][$stat['filename']] = $stat;
383 }
384 }
385
386 if (array_key_exists('missingfiles', $stats)) {
387 $result['missingfiles'] = $stats['missingfiles'];
388 }
389
390 $resp['get_files_stats'] = $result;
391 }
392
393 break;
394 default:
395 $resp = false;
396 }
397 $end_stream_info = $this->stream->endStream();
398 if (!empty($end_stream_info) && is_array($resp)) {
399 $resp = array_merge($resp, $end_stream_info);
400 }
401 } else {
402 $resp = $stream_init_info;
403 }
404 return $resp;
405 }
406 }
407 endif;