Passed
Push — master ( 5cdc85...37718d )
by Morris
38:53 queued 21:57
created

OC_Files::getSingleFile()   B

Complexity

Conditions 11
Paths 32

Size

Total Lines 57
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 40
nc 32
nop 4
dl 0
loc 57
rs 7.3166
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bart Visscher <[email protected]>
7
 * @author Björn Schießle <[email protected]>
8
 * @author Clark Tomlinson <[email protected]>
9
 * @author Frank Karlitschek <[email protected]>
10
 * @author Jakob Sack <[email protected]>
11
 * @author Joas Schilling <[email protected]>
12
 * @author Jörn Friedrich Dreyer <[email protected]>
13
 * @author Ko- <[email protected]>
14
 * @author Lukas Reschke <[email protected]>
15
 * @author Michael Gapczynski <[email protected]>
16
 * @author Nicolai Ehemann <[email protected]>
17
 * @author noveens <[email protected]>
18
 * @author Piotr Filiciak <[email protected]>
19
 * @author Robin Appelman <[email protected]>
20
 * @author Robin McCorkell <[email protected]>
21
 * @author Thibaut GRIDEL <[email protected]>
22
 * @author Thomas Müller <[email protected]>
23
 * @author Victor Dubiniuk <[email protected]>
24
 * @author Vincent Petry <[email protected]>
25
 *
26
 * @license AGPL-3.0
27
 *
28
 * This code is free software: you can redistribute it and/or modify
29
 * it under the terms of the GNU Affero General Public License, version 3,
30
 * as published by the Free Software Foundation.
31
 *
32
 * This program is distributed in the hope that it will be useful,
33
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
 * GNU Affero General Public License for more details.
36
 *
37
 * You should have received a copy of the GNU Affero General Public License, version 3,
38
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
39
 *
40
 */
41
42
use OC\Files\View;
43
use OC\Streamer;
44
use OCP\ILogger;
45
use OCP\Lock\ILockingProvider;
46
47
/**
48
 * Class for file server access
49
 *
50
 */
51
class OC_Files {
52
	const FILE = 1;
53
	const ZIP_FILES = 2;
54
	const ZIP_DIR = 3;
55
56
	const UPLOAD_MIN_LIMIT_BYTES = 1048576; // 1 MiB
57
58
59
	private static $multipartBoundary = '';
60
61
	/**
62
	 * @return string
63
	 */
64
	private static function getBoundary() {
65
		if (empty(self::$multipartBoundary)) {
66
			self::$multipartBoundary = md5(mt_rand());
67
		}
68
		return self::$multipartBoundary;
69
	}
70
71
	/**
72
	 * @param string $filename
73
	 * @param string $name
74
	 * @param array $rangeArray ('from'=>int,'to'=>int), ...
75
	 */
76
	private static function sendHeaders($filename, $name, array $rangeArray) {
77
		OC_Response::setContentDispositionHeader($name, 'attachment');
78
		header('Content-Transfer-Encoding: binary', true);
79
		header('Pragma: public');// enable caching in IE
80
		header('Expires: 0');
81
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
82
		$fileSize = \OC\Files\Filesystem::filesize($filename);
83
		$type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename));
0 ignored issues
show
Bug introduced by
It seems like OC\Files\Filesystem::getMimeType($filename) can also be of type false; however, parameter $mimeType of OCP\Files\IMimeTypeDetector::getSecureMimeType() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

83
		$type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(/** @scrutinizer ignore-type */ \OC\Files\Filesystem::getMimeType($filename));
Loading history...
84
		if ($fileSize > -1) {
85
			if (!empty($rangeArray)) {
86
			    http_response_code(206);
87
			    header('Accept-Ranges: bytes', true);
88
			    if (count($rangeArray) > 1) {
89
				$type = 'multipart/byteranges; boundary='.self::getBoundary();
90
				// no Content-Length header here
91
			    }
92
			    else {
93
				header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true);
0 ignored issues
show
Bug introduced by
It seems like $fileSize can also be of type false; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

93
				header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], /** @scrutinizer ignore-type */ $fileSize), true);
Loading history...
94
				OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1);
95
			    }
96
			}
97
			else {
98
			    OC_Response::setContentLengthHeader($fileSize);
0 ignored issues
show
Bug introduced by
It seems like $fileSize can also be of type false; however, parameter $length of OC_Response::setContentLengthHeader() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
			    OC_Response::setContentLengthHeader(/** @scrutinizer ignore-type */ $fileSize);
Loading history...
99
			}
100
		}
101
		header('Content-Type: '.$type, true);
102
	}
103
104
	/**
105
	 * return the content of a file or return a zip file containing multiple files
106
	 *
107
	 * @param string $dir
108
	 * @param string $files ; separated list of files to download
109
	 * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
110
	 */
111
	public static function get($dir, $files, $params = null) {
112
113
		$view = \OC\Files\Filesystem::getView();
114
		$getType = self::FILE;
115
		$filename = $dir;
116
		try {
117
118
			if (is_array($files) && count($files) === 1) {
0 ignored issues
show
introduced by
The condition is_array($files) is always false.
Loading history...
119
				$files = $files[0];
120
			}
121
122
			if (!is_array($files)) {
0 ignored issues
show
introduced by
The condition is_array($files) is always false.
Loading history...
123
				$filename = $dir . '/' . $files;
124
				if (!$view->is_dir($filename)) {
125
					self::getSingleFile($view, $dir, $files, is_null($params) ? array() : $params);
126
					return;
127
				}
128
			}
129
130
			$name = 'download';
131
			if (is_array($files)) {
0 ignored issues
show
introduced by
The condition is_array($files) is always false.
Loading history...
132
				$getType = self::ZIP_FILES;
133
				$basename = basename($dir);
134
				if ($basename) {
135
					$name = $basename;
136
				}
137
138
				$filename = $dir . '/' . $name;
139
			} else {
140
				$filename = $dir . '/' . $files;
141
				$getType = self::ZIP_DIR;
142
				// downloading root ?
143
				if ($files !== '') {
144
					$name = $files;
145
				}
146
			}
147
148
			self::lockFiles($view, $dir, $files);
149
150
			/* Calculate filesize and number of files */
151
			if ($getType === self::ZIP_FILES) {
0 ignored issues
show
introduced by
The condition $getType === self::ZIP_FILES is always false.
Loading history...
152
				$fileInfos = array();
153
				$fileSize = 0;
154
				foreach ($files as $file) {
155
					$fileInfo = \OC\Files\Filesystem::getFileInfo($dir . '/' . $file);
156
					$fileSize += $fileInfo->getSize();
157
					$fileInfos[] = $fileInfo;
158
				}
159
				$numberOfFiles = self::getNumberOfFiles($fileInfos);
160
			} elseif ($getType === self::ZIP_DIR) {
0 ignored issues
show
introduced by
The condition $getType === self::ZIP_DIR is always true.
Loading history...
161
				$fileInfo = \OC\Files\Filesystem::getFileInfo($dir . '/' . $files);
162
				$fileSize = $fileInfo->getSize();
163
				$numberOfFiles = self::getNumberOfFiles(array($fileInfo));
0 ignored issues
show
Bug introduced by
array($fileInfo) of type array<integer,OC\Files\FileInfo|false> is incompatible with the type OCP\Files\FileInfo[] expected by parameter $fileInfos of OC_Files::getNumberOfFiles(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

163
				$numberOfFiles = self::getNumberOfFiles(/** @scrutinizer ignore-type */ array($fileInfo));
Loading history...
164
			}
165
166
			$streamer = new Streamer(\OC::$server->getRequest(), $fileSize, $numberOfFiles);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $numberOfFiles does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $fileSize does not seem to be defined for all execution paths leading up to this point.
Loading history...
167
			OC_Util::obEnd();
168
169
			$streamer->sendHeaders($name);
170
			$executionTime = (int)OC::$server->getIniWrapper()->getNumeric('max_execution_time');
171
			if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
172
				@set_time_limit(0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for set_time_limit(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

172
				/** @scrutinizer ignore-unhandled */ @set_time_limit(0);

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...
173
			}
174
			ignore_user_abort(true);
175
176
			if ($getType === self::ZIP_FILES) {
0 ignored issues
show
introduced by
The condition $getType === self::ZIP_FILES is always false.
Loading history...
177
				foreach ($files as $file) {
178
					$file = $dir . '/' . $file;
179
					if (\OC\Files\Filesystem::is_file($file)) {
180
						$fileSize = \OC\Files\Filesystem::filesize($file);
181
						$fileTime = \OC\Files\Filesystem::filemtime($file);
182
						$fh = \OC\Files\Filesystem::fopen($file, 'r');
183
						$streamer->addFileFromStream($fh, basename($file), $fileSize, $fileTime);
184
						fclose($fh);
185
					} elseif (\OC\Files\Filesystem::is_dir($file)) {
186
						$streamer->addDirRecursive($file);
187
					}
188
				}
189
			} elseif ($getType === self::ZIP_DIR) {
0 ignored issues
show
introduced by
The condition $getType === self::ZIP_DIR is always true.
Loading history...
190
				$file = $dir . '/' . $files;
191
				$streamer->addDirRecursive($file);
192
			}
193
			$streamer->finalize();
194
			set_time_limit($executionTime);
195
			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
196
		} catch (\OCP\Lock\LockedException $ex) {
197
			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
198
			OC::$server->getLogger()->logException($ex);
199
			$l = \OC::$server->getL10N('core');
200
			$hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
201
			\OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint, 200);
202
		} catch (\OCP\Files\ForbiddenException $ex) {
203
			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
204
			OC::$server->getLogger()->logException($ex);
205
			$l = \OC::$server->getL10N('core');
206
			\OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage(), 200);
207
		} catch (\Exception $ex) {
208
			self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
209
			OC::$server->getLogger()->logException($ex);
210
			$l = \OC::$server->getL10N('core');
211
			$hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
212
			\OC_Template::printErrorPage($l->t('Can\'t read file'), $hint, 200);
213
		}
214
	}
215
216
	/**
217
	 * @param string $rangeHeaderPos
218
	 * @param int $fileSize
219
	 * @return array $rangeArray ('from'=>int,'to'=>int), ...
220
	 */
221
	private static function parseHttpRangeHeader($rangeHeaderPos, $fileSize) {
222
		$rArray=explode(',', $rangeHeaderPos);
223
		$minOffset = 0;
224
		$ind = 0;
225
226
		$rangeArray = array();
227
228
		foreach ($rArray as $value) {
229
			$ranges = explode('-', $value);
230
			if (is_numeric($ranges[0])) {
231
				if ($ranges[0] < $minOffset) { // case: bytes=500-700,601-999
232
					$ranges[0] = $minOffset;
233
				}
234
				if ($ind > 0 && $rangeArray[$ind-1]['to']+1 == $ranges[0]) { // case: bytes=500-600,601-999
235
					$ind--;
236
					$ranges[0] = $rangeArray[$ind]['from'];
237
				}
238
			}
239
240
			if (is_numeric($ranges[0]) && is_numeric($ranges[1]) && $ranges[0] < $fileSize && $ranges[0] <= $ranges[1]) {
241
				// case: x-x
242
				if ($ranges[1] >= $fileSize) {
243
					$ranges[1] = $fileSize-1;
244
				}
245
				$rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $ranges[1], 'size' => $fileSize );
246
				$minOffset = $ranges[1] + 1;
247
				if ($minOffset >= $fileSize) {
248
					break;
249
				}
250
			}
251
			elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) {
252
				// case: x-
253
				$rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $fileSize-1, 'size' => $fileSize );
254
				break;
255
			}
256
			elseif (is_numeric($ranges[1])) {
257
				// case: -x
258
				if ($ranges[1] > $fileSize) {
259
					$ranges[1] = $fileSize;
260
				}
261
				$rangeArray[$ind++] = array( 'from' => $fileSize-$ranges[1], 'to' => $fileSize-1, 'size' => $fileSize );
262
				break;
263
			}
264
		}
265
		return $rangeArray;
266
	}
267
268
	/**
269
	 * @param View $view
270
	 * @param string $name
271
	 * @param string $dir
272
	 * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header
273
	 */
274
	private static function getSingleFile($view, $dir, $name, $params) {
275
		$filename = $dir . '/' . $name;
276
		OC_Util::obEnd();
277
		$view->lockFile($filename, ILockingProvider::LOCK_SHARED);
278
		
279
		$rangeArray = array();
280
281
		if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') {
282
			$rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), 
283
								 \OC\Files\Filesystem::filesize($filename));
0 ignored issues
show
Bug introduced by
It seems like OC\Files\Filesystem::filesize($filename) can also be of type false; however, parameter $fileSize of OC_Files::parseHttpRangeHeader() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

283
								 /** @scrutinizer ignore-type */ \OC\Files\Filesystem::filesize($filename));
Loading history...
284
		}
285
		
286
		if (\OC\Files\Filesystem::isReadable($filename)) {
287
			self::sendHeaders($filename, $name, $rangeArray);
288
		} elseif (!\OC\Files\Filesystem::file_exists($filename)) {
289
			http_response_code(404);
290
			$tmpl = new OC_Template('', '404', 'guest');
291
			$tmpl->printPage();
292
			exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
293
		} else {
294
			http_response_code(403);
295
			die('403 Forbidden');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
296
		}
297
		if (isset($params['head']) && $params['head']) {
298
			return;
299
		}
300
		if (!empty($rangeArray)) {
301
			try {
302
			    if (count($rangeArray) == 1) {
303
				$view->readfilePart($filename, $rangeArray[0]['from'], $rangeArray[0]['to']);
304
			    }
305
			    else {
306
				// check if file is seekable (if not throw UnseekableException)
307
				// we have to check it before body contents
308
				$view->readfilePart($filename, $rangeArray[0]['size'], $rangeArray[0]['size']);
309
310
				$type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename));
0 ignored issues
show
Bug introduced by
It seems like OC\Files\Filesystem::getMimeType($filename) can also be of type false; however, parameter $mimeType of OCP\Files\IMimeTypeDetector::getSecureMimeType() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

310
				$type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(/** @scrutinizer ignore-type */ \OC\Files\Filesystem::getMimeType($filename));
Loading history...
311
312
				foreach ($rangeArray as $range) {
313
				    echo "\r\n--".self::getBoundary()."\r\n".
314
				         "Content-type: ".$type."\r\n".
315
				         "Content-range: bytes ".$range['from']."-".$range['to']."/".$range['size']."\r\n\r\n";
316
				    $view->readfilePart($filename, $range['from'], $range['to']);
317
				}
318
				echo "\r\n--".self::getBoundary()."--\r\n";
319
			    }
320
			} catch (\OCP\Files\UnseekableException $ex) {
321
			    // file is unseekable
322
			    header_remove('Accept-Ranges');
323
			    header_remove('Content-Range');
324
			    http_response_code(200);
325
			    self::sendHeaders($filename, $name, array());
326
			    $view->readfile($filename);
327
			}
328
		}
329
		else {
330
		    $view->readfile($filename);
331
		}
332
	}
333
334
	/**
335
	 * Returns the total (recursive) number of files and folders in the given
336
	 * FileInfos.
337
	 *
338
	 * @param \OCP\Files\FileInfo[] $fileInfos the FileInfos to count
339
	 * @return int the total number of files and folders
340
	 */
341
	private static function getNumberOfFiles($fileInfos) {
342
		$numberOfFiles = 0;
343
344
		$view = new View();
345
346
		while ($fileInfo = array_pop($fileInfos)) {
347
			$numberOfFiles++;
348
349
			if ($fileInfo->getType() === \OCP\Files\FileInfo::TYPE_FOLDER) {
350
				$fileInfos = array_merge($fileInfos, $view->getDirectoryContent($fileInfo->getPath()));
351
			}
352
		}
353
354
		return $numberOfFiles;
355
	}
356
357
	/**
358
	 * @param View $view
359
	 * @param string $dir
360
	 * @param string[]|string $files
361
	 */
362
	public static function lockFiles($view, $dir, $files) {
363
		if (!is_array($files)) {
364
			$file = $dir . '/' . $files;
365
			$files = [$file];
366
		}
367
		foreach ($files as $file) {
368
			$file = $dir . '/' . $file;
369
			$view->lockFile($file, ILockingProvider::LOCK_SHARED);
370
			if ($view->is_dir($file)) {
371
				$contents = $view->getDirectoryContent($file);
372
				$contents = array_map(function($fileInfo) use ($file) {
373
					/** @var \OCP\Files\FileInfo $fileInfo */
374
					return $file . '/' . $fileInfo->getName();
375
				}, $contents);
376
				self::lockFiles($view, $dir, $contents);
377
			}
378
		}
379
	}
380
381
	/**
382
	 * set the maximum upload size limit for apache hosts using .htaccess
383
	 *
384
	 * @param int $size file size in bytes
385
	 * @param array $files override '.htaccess' and '.user.ini' locations
386
	 * @return bool|int false on failure, size on success
387
	 */
388
	public static function setUploadLimit($size, $files = []) {
389
		//don't allow user to break his config
390
		$size = (int)$size;
391
		if ($size < self::UPLOAD_MIN_LIMIT_BYTES) {
392
			return false;
393
		}
394
		$size = OC_Helper::phpFileSize($size);
395
396
		$phpValueKeys = array(
397
			'upload_max_filesize',
398
			'post_max_size'
399
		);
400
401
		// default locations if not overridden by $files
402
		$files = array_merge([
403
			'.htaccess' => OC::$SERVERROOT . '/.htaccess',
404
			'.user.ini' => OC::$SERVERROOT . '/.user.ini'
405
		], $files);
406
407
		$updateFiles = [
408
			$files['.htaccess'] => [
409
				'pattern' => '/php_value %1$s (\S)*/',
410
				'setting' => 'php_value %1$s %2$s'
411
			],
412
			$files['.user.ini'] => [
413
				'pattern' => '/%1$s=(\S)*/',
414
				'setting' => '%1$s=%2$s'
415
			]
416
		];
417
418
		$success = true;
419
420
		foreach ($updateFiles as $filename => $patternMap) {
421
			// suppress warnings from fopen()
422
			$handle = @fopen($filename, 'r+');
423
			if (!$handle) {
424
				\OCP\Util::writeLog('files',
0 ignored issues
show
Deprecated Code introduced by
The function OCP\Util::writeLog() has been deprecated: 13.0.0 use log of \OCP\ILogger ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

424
				/** @scrutinizer ignore-deprecated */ \OCP\Util::writeLog('files',

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
425
					'Can\'t write upload limit to ' . $filename . '. Please check the file permissions',
426
					ILogger::WARN);
427
				$success = false;
428
				continue; // try to update as many files as possible
429
			}
430
431
			$content = '';
432
			while (!feof($handle)) {
433
				$content .= fread($handle, 1000);
434
			}
435
436
			foreach ($phpValueKeys as $key) {
437
				$pattern = vsprintf($patternMap['pattern'], [$key]);
438
				$setting = vsprintf($patternMap['setting'], [$key, $size]);
439
				$hasReplaced = 0;
440
				$newContent = preg_replace($pattern, $setting, $content, 2, $hasReplaced);
441
				if ($newContent !== null) {
442
					$content = $newContent;
443
				}
444
				if ($hasReplaced === 0) {
445
					$content .= "\n" . $setting;
446
				}
447
			}
448
449
			// write file back
450
			ftruncate($handle, 0);
451
			rewind($handle);
452
			fwrite($handle, $content);
453
454
			fclose($handle);
455
		}
456
457
		if ($success) {
458
			return OC_Helper::computerFileSize($size);
459
		}
460
		return false;
461
	}
462
463
	/**
464
	 * @param string $dir
465
	 * @param $files
466
	 * @param integer $getType
467
	 * @param View $view
468
	 * @param string $filename
469
	 */
470
	private static function unlockAllTheFiles($dir, $files, $getType, $view, $filename) {
471
		if ($getType === self::FILE) {
472
			$view->unlockFile($filename, ILockingProvider::LOCK_SHARED);
473
		}
474
		if ($getType === self::ZIP_FILES) {
475
			foreach ($files as $file) {
476
				$file = $dir . '/' . $file;
477
				$view->unlockFile($file, ILockingProvider::LOCK_SHARED);
478
			}
479
		}
480
		if ($getType === self::ZIP_DIR) {
481
			$file = $dir . '/' . $files;
482
			$view->unlockFile($file, ILockingProvider::LOCK_SHARED);
483
		}
484
	}
485
486
}
487