Completed
Push — master ( c5407f...b0a4e7 )
by Thomas
21:40
created

OC_Helper::getCleanedPath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Bart Visscher <[email protected]>
5
 * @author Björn Schießle <[email protected]>
6
 * @author Christopher Schäpers <[email protected]>
7
 * @author Clark Tomlinson <[email protected]>
8
 * @author Fabian Henze <[email protected]>
9
 * @author Felix Moeller <[email protected]>
10
 * @author Georg Ehrke <[email protected]>
11
 * @author Jakob Sack <[email protected]>
12
 * @author Jan-Christoph Borchardt <[email protected]>
13
 * @author Joas Schilling <[email protected]>
14
 * @author Jörn Friedrich Dreyer <[email protected]>
15
 * @author Lukas Reschke <[email protected]>
16
 * @author Martin Mattel <[email protected]>
17
 * @author Michael Gapczynski <[email protected]>
18
 * @author Morris Jobke <[email protected]>
19
 * @author Olivier Paroz <[email protected]>
20
 * @author Pellaeon Lin <[email protected]>
21
 * @author RealRancor <[email protected]>
22
 * @author Robin Appelman <[email protected]>
23
 * @author Robin McCorkell <[email protected]>
24
 * @author Roeland Jago Douma <[email protected]>
25
 * @author Simon Könnecke <[email protected]>
26
 * @author Thomas Müller <[email protected]>
27
 * @author Thomas Tanghus <[email protected]>
28
 * @author Vincent Petry <[email protected]>
29
 *
30
 * @copyright Copyright (c) 2018, ownCloud GmbH
31
 * @license AGPL-3.0
32
 *
33
 * This code is free software: you can redistribute it and/or modify
34
 * it under the terms of the GNU Affero General Public License, version 3,
35
 * as published by the Free Software Foundation.
36
 *
37
 * This program is distributed in the hope that it will be useful,
38
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40
 * GNU Affero General Public License for more details.
41
 *
42
 * You should have received a copy of the GNU Affero General Public License, version 3,
43
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
44
 *
45
 */
46
use Symfony\Component\Process\ExecutableFinder;
47
48
/**
49
 * Collection of useful functions
50
 */
51
class OC_Helper {
52
	private static $templateManager;
53
54
	/**
55
	 * Creates an absolute url for public use
56
	 * @param string $service id
57
	 * @param bool $add_slash
58
	 * @return string the url
59
	 *
60
	 * Returns a absolute url to the given service.
61
	 */
62
	public static function linkToPublic($service, $add_slash = false) {
63
		if ($service === 'files') {
64
			$url = OC::$server->getURLGenerator()->getAbsoluteURL('/s');
65
		} else {
66
			$url = OC::$server->getURLGenerator()->getAbsoluteURL(OC::$server->getURLGenerator()->linkTo('', 'public.php').'?service='.$service);
67
		}
68
		return $url . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : '');
69
	}
70
71
	/**
72
	 * Make a human file size
73
	 * @param int $bytes file size in bytes
74
	 * @return string a human readable file size
75
	 *
76
	 * Makes 2048 to 2 kB.
77
	 */
78
	public static function humanFileSize($bytes) {
79
		if ($bytes < 0) {
80
			return "?";
81
		}
82
		if ($bytes < 1024) {
83
			return "$bytes B";
84
		}
85
		$bytes = round($bytes / 1024, 0);
86
		if ($bytes < 1024) {
87
			return "$bytes KB";
88
		}
89
		$bytes = round($bytes / 1024, 1);
90
		if ($bytes < 1024) {
91
			return "$bytes MB";
92
		}
93
		$bytes = round($bytes / 1024, 1);
94
		if ($bytes < 1024) {
95
			return "$bytes GB";
96
		}
97
		$bytes = round($bytes / 1024, 1);
98
		if ($bytes < 1024) {
99
			return "$bytes TB";
100
		}
101
102
		$bytes = round($bytes / 1024, 1);
103
		return "$bytes PB";
104
	}
105
106
	/**
107
	 * Make a php file size
108
	 * @param int $bytes file size in bytes
109
	 * @return string a php parseable file size
110
	 *
111
	 * Makes 2048 to 2k and 2^41 to 2048G
112
	 */
113
	public static function phpFileSize($bytes) {
114
		if ($bytes < 0) {
115
			return "?";
116
		}
117
		if ($bytes < 1024) {
118
			return $bytes . "B";
119
		}
120
		$bytes = round($bytes / 1024, 1);
121
		if ($bytes < 1024) {
122
			return $bytes . "K";
123
		}
124
		$bytes = round($bytes / 1024, 1);
125
		if ($bytes < 1024) {
126
			return $bytes . "M";
127
		}
128
		$bytes = round($bytes / 1024, 1);
129
		return $bytes . "G";
130
	}
131
132
	/**
133
	 * Make a computer file size
134
	 * @param string $str file size in human readable format
135
	 * @return float a file size in bytes
136
	 *
137
	 * Makes 2kB to 2048.
138
	 *
139
	 * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
140
	 */
141
	public static function computerFileSize($str) {
142
		if (!is_string($str)) {
143
			return false;
144
		}
145
146
		$str = trim(strtolower($str));
147
148
		$bytesArray = [
149
			'b' => 1,
150
			'k' => 1024,
151
			'kb' => 1024,
152
			'mb' => 1024 * 1024,
153
			'm' => 1024 * 1024,
154
			'gb' => 1024 * 1024 * 1024,
155
			'g' => 1024 * 1024 * 1024,
156
			'tb' => 1024 * 1024 * 1024 * 1024,
157
			't' => 1024 * 1024 * 1024 * 1024,
158
			'pb' => 1024 * 1024 * 1024 * 1024 * 1024,
159
			'p' => 1024 * 1024 * 1024 * 1024 * 1024,
160
		];
161
162
		preg_match('/^([0-9]*)(\.([0-9]+))?( +)?([kmgtp]?b?)$/i', $str, $matches);
163
		if(empty($matches)) {
164
			return false;
165
		}
166
167
		$bytes = floatval($str);
168
		if (!is_finite($bytes)) {
169
			return false;
170
		}
171
172
		if (!empty($matches[5])) {
173
			$bytes *= $bytesArray[$matches[5]];
174
		}
175
176
		$bytes = round($bytes);
177
178
		return $bytes;
179
	}
180
181
	/**
182
	 * Recursive copying of folders
183
	 * @param string $src source folder
184
	 * @param string $dest target folder
185
	 *
186
	 */
187
	static function copyr($src, $dest) {
188
		if (is_dir($src)) {
189
			if (!is_dir($dest)) {
190
				mkdir($dest);
191
			}
192
			$files = scandir($src);
193
			foreach ($files as $file) {
194
				if ($file != "." && $file != "..") {
195
					self::copyr("$src/$file", "$dest/$file");
196
				}
197
			}
198
		} elseif (file_exists($src) && !\OC\Files\Filesystem::isForbiddenFileOrDir($src)) {
199
			copy($src, $dest);
200
		}
201
	}
202
203
	/**
204
	 * Recursive deletion of folders
205
	 * @param string $dir path to the folder
206
	 * @param bool $deleteSelf if set to false only the content of the folder will be deleted
207
	 * @return bool
208
	 */
209
	static function rmdirr($dir, $deleteSelf = true) {
210
		if (is_dir($dir)) {
211
			$files = new RecursiveIteratorIterator(
212
				new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
213
				RecursiveIteratorIterator::CHILD_FIRST
214
			);
215
216
			foreach ($files as $fileInfo) {
217
				/** @var SplFileInfo $fileInfo */
218
				if ($fileInfo->isLink()) {
219
					unlink($fileInfo->getPathname());
220
				} else if ($fileInfo->isDir()) {
221
					rmdir($fileInfo->getRealPath());
222
				} else {
223
					unlink($fileInfo->getRealPath());
224
				}
225
			}
226
			if ($deleteSelf) {
227
				rmdir($dir);
228
			}
229
		} elseif (file_exists($dir)) {
230
			if ($deleteSelf) {
231
				unlink($dir);
232
			}
233
		}
234
		if (!$deleteSelf) {
235
			return true;
236
		}
237
238
		return !file_exists($dir);
239
	}
240
241
	/**
242
	 * @return \OC\Files\Type\TemplateManager
243
	 */
244
	static public function getFileTemplateManager() {
245
		if (!self::$templateManager) {
246
			self::$templateManager = new \OC\Files\Type\TemplateManager();
247
		}
248
		return self::$templateManager;
249
	}
250
251
	/**
252
	 * detect if a given program is found in the search PATH
253
	 *
254
	 * @param string $name
255
	 * @param bool $path
256
	 * @internal param string $program name
257
	 * @internal param string $optional search path, defaults to $PATH
258
	 * @return bool    true if executable program found in path
259
	 */
260
	public static function canExecute($name, $path = false) {
261
		// path defaults to PATH from environment if not set
262
		if ($path === false) {
263
			$path = getenv("PATH");
264
		}
265
		// we look for an executable file of that name
266
		$exts = [""];
267
		$check_fn = "is_executable";
268
		// Default check will be done with $path directories :
269
		$dirs = explode(PATH_SEPARATOR, $path);
270
		// WARNING : We have to check if open_basedir is enabled :
271
		$obd = OC::$server->getIniWrapper()->getString('open_basedir');
272
		if ($obd != "none") {
273
			$obd_values = explode(PATH_SEPARATOR, $obd);
274
			if (count($obd_values) > 0 and $obd_values[0]) {
275
				// open_basedir is in effect !
276
				// We need to check if the program is in one of these dirs :
277
				$dirs = $obd_values;
278
			}
279
		}
280
		foreach ($dirs as $dir) {
281
			foreach ($exts as $ext) {
282
				if ($check_fn("$dir/$name" . $ext))
283
					return true;
284
			}
285
		}
286
		return false;
287
	}
288
289
	/**
290
	 * copy the contents of one stream to another
291
	 *
292
	 * @param resource $source
293
	 * @param resource $target
294
	 * @return array the number of bytes copied and result
295
	 */
296
	public static function streamCopy($source, $target) {
297
		if (!$source or !$target) {
298
			return [0, false];
299
		}
300
		$bufSize = 8192;
301
		$result = true;
302
		$count = 0;
303
		while (!feof($source)) {
304
			$buf = fread($source, $bufSize);
305
			$bytesWritten = fwrite($target, $buf);
306
			if ($bytesWritten !== false) {
307
				$count += $bytesWritten;
308
			}
309
			// note: strlen is expensive so only use it when necessary,
310
			// on the last block
311
			if ($bytesWritten === false
312
				|| ($bytesWritten < $bufSize && $bytesWritten < strlen($buf))
313
			) {
314
				// write error, could be disk full ?
315
				$result = false;
316
				break;
317
			}
318
		}
319
		return [$count, $result];
320
	}
321
322
	/**
323
	 * Adds a suffix to the name in case the file exists
324
	 *
325
	 * @param string $path
326
	 * @param string $filename
327
	 * @return string
328
	 */
329
	public static function buildNotExistingFileName($path, $filename) {
330
		$view = \OC\Files\Filesystem::getView();
331
		return self::buildNotExistingFileNameForView($path, $filename, $view);
332
	}
333
334
	/**
335
	 * Adds a suffix to the name in case the file exists
336
	 *
337
	 * @param string $path
338
	 * @param string $filename
339
	 * @return string
340
	 */
341
	public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) {
342
		if ($path === '/') {
343
			$path = '';
344
		}
345
		if ($pos = strrpos($filename, '.')) {
346
			$name = substr($filename, 0, $pos);
347
			$ext = substr($filename, $pos);
348
		} else {
349
			$name = $filename;
350
			$ext = '';
351
		}
352
353
		$newpath = $path . '/' . $filename;
354
		if ($view->file_exists($newpath)) {
355
			if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
356
				//Replace the last "(number)" with "(number+1)"
357
				$last_match = count($matches[0]) - 1;
358
				$counter = $matches[1][$last_match][0] + 1;
359
				$offset = $matches[0][$last_match][1];
360
				$match_length = strlen($matches[0][$last_match][0]);
361
			} else {
362
				$counter = 2;
363
				$match_length = 0;
364
				$offset = false;
365
			}
366
			do {
367
				if ($offset) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $offset 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...
368
					//Replace the last "(number)" with "(number+1)"
369
					$newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length);
370
				} else {
371
					$newname = $name . ' (' . $counter . ')';
372
				}
373
				$newpath = $path . '/' . $newname . $ext;
374
				$counter++;
375
			} while ($view->file_exists($newpath));
376
		}
377
378
		return $newpath;
379
	}
380
381
	/**
382
	 * Checks if $sub is a subdirectory of $parent
383
	 *
384
	 * @param string $sub
385
	 * @param string $parent
386
	 * @return bool
387
	 */
388
	public static function isSubDirectory($sub, $parent) {
389
		$realpathSub = realpath($sub);
390
		$realpathParent = realpath($parent);
391
392
		// realpath() may return false in case the directory does not exist
393
		// since we can not be sure how different PHP versions may behave here
394
		// we do an additional check whether realpath returned false
395
		if($realpathSub === false ||  $realpathParent === false) {
396
			return false;
397
		}
398
399
		// Check whether $sub is a subdirectory of $parent
400
		if (strpos($realpathSub, $realpathParent) === 0) {
401
			return true;
402
		}
403
404
		return false;
405
	}
406
407
	/**
408
	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
409
	 *
410
	 * @param array $input The array to work on
411
	 * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default)
412
	 * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8
413
	 * @return array
414
	 *
415
	 * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is.
416
	 * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715
417
	 *
418
	 */
419
	public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') {
420
		$case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER;
421
		$ret = [];
422
		foreach ($input as $k => $v) {
423
			$ret[mb_convert_case($k, $case, $encoding)] = $v;
424
		}
425
		return $ret;
426
	}
427
428
	/**
429
	 * performs a search in a nested array
430
	 * @param array $haystack the array to be searched
431
	 * @param string $needle the search string
432
	 * @param string $index optional, only search this key name
433
	 * @return mixed the key of the matching field, otherwise false
434
	 *
435
	 * performs a search in a nested array
436
	 *
437
	 * taken from http://www.php.net/manual/en/function.array-search.php#97645
438
	 */
439
	public static function recursiveArraySearch($haystack, $needle, $index = null) {
440
		$aIt = new RecursiveArrayIterator($haystack);
441
		$it = new RecursiveIteratorIterator($aIt);
442
443
		while ($it->valid()) {
444
			if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) {
445
				return $aIt->key();
446
			}
447
448
			$it->next();
449
		}
450
451
		return false;
452
	}
453
454
	/**
455
	 * calculates the maximum upload size respecting system settings, free space and user quota
456
	 *
457
	 * @param string $dir the current folder where the user currently operates
458
	 * @param int $freeSpace the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly
459
	 * @return int number of bytes representing
460
	 */
461
	public static function maxUploadFilesize($dir, $freeSpace = null) {
462
		if (is_null($freeSpace) || $freeSpace < 0){
463
			$freeSpace = self::freeSpace($dir);
464
		}
465
		return min($freeSpace, self::uploadLimit());
466
	}
467
468
	/**
469
	 * Calculate free space left within user quota
470
	 *
471
	 * @param string $dir the current folder where the user currently operates
472
	 * @return int number of bytes representing
473
	 */
474
	public static function freeSpace($dir) {
475
		$freeSpace = \OC\Files\Filesystem::free_space($dir);
476 View Code Duplication
		if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
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...
477
			$freeSpace = max($freeSpace, 0);
478
			return $freeSpace;
479
		} else {
480
			return (INF > 0)? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
481
		}
482
	}
483
484
	/**
485
	 * Calculate PHP upload limit
486
	 *
487
	 * @return int PHP upload file size limit
488
	 */
489
	public static function uploadLimit() {
490
		$ini = \OC::$server->getIniWrapper();
491
		$upload_max_filesize = OCP\Util::computerFileSize($ini->get('upload_max_filesize'));
492
		$post_max_size = OCP\Util::computerFileSize($ini->get('post_max_size'));
493
		if ((int)$upload_max_filesize === 0 and (int)$post_max_size === 0) {
494
			return INF;
495
		} elseif ((int)$upload_max_filesize === 0 or (int)$post_max_size === 0) {
496
			return max($upload_max_filesize, $post_max_size); //only the non 0 value counts
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression max($upload_max_filesize, $post_max_size); of type false|double adds false to the return on line 496 which is incompatible with the return type documented by OC_Helper::uploadLimit of type integer. It seems like you forgot to handle an error condition.
Loading history...
497
		} else {
498
			return min($upload_max_filesize, $post_max_size);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression min($upload_max_filesize, $post_max_size); of type false|double adds false to the return on line 498 which is incompatible with the return type documented by OC_Helper::uploadLimit of type integer. It seems like you forgot to handle an error condition.
Loading history...
499
		}
500
	}
501
502
	/**
503
	 * Checks if a function is available
504
	 *
505
	 * @param string $function_name
506
	 * @return bool
507
	 */
508
	public static function is_function_enabled($function_name) {
509
		if (!function_exists($function_name)) {
510
			return false;
511
		}
512
		$ini = \OC::$server->getIniWrapper();
513
		$disabled = explode(',', $ini->get('disable_functions'));
514
		$disabled = array_map('trim', $disabled);
515
		if (in_array($function_name, $disabled)) {
516
			return false;
517
		}
518
		$disabled = explode(',', $ini->get('suhosin.executor.func.blacklist'));
519
		$disabled = array_map('trim', $disabled);
520
		if (in_array($function_name, $disabled)) {
521
			return false;
522
		}
523
		return true;
524
	}
525
526
	/**
527
	 * Try to find a program
528
	 *
529
	 * @param string $program
530
	 * @return null|string
531
	 */
532
	public static function findBinaryPath($program) {
533
		$memcache = \OC::$server->getMemCacheFactory()->create('findBinaryPath');
534
		if ($memcache->hasKey($program)) {
535
			return $memcache->get($program);
536
		}
537
		$result = null;
538
		if (self::is_function_enabled('exec')) {
539
			$exeSniffer = new ExecutableFinder();
540
			// Returns null if nothing is found
541
			$result = $exeSniffer->find($program);
542
			if (empty($result)) {
543
				$command = 'find ' . self::getCleanedPath(getenv('PATH')) . ' -name ' . escapeshellarg($program) . ' 2> /dev/null';
544
				exec($command, $output, $returnCode);
545
				if (count($output) > 0) {
546
					$result = escapeshellcmd($output[0]);
547
				}
548
			}
549
		}
550
		// store the value for 5 minutes
551
		$memcache->set($program, $result, 300);
552
		return $result;
553
	}
554
555
	/**
556
	 * Return a validated (sanitised) version of the system path
557
	 *
558
	 * The system path needs to be validated/sanitised before being used, as identified in http://bit.ly/2CEUagp (HackerOne).
559
	 * This method filters out of the retrieved system path, only valid path directories, if the path is defined. Otherwise
560
	 * it returns a defined set of paths.
561
	 *
562
	 * @param string $path
563
	 * @return string|null
564
	 */
565
	public static function getCleanedPath($path = '') {
566
		$pattern = "((\/[\w\d]*)+)";
567
568
		if (preg_match_all($pattern, $path, $matches) > 0) {
569
			return implode(' ', $matches[0]);
570
		}
571
572
		return '/usr/local/bin /usr/bin /opt/bin /bin';
573
	}
574
575
	/**
576
	 * Calculate the disc space for the given path
577
	 *
578
	 * @param string $path
579
	 * @param \OCP\Files\FileInfo $rootInfo (optional)
580
	 * @return array
581
	 * @throws \OCP\Files\NotFoundException
582
	 */
583
	public static function getStorageInfo($path, $rootInfo = null) {
584
		// return storage info without adding mount points
585
		$includeExtStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false);
586
587
		if (!$rootInfo) {
588
			$rootInfo = \OC\Files\Filesystem::getFileInfo($path, false);
589
		}
590
		if (!$rootInfo instanceof \OCP\Files\FileInfo) {
591
			throw new \OCP\Files\NotFoundException();
592
		}
593
		$used = $rootInfo->getSize();
594
		if ($used < 0) {
595
			$used = 0;
596
		}
597
		$quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
598
		$storage = $rootInfo->getStorage();
599
		$sourceStorage = $storage;
600
		if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
601
			$includeExtStorage = false;
602
			$sourceStorage = $storage->getSourceStorage();
603
		}
604
		if ($includeExtStorage) {
605
			$quota = OC_Util::getUserQuota(\OCP\User::getUser());
606
			if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
607
				// always get free space / total space from root + mount points
608
				return self::getGlobalStorageInfo();
609
			}
610
		}
611
612
		// TODO: need a better way to get total space from storage
613
		if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) {
614
			/** @var \OC\Files\Storage\Wrapper\Quota $storage */
615
			$quota = $sourceStorage->getQuota();
616
		}
617
		$free = $sourceStorage->free_space('');
618
		if ($free >= 0) {
619
			$total = $free + $used;
620
		} else {
621
			$total = $free; //either unknown or unlimited
622
		}
623 View Code Duplication
		if ($total > 0) {
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...
624
			if ($quota > 0 && $total > $quota) {
625
				$total = $quota;
626
			}
627
			// prevent division by zero or error codes (negative values)
628
			$relative = round(($used / $total) * 10000) / 100;
629
		} else {
630
			$relative = 0;
631
		}
632
633
		$ownerId = $storage->getOwner($path);
634
		$ownerDisplayName = '';
635
		$owner = \OC::$server->getUserManager()->get($ownerId);
636
		if($owner) {
637
			$ownerDisplayName = $owner->getDisplayName();
638
		}
639
640
		return [
641
			'free' => $free,
642
			'used' => $used,
643
			'quota' => $quota,
644
			'total' => $total,
645
			'relative' => $relative,
646
			'owner' => $ownerId,
647
			'ownerDisplayName' => $ownerDisplayName,
648
		];
649
	}
650
651
	/**
652
	 * Get storage info including all mount points and quota
653
	 *
654
	 * @return array
655
	 */
656
	private static function getGlobalStorageInfo() {
657
		$quota = OC_Util::getUserQuota(\OCP\User::getUser());
658
659
		$rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext');
0 ignored issues
show
Documentation introduced by
'ext' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
660
		$used = $rootInfo['size'];
661
		if ($used < 0) {
662
			$used = 0;
663
		}
664
665
		$total = $quota;
666
		$free = $quota - $used;
667
668 View Code Duplication
		if ($total > 0) {
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...
669
			if ($quota > 0 && $total > $quota) {
670
				$total = $quota;
671
			}
672
			// prevent division by zero or error codes (negative values)
673
			$relative = round(($used / $total) * 10000) / 100;
674
		} else {
675
			$relative = 0;
676
		}
677
678
		return ['free' => $free, 'used' => $used, 'total' => $total, 'relative' => $relative];
679
680
	}
681
}
682