PluginProbe
The WP Remote WordPress Plugin / 4.74
The WP Remote WordPress Plugin v4.74
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 4.74, at callback/wings/fs.php

394 lines 10.6 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.1;
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[] = $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 = urldecode($params['initdir']);
255 $offset = intval(urldecode($params['offset']));
256 $limit = intval(urldecode($params['limit']));
257 $bsize = intval(urldecode($params['bsize']));
258 $regex = urldecode($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(urldecode($params['bsize']));
272 foreach($dir_options as $option) {
273 $dir = urldecode($option['dir']);
274 $offset = intval(urldecode($option['offset']));
275 $limit = intval(urldecode($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 $md5 = array_key_exists('md5', $params) ? $params['md5'] : false;
292 $stats = $this->getFilesStats(
293 $params['files'], $params['offset'], $params['limit'], $params['bsize'], $md5
294 );
295 $resp = array('stats' => $stats);
296 break;
297 case "sendmanyfiles":
298 $files = $params['files'];
299 $offset = intval(urldecode($params['offset']));
300 $limit = intval(urldecode($params['limit']));
301 $bsize = intval(urldecode($params['bsize']));
302 $resp = $this->uploadFiles($files, $offset, $limit, $bsize);
303 break;
304 case "filelist":
305 $dir_options = array();
306 if (array_key_exists('dir_options', $params)) {
307 $dir_options = $params['dir_options'];
308 }
309 if (array_key_exists('chdir', $params)) {
310 chdir(ABSPATH);
311 }
312 $resp = array();
313 foreach($dir_options as $options) {
314 $glob_option = 0;
315 if (array_key_exists('onlydir', $options)) {
316 $glob_option = GLOB_ONLYDIR;
317 }
318
319 $regexes = array("*", ".*");
320 if (array_key_exists('regex', $options)) {
321 $regexes = array($options['regex']);
322 }
323
324 $md5 = false;
325 if (array_key_exists('md5', $options)) {
326 $md5 = $options['md5'];
327 }
328
329 $directoryList = array();
330
331 foreach($regexes as $regex) {
332 $directoryList = array_merge($directoryList, glob($options['dir'].$regex, $glob_option));
333 }
334 $resp[$options['dir']] = array('stats' => $this->getFilesStats($directoryList, 0, 0, 0, $md5));
335 }
336 break;
337 case "dirsexists":
338 $resp = array();
339 $dirs = $params['dirs'];
340
341 foreach ($dirs as $dir) {
342 $path = ABSPATH.$dir;
343 if (file_exists($path) && is_dir($path) && !is_link($path)) {
344 $resp[$dir] = true;
345 } else {
346 $resp[$dir] = false;
347 }
348 }
349
350 $resp["status"] = "Done";
351 break;
352 case "gtfilescntent":
353 $files = $params['files'];
354 $withContent = array_key_exists('withcontent', $params) ? $params['withcontent'] : true;
355 $resp = array("files_content" => $this->getFilesContent($files, $withContent));
356 break;
357 case "gtfls":
358 $resp = array();
359
360 if (array_key_exists('get_files_content', $params)) {
361 $args = $params['get_files_content'];
362 $with_content = array_key_exists('withcontent', $args) ? $args['withcontent'] : true;
363 $resp['get_files_content'] = $this->getFilesContent($args['files'], $with_content);
364 }
365
366 if (array_key_exists('get_files_stats', $params)) {
367 $args = $params['get_files_stats'];
368 $md5 = array_key_exists('md5', $args) ? $args['md5'] : false;
369 $stats = $this->getFilesStats(
370 $args['files'], $args['offset'], $args['limit'], $args['bsize'], $md5
371 );
372
373 $result = array();
374 foreach ($stats as $stat) {
375 $result[$stat['filename']] = $stat;
376 }
377 $resp['get_files_stats'] = $result;
378 }
379
380 break;
381 default:
382 $resp = false;
383 }
384 $end_stream_info = $this->stream->endStream();
385 if (!empty($end_stream_info) && is_array($resp)) {
386 $resp = array_merge($resp, $end_stream_info);
387 }
388 } else {
389 $resp = $stream_init_info;
390 }
391 return $resp;
392 }
393 }
394 endif;