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)); |
|
|
|
|
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); |
|
|
|
|
94
|
|
|
OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1); |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
else { |
98
|
|
|
OC_Response::setContentLengthHeader($fileSize); |
|
|
|
|
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) { |
|
|
|
|
119
|
|
|
$files = $files[0]; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
if (!is_array($files)) { |
|
|
|
|
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)) { |
|
|
|
|
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) { |
|
|
|
|
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) { |
|
|
|
|
161
|
|
|
$fileInfo = \OC\Files\Filesystem::getFileInfo($dir . '/' . $files); |
162
|
|
|
$fileSize = $fileInfo->getSize(); |
163
|
|
|
$numberOfFiles = self::getNumberOfFiles(array($fileInfo)); |
|
|
|
|
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
$streamer = new Streamer(\OC::$server->getRequest(), $fileSize, $numberOfFiles); |
|
|
|
|
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); |
|
|
|
|
173
|
|
|
} |
174
|
|
|
ignore_user_abort(true); |
175
|
|
|
|
176
|
|
|
if ($getType === self::ZIP_FILES) { |
|
|
|
|
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) { |
|
|
|
|
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)); |
|
|
|
|
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(); |
|
|
|
|
293
|
|
|
} else { |
294
|
|
|
http_response_code(403); |
295
|
|
|
die('403 Forbidden'); |
|
|
|
|
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)); |
|
|
|
|
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', |
|
|
|
|
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
|
|
|
|