PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / framework / base / file.php

file.php in Defender Security – Malware Scanner, Login Security & Firewall 3.0.1, at framework/base/file.php

461 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Author: Hoang Ngo
4 */
5
6 namespace Calotes\Base;
7
8 class File {
9 const ENGINE_SPL = 'spl', ENGINE_SCANDIR = 'scan_dir', ENGINE_OPENDIR = 'open_dir';
10 /**
11 * Engine use to create a dir tree
12 *
13 * @var string
14 */
15 public $engine = '';
16 /**
17 * Absolute path to a folder need to create a dir tre
18 *
19 * @var string
20 */
21 public $path = '';
22
23 /**
24 * Is the result including file?
25 *
26 * @var bool
27 */
28 public $include_file = true;
29 /**
30 * Is the result include dir
31 *
32 * @var bool
33 */
34 public $include_dir = true;
35
36 /**
37 * @var bool
38 */
39 public $include_hidden = false;
40
41 /**
42 * This is where to define the rules for exclude files out of the result
43 *
44 * 'ext'=>array('jpg','gif') file extension you don't want appear in the result
45 * 'path'=>array('/tmp/file1.txt','/tmp/file2') absolute path to files
46 * 'dir'=>array('/tmp/','/dir/') absolute path to the directory you dont want to include files
47 * 'filename'=>array('abc*') file name you don't want to include, can be regex,
48 *
49 * @var array
50 */
51 public $exclude = array();
52
53 /**
54 * This is where to define the rules for include files, please note that if $include is provided, the $exclude
55 * will get ignored
56 *
57 * 'ext'=>array('jpg','gif') file extension you don't want appear in the result
58 * 'path'=>array('/tmp/file1.txt','/tmp/file2') absolute path to files
59 * 'dir'=>array('/tmp/','/dir/') absolute path to the directory you dont want to include files
60 * 'filename'=>array('abc*') file name you don't want to include, can be regex,
61 *
62 * @var array
63 */
64 public $include = array();
65
66 /**
67 * Does this search recursive
68 *
69 * @var bool
70 */
71 public $is_recursive = true;
72
73 /**
74 * if provided, only search file smaller than this
75 *
76 * @var bool
77 */
78 public $max_filesize = false;
79
80 /**
81 * @param $path
82 * @param bool|true $include_file
83 * @param bool|false $include_dir
84 * @param array $include
85 * @param array $exclude
86 * @param bool|true $is_recursive
87 * @param bool|int $max_filesize
88 */
89 public function __construct( $path, $include_file = true, $include_dir = false, $include = array(), $exclude = array(), $is_recursive = true, $include_hidden = false, $max_filesize = false ) {
90 $this->path = $path;
91 $this->include_file = $include_file;
92 $this->include_dir = $include_dir;
93 $this->include = $include;
94 $this->exclude = $exclude;
95 $this->is_recursive = $is_recursive;
96 $this->engine = self::ENGINE_SCANDIR;
97 $this->include_hidden = $include_hidden;
98 $this->max_filesize = $max_filesize;
99 }
100
101 /**
102 * @return array
103 */
104 public function get_dir_tree() {
105 $result = array();
106 if ( ! is_dir( $this->path ) ) {
107 return $result;
108 }
109
110 if ( $this->engine == self::ENGINE_SPL ) {
111 $result = $this->_get_dir_tree_by_spl();
112 } elseif ( $this->engine == self::ENGINE_SCANDIR ) {
113 $result = $this->_get_dir_tree_by_scandir();
114 } elseif ( $this->engine == self::ENGINE_OPENDIR ) {
115 $result = $this->_get_dir_tree_by_open_dir();
116 }
117
118 return $result;
119 }
120
121 /**
122 * Create a dir tree by SPL library
123 *
124 * @return array
125 */
126 private function _get_dir_tree_by_spl() {
127 $path = $this->path;
128 $data = array();
129 if ( $this->is_recursive ) {
130 $directory_flag = \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO
131 | \FilesystemIterator::UNIX_PATHS | \FilesystemIterator::SKIP_DOTS;
132 $directory = new \RecursiveDirectoryIterator( $path, $directory_flag );
133
134 if ( ! empty( $this->include ) || ! empty( $this->exclude ) ) {
135 $directory = new \RecursiveCallbackFilterIterator(
136 $directory,
137 array(
138 &$this,
139 'filter_directory',
140 )
141 );
142 }
143 $tree = new \RecursiveIteratorIterator( $directory, \RecursiveIteratorIterator::SELF_FIRST );
144 if ( $this->is_recursive !== true ) {
145 $tree->setMaxDepth( $this->is_recursive );
146 }
147 } else {
148 $tree = new \FilesystemIterator( $path );
149 }
150
151 foreach ( $tree as $file ) {
152 $real_path = $file->getRealPath();
153
154 $is_hidden = explode( DIRECTORY_SEPARATOR . '.', $real_path );
155 if ( count( $is_hidden ) > 1 && $this->include_hidden == false ) {
156 continue;
157 }
158 if ( $this->is_recursive == false ) {
159 // have to filter this, for un recursive
160 if ( ! empty( $this->include ) || ! empty( $this->exclude ) ) {
161 if ( $this->filter_directory( $real_path ) == false ) {
162 continue;
163 }
164 }
165 }
166
167 if ( $this->include_file == false && $file->isFile() ) {
168 continue;
169 }
170
171 if ( $this->include_dir == false && $file->isDir() ) {
172 continue;
173 }
174
175 if ( $file->isFile() && is_numeric( $this->max_filesize ) ) {
176 // convert max to bytes
177 $max_size = $this->max_filesize * ( pow( 1024, 2 ) );
178 if ( $file->getSize() > $max_size ) {
179 continue;
180 }
181 }
182
183 $data[] = $real_path;
184 }
185
186 return $data;
187 }
188
189 /**
190 * @param null $path
191 *
192 * @return array
193 */
194 private function _get_dir_tree_by_scandir( $path = null ) {
195 if ( is_null( $path ) ) {
196 $path = $this->path;
197 }
198 $path = rtrim( $path, DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR;
199 $rfiles = scandir( $path );
200 $data = array();
201
202 foreach ( $rfiles as $rfile ) {
203 if ( $rfile == '.' || $rfile == '..' ) {
204 continue;
205 }
206 if ( substr( pathinfo( $rfile, PATHINFO_BASENAME ), 0, 1 ) == '.'
207 && $this->include_hidden == false ) {
208 // hidden files, move on
209 continue;
210 }
211
212 $real_path = $path . $rfile;
213
214 $type = filetype( $real_path );
215
216 if ( ( ! empty( $this->include ) || ! empty( $this->exclude ) ) && ( $this->filter_directory( $real_path, $type ) == false ) ) {
217 continue;
218 }
219
220 if ( $type == 'file' && $this->include_file == true ) {
221 if ( is_numeric( $this->max_filesize ) ) {
222 $max_size = $this->max_filesize * ( pow( 1024, 2 ) );
223 if ( filesize( $real_path ) > $max_size ) {
224 continue;
225 } else {
226 $data[] = $real_path;
227 }
228 } else {
229 $data[] = $real_path;
230 }
231 }
232
233 if ( $type == 'dir' ) {
234 if ( $this->include_dir ) {
235 $data[] = $real_path;
236 }
237 if ( $this->is_recursive ) {
238 $tdata = $this->_get_dir_tree_by_scandir( $real_path );
239 $data = array_merge( $data, $tdata );
240 }
241 }
242 }
243
244 return $data;
245 }
246
247 /**
248 * Query files on path using opendir&readir
249 *
250 * @param null $path
251 *
252 * @return array
253 * @since 1.0.5
254 */
255 private function _get_dir_tree_by_open_dir( $path = null ) {
256 if ( is_null( $path ) ) {
257 $path = $this->path;
258 }
259 $path = rtrim( $path, DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR;
260 $data = array();
261
262 if ( $dh = opendir( $path ) ) {
263 while ( ( $file = readdir( $dh ) ) !== false ) {
264 if ( $file == '.' || $file == '..' ) {
265 continue;
266 }
267 $real_path = $path . $file;
268 if ( substr( pathinfo( $real_path, PATHINFO_BASENAME ), 0, 1 ) == '.' ) {
269 // hidden files, move on
270 continue;
271 }
272
273 if ( ( ! empty( $this->include ) || ! empty( $this->exclude ) ) && ( $this->filter_directory( $real_path ) == false ) ) {
274 continue;
275 }
276
277 $type = filetype( $real_path );
278
279 if ( $type == 'file' && $this->include_file == true ) {
280 if ( is_numeric( $this->max_filesize ) ) {
281 $max_size = $this->max_filesize * ( pow( 1024, 2 ) );
282 if ( filesize( $real_path ) > $max_size ) {
283 continue;
284 } else {
285 $data[] = $real_path;
286 }
287 } else {
288 $data[] = $real_path;
289 }
290 }
291
292 if ( $type == 'dir' ) {
293 if ( $this->include_dir ) {
294 $data[] = $real_path;
295 }
296 if ( $this->is_recursive ) {
297 $tdata = $this->_get_dir_tree_by_open_dir( $real_path );
298 $data = array_merge( $data, $tdata );
299 }
300 }
301 }
302 closedir( $dh );
303 }
304
305 return $data;
306 }
307
308 /**
309 * Filter for recursive directory tree
310 *
311 * @param $current
312 *
313 * @return bool
314 */
315 public function filter_directory( $current, $filetype = null ) {
316 if ( ! empty( $this->include ) ) {
317 return $this->_filter_include( $current, $filetype );
318 } elseif ( ! empty( $this->exclude ) ) {
319 return $this->_filter_exclude( $current, $filetype );
320 }
321 }
322
323 /**
324 * @param $path
325 *
326 * @return bool
327 */
328 private function _filter_include( $path, $filetype = null ) {
329 $include = $this->include;
330 $exclude = $this->exclude;
331 $applied = 0;
332 $dir_include = isset( $include['dir'] ) ? $include['dir'] : array();
333 $dir_exclude = isset( $exclude['dir'] ) ? $exclude['dir'] : array();
334
335 if ( ! is_null( $filetype ) ) {
336 $type = $filetype;
337 } else {
338 $type = filetype( $path );
339 }
340
341 if ( is_array( $dir_include ) && count( $dir_include ) ) {
342 if ( is_array( $dir_exclude ) ) {
343 foreach ( $dir_exclude as $dir ) {
344 if ( strpos( $path, $dir ) === 0 ) {
345 // this mean, exlucde matched, we wont list this
346 // move to next loop
347 continue;
348 }
349 }
350 }
351
352 foreach ( $dir_include as $dir ) {
353 if ( strpos( $path, $dir ) === 0 ) {
354 return true;
355 }
356 }
357 $applied ++;
358 }
359
360 // next extension
361 $ext_include = isset( $include['ext'] ) ? $include['ext'] : array();
362
363 if ( is_array( $ext_include ) && count( $ext_include ) && $type == 'file' ) {
364 // we will uses foreach and strcasecmp instead of regex cause it faster
365 foreach ( $ext_include as $ext ) {
366 if ( strcasecmp( pathinfo( $path, PATHINFO_EXTENSION ), $ext ) === 0 ) {
367 // match
368 return true;
369 }
370 }
371 $applied ++;
372 }
373
374 // now filename
375 $filename_include = isset( $include['filename'] ) ? $include['filename'] : array();
376 if ( is_array( $filename_include ) && count( $filename_include ) && $type == 'file' ) {
377 foreach ( $filename_include as $filename ) {
378 if ( preg_match( '/' . $filename . '/', pathinfo( $path, PATHINFO_BASENAME ) ) ) {
379 return true;
380 }
381 }
382 $applied ++;
383 }
384
385 // now abs path
386 $path_include = isset( $include['path'] ) ? $include['path'] : array();
387 if ( is_array( $path_include ) && count( $path_include ) && $type == 'file' ) {
388 foreach ( $path_include as $p ) {
389 if ( strcmp( $p, $path ) === 0 ) {
390 return true;
391 }
392 }
393 $applied ++;
394 }
395
396 if ( $applied == 0 ) {
397 return true;
398 }
399
400 return false;
401 }
402
403 /**
404 * Run the filter for a file/dir
405 *
406 * @param $path
407 *
408 * @return bool
409 */
410 private function _filter_exclude( $path, $filetype = null ) {
411 $exclude = $this->exclude;
412 // first filer dir, or file inside dir
413 if ( ! is_null( $filetype ) ) {
414 $type = $filetype;
415 } else {
416 $type = filetype( $path );
417 }
418 $dir_exclude = isset( $exclude['dir'] ) ? $exclude['dir'] : array();
419 if ( is_array( $dir_exclude ) && count( $dir_exclude ) ) {
420 foreach ( $dir_exclude as $dir ) {
421 if ( strpos( $path, $dir ) === 0 ) {
422 return false;
423 }
424 }
425 }
426
427 // next extension
428 $ext_exclude = isset( $exclude['ext'] ) ? $exclude['ext'] : array();
429 if ( is_array( $ext_exclude ) && count( $ext_exclude ) && $type == 'file' ) {
430 // we will uses foreach and strcasecmp instead of regex cause it faster
431 foreach ( $ext_exclude as $ext ) {
432 if ( strcasecmp( pathinfo( $path, PATHINFO_EXTENSION ), $ext ) === 0 ) {
433 // match
434 return false;
435 }
436 }
437 }
438 // now filename
439 $filename_exclude = isset( $exclude['filename'] ) ? $exclude['filename'] : array();
440 if ( is_array( $filename_exclude ) && count( $filename_exclude ) && $type == 'file' ) {
441 foreach ( $filename_exclude as $filename ) {
442 if ( preg_match( '/' . $filename . '/', pathinfo( $path, PATHINFO_BASENAME ) ) ) {
443 return false;
444 }
445 }
446 }
447
448 // now abs path
449 $path_exclude = isset( $exclude['path'] ) ? $exclude['path'] : array();
450 if ( is_array( $path_exclude ) && count( $path_exclude ) && $type == 'file' ) {
451 foreach ( $path_exclude as $p ) {
452 if ( strcmp( $p, $path ) === 0 ) {
453 return false;
454 }
455 }
456 }
457
458 return true;
459 }
460 }
461