Completed
Push — master ( 43c1e5...b34843 )
by Morris
30:43 queued 15:08
created

AmazonS3::writeBack()   A

Complexity

Conditions 2
Paths 6

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 6
nop 2
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author André Gaul <[email protected]>
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Christian Berendt <[email protected]>
8
 * @author Christopher T. Johnson <[email protected]>
9
 * @author Johan Björk <[email protected]>
10
 * @author Jörn Friedrich Dreyer <[email protected]>
11
 * @author Martin Mattel <[email protected]>
12
 * @author Michael Gapczynski <[email protected]>
13
 * @author Morris Jobke <[email protected]>
14
 * @author Philipp Kapfer <[email protected]>
15
 * @author Robin Appelman <[email protected]>
16
 * @author Robin McCorkell <[email protected]>
17
 * @author Thomas Müller <[email protected]>
18
 * @author Vincent Petry <[email protected]>
19
 *
20
 * @license AGPL-3.0
21
 *
22
 * This code is free software: you can redistribute it and/or modify
23
 * it under the terms of the GNU Affero General Public License, version 3,
24
 * as published by the Free Software Foundation.
25
 *
26
 * This program is distributed in the hope that it will be useful,
27
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
 * GNU Affero General Public License for more details.
30
 *
31
 * You should have received a copy of the GNU Affero General Public License, version 3,
32
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
33
 *
34
 */
35
36
namespace OCA\Files_External\Lib\Storage;
37
38
use Aws\Result;
39
use Aws\S3\S3Client;
40
use Aws\S3\Exception\S3Exception;
41
use Icewind\Streams\CallbackWrapper;
42
use Icewind\Streams\IteratorDirectory;
43
use OC\Cache\CappedMemoryCache;
44
use OC\Files\ObjectStore\S3ConnectionTrait;
45
use OC\Files\ObjectStore\S3ObjectTrait;
46
use OCP\Constants;
47
48
class AmazonS3 extends \OC\Files\Storage\Common {
49
	use S3ConnectionTrait;
50
	use S3ObjectTrait;
51
52
	public function needsPartFile() {
53
		return false;
54
	}
55
56
	/**
57
	 * @var int in seconds
58
	 */
59
	private $rescanDelay = 10;
60
61
	/** @var CappedMemoryCache|Result[] */
62
	private $objectCache;
63
64
	public function __construct($parameters) {
65
		parent::__construct($parameters);
66
		$this->parseParams($parameters);
67
		$this->objectCache = new CappedMemoryCache();
68
	}
69
70
	/**
71
	 * @param string $path
72
	 * @return string correctly encoded path
73
	 */
74
	private function normalizePath($path) {
75
		$path = trim($path, '/');
76
77
		if (!$path) {
78
			$path = '.';
79
		}
80
81
		return $path;
82
	}
83
84
	private function isRoot($path) {
85
		return $path === '.';
86
	}
87
88
	private function cleanKey($path) {
89
		if ($this->isRoot($path)) {
90
			return '/';
91
		}
92
		return $path;
93
	}
94
95
	private function clearCache() {
96
		$this->objectCache = new CappedMemoryCache();
97
	}
98
99
	private function invalidateCache($key) {
100
		unset($this->objectCache[$key]);
101
		$keys = array_keys($this->objectCache->getData());
102
		$keyLength = strlen($key);
103
		foreach ($keys as $existingKey) {
104
			if (substr($existingKey, 0, $keyLength) === $key) {
105
				unset($this->objectCache[$existingKey]);
106
			}
107
		}
108
	}
109
110
	/**
111
	 * @param $key
112
	 * @return Result|boolean
113
	 */
114
	private function headObject($key) {
115
		if (!isset($this->objectCache[$key])) {
116
			try {
117
				$this->objectCache[$key] = $this->getConnection()->headObject(array(
118
					'Bucket' => $this->bucket,
119
					'Key' => $key
120
				));
121
			} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
122
				if ($e->getStatusCode() >= 500) {
123
					throw $e;
124
				}
125
				$this->objectCache[$key] = false;
126
			}
127
		}
128
129
		return $this->objectCache[$key];
130
	}
131
132
	/**
133
	 * Updates old storage ids (v0.2.1 and older) that are based on key and secret to new ones based on the bucket name.
134
	 * TODO Do this in an update.php. requires iterating over all users and loading the mount.json from their home
135
	 *
136
	 * @param array $params
137
	 */
138
	public function updateLegacyId(array $params) {
139
		$oldId = 'amazon::' . $params['key'] . md5($params['secret']);
140
141
		// find by old id or bucket
142
		$stmt = \OC::$server->getDatabaseConnection()->prepare(
143
			'SELECT `numeric_id`, `id` FROM `*PREFIX*storages` WHERE `id` IN (?, ?)'
144
		);
145
		$stmt->execute(array($oldId, $this->id));
146
		while ($row = $stmt->fetch()) {
147
			$storages[$row['id']] = $row['numeric_id'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$storages was never initialized. Although not strictly required by PHP, it is generally a good practice to add $storages = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
148
		}
149
150
		if (isset($storages[$this->id]) && isset($storages[$oldId])) {
151
			// if both ids exist, delete the old storage and corresponding filecache entries
152
			\OC\Files\Cache\Storage::remove($oldId);
153
		} else if (isset($storages[$oldId])) {
154
			// if only the old id exists do an update
155
			$stmt = \OC::$server->getDatabaseConnection()->prepare(
156
				'UPDATE `*PREFIX*storages` SET `id` = ? WHERE `id` = ?'
157
			);
158
			$stmt->execute(array($this->id, $oldId));
159
		}
160
		// only the bucket based id may exist, do nothing
161
	}
162
163
	/**
164
	 * Remove a file or folder
165
	 *
166
	 * @param string $path
167
	 * @return bool
168
	 */
169
	protected function remove($path) {
170
		// remember fileType to reduce http calls
171
		$fileType = $this->filetype($path);
172
		if ($fileType === 'dir') {
173
			return $this->rmdir($path);
174
		} else if ($fileType === 'file') {
175
			return $this->unlink($path);
176
		} else {
177
			return false;
178
		}
179
	}
180
181
	public function mkdir($path) {
182
		$path = $this->normalizePath($path);
183
184
		if ($this->is_dir($path)) {
185
			return false;
186
		}
187
188
		try {
189
			$this->getConnection()->putObject(array(
190
				'Bucket' => $this->bucket,
191
				'Key' => $path . '/',
192
				'Body' => '',
193
				'ContentType' => 'httpd/unix-directory'
194
			));
195
			$this->testTimeout();
196
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
197
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
198
			return false;
199
		}
200
201
		$this->invalidateCache($path);
202
203
		return true;
204
	}
205
206
	public function file_exists($path) {
207
		return $this->filetype($path) !== false;
208
	}
209
210
211
	public function rmdir($path) {
212
		$path = $this->normalizePath($path);
213
214
		if ($this->isRoot($path)) {
215
			return $this->clearBucket();
216
		}
217
218
		if (!$this->file_exists($path)) {
219
			return false;
220
		}
221
222
		$this->invalidateCache($path);
223
		return $this->batchDelete($path);
224
	}
225
226
	protected function clearBucket() {
227
		$this->clearCache();
228
		try {
229
			$this->getConnection()->clearBucket($this->bucket);
230
			return true;
231
			// clearBucket() is not working with Ceph, so if it fails we try the slower approach
232
		} catch (\Exception $e) {
233
			return $this->batchDelete();
234
		}
235
	}
236
237
	private function batchDelete($path = null) {
238
		$params = array(
239
			'Bucket' => $this->bucket
240
		);
241
		if ($path !== null) {
242
			$params['Prefix'] = $path . '/';
243
		}
244
		try {
245
			$connection = $this->getConnection();
246
			// Since there are no real directories on S3, we need
247
			// to delete all objects prefixed with the path.
248
			do {
249
				// instead of the iterator, manually loop over the list ...
250
				$objects = $connection->listObjects($params);
251
				// ... so we can delete the files in batches
252
				if (isset($objects['Contents'])) {
253
					$connection->deleteObjects([
254
						'Bucket' => $this->bucket,
255
						'Delete' => [
256
							'Objects' => $objects['Contents']
257
						]
258
					]);
259
					$this->testTimeout();
260
				}
261
				// we reached the end when the list is no longer truncated
262
			} while ($objects['IsTruncated']);
263
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
264
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
265
			return false;
266
		}
267
		return true;
268
	}
269
270
	public function opendir($path) {
271
		$path = $this->normalizePath($path);
272
273
		if ($this->isRoot($path)) {
274
			$path = '';
275
		} else {
276
			$path .= '/';
277
		}
278
279
		try {
280
			$files = array();
281
			$results = $this->getConnection()->getPaginator('ListObjects', [
282
				'Bucket' => $this->bucket,
283
				'Delimiter' => '/',
284
				'Prefix' => $path,
285
			]);
286
287
			foreach ($results as $result) {
288
				// sub folders
289
				if (is_array($result['CommonPrefixes'])) {
290
					foreach ($result['CommonPrefixes'] as $prefix) {
291
						$files[] = substr(trim($prefix['Prefix'], '/'), strlen($path));
292
					}
293
				}
294
				if (is_array($result['Contents'])) {
295
					foreach ($result['Contents'] as $object) {
296
						if (isset($object['Key']) && $object['Key'] === $path) {
297
							// it's the directory itself, skip
298
							continue;
299
						}
300
						$file = basename(
301
							isset($object['Key']) ? $object['Key'] : $object['Prefix']
302
						);
303
						$files[] = $file;
304
					}
305
				}
306
			}
307
308
			return IteratorDirectory::wrap($files);
309
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
310
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
311
			return false;
312
		}
313
	}
314
315
	public function stat($path) {
316
		$path = $this->normalizePath($path);
317
318
		try {
319
			$stat = array();
320
			if ($this->is_dir($path)) {
321
				//folders don't really exist
322
				$stat['size'] = -1; //unknown
323
				$stat['mtime'] = time() - $this->rescanDelay * 1000;
324
			} else {
325
				$result = $this->headObject($path);
326
327
				$stat['size'] = $result['ContentLength'] ? $result['ContentLength'] : 0;
328
				if (isset($result['Metadata']['lastmodified'])) {
329
					$stat['mtime'] = strtotime($result['Metadata']['lastmodified']);
330
				} else {
331
					$stat['mtime'] = strtotime($result['LastModified']);
332
				}
333
			}
334
			$stat['atime'] = time();
335
336
			return $stat;
337
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
338
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
339
			return false;
340
		}
341
	}
342
343
	public function is_dir($path) {
344
		$path = $this->normalizePath($path);
345
		try {
346
			return $this->isRoot($path) || $this->headObject($path . '/');
347
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
348
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
349
			return false;
350
		}
351
	}
352
353
	public function filetype($path) {
354
		$path = $this->normalizePath($path);
355
356
		if ($this->isRoot($path)) {
357
			return 'dir';
358
		}
359
360
		try {
361
			if ($this->headObject($path)) {
362
				return 'file';
363
			}
364
			if ($this->headObject($path . '/')) {
365
				return 'dir';
366
			}
367
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
368
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
369
			return false;
370
		}
371
372
		return false;
373
	}
374
375
	public function getPermissions($path) {
376
		$type = $this->filetype($path);
377
		if (!$type) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type 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...
378
			return 0;
379
		}
380
		return $type === 'dir' ? Constants::PERMISSION_ALL : Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE;
381
	}
382
383
	public function unlink($path) {
384
		$path = $this->normalizePath($path);
385
386
		if ($this->is_dir($path)) {
387
			return $this->rmdir($path);
388
		}
389
390
		try {
391
			$this->deleteObject($path);
392
			$this->invalidateCache($path);
393
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
394
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
395
			return false;
396
		}
397
398
		return true;
399
	}
400
401
	public function fopen($path, $mode) {
402
		$path = $this->normalizePath($path);
403
404
		switch ($mode) {
405
			case 'r':
406 View Code Duplication
			case 'rb':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
407
				try {
408
					return $this->readObject($path);
409
				} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
410
					\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
411
					return false;
412
				}
413
			case 'w':
414 View Code Duplication
			case 'wb':
415
				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
416
417
				$handle = fopen($tmpFile, 'w');
418
				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
419
					$this->writeBack($tmpFile, $path);
420
				});
421
			case 'a':
422
			case 'ab':
423
			case 'r+':
424
			case 'w+':
425
			case 'wb+':
426
			case 'a+':
427
			case 'x':
428
			case 'x+':
429
			case 'c':
430
			case 'c+':
431
				if (strrpos($path, '.') !== false) {
432
					$ext = substr($path, strrpos($path, '.'));
433
				} else {
434
					$ext = '';
435
				}
436
				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
437
				if ($this->file_exists($path)) {
438
					$source = $this->readObject($path);
439
					file_put_contents($tmpFile, $source);
440
				}
441
442
				$handle = fopen($tmpFile, $mode);
443
				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
444
					$this->writeBack($tmpFile, $path);
445
				});
446
		}
447
		return false;
448
	}
449
450
	public function touch($path, $mtime = null) {
451
		$path = $this->normalizePath($path);
452
453
		$metadata = array();
0 ignored issues
show
Unused Code introduced by
$metadata 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...
454
		if (is_null($mtime)) {
455
			$mtime = time();
456
		}
457
		$metadata = [
458
			'lastmodified' => gmdate(\DateTime::RFC1123, $mtime)
459
		];
460
461
		$fileType = $this->filetype($path);
462
		try {
463
			if ($fileType !== false) {
464
				if ($fileType === 'dir' && !$this->isRoot($path)) {
465
					$path .= '/';
466
				}
467
				$this->getConnection()->copyObject([
468
					'Bucket' => $this->bucket,
469
					'Key' => $this->cleanKey($path),
470
					'Metadata' => $metadata,
471
					'CopySource' => $this->bucket . '/' . $path,
472
					'MetadataDirective' => 'REPLACE',
473
				]);
474
				$this->testTimeout();
475
			} else {
476
				$mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
477
				$this->getConnection()->putObject([
478
					'Bucket' => $this->bucket,
479
					'Key' => $this->cleanKey($path),
480
					'Metadata' => $metadata,
481
					'Body' => '',
482
					'ContentType' => $mimeType,
483
					'MetadataDirective' => 'REPLACE',
484
				]);
485
				$this->testTimeout();
486
			}
487
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
488
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
489
			return false;
490
		}
491
492
		$this->invalidateCache($path);
493
		return true;
494
	}
495
496
	public function copy($path1, $path2) {
497
		$path1 = $this->normalizePath($path1);
498
		$path2 = $this->normalizePath($path2);
499
500
		if ($this->is_file($path1)) {
501
			try {
502
				$this->getConnection()->copyObject(array(
503
					'Bucket' => $this->bucket,
504
					'Key' => $this->cleanKey($path2),
505
					'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1)
506
				));
507
				$this->testTimeout();
508
			} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
509
				\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
510
				return false;
511
			}
512
		} else {
513
			$this->remove($path2);
514
515
			try {
516
				$this->getConnection()->copyObject(array(
517
					'Bucket' => $this->bucket,
518
					'Key' => $path2 . '/',
519
					'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1 . '/')
520
				));
521
				$this->testTimeout();
522
			} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
523
				\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
524
				return false;
525
			}
526
527
			$dh = $this->opendir($path1);
528
			if (is_resource($dh)) {
529
				while (($file = readdir($dh)) !== false) {
530
					if (\OC\Files\Filesystem::isIgnoredDir($file)) {
531
						continue;
532
					}
533
534
					$source = $path1 . '/' . $file;
535
					$target = $path2 . '/' . $file;
536
					$this->copy($source, $target);
537
				}
538
			}
539
		}
540
541
		$this->invalidateCache($path2);
542
543
		return true;
544
	}
545
546
	public function rename($path1, $path2) {
547
		$path1 = $this->normalizePath($path1);
548
		$path2 = $this->normalizePath($path2);
549
550
		if ($this->is_file($path1)) {
551
552
			if ($this->copy($path1, $path2) === false) {
553
				return false;
554
			}
555
556
			if ($this->unlink($path1) === false) {
557
				$this->unlink($path2);
558
				return false;
559
			}
560
		} else {
561
562
			if ($this->copy($path1, $path2) === false) {
563
				return false;
564
			}
565
566
			if ($this->rmdir($path1) === false) {
567
				$this->rmdir($path2);
568
				return false;
569
			}
570
		}
571
572
		return true;
573
	}
574
575
	public function test() {
576
		$this->getConnection()->headBucket([
577
			'Bucket' => $this->bucket
578
		]);
579
		return true;
580
	}
581
582
	public function getId() {
583
		return $this->id;
584
	}
585
586
	public function writeBack($tmpFile, $path) {
587
		try {
588
			$source = fopen($tmpFile, 'r');
589
			$this->writeObject($path, $source);
590
			$this->invalidateCache($path);
591
			fclose($source);
592
593
			unlink($tmpFile);
594
			return true;
595
		} catch (S3Exception $e) {
0 ignored issues
show
Bug introduced by
The class Aws\S3\Exception\S3Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
596
			\OC::$server->getLogger()->logException($e, ['app' => 'files_external']);
597
			return false;
598
		}
599
	}
600
601
	/**
602
	 * check if curl is installed
603
	 */
604
	public static function checkDependencies() {
605
		return true;
606
	}
607
608
}
609