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 |
||
2 | |||
3 | // Implement similar functionality in PHP 5.2 or 5.3 |
||
4 | // http://php.net/manual/class.recursivecallbackfilteriterator.php#110974 |
||
5 | if (! class_exists('RecursiveCallbackFilterIterator', false)) { |
||
6 | class RecursiveCallbackFilterIterator extends RecursiveFilterIterator { |
||
0 ignored issues
–
show
|
|||
7 | |||
8 | public function __construct ( RecursiveIterator $iterator, $callback ) { |
||
9 | $this->callback = $callback; |
||
0 ignored issues
–
show
The property
callback does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
10 | parent::__construct($iterator); |
||
11 | } |
||
12 | |||
13 | public function accept () { |
||
14 | $callback = $this->callback; |
||
15 | return $callback(parent::current(), parent::key(), parent::getInnerIterator()); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
current() instead of accept() ). Are you sure this is correct? If so, you might want to change this to $this->current() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() It seems like you call parent on a different method (
key() instead of accept() ). Are you sure this is correct? If so, you might want to change this to $this->key() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() It seems like you call parent on a different method (
getInnerIterator() instead of accept() ). Are you sure this is correct? If so, you might want to change this to $this->getInnerIterator() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
16 | } |
||
17 | |||
18 | public function getChildren () { |
||
19 | return new self($this->getInnerIterator()->getChildren(), $this->callback); |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Iterator as the method getChildren() does only exist in the following implementations of said interface: ParentIterator , RecursiveArrayIterator , RecursiveCachingIterator , RecursiveCallbackFilterIterator , RecursiveDirectoryIterator , RecursiveFilterIterator , RecursiveRegexIterator , SimpleXMLIterator , SplFileObject , SplTempFileObject .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
20 | } |
||
21 | } |
||
22 | } |
||
23 | |||
24 | /** |
||
25 | * elFinder driver for local filesystem. |
||
26 | * |
||
27 | * @author Dmitry (dio) Levashov |
||
28 | * @author Troex Nevelin |
||
29 | **/ |
||
30 | class elFinderVolumeLocalFileSystem extends elFinderVolumeDriver { |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
31 | |||
32 | /** |
||
33 | * Driver id |
||
34 | * Must be started from letter and contains [a-z0-9] |
||
35 | * Used as part of volume id |
||
36 | * |
||
37 | * @var string |
||
38 | **/ |
||
39 | protected $driverId = 'l'; |
||
40 | |||
41 | /** |
||
42 | * Required to count total archive files size |
||
43 | * |
||
44 | * @var int |
||
45 | **/ |
||
46 | protected $archiveSize = 0; |
||
47 | |||
48 | /** |
||
49 | * Current query word on doSearch |
||
50 | * |
||
51 | * @var string |
||
52 | **/ |
||
53 | private $doSearchCurrentQuery = ''; |
||
54 | |||
55 | /** |
||
56 | * Constructor |
||
57 | * Extend options with required fields |
||
58 | * |
||
59 | * @return void |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Adding a
@return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.
Adding a Please refer to the PHP core documentation on constructors. ![]() |
|||
60 | * @author Dmitry (dio) Levashov |
||
61 | **/ |
||
62 | public function __construct() { |
||
63 | $this->options['alias'] = ''; // alias to replace root dir name |
||
64 | $this->options['dirMode'] = 0755; // new dirs mode |
||
65 | $this->options['fileMode'] = 0644; // new files mode |
||
66 | $this->options['quarantine'] = '.quarantine'; // quarantine folder name - required to check archive (must be hidden) |
||
67 | $this->options['maxArcFilesSize'] = 0; // max allowed archive files size (0 - no limit) |
||
68 | $this->options['rootCssClass'] = 'elfinder-navbar-root-local'; |
||
69 | } |
||
70 | |||
71 | /*********************************************************************/ |
||
72 | /* INIT AND CONFIGURE */ |
||
73 | /*********************************************************************/ |
||
74 | |||
75 | /** |
||
76 | * Prepare driver before mount volume. |
||
77 | * Return true if volume is ready. |
||
78 | * |
||
79 | * @return bool |
||
80 | **/ |
||
81 | protected function init() { |
||
82 | // Normalize directory separator for windows |
||
83 | if (DIRECTORY_SEPARATOR !== '/') { |
||
84 | foreach(array('path', 'tmbPath', 'tmpPath', 'quarantine') as $key) { |
||
85 | if (!empty($this->options[$key])) { |
||
86 | $this->options[$key] = str_replace('/', DIRECTORY_SEPARATOR, $this->options[$key]); |
||
87 | } |
||
88 | } |
||
89 | } |
||
90 | if (!$cwd = getcwd()) { |
||
91 | return $this->setError('elFinder LocalVolumeDriver requires a result of getcwd().'); |
||
92 | } |
||
93 | // detect systemRoot |
||
94 | if (!isset($this->options['systemRoot'])) { |
||
95 | if ($cwd[0] === $this->separator || $this->root[0] === $this->separator) { |
||
96 | $this->systemRoot = $this->separator; |
||
97 | } else if (preg_match('/^([a-zA-Z]:'.preg_quote($this->separator, '/').')/', $this->root, $m)) { |
||
98 | $this->systemRoot = $m[1]; |
||
99 | } else if (preg_match('/^([a-zA-Z]:'.preg_quote($this->separator, '/').')/', $cwd, $m)) { |
||
100 | $this->systemRoot = $m[1]; |
||
101 | } |
||
102 | } |
||
103 | $this->root = $this->getFullPath($this->root, $cwd); |
||
104 | if (!empty($this->options['startPath'])) { |
||
105 | $this->options['startPath'] = $this->getFullPath($this->options['startPath'], $cwd); |
||
106 | } |
||
107 | |||
108 | if (is_null($this->options['syncChkAsTs'])) { |
||
109 | $this->options['syncChkAsTs'] = true; |
||
110 | } |
||
111 | if (is_null($this->options['syncCheckFunc'])) { |
||
112 | $this->options['syncCheckFunc'] = array($this, 'localFileSystemInotify'); |
||
113 | } |
||
114 | |||
115 | return true; |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Configure after successfull mount. |
||
120 | * |
||
121 | * @return void |
||
122 | * @author Dmitry (dio) Levashov |
||
123 | **/ |
||
124 | protected function configure() { |
||
125 | $root = $this->stat($this->root); |
||
126 | |||
127 | // chek thumbnails path |
||
128 | if ($this->options['tmbPath']) { |
||
129 | $this->options['tmbPath'] = strpos($this->options['tmbPath'], DIRECTORY_SEPARATOR) === false |
||
130 | // tmb path set as dirname under root dir |
||
131 | ? $this->_abspath($this->options['tmbPath']) |
||
132 | // tmb path as full path |
||
133 | : $this->_normpath($this->options['tmbPath']); |
||
134 | } |
||
135 | |||
136 | parent::configure(); |
||
137 | |||
138 | // set $this->tmp by options['tmpPath'] |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
39% 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. ![]() |
|||
139 | View Code Duplication | if (!empty($this->options['tmpPath'])) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
140 | if ((is_dir($this->options['tmpPath']) || @mkdir($this->options['tmpPath'], 0755, true)) && is_writable($this->options['tmpPath'])) { |
||
141 | $this->tmp = $this->options['tmpPath']; |
||
0 ignored issues
–
show
The property
tmp does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
142 | } |
||
143 | } |
||
144 | |||
145 | // if no thumbnails url - try detect it |
||
146 | if ($root['read'] && !$this->tmbURL && $this->URL) { |
||
147 | if (strpos($this->tmbPath, $this->root) === 0) { |
||
148 | $this->tmbURL = $this->URL.str_replace(DIRECTORY_SEPARATOR, '/', substr($this->tmbPath, strlen($this->root)+1)); |
||
149 | if (preg_match("|[^/?&=]$|", $this->tmbURL)) { |
||
150 | $this->tmbURL .= '/'; |
||
151 | } |
||
152 | } |
||
153 | } |
||
154 | |||
155 | // check quarantine dir |
||
156 | $this->quarantine = ''; |
||
0 ignored issues
–
show
The property
quarantine does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
157 | if (!empty($this->options['quarantine'])) { |
||
158 | if (is_dir($this->options['quarantine'])) { |
||
159 | if (is_writable($this->options['quarantine'])) { |
||
160 | $this->quarantine = $this->options['quarantine']; |
||
161 | } |
||
162 | $this->options['quarantine'] = ''; |
||
163 | } else { |
||
164 | $this->quarantine = $this->_abspath($this->options['quarantine']); |
||
165 | if ((!is_dir($this->quarantine) && !$this->_mkdir($this->root, $this->options['quarantine'])) || !is_writable($this->quarantine)) { |
||
0 ignored issues
–
show
The expression
$this->_mkdir($this->roo...>options['quarantine']) 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
![]() |
|||
166 | $this->options['quarantine'] = $this->quarantine = ''; |
||
167 | } |
||
168 | } |
||
169 | } |
||
170 | |||
171 | if (!$this->quarantine) { |
||
172 | $this->archivers['extract'] = array(); |
||
173 | $this->disabled[] = 'extract'; |
||
174 | } |
||
175 | |||
176 | if ($this->options['quarantine']) { |
||
177 | $this->attributes[] = array( |
||
178 | 'pattern' => '~^'.preg_quote(DIRECTORY_SEPARATOR.$this->options['quarantine']).'$~', |
||
179 | 'read' => false, |
||
180 | 'write' => false, |
||
181 | 'locked' => true, |
||
182 | 'hidden' => true |
||
183 | ); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Long pooling sync checker |
||
189 | * This function require server command `inotifywait` |
||
190 | * If `inotifywait` need full path, Please add `define('ELFINER_INOTIFYWAIT_PATH', '/PATH_TO/inotifywait');` into connector.php |
||
191 | * |
||
192 | * @param string $path |
||
193 | * @param int $standby |
||
194 | * @param number $compare |
||
195 | * @return number|bool |
||
196 | */ |
||
197 | public function localFileSystemInotify($path, $standby, $compare) { |
||
198 | if (isset($this->sessionCache['localFileSystemInotify_disable'])) { |
||
199 | return false; |
||
200 | } |
||
201 | $path = realpath($path); |
||
202 | $mtime = filemtime($path); |
||
203 | if ($mtime != $compare) { |
||
204 | return $mtime; |
||
205 | } |
||
206 | $inotifywait = defined('ELFINER_INOTIFYWAIT_PATH')? ELFINER_INOTIFYWAIT_PATH : 'inotifywait'; |
||
207 | $path = escapeshellarg($path); |
||
208 | $standby = max(1, intval($standby)); |
||
209 | $cmd = $inotifywait.' '.$path.' -t '.$standby.' -e moved_to,moved_from,move,create,delete,delete_self'; |
||
210 | $this->procExec($cmd , $o, $r); |
||
211 | if ($r === 0) { |
||
212 | // changed |
||
213 | clearstatcache(); |
||
214 | return filemtime($path); |
||
215 | } else if ($r === 2) { |
||
216 | // not changed (timeout) |
||
217 | return $compare; |
||
218 | } |
||
219 | // error |
||
220 | // cache to $_SESSION |
||
221 | $sessionStart = $this->sessionRestart(); |
||
222 | if ($sessionStart) { |
||
223 | $this->sessionCache['localFileSystemInotify_disable'] = true; |
||
224 | session_write_close(); |
||
225 | } |
||
226 | |||
227 | return false; |
||
228 | } |
||
229 | |||
230 | /*********************************************************************/ |
||
231 | /* FS API */ |
||
232 | /*********************************************************************/ |
||
233 | |||
234 | /*********************** paths/urls *************************/ |
||
235 | |||
236 | /** |
||
237 | * Return parent directory path |
||
238 | * |
||
239 | * @param string $path file path |
||
240 | * @return string |
||
241 | * @author Dmitry (dio) Levashov |
||
242 | **/ |
||
243 | protected function _dirname($path) { |
||
244 | return dirname($path); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * Return file name |
||
249 | * |
||
250 | * @param string $path file path |
||
251 | * @return string |
||
252 | * @author Dmitry (dio) Levashov |
||
253 | **/ |
||
254 | protected function _basename($path) { |
||
255 | return basename($path); |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * Join dir name and file name and retur full path |
||
260 | * |
||
261 | * @param string $dir |
||
262 | * @param string $name |
||
263 | * @return string |
||
264 | * @author Dmitry (dio) Levashov |
||
265 | **/ |
||
266 | protected function _joinPath($dir, $name) { |
||
267 | return rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $name; |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Return normalized path, this works the same as os.path.normpath() in Python |
||
272 | * |
||
273 | * @param string $path path |
||
274 | * @return string |
||
275 | * @author Troex Nevelin |
||
276 | **/ |
||
277 | protected function _normpath($path) { |
||
278 | if (empty($path)) { |
||
279 | return '.'; |
||
280 | } |
||
281 | |||
282 | $changeSep = (DIRECTORY_SEPARATOR !== '/'); |
||
283 | if ($changeSep) { |
||
284 | $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); |
||
285 | } |
||
286 | |||
287 | if (strpos($path, '/') === 0) { |
||
288 | $initial_slashes = true; |
||
289 | } else { |
||
290 | $initial_slashes = false; |
||
291 | } |
||
292 | |||
293 | View Code Duplication | if (($initial_slashes) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
294 | && (strpos($path, '//') === 0) |
||
295 | && (strpos($path, '///') === false)) { |
||
296 | $initial_slashes = 2; |
||
297 | } |
||
298 | |||
299 | $initial_slashes = (int) $initial_slashes; |
||
300 | |||
301 | $comps = explode('/', $path); |
||
302 | $new_comps = array(); |
||
303 | View Code Duplication | foreach ($comps as $comp) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
304 | if (in_array($comp, array('', '.'))) { |
||
305 | continue; |
||
306 | } |
||
307 | |||
308 | if (($comp != '..') |
||
309 | || (!$initial_slashes && !$new_comps) |
||
0 ignored issues
–
show
The expression
$new_comps 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 ![]() |
|||
310 | || ($new_comps && (end($new_comps) == '..'))) { |
||
0 ignored issues
–
show
The expression
$new_comps 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 ![]() |
|||
311 | array_push($new_comps, $comp); |
||
312 | } elseif ($new_comps) { |
||
0 ignored issues
–
show
The expression
$new_comps 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 ![]() |
|||
313 | array_pop($new_comps); |
||
314 | } |
||
315 | } |
||
316 | $comps = $new_comps; |
||
317 | $path = implode('/', $comps); |
||
318 | if ($initial_slashes) { |
||
319 | $path = str_repeat('/', $initial_slashes) . $path; |
||
320 | } |
||
321 | |||
322 | if ($changeSep) { |
||
323 | $path = str_replace('/', DIRECTORY_SEPARATOR, $path); |
||
324 | } |
||
325 | |||
326 | return $path ? $path : '.'; |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * Return file path related to root dir |
||
331 | * |
||
332 | * @param string $path file path |
||
333 | * @return string |
||
334 | * @author Dmitry (dio) Levashov |
||
335 | **/ |
||
336 | View Code Duplication | protected function _relpath($path) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
337 | if ($path === $this->root) { |
||
338 | return ''; |
||
339 | } else { |
||
340 | if (strpos($path, $this->root) === 0) { |
||
341 | return ltrim(substr($path, strlen($this->root)), DIRECTORY_SEPARATOR); |
||
342 | } else { |
||
343 | // for link |
||
344 | return $path; |
||
345 | } |
||
346 | } |
||
347 | } |
||
348 | |||
349 | /** |
||
350 | * Convert path related to root dir into real path |
||
351 | * |
||
352 | * @param string $path file path |
||
353 | * @return string |
||
354 | * @author Dmitry (dio) Levashov |
||
355 | **/ |
||
356 | protected function _abspath($path) { |
||
357 | if ($path === DIRECTORY_SEPARATOR) { |
||
358 | return $this->root; |
||
359 | } else { |
||
360 | if ($path[0] === DIRECTORY_SEPARATOR) { |
||
361 | // for link |
||
362 | return $path; |
||
363 | } else { |
||
364 | return $this->_joinPath($this->root, $path); |
||
365 | } |
||
366 | } |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * Return fake path started from root dir |
||
371 | * |
||
372 | * @param string $path file path |
||
373 | * @return string |
||
374 | * @author Dmitry (dio) Levashov |
||
375 | **/ |
||
376 | protected function _path($path) { |
||
377 | return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path)); |
||
378 | } |
||
379 | |||
380 | /** |
||
381 | * Return true if $path is children of $parent |
||
382 | * |
||
383 | * @param string $path path to check |
||
384 | * @param string $parent parent path |
||
385 | * @return bool |
||
386 | * @author Dmitry (dio) Levashov |
||
387 | **/ |
||
388 | protected function _inpath($path, $parent) { |
||
389 | $cwd = getcwd(); |
||
390 | $real_path = $this->getFullPath($path, $cwd); |
||
391 | $real_parent = $this->getFullPath($parent, $cwd); |
||
392 | if ($real_path && $real_parent) { |
||
393 | return $real_path === $real_parent || strpos($real_path, rtrim($real_parent, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR) === 0; |
||
394 | } |
||
395 | return false; |
||
396 | } |
||
397 | |||
398 | |||
399 | |||
400 | /***************** file stat ********************/ |
||
401 | |||
402 | /** |
||
403 | * Return stat for given path. |
||
404 | * Stat contains following fields: |
||
405 | * - (int) size file size in b. required |
||
406 | * - (int) ts file modification time in unix time. required |
||
407 | * - (string) mime mimetype. required for folders, others - optionally |
||
408 | * - (bool) read read permissions. required |
||
409 | * - (bool) write write permissions. required |
||
410 | * - (bool) locked is object locked. optionally |
||
411 | * - (bool) hidden is object hidden. optionally |
||
412 | * - (string) alias for symlinks - link target path relative to root path. optionally |
||
413 | * - (string) target for symlinks - link target path. optionally |
||
414 | * |
||
415 | * If file does not exists - returns empty array or false. |
||
416 | * |
||
417 | * @param string $path file path |
||
418 | * @return array|false |
||
419 | * @author Dmitry (dio) Levashov |
||
420 | **/ |
||
421 | protected function _stat($path) { |
||
422 | |||
423 | static $statOwner; |
||
424 | if (is_null($statOwner)) { |
||
425 | $statOwner = (!empty($this->options['statOwner'])); |
||
426 | } |
||
427 | |||
428 | $stat = array(); |
||
429 | |||
430 | if (!file_exists($path) && !is_link($path)) { |
||
431 | return $stat; |
||
432 | } |
||
433 | |||
434 | //Verifies the given path is the root or is inside the root. Prevents directory traveral. |
||
435 | if (!$this->_inpath($path, $this->root)) { |
||
436 | return $stat; |
||
437 | } |
||
438 | |||
439 | $gid = $uid = 0; |
||
0 ignored issues
–
show
$uid 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 ![]() $gid 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 ![]() |
|||
440 | $stat['isowner'] = false; |
||
441 | $linkreadable = false; |
||
442 | if ($path != $this->root && is_link($path)) { |
||
443 | if (!($target = $this->readlink($path)) |
||
444 | || $target == $path) { |
||
445 | if (is_null($target)) { |
||
446 | $stat = array(); |
||
447 | return $stat; |
||
448 | } else { |
||
449 | $stat['mime'] = 'symlink-broken'; |
||
450 | $target = readlink($path); |
||
451 | $lstat = lstat($path); |
||
452 | $ostat = $this->getOwnerStat($lstat['uid'], $lstat['gid']); |
||
453 | $linkreadable = !empty($ostat['isowner']); |
||
454 | } |
||
455 | } |
||
456 | $stat['alias'] = $this->_path($target); |
||
457 | $stat['target'] = $target; |
||
458 | } |
||
459 | $size = sprintf('%u', @filesize($path)); |
||
460 | $stat['ts'] = filemtime($path); |
||
461 | if ($statOwner) { |
||
462 | $fstat = stat($path); |
||
463 | $uid = $fstat['uid']; |
||
464 | $gid = $fstat['gid']; |
||
465 | $stat['perm'] = substr((string)decoct($fstat['mode']), -4); |
||
466 | $stat = array_merge($stat, $this->getOwnerStat($uid, $gid)); |
||
467 | } |
||
468 | |||
469 | $dir = is_dir($path); |
||
470 | |||
471 | if (!isset($stat['mime'])) { |
||
472 | $stat['mime'] = $dir ? 'directory' : $this->mimetype($path); |
||
473 | } |
||
474 | //logical rights first |
||
475 | $stat['read'] = ($linkreadable || is_readable($path))? null : false; |
||
476 | $stat['write'] = is_writable($path)? null : false; |
||
477 | |||
478 | if (is_null($stat['read'])) { |
||
479 | $stat['size'] = $dir ? 0 : $size; |
||
480 | } |
||
481 | |||
482 | return $stat; |
||
483 | } |
||
484 | |||
485 | /** |
||
486 | * Get stat `owner`, `group` and `isowner` by `uid` and `gid` |
||
487 | * Sub-fuction of _stat() and _scandir() |
||
488 | * |
||
489 | * @param integer $uid |
||
490 | * @param integer $gid |
||
491 | * @return array stat |
||
492 | */ |
||
493 | protected function getOwnerStat($uid, $gid) { |
||
494 | static $names = null; |
||
495 | static $phpuid = null; |
||
496 | |||
497 | if (is_null($names)) { |
||
498 | $names = array('uid' => array(), 'gid' =>array()); |
||
499 | } |
||
500 | if (is_null($phpuid)) { |
||
501 | if (is_callable('posix_getuid')) { |
||
502 | $phpuid = posix_getuid(); |
||
503 | } else { |
||
504 | $phpuid = 0; |
||
505 | } |
||
506 | } |
||
507 | |||
508 | $stat = array(); |
||
509 | |||
510 | if ($uid) { |
||
511 | $stat['isowner'] = ($phpuid == $uid); |
||
512 | View Code Duplication | if (isset($names['uid'][$uid])) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
513 | $stat['owner'] = $names['uid'][$uid]; |
||
514 | } else if (is_callable('posix_getpwuid')) { |
||
515 | $pwuid = posix_getpwuid($uid); |
||
516 | $stat['owner'] = $names['uid'][$uid] = $pwuid['name']; |
||
517 | } else { |
||
518 | $stat['owner'] = $names['uid'][$uid] = $uid; |
||
519 | } |
||
520 | } |
||
521 | View Code Duplication | if ($gid) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
522 | if (isset($names['gid'][$gid])) { |
||
523 | $stat['group'] = $names['gid'][$gid]; |
||
524 | } else if (is_callable('posix_getgrgid')) { |
||
525 | $grgid = posix_getgrgid($gid); |
||
526 | $stat['group'] = $names['gid'][$gid] = $grgid['name']; |
||
527 | } else { |
||
528 | $stat['group'] = $names['gid'][$gid] = $gid; |
||
529 | } |
||
530 | } |
||
531 | |||
532 | return $stat; |
||
533 | } |
||
534 | |||
535 | /** |
||
536 | * Return true if path is dir and has at least one childs directory |
||
537 | * |
||
538 | * @param string $path dir path |
||
539 | * @return bool |
||
540 | * @author Dmitry (dio) Levashov |
||
541 | **/ |
||
542 | protected function _subdirs($path) { |
||
543 | |||
544 | $dirs = false; |
||
545 | if (is_dir($path)) { |
||
546 | $dirItr = new ParentIterator( |
||
547 | new RecursiveDirectoryIterator($path, |
||
548 | FilesystemIterator::SKIP_DOTS | |
||
549 | (defined('RecursiveDirectoryIterator::FOLLOW_SYMLINKS')? |
||
550 | RecursiveDirectoryIterator::FOLLOW_SYMLINKS : 0) |
||
551 | ) |
||
552 | ); |
||
553 | $dirItr->rewind(); |
||
554 | if ($dirItr->hasChildren()) { |
||
555 | $dirs = true; |
||
556 | $name = $dirItr->getSubPathName(); |
||
557 | while($name) { |
||
558 | if (!$this->attr($path . DIRECTORY_SEPARATOR . $name, 'read', null, true)) { |
||
559 | $dirs = false; |
||
560 | $dirItr->next(); |
||
561 | $name = $dirItr->getSubPathName(); |
||
562 | continue; |
||
563 | } |
||
564 | $dirs = true; |
||
565 | break; |
||
566 | } |
||
567 | } |
||
568 | } |
||
569 | return $dirs; |
||
570 | } |
||
571 | |||
572 | /** |
||
573 | * Return object width and height |
||
574 | * Usualy used for images, but can be realize for video etc... |
||
575 | * |
||
576 | * @param string $path file path |
||
577 | * @param string $mime file mime type |
||
578 | * @return string |
||
579 | * @author Dmitry (dio) Levashov |
||
580 | **/ |
||
581 | protected function _dimensions($path, $mime) { |
||
582 | clearstatcache(); |
||
583 | return strpos($mime, 'image') === 0 && ($s = @getimagesize($path)) !== false |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
The expression
strpos($mime, 'image') =... . 'x' . $s[1] : false; of type string|false adds false to the return on line 583 which is incompatible with the return type declared by the abstract method elFinderVolumeDriver::_dimensions of type string . It seems like you forgot to handle an error condition.
![]() |
|||
584 | ? $s[0].'x'.$s[1] |
||
0 ignored issues
–
show
The variable
$s 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
![]() |
|||
585 | : false; |
||
586 | } |
||
587 | /******************** file/dir content *********************/ |
||
588 | |||
589 | /** |
||
590 | * Return symlink target file |
||
591 | * |
||
592 | * @param string $path link path |
||
593 | * @return string |
||
594 | * @author Dmitry (dio) Levashov |
||
595 | **/ |
||
596 | protected function readlink($path) { |
||
597 | if (!($target = @readlink($path))) { |
||
598 | return null; |
||
599 | } |
||
600 | |||
601 | if (strpos($target, $this->systemRoot) !== 0) { |
||
602 | $target = $this->_joinPath(dirname($path), $target); |
||
603 | } |
||
604 | |||
605 | if (!file_exists($target)) { |
||
606 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by elFinderVolumeLocalFileSystem::readlink of type string .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
607 | } |
||
608 | |||
609 | return $target; |
||
610 | } |
||
611 | |||
612 | /** |
||
613 | * Return files list in directory. |
||
614 | * |
||
615 | * @param string $path dir path |
||
616 | * @return array |
||
617 | * @author Dmitry (dio) Levashov |
||
618 | **/ |
||
619 | protected function _scandir($path) { |
||
620 | $files = array(); |
||
621 | $cache = array(); |
||
622 | $statOwner = (!empty($this->options['statOwner'])); |
||
623 | $dirItr = array(); |
||
624 | try { |
||
625 | $dirItr = new DirectoryIterator($path); |
||
626 | } catch (UnexpectedValueException $e) {} |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
627 | |||
628 | foreach ($dirItr as $file) { |
||
629 | try { |
||
630 | if ($file->isDot()) { continue; } |
||
631 | |||
632 | $files[] = $fpath = $file->getPathname(); |
||
633 | |||
634 | $br = false; |
||
635 | $stat = array(); |
||
636 | |||
637 | $gid = $uid = 0; |
||
638 | $stat['isowner'] = false; |
||
639 | $linkreadable = false; |
||
640 | if ($file->isLink()) { |
||
641 | if (!($target = $this->readlink($fpath)) |
||
642 | || $target == $fpath) { |
||
643 | if (is_null($target)) { |
||
644 | $stat = array(); |
||
645 | $br = true; |
||
646 | } else { |
||
647 | $_path = $fpath; |
||
648 | $stat['mime'] = 'symlink-broken'; |
||
649 | $target = readlink($_path); |
||
650 | $lstat = lstat($_path); |
||
651 | $ostat = $this->getOwnerStat($lstat['uid'], $lstat['gid']); |
||
652 | $linkreadable = !empty($ostat['isowner']); |
||
653 | $dir = false; |
||
654 | $stat['alias'] = $this->_path($target); |
||
655 | $stat['target'] = $target; |
||
656 | } |
||
657 | } else { |
||
658 | $dir = is_dir($target); |
||
659 | $stat['alias'] = $this->_path($target); |
||
660 | $stat['target'] = $target; |
||
661 | $stat['mime'] = $dir ? 'directory' : $this->mimetype($stat['alias']); |
||
662 | } |
||
663 | } else { |
||
664 | $dir = $file->isDir(); |
||
665 | $stat['mime'] = $dir ? 'directory' : $this->mimetype($fpath); |
||
666 | } |
||
667 | $size = sprintf('%u', $file->getSize()); |
||
668 | $stat['ts'] = $file->getMTime(); |
||
669 | if (!$br) { |
||
670 | if ($statOwner && !$linkreadable) { |
||
671 | $uid = $file->getOwner(); |
||
672 | $gid = $file->getGroup(); |
||
673 | $stat['perm'] = substr((string)decoct($file->getPerms()), -4); |
||
674 | $stat = array_merge($stat, $this->getOwnerStat($uid, $gid)); |
||
675 | } |
||
676 | |||
677 | //logical rights first |
||
678 | $stat['read'] = ($linkreadable || $file->isReadable())? null : false; |
||
679 | $stat['write'] = $file->isWritable()? null : false; |
||
680 | |||
681 | if (is_null($stat['read'])) { |
||
682 | $stat['size'] = $dir ? 0 : $size; |
||
0 ignored issues
–
show
The variable
$dir 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
![]() |
|||
683 | } |
||
684 | |||
685 | } |
||
686 | |||
687 | $cache[] = array($fpath, $stat); |
||
688 | } catch (RuntimeException $e) { |
||
689 | continue; |
||
690 | } |
||
691 | } |
||
692 | |||
693 | if ($cache) { |
||
0 ignored issues
–
show
The expression
$cache 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 ![]() |
|||
694 | $cache = $this->convEncOut($cache, false); |
||
695 | foreach($cache as $d) { |
||
696 | $this->updateCache($d[0], $d[1]); |
||
697 | } |
||
698 | } |
||
699 | |||
700 | return $files; |
||
701 | } |
||
702 | |||
703 | /** |
||
704 | * Open file and return file pointer |
||
705 | * |
||
706 | * @param string $path file path |
||
707 | * @param bool $write open file for writing |
||
0 ignored issues
–
show
There is no parameter named
$write . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
708 | * @return resource|false |
||
709 | * @author Dmitry (dio) Levashov |
||
710 | **/ |
||
711 | protected function _fopen($path, $mode='rb') { |
||
712 | return @fopen($path, $mode); |
||
713 | } |
||
714 | |||
715 | /** |
||
716 | * Close opened file |
||
717 | * |
||
718 | * @param resource $fp file pointer |
||
719 | * @return bool |
||
720 | * @author Dmitry (dio) Levashov |
||
721 | **/ |
||
722 | protected function _fclose($fp, $path='') { |
||
723 | return @fclose($fp); |
||
724 | } |
||
725 | |||
726 | /******************** file/dir manipulations *************************/ |
||
727 | |||
728 | /** |
||
729 | * Create dir and return created dir path or false on failed |
||
730 | * |
||
731 | * @param string $path parent dir path |
||
732 | * @param string $name new directory name |
||
733 | * @return string|bool |
||
734 | * @author Dmitry (dio) Levashov |
||
735 | **/ |
||
736 | View Code Duplication | protected function _mkdir($path, $name) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
737 | $path = $this->_joinPath($path, $name); |
||
738 | |||
739 | if (@mkdir($path)) { |
||
740 | @chmod($path, $this->options['dirMode']); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
741 | clearstatcache(); |
||
742 | return $path; |
||
743 | } |
||
744 | |||
745 | return false; |
||
746 | } |
||
747 | |||
748 | /** |
||
749 | * Create file and return it's path or false on failed |
||
750 | * |
||
751 | * @param string $path parent dir path |
||
752 | * @param string $name new file name |
||
753 | * @return string|bool |
||
754 | * @author Dmitry (dio) Levashov |
||
755 | **/ |
||
756 | View Code Duplication | protected function _mkfile($path, $name) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
757 | $path = $this->_joinPath($path, $name); |
||
758 | |||
759 | if (($fp = @fopen($path, 'w'))) { |
||
760 | @fclose($fp); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
761 | @chmod($path, $this->options['fileMode']); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
762 | clearstatcache(); |
||
763 | return $path; |
||
764 | } |
||
765 | return false; |
||
766 | } |
||
767 | |||
768 | /** |
||
769 | * Create symlink |
||
770 | * |
||
771 | * @param string $source file to link to |
||
772 | * @param string $targetDir folder to create link in |
||
773 | * @param string $name symlink name |
||
774 | * @return bool |
||
775 | * @author Dmitry (dio) Levashov |
||
776 | **/ |
||
777 | protected function _symlink($source, $targetDir, $name) { |
||
778 | return @symlink($source, $this->_joinPath($targetDir, $name)); |
||
779 | } |
||
780 | |||
781 | /** |
||
782 | * Copy file into another file |
||
783 | * |
||
784 | * @param string $source source file path |
||
785 | * @param string $targetDir target directory path |
||
786 | * @param string $name new file name |
||
787 | * @return bool |
||
788 | * @author Dmitry (dio) Levashov |
||
789 | **/ |
||
790 | protected function _copy($source, $targetDir, $name) { |
||
791 | $ret = copy($source, $this->_joinPath($targetDir, $name)); |
||
792 | $ret && clearstatcache(); |
||
793 | return $ret; |
||
794 | } |
||
795 | |||
796 | /** |
||
797 | * Move file into another parent dir. |
||
798 | * Return new file path or false. |
||
799 | * |
||
800 | * @param string $source source file path |
||
801 | * @param string $target target dir path |
||
0 ignored issues
–
show
There is no parameter named
$target . Did you maybe mean $targetDir ?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit. Consider the following example. The parameter /**
* @param array $germany
* @param array $ireland
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was changed, but the annotation was not. ![]() |
|||
802 | * @param string $name file name |
||
803 | * @return string|bool |
||
804 | * @author Dmitry (dio) Levashov |
||
805 | **/ |
||
806 | protected function _move($source, $targetDir, $name) { |
||
807 | $target = $this->_joinPath($targetDir, $name); |
||
808 | $ret = @rename($source, $target) ? $target : false; |
||
809 | $ret && clearstatcache(); |
||
0 ignored issues
–
show
The expression
$ret of type string|false is loosely compared to true ; 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
![]() |
|||
810 | return $ret; |
||
811 | } |
||
812 | |||
813 | /** |
||
814 | * Remove file |
||
815 | * |
||
816 | * @param string $path file path |
||
817 | * @return bool |
||
818 | * @author Dmitry (dio) Levashov |
||
819 | **/ |
||
820 | protected function _unlink($path) { |
||
821 | $ret = @unlink($path); |
||
822 | $ret && clearstatcache(); |
||
823 | return $ret; |
||
824 | } |
||
825 | |||
826 | /** |
||
827 | * Remove dir |
||
828 | * |
||
829 | * @param string $path dir path |
||
830 | * @return bool |
||
831 | * @author Dmitry (dio) Levashov |
||
832 | **/ |
||
833 | protected function _rmdir($path) { |
||
834 | $ret = @rmdir($path); |
||
835 | $ret && clearstatcache(); |
||
836 | return $ret; |
||
837 | } |
||
838 | |||
839 | /** |
||
840 | * Create new file and write into it from file pointer. |
||
841 | * Return new file path or false on error. |
||
842 | * |
||
843 | * @param resource $fp file pointer |
||
844 | * @param string $dir target dir path |
||
845 | * @param string $name file name |
||
846 | * @param array $stat file stat (required by some virtual fs) |
||
847 | * @return bool|string |
||
848 | * @author Dmitry (dio) Levashov |
||
849 | **/ |
||
850 | protected function _save($fp, $dir, $name, $stat) { |
||
851 | $path = $this->_joinPath($dir, $name); |
||
852 | |||
853 | $meta = stream_get_meta_data($fp); |
||
854 | $uri = isset($meta['uri'])? $meta['uri'] : ''; |
||
855 | if ($uri && @is_file($uri)) { |
||
856 | fclose($fp); |
||
857 | $isCmdPaste = ($this->ARGS['cmd'] === 'paste'); |
||
858 | $isCmdCopy = ($isCmdPaste && empty($this->ARGS['cut'])); |
||
859 | if (($isCmdCopy || !@rename($uri, $path)) && !@copy($uri, $path)) { |
||
860 | return false; |
||
861 | } |
||
862 | // re-create the source file for remove processing of paste command |
||
863 | $isCmdPaste && !$isCmdCopy && touch($uri); |
||
864 | } else { |
||
865 | if (@file_put_contents($path, $fp, LOCK_EX) === false) { |
||
866 | return false; |
||
867 | } |
||
868 | } |
||
869 | |||
870 | @chmod($path, $this->options['fileMode']); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
871 | clearstatcache(); |
||
872 | return $path; |
||
873 | } |
||
874 | |||
875 | /** |
||
876 | * Get file contents |
||
877 | * |
||
878 | * @param string $path file path |
||
879 | * @return string|false |
||
880 | * @author Dmitry (dio) Levashov |
||
881 | **/ |
||
882 | protected function _getContents($path) { |
||
883 | return file_get_contents($path); |
||
884 | } |
||
885 | |||
886 | /** |
||
887 | * Write a string to a file |
||
888 | * |
||
889 | * @param string $path file path |
||
890 | * @param string $content new file content |
||
891 | * @return bool |
||
892 | * @author Dmitry (dio) Levashov |
||
893 | **/ |
||
894 | protected function _filePutContents($path, $content) { |
||
895 | if (@file_put_contents($path, $content, LOCK_EX) !== false) { |
||
896 | clearstatcache(); |
||
897 | return true; |
||
898 | } |
||
899 | return false; |
||
900 | } |
||
901 | |||
902 | /** |
||
903 | * Detect available archivers |
||
904 | * |
||
905 | * @return void |
||
906 | **/ |
||
907 | protected function _checkArchivers() { |
||
908 | $this->archivers = $this->getArchivers(); |
||
909 | return; |
||
910 | } |
||
911 | |||
912 | /** |
||
913 | * chmod availability |
||
914 | * |
||
915 | * @return bool |
||
916 | **/ |
||
917 | protected function _chmod($path, $mode) { |
||
918 | $modeOct = is_string($mode) ? octdec($mode) : octdec(sprintf("%04o",$mode)); |
||
919 | $ret = @chmod($path, $modeOct); |
||
920 | $ret && clearstatcache(); |
||
921 | return $ret; |
||
922 | } |
||
923 | |||
924 | /** |
||
925 | * Recursive symlinks search |
||
926 | * |
||
927 | * @param string $path file/dir path |
||
928 | * @return bool |
||
929 | * @author Dmitry (dio) Levashov |
||
930 | **/ |
||
931 | protected function _findSymlinks($path) { |
||
932 | if (is_link($path)) { |
||
933 | return true; |
||
934 | } |
||
935 | |||
936 | if (is_dir($path)) { |
||
937 | foreach (scandir($path) as $name) { |
||
938 | if ($name != '.' && $name != '..') { |
||
939 | $p = $path.DIRECTORY_SEPARATOR.$name; |
||
940 | if (is_link($p) || !$this->nameAccepted($name) |
||
941 | || |
||
942 | (($mimeByName = elFinderVolumeDriver::mimetypeInternalDetect($name)) && $mimeByName !== 'unknown' && !$this->allowPutMime($mimeByName))) { |
||
943 | $this->setError(elFinder::ERROR_SAVE, $name); |
||
944 | return true; |
||
945 | } |
||
946 | if (is_dir($p) && $this->_findSymlinks($p)) { |
||
947 | return true; |
||
948 | } elseif (is_file($p)) { |
||
949 | $this->archiveSize += sprintf('%u', filesize($p)); |
||
950 | } |
||
951 | } |
||
952 | } |
||
953 | } else { |
||
954 | |||
955 | $this->archiveSize += sprintf('%u', filesize($path)); |
||
956 | } |
||
957 | |||
958 | return false; |
||
959 | } |
||
960 | |||
961 | /** |
||
962 | * Extract files from archive |
||
963 | * |
||
964 | * @param string $path archive path |
||
965 | * @param array $arc archiver command and arguments (same as in $this->archivers) |
||
966 | * @return true |
||
967 | * @author Dmitry (dio) Levashov, |
||
968 | * @author Alexey Sukhotin |
||
969 | **/ |
||
970 | protected function _extract($path, $arc) { |
||
971 | |||
972 | if ($this->quarantine) { |
||
973 | |||
974 | $dir = $this->quarantine.DIRECTORY_SEPARATOR.md5(basename($path).mt_rand()); |
||
975 | $archive = $dir.DIRECTORY_SEPARATOR.basename($path); |
||
976 | |||
977 | if (!@mkdir($dir)) { |
||
978 | return false; |
||
979 | } |
||
980 | |||
981 | // insurance unexpected shutdown |
||
982 | register_shutdown_function(array($this, 'rmdirRecursive'), realpath($dir)); |
||
983 | |||
984 | chmod($dir, 0777); |
||
985 | |||
986 | // copy in quarantine |
||
987 | if (!copy($path, $archive)) { |
||
988 | return false; |
||
989 | } |
||
990 | |||
991 | // extract in quarantine |
||
992 | $this->unpackArchive($archive, $arc); |
||
993 | |||
994 | // get files list |
||
995 | $ls = array(); |
||
996 | foreach (scandir($dir) as $i => $name) { |
||
997 | if ($name != '.' && $name != '..') { |
||
998 | $ls[] = $name; |
||
999 | } |
||
1000 | } |
||
1001 | |||
1002 | // no files - extract error ? |
||
1003 | if (empty($ls)) { |
||
1004 | return false; |
||
1005 | } |
||
1006 | |||
1007 | $this->archiveSize = 0; |
||
1008 | |||
1009 | // find symlinks |
||
1010 | $symlinks = $this->_findSymlinks($dir); |
||
1011 | |||
1012 | View Code Duplication | if ($symlinks) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1013 | $this->delTree($dir); |
||
1014 | return $this->setError(array_merge($this->error, array(elFinder::ERROR_ARC_SYMLINKS))); |
||
1015 | } |
||
1016 | |||
1017 | // check max files size |
||
1018 | View Code Duplication | if ($this->options['maxArcFilesSize'] > 0 && $this->options['maxArcFilesSize'] < $this->archiveSize) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1019 | $this->delTree($dir); |
||
1020 | return $this->setError(elFinder::ERROR_ARC_MAXSIZE); |
||
1021 | } |
||
1022 | |||
1023 | $extractTo = $this->extractToNewdir; // 'auto', ture or false |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
45% 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. ![]() |
|||
1024 | |||
1025 | // archive contains one item - extract in archive dir |
||
1026 | $name = ''; |
||
1027 | $src = $dir.DIRECTORY_SEPARATOR.$ls[0]; |
||
1028 | if (($extractTo === 'auto' || !$extractTo) && count($ls) === 1 && is_file($src)) { |
||
0 ignored issues
–
show
|
|||
1029 | $name = $ls[0]; |
||
1030 | } else if ($extractTo === 'auto' || $extractTo) { |
||
0 ignored issues
–
show
|
|||
1031 | // for several files - create new directory |
||
1032 | // create unique name for directory |
||
1033 | $src = $dir; |
||
1034 | $name = basename($path); |
||
1035 | View Code Duplication | if (preg_match('/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/i', $name, $m)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
1036 | $name = substr($name, 0, strlen($name)-strlen($m[0])); |
||
1037 | } |
||
1038 | $test = dirname($path).DIRECTORY_SEPARATOR.$name; |
||
1039 | if (file_exists($test) || is_link($test)) { |
||
1040 | $name = $this->uniqueName(dirname($path), $name, '-', false); |
||
1041 | } |
||
1042 | } |
||
1043 | |||
1044 | if ($name !== '') { |
||
1045 | $result = dirname($path).DIRECTORY_SEPARATOR.$name; |
||
1046 | |||
1047 | if (! @rename($src, $result)) { |
||
1048 | $this->delTree($dir); |
||
1049 | return false; |
||
1050 | } |
||
1051 | } else { |
||
1052 | $dstDir = dirname($path); |
||
1053 | $res = false; |
||
0 ignored issues
–
show
$res 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 ![]() |
|||
1054 | $result = array(); |
||
1055 | foreach($ls as $name) { |
||
1056 | $target = $dstDir.DIRECTORY_SEPARATOR.$name; |
||
1057 | if (is_dir($target)) { |
||
1058 | $this->delTree($target); |
||
1059 | } |
||
1060 | if (@rename($dir.DIRECTORY_SEPARATOR.$name, $target)) { |
||
1061 | $result[] = $target; |
||
1062 | } |
||
1063 | } |
||
1064 | if (!$result) { |
||
0 ignored issues
–
show
The expression
$result 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 ![]() |
|||
1065 | $this->delTree($dir); |
||
1066 | return false; |
||
1067 | } |
||
1068 | } |
||
1069 | |||
1070 | is_dir($dir) && $this->delTree($dir); |
||
1071 | |||
1072 | return (is_array($result) || file_exists($result)) ? $result : false; |
||
0 ignored issues
–
show
The return type of
return is_array($result)...ult) ? $result : false; (array|string|false ) is incompatible with the return type declared by the abstract method elFinderVolumeDriver::_extract of type boolean .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
1073 | } |
||
1074 | } |
||
1075 | |||
1076 | /** |
||
1077 | * Create archive and return its path |
||
1078 | * |
||
1079 | * @param string $dir target dir |
||
1080 | * @param array $files files names list |
||
1081 | * @param string $name archive name |
||
1082 | * @param array $arc archiver options |
||
1083 | * @return string|bool |
||
1084 | * @author Dmitry (dio) Levashov, |
||
1085 | * @author Alexey Sukhotin |
||
1086 | **/ |
||
1087 | protected function _archive($dir, $files, $name, $arc) { |
||
1088 | return $this->makeArchive($dir, $files, $name, $arc); |
||
1089 | } |
||
1090 | |||
1091 | /******************** Over write functions *************************/ |
||
1092 | |||
1093 | /** |
||
1094 | * File path of local server side work file path |
||
1095 | * |
||
1096 | * @param string $path |
||
1097 | * @return string |
||
1098 | * @author Naoki Sawada |
||
1099 | */ |
||
1100 | protected function getWorkFile($path) { |
||
1101 | return $path; |
||
1102 | } |
||
1103 | |||
1104 | /** |
||
1105 | * Delete dirctory trees |
||
1106 | * |
||
1107 | * @param string $localpath path need convert encoding to server encoding |
||
1108 | * @return boolean |
||
1109 | * @author Naoki Sawada |
||
1110 | */ |
||
1111 | protected function delTree($localpath) { |
||
1112 | return $this->rmdirRecursive($localpath); |
||
1113 | } |
||
1114 | |||
1115 | /******************** Over write (Optimized) functions *************************/ |
||
1116 | |||
1117 | /** |
||
1118 | * Recursive files search |
||
1119 | * |
||
1120 | * @param string $path dir path |
||
1121 | * @param string $q search string |
||
1122 | * @param array $mimes |
||
1123 | * @return array |
||
1124 | * @author Dmitry (dio) Levashov |
||
1125 | * @author Naoki Sawada |
||
1126 | **/ |
||
1127 | protected function doSearch($path, $q, $mimes) { |
||
1128 | if ($this->encoding) { |
||
1129 | // non UTF-8 use elFinderVolumeDriver::doSearch() |
||
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. ![]() |
|||
1130 | return parent::doSearch($path, $q, $mimes); |
||
1131 | } |
||
1132 | |||
1133 | $this->doSearchCurrentQuery = $q; |
||
1134 | $match = array(); |
||
1135 | try { |
||
1136 | $iterator = new RecursiveIteratorIterator( |
||
1137 | new RecursiveCallbackFilterIterator( |
||
1138 | new RecursiveDirectoryIterator($path, |
||
1139 | FilesystemIterator::KEY_AS_PATHNAME | |
||
1140 | FilesystemIterator::SKIP_DOTS | |
||
1141 | (defined('RecursiveDirectoryIterator::FOLLOW_SYMLINKS')? |
||
1142 | RecursiveDirectoryIterator::FOLLOW_SYMLINKS : 0) |
||
1143 | ), |
||
1144 | array($this, 'localFileSystemSearchIteratorFilter') |
||
1145 | ), |
||
1146 | RecursiveIteratorIterator::SELF_FIRST, |
||
1147 | RecursiveIteratorIterator::CATCH_GET_CHILD |
||
1148 | ); |
||
1149 | foreach ($iterator as $key => $node) { |
||
1150 | if ($node->isDir()) { |
||
1151 | if ($this->stripos($node->getFilename(), $q) !== false) { |
||
1152 | $match[] = $key; |
||
1153 | } |
||
1154 | } else { |
||
1155 | $match[] = $key; |
||
1156 | } |
||
1157 | } |
||
1158 | } catch (Exception $e) {} |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
1159 | |||
1160 | $result = array(); |
||
1161 | |||
1162 | if ($match) { |
||
0 ignored issues
–
show
The expression
$match 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 ![]() |
|||
1163 | foreach($match as $p) { |
||
1164 | $stat = $this->stat($p); |
||
1165 | |||
1166 | if (!$stat) { // invalid links |
||
0 ignored issues
–
show
The expression
$stat 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 ![]() |
|||
1167 | continue; |
||
1168 | } |
||
1169 | |||
1170 | if (!empty($stat['hidden']) || !$this->mimeAccepted($stat['mime'], $mimes)) { |
||
1171 | continue; |
||
1172 | } |
||
1173 | |||
1174 | $name = $stat['name']; |
||
0 ignored issues
–
show
$name 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 ![]() |
|||
1175 | |||
1176 | if ((!$mimes || $stat['mime'] !== 'directory')) { |
||
0 ignored issues
–
show
The expression
$mimes 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 ![]() |
|||
1177 | $stat['path'] = $this->path($stat['hash']); |
||
1178 | if ($this->URL && !isset($stat['url'])) { |
||
1179 | $path = str_replace(DIRECTORY_SEPARATOR, '/', substr($p, strlen($this->root) + 1)); |
||
1180 | $stat['url'] = $this->URL . $path; |
||
1181 | } |
||
1182 | |||
1183 | $result[] = $stat; |
||
1184 | } |
||
1185 | } |
||
1186 | } |
||
1187 | |||
1188 | return $result; |
||
1189 | } |
||
1190 | |||
1191 | /******************** Original local functions *************************/ |
||
1192 | |||
1193 | public function localFileSystemSearchIteratorFilter($file, $key, $iterator) { |
||
1194 | if ($iterator->hasChildren()) { |
||
1195 | return (bool)$this->attr($key, 'read', null, true); |
||
1196 | } |
||
1197 | return ($this->stripos($file->getFilename(), $this->doSearchCurrentQuery) === false)? false : true; |
||
1198 | } |
||
1199 | |||
1200 | } // END class |
||
1201 | |||
1202 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.