Completed
Push — 2.x ( 80fc60...396f01 )
by Naoki
03:49
created

elFinderVolumeLocalFileSystem::getWorkFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/**
4
 * elFinder driver for local filesystem.
5
 *
6
 * @author Dmitry (dio) Levashov
7
 * @author Troex Nevelin
8
 **/
9
class elFinderVolumeLocalFileSystem extends elFinderVolumeDriver {
1 ignored issue
show
Coding Style Compatibility introduced by
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.

Loading history...
Coding Style introduced by
As per PSR2, the opening brace for this class should be on a new line.
Loading history...
10
	
11
	/**
12
	 * Driver id
13
	 * Must be started from letter and contains [a-z0-9]
14
	 * Used as part of volume id
15
	 *
16
	 * @var string
17
	 **/
18
	protected $driverId = 'l';
19
	
20
	/**
21
	 * Required to count total archive files size
22
	 *
23
	 * @var int
24
	 **/
25
	protected $archiveSize = 0;
26
	
27
	/**
28
	 * Constructor
29
	 * Extend options with required fields
30
	 *
31
	 * @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 @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
32
	 * @author Dmitry (dio) Levashov
33
	 **/
34
	public function __construct() {
35
		$this->options['alias']    = '';              // alias to replace root dir name
36
		$this->options['dirMode']  = 0755;            // new dirs mode
37
		$this->options['fileMode'] = 0644;            // new files mode
38
		$this->options['quarantine'] = '.quarantine';  // quarantine folder name - required to check archive (must be hidden)
39
		$this->options['maxArcFilesSize'] = 0;        // max allowed archive files size (0 - no limit)
40
		$this->options['rootCssClass'] = 'elfinder-navbar-root-local';
41
	}
42
	
43
	/*********************************************************************/
44
	/*                        INIT AND CONFIGURE                         */
45
	/*********************************************************************/
46
	
47
	/**
48
	 * Prepare driver before mount volume.
49
	 * Return true if volume is ready.
50
	 *
51
	 * @return bool
52
	 **/
53
	protected function init() {
54
		// Normalize directory separator for windows
55
		if (DIRECTORY_SEPARATOR !== '/') {
56
			foreach(array('path', 'tmpPath', 'quarantine') as $key) {
57
				if ($this->options[$key]) {
58
					$this->options[$key] = str_replace('/', DIRECTORY_SEPARATOR, $this->options[$key]);
59
				}
60
			}
61
		}
62
		if (!$cwd = getcwd()) {
63
			return $this->setError('elFinder LocalVolumeDriver requires a result of getcwd().');
64
		}
65
		// detect systemRoot
66
		if (!isset($this->options['systemRoot'])) {
67
			if ($cwd[0] === $this->separator || $this->root[0] === $this->separator) {
68
				$this->systemRoot = $this->separator;
69
			} else if (preg_match('/^([a-zA-Z]:'.preg_quote($this->separator, '/').')/', $this->root, $m)) {
70
				$this->systemRoot = $m[1];
71
			} else if (preg_match('/^([a-zA-Z]:'.preg_quote($this->separator, '/').')/', $cwd, $m)) {
72
				$this->systemRoot = $m[1];
73
			}
74
		}
75
		$this->root = $this->getFullPath($this->root, $cwd);
76
		return true;
77
	}
78
	
79
	/**
80
	 * Configure after successfull mount.
81
	 *
82
	 * @return void
83
	 * @author Dmitry (dio) Levashov
84
	 **/
85
	protected function configure() {
86
		$root = $this->stat($this->root);
87
		
88
		// chek thumbnails path
89
		if ($this->options['tmbPath']) {
90
			$this->options['tmbPath'] = strpos($this->options['tmbPath'], DIRECTORY_SEPARATOR) === false
91
				// tmb path set as dirname under root dir
92
				? $this->_abspath($this->options['tmbPath'])
93
				// tmb path as full path
94
				: $this->_normpath($this->options['tmbPath']);
95
		}
96
97
		parent::configure();
98
		
99
		// if no thumbnails url - try detect it
100
		if ($root['read'] && !$this->tmbURL && $this->URL) {
101
			if (strpos($this->tmbPath, $this->root) === 0) {
102
				$this->tmbURL = $this->URL.str_replace(DIRECTORY_SEPARATOR, '/', substr($this->tmbPath, strlen($this->root)+1));
103
				if (preg_match("|[^/?&=]$|", $this->tmbURL)) {
104
					$this->tmbURL .= '/';
105
				}
106
			}
107
		}
108
109
		// check quarantine dir
110
		$this->quarantine = '';
0 ignored issues
show
Bug introduced by
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;
Loading history...
111
		if (!empty($this->options['quarantine'])) {
112
			if (is_dir($this->options['quarantine'])) {
113
				if (is_writable($this->options['quarantine'])) {
114
					$this->quarantine = $this->options['quarantine'];
115
				}
116
				$this->options['quarantine'] = '';
117
			} else {
118
				$this->quarantine = $this->_abspath($this->options['quarantine']);
119
				if ((!is_dir($this->quarantine) && !$this->_mkdir($this->root, $this->options['quarantine'])) || !is_writable($this->quarantine)) {
0 ignored issues
show
Bug Best Practice introduced by
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 ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
120
					$this->options['quarantine'] = $this->quarantine = '';
121
				}
122
			}
123
		}
124
		
125
		if (!$this->quarantine) {
126
			$this->archivers['extract'] = array();
127
			$this->disabled[] = 'extract';
128
		}
129
		
130
		if ($this->options['quarantine']) {
131
			$this->attributes[] = array(
132
					'pattern' => '~^'.preg_quote(DIRECTORY_SEPARATOR.$this->options['quarantine']).'$~',
133
					'read'    => false,
134
					'write'   => false,
135
					'locked'  => true,
136
					'hidden'  => true
137
			);
138
		}
139
	}
140
	
141
	/*********************************************************************/
142
	/*                               FS API                              */
143
	/*********************************************************************/
144
145
	/*********************** paths/urls *************************/
146
	
147
	/**
148
	 * Return parent directory path
149
	 *
150
	 * @param  string  $path  file path
151
	 * @return string
152
	 * @author Dmitry (dio) Levashov
153
	 **/
154
	protected function _dirname($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_dirname" should not be prefixed with an underscore to indicate visibility
Loading history...
155
		return dirname($path);
156
	}
157
158
	/**
159
	 * Return file name
160
	 *
161
	 * @param  string  $path  file path
162
	 * @return string
163
	 * @author Dmitry (dio) Levashov
164
	 **/
165
	protected function _basename($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_basename" should not be prefixed with an underscore to indicate visibility
Loading history...
166
		return basename($path);
167
	}
168
169
	/**
170
	 * Join dir name and file name and retur full path
171
	 *
172
	 * @param  string  $dir
173
	 * @param  string  $name
174
	 * @return string
175
	 * @author Dmitry (dio) Levashov
176
	 **/
177
	protected function _joinPath($dir, $name) {
1 ignored issue
show
Coding Style introduced by
Method name "_joinPath" should not be prefixed with an underscore to indicate visibility
Loading history...
178
		return rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $name;
179
	}
180
	
181
	/**
182
	 * Return normalized path, this works the same as os.path.normpath() in Python
183
	 *
184
	 * @param  string  $path  path
185
	 * @return string
186
	 * @author Troex Nevelin
187
	 **/
188
	protected function _normpath($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_normpath" should not be prefixed with an underscore to indicate visibility
Loading history...
189
		if (empty($path)) {
190
			return '.';
191
		}
192
		
193
		$changeSep = (DIRECTORY_SEPARATOR !== '/');
194
		if ($changeSep) {
195
			$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
196
		}
197
198
		if (strpos($path, '/') === 0) {
199
			$initial_slashes = true;
200
		} else {
201
			$initial_slashes = false;
202
		}
203
			
204 View Code Duplication
		if (($initial_slashes) 
0 ignored issues
show
Duplication introduced by
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.

Loading history...
205
		&& (strpos($path, '//') === 0) 
206
		&& (strpos($path, '///') === false)) {
207
			$initial_slashes = 2;
208
		}
209
			
210
		$initial_slashes = (int) $initial_slashes;
211
212
		$comps = explode('/', $path);
213
		$new_comps = array();
214 View Code Duplication
		foreach ($comps as $comp) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
215
			if (in_array($comp, array('', '.'))) {
216
				continue;
217
			}
218
				
219
			if (($comp != '..') 
220
			|| (!$initial_slashes && !$new_comps) 
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
221
			|| ($new_comps && (end($new_comps) == '..'))) {
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
222
				array_push($new_comps, $comp);
223
			} elseif ($new_comps) {
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
224
				array_pop($new_comps);
225
			}
226
		}
227
		$comps = $new_comps;
228
		$path = implode('/', $comps);
229
		if ($initial_slashes) {
230
			$path = str_repeat('/', $initial_slashes) . $path;
231
		}
232
		
233
		if ($changeSep) {
234
			$path = str_replace('/', DIRECTORY_SEPARATOR, $path);
235
		}
236
		
237
		return $path ? $path : '.';
238
	}
239
	
240
	/**
241
	 * Return file path related to root dir
242
	 *
243
	 * @param  string  $path  file path
244
	 * @return string
245
	 * @author Dmitry (dio) Levashov
246
	 **/
247 View Code Duplication
	protected function _relpath($path) {
1 ignored issue
show
Duplication introduced by
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.

Loading history...
Coding Style introduced by
Method name "_relpath" should not be prefixed with an underscore to indicate visibility
Loading history...
248
		if ($path === $this->root) {
249
			return '';
250
		} else {
251
			if (strpos($path, $this->root) === 0) {
252
				return ltrim(substr($path, strlen($this->root)), DIRECTORY_SEPARATOR);
253
			} else {
254
				// for link
255
				return $path;
256
			}
257
		}
258
	}
259
	
260
	/**
261
	 * Convert path related to root dir into real path
262
	 *
263
	 * @param  string  $path  file path
264
	 * @return string
265
	 * @author Dmitry (dio) Levashov
266
	 **/
267
	protected function _abspath($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_abspath" should not be prefixed with an underscore to indicate visibility
Loading history...
268
		if ($path === DIRECTORY_SEPARATOR) {
269
			return $this->root;
270
		} else {
271
			if ($path[0] === DIRECTORY_SEPARATOR) {
272
				// for link
273
				return $path;
274
			} else {
275
				return $this->_joinPath($this->root, $path);
276
			}
277
		}
278
	}
279
	
280
	/**
281
	 * Return fake path started from root dir
282
	 *
283
	 * @param  string  $path  file path
284
	 * @return string
285
	 * @author Dmitry (dio) Levashov
286
	 **/
287
	protected function _path($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_path" should not be prefixed with an underscore to indicate visibility
Loading history...
288
		return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
289
	}
290
	
291
	/**
292
	 * Return true if $path is children of $parent
293
	 *
294
	 * @param  string  $path    path to check
295
	 * @param  string  $parent  parent path
296
	 * @return bool
297
	 * @author Dmitry (dio) Levashov
298
	 **/
299
	protected function _inpath($path, $parent) {
1 ignored issue
show
Coding Style introduced by
Method name "_inpath" should not be prefixed with an underscore to indicate visibility
Loading history...
300
		$cwd = getcwd();
301
		$real_path   = $this->getFullPath($path,   $cwd);
302
		$real_parent = $this->getFullPath($parent, $cwd);
303
		if ($real_path && $real_parent) {
304
			return $real_path === $real_parent || strpos($real_path, rtrim($real_parent, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR) === 0;
305
		}
306
		return false;
307
	}
308
	
309
	
310
	
311
	/***************** file stat ********************/
312
313
	/**
314
	 * Return stat for given path.
315
	 * Stat contains following fields:
316
	 * - (int)    size    file size in b. required
317
	 * - (int)    ts      file modification time in unix time. required
318
	 * - (string) mime    mimetype. required for folders, others - optionally
319
	 * - (bool)   read    read permissions. required
320
	 * - (bool)   write   write permissions. required
321
	 * - (bool)   locked  is object locked. optionally
322
	 * - (bool)   hidden  is object hidden. optionally
323
	 * - (string) alias   for symlinks - link target path relative to root path. optionally
324
	 * - (string) target  for symlinks - link target path. optionally
325
	 *
326
	 * If file does not exists - returns empty array or false.
327
	 *
328
	 * @param  string  $path    file path 
329
	 * @return array|false
330
	 * @author Dmitry (dio) Levashov
331
	 **/
332
	protected function _stat($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_stat" should not be prefixed with an underscore to indicate visibility
Loading history...
333
		
334
		static $statOwner;
335
		if (is_null($statOwner)) {
1 ignored issue
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
336
			$statOwner = (!empty($this->options['statOwner']));
337
		}
338
		
339
		$stat = array();
340
341
		if (!file_exists($path) && !is_link($path)) {
342
			return $stat;
343
		}
344
345
		//Verifies the given path is the root or is inside the root. Prevents directory traveral.
346
		if (!$this->_inpath($path, $this->root)) {
347
			return $stat;
348
		}
349
350
		$gid = $uid = 0;
0 ignored issues
show
Unused Code introduced by
$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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Unused Code introduced by
$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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
351
		$stat['isowner'] = false;
352
		$linkreadable = false;
353
		if ($path != $this->root && is_link($path)) {
354
			if (!($target = $this->readlink($path))
355
			|| $target == $path) {
356
				if (is_null($target)) {
1 ignored issue
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
357
					$stat = array();
358
					return $stat;
359
				} else {
360
					$stat['mime']  = 'symlink-broken';
361
					$target = readlink($path);
362
					$lstat = lstat($path);
363
					$ostat = $this->getOwnerStat($lstat['uid'], $lstat['gid']);
364
					$linkreadable = !empty($ostat['isowner']);
365
				}
366
			}
367
			$stat['alias'] = $this->_path($target);
368
			$stat['target'] = $target;
369
		}
370
		$size = sprintf('%u', @filesize($path));
371
		$stat['ts'] = filemtime($path);
372
		if ($statOwner) {
373
			$fstat = stat($path);
374
			$uid = $fstat['uid'];
375
			$gid = $fstat['gid'];
376
			$stat['perm'] = substr((string)decoct($fstat['mode']), -4);
377
			$stat = array_merge($stat, $this->getOwnerStat($uid, $gid));
378
		}
379
		
380
		$dir = is_dir($path);
381
		
382
		if (!isset($stat['mime'])) {
383
			$stat['mime'] = $dir ? 'directory' : $this->mimetype($path);
384
		}
385
		//logical rights first
386
		$stat['read'] = ($linkreadable || is_readable($path))? null : false;
387
		$stat['write'] = is_writable($path)? null : false;
388
389
		if (is_null($stat['read'])) {
1 ignored issue
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
390
			$stat['size'] = $dir ? 0 : $size;
391
		}
392
		
393
		return $stat;
394
	}
395
	
396
	/**
397
	 * Get stat `owner`, `group` and `isowner` by `uid` and `gid`
398
	 * Sub-fuction of _stat() and _scandir()
399
	 * 
400
	 * @param integer $uid
401
	 * @param integer $gid
402
	 * @return array  stat
403
	 */
404
	protected function getOwnerStat($uid, $gid) {
405
		static $names = null;
406
		static $phpuid = null;
407
		
408
		if (is_null($names)) {
1 ignored issue
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
409
			$names = array('uid' => array(), 'gid' =>array());
410
		}
411
		if (is_null($phpuid)) {
1 ignored issue
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
412
			if (is_callable('posix_getuid')) {
413
				$phpuid = posix_getuid();
414
			} else {
415
				$phpuid = 0;
416
			}
417
		}
418
		
419
		$stat = array();
420
		
421
		if ($uid) {
422
			$stat['isowner'] = ($phpuid == $uid);
423 View Code Duplication
			if (isset($names['uid'][$uid])) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
424
				$stat['owner'] = $names['uid'][$uid];
425
			} else if (is_callable('posix_getpwuid')) {
426
				$pwuid = posix_getpwuid($uid);
427
				$stat['owner'] = $names['uid'][$uid] = $pwuid['name'];
428
			} else {
429
				$stat['owner'] = $names['uid'][$uid] = $uid;
430
			}
431
		}
432 View Code Duplication
		if ($gid) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
433
			if (isset($names['gid'][$gid])) {
434
				$stat['group'] = $names['gid'][$gid];
435
			} else if (is_callable('posix_getgrgid')) {
436
				$grgid = posix_getgrgid($gid);
437
				$stat['group'] = $names['gid'][$gid] = $grgid['name'];
438
			} else {
439
				$stat['group'] = $names['gid'][$gid] = $gid;
440
			}
441
		}
442
		
443
		return $stat;
444
	}
445
446
	/**
447
	 * Return true if path is dir and has at least one childs directory
448
	 *
449
	 * @param  string  $path  dir path
450
	 * @return bool
451
	 * @author Dmitry (dio) Levashov
452
	 **/
453
	protected function _subdirs($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_subdirs" should not be prefixed with an underscore to indicate visibility
Loading history...
454
455
		if (is_dir($path)) {
456
			return (bool)glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
457
		}
458
		return false;
459
	}
460
	
461
	/**
462
	 * Return object width and height
463
	 * Usualy used for images, but can be realize for video etc...
464
	 *
465
	 * @param  string  $path  file path
466
	 * @param  string  $mime  file mime type
467
	 * @return string
468
	 * @author Dmitry (dio) Levashov
469
	 **/
470
	protected function _dimensions($path, $mime) {
1 ignored issue
show
Coding Style introduced by
Method name "_dimensions" should not be prefixed with an underscore to indicate visibility
Loading history...
471
		clearstatcache();
472
		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 472 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.
Loading history...
473
			? $s[0].'x'.$s[1] 
0 ignored issues
show
Bug introduced by
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

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
474
			: false;
475
	}
476
	/******************** file/dir content *********************/
477
	
478
	/**
479
	 * Return symlink target file
480
	 *
481
	 * @param  string  $path  link path
482
	 * @return string
483
	 * @author Dmitry (dio) Levashov
484
	 **/
485
	protected function readlink($path) {
486
		if (!($target = @readlink($path))) {
487
			return null;
488
		}
489
490
		if (strpos($target, $this->systemRoot) !== 0) {
491
			$target = $this->_joinPath(dirname($path), $target);
492
		}
493
494
		if (!file_exists($target)) {
495
			return false;
0 ignored issues
show
Bug Best Practice introduced by
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 my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
496
		}
497
		
498
		return $target;
499
	}
500
		
501
	/**
502
	 * Return files list in directory.
503
	 *
504
	 * @param  string  $path  dir path
505
	 * @return array
506
	 * @author Dmitry (dio) Levashov
507
	 **/
508
	protected function _scandir($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_scandir" should not be prefixed with an underscore to indicate visibility
Loading history...
509
		$files = array();
510
		$cache = array();
511
		$statOwner = (!empty($this->options['statOwner']));
512
		$dirItr = array();
513
		try {
514
			$dirItr = new DirectoryIterator($path);
515
		} catch (UnexpectedValueException $e) {}
1 ignored issue
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Unused Code introduced by
This catchblock is empty and will swallow any caught exception.

This check looks for ``catch` blocks that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

Empty catch blocks will swallow any caught exception, sometimes causing bugs in your code that are very hard to debug. Consider logging the exception to a debug log or re-throwing it in some way, shape or form.

Loading history...
516
		
517
		foreach ($dirItr as $file) {
518
			try {
519
				if ($file->isDot()) { continue; }
520
				
521
				$files[] = $fpath = $file->getPathname();
522
				
523
				$br = false;
524
				$stat = array();
525
				
526
				$gid = $uid = 0;
527
				$stat['isowner'] = false;
528
				$linkreadable = false;
529
				if ($file->isLink()) {
530
					if (!($target = $this->readlink($fpath))
531
					|| $target == $fpath) {
532
						if (is_null($target)) {
1 ignored issue
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
533
							$stat = array();
534
							$br = true;
535
						} else {
536
							$_path = $fpath;
537
							$stat['mime']  = 'symlink-broken';
538
							$target = readlink($_path);
539
							$lstat = lstat($_path);
540
							$ostat = $this->getOwnerStat($lstat['uid'], $lstat['gid']);
541
							$linkreadable = !empty($ostat['isowner']);
542
							$dir = false;
543
							$stat['alias'] = $this->_path($target);
544
							$stat['target'] = $target;
545
						}
546
					} else {
547
						$dir = is_dir($target);
548
						$stat['alias'] = $this->_path($target);
549
						$stat['target'] = $target;
550
						$stat['mime'] = $dir ? 'directory' : $this->mimetype($stat['alias']);
551
					}
552
				} else {
553
					$dir = $file->isDir();
554
					$stat['mime'] = $dir ? 'directory' : $this->mimetype($fpath);
555
				}
556
				$size = sprintf('%u', $file->getSize());
557
				$stat['ts'] = $file->getMTime();
558
				if (!$br) {
559
					if ($statOwner && !$linkreadable) {
560
						$uid = $file->getOwner();
561
						$gid = $file->getGroup();
562
						$stat['perm'] = substr((string)decoct($file->getPerms()), -4);
563
						$stat = array_merge($stat, $this->getOwnerStat($uid, $gid));
564
					}
565
					
566
					//logical rights first
567
					$stat['read'] = ($linkreadable || $file->isReadable())? null : false;
568
					$stat['write'] = $file->isWritable()? null : false;
569
					
570
					if (is_null($stat['read'])) {
1 ignored issue
show
Coding Style introduced by
As per coding-style, please use === null instead of is_null.
Loading history...
571
						$stat['size'] = $dir ? 0 : $size;
0 ignored issues
show
Bug introduced by
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

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
572
					}
573
					
574
				}
575
				
576
				$cache[] = array($fpath, $stat);
577
			} catch (RuntimeException $e) {
578
				continue;
579
			}
580
		}
581
		
582
		if ($cache) {
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
583
			$cache = $this->convEncOut($cache, false);
584
			foreach($cache as $d) {
585
				$this->updateCache($d[0], $d[1]);
586
			}
587
		}
588
		
589
		return $files;
590
	}
591
		
592
	/**
593
	 * Open file and return file pointer
594
	 *
595
	 * @param  string  $path  file path
596
	 * @param  bool    $write open file for writing
0 ignored issues
show
Bug introduced by
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 $italy is not defined by the method finale(...).

/**
 * @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.

Loading history...
597
	 * @return resource|false
598
	 * @author Dmitry (dio) Levashov
599
	 **/
600
	protected function _fopen($path, $mode='rb') {
1 ignored issue
show
Coding Style introduced by
Method name "_fopen" should not be prefixed with an underscore to indicate visibility
Loading history...
601
		return @fopen($path, $mode);
602
	}
603
	
604
	/**
605
	 * Close opened file
606
	 *
607
	 * @param  resource  $fp  file pointer
608
	 * @return bool
609
	 * @author Dmitry (dio) Levashov
610
	 **/
611
	protected function _fclose($fp, $path='') {
1 ignored issue
show
Coding Style introduced by
Method name "_fclose" should not be prefixed with an underscore to indicate visibility
Loading history...
612
		return @fclose($fp);
613
	}
614
	
615
	/********************  file/dir manipulations *************************/
616
	
617
	/**
618
	 * Create dir and return created dir path or false on failed
619
	 *
620
	 * @param  string  $path  parent dir path
621
	 * @param string  $name  new directory name
622
	 * @return string|bool
623
	 * @author Dmitry (dio) Levashov
624
	 **/
625 View Code Duplication
	protected function _mkdir($path, $name) {
1 ignored issue
show
Duplication introduced by
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.

Loading history...
Coding Style introduced by
Method name "_mkdir" should not be prefixed with an underscore to indicate visibility
Loading history...
626
		$path = $this->_joinPath($path, $name);
627
628
		if (@mkdir($path)) {
629
			@chmod($path, $this->options['dirMode']);
0 ignored issues
show
Security Best Practice introduced by
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.');
}
Loading history...
630
			clearstatcache();
631
			return $path;
632
		}
633
634
		return false;
635
	}
636
	
637
	/**
638
	 * Create file and return it's path or false on failed
639
	 *
640
	 * @param  string  $path  parent dir path
641
	 * @param string  $name  new file name
642
	 * @return string|bool
643
	 * @author Dmitry (dio) Levashov
644
	 **/
645 View Code Duplication
	protected function _mkfile($path, $name) {
1 ignored issue
show
Duplication introduced by
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.

Loading history...
Coding Style introduced by
Method name "_mkfile" should not be prefixed with an underscore to indicate visibility
Loading history...
646
		$path = $this->_joinPath($path, $name);
647
		
648
		if (($fp = @fopen($path, 'w'))) {
649
			@fclose($fp);
0 ignored issues
show
Security Best Practice introduced by
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.');
}
Loading history...
650
			@chmod($path, $this->options['fileMode']);
0 ignored issues
show
Security Best Practice introduced by
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.');
}
Loading history...
651
			clearstatcache();
652
			return $path;
653
		}
654
		return false;
655
	}
656
	
657
	/**
658
	 * Create symlink
659
	 *
660
	 * @param  string  $source     file to link to
661
	 * @param  string  $targetDir  folder to create link in
662
	 * @param  string  $name       symlink name
663
	 * @return bool
664
	 * @author Dmitry (dio) Levashov
665
	 **/
666
	protected function _symlink($source, $targetDir, $name) {
1 ignored issue
show
Coding Style introduced by
Method name "_symlink" should not be prefixed with an underscore to indicate visibility
Loading history...
667
		return @symlink($source, $this->_joinPath($targetDir, $name));
668
	}
669
	
670
	/**
671
	 * Copy file into another file
672
	 *
673
	 * @param  string  $source     source file path
674
	 * @param  string  $targetDir  target directory path
675
	 * @param  string  $name       new file name
676
	 * @return bool
677
	 * @author Dmitry (dio) Levashov
678
	 **/
679
	protected function _copy($source, $targetDir, $name) {
1 ignored issue
show
Coding Style introduced by
Method name "_copy" should not be prefixed with an underscore to indicate visibility
Loading history...
680
		$ret = copy($source, $this->_joinPath($targetDir, $name));
681
		$ret && clearstatcache();
682
		return $ret;
683
	}
684
	
685
	/**
686
	 * Move file into another parent dir.
687
	 * Return new file path or false.
688
	 *
689
	 * @param  string  $source  source file path
690
	 * @param  string  $target  target dir path
0 ignored issues
show
Documentation introduced by
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 $ireland is not defined by the method finale(...).

/**
 * @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.

Loading history...
691
	 * @param  string  $name    file name
692
	 * @return string|bool
693
	 * @author Dmitry (dio) Levashov
694
	 **/
695
	protected function _move($source, $targetDir, $name) {
1 ignored issue
show
Coding Style introduced by
Method name "_move" should not be prefixed with an underscore to indicate visibility
Loading history...
696
		$target = $this->_joinPath($targetDir, $name);
697
		$ret = @rename($source, $target) ? $target : false;
698
		$ret && clearstatcache();
0 ignored issues
show
Bug Best Practice introduced by
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 ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
699
		return $ret;
700
	}
701
		
702
	/**
703
	 * Remove file
704
	 *
705
	 * @param  string  $path  file path
706
	 * @return bool
707
	 * @author Dmitry (dio) Levashov
708
	 **/
709
	protected function _unlink($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_unlink" should not be prefixed with an underscore to indicate visibility
Loading history...
710
		$ret = @unlink($path);
711
		$ret && clearstatcache();
712
		return $ret;
713
	}
714
715
	/**
716
	 * Remove dir
717
	 *
718
	 * @param  string  $path  dir path
719
	 * @return bool
720
	 * @author Dmitry (dio) Levashov
721
	 **/
722
	protected function _rmdir($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_rmdir" should not be prefixed with an underscore to indicate visibility
Loading history...
723
		$ret = @rmdir($path);
724
		$ret && clearstatcache();
725
		return $ret;
726
	}
727
	
728
	/**
729
	 * Create new file and write into it from file pointer.
730
	 * Return new file path or false on error.
731
	 *
732
	 * @param  resource  $fp   file pointer
733
	 * @param  string    $dir  target dir path
734
	 * @param  string    $name file name
735
	 * @param  array     $stat file stat (required by some virtual fs)
736
	 * @return bool|string
737
	 * @author Dmitry (dio) Levashov
738
	 **/
739
	protected function _save($fp, $dir, $name, $stat) {
1 ignored issue
show
Coding Style introduced by
Method name "_save" should not be prefixed with an underscore to indicate visibility
Loading history...
740
		$path = $this->_joinPath($dir, $name);
741
742
		$meta = stream_get_meta_data($fp);
743
		$uri = isset($meta['uri'])? $meta['uri'] : '';
744
		if ($uri && @is_file($uri)) {
745
			fclose($fp);
746
			$isCmdPaste = ($this->ARGS['cmd'] === 'paste');
747
			$isCmdCopy = ($isCmdPaste && empty($this->ARGS['cut']));
748
			if (($isCmdCopy || !@rename($uri, $path)) && !@copy($uri, $path)) {
749
				return false;
750
			}
751
			// re-create the source file for remove processing of paste command
752
			$isCmdPaste && !$isCmdCopy && touch($uri);
753
		} else {
754
			if (@file_put_contents($path, $fp, LOCK_EX) === false) {
755
				return false;
756
			}
757
		}
758
759
		@chmod($path, $this->options['fileMode']);
0 ignored issues
show
Security Best Practice introduced by
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.');
}
Loading history...
760
		clearstatcache();
761
		return $path;
762
	}
763
	
764
	/**
765
	 * Get file contents
766
	 *
767
	 * @param  string  $path  file path
768
	 * @return string|false
769
	 * @author Dmitry (dio) Levashov
770
	 **/
771
	protected function _getContents($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_getContents" should not be prefixed with an underscore to indicate visibility
Loading history...
772
		return file_get_contents($path);
773
	}
774
	
775
	/**
776
	 * Write a string to a file
777
	 *
778
	 * @param  string  $path     file path
779
	 * @param  string  $content  new file content
780
	 * @return bool
781
	 * @author Dmitry (dio) Levashov
782
	 **/
783
	protected function _filePutContents($path, $content) {
1 ignored issue
show
Coding Style introduced by
Method name "_filePutContents" should not be prefixed with an underscore to indicate visibility
Loading history...
784
		if (@file_put_contents($path, $content, LOCK_EX) !== false) {
785
			clearstatcache();
786
			return true;
787
		}
788
		return false;
789
	}
790
791
	/**
792
	 * Detect available archivers
793
	 *
794
	 * @return void
795
	 **/
796
	protected function _checkArchivers() {
1 ignored issue
show
Coding Style introduced by
Method name "_checkArchivers" should not be prefixed with an underscore to indicate visibility
Loading history...
797
		$this->archivers = $this->getArchivers();
798
		return;
799
	}
800
801
	/**
802
	 * chmod availability
803
	 *
804
	 * @return bool
805
	 **/
806
	protected function _chmod($path, $mode) {
1 ignored issue
show
Coding Style introduced by
Method name "_chmod" should not be prefixed with an underscore to indicate visibility
Loading history...
807
		$modeOct = is_string($mode) ? octdec($mode) : octdec(sprintf("%04o",$mode));
808
		$ret = @chmod($path, $modeOct);
809
		$ret && clearstatcache();
810
		return  $ret;
811
	}
812
813
	/**
814
	 * Recursive symlinks search
815
	 *
816
	 * @param  string  $path  file/dir path
817
	 * @return bool
818
	 * @author Dmitry (dio) Levashov
819
	 **/
820
	protected function _findSymlinks($path) {
1 ignored issue
show
Coding Style introduced by
Method name "_findSymlinks" should not be prefixed with an underscore to indicate visibility
Loading history...
821
		if (is_link($path)) {
822
			return true;
823
		}
824
		
825
		if (is_dir($path)) {
826
			foreach (scandir($path) as $name) {
827
				if ($name != '.' && $name != '..') {
828
					$p = $path.DIRECTORY_SEPARATOR.$name;
829
					if (is_link($p) || !$this->nameAccepted($name)
830
						||
831
					(($mimeByName = elFinderVolumeDriver::mimetypeInternalDetect($name)) && $mimeByName !== 'unknown' && !$this->allowPutMime($mimeByName))) {
832
						$this->setError(elFinder::ERROR_SAVE, $name);
833
						return true;
834
					}
835
					if (is_dir($p) && $this->_findSymlinks($p)) {
836
						return true;
837
					} elseif (is_file($p)) {
838
						$this->archiveSize += sprintf('%u', filesize($p));
839
					}
840
				}
841
			}
842
		} else {
843
			
844
			$this->archiveSize += sprintf('%u', filesize($path));
845
		}
846
		
847
		return false;
848
	}
849
850
	/**
851
	 * Extract files from archive
852
	 *
853
	 * @param  string  $path  archive path
854
	 * @param  array   $arc   archiver command and arguments (same as in $this->archivers)
855
	 * @return true
856
	 * @author Dmitry (dio) Levashov, 
857
	 * @author Alexey Sukhotin
858
	 **/
859
	protected function _extract($path, $arc) {
1 ignored issue
show
Coding Style introduced by
Method name "_extract" should not be prefixed with an underscore to indicate visibility
Loading history...
860
		
861
		if ($this->quarantine) {
862
863
			$dir     = $this->quarantine.DIRECTORY_SEPARATOR.md5(basename($path).mt_rand());
864
			$archive = $dir.DIRECTORY_SEPARATOR.basename($path);
865
			
866
			if (!@mkdir($dir)) {
867
				return false;
868
			}
869
			
870
			// insurance unexpected shutdown
871
			register_shutdown_function(array($this, 'rmdirRecursive'), realpath($dir));
872
			
873
			chmod($dir, 0777);
874
			
875
			// copy in quarantine
876
			if (!copy($path, $archive)) {
877
				return false;
878
			}
879
			
880
			// extract in quarantine
881
			$this->unpackArchive($archive, $arc);
882
			
883
			// get files list
884
			$ls = array();
885
			foreach (scandir($dir) as $i => $name) {
886
				if ($name != '.' && $name != '..') {
887
					$ls[] = $name;
888
				}
889
			}
890
			
891
			// no files - extract error ?
892
			if (empty($ls)) {
893
				return false;
894
			}
895
			
896
			$this->archiveSize = 0;
897
			
898
			// find symlinks
899
			$symlinks = $this->_findSymlinks($dir);
900
			
901 View Code Duplication
			if ($symlinks) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
902
				$this->delTree($dir);
903
				return $this->setError(array_merge($this->error, array(elFinder::ERROR_ARC_SYMLINKS)));
904
			}
905
906
			// check max files size
907 View Code Duplication
			if ($this->options['maxArcFilesSize'] > 0 && $this->options['maxArcFilesSize'] < $this->archiveSize) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
908
				$this->delTree($dir);
909
				return $this->setError(elFinder::ERROR_ARC_MAXSIZE);
910
			}
911
			
912
			$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.

Loading history...
913
			
914
			// archive contains one item - extract in archive dir
915
			$name = '';
916
			$src = $dir.DIRECTORY_SEPARATOR.$ls[0];
917
			if (($extractTo === 'auto' || !$extractTo) && count($ls) === 1 && is_file($src)) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $extractTo (integer) and 'auto' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
918
				$name = $ls[0];
919
			} else if ($extractTo === 'auto' || $extractTo) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $extractTo (integer) and 'auto' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
920
				// for several files - create new directory
921
				// create unique name for directory
922
				$src = $dir;
923
				$name = basename($path);
924 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
Duplication introduced by
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.

Loading history...
925
					$name = substr($name, 0,  strlen($name)-strlen($m[0]));
926
				}
927
				$test = dirname($path).DIRECTORY_SEPARATOR.$name;
928
				if (file_exists($test) || is_link($test)) {
929
					$name = $this->uniqueName(dirname($path), $name, '-', false);
930
				}
931
			}
932
			
933
			if ($name !== '') {
934
				$result  = dirname($path).DIRECTORY_SEPARATOR.$name;
935
936
				if (! @rename($src, $result)) {
937
					$this->delTree($dir);
938
					return false;
939
				}
940
			} else {
941
				$dstDir = dirname($path);
942
				$res = false;
0 ignored issues
show
Unused Code introduced by
$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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
943
				$result = array();
944
				foreach($ls as $name) {
945
					$target = $dstDir.DIRECTORY_SEPARATOR.$name;
946
					if (is_dir($target)) {
947
						$this->delTree($target);
948
					}
949
					if (@rename($dir.DIRECTORY_SEPARATOR.$name, $target)) {
950
						$result[] = $target;
951
					}
952
				}
953
				if (!$result) {
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
954
					$this->delTree($dir);
955
					return false;
956
				}
957
			}
958
			
959
			is_dir($dir) && $this->delTree($dir);
960
			
961
			return (is_array($result) || file_exists($result)) ? $result : false;
0 ignored issues
show
Bug Best Practice introduced by
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 my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
962
		}
963
	}
964
	
965
	/**
966
	 * Create archive and return its path
967
	 *
968
	 * @param  string  $dir    target dir
969
	 * @param  array   $files  files names list
970
	 * @param  string  $name   archive name
971
	 * @param  array   $arc    archiver options
972
	 * @return string|bool
973
	 * @author Dmitry (dio) Levashov, 
974
	 * @author Alexey Sukhotin
975
	 **/
976
	protected function _archive($dir, $files, $name, $arc) {
1 ignored issue
show
Coding Style introduced by
Method name "_archive" should not be prefixed with an underscore to indicate visibility
Loading history...
977
		return $this->makeArchive($dir, $files, $name, $arc);
978
	}
979
	
980
	/******************** Over write functions *************************/
981
	
982
	/**
983
	 * File path of local server side work file path
984
	 *
985
	 * @param  string $path
986
	 * @return string
987
	 * @author Naoki Sawada
988
	 */
989
	protected function getWorkFile($path) {
990
		return $path;
991
	}
992
993
	/**
994
	 * Delete dirctory trees
995
	 *
996
	 * @param string $localpath path need convert encoding to server encoding
997
	 * @return boolean
998
	 * @author Naoki Sawada
999
	 */
1000
	protected function delTree($localpath) {
1001
		return $this->rmdirRecursive($localpath);
1002
	}
1003
1004
	/******************** Over write (Optimized) functions *************************/
1005
	
1006
	/**
1007
	 * Recursive files search
1008
	 *
1009
	 * @param  string  $path   dir path
1010
	 * @param  string  $q      search string
1011
	 * @param  array   $mimes
1012
	 * @return array
1013
	 * @author Dmitry (dio) Levashov
1014
	 * @author Naoki Sawada
1015
	 **/
1016
	protected function doSearch($path, $q, $mimes) {
1017
		$result = array();
1018
	
1019
		$path = $this->convEncIn($path);
1020
		$dirs = glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*', GLOB_ONLYDIR);
1021
		$match = glob(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*'.$q.'*', GLOB_NOSORT);
1022
		if ($dirs) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $dirs 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 empty(..) or ! empty(...) instead.

Loading history...
1023
			$dirs = $this->convEncOut($dirs, false);
1024
		} 
1025
		$match = $this->convEncOut($match);
1026
		if ($match) {
1027
			foreach($match as $p) {
1028
				$stat = $this->stat($p);
1029
		
1030
				if (!$stat) { // invalid links
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
1031
					continue;
1032
				}
1033
		
1034
				if (!empty($stat['hidden']) || !$this->mimeAccepted($stat['mime'], $mimes)) {
1035
					continue;
1036
				}
1037
					
1038
				$name = $stat['name'];
0 ignored issues
show
Unused Code introduced by
$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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1039
		
1040
				if ((!$mimes || $stat['mime'] !== 'directory')) {
0 ignored issues
show
Bug Best Practice introduced by
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 empty(..) or ! empty(...) instead.

Loading history...
1041
					$stat['path'] = $this->path($stat['hash']);
1042 View Code Duplication
					if ($this->URL && !isset($stat['url'])) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
1043
						$path = str_replace(DIRECTORY_SEPARATOR, '/', substr($p, strlen($this->root) + 1));
1044
						if ($this->encoding) {
1045
							$path = str_replace('%2F', '/', rawurlencode($this->convEncIn($path, true)));
1046
						}
1047
						$stat['url'] = $this->URL . $path;
1048
					}
1049
		
1050
					$result[] = $stat;
1051
				}
1052
			}
1053
		}
1054
		if ($dirs) {
1055
			foreach($dirs as $dir) {
1056
				$stat = $this->stat($dir);
1057 View Code Duplication
				if ($stat['read'] && !isset($stat['alias'])) {
0 ignored issues
show
Duplication introduced by
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.

Loading history...
1058
					@set_time_limit(30);
0 ignored issues
show
Security Best Practice introduced by
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.');
}
Loading history...
1059
					$result = array_merge($result, $this->doSearch($dir, $q, $mimes));
1060
				}
1061
			}
1062
		}
1063
	
1064
		return $result;
1065
	}
1066
	
1067
} // END class 
2 ignored issues
show
Coding Style introduced by
According to PSR2, the closing brace of classes should be placed on the next line directly after the body.

Below you find some examples:

// Incorrect placement according to PSR2
class MyClass
{
    public function foo()
    {

    }
    // This blank line is not allowed.

}

// Correct
class MyClass
{
    public function foo()
    {

    } // No blank lines after this line.
}
Loading history...
Coding Style introduced by
The closing brace of a class hould be on a line by itself.
Loading history...
1068