forked from e107inc/e107
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfile_class.php
357 lines (315 loc) · 9.02 KB
/
file_class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
<?php
/*
* e107 website system
*
* Copyright (C) 2008-2009 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*
*
*
* $Source: /cvs_backup/e107_0.8/e107_handlers/file_class.php,v $
* $Revision$
* $Date$
* $Author$
*/
if (!defined('e107_INIT')) { exit; }
/*
Class to return a list of files, with options to specify a filename matching string and exclude specified directories.
get_files() is the usual entry point.
$path - start directory (doesn't matter whether it has a trailing '/' or not - its stripped)
$fmask - regex expression of file names to match (empty string matches all). Omit the start and end delimiters - '#' is added here.
If the first character is '~', this becomes a list of files to exclude (the '~' is stripped)
Note that 'special' characters such as '.' must be escaped by the caller
There is a standard list of files which are always excluded (not affected by the leading '~')
The regex is case-sensitive.
$omit - specifies directories to exclude, in addition to the standard list. Does an exact, case-sensitive match.
'standard' or empty string - uses the standard exclude list
Otherwise a single directory name, or an array of names.
$recurse_level - number of directory levels to search.
If the standard file or directory filter is unacceptable in a special application, the relevant variable can be set to an empty array (emphasis - ARRAY).
setDefaults() restores the defaults - preferable to setting using a 'fixed' string. Can be called prior to using the class without knowledge of what went before.
get_dirs() returns a list of the directories in a specified directory (no recursion) - similar critera to get_files()
rmtree() attempts to remove a complete directory tree, including the files it contains
Note:
Directory filters look for an exact match (i.e. regex not supported)
Behaviour is slightly different to previous version:
$omit used to be applied to just files (so would recurse down a tree even if no files match) - now used for directories
The default file and directory filters are always applied (unless modified between instantiation/set defaults and call)
*/
class e_file
{
public $dirFilter; // Array of directory names to ignore (in addition to any set by caller)
public $fileFilter; // Array of file names to ignore (in addition to any set by caller)
/**
* Defines what array format should return get_files() method
* If one of 'fname', 'path', 'full' - numerical array.
* If default - associative array (depends on $finfo value).
*
* @see get_files()
* @var string one of the following: default (BC) | fname | path | full
*/
public $mode = 'default';
/**
* Defines what info should gatter get_files method.
* Works only in 'default' mode.
*
* @var string default (BC) | image | file | all
*/
public $finfo = 'default';
// Constructor
function __construct()
{
$this->setDefaults();
}
function setDefaults()
{
$this->dirFilter = array('/', 'CVS', '.svn'); // Default directory filter (exact matches only)
$this->fileFilter = array('^thumbs\.db$','^Thumbs\.db$','.*\._$','^\.htaccess$','^index\.html$','^null\.txt$','\.bak$','^.tmp'); // Default file filter (regex format)
}
public function setFileInfo($val='default')
{
$this->finfo = $val;
}
/**
* Read files from given path
*
* @param string $path
* @param string $fmask [optional]
* @param string $omit [optional]
* @param integer $recurse_level [optional]
* @return array of file names/paths
*/
function get_files($path, $fmask = '', $omit='standard', $recurse_level = 0)
{
$ret = array();
$invert = FALSE;
if (substr($fmask,0,1) == '~')
{
$invert = TRUE; // Invert selection - exclude files which match selection
$fmask = substr($fmask,1);
}
if($recurse_level < 0)
{
return $ret;
}
if(substr($path,-1) == '/')
{
$path = substr($path, 0, -1);
}
if(!$handle = opendir($path))
{
return $ret;
}
if (($omit == 'standard') || ($omit == ''))
{
$omit = array();
}
else
{
if (!is_array($omit))
{
$omit = array($omit);
}
}
while (false !== ($file = readdir($handle)))
{
if(is_dir($path.'/'.$file))
{ // Its a directory - recurse into it unless a filtered directory or required depth achieved
// Must always check for '.' and '..'
if(($file != '.') && ($file != '..') && !in_array($file, $this->dirFilter) && !in_array($file, $omit) && ($recurse_level > 0))
{
$xx = $this->get_files($path.'/'.$file, $fmask, $omit, $recurse_level - 1);
$ret = array_merge($ret,$xx);
}
}
else
{
// Now check against standard reject list and caller-specified list
if (($fmask == '') || ($invert != preg_match("#".$fmask."#", $file)))
{ // File passes caller's filter here
$rejected = FALSE;
// Check against the generic file reject filter
foreach($this->fileFilter as $rmask)
{
if(preg_match("#".$rmask."#", $file))
{
$rejected = TRUE;
break; // continue 2 may well work
}
}
if($rejected == FALSE)
{
switch($this->mode)
{
case 'fname':
$ret[] = $file;
break;
case 'path':
$ret[] = $path."/";
break;
case 'full':
$ret[] = $path."/".$file;
break;
case 'all':
default:
if('default' != $this->finfo)
{
$finfo = $this->get_file_info($path."/".$file, ('file' != $this->finfo)); // -> 'all' & 'image'
}
$finfo['path'] = $path."/"; // important: leave this slash here and update other file instead.
$finfo['fname'] = $file;
$ret[] = $finfo;
break;
}
}
}
}
}
return $ret;
}
function get_file_info($path_to_file, $imgcheck = true)
{
$finfo = array();
if($imgcheck && ($tmp = getimagesize($path_to_file)))
{
$finfo['img-width'] = $tmp[0];
$finfo['img-height'] = $tmp[1];
$finfo['mime'] = $tmp['mime'];
}
$tmp = stat($path_to_file);
if($tmp)
{
$finfo['fsize'] = $tmp['size'];
$finfo['modified'] = $tmp['mtime'];
}
// associative array elements: dirname, basename, extension, filename
$finfo['pathinfo'] = pathinfo($path_to_file);
return $finfo;
}
// Get a list of directories matching $fmask, omitting any in the $omit array - same calling syntax as get_files()
// N.B. - no recursion - just looks in the specified directory.
function get_dirs($path, $fmask = '', $omit='standard')
{
$ret = array();
if(substr($path,-1) == '/')
{
$path = substr($path, 0, -1);
}
if(!$handle = opendir($path))
{
return $ret;
}
if($omit == 'standard')
{
$omit = array();
}
else
{
if (!is_array($omit))
{
$omit = array($omit);
}
}
while (false !== ($file = readdir($handle)))
{
if(is_dir($path.'/'.$file) && ($file != '.') && ($file != '..') && !in_array($file, $this->dirFilter) && !in_array($file, $omit) && ($fmask == '' || preg_match("#".$fmask."#", $file)))
{
$ret[] = $file;
}
}
return $ret;
}
// Delete a complete directory tree
function rmtree($dir)
{
if (substr($dir, -1) != '/')
{
$dir .= '/';
}
if ($handle = opendir($dir))
{
while ($obj = readdir($handle))
{
if ($obj != '.' && $obj != '..')
{
if (is_dir($dir.$obj))
{
if (!$this->rmtree($dir.$obj))
{
return false;
}
}
elseif (is_file($dir.$obj))
{
if (!unlink($dir.$obj))
{
return false;
}
}
}
}
closedir($handle);
if (!@rmdir($dir))
{
return false;
}
return true;
}
return false;
}
/**
* Parse a file size string (e.g. 16M) and compute the simple numeric value.
*
* @param string $source - input string which may include 'multiplier' characters such as 'M' or 'G'. Converted to 'decoded value'
* @param int $compare - a 'compare' value
* @param string $action - values (gt|lt)
*
* @return int file size value.
* If the decoded value evaluates to zero, returns the value of $compare
* If $action == 'gt', return the larger of the decoded value and $compare
* If $action == 'lt', return the smaller of the decoded value and $compare
*/
function file_size_decode($source, $compare = 0, $action = '')
{
$source = trim($source);
if (strtolower(substr($source, -1, 1)) == 'b')
$source = substr($source, 0, -1); // Trim a trailing byte indicator
$mult = 1;
if (strlen($source) && (strtoupper(substr($source, -1, 1)) == 'B'))
$source = substr($source, 0, -1);
if (!$source || is_numeric($source))
{
$val = $source;
}
else
{
$val = substr($source, 0, -1);
switch (substr($source, -1, 1))
{
case 'T':
$val = $val * 1024;
case 'G':
$val = $val * 1024;
case 'M':
$val = $val * 1024;
case 'K':
case 'k':
$val = $val * 1024;
break;
}
}
if ($val == 0)
return $compare;
switch ($action)
{
case 'lt':
return min($val, $compare);
case 'gt':
return max($val, $compare);
default:
return $val;
}
return 0;
}
}