This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
0 ignored issues
–
show
|
|||
2 | defined('PH7') or exit('Restricted access'); |
||
3 | if (!\PH7\Admin::auth()) exit('Restricted access'); // Accessible only for admins |
||
4 | |||
5 | /** |
||
6 | * elFinder - file manager for web. |
||
7 | * Core class. |
||
8 | * |
||
9 | * @package elfinder |
||
10 | * @author Dmitry (dio) Levashov |
||
11 | * @author Troex Nevelin |
||
12 | * @author Alexey Sukhotin |
||
13 | **/ |
||
14 | class elFinder |
||
15 | { |
||
16 | |||
17 | /** |
||
18 | * API version number |
||
19 | * |
||
20 | * @var string |
||
21 | **/ |
||
22 | protected $version = '2.1'; |
||
23 | |||
24 | /** |
||
25 | * Storages (root dirs) |
||
26 | * |
||
27 | * @var array |
||
28 | **/ |
||
29 | protected $volumes = array(); |
||
30 | |||
31 | /** |
||
32 | * Network mount drivers |
||
33 | * |
||
34 | * @var array |
||
35 | */ |
||
36 | public static $netDrivers = array(); |
||
37 | |||
38 | /** |
||
39 | * elFinder global locale |
||
40 | * |
||
41 | * @var string |
||
42 | */ |
||
43 | public static $locale = ''; |
||
44 | |||
45 | /** |
||
46 | * elFinderVolumeDriver default mime.type file path |
||
47 | * |
||
48 | * @var string |
||
49 | */ |
||
50 | public static $defaultMimefile = ''; |
||
51 | |||
52 | /** |
||
53 | * elFinder session wrapper object |
||
54 | * |
||
55 | * @var elFinderSessionInterface |
||
56 | */ |
||
57 | protected $session; |
||
58 | |||
59 | /** |
||
60 | * elFinder global sessionCacheKey |
||
61 | * |
||
62 | * @deprecated |
||
63 | * @var string |
||
64 | */ |
||
65 | public static $sessionCacheKey = ''; |
||
66 | |||
67 | /** |
||
68 | * Is session closed |
||
69 | * |
||
70 | * @deprecated |
||
71 | * @var bool |
||
72 | */ |
||
73 | private static $sessionClosed = false; |
||
74 | |||
75 | /** |
||
76 | * elFinder base64encodeSessionData |
||
77 | * elFinder save session data as `UTF-8` |
||
78 | * If the session storage mechanism of the system does not allow `UTF-8` |
||
79 | * And it must be `true` option 'base64encodeSessionData' of elFinder |
||
80 | * |
||
81 | * @var bool |
||
82 | */ |
||
83 | protected static $base64encodeSessionData = false; |
||
84 | |||
85 | /** |
||
86 | * elFinder common tempraly path |
||
87 | * |
||
88 | * @var string |
||
89 | **/ |
||
90 | protected static $commonTempPath = ''; |
||
91 | |||
92 | /** |
||
93 | * Additional volume root options for network mounting volume |
||
94 | * |
||
95 | * @var array |
||
96 | */ |
||
97 | protected $optionsNetVolumes = array(); |
||
98 | |||
99 | /** |
||
100 | * Session key of net mount volumes |
||
101 | * |
||
102 | * @deprecated |
||
103 | * @var string |
||
104 | */ |
||
105 | protected $netVolumesSessionKey = ''; |
||
106 | |||
107 | /** |
||
108 | * Mounted volumes count |
||
109 | * Required to create unique volume id |
||
110 | * |
||
111 | * @var int |
||
112 | **/ |
||
113 | public static $volumesCnt = 1; |
||
114 | |||
115 | /** |
||
116 | * Default root (storage) |
||
117 | * |
||
118 | * @var elFinderStorageDriver |
||
119 | **/ |
||
120 | protected $default = null; |
||
121 | |||
122 | /** |
||
123 | * Commands and required arguments list |
||
124 | * |
||
125 | * @var array |
||
126 | **/ |
||
127 | protected $commands = array( |
||
128 | 'open' => array('target' => false, 'tree' => false, 'init' => false, 'mimes' => false, 'compare' => false), |
||
129 | 'ls' => array('target' => true, 'mimes' => false, 'intersect' => false), |
||
130 | 'tree' => array('target' => true), |
||
131 | 'parents' => array('target' => true), |
||
132 | 'tmb' => array('targets' => true), |
||
133 | 'file' => array('target' => true, 'download' => false), |
||
134 | 'zipdl' => array('targets' => true, 'download' => false), |
||
135 | 'size' => array('targets' => true), |
||
136 | 'mkdir' => array('target' => true, 'name' => false, 'dirs' => false), |
||
137 | 'mkfile' => array('target' => true, 'name' => true, 'mimes' => false), |
||
138 | 'rm' => array('targets' => true), |
||
139 | 'rename' => array('target' => true, 'name' => true, 'mimes' => false), |
||
140 | 'duplicate' => array('targets' => true, 'suffix' => false), |
||
141 | 'paste' => array('dst' => true, 'targets' => true, 'cut' => false, 'mimes' => false, 'renames' => false, 'hashes' => false, 'suffix' => false), |
||
142 | 'upload' => array('target' => true, 'FILES' => true, 'mimes' => false, 'html' => false, 'upload' => false, 'name' => false, 'upload_path' => false, 'chunk' => false, 'cid' => false, 'node' => false, 'renames' => false, 'hashes' => false, 'suffix' => false, 'mtime' => false), |
||
143 | 'get' => array('target' => true, 'conv' => false), |
||
144 | 'put' => array('target' => true, 'content' => '', 'mimes' => false), |
||
145 | 'archive' => array('targets' => true, 'type' => true, 'mimes' => false, 'name' => false), |
||
146 | 'extract' => array('target' => true, 'mimes' => false, 'makedir' => false), |
||
147 | 'search' => array('q' => true, 'mimes' => false, 'target' => false), |
||
148 | 'info' => array('targets' => true, 'compare' => false), |
||
149 | 'dim' => array('target' => true), |
||
150 | 'resize' => array('target' => true, 'width' => true, 'height' => true, 'mode' => false, 'x' => false, 'y' => false, 'degree' => false, 'quality' => false), |
||
151 | 'netmount' => array('protocol' => true, 'host' => true, 'path' => false, 'port' => false, 'user' => false, 'pass' => false, 'alias' => false, 'options' => false), |
||
152 | 'url' => array('target' => true, 'options' => false), |
||
153 | 'callback' => array('node' => true, 'json' => false, 'bind' => false, 'done' => false), |
||
154 | 'chmod' => array('targets' => true, 'mode' => true) |
||
155 | ); |
||
156 | |||
157 | /** |
||
158 | * Plugins instance |
||
159 | * |
||
160 | * @var array |
||
161 | **/ |
||
162 | protected $plugins = array(); |
||
163 | |||
164 | /** |
||
165 | * Commands listeners |
||
166 | * |
||
167 | * @var array |
||
168 | **/ |
||
169 | protected $listeners = array(); |
||
170 | |||
171 | /** |
||
172 | * script work time for debug |
||
173 | * |
||
174 | * @var string |
||
175 | **/ |
||
176 | protected $time = 0; |
||
177 | /** |
||
178 | * Is elFinder init correctly? |
||
179 | * |
||
180 | * @var bool |
||
181 | **/ |
||
182 | protected $loaded = false; |
||
183 | /** |
||
184 | * Send debug to client? |
||
185 | * |
||
186 | * @var string |
||
187 | **/ |
||
188 | protected $debug = false; |
||
189 | |||
190 | /** |
||
191 | * Call `session_write_close()` before exec command? |
||
192 | * |
||
193 | * @var bool |
||
194 | */ |
||
195 | protected $sessionCloseEarlier = true; |
||
196 | |||
197 | /** |
||
198 | * SESSION use commands @see __construct() |
||
199 | * |
||
200 | * @var array |
||
201 | */ |
||
202 | protected $sessionUseCmds = array(); |
||
203 | |||
204 | /** |
||
205 | * session expires timeout |
||
206 | * |
||
207 | * @var int |
||
208 | **/ |
||
209 | protected $timeout = 0; |
||
210 | |||
211 | /** |
||
212 | * Temp dir path for Upload |
||
213 | * |
||
214 | * @var string |
||
215 | */ |
||
216 | protected $uploadTempPath = ''; |
||
217 | |||
218 | /** |
||
219 | * Max allowed archive files size (0 - no limit) |
||
220 | * |
||
221 | * @var integer |
||
222 | */ |
||
223 | protected $maxArcFilesSize = 0; |
||
224 | |||
225 | /** |
||
226 | * undocumented class variable |
||
227 | * |
||
228 | * @var string |
||
229 | **/ |
||
230 | protected $uploadDebug = ''; |
||
231 | |||
232 | /** |
||
233 | * Errors from PHP |
||
234 | * |
||
235 | * @var array |
||
236 | **/ |
||
237 | public static $phpErrors = array(); |
||
238 | |||
239 | /** |
||
240 | * Errors from not mounted volumes |
||
241 | * |
||
242 | * @var array |
||
243 | **/ |
||
244 | public $mountErrors = array(); |
||
245 | |||
246 | /** |
||
247 | * URL for callback output window for CORS |
||
248 | * redirect to this URL when callback output |
||
249 | * |
||
250 | * @var string URL |
||
251 | */ |
||
252 | protected $callbackWindowURL = ''; |
||
253 | |||
254 | // Errors messages |
||
255 | const ERROR_UNKNOWN = 'errUnknown'; |
||
256 | const ERROR_UNKNOWN_CMD = 'errUnknownCmd'; |
||
257 | const ERROR_CONF = 'errConf'; |
||
258 | const ERROR_CONF_NO_JSON = 'errJSON'; |
||
259 | const ERROR_CONF_NO_VOL = 'errNoVolumes'; |
||
260 | const ERROR_INV_PARAMS = 'errCmdParams'; |
||
261 | const ERROR_OPEN = 'errOpen'; |
||
262 | const ERROR_DIR_NOT_FOUND = 'errFolderNotFound'; |
||
263 | const ERROR_FILE_NOT_FOUND = 'errFileNotFound'; // 'File not found.' |
||
264 | const ERROR_TRGDIR_NOT_FOUND = 'errTrgFolderNotFound'; // 'Target folder "$1" not found.' |
||
265 | const ERROR_NOT_DIR = 'errNotFolder'; |
||
266 | const ERROR_NOT_FILE = 'errNotFile'; |
||
267 | const ERROR_PERM_DENIED = 'errPerm'; |
||
268 | const ERROR_LOCKED = 'errLocked'; // '"$1" is locked and can not be renamed, moved or removed.' |
||
269 | const ERROR_EXISTS = 'errExists'; // 'File named "$1" already exists.' |
||
270 | const ERROR_INVALID_NAME = 'errInvName'; // 'Invalid file name.' |
||
271 | const ERROR_MKDIR = 'errMkdir'; |
||
272 | const ERROR_MKFILE = 'errMkfile'; |
||
273 | const ERROR_RENAME = 'errRename'; |
||
274 | const ERROR_COPY = 'errCopy'; |
||
275 | const ERROR_MOVE = 'errMove'; |
||
276 | const ERROR_COPY_FROM = 'errCopyFrom'; |
||
277 | const ERROR_COPY_TO = 'errCopyTo'; |
||
278 | const ERROR_COPY_ITSELF = 'errCopyInItself'; |
||
279 | const ERROR_REPLACE = 'errReplace'; // 'Unable to replace "$1".' |
||
280 | const ERROR_RM = 'errRm'; // 'Unable to remove "$1".' |
||
281 | const ERROR_RM_SRC = 'errRmSrc'; // 'Unable remove source file(s)' |
||
282 | const ERROR_MKOUTLINK = 'errMkOutLink'; // 'Unable to create a link to outside the volume root.' |
||
283 | const ERROR_UPLOAD = 'errUpload'; // 'Upload error.' |
||
284 | const ERROR_UPLOAD_FILE = 'errUploadFile'; // 'Unable to upload "$1".' |
||
285 | const ERROR_UPLOAD_NO_FILES = 'errUploadNoFiles'; // 'No files found for upload.' |
||
286 | const ERROR_UPLOAD_TOTAL_SIZE = 'errUploadTotalSize'; // 'Data exceeds the maximum allowed size.' |
||
287 | const ERROR_UPLOAD_FILE_SIZE = 'errUploadFileSize'; // 'File exceeds maximum allowed size.' |
||
288 | const ERROR_UPLOAD_FILE_MIME = 'errUploadMime'; // 'File type not allowed.' |
||
289 | const ERROR_UPLOAD_TRANSFER = 'errUploadTransfer'; // '"$1" transfer error.' |
||
290 | const ERROR_UPLOAD_TEMP = 'errUploadTemp'; // 'Unable to make temporary file for upload.' |
||
291 | const ERROR_ACCESS_DENIED = 'errAccess'; |
||
292 | const ERROR_NOT_REPLACE = 'errNotReplace'; // Object "$1" already exists at this location and can not be replaced with object of another type. |
||
293 | const ERROR_SAVE = 'errSave'; |
||
294 | const ERROR_EXTRACT = 'errExtract'; |
||
295 | const ERROR_ARCHIVE = 'errArchive'; |
||
296 | const ERROR_NOT_ARCHIVE = 'errNoArchive'; |
||
297 | const ERROR_ARCHIVE_TYPE = 'errArcType'; |
||
298 | const ERROR_ARC_SYMLINKS = 'errArcSymlinks'; |
||
299 | const ERROR_ARC_MAXSIZE = 'errArcMaxSize'; |
||
300 | const ERROR_RESIZE = 'errResize'; |
||
301 | const ERROR_UNSUPPORT_TYPE = 'errUsupportType'; |
||
302 | const ERROR_CONV_UTF8 = 'errConvUTF8'; |
||
303 | const ERROR_NOT_UTF8_CONTENT = 'errNotUTF8Content'; |
||
304 | const ERROR_NETMOUNT = 'errNetMount'; |
||
305 | const ERROR_NETUNMOUNT = 'errNetUnMount'; |
||
306 | const ERROR_NETMOUNT_NO_DRIVER = 'errNetMountNoDriver'; |
||
307 | const ERROR_NETMOUNT_FAILED = 'errNetMountFailed'; |
||
308 | |||
309 | const ERROR_SESSION_EXPIRES = 'errSessionExpires'; |
||
310 | |||
311 | const ERROR_CREATING_TEMP_DIR = 'errCreatingTempDir'; |
||
312 | const ERROR_FTP_DOWNLOAD_FILE = 'errFtpDownloadFile'; |
||
313 | const ERROR_FTP_UPLOAD_FILE = 'errFtpUploadFile'; |
||
314 | const ERROR_FTP_MKDIR = 'errFtpMkdir'; |
||
315 | const ERROR_ARCHIVE_EXEC = 'errArchiveExec'; |
||
316 | const ERROR_EXTRACT_EXEC = 'errExtractExec'; |
||
317 | const ERROR_SEARCH_TIMEOUT = 'errSearchTimeout'; // 'Timed out while searching "$1". Search result is partial.' |
||
318 | const ERROR_REAUTH_REQUIRE = 'errReauthRequire'; // 'Re-authorization is required.' |
||
319 | |||
320 | /** |
||
321 | * Constructor |
||
322 | * |
||
323 | * @param array elFinder and roots configurations |
||
324 | * @author Dmitry (dio) Levashov |
||
325 | */ |
||
326 | public function __construct($opts) |
||
0 ignored issues
–
show
__construct uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
__construct uses the super-global variable $_POST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
__construct uses the super-global variable $_GET which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
327 | { |
||
328 | // set error handler of WARNING, NOTICE |
||
329 | set_error_handler('elFinder::phpErrorHandler', E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE); |
||
330 | |||
331 | // setup debug mode |
||
332 | $this->debug = (isset($opts['debug']) && $opts['debug'] ? true : false); |
||
0 ignored issues
–
show
The property
$debug was declared of type string , but isset($opts['debug']) &&...'debug'] ? true : false is of type boolean . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
Loading history...
|
|||
333 | if ($this->debug) { |
||
334 | error_reporting(-1); |
||
335 | ini_set('diaplay_errors', '1'); |
||
336 | } |
||
337 | |||
338 | if (!interface_exists('elFinderSessionInterface')) { |
||
339 | include_once dirname(__FILE__) . '/elFinderSessionInterface.php'; |
||
340 | } |
||
341 | |||
342 | // session handler |
||
343 | if (!empty($opts['session']) && $opts['session'] instanceof elFinderSessionInterface) { |
||
344 | $this->session = $opts['session']; |
||
345 | } else { |
||
346 | $sessionOpts = array( |
||
347 | 'base64encode' => !empty($opts['base64encodeSessionData']), |
||
348 | 'keys' => array( |
||
349 | 'default' => !empty($opts['sessionCacheKey']) ? $opts['sessionCacheKey'] : 'elFinderCaches', |
||
350 | 'netvolume' => !empty($opts['netVolumesSessionKey'])? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes' |
||
351 | ) |
||
352 | ); |
||
353 | if (! class_exists('elFinderSession')) { |
||
354 | include_once dirname(__FILE__) . '/elFinderSession.php'; |
||
355 | } |
||
356 | $this->session = new elFinderSession($sessionOpts); |
||
357 | } |
||
358 | // try session start | restart |
||
359 | $this->session->start(); |
||
360 | |||
361 | $sessionUseCmds = array(); |
||
362 | if (isset($opts['sessionUseCmds']) && is_array($opts['sessionUseCmds'])) { |
||
363 | $sessionUseCmds = $opts['sessionUseCmds']; |
||
364 | } |
||
365 | |||
366 | // set self::$volumesCnt by HTTP header "X-elFinder-VolumesCntStart" |
||
367 | if (isset($_SERVER['HTTP_X_ELFINDER_VOLUMESCNTSTART']) && ($volumesCntStart = intval($_SERVER['HTTP_X_ELFINDER_VOLUMESCNTSTART']))) { |
||
368 | self::$volumesCnt = $volumesCntStart; |
||
369 | } |
||
370 | |||
371 | $this->time = $this->utime(); |
||
0 ignored issues
–
show
The property
$time was declared of type string , but $this->utime() is of type double . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
Loading history...
|
|||
372 | $this->sessionCloseEarlier = isset($opts['sessionCloseEarlier'])? (bool)$opts['sessionCloseEarlier'] : true; |
||
373 | $this->sessionUseCmds = array_flip($sessionUseCmds); |
||
374 | $this->timeout = (isset($opts['timeout']) ? $opts['timeout'] : 0); |
||
375 | $this->uploadTempPath = (isset($opts['uploadTempPath']) ? $opts['uploadTempPath'] : ''); |
||
376 | $this->callbackWindowURL = (isset($opts['callbackWindowURL']) ? $opts['callbackWindowURL'] : ''); |
||
377 | elFinder::$commonTempPath = (isset($opts['commonTempPath']) ? $opts['commonTempPath'] : './.tmp'); |
||
378 | if (!is_writable(elFinder::$commonTempPath)) { |
||
379 | elFinder::$commonTempPath = ''; |
||
380 | } |
||
381 | $this->maxArcFilesSize = isset($opts['maxArcFilesSize'])? intval($opts['maxArcFilesSize']) : 0; |
||
382 | $this->optionsNetVolumes = (isset($opts['optionsNetVolumes']) && is_array($opts['optionsNetVolumes']))? $opts['optionsNetVolumes'] : array(); |
||
383 | |||
384 | // deprecated settings |
||
385 | $this->netVolumesSessionKey = !empty($opts['netVolumesSessionKey'])? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes'; |
||
0 ignored issues
–
show
The property
elFinder::$netVolumesSessionKey has been deprecated.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
386 | self::$sessionCacheKey = !empty($opts['sessionCacheKey']) ? $opts['sessionCacheKey'] : 'elFinderCaches'; |
||
0 ignored issues
–
show
The property
elFinder::$sessionCacheKey has been deprecated.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
387 | |||
388 | // check session cache |
||
389 | $_optsMD5 = md5(json_encode($opts['roots'])); |
||
390 | if ($this->session->get('_optsMD5') !== $_optsMD5) { |
||
391 | $this->session->set('_optsMD5', $_optsMD5); |
||
392 | } |
||
393 | |||
394 | // setlocale and global locale regists to elFinder::locale |
||
395 | self::$locale = !empty($opts['locale']) ? $opts['locale'] : 'en_US.UTF-8'; |
||
396 | if (false === setlocale(LC_ALL, self::$locale)) { |
||
397 | self::$locale = setlocale(LC_ALL, ''); |
||
398 | } |
||
399 | |||
400 | // set defaultMimefile |
||
401 | elFinder::$defaultMimefile = (isset($opts['defaultMimefile']) ? $opts['defaultMimefile'] : ''); |
||
402 | |||
403 | // bind events listeners |
||
404 | if (!empty($opts['bind']) && is_array($opts['bind'])) { |
||
405 | $_req = $_SERVER["REQUEST_METHOD"] == 'POST' ? $_POST : $_GET; |
||
406 | $_reqCmd = isset($_req['cmd']) ? $_req['cmd'] : ''; |
||
407 | foreach ($opts['bind'] as $cmd => $handlers) { |
||
408 | $doRegist = (strpos($cmd, '*') !== false); |
||
409 | if (! $doRegist) { |
||
410 | $_getcmd = create_function('$cmd', 'list($ret) = explode(\'.\', $cmd);return trim($ret);'); |
||
0 ignored issues
–
show
The use of
create_function is highly discouraged, better use a closure.
// Instead of
$function = create_function('$a, $b', 'return $a + $b');
// Better use
$function = function($a, $b) { return $a + $b; }
Loading history...
|
|||
411 | $doRegist = ($_reqCmd && in_array($_reqCmd, array_map($_getcmd, explode(' ', $cmd)))); |
||
412 | } |
||
413 | if ($doRegist) { |
||
414 | // for backward compatibility |
||
415 | if (! is_array($handlers)) { |
||
416 | $handlers = array($handlers); |
||
417 | } else { |
||
418 | if (count($handlers) === 2 && is_object($handlers[0])) { |
||
419 | $handlers = array($handlers); |
||
420 | } |
||
421 | } |
||
422 | foreach($handlers as $handler) { |
||
423 | if ($handler) { |
||
424 | if (is_string($handler) && strpos($handler, '.')) { |
||
425 | list($_domain, $_name, $_method) = array_pad(explode('.', $handler), 3, ''); |
||
426 | if (strcasecmp($_domain, 'plugin') === 0) { |
||
427 | if ($plugin = $this->getPluginInstance($_name, isset($opts['plugin'][$_name])? $opts['plugin'][$_name] : array()) |
||
428 | and method_exists($plugin, $_method)) { |
||
429 | $this->bind($cmd, array($plugin, $_method)); |
||
430 | } |
||
431 | } |
||
432 | } else { |
||
433 | $this->bind($cmd, $handler); |
||
434 | } |
||
435 | } |
||
436 | } |
||
437 | } |
||
438 | } |
||
439 | } |
||
440 | |||
441 | if (!isset($opts['roots']) || !is_array($opts['roots'])) { |
||
442 | $opts['roots'] = array(); |
||
443 | } |
||
444 | |||
445 | // check for net volumes stored in session |
||
446 | $netVolumes = $this->getNetVolumes(); |
||
447 | foreach ($netVolumes as $key => $root) { |
||
448 | if (! isset($root['id'])) { |
||
449 | // given fixed unique id |
||
450 | if (! $root['id'] = $this->getNetVolumeUniqueId($netVolumes)) { |
||
451 | $this->mountErrors[] = 'Netmount Driver "'.$root['driver'].'" : Could\'t given volume id.'; |
||
452 | continue; |
||
453 | } |
||
454 | } |
||
455 | $opts['roots'][$key] = $root; |
||
456 | } |
||
457 | |||
458 | // "mount" volumes |
||
459 | foreach ($opts['roots'] as $i => $o) { |
||
460 | $class = 'elFinderVolume'.(isset($o['driver']) ? $o['driver'] : ''); |
||
461 | |||
462 | if (class_exists($class)) { |
||
463 | $volume = new $class(); |
||
464 | |||
465 | try { |
||
466 | if ($this->maxArcFilesSize && (empty($o['maxArcFilesSize']) || $this->maxArcFilesSize < $o['maxArcFilesSize'])) { |
||
467 | $o['maxArcFilesSize'] = $this->maxArcFilesSize; |
||
468 | } |
||
469 | // pass session handler |
||
470 | $volume->setSession($this->session); |
||
471 | if ($volume->mount($o)) { |
||
472 | // unique volume id (ends on "_") - used as prefix to files hash |
||
473 | $id = $volume->id(); |
||
474 | |||
475 | $this->volumes[$id] = $volume; |
||
476 | if ((!$this->default || $volume->root() !== $volume->defaultPath()) && $volume->isReadable()) { |
||
477 | $this->default = $this->volumes[$id]; |
||
478 | } |
||
479 | } else { |
||
480 | $this->removeNetVolume($i, $volume); |
||
481 | $this->mountErrors[] = 'Driver "'.$class.'" : '.implode(' ', $volume->error()); |
||
482 | } |
||
483 | } catch (Exception $e) { |
||
484 | $this->removeNetVolume($i, $volume); |
||
485 | $this->mountErrors[] = 'Driver "'.$class.'" : '.$e->getMessage(); |
||
486 | } |
||
487 | } else { |
||
488 | $this->mountErrors[] = 'Driver "'.$class.'" does not exist'; |
||
489 | } |
||
490 | } |
||
491 | |||
492 | // if at least one readable volume - ii desu >_< |
||
493 | $this->loaded = !empty($this->default); |
||
494 | |||
495 | // restore error handler for now |
||
496 | restore_error_handler(); |
||
497 | } |
||
498 | |||
499 | /** |
||
500 | * Return elFinder session wrapper instance |
||
501 | * |
||
502 | * @return object elFinderSessionInterface |
||
503 | **/ |
||
504 | public function getSession() { |
||
505 | return $this->session; |
||
506 | } |
||
507 | |||
508 | /** |
||
509 | * Return true if fm init correctly |
||
510 | * |
||
511 | * @return bool |
||
512 | * @author Dmitry (dio) Levashov |
||
513 | **/ |
||
514 | public function loaded() { |
||
515 | return $this->loaded; |
||
516 | } |
||
517 | |||
518 | /** |
||
519 | * Return version (api) number |
||
520 | * |
||
521 | * @return string |
||
522 | * @author Dmitry (dio) Levashov |
||
523 | **/ |
||
524 | public function version() { |
||
525 | return $this->version; |
||
526 | } |
||
527 | |||
528 | /** |
||
529 | * Add handler to elFinder command |
||
530 | * |
||
531 | * @param string command name |
||
532 | * @param string|array callback name or array(object, method) |
||
533 | * @return elFinder |
||
534 | * @author Dmitry (dio) Levashov |
||
535 | **/ |
||
536 | public function bind($cmd, $handler) { |
||
537 | $allCmds = array_keys($this->commands); |
||
538 | $cmds = array(); |
||
539 | foreach(explode(' ', $cmd) as $_cmd) { |
||
540 | if ($_cmd !== '') { |
||
541 | if ($all = strpos($_cmd, '*') !== false) { |
||
0 ignored issues
–
show
$all is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
542 | list(, $sub) = array_pad(explode('.', $_cmd), 2, ''); |
||
543 | if ($sub) { |
||
544 | $sub = str_replace('\'', '\\\'', $sub); |
||
545 | $addSub = create_function('$cmd', 'return $cmd . \'.\' . trim(\'' . $sub . '\');'); |
||
0 ignored issues
–
show
The use of
create_function is highly discouraged, better use a closure.
// Instead of
$function = create_function('$a, $b', 'return $a + $b');
// Better use
$function = function($a, $b) { return $a + $b; }
Loading history...
|
|||
546 | $cmds = array_merge($cmds, array_map($addSub, $allCmds)); |
||
547 | } else { |
||
548 | $cmds = array_merge($cmds, $allCmds); |
||
549 | } |
||
550 | } else { |
||
551 | $cmds[] = $_cmd; |
||
552 | } |
||
553 | } |
||
554 | } |
||
555 | $cmds = array_unique($cmds); |
||
556 | |||
557 | foreach ($cmds as $cmd) { |
||
558 | if (!isset($this->listeners[$cmd])) { |
||
559 | $this->listeners[$cmd] = array(); |
||
560 | } |
||
561 | |||
562 | if (is_callable($handler)) { |
||
563 | $this->listeners[$cmd][] = $handler; |
||
564 | } |
||
565 | } |
||
566 | |||
567 | return $this; |
||
568 | } |
||
569 | |||
570 | /** |
||
571 | * Remove event (command exec) handler |
||
572 | * |
||
573 | * @param string command name |
||
574 | * @param string|array callback name or array(object, method) |
||
575 | * @return elFinder |
||
576 | * @author Dmitry (dio) Levashov |
||
577 | **/ |
||
578 | public function unbind($cmd, $handler) { |
||
579 | if (!empty($this->listeners[$cmd])) { |
||
580 | foreach ($this->listeners[$cmd] as $i => $h) { |
||
581 | if ($h === $handler) { |
||
582 | unset($this->listeners[$cmd][$i]); |
||
583 | return $this; |
||
584 | } |
||
585 | } |
||
586 | } |
||
587 | return $this; |
||
588 | } |
||
589 | |||
590 | /** |
||
591 | * Return true if command exists |
||
592 | * |
||
593 | * @param string command name |
||
594 | * @return bool |
||
595 | * @author Dmitry (dio) Levashov |
||
596 | **/ |
||
597 | public function commandExists($cmd) { |
||
598 | return $this->loaded && isset($this->commands[$cmd]) && method_exists($this, $cmd); |
||
599 | } |
||
600 | |||
601 | /** |
||
602 | * Return root - file's owner (public func of volume()) |
||
603 | * |
||
604 | * @param string file hash |
||
605 | * @return elFinderStorageDriver |
||
606 | * @author Naoki Sawada |
||
607 | */ |
||
608 | public function getVolume($hash) { |
||
609 | return $this->volume($hash); |
||
610 | } |
||
611 | |||
612 | /** |
||
613 | * Return command required arguments info |
||
614 | * |
||
615 | * @param string command name |
||
616 | * @return array |
||
617 | * @author Dmitry (dio) Levashov |
||
618 | **/ |
||
619 | public function commandArgsList($cmd) { |
||
620 | return $this->commandExists($cmd) ? $this->commands[$cmd] : array(); |
||
621 | } |
||
622 | |||
623 | private function session_expires() { |
||
624 | |||
625 | if (! $last = $this->session->get(':LAST_ACTIVITY')) { |
||
626 | $this->session->set(':LAST_ACTIVITY', time()); |
||
627 | return false; |
||
628 | } |
||
629 | |||
630 | if ( ($this->timeout > 0) && (time() - $last > $this->timeout) ) { |
||
631 | return true; |
||
632 | } |
||
633 | |||
634 | $this->session->set(':LAST_ACTIVITY', time()); |
||
635 | return false; |
||
636 | } |
||
637 | |||
638 | /** |
||
639 | * Exec command and return result |
||
640 | * |
||
641 | * @param string $cmd command name |
||
642 | * @param array $args command arguments |
||
643 | * @return array |
||
644 | * @author Dmitry (dio) Levashov |
||
645 | **/ |
||
646 | public function exec($cmd, $args) { |
||
647 | // set error handler of WARNING, NOTICE |
||
648 | set_error_handler('elFinder::phpErrorHandler', E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE); |
||
649 | |||
650 | if (!$this->loaded) { |
||
651 | return array('error' => $this->error(self::ERROR_CONF, self::ERROR_CONF_NO_VOL)); |
||
652 | } |
||
653 | |||
654 | if ($this->session_expires()) { |
||
655 | return array('error' => $this->error(self::ERROR_SESSION_EXPIRES)); |
||
656 | } |
||
657 | |||
658 | if (!$this->commandExists($cmd)) { |
||
659 | return array('error' => $this->error(self::ERROR_UNKNOWN_CMD)); |
||
660 | } |
||
661 | |||
662 | if (!empty($args['mimes']) && is_array($args['mimes'])) { |
||
663 | foreach ($this->volumes as $id => $v) { |
||
664 | $this->volumes[$id]->setMimesFilter($args['mimes']); |
||
665 | } |
||
666 | } |
||
667 | |||
668 | // detect destination dirHash and volume |
||
669 | $dstVolume = false; |
||
670 | $dst = ! empty($args['target'])? $args['target'] : (! empty($args['dst'])? $args['dst'] : ''); |
||
671 | if ($dst) { |
||
672 | $dstVolume = $this->volume($dst); |
||
673 | } else if (isset($args['targets']) && is_array($args['targets']) && isset($args['targets'][0])) { |
||
674 | $dst = $args['targets'][0]; |
||
675 | $dstVolume = $this->volume($dst); |
||
676 | if (($_stat = $dstVolume->file($dst)) && ! empty($_stat['phash'])) { |
||
677 | $dst = $_stat['phash']; |
||
678 | } else { |
||
679 | $dst = ''; |
||
680 | } |
||
681 | } |
||
682 | |||
683 | // call pre handlers for this command |
||
684 | $args['sessionCloseEarlier'] = isset($this->sessionUseCmds[$cmd])? false : $this->sessionCloseEarlier; |
||
685 | if (!empty($this->listeners[$cmd.'.pre'])) { |
||
686 | foreach ($this->listeners[$cmd.'.pre'] as $handler) { |
||
687 | call_user_func_array($handler, array($cmd, &$args, $this, $dstVolume)); |
||
688 | } |
||
689 | } |
||
690 | |||
691 | // unlock session data for multiple access |
||
692 | if ($this->sessionCloseEarlier && $args['sessionCloseEarlier']) { |
||
693 | $this->session->close(); |
||
694 | // deprecated property |
||
695 | elFinder::$sessionClosed = true; |
||
0 ignored issues
–
show
The property
elFinder::$sessionClosed has been deprecated.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
696 | } |
||
697 | |||
698 | if (substr(PHP_OS,0,3) === 'WIN') { |
||
699 | // set time out |
||
700 | elFinder::extendTimeLimit(300); |
||
701 | } |
||
702 | |||
703 | try { |
||
704 | $result = $this->$cmd($args); |
||
705 | } catch (Exception $e) { |
||
706 | $result = array( |
||
707 | 'error' => htmlspecialchars($e->getMessage()), |
||
708 | 'sync' => true |
||
709 | ); |
||
710 | } |
||
711 | |||
712 | // check change dstDir |
||
713 | $changeDst = false; |
||
714 | if ($dst && $dstVolume && (! empty($result['added']) || ! empty($result['removed']))) { |
||
715 | $changeDst = true; |
||
716 | } |
||
717 | |||
718 | foreach ($this->volumes as $volume) { |
||
719 | if (isset($result['removed'])) { |
||
720 | $result['removed'] = array_merge($result['removed'], $volume->removed()); |
||
721 | if (! $changeDst && $dst && $dstVolume && $volume === $dstVolume) { |
||
722 | $changeDst = true; |
||
723 | } |
||
724 | } |
||
725 | if (isset($result['added'])) { |
||
726 | $result['added'] = array_merge($result['added'], $volume->added()); |
||
727 | if (! $changeDst && $dst && $dstVolume && $volume === $dstVolume) { |
||
728 | $changeDst = true; |
||
729 | } |
||
730 | } |
||
731 | $volume->resetResultStat(); |
||
732 | } |
||
733 | |||
734 | // dstDir is changed |
||
735 | if ($changeDst) { |
||
736 | if ($dstDir = $dstVolume->dir($dst)) { |
||
737 | if (! isset($result['changed'])) { |
||
738 | $result['changed'] = array(); |
||
739 | } |
||
740 | $result['changed'][] = $dstDir; |
||
741 | } |
||
742 | } |
||
743 | |||
744 | // call handlers for this command |
||
745 | if (!empty($this->listeners[$cmd])) { |
||
746 | foreach ($this->listeners[$cmd] as $handler) { |
||
747 | if (call_user_func_array($handler,array($cmd, &$result, $args, $this, $dstVolume))) { |
||
748 | // handler return true to force sync client after command completed |
||
749 | $result['sync'] = true; |
||
750 | } |
||
751 | } |
||
752 | } |
||
753 | |||
754 | // replace removed files info with removed files hashes |
||
755 | if (!empty($result['removed'])) { |
||
756 | $removed = array(); |
||
757 | foreach ($result['removed'] as $file) { |
||
758 | $removed[] = $file['hash']; |
||
759 | } |
||
760 | $result['removed'] = array_unique($removed); |
||
761 | } |
||
762 | // remove hidden files and filter files by mimetypes |
||
763 | if (!empty($result['added'])) { |
||
764 | $result['added'] = $this->filter($result['added']); |
||
765 | } |
||
766 | // remove hidden files and filter files by mimetypes |
||
767 | if (!empty($result['changed'])) { |
||
768 | $result['changed'] = $this->filter($result['changed']); |
||
769 | } |
||
770 | |||
771 | if ($this->debug || !empty($args['debug'])) { |
||
772 | $result['debug'] = array( |
||
773 | 'connector' => 'php', |
||
774 | 'phpver' => PHP_VERSION, |
||
775 | 'time' => $this->utime() - $this->time, |
||
776 | 'memory' => (function_exists('memory_get_peak_usage') ? ceil(memory_get_peak_usage()/1024).'Kb / ' : '').ceil(memory_get_usage()/1024).'Kb / '.ini_get('memory_limit'), |
||
777 | 'upload' => $this->uploadDebug, |
||
778 | 'volumes' => array(), |
||
779 | 'mountErrors' => $this->mountErrors, |
||
780 | 'phpErrors' => elFinder::$phpErrors |
||
781 | ); |
||
782 | elFinder::$phpErrors = array(); |
||
783 | |||
784 | foreach ($this->volumes as $id => $volume) { |
||
785 | $result['debug']['volumes'][] = $volume->debug(); |
||
786 | } |
||
787 | } |
||
788 | |||
789 | foreach ($this->volumes as $volume) { |
||
790 | $volume->umount(); |
||
791 | } |
||
792 | |||
793 | if (!empty($result['callback'])) { |
||
794 | $result['callback']['json'] = json_encode($result); |
||
795 | $this->callback($result['callback']); |
||
796 | } else { |
||
797 | return $result; |
||
798 | } |
||
799 | //TODO: Add return statement here |
||
800 | } |
||
801 | |||
802 | /** |
||
803 | * Return file real path |
||
804 | * |
||
805 | * @param string $hash file hash |
||
806 | * @return string |
||
807 | * @author Dmitry (dio) Levashov |
||
808 | **/ |
||
809 | public function realpath($hash) { |
||
810 | if (($volume = $this->volume($hash)) == false) { |
||
811 | return false; |
||
812 | } |
||
813 | return $volume->realpath($hash); |
||
814 | } |
||
815 | |||
816 | /** |
||
817 | * Return network volumes config. |
||
818 | * |
||
819 | * @return array |
||
820 | * @author Dmitry (dio) Levashov |
||
821 | */ |
||
822 | protected function getNetVolumes() { |
||
823 | if ($data = $this->session->get('netvolume', array())) { |
||
824 | return $data; |
||
825 | } |
||
826 | return array(); |
||
827 | } |
||
828 | |||
829 | /** |
||
830 | * Save network volumes config. |
||
831 | * |
||
832 | * @param array $volumes volumes config |
||
833 | * @return void |
||
834 | * @author Dmitry (dio) Levashov |
||
835 | */ |
||
836 | protected function saveNetVolumes($volumes) { |
||
837 | $this->session->set('netvolume', $volumes); |
||
838 | } |
||
839 | |||
840 | /** |
||
841 | * Remove netmount volume |
||
842 | * |
||
843 | * @param string $key netvolume key |
||
844 | * @param object $volume volume driver instance |
||
845 | * @return bool |
||
846 | */ |
||
847 | protected function removeNetVolume($key, $volume) { |
||
848 | $netVolumes = $this->getNetVolumes(); |
||
849 | $res = true; |
||
850 | if (is_object($volume) && method_exists($volume, 'netunmount')) { |
||
851 | $res = $volume->netunmount($netVolumes, $key); |
||
852 | } |
||
853 | if ($res) { |
||
854 | if (is_string($key) && isset($netVolumes[$key])) { |
||
855 | unset($netVolumes[$key]); |
||
856 | $this->saveNetVolumes($netVolumes); |
||
857 | return true; |
||
858 | } |
||
859 | } |
||
860 | return false; |
||
861 | } |
||
862 | |||
863 | /** |
||
864 | * Get plugin instance & set to $this->plugins |
||
865 | * |
||
866 | * @param string $name Plugin name (dirctory name) |
||
867 | * @param array $opts Plugin options (optional) |
||
868 | * @return object | bool Plugin object instance Or false |
||
869 | * @author Naoki Sawada |
||
870 | */ |
||
871 | protected function getPluginInstance($name, $opts = array()) { |
||
872 | $key = strtolower($name); |
||
873 | if (! isset($this->plugins[$key])) { |
||
874 | $class = 'elFinderPlugin' . $name; |
||
875 | // to try auto load |
||
876 | if (! class_exists($class)) { |
||
877 | $p_file = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . $name . DIRECTORY_SEPARATOR . 'plugin.php'; |
||
878 | if (is_file($p_file)) { |
||
879 | include_once $p_file; |
||
880 | } |
||
881 | } |
||
882 | if (class_exists($class, false)) { |
||
883 | $this->plugins[$key] = new $class($opts); |
||
884 | } else { |
||
885 | $this->plugins[$key] = false; |
||
886 | } |
||
887 | } |
||
888 | return $this->plugins[$key]; |
||
889 | } |
||
890 | |||
891 | /***************************************************************************/ |
||
892 | /* commands */ |
||
893 | /***************************************************************************/ |
||
894 | |||
895 | /** |
||
896 | * Normalize error messages |
||
897 | * |
||
898 | * @return array |
||
899 | * @author Dmitry (dio) Levashov |
||
900 | **/ |
||
901 | public function error() { |
||
902 | $errors = array(); |
||
903 | |||
904 | foreach (func_get_args() as $msg) { |
||
905 | if (is_array($msg)) { |
||
906 | $errors = array_merge($errors, $msg); |
||
907 | } else { |
||
908 | $errors[] = $msg; |
||
909 | } |
||
910 | } |
||
911 | |||
912 | return count($errors) ? $errors : array(self::ERROR_UNKNOWN); |
||
913 | } |
||
914 | |||
915 | protected function netmount($args) { |
||
916 | $options = array(); |
||
917 | $protocol = $args['protocol']; |
||
918 | |||
919 | if ($protocol === 'netunmount') { |
||
920 | if (! empty($args['user']) && $volume = $this->volume($args['user'])) { |
||
921 | if ($this->removeNetVolume($args['host'], $volume)) { |
||
922 | return array('removed' => array(array('hash' => $volume->root()))); |
||
923 | } |
||
924 | } |
||
925 | return array('sync' => true, 'error' => $this->error(self::ERROR_NETUNMOUNT)); |
||
926 | } |
||
927 | |||
928 | $driver = isset(self::$netDrivers[$protocol]) ? self::$netDrivers[$protocol] : ''; |
||
929 | $class = 'elFinderVolume'.$driver; |
||
930 | |||
931 | if (!class_exists($class)) { |
||
932 | return array('error' => $this->error(self::ERROR_NETMOUNT, $args['host'], self::ERROR_NETMOUNT_NO_DRIVER)); |
||
933 | } |
||
934 | |||
935 | if (!$args['path']) { |
||
936 | $args['path'] = '/'; |
||
937 | } |
||
938 | |||
939 | foreach ($args as $k => $v) { |
||
940 | if ($k != 'options' && $k != 'protocol' && $v) { |
||
941 | $options[$k] = $v; |
||
942 | } |
||
943 | } |
||
944 | |||
945 | if (is_array($args['options'])) { |
||
946 | foreach ($args['options'] as $key => $value) { |
||
947 | $options[$key] = $value; |
||
948 | } |
||
949 | } |
||
950 | |||
951 | $volume = new $class(); |
||
952 | |||
953 | // pass session handler |
||
954 | $volume->setSession($this->session); |
||
955 | |||
956 | if (method_exists($volume, 'netmountPrepare')) { |
||
957 | $options = $volume->netmountPrepare($options); |
||
958 | if (isset($options['exit'])) { |
||
959 | if ($options['exit'] === 'callback') { |
||
960 | $this->callback($options['out']); |
||
961 | } |
||
962 | return $options; |
||
963 | } |
||
964 | } |
||
965 | |||
966 | $netVolumes = $this->getNetVolumes(); |
||
967 | |||
968 | if (! isset($options['id'])) { |
||
969 | // given fixed unique id |
||
970 | if (! $options['id'] = $this->getNetVolumeUniqueId($netVolumes)) { |
||
971 | return array('error' => $this->error(self::ERROR_NETMOUNT, $args['host'], 'Could\'t given volume id.')); |
||
972 | } |
||
973 | } |
||
974 | |||
975 | // load additional volume root options |
||
976 | if (! empty($this->optionsNetVolumes['*'])) { |
||
977 | $options = array_merge($options, $this->optionsNetVolumes['*']); |
||
978 | } |
||
979 | if (! empty($this->optionsNetVolumes[$protocol])) { |
||
980 | $options = array_merge($options, $this->optionsNetVolumes[$protocol]); |
||
981 | } |
||
982 | |||
983 | if (! $key = $volume->netMountKey) { |
||
984 | $key = md5($protocol . '-' . serialize($options)); |
||
985 | } |
||
986 | $options['netkey'] = $key; |
||
987 | |||
988 | if ($volume->mount($options)) { |
||
989 | $options['driver'] = $driver; |
||
990 | $netVolumes[$key] = $options; |
||
991 | $this->saveNetVolumes($netVolumes); |
||
992 | $rootstat = $volume->file($volume->root()); |
||
993 | return array('added' => array($rootstat)); |
||
994 | } else { |
||
995 | $this->removeNetVolume(null, $volume); |
||
996 | return array('error' => $this->error(self::ERROR_NETMOUNT, $args['host'], implode(' ', $volume->error()))); |
||
997 | } |
||
998 | } |
||
999 | |||
1000 | /** |
||
1001 | * "Open" directory |
||
1002 | * Return array with following elements |
||
1003 | * - cwd - opened dir info |
||
1004 | * - files - opened dir content [and dirs tree if $args[tree]] |
||
1005 | * - api - api version (if $args[init]) |
||
1006 | * - uplMaxSize - if $args[init] |
||
1007 | * - error - on failed |
||
1008 | * |
||
1009 | * @param array command arguments |
||
1010 | * @return array |
||
1011 | * @author Dmitry (dio) Levashov |
||
1012 | **/ |
||
1013 | protected function open($args) { |
||
1014 | $target = $args['target']; |
||
1015 | $init = !empty($args['init']); |
||
1016 | $tree = !empty($args['tree']); |
||
1017 | $volume = $this->volume($target); |
||
1018 | $cwd = $volume ? $volume->dir($target) : false; |
||
1019 | $hash = $init ? 'default folder' : '#'.$target; |
||
1020 | $sleep = 0; |
||
0 ignored issues
–
show
$sleep is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
1021 | $compare = ''; |
||
1022 | |||
1023 | // on init request we can get invalid dir hash - |
||
1024 | // dir which can not be opened now, but remembered by client, |
||
1025 | // so open default dir |
||
1026 | if ((!$cwd || !$cwd['read']) && $init) { |
||
1027 | $volume = $this->default; |
||
1028 | $cwd = $volume->dir($volume->defaultPath()); |
||
1029 | } |
||
1030 | |||
1031 | if (!$cwd) { |
||
1032 | return array('error' => $this->error(self::ERROR_OPEN, $hash, self::ERROR_DIR_NOT_FOUND)); |
||
1033 | } |
||
1034 | if (!$cwd['read']) { |
||
1035 | return array('error' => $this->error(self::ERROR_OPEN, $hash, self::ERROR_PERM_DENIED)); |
||
1036 | } |
||
1037 | |||
1038 | $files = array(); |
||
1039 | |||
1040 | // get other volume root |
||
1041 | if ($tree) { |
||
1042 | foreach ($this->volumes as $id => $v) { |
||
1043 | $files[] = $v->file($v->root()); |
||
1044 | } |
||
1045 | } |
||
1046 | |||
1047 | // get current working directory files list |
||
1048 | if (($ls = $volume->scandir($cwd['hash'])) === false) { |
||
1049 | return array('error' => $this->error(self::ERROR_OPEN, $cwd['name'], $volume->error())); |
||
1050 | } |
||
1051 | // long polling mode |
||
1052 | if ($args['compare']) { |
||
1053 | $sleep = max(1, (int)$volume->getOption('lsPlSleep')); |
||
1054 | $standby = (int)$volume->getOption('plStandby'); |
||
1055 | if ($standby > 0 && $sleep > $standby) { |
||
1056 | $standby = $sleep; |
||
1057 | } |
||
1058 | $limit = max(0, floor($standby / $sleep)) + 1; |
||
1059 | do { |
||
1060 | elFinder::extendTimeLimit(30 + $sleep); |
||
1061 | $_mtime = 0; |
||
1062 | foreach($ls as $_f) { |
||
1063 | $_mtime = max($_mtime, $_f['ts']); |
||
1064 | } |
||
1065 | $compare = strval(count($ls)).':'.strval($_mtime); |
||
1066 | if ($compare !== $args['compare']) { |
||
1067 | break; |
||
1068 | } |
||
1069 | if (--$limit) { |
||
1070 | sleep($sleep); |
||
1071 | $volume->clearstatcache(); |
||
1072 | if (($ls = $volume->scandir($cwd['hash'])) === false) { |
||
1073 | break; |
||
1074 | } |
||
1075 | } |
||
1076 | } while($limit); |
||
1077 | if ($ls === false) { |
||
1078 | return array('error' => $this->error(self::ERROR_OPEN, $cwd['name'], $volume->error())); |
||
1079 | } |
||
1080 | } |
||
1081 | |||
1082 | if ($ls) { |
||
1083 | if ($files) { |
||
0 ignored issues
–
show
The expression
$files of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
1084 | $files = array_merge($files, $ls); |
||
1085 | } else { |
||
1086 | $files = $ls; |
||
1087 | } |
||
1088 | } |
||
1089 | |||
1090 | $result = array( |
||
1091 | 'cwd' => $cwd, |
||
1092 | 'options' => $volume->options($cwd['hash']), |
||
1093 | 'files' => $files |
||
1094 | ); |
||
1095 | |||
1096 | if ($compare) { |
||
1097 | $result['cwd']['compare'] = $compare; |
||
1098 | } |
||
1099 | |||
1100 | if (!empty($args['init'])) { |
||
1101 | $result['api'] = $this->version; |
||
1102 | $result['uplMaxSize'] = ini_get('upload_max_filesize'); |
||
1103 | $result['uplMaxFile'] = ini_get('max_file_uploads'); |
||
1104 | $result['netDrivers'] = array_keys(self::$netDrivers); |
||
1105 | if ($volume) { |
||
1106 | $result['cwd']['root'] = $volume->root(); |
||
1107 | } |
||
1108 | } |
||
1109 | |||
1110 | return $result; |
||
1111 | } |
||
1112 | |||
1113 | /** |
||
1114 | * Return dir files names list |
||
1115 | * |
||
1116 | * @param array command arguments |
||
1117 | * @return array |
||
1118 | * @author Dmitry (dio) Levashov |
||
1119 | **/ |
||
1120 | protected function ls($args) { |
||
1121 | $target = $args['target']; |
||
1122 | $intersect = isset($args['intersect'])? $args['intersect'] : array(); |
||
1123 | |||
1124 | if (($volume = $this->volume($target)) == false |
||
1125 | || ($list = $volume->ls($target, $intersect)) === false) { |
||
1126 | return array('error' => $this->error(self::ERROR_OPEN, '#'.$target)); |
||
1127 | } |
||
1128 | return array('list' => $list); |
||
1129 | } |
||
1130 | |||
1131 | /** |
||
1132 | * Return subdirs for required directory |
||
1133 | * |
||
1134 | * @param array command arguments |
||
1135 | * @return array |
||
1136 | * @author Dmitry (dio) Levashov |
||
1137 | **/ |
||
1138 | protected function tree($args) { |
||
1139 | $target = $args['target']; |
||
1140 | |||
1141 | if (($volume = $this->volume($target)) == false |
||
1142 | || ($tree = $volume->tree($target)) == false) { |
||
1143 | return array('error' => $this->error(self::ERROR_OPEN, '#'.$target)); |
||
1144 | } |
||
1145 | |||
1146 | return array('tree' => $tree); |
||
1147 | } |
||
1148 | |||
1149 | /** |
||
1150 | * Return parents dir for required directory |
||
1151 | * |
||
1152 | * @param array command arguments |
||
1153 | * @return array |
||
1154 | * @author Dmitry (dio) Levashov |
||
1155 | **/ |
||
1156 | protected function parents($args) { |
||
1157 | $target = $args['target']; |
||
1158 | |||
1159 | if (($volume = $this->volume($target)) == false |
||
1160 | || ($tree = $volume->parents($target)) == false) { |
||
1161 | return array('error' => $this->error(self::ERROR_OPEN, '#'.$target)); |
||
1162 | } |
||
1163 | |||
1164 | return array('tree' => $tree); |
||
1165 | } |
||
1166 | |||
1167 | /** |
||
1168 | * Return new created thumbnails list |
||
1169 | * |
||
1170 | * @param array command arguments |
||
1171 | * @return array |
||
1172 | * @author Dmitry (dio) Levashov |
||
1173 | **/ |
||
1174 | protected function tmb($args) { |
||
1175 | |||
1176 | $result = array('images' => array()); |
||
1177 | $targets = $args['targets']; |
||
1178 | |||
1179 | foreach ($targets as $target) { |
||
1180 | if (($volume = $this->volume($target)) != false |
||
1181 | && (($tmb = $volume->tmb($target)) != false)) { |
||
1182 | $result['images'][$target] = $tmb; |
||
1183 | } |
||
1184 | } |
||
1185 | return $result; |
||
1186 | } |
||
1187 | |||
1188 | /** |
||
1189 | * Download files/folders as an archive file |
||
1190 | * |
||
1191 | * 1st: Return srrsy contains download archive file info |
||
1192 | * 2nd: Return array contains opened file pointer, root itself and required headers |
||
1193 | * |
||
1194 | * @param array command arguments |
||
1195 | * @return array |
||
1196 | * @author Naoki Sawada |
||
1197 | **/ |
||
1198 | protected function zipdl($args) { |
||
0 ignored issues
–
show
zipdl uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
1199 | $targets = $args['targets']; |
||
1200 | $download = !empty($args['download']); |
||
1201 | $h404 = 'HTTP/1.x 404 Not Found'; |
||
1202 | |||
1203 | if (!$download) { |
||
1204 | //1st: Return srrsy contains download archive file info |
||
1205 | $error = array(self::ERROR_ARCHIVE); |
||
1206 | if (($volume = $this->volume($targets[0])) !== false) { |
||
1207 | if ($dlres = $volume->zipdl($targets)) { |
||
1208 | $path = $dlres['path']; |
||
1209 | register_shutdown_function(create_function('$f', 'connection_status() && is_file($f) && unlink($f);'), $path); |
||
0 ignored issues
–
show
The use of
create_function is highly discouraged, better use a closure.
// Instead of
$function = create_function('$a, $b', 'return $a + $b');
// Better use
$function = function($a, $b) { return $a + $b; }
Loading history...
|
|||
1210 | if (count($targets) === 1) { |
||
1211 | $name = basename($volume->path($targets[0])); |
||
1212 | } else { |
||
1213 | $name = $dlres['prefix'].'_Files'; |
||
1214 | } |
||
1215 | $name .= '.'.$dlres['ext']; |
||
1216 | $result = array( |
||
1217 | 'zipdl' => array( |
||
1218 | 'file' => basename($path), |
||
1219 | 'name' => $name, |
||
1220 | 'mime' => $dlres['mime'] |
||
1221 | ) |
||
1222 | ); |
||
1223 | return $result; |
||
1224 | } |
||
1225 | $error = array_merge($error, $volume->error()); |
||
1226 | } |
||
1227 | return array('error' => $error); |
||
1228 | } else { |
||
1229 | // 2nd: Return array contains opened file pointer, root itself and required headers |
||
1230 | if (count($targets) !== 4 || ($volume = $this->volume($targets[0])) == false) { |
||
1231 | return array('error' => 'File not found', 'header' => $h404, 'raw' => true); |
||
1232 | } |
||
1233 | $file = $targets[1]; |
||
1234 | $path = $volume->getTempPath().DIRECTORY_SEPARATOR.$file; |
||
1235 | register_shutdown_function(create_function('$f', 'is_file($f) && unlink($f);'), $path); |
||
0 ignored issues
–
show
The use of
create_function is highly discouraged, better use a closure.
// Instead of
$function = create_function('$a, $b', 'return $a + $b');
// Better use
$function = function($a, $b) { return $a + $b; }
Loading history...
|
|||
1236 | if (!is_readable($path)) { |
||
1237 | return array('error' => 'File not found', 'header' => $h404, 'raw' => true); |
||
1238 | } |
||
1239 | $name = $targets[2]; |
||
1240 | $mime = $targets[3]; |
||
1241 | |||
1242 | $filenameEncoded = rawurlencode($name); |
||
1243 | if (strpos($filenameEncoded, '%') === false) { // ASCII only |
||
1244 | $filename = 'filename="'.$name.'"'; |
||
1245 | } else { |
||
1246 | $ua = $_SERVER['HTTP_USER_AGENT']; |
||
1247 | if (preg_match('/MSIE [4-8]/', $ua)) { // IE < 9 do not support RFC 6266 (RFC 2231/RFC 5987) |
||
1248 | $filename = 'filename="'.$filenameEncoded.'"'; |
||
1249 | } elseif (strpos($ua, 'Chrome') === false && strpos($ua, 'Safari') !== false && preg_match('#Version/[3-5]#', $ua)) { // Safari < 6 |
||
1250 | $filename = 'filename="'.str_replace('"', '', $name).'"'; |
||
1251 | } else { // RFC 6266 (RFC 2231/RFC 5987) |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
36% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them.
Loading history...
|
|||
1252 | $filename = 'filename*=UTF-8\'\''.$filenameEncoded; |
||
1253 | } |
||
1254 | } |
||
1255 | |||
1256 | $fp = fopen($path, 'rb'); |
||
1257 | $file = fstat($fp); |
||
1258 | $result = array( |
||
1259 | 'pointer' => $fp, |
||
1260 | 'header' => array( |
||
1261 | 'Content-Type: '.$mime, |
||
1262 | 'Content-Disposition: attachment; '.$filename, |
||
1263 | 'Content-Transfer-Encoding: binary', |
||
1264 | 'Content-Length: '.$file['size'], |
||
1265 | 'Accept-Ranges: none', |
||
1266 | 'Connection: close' |
||
1267 | ) |
||
1268 | ); |
||
1269 | return $result; |
||
1270 | } |
||
1271 | } |
||
1272 | |||
1273 | /** |
||
1274 | * Required to output file in browser when volume URL is not set |
||
1275 | * Return array contains opened file pointer, root itself and required headers |
||
1276 | * |
||
1277 | * @param array command arguments |
||
1278 | * @return array |
||
1279 | * @author Dmitry (dio) Levashov |
||
1280 | **/ |
||
1281 | protected function file($args) { |
||
0 ignored issues
–
show
file uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
1282 | $target = $args['target']; |
||
1283 | $download = !empty($args['download']); |
||
1284 | $h403 = 'HTTP/1.x 403 Access Denied'; |
||
1285 | $h404 = 'HTTP/1.x 404 Not Found'; |
||
1286 | |||
1287 | if (($volume = $this->volume($target)) == false) { |
||
1288 | return array('error' => 'File not found', 'header' => $h404, 'raw' => true); |
||
1289 | } |
||
1290 | |||
1291 | if (($file = $volume->file($target)) == false) { |
||
1292 | return array('error' => 'File not found', 'header' => $h404, 'raw' => true); |
||
1293 | } |
||
1294 | |||
1295 | if (!$file['read']) { |
||
1296 | return array('error' => 'Access denied', 'header' => $h403, 'raw' => true); |
||
1297 | } |
||
1298 | |||
1299 | if (($fp = $volume->open($target)) == false) { |
||
1300 | return array('error' => 'File not found', 'header' => $h404, 'raw' => true); |
||
1301 | } |
||
1302 | |||
1303 | // allow change MIME type by 'file.pre' callback functions |
||
1304 | $mime = isset($args['mime'])? $args['mime'] : $file['mime']; |
||
1305 | if ($download) { |
||
1306 | $disp = 'attachment'; |
||
1307 | } else { |
||
1308 | $dispInlineRegex = $volume->getOption('dispInlineRegex'); |
||
1309 | $inlineRegex = false; |
||
1310 | if ($dispInlineRegex) { |
||
1311 | $inlineRegex = '#' . str_replace('#', '\\#', $dispInlineRegex) . '#'; |
||
1312 | try { |
||
1313 | preg_match($inlineRegex, ''); |
||
1314 | } catch(Exception $e) { |
||
1315 | $inlineRegex = false; |
||
1316 | } |
||
1317 | } |
||
1318 | if (!$inlineRegex) { |
||
0 ignored issues
–
show
The expression
$inlineRegex of type string|false is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
Loading history...
|
|||
1319 | $inlineRegex = '#^(?:(?:image|text)|application/x-shockwave-flash$)#'; |
||
1320 | } |
||
1321 | $disp = preg_match($inlineRegex, $mime)? 'inline' : 'attachment'; |
||
1322 | } |
||
1323 | |||
1324 | $filenameEncoded = rawurlencode($file['name']); |
||
1325 | if (strpos($filenameEncoded, '%') === false) { // ASCII only |
||
1326 | $filename = 'filename="'.$file['name'].'"'; |
||
1327 | } else { |
||
1328 | $ua = $_SERVER['HTTP_USER_AGENT']; |
||
1329 | if (preg_match('/MSIE [4-8]/', $ua)) { // IE < 9 do not support RFC 6266 (RFC 2231/RFC 5987) |
||
1330 | $filename = 'filename="'.$filenameEncoded.'"'; |
||
1331 | } elseif (strpos($ua, 'Chrome') === false && strpos($ua, 'Safari') !== false && preg_match('#Version/[3-5]#', $ua)) { // Safari < 6 |
||
1332 | $filename = 'filename="'.str_replace('"', '', $file['name']).'"'; |
||
1333 | } else { // RFC 6266 (RFC 2231/RFC 5987) |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
36% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them.
Loading history...
|
|||
1334 | $filename = 'filename*=UTF-8\'\''.$filenameEncoded; |
||
1335 | } |
||
1336 | } |
||
1337 | |||
1338 | $result = array( |
||
1339 | 'volume' => $volume, |
||
1340 | 'pointer' => $fp, |
||
1341 | 'info' => $file, |
||
1342 | 'header' => array( |
||
1343 | 'Content-Type: '.$mime, |
||
1344 | 'Content-Disposition: '.$disp.'; '.$filename, |
||
1345 | 'Content-Transfer-Encoding: binary', |
||
1346 | 'Content-Length: '.$file['size'], |
||
1347 | 'Connection: close' |
||
1348 | ) |
||
1349 | ); |
||
1350 | if (isset($file['url']) && $file['url'] && $file['url'] != 1) { |
||
1351 | $result['header'][] = 'Content-Location: '.$file['url']; |
||
1352 | } |
||
1353 | return $result; |
||
1354 | } |
||
1355 | |||
1356 | /** |
||
1357 | * Count total files size |
||
1358 | * |
||
1359 | * @param array command arguments |
||
1360 | * @return array |
||
1361 | * @author Dmitry (dio) Levashov |
||
1362 | **/ |
||
1363 | protected function size($args) { |
||
1364 | $size = 0; |
||
1365 | |||
1366 | foreach ($args['targets'] as $target) { |
||
1367 | if (($volume = $this->volume($target)) == false |
||
1368 | || ($file = $volume->file($target)) == false |
||
1369 | || !$file['read']) { |
||
1370 | return array('error' => $this->error(self::ERROR_OPEN, '#'.$target)); |
||
1371 | } |
||
1372 | |||
1373 | $size += $volume->size($target); |
||
1374 | } |
||
1375 | return array('size' => $size); |
||
1376 | } |
||
1377 | |||
1378 | /** |
||
1379 | * Create directory |
||
1380 | * |
||
1381 | * @param array command arguments |
||
1382 | * @return array |
||
1383 | * @author Dmitry (dio) Levashov |
||
1384 | **/ |
||
1385 | protected function mkdir($args) { |
||
1386 | $target = $args['target']; |
||
1387 | $name = $args['name']; |
||
1388 | $dirs = $args['dirs']; |
||
1389 | if ($name === '' && !$dirs) { |
||
1390 | return array('error' => $this->error(self::ERROR_INV_PARAMS, 'mkdir')); |
||
1391 | } |
||
1392 | |||
1393 | if (($volume = $this->volume($target)) == false) { |
||
1394 | return array('error' => $this->error(self::ERROR_MKDIR, $name, self::ERROR_TRGDIR_NOT_FOUND, '#'.$target)); |
||
1395 | } |
||
1396 | if ($dirs) { |
||
1397 | sort($dirs); |
||
1398 | $reset = null; |
||
1399 | $mkdirs = array(); |
||
1400 | foreach($dirs as $dir) { |
||
1401 | $tgt =& $mkdirs; |
||
1402 | $_names = explode('/', trim($dir, '/')); |
||
1403 | foreach($_names as $_key => $_name) { |
||
1404 | if (! isset($tgt[$_name])) { |
||
1405 | $tgt[$_name] = array(); |
||
1406 | } |
||
1407 | $tgt =& $tgt[$_name]; |
||
1408 | } |
||
1409 | $tgt =& $reset; |
||
1410 | } |
||
1411 | return ($res = $this->ensureDirsRecursively($volume, $target, $mkdirs)) === false |
||
0 ignored issues
–
show
$mkdirs is of type array , but the function expects a string .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
1412 | ? array('error' => $this->error(self::ERROR_MKDIR, $name, $volume->error())) |
||
1413 | : array('added' => $res['stats'], 'hashes' => $res['hashes']); |
||
1414 | } else { |
||
1415 | return ($dir = $volume->mkdir($target, $name)) == false |
||
1416 | ? array('error' => $this->error(self::ERROR_MKDIR, $name, $volume->error())) |
||
1417 | : array('added' => array($dir)); |
||
1418 | } |
||
1419 | } |
||
1420 | |||
1421 | /** |
||
1422 | * Create empty file |
||
1423 | * |
||
1424 | * @param array command arguments |
||
1425 | * @return array |
||
1426 | * @author Dmitry (dio) Levashov |
||
1427 | **/ |
||
1428 | protected function mkfile($args) { |
||
1429 | $target = $args['target']; |
||
1430 | $name = $args['name']; |
||
1431 | |||
1432 | if (($volume = $this->volume($target)) == false) { |
||
1433 | return array('error' => $this->error(self::ERROR_MKFILE, $name, self::ERROR_TRGDIR_NOT_FOUND, '#'.$target)); |
||
1434 | } |
||
1435 | |||
1436 | return ($file = $volume->mkfile($target, $args['name'])) == false |
||
1437 | ? array('error' => $this->error(self::ERROR_MKFILE, $name, $volume->error())) |
||
1438 | : array('added' => array($file)); |
||
1439 | } |
||
1440 | |||
1441 | /** |
||
1442 | * Rename file |
||
1443 | * |
||
1444 | * @param array $args |
||
1445 | * @return array |
||
1446 | * @author Dmitry (dio) Levashov |
||
1447 | **/ |
||
1448 | protected function rename($args) { |
||
1449 | $target = $args['target']; |
||
1450 | $name = $args['name']; |
||
1451 | |||
1452 | if (($volume = $this->volume($target)) == false |
||
1453 | || ($rm = $volume->file($target)) == false) { |
||
1454 | return array('error' => $this->error(self::ERROR_RENAME, '#'.$target, self::ERROR_FILE_NOT_FOUND)); |
||
1455 | } |
||
1456 | $rm['realpath'] = $volume->realpath($target); |
||
1457 | |||
1458 | return ($file = $volume->rename($target, $name)) == false |
||
1459 | ? array('error' => $this->error(self::ERROR_RENAME, $rm['name'], $volume->error())) |
||
1460 | : array('added' => array($file), 'removed' => array($rm)); |
||
1461 | } |
||
1462 | |||
1463 | /** |
||
1464 | * Duplicate file - create copy with "copy %d" suffix |
||
1465 | * |
||
1466 | * @param array $args command arguments |
||
1467 | * @return array |
||
1468 | * @author Dmitry (dio) Levashov |
||
1469 | **/ |
||
1470 | protected function duplicate($args) { |
||
1471 | $targets = is_array($args['targets']) ? $args['targets'] : array(); |
||
1472 | $result = array('added' => array()); |
||
1473 | $suffix = empty($args['suffix']) ? 'copy' : $args['suffix']; |
||
1474 | |||
1475 | foreach ($targets as $target) { |
||
1476 | if (($volume = $this->volume($target)) == false |
||
1477 | || ($src = $volume->file($target)) == false) { |
||
1478 | $result['warning'] = $this->error(self::ERROR_COPY, '#'.$target, self::ERROR_FILE_NOT_FOUND); |
||
1479 | break; |
||
1480 | } |
||
1481 | |||
1482 | if (($file = $volume->duplicate($target, $suffix)) == false) { |
||
1483 | $result['warning'] = $this->error($volume->error()); |
||
1484 | break; |
||
1485 | } |
||
1486 | |||
1487 | $result['added'][] = $file; |
||
1488 | } |
||
1489 | |||
1490 | return $result; |
||
1491 | } |
||
1492 | |||
1493 | /** |
||
1494 | * Remove dirs/files |
||
1495 | * |
||
1496 | * @param array command arguments |
||
1497 | * @return array |
||
1498 | * @author Dmitry (dio) Levashov |
||
1499 | **/ |
||
1500 | protected function rm($args) { |
||
1501 | $targets = is_array($args['targets']) ? $args['targets'] : array(); |
||
1502 | $result = array('removed' => array()); |
||
1503 | |||
1504 | foreach ($targets as $target) { |
||
1505 | if (($volume = $this->volume($target)) == false) { |
||
1506 | $result['warning'] = $this->error(self::ERROR_RM, '#'.$target, self::ERROR_FILE_NOT_FOUND); |
||
1507 | return $result; |
||
1508 | } |
||
1509 | if (!$volume->rm($target)) { |
||
1510 | $result['warning'] = $this->error($volume->error()); |
||
1511 | return $result; |
||
1512 | } |
||
1513 | } |
||
1514 | |||
1515 | return $result; |
||
1516 | } |
||
1517 | |||
1518 | /** |
||
1519 | * Get remote contents |
||
1520 | * |
||
1521 | * @param string $url target url |
||
1522 | * @param int $timeout timeout (sec) |
||
1523 | * @param int $redirect_max redirect max count |
||
1524 | * @param string $ua |
||
1525 | * @param resource $fp |
||
1526 | * @return string or bool(false) |
||
1527 | * @retval string contents |
||
1528 | * @retval false error |
||
1529 | * @author Naoki Sawada |
||
1530 | **/ |
||
1531 | protected function get_remote_contents( &$url, $timeout = 30, $redirect_max = 5, $ua = 'Mozilla/5.0', $fp = null ) { |
||
1532 | $method = (function_exists('curl_exec') && !ini_get('safe_mode') && !ini_get('open_basedir'))? 'curl_get_contents' : 'fsock_get_contents'; |
||
1533 | return $this->$method( $url, $timeout, $redirect_max, $ua, $fp ); |
||
1534 | } |
||
1535 | |||
1536 | /** |
||
1537 | * Get remote contents with cURL |
||
1538 | * |
||
1539 | * @param string $url target url |
||
1540 | * @param int $timeout timeout (sec) |
||
1541 | * @param int $redirect_max redirect max count |
||
1542 | * @param string $ua |
||
1543 | * @param resource $outfp |
||
1544 | * @return string or bool(false) |
||
1545 | * @retval string contents |
||
1546 | * @retval false error |
||
1547 | * @author Naoki Sawada |
||
1548 | **/ |
||
1549 | protected function curl_get_contents( &$url, $timeout, $redirect_max, $ua, $outfp ){ |
||
1550 | $ch = curl_init(); |
||
1551 | curl_setopt( $ch, CURLOPT_URL, $url ); |
||
1552 | curl_setopt( $ch, CURLOPT_HEADER, false ); |
||
1553 | if ($outfp) { |
||
1554 | curl_setopt( $ch, CURLOPT_FILE, $outfp ); |
||
1555 | } else { |
||
1556 | curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); |
||
1557 | curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true ); |
||
1558 | } |
||
1559 | curl_setopt( $ch, CURLOPT_LOW_SPEED_LIMIT, 1 ); |
||
1560 | curl_setopt( $ch, CURLOPT_LOW_SPEED_TIME, $timeout ); |
||
1561 | curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false ); |
||
1562 | curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1); |
||
1563 | curl_setopt( $ch, CURLOPT_MAXREDIRS, $redirect_max); |
||
1564 | curl_setopt( $ch, CURLOPT_USERAGENT, $ua); |
||
1565 | $result = curl_exec( $ch ); |
||
1566 | $url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); |
||
1567 | curl_close( $ch ); |
||
1568 | return $outfp? $outfp : $result; |
||
1569 | } |
||
1570 | |||
1571 | /** |
||
1572 | * Get remote contents with fsockopen() |
||
1573 | * |
||
1574 | * @param string $url url |
||
1575 | * @param int $timeout timeout (sec) |
||
1576 | * @param int $redirect_max redirect max count |
||
1577 | * @param string $ua |
||
1578 | * @param resource $outfp |
||
1579 | * @return string or bool(false) |
||
1580 | * @retval string contents |
||
1581 | * @retval false error |
||
1582 | * @author Naoki Sawada |
||
1583 | */ |
||
1584 | protected function fsock_get_contents( &$url, $timeout, $redirect_max, $ua, $outfp ) { |
||
1585 | |||
1586 | $connect_timeout = 3; |
||
1587 | $connect_try = 3; |
||
1588 | $method = 'GET'; |
||
1589 | $readsize = 4096; |
||
1590 | $ssl = ''; |
||
1591 | |||
1592 | $getSize = null; |
||
1593 | $headers = ''; |
||
1594 | |||
1595 | $arr = parse_url($url); |
||
1596 | if (!$arr){ |
||
1597 | // Bad request |
||
1598 | return false; |
||
1599 | } |
||
1600 | if ($arr['scheme'] === 'https') { |
||
1601 | $ssl = 'ssl://'; |
||
1602 | } |
||
1603 | |||
1604 | // query |
||
1605 | $arr['query'] = isset($arr['query']) ? '?'.$arr['query'] : ''; |
||
1606 | // port |
||
1607 | $arr['port'] = isset($arr['port']) ? $arr['port'] : ($ssl? 443 : 80); |
||
1608 | |||
1609 | $url_base = $arr['scheme'].'://'.$arr['host'].':'.$arr['port']; |
||
1610 | $url_path = isset($arr['path']) ? $arr['path'] : '/'; |
||
1611 | $uri = $url_path.$arr['query']; |
||
1612 | |||
1613 | $query = $method.' '.$uri." HTTP/1.0\r\n"; |
||
1614 | $query .= "Host: ".$arr['host']."\r\n"; |
||
1615 | $query .= "Accept: */*\r\n"; |
||
1616 | $query .= "Connection: close\r\n"; |
||
1617 | if (!empty($ua)) $query .= "User-Agent: ".$ua."\r\n"; |
||
1618 | if (!is_null($getSize)) $query .= 'Range: bytes=0-' . ($getSize - 1) . "\r\n"; |
||
1619 | |||
1620 | $query .= $headers; |
||
1621 | |||
1622 | $query .= "\r\n"; |
||
1623 | |||
1624 | $fp = $connect_try_count = 0; |
||
1625 | while( !$fp && $connect_try_count < $connect_try ) { |
||
1626 | |||
1627 | $errno = 0; |
||
1628 | $errstr = ""; |
||
1629 | $fp = fsockopen( |
||
1630 | $ssl.$arr['host'], |
||
1631 | $arr['port'], |
||
1632 | $errno,$errstr,$connect_timeout); |
||
1633 | if ($fp) break; |
||
1634 | $connect_try_count++; |
||
1635 | if (connection_aborted()) { |
||
1636 | exit(); |
||
0 ignored issues
–
show
The method
fsock_get_contents() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an
Loading history...
|
|||
1637 | } |
||
1638 | sleep(1); // wait 1sec |
||
1639 | } |
||
1640 | |||
1641 | $fwrite = 0; |
||
0 ignored issues
–
show
$fwrite is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
1642 | for ($written = 0; $written < strlen($query); $written += $fwrite) { |
||
1643 | $fwrite = fwrite($fp, substr($query, $written)); |
||
1644 | if (!$fwrite) { |
||
1645 | break; |
||
1646 | } |
||
1647 | } |
||
1648 | |||
1649 | $response = ''; |
||
0 ignored issues
–
show
$response is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
1650 | |||
1651 | if ($timeout) { |
||
1652 | socket_set_timeout($fp, $timeout); |
||
1653 | } |
||
1654 | |||
1655 | $_response = ''; |
||
1656 | $header = ''; |
||
1657 | while($_response !== "\r\n"){ |
||
1658 | $_response = fgets($fp, $readsize); |
||
1659 | $header .= $_response; |
||
1660 | }; |
||
1661 | |||
1662 | $rccd = array_pad(explode(' ',$header,2), 2, ''); // array('HTTP/1.1','200') |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
86% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them.
Loading history...
|
|||
1663 | $rc = (int)$rccd[1]; |
||
1664 | |||
1665 | $ret = false; |
||
1666 | // Redirect |
||
1667 | switch ($rc) { |
||
1668 | case 307: // Temporary Redirect |
||
1669 | case 303: // See Other |
||
1670 | case 302: // Moved Temporarily |
||
1671 | case 301: // Moved Permanently |
||
1672 | $matches = array(); |
||
1673 | if (preg_match('/^Location: (.+?)(#.+)?$/im',$header,$matches) && --$redirect_max > 0) { |
||
1674 | $_url = $url; |
||
1675 | $url = trim($matches[1]); |
||
1676 | $hash = isset($matches[2])? trim($matches[2]) : ''; |
||
0 ignored issues
–
show
$hash is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
1677 | if (!preg_match('/^https?:\//',$url)) { // no scheme |
||
1678 | if ($url{0} != '/') { // Relative path |
||
1679 | // to Absolute path |
||
1680 | $url = substr($url_path,0,strrpos($url_path,'/')).'/'.$url; |
||
1681 | } |
||
1682 | // add sheme,host |
||
1683 | $url = $url_base.$url; |
||
1684 | } |
||
1685 | if ($_url !== $url) { |
||
1686 | fclose($fp); |
||
1687 | return $this->fsock_get_contents( $url, $timeout, $redirect_max, $ua, $outfp ); |
||
1688 | } |
||
1689 | } |
||
1690 | break; |
||
1691 | case 200: |
||
1692 | $ret = true; |
||
1693 | } |
||
1694 | if (! $ret) { |
||
1695 | fclose($fp); |
||
1696 | return false; |
||
1697 | } |
||
1698 | |||
1699 | $body = ''; |
||
1700 | if (!$outfp) { |
||
1701 | $outfp = fopen('php://temp', 'rwb'); |
||
1702 | $body = true; |
||
1703 | } |
||
1704 | while(fwrite($outfp, fread($fp, $readsize))) { |
||
1705 | if ($timeout) { |
||
1706 | $_status = socket_get_status($fp); |
||
1707 | if ($_status['timed_out']) { |
||
1708 | fclose($outfp); |
||
1709 | fclose($fp); |
||
1710 | return false; // Request Time-out |
||
1711 | } |
||
1712 | } |
||
1713 | } |
||
1714 | if ($body) { |
||
1715 | rewind($outfp); |
||
1716 | $body = stream_get_contents($outfp); |
||
1717 | fclose($outfp); |
||
1718 | $outfp = null; |
||
1719 | } |
||
1720 | |||
1721 | fclose($fp); |
||
1722 | |||
1723 | return $outfp? $outfp : $body; // Data |
||
0 ignored issues
–
show
|
|||
1724 | } |
||
1725 | |||
1726 | /** |
||
1727 | * Parse Data URI scheme |
||
1728 | * |
||
1729 | * @param string $str |
||
1730 | * @param array $extTable |
||
1731 | * @return array |
||
1732 | * @author Naoki Sawada |
||
1733 | */ |
||
1734 | protected function parse_data_scheme( $str, $extTable ) { |
||
1735 | $data = $name = ''; |
||
1736 | if ($fp = fopen('data://'.substr($str, 5), 'rb')) { |
||
1737 | if ($data = stream_get_contents($fp)) { |
||
1738 | $meta = stream_get_meta_data($fp); |
||
1739 | $ext = isset($extTable[$meta['mediatype']])? '.' . $extTable[$meta['mediatype']] : ''; |
||
1740 | $name = substr(md5($data), 0, 8) . $ext; |
||
1741 | } |
||
1742 | fclose($fp); |
||
1743 | } |
||
1744 | return array($data, $name); |
||
1745 | } |
||
1746 | |||
1747 | /** |
||
1748 | * Detect file type extension by local path |
||
1749 | * |
||
1750 | * @param string $path Local path |
||
1751 | * @return string file type extension with dot |
||
1752 | * @author Naoki Sawada |
||
1753 | */ |
||
1754 | protected function detectFileExtension($path) { |
||
1755 | static $type, $finfo; |
||
1756 | if (!$type) { |
||
1757 | $keys = array_keys($this->volumes); |
||
1758 | $volume = $this->volumes[$keys[0]]; |
||
1759 | |||
1760 | if (class_exists('finfo', false)) { |
||
1761 | $tmpFileInfo = explode(';', finfo_file(finfo_open(FILEINFO_MIME), __FILE__)); |
||
1762 | } else { |
||
1763 | $tmpFileInfo = false; |
||
1764 | } |
||
1765 | $regexp = '/text\/x\-(php|c\+\+)/'; |
||
1766 | if ($tmpFileInfo && preg_match($regexp, array_shift($tmpFileInfo))) { |
||
1767 | $type = 'finfo'; |
||
1768 | $finfo = finfo_open(FILEINFO_MIME); |
||
1769 | } elseif (function_exists('mime_content_type') |
||
1770 | && preg_match($regexp, array_shift(explode(';', mime_content_type(__FILE__))))) { |
||
0 ignored issues
–
show
|
|||
1771 | $type = 'mime_content_type'; |
||
1772 | } elseif (function_exists('getimagesize')) { |
||
1773 | $type = 'getimagesize'; |
||
1774 | } else { |
||
1775 | $type = 'none'; |
||
1776 | } |
||
1777 | } |
||
1778 | |||
1779 | $mime = ''; |
||
1780 | if ($type === 'finfo') { |
||
1781 | $mime = finfo_file($finfo, $path); |
||
1782 | } elseif ($type === 'mime_content_type') { |
||
1783 | $mime = mime_content_type($path); |
||
1784 | } elseif ($type === 'getimagesize') { |
||
1785 | if ($img = getimagesize($path)) { |
||
1786 | $mime = $img['mime']; |
||
1787 | } |
||
1788 | } |
||
1789 | |||
1790 | if ($mime) { |
||
1791 | $mime = explode(';', $mime); |
||
1792 | $mime = trim($mime[0]); |
||
1793 | |||
1794 | if (in_array($mime, array('application/x-empty', 'inode/x-empty'))) { |
||
1795 | // finfo return this mime for empty files |
||
1796 | $mime = 'text/plain'; |
||
1797 | } elseif ($mime == 'application/x-zip') { |
||
1798 | // http://elrte.org/redmine/issues/163 |
||
1799 | $mime = 'application/zip'; |
||
1800 | } |
||
1801 | } |
||
1802 | |||
1803 | $ext = $mime? $volume->getExtentionByMime($mime) : ''; |
||
0 ignored issues
–
show
The variable
$volume does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
1804 | return $ext? ('.' . $ext) : ''; |
||
1805 | } |
||
1806 | |||
1807 | /** |
||
1808 | * Get temporary directory path |
||
1809 | * |
||
1810 | * @param string $volumeTempPath |
||
1811 | * @return string |
||
1812 | * @author Naoki Sawada |
||
1813 | */ |
||
1814 | private function getTempDir($volumeTempPath = null) { |
||
1815 | $testDirs = array(); |
||
1816 | if ($this->uploadTempPath) { |
||
1817 | $testDirs[] = rtrim(realpath($this->uploadTempPath), DIRECTORY_SEPARATOR); |
||
1818 | } |
||
1819 | if ($volumeTempPath) { |
||
0 ignored issues
–
show
The expression
$volumeTempPath of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
Loading history...
|
|||
1820 | $testDirs[] = rtrim(realpath($volumeTempPath), DIRECTORY_SEPARATOR); |
||
1821 | } |
||
1822 | if (function_exists('sys_get_temp_dir')) { |
||
1823 | $testDirs[] = sys_get_temp_dir(); |
||
1824 | } |
||
1825 | $tempDir = ''; |
||
1826 | foreach($testDirs as $testDir) { |
||
1827 | if (!$testDir || !is_dir($testDir)) continue; |
||
1828 | if (is_writable($testDir)) { |
||
1829 | $tempDir = $testDir; |
||
1830 | $gc = time() - 3600; |
||
1831 | foreach(glob($tempDir . DIRECTORY_SEPARATOR .'ELF*') as $cf) { |
||
1832 | if (filemtime($cf) < $gc) { |
||
1833 | unlink($cf); |
||
1834 | } |
||
1835 | } |
||
1836 | break; |
||
1837 | } |
||
1838 | } |
||
1839 | return $tempDir; |
||
1840 | } |
||
1841 | |||
1842 | /** |
||
1843 | * chmod |
||
1844 | * |
||
1845 | * @param array command arguments |
||
1846 | * @return array |
||
1847 | * @author David Bartle |
||
1848 | **/ |
||
1849 | protected function chmod($args) { |
||
1850 | $targets = $args['targets']; |
||
1851 | $mode = intval((string)$args['mode'], 8); |
||
1852 | |||
1853 | if (!is_array($targets)) { |
||
1854 | $targets = array($targets); |
||
1855 | } |
||
1856 | |||
1857 | $result = array(); |
||
1858 | |||
1859 | if (($volume = $this->volume($targets[0])) == false) { |
||
1860 | $result['error'] = $this->error(self::ERROR_CONF_NO_VOL); |
||
1861 | return $result; |
||
1862 | } |
||
1863 | |||
1864 | $files = array(); |
||
1865 | $errors = array(); |
||
1866 | foreach($targets as $target) { |
||
1867 | $file = $volume->chmod($target, $mode); |
||
1868 | if ($file) { |
||
1869 | $files = array_merge($files, is_array($file)? $file : array($file)); |
||
1870 | } else { |
||
1871 | $errors = array_merge($errors, $volume->error()); |
||
1872 | } |
||
1873 | } |
||
1874 | |||
1875 | if ($files) { |
||
0 ignored issues
–
show
The expression
$files of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
1876 | $result['changed'] = $files; |
||
1877 | if ($errors) { |
||
0 ignored issues
–
show
The expression
$errors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
1878 | $result['warning'] = $this->error($errors); |
||
1879 | } |
||
1880 | } else { |
||
1881 | $result['error'] = $this->error($errors); |
||
1882 | } |
||
1883 | |||
1884 | return $result; |
||
1885 | } |
||
1886 | |||
1887 | /** |
||
1888 | * Check chunked upload files |
||
1889 | * |
||
1890 | * @param string $tmpname uploaded temporary file path |
||
1891 | * @param string $chunk uploaded chunk file name |
||
1892 | * @param string $cid uploaded chunked file id |
||
1893 | * @param string $tempDir temporary dirctroy path |
||
1894 | * @param null $volume |
||
1895 | * @return array or (empty, empty) |
||
1896 | * @author Naoki Sawada |
||
1897 | */ |
||
1898 | private function checkChunkedFile($tmpname, $chunk, $cid, $tempDir, $volume = null) { |
||
0 ignored issues
–
show
checkChunkedFile uses the super-global variable $_POST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
1899 | if (preg_match('/^(.+)(\.\d+_(\d+))\.part$/s', $chunk, $m)) { |
||
1900 | $fname = $m[1]; |
||
1901 | $encname = md5($cid . '_' . $fname); |
||
1902 | $base = $tempDir . DIRECTORY_SEPARATOR . 'ELF' . $encname; |
||
1903 | $clast = intval($m[3]); |
||
1904 | if (is_null($tmpname)) { |
||
1905 | ignore_user_abort(true); |
||
1906 | sleep(10); // wait 10 sec |
||
1907 | // chunked file upload fail |
||
1908 | foreach(glob($base . '*') as $cf) { |
||
1909 | unlink($cf); |
||
1910 | } |
||
1911 | ignore_user_abort(false); |
||
1912 | return; |
||
1913 | } |
||
1914 | |||
1915 | $range = isset($_POST['range'])? trim($_POST['range']) : ''; |
||
1916 | if ($range && preg_match('/^(\d+),(\d+),(\d+)$/', $range, $ranges)) { |
||
1917 | $start = $ranges[1]; |
||
1918 | $len = $ranges[2]; |
||
1919 | $size = $ranges[3]; |
||
1920 | $tmp = $base . '.part'; |
||
1921 | $csize = filesize($tmpname); |
||
1922 | |||
1923 | $tmpExists = is_file($tmp); |
||
1924 | if (!$tmpExists) { |
||
1925 | // check upload max size |
||
1926 | $uploadMaxSize = $volume->getUploadMaxSize(); |
||
0 ignored issues
–
show
|
|||
1927 | if ($uploadMaxSize > 0 && $size > $uploadMaxSize) { |
||
1928 | return array(self::ERROR_UPLOAD_FILE_SIZE, false); |
||
1929 | } |
||
1930 | // make temp file |
||
1931 | $ok = false; |
||
1932 | if ($fp = fopen($tmp, 'wb')) { |
||
1933 | flock($fp, LOCK_EX); |
||
1934 | $ok = ftruncate($fp, $size); |
||
1935 | flock($fp, LOCK_UN); |
||
1936 | fclose($fp); |
||
1937 | touch($base); |
||
1938 | } |
||
1939 | if (!$ok) { |
||
1940 | unlink($tmp); |
||
1941 | return array(self::ERROR_UPLOAD_TEMP, false); |
||
1942 | } |
||
1943 | } else { |
||
1944 | // wait until makeing temp file (for anothor session) |
||
1945 | $cnt = 1200; // Time limit 120 sec |
||
1946 | while(!is_file($base) && --$cnt) { |
||
1947 | usleep(100000); // wait 100ms |
||
1948 | } |
||
1949 | if (!$cnt) { |
||
1950 | return array(self::ERROR_UPLOAD_TEMP, false); |
||
1951 | } |
||
1952 | } |
||
1953 | |||
1954 | // check size info |
||
1955 | if ($len != $csize || $start + $len > $size || ($tmpExists && $size != filesize($tmp))) { |
||
1956 | return array(self::ERROR_UPLOAD_TEMP, false); |
||
1957 | } |
||
1958 | |||
1959 | // write chunk data |
||
1960 | $writelen = 0; |
||
0 ignored issues
–
show
$writelen is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
1961 | $src = fopen($tmpname, 'rb'); |
||
1962 | $fp = fopen($tmp, 'cb'); |
||
1963 | fseek($fp, $start); |
||
1964 | $writelen = stream_copy_to_stream($src, $fp, $len); |
||
1965 | fclose($fp); |
||
1966 | fclose($src); |
||
1967 | if ($writelen != $len) { |
||
1968 | return array(self::ERROR_UPLOAD_TEMP, false); |
||
1969 | } |
||
1970 | |||
1971 | // write counts |
||
1972 | file_put_contents($base, "\0", FILE_APPEND | LOCK_EX); |
||
1973 | |||
1974 | if (filesize($base) >= $clast + 1) { |
||
1975 | // Completion |
||
1976 | unlink($base); |
||
1977 | return array($tmp, $fname); |
||
1978 | } |
||
1979 | } else { |
||
1980 | // old way |
||
1981 | $part = $base . $m[2]; |
||
1982 | if (move_uploaded_file($tmpname, $part)) { |
||
1983 | chmod($part, 0600); |
||
1984 | if ($clast < count(glob($base . '*'))) { |
||
1985 | $parts = array(); |
||
1986 | for ($i = 0; $i <= $clast; $i++) { |
||
1987 | $name = $base . '.' . $i . '_' . $clast; |
||
1988 | if (is_readable($name)) { |
||
1989 | $parts[] = $name; |
||
1990 | } else { |
||
1991 | $parts = null; |
||
1992 | break; |
||
1993 | } |
||
1994 | } |
||
1995 | if ($parts) { |
||
1996 | if (!is_file($base)) { |
||
1997 | touch($base); |
||
1998 | if ($resfile = tempnam($tempDir, 'ELF')) { |
||
1999 | $target = fopen($resfile, 'wb'); |
||
2000 | foreach($parts as $f) { |
||
2001 | $fp = fopen($f, 'rb'); |
||
2002 | while (!feof($fp)) { |
||
2003 | fwrite($target, fread($fp, 8192)); |
||
2004 | } |
||
2005 | fclose($fp); |
||
2006 | unlink($f); |
||
2007 | } |
||
2008 | fclose($target); |
||
2009 | unlink($base); |
||
2010 | return array($resfile, $fname); |
||
2011 | } |
||
2012 | unlink($base); |
||
2013 | } |
||
2014 | } |
||
2015 | } |
||
2016 | } |
||
2017 | } |
||
2018 | } |
||
2019 | return array('', ''); |
||
2020 | } |
||
2021 | |||
2022 | /** |
||
2023 | * Save uploaded files |
||
2024 | * |
||
2025 | * @param array |
||
2026 | * @return array |
||
2027 | * @author Dmitry (dio) Levashov |
||
2028 | **/ |
||
2029 | protected function upload($args) { |
||
0 ignored issues
–
show
upload uses the super-global variable $GLOBALS which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
upload uses the super-global variable $_POST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
2030 | $ngReg = '/[\/\\?*:|"<>]/'; |
||
2031 | $target = $args['target']; |
||
2032 | $volume = $this->volume($target); |
||
2033 | $files = isset($args['FILES']['upload']) && is_array($args['FILES']['upload']) ? $args['FILES']['upload'] : array(); |
||
2034 | $header = empty($args['html']) ? array() : array('header' => 'Content-Type: text/html; charset=utf-8'); |
||
2035 | $result = array_merge(array('added' => array()), $header); |
||
2036 | $paths = $args['upload_path']? $args['upload_path'] : array(); |
||
2037 | $chunk = $args['chunk']? $args['chunk'] : ''; |
||
2038 | $cid = $args['cid']? (int)$args['cid'] : ''; |
||
2039 | $mtimes = $args['mtime']? $args['mtime'] : array(); |
||
2040 | |||
2041 | $renames = $hashes = array(); |
||
2042 | $suffix = '~'; |
||
2043 | if ($args['renames'] && is_array($args['renames'])) { |
||
2044 | $renames = array_flip($args['renames']); |
||
2045 | if (is_string($args['suffix']) && ! preg_match($ngReg, $args['suffix'])) { |
||
2046 | $suffix = $args['suffix']; |
||
2047 | } |
||
2048 | } |
||
2049 | if ($args['hashes'] && is_array($args['hashes'])) { |
||
2050 | $hashes = array_flip($args['hashes']); |
||
2051 | } |
||
2052 | |||
2053 | if (!$volume) { |
||
2054 | return array_merge(array('error' => $this->error(self::ERROR_UPLOAD, self::ERROR_TRGDIR_NOT_FOUND, '#'.$target)), $header); |
||
2055 | } |
||
2056 | |||
2057 | // regist Shutdown function |
||
2058 | $GLOBALS['elFinderTempFiles'] = array(); |
||
2059 | // if (version_compare(PHP_VERSION, '5.3.0', '>=')) { |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
57% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them.
Loading history...
|
|||
2060 | // $shutdownfunc = function(){ // <- Parse error on PHP < 5.3 ;-( |
||
2061 | // foreach(array_keys($GLOBALS['elFinderTempFiles']) as $f){ |
||
2062 | // unlink($f); |
||
2063 | // } |
||
2064 | // }; |
||
2065 | // } else { |
||
2066 | $shutdownfunc = create_function('', ' |
||
0 ignored issues
–
show
The use of
create_function is highly discouraged, better use a closure.
// Instead of
$function = create_function('$a, $b', 'return $a + $b');
// Better use
$function = function($a, $b) { return $a + $b; }
Loading history...
|
|||
2067 | foreach(array_keys($GLOBALS[\'elFinderTempFiles\']) as $f){ |
||
2068 | is_file($f) && unlink($f); |
||
2069 | } |
||
2070 | '); |
||
2071 | // } |
||
2072 | register_shutdown_function($shutdownfunc); |
||
2073 | |||
2074 | // file extentions table by MIME |
||
2075 | $extTable = array_flip(array_unique($volume->getMimeTable())); |
||
2076 | |||
2077 | if (empty($files)) { |
||
2078 | |||
2079 | //--- This part is unnecessary code from 2.1.7 START ---// |
||
2080 | if (!$args['upload'] && $args['name'] && is_array($args['name'])) { |
||
2081 | $error = ''; |
||
2082 | $result['name'] = array(); |
||
2083 | foreach($args['name'] as $_i => $_name) { |
||
2084 | if (!$volume->isUploadableByName($_name)) { |
||
2085 | $error = $this->error(self::ERROR_UPLOAD_FILE, $_name, self::ERROR_UPLOAD_FILE_MIME); |
||
2086 | break; |
||
2087 | } |
||
2088 | $result['name'][$_i] = preg_replace($ngReg, '_', $_name); |
||
2089 | } |
||
2090 | if ($error) { |
||
2091 | $result['error'] = $error; |
||
2092 | return $result; |
||
2093 | } |
||
2094 | $result = array_merge_recursive($result, $this->ls($args)); |
||
2095 | if (empty($result['list'])) { |
||
2096 | $result['name'] = array(); |
||
2097 | } else { |
||
2098 | // It is using the old(<=2.1.6) JavaScript in the new(>2.1.6) back-end? |
||
2099 | unset($result['list']['exists'], $result['list']['hashes']); |
||
2100 | $result['name'] = array_merge(array_intersect($result['name'], $result['list'])); |
||
2101 | } |
||
2102 | return $result; |
||
2103 | } |
||
2104 | //--- This part is unnessesaly code from 2.1.7 END ---// |
||
2105 | |||
2106 | if (isset($args['upload']) && is_array($args['upload']) && ($tempDir = $this->getTempDir($volume->getTempPath()))) { |
||
2107 | $names = array(); |
||
2108 | foreach($args['upload'] as $i => $url) { |
||
2109 | // check chunked file upload commit |
||
2110 | if ($args['chunk']) { |
||
2111 | if ($url === 'chunkfail' && $args['mimes'] === 'chunkfail') { |
||
2112 | $this->checkChunkedFile(null, $chunk, $cid, $tempDir); |
||
2113 | if (preg_match('/^(.+)(\.\d+_(\d+))\.part$/s', $chunk, $m)) { |
||
2114 | $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $m[1], self::ERROR_UPLOAD_TRANSFER); |
||
2115 | } |
||
2116 | return $result; |
||
2117 | } else { |
||
2118 | $tmpfname = $tempDir . '/' . $args['chunk']; |
||
2119 | $files['tmp_name'][$i] = $tmpfname; |
||
2120 | $files['name'][$i] = $url; |
||
2121 | $files['error'][$i] = 0; |
||
2122 | $GLOBALS['elFinderTempFiles'][$tmpfname] = true; |
||
2123 | break; |
||
2124 | } |
||
2125 | } |
||
2126 | |||
2127 | $tmpfname = $tempDir . DIRECTORY_SEPARATOR . 'ELF_FATCH_' . md5($url.microtime(true)); |
||
2128 | |||
2129 | $_name = ''; |
||
2130 | // check is data: |
||
2131 | if (substr($url, 0, 5) === 'data:') { |
||
2132 | list($data, $args['name'][$i]) = $this->parse_data_scheme($url, $extTable); |
||
2133 | } else { |
||
2134 | $fp = fopen($tmpfname, 'wb'); |
||
2135 | $data = $this->get_remote_contents($url, 30, 5, 'Mozilla/5.0', $fp); |
||
2136 | $_POST['overwrite'] = false; |
||
2137 | $_name = preg_replace('~^.*?([^/#?]+)(?:\?.*)?(?:#.*)?$~', '$1', rawurldecode($url)); |
||
2138 | // Check `Content-Disposition` response header |
||
2139 | if ($data && ($headers = get_headers($url, true)) && !empty($headers['Content-Disposition'])) { |
||
2140 | if (preg_match('/filename\*?=(?:([a-zA-Z0-9_-]+?)\'\')?"?([a-z0-9_.~%-]+)"?/i', $headers['Content-Disposition'], $m)) { |
||
2141 | $_name = rawurldecode($m[2]); |
||
2142 | if ($m[1] && strtoupper($m[1]) !== 'UTF-8' && function_exists('mb_convert_encoding')) { |
||
2143 | $_name = mb_convert_encoding($_name, 'UTF-8', $m[1]); |
||
2144 | } |
||
2145 | } |
||
2146 | } |
||
2147 | } |
||
2148 | if ($data) { |
||
2149 | if (isset($args['name'][$i])) { |
||
2150 | $_name = $args['name'][$i]; |
||
2151 | } |
||
2152 | if ($_name) { |
||
2153 | $_ext = ''; |
||
2154 | if (preg_match('/(\.[a-z0-9]{1,7})$/', $_name, $_match)) { |
||
2155 | $_ext = $_match[1]; |
||
2156 | } |
||
2157 | if ((is_resource($data) && fclose($data)) || file_put_contents($tmpfname, $data)) { |
||
2158 | $GLOBALS['elFinderTempFiles'][$tmpfname] = true; |
||
2159 | $_name = preg_replace($ngReg, '_', $_name); |
||
2160 | list($_a, $_b) = array_pad(explode('.', $_name, 2), 2, ''); |
||
2161 | if ($_b === '') { |
||
2162 | if ($_ext) { |
||
2163 | rename($tmpfname, $tmpfname . $_ext); |
||
2164 | $tmpfname = $tmpfname . $_ext; |
||
2165 | } |
||
2166 | $_b = $this->detectFileExtension($tmpfname); |
||
2167 | $_name = $_a.$_b; |
||
2168 | } else { |
||
2169 | $_b = '.'.$_b; |
||
2170 | } |
||
2171 | if (isset($names[$_name])) { |
||
2172 | $_name = $_a.'_'.$names[$_name]++.$_b; |
||
2173 | } else { |
||
2174 | $names[$_name] = 1; |
||
2175 | } |
||
2176 | $files['tmp_name'][$i] = $tmpfname; |
||
2177 | $files['name'][$i] = $_name; |
||
2178 | $files['error'][$i] = 0; |
||
2179 | } else { |
||
2180 | unlink($tmpfname); |
||
2181 | } |
||
2182 | } |
||
2183 | } |
||
2184 | } |
||
2185 | } |
||
2186 | if (empty($files)) { |
||
2187 | return array_merge(array('error' => $this->error(self::ERROR_UPLOAD, self::ERROR_UPLOAD_NO_FILES)), $header); |
||
2188 | } |
||
2189 | } |
||
2190 | |||
2191 | $addedDirs = array(); |
||
2192 | foreach ($files['name'] as $i => $name) { |
||
2193 | if (($error = $files['error'][$i]) > 0) { |
||
2194 | $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, $error == UPLOAD_ERR_INI_SIZE || $error == UPLOAD_ERR_FORM_SIZE ? self::ERROR_UPLOAD_FILE_SIZE : self::ERROR_UPLOAD_TRANSFER); |
||
2195 | $this->uploadDebug = 'Upload error code: '.$error; |
||
2196 | break; |
||
2197 | } |
||
2198 | |||
2199 | $tmpname = $files['tmp_name'][$i]; |
||
2200 | $path = ($paths && isset($paths[$i]))? $paths[$i] : ''; |
||
2201 | $mtime = isset($mtimes[$i])? $mtimes[$i] : 0; |
||
2202 | if ($name === 'blob') { |
||
2203 | if ($chunk) { |
||
2204 | if ($tempDir = $this->getTempDir($volume->getTempPath())) { |
||
2205 | list($tmpname, $name) = $this->checkChunkedFile($tmpname, $chunk, $cid, $tempDir, $volume); |
||
2206 | if ($tmpname) { |
||
2207 | if ($name === false) { |
||
2208 | preg_match('/^(.+)(\.\d+_(\d+))\.part$/s', $chunk, $m); |
||
2209 | $result['error'] = $this->error(self::ERROR_UPLOAD_FILE, $m[1], $tmpname); |
||
2210 | $result['_chunkfailure'] = true; |
||
2211 | $this->uploadDebug = 'Upload error: ' . $tmpname; |
||
2212 | } else if ($name) { |
||
2213 | $result['_chunkmerged'] = basename($tmpname); |
||
2214 | $result['_name'] = $name; |
||
2215 | $result['_mtime'] = $mtime; |
||
2216 | } |
||
2217 | } |
||
2218 | } else { |
||
2219 | $result['error'] = $this->error(self::ERROR_UPLOAD_FILE, $chunk, self::ERROR_UPLOAD_TRANSFER); |
||
2220 | $this->uploadDebug = 'Upload error: unable open tmp file'; |
||
2221 | } |
||
2222 | return $result; |
||
2223 | } else { |
||
2224 | // for form clipboard with Google Chrome |
||
2225 | $type = $files['type'][$i]; |
||
2226 | $ext = isset($extTable[$type])? '.' . $extTable[$type] : ''; |
||
2227 | $name = substr(md5(basename($tmpname)), 0, 8) . $ext; |
||
2228 | } |
||
2229 | } |
||
2230 | |||
2231 | // do hook function 'upload.presave' |
||
2232 | if (! empty($this->listeners['upload.presave'])) { |
||
2233 | foreach($this->listeners['upload.presave'] as $handler) { |
||
2234 | call_user_func_array($handler, array(&$path, &$name, $tmpname, $this, $volume)); |
||
2235 | } |
||
2236 | } |
||
2237 | |||
2238 | if ($mtime) { |
||
2239 | touch($tmpname, $mtime); |
||
2240 | } |
||
2241 | |||
2242 | if (($fp = fopen($tmpname, 'rb')) == false) { |
||
2243 | $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, self::ERROR_UPLOAD_TRANSFER); |
||
2244 | $this->uploadDebug = 'Upload error: unable open tmp file'; |
||
2245 | if (! is_uploaded_file($tmpname)) { |
||
2246 | if ( unlink($tmpname)) unset($GLOBALS['elFinderTempFiles'][$tmpfname]); |
||
2247 | continue; |
||
2248 | } |
||
2249 | break; |
||
2250 | } |
||
2251 | $rnres = array(); |
||
2252 | if ($path !== '' && $path !== $target) { |
||
2253 | if ($dir = $volume->dir($path)) { |
||
2254 | $_target = $path; |
||
2255 | if (! isset($addedDirs[$path])) { |
||
2256 | $addedDirs[$path] = true; |
||
2257 | $result['added'][] =$dir; |
||
2258 | } |
||
2259 | } else { |
||
2260 | $result['error'] = $this->error(self::ERROR_UPLOAD, self::ERROR_TRGDIR_NOT_FOUND, 'hash@'.$path); |
||
2261 | break; |
||
2262 | } |
||
2263 | } else { |
||
2264 | $_target = $target; |
||
2265 | // file rename for backup |
||
2266 | if (isset($renames[$name])) { |
||
2267 | $dir = $volume->realpath($_target); |
||
2268 | if (isset($hashes[$name])) { |
||
2269 | $hash = $hashes[$name]; |
||
2270 | } else { |
||
2271 | $hash = $volume->getHash($dir, $name); |
||
2272 | } |
||
2273 | $rnres = $this->rename(array('target' => $hash, 'name' => $volume->uniqueName($dir, $name, $suffix, true, 0))); |
||
2274 | if (!empty($rnres['error'])) { |
||
2275 | $result['warning'] = $rnres['error']; |
||
2276 | break; |
||
2277 | } |
||
2278 | } |
||
2279 | } |
||
2280 | if (! $_target || ($file = $volume->upload($fp, $_target, $name, $tmpname, $hashes)) === false) { |
||
2281 | $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $name, $volume->error()); |
||
2282 | fclose($fp); |
||
2283 | if (! is_uploaded_file($tmpname)) { |
||
2284 | if ( unlink($tmpname)) unset($GLOBALS['elFinderTempFiles'][$tmpname]);; |
||
2285 | continue; |
||
2286 | } |
||
2287 | break; |
||
2288 | } |
||
2289 | |||
2290 | is_resource($fp) && fclose($fp); |
||
2291 | if (! is_uploaded_file($tmpname)){ |
||
2292 | clearstatcache(); |
||
2293 | if (!is_file($tmpname) || unlink($tmpname)) { |
||
2294 | unset($GLOBALS['elFinderTempFiles'][$tmpname]); |
||
2295 | } |
||
2296 | } |
||
2297 | $result['added'][] = $file; |
||
2298 | if ($rnres) { |
||
0 ignored issues
–
show
The expression
$rnres of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
2299 | $result = array_merge_recursive($result, $rnres); |
||
2300 | } |
||
2301 | } |
||
2302 | if ($GLOBALS['elFinderTempFiles']) { |
||
2303 | foreach(array_keys($GLOBALS['elFinderTempFiles']) as $_temp) { |
||
2304 | unlink($_temp); |
||
2305 | } |
||
2306 | } |
||
2307 | $result['removed'] = $volume->removed(); |
||
2308 | |||
2309 | if (!empty($args['node'])) { |
||
2310 | $result['callback'] = array( |
||
2311 | 'node' => $args['node'], |
||
2312 | 'bind' => 'upload' |
||
2313 | ); |
||
2314 | } |
||
2315 | return $result; |
||
2316 | } |
||
2317 | |||
2318 | /** |
||
2319 | * Copy/move files into new destination |
||
2320 | * |
||
2321 | * @param array command arguments |
||
2322 | * @return array |
||
2323 | * @author Dmitry (dio) Levashov |
||
2324 | **/ |
||
2325 | protected function paste($args) { |
||
2326 | $dst = $args['dst']; |
||
2327 | $targets = is_array($args['targets']) ? $args['targets'] : array(); |
||
2328 | $cut = !empty($args['cut']); |
||
2329 | $error = $cut ? self::ERROR_MOVE : self::ERROR_COPY; |
||
2330 | $result = array('changed' => array(), 'added' => array(), 'removed' => array()); |
||
2331 | |||
2332 | if (($dstVolume = $this->volume($dst)) == false) { |
||
2333 | return array('error' => $this->error($error, '#'.$targets[0], self::ERROR_TRGDIR_NOT_FOUND, '#'.$dst)); |
||
2334 | } |
||
2335 | |||
2336 | $hashes = $renames = array(); |
||
2337 | $suffix = '~'; |
||
2338 | if (!empty($args['renames'])) { |
||
2339 | $renames = array_flip($args['renames']); |
||
2340 | if (is_string($args['suffix']) && ! preg_match('/[\/\\?*:|"<>]/', $args['suffix'])) { |
||
2341 | $suffix = $args['suffix']; |
||
2342 | } |
||
2343 | } |
||
2344 | if (!empty($args['hashes'])) { |
||
2345 | $hashes = array_flip($args['hashes']); |
||
2346 | } |
||
2347 | |||
2348 | foreach ($targets as $target) { |
||
2349 | if (($srcVolume = $this->volume($target)) == false) { |
||
2350 | $result['warning'] = $this->error($error, '#'.$target, self::ERROR_FILE_NOT_FOUND); |
||
2351 | break; |
||
2352 | } |
||
2353 | |||
2354 | $rnres = array(); |
||
2355 | if ($renames) { |
||
0 ignored issues
–
show
The expression
$renames of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
2356 | $file = $srcVolume->file($target); |
||
2357 | if (isset($renames[$file['name']])) { |
||
2358 | $dir = $dstVolume->realpath($dst); |
||
2359 | if (isset($hashes[$file['name']])) { |
||
2360 | $hash = $hashes[$file['name']]; |
||
2361 | } else { |
||
2362 | $hash = $dstVolume->getHash($dir, $file['name']); |
||
2363 | } |
||
2364 | $rnres = $this->rename(array('target' => $hash, 'name' => $dstVolume->uniqueName($dir, $file['name'], $suffix, true, 0))); |
||
2365 | if (!empty($rnres['error'])) { |
||
2366 | $result['warning'] = $rnres['error']; |
||
2367 | break; |
||
2368 | } |
||
2369 | } |
||
2370 | } |
||
2371 | |||
2372 | if (($file = $dstVolume->paste($srcVolume, $target, $dst, $cut, $hashes)) == false) { |
||
2373 | $result['warning'] = $this->error($dstVolume->error()); |
||
2374 | break; |
||
2375 | } |
||
2376 | |||
2377 | $dirChange = ! empty($file['dirChange']); |
||
2378 | unset($file['dirChange']); |
||
2379 | if ($dirChange) { |
||
2380 | $result['changed'][] = $file; |
||
2381 | } else { |
||
2382 | $result['added'][] = $file; |
||
2383 | } |
||
2384 | if ($rnres) { |
||
0 ignored issues
–
show
The expression
$rnres of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
2385 | $result = array_merge_recursive($result, $rnres); |
||
2386 | } |
||
2387 | } |
||
2388 | return $result; |
||
2389 | } |
||
2390 | |||
2391 | /** |
||
2392 | * Return file content |
||
2393 | * |
||
2394 | * @param array $args command arguments |
||
2395 | * @return array |
||
2396 | * @author Dmitry (dio) Levashov |
||
2397 | **/ |
||
2398 | protected function get($args) { |
||
2399 | $target = $args['target']; |
||
2400 | $volume = $this->volume($target); |
||
2401 | |||
2402 | if (!$volume || ($file = $volume->file($target)) == false) { |
||
2403 | return array('error' => $this->error(self::ERROR_OPEN, '#'.$target, self::ERROR_FILE_NOT_FOUND)); |
||
2404 | } |
||
2405 | |||
2406 | if (($content = $volume->getContents($target)) === false) { |
||
2407 | return array('error' => $this->error(self::ERROR_OPEN, $volume->path($target), $volume->error())); |
||
2408 | } |
||
2409 | |||
2410 | if ($args['conv'] && function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding')) { |
||
2411 | $mime = isset($file['mime'])? $file['mime'] : ''; |
||
2412 | if ($mime && strtolower(substr($mime, 0, 4)) === 'text') { |
||
2413 | if ($enc = mb_detect_encoding ( $content , mb_detect_order(), true)) { |
||
2414 | if (strtolower($enc) !== 'utf-8') { |
||
2415 | $content = mb_convert_encoding($content, 'UTF-8', $enc); |
||
2416 | } |
||
2417 | } |
||
2418 | } |
||
2419 | } |
||
2420 | |||
2421 | $json = json_encode($content); |
||
2422 | |||
2423 | if ($json === false || strlen($json) < strlen($content)) { |
||
2424 | if ($args['conv']) { |
||
2425 | return array('error' => $this->error(self::ERROR_CONV_UTF8,self::ERROR_NOT_UTF8_CONTENT, $volume->path($target))); |
||
2426 | } else { |
||
2427 | return array('doconv' => true); |
||
2428 | } |
||
2429 | } |
||
2430 | |||
2431 | return array('content' => $content); |
||
2432 | } |
||
2433 | |||
2434 | /** |
||
2435 | * Save content into text file |
||
2436 | * |
||
2437 | * @param $args |
||
2438 | * @return array |
||
2439 | * @author Dmitry (dio) Levashov |
||
2440 | */ |
||
2441 | protected function put($args) { |
||
2442 | $target = $args['target']; |
||
2443 | |||
2444 | if (($volume = $this->volume($target)) == false |
||
2445 | || ($file = $volume->file($target)) == false) { |
||
2446 | return array('error' => $this->error(self::ERROR_SAVE, '#'.$target, self::ERROR_FILE_NOT_FOUND)); |
||
2447 | } |
||
2448 | |||
2449 | if (($file = $volume->putContents($target, $args['content'])) == false) { |
||
2450 | return array('error' => $this->error(self::ERROR_SAVE, $volume->path($target), $volume->error())); |
||
2451 | } |
||
2452 | |||
2453 | return array('changed' => array($file)); |
||
2454 | } |
||
2455 | |||
2456 | /** |
||
2457 | * Extract files from archive |
||
2458 | * |
||
2459 | * @param array $args command arguments |
||
2460 | * @return array |
||
2461 | * @author Dmitry (dio) Levashov, |
||
2462 | * @author Alexey Sukhotin |
||
2463 | **/ |
||
2464 | protected function extract($args) { |
||
2465 | $target = $args['target']; |
||
2466 | $mimes = !empty($args['mimes']) && is_array($args['mimes']) ? $args['mimes'] : array(); |
||
0 ignored issues
–
show
$mimes is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
2467 | $error = array(self::ERROR_EXTRACT, '#'.$target); |
||
0 ignored issues
–
show
$error is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
2468 | $makedir = isset($args['makedir'])? (bool)$args['makedir'] : null; |
||
2469 | |||
2470 | if (($volume = $this->volume($target)) == false |
||
2471 | || ($file = $volume->file($target)) == false) { |
||
2472 | return array('error' => $this->error(self::ERROR_EXTRACT, '#'.$target, self::ERROR_FILE_NOT_FOUND)); |
||
2473 | } |
||
2474 | |||
2475 | return ($file = $volume->extract($target, $makedir)) |
||
2476 | ? array('added' => isset($file['read'])? array($file) : $file) |
||
2477 | : array('error' => $this->error(self::ERROR_EXTRACT, $volume->path($target), $volume->error())); |
||
2478 | } |
||
2479 | |||
2480 | /** |
||
2481 | * Create archive |
||
2482 | * |
||
2483 | * @param array $args command arguments |
||
2484 | * @return array |
||
2485 | * @author Dmitry (dio) Levashov, |
||
2486 | * @author Alexey Sukhotin |
||
2487 | **/ |
||
2488 | protected function archive($args) { |
||
2489 | $type = $args['type']; |
||
0 ignored issues
–
show
$type is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
2490 | $targets = isset($args['targets']) && is_array($args['targets']) ? $args['targets'] : array(); |
||
2491 | $name = isset($args['name'])? $args['name'] : ''; |
||
2492 | |||
2493 | if (($volume = $this->volume($targets[0])) == false) { |
||
2494 | return $this->error(self::ERROR_ARCHIVE, self::ERROR_TRGDIR_NOT_FOUND); |
||
2495 | } |
||
2496 | |||
2497 | return ($file = $volume->archive($targets, $args['type'], $name)) |
||
2498 | ? array('added' => array($file)) |
||
2499 | : array('error' => $this->error(self::ERROR_ARCHIVE, $volume->error())); |
||
2500 | } |
||
2501 | |||
2502 | /** |
||
2503 | * Search files |
||
2504 | * |
||
2505 | * @param array $args command arguments |
||
2506 | * @return array |
||
2507 | * @author Dmitry Levashov |
||
2508 | **/ |
||
2509 | protected function search($args) { |
||
2510 | $q = trim($args['q']); |
||
2511 | $mimes = !empty($args['mimes']) && is_array($args['mimes']) ? $args['mimes'] : array(); |
||
2512 | $target = !empty($args['target'])? $args['target'] : null; |
||
2513 | $result = array(); |
||
2514 | $errors = array(); |
||
2515 | |||
2516 | if ($target) { |
||
2517 | if ($volume = $this->volume($target)) { |
||
2518 | $result = $volume->search($q, $mimes, $target); |
||
2519 | $errors = array_merge($errors, $volume->error()); |
||
2520 | } |
||
2521 | } else { |
||
2522 | foreach ($this->volumes as $volume) { |
||
2523 | $result = array_merge($result, $volume->search($q, $mimes)); |
||
2524 | $errors = array_merge($errors, $volume->error()); |
||
2525 | } |
||
2526 | } |
||
2527 | |||
2528 | $result = array('files' => $result); |
||
2529 | if ($errors) { |
||
0 ignored issues
–
show
The expression
$errors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
2530 | $result['warning'] = $errors; |
||
2531 | } |
||
2532 | return $result; |
||
2533 | } |
||
2534 | |||
2535 | /** |
||
2536 | * Return file info (used by client "places" ui) |
||
2537 | * |
||
2538 | * @param array $args command arguments |
||
2539 | * @return array |
||
2540 | * @author Dmitry Levashov |
||
2541 | **/ |
||
2542 | protected function info($args) { |
||
2543 | $files = array(); |
||
2544 | $sleep = 0; |
||
0 ignored issues
–
show
$sleep is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
2545 | $compare = null; |
||
2546 | // long polling mode |
||
2547 | if ($args['compare'] && count($args['targets']) === 1) { |
||
2548 | $compare = intval($args['compare']); |
||
2549 | $hash = $args['targets'][0]; |
||
2550 | if ($volume = $this->volume($hash)) { |
||
2551 | $standby = (int)$volume->getOption('plStandby'); |
||
2552 | $_compare = false; |
||
2553 | if (($syncCheckFunc = $volume->getOption('syncCheckFunc')) && is_callable($syncCheckFunc)) { |
||
2554 | $_compare = call_user_func_array($syncCheckFunc, array($volume->realpath($hash), $standby, $compare, $volume, $this)); |
||
2555 | } |
||
2556 | if ($_compare !== false) { |
||
2557 | $compare = $_compare; |
||
2558 | } else { |
||
2559 | $sleep = max(1, (int)$volume->getOption('tsPlSleep')); |
||
2560 | $limit = max(1, $standby / $sleep) + 1; |
||
2561 | do { |
||
2562 | elFinder::extendTimeLimit(30 + $sleep); |
||
2563 | $volume->clearstatcache(); |
||
2564 | if (($info = $volume->file($hash)) != false) { |
||
2565 | if ($info['ts'] != $compare) { |
||
2566 | $compare = $info['ts']; |
||
2567 | break; |
||
2568 | } |
||
2569 | } else { |
||
2570 | $compare = 0; |
||
2571 | break; |
||
2572 | } |
||
2573 | if (--$limit) { |
||
2574 | sleep($sleep); |
||
2575 | } |
||
2576 | } while($limit); |
||
2577 | } |
||
2578 | } |
||
2579 | } else { |
||
2580 | foreach ($args['targets'] as $hash) { |
||
2581 | if (($volume = $this->volume($hash)) != false |
||
2582 | && ($info = $volume->file($hash)) != false) { |
||
2583 | $info['path'] = $volume->path($hash); |
||
2584 | $files[] = $info; |
||
2585 | } |
||
2586 | } |
||
2587 | } |
||
2588 | |||
2589 | $result = array('files' => $files); |
||
2590 | if (!is_null($compare)) { |
||
2591 | $result['compare'] = strval($compare); |
||
2592 | } |
||
2593 | return $result; |
||
2594 | } |
||
2595 | |||
2596 | /** |
||
2597 | * Return image dimensions |
||
2598 | * |
||
2599 | * @param array $args command arguments |
||
2600 | * @return array |
||
2601 | * @author Dmitry (dio) Levashov |
||
2602 | **/ |
||
2603 | protected function dim($args) { |
||
2604 | $target = $args['target']; |
||
2605 | |||
2606 | if (($volume = $this->volume($target)) != false) { |
||
2607 | $dim = $volume->dimensions($target); |
||
2608 | return $dim ? array('dim' => $dim) : array(); |
||
2609 | } |
||
2610 | return array(); |
||
2611 | } |
||
2612 | |||
2613 | /** |
||
2614 | * Resize image |
||
2615 | * |
||
2616 | * @param array command arguments |
||
2617 | * @return array |
||
2618 | * @author Dmitry (dio) Levashov |
||
2619 | * @author Alexey Sukhotin |
||
2620 | **/ |
||
2621 | protected function resize($args) { |
||
2622 | $target = $args['target']; |
||
2623 | $width = $args['width']; |
||
2624 | $height = $args['height']; |
||
2625 | $x = (int)$args['x']; |
||
2626 | $y = (int)$args['y']; |
||
2627 | $mode = $args['mode']; |
||
2628 | $bg = null; |
||
2629 | $degree = (int)$args['degree']; |
||
2630 | $quality= (int)$args['quality']; |
||
2631 | |||
2632 | if (($volume = $this->volume($target)) == false |
||
2633 | || ($file = $volume->file($target)) == false) { |
||
2634 | return array('error' => $this->error(self::ERROR_RESIZE, '#'.$target, self::ERROR_FILE_NOT_FOUND)); |
||
2635 | } |
||
2636 | |||
2637 | return ($file = $volume->resize($target, $width, $height, $x, $y, $mode, $bg, $degree, $quality)) |
||
2638 | ? array('changed' => array($file)) |
||
2639 | : array('error' => $this->error(self::ERROR_RESIZE, $volume->path($target), $volume->error())); |
||
2640 | } |
||
2641 | |||
2642 | /** |
||
2643 | * Return content URL |
||
2644 | * |
||
2645 | * @param array $args command arguments |
||
2646 | * @return array |
||
2647 | * @author Naoki Sawada |
||
2648 | **/ |
||
2649 | protected function url($args) { |
||
2650 | $target = $args['target']; |
||
2651 | $options = isset($args['options'])? $args['options'] : array(); |
||
2652 | if (($volume = $this->volume($target)) != false) { |
||
2653 | $url = $volume->getContentUrl($target, $options); |
||
2654 | return $url ? array('url' => $url) : array(); |
||
2655 | } |
||
2656 | return array(); |
||
2657 | } |
||
2658 | |||
2659 | /** |
||
2660 | * Output callback result with JavaScript that control elFinder |
||
2661 | * or HTTP redirect to callbackWindowURL |
||
2662 | * |
||
2663 | * @param array command arguments |
||
2664 | * @author Naoki Sawada |
||
2665 | */ |
||
2666 | protected function callback($args) { |
||
2667 | $checkReg = '/[^a-zA-Z0-9;._-]/'; |
||
2668 | $node = (isset($args['node']) && !preg_match($checkReg, $args['node']))? $args['node'] : ''; |
||
2669 | $json = (isset($args['json']) && json_decode($args['json']))? $args['json'] : '{}'; |
||
2670 | $bind = (isset($args['bind']) && !preg_match($checkReg, $args['bind']))? $args['bind'] : ''; |
||
2671 | $done = (!empty($args['done'])); |
||
2672 | |||
2673 | while( ob_get_level() ) { |
||
2674 | if (! ob_end_clean()) { |
||
2675 | break; |
||
2676 | } |
||
2677 | } |
||
2678 | |||
2679 | if ($done || ! $this->callbackWindowURL) { |
||
2680 | $script = ''; |
||
2681 | if ($node) { |
||
2682 | $script .= ' |
||
2683 | var w = window.opener || window.parent || window; |
||
2684 | try { |
||
2685 | var elf = w.document.getElementById(\''.$node.'\').elfinder; |
||
2686 | if (elf) { |
||
2687 | var data = '.$json.'; |
||
2688 | if (data.error) { |
||
2689 | elf.error(data.error); |
||
2690 | } else { |
||
2691 | data.warning && elf.error(data.warning); |
||
2692 | data.removed && data.removed.length && elf.remove(data); |
||
2693 | data.added && data.added.length && elf.add(data); |
||
2694 | data.changed && data.changed.length && elf.change(data);'; |
||
2695 | if ($bind) { |
||
2696 | $script .= ' |
||
2697 | elf.trigger(\''.$bind.'\', data);'; |
||
2698 | } |
||
2699 | $script .= ' |
||
2700 | data.sync && elf.sync(); |
||
2701 | } |
||
2702 | } |
||
2703 | } catch(e) { |
||
2704 | // for CORS |
||
2705 | w.postMessage && w.postMessage(JSON.stringify({bind:\''.$bind.'\',data:'.$json.'}), \'*\'); |
||
2706 | }'; |
||
2707 | } |
||
2708 | $script .= 'window.close();'; |
||
2709 | |||
2710 | $out = '<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><script>'.$script.'</script></head><body><a href="#" onlick="window.close();return false;">Close this window</a></body></html>'; |
||
2711 | |||
2712 | header('Content-Type: text/html; charset=utf-8'); |
||
2713 | header('Content-Length: '.strlen($out)); |
||
2714 | header('Cache-Control: private'); |
||
2715 | header('Pragma: no-cache'); |
||
2716 | |||
2717 | echo $out; |
||
2718 | |||
2719 | } else { |
||
2720 | $url = $this->callbackWindowURL; |
||
2721 | $url .= ((strpos($url, '?') === false)? '?' : '&') |
||
2722 | . '&node=' . rawurlencode($node) |
||
2723 | . (($json !== '{}')? ('&json=' . rawurlencode($json)) : '') |
||
2724 | . ($bind? ('&bind=' . rawurlencode($bind)) : '') |
||
2725 | . '&done=1'; |
||
2726 | |||
2727 | header('Location: ' . $url); |
||
2728 | |||
2729 | } |
||
2730 | exit(); |
||
0 ignored issues
–
show
The method
callback() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an
Loading history...
|
|||
2731 | } |
||
2732 | |||
2733 | /** |
||
2734 | * PHP error handler, catch error types only E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE |
||
2735 | * |
||
2736 | * @param int $errno |
||
2737 | * @param string $errstr |
||
2738 | * @param string $errfile |
||
2739 | * @param int $errline |
||
2740 | * @return void|boolean |
||
2741 | */ |
||
2742 | public static function phpErrorHandler($errno, $errstr, $errfile, $errline) { |
||
2743 | static $base = null; |
||
2744 | |||
2745 | if (is_null($base)) { |
||
2746 | $base = dirname(__FILE__) . DIRECTORY_SEPARATOR; |
||
2747 | } |
||
2748 | |||
2749 | if (! (error_reporting() & $errno)) { |
||
2750 | return; |
||
2751 | } |
||
2752 | |||
2753 | $errfile = str_replace($base, '', $errfile); |
||
2754 | |||
2755 | $proc = false; |
||
2756 | switch ($errno) { |
||
2757 | case E_WARNING: |
||
2758 | case E_USER_WARNING: |
||
2759 | elFinder::$phpErrors[] = "WARNING: $errstr in $errfile line $errline."; |
||
2760 | $proc = true; |
||
2761 | break; |
||
2762 | |||
2763 | case E_NOTICE: |
||
2764 | case E_USER_NOTICE: |
||
2765 | elFinder::$phpErrors[] = "NOTICE: $errstr in $errfile line $errline."; |
||
2766 | $proc = true; |
||
2767 | break; |
||
2768 | } |
||
2769 | |||
2770 | return $proc; |
||
2771 | } |
||
2772 | |||
2773 | /***************************************************************************/ |
||
2774 | /* utils */ |
||
2775 | /***************************************************************************/ |
||
2776 | |||
2777 | /** |
||
2778 | * Return root - file's owner |
||
2779 | * |
||
2780 | * @param string file hash |
||
2781 | * @return elFinderStorageDriver |
||
2782 | * @author Dmitry (dio) Levashov |
||
2783 | **/ |
||
2784 | protected function volume($hash) { |
||
2785 | foreach ($this->volumes as $id => $v) { |
||
2786 | if (strpos(''.$hash, $id) === 0) { |
||
2787 | return $this->volumes[$id]; |
||
2788 | } |
||
2789 | } |
||
2790 | return false; |
||
2791 | } |
||
2792 | |||
2793 | /** |
||
2794 | * Return files info array |
||
2795 | * |
||
2796 | * @param array $data one file info or files info |
||
2797 | * @return array |
||
2798 | * @author Dmitry (dio) Levashov |
||
2799 | **/ |
||
2800 | protected function toArray($data) { |
||
2801 | return isset($data['hash']) || !is_array($data) ? array($data) : $data; |
||
2802 | } |
||
2803 | |||
2804 | /** |
||
2805 | * Return fils hashes list |
||
2806 | * |
||
2807 | * @param array $files files info |
||
2808 | * @return array |
||
2809 | * @author Dmitry (dio) Levashov |
||
2810 | **/ |
||
2811 | protected function hashes($files) { |
||
2812 | $ret = array(); |
||
2813 | foreach ($files as $file) { |
||
2814 | $ret[] = $file['hash']; |
||
2815 | } |
||
2816 | return $ret; |
||
2817 | } |
||
2818 | |||
2819 | /** |
||
2820 | * Remove from files list hidden files and files with required mime types |
||
2821 | * |
||
2822 | * @param array $files files info |
||
2823 | * @return array |
||
2824 | * @author Dmitry (dio) Levashov |
||
2825 | **/ |
||
2826 | protected function filter($files) { |
||
2827 | $exists = array(); |
||
2828 | foreach ($files as $i => $file) { |
||
2829 | if (isset($exists[$file['hash']]) || !empty($file['hidden']) || !$this->default->mimeAccepted($file['mime'])) { |
||
2830 | unset($files[$i]); |
||
2831 | } |
||
2832 | $exists[$file['hash']] = true; |
||
2833 | } |
||
2834 | return array_values($files); |
||
2835 | } |
||
2836 | |||
2837 | protected function utime() { |
||
2838 | $time = explode(" ", microtime()); |
||
2839 | return (double)$time[1] + (double)$time[0]; |
||
2840 | } |
||
2841 | |||
2842 | /** |
||
2843 | * Return Network mount volume unique ID |
||
2844 | * |
||
2845 | * @param array $netVolumes Saved netvolumes array |
||
2846 | * @param string $prefix Id prefix |
||
2847 | * @return string|false |
||
2848 | * @author Naoki Sawada |
||
2849 | **/ |
||
2850 | protected function getNetVolumeUniqueId($netVolumes = null, $prefix = 'nm') { |
||
2851 | $id = false; |
||
0 ignored issues
–
show
$id is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
2852 | if (is_null($netVolumes)) { |
||
2853 | $netVolumes = $this->getNetVolumes(); |
||
2854 | } |
||
2855 | $ids = array(); |
||
2856 | foreach($netVolumes as $vOps) { |
||
2857 | if (isset($vOps['id']) && strpos($vOps['id'], $prefix) === 0) { |
||
2858 | $ids[$vOps['id']] = true; |
||
2859 | } |
||
2860 | } |
||
2861 | if (! $ids) { |
||
0 ignored issues
–
show
The expression
$ids of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using
Loading history...
|
|||
2862 | $id = $prefix.'1'; |
||
2863 | } else { |
||
2864 | $i = 0; |
||
2865 | while(isset($ids[$prefix.++$i]) && $i < 10000); |
||
2866 | $id = $prefix.$i; |
||
2867 | if (isset($ids[$id])) { |
||
2868 | $id = false; |
||
2869 | } |
||
2870 | } |
||
2871 | return $id; |
||
2872 | } |
||
2873 | |||
2874 | /** |
||
2875 | * Ensure directories recursively |
||
2876 | * |
||
2877 | * @param object $volume Volume object |
||
2878 | * @param string $target Target hash |
||
2879 | * @param string $dirs Array of directory tree to ensure |
||
2880 | * @param string $path Relative path form target hash |
||
2881 | * @return array|false array('stats' => array([stat of maked directory]), 'hashes' => array('[path]' => '[hash]')) |
||
2882 | * @author Naoki Sawada |
||
2883 | **/ |
||
2884 | protected function ensureDirsRecursively($volume, $target, $dirs, $path = '') { |
||
2885 | $res = array('stats' => array(), 'hashes' => array()); |
||
2886 | foreach($dirs as $name => $sub) { |
||
0 ignored issues
–
show
|
|||
2887 | $name = (string)$name; |
||
2888 | if ((($parent = $volume->realpath($target)) && ($dir = $volume->dir($volume->getHash($parent, $name)))) || ($dir = $volume->mkdir($target, $name))) { |
||
2889 | $_path = $path . '/' . $name; |
||
2890 | $res['stats'][] = $dir; |
||
2891 | $res['hashes'][$_path] = $dir['hash']; |
||
2892 | if (count($sub)) { |
||
2893 | if ($subRes = $this->ensureDirsRecursively($volume, $dir['hash'], $sub, $_path)) { |
||
2894 | $res = array_merge_recursive($res, $subRes); |
||
2895 | } else { |
||
2896 | return false; |
||
2897 | } |
||
2898 | } |
||
2899 | } else { |
||
2900 | return false; |
||
2901 | } |
||
2902 | } |
||
2903 | return $res; |
||
2904 | } |
||
2905 | |||
2906 | /***************************************************************************/ |
||
2907 | /* static utils */ |
||
2908 | /***************************************************************************/ |
||
2909 | |||
2910 | /** |
||
2911 | * Return Is Animation Gif |
||
2912 | * |
||
2913 | * @param string $path server local path of target image |
||
2914 | * @return bool |
||
2915 | */ |
||
2916 | public static function isAnimationGif($path) { |
||
2917 | list($width, $height, $type, $attr) = getimagesize($path); |
||
0 ignored issues
–
show
The assignment to
$width is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
Loading history...
The assignment to
$height is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
Loading history...
The assignment to
$attr is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
Loading history...
|
|||
2918 | switch ($type) { |
||
2919 | case IMAGETYPE_GIF: |
||
2920 | break; |
||
2921 | default: |
||
2922 | return false; |
||
2923 | } |
||
2924 | |||
2925 | $imgcnt = 0; |
||
2926 | $fp = fopen($path, 'rb'); |
||
2927 | fread($fp, 4); |
||
2928 | $c = fread($fp,1); |
||
2929 | if (ord($c) != 0x39) { // GIF89a |
||
2930 | return false; |
||
2931 | } |
||
2932 | |||
2933 | while (!feof($fp)) { |
||
2934 | do { |
||
2935 | $c = fread($fp, 1); |
||
2936 | } while(ord($c) != 0x21 && !feof($fp)); |
||
2937 | |||
2938 | if (feof($fp)) { |
||
2939 | break; |
||
2940 | } |
||
2941 | |||
2942 | $c2 = fread($fp,2); |
||
2943 | if (bin2hex($c2) == "f904") { |
||
2944 | $imgcnt++; |
||
2945 | } |
||
2946 | |||
2947 | if (feof($fp)) { |
||
2948 | break; |
||
2949 | } |
||
2950 | } |
||
2951 | |||
2952 | if ($imgcnt > 1) { |
||
2953 | return true; |
||
2954 | } else { |
||
2955 | return false; |
||
2956 | } |
||
2957 | } |
||
2958 | |||
2959 | /** |
||
2960 | * Return Is seekable stream resource |
||
2961 | * |
||
2962 | * @param resource $resource |
||
2963 | * @return bool |
||
2964 | */ |
||
2965 | public static function isSeekableStream($resource) { |
||
2966 | $metadata = stream_get_meta_data($resource); |
||
2967 | return $metadata['seekable']; |
||
2968 | } |
||
2969 | |||
2970 | /** |
||
2971 | * Rewind stream resource |
||
2972 | * |
||
2973 | * @param resource $resource |
||
2974 | * @return void |
||
2975 | */ |
||
2976 | public static function rewind($resource) { |
||
2977 | self::isSeekableStream($resource) && rewind($resource); |
||
2978 | } |
||
2979 | |||
2980 | /** |
||
2981 | * serialize and base64_encode of session data (If needed) |
||
2982 | * |
||
2983 | * @deprecated |
||
2984 | * @param mixed $var target variable |
||
2985 | * @author Naoki Sawada |
||
2986 | * @return mixed|string |
||
2987 | */ |
||
2988 | public static function sessionDataEncode($var) { |
||
2989 | if (self::$base64encodeSessionData) { |
||
2990 | $var = base64_encode(serialize($var)); |
||
2991 | } |
||
2992 | return $var; |
||
2993 | } |
||
2994 | |||
2995 | /** |
||
2996 | * base64_decode and unserialize of session data (If needed) |
||
2997 | * |
||
2998 | * @deprecated |
||
2999 | * @param mixed $var target variable |
||
3000 | * @param bool $checkIs data type for check (array|string|object|int) |
||
3001 | * @author Naoki Sawada |
||
3002 | * @return bool|mixed |
||
3003 | */ |
||
3004 | public static function sessionDataDecode(&$var, $checkIs = null) { |
||
3005 | if (self::$base64encodeSessionData) { |
||
3006 | $data = unserialize(base64_decode($var)); |
||
3007 | } else { |
||
3008 | $data = $var; |
||
3009 | } |
||
3010 | $chk = true; |
||
3011 | if ($checkIs) { |
||
3012 | switch ($checkIs) { |
||
3013 | case 'array': |
||
3014 | $chk = is_array($data); |
||
3015 | break; |
||
3016 | case 'string': |
||
3017 | $chk = is_string($data); |
||
3018 | break; |
||
3019 | case 'object': |
||
3020 | $chk = is_object($data); |
||
3021 | break; |
||
3022 | case 'int': |
||
3023 | $chk = is_int($data); |
||
3024 | break; |
||
3025 | } |
||
3026 | } |
||
3027 | if (!$chk) { |
||
3028 | unset($var); |
||
3029 | return false; |
||
3030 | } |
||
3031 | return $data; |
||
3032 | } |
||
3033 | |||
3034 | /** |
||
3035 | * Call session_write_close() if session is restarted |
||
3036 | * |
||
3037 | * @deprecated |
||
3038 | * @return void |
||
3039 | */ |
||
3040 | public static function sessionWrite() { |
||
3041 | if (session_id()) { |
||
3042 | session_write_close(); |
||
3043 | } |
||
3044 | } |
||
3045 | |||
3046 | /** |
||
3047 | * Return elFinder static variable |
||
3048 | * |
||
3049 | * @param $key |
||
3050 | * @return mixed|null |
||
3051 | */ |
||
3052 | public static function getStaticVar($key) { |
||
3053 | return isset(elFinder::$$key)? elFinder::$$key : null; |
||
3054 | } |
||
3055 | |||
3056 | /** |
||
3057 | * Extend PHP execution time limit |
||
3058 | * |
||
3059 | * @param Int $time |
||
3060 | * @return void |
||
3061 | */ |
||
3062 | public static function extendTimeLimit($time = null) { |
||
3063 | static $defLimit = null; |
||
3064 | if (is_null($defLimit)) { |
||
3065 | $defLimit = ini_get('max_execution_time'); |
||
3066 | } |
||
3067 | if ($defLimit != 0) { |
||
3068 | $time = is_null($time)? $defLimit : max($defLimit, $time); |
||
3069 | set_time_limit($time); |
||
3070 | } |
||
3071 | } |
||
3072 | |||
3073 | } // END class |
||
3074 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.