Completed
Pull Request — master (#5231)
by Morris
16:38
created
apps/files_external/lib/Lib/Storage/AmazonS3.php 3 patches
Doc Comments   +6 added lines patch added patch discarded remove patch
@@ -191,6 +191,9 @@  discard block
 block discarded – undo
191 191
 		return false;
192 192
 	}
193 193
 
194
+	/**
195
+	 * @param string $path
196
+	 */
194 197
 	private function batchDelete ($path = null) {
195 198
 		$params = array(
196 199
 			'Bucket' => $this->bucket
@@ -516,6 +519,9 @@  discard block
 block discarded – undo
516 519
 		return $this->id;
517 520
 	}
518 521
 
522
+	/**
523
+	 * @param string $path
524
+	 */
519 525
 	public function writeBack($tmpFile, $path) {
520 526
 		try {
521 527
 			$this->getConnection()->putObject(array(
Please login to merge, or discard this patch.
Indentation   +494 added lines, -494 removed lines patch added patch discarded remove patch
@@ -37,7 +37,7 @@  discard block
 block discarded – undo
37 37
 namespace OCA\Files_External\Lib\Storage;
38 38
 
39 39
 set_include_path(get_include_path() . PATH_SEPARATOR .
40
-	\OC_App::getAppPath('files_external') . '/3rdparty/aws-sdk-php');
40
+    \OC_App::getAppPath('files_external') . '/3rdparty/aws-sdk-php');
41 41
 require_once 'aws-autoloader.php';
42 42
 
43 43
 use Aws\S3\S3Client;
@@ -47,498 +47,498 @@  discard block
 block discarded – undo
47 47
 use OC\Files\ObjectStore\S3ConnectionTrait;
48 48
 
49 49
 class AmazonS3 extends \OC\Files\Storage\Common {
50
-	use S3ConnectionTrait;
51
-
52
-	/**
53
-	 * @var array
54
-	 */
55
-	private static $tmpFiles = array();
56
-
57
-	/**
58
-	 * @var int in seconds
59
-	 */
60
-	private $rescanDelay = 10;
61
-
62
-	public function __construct($parameters) {
63
-		parent::__construct($parameters);
64
-		$this->parseParams($parameters);
65
-	}
66
-
67
-	/**
68
-	 * @param string $path
69
-	 * @return string correctly encoded path
70
-	 */
71
-	private function normalizePath($path) {
72
-		$path = trim($path, '/');
73
-
74
-		if (!$path) {
75
-			$path = '.';
76
-		}
77
-
78
-		return $path;
79
-	}
80
-
81
-	private function isRoot($path) {
82
-		return $path === '.';
83
-	}
84
-
85
-	private function cleanKey($path) {
86
-		if ($this->isRoot($path)) {
87
-			return '/';
88
-		}
89
-		return $path;
90
-	}
91
-
92
-	/**
93
-	 * Updates old storage ids (v0.2.1 and older) that are based on key and secret to new ones based on the bucket name.
94
-	 * TODO Do this in an update.php. requires iterating over all users and loading the mount.json from their home
95
-	 *
96
-	 * @param array $params
97
-	 */
98
-	public function updateLegacyId (array $params) {
99
-		$oldId = 'amazon::' . $params['key'] . md5($params['secret']);
100
-
101
-		// find by old id or bucket
102
-		$stmt = \OC::$server->getDatabaseConnection()->prepare(
103
-			'SELECT `numeric_id`, `id` FROM `*PREFIX*storages` WHERE `id` IN (?, ?)'
104
-		);
105
-		$stmt->execute(array($oldId, $this->id));
106
-		while ($row = $stmt->fetch()) {
107
-			$storages[$row['id']] = $row['numeric_id'];
108
-		}
109
-
110
-		if (isset($storages[$this->id]) && isset($storages[$oldId])) {
111
-			// if both ids exist, delete the old storage and corresponding filecache entries
112
-			\OC\Files\Cache\Storage::remove($oldId);
113
-		} else if (isset($storages[$oldId])) {
114
-			// if only the old id exists do an update
115
-			$stmt = \OC::$server->getDatabaseConnection()->prepare(
116
-				'UPDATE `*PREFIX*storages` SET `id` = ? WHERE `id` = ?'
117
-			);
118
-			$stmt->execute(array($this->id, $oldId));
119
-		}
120
-		// only the bucket based id may exist, do nothing
121
-	}
122
-
123
-	/**
124
-	 * Remove a file or folder
125
-	 *
126
-	 * @param string $path
127
-	 * @return bool
128
-	 */
129
-	protected function remove($path) {
130
-		// remember fileType to reduce http calls
131
-		$fileType = $this->filetype($path);
132
-		if ($fileType === 'dir') {
133
-			return $this->rmdir($path);
134
-		} else if ($fileType === 'file') {
135
-			return $this->unlink($path);
136
-		} else {
137
-			return false;
138
-		}
139
-	}
140
-
141
-	public function mkdir($path) {
142
-		$path = $this->normalizePath($path);
143
-
144
-		if ($this->is_dir($path)) {
145
-			return false;
146
-		}
147
-
148
-		try {
149
-			$this->getConnection()->putObject(array(
150
-				'Bucket' => $this->bucket,
151
-				'Key' => $path . '/',
152
-				'Body' => '',
153
-				'ContentType' => 'httpd/unix-directory'
154
-			));
155
-			$this->testTimeout();
156
-		} catch (S3Exception $e) {
157
-			\OCP\Util::logException('files_external', $e);
158
-			return false;
159
-		}
160
-
161
-		return true;
162
-	}
163
-
164
-	public function file_exists($path) {
165
-		return $this->filetype($path) !== false;
166
-	}
167
-
168
-
169
-	public function rmdir($path) {
170
-		$path = $this->normalizePath($path);
171
-
172
-		if ($this->isRoot($path)) {
173
-			return $this->clearBucket();
174
-		}
175
-
176
-		if (!$this->file_exists($path)) {
177
-			return false;
178
-		}
179
-
180
-		return $this->batchDelete($path);
181
-	}
182
-
183
-	protected function clearBucket() {
184
-		try {
185
-			$this->getConnection()->clearBucket($this->bucket);
186
-			return true;
187
-			// clearBucket() is not working with Ceph, so if it fails we try the slower approach
188
-		} catch (\Exception $e) {
189
-			return $this->batchDelete();
190
-		}
191
-		return false;
192
-	}
193
-
194
-	private function batchDelete ($path = null) {
195
-		$params = array(
196
-			'Bucket' => $this->bucket
197
-		);
198
-		if ($path !== null) {
199
-			$params['Prefix'] = $path . '/';
200
-		}
201
-		try {
202
-			// Since there are no real directories on S3, we need
203
-			// to delete all objects prefixed with the path.
204
-			do {
205
-				// instead of the iterator, manually loop over the list ...
206
-				$objects = $this->getConnection()->listObjects($params);
207
-				// ... so we can delete the files in batches
208
-				$this->getConnection()->deleteObjects(array(
209
-					'Bucket' => $this->bucket,
210
-					'Objects' => $objects['Contents']
211
-				));
212
-				$this->testTimeout();
213
-				// we reached the end when the list is no longer truncated
214
-			} while ($objects['IsTruncated']);
215
-		} catch (S3Exception $e) {
216
-			\OCP\Util::logException('files_external', $e);
217
-			return false;
218
-		}
219
-		return true;
220
-	}
221
-
222
-	public function opendir($path) {
223
-		$path = $this->normalizePath($path);
224
-
225
-		if ($this->isRoot($path)) {
226
-			$path = '';
227
-		} else {
228
-			$path .= '/';
229
-		}
230
-
231
-		try {
232
-			$files = array();
233
-			$result = $this->getConnection()->getIterator('ListObjects', array(
234
-				'Bucket' => $this->bucket,
235
-				'Delimiter' => '/',
236
-				'Prefix' => $path
237
-			), array('return_prefixes' => true));
238
-
239
-			foreach ($result as $object) {
240
-				if (isset($object['Key']) && $object['Key'] === $path) {
241
-					// it's the directory itself, skip
242
-					continue;
243
-				}
244
-				$file = basename(
245
-					isset($object['Key']) ? $object['Key'] : $object['Prefix']
246
-				);
247
-				$files[] = $file;
248
-			}
249
-
250
-			return IteratorDirectory::wrap($files);
251
-		} catch (S3Exception $e) {
252
-			\OCP\Util::logException('files_external', $e);
253
-			return false;
254
-		}
255
-	}
256
-
257
-	public function stat($path) {
258
-		$path = $this->normalizePath($path);
259
-
260
-		try {
261
-			$stat = array();
262
-			if ($this->is_dir($path)) {
263
-				//folders don't really exist
264
-				$stat['size'] = -1; //unknown
265
-				$stat['mtime'] = time() - $this->rescanDelay * 1000;
266
-			} else {
267
-				$result = $this->getConnection()->headObject(array(
268
-					'Bucket' => $this->bucket,
269
-					'Key' => $path
270
-				));
271
-
272
-				$stat['size'] = $result['ContentLength'] ? $result['ContentLength'] : 0;
273
-				if ($result['Metadata']['lastmodified']) {
274
-					$stat['mtime'] = strtotime($result['Metadata']['lastmodified']);
275
-				} else {
276
-					$stat['mtime'] = strtotime($result['LastModified']);
277
-				}
278
-			}
279
-			$stat['atime'] = time();
280
-
281
-			return $stat;
282
-		} catch(S3Exception $e) {
283
-			\OCP\Util::logException('files_external', $e);
284
-			return false;
285
-		}
286
-	}
287
-
288
-	public function filetype($path) {
289
-		$path = $this->normalizePath($path);
290
-
291
-		if ($this->isRoot($path)) {
292
-			return 'dir';
293
-		}
294
-
295
-		try {
296
-			if ($this->getConnection()->doesObjectExist($this->bucket, $path)) {
297
-				return 'file';
298
-			}
299
-			if ($this->getConnection()->doesObjectExist($this->bucket, $path.'/')) {
300
-				return 'dir';
301
-			}
302
-		} catch (S3Exception $e) {
303
-			\OCP\Util::logException('files_external', $e);
304
-			return false;
305
-		}
306
-
307
-		return false;
308
-	}
309
-
310
-	public function unlink($path) {
311
-		$path = $this->normalizePath($path);
312
-
313
-		if ($this->is_dir($path)) {
314
-			return $this->rmdir($path);
315
-		}
316
-
317
-		try {
318
-			$this->getConnection()->deleteObject(array(
319
-				'Bucket' => $this->bucket,
320
-				'Key' => $path
321
-			));
322
-			$this->testTimeout();
323
-		} catch (S3Exception $e) {
324
-			\OCP\Util::logException('files_external', $e);
325
-			return false;
326
-		}
327
-
328
-		return true;
329
-	}
330
-
331
-	public function fopen($path, $mode) {
332
-		$path = $this->normalizePath($path);
333
-
334
-		switch ($mode) {
335
-			case 'r':
336
-			case 'rb':
337
-				$tmpFile = \OCP\Files::tmpFile();
338
-				self::$tmpFiles[$tmpFile] = $path;
339
-
340
-				try {
341
-					$this->getConnection()->getObject(array(
342
-						'Bucket' => $this->bucket,
343
-						'Key' => $path,
344
-						'SaveAs' => $tmpFile
345
-					));
346
-				} catch (S3Exception $e) {
347
-					\OCP\Util::logException('files_external', $e);
348
-					return false;
349
-				}
350
-
351
-				return fopen($tmpFile, 'r');
352
-			case 'w':
353
-			case 'wb':
354
-			case 'a':
355
-			case 'ab':
356
-			case 'r+':
357
-			case 'w+':
358
-			case 'wb+':
359
-			case 'a+':
360
-			case 'x':
361
-			case 'x+':
362
-			case 'c':
363
-			case 'c+':
364
-				if (strrpos($path, '.') !== false) {
365
-					$ext = substr($path, strrpos($path, '.'));
366
-				} else {
367
-					$ext = '';
368
-				}
369
-				$tmpFile = \OCP\Files::tmpFile($ext);
370
-				if ($this->file_exists($path)) {
371
-					$source = $this->fopen($path, 'r');
372
-					file_put_contents($tmpFile, $source);
373
-				}
374
-
375
-				$handle = fopen($tmpFile, $mode);
376
-				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
377
-					$this->writeBack($tmpFile, $path);
378
-				});
379
-		}
380
-		return false;
381
-	}
382
-
383
-	public function touch($path, $mtime = null) {
384
-		$path = $this->normalizePath($path);
385
-
386
-		$metadata = array();
387
-		if (is_null($mtime)) {
388
-			$mtime = time();
389
-		}
390
-		$metadata = [
391
-			'lastmodified' => gmdate(\Aws\Common\Enum\DateFormat::RFC1123, $mtime)
392
-		];
393
-
394
-		$fileType = $this->filetype($path);
395
-		try {
396
-			if ($fileType !== false) {
397
-				if ($fileType === 'dir' && ! $this->isRoot($path)) {
398
-					$path .= '/';
399
-				}
400
-				$this->getConnection()->copyObject([
401
-					'Bucket' => $this->bucket,
402
-					'Key' => $this->cleanKey($path),
403
-					'Metadata' => $metadata,
404
-					'CopySource' => $this->bucket . '/' . $path,
405
-					'MetadataDirective' => 'REPLACE',
406
-				]);
407
-				$this->testTimeout();
408
-			} else {
409
-				$mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
410
-				$this->getConnection()->putObject([
411
-					'Bucket' => $this->bucket,
412
-					'Key' => $this->cleanKey($path),
413
-					'Metadata' => $metadata,
414
-					'Body' => '',
415
-					'ContentType' => $mimeType,
416
-					'MetadataDirective' => 'REPLACE',
417
-				]);
418
-				$this->testTimeout();
419
-			}
420
-		} catch (S3Exception $e) {
421
-			\OCP\Util::logException('files_external', $e);
422
-			return false;
423
-		}
424
-
425
-		return true;
426
-	}
427
-
428
-	public function copy($path1, $path2) {
429
-		$path1 = $this->normalizePath($path1);
430
-		$path2 = $this->normalizePath($path2);
431
-
432
-		if ($this->is_file($path1)) {
433
-			try {
434
-				$this->getConnection()->copyObject(array(
435
-					'Bucket' => $this->bucket,
436
-					'Key' => $this->cleanKey($path2),
437
-					'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1)
438
-				));
439
-				$this->testTimeout();
440
-			} catch (S3Exception $e) {
441
-				\OCP\Util::logException('files_external', $e);
442
-				return false;
443
-			}
444
-		} else {
445
-			$this->remove($path2);
446
-
447
-			try {
448
-				$this->getConnection()->copyObject(array(
449
-					'Bucket' => $this->bucket,
450
-					'Key' => $path2 . '/',
451
-					'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1 . '/')
452
-				));
453
-				$this->testTimeout();
454
-			} catch (S3Exception $e) {
455
-				\OCP\Util::logException('files_external', $e);
456
-				return false;
457
-			}
458
-
459
-			$dh = $this->opendir($path1);
460
-			if (is_resource($dh)) {
461
-				while (($file = readdir($dh)) !== false) {
462
-					if (\OC\Files\Filesystem::isIgnoredDir($file)) {
463
-						continue;
464
-					}
465
-
466
-					$source = $path1 . '/' . $file;
467
-					$target = $path2 . '/' . $file;
468
-					$this->copy($source, $target);
469
-				}
470
-			}
471
-		}
472
-
473
-		return true;
474
-	}
475
-
476
-	public function rename($path1, $path2) {
477
-		$path1 = $this->normalizePath($path1);
478
-		$path2 = $this->normalizePath($path2);
479
-
480
-		if ($this->is_file($path1)) {
481
-
482
-			if ($this->copy($path1, $path2) === false) {
483
-				return false;
484
-			}
485
-
486
-			if ($this->unlink($path1) === false) {
487
-				$this->unlink($path2);
488
-				return false;
489
-			}
490
-		} else {
491
-
492
-			if ($this->copy($path1, $path2) === false) {
493
-				return false;
494
-			}
495
-
496
-			if ($this->rmdir($path1) === false) {
497
-				$this->rmdir($path2);
498
-				return false;
499
-			}
500
-		}
501
-
502
-		return true;
503
-	}
504
-
505
-	public function test() {
506
-		$test = $this->getConnection()->getBucketAcl(array(
507
-			'Bucket' => $this->bucket,
508
-		));
509
-		if (isset($test) && !is_null($test->getPath('Owner/ID'))) {
510
-			return true;
511
-		}
512
-		return false;
513
-	}
514
-
515
-	public function getId() {
516
-		return $this->id;
517
-	}
518
-
519
-	public function writeBack($tmpFile, $path) {
520
-		try {
521
-			$this->getConnection()->putObject(array(
522
-				'Bucket' => $this->bucket,
523
-				'Key' => $this->cleanKey($path),
524
-				'SourceFile' => $tmpFile,
525
-				'ContentType' => \OC::$server->getMimeTypeDetector()->detect($tmpFile),
526
-				'ContentLength' => filesize($tmpFile)
527
-			));
528
-			$this->testTimeout();
529
-
530
-			unlink($tmpFile);
531
-		} catch (S3Exception $e) {
532
-			\OCP\Util::logException('files_external', $e);
533
-			return false;
534
-		}
535
-	}
536
-
537
-	/**
538
-	 * check if curl is installed
539
-	 */
540
-	public static function checkDependencies() {
541
-		return true;
542
-	}
50
+    use S3ConnectionTrait;
51
+
52
+    /**
53
+     * @var array
54
+     */
55
+    private static $tmpFiles = array();
56
+
57
+    /**
58
+     * @var int in seconds
59
+     */
60
+    private $rescanDelay = 10;
61
+
62
+    public function __construct($parameters) {
63
+        parent::__construct($parameters);
64
+        $this->parseParams($parameters);
65
+    }
66
+
67
+    /**
68
+     * @param string $path
69
+     * @return string correctly encoded path
70
+     */
71
+    private function normalizePath($path) {
72
+        $path = trim($path, '/');
73
+
74
+        if (!$path) {
75
+            $path = '.';
76
+        }
77
+
78
+        return $path;
79
+    }
80
+
81
+    private function isRoot($path) {
82
+        return $path === '.';
83
+    }
84
+
85
+    private function cleanKey($path) {
86
+        if ($this->isRoot($path)) {
87
+            return '/';
88
+        }
89
+        return $path;
90
+    }
91
+
92
+    /**
93
+     * Updates old storage ids (v0.2.1 and older) that are based on key and secret to new ones based on the bucket name.
94
+     * TODO Do this in an update.php. requires iterating over all users and loading the mount.json from their home
95
+     *
96
+     * @param array $params
97
+     */
98
+    public function updateLegacyId (array $params) {
99
+        $oldId = 'amazon::' . $params['key'] . md5($params['secret']);
100
+
101
+        // find by old id or bucket
102
+        $stmt = \OC::$server->getDatabaseConnection()->prepare(
103
+            'SELECT `numeric_id`, `id` FROM `*PREFIX*storages` WHERE `id` IN (?, ?)'
104
+        );
105
+        $stmt->execute(array($oldId, $this->id));
106
+        while ($row = $stmt->fetch()) {
107
+            $storages[$row['id']] = $row['numeric_id'];
108
+        }
109
+
110
+        if (isset($storages[$this->id]) && isset($storages[$oldId])) {
111
+            // if both ids exist, delete the old storage and corresponding filecache entries
112
+            \OC\Files\Cache\Storage::remove($oldId);
113
+        } else if (isset($storages[$oldId])) {
114
+            // if only the old id exists do an update
115
+            $stmt = \OC::$server->getDatabaseConnection()->prepare(
116
+                'UPDATE `*PREFIX*storages` SET `id` = ? WHERE `id` = ?'
117
+            );
118
+            $stmt->execute(array($this->id, $oldId));
119
+        }
120
+        // only the bucket based id may exist, do nothing
121
+    }
122
+
123
+    /**
124
+     * Remove a file or folder
125
+     *
126
+     * @param string $path
127
+     * @return bool
128
+     */
129
+    protected function remove($path) {
130
+        // remember fileType to reduce http calls
131
+        $fileType = $this->filetype($path);
132
+        if ($fileType === 'dir') {
133
+            return $this->rmdir($path);
134
+        } else if ($fileType === 'file') {
135
+            return $this->unlink($path);
136
+        } else {
137
+            return false;
138
+        }
139
+    }
140
+
141
+    public function mkdir($path) {
142
+        $path = $this->normalizePath($path);
143
+
144
+        if ($this->is_dir($path)) {
145
+            return false;
146
+        }
147
+
148
+        try {
149
+            $this->getConnection()->putObject(array(
150
+                'Bucket' => $this->bucket,
151
+                'Key' => $path . '/',
152
+                'Body' => '',
153
+                'ContentType' => 'httpd/unix-directory'
154
+            ));
155
+            $this->testTimeout();
156
+        } catch (S3Exception $e) {
157
+            \OCP\Util::logException('files_external', $e);
158
+            return false;
159
+        }
160
+
161
+        return true;
162
+    }
163
+
164
+    public function file_exists($path) {
165
+        return $this->filetype($path) !== false;
166
+    }
167
+
168
+
169
+    public function rmdir($path) {
170
+        $path = $this->normalizePath($path);
171
+
172
+        if ($this->isRoot($path)) {
173
+            return $this->clearBucket();
174
+        }
175
+
176
+        if (!$this->file_exists($path)) {
177
+            return false;
178
+        }
179
+
180
+        return $this->batchDelete($path);
181
+    }
182
+
183
+    protected function clearBucket() {
184
+        try {
185
+            $this->getConnection()->clearBucket($this->bucket);
186
+            return true;
187
+            // clearBucket() is not working with Ceph, so if it fails we try the slower approach
188
+        } catch (\Exception $e) {
189
+            return $this->batchDelete();
190
+        }
191
+        return false;
192
+    }
193
+
194
+    private function batchDelete ($path = null) {
195
+        $params = array(
196
+            'Bucket' => $this->bucket
197
+        );
198
+        if ($path !== null) {
199
+            $params['Prefix'] = $path . '/';
200
+        }
201
+        try {
202
+            // Since there are no real directories on S3, we need
203
+            // to delete all objects prefixed with the path.
204
+            do {
205
+                // instead of the iterator, manually loop over the list ...
206
+                $objects = $this->getConnection()->listObjects($params);
207
+                // ... so we can delete the files in batches
208
+                $this->getConnection()->deleteObjects(array(
209
+                    'Bucket' => $this->bucket,
210
+                    'Objects' => $objects['Contents']
211
+                ));
212
+                $this->testTimeout();
213
+                // we reached the end when the list is no longer truncated
214
+            } while ($objects['IsTruncated']);
215
+        } catch (S3Exception $e) {
216
+            \OCP\Util::logException('files_external', $e);
217
+            return false;
218
+        }
219
+        return true;
220
+    }
221
+
222
+    public function opendir($path) {
223
+        $path = $this->normalizePath($path);
224
+
225
+        if ($this->isRoot($path)) {
226
+            $path = '';
227
+        } else {
228
+            $path .= '/';
229
+        }
230
+
231
+        try {
232
+            $files = array();
233
+            $result = $this->getConnection()->getIterator('ListObjects', array(
234
+                'Bucket' => $this->bucket,
235
+                'Delimiter' => '/',
236
+                'Prefix' => $path
237
+            ), array('return_prefixes' => true));
238
+
239
+            foreach ($result as $object) {
240
+                if (isset($object['Key']) && $object['Key'] === $path) {
241
+                    // it's the directory itself, skip
242
+                    continue;
243
+                }
244
+                $file = basename(
245
+                    isset($object['Key']) ? $object['Key'] : $object['Prefix']
246
+                );
247
+                $files[] = $file;
248
+            }
249
+
250
+            return IteratorDirectory::wrap($files);
251
+        } catch (S3Exception $e) {
252
+            \OCP\Util::logException('files_external', $e);
253
+            return false;
254
+        }
255
+    }
256
+
257
+    public function stat($path) {
258
+        $path = $this->normalizePath($path);
259
+
260
+        try {
261
+            $stat = array();
262
+            if ($this->is_dir($path)) {
263
+                //folders don't really exist
264
+                $stat['size'] = -1; //unknown
265
+                $stat['mtime'] = time() - $this->rescanDelay * 1000;
266
+            } else {
267
+                $result = $this->getConnection()->headObject(array(
268
+                    'Bucket' => $this->bucket,
269
+                    'Key' => $path
270
+                ));
271
+
272
+                $stat['size'] = $result['ContentLength'] ? $result['ContentLength'] : 0;
273
+                if ($result['Metadata']['lastmodified']) {
274
+                    $stat['mtime'] = strtotime($result['Metadata']['lastmodified']);
275
+                } else {
276
+                    $stat['mtime'] = strtotime($result['LastModified']);
277
+                }
278
+            }
279
+            $stat['atime'] = time();
280
+
281
+            return $stat;
282
+        } catch(S3Exception $e) {
283
+            \OCP\Util::logException('files_external', $e);
284
+            return false;
285
+        }
286
+    }
287
+
288
+    public function filetype($path) {
289
+        $path = $this->normalizePath($path);
290
+
291
+        if ($this->isRoot($path)) {
292
+            return 'dir';
293
+        }
294
+
295
+        try {
296
+            if ($this->getConnection()->doesObjectExist($this->bucket, $path)) {
297
+                return 'file';
298
+            }
299
+            if ($this->getConnection()->doesObjectExist($this->bucket, $path.'/')) {
300
+                return 'dir';
301
+            }
302
+        } catch (S3Exception $e) {
303
+            \OCP\Util::logException('files_external', $e);
304
+            return false;
305
+        }
306
+
307
+        return false;
308
+    }
309
+
310
+    public function unlink($path) {
311
+        $path = $this->normalizePath($path);
312
+
313
+        if ($this->is_dir($path)) {
314
+            return $this->rmdir($path);
315
+        }
316
+
317
+        try {
318
+            $this->getConnection()->deleteObject(array(
319
+                'Bucket' => $this->bucket,
320
+                'Key' => $path
321
+            ));
322
+            $this->testTimeout();
323
+        } catch (S3Exception $e) {
324
+            \OCP\Util::logException('files_external', $e);
325
+            return false;
326
+        }
327
+
328
+        return true;
329
+    }
330
+
331
+    public function fopen($path, $mode) {
332
+        $path = $this->normalizePath($path);
333
+
334
+        switch ($mode) {
335
+            case 'r':
336
+            case 'rb':
337
+                $tmpFile = \OCP\Files::tmpFile();
338
+                self::$tmpFiles[$tmpFile] = $path;
339
+
340
+                try {
341
+                    $this->getConnection()->getObject(array(
342
+                        'Bucket' => $this->bucket,
343
+                        'Key' => $path,
344
+                        'SaveAs' => $tmpFile
345
+                    ));
346
+                } catch (S3Exception $e) {
347
+                    \OCP\Util::logException('files_external', $e);
348
+                    return false;
349
+                }
350
+
351
+                return fopen($tmpFile, 'r');
352
+            case 'w':
353
+            case 'wb':
354
+            case 'a':
355
+            case 'ab':
356
+            case 'r+':
357
+            case 'w+':
358
+            case 'wb+':
359
+            case 'a+':
360
+            case 'x':
361
+            case 'x+':
362
+            case 'c':
363
+            case 'c+':
364
+                if (strrpos($path, '.') !== false) {
365
+                    $ext = substr($path, strrpos($path, '.'));
366
+                } else {
367
+                    $ext = '';
368
+                }
369
+                $tmpFile = \OCP\Files::tmpFile($ext);
370
+                if ($this->file_exists($path)) {
371
+                    $source = $this->fopen($path, 'r');
372
+                    file_put_contents($tmpFile, $source);
373
+                }
374
+
375
+                $handle = fopen($tmpFile, $mode);
376
+                return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
377
+                    $this->writeBack($tmpFile, $path);
378
+                });
379
+        }
380
+        return false;
381
+    }
382
+
383
+    public function touch($path, $mtime = null) {
384
+        $path = $this->normalizePath($path);
385
+
386
+        $metadata = array();
387
+        if (is_null($mtime)) {
388
+            $mtime = time();
389
+        }
390
+        $metadata = [
391
+            'lastmodified' => gmdate(\Aws\Common\Enum\DateFormat::RFC1123, $mtime)
392
+        ];
393
+
394
+        $fileType = $this->filetype($path);
395
+        try {
396
+            if ($fileType !== false) {
397
+                if ($fileType === 'dir' && ! $this->isRoot($path)) {
398
+                    $path .= '/';
399
+                }
400
+                $this->getConnection()->copyObject([
401
+                    'Bucket' => $this->bucket,
402
+                    'Key' => $this->cleanKey($path),
403
+                    'Metadata' => $metadata,
404
+                    'CopySource' => $this->bucket . '/' . $path,
405
+                    'MetadataDirective' => 'REPLACE',
406
+                ]);
407
+                $this->testTimeout();
408
+            } else {
409
+                $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
410
+                $this->getConnection()->putObject([
411
+                    'Bucket' => $this->bucket,
412
+                    'Key' => $this->cleanKey($path),
413
+                    'Metadata' => $metadata,
414
+                    'Body' => '',
415
+                    'ContentType' => $mimeType,
416
+                    'MetadataDirective' => 'REPLACE',
417
+                ]);
418
+                $this->testTimeout();
419
+            }
420
+        } catch (S3Exception $e) {
421
+            \OCP\Util::logException('files_external', $e);
422
+            return false;
423
+        }
424
+
425
+        return true;
426
+    }
427
+
428
+    public function copy($path1, $path2) {
429
+        $path1 = $this->normalizePath($path1);
430
+        $path2 = $this->normalizePath($path2);
431
+
432
+        if ($this->is_file($path1)) {
433
+            try {
434
+                $this->getConnection()->copyObject(array(
435
+                    'Bucket' => $this->bucket,
436
+                    'Key' => $this->cleanKey($path2),
437
+                    'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1)
438
+                ));
439
+                $this->testTimeout();
440
+            } catch (S3Exception $e) {
441
+                \OCP\Util::logException('files_external', $e);
442
+                return false;
443
+            }
444
+        } else {
445
+            $this->remove($path2);
446
+
447
+            try {
448
+                $this->getConnection()->copyObject(array(
449
+                    'Bucket' => $this->bucket,
450
+                    'Key' => $path2 . '/',
451
+                    'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1 . '/')
452
+                ));
453
+                $this->testTimeout();
454
+            } catch (S3Exception $e) {
455
+                \OCP\Util::logException('files_external', $e);
456
+                return false;
457
+            }
458
+
459
+            $dh = $this->opendir($path1);
460
+            if (is_resource($dh)) {
461
+                while (($file = readdir($dh)) !== false) {
462
+                    if (\OC\Files\Filesystem::isIgnoredDir($file)) {
463
+                        continue;
464
+                    }
465
+
466
+                    $source = $path1 . '/' . $file;
467
+                    $target = $path2 . '/' . $file;
468
+                    $this->copy($source, $target);
469
+                }
470
+            }
471
+        }
472
+
473
+        return true;
474
+    }
475
+
476
+    public function rename($path1, $path2) {
477
+        $path1 = $this->normalizePath($path1);
478
+        $path2 = $this->normalizePath($path2);
479
+
480
+        if ($this->is_file($path1)) {
481
+
482
+            if ($this->copy($path1, $path2) === false) {
483
+                return false;
484
+            }
485
+
486
+            if ($this->unlink($path1) === false) {
487
+                $this->unlink($path2);
488
+                return false;
489
+            }
490
+        } else {
491
+
492
+            if ($this->copy($path1, $path2) === false) {
493
+                return false;
494
+            }
495
+
496
+            if ($this->rmdir($path1) === false) {
497
+                $this->rmdir($path2);
498
+                return false;
499
+            }
500
+        }
501
+
502
+        return true;
503
+    }
504
+
505
+    public function test() {
506
+        $test = $this->getConnection()->getBucketAcl(array(
507
+            'Bucket' => $this->bucket,
508
+        ));
509
+        if (isset($test) && !is_null($test->getPath('Owner/ID'))) {
510
+            return true;
511
+        }
512
+        return false;
513
+    }
514
+
515
+    public function getId() {
516
+        return $this->id;
517
+    }
518
+
519
+    public function writeBack($tmpFile, $path) {
520
+        try {
521
+            $this->getConnection()->putObject(array(
522
+                'Bucket' => $this->bucket,
523
+                'Key' => $this->cleanKey($path),
524
+                'SourceFile' => $tmpFile,
525
+                'ContentType' => \OC::$server->getMimeTypeDetector()->detect($tmpFile),
526
+                'ContentLength' => filesize($tmpFile)
527
+            ));
528
+            $this->testTimeout();
529
+
530
+            unlink($tmpFile);
531
+        } catch (S3Exception $e) {
532
+            \OCP\Util::logException('files_external', $e);
533
+            return false;
534
+        }
535
+    }
536
+
537
+    /**
538
+     * check if curl is installed
539
+     */
540
+    public static function checkDependencies() {
541
+        return true;
542
+    }
543 543
 
544 544
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -36,8 +36,8 @@  discard block
 block discarded – undo
36 36
 
37 37
 namespace OCA\Files_External\Lib\Storage;
38 38
 
39
-set_include_path(get_include_path() . PATH_SEPARATOR .
40
-	\OC_App::getAppPath('files_external') . '/3rdparty/aws-sdk-php');
39
+set_include_path(get_include_path().PATH_SEPARATOR.
40
+	\OC_App::getAppPath('files_external').'/3rdparty/aws-sdk-php');
41 41
 require_once 'aws-autoloader.php';
42 42
 
43 43
 use Aws\S3\S3Client;
@@ -95,8 +95,8 @@  discard block
 block discarded – undo
95 95
 	 *
96 96
 	 * @param array $params
97 97
 	 */
98
-	public function updateLegacyId (array $params) {
99
-		$oldId = 'amazon::' . $params['key'] . md5($params['secret']);
98
+	public function updateLegacyId(array $params) {
99
+		$oldId = 'amazon::'.$params['key'].md5($params['secret']);
100 100
 
101 101
 		// find by old id or bucket
102 102
 		$stmt = \OC::$server->getDatabaseConnection()->prepare(
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
 		try {
149 149
 			$this->getConnection()->putObject(array(
150 150
 				'Bucket' => $this->bucket,
151
-				'Key' => $path . '/',
151
+				'Key' => $path.'/',
152 152
 				'Body' => '',
153 153
 				'ContentType' => 'httpd/unix-directory'
154 154
 			));
@@ -191,12 +191,12 @@  discard block
 block discarded – undo
191 191
 		return false;
192 192
 	}
193 193
 
194
-	private function batchDelete ($path = null) {
194
+	private function batchDelete($path = null) {
195 195
 		$params = array(
196 196
 			'Bucket' => $this->bucket
197 197
 		);
198 198
 		if ($path !== null) {
199
-			$params['Prefix'] = $path . '/';
199
+			$params['Prefix'] = $path.'/';
200 200
 		}
201 201
 		try {
202 202
 			// Since there are no real directories on S3, we need
@@ -279,7 +279,7 @@  discard block
 block discarded – undo
279 279
 			$stat['atime'] = time();
280 280
 
281 281
 			return $stat;
282
-		} catch(S3Exception $e) {
282
+		} catch (S3Exception $e) {
283 283
 			\OCP\Util::logException('files_external', $e);
284 284
 			return false;
285 285
 		}
@@ -394,14 +394,14 @@  discard block
 block discarded – undo
394 394
 		$fileType = $this->filetype($path);
395 395
 		try {
396 396
 			if ($fileType !== false) {
397
-				if ($fileType === 'dir' && ! $this->isRoot($path)) {
397
+				if ($fileType === 'dir' && !$this->isRoot($path)) {
398 398
 					$path .= '/';
399 399
 				}
400 400
 				$this->getConnection()->copyObject([
401 401
 					'Bucket' => $this->bucket,
402 402
 					'Key' => $this->cleanKey($path),
403 403
 					'Metadata' => $metadata,
404
-					'CopySource' => $this->bucket . '/' . $path,
404
+					'CopySource' => $this->bucket.'/'.$path,
405 405
 					'MetadataDirective' => 'REPLACE',
406 406
 				]);
407 407
 				$this->testTimeout();
@@ -434,7 +434,7 @@  discard block
 block discarded – undo
434 434
 				$this->getConnection()->copyObject(array(
435 435
 					'Bucket' => $this->bucket,
436 436
 					'Key' => $this->cleanKey($path2),
437
-					'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1)
437
+					'CopySource' => S3Client::encodeKey($this->bucket.'/'.$path1)
438 438
 				));
439 439
 				$this->testTimeout();
440 440
 			} catch (S3Exception $e) {
@@ -447,8 +447,8 @@  discard block
 block discarded – undo
447 447
 			try {
448 448
 				$this->getConnection()->copyObject(array(
449 449
 					'Bucket' => $this->bucket,
450
-					'Key' => $path2 . '/',
451
-					'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1 . '/')
450
+					'Key' => $path2.'/',
451
+					'CopySource' => S3Client::encodeKey($this->bucket.'/'.$path1.'/')
452 452
 				));
453 453
 				$this->testTimeout();
454 454
 			} catch (S3Exception $e) {
@@ -463,8 +463,8 @@  discard block
 block discarded – undo
463 463
 						continue;
464 464
 					}
465 465
 
466
-					$source = $path1 . '/' . $file;
467
-					$target = $path2 . '/' . $file;
466
+					$source = $path1.'/'.$file;
467
+					$target = $path2.'/'.$file;
468 468
 					$this->copy($source, $target);
469 469
 				}
470 470
 			}
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Storage/Dropbox.php 3 patches
Doc Comments   +6 added lines patch added patch discarded remove patch
@@ -76,6 +76,9 @@  discard block
 block discarded – undo
76 76
 		return false;
77 77
 	}
78 78
 
79
+	/**
80
+	 * @param string $path
81
+	 */
79 82
 	private function setMetaData($path, $metaData) {
80 83
 		$this->metaData[ltrim($path, '/')] = $metaData;
81 84
 	}
@@ -316,6 +319,9 @@  discard block
 block discarded – undo
316 319
 		return false;
317 320
 	}
318 321
 
322
+	/**
323
+	 * @param string $path
324
+	 */
319 325
 	public function writeBack($tmpFile, $path) {
320 326
 		$handle = fopen($tmpFile, 'r');
321 327
 		try {
Please login to merge, or discard this patch.
Indentation   +290 added lines, -290 removed lines patch added patch discarded remove patch
@@ -40,317 +40,317 @@
 block discarded – undo
40 40
 
41 41
 class Dropbox extends \OC\Files\Storage\Common {
42 42
 
43
-	private $dropbox;
44
-	private $root;
45
-	private $id;
46
-	private $metaData = array();
47
-	private $oauth;
43
+    private $dropbox;
44
+    private $root;
45
+    private $id;
46
+    private $metaData = array();
47
+    private $oauth;
48 48
 
49
-	public function __construct($params) {
50
-		if (isset($params['configured']) && $params['configured'] == 'true'
51
-			&& isset($params['app_key'])
52
-			&& isset($params['app_secret'])
53
-			&& isset($params['token'])
54
-			&& isset($params['token_secret'])
55
-		) {
56
-			$this->root = isset($params['root']) ? $params['root'] : '';
57
-			$this->id = 'dropbox::'.$params['app_key'] . $params['token']. '/' . $this->root;
58
-			$this->oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']);
59
-			$this->oauth->setToken($params['token'], $params['token_secret']);
60
-			// note: Dropbox_API connection is lazy
61
-			$this->dropbox = new \Dropbox_API($this->oauth, 'auto');
62
-		} else {
63
-			throw new \Exception('Creating Dropbox storage failed');
64
-		}
65
-	}
49
+    public function __construct($params) {
50
+        if (isset($params['configured']) && $params['configured'] == 'true'
51
+            && isset($params['app_key'])
52
+            && isset($params['app_secret'])
53
+            && isset($params['token'])
54
+            && isset($params['token_secret'])
55
+        ) {
56
+            $this->root = isset($params['root']) ? $params['root'] : '';
57
+            $this->id = 'dropbox::'.$params['app_key'] . $params['token']. '/' . $this->root;
58
+            $this->oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']);
59
+            $this->oauth->setToken($params['token'], $params['token_secret']);
60
+            // note: Dropbox_API connection is lazy
61
+            $this->dropbox = new \Dropbox_API($this->oauth, 'auto');
62
+        } else {
63
+            throw new \Exception('Creating Dropbox storage failed');
64
+        }
65
+    }
66 66
 
67
-	/**
68
-	 * @param string $path
69
-	 */
70
-	private function deleteMetaData($path) {
71
-		$path = ltrim($this->root.$path, '/');
72
-		if (isset($this->metaData[$path])) {
73
-			unset($this->metaData[$path]);
74
-			return true;
75
-		}
76
-		return false;
77
-	}
67
+    /**
68
+     * @param string $path
69
+     */
70
+    private function deleteMetaData($path) {
71
+        $path = ltrim($this->root.$path, '/');
72
+        if (isset($this->metaData[$path])) {
73
+            unset($this->metaData[$path]);
74
+            return true;
75
+        }
76
+        return false;
77
+    }
78 78
 
79
-	private function setMetaData($path, $metaData) {
80
-		$this->metaData[ltrim($path, '/')] = $metaData;
81
-	}
79
+    private function setMetaData($path, $metaData) {
80
+        $this->metaData[ltrim($path, '/')] = $metaData;
81
+    }
82 82
 
83
-	/**
84
-	 * Returns the path's metadata
85
-	 * @param string $path path for which to return the metadata
86
-	 * @param bool $list if true, also return the directory's contents
87
-	 * @return mixed directory contents if $list is true, file metadata if $list is
88
-	 * false, null if the file doesn't exist or "false" if the operation failed
89
-	 */
90
-	private function getDropBoxMetaData($path, $list = false) {
91
-		$path = ltrim($this->root.$path, '/');
92
-		if ( ! $list && isset($this->metaData[$path])) {
93
-			return $this->metaData[$path];
94
-		} else {
95
-			if ($list) {
96
-				try {
97
-					$response = $this->dropbox->getMetaData($path);
98
-				} catch (\Dropbox_Exception_Forbidden $e) {
99
-					throw new StorageNotAvailableException('Dropbox API rate limit exceeded', StorageNotAvailableException::STATUS_ERROR, $e);
100
-				} catch (\Exception $exception) {
101
-					\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
102
-					return false;
103
-				}
104
-				$contents = array();
105
-				if ($response && isset($response['contents'])) {
106
-					// Cache folder's contents
107
-					foreach ($response['contents'] as $file) {
108
-						if (!isset($file['is_deleted']) || !$file['is_deleted']) {
109
-							$this->setMetaData($path.'/'.basename($file['path']), $file);
110
-							$contents[] = $file;
111
-						}
112
-					}
113
-					unset($response['contents']);
114
-				}
115
-				if (!isset($response['is_deleted']) || !$response['is_deleted']) {
116
-					$this->setMetaData($path, $response);
117
-				}
118
-				// Return contents of folder only
119
-				return $contents;
120
-			} else {
121
-				try {
122
-					$requestPath = $path;
123
-					if ($path === '.') {
124
-						$requestPath = '';
125
-					}
83
+    /**
84
+     * Returns the path's metadata
85
+     * @param string $path path for which to return the metadata
86
+     * @param bool $list if true, also return the directory's contents
87
+     * @return mixed directory contents if $list is true, file metadata if $list is
88
+     * false, null if the file doesn't exist or "false" if the operation failed
89
+     */
90
+    private function getDropBoxMetaData($path, $list = false) {
91
+        $path = ltrim($this->root.$path, '/');
92
+        if ( ! $list && isset($this->metaData[$path])) {
93
+            return $this->metaData[$path];
94
+        } else {
95
+            if ($list) {
96
+                try {
97
+                    $response = $this->dropbox->getMetaData($path);
98
+                } catch (\Dropbox_Exception_Forbidden $e) {
99
+                    throw new StorageNotAvailableException('Dropbox API rate limit exceeded', StorageNotAvailableException::STATUS_ERROR, $e);
100
+                } catch (\Exception $exception) {
101
+                    \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
102
+                    return false;
103
+                }
104
+                $contents = array();
105
+                if ($response && isset($response['contents'])) {
106
+                    // Cache folder's contents
107
+                    foreach ($response['contents'] as $file) {
108
+                        if (!isset($file['is_deleted']) || !$file['is_deleted']) {
109
+                            $this->setMetaData($path.'/'.basename($file['path']), $file);
110
+                            $contents[] = $file;
111
+                        }
112
+                    }
113
+                    unset($response['contents']);
114
+                }
115
+                if (!isset($response['is_deleted']) || !$response['is_deleted']) {
116
+                    $this->setMetaData($path, $response);
117
+                }
118
+                // Return contents of folder only
119
+                return $contents;
120
+            } else {
121
+                try {
122
+                    $requestPath = $path;
123
+                    if ($path === '.') {
124
+                        $requestPath = '';
125
+                    }
126 126
 
127
-					$response = $this->dropbox->getMetaData($requestPath, 'false');
128
-					if (!isset($response['is_deleted']) || !$response['is_deleted']) {
129
-						$this->setMetaData($path, $response);
130
-						return $response;
131
-					}
132
-					return null;
133
-				} catch (\Dropbox_Exception_Forbidden $e) {
134
-					throw new StorageNotAvailableException('Dropbox API rate limit exceeded', StorageNotAvailableException::STATUS_ERROR, $e);
135
-				} catch (\Exception $exception) {
136
-					if ($exception instanceof \Dropbox_Exception_NotFound) {
137
-						// don't log, might be a file_exist check
138
-						return false;
139
-					}
140
-					\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
141
-					return false;
142
-				}
143
-			}
144
-		}
145
-	}
127
+                    $response = $this->dropbox->getMetaData($requestPath, 'false');
128
+                    if (!isset($response['is_deleted']) || !$response['is_deleted']) {
129
+                        $this->setMetaData($path, $response);
130
+                        return $response;
131
+                    }
132
+                    return null;
133
+                } catch (\Dropbox_Exception_Forbidden $e) {
134
+                    throw new StorageNotAvailableException('Dropbox API rate limit exceeded', StorageNotAvailableException::STATUS_ERROR, $e);
135
+                } catch (\Exception $exception) {
136
+                    if ($exception instanceof \Dropbox_Exception_NotFound) {
137
+                        // don't log, might be a file_exist check
138
+                        return false;
139
+                    }
140
+                    \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
141
+                    return false;
142
+                }
143
+            }
144
+        }
145
+    }
146 146
 
147
-	public function getId(){
148
-		return $this->id;
149
-	}
147
+    public function getId(){
148
+        return $this->id;
149
+    }
150 150
 
151
-	public function mkdir($path) {
152
-		$path = $this->root.$path;
153
-		try {
154
-			$this->dropbox->createFolder($path);
155
-			return true;
156
-		} catch (\Exception $exception) {
157
-			\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
158
-			return false;
159
-		}
160
-	}
151
+    public function mkdir($path) {
152
+        $path = $this->root.$path;
153
+        try {
154
+            $this->dropbox->createFolder($path);
155
+            return true;
156
+        } catch (\Exception $exception) {
157
+            \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
158
+            return false;
159
+        }
160
+    }
161 161
 
162
-	public function rmdir($path) {
163
-		return $this->unlink($path);
164
-	}
162
+    public function rmdir($path) {
163
+        return $this->unlink($path);
164
+    }
165 165
 
166
-	public function opendir($path) {
167
-		$contents = $this->getDropBoxMetaData($path, true);
168
-		if ($contents !== false) {
169
-			$files = array();
170
-			foreach ($contents as $file) {
171
-				$files[] = basename($file['path']);
172
-			}
173
-			return IteratorDirectory::wrap($files);
174
-		}
175
-		return false;
176
-	}
166
+    public function opendir($path) {
167
+        $contents = $this->getDropBoxMetaData($path, true);
168
+        if ($contents !== false) {
169
+            $files = array();
170
+            foreach ($contents as $file) {
171
+                $files[] = basename($file['path']);
172
+            }
173
+            return IteratorDirectory::wrap($files);
174
+        }
175
+        return false;
176
+    }
177 177
 
178
-	public function stat($path) {
179
-		$metaData = $this->getDropBoxMetaData($path);
180
-		if ($metaData) {
181
-			$stat['size'] = $metaData['bytes'];
182
-			$stat['atime'] = time();
183
-			$stat['mtime'] = (isset($metaData['modified'])) ? strtotime($metaData['modified']) : time();
184
-			return $stat;
185
-		}
186
-		return false;
187
-	}
178
+    public function stat($path) {
179
+        $metaData = $this->getDropBoxMetaData($path);
180
+        if ($metaData) {
181
+            $stat['size'] = $metaData['bytes'];
182
+            $stat['atime'] = time();
183
+            $stat['mtime'] = (isset($metaData['modified'])) ? strtotime($metaData['modified']) : time();
184
+            return $stat;
185
+        }
186
+        return false;
187
+    }
188 188
 
189
-	public function filetype($path) {
190
-		if ($path == '' || $path == '/') {
191
-			return 'dir';
192
-		} else {
193
-			$metaData = $this->getDropBoxMetaData($path);
194
-			if ($metaData) {
195
-				if ($metaData['is_dir'] == 'true') {
196
-					return 'dir';
197
-				} else {
198
-					return 'file';
199
-				}
200
-			}
201
-		}
202
-		return false;
203
-	}
189
+    public function filetype($path) {
190
+        if ($path == '' || $path == '/') {
191
+            return 'dir';
192
+        } else {
193
+            $metaData = $this->getDropBoxMetaData($path);
194
+            if ($metaData) {
195
+                if ($metaData['is_dir'] == 'true') {
196
+                    return 'dir';
197
+                } else {
198
+                    return 'file';
199
+                }
200
+            }
201
+        }
202
+        return false;
203
+    }
204 204
 
205
-	public function file_exists($path) {
206
-		if ($path == '' || $path == '/') {
207
-			return true;
208
-		}
209
-		if ($this->getDropBoxMetaData($path)) {
210
-			return true;
211
-		}
212
-		return false;
213
-	}
205
+    public function file_exists($path) {
206
+        if ($path == '' || $path == '/') {
207
+            return true;
208
+        }
209
+        if ($this->getDropBoxMetaData($path)) {
210
+            return true;
211
+        }
212
+        return false;
213
+    }
214 214
 
215
-	public function unlink($path) {
216
-		try {
217
-			$this->dropbox->delete($this->root.$path);
218
-			$this->deleteMetaData($path);
219
-			return true;
220
-		} catch (\Exception $exception) {
221
-			\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
222
-			return false;
223
-		}
224
-	}
215
+    public function unlink($path) {
216
+        try {
217
+            $this->dropbox->delete($this->root.$path);
218
+            $this->deleteMetaData($path);
219
+            return true;
220
+        } catch (\Exception $exception) {
221
+            \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
222
+            return false;
223
+        }
224
+    }
225 225
 
226
-	public function rename($path1, $path2) {
227
-		try {
228
-			// overwrite if target file exists and is not a directory
229
-			$destMetaData = $this->getDropBoxMetaData($path2);
230
-			if (isset($destMetaData) && $destMetaData !== false && !$destMetaData['is_dir']) {
231
-				$this->unlink($path2);
232
-			}
233
-			$this->dropbox->move($this->root.$path1, $this->root.$path2);
234
-			$this->deleteMetaData($path1);
235
-			return true;
236
-		} catch (\Exception $exception) {
237
-			\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
238
-			return false;
239
-		}
240
-	}
226
+    public function rename($path1, $path2) {
227
+        try {
228
+            // overwrite if target file exists and is not a directory
229
+            $destMetaData = $this->getDropBoxMetaData($path2);
230
+            if (isset($destMetaData) && $destMetaData !== false && !$destMetaData['is_dir']) {
231
+                $this->unlink($path2);
232
+            }
233
+            $this->dropbox->move($this->root.$path1, $this->root.$path2);
234
+            $this->deleteMetaData($path1);
235
+            return true;
236
+        } catch (\Exception $exception) {
237
+            \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
238
+            return false;
239
+        }
240
+    }
241 241
 
242
-	public function copy($path1, $path2) {
243
-		$path1 = $this->root.$path1;
244
-		$path2 = $this->root.$path2;
245
-		try {
246
-			$this->dropbox->copy($path1, $path2);
247
-			return true;
248
-		} catch (\Exception $exception) {
249
-			\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
250
-			return false;
251
-		}
252
-	}
242
+    public function copy($path1, $path2) {
243
+        $path1 = $this->root.$path1;
244
+        $path2 = $this->root.$path2;
245
+        try {
246
+            $this->dropbox->copy($path1, $path2);
247
+            return true;
248
+        } catch (\Exception $exception) {
249
+            \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
250
+            return false;
251
+        }
252
+    }
253 253
 
254
-	public function fopen($path, $mode) {
255
-		$path = $this->root.$path;
256
-		switch ($mode) {
257
-			case 'r':
258
-			case 'rb':
259
-				try {
260
-					// slashes need to stay
261
-					$encodedPath = str_replace('%2F', '/', rawurlencode(trim($path, '/')));
262
-					$downloadUrl = 'https://api-content.dropbox.com/1/files/auto/' . $encodedPath;
263
-					$headers = $this->oauth->getOAuthHeader($downloadUrl, [], 'GET');
254
+    public function fopen($path, $mode) {
255
+        $path = $this->root.$path;
256
+        switch ($mode) {
257
+            case 'r':
258
+            case 'rb':
259
+                try {
260
+                    // slashes need to stay
261
+                    $encodedPath = str_replace('%2F', '/', rawurlencode(trim($path, '/')));
262
+                    $downloadUrl = 'https://api-content.dropbox.com/1/files/auto/' . $encodedPath;
263
+                    $headers = $this->oauth->getOAuthHeader($downloadUrl, [], 'GET');
264 264
 
265
-					$client = \OC::$server->getHTTPClientService()->newClient();
266
-					try {
267
-						$response = $client->get($downloadUrl, [
268
-							'headers' => $headers,
269
-							'stream' => true,
270
-						]);
271
-					} catch (RequestException $e) {
272
-						if (!is_null($e->getResponse())) {
273
-							if ($e->getResponse()->getStatusCode() === 404) {
274
-								return false;
275
-							} else {
276
-								throw $e;
277
-							}
278
-						} else {
279
-							throw $e;
280
-						}
281
-					}
265
+                    $client = \OC::$server->getHTTPClientService()->newClient();
266
+                    try {
267
+                        $response = $client->get($downloadUrl, [
268
+                            'headers' => $headers,
269
+                            'stream' => true,
270
+                        ]);
271
+                    } catch (RequestException $e) {
272
+                        if (!is_null($e->getResponse())) {
273
+                            if ($e->getResponse()->getStatusCode() === 404) {
274
+                                return false;
275
+                            } else {
276
+                                throw $e;
277
+                            }
278
+                        } else {
279
+                            throw $e;
280
+                        }
281
+                    }
282 282
 
283
-					$handle = $response->getBody();
284
-					return RetryWrapper::wrap($handle);
285
-				} catch (\Exception $exception) {
286
-					\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
287
-					return false;
288
-				}
289
-			case 'w':
290
-			case 'wb':
291
-			case 'a':
292
-			case 'ab':
293
-			case 'r+':
294
-			case 'w+':
295
-			case 'wb+':
296
-			case 'a+':
297
-			case 'x':
298
-			case 'x+':
299
-			case 'c':
300
-			case 'c+':
301
-				if (strrpos($path, '.') !== false) {
302
-					$ext = substr($path, strrpos($path, '.'));
303
-				} else {
304
-					$ext = '';
305
-				}
306
-				$tmpFile = \OCP\Files::tmpFile($ext);
307
-				if ($this->file_exists($path)) {
308
-					$source = $this->fopen($path, 'r');
309
-					file_put_contents($tmpFile, $source);
310
-				}
311
-			$handle = fopen($tmpFile, $mode);
312
-			return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
313
-				$this->writeBack($tmpFile, $path);
314
-			});
315
-		}
316
-		return false;
317
-	}
283
+                    $handle = $response->getBody();
284
+                    return RetryWrapper::wrap($handle);
285
+                } catch (\Exception $exception) {
286
+                    \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
287
+                    return false;
288
+                }
289
+            case 'w':
290
+            case 'wb':
291
+            case 'a':
292
+            case 'ab':
293
+            case 'r+':
294
+            case 'w+':
295
+            case 'wb+':
296
+            case 'a+':
297
+            case 'x':
298
+            case 'x+':
299
+            case 'c':
300
+            case 'c+':
301
+                if (strrpos($path, '.') !== false) {
302
+                    $ext = substr($path, strrpos($path, '.'));
303
+                } else {
304
+                    $ext = '';
305
+                }
306
+                $tmpFile = \OCP\Files::tmpFile($ext);
307
+                if ($this->file_exists($path)) {
308
+                    $source = $this->fopen($path, 'r');
309
+                    file_put_contents($tmpFile, $source);
310
+                }
311
+            $handle = fopen($tmpFile, $mode);
312
+            return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
313
+                $this->writeBack($tmpFile, $path);
314
+            });
315
+        }
316
+        return false;
317
+    }
318 318
 
319
-	public function writeBack($tmpFile, $path) {
320
-		$handle = fopen($tmpFile, 'r');
321
-		try {
322
-			$this->dropbox->putFile($path, $handle);
323
-			unlink($tmpFile);
324
-			$this->deleteMetaData($path);
325
-		} catch (\Exception $exception) {
326
-			\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
327
-		}
328
-	}
319
+    public function writeBack($tmpFile, $path) {
320
+        $handle = fopen($tmpFile, 'r');
321
+        try {
322
+            $this->dropbox->putFile($path, $handle);
323
+            unlink($tmpFile);
324
+            $this->deleteMetaData($path);
325
+        } catch (\Exception $exception) {
326
+            \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
327
+        }
328
+    }
329 329
 
330
-	public function free_space($path) {
331
-		try {
332
-			$info = $this->dropbox->getAccountInfo();
333
-			return $info['quota_info']['quota'] - $info['quota_info']['normal'];
334
-		} catch (\Exception $exception) {
335
-			\OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
336
-			return false;
337
-		}
338
-	}
330
+    public function free_space($path) {
331
+        try {
332
+            $info = $this->dropbox->getAccountInfo();
333
+            return $info['quota_info']['quota'] - $info['quota_info']['normal'];
334
+        } catch (\Exception $exception) {
335
+            \OCP\Util::writeLog('files_external', $exception->getMessage(), \OCP\Util::ERROR);
336
+            return false;
337
+        }
338
+    }
339 339
 
340
-	public function touch($path, $mtime = null) {
341
-		if ($this->file_exists($path)) {
342
-			return false;
343
-		} else {
344
-			$this->file_put_contents($path, '');
345
-		}
346
-		return true;
347
-	}
340
+    public function touch($path, $mtime = null) {
341
+        if ($this->file_exists($path)) {
342
+            return false;
343
+        } else {
344
+            $this->file_put_contents($path, '');
345
+        }
346
+        return true;
347
+    }
348 348
 
349
-	/**
350
-	 * check if curl is installed
351
-	 */
352
-	public static function checkDependencies() {
353
-		return true;
354
-	}
349
+    /**
350
+     * check if curl is installed
351
+     */
352
+    public static function checkDependencies() {
353
+        return true;
354
+    }
355 355
 
356 356
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -36,7 +36,7 @@  discard block
 block discarded – undo
36 36
 use Icewind\Streams\RetryWrapper;
37 37
 use OCP\Files\StorageNotAvailableException;
38 38
 
39
-require_once __DIR__ . '/../../../3rdparty/Dropbox/autoload.php';
39
+require_once __DIR__.'/../../../3rdparty/Dropbox/autoload.php';
40 40
 
41 41
 class Dropbox extends \OC\Files\Storage\Common {
42 42
 
@@ -54,7 +54,7 @@  discard block
 block discarded – undo
54 54
 			&& isset($params['token_secret'])
55 55
 		) {
56 56
 			$this->root = isset($params['root']) ? $params['root'] : '';
57
-			$this->id = 'dropbox::'.$params['app_key'] . $params['token']. '/' . $this->root;
57
+			$this->id = 'dropbox::'.$params['app_key'].$params['token'].'/'.$this->root;
58 58
 			$this->oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']);
59 59
 			$this->oauth->setToken($params['token'], $params['token_secret']);
60 60
 			// note: Dropbox_API connection is lazy
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
 	 */
90 90
 	private function getDropBoxMetaData($path, $list = false) {
91 91
 		$path = ltrim($this->root.$path, '/');
92
-		if ( ! $list && isset($this->metaData[$path])) {
92
+		if (!$list && isset($this->metaData[$path])) {
93 93
 			return $this->metaData[$path];
94 94
 		} else {
95 95
 			if ($list) {
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
 		}
145 145
 	}
146 146
 
147
-	public function getId(){
147
+	public function getId() {
148 148
 		return $this->id;
149 149
 	}
150 150
 
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
259 259
 				try {
260 260
 					// slashes need to stay
261 261
 					$encodedPath = str_replace('%2F', '/', rawurlencode(trim($path, '/')));
262
-					$downloadUrl = 'https://api-content.dropbox.com/1/files/auto/' . $encodedPath;
262
+					$downloadUrl = 'https://api-content.dropbox.com/1/files/auto/'.$encodedPath;
263 263
 					$headers = $this->oauth->getOAuthHeader($downloadUrl, [], 'GET');
264 264
 
265 265
 					$client = \OC::$server->getHTTPClientService()->newClient();
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
 					file_put_contents($tmpFile, $source);
310 310
 				}
311 311
 			$handle = fopen($tmpFile, $mode);
312
-			return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
312
+			return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
313 313
 				$this->writeBack($tmpFile, $path);
314 314
 			});
315 315
 		}
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Storage/Google.php 3 patches
Doc Comments   +4 added lines, -1 removed lines patch added patch discarded remove patch
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
 	 *
217 217
 	 * @param \Google_Service_Drive_DriveFile
218 218
 	 *
219
-	 * @return true if the file is a Google Doc file, false otherwise
219
+	 * @return boolean if the file is a Google Doc file, false otherwise
220 220
 	 */
221 221
 	private function isGoogleDocFile($file) {
222 222
 		return $this->getGoogleDocExtension($file->getMimeType()) !== '';
@@ -505,6 +505,9 @@  discard block
 block discarded – undo
505 505
 		}
506 506
 	}
507 507
 
508
+	/**
509
+	 * @param string $path
510
+	 */
508 511
 	public function writeBack($tmpFile, $path) {
509 512
 		$parentFolder = $this->getDriveFile(dirname($path));
510 513
 		if ($parentFolder) {
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -123,7 +123,7 @@  discard block
 block discarded – undo
123 123
 				if (isset($this->driveFiles[$path])) {
124 124
 					$parentId = $this->driveFiles[$path]->getId();
125 125
 				} else {
126
-					$q = "title='" . str_replace("'","\\'", $name) . "' and '" . str_replace("'","\\'", $parentId) . "' in parents and trashed = false";
126
+					$q = "title='".str_replace("'", "\\'", $name)."' and '".str_replace("'", "\\'", $parentId)."' in parents and trashed = false";
127 127
 					$result = $this->service->files->listFiles(array('q' => $q))->getItems();
128 128
 					if (!empty($result)) {
129 129
 						// Google Drive allows files with the same name, Nextcloud doesn't
@@ -236,7 +236,7 @@  discard block
 block discarded – undo
236 236
 				if ($result) {
237 237
 					$this->setDriveFile($path, $result);
238 238
 				}
239
-				return (bool)$result;
239
+				return (bool) $result;
240 240
 			}
241 241
 		}
242 242
 		return false;
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
 		}
249 249
 		if (trim($path, '/') === '') {
250 250
 			$dir = $this->opendir($path);
251
-			if(is_resource($dir)) {
251
+			if (is_resource($dir)) {
252 252
 				while (($file = readdir($dir)) !== false) {
253 253
 					if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
254 254
 						if (!$this->unlink($path.'/'.$file)) {
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
 				if ($pageToken !== true) {
277 277
 					$params['pageToken'] = $pageToken;
278 278
 				}
279
-				$params['q'] = "'" . str_replace("'","\\'", $folder->getId()) . "' in parents and trashed = false";
279
+				$params['q'] = "'".str_replace("'", "\\'", $folder->getId())."' in parents and trashed = false";
280 280
 				$children = $this->service->files->listFiles($params);
281 281
 				foreach ($children->getItems() as $child) {
282 282
 					$name = $child->getTitle();
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
 	}
370 370
 
371 371
 	public function file_exists($path) {
372
-		return (bool)$this->getDriveFile($path);
372
+		return (bool) $this->getDriveFile($path);
373 373
 	}
374 374
 
375 375
 	public function unlink($path) {
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
 			if ($result) {
380 380
 				$this->setDriveFile($path, false);
381 381
 			}
382
-			return (bool)$result;
382
+			return (bool) $result;
383 383
 		} else {
384 384
 			return false;
385 385
 		}
@@ -427,7 +427,7 @@  discard block
 block discarded – undo
427 427
 					}
428 428
 				}
429 429
 			}
430
-			return (bool)$result;
430
+			return (bool) $result;
431 431
 		} else {
432 432
 			return false;
433 433
 		}
@@ -462,10 +462,10 @@  discard block
 block discarded – undo
462 462
 							$response = $client->get($downloadUrl, [
463 463
 								'headers' => $httpRequest->getRequestHeaders(),
464 464
 								'stream' => true,
465
-								'verify' => realpath(__DIR__ . '/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
465
+								'verify' => realpath(__DIR__.'/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
466 466
 							]);
467 467
 						} catch (RequestException $e) {
468
-							if(!is_null($e->getResponse())) {
468
+							if (!is_null($e->getResponse())) {
469 469
 								if ($e->getResponse()->getStatusCode() === 404) {
470 470
 									return false;
471 471
 								} else {
@@ -499,7 +499,7 @@  discard block
 block discarded – undo
499 499
 					file_put_contents($tmpFile, $source);
500 500
 				}
501 501
 				$handle = fopen($tmpFile, $mode);
502
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
502
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
503 503
 					$this->writeBack($tmpFile, $path);
504 504
 				});
505 505
 		}
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
 		if ($result) {
642 642
 			$this->setDriveFile($path, $result);
643 643
 		}
644
-		return (bool)$result;
644
+		return (bool) $result;
645 645
 	}
646 646
 
647 647
 	public function test() {
@@ -668,7 +668,7 @@  discard block
 block discarded – undo
668 668
 					'includeSubscribed' => true,
669 669
 				);
670 670
 				if (isset($startChangeId)) {
671
-					$startChangeId = (int)$startChangeId;
671
+					$startChangeId = (int) $startChangeId;
672 672
 					$largestChangeId = $startChangeId;
673 673
 					$params['startChangeId'] = $startChangeId + 1;
674 674
 				} else {
Please login to merge, or discard this patch.
Indentation   +676 added lines, -676 removed lines patch added patch discarded remove patch
@@ -41,352 +41,352 @@  discard block
 block discarded – undo
41 41
 use Icewind\Streams\RetryWrapper;
42 42
 
43 43
 set_include_path(get_include_path().PATH_SEPARATOR.
44
-	\OC_App::getAppPath('files_external').'/3rdparty/google-api-php-client/src');
44
+    \OC_App::getAppPath('files_external').'/3rdparty/google-api-php-client/src');
45 45
 require_once 'Google/autoload.php';
46 46
 
47 47
 class Google extends \OC\Files\Storage\Common {
48 48
 
49
-	private $client;
50
-	private $id;
51
-	private $service;
52
-	private $driveFiles;
53
-
54
-	// Google Doc mimetypes
55
-	const FOLDER = 'application/vnd.google-apps.folder';
56
-	const DOCUMENT = 'application/vnd.google-apps.document';
57
-	const SPREADSHEET = 'application/vnd.google-apps.spreadsheet';
58
-	const DRAWING = 'application/vnd.google-apps.drawing';
59
-	const PRESENTATION = 'application/vnd.google-apps.presentation';
60
-	const MAP = 'application/vnd.google-apps.map';
61
-
62
-	public function __construct($params) {
63
-		if (isset($params['configured']) && $params['configured'] === 'true'
64
-			&& isset($params['client_id']) && isset($params['client_secret'])
65
-			&& isset($params['token'])
66
-		) {
67
-			$this->client = new \Google_Client();
68
-			$this->client->setClientId($params['client_id']);
69
-			$this->client->setClientSecret($params['client_secret']);
70
-			$this->client->setScopes(array('https://www.googleapis.com/auth/drive'));
71
-			$this->client->setAccessToken($params['token']);
72
-			// if curl isn't available we're likely to run into
73
-			// https://github.com/google/google-api-php-client/issues/59
74
-			// - disable gzip to avoid it.
75
-			if (!function_exists('curl_version') || !function_exists('curl_exec')) {
76
-				$this->client->setClassConfig("Google_Http_Request", "disable_gzip", true);
77
-			}
78
-			// note: API connection is lazy
79
-			$this->service = new \Google_Service_Drive($this->client);
80
-			$token = json_decode($params['token'], true);
81
-			$this->id = 'google::'.substr($params['client_id'], 0, 30).$token['created'];
82
-		} else {
83
-			throw new \Exception('Creating Google storage failed');
84
-		}
85
-	}
86
-
87
-	public function getId() {
88
-		return $this->id;
89
-	}
90
-
91
-	/**
92
-	 * Get the Google_Service_Drive_DriveFile object for the specified path.
93
-	 * Returns false on failure.
94
-	 * @param string $path
95
-	 * @return \Google_Service_Drive_DriveFile|false
96
-	 */
97
-	private function getDriveFile($path) {
98
-		// Remove leading and trailing slashes
99
-		$path = trim($path, '/');
100
-		if ($path === '.') {
101
-			$path = '';
102
-		}
103
-		if (isset($this->driveFiles[$path])) {
104
-			return $this->driveFiles[$path];
105
-		} else if ($path === '') {
106
-			$root = $this->service->files->get('root');
107
-			$this->driveFiles[$path] = $root;
108
-			return $root;
109
-		} else {
110
-			// Google Drive SDK does not have methods for retrieving files by path
111
-			// Instead we must find the id of the parent folder of the file
112
-			$parentId = $this->getDriveFile('')->getId();
113
-			$folderNames = explode('/', $path);
114
-			$path = '';
115
-			// Loop through each folder of this path to get to the file
116
-			foreach ($folderNames as $name) {
117
-				// Reconstruct path from beginning
118
-				if ($path === '') {
119
-					$path .= $name;
120
-				} else {
121
-					$path .= '/'.$name;
122
-				}
123
-				if (isset($this->driveFiles[$path])) {
124
-					$parentId = $this->driveFiles[$path]->getId();
125
-				} else {
126
-					$q = "title='" . str_replace("'","\\'", $name) . "' and '" . str_replace("'","\\'", $parentId) . "' in parents and trashed = false";
127
-					$result = $this->service->files->listFiles(array('q' => $q))->getItems();
128
-					if (!empty($result)) {
129
-						// Google Drive allows files with the same name, Nextcloud doesn't
130
-						if (count($result) > 1) {
131
-							$this->onDuplicateFileDetected($path);
132
-							return false;
133
-						} else {
134
-							$file = current($result);
135
-							$this->driveFiles[$path] = $file;
136
-							$parentId = $file->getId();
137
-						}
138
-					} else {
139
-						// Google Docs have no extension in their title, so try without extension
140
-						$pos = strrpos($path, '.');
141
-						if ($pos !== false) {
142
-							$pathWithoutExt = substr($path, 0, $pos);
143
-							$file = $this->getDriveFile($pathWithoutExt);
144
-							if ($file && $this->isGoogleDocFile($file)) {
145
-								// Switch cached Google_Service_Drive_DriveFile to the correct index
146
-								unset($this->driveFiles[$pathWithoutExt]);
147
-								$this->driveFiles[$path] = $file;
148
-								$parentId = $file->getId();
149
-							} else {
150
-								return false;
151
-							}
152
-						} else {
153
-							return false;
154
-						}
155
-					}
156
-				}
157
-			}
158
-			return $this->driveFiles[$path];
159
-		}
160
-	}
161
-
162
-	/**
163
-	 * Set the Google_Service_Drive_DriveFile object in the cache
164
-	 * @param string $path
165
-	 * @param \Google_Service_Drive_DriveFile|false $file
166
-	 */
167
-	private function setDriveFile($path, $file) {
168
-		$path = trim($path, '/');
169
-		$this->driveFiles[$path] = $file;
170
-		if ($file === false) {
171
-			// Remove all children
172
-			$len = strlen($path);
173
-			foreach ($this->driveFiles as $key => $file) {
174
-				if (substr($key, 0, $len) === $path) {
175
-					unset($this->driveFiles[$key]);
176
-				}
177
-			}
178
-		}
179
-	}
180
-
181
-	/**
182
-	 * Write a log message to inform about duplicate file names
183
-	 * @param string $path
184
-	 */
185
-	private function onDuplicateFileDetected($path) {
186
-		$about = $this->service->about->get();
187
-		$user = $about->getName();
188
-		\OCP\Util::writeLog('files_external',
189
-			'Ignoring duplicate file name: '.$path.' on Google Drive for Google user: '.$user,
190
-			\OCP\Util::INFO
191
-		);
192
-	}
193
-
194
-	/**
195
-	 * Generate file extension for a Google Doc, choosing Open Document formats for download
196
-	 * @param string $mimetype
197
-	 * @return string
198
-	 */
199
-	private function getGoogleDocExtension($mimetype) {
200
-		if ($mimetype === self::DOCUMENT) {
201
-			return 'odt';
202
-		} else if ($mimetype === self::SPREADSHEET) {
203
-			return 'ods';
204
-		} else if ($mimetype === self::DRAWING) {
205
-			return 'jpg';
206
-		} else if ($mimetype === self::PRESENTATION) {
207
-			// Download as .odp is not available
208
-			return 'pdf';
209
-		} else {
210
-			return '';
211
-		}
212
-	}
213
-
214
-	/**
215
-	 * Returns whether the given drive file is a Google Doc file
216
-	 *
217
-	 * @param \Google_Service_Drive_DriveFile
218
-	 *
219
-	 * @return true if the file is a Google Doc file, false otherwise
220
-	 */
221
-	private function isGoogleDocFile($file) {
222
-		return $this->getGoogleDocExtension($file->getMimeType()) !== '';
223
-	}
224
-
225
-	public function mkdir($path) {
226
-		if (!$this->is_dir($path)) {
227
-			$parentFolder = $this->getDriveFile(dirname($path));
228
-			if ($parentFolder) {
229
-				$folder = new \Google_Service_Drive_DriveFile();
230
-				$folder->setTitle(basename($path));
231
-				$folder->setMimeType(self::FOLDER);
232
-				$parent = new \Google_Service_Drive_ParentReference();
233
-				$parent->setId($parentFolder->getId());
234
-				$folder->setParents(array($parent));
235
-				$result = $this->service->files->insert($folder);
236
-				if ($result) {
237
-					$this->setDriveFile($path, $result);
238
-				}
239
-				return (bool)$result;
240
-			}
241
-		}
242
-		return false;
243
-	}
244
-
245
-	public function rmdir($path) {
246
-		if (!$this->isDeletable($path)) {
247
-			return false;
248
-		}
249
-		if (trim($path, '/') === '') {
250
-			$dir = $this->opendir($path);
251
-			if(is_resource($dir)) {
252
-				while (($file = readdir($dir)) !== false) {
253
-					if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
254
-						if (!$this->unlink($path.'/'.$file)) {
255
-							return false;
256
-						}
257
-					}
258
-				}
259
-				closedir($dir);
260
-			}
261
-			$this->driveFiles = array();
262
-			return true;
263
-		} else {
264
-			return $this->unlink($path);
265
-		}
266
-	}
267
-
268
-	public function opendir($path) {
269
-		$folder = $this->getDriveFile($path);
270
-		if ($folder) {
271
-			$files = array();
272
-			$duplicates = array();
273
-			$pageToken = true;
274
-			while ($pageToken) {
275
-				$params = array();
276
-				if ($pageToken !== true) {
277
-					$params['pageToken'] = $pageToken;
278
-				}
279
-				$params['q'] = "'" . str_replace("'","\\'", $folder->getId()) . "' in parents and trashed = false";
280
-				$children = $this->service->files->listFiles($params);
281
-				foreach ($children->getItems() as $child) {
282
-					$name = $child->getTitle();
283
-					// Check if this is a Google Doc i.e. no extension in name
284
-					$extension = $child->getFileExtension();
285
-					if (empty($extension)) {
286
-						if ($child->getMimeType() === self::MAP) {
287
-							continue; // No method known to transfer map files, ignore it
288
-						} else if ($child->getMimeType() !== self::FOLDER) {
289
-							$name .= '.'.$this->getGoogleDocExtension($child->getMimeType());
290
-						}
291
-					}
292
-					if ($path === '') {
293
-						$filepath = $name;
294
-					} else {
295
-						$filepath = $path.'/'.$name;
296
-					}
297
-					// Google Drive allows files with the same name, Nextcloud doesn't
298
-					// Prevent opendir() from returning any duplicate files
299
-					$key = array_search($name, $files);
300
-					if ($key !== false || isset($duplicates[$filepath])) {
301
-						if (!isset($duplicates[$filepath])) {
302
-							$duplicates[$filepath] = true;
303
-							$this->setDriveFile($filepath, false);
304
-							unset($files[$key]);
305
-							$this->onDuplicateFileDetected($filepath);
306
-						}
307
-					} else {
308
-						// Cache the Google_Service_Drive_DriveFile for future use
309
-						$this->setDriveFile($filepath, $child);
310
-						$files[] = $name;
311
-					}
312
-				}
313
-				$pageToken = $children->getNextPageToken();
314
-			}
315
-			return IteratorDirectory::wrap($files);
316
-		} else {
317
-			return false;
318
-		}
319
-	}
320
-
321
-	public function stat($path) {
322
-		$file = $this->getDriveFile($path);
323
-		if ($file) {
324
-			$stat = array();
325
-			if ($this->filetype($path) === 'dir') {
326
-				$stat['size'] = 0;
327
-			} else {
328
-				// Check if this is a Google Doc
329
-				if ($this->isGoogleDocFile($file)) {
330
-					// Return unknown file size
331
-					$stat['size'] = \OCP\Files\FileInfo::SPACE_UNKNOWN;
332
-				} else {
333
-					$stat['size'] = $file->getFileSize();
334
-				}
335
-			}
336
-			$stat['atime'] = strtotime($file->getLastViewedByMeDate());
337
-			$stat['mtime'] = strtotime($file->getModifiedDate());
338
-			$stat['ctime'] = strtotime($file->getCreatedDate());
339
-			return $stat;
340
-		} else {
341
-			return false;
342
-		}
343
-	}
344
-
345
-	public function filetype($path) {
346
-		if ($path === '') {
347
-			return 'dir';
348
-		} else {
349
-			$file = $this->getDriveFile($path);
350
-			if ($file) {
351
-				if ($file->getMimeType() === self::FOLDER) {
352
-					return 'dir';
353
-				} else {
354
-					return 'file';
355
-				}
356
-			} else {
357
-				return false;
358
-			}
359
-		}
360
-	}
361
-
362
-	public function isUpdatable($path) {
363
-		$file = $this->getDriveFile($path);
364
-		if ($file) {
365
-			return $file->getEditable();
366
-		} else {
367
-			return false;
368
-		}
369
-	}
370
-
371
-	public function file_exists($path) {
372
-		return (bool)$this->getDriveFile($path);
373
-	}
374
-
375
-	public function unlink($path) {
376
-		$file = $this->getDriveFile($path);
377
-		if ($file) {
378
-			$result = $this->service->files->trash($file->getId());
379
-			if ($result) {
380
-				$this->setDriveFile($path, false);
381
-			}
382
-			return (bool)$result;
383
-		} else {
384
-			return false;
385
-		}
386
-	}
387
-
388
-	public function rename($path1, $path2) {
389
-		// Avoid duplicate files with the same name
49
+    private $client;
50
+    private $id;
51
+    private $service;
52
+    private $driveFiles;
53
+
54
+    // Google Doc mimetypes
55
+    const FOLDER = 'application/vnd.google-apps.folder';
56
+    const DOCUMENT = 'application/vnd.google-apps.document';
57
+    const SPREADSHEET = 'application/vnd.google-apps.spreadsheet';
58
+    const DRAWING = 'application/vnd.google-apps.drawing';
59
+    const PRESENTATION = 'application/vnd.google-apps.presentation';
60
+    const MAP = 'application/vnd.google-apps.map';
61
+
62
+    public function __construct($params) {
63
+        if (isset($params['configured']) && $params['configured'] === 'true'
64
+            && isset($params['client_id']) && isset($params['client_secret'])
65
+            && isset($params['token'])
66
+        ) {
67
+            $this->client = new \Google_Client();
68
+            $this->client->setClientId($params['client_id']);
69
+            $this->client->setClientSecret($params['client_secret']);
70
+            $this->client->setScopes(array('https://www.googleapis.com/auth/drive'));
71
+            $this->client->setAccessToken($params['token']);
72
+            // if curl isn't available we're likely to run into
73
+            // https://github.com/google/google-api-php-client/issues/59
74
+            // - disable gzip to avoid it.
75
+            if (!function_exists('curl_version') || !function_exists('curl_exec')) {
76
+                $this->client->setClassConfig("Google_Http_Request", "disable_gzip", true);
77
+            }
78
+            // note: API connection is lazy
79
+            $this->service = new \Google_Service_Drive($this->client);
80
+            $token = json_decode($params['token'], true);
81
+            $this->id = 'google::'.substr($params['client_id'], 0, 30).$token['created'];
82
+        } else {
83
+            throw new \Exception('Creating Google storage failed');
84
+        }
85
+    }
86
+
87
+    public function getId() {
88
+        return $this->id;
89
+    }
90
+
91
+    /**
92
+     * Get the Google_Service_Drive_DriveFile object for the specified path.
93
+     * Returns false on failure.
94
+     * @param string $path
95
+     * @return \Google_Service_Drive_DriveFile|false
96
+     */
97
+    private function getDriveFile($path) {
98
+        // Remove leading and trailing slashes
99
+        $path = trim($path, '/');
100
+        if ($path === '.') {
101
+            $path = '';
102
+        }
103
+        if (isset($this->driveFiles[$path])) {
104
+            return $this->driveFiles[$path];
105
+        } else if ($path === '') {
106
+            $root = $this->service->files->get('root');
107
+            $this->driveFiles[$path] = $root;
108
+            return $root;
109
+        } else {
110
+            // Google Drive SDK does not have methods for retrieving files by path
111
+            // Instead we must find the id of the parent folder of the file
112
+            $parentId = $this->getDriveFile('')->getId();
113
+            $folderNames = explode('/', $path);
114
+            $path = '';
115
+            // Loop through each folder of this path to get to the file
116
+            foreach ($folderNames as $name) {
117
+                // Reconstruct path from beginning
118
+                if ($path === '') {
119
+                    $path .= $name;
120
+                } else {
121
+                    $path .= '/'.$name;
122
+                }
123
+                if (isset($this->driveFiles[$path])) {
124
+                    $parentId = $this->driveFiles[$path]->getId();
125
+                } else {
126
+                    $q = "title='" . str_replace("'","\\'", $name) . "' and '" . str_replace("'","\\'", $parentId) . "' in parents and trashed = false";
127
+                    $result = $this->service->files->listFiles(array('q' => $q))->getItems();
128
+                    if (!empty($result)) {
129
+                        // Google Drive allows files with the same name, Nextcloud doesn't
130
+                        if (count($result) > 1) {
131
+                            $this->onDuplicateFileDetected($path);
132
+                            return false;
133
+                        } else {
134
+                            $file = current($result);
135
+                            $this->driveFiles[$path] = $file;
136
+                            $parentId = $file->getId();
137
+                        }
138
+                    } else {
139
+                        // Google Docs have no extension in their title, so try without extension
140
+                        $pos = strrpos($path, '.');
141
+                        if ($pos !== false) {
142
+                            $pathWithoutExt = substr($path, 0, $pos);
143
+                            $file = $this->getDriveFile($pathWithoutExt);
144
+                            if ($file && $this->isGoogleDocFile($file)) {
145
+                                // Switch cached Google_Service_Drive_DriveFile to the correct index
146
+                                unset($this->driveFiles[$pathWithoutExt]);
147
+                                $this->driveFiles[$path] = $file;
148
+                                $parentId = $file->getId();
149
+                            } else {
150
+                                return false;
151
+                            }
152
+                        } else {
153
+                            return false;
154
+                        }
155
+                    }
156
+                }
157
+            }
158
+            return $this->driveFiles[$path];
159
+        }
160
+    }
161
+
162
+    /**
163
+     * Set the Google_Service_Drive_DriveFile object in the cache
164
+     * @param string $path
165
+     * @param \Google_Service_Drive_DriveFile|false $file
166
+     */
167
+    private function setDriveFile($path, $file) {
168
+        $path = trim($path, '/');
169
+        $this->driveFiles[$path] = $file;
170
+        if ($file === false) {
171
+            // Remove all children
172
+            $len = strlen($path);
173
+            foreach ($this->driveFiles as $key => $file) {
174
+                if (substr($key, 0, $len) === $path) {
175
+                    unset($this->driveFiles[$key]);
176
+                }
177
+            }
178
+        }
179
+    }
180
+
181
+    /**
182
+     * Write a log message to inform about duplicate file names
183
+     * @param string $path
184
+     */
185
+    private function onDuplicateFileDetected($path) {
186
+        $about = $this->service->about->get();
187
+        $user = $about->getName();
188
+        \OCP\Util::writeLog('files_external',
189
+            'Ignoring duplicate file name: '.$path.' on Google Drive for Google user: '.$user,
190
+            \OCP\Util::INFO
191
+        );
192
+    }
193
+
194
+    /**
195
+     * Generate file extension for a Google Doc, choosing Open Document formats for download
196
+     * @param string $mimetype
197
+     * @return string
198
+     */
199
+    private function getGoogleDocExtension($mimetype) {
200
+        if ($mimetype === self::DOCUMENT) {
201
+            return 'odt';
202
+        } else if ($mimetype === self::SPREADSHEET) {
203
+            return 'ods';
204
+        } else if ($mimetype === self::DRAWING) {
205
+            return 'jpg';
206
+        } else if ($mimetype === self::PRESENTATION) {
207
+            // Download as .odp is not available
208
+            return 'pdf';
209
+        } else {
210
+            return '';
211
+        }
212
+    }
213
+
214
+    /**
215
+     * Returns whether the given drive file is a Google Doc file
216
+     *
217
+     * @param \Google_Service_Drive_DriveFile
218
+     *
219
+     * @return true if the file is a Google Doc file, false otherwise
220
+     */
221
+    private function isGoogleDocFile($file) {
222
+        return $this->getGoogleDocExtension($file->getMimeType()) !== '';
223
+    }
224
+
225
+    public function mkdir($path) {
226
+        if (!$this->is_dir($path)) {
227
+            $parentFolder = $this->getDriveFile(dirname($path));
228
+            if ($parentFolder) {
229
+                $folder = new \Google_Service_Drive_DriveFile();
230
+                $folder->setTitle(basename($path));
231
+                $folder->setMimeType(self::FOLDER);
232
+                $parent = new \Google_Service_Drive_ParentReference();
233
+                $parent->setId($parentFolder->getId());
234
+                $folder->setParents(array($parent));
235
+                $result = $this->service->files->insert($folder);
236
+                if ($result) {
237
+                    $this->setDriveFile($path, $result);
238
+                }
239
+                return (bool)$result;
240
+            }
241
+        }
242
+        return false;
243
+    }
244
+
245
+    public function rmdir($path) {
246
+        if (!$this->isDeletable($path)) {
247
+            return false;
248
+        }
249
+        if (trim($path, '/') === '') {
250
+            $dir = $this->opendir($path);
251
+            if(is_resource($dir)) {
252
+                while (($file = readdir($dir)) !== false) {
253
+                    if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
254
+                        if (!$this->unlink($path.'/'.$file)) {
255
+                            return false;
256
+                        }
257
+                    }
258
+                }
259
+                closedir($dir);
260
+            }
261
+            $this->driveFiles = array();
262
+            return true;
263
+        } else {
264
+            return $this->unlink($path);
265
+        }
266
+    }
267
+
268
+    public function opendir($path) {
269
+        $folder = $this->getDriveFile($path);
270
+        if ($folder) {
271
+            $files = array();
272
+            $duplicates = array();
273
+            $pageToken = true;
274
+            while ($pageToken) {
275
+                $params = array();
276
+                if ($pageToken !== true) {
277
+                    $params['pageToken'] = $pageToken;
278
+                }
279
+                $params['q'] = "'" . str_replace("'","\\'", $folder->getId()) . "' in parents and trashed = false";
280
+                $children = $this->service->files->listFiles($params);
281
+                foreach ($children->getItems() as $child) {
282
+                    $name = $child->getTitle();
283
+                    // Check if this is a Google Doc i.e. no extension in name
284
+                    $extension = $child->getFileExtension();
285
+                    if (empty($extension)) {
286
+                        if ($child->getMimeType() === self::MAP) {
287
+                            continue; // No method known to transfer map files, ignore it
288
+                        } else if ($child->getMimeType() !== self::FOLDER) {
289
+                            $name .= '.'.$this->getGoogleDocExtension($child->getMimeType());
290
+                        }
291
+                    }
292
+                    if ($path === '') {
293
+                        $filepath = $name;
294
+                    } else {
295
+                        $filepath = $path.'/'.$name;
296
+                    }
297
+                    // Google Drive allows files with the same name, Nextcloud doesn't
298
+                    // Prevent opendir() from returning any duplicate files
299
+                    $key = array_search($name, $files);
300
+                    if ($key !== false || isset($duplicates[$filepath])) {
301
+                        if (!isset($duplicates[$filepath])) {
302
+                            $duplicates[$filepath] = true;
303
+                            $this->setDriveFile($filepath, false);
304
+                            unset($files[$key]);
305
+                            $this->onDuplicateFileDetected($filepath);
306
+                        }
307
+                    } else {
308
+                        // Cache the Google_Service_Drive_DriveFile for future use
309
+                        $this->setDriveFile($filepath, $child);
310
+                        $files[] = $name;
311
+                    }
312
+                }
313
+                $pageToken = $children->getNextPageToken();
314
+            }
315
+            return IteratorDirectory::wrap($files);
316
+        } else {
317
+            return false;
318
+        }
319
+    }
320
+
321
+    public function stat($path) {
322
+        $file = $this->getDriveFile($path);
323
+        if ($file) {
324
+            $stat = array();
325
+            if ($this->filetype($path) === 'dir') {
326
+                $stat['size'] = 0;
327
+            } else {
328
+                // Check if this is a Google Doc
329
+                if ($this->isGoogleDocFile($file)) {
330
+                    // Return unknown file size
331
+                    $stat['size'] = \OCP\Files\FileInfo::SPACE_UNKNOWN;
332
+                } else {
333
+                    $stat['size'] = $file->getFileSize();
334
+                }
335
+            }
336
+            $stat['atime'] = strtotime($file->getLastViewedByMeDate());
337
+            $stat['mtime'] = strtotime($file->getModifiedDate());
338
+            $stat['ctime'] = strtotime($file->getCreatedDate());
339
+            return $stat;
340
+        } else {
341
+            return false;
342
+        }
343
+    }
344
+
345
+    public function filetype($path) {
346
+        if ($path === '') {
347
+            return 'dir';
348
+        } else {
349
+            $file = $this->getDriveFile($path);
350
+            if ($file) {
351
+                if ($file->getMimeType() === self::FOLDER) {
352
+                    return 'dir';
353
+                } else {
354
+                    return 'file';
355
+                }
356
+            } else {
357
+                return false;
358
+            }
359
+        }
360
+    }
361
+
362
+    public function isUpdatable($path) {
363
+        $file = $this->getDriveFile($path);
364
+        if ($file) {
365
+            return $file->getEditable();
366
+        } else {
367
+            return false;
368
+        }
369
+    }
370
+
371
+    public function file_exists($path) {
372
+        return (bool)$this->getDriveFile($path);
373
+    }
374
+
375
+    public function unlink($path) {
376
+        $file = $this->getDriveFile($path);
377
+        if ($file) {
378
+            $result = $this->service->files->trash($file->getId());
379
+            if ($result) {
380
+                $this->setDriveFile($path, false);
381
+            }
382
+            return (bool)$result;
383
+        } else {
384
+            return false;
385
+        }
386
+    }
387
+
388
+    public function rename($path1, $path2) {
389
+        // Avoid duplicate files with the same name
390 390
                 $testRegex = '/^.+\.ocTransferId\d+\.part$/';
391 391
                 if (preg_match($testRegex, $path1)) {
392 392
                         if ($this->is_file($path2)) {
@@ -399,339 +399,339 @@  discard block
 block discarded – undo
399 399
                         }
400 400
                 }
401 401
 		
402
-		$file = $this->getDriveFile($path1);
403
-		if ($file) {
404
-			$newFile = $this->getDriveFile($path2);
405
-			if (dirname($path1) === dirname($path2)) {
406
-				if ($newFile) {
407
-					// rename to the name of the target file, could be an office file without extension
408
-					$file->setTitle($newFile->getTitle());
409
-				} else {
410
-					$file->setTitle(basename(($path2)));
411
-				}
412
-			} else {
413
-				// Change file parent
414
-				$parentFolder2 = $this->getDriveFile(dirname($path2));
415
-				if ($parentFolder2) {
416
-					$parent = new \Google_Service_Drive_ParentReference();
417
-					$parent->setId($parentFolder2->getId());
418
-					$file->setParents(array($parent));
419
-				} else {
420
-					return false;
421
-				}
422
-			}
423
-			// We need to get the object for the existing file with the same
424
-			// name (if there is one) before we do the patch. If oldfile
425
-			// exists and is a directory we have to delete it before we
426
-			// do the rename too.
427
-			$oldfile = $this->getDriveFile($path2);
428
-			if ($oldfile && $this->is_dir($path2)) {
429
-				$this->rmdir($path2);
430
-				$oldfile = false;
431
-			}
432
-			$result = $this->service->files->patch($file->getId(), $file);
433
-			if ($result) {
434
-				$this->setDriveFile($path1, false);
435
-				$this->setDriveFile($path2, $result);
436
-				if ($oldfile && $newFile) {
437
-					// only delete if they have a different id (same id can happen for part files)
438
-					if ($newFile->getId() !== $oldfile->getId()) {
439
-						$this->service->files->delete($oldfile->getId());
440
-					}
441
-				}
442
-			}
443
-			return (bool)$result;
444
-		} else {
445
-			return false;
446
-		}
447
-	}
448
-
449
-	public function fopen($path, $mode) {
450
-		$pos = strrpos($path, '.');
451
-		if ($pos !== false) {
452
-			$ext = substr($path, $pos);
453
-		} else {
454
-			$ext = '';
455
-		}
456
-		switch ($mode) {
457
-			case 'r':
458
-			case 'rb':
459
-				$file = $this->getDriveFile($path);
460
-				if ($file) {
461
-					$exportLinks = $file->getExportLinks();
462
-					$mimetype = $this->getMimeType($path);
463
-					$downloadUrl = null;
464
-					if ($exportLinks && isset($exportLinks[$mimetype])) {
465
-						$downloadUrl = $exportLinks[$mimetype];
466
-					} else {
467
-						$downloadUrl = $file->getDownloadUrl();
468
-					}
469
-					if (isset($downloadUrl)) {
470
-						$request = new \Google_Http_Request($downloadUrl, 'GET', null, null);
471
-						$httpRequest = $this->client->getAuth()->sign($request);
472
-						// the library's service doesn't support streaming, so we use Guzzle instead
473
-						$client = \OC::$server->getHTTPClientService()->newClient();
474
-						try {
475
-							$response = $client->get($downloadUrl, [
476
-								'headers' => $httpRequest->getRequestHeaders(),
477
-								'stream' => true,
478
-								'verify' => realpath(__DIR__ . '/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
479
-							]);
480
-						} catch (RequestException $e) {
481
-							if(!is_null($e->getResponse())) {
482
-								if ($e->getResponse()->getStatusCode() === 404) {
483
-									return false;
484
-								} else {
485
-									throw $e;
486
-								}
487
-							} else {
488
-								throw $e;
489
-							}
490
-						}
491
-
492
-						$handle = $response->getBody();
493
-						return RetryWrapper::wrap($handle);
494
-					}
495
-				}
496
-				return false;
497
-			case 'w':
498
-			case 'wb':
499
-			case 'a':
500
-			case 'ab':
501
-			case 'r+':
502
-			case 'w+':
503
-			case 'wb+':
504
-			case 'a+':
505
-			case 'x':
506
-			case 'x+':
507
-			case 'c':
508
-			case 'c+':
509
-				$tmpFile = \OCP\Files::tmpFile($ext);
510
-				if ($this->file_exists($path)) {
511
-					$source = $this->fopen($path, 'rb');
512
-					file_put_contents($tmpFile, $source);
513
-				}
514
-				$handle = fopen($tmpFile, $mode);
515
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
516
-					$this->writeBack($tmpFile, $path);
517
-				});
518
-		}
519
-	}
520
-
521
-	public function writeBack($tmpFile, $path) {
522
-		$parentFolder = $this->getDriveFile(dirname($path));
523
-		if ($parentFolder) {
524
-			$mimetype = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
525
-			$params = array(
526
-				'mimeType' => $mimetype,
527
-				'uploadType' => 'media'
528
-			);
529
-			$result = false;
530
-
531
-			$chunkSizeBytes = 10 * 1024 * 1024;
532
-
533
-			$useChunking = false;
534
-			$size = filesize($tmpFile);
535
-			if ($size > $chunkSizeBytes) {
536
-				$useChunking = true;
537
-			} else {
538
-				$params['data'] = file_get_contents($tmpFile);
539
-			}
540
-
541
-			if ($this->file_exists($path)) {
542
-				$file = $this->getDriveFile($path);
543
-				$this->client->setDefer($useChunking);
544
-				$request = $this->service->files->update($file->getId(), $file, $params);
545
-			} else {
546
-				$file = new \Google_Service_Drive_DriveFile();
547
-				$file->setTitle(basename($path));
548
-				$file->setMimeType($mimetype);
549
-				$parent = new \Google_Service_Drive_ParentReference();
550
-				$parent->setId($parentFolder->getId());
551
-				$file->setParents(array($parent));
552
-				$this->client->setDefer($useChunking);
553
-				$request = $this->service->files->insert($file, $params);
554
-			}
555
-
556
-			if ($useChunking) {
557
-				// Create a media file upload to represent our upload process.
558
-				$media = new \Google_Http_MediaFileUpload(
559
-					$this->client,
560
-					$request,
561
-					'text/plain',
562
-					null,
563
-					true,
564
-					$chunkSizeBytes
565
-				);
566
-				$media->setFileSize($size);
567
-
568
-				// Upload the various chunks. $status will be false until the process is
569
-				// complete.
570
-				$status = false;
571
-				$handle = fopen($tmpFile, 'rb');
572
-				while (!$status && !feof($handle)) {
573
-					$chunk = fread($handle, $chunkSizeBytes);
574
-					$status = $media->nextChunk($chunk);
575
-				}
576
-
577
-				// The final value of $status will be the data from the API for the object
578
-				// that has been uploaded.
579
-				$result = false;
580
-				if ($status !== false) {
581
-					$result = $status;
582
-				}
583
-
584
-				fclose($handle);
585
-			} else {
586
-				$result = $request;
587
-			}
588
-
589
-			// Reset to the client to execute requests immediately in the future.
590
-			$this->client->setDefer(false);
591
-
592
-			if ($result) {
593
-				$this->setDriveFile($path, $result);
594
-			}
595
-		}
596
-	}
597
-
598
-	public function getMimeType($path) {
599
-		$file = $this->getDriveFile($path);
600
-		if ($file) {
601
-			$mimetype = $file->getMimeType();
602
-			// Convert Google Doc mimetypes, choosing Open Document formats for download
603
-			if ($mimetype === self::FOLDER) {
604
-				return 'httpd/unix-directory';
605
-			} else if ($mimetype === self::DOCUMENT) {
606
-				return 'application/vnd.oasis.opendocument.text';
607
-			} else if ($mimetype === self::SPREADSHEET) {
608
-				return 'application/x-vnd.oasis.opendocument.spreadsheet';
609
-			} else if ($mimetype === self::DRAWING) {
610
-				return 'image/jpeg';
611
-			} else if ($mimetype === self::PRESENTATION) {
612
-				// Download as .odp is not available
613
-				return 'application/pdf';
614
-			} else {
615
-				// use extension-based detection, could be an encrypted file
616
-				return parent::getMimeType($path);
617
-			}
618
-		} else {
619
-			return false;
620
-		}
621
-	}
622
-
623
-	public function free_space($path) {
624
-		$about = $this->service->about->get();
625
-		return $about->getQuotaBytesTotal() - $about->getQuotaBytesUsed();
626
-	}
627
-
628
-	public function touch($path, $mtime = null) {
629
-		$file = $this->getDriveFile($path);
630
-		$result = false;
631
-		if ($file) {
632
-			if (isset($mtime)) {
633
-				// This is just RFC3339, but frustratingly, GDrive's API *requires*
634
-				// the fractions portion be present, while no handy PHP constant
635
-				// for RFC3339 or ISO8601 includes it. So we do it ourselves.
636
-				$file->setModifiedDate(date('Y-m-d\TH:i:s.uP', $mtime));
637
-				$result = $this->service->files->patch($file->getId(), $file, array(
638
-					'setModifiedDate' => true,
639
-				));
640
-			} else {
641
-				$result = $this->service->files->touch($file->getId());
642
-			}
643
-		} else {
644
-			$parentFolder = $this->getDriveFile(dirname($path));
645
-			if ($parentFolder) {
646
-				$file = new \Google_Service_Drive_DriveFile();
647
-				$file->setTitle(basename($path));
648
-				$parent = new \Google_Service_Drive_ParentReference();
649
-				$parent->setId($parentFolder->getId());
650
-				$file->setParents(array($parent));
651
-				$result = $this->service->files->insert($file);
652
-			}
653
-		}
654
-		if ($result) {
655
-			$this->setDriveFile($path, $result);
656
-		}
657
-		return (bool)$result;
658
-	}
659
-
660
-	public function test() {
661
-		if ($this->free_space('')) {
662
-			return true;
663
-		}
664
-		return false;
665
-	}
666
-
667
-	public function hasUpdated($path, $time) {
668
-		$appConfig = \OC::$server->getAppConfig();
669
-		if ($this->is_file($path)) {
670
-			return parent::hasUpdated($path, $time);
671
-		} else {
672
-			// Google Drive doesn't change modified times of folders when files inside are updated
673
-			// Instead we use the Changes API to see if folders have been updated, and it's a pain
674
-			$folder = $this->getDriveFile($path);
675
-			if ($folder) {
676
-				$result = false;
677
-				$folderId = $folder->getId();
678
-				$startChangeId = $appConfig->getValue('files_external', $this->getId().'cId');
679
-				$params = array(
680
-					'includeDeleted' => true,
681
-					'includeSubscribed' => true,
682
-				);
683
-				if (isset($startChangeId)) {
684
-					$startChangeId = (int)$startChangeId;
685
-					$largestChangeId = $startChangeId;
686
-					$params['startChangeId'] = $startChangeId + 1;
687
-				} else {
688
-					$largestChangeId = 0;
689
-				}
690
-				$pageToken = true;
691
-				while ($pageToken) {
692
-					if ($pageToken !== true) {
693
-						$params['pageToken'] = $pageToken;
694
-					}
695
-					$changes = $this->service->changes->listChanges($params);
696
-					if ($largestChangeId === 0 || $largestChangeId === $startChangeId) {
697
-						$largestChangeId = $changes->getLargestChangeId();
698
-					}
699
-					if (isset($startChangeId)) {
700
-						// Check if a file in this folder has been updated
701
-						// There is no way to filter by folder at the API level...
702
-						foreach ($changes->getItems() as $change) {
703
-							$file = $change->getFile();
704
-							if ($file) {
705
-								foreach ($file->getParents() as $parent) {
706
-									if ($parent->getId() === $folderId) {
707
-										$result = true;
708
-									// Check if there are changes in different folders
709
-									} else if ($change->getId() <= $largestChangeId) {
710
-										// Decrement id so this change is fetched when called again
711
-										$largestChangeId = $change->getId();
712
-										$largestChangeId--;
713
-									}
714
-								}
715
-							}
716
-						}
717
-						$pageToken = $changes->getNextPageToken();
718
-					} else {
719
-						// Assuming the initial scan just occurred and changes are negligible
720
-						break;
721
-					}
722
-				}
723
-				$appConfig->setValue('files_external', $this->getId().'cId', $largestChangeId);
724
-				return $result;
725
-			}
726
-		}
727
-		return false;
728
-	}
729
-
730
-	/**
731
-	 * check if curl is installed
732
-	 */
733
-	public static function checkDependencies() {
734
-		return true;
735
-	}
402
+        $file = $this->getDriveFile($path1);
403
+        if ($file) {
404
+            $newFile = $this->getDriveFile($path2);
405
+            if (dirname($path1) === dirname($path2)) {
406
+                if ($newFile) {
407
+                    // rename to the name of the target file, could be an office file without extension
408
+                    $file->setTitle($newFile->getTitle());
409
+                } else {
410
+                    $file->setTitle(basename(($path2)));
411
+                }
412
+            } else {
413
+                // Change file parent
414
+                $parentFolder2 = $this->getDriveFile(dirname($path2));
415
+                if ($parentFolder2) {
416
+                    $parent = new \Google_Service_Drive_ParentReference();
417
+                    $parent->setId($parentFolder2->getId());
418
+                    $file->setParents(array($parent));
419
+                } else {
420
+                    return false;
421
+                }
422
+            }
423
+            // We need to get the object for the existing file with the same
424
+            // name (if there is one) before we do the patch. If oldfile
425
+            // exists and is a directory we have to delete it before we
426
+            // do the rename too.
427
+            $oldfile = $this->getDriveFile($path2);
428
+            if ($oldfile && $this->is_dir($path2)) {
429
+                $this->rmdir($path2);
430
+                $oldfile = false;
431
+            }
432
+            $result = $this->service->files->patch($file->getId(), $file);
433
+            if ($result) {
434
+                $this->setDriveFile($path1, false);
435
+                $this->setDriveFile($path2, $result);
436
+                if ($oldfile && $newFile) {
437
+                    // only delete if they have a different id (same id can happen for part files)
438
+                    if ($newFile->getId() !== $oldfile->getId()) {
439
+                        $this->service->files->delete($oldfile->getId());
440
+                    }
441
+                }
442
+            }
443
+            return (bool)$result;
444
+        } else {
445
+            return false;
446
+        }
447
+    }
448
+
449
+    public function fopen($path, $mode) {
450
+        $pos = strrpos($path, '.');
451
+        if ($pos !== false) {
452
+            $ext = substr($path, $pos);
453
+        } else {
454
+            $ext = '';
455
+        }
456
+        switch ($mode) {
457
+            case 'r':
458
+            case 'rb':
459
+                $file = $this->getDriveFile($path);
460
+                if ($file) {
461
+                    $exportLinks = $file->getExportLinks();
462
+                    $mimetype = $this->getMimeType($path);
463
+                    $downloadUrl = null;
464
+                    if ($exportLinks && isset($exportLinks[$mimetype])) {
465
+                        $downloadUrl = $exportLinks[$mimetype];
466
+                    } else {
467
+                        $downloadUrl = $file->getDownloadUrl();
468
+                    }
469
+                    if (isset($downloadUrl)) {
470
+                        $request = new \Google_Http_Request($downloadUrl, 'GET', null, null);
471
+                        $httpRequest = $this->client->getAuth()->sign($request);
472
+                        // the library's service doesn't support streaming, so we use Guzzle instead
473
+                        $client = \OC::$server->getHTTPClientService()->newClient();
474
+                        try {
475
+                            $response = $client->get($downloadUrl, [
476
+                                'headers' => $httpRequest->getRequestHeaders(),
477
+                                'stream' => true,
478
+                                'verify' => realpath(__DIR__ . '/../../../3rdparty/google-api-php-client/src/Google/IO/cacerts.pem'),
479
+                            ]);
480
+                        } catch (RequestException $e) {
481
+                            if(!is_null($e->getResponse())) {
482
+                                if ($e->getResponse()->getStatusCode() === 404) {
483
+                                    return false;
484
+                                } else {
485
+                                    throw $e;
486
+                                }
487
+                            } else {
488
+                                throw $e;
489
+                            }
490
+                        }
491
+
492
+                        $handle = $response->getBody();
493
+                        return RetryWrapper::wrap($handle);
494
+                    }
495
+                }
496
+                return false;
497
+            case 'w':
498
+            case 'wb':
499
+            case 'a':
500
+            case 'ab':
501
+            case 'r+':
502
+            case 'w+':
503
+            case 'wb+':
504
+            case 'a+':
505
+            case 'x':
506
+            case 'x+':
507
+            case 'c':
508
+            case 'c+':
509
+                $tmpFile = \OCP\Files::tmpFile($ext);
510
+                if ($this->file_exists($path)) {
511
+                    $source = $this->fopen($path, 'rb');
512
+                    file_put_contents($tmpFile, $source);
513
+                }
514
+                $handle = fopen($tmpFile, $mode);
515
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
516
+                    $this->writeBack($tmpFile, $path);
517
+                });
518
+        }
519
+    }
520
+
521
+    public function writeBack($tmpFile, $path) {
522
+        $parentFolder = $this->getDriveFile(dirname($path));
523
+        if ($parentFolder) {
524
+            $mimetype = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
525
+            $params = array(
526
+                'mimeType' => $mimetype,
527
+                'uploadType' => 'media'
528
+            );
529
+            $result = false;
530
+
531
+            $chunkSizeBytes = 10 * 1024 * 1024;
532
+
533
+            $useChunking = false;
534
+            $size = filesize($tmpFile);
535
+            if ($size > $chunkSizeBytes) {
536
+                $useChunking = true;
537
+            } else {
538
+                $params['data'] = file_get_contents($tmpFile);
539
+            }
540
+
541
+            if ($this->file_exists($path)) {
542
+                $file = $this->getDriveFile($path);
543
+                $this->client->setDefer($useChunking);
544
+                $request = $this->service->files->update($file->getId(), $file, $params);
545
+            } else {
546
+                $file = new \Google_Service_Drive_DriveFile();
547
+                $file->setTitle(basename($path));
548
+                $file->setMimeType($mimetype);
549
+                $parent = new \Google_Service_Drive_ParentReference();
550
+                $parent->setId($parentFolder->getId());
551
+                $file->setParents(array($parent));
552
+                $this->client->setDefer($useChunking);
553
+                $request = $this->service->files->insert($file, $params);
554
+            }
555
+
556
+            if ($useChunking) {
557
+                // Create a media file upload to represent our upload process.
558
+                $media = new \Google_Http_MediaFileUpload(
559
+                    $this->client,
560
+                    $request,
561
+                    'text/plain',
562
+                    null,
563
+                    true,
564
+                    $chunkSizeBytes
565
+                );
566
+                $media->setFileSize($size);
567
+
568
+                // Upload the various chunks. $status will be false until the process is
569
+                // complete.
570
+                $status = false;
571
+                $handle = fopen($tmpFile, 'rb');
572
+                while (!$status && !feof($handle)) {
573
+                    $chunk = fread($handle, $chunkSizeBytes);
574
+                    $status = $media->nextChunk($chunk);
575
+                }
576
+
577
+                // The final value of $status will be the data from the API for the object
578
+                // that has been uploaded.
579
+                $result = false;
580
+                if ($status !== false) {
581
+                    $result = $status;
582
+                }
583
+
584
+                fclose($handle);
585
+            } else {
586
+                $result = $request;
587
+            }
588
+
589
+            // Reset to the client to execute requests immediately in the future.
590
+            $this->client->setDefer(false);
591
+
592
+            if ($result) {
593
+                $this->setDriveFile($path, $result);
594
+            }
595
+        }
596
+    }
597
+
598
+    public function getMimeType($path) {
599
+        $file = $this->getDriveFile($path);
600
+        if ($file) {
601
+            $mimetype = $file->getMimeType();
602
+            // Convert Google Doc mimetypes, choosing Open Document formats for download
603
+            if ($mimetype === self::FOLDER) {
604
+                return 'httpd/unix-directory';
605
+            } else if ($mimetype === self::DOCUMENT) {
606
+                return 'application/vnd.oasis.opendocument.text';
607
+            } else if ($mimetype === self::SPREADSHEET) {
608
+                return 'application/x-vnd.oasis.opendocument.spreadsheet';
609
+            } else if ($mimetype === self::DRAWING) {
610
+                return 'image/jpeg';
611
+            } else if ($mimetype === self::PRESENTATION) {
612
+                // Download as .odp is not available
613
+                return 'application/pdf';
614
+            } else {
615
+                // use extension-based detection, could be an encrypted file
616
+                return parent::getMimeType($path);
617
+            }
618
+        } else {
619
+            return false;
620
+        }
621
+    }
622
+
623
+    public function free_space($path) {
624
+        $about = $this->service->about->get();
625
+        return $about->getQuotaBytesTotal() - $about->getQuotaBytesUsed();
626
+    }
627
+
628
+    public function touch($path, $mtime = null) {
629
+        $file = $this->getDriveFile($path);
630
+        $result = false;
631
+        if ($file) {
632
+            if (isset($mtime)) {
633
+                // This is just RFC3339, but frustratingly, GDrive's API *requires*
634
+                // the fractions portion be present, while no handy PHP constant
635
+                // for RFC3339 or ISO8601 includes it. So we do it ourselves.
636
+                $file->setModifiedDate(date('Y-m-d\TH:i:s.uP', $mtime));
637
+                $result = $this->service->files->patch($file->getId(), $file, array(
638
+                    'setModifiedDate' => true,
639
+                ));
640
+            } else {
641
+                $result = $this->service->files->touch($file->getId());
642
+            }
643
+        } else {
644
+            $parentFolder = $this->getDriveFile(dirname($path));
645
+            if ($parentFolder) {
646
+                $file = new \Google_Service_Drive_DriveFile();
647
+                $file->setTitle(basename($path));
648
+                $parent = new \Google_Service_Drive_ParentReference();
649
+                $parent->setId($parentFolder->getId());
650
+                $file->setParents(array($parent));
651
+                $result = $this->service->files->insert($file);
652
+            }
653
+        }
654
+        if ($result) {
655
+            $this->setDriveFile($path, $result);
656
+        }
657
+        return (bool)$result;
658
+    }
659
+
660
+    public function test() {
661
+        if ($this->free_space('')) {
662
+            return true;
663
+        }
664
+        return false;
665
+    }
666
+
667
+    public function hasUpdated($path, $time) {
668
+        $appConfig = \OC::$server->getAppConfig();
669
+        if ($this->is_file($path)) {
670
+            return parent::hasUpdated($path, $time);
671
+        } else {
672
+            // Google Drive doesn't change modified times of folders when files inside are updated
673
+            // Instead we use the Changes API to see if folders have been updated, and it's a pain
674
+            $folder = $this->getDriveFile($path);
675
+            if ($folder) {
676
+                $result = false;
677
+                $folderId = $folder->getId();
678
+                $startChangeId = $appConfig->getValue('files_external', $this->getId().'cId');
679
+                $params = array(
680
+                    'includeDeleted' => true,
681
+                    'includeSubscribed' => true,
682
+                );
683
+                if (isset($startChangeId)) {
684
+                    $startChangeId = (int)$startChangeId;
685
+                    $largestChangeId = $startChangeId;
686
+                    $params['startChangeId'] = $startChangeId + 1;
687
+                } else {
688
+                    $largestChangeId = 0;
689
+                }
690
+                $pageToken = true;
691
+                while ($pageToken) {
692
+                    if ($pageToken !== true) {
693
+                        $params['pageToken'] = $pageToken;
694
+                    }
695
+                    $changes = $this->service->changes->listChanges($params);
696
+                    if ($largestChangeId === 0 || $largestChangeId === $startChangeId) {
697
+                        $largestChangeId = $changes->getLargestChangeId();
698
+                    }
699
+                    if (isset($startChangeId)) {
700
+                        // Check if a file in this folder has been updated
701
+                        // There is no way to filter by folder at the API level...
702
+                        foreach ($changes->getItems() as $change) {
703
+                            $file = $change->getFile();
704
+                            if ($file) {
705
+                                foreach ($file->getParents() as $parent) {
706
+                                    if ($parent->getId() === $folderId) {
707
+                                        $result = true;
708
+                                    // Check if there are changes in different folders
709
+                                    } else if ($change->getId() <= $largestChangeId) {
710
+                                        // Decrement id so this change is fetched when called again
711
+                                        $largestChangeId = $change->getId();
712
+                                        $largestChangeId--;
713
+                                    }
714
+                                }
715
+                            }
716
+                        }
717
+                        $pageToken = $changes->getNextPageToken();
718
+                    } else {
719
+                        // Assuming the initial scan just occurred and changes are negligible
720
+                        break;
721
+                    }
722
+                }
723
+                $appConfig->setValue('files_external', $this->getId().'cId', $largestChangeId);
724
+                return $result;
725
+            }
726
+        }
727
+        return false;
728
+    }
729
+
730
+    /**
731
+     * check if curl is installed
732
+     */
733
+    public static function checkDependencies() {
734
+        return true;
735
+    }
736 736
 
737 737
 }
Please login to merge, or discard this patch.
lib/private/Archive/TAR.php 3 patches
Doc Comments   +1 added lines patch added patch discarded remove patch
@@ -370,6 +370,7 @@
 block discarded – undo
370 370
 
371 371
 	/**
372 372
 	 * write back temporary files
373
+	 * @param string $path
373 374
 	 */
374 375
 	function writeBack($tmpFile, $path) {
375 376
 		$this->addFile($path, $tmpFile);
Please login to merge, or discard this patch.
Indentation   +331 added lines, -331 removed lines patch added patch discarded remove patch
@@ -36,355 +36,355 @@
 block discarded – undo
36 36
 use Icewind\Streams\CallbackWrapper;
37 37
 
38 38
 class TAR extends Archive {
39
-	const PLAIN = 0;
40
-	const GZIP = 1;
41
-	const BZIP = 2;
39
+    const PLAIN = 0;
40
+    const GZIP = 1;
41
+    const BZIP = 2;
42 42
 
43
-	private $fileList;
44
-	private $cachedHeaders;
43
+    private $fileList;
44
+    private $cachedHeaders;
45 45
 
46
-	/**
47
-	 * @var \Archive_Tar tar
48
-	 */
49
-	private $tar = null;
50
-	private $path;
46
+    /**
47
+     * @var \Archive_Tar tar
48
+     */
49
+    private $tar = null;
50
+    private $path;
51 51
 
52
-	/**
53
-	 * @param string $source
54
-	 */
55
-	function __construct($source) {
56
-		$types = array(null, 'gz', 'bz2');
57
-		$this->path = $source;
58
-		$this->tar = new \Archive_Tar($source, $types[self::getTarType($source)]);
59
-	}
52
+    /**
53
+     * @param string $source
54
+     */
55
+    function __construct($source) {
56
+        $types = array(null, 'gz', 'bz2');
57
+        $this->path = $source;
58
+        $this->tar = new \Archive_Tar($source, $types[self::getTarType($source)]);
59
+    }
60 60
 
61
-	/**
62
-	 * try to detect the type of tar compression
63
-	 *
64
-	 * @param string $file
65
-	 * @return integer
66
-	 */
67
-	static public function getTarType($file) {
68
-		if (strpos($file, '.')) {
69
-			$extension = substr($file, strrpos($file, '.'));
70
-			switch ($extension) {
71
-				case '.gz':
72
-				case '.tgz':
73
-					return self::GZIP;
74
-				case '.bz':
75
-				case '.bz2':
76
-					return self::BZIP;
77
-				case '.tar':
78
-					return self::PLAIN;
79
-				default:
80
-					return self::PLAIN;
81
-			}
82
-		} else {
83
-			return self::PLAIN;
84
-		}
85
-	}
61
+    /**
62
+     * try to detect the type of tar compression
63
+     *
64
+     * @param string $file
65
+     * @return integer
66
+     */
67
+    static public function getTarType($file) {
68
+        if (strpos($file, '.')) {
69
+            $extension = substr($file, strrpos($file, '.'));
70
+            switch ($extension) {
71
+                case '.gz':
72
+                case '.tgz':
73
+                    return self::GZIP;
74
+                case '.bz':
75
+                case '.bz2':
76
+                    return self::BZIP;
77
+                case '.tar':
78
+                    return self::PLAIN;
79
+                default:
80
+                    return self::PLAIN;
81
+            }
82
+        } else {
83
+            return self::PLAIN;
84
+        }
85
+    }
86 86
 
87
-	/**
88
-	 * add an empty folder to the archive
89
-	 *
90
-	 * @param string $path
91
-	 * @return bool
92
-	 */
93
-	function addFolder($path) {
94
-		$tmpBase = \OC::$server->getTempManager()->getTemporaryFolder();
95
-		if (substr($path, -1, 1) != '/') {
96
-			$path .= '/';
97
-		}
98
-		if ($this->fileExists($path)) {
99
-			return false;
100
-		}
101
-		$parts = explode('/', $path);
102
-		$folder = $tmpBase;
103
-		foreach ($parts as $part) {
104
-			$folder .= '/' . $part;
105
-			if (!is_dir($folder)) {
106
-				mkdir($folder);
107
-			}
108
-		}
109
-		$result = $this->tar->addModify(array($tmpBase . $path), '', $tmpBase);
110
-		rmdir($tmpBase . $path);
111
-		$this->fileList = false;
112
-		$this->cachedHeaders = false;
113
-		return $result;
114
-	}
87
+    /**
88
+     * add an empty folder to the archive
89
+     *
90
+     * @param string $path
91
+     * @return bool
92
+     */
93
+    function addFolder($path) {
94
+        $tmpBase = \OC::$server->getTempManager()->getTemporaryFolder();
95
+        if (substr($path, -1, 1) != '/') {
96
+            $path .= '/';
97
+        }
98
+        if ($this->fileExists($path)) {
99
+            return false;
100
+        }
101
+        $parts = explode('/', $path);
102
+        $folder = $tmpBase;
103
+        foreach ($parts as $part) {
104
+            $folder .= '/' . $part;
105
+            if (!is_dir($folder)) {
106
+                mkdir($folder);
107
+            }
108
+        }
109
+        $result = $this->tar->addModify(array($tmpBase . $path), '', $tmpBase);
110
+        rmdir($tmpBase . $path);
111
+        $this->fileList = false;
112
+        $this->cachedHeaders = false;
113
+        return $result;
114
+    }
115 115
 
116
-	/**
117
-	 * add a file to the archive
118
-	 *
119
-	 * @param string $path
120
-	 * @param string $source either a local file or string data
121
-	 * @return bool
122
-	 */
123
-	function addFile($path, $source = '') {
124
-		if ($this->fileExists($path)) {
125
-			$this->remove($path);
126
-		}
127
-		if ($source and $source[0] == '/' and file_exists($source)) {
128
-			$source = file_get_contents($source);
129
-		}
130
-		$result = $this->tar->addString($path, $source);
131
-		$this->fileList = false;
132
-		$this->cachedHeaders = false;
133
-		return $result;
134
-	}
116
+    /**
117
+     * add a file to the archive
118
+     *
119
+     * @param string $path
120
+     * @param string $source either a local file or string data
121
+     * @return bool
122
+     */
123
+    function addFile($path, $source = '') {
124
+        if ($this->fileExists($path)) {
125
+            $this->remove($path);
126
+        }
127
+        if ($source and $source[0] == '/' and file_exists($source)) {
128
+            $source = file_get_contents($source);
129
+        }
130
+        $result = $this->tar->addString($path, $source);
131
+        $this->fileList = false;
132
+        $this->cachedHeaders = false;
133
+        return $result;
134
+    }
135 135
 
136
-	/**
137
-	 * rename a file or folder in the archive
138
-	 *
139
-	 * @param string $source
140
-	 * @param string $dest
141
-	 * @return bool
142
-	 */
143
-	function rename($source, $dest) {
144
-		//no proper way to delete, rename entire archive, rename file and remake archive
145
-		$tmp = \OCP\Files::tmpFolder();
146
-		$this->tar->extract($tmp);
147
-		rename($tmp . $source, $tmp . $dest);
148
-		$this->tar = null;
149
-		unlink($this->path);
150
-		$types = array(null, 'gz', 'bz');
151
-		$this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]);
152
-		$this->tar->createModify(array($tmp), '', $tmp . '/');
153
-		$this->fileList = false;
154
-		$this->cachedHeaders = false;
155
-		return true;
156
-	}
136
+    /**
137
+     * rename a file or folder in the archive
138
+     *
139
+     * @param string $source
140
+     * @param string $dest
141
+     * @return bool
142
+     */
143
+    function rename($source, $dest) {
144
+        //no proper way to delete, rename entire archive, rename file and remake archive
145
+        $tmp = \OCP\Files::tmpFolder();
146
+        $this->tar->extract($tmp);
147
+        rename($tmp . $source, $tmp . $dest);
148
+        $this->tar = null;
149
+        unlink($this->path);
150
+        $types = array(null, 'gz', 'bz');
151
+        $this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]);
152
+        $this->tar->createModify(array($tmp), '', $tmp . '/');
153
+        $this->fileList = false;
154
+        $this->cachedHeaders = false;
155
+        return true;
156
+    }
157 157
 
158
-	/**
159
-	 * @param string $file
160
-	 */
161
-	private function getHeader($file) {
162
-		if (!$this->cachedHeaders) {
163
-			$this->cachedHeaders = $this->tar->listContent();
164
-		}
165
-		foreach ($this->cachedHeaders as $header) {
166
-			if ($file == $header['filename']
167
-				or $file . '/' == $header['filename']
168
-				or '/' . $file . '/' == $header['filename']
169
-				or '/' . $file == $header['filename']
170
-			) {
171
-				return $header;
172
-			}
173
-		}
174
-		return null;
175
-	}
158
+    /**
159
+     * @param string $file
160
+     */
161
+    private function getHeader($file) {
162
+        if (!$this->cachedHeaders) {
163
+            $this->cachedHeaders = $this->tar->listContent();
164
+        }
165
+        foreach ($this->cachedHeaders as $header) {
166
+            if ($file == $header['filename']
167
+                or $file . '/' == $header['filename']
168
+                or '/' . $file . '/' == $header['filename']
169
+                or '/' . $file == $header['filename']
170
+            ) {
171
+                return $header;
172
+            }
173
+        }
174
+        return null;
175
+    }
176 176
 
177
-	/**
178
-	 * get the uncompressed size of a file in the archive
179
-	 *
180
-	 * @param string $path
181
-	 * @return int
182
-	 */
183
-	function filesize($path) {
184
-		$stat = $this->getHeader($path);
185
-		return $stat['size'];
186
-	}
177
+    /**
178
+     * get the uncompressed size of a file in the archive
179
+     *
180
+     * @param string $path
181
+     * @return int
182
+     */
183
+    function filesize($path) {
184
+        $stat = $this->getHeader($path);
185
+        return $stat['size'];
186
+    }
187 187
 
188
-	/**
189
-	 * get the last modified time of a file in the archive
190
-	 *
191
-	 * @param string $path
192
-	 * @return int
193
-	 */
194
-	function mtime($path) {
195
-		$stat = $this->getHeader($path);
196
-		return $stat['mtime'];
197
-	}
188
+    /**
189
+     * get the last modified time of a file in the archive
190
+     *
191
+     * @param string $path
192
+     * @return int
193
+     */
194
+    function mtime($path) {
195
+        $stat = $this->getHeader($path);
196
+        return $stat['mtime'];
197
+    }
198 198
 
199
-	/**
200
-	 * get the files in a folder
201
-	 *
202
-	 * @param string $path
203
-	 * @return array
204
-	 */
205
-	function getFolder($path) {
206
-		$files = $this->getFiles();
207
-		$folderContent = array();
208
-		$pathLength = strlen($path);
209
-		foreach ($files as $file) {
210
-			if ($file[0] == '/') {
211
-				$file = substr($file, 1);
212
-			}
213
-			if (substr($file, 0, $pathLength) == $path and $file != $path) {
214
-				$result = substr($file, $pathLength);
215
-				if ($pos = strpos($result, '/')) {
216
-					$result = substr($result, 0, $pos + 1);
217
-				}
218
-				if (array_search($result, $folderContent) === false) {
219
-					$folderContent[] = $result;
220
-				}
221
-			}
222
-		}
223
-		return $folderContent;
224
-	}
199
+    /**
200
+     * get the files in a folder
201
+     *
202
+     * @param string $path
203
+     * @return array
204
+     */
205
+    function getFolder($path) {
206
+        $files = $this->getFiles();
207
+        $folderContent = array();
208
+        $pathLength = strlen($path);
209
+        foreach ($files as $file) {
210
+            if ($file[0] == '/') {
211
+                $file = substr($file, 1);
212
+            }
213
+            if (substr($file, 0, $pathLength) == $path and $file != $path) {
214
+                $result = substr($file, $pathLength);
215
+                if ($pos = strpos($result, '/')) {
216
+                    $result = substr($result, 0, $pos + 1);
217
+                }
218
+                if (array_search($result, $folderContent) === false) {
219
+                    $folderContent[] = $result;
220
+                }
221
+            }
222
+        }
223
+        return $folderContent;
224
+    }
225 225
 
226
-	/**
227
-	 * get all files in the archive
228
-	 *
229
-	 * @return array
230
-	 */
231
-	function getFiles() {
232
-		if ($this->fileList) {
233
-			return $this->fileList;
234
-		}
235
-		if (!$this->cachedHeaders) {
236
-			$this->cachedHeaders = $this->tar->listContent();
237
-		}
238
-		$files = array();
239
-		foreach ($this->cachedHeaders as $header) {
240
-			$files[] = $header['filename'];
241
-		}
242
-		$this->fileList = $files;
243
-		return $files;
244
-	}
226
+    /**
227
+     * get all files in the archive
228
+     *
229
+     * @return array
230
+     */
231
+    function getFiles() {
232
+        if ($this->fileList) {
233
+            return $this->fileList;
234
+        }
235
+        if (!$this->cachedHeaders) {
236
+            $this->cachedHeaders = $this->tar->listContent();
237
+        }
238
+        $files = array();
239
+        foreach ($this->cachedHeaders as $header) {
240
+            $files[] = $header['filename'];
241
+        }
242
+        $this->fileList = $files;
243
+        return $files;
244
+    }
245 245
 
246
-	/**
247
-	 * get the content of a file
248
-	 *
249
-	 * @param string $path
250
-	 * @return string
251
-	 */
252
-	function getFile($path) {
253
-		return $this->tar->extractInString($path);
254
-	}
246
+    /**
247
+     * get the content of a file
248
+     *
249
+     * @param string $path
250
+     * @return string
251
+     */
252
+    function getFile($path) {
253
+        return $this->tar->extractInString($path);
254
+    }
255 255
 
256
-	/**
257
-	 * extract a single file from the archive
258
-	 *
259
-	 * @param string $path
260
-	 * @param string $dest
261
-	 * @return bool
262
-	 */
263
-	function extractFile($path, $dest) {
264
-		$tmp = \OCP\Files::tmpFolder();
265
-		if (!$this->fileExists($path)) {
266
-			return false;
267
-		}
268
-		if ($this->fileExists('/' . $path)) {
269
-			$success = $this->tar->extractList(array('/' . $path), $tmp);
270
-		} else {
271
-			$success = $this->tar->extractList(array($path), $tmp);
272
-		}
273
-		if ($success) {
274
-			rename($tmp . $path, $dest);
275
-		}
276
-		\OCP\Files::rmdirr($tmp);
277
-		return $success;
278
-	}
256
+    /**
257
+     * extract a single file from the archive
258
+     *
259
+     * @param string $path
260
+     * @param string $dest
261
+     * @return bool
262
+     */
263
+    function extractFile($path, $dest) {
264
+        $tmp = \OCP\Files::tmpFolder();
265
+        if (!$this->fileExists($path)) {
266
+            return false;
267
+        }
268
+        if ($this->fileExists('/' . $path)) {
269
+            $success = $this->tar->extractList(array('/' . $path), $tmp);
270
+        } else {
271
+            $success = $this->tar->extractList(array($path), $tmp);
272
+        }
273
+        if ($success) {
274
+            rename($tmp . $path, $dest);
275
+        }
276
+        \OCP\Files::rmdirr($tmp);
277
+        return $success;
278
+    }
279 279
 
280
-	/**
281
-	 * extract the archive
282
-	 *
283
-	 * @param string $dest
284
-	 * @return bool
285
-	 */
286
-	function extract($dest) {
287
-		return $this->tar->extract($dest);
288
-	}
280
+    /**
281
+     * extract the archive
282
+     *
283
+     * @param string $dest
284
+     * @return bool
285
+     */
286
+    function extract($dest) {
287
+        return $this->tar->extract($dest);
288
+    }
289 289
 
290
-	/**
291
-	 * check if a file or folder exists in the archive
292
-	 *
293
-	 * @param string $path
294
-	 * @return bool
295
-	 */
296
-	function fileExists($path) {
297
-		$files = $this->getFiles();
298
-		if ((array_search($path, $files) !== false) or (array_search($path . '/', $files) !== false)) {
299
-			return true;
300
-		} else {
301
-			$folderPath = $path;
302
-			if (substr($folderPath, -1, 1) != '/') {
303
-				$folderPath .= '/';
304
-			}
305
-			$pathLength = strlen($folderPath);
306
-			foreach ($files as $file) {
307
-				if (strlen($file) > $pathLength and substr($file, 0, $pathLength) == $folderPath) {
308
-					return true;
309
-				}
310
-			}
311
-		}
312
-		if ($path[0] != '/') { //not all programs agree on the use of a leading /
313
-			return $this->fileExists('/' . $path);
314
-		} else {
315
-			return false;
316
-		}
317
-	}
290
+    /**
291
+     * check if a file or folder exists in the archive
292
+     *
293
+     * @param string $path
294
+     * @return bool
295
+     */
296
+    function fileExists($path) {
297
+        $files = $this->getFiles();
298
+        if ((array_search($path, $files) !== false) or (array_search($path . '/', $files) !== false)) {
299
+            return true;
300
+        } else {
301
+            $folderPath = $path;
302
+            if (substr($folderPath, -1, 1) != '/') {
303
+                $folderPath .= '/';
304
+            }
305
+            $pathLength = strlen($folderPath);
306
+            foreach ($files as $file) {
307
+                if (strlen($file) > $pathLength and substr($file, 0, $pathLength) == $folderPath) {
308
+                    return true;
309
+                }
310
+            }
311
+        }
312
+        if ($path[0] != '/') { //not all programs agree on the use of a leading /
313
+            return $this->fileExists('/' . $path);
314
+        } else {
315
+            return false;
316
+        }
317
+    }
318 318
 
319
-	/**
320
-	 * remove a file or folder from the archive
321
-	 *
322
-	 * @param string $path
323
-	 * @return bool
324
-	 */
325
-	function remove($path) {
326
-		if (!$this->fileExists($path)) {
327
-			return false;
328
-		}
329
-		$this->fileList = false;
330
-		$this->cachedHeaders = false;
331
-		//no proper way to delete, extract entire archive, delete file and remake archive
332
-		$tmp = \OCP\Files::tmpFolder();
333
-		$this->tar->extract($tmp);
334
-		\OCP\Files::rmdirr($tmp . $path);
335
-		$this->tar = null;
336
-		unlink($this->path);
337
-		$this->reopen();
338
-		$this->tar->createModify(array($tmp), '', $tmp);
339
-		return true;
340
-	}
319
+    /**
320
+     * remove a file or folder from the archive
321
+     *
322
+     * @param string $path
323
+     * @return bool
324
+     */
325
+    function remove($path) {
326
+        if (!$this->fileExists($path)) {
327
+            return false;
328
+        }
329
+        $this->fileList = false;
330
+        $this->cachedHeaders = false;
331
+        //no proper way to delete, extract entire archive, delete file and remake archive
332
+        $tmp = \OCP\Files::tmpFolder();
333
+        $this->tar->extract($tmp);
334
+        \OCP\Files::rmdirr($tmp . $path);
335
+        $this->tar = null;
336
+        unlink($this->path);
337
+        $this->reopen();
338
+        $this->tar->createModify(array($tmp), '', $tmp);
339
+        return true;
340
+    }
341 341
 
342
-	/**
343
-	 * get a file handler
344
-	 *
345
-	 * @param string $path
346
-	 * @param string $mode
347
-	 * @return resource
348
-	 */
349
-	function getStream($path, $mode) {
350
-		if (strrpos($path, '.') !== false) {
351
-			$ext = substr($path, strrpos($path, '.'));
352
-		} else {
353
-			$ext = '';
354
-		}
355
-		$tmpFile = \OCP\Files::tmpFile($ext);
356
-		if ($this->fileExists($path)) {
357
-			$this->extractFile($path, $tmpFile);
358
-		} elseif ($mode == 'r' or $mode == 'rb') {
359
-			return false;
360
-		}
361
-		if ($mode == 'r' or $mode == 'rb') {
362
-			return fopen($tmpFile, $mode);
363
-		} else {
364
-			$handle = fopen($tmpFile, $mode);
365
-			return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
366
-				$this->writeBack($tmpFile, $path);
367
-			});
368
-		}
369
-	}
342
+    /**
343
+     * get a file handler
344
+     *
345
+     * @param string $path
346
+     * @param string $mode
347
+     * @return resource
348
+     */
349
+    function getStream($path, $mode) {
350
+        if (strrpos($path, '.') !== false) {
351
+            $ext = substr($path, strrpos($path, '.'));
352
+        } else {
353
+            $ext = '';
354
+        }
355
+        $tmpFile = \OCP\Files::tmpFile($ext);
356
+        if ($this->fileExists($path)) {
357
+            $this->extractFile($path, $tmpFile);
358
+        } elseif ($mode == 'r' or $mode == 'rb') {
359
+            return false;
360
+        }
361
+        if ($mode == 'r' or $mode == 'rb') {
362
+            return fopen($tmpFile, $mode);
363
+        } else {
364
+            $handle = fopen($tmpFile, $mode);
365
+            return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
366
+                $this->writeBack($tmpFile, $path);
367
+            });
368
+        }
369
+    }
370 370
 
371
-	/**
372
-	 * write back temporary files
373
-	 */
374
-	function writeBack($tmpFile, $path) {
375
-		$this->addFile($path, $tmpFile);
376
-		unlink($tmpFile);
377
-	}
371
+    /**
372
+     * write back temporary files
373
+     */
374
+    function writeBack($tmpFile, $path) {
375
+        $this->addFile($path, $tmpFile);
376
+        unlink($tmpFile);
377
+    }
378 378
 
379
-	/**
380
-	 * reopen the archive to ensure everything is written
381
-	 */
382
-	private function reopen() {
383
-		if ($this->tar) {
384
-			$this->tar->_close();
385
-			$this->tar = null;
386
-		}
387
-		$types = array(null, 'gz', 'bz');
388
-		$this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]);
389
-	}
379
+    /**
380
+     * reopen the archive to ensure everything is written
381
+     */
382
+    private function reopen() {
383
+        if ($this->tar) {
384
+            $this->tar->_close();
385
+            $this->tar = null;
386
+        }
387
+        $types = array(null, 'gz', 'bz');
388
+        $this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]);
389
+    }
390 390
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -101,13 +101,13 @@  discard block
 block discarded – undo
101 101
 		$parts = explode('/', $path);
102 102
 		$folder = $tmpBase;
103 103
 		foreach ($parts as $part) {
104
-			$folder .= '/' . $part;
104
+			$folder .= '/'.$part;
105 105
 			if (!is_dir($folder)) {
106 106
 				mkdir($folder);
107 107
 			}
108 108
 		}
109
-		$result = $this->tar->addModify(array($tmpBase . $path), '', $tmpBase);
110
-		rmdir($tmpBase . $path);
109
+		$result = $this->tar->addModify(array($tmpBase.$path), '', $tmpBase);
110
+		rmdir($tmpBase.$path);
111 111
 		$this->fileList = false;
112 112
 		$this->cachedHeaders = false;
113 113
 		return $result;
@@ -144,12 +144,12 @@  discard block
 block discarded – undo
144 144
 		//no proper way to delete, rename entire archive, rename file and remake archive
145 145
 		$tmp = \OCP\Files::tmpFolder();
146 146
 		$this->tar->extract($tmp);
147
-		rename($tmp . $source, $tmp . $dest);
147
+		rename($tmp.$source, $tmp.$dest);
148 148
 		$this->tar = null;
149 149
 		unlink($this->path);
150 150
 		$types = array(null, 'gz', 'bz');
151 151
 		$this->tar = new \Archive_Tar($this->path, $types[self::getTarType($this->path)]);
152
-		$this->tar->createModify(array($tmp), '', $tmp . '/');
152
+		$this->tar->createModify(array($tmp), '', $tmp.'/');
153 153
 		$this->fileList = false;
154 154
 		$this->cachedHeaders = false;
155 155
 		return true;
@@ -164,9 +164,9 @@  discard block
 block discarded – undo
164 164
 		}
165 165
 		foreach ($this->cachedHeaders as $header) {
166 166
 			if ($file == $header['filename']
167
-				or $file . '/' == $header['filename']
168
-				or '/' . $file . '/' == $header['filename']
169
-				or '/' . $file == $header['filename']
167
+				or $file.'/' == $header['filename']
168
+				or '/'.$file.'/' == $header['filename']
169
+				or '/'.$file == $header['filename']
170 170
 			) {
171 171
 				return $header;
172 172
 			}
@@ -265,13 +265,13 @@  discard block
 block discarded – undo
265 265
 		if (!$this->fileExists($path)) {
266 266
 			return false;
267 267
 		}
268
-		if ($this->fileExists('/' . $path)) {
269
-			$success = $this->tar->extractList(array('/' . $path), $tmp);
268
+		if ($this->fileExists('/'.$path)) {
269
+			$success = $this->tar->extractList(array('/'.$path), $tmp);
270 270
 		} else {
271 271
 			$success = $this->tar->extractList(array($path), $tmp);
272 272
 		}
273 273
 		if ($success) {
274
-			rename($tmp . $path, $dest);
274
+			rename($tmp.$path, $dest);
275 275
 		}
276 276
 		\OCP\Files::rmdirr($tmp);
277 277
 		return $success;
@@ -295,7 +295,7 @@  discard block
 block discarded – undo
295 295
 	 */
296 296
 	function fileExists($path) {
297 297
 		$files = $this->getFiles();
298
-		if ((array_search($path, $files) !== false) or (array_search($path . '/', $files) !== false)) {
298
+		if ((array_search($path, $files) !== false) or (array_search($path.'/', $files) !== false)) {
299 299
 			return true;
300 300
 		} else {
301 301
 			$folderPath = $path;
@@ -310,7 +310,7 @@  discard block
 block discarded – undo
310 310
 			}
311 311
 		}
312 312
 		if ($path[0] != '/') { //not all programs agree on the use of a leading /
313
-			return $this->fileExists('/' . $path);
313
+			return $this->fileExists('/'.$path);
314 314
 		} else {
315 315
 			return false;
316 316
 		}
@@ -331,7 +331,7 @@  discard block
 block discarded – undo
331 331
 		//no proper way to delete, extract entire archive, delete file and remake archive
332 332
 		$tmp = \OCP\Files::tmpFolder();
333 333
 		$this->tar->extract($tmp);
334
-		\OCP\Files::rmdirr($tmp . $path);
334
+		\OCP\Files::rmdirr($tmp.$path);
335 335
 		$this->tar = null;
336 336
 		unlink($this->path);
337 337
 		$this->reopen();
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
 			return fopen($tmpFile, $mode);
363 363
 		} else {
364 364
 			$handle = fopen($tmpFile, $mode);
365
-			return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
365
+			return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
366 366
 				$this->writeBack($tmpFile, $path);
367 367
 			});
368 368
 		}
Please login to merge, or discard this patch.
lib/private/Files/ObjectStore/ObjectStoreStorage.php 3 patches
Doc Comments   +6 added lines patch added patch discarded remove patch
@@ -162,6 +162,9 @@  discard block
 block discarded – undo
162 162
 		return true;
163 163
 	}
164 164
 
165
+	/**
166
+	 * @param string $path
167
+	 */
165 168
 	private function rmObjects($path) {
166 169
 		$children = $this->getCache()->getFolderContents($path);
167 170
 		foreach ($children as $child) {
@@ -364,6 +367,9 @@  discard block
 block discarded – undo
364 367
 		return true;
365 368
 	}
366 369
 
370
+	/**
371
+	 * @param string $path
372
+	 */
367 373
 	public function writeBack($tmpFile, $path) {
368 374
 		$stat = $this->stat($path);
369 375
 		if (empty($stat)) {
Please login to merge, or discard this patch.
Indentation   +386 added lines, -386 removed lines patch added patch discarded remove patch
@@ -31,390 +31,390 @@
 block discarded – undo
31 31
 use OCP\Files\ObjectStore\IObjectStore;
32 32
 
33 33
 class ObjectStoreStorage extends \OC\Files\Storage\Common {
34
-	/**
35
-	 * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
36
-	 */
37
-	protected $objectStore;
38
-	/**
39
-	 * @var string $id
40
-	 */
41
-	protected $id;
42
-	/**
43
-	 * @var \OC\User\User $user
44
-	 */
45
-	protected $user;
46
-
47
-	private $objectPrefix = 'urn:oid:';
48
-
49
-	private $logger;
50
-
51
-	public function __construct($params) {
52
-		if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
53
-			$this->objectStore = $params['objectstore'];
54
-		} else {
55
-			throw new \Exception('missing IObjectStore instance');
56
-		}
57
-		if (isset($params['storageid'])) {
58
-			$this->id = 'object::store:' . $params['storageid'];
59
-		} else {
60
-			$this->id = 'object::store:' . $this->objectStore->getStorageId();
61
-		}
62
-		if (isset($params['objectPrefix'])) {
63
-			$this->objectPrefix = $params['objectPrefix'];
64
-		}
65
-		//initialize cache with root directory in cache
66
-		if (!$this->is_dir('/')) {
67
-			$this->mkdir('/');
68
-		}
69
-
70
-		$this->logger = \OC::$server->getLogger();
71
-	}
72
-
73
-	public function mkdir($path) {
74
-		$path = $this->normalizePath($path);
75
-
76
-		if ($this->file_exists($path)) {
77
-			return false;
78
-		}
79
-
80
-		$mTime = time();
81
-		$data = [
82
-			'mimetype' => 'httpd/unix-directory',
83
-			'size' => 0,
84
-			'mtime' => $mTime,
85
-			'storage_mtime' => $mTime,
86
-			'permissions' => \OCP\Constants::PERMISSION_ALL,
87
-		];
88
-		if ($path === '') {
89
-			//create root on the fly
90
-			$data['etag'] = $this->getETag('');
91
-			$this->getCache()->put('', $data);
92
-			return true;
93
-		} else {
94
-			// if parent does not exist, create it
95
-			$parent = $this->normalizePath(dirname($path));
96
-			$parentType = $this->filetype($parent);
97
-			if ($parentType === false) {
98
-				if (!$this->mkdir($parent)) {
99
-					// something went wrong
100
-					return false;
101
-				}
102
-			} else if ($parentType === 'file') {
103
-				// parent is a file
104
-				return false;
105
-			}
106
-			// finally create the new dir
107
-			$mTime = time(); // update mtime
108
-			$data['mtime'] = $mTime;
109
-			$data['storage_mtime'] = $mTime;
110
-			$data['etag'] = $this->getETag($path);
111
-			$this->getCache()->put($path, $data);
112
-			return true;
113
-		}
114
-	}
115
-
116
-	/**
117
-	 * @param string $path
118
-	 * @return string
119
-	 */
120
-	private function normalizePath($path) {
121
-		$path = trim($path, '/');
122
-		//FIXME why do we sometimes get a path like 'files//username'?
123
-		$path = str_replace('//', '/', $path);
124
-
125
-		// dirname('/folder') returns '.' but internally (in the cache) we store the root as ''
126
-		if (!$path || $path === '.') {
127
-			$path = '';
128
-		}
129
-
130
-		return $path;
131
-	}
132
-
133
-	/**
134
-	 * Object Stores use a NoopScanner because metadata is directly stored in
135
-	 * the file cache and cannot really scan the filesystem. The storage passed in is not used anywhere.
136
-	 *
137
-	 * @param string $path
138
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
139
-	 * @return \OC\Files\ObjectStore\NoopScanner
140
-	 */
141
-	public function getScanner($path = '', $storage = null) {
142
-		if (!$storage) {
143
-			$storage = $this;
144
-		}
145
-		if (!isset($this->scanner)) {
146
-			$this->scanner = new NoopScanner($storage);
147
-		}
148
-		return $this->scanner;
149
-	}
150
-
151
-	public function getId() {
152
-		return $this->id;
153
-	}
154
-
155
-	public function rmdir($path) {
156
-		$path = $this->normalizePath($path);
157
-
158
-		if (!$this->is_dir($path)) {
159
-			return false;
160
-		}
161
-
162
-		$this->rmObjects($path);
163
-
164
-		$this->getCache()->remove($path);
165
-
166
-		return true;
167
-	}
168
-
169
-	private function rmObjects($path) {
170
-		$children = $this->getCache()->getFolderContents($path);
171
-		foreach ($children as $child) {
172
-			if ($child['mimetype'] === 'httpd/unix-directory') {
173
-				$this->rmObjects($child['path']);
174
-			} else {
175
-				$this->unlink($child['path']);
176
-			}
177
-		}
178
-	}
179
-
180
-	public function unlink($path) {
181
-		$path = $this->normalizePath($path);
182
-		$stat = $this->stat($path);
183
-
184
-		if ($stat && isset($stat['fileid'])) {
185
-			if ($stat['mimetype'] === 'httpd/unix-directory') {
186
-				return $this->rmdir($path);
187
-			}
188
-			try {
189
-				$this->objectStore->deleteObject($this->getURN($stat['fileid']));
190
-			} catch (\Exception $ex) {
191
-				if ($ex->getCode() !== 404) {
192
-					$this->logger->logException($ex, [
193
-						'app' => 'objectstore',
194
-						'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
195
-					]);
196
-					return false;
197
-				} else {
198
-					//removing from cache is ok as it does not exist in the objectstore anyway
199
-				}
200
-			}
201
-			$this->getCache()->remove($path);
202
-			return true;
203
-		}
204
-		return false;
205
-	}
206
-
207
-	public function stat($path) {
208
-		$path = $this->normalizePath($path);
209
-		$cacheEntry = $this->getCache()->get($path);
210
-		if ($cacheEntry instanceof CacheEntry) {
211
-			return $cacheEntry->getData();
212
-		} else {
213
-			return false;
214
-		}
215
-	}
216
-
217
-	/**
218
-	 * Override this method if you need a different unique resource identifier for your object storage implementation.
219
-	 * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users.
220
-	 * You may need a mapping table to store your URN if it cannot be generated from the fileid.
221
-	 *
222
-	 * @param int $fileId the fileid
223
-	 * @return null|string the unified resource name used to identify the object
224
-	 */
225
-	protected function getURN($fileId) {
226
-		if (is_numeric($fileId)) {
227
-			return $this->objectPrefix . $fileId;
228
-		}
229
-		return null;
230
-	}
231
-
232
-	public function opendir($path) {
233
-		$path = $this->normalizePath($path);
234
-
235
-		try {
236
-			$files = array();
237
-			$folderContents = $this->getCache()->getFolderContents($path);
238
-			foreach ($folderContents as $file) {
239
-				$files[] = $file['name'];
240
-			}
241
-
242
-			return IteratorDirectory::wrap($files);
243
-		} catch (\Exception $e) {
244
-			$this->logger->logException($e);
245
-			return false;
246
-		}
247
-	}
248
-
249
-	public function filetype($path) {
250
-		$path = $this->normalizePath($path);
251
-		$stat = $this->stat($path);
252
-		if ($stat) {
253
-			if ($stat['mimetype'] === 'httpd/unix-directory') {
254
-				return 'dir';
255
-			}
256
-			return 'file';
257
-		} else {
258
-			return false;
259
-		}
260
-	}
261
-
262
-	public function fopen($path, $mode) {
263
-		$path = $this->normalizePath($path);
264
-
265
-		switch ($mode) {
266
-			case 'r':
267
-			case 'rb':
268
-				$stat = $this->stat($path);
269
-				if (is_array($stat)) {
270
-					try {
271
-						return $this->objectStore->readObject($this->getURN($stat['fileid']));
272
-					} catch (\Exception $ex) {
273
-						$this->logger->logException($ex, [
274
-							'app' => 'objectstore',
275
-							'message' => 'Count not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
276
-						]);
277
-						return false;
278
-					}
279
-				} else {
280
-					return false;
281
-				}
282
-			case 'w':
283
-			case 'wb':
284
-			case 'a':
285
-			case 'ab':
286
-			case 'r+':
287
-			case 'w+':
288
-			case 'wb+':
289
-			case 'a+':
290
-			case 'x':
291
-			case 'x+':
292
-			case 'c':
293
-			case 'c+':
294
-				if (strrpos($path, '.') !== false) {
295
-					$ext = substr($path, strrpos($path, '.'));
296
-				} else {
297
-					$ext = '';
298
-				}
299
-				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
300
-				if ($this->file_exists($path)) {
301
-					$source = $this->fopen($path, 'r');
302
-					file_put_contents($tmpFile, $source);
303
-				}
304
-				$handle = fopen($tmpFile, $mode);
305
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
306
-					$this->writeBack($tmpFile, $path);
307
-				});
308
-		}
309
-		return false;
310
-	}
311
-
312
-	public function file_exists($path) {
313
-		$path = $this->normalizePath($path);
314
-		return (bool)$this->stat($path);
315
-	}
316
-
317
-	public function rename($source, $target) {
318
-		$source = $this->normalizePath($source);
319
-		$target = $this->normalizePath($target);
320
-		$this->remove($target);
321
-		$this->getCache()->move($source, $target);
322
-		$this->touch(dirname($target));
323
-		return true;
324
-	}
325
-
326
-	public function getMimeType($path) {
327
-		$path = $this->normalizePath($path);
328
-		$stat = $this->stat($path);
329
-		if (is_array($stat)) {
330
-			return $stat['mimetype'];
331
-		} else {
332
-			return false;
333
-		}
334
-	}
335
-
336
-	public function touch($path, $mtime = null) {
337
-		if (is_null($mtime)) {
338
-			$mtime = time();
339
-		}
340
-
341
-		$path = $this->normalizePath($path);
342
-		$dirName = dirname($path);
343
-		$parentExists = $this->is_dir($dirName);
344
-		if (!$parentExists) {
345
-			return false;
346
-		}
347
-
348
-		$stat = $this->stat($path);
349
-		if (is_array($stat)) {
350
-			// update existing mtime in db
351
-			$stat['mtime'] = $mtime;
352
-			$this->getCache()->update($stat['fileid'], $stat);
353
-		} else {
354
-			$mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
355
-			// create new file
356
-			$stat = array(
357
-				'etag' => $this->getETag($path),
358
-				'mimetype' => $mimeType,
359
-				'size' => 0,
360
-				'mtime' => $mtime,
361
-				'storage_mtime' => $mtime,
362
-				'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
363
-			);
364
-			$fileId = $this->getCache()->put($path, $stat);
365
-			try {
366
-				//read an empty file from memory
367
-				$this->objectStore->writeObject($this->getURN($fileId), fopen('php://memory', 'r'));
368
-			} catch (\Exception $ex) {
369
-				$this->getCache()->remove($path);
370
-				$this->logger->logException($ex, [
371
-					'app' => 'objectstore',
372
-					'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
373
-				]);
374
-				return false;
375
-			}
376
-		}
377
-		return true;
378
-	}
379
-
380
-	public function writeBack($tmpFile, $path) {
381
-		$stat = $this->stat($path);
382
-		if (empty($stat)) {
383
-			// create new file
384
-			$stat = array(
385
-				'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
386
-			);
387
-		}
388
-		// update stat with new data
389
-		$mTime = time();
390
-		$stat['size'] = filesize($tmpFile);
391
-		$stat['mtime'] = $mTime;
392
-		$stat['storage_mtime'] = $mTime;
393
-		$stat['mimetype'] = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
394
-		$stat['etag'] = $this->getETag($path);
395
-
396
-		$fileId = $this->getCache()->put($path, $stat);
397
-		try {
398
-			//upload to object storage
399
-			$this->objectStore->writeObject($this->getURN($fileId), fopen($tmpFile, 'r'));
400
-		} catch (\Exception $ex) {
401
-			$this->getCache()->remove($path);
402
-			$this->logger->logException($ex, [
403
-				'app' => 'objectstore',
404
-				'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
405
-			]);
406
-			throw $ex; // make this bubble up
407
-		}
408
-	}
409
-
410
-	/**
411
-	 * external changes are not supported, exclusive access to the object storage is assumed
412
-	 *
413
-	 * @param string $path
414
-	 * @param int $time
415
-	 * @return false
416
-	 */
417
-	public function hasUpdated($path, $time) {
418
-		return false;
419
-	}
34
+    /**
35
+     * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
36
+     */
37
+    protected $objectStore;
38
+    /**
39
+     * @var string $id
40
+     */
41
+    protected $id;
42
+    /**
43
+     * @var \OC\User\User $user
44
+     */
45
+    protected $user;
46
+
47
+    private $objectPrefix = 'urn:oid:';
48
+
49
+    private $logger;
50
+
51
+    public function __construct($params) {
52
+        if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
53
+            $this->objectStore = $params['objectstore'];
54
+        } else {
55
+            throw new \Exception('missing IObjectStore instance');
56
+        }
57
+        if (isset($params['storageid'])) {
58
+            $this->id = 'object::store:' . $params['storageid'];
59
+        } else {
60
+            $this->id = 'object::store:' . $this->objectStore->getStorageId();
61
+        }
62
+        if (isset($params['objectPrefix'])) {
63
+            $this->objectPrefix = $params['objectPrefix'];
64
+        }
65
+        //initialize cache with root directory in cache
66
+        if (!$this->is_dir('/')) {
67
+            $this->mkdir('/');
68
+        }
69
+
70
+        $this->logger = \OC::$server->getLogger();
71
+    }
72
+
73
+    public function mkdir($path) {
74
+        $path = $this->normalizePath($path);
75
+
76
+        if ($this->file_exists($path)) {
77
+            return false;
78
+        }
79
+
80
+        $mTime = time();
81
+        $data = [
82
+            'mimetype' => 'httpd/unix-directory',
83
+            'size' => 0,
84
+            'mtime' => $mTime,
85
+            'storage_mtime' => $mTime,
86
+            'permissions' => \OCP\Constants::PERMISSION_ALL,
87
+        ];
88
+        if ($path === '') {
89
+            //create root on the fly
90
+            $data['etag'] = $this->getETag('');
91
+            $this->getCache()->put('', $data);
92
+            return true;
93
+        } else {
94
+            // if parent does not exist, create it
95
+            $parent = $this->normalizePath(dirname($path));
96
+            $parentType = $this->filetype($parent);
97
+            if ($parentType === false) {
98
+                if (!$this->mkdir($parent)) {
99
+                    // something went wrong
100
+                    return false;
101
+                }
102
+            } else if ($parentType === 'file') {
103
+                // parent is a file
104
+                return false;
105
+            }
106
+            // finally create the new dir
107
+            $mTime = time(); // update mtime
108
+            $data['mtime'] = $mTime;
109
+            $data['storage_mtime'] = $mTime;
110
+            $data['etag'] = $this->getETag($path);
111
+            $this->getCache()->put($path, $data);
112
+            return true;
113
+        }
114
+    }
115
+
116
+    /**
117
+     * @param string $path
118
+     * @return string
119
+     */
120
+    private function normalizePath($path) {
121
+        $path = trim($path, '/');
122
+        //FIXME why do we sometimes get a path like 'files//username'?
123
+        $path = str_replace('//', '/', $path);
124
+
125
+        // dirname('/folder') returns '.' but internally (in the cache) we store the root as ''
126
+        if (!$path || $path === '.') {
127
+            $path = '';
128
+        }
129
+
130
+        return $path;
131
+    }
132
+
133
+    /**
134
+     * Object Stores use a NoopScanner because metadata is directly stored in
135
+     * the file cache and cannot really scan the filesystem. The storage passed in is not used anywhere.
136
+     *
137
+     * @param string $path
138
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
139
+     * @return \OC\Files\ObjectStore\NoopScanner
140
+     */
141
+    public function getScanner($path = '', $storage = null) {
142
+        if (!$storage) {
143
+            $storage = $this;
144
+        }
145
+        if (!isset($this->scanner)) {
146
+            $this->scanner = new NoopScanner($storage);
147
+        }
148
+        return $this->scanner;
149
+    }
150
+
151
+    public function getId() {
152
+        return $this->id;
153
+    }
154
+
155
+    public function rmdir($path) {
156
+        $path = $this->normalizePath($path);
157
+
158
+        if (!$this->is_dir($path)) {
159
+            return false;
160
+        }
161
+
162
+        $this->rmObjects($path);
163
+
164
+        $this->getCache()->remove($path);
165
+
166
+        return true;
167
+    }
168
+
169
+    private function rmObjects($path) {
170
+        $children = $this->getCache()->getFolderContents($path);
171
+        foreach ($children as $child) {
172
+            if ($child['mimetype'] === 'httpd/unix-directory') {
173
+                $this->rmObjects($child['path']);
174
+            } else {
175
+                $this->unlink($child['path']);
176
+            }
177
+        }
178
+    }
179
+
180
+    public function unlink($path) {
181
+        $path = $this->normalizePath($path);
182
+        $stat = $this->stat($path);
183
+
184
+        if ($stat && isset($stat['fileid'])) {
185
+            if ($stat['mimetype'] === 'httpd/unix-directory') {
186
+                return $this->rmdir($path);
187
+            }
188
+            try {
189
+                $this->objectStore->deleteObject($this->getURN($stat['fileid']));
190
+            } catch (\Exception $ex) {
191
+                if ($ex->getCode() !== 404) {
192
+                    $this->logger->logException($ex, [
193
+                        'app' => 'objectstore',
194
+                        'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
195
+                    ]);
196
+                    return false;
197
+                } else {
198
+                    //removing from cache is ok as it does not exist in the objectstore anyway
199
+                }
200
+            }
201
+            $this->getCache()->remove($path);
202
+            return true;
203
+        }
204
+        return false;
205
+    }
206
+
207
+    public function stat($path) {
208
+        $path = $this->normalizePath($path);
209
+        $cacheEntry = $this->getCache()->get($path);
210
+        if ($cacheEntry instanceof CacheEntry) {
211
+            return $cacheEntry->getData();
212
+        } else {
213
+            return false;
214
+        }
215
+    }
216
+
217
+    /**
218
+     * Override this method if you need a different unique resource identifier for your object storage implementation.
219
+     * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users.
220
+     * You may need a mapping table to store your URN if it cannot be generated from the fileid.
221
+     *
222
+     * @param int $fileId the fileid
223
+     * @return null|string the unified resource name used to identify the object
224
+     */
225
+    protected function getURN($fileId) {
226
+        if (is_numeric($fileId)) {
227
+            return $this->objectPrefix . $fileId;
228
+        }
229
+        return null;
230
+    }
231
+
232
+    public function opendir($path) {
233
+        $path = $this->normalizePath($path);
234
+
235
+        try {
236
+            $files = array();
237
+            $folderContents = $this->getCache()->getFolderContents($path);
238
+            foreach ($folderContents as $file) {
239
+                $files[] = $file['name'];
240
+            }
241
+
242
+            return IteratorDirectory::wrap($files);
243
+        } catch (\Exception $e) {
244
+            $this->logger->logException($e);
245
+            return false;
246
+        }
247
+    }
248
+
249
+    public function filetype($path) {
250
+        $path = $this->normalizePath($path);
251
+        $stat = $this->stat($path);
252
+        if ($stat) {
253
+            if ($stat['mimetype'] === 'httpd/unix-directory') {
254
+                return 'dir';
255
+            }
256
+            return 'file';
257
+        } else {
258
+            return false;
259
+        }
260
+    }
261
+
262
+    public function fopen($path, $mode) {
263
+        $path = $this->normalizePath($path);
264
+
265
+        switch ($mode) {
266
+            case 'r':
267
+            case 'rb':
268
+                $stat = $this->stat($path);
269
+                if (is_array($stat)) {
270
+                    try {
271
+                        return $this->objectStore->readObject($this->getURN($stat['fileid']));
272
+                    } catch (\Exception $ex) {
273
+                        $this->logger->logException($ex, [
274
+                            'app' => 'objectstore',
275
+                            'message' => 'Count not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
276
+                        ]);
277
+                        return false;
278
+                    }
279
+                } else {
280
+                    return false;
281
+                }
282
+            case 'w':
283
+            case 'wb':
284
+            case 'a':
285
+            case 'ab':
286
+            case 'r+':
287
+            case 'w+':
288
+            case 'wb+':
289
+            case 'a+':
290
+            case 'x':
291
+            case 'x+':
292
+            case 'c':
293
+            case 'c+':
294
+                if (strrpos($path, '.') !== false) {
295
+                    $ext = substr($path, strrpos($path, '.'));
296
+                } else {
297
+                    $ext = '';
298
+                }
299
+                $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
300
+                if ($this->file_exists($path)) {
301
+                    $source = $this->fopen($path, 'r');
302
+                    file_put_contents($tmpFile, $source);
303
+                }
304
+                $handle = fopen($tmpFile, $mode);
305
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
306
+                    $this->writeBack($tmpFile, $path);
307
+                });
308
+        }
309
+        return false;
310
+    }
311
+
312
+    public function file_exists($path) {
313
+        $path = $this->normalizePath($path);
314
+        return (bool)$this->stat($path);
315
+    }
316
+
317
+    public function rename($source, $target) {
318
+        $source = $this->normalizePath($source);
319
+        $target = $this->normalizePath($target);
320
+        $this->remove($target);
321
+        $this->getCache()->move($source, $target);
322
+        $this->touch(dirname($target));
323
+        return true;
324
+    }
325
+
326
+    public function getMimeType($path) {
327
+        $path = $this->normalizePath($path);
328
+        $stat = $this->stat($path);
329
+        if (is_array($stat)) {
330
+            return $stat['mimetype'];
331
+        } else {
332
+            return false;
333
+        }
334
+    }
335
+
336
+    public function touch($path, $mtime = null) {
337
+        if (is_null($mtime)) {
338
+            $mtime = time();
339
+        }
340
+
341
+        $path = $this->normalizePath($path);
342
+        $dirName = dirname($path);
343
+        $parentExists = $this->is_dir($dirName);
344
+        if (!$parentExists) {
345
+            return false;
346
+        }
347
+
348
+        $stat = $this->stat($path);
349
+        if (is_array($stat)) {
350
+            // update existing mtime in db
351
+            $stat['mtime'] = $mtime;
352
+            $this->getCache()->update($stat['fileid'], $stat);
353
+        } else {
354
+            $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
355
+            // create new file
356
+            $stat = array(
357
+                'etag' => $this->getETag($path),
358
+                'mimetype' => $mimeType,
359
+                'size' => 0,
360
+                'mtime' => $mtime,
361
+                'storage_mtime' => $mtime,
362
+                'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
363
+            );
364
+            $fileId = $this->getCache()->put($path, $stat);
365
+            try {
366
+                //read an empty file from memory
367
+                $this->objectStore->writeObject($this->getURN($fileId), fopen('php://memory', 'r'));
368
+            } catch (\Exception $ex) {
369
+                $this->getCache()->remove($path);
370
+                $this->logger->logException($ex, [
371
+                    'app' => 'objectstore',
372
+                    'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
373
+                ]);
374
+                return false;
375
+            }
376
+        }
377
+        return true;
378
+    }
379
+
380
+    public function writeBack($tmpFile, $path) {
381
+        $stat = $this->stat($path);
382
+        if (empty($stat)) {
383
+            // create new file
384
+            $stat = array(
385
+                'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
386
+            );
387
+        }
388
+        // update stat with new data
389
+        $mTime = time();
390
+        $stat['size'] = filesize($tmpFile);
391
+        $stat['mtime'] = $mTime;
392
+        $stat['storage_mtime'] = $mTime;
393
+        $stat['mimetype'] = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
394
+        $stat['etag'] = $this->getETag($path);
395
+
396
+        $fileId = $this->getCache()->put($path, $stat);
397
+        try {
398
+            //upload to object storage
399
+            $this->objectStore->writeObject($this->getURN($fileId), fopen($tmpFile, 'r'));
400
+        } catch (\Exception $ex) {
401
+            $this->getCache()->remove($path);
402
+            $this->logger->logException($ex, [
403
+                'app' => 'objectstore',
404
+                'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
405
+            ]);
406
+            throw $ex; // make this bubble up
407
+        }
408
+    }
409
+
410
+    /**
411
+     * external changes are not supported, exclusive access to the object storage is assumed
412
+     *
413
+     * @param string $path
414
+     * @param int $time
415
+     * @return false
416
+     */
417
+    public function hasUpdated($path, $time) {
418
+        return false;
419
+    }
420 420
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -55,9 +55,9 @@  discard block
 block discarded – undo
55 55
 			throw new \Exception('missing IObjectStore instance');
56 56
 		}
57 57
 		if (isset($params['storageid'])) {
58
-			$this->id = 'object::store:' . $params['storageid'];
58
+			$this->id = 'object::store:'.$params['storageid'];
59 59
 		} else {
60
-			$this->id = 'object::store:' . $this->objectStore->getStorageId();
60
+			$this->id = 'object::store:'.$this->objectStore->getStorageId();
61 61
 		}
62 62
 		if (isset($params['objectPrefix'])) {
63 63
 			$this->objectPrefix = $params['objectPrefix'];
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
 				if ($ex->getCode() !== 404) {
192 192
 					$this->logger->logException($ex, [
193 193
 						'app' => 'objectstore',
194
-						'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
194
+						'message' => 'Could not delete object '.$this->getURN($stat['fileid']).' for '.$path,
195 195
 					]);
196 196
 					return false;
197 197
 				} else {
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 	 */
225 225
 	protected function getURN($fileId) {
226 226
 		if (is_numeric($fileId)) {
227
-			return $this->objectPrefix . $fileId;
227
+			return $this->objectPrefix.$fileId;
228 228
 		}
229 229
 		return null;
230 230
 	}
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
 					} catch (\Exception $ex) {
273 273
 						$this->logger->logException($ex, [
274 274
 							'app' => 'objectstore',
275
-							'message' => 'Count not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
275
+							'message' => 'Count not get object '.$this->getURN($stat['fileid']).' for file '.$path,
276 276
 						]);
277 277
 						return false;
278 278
 					}
@@ -302,7 +302,7 @@  discard block
 block discarded – undo
302 302
 					file_put_contents($tmpFile, $source);
303 303
 				}
304 304
 				$handle = fopen($tmpFile, $mode);
305
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
305
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
306 306
 					$this->writeBack($tmpFile, $path);
307 307
 				});
308 308
 		}
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
 
312 312
 	public function file_exists($path) {
313 313
 		$path = $this->normalizePath($path);
314
-		return (bool)$this->stat($path);
314
+		return (bool) $this->stat($path);
315 315
 	}
316 316
 
317 317
 	public function rename($source, $target) {
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
 				$this->getCache()->remove($path);
370 370
 				$this->logger->logException($ex, [
371 371
 					'app' => 'objectstore',
372
-					'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
372
+					'message' => 'Could not create object '.$this->getURN($fileId).' for '.$path,
373 373
 				]);
374 374
 				return false;
375 375
 			}
@@ -401,7 +401,7 @@  discard block
 block discarded – undo
401 401
 			$this->getCache()->remove($path);
402 402
 			$this->logger->logException($ex, [
403 403
 				'app' => 'objectstore',
404
-				'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
404
+				'message' => 'Could not create object '.$this->getURN($fileId).' for '.$path,
405 405
 			]);
406 406
 			throw $ex; // make this bubble up
407 407
 		}
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -102,7 +102,7 @@
 block discarded – undo
102 102
 
103 103
 	/**
104 104
 	 * @param \Icewind\SMB\Change $change
105
-	 * @return IChange|null
105
+	 * @return null|Change
106 106
 	 */
107 107
 	private function mapChange(\Icewind\SMB\Change $change) {
108 108
 		$path = $this->relativePath($change->getPath());
Please login to merge, or discard this patch.
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -29,122 +29,122 @@
 block discarded – undo
29 29
 use OCP\Files\Notify\INotifyHandler;
30 30
 
31 31
 class SMBNotifyHandler implements INotifyHandler {
32
-	/**
33
-	 * @var \Icewind\SMB\INotifyHandler
34
-	 */
35
-	private $shareNotifyHandler;
32
+    /**
33
+     * @var \Icewind\SMB\INotifyHandler
34
+     */
35
+    private $shareNotifyHandler;
36 36
 
37
-	/**
38
-	 * @var string
39
-	 */
40
-	private $root;
37
+    /**
38
+     * @var string
39
+     */
40
+    private $root;
41 41
 
42
-	private $oldRenamePath = null;
42
+    private $oldRenamePath = null;
43 43
 
44
-	/**
45
-	 * SMBNotifyHandler constructor.
46
-	 *
47
-	 * @param \Icewind\SMB\INotifyHandler $shareNotifyHandler
48
-	 * @param string $root
49
-	 */
50
-	public function __construct(\Icewind\SMB\INotifyHandler $shareNotifyHandler, $root) {
51
-		$this->shareNotifyHandler = $shareNotifyHandler;
52
-		$this->root = $root;
53
-	}
44
+    /**
45
+     * SMBNotifyHandler constructor.
46
+     *
47
+     * @param \Icewind\SMB\INotifyHandler $shareNotifyHandler
48
+     * @param string $root
49
+     */
50
+    public function __construct(\Icewind\SMB\INotifyHandler $shareNotifyHandler, $root) {
51
+        $this->shareNotifyHandler = $shareNotifyHandler;
52
+        $this->root = $root;
53
+    }
54 54
 
55
-	private function relativePath($fullPath) {
56
-		if ($fullPath === $this->root) {
57
-			return '';
58
-		} else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
59
-			return substr($fullPath, strlen($this->root));
60
-		} else {
61
-			return null;
62
-		}
63
-	}
55
+    private function relativePath($fullPath) {
56
+        if ($fullPath === $this->root) {
57
+            return '';
58
+        } else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
59
+            return substr($fullPath, strlen($this->root));
60
+        } else {
61
+            return null;
62
+        }
63
+    }
64 64
 
65
-	public function listen(callable $callback) {
66
-		$oldRenamePath = null;
67
-		$this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
68
-			$change = $this->mapChange($shareChange);
69
-			if (!is_null($change)) {
70
-				return $callback($change);
71
-			} else {
72
-				return true;
73
-			}
74
-		});
75
-	}
65
+    public function listen(callable $callback) {
66
+        $oldRenamePath = null;
67
+        $this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
68
+            $change = $this->mapChange($shareChange);
69
+            if (!is_null($change)) {
70
+                return $callback($change);
71
+            } else {
72
+                return true;
73
+            }
74
+        });
75
+    }
76 76
 
77
-	/**
78
-	 * Get all changes detected since the start of the notify process or the last call to getChanges
79
-	 *
80
-	 * @return IChange[]
81
-	 */
82
-	public function getChanges() {
83
-		$shareChanges = $this->shareNotifyHandler->getChanges();
84
-		$changes = [];
85
-		foreach ($shareChanges as $shareChange) {
86
-			$change = $this->mapChange($shareChange);
87
-			if ($change) {
88
-				$changes[] = $change;
89
-			}
90
-		}
91
-		return $changes;
92
-	}
77
+    /**
78
+     * Get all changes detected since the start of the notify process or the last call to getChanges
79
+     *
80
+     * @return IChange[]
81
+     */
82
+    public function getChanges() {
83
+        $shareChanges = $this->shareNotifyHandler->getChanges();
84
+        $changes = [];
85
+        foreach ($shareChanges as $shareChange) {
86
+            $change = $this->mapChange($shareChange);
87
+            if ($change) {
88
+                $changes[] = $change;
89
+            }
90
+        }
91
+        return $changes;
92
+    }
93 93
 
94
-	/**
95
-	 * Stop listening for changes
96
-	 *
97
-	 * Note that any pending changes will be discarded
98
-	 */
99
-	public function stop() {
100
-		$this->shareNotifyHandler->stop();
101
-	}
94
+    /**
95
+     * Stop listening for changes
96
+     *
97
+     * Note that any pending changes will be discarded
98
+     */
99
+    public function stop() {
100
+        $this->shareNotifyHandler->stop();
101
+    }
102 102
 
103
-	/**
104
-	 * @param \Icewind\SMB\Change $change
105
-	 * @return IChange|null
106
-	 */
107
-	private function mapChange(\Icewind\SMB\Change $change) {
108
-		$path = $this->relativePath($change->getPath());
109
-		if (is_null($path)) {
110
-			return null;
111
-		}
112
-		if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) {
113
-			$this->oldRenamePath = $path;
114
-			return null;
115
-		}
116
-		$type = $this->mapNotifyType($change->getCode());
117
-		if (is_null($type)) {
118
-			return null;
119
-		}
120
-		if ($type === IChange::RENAMED) {
121
-			if (!is_null($this->oldRenamePath)) {
122
-				$result = new RenameChange($type, $this->oldRenamePath, $path);
123
-				$this->oldRenamePath = null;
124
-			} else {
125
-				$result = null;
126
-			}
127
-		} else {
128
-			$result = new Change($type, $path);
129
-		}
130
-		return $result;
131
-	}
103
+    /**
104
+     * @param \Icewind\SMB\Change $change
105
+     * @return IChange|null
106
+     */
107
+    private function mapChange(\Icewind\SMB\Change $change) {
108
+        $path = $this->relativePath($change->getPath());
109
+        if (is_null($path)) {
110
+            return null;
111
+        }
112
+        if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) {
113
+            $this->oldRenamePath = $path;
114
+            return null;
115
+        }
116
+        $type = $this->mapNotifyType($change->getCode());
117
+        if (is_null($type)) {
118
+            return null;
119
+        }
120
+        if ($type === IChange::RENAMED) {
121
+            if (!is_null($this->oldRenamePath)) {
122
+                $result = new RenameChange($type, $this->oldRenamePath, $path);
123
+                $this->oldRenamePath = null;
124
+            } else {
125
+                $result = null;
126
+            }
127
+        } else {
128
+            $result = new Change($type, $path);
129
+        }
130
+        return $result;
131
+    }
132 132
 
133
-	private function mapNotifyType($smbType) {
134
-		switch ($smbType) {
135
-			case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED:
136
-				return IChange::ADDED;
137
-			case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED:
138
-				return IChange::REMOVED;
139
-			case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED:
140
-			case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM:
141
-			case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM:
142
-			case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM:
143
-				return IChange::MODIFIED;
144
-			case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW:
145
-				return IChange::RENAMED;
146
-			default:
147
-				return null;
148
-		}
149
-	}
133
+    private function mapNotifyType($smbType) {
134
+        switch ($smbType) {
135
+            case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED:
136
+                return IChange::ADDED;
137
+            case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED:
138
+                return IChange::REMOVED;
139
+            case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED:
140
+            case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM:
141
+            case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM:
142
+            case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM:
143
+                return IChange::MODIFIED;
144
+            case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW:
145
+                return IChange::RENAMED;
146
+            default:
147
+                return null;
148
+        }
149
+    }
150 150
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -64,7 +64,7 @@
 block discarded – undo
64 64
 
65 65
 	public function listen(callable $callback) {
66 66
 		$oldRenamePath = null;
67
-		$this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
67
+		$this->shareNotifyHandler->listen(function(\Icewind\SMB\Change $shareChange) use ($callback) {
68 68
 			$change = $this->mapChange($shareChange);
69 69
 			if (!is_null($change)) {
70 70
 				return $callback($change);
Please login to merge, or discard this patch.
lib/private/legacy/app.php 3 patches
Doc Comments   +6 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1063,7 +1063,7 @@  discard block
 block discarded – undo
1063 1063
 	 * @param string $app
1064 1064
 	 * @param \OCP\IConfig $config
1065 1065
 	 * @param \OCP\IL10N $l
1066
-	 * @return bool
1066
+	 * @return string
1067 1067
 	 *
1068 1068
 	 * @throws Exception if app is not compatible with this version of ownCloud
1069 1069
 	 * @throws Exception if no app-name was specified
@@ -1243,6 +1243,11 @@  discard block
 block discarded – undo
1243 1243
 		}
1244 1244
 	}
1245 1245
 
1246
+	/**
1247
+	 * @param string $lang
1248
+	 *
1249
+	 * @return string
1250
+	 */
1246 1251
 	protected static function findBestL10NOption($options, $lang) {
1247 1252
 		$fallback = $similarLangFallback = $englishFallback = false;
1248 1253
 
Please login to merge, or discard this patch.
Indentation   +1191 added lines, -1191 removed lines patch added patch discarded remove patch
@@ -61,1195 +61,1195 @@
 block discarded – undo
61 61
  * upgrading and removing apps.
62 62
  */
63 63
 class OC_App {
64
-	static private $appVersion = [];
65
-	static private $adminForms = array();
66
-	static private $personalForms = array();
67
-	static private $appInfo = array();
68
-	static private $appTypes = array();
69
-	static private $loadedApps = array();
70
-	static private $altLogin = array();
71
-	static private $alreadyRegistered = [];
72
-	const officialApp = 200;
73
-
74
-	/**
75
-	 * clean the appId
76
-	 *
77
-	 * @param string|boolean $app AppId that needs to be cleaned
78
-	 * @return string
79
-	 */
80
-	public static function cleanAppId($app) {
81
-		return str_replace(array('\0', '/', '\\', '..'), '', $app);
82
-	}
83
-
84
-	/**
85
-	 * Check if an app is loaded
86
-	 *
87
-	 * @param string $app
88
-	 * @return bool
89
-	 */
90
-	public static function isAppLoaded($app) {
91
-		return in_array($app, self::$loadedApps, true);
92
-	}
93
-
94
-	/**
95
-	 * loads all apps
96
-	 *
97
-	 * @param string[] | string | null $types
98
-	 * @return bool
99
-	 *
100
-	 * This function walks through the ownCloud directory and loads all apps
101
-	 * it can find. A directory contains an app if the file /appinfo/info.xml
102
-	 * exists.
103
-	 *
104
-	 * if $types is set, only apps of those types will be loaded
105
-	 */
106
-	public static function loadApps($types = null) {
107
-		if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
108
-			return false;
109
-		}
110
-		// Load the enabled apps here
111
-		$apps = self::getEnabledApps();
112
-
113
-		// Add each apps' folder as allowed class path
114
-		foreach($apps as $app) {
115
-			$path = self::getAppPath($app);
116
-			if($path !== false) {
117
-				self::registerAutoloading($app, $path);
118
-			}
119
-		}
120
-
121
-		// prevent app.php from printing output
122
-		ob_start();
123
-		foreach ($apps as $app) {
124
-			if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
125
-				self::loadApp($app);
126
-			}
127
-		}
128
-		ob_end_clean();
129
-
130
-		return true;
131
-	}
132
-
133
-	/**
134
-	 * load a single app
135
-	 *
136
-	 * @param string $app
137
-	 */
138
-	public static function loadApp($app) {
139
-		self::$loadedApps[] = $app;
140
-		$appPath = self::getAppPath($app);
141
-		if($appPath === false) {
142
-			return;
143
-		}
144
-
145
-		// in case someone calls loadApp() directly
146
-		self::registerAutoloading($app, $appPath);
147
-
148
-		if (is_file($appPath . '/appinfo/app.php')) {
149
-			\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
150
-			self::requireAppFile($app);
151
-			if (self::isType($app, array('authentication'))) {
152
-				// since authentication apps affect the "is app enabled for group" check,
153
-				// the enabled apps cache needs to be cleared to make sure that the
154
-				// next time getEnableApps() is called it will also include apps that were
155
-				// enabled for groups
156
-				self::$enabledAppsCache = array();
157
-			}
158
-			\OC::$server->getEventLogger()->end('load_app_' . $app);
159
-		}
160
-
161
-		$info = self::getAppInfo($app);
162
-		if (!empty($info['activity']['filters'])) {
163
-			foreach ($info['activity']['filters'] as $filter) {
164
-				\OC::$server->getActivityManager()->registerFilter($filter);
165
-			}
166
-		}
167
-		if (!empty($info['activity']['settings'])) {
168
-			foreach ($info['activity']['settings'] as $setting) {
169
-				\OC::$server->getActivityManager()->registerSetting($setting);
170
-			}
171
-		}
172
-		if (!empty($info['activity']['providers'])) {
173
-			foreach ($info['activity']['providers'] as $provider) {
174
-				\OC::$server->getActivityManager()->registerProvider($provider);
175
-			}
176
-		}
177
-	}
178
-
179
-	/**
180
-	 * @internal
181
-	 * @param string $app
182
-	 * @param string $path
183
-	 */
184
-	public static function registerAutoloading($app, $path) {
185
-		$key = $app . '-' . $path;
186
-		if(isset(self::$alreadyRegistered[$key])) {
187
-			return;
188
-		}
189
-		self::$alreadyRegistered[$key] = true;
190
-		// Register on PSR-4 composer autoloader
191
-		$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
192
-		\OC::$server->registerNamespace($app, $appNamespace);
193
-		\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
194
-		if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
195
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
196
-		}
197
-
198
-		// Register on legacy autoloader
199
-		\OC::$loader->addValidRoot($path);
200
-	}
201
-
202
-	/**
203
-	 * Load app.php from the given app
204
-	 *
205
-	 * @param string $app app name
206
-	 */
207
-	private static function requireAppFile($app) {
208
-		try {
209
-			// encapsulated here to avoid variable scope conflicts
210
-			require_once $app . '/appinfo/app.php';
211
-		} catch (Error $ex) {
212
-			\OC::$server->getLogger()->logException($ex);
213
-			$blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
214
-			if (!in_array($app, $blacklist)) {
215
-				self::disable($app);
216
-			}
217
-		}
218
-	}
219
-
220
-	/**
221
-	 * check if an app is of a specific type
222
-	 *
223
-	 * @param string $app
224
-	 * @param string|array $types
225
-	 * @return bool
226
-	 */
227
-	public static function isType($app, $types) {
228
-		if (is_string($types)) {
229
-			$types = array($types);
230
-		}
231
-		$appTypes = self::getAppTypes($app);
232
-		foreach ($types as $type) {
233
-			if (array_search($type, $appTypes) !== false) {
234
-				return true;
235
-			}
236
-		}
237
-		return false;
238
-	}
239
-
240
-	/**
241
-	 * get the types of an app
242
-	 *
243
-	 * @param string $app
244
-	 * @return array
245
-	 */
246
-	private static function getAppTypes($app) {
247
-		//load the cache
248
-		if (count(self::$appTypes) == 0) {
249
-			self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
250
-		}
251
-
252
-		if (isset(self::$appTypes[$app])) {
253
-			return explode(',', self::$appTypes[$app]);
254
-		} else {
255
-			return array();
256
-		}
257
-	}
258
-
259
-	/**
260
-	 * read app types from info.xml and cache them in the database
261
-	 */
262
-	public static function setAppTypes($app) {
263
-		$appData = self::getAppInfo($app);
264
-		if(!is_array($appData)) {
265
-			return;
266
-		}
267
-
268
-		if (isset($appData['types'])) {
269
-			$appTypes = implode(',', $appData['types']);
270
-		} else {
271
-			$appTypes = '';
272
-			$appData['types'] = [];
273
-		}
274
-
275
-		\OC::$server->getAppConfig()->setValue($app, 'types', $appTypes);
276
-
277
-		if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) {
278
-			$enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'yes');
279
-			if ($enabled !== 'yes' && $enabled !== 'no') {
280
-				\OC::$server->getAppConfig()->setValue($app, 'enabled', 'yes');
281
-			}
282
-		}
283
-	}
284
-
285
-	/**
286
-	 * check if app is shipped
287
-	 *
288
-	 * @param string $appId the id of the app to check
289
-	 * @return bool
290
-	 *
291
-	 * Check if an app that is installed is a shipped app or installed from the appstore.
292
-	 */
293
-	public static function isShipped($appId) {
294
-		return \OC::$server->getAppManager()->isShipped($appId);
295
-	}
296
-
297
-	/**
298
-	 * get all enabled apps
299
-	 */
300
-	protected static $enabledAppsCache = array();
301
-
302
-	/**
303
-	 * Returns apps enabled for the current user.
304
-	 *
305
-	 * @param bool $forceRefresh whether to refresh the cache
306
-	 * @param bool $all whether to return apps for all users, not only the
307
-	 * currently logged in one
308
-	 * @return string[]
309
-	 */
310
-	public static function getEnabledApps($forceRefresh = false, $all = false) {
311
-		if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
312
-			return array();
313
-		}
314
-		// in incognito mode or when logged out, $user will be false,
315
-		// which is also the case during an upgrade
316
-		$appManager = \OC::$server->getAppManager();
317
-		if ($all) {
318
-			$user = null;
319
-		} else {
320
-			$user = \OC::$server->getUserSession()->getUser();
321
-		}
322
-
323
-		if (is_null($user)) {
324
-			$apps = $appManager->getInstalledApps();
325
-		} else {
326
-			$apps = $appManager->getEnabledAppsForUser($user);
327
-		}
328
-		$apps = array_filter($apps, function ($app) {
329
-			return $app !== 'files';//we add this manually
330
-		});
331
-		sort($apps);
332
-		array_unshift($apps, 'files');
333
-		return $apps;
334
-	}
335
-
336
-	/**
337
-	 * checks whether or not an app is enabled
338
-	 *
339
-	 * @param string $app app
340
-	 * @return bool
341
-	 *
342
-	 * This function checks whether or not an app is enabled.
343
-	 */
344
-	public static function isEnabled($app) {
345
-		return \OC::$server->getAppManager()->isEnabledForUser($app);
346
-	}
347
-
348
-	/**
349
-	 * enables an app
350
-	 *
351
-	 * @param string $appId
352
-	 * @param array $groups (optional) when set, only these groups will have access to the app
353
-	 * @throws \Exception
354
-	 * @return void
355
-	 *
356
-	 * This function set an app as enabled in appconfig.
357
-	 */
358
-	public function enable($appId,
359
-						   $groups = null) {
360
-		self::$enabledAppsCache = []; // flush
361
-
362
-		// Check if app is already downloaded
363
-		$installer = new Installer(
364
-			\OC::$server->getAppFetcher(),
365
-			\OC::$server->getHTTPClientService(),
366
-			\OC::$server->getTempManager(),
367
-			\OC::$server->getLogger(),
368
-			\OC::$server->getConfig()
369
-		);
370
-		$isDownloaded = $installer->isDownloaded($appId);
371
-
372
-		if(!$isDownloaded) {
373
-			$installer->downloadApp($appId);
374
-		}
375
-
376
-		$installer->installApp($appId);
377
-
378
-		$appManager = \OC::$server->getAppManager();
379
-		if (!is_null($groups)) {
380
-			$groupManager = \OC::$server->getGroupManager();
381
-			$groupsList = [];
382
-			foreach ($groups as $group) {
383
-				$groupItem = $groupManager->get($group);
384
-				if ($groupItem instanceof \OCP\IGroup) {
385
-					$groupsList[] = $groupManager->get($group);
386
-				}
387
-			}
388
-			$appManager->enableAppForGroups($appId, $groupsList);
389
-		} else {
390
-			$appManager->enableApp($appId);
391
-		}
392
-	}
393
-
394
-	/**
395
-	 * @param string $app
396
-	 * @return bool
397
-	 */
398
-	public static function removeApp($app) {
399
-		if (self::isShipped($app)) {
400
-			return false;
401
-		}
402
-
403
-		$installer = new Installer(
404
-			\OC::$server->getAppFetcher(),
405
-			\OC::$server->getHTTPClientService(),
406
-			\OC::$server->getTempManager(),
407
-			\OC::$server->getLogger(),
408
-			\OC::$server->getConfig()
409
-		);
410
-		return $installer->removeApp($app);
411
-	}
412
-
413
-	/**
414
-	 * This function set an app as disabled in appconfig.
415
-	 *
416
-	 * @param string $app app
417
-	 * @throws Exception
418
-	 */
419
-	public static function disable($app) {
420
-		// flush
421
-		self::$enabledAppsCache = array();
422
-
423
-		// run uninstall steps
424
-		$appData = OC_App::getAppInfo($app);
425
-		if (!is_null($appData)) {
426
-			OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']);
427
-		}
428
-
429
-		// emit disable hook - needed anymore ?
430
-		\OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
431
-
432
-		// finally disable it
433
-		$appManager = \OC::$server->getAppManager();
434
-		$appManager->disableApp($app);
435
-	}
436
-
437
-	// This is private as well. It simply works, so don't ask for more details
438
-	private static function proceedNavigation($list) {
439
-		usort($list, function($a, $b) {
440
-			if (isset($a['order']) && isset($b['order'])) {
441
-				return ($a['order'] < $b['order']) ? -1 : 1;
442
-			} else if (isset($a['order']) || isset($b['order'])) {
443
-				return isset($a['order']) ? -1 : 1;
444
-			} else {
445
-				return ($a['name'] < $b['name']) ? -1 : 1;
446
-			}
447
-		});
448
-
449
-		$activeApp = OC::$server->getNavigationManager()->getActiveEntry();
450
-		foreach ($list as $index => &$navEntry) {
451
-			if ($navEntry['id'] == $activeApp) {
452
-				$navEntry['active'] = true;
453
-			} else {
454
-				$navEntry['active'] = false;
455
-			}
456
-		}
457
-		unset($navEntry);
458
-
459
-		return $list;
460
-	}
461
-
462
-	/**
463
-	 * Get the path where to install apps
464
-	 *
465
-	 * @return string|false
466
-	 */
467
-	public static function getInstallPath() {
468
-		if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
469
-			return false;
470
-		}
471
-
472
-		foreach (OC::$APPSROOTS as $dir) {
473
-			if (isset($dir['writable']) && $dir['writable'] === true) {
474
-				return $dir['path'];
475
-			}
476
-		}
477
-
478
-		\OCP\Util::writeLog('core', 'No application directories are marked as writable.', \OCP\Util::ERROR);
479
-		return null;
480
-	}
481
-
482
-
483
-	/**
484
-	 * search for an app in all app-directories
485
-	 *
486
-	 * @param string $appId
487
-	 * @return false|string
488
-	 */
489
-	public static function findAppInDirectories($appId) {
490
-		$sanitizedAppId = self::cleanAppId($appId);
491
-		if($sanitizedAppId !== $appId) {
492
-			return false;
493
-		}
494
-		static $app_dir = array();
495
-
496
-		if (isset($app_dir[$appId])) {
497
-			return $app_dir[$appId];
498
-		}
499
-
500
-		$possibleApps = array();
501
-		foreach (OC::$APPSROOTS as $dir) {
502
-			if (file_exists($dir['path'] . '/' . $appId)) {
503
-				$possibleApps[] = $dir;
504
-			}
505
-		}
506
-
507
-		if (empty($possibleApps)) {
508
-			return false;
509
-		} elseif (count($possibleApps) === 1) {
510
-			$dir = array_shift($possibleApps);
511
-			$app_dir[$appId] = $dir;
512
-			return $dir;
513
-		} else {
514
-			$versionToLoad = array();
515
-			foreach ($possibleApps as $possibleApp) {
516
-				$version = self::getAppVersionByPath($possibleApp['path']);
517
-				if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
518
-					$versionToLoad = array(
519
-						'dir' => $possibleApp,
520
-						'version' => $version,
521
-					);
522
-				}
523
-			}
524
-			$app_dir[$appId] = $versionToLoad['dir'];
525
-			return $versionToLoad['dir'];
526
-			//TODO - write test
527
-		}
528
-	}
529
-
530
-	/**
531
-	 * Get the directory for the given app.
532
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
533
-	 *
534
-	 * @param string $appId
535
-	 * @return string|false
536
-	 */
537
-	public static function getAppPath($appId) {
538
-		if ($appId === null || trim($appId) === '') {
539
-			return false;
540
-		}
541
-
542
-		if (($dir = self::findAppInDirectories($appId)) != false) {
543
-			return $dir['path'] . '/' . $appId;
544
-		}
545
-		return false;
546
-	}
547
-
548
-	/**
549
-	 * Get the path for the given app on the access
550
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
551
-	 *
552
-	 * @param string $appId
553
-	 * @return string|false
554
-	 */
555
-	public static function getAppWebPath($appId) {
556
-		if (($dir = self::findAppInDirectories($appId)) != false) {
557
-			return OC::$WEBROOT . $dir['url'] . '/' . $appId;
558
-		}
559
-		return false;
560
-	}
561
-
562
-	/**
563
-	 * get the last version of the app from appinfo/info.xml
564
-	 *
565
-	 * @param string $appId
566
-	 * @param bool $useCache
567
-	 * @return string
568
-	 */
569
-	public static function getAppVersion($appId, $useCache = true) {
570
-		if($useCache && isset(self::$appVersion[$appId])) {
571
-			return self::$appVersion[$appId];
572
-		}
573
-
574
-		$file = self::getAppPath($appId);
575
-		self::$appVersion[$appId] = ($file !== false) ? self::getAppVersionByPath($file) : '0';
576
-		return self::$appVersion[$appId];
577
-	}
578
-
579
-	/**
580
-	 * get app's version based on it's path
581
-	 *
582
-	 * @param string $path
583
-	 * @return string
584
-	 */
585
-	public static function getAppVersionByPath($path) {
586
-		$infoFile = $path . '/appinfo/info.xml';
587
-		$appData = self::getAppInfo($infoFile, true);
588
-		return isset($appData['version']) ? $appData['version'] : '';
589
-	}
590
-
591
-
592
-	/**
593
-	 * Read all app metadata from the info.xml file
594
-	 *
595
-	 * @param string $appId id of the app or the path of the info.xml file
596
-	 * @param bool $path
597
-	 * @param string $lang
598
-	 * @return array|null
599
-	 * @note all data is read from info.xml, not just pre-defined fields
600
-	 */
601
-	public static function getAppInfo($appId, $path = false, $lang = null) {
602
-		if ($path) {
603
-			$file = $appId;
604
-		} else {
605
-			if ($lang === null && isset(self::$appInfo[$appId])) {
606
-				return self::$appInfo[$appId];
607
-			}
608
-			$appPath = self::getAppPath($appId);
609
-			if($appPath === false) {
610
-				return null;
611
-			}
612
-			$file = $appPath . '/appinfo/info.xml';
613
-		}
614
-
615
-		$parser = new InfoParser(\OC::$server->getMemCacheFactory()->create('core.appinfo'));
616
-		$data = $parser->parse($file);
617
-
618
-		if (is_array($data)) {
619
-			$data = OC_App::parseAppInfo($data, $lang);
620
-		}
621
-		if(isset($data['ocsid'])) {
622
-			$storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
623
-			if($storedId !== '' && $storedId !== $data['ocsid']) {
624
-				$data['ocsid'] = $storedId;
625
-			}
626
-		}
627
-
628
-		if ($lang === null) {
629
-			self::$appInfo[$appId] = $data;
630
-		}
631
-
632
-		return $data;
633
-	}
634
-
635
-	/**
636
-	 * Returns the navigation
637
-	 *
638
-	 * @return array
639
-	 *
640
-	 * This function returns an array containing all entries added. The
641
-	 * entries are sorted by the key 'order' ascending. Additional to the keys
642
-	 * given for each app the following keys exist:
643
-	 *   - active: boolean, signals if the user is on this navigation entry
644
-	 */
645
-	public static function getNavigation() {
646
-		$entries = OC::$server->getNavigationManager()->getAll();
647
-		return self::proceedNavigation($entries);
648
-	}
649
-
650
-	/**
651
-	 * Returns the Settings Navigation
652
-	 *
653
-	 * @return string[]
654
-	 *
655
-	 * This function returns an array containing all settings pages added. The
656
-	 * entries are sorted by the key 'order' ascending.
657
-	 */
658
-	public static function getSettingsNavigation() {
659
-		$entries = OC::$server->getNavigationManager()->getAll('settings');
660
-		return self::proceedNavigation($entries);
661
-	}
662
-
663
-	/**
664
-	 * get the id of loaded app
665
-	 *
666
-	 * @return string
667
-	 */
668
-	public static function getCurrentApp() {
669
-		$request = \OC::$server->getRequest();
670
-		$script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
671
-		$topFolder = substr($script, 0, strpos($script, '/'));
672
-		if (empty($topFolder)) {
673
-			$path_info = $request->getPathInfo();
674
-			if ($path_info) {
675
-				$topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
676
-			}
677
-		}
678
-		if ($topFolder == 'apps') {
679
-			$length = strlen($topFolder);
680
-			return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1);
681
-		} else {
682
-			return $topFolder;
683
-		}
684
-	}
685
-
686
-	/**
687
-	 * @param string $type
688
-	 * @return array
689
-	 */
690
-	public static function getForms($type) {
691
-		$forms = array();
692
-		switch ($type) {
693
-			case 'admin':
694
-				$source = self::$adminForms;
695
-				break;
696
-			case 'personal':
697
-				$source = self::$personalForms;
698
-				break;
699
-			default:
700
-				return array();
701
-		}
702
-		foreach ($source as $form) {
703
-			$forms[] = include $form;
704
-		}
705
-		return $forms;
706
-	}
707
-
708
-	/**
709
-	 * register an admin form to be shown
710
-	 *
711
-	 * @param string $app
712
-	 * @param string $page
713
-	 */
714
-	public static function registerAdmin($app, $page) {
715
-		self::$adminForms[] = $app . '/' . $page . '.php';
716
-	}
717
-
718
-	/**
719
-	 * register a personal form to be shown
720
-	 * @param string $app
721
-	 * @param string $page
722
-	 */
723
-	public static function registerPersonal($app, $page) {
724
-		self::$personalForms[] = $app . '/' . $page . '.php';
725
-	}
726
-
727
-	/**
728
-	 * @param array $entry
729
-	 */
730
-	public static function registerLogIn(array $entry) {
731
-		self::$altLogin[] = $entry;
732
-	}
733
-
734
-	/**
735
-	 * @return array
736
-	 */
737
-	public static function getAlternativeLogIns() {
738
-		return self::$altLogin;
739
-	}
740
-
741
-	/**
742
-	 * get a list of all apps in the apps folder
743
-	 *
744
-	 * @return array an array of app names (string IDs)
745
-	 * @todo: change the name of this method to getInstalledApps, which is more accurate
746
-	 */
747
-	public static function getAllApps() {
748
-
749
-		$apps = array();
750
-
751
-		foreach (OC::$APPSROOTS as $apps_dir) {
752
-			if (!is_readable($apps_dir['path'])) {
753
-				\OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
754
-				continue;
755
-			}
756
-			$dh = opendir($apps_dir['path']);
757
-
758
-			if (is_resource($dh)) {
759
-				while (($file = readdir($dh)) !== false) {
760
-
761
-					if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
762
-
763
-						$apps[] = $file;
764
-					}
765
-				}
766
-			}
767
-		}
768
-
769
-		return $apps;
770
-	}
771
-
772
-	/**
773
-	 * List all apps, this is used in apps.php
774
-	 *
775
-	 * @return array
776
-	 */
777
-	public function listAllApps() {
778
-		$installedApps = OC_App::getAllApps();
779
-
780
-		//we don't want to show configuration for these
781
-		$blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
782
-		$appList = array();
783
-		$langCode = \OC::$server->getL10N('core')->getLanguageCode();
784
-		$urlGenerator = \OC::$server->getURLGenerator();
785
-
786
-		foreach ($installedApps as $app) {
787
-			if (array_search($app, $blacklist) === false) {
788
-
789
-				$info = OC_App::getAppInfo($app, false, $langCode);
790
-				if (!is_array($info)) {
791
-					\OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
792
-					continue;
793
-				}
794
-
795
-				if (!isset($info['name'])) {
796
-					\OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
797
-					continue;
798
-				}
799
-
800
-				$enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'no');
801
-				$info['groups'] = null;
802
-				if ($enabled === 'yes') {
803
-					$active = true;
804
-				} else if ($enabled === 'no') {
805
-					$active = false;
806
-				} else {
807
-					$active = true;
808
-					$info['groups'] = $enabled;
809
-				}
810
-
811
-				$info['active'] = $active;
812
-
813
-				if (self::isShipped($app)) {
814
-					$info['internal'] = true;
815
-					$info['level'] = self::officialApp;
816
-					$info['removable'] = false;
817
-				} else {
818
-					$info['internal'] = false;
819
-					$info['removable'] = true;
820
-				}
821
-
822
-				$appPath = self::getAppPath($app);
823
-				if($appPath !== false) {
824
-					$appIcon = $appPath . '/img/' . $app . '.svg';
825
-					if (file_exists($appIcon)) {
826
-						$info['preview'] = \OC::$server->getURLGenerator()->imagePath($app, $app . '.svg');
827
-						$info['previewAsIcon'] = true;
828
-					} else {
829
-						$appIcon = $appPath . '/img/app.svg';
830
-						if (file_exists($appIcon)) {
831
-							$info['preview'] = \OC::$server->getURLGenerator()->imagePath($app, 'app.svg');
832
-							$info['previewAsIcon'] = true;
833
-						}
834
-					}
835
-				}
836
-				// fix documentation
837
-				if (isset($info['documentation']) && is_array($info['documentation'])) {
838
-					foreach ($info['documentation'] as $key => $url) {
839
-						// If it is not an absolute URL we assume it is a key
840
-						// i.e. admin-ldap will get converted to go.php?to=admin-ldap
841
-						if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
842
-							$url = $urlGenerator->linkToDocs($url);
843
-						}
844
-
845
-						$info['documentation'][$key] = $url;
846
-					}
847
-				}
848
-
849
-				$info['version'] = OC_App::getAppVersion($app);
850
-				$appList[] = $info;
851
-			}
852
-		}
853
-
854
-		return $appList;
855
-	}
856
-
857
-	/**
858
-	 * Returns the internal app ID or false
859
-	 * @param string $ocsID
860
-	 * @return string|false
861
-	 */
862
-	public static function getInternalAppIdByOcs($ocsID) {
863
-		if(is_numeric($ocsID)) {
864
-			$idArray = \OC::$server->getAppConfig()->getValues(false, 'ocsid');
865
-			if(array_search($ocsID, $idArray)) {
866
-				return array_search($ocsID, $idArray);
867
-			}
868
-		}
869
-		return false;
870
-	}
871
-
872
-	public static function shouldUpgrade($app) {
873
-		$versions = self::getAppVersions();
874
-		$currentVersion = OC_App::getAppVersion($app);
875
-		if ($currentVersion && isset($versions[$app])) {
876
-			$installedVersion = $versions[$app];
877
-			if (!version_compare($currentVersion, $installedVersion, '=')) {
878
-				return true;
879
-			}
880
-		}
881
-		return false;
882
-	}
883
-
884
-	/**
885
-	 * Adjust the number of version parts of $version1 to match
886
-	 * the number of version parts of $version2.
887
-	 *
888
-	 * @param string $version1 version to adjust
889
-	 * @param string $version2 version to take the number of parts from
890
-	 * @return string shortened $version1
891
-	 */
892
-	private static function adjustVersionParts($version1, $version2) {
893
-		$version1 = explode('.', $version1);
894
-		$version2 = explode('.', $version2);
895
-		// reduce $version1 to match the number of parts in $version2
896
-		while (count($version1) > count($version2)) {
897
-			array_pop($version1);
898
-		}
899
-		// if $version1 does not have enough parts, add some
900
-		while (count($version1) < count($version2)) {
901
-			$version1[] = '0';
902
-		}
903
-		return implode('.', $version1);
904
-	}
905
-
906
-	/**
907
-	 * Check whether the current ownCloud version matches the given
908
-	 * application's version requirements.
909
-	 *
910
-	 * The comparison is made based on the number of parts that the
911
-	 * app info version has. For example for ownCloud 6.0.3 if the
912
-	 * app info version is expecting version 6.0, the comparison is
913
-	 * made on the first two parts of the ownCloud version.
914
-	 * This means that it's possible to specify "requiremin" => 6
915
-	 * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
916
-	 *
917
-	 * @param string $ocVersion ownCloud version to check against
918
-	 * @param array $appInfo app info (from xml)
919
-	 *
920
-	 * @return boolean true if compatible, otherwise false
921
-	 */
922
-	public static function isAppCompatible($ocVersion, $appInfo) {
923
-		$requireMin = '';
924
-		$requireMax = '';
925
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
926
-			$requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
927
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
928
-			$requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
929
-		} else if (isset($appInfo['requiremin'])) {
930
-			$requireMin = $appInfo['requiremin'];
931
-		} else if (isset($appInfo['require'])) {
932
-			$requireMin = $appInfo['require'];
933
-		}
934
-
935
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
936
-			$requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
937
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
938
-			$requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
939
-		} else if (isset($appInfo['requiremax'])) {
940
-			$requireMax = $appInfo['requiremax'];
941
-		}
942
-
943
-		if (is_array($ocVersion)) {
944
-			$ocVersion = implode('.', $ocVersion);
945
-		}
946
-
947
-		if (!empty($requireMin)
948
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
949
-		) {
950
-
951
-			return false;
952
-		}
953
-
954
-		if (!empty($requireMax)
955
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
956
-		) {
957
-			return false;
958
-		}
959
-
960
-		return true;
961
-	}
962
-
963
-	/**
964
-	 * get the installed version of all apps
965
-	 */
966
-	public static function getAppVersions() {
967
-		static $versions;
968
-
969
-		if(!$versions) {
970
-			$appConfig = \OC::$server->getAppConfig();
971
-			$versions = $appConfig->getValues(false, 'installed_version');
972
-		}
973
-		return $versions;
974
-	}
975
-
976
-	/**
977
-	 * @param string $app
978
-	 * @param \OCP\IConfig $config
979
-	 * @param \OCP\IL10N $l
980
-	 * @return bool
981
-	 *
982
-	 * @throws Exception if app is not compatible with this version of ownCloud
983
-	 * @throws Exception if no app-name was specified
984
-	 */
985
-	public function installApp($app,
986
-							   \OCP\IConfig $config,
987
-							   \OCP\IL10N $l) {
988
-		if ($app !== false) {
989
-			// check if the app is compatible with this version of ownCloud
990
-			$info = self::getAppInfo($app);
991
-			if(!is_array($info)) {
992
-				throw new \Exception(
993
-					$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
994
-						[$info['name']]
995
-					)
996
-				);
997
-			}
998
-
999
-			$version = \OCP\Util::getVersion();
1000
-			if (!self::isAppCompatible($version, $info)) {
1001
-				throw new \Exception(
1002
-					$l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
1003
-						array($info['name'])
1004
-					)
1005
-				);
1006
-			}
1007
-
1008
-			// check for required dependencies
1009
-			self::checkAppDependencies($config, $l, $info);
1010
-
1011
-			$config->setAppValue($app, 'enabled', 'yes');
1012
-			if (isset($appData['id'])) {
1013
-				$config->setAppValue($app, 'ocsid', $appData['id']);
1014
-			}
1015
-
1016
-			if(isset($info['settings']) && is_array($info['settings'])) {
1017
-				$appPath = self::getAppPath($app);
1018
-				self::registerAutoloading($app, $appPath);
1019
-				\OC::$server->getSettingsManager()->setupSettings($info['settings']);
1020
-			}
1021
-
1022
-			\OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
1023
-		} else {
1024
-			if(empty($appName) ) {
1025
-				throw new \Exception($l->t("No app name specified"));
1026
-			} else {
1027
-				throw new \Exception($l->t("App '%s' could not be installed!", $appName));
1028
-			}
1029
-		}
1030
-
1031
-		return $app;
1032
-	}
1033
-
1034
-	/**
1035
-	 * update the database for the app and call the update script
1036
-	 *
1037
-	 * @param string $appId
1038
-	 * @return bool
1039
-	 */
1040
-	public static function updateApp($appId) {
1041
-		$appPath = self::getAppPath($appId);
1042
-		if($appPath === false) {
1043
-			return false;
1044
-		}
1045
-		self::registerAutoloading($appId, $appPath);
1046
-
1047
-		$appData = self::getAppInfo($appId);
1048
-		self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1049
-
1050
-		if (file_exists($appPath . '/appinfo/database.xml')) {
1051
-			OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1052
-		} else {
1053
-			$ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1054
-			$ms->migrate();
1055
-		}
1056
-
1057
-		self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
1058
-		self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
1059
-		unset(self::$appVersion[$appId]);
1060
-
1061
-		// run upgrade code
1062
-		if (file_exists($appPath . '/appinfo/update.php')) {
1063
-			self::loadApp($appId);
1064
-			include $appPath . '/appinfo/update.php';
1065
-		}
1066
-		self::setupBackgroundJobs($appData['background-jobs']);
1067
-		if(isset($appData['settings']) && is_array($appData['settings'])) {
1068
-			\OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1069
-		}
1070
-
1071
-		//set remote/public handlers
1072
-		if (array_key_exists('ocsid', $appData)) {
1073
-			\OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1074
-		} elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1075
-			\OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1076
-		}
1077
-		foreach ($appData['remote'] as $name => $path) {
1078
-			\OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1079
-		}
1080
-		foreach ($appData['public'] as $name => $path) {
1081
-			\OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1082
-		}
1083
-
1084
-		self::setAppTypes($appId);
1085
-
1086
-		$version = \OC_App::getAppVersion($appId);
1087
-		\OC::$server->getAppConfig()->setValue($appId, 'installed_version', $version);
1088
-
1089
-		\OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
1090
-			ManagerEvent::EVENT_APP_UPDATE, $appId
1091
-		));
1092
-
1093
-		return true;
1094
-	}
1095
-
1096
-	/**
1097
-	 * @param string $appId
1098
-	 * @param string[] $steps
1099
-	 * @throws \OC\NeedsUpdateException
1100
-	 */
1101
-	public static function executeRepairSteps($appId, array $steps) {
1102
-		if (empty($steps)) {
1103
-			return;
1104
-		}
1105
-		// load the app
1106
-		self::loadApp($appId);
1107
-
1108
-		$dispatcher = OC::$server->getEventDispatcher();
1109
-
1110
-		// load the steps
1111
-		$r = new Repair([], $dispatcher);
1112
-		foreach ($steps as $step) {
1113
-			try {
1114
-				$r->addStep($step);
1115
-			} catch (Exception $ex) {
1116
-				$r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
1117
-				\OC::$server->getLogger()->logException($ex);
1118
-			}
1119
-		}
1120
-		// run the steps
1121
-		$r->run();
1122
-	}
1123
-
1124
-	public static function setupBackgroundJobs(array $jobs) {
1125
-		$queue = \OC::$server->getJobList();
1126
-		foreach ($jobs as $job) {
1127
-			$queue->add($job);
1128
-		}
1129
-	}
1130
-
1131
-	/**
1132
-	 * @param string $appId
1133
-	 * @param string[] $steps
1134
-	 */
1135
-	private static function setupLiveMigrations($appId, array $steps) {
1136
-		$queue = \OC::$server->getJobList();
1137
-		foreach ($steps as $step) {
1138
-			$queue->add('OC\Migration\BackgroundRepair', [
1139
-				'app' => $appId,
1140
-				'step' => $step]);
1141
-		}
1142
-	}
1143
-
1144
-	/**
1145
-	 * @param string $appId
1146
-	 * @return \OC\Files\View|false
1147
-	 */
1148
-	public static function getStorage($appId) {
1149
-		if (OC_App::isEnabled($appId)) { //sanity check
1150
-			if (\OC::$server->getUserSession()->isLoggedIn()) {
1151
-				$view = new \OC\Files\View('/' . OC_User::getUser());
1152
-				if (!$view->file_exists($appId)) {
1153
-					$view->mkdir($appId);
1154
-				}
1155
-				return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1156
-			} else {
1157
-				\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1158
-				return false;
1159
-			}
1160
-		} else {
1161
-			\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1162
-			return false;
1163
-		}
1164
-	}
1165
-
1166
-	protected static function findBestL10NOption($options, $lang) {
1167
-		$fallback = $similarLangFallback = $englishFallback = false;
1168
-
1169
-		$lang = strtolower($lang);
1170
-		$similarLang = $lang;
1171
-		if (strpos($similarLang, '_')) {
1172
-			// For "de_DE" we want to find "de" and the other way around
1173
-			$similarLang = substr($lang, 0, strpos($lang, '_'));
1174
-		}
1175
-
1176
-		foreach ($options as $option) {
1177
-			if (is_array($option)) {
1178
-				if ($fallback === false) {
1179
-					$fallback = $option['@value'];
1180
-				}
1181
-
1182
-				if (!isset($option['@attributes']['lang'])) {
1183
-					continue;
1184
-				}
1185
-
1186
-				$attributeLang = strtolower($option['@attributes']['lang']);
1187
-				if ($attributeLang === $lang) {
1188
-					return $option['@value'];
1189
-				}
1190
-
1191
-				if ($attributeLang === $similarLang) {
1192
-					$similarLangFallback = $option['@value'];
1193
-				} else if (strpos($attributeLang, $similarLang . '_') === 0) {
1194
-					if ($similarLangFallback === false) {
1195
-						$similarLangFallback =  $option['@value'];
1196
-					}
1197
-				}
1198
-			} else {
1199
-				$englishFallback = $option;
1200
-			}
1201
-		}
1202
-
1203
-		if ($similarLangFallback !== false) {
1204
-			return $similarLangFallback;
1205
-		} else if ($englishFallback !== false) {
1206
-			return $englishFallback;
1207
-		}
1208
-		return (string) $fallback;
1209
-	}
1210
-
1211
-	/**
1212
-	 * parses the app data array and enhanced the 'description' value
1213
-	 *
1214
-	 * @param array $data the app data
1215
-	 * @param string $lang
1216
-	 * @return array improved app data
1217
-	 */
1218
-	public static function parseAppInfo(array $data, $lang = null) {
1219
-
1220
-		if ($lang && isset($data['name']) && is_array($data['name'])) {
1221
-			$data['name'] = self::findBestL10NOption($data['name'], $lang);
1222
-		}
1223
-		if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1224
-			$data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1225
-		}
1226
-		if ($lang && isset($data['description']) && is_array($data['description'])) {
1227
-			$data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1228
-		} else if (isset($data['description']) && is_string($data['description'])) {
1229
-			$data['description'] = trim($data['description']);
1230
-		} else  {
1231
-			$data['description'] = '';
1232
-		}
1233
-
1234
-		return $data;
1235
-	}
1236
-
1237
-	/**
1238
-	 * @param \OCP\IConfig $config
1239
-	 * @param \OCP\IL10N $l
1240
-	 * @param array $info
1241
-	 * @throws \Exception
1242
-	 */
1243
-	public static function checkAppDependencies($config, $l, $info) {
1244
-		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1245
-		$missing = $dependencyAnalyzer->analyze($info);
1246
-		if (!empty($missing)) {
1247
-			$missingMsg = join(PHP_EOL, $missing);
1248
-			throw new \Exception(
1249
-				$l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
1250
-					[$info['name'], $missingMsg]
1251
-				)
1252
-			);
1253
-		}
1254
-	}
64
+    static private $appVersion = [];
65
+    static private $adminForms = array();
66
+    static private $personalForms = array();
67
+    static private $appInfo = array();
68
+    static private $appTypes = array();
69
+    static private $loadedApps = array();
70
+    static private $altLogin = array();
71
+    static private $alreadyRegistered = [];
72
+    const officialApp = 200;
73
+
74
+    /**
75
+     * clean the appId
76
+     *
77
+     * @param string|boolean $app AppId that needs to be cleaned
78
+     * @return string
79
+     */
80
+    public static function cleanAppId($app) {
81
+        return str_replace(array('\0', '/', '\\', '..'), '', $app);
82
+    }
83
+
84
+    /**
85
+     * Check if an app is loaded
86
+     *
87
+     * @param string $app
88
+     * @return bool
89
+     */
90
+    public static function isAppLoaded($app) {
91
+        return in_array($app, self::$loadedApps, true);
92
+    }
93
+
94
+    /**
95
+     * loads all apps
96
+     *
97
+     * @param string[] | string | null $types
98
+     * @return bool
99
+     *
100
+     * This function walks through the ownCloud directory and loads all apps
101
+     * it can find. A directory contains an app if the file /appinfo/info.xml
102
+     * exists.
103
+     *
104
+     * if $types is set, only apps of those types will be loaded
105
+     */
106
+    public static function loadApps($types = null) {
107
+        if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
108
+            return false;
109
+        }
110
+        // Load the enabled apps here
111
+        $apps = self::getEnabledApps();
112
+
113
+        // Add each apps' folder as allowed class path
114
+        foreach($apps as $app) {
115
+            $path = self::getAppPath($app);
116
+            if($path !== false) {
117
+                self::registerAutoloading($app, $path);
118
+            }
119
+        }
120
+
121
+        // prevent app.php from printing output
122
+        ob_start();
123
+        foreach ($apps as $app) {
124
+            if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
125
+                self::loadApp($app);
126
+            }
127
+        }
128
+        ob_end_clean();
129
+
130
+        return true;
131
+    }
132
+
133
+    /**
134
+     * load a single app
135
+     *
136
+     * @param string $app
137
+     */
138
+    public static function loadApp($app) {
139
+        self::$loadedApps[] = $app;
140
+        $appPath = self::getAppPath($app);
141
+        if($appPath === false) {
142
+            return;
143
+        }
144
+
145
+        // in case someone calls loadApp() directly
146
+        self::registerAutoloading($app, $appPath);
147
+
148
+        if (is_file($appPath . '/appinfo/app.php')) {
149
+            \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
150
+            self::requireAppFile($app);
151
+            if (self::isType($app, array('authentication'))) {
152
+                // since authentication apps affect the "is app enabled for group" check,
153
+                // the enabled apps cache needs to be cleared to make sure that the
154
+                // next time getEnableApps() is called it will also include apps that were
155
+                // enabled for groups
156
+                self::$enabledAppsCache = array();
157
+            }
158
+            \OC::$server->getEventLogger()->end('load_app_' . $app);
159
+        }
160
+
161
+        $info = self::getAppInfo($app);
162
+        if (!empty($info['activity']['filters'])) {
163
+            foreach ($info['activity']['filters'] as $filter) {
164
+                \OC::$server->getActivityManager()->registerFilter($filter);
165
+            }
166
+        }
167
+        if (!empty($info['activity']['settings'])) {
168
+            foreach ($info['activity']['settings'] as $setting) {
169
+                \OC::$server->getActivityManager()->registerSetting($setting);
170
+            }
171
+        }
172
+        if (!empty($info['activity']['providers'])) {
173
+            foreach ($info['activity']['providers'] as $provider) {
174
+                \OC::$server->getActivityManager()->registerProvider($provider);
175
+            }
176
+        }
177
+    }
178
+
179
+    /**
180
+     * @internal
181
+     * @param string $app
182
+     * @param string $path
183
+     */
184
+    public static function registerAutoloading($app, $path) {
185
+        $key = $app . '-' . $path;
186
+        if(isset(self::$alreadyRegistered[$key])) {
187
+            return;
188
+        }
189
+        self::$alreadyRegistered[$key] = true;
190
+        // Register on PSR-4 composer autoloader
191
+        $appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
192
+        \OC::$server->registerNamespace($app, $appNamespace);
193
+        \OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
194
+        if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
195
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
196
+        }
197
+
198
+        // Register on legacy autoloader
199
+        \OC::$loader->addValidRoot($path);
200
+    }
201
+
202
+    /**
203
+     * Load app.php from the given app
204
+     *
205
+     * @param string $app app name
206
+     */
207
+    private static function requireAppFile($app) {
208
+        try {
209
+            // encapsulated here to avoid variable scope conflicts
210
+            require_once $app . '/appinfo/app.php';
211
+        } catch (Error $ex) {
212
+            \OC::$server->getLogger()->logException($ex);
213
+            $blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
214
+            if (!in_array($app, $blacklist)) {
215
+                self::disable($app);
216
+            }
217
+        }
218
+    }
219
+
220
+    /**
221
+     * check if an app is of a specific type
222
+     *
223
+     * @param string $app
224
+     * @param string|array $types
225
+     * @return bool
226
+     */
227
+    public static function isType($app, $types) {
228
+        if (is_string($types)) {
229
+            $types = array($types);
230
+        }
231
+        $appTypes = self::getAppTypes($app);
232
+        foreach ($types as $type) {
233
+            if (array_search($type, $appTypes) !== false) {
234
+                return true;
235
+            }
236
+        }
237
+        return false;
238
+    }
239
+
240
+    /**
241
+     * get the types of an app
242
+     *
243
+     * @param string $app
244
+     * @return array
245
+     */
246
+    private static function getAppTypes($app) {
247
+        //load the cache
248
+        if (count(self::$appTypes) == 0) {
249
+            self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
250
+        }
251
+
252
+        if (isset(self::$appTypes[$app])) {
253
+            return explode(',', self::$appTypes[$app]);
254
+        } else {
255
+            return array();
256
+        }
257
+    }
258
+
259
+    /**
260
+     * read app types from info.xml and cache them in the database
261
+     */
262
+    public static function setAppTypes($app) {
263
+        $appData = self::getAppInfo($app);
264
+        if(!is_array($appData)) {
265
+            return;
266
+        }
267
+
268
+        if (isset($appData['types'])) {
269
+            $appTypes = implode(',', $appData['types']);
270
+        } else {
271
+            $appTypes = '';
272
+            $appData['types'] = [];
273
+        }
274
+
275
+        \OC::$server->getAppConfig()->setValue($app, 'types', $appTypes);
276
+
277
+        if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) {
278
+            $enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'yes');
279
+            if ($enabled !== 'yes' && $enabled !== 'no') {
280
+                \OC::$server->getAppConfig()->setValue($app, 'enabled', 'yes');
281
+            }
282
+        }
283
+    }
284
+
285
+    /**
286
+     * check if app is shipped
287
+     *
288
+     * @param string $appId the id of the app to check
289
+     * @return bool
290
+     *
291
+     * Check if an app that is installed is a shipped app or installed from the appstore.
292
+     */
293
+    public static function isShipped($appId) {
294
+        return \OC::$server->getAppManager()->isShipped($appId);
295
+    }
296
+
297
+    /**
298
+     * get all enabled apps
299
+     */
300
+    protected static $enabledAppsCache = array();
301
+
302
+    /**
303
+     * Returns apps enabled for the current user.
304
+     *
305
+     * @param bool $forceRefresh whether to refresh the cache
306
+     * @param bool $all whether to return apps for all users, not only the
307
+     * currently logged in one
308
+     * @return string[]
309
+     */
310
+    public static function getEnabledApps($forceRefresh = false, $all = false) {
311
+        if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
312
+            return array();
313
+        }
314
+        // in incognito mode or when logged out, $user will be false,
315
+        // which is also the case during an upgrade
316
+        $appManager = \OC::$server->getAppManager();
317
+        if ($all) {
318
+            $user = null;
319
+        } else {
320
+            $user = \OC::$server->getUserSession()->getUser();
321
+        }
322
+
323
+        if (is_null($user)) {
324
+            $apps = $appManager->getInstalledApps();
325
+        } else {
326
+            $apps = $appManager->getEnabledAppsForUser($user);
327
+        }
328
+        $apps = array_filter($apps, function ($app) {
329
+            return $app !== 'files';//we add this manually
330
+        });
331
+        sort($apps);
332
+        array_unshift($apps, 'files');
333
+        return $apps;
334
+    }
335
+
336
+    /**
337
+     * checks whether or not an app is enabled
338
+     *
339
+     * @param string $app app
340
+     * @return bool
341
+     *
342
+     * This function checks whether or not an app is enabled.
343
+     */
344
+    public static function isEnabled($app) {
345
+        return \OC::$server->getAppManager()->isEnabledForUser($app);
346
+    }
347
+
348
+    /**
349
+     * enables an app
350
+     *
351
+     * @param string $appId
352
+     * @param array $groups (optional) when set, only these groups will have access to the app
353
+     * @throws \Exception
354
+     * @return void
355
+     *
356
+     * This function set an app as enabled in appconfig.
357
+     */
358
+    public function enable($appId,
359
+                            $groups = null) {
360
+        self::$enabledAppsCache = []; // flush
361
+
362
+        // Check if app is already downloaded
363
+        $installer = new Installer(
364
+            \OC::$server->getAppFetcher(),
365
+            \OC::$server->getHTTPClientService(),
366
+            \OC::$server->getTempManager(),
367
+            \OC::$server->getLogger(),
368
+            \OC::$server->getConfig()
369
+        );
370
+        $isDownloaded = $installer->isDownloaded($appId);
371
+
372
+        if(!$isDownloaded) {
373
+            $installer->downloadApp($appId);
374
+        }
375
+
376
+        $installer->installApp($appId);
377
+
378
+        $appManager = \OC::$server->getAppManager();
379
+        if (!is_null($groups)) {
380
+            $groupManager = \OC::$server->getGroupManager();
381
+            $groupsList = [];
382
+            foreach ($groups as $group) {
383
+                $groupItem = $groupManager->get($group);
384
+                if ($groupItem instanceof \OCP\IGroup) {
385
+                    $groupsList[] = $groupManager->get($group);
386
+                }
387
+            }
388
+            $appManager->enableAppForGroups($appId, $groupsList);
389
+        } else {
390
+            $appManager->enableApp($appId);
391
+        }
392
+    }
393
+
394
+    /**
395
+     * @param string $app
396
+     * @return bool
397
+     */
398
+    public static function removeApp($app) {
399
+        if (self::isShipped($app)) {
400
+            return false;
401
+        }
402
+
403
+        $installer = new Installer(
404
+            \OC::$server->getAppFetcher(),
405
+            \OC::$server->getHTTPClientService(),
406
+            \OC::$server->getTempManager(),
407
+            \OC::$server->getLogger(),
408
+            \OC::$server->getConfig()
409
+        );
410
+        return $installer->removeApp($app);
411
+    }
412
+
413
+    /**
414
+     * This function set an app as disabled in appconfig.
415
+     *
416
+     * @param string $app app
417
+     * @throws Exception
418
+     */
419
+    public static function disable($app) {
420
+        // flush
421
+        self::$enabledAppsCache = array();
422
+
423
+        // run uninstall steps
424
+        $appData = OC_App::getAppInfo($app);
425
+        if (!is_null($appData)) {
426
+            OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']);
427
+        }
428
+
429
+        // emit disable hook - needed anymore ?
430
+        \OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
431
+
432
+        // finally disable it
433
+        $appManager = \OC::$server->getAppManager();
434
+        $appManager->disableApp($app);
435
+    }
436
+
437
+    // This is private as well. It simply works, so don't ask for more details
438
+    private static function proceedNavigation($list) {
439
+        usort($list, function($a, $b) {
440
+            if (isset($a['order']) && isset($b['order'])) {
441
+                return ($a['order'] < $b['order']) ? -1 : 1;
442
+            } else if (isset($a['order']) || isset($b['order'])) {
443
+                return isset($a['order']) ? -1 : 1;
444
+            } else {
445
+                return ($a['name'] < $b['name']) ? -1 : 1;
446
+            }
447
+        });
448
+
449
+        $activeApp = OC::$server->getNavigationManager()->getActiveEntry();
450
+        foreach ($list as $index => &$navEntry) {
451
+            if ($navEntry['id'] == $activeApp) {
452
+                $navEntry['active'] = true;
453
+            } else {
454
+                $navEntry['active'] = false;
455
+            }
456
+        }
457
+        unset($navEntry);
458
+
459
+        return $list;
460
+    }
461
+
462
+    /**
463
+     * Get the path where to install apps
464
+     *
465
+     * @return string|false
466
+     */
467
+    public static function getInstallPath() {
468
+        if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
469
+            return false;
470
+        }
471
+
472
+        foreach (OC::$APPSROOTS as $dir) {
473
+            if (isset($dir['writable']) && $dir['writable'] === true) {
474
+                return $dir['path'];
475
+            }
476
+        }
477
+
478
+        \OCP\Util::writeLog('core', 'No application directories are marked as writable.', \OCP\Util::ERROR);
479
+        return null;
480
+    }
481
+
482
+
483
+    /**
484
+     * search for an app in all app-directories
485
+     *
486
+     * @param string $appId
487
+     * @return false|string
488
+     */
489
+    public static function findAppInDirectories($appId) {
490
+        $sanitizedAppId = self::cleanAppId($appId);
491
+        if($sanitizedAppId !== $appId) {
492
+            return false;
493
+        }
494
+        static $app_dir = array();
495
+
496
+        if (isset($app_dir[$appId])) {
497
+            return $app_dir[$appId];
498
+        }
499
+
500
+        $possibleApps = array();
501
+        foreach (OC::$APPSROOTS as $dir) {
502
+            if (file_exists($dir['path'] . '/' . $appId)) {
503
+                $possibleApps[] = $dir;
504
+            }
505
+        }
506
+
507
+        if (empty($possibleApps)) {
508
+            return false;
509
+        } elseif (count($possibleApps) === 1) {
510
+            $dir = array_shift($possibleApps);
511
+            $app_dir[$appId] = $dir;
512
+            return $dir;
513
+        } else {
514
+            $versionToLoad = array();
515
+            foreach ($possibleApps as $possibleApp) {
516
+                $version = self::getAppVersionByPath($possibleApp['path']);
517
+                if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
518
+                    $versionToLoad = array(
519
+                        'dir' => $possibleApp,
520
+                        'version' => $version,
521
+                    );
522
+                }
523
+            }
524
+            $app_dir[$appId] = $versionToLoad['dir'];
525
+            return $versionToLoad['dir'];
526
+            //TODO - write test
527
+        }
528
+    }
529
+
530
+    /**
531
+     * Get the directory for the given app.
532
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
533
+     *
534
+     * @param string $appId
535
+     * @return string|false
536
+     */
537
+    public static function getAppPath($appId) {
538
+        if ($appId === null || trim($appId) === '') {
539
+            return false;
540
+        }
541
+
542
+        if (($dir = self::findAppInDirectories($appId)) != false) {
543
+            return $dir['path'] . '/' . $appId;
544
+        }
545
+        return false;
546
+    }
547
+
548
+    /**
549
+     * Get the path for the given app on the access
550
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
551
+     *
552
+     * @param string $appId
553
+     * @return string|false
554
+     */
555
+    public static function getAppWebPath($appId) {
556
+        if (($dir = self::findAppInDirectories($appId)) != false) {
557
+            return OC::$WEBROOT . $dir['url'] . '/' . $appId;
558
+        }
559
+        return false;
560
+    }
561
+
562
+    /**
563
+     * get the last version of the app from appinfo/info.xml
564
+     *
565
+     * @param string $appId
566
+     * @param bool $useCache
567
+     * @return string
568
+     */
569
+    public static function getAppVersion($appId, $useCache = true) {
570
+        if($useCache && isset(self::$appVersion[$appId])) {
571
+            return self::$appVersion[$appId];
572
+        }
573
+
574
+        $file = self::getAppPath($appId);
575
+        self::$appVersion[$appId] = ($file !== false) ? self::getAppVersionByPath($file) : '0';
576
+        return self::$appVersion[$appId];
577
+    }
578
+
579
+    /**
580
+     * get app's version based on it's path
581
+     *
582
+     * @param string $path
583
+     * @return string
584
+     */
585
+    public static function getAppVersionByPath($path) {
586
+        $infoFile = $path . '/appinfo/info.xml';
587
+        $appData = self::getAppInfo($infoFile, true);
588
+        return isset($appData['version']) ? $appData['version'] : '';
589
+    }
590
+
591
+
592
+    /**
593
+     * Read all app metadata from the info.xml file
594
+     *
595
+     * @param string $appId id of the app or the path of the info.xml file
596
+     * @param bool $path
597
+     * @param string $lang
598
+     * @return array|null
599
+     * @note all data is read from info.xml, not just pre-defined fields
600
+     */
601
+    public static function getAppInfo($appId, $path = false, $lang = null) {
602
+        if ($path) {
603
+            $file = $appId;
604
+        } else {
605
+            if ($lang === null && isset(self::$appInfo[$appId])) {
606
+                return self::$appInfo[$appId];
607
+            }
608
+            $appPath = self::getAppPath($appId);
609
+            if($appPath === false) {
610
+                return null;
611
+            }
612
+            $file = $appPath . '/appinfo/info.xml';
613
+        }
614
+
615
+        $parser = new InfoParser(\OC::$server->getMemCacheFactory()->create('core.appinfo'));
616
+        $data = $parser->parse($file);
617
+
618
+        if (is_array($data)) {
619
+            $data = OC_App::parseAppInfo($data, $lang);
620
+        }
621
+        if(isset($data['ocsid'])) {
622
+            $storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
623
+            if($storedId !== '' && $storedId !== $data['ocsid']) {
624
+                $data['ocsid'] = $storedId;
625
+            }
626
+        }
627
+
628
+        if ($lang === null) {
629
+            self::$appInfo[$appId] = $data;
630
+        }
631
+
632
+        return $data;
633
+    }
634
+
635
+    /**
636
+     * Returns the navigation
637
+     *
638
+     * @return array
639
+     *
640
+     * This function returns an array containing all entries added. The
641
+     * entries are sorted by the key 'order' ascending. Additional to the keys
642
+     * given for each app the following keys exist:
643
+     *   - active: boolean, signals if the user is on this navigation entry
644
+     */
645
+    public static function getNavigation() {
646
+        $entries = OC::$server->getNavigationManager()->getAll();
647
+        return self::proceedNavigation($entries);
648
+    }
649
+
650
+    /**
651
+     * Returns the Settings Navigation
652
+     *
653
+     * @return string[]
654
+     *
655
+     * This function returns an array containing all settings pages added. The
656
+     * entries are sorted by the key 'order' ascending.
657
+     */
658
+    public static function getSettingsNavigation() {
659
+        $entries = OC::$server->getNavigationManager()->getAll('settings');
660
+        return self::proceedNavigation($entries);
661
+    }
662
+
663
+    /**
664
+     * get the id of loaded app
665
+     *
666
+     * @return string
667
+     */
668
+    public static function getCurrentApp() {
669
+        $request = \OC::$server->getRequest();
670
+        $script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
671
+        $topFolder = substr($script, 0, strpos($script, '/'));
672
+        if (empty($topFolder)) {
673
+            $path_info = $request->getPathInfo();
674
+            if ($path_info) {
675
+                $topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
676
+            }
677
+        }
678
+        if ($topFolder == 'apps') {
679
+            $length = strlen($topFolder);
680
+            return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1);
681
+        } else {
682
+            return $topFolder;
683
+        }
684
+    }
685
+
686
+    /**
687
+     * @param string $type
688
+     * @return array
689
+     */
690
+    public static function getForms($type) {
691
+        $forms = array();
692
+        switch ($type) {
693
+            case 'admin':
694
+                $source = self::$adminForms;
695
+                break;
696
+            case 'personal':
697
+                $source = self::$personalForms;
698
+                break;
699
+            default:
700
+                return array();
701
+        }
702
+        foreach ($source as $form) {
703
+            $forms[] = include $form;
704
+        }
705
+        return $forms;
706
+    }
707
+
708
+    /**
709
+     * register an admin form to be shown
710
+     *
711
+     * @param string $app
712
+     * @param string $page
713
+     */
714
+    public static function registerAdmin($app, $page) {
715
+        self::$adminForms[] = $app . '/' . $page . '.php';
716
+    }
717
+
718
+    /**
719
+     * register a personal form to be shown
720
+     * @param string $app
721
+     * @param string $page
722
+     */
723
+    public static function registerPersonal($app, $page) {
724
+        self::$personalForms[] = $app . '/' . $page . '.php';
725
+    }
726
+
727
+    /**
728
+     * @param array $entry
729
+     */
730
+    public static function registerLogIn(array $entry) {
731
+        self::$altLogin[] = $entry;
732
+    }
733
+
734
+    /**
735
+     * @return array
736
+     */
737
+    public static function getAlternativeLogIns() {
738
+        return self::$altLogin;
739
+    }
740
+
741
+    /**
742
+     * get a list of all apps in the apps folder
743
+     *
744
+     * @return array an array of app names (string IDs)
745
+     * @todo: change the name of this method to getInstalledApps, which is more accurate
746
+     */
747
+    public static function getAllApps() {
748
+
749
+        $apps = array();
750
+
751
+        foreach (OC::$APPSROOTS as $apps_dir) {
752
+            if (!is_readable($apps_dir['path'])) {
753
+                \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
754
+                continue;
755
+            }
756
+            $dh = opendir($apps_dir['path']);
757
+
758
+            if (is_resource($dh)) {
759
+                while (($file = readdir($dh)) !== false) {
760
+
761
+                    if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
762
+
763
+                        $apps[] = $file;
764
+                    }
765
+                }
766
+            }
767
+        }
768
+
769
+        return $apps;
770
+    }
771
+
772
+    /**
773
+     * List all apps, this is used in apps.php
774
+     *
775
+     * @return array
776
+     */
777
+    public function listAllApps() {
778
+        $installedApps = OC_App::getAllApps();
779
+
780
+        //we don't want to show configuration for these
781
+        $blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
782
+        $appList = array();
783
+        $langCode = \OC::$server->getL10N('core')->getLanguageCode();
784
+        $urlGenerator = \OC::$server->getURLGenerator();
785
+
786
+        foreach ($installedApps as $app) {
787
+            if (array_search($app, $blacklist) === false) {
788
+
789
+                $info = OC_App::getAppInfo($app, false, $langCode);
790
+                if (!is_array($info)) {
791
+                    \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
792
+                    continue;
793
+                }
794
+
795
+                if (!isset($info['name'])) {
796
+                    \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
797
+                    continue;
798
+                }
799
+
800
+                $enabled = \OC::$server->getAppConfig()->getValue($app, 'enabled', 'no');
801
+                $info['groups'] = null;
802
+                if ($enabled === 'yes') {
803
+                    $active = true;
804
+                } else if ($enabled === 'no') {
805
+                    $active = false;
806
+                } else {
807
+                    $active = true;
808
+                    $info['groups'] = $enabled;
809
+                }
810
+
811
+                $info['active'] = $active;
812
+
813
+                if (self::isShipped($app)) {
814
+                    $info['internal'] = true;
815
+                    $info['level'] = self::officialApp;
816
+                    $info['removable'] = false;
817
+                } else {
818
+                    $info['internal'] = false;
819
+                    $info['removable'] = true;
820
+                }
821
+
822
+                $appPath = self::getAppPath($app);
823
+                if($appPath !== false) {
824
+                    $appIcon = $appPath . '/img/' . $app . '.svg';
825
+                    if (file_exists($appIcon)) {
826
+                        $info['preview'] = \OC::$server->getURLGenerator()->imagePath($app, $app . '.svg');
827
+                        $info['previewAsIcon'] = true;
828
+                    } else {
829
+                        $appIcon = $appPath . '/img/app.svg';
830
+                        if (file_exists($appIcon)) {
831
+                            $info['preview'] = \OC::$server->getURLGenerator()->imagePath($app, 'app.svg');
832
+                            $info['previewAsIcon'] = true;
833
+                        }
834
+                    }
835
+                }
836
+                // fix documentation
837
+                if (isset($info['documentation']) && is_array($info['documentation'])) {
838
+                    foreach ($info['documentation'] as $key => $url) {
839
+                        // If it is not an absolute URL we assume it is a key
840
+                        // i.e. admin-ldap will get converted to go.php?to=admin-ldap
841
+                        if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
842
+                            $url = $urlGenerator->linkToDocs($url);
843
+                        }
844
+
845
+                        $info['documentation'][$key] = $url;
846
+                    }
847
+                }
848
+
849
+                $info['version'] = OC_App::getAppVersion($app);
850
+                $appList[] = $info;
851
+            }
852
+        }
853
+
854
+        return $appList;
855
+    }
856
+
857
+    /**
858
+     * Returns the internal app ID or false
859
+     * @param string $ocsID
860
+     * @return string|false
861
+     */
862
+    public static function getInternalAppIdByOcs($ocsID) {
863
+        if(is_numeric($ocsID)) {
864
+            $idArray = \OC::$server->getAppConfig()->getValues(false, 'ocsid');
865
+            if(array_search($ocsID, $idArray)) {
866
+                return array_search($ocsID, $idArray);
867
+            }
868
+        }
869
+        return false;
870
+    }
871
+
872
+    public static function shouldUpgrade($app) {
873
+        $versions = self::getAppVersions();
874
+        $currentVersion = OC_App::getAppVersion($app);
875
+        if ($currentVersion && isset($versions[$app])) {
876
+            $installedVersion = $versions[$app];
877
+            if (!version_compare($currentVersion, $installedVersion, '=')) {
878
+                return true;
879
+            }
880
+        }
881
+        return false;
882
+    }
883
+
884
+    /**
885
+     * Adjust the number of version parts of $version1 to match
886
+     * the number of version parts of $version2.
887
+     *
888
+     * @param string $version1 version to adjust
889
+     * @param string $version2 version to take the number of parts from
890
+     * @return string shortened $version1
891
+     */
892
+    private static function adjustVersionParts($version1, $version2) {
893
+        $version1 = explode('.', $version1);
894
+        $version2 = explode('.', $version2);
895
+        // reduce $version1 to match the number of parts in $version2
896
+        while (count($version1) > count($version2)) {
897
+            array_pop($version1);
898
+        }
899
+        // if $version1 does not have enough parts, add some
900
+        while (count($version1) < count($version2)) {
901
+            $version1[] = '0';
902
+        }
903
+        return implode('.', $version1);
904
+    }
905
+
906
+    /**
907
+     * Check whether the current ownCloud version matches the given
908
+     * application's version requirements.
909
+     *
910
+     * The comparison is made based on the number of parts that the
911
+     * app info version has. For example for ownCloud 6.0.3 if the
912
+     * app info version is expecting version 6.0, the comparison is
913
+     * made on the first two parts of the ownCloud version.
914
+     * This means that it's possible to specify "requiremin" => 6
915
+     * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
916
+     *
917
+     * @param string $ocVersion ownCloud version to check against
918
+     * @param array $appInfo app info (from xml)
919
+     *
920
+     * @return boolean true if compatible, otherwise false
921
+     */
922
+    public static function isAppCompatible($ocVersion, $appInfo) {
923
+        $requireMin = '';
924
+        $requireMax = '';
925
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
926
+            $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
927
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
928
+            $requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
929
+        } else if (isset($appInfo['requiremin'])) {
930
+            $requireMin = $appInfo['requiremin'];
931
+        } else if (isset($appInfo['require'])) {
932
+            $requireMin = $appInfo['require'];
933
+        }
934
+
935
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
936
+            $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
937
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
938
+            $requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
939
+        } else if (isset($appInfo['requiremax'])) {
940
+            $requireMax = $appInfo['requiremax'];
941
+        }
942
+
943
+        if (is_array($ocVersion)) {
944
+            $ocVersion = implode('.', $ocVersion);
945
+        }
946
+
947
+        if (!empty($requireMin)
948
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
949
+        ) {
950
+
951
+            return false;
952
+        }
953
+
954
+        if (!empty($requireMax)
955
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
956
+        ) {
957
+            return false;
958
+        }
959
+
960
+        return true;
961
+    }
962
+
963
+    /**
964
+     * get the installed version of all apps
965
+     */
966
+    public static function getAppVersions() {
967
+        static $versions;
968
+
969
+        if(!$versions) {
970
+            $appConfig = \OC::$server->getAppConfig();
971
+            $versions = $appConfig->getValues(false, 'installed_version');
972
+        }
973
+        return $versions;
974
+    }
975
+
976
+    /**
977
+     * @param string $app
978
+     * @param \OCP\IConfig $config
979
+     * @param \OCP\IL10N $l
980
+     * @return bool
981
+     *
982
+     * @throws Exception if app is not compatible with this version of ownCloud
983
+     * @throws Exception if no app-name was specified
984
+     */
985
+    public function installApp($app,
986
+                                \OCP\IConfig $config,
987
+                                \OCP\IL10N $l) {
988
+        if ($app !== false) {
989
+            // check if the app is compatible with this version of ownCloud
990
+            $info = self::getAppInfo($app);
991
+            if(!is_array($info)) {
992
+                throw new \Exception(
993
+                    $l->t('App "%s" cannot be installed because appinfo file cannot be read.',
994
+                        [$info['name']]
995
+                    )
996
+                );
997
+            }
998
+
999
+            $version = \OCP\Util::getVersion();
1000
+            if (!self::isAppCompatible($version, $info)) {
1001
+                throw new \Exception(
1002
+                    $l->t('App "%s" cannot be installed because it is not compatible with this version of the server.',
1003
+                        array($info['name'])
1004
+                    )
1005
+                );
1006
+            }
1007
+
1008
+            // check for required dependencies
1009
+            self::checkAppDependencies($config, $l, $info);
1010
+
1011
+            $config->setAppValue($app, 'enabled', 'yes');
1012
+            if (isset($appData['id'])) {
1013
+                $config->setAppValue($app, 'ocsid', $appData['id']);
1014
+            }
1015
+
1016
+            if(isset($info['settings']) && is_array($info['settings'])) {
1017
+                $appPath = self::getAppPath($app);
1018
+                self::registerAutoloading($app, $appPath);
1019
+                \OC::$server->getSettingsManager()->setupSettings($info['settings']);
1020
+            }
1021
+
1022
+            \OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
1023
+        } else {
1024
+            if(empty($appName) ) {
1025
+                throw new \Exception($l->t("No app name specified"));
1026
+            } else {
1027
+                throw new \Exception($l->t("App '%s' could not be installed!", $appName));
1028
+            }
1029
+        }
1030
+
1031
+        return $app;
1032
+    }
1033
+
1034
+    /**
1035
+     * update the database for the app and call the update script
1036
+     *
1037
+     * @param string $appId
1038
+     * @return bool
1039
+     */
1040
+    public static function updateApp($appId) {
1041
+        $appPath = self::getAppPath($appId);
1042
+        if($appPath === false) {
1043
+            return false;
1044
+        }
1045
+        self::registerAutoloading($appId, $appPath);
1046
+
1047
+        $appData = self::getAppInfo($appId);
1048
+        self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1049
+
1050
+        if (file_exists($appPath . '/appinfo/database.xml')) {
1051
+            OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1052
+        } else {
1053
+            $ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1054
+            $ms->migrate();
1055
+        }
1056
+
1057
+        self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
1058
+        self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
1059
+        unset(self::$appVersion[$appId]);
1060
+
1061
+        // run upgrade code
1062
+        if (file_exists($appPath . '/appinfo/update.php')) {
1063
+            self::loadApp($appId);
1064
+            include $appPath . '/appinfo/update.php';
1065
+        }
1066
+        self::setupBackgroundJobs($appData['background-jobs']);
1067
+        if(isset($appData['settings']) && is_array($appData['settings'])) {
1068
+            \OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1069
+        }
1070
+
1071
+        //set remote/public handlers
1072
+        if (array_key_exists('ocsid', $appData)) {
1073
+            \OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1074
+        } elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1075
+            \OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1076
+        }
1077
+        foreach ($appData['remote'] as $name => $path) {
1078
+            \OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1079
+        }
1080
+        foreach ($appData['public'] as $name => $path) {
1081
+            \OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1082
+        }
1083
+
1084
+        self::setAppTypes($appId);
1085
+
1086
+        $version = \OC_App::getAppVersion($appId);
1087
+        \OC::$server->getAppConfig()->setValue($appId, 'installed_version', $version);
1088
+
1089
+        \OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
1090
+            ManagerEvent::EVENT_APP_UPDATE, $appId
1091
+        ));
1092
+
1093
+        return true;
1094
+    }
1095
+
1096
+    /**
1097
+     * @param string $appId
1098
+     * @param string[] $steps
1099
+     * @throws \OC\NeedsUpdateException
1100
+     */
1101
+    public static function executeRepairSteps($appId, array $steps) {
1102
+        if (empty($steps)) {
1103
+            return;
1104
+        }
1105
+        // load the app
1106
+        self::loadApp($appId);
1107
+
1108
+        $dispatcher = OC::$server->getEventDispatcher();
1109
+
1110
+        // load the steps
1111
+        $r = new Repair([], $dispatcher);
1112
+        foreach ($steps as $step) {
1113
+            try {
1114
+                $r->addStep($step);
1115
+            } catch (Exception $ex) {
1116
+                $r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
1117
+                \OC::$server->getLogger()->logException($ex);
1118
+            }
1119
+        }
1120
+        // run the steps
1121
+        $r->run();
1122
+    }
1123
+
1124
+    public static function setupBackgroundJobs(array $jobs) {
1125
+        $queue = \OC::$server->getJobList();
1126
+        foreach ($jobs as $job) {
1127
+            $queue->add($job);
1128
+        }
1129
+    }
1130
+
1131
+    /**
1132
+     * @param string $appId
1133
+     * @param string[] $steps
1134
+     */
1135
+    private static function setupLiveMigrations($appId, array $steps) {
1136
+        $queue = \OC::$server->getJobList();
1137
+        foreach ($steps as $step) {
1138
+            $queue->add('OC\Migration\BackgroundRepair', [
1139
+                'app' => $appId,
1140
+                'step' => $step]);
1141
+        }
1142
+    }
1143
+
1144
+    /**
1145
+     * @param string $appId
1146
+     * @return \OC\Files\View|false
1147
+     */
1148
+    public static function getStorage($appId) {
1149
+        if (OC_App::isEnabled($appId)) { //sanity check
1150
+            if (\OC::$server->getUserSession()->isLoggedIn()) {
1151
+                $view = new \OC\Files\View('/' . OC_User::getUser());
1152
+                if (!$view->file_exists($appId)) {
1153
+                    $view->mkdir($appId);
1154
+                }
1155
+                return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1156
+            } else {
1157
+                \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1158
+                return false;
1159
+            }
1160
+        } else {
1161
+            \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1162
+            return false;
1163
+        }
1164
+    }
1165
+
1166
+    protected static function findBestL10NOption($options, $lang) {
1167
+        $fallback = $similarLangFallback = $englishFallback = false;
1168
+
1169
+        $lang = strtolower($lang);
1170
+        $similarLang = $lang;
1171
+        if (strpos($similarLang, '_')) {
1172
+            // For "de_DE" we want to find "de" and the other way around
1173
+            $similarLang = substr($lang, 0, strpos($lang, '_'));
1174
+        }
1175
+
1176
+        foreach ($options as $option) {
1177
+            if (is_array($option)) {
1178
+                if ($fallback === false) {
1179
+                    $fallback = $option['@value'];
1180
+                }
1181
+
1182
+                if (!isset($option['@attributes']['lang'])) {
1183
+                    continue;
1184
+                }
1185
+
1186
+                $attributeLang = strtolower($option['@attributes']['lang']);
1187
+                if ($attributeLang === $lang) {
1188
+                    return $option['@value'];
1189
+                }
1190
+
1191
+                if ($attributeLang === $similarLang) {
1192
+                    $similarLangFallback = $option['@value'];
1193
+                } else if (strpos($attributeLang, $similarLang . '_') === 0) {
1194
+                    if ($similarLangFallback === false) {
1195
+                        $similarLangFallback =  $option['@value'];
1196
+                    }
1197
+                }
1198
+            } else {
1199
+                $englishFallback = $option;
1200
+            }
1201
+        }
1202
+
1203
+        if ($similarLangFallback !== false) {
1204
+            return $similarLangFallback;
1205
+        } else if ($englishFallback !== false) {
1206
+            return $englishFallback;
1207
+        }
1208
+        return (string) $fallback;
1209
+    }
1210
+
1211
+    /**
1212
+     * parses the app data array and enhanced the 'description' value
1213
+     *
1214
+     * @param array $data the app data
1215
+     * @param string $lang
1216
+     * @return array improved app data
1217
+     */
1218
+    public static function parseAppInfo(array $data, $lang = null) {
1219
+
1220
+        if ($lang && isset($data['name']) && is_array($data['name'])) {
1221
+            $data['name'] = self::findBestL10NOption($data['name'], $lang);
1222
+        }
1223
+        if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1224
+            $data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1225
+        }
1226
+        if ($lang && isset($data['description']) && is_array($data['description'])) {
1227
+            $data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1228
+        } else if (isset($data['description']) && is_string($data['description'])) {
1229
+            $data['description'] = trim($data['description']);
1230
+        } else  {
1231
+            $data['description'] = '';
1232
+        }
1233
+
1234
+        return $data;
1235
+    }
1236
+
1237
+    /**
1238
+     * @param \OCP\IConfig $config
1239
+     * @param \OCP\IL10N $l
1240
+     * @param array $info
1241
+     * @throws \Exception
1242
+     */
1243
+    public static function checkAppDependencies($config, $l, $info) {
1244
+        $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1245
+        $missing = $dependencyAnalyzer->analyze($info);
1246
+        if (!empty($missing)) {
1247
+            $missingMsg = join(PHP_EOL, $missing);
1248
+            throw new \Exception(
1249
+                $l->t('App "%s" cannot be installed because the following dependencies are not fulfilled: %s',
1250
+                    [$info['name'], $missingMsg]
1251
+                )
1252
+            );
1253
+        }
1254
+    }
1255 1255
 }
Please login to merge, or discard this patch.
Spacing   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -111,9 +111,9 @@  discard block
 block discarded – undo
111 111
 		$apps = self::getEnabledApps();
112 112
 
113 113
 		// Add each apps' folder as allowed class path
114
-		foreach($apps as $app) {
114
+		foreach ($apps as $app) {
115 115
 			$path = self::getAppPath($app);
116
-			if($path !== false) {
116
+			if ($path !== false) {
117 117
 				self::registerAutoloading($app, $path);
118 118
 			}
119 119
 		}
@@ -138,15 +138,15 @@  discard block
 block discarded – undo
138 138
 	public static function loadApp($app) {
139 139
 		self::$loadedApps[] = $app;
140 140
 		$appPath = self::getAppPath($app);
141
-		if($appPath === false) {
141
+		if ($appPath === false) {
142 142
 			return;
143 143
 		}
144 144
 
145 145
 		// in case someone calls loadApp() directly
146 146
 		self::registerAutoloading($app, $appPath);
147 147
 
148
-		if (is_file($appPath . '/appinfo/app.php')) {
149
-			\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
148
+		if (is_file($appPath.'/appinfo/app.php')) {
149
+			\OC::$server->getEventLogger()->start('load_app_'.$app, 'Load app: '.$app);
150 150
 			self::requireAppFile($app);
151 151
 			if (self::isType($app, array('authentication'))) {
152 152
 				// since authentication apps affect the "is app enabled for group" check,
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
 				// enabled for groups
156 156
 				self::$enabledAppsCache = array();
157 157
 			}
158
-			\OC::$server->getEventLogger()->end('load_app_' . $app);
158
+			\OC::$server->getEventLogger()->end('load_app_'.$app);
159 159
 		}
160 160
 
161 161
 		$info = self::getAppInfo($app);
@@ -182,17 +182,17 @@  discard block
 block discarded – undo
182 182
 	 * @param string $path
183 183
 	 */
184 184
 	public static function registerAutoloading($app, $path) {
185
-		$key = $app . '-' . $path;
186
-		if(isset(self::$alreadyRegistered[$key])) {
185
+		$key = $app.'-'.$path;
186
+		if (isset(self::$alreadyRegistered[$key])) {
187 187
 			return;
188 188
 		}
189 189
 		self::$alreadyRegistered[$key] = true;
190 190
 		// Register on PSR-4 composer autoloader
191 191
 		$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
192 192
 		\OC::$server->registerNamespace($app, $appNamespace);
193
-		\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
193
+		\OC::$composerAutoloader->addPsr4($appNamespace.'\\', $path.'/lib/', true);
194 194
 		if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
195
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
195
+			\OC::$composerAutoloader->addPsr4($appNamespace.'\\Tests\\', $path.'/tests/', true);
196 196
 		}
197 197
 
198 198
 		// Register on legacy autoloader
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
 	private static function requireAppFile($app) {
208 208
 		try {
209 209
 			// encapsulated here to avoid variable scope conflicts
210
-			require_once $app . '/appinfo/app.php';
210
+			require_once $app.'/appinfo/app.php';
211 211
 		} catch (Error $ex) {
212 212
 			\OC::$server->getLogger()->logException($ex);
213 213
 			$blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps();
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
 	 */
262 262
 	public static function setAppTypes($app) {
263 263
 		$appData = self::getAppInfo($app);
264
-		if(!is_array($appData)) {
264
+		if (!is_array($appData)) {
265 265
 			return;
266 266
 		}
267 267
 
@@ -325,8 +325,8 @@  discard block
 block discarded – undo
325 325
 		} else {
326 326
 			$apps = $appManager->getEnabledAppsForUser($user);
327 327
 		}
328
-		$apps = array_filter($apps, function ($app) {
329
-			return $app !== 'files';//we add this manually
328
+		$apps = array_filter($apps, function($app) {
329
+			return $app !== 'files'; //we add this manually
330 330
 		});
331 331
 		sort($apps);
332 332
 		array_unshift($apps, 'files');
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
 		);
370 370
 		$isDownloaded = $installer->isDownloaded($appId);
371 371
 
372
-		if(!$isDownloaded) {
372
+		if (!$isDownloaded) {
373 373
 			$installer->downloadApp($appId);
374 374
 		}
375 375
 
@@ -488,7 +488,7 @@  discard block
 block discarded – undo
488 488
 	 */
489 489
 	public static function findAppInDirectories($appId) {
490 490
 		$sanitizedAppId = self::cleanAppId($appId);
491
-		if($sanitizedAppId !== $appId) {
491
+		if ($sanitizedAppId !== $appId) {
492 492
 			return false;
493 493
 		}
494 494
 		static $app_dir = array();
@@ -499,7 +499,7 @@  discard block
 block discarded – undo
499 499
 
500 500
 		$possibleApps = array();
501 501
 		foreach (OC::$APPSROOTS as $dir) {
502
-			if (file_exists($dir['path'] . '/' . $appId)) {
502
+			if (file_exists($dir['path'].'/'.$appId)) {
503 503
 				$possibleApps[] = $dir;
504 504
 			}
505 505
 		}
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
 		}
541 541
 
542 542
 		if (($dir = self::findAppInDirectories($appId)) != false) {
543
-			return $dir['path'] . '/' . $appId;
543
+			return $dir['path'].'/'.$appId;
544 544
 		}
545 545
 		return false;
546 546
 	}
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
 	 */
555 555
 	public static function getAppWebPath($appId) {
556 556
 		if (($dir = self::findAppInDirectories($appId)) != false) {
557
-			return OC::$WEBROOT . $dir['url'] . '/' . $appId;
557
+			return OC::$WEBROOT.$dir['url'].'/'.$appId;
558 558
 		}
559 559
 		return false;
560 560
 	}
@@ -567,7 +567,7 @@  discard block
 block discarded – undo
567 567
 	 * @return string
568 568
 	 */
569 569
 	public static function getAppVersion($appId, $useCache = true) {
570
-		if($useCache && isset(self::$appVersion[$appId])) {
570
+		if ($useCache && isset(self::$appVersion[$appId])) {
571 571
 			return self::$appVersion[$appId];
572 572
 		}
573 573
 
@@ -583,7 +583,7 @@  discard block
 block discarded – undo
583 583
 	 * @return string
584 584
 	 */
585 585
 	public static function getAppVersionByPath($path) {
586
-		$infoFile = $path . '/appinfo/info.xml';
586
+		$infoFile = $path.'/appinfo/info.xml';
587 587
 		$appData = self::getAppInfo($infoFile, true);
588 588
 		return isset($appData['version']) ? $appData['version'] : '';
589 589
 	}
@@ -606,10 +606,10 @@  discard block
 block discarded – undo
606 606
 				return self::$appInfo[$appId];
607 607
 			}
608 608
 			$appPath = self::getAppPath($appId);
609
-			if($appPath === false) {
609
+			if ($appPath === false) {
610 610
 				return null;
611 611
 			}
612
-			$file = $appPath . '/appinfo/info.xml';
612
+			$file = $appPath.'/appinfo/info.xml';
613 613
 		}
614 614
 
615 615
 		$parser = new InfoParser(\OC::$server->getMemCacheFactory()->create('core.appinfo'));
@@ -618,9 +618,9 @@  discard block
 block discarded – undo
618 618
 		if (is_array($data)) {
619 619
 			$data = OC_App::parseAppInfo($data, $lang);
620 620
 		}
621
-		if(isset($data['ocsid'])) {
621
+		if (isset($data['ocsid'])) {
622 622
 			$storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
623
-			if($storedId !== '' && $storedId !== $data['ocsid']) {
623
+			if ($storedId !== '' && $storedId !== $data['ocsid']) {
624 624
 				$data['ocsid'] = $storedId;
625 625
 			}
626 626
 		}
@@ -712,7 +712,7 @@  discard block
 block discarded – undo
712 712
 	 * @param string $page
713 713
 	 */
714 714
 	public static function registerAdmin($app, $page) {
715
-		self::$adminForms[] = $app . '/' . $page . '.php';
715
+		self::$adminForms[] = $app.'/'.$page.'.php';
716 716
 	}
717 717
 
718 718
 	/**
@@ -721,7 +721,7 @@  discard block
 block discarded – undo
721 721
 	 * @param string $page
722 722
 	 */
723 723
 	public static function registerPersonal($app, $page) {
724
-		self::$personalForms[] = $app . '/' . $page . '.php';
724
+		self::$personalForms[] = $app.'/'.$page.'.php';
725 725
 	}
726 726
 
727 727
 	/**
@@ -750,7 +750,7 @@  discard block
 block discarded – undo
750 750
 
751 751
 		foreach (OC::$APPSROOTS as $apps_dir) {
752 752
 			if (!is_readable($apps_dir['path'])) {
753
-				\OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
753
+				\OCP\Util::writeLog('core', 'unable to read app folder : '.$apps_dir['path'], \OCP\Util::WARN);
754 754
 				continue;
755 755
 			}
756 756
 			$dh = opendir($apps_dir['path']);
@@ -758,7 +758,7 @@  discard block
 block discarded – undo
758 758
 			if (is_resource($dh)) {
759 759
 				while (($file = readdir($dh)) !== false) {
760 760
 
761
-					if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
761
+					if ($file[0] != '.' and is_dir($apps_dir['path'].'/'.$file) and is_file($apps_dir['path'].'/'.$file.'/appinfo/info.xml')) {
762 762
 
763 763
 						$apps[] = $file;
764 764
 					}
@@ -788,12 +788,12 @@  discard block
 block discarded – undo
788 788
 
789 789
 				$info = OC_App::getAppInfo($app, false, $langCode);
790 790
 				if (!is_array($info)) {
791
-					\OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
791
+					\OCP\Util::writeLog('core', 'Could not read app info file for app "'.$app.'"', \OCP\Util::ERROR);
792 792
 					continue;
793 793
 				}
794 794
 
795 795
 				if (!isset($info['name'])) {
796
-					\OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
796
+					\OCP\Util::writeLog('core', 'App id "'.$app.'" has no name in appinfo', \OCP\Util::ERROR);
797 797
 					continue;
798 798
 				}
799 799
 
@@ -820,13 +820,13 @@  discard block
 block discarded – undo
820 820
 				}
821 821
 
822 822
 				$appPath = self::getAppPath($app);
823
-				if($appPath !== false) {
824
-					$appIcon = $appPath . '/img/' . $app . '.svg';
823
+				if ($appPath !== false) {
824
+					$appIcon = $appPath.'/img/'.$app.'.svg';
825 825
 					if (file_exists($appIcon)) {
826
-						$info['preview'] = \OC::$server->getURLGenerator()->imagePath($app, $app . '.svg');
826
+						$info['preview'] = \OC::$server->getURLGenerator()->imagePath($app, $app.'.svg');
827 827
 						$info['previewAsIcon'] = true;
828 828
 					} else {
829
-						$appIcon = $appPath . '/img/app.svg';
829
+						$appIcon = $appPath.'/img/app.svg';
830 830
 						if (file_exists($appIcon)) {
831 831
 							$info['preview'] = \OC::$server->getURLGenerator()->imagePath($app, 'app.svg');
832 832
 							$info['previewAsIcon'] = true;
@@ -860,9 +860,9 @@  discard block
 block discarded – undo
860 860
 	 * @return string|false
861 861
 	 */
862 862
 	public static function getInternalAppIdByOcs($ocsID) {
863
-		if(is_numeric($ocsID)) {
863
+		if (is_numeric($ocsID)) {
864 864
 			$idArray = \OC::$server->getAppConfig()->getValues(false, 'ocsid');
865
-			if(array_search($ocsID, $idArray)) {
865
+			if (array_search($ocsID, $idArray)) {
866 866
 				return array_search($ocsID, $idArray);
867 867
 			}
868 868
 		}
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
 	public static function getAppVersions() {
967 967
 		static $versions;
968 968
 
969
-		if(!$versions) {
969
+		if (!$versions) {
970 970
 			$appConfig = \OC::$server->getAppConfig();
971 971
 			$versions = $appConfig->getValues(false, 'installed_version');
972 972
 		}
@@ -988,7 +988,7 @@  discard block
 block discarded – undo
988 988
 		if ($app !== false) {
989 989
 			// check if the app is compatible with this version of ownCloud
990 990
 			$info = self::getAppInfo($app);
991
-			if(!is_array($info)) {
991
+			if (!is_array($info)) {
992 992
 				throw new \Exception(
993 993
 					$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
994 994
 						[$info['name']]
@@ -1013,7 +1013,7 @@  discard block
 block discarded – undo
1013 1013
 				$config->setAppValue($app, 'ocsid', $appData['id']);
1014 1014
 			}
1015 1015
 
1016
-			if(isset($info['settings']) && is_array($info['settings'])) {
1016
+			if (isset($info['settings']) && is_array($info['settings'])) {
1017 1017
 				$appPath = self::getAppPath($app);
1018 1018
 				self::registerAutoloading($app, $appPath);
1019 1019
 				\OC::$server->getSettingsManager()->setupSettings($info['settings']);
@@ -1021,7 +1021,7 @@  discard block
 block discarded – undo
1021 1021
 
1022 1022
 			\OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
1023 1023
 		} else {
1024
-			if(empty($appName) ) {
1024
+			if (empty($appName)) {
1025 1025
 				throw new \Exception($l->t("No app name specified"));
1026 1026
 			} else {
1027 1027
 				throw new \Exception($l->t("App '%s' could not be installed!", $appName));
@@ -1039,7 +1039,7 @@  discard block
 block discarded – undo
1039 1039
 	 */
1040 1040
 	public static function updateApp($appId) {
1041 1041
 		$appPath = self::getAppPath($appId);
1042
-		if($appPath === false) {
1042
+		if ($appPath === false) {
1043 1043
 			return false;
1044 1044
 		}
1045 1045
 		self::registerAutoloading($appId, $appPath);
@@ -1047,8 +1047,8 @@  discard block
 block discarded – undo
1047 1047
 		$appData = self::getAppInfo($appId);
1048 1048
 		self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
1049 1049
 
1050
-		if (file_exists($appPath . '/appinfo/database.xml')) {
1051
-			OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
1050
+		if (file_exists($appPath.'/appinfo/database.xml')) {
1051
+			OC_DB::updateDbFromStructure($appPath.'/appinfo/database.xml');
1052 1052
 		} else {
1053 1053
 			$ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
1054 1054
 			$ms->migrate();
@@ -1059,26 +1059,26 @@  discard block
 block discarded – undo
1059 1059
 		unset(self::$appVersion[$appId]);
1060 1060
 
1061 1061
 		// run upgrade code
1062
-		if (file_exists($appPath . '/appinfo/update.php')) {
1062
+		if (file_exists($appPath.'/appinfo/update.php')) {
1063 1063
 			self::loadApp($appId);
1064
-			include $appPath . '/appinfo/update.php';
1064
+			include $appPath.'/appinfo/update.php';
1065 1065
 		}
1066 1066
 		self::setupBackgroundJobs($appData['background-jobs']);
1067
-		if(isset($appData['settings']) && is_array($appData['settings'])) {
1067
+		if (isset($appData['settings']) && is_array($appData['settings'])) {
1068 1068
 			\OC::$server->getSettingsManager()->setupSettings($appData['settings']);
1069 1069
 		}
1070 1070
 
1071 1071
 		//set remote/public handlers
1072 1072
 		if (array_key_exists('ocsid', $appData)) {
1073 1073
 			\OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
1074
-		} elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1074
+		} elseif (\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
1075 1075
 			\OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
1076 1076
 		}
1077 1077
 		foreach ($appData['remote'] as $name => $path) {
1078
-			\OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
1078
+			\OC::$server->getConfig()->setAppValue('core', 'remote_'.$name, $appId.'/'.$path);
1079 1079
 		}
1080 1080
 		foreach ($appData['public'] as $name => $path) {
1081
-			\OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
1081
+			\OC::$server->getConfig()->setAppValue('core', 'public_'.$name, $appId.'/'.$path);
1082 1082
 		}
1083 1083
 
1084 1084
 		self::setAppTypes($appId);
@@ -1148,17 +1148,17 @@  discard block
 block discarded – undo
1148 1148
 	public static function getStorage($appId) {
1149 1149
 		if (OC_App::isEnabled($appId)) { //sanity check
1150 1150
 			if (\OC::$server->getUserSession()->isLoggedIn()) {
1151
-				$view = new \OC\Files\View('/' . OC_User::getUser());
1151
+				$view = new \OC\Files\View('/'.OC_User::getUser());
1152 1152
 				if (!$view->file_exists($appId)) {
1153 1153
 					$view->mkdir($appId);
1154 1154
 				}
1155
-				return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1155
+				return new \OC\Files\View('/'.OC_User::getUser().'/'.$appId);
1156 1156
 			} else {
1157
-				\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
1157
+				\OCP\Util::writeLog('core', 'Can\'t get app storage, app '.$appId.', user not logged in', \OCP\Util::ERROR);
1158 1158
 				return false;
1159 1159
 			}
1160 1160
 		} else {
1161
-			\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
1161
+			\OCP\Util::writeLog('core', 'Can\'t get app storage, app '.$appId.' not enabled', \OCP\Util::ERROR);
1162 1162
 			return false;
1163 1163
 		}
1164 1164
 	}
@@ -1190,9 +1190,9 @@  discard block
 block discarded – undo
1190 1190
 
1191 1191
 				if ($attributeLang === $similarLang) {
1192 1192
 					$similarLangFallback = $option['@value'];
1193
-				} else if (strpos($attributeLang, $similarLang . '_') === 0) {
1193
+				} else if (strpos($attributeLang, $similarLang.'_') === 0) {
1194 1194
 					if ($similarLangFallback === false) {
1195
-						$similarLangFallback =  $option['@value'];
1195
+						$similarLangFallback = $option['@value'];
1196 1196
 					}
1197 1197
 				}
1198 1198
 			} else {
@@ -1227,7 +1227,7 @@  discard block
 block discarded – undo
1227 1227
 			$data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1228 1228
 		} else if (isset($data['description']) && is_string($data['description'])) {
1229 1229
 			$data['description'] = trim($data['description']);
1230
-		} else  {
1230
+		} else {
1231 1231
 			$data['description'] = '';
1232 1232
 		}
1233 1233
 
Please login to merge, or discard this patch.
lib/private/Files/Node/File.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@
 block discarded – undo
31 31
 	 * Creates a Folder that represents a non-existing path
32 32
 	 *
33 33
 	 * @param string $path path
34
-	 * @return string non-existing node class
34
+	 * @return NonExistingFile non-existing node class
35 35
 	 */
36 36
 	protected function createNonExistingNode($path) {
37 37
 		return new NonExistingFile($this->root, $this->view, $path);
Please login to merge, or discard this patch.
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -29,113 +29,113 @@
 block discarded – undo
29 29
 use OCP\Files\NotPermittedException;
30 30
 
31 31
 class File extends Node implements \OCP\Files\File {
32
-	/**
33
-	 * Creates a Folder that represents a non-existing path
34
-	 *
35
-	 * @param string $path path
36
-	 * @return string non-existing node class
37
-	 */
38
-	protected function createNonExistingNode($path) {
39
-		return new NonExistingFile($this->root, $this->view, $path);
40
-	}
32
+    /**
33
+     * Creates a Folder that represents a non-existing path
34
+     *
35
+     * @param string $path path
36
+     * @return string non-existing node class
37
+     */
38
+    protected function createNonExistingNode($path) {
39
+        return new NonExistingFile($this->root, $this->view, $path);
40
+    }
41 41
 
42
-	/**
43
-	 * @return string
44
-	 * @throws \OCP\Files\NotPermittedException
45
-	 */
46
-	public function getContent() {
47
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_READ)) {
48
-			/**
49
-			 * @var \OC\Files\Storage\Storage $storage;
50
-			 */
51
-			return $this->view->file_get_contents($this->path);
52
-		} else {
53
-			throw new NotPermittedException();
54
-		}
55
-	}
42
+    /**
43
+     * @return string
44
+     * @throws \OCP\Files\NotPermittedException
45
+     */
46
+    public function getContent() {
47
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_READ)) {
48
+            /**
49
+             * @var \OC\Files\Storage\Storage $storage;
50
+             */
51
+            return $this->view->file_get_contents($this->path);
52
+        } else {
53
+            throw new NotPermittedException();
54
+        }
55
+    }
56 56
 
57
-	/**
58
-	 * @param string $data
59
-	 * @throws \OCP\Files\NotPermittedException
60
-	 */
61
-	public function putContent($data) {
62
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) {
63
-			$this->sendHooks(array('preWrite'));
64
-			$this->view->file_put_contents($this->path, $data);
65
-			$this->fileInfo = null;
66
-			$this->sendHooks(array('postWrite'));
67
-		} else {
68
-			throw new NotPermittedException();
69
-		}
70
-	}
57
+    /**
58
+     * @param string $data
59
+     * @throws \OCP\Files\NotPermittedException
60
+     */
61
+    public function putContent($data) {
62
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) {
63
+            $this->sendHooks(array('preWrite'));
64
+            $this->view->file_put_contents($this->path, $data);
65
+            $this->fileInfo = null;
66
+            $this->sendHooks(array('postWrite'));
67
+        } else {
68
+            throw new NotPermittedException();
69
+        }
70
+    }
71 71
 
72
-	/**
73
-	 * @param string $mode
74
-	 * @return resource
75
-	 * @throws \OCP\Files\NotPermittedException
76
-	 */
77
-	public function fopen($mode) {
78
-		$preHooks = array();
79
-		$postHooks = array();
80
-		$requiredPermissions = \OCP\Constants::PERMISSION_READ;
81
-		switch ($mode) {
82
-			case 'r+':
83
-			case 'rb+':
84
-			case 'w+':
85
-			case 'wb+':
86
-			case 'x+':
87
-			case 'xb+':
88
-			case 'a+':
89
-			case 'ab+':
90
-			case 'w':
91
-			case 'wb':
92
-			case 'x':
93
-			case 'xb':
94
-			case 'a':
95
-			case 'ab':
96
-				$preHooks[] = 'preWrite';
97
-				$postHooks[] = 'postWrite';
98
-				$requiredPermissions |= \OCP\Constants::PERMISSION_UPDATE;
99
-				break;
100
-		}
72
+    /**
73
+     * @param string $mode
74
+     * @return resource
75
+     * @throws \OCP\Files\NotPermittedException
76
+     */
77
+    public function fopen($mode) {
78
+        $preHooks = array();
79
+        $postHooks = array();
80
+        $requiredPermissions = \OCP\Constants::PERMISSION_READ;
81
+        switch ($mode) {
82
+            case 'r+':
83
+            case 'rb+':
84
+            case 'w+':
85
+            case 'wb+':
86
+            case 'x+':
87
+            case 'xb+':
88
+            case 'a+':
89
+            case 'ab+':
90
+            case 'w':
91
+            case 'wb':
92
+            case 'x':
93
+            case 'xb':
94
+            case 'a':
95
+            case 'ab':
96
+                $preHooks[] = 'preWrite';
97
+                $postHooks[] = 'postWrite';
98
+                $requiredPermissions |= \OCP\Constants::PERMISSION_UPDATE;
99
+                break;
100
+        }
101 101
 
102
-		if ($this->checkPermissions($requiredPermissions)) {
103
-			$this->sendHooks($preHooks);
104
-			$result = $this->view->fopen($this->path, $mode);
105
-			$this->sendHooks($postHooks);
106
-			return $result;
107
-		} else {
108
-			throw new NotPermittedException();
109
-		}
110
-	}
102
+        if ($this->checkPermissions($requiredPermissions)) {
103
+            $this->sendHooks($preHooks);
104
+            $result = $this->view->fopen($this->path, $mode);
105
+            $this->sendHooks($postHooks);
106
+            return $result;
107
+        } else {
108
+            throw new NotPermittedException();
109
+        }
110
+    }
111 111
 
112
-	public function delete() {
113
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
114
-			$this->sendHooks(array('preDelete'));
115
-			$fileInfo = $this->getFileInfo();
116
-			$this->view->unlink($this->path);
117
-			$nonExisting = new NonExistingFile($this->root, $this->view, $this->path, $fileInfo);
118
-			$this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
119
-			$this->exists = false;
120
-			$this->fileInfo = null;
121
-		} else {
122
-			throw new NotPermittedException();
123
-		}
124
-	}
112
+    public function delete() {
113
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
114
+            $this->sendHooks(array('preDelete'));
115
+            $fileInfo = $this->getFileInfo();
116
+            $this->view->unlink($this->path);
117
+            $nonExisting = new NonExistingFile($this->root, $this->view, $this->path, $fileInfo);
118
+            $this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
119
+            $this->exists = false;
120
+            $this->fileInfo = null;
121
+        } else {
122
+            throw new NotPermittedException();
123
+        }
124
+    }
125 125
 
126
-	/**
127
-	 * @param string $type
128
-	 * @param bool $raw
129
-	 * @return string
130
-	 */
131
-	public function hash($type, $raw = false) {
132
-		return $this->view->hash($type, $this->path, $raw);
133
-	}
126
+    /**
127
+     * @param string $type
128
+     * @param bool $raw
129
+     * @return string
130
+     */
131
+    public function hash($type, $raw = false) {
132
+        return $this->view->hash($type, $this->path, $raw);
133
+    }
134 134
 
135
-	/**
136
-	 * @inheritdoc
137
-	 */
138
-	public function getChecksum() {
139
-		return $this->getFileInfo()->getChecksum();
140
-	}
135
+    /**
136
+     * @inheritdoc
137
+     */
138
+    public function getChecksum() {
139
+        return $this->getFileInfo()->getChecksum();
140
+    }
141 141
 }
Please login to merge, or discard this patch.
lib/private/Files/Node/Folder.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -37,7 +37,7 @@
 block discarded – undo
37 37
 	 * Creates a Folder that represents a non-existing path
38 38
 	 *
39 39
 	 * @param string $path path
40
-	 * @return string non-existing node class
40
+	 * @return NonExistingFolder non-existing node class
41 41
 	 */
42 42
 	protected function createNonExistingNode($path) {
43 43
 		return new NonExistingFolder($this->root, $this->view, $path);
Please login to merge, or discard this patch.
Indentation   +395 added lines, -395 removed lines patch added patch discarded remove patch
@@ -36,399 +36,399 @@
 block discarded – undo
36 36
 use OCP\Files\Search\ISearchOperator;
37 37
 
38 38
 class Folder extends Node implements \OCP\Files\Folder {
39
-	/**
40
-	 * Creates a Folder that represents a non-existing path
41
-	 *
42
-	 * @param string $path path
43
-	 * @return string non-existing node class
44
-	 */
45
-	protected function createNonExistingNode($path) {
46
-		return new NonExistingFolder($this->root, $this->view, $path);
47
-	}
48
-
49
-	/**
50
-	 * @param string $path path relative to the folder
51
-	 * @return string
52
-	 * @throws \OCP\Files\NotPermittedException
53
-	 */
54
-	public function getFullPath($path) {
55
-		if (!$this->isValidPath($path)) {
56
-			throw new NotPermittedException('Invalid path');
57
-		}
58
-		return $this->path . $this->normalizePath($path);
59
-	}
60
-
61
-	/**
62
-	 * @param string $path
63
-	 * @return string
64
-	 */
65
-	public function getRelativePath($path) {
66
-		if ($this->path === '' or $this->path === '/') {
67
-			return $this->normalizePath($path);
68
-		}
69
-		if ($path === $this->path) {
70
-			return '/';
71
-		} else if (strpos($path, $this->path . '/') !== 0) {
72
-			return null;
73
-		} else {
74
-			$path = substr($path, strlen($this->path));
75
-			return $this->normalizePath($path);
76
-		}
77
-	}
78
-
79
-	/**
80
-	 * check if a node is a (grand-)child of the folder
81
-	 *
82
-	 * @param \OC\Files\Node\Node $node
83
-	 * @return bool
84
-	 */
85
-	public function isSubNode($node) {
86
-		return strpos($node->getPath(), $this->path . '/') === 0;
87
-	}
88
-
89
-	/**
90
-	 * get the content of this directory
91
-	 *
92
-	 * @throws \OCP\Files\NotFoundException
93
-	 * @return Node[]
94
-	 */
95
-	public function getDirectoryListing() {
96
-		$folderContent = $this->view->getDirectoryContent($this->path);
97
-
98
-		return array_map(function (FileInfo $info) {
99
-			if ($info->getMimetype() === 'httpd/unix-directory') {
100
-				return new Folder($this->root, $this->view, $info->getPath(), $info);
101
-			} else {
102
-				return new File($this->root, $this->view, $info->getPath(), $info);
103
-			}
104
-		}, $folderContent);
105
-	}
106
-
107
-	/**
108
-	 * @param string $path
109
-	 * @param FileInfo $info
110
-	 * @return File|Folder
111
-	 */
112
-	protected function createNode($path, FileInfo $info = null) {
113
-		if (is_null($info)) {
114
-			$isDir = $this->view->is_dir($path);
115
-		} else {
116
-			$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
117
-		}
118
-		if ($isDir) {
119
-			return new Folder($this->root, $this->view, $path, $info);
120
-		} else {
121
-			return new File($this->root, $this->view, $path, $info);
122
-		}
123
-	}
124
-
125
-	/**
126
-	 * Get the node at $path
127
-	 *
128
-	 * @param string $path
129
-	 * @return \OC\Files\Node\Node
130
-	 * @throws \OCP\Files\NotFoundException
131
-	 */
132
-	public function get($path) {
133
-		return $this->root->get($this->getFullPath($path));
134
-	}
135
-
136
-	/**
137
-	 * @param string $path
138
-	 * @return bool
139
-	 */
140
-	public function nodeExists($path) {
141
-		try {
142
-			$this->get($path);
143
-			return true;
144
-		} catch (NotFoundException $e) {
145
-			return false;
146
-		}
147
-	}
148
-
149
-	/**
150
-	 * @param string $path
151
-	 * @return \OC\Files\Node\Folder
152
-	 * @throws \OCP\Files\NotPermittedException
153
-	 */
154
-	public function newFolder($path) {
155
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
156
-			$fullPath = $this->getFullPath($path);
157
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
158
-			$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
159
-			$this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
160
-			$this->view->mkdir($fullPath);
161
-			$node = new Folder($this->root, $this->view, $fullPath);
162
-			$this->root->emit('\OC\Files', 'postWrite', array($node));
163
-			$this->root->emit('\OC\Files', 'postCreate', array($node));
164
-			return $node;
165
-		} else {
166
-			throw new NotPermittedException('No create permission for folder');
167
-		}
168
-	}
169
-
170
-	/**
171
-	 * @param string $path
172
-	 * @return \OC\Files\Node\File
173
-	 * @throws \OCP\Files\NotPermittedException
174
-	 */
175
-	public function newFile($path) {
176
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
177
-			$fullPath = $this->getFullPath($path);
178
-			$nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
179
-			$this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
180
-			$this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
181
-			$this->view->touch($fullPath);
182
-			$node = new File($this->root, $this->view, $fullPath);
183
-			$this->root->emit('\OC\Files', 'postWrite', array($node));
184
-			$this->root->emit('\OC\Files', 'postCreate', array($node));
185
-			return $node;
186
-		} else {
187
-			throw new NotPermittedException('No create permission for path');
188
-		}
189
-	}
190
-
191
-	/**
192
-	 * search for files with the name matching $query
193
-	 *
194
-	 * @param string|ISearchOperator $query
195
-	 * @return \OC\Files\Node\Node[]
196
-	 */
197
-	public function search($query) {
198
-		if (is_string($query)) {
199
-			return $this->searchCommon('search', array('%' . $query . '%'));
200
-		} else {
201
-			return $this->searchCommon('searchQuery', array($query));
202
-		}
203
-	}
204
-
205
-	/**
206
-	 * search for files by mimetype
207
-	 *
208
-	 * @param string $mimetype
209
-	 * @return Node[]
210
-	 */
211
-	public function searchByMime($mimetype) {
212
-		return $this->searchCommon('searchByMime', array($mimetype));
213
-	}
214
-
215
-	/**
216
-	 * search for files by tag
217
-	 *
218
-	 * @param string|int $tag name or tag id
219
-	 * @param string $userId owner of the tags
220
-	 * @return Node[]
221
-	 */
222
-	public function searchByTag($tag, $userId) {
223
-		return $this->searchCommon('searchByTag', array($tag, $userId));
224
-	}
225
-
226
-	/**
227
-	 * @param string $method cache method
228
-	 * @param array $args call args
229
-	 * @return \OC\Files\Node\Node[]
230
-	 */
231
-	private function searchCommon($method, $args) {
232
-		$files = array();
233
-		$rootLength = strlen($this->path);
234
-		$mount = $this->root->getMount($this->path);
235
-		$storage = $mount->getStorage();
236
-		$internalPath = $mount->getInternalPath($this->path);
237
-		$internalPath = rtrim($internalPath, '/');
238
-		if ($internalPath !== '') {
239
-			$internalPath = $internalPath . '/';
240
-		}
241
-		$internalRootLength = strlen($internalPath);
242
-
243
-		$cache = $storage->getCache('');
244
-
245
-		$results = call_user_func_array(array($cache, $method), $args);
246
-		foreach ($results as $result) {
247
-			if ($internalRootLength === 0 or substr($result['path'], 0, $internalRootLength) === $internalPath) {
248
-				$result['internalPath'] = $result['path'];
249
-				$result['path'] = substr($result['path'], $internalRootLength);
250
-				$result['storage'] = $storage;
251
-				$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
252
-			}
253
-		}
254
-
255
-		$mounts = $this->root->getMountsIn($this->path);
256
-		foreach ($mounts as $mount) {
257
-			$storage = $mount->getStorage();
258
-			if ($storage) {
259
-				$cache = $storage->getCache('');
260
-
261
-				$relativeMountPoint = substr($mount->getMountPoint(), $rootLength);
262
-				$results = call_user_func_array(array($cache, $method), $args);
263
-				foreach ($results as $result) {
264
-					$result['internalPath'] = $result['path'];
265
-					$result['path'] = $relativeMountPoint . $result['path'];
266
-					$result['storage'] = $storage;
267
-					$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
268
-				}
269
-			}
270
-		}
271
-
272
-		return array_map(function (FileInfo $file) {
273
-			return $this->createNode($file->getPath(), $file);
274
-		}, $files);
275
-	}
276
-
277
-	/**
278
-	 * @param int $id
279
-	 * @return \OC\Files\Node\Node[]
280
-	 */
281
-	public function getById($id) {
282
-		$mountCache = $this->root->getUserMountCache();
283
-		if (strpos($this->getPath(), '/', 1) > 0) {
284
-			list(, $user) = explode('/', $this->getPath());
285
-		} else {
286
-			$user = null;
287
-		}
288
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
289
-		$mounts = $this->root->getMountsIn($this->path);
290
-		$mounts[] = $this->root->getMount($this->path);
291
-		/** @var IMountPoint[] $folderMounts */
292
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
293
-			return $mountPoint->getMountPoint();
294
-		}, $mounts), $mounts);
295
-
296
-		/** @var ICachedMountInfo[] $mountsContainingFile */
297
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
298
-			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
299
-		}));
300
-
301
-		if (count($mountsContainingFile) === 0) {
302
-			return [];
303
-		}
304
-
305
-		// we only need to get the cache info once, since all mounts we found point to the same storage
306
-
307
-		$mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()];
308
-		$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
309
-		if (!$cacheEntry) {
310
-			return [];
311
-		}
312
-		// cache jails will hide the "true" internal path
313
-		$internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
314
-
315
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
316
-			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
317
-			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
318
-			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
319
-			$absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount;
320
-			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
321
-				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
322
-				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
323
-			));
324
-		}, $mountsContainingFile);
325
-
326
-		return array_filter($nodes, function (Node $node) {
327
-			return $this->getRelativePath($node->getPath());
328
-		});
329
-	}
330
-
331
-	public function getFreeSpace() {
332
-		return $this->view->free_space($this->path);
333
-	}
334
-
335
-	public function delete() {
336
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
337
-			$this->sendHooks(array('preDelete'));
338
-			$fileInfo = $this->getFileInfo();
339
-			$this->view->rmdir($this->path);
340
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
341
-			$this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
342
-			$this->exists = false;
343
-		} else {
344
-			throw new NotPermittedException('No delete permission for path');
345
-		}
346
-	}
347
-
348
-	/**
349
-	 * Add a suffix to the name in case the file exists
350
-	 *
351
-	 * @param string $name
352
-	 * @return string
353
-	 * @throws NotPermittedException
354
-	 */
355
-	public function getNonExistingName($name) {
356
-		$uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
357
-		return trim($this->getRelativePath($uniqueName), '/');
358
-	}
359
-
360
-	/**
361
-	 * @param int $limit
362
-	 * @param int $offset
363
-	 * @return \OCP\Files\Node[]
364
-	 */
365
-	public function getRecent($limit, $offset = 0) {
366
-		$mimetypeLoader = \OC::$server->getMimeTypeLoader();
367
-		$mounts = $this->root->getMountsIn($this->path);
368
-		$mounts[] = $this->getMountPoint();
369
-
370
-		$mounts = array_filter($mounts, function (IMountPoint $mount) {
371
-			return $mount->getStorage();
372
-		});
373
-		$storageIds = array_map(function (IMountPoint $mount) {
374
-			return $mount->getStorage()->getCache()->getNumericStorageId();
375
-		}, $mounts);
376
-		/** @var IMountPoint[] $mountMap */
377
-		$mountMap = array_combine($storageIds, $mounts);
378
-		$folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
379
-
380
-		//todo look into options of filtering path based on storage id (only search in files/ for home storage, filter by share root for shared, etc)
381
-
382
-		$builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
383
-		$query = $builder
384
-			->select('f.*')
385
-			->from('filecache', 'f')
386
-			->andWhere($builder->expr()->in('f.storage', $builder->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY)))
387
-			->andWhere($builder->expr()->orX(
388
-			// handle non empty folders separate
389
-				$builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
390
-				$builder->expr()->eq('f.size', new Literal(0))
391
-			))
392
-			->orderBy('f.mtime', 'DESC')
393
-			->setMaxResults($limit)
394
-			->setFirstResult($offset);
395
-
396
-		$result = $query->execute()->fetchAll();
397
-
398
-		$files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
399
-			$mount = $mountMap[$entry['storage']];
400
-			$entry['internalPath'] = $entry['path'];
401
-			$entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
402
-			$entry['mimepart'] = $mimetypeLoader->getMimetypeById($entry['mimepart']);
403
-			$path = $this->getAbsolutePath($mount, $entry['path']);
404
-			if (is_null($path)) {
405
-				return null;
406
-			}
407
-			$fileInfo = new \OC\Files\FileInfo($path, $mount->getStorage(), $entry['internalPath'], $entry, $mount);
408
-			return $this->root->createNode($fileInfo->getPath(), $fileInfo);
409
-		}, $result));
410
-
411
-		return array_values(array_filter($files, function (Node $node) {
412
-			$relative = $this->getRelativePath($node->getPath());
413
-			return $relative !== null && $relative !== '/';
414
-		}));
415
-	}
416
-
417
-	private function getAbsolutePath(IMountPoint $mount, $path) {
418
-		$storage = $mount->getStorage();
419
-		if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Jail')) {
420
-			/** @var \OC\Files\Storage\Wrapper\Jail $storage */
421
-			$jailRoot = $storage->getUnjailedPath('');
422
-			$rootLength = strlen($jailRoot) + 1;
423
-			if ($path === $jailRoot) {
424
-				return $mount->getMountPoint();
425
-			} else if (substr($path, 0, $rootLength) === $jailRoot . '/') {
426
-				return $mount->getMountPoint() . substr($path, $rootLength);
427
-			} else {
428
-				return null;
429
-			}
430
-		} else {
431
-			return $mount->getMountPoint() . $path;
432
-		}
433
-	}
39
+    /**
40
+     * Creates a Folder that represents a non-existing path
41
+     *
42
+     * @param string $path path
43
+     * @return string non-existing node class
44
+     */
45
+    protected function createNonExistingNode($path) {
46
+        return new NonExistingFolder($this->root, $this->view, $path);
47
+    }
48
+
49
+    /**
50
+     * @param string $path path relative to the folder
51
+     * @return string
52
+     * @throws \OCP\Files\NotPermittedException
53
+     */
54
+    public function getFullPath($path) {
55
+        if (!$this->isValidPath($path)) {
56
+            throw new NotPermittedException('Invalid path');
57
+        }
58
+        return $this->path . $this->normalizePath($path);
59
+    }
60
+
61
+    /**
62
+     * @param string $path
63
+     * @return string
64
+     */
65
+    public function getRelativePath($path) {
66
+        if ($this->path === '' or $this->path === '/') {
67
+            return $this->normalizePath($path);
68
+        }
69
+        if ($path === $this->path) {
70
+            return '/';
71
+        } else if (strpos($path, $this->path . '/') !== 0) {
72
+            return null;
73
+        } else {
74
+            $path = substr($path, strlen($this->path));
75
+            return $this->normalizePath($path);
76
+        }
77
+    }
78
+
79
+    /**
80
+     * check if a node is a (grand-)child of the folder
81
+     *
82
+     * @param \OC\Files\Node\Node $node
83
+     * @return bool
84
+     */
85
+    public function isSubNode($node) {
86
+        return strpos($node->getPath(), $this->path . '/') === 0;
87
+    }
88
+
89
+    /**
90
+     * get the content of this directory
91
+     *
92
+     * @throws \OCP\Files\NotFoundException
93
+     * @return Node[]
94
+     */
95
+    public function getDirectoryListing() {
96
+        $folderContent = $this->view->getDirectoryContent($this->path);
97
+
98
+        return array_map(function (FileInfo $info) {
99
+            if ($info->getMimetype() === 'httpd/unix-directory') {
100
+                return new Folder($this->root, $this->view, $info->getPath(), $info);
101
+            } else {
102
+                return new File($this->root, $this->view, $info->getPath(), $info);
103
+            }
104
+        }, $folderContent);
105
+    }
106
+
107
+    /**
108
+     * @param string $path
109
+     * @param FileInfo $info
110
+     * @return File|Folder
111
+     */
112
+    protected function createNode($path, FileInfo $info = null) {
113
+        if (is_null($info)) {
114
+            $isDir = $this->view->is_dir($path);
115
+        } else {
116
+            $isDir = $info->getType() === FileInfo::TYPE_FOLDER;
117
+        }
118
+        if ($isDir) {
119
+            return new Folder($this->root, $this->view, $path, $info);
120
+        } else {
121
+            return new File($this->root, $this->view, $path, $info);
122
+        }
123
+    }
124
+
125
+    /**
126
+     * Get the node at $path
127
+     *
128
+     * @param string $path
129
+     * @return \OC\Files\Node\Node
130
+     * @throws \OCP\Files\NotFoundException
131
+     */
132
+    public function get($path) {
133
+        return $this->root->get($this->getFullPath($path));
134
+    }
135
+
136
+    /**
137
+     * @param string $path
138
+     * @return bool
139
+     */
140
+    public function nodeExists($path) {
141
+        try {
142
+            $this->get($path);
143
+            return true;
144
+        } catch (NotFoundException $e) {
145
+            return false;
146
+        }
147
+    }
148
+
149
+    /**
150
+     * @param string $path
151
+     * @return \OC\Files\Node\Folder
152
+     * @throws \OCP\Files\NotPermittedException
153
+     */
154
+    public function newFolder($path) {
155
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
156
+            $fullPath = $this->getFullPath($path);
157
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
158
+            $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
159
+            $this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
160
+            $this->view->mkdir($fullPath);
161
+            $node = new Folder($this->root, $this->view, $fullPath);
162
+            $this->root->emit('\OC\Files', 'postWrite', array($node));
163
+            $this->root->emit('\OC\Files', 'postCreate', array($node));
164
+            return $node;
165
+        } else {
166
+            throw new NotPermittedException('No create permission for folder');
167
+        }
168
+    }
169
+
170
+    /**
171
+     * @param string $path
172
+     * @return \OC\Files\Node\File
173
+     * @throws \OCP\Files\NotPermittedException
174
+     */
175
+    public function newFile($path) {
176
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
177
+            $fullPath = $this->getFullPath($path);
178
+            $nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
179
+            $this->root->emit('\OC\Files', 'preWrite', array($nonExisting));
180
+            $this->root->emit('\OC\Files', 'preCreate', array($nonExisting));
181
+            $this->view->touch($fullPath);
182
+            $node = new File($this->root, $this->view, $fullPath);
183
+            $this->root->emit('\OC\Files', 'postWrite', array($node));
184
+            $this->root->emit('\OC\Files', 'postCreate', array($node));
185
+            return $node;
186
+        } else {
187
+            throw new NotPermittedException('No create permission for path');
188
+        }
189
+    }
190
+
191
+    /**
192
+     * search for files with the name matching $query
193
+     *
194
+     * @param string|ISearchOperator $query
195
+     * @return \OC\Files\Node\Node[]
196
+     */
197
+    public function search($query) {
198
+        if (is_string($query)) {
199
+            return $this->searchCommon('search', array('%' . $query . '%'));
200
+        } else {
201
+            return $this->searchCommon('searchQuery', array($query));
202
+        }
203
+    }
204
+
205
+    /**
206
+     * search for files by mimetype
207
+     *
208
+     * @param string $mimetype
209
+     * @return Node[]
210
+     */
211
+    public function searchByMime($mimetype) {
212
+        return $this->searchCommon('searchByMime', array($mimetype));
213
+    }
214
+
215
+    /**
216
+     * search for files by tag
217
+     *
218
+     * @param string|int $tag name or tag id
219
+     * @param string $userId owner of the tags
220
+     * @return Node[]
221
+     */
222
+    public function searchByTag($tag, $userId) {
223
+        return $this->searchCommon('searchByTag', array($tag, $userId));
224
+    }
225
+
226
+    /**
227
+     * @param string $method cache method
228
+     * @param array $args call args
229
+     * @return \OC\Files\Node\Node[]
230
+     */
231
+    private function searchCommon($method, $args) {
232
+        $files = array();
233
+        $rootLength = strlen($this->path);
234
+        $mount = $this->root->getMount($this->path);
235
+        $storage = $mount->getStorage();
236
+        $internalPath = $mount->getInternalPath($this->path);
237
+        $internalPath = rtrim($internalPath, '/');
238
+        if ($internalPath !== '') {
239
+            $internalPath = $internalPath . '/';
240
+        }
241
+        $internalRootLength = strlen($internalPath);
242
+
243
+        $cache = $storage->getCache('');
244
+
245
+        $results = call_user_func_array(array($cache, $method), $args);
246
+        foreach ($results as $result) {
247
+            if ($internalRootLength === 0 or substr($result['path'], 0, $internalRootLength) === $internalPath) {
248
+                $result['internalPath'] = $result['path'];
249
+                $result['path'] = substr($result['path'], $internalRootLength);
250
+                $result['storage'] = $storage;
251
+                $files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
252
+            }
253
+        }
254
+
255
+        $mounts = $this->root->getMountsIn($this->path);
256
+        foreach ($mounts as $mount) {
257
+            $storage = $mount->getStorage();
258
+            if ($storage) {
259
+                $cache = $storage->getCache('');
260
+
261
+                $relativeMountPoint = substr($mount->getMountPoint(), $rootLength);
262
+                $results = call_user_func_array(array($cache, $method), $args);
263
+                foreach ($results as $result) {
264
+                    $result['internalPath'] = $result['path'];
265
+                    $result['path'] = $relativeMountPoint . $result['path'];
266
+                    $result['storage'] = $storage;
267
+                    $files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
268
+                }
269
+            }
270
+        }
271
+
272
+        return array_map(function (FileInfo $file) {
273
+            return $this->createNode($file->getPath(), $file);
274
+        }, $files);
275
+    }
276
+
277
+    /**
278
+     * @param int $id
279
+     * @return \OC\Files\Node\Node[]
280
+     */
281
+    public function getById($id) {
282
+        $mountCache = $this->root->getUserMountCache();
283
+        if (strpos($this->getPath(), '/', 1) > 0) {
284
+            list(, $user) = explode('/', $this->getPath());
285
+        } else {
286
+            $user = null;
287
+        }
288
+        $mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
289
+        $mounts = $this->root->getMountsIn($this->path);
290
+        $mounts[] = $this->root->getMount($this->path);
291
+        /** @var IMountPoint[] $folderMounts */
292
+        $folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
293
+            return $mountPoint->getMountPoint();
294
+        }, $mounts), $mounts);
295
+
296
+        /** @var ICachedMountInfo[] $mountsContainingFile */
297
+        $mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
298
+            return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
299
+        }));
300
+
301
+        if (count($mountsContainingFile) === 0) {
302
+            return [];
303
+        }
304
+
305
+        // we only need to get the cache info once, since all mounts we found point to the same storage
306
+
307
+        $mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()];
308
+        $cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
309
+        if (!$cacheEntry) {
310
+            return [];
311
+        }
312
+        // cache jails will hide the "true" internal path
313
+        $internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
314
+
315
+        $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
316
+            $mount = $folderMounts[$cachedMountInfo->getMountPoint()];
317
+            $pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
318
+            $pathRelativeToMount = ltrim($pathRelativeToMount, '/');
319
+            $absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount;
320
+            return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
321
+                $absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
322
+                \OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
323
+            ));
324
+        }, $mountsContainingFile);
325
+
326
+        return array_filter($nodes, function (Node $node) {
327
+            return $this->getRelativePath($node->getPath());
328
+        });
329
+    }
330
+
331
+    public function getFreeSpace() {
332
+        return $this->view->free_space($this->path);
333
+    }
334
+
335
+    public function delete() {
336
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
337
+            $this->sendHooks(array('preDelete'));
338
+            $fileInfo = $this->getFileInfo();
339
+            $this->view->rmdir($this->path);
340
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
341
+            $this->root->emit('\OC\Files', 'postDelete', array($nonExisting));
342
+            $this->exists = false;
343
+        } else {
344
+            throw new NotPermittedException('No delete permission for path');
345
+        }
346
+    }
347
+
348
+    /**
349
+     * Add a suffix to the name in case the file exists
350
+     *
351
+     * @param string $name
352
+     * @return string
353
+     * @throws NotPermittedException
354
+     */
355
+    public function getNonExistingName($name) {
356
+        $uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
357
+        return trim($this->getRelativePath($uniqueName), '/');
358
+    }
359
+
360
+    /**
361
+     * @param int $limit
362
+     * @param int $offset
363
+     * @return \OCP\Files\Node[]
364
+     */
365
+    public function getRecent($limit, $offset = 0) {
366
+        $mimetypeLoader = \OC::$server->getMimeTypeLoader();
367
+        $mounts = $this->root->getMountsIn($this->path);
368
+        $mounts[] = $this->getMountPoint();
369
+
370
+        $mounts = array_filter($mounts, function (IMountPoint $mount) {
371
+            return $mount->getStorage();
372
+        });
373
+        $storageIds = array_map(function (IMountPoint $mount) {
374
+            return $mount->getStorage()->getCache()->getNumericStorageId();
375
+        }, $mounts);
376
+        /** @var IMountPoint[] $mountMap */
377
+        $mountMap = array_combine($storageIds, $mounts);
378
+        $folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
379
+
380
+        //todo look into options of filtering path based on storage id (only search in files/ for home storage, filter by share root for shared, etc)
381
+
382
+        $builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
383
+        $query = $builder
384
+            ->select('f.*')
385
+            ->from('filecache', 'f')
386
+            ->andWhere($builder->expr()->in('f.storage', $builder->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY)))
387
+            ->andWhere($builder->expr()->orX(
388
+            // handle non empty folders separate
389
+                $builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
390
+                $builder->expr()->eq('f.size', new Literal(0))
391
+            ))
392
+            ->orderBy('f.mtime', 'DESC')
393
+            ->setMaxResults($limit)
394
+            ->setFirstResult($offset);
395
+
396
+        $result = $query->execute()->fetchAll();
397
+
398
+        $files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
399
+            $mount = $mountMap[$entry['storage']];
400
+            $entry['internalPath'] = $entry['path'];
401
+            $entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
402
+            $entry['mimepart'] = $mimetypeLoader->getMimetypeById($entry['mimepart']);
403
+            $path = $this->getAbsolutePath($mount, $entry['path']);
404
+            if (is_null($path)) {
405
+                return null;
406
+            }
407
+            $fileInfo = new \OC\Files\FileInfo($path, $mount->getStorage(), $entry['internalPath'], $entry, $mount);
408
+            return $this->root->createNode($fileInfo->getPath(), $fileInfo);
409
+        }, $result));
410
+
411
+        return array_values(array_filter($files, function (Node $node) {
412
+            $relative = $this->getRelativePath($node->getPath());
413
+            return $relative !== null && $relative !== '/';
414
+        }));
415
+    }
416
+
417
+    private function getAbsolutePath(IMountPoint $mount, $path) {
418
+        $storage = $mount->getStorage();
419
+        if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Jail')) {
420
+            /** @var \OC\Files\Storage\Wrapper\Jail $storage */
421
+            $jailRoot = $storage->getUnjailedPath('');
422
+            $rootLength = strlen($jailRoot) + 1;
423
+            if ($path === $jailRoot) {
424
+                return $mount->getMountPoint();
425
+            } else if (substr($path, 0, $rootLength) === $jailRoot . '/') {
426
+                return $mount->getMountPoint() . substr($path, $rootLength);
427
+            } else {
428
+                return null;
429
+            }
430
+        } else {
431
+            return $mount->getMountPoint() . $path;
432
+        }
433
+    }
434 434
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -55,7 +55,7 @@  discard block
 block discarded – undo
55 55
 		if (!$this->isValidPath($path)) {
56 56
 			throw new NotPermittedException('Invalid path');
57 57
 		}
58
-		return $this->path . $this->normalizePath($path);
58
+		return $this->path.$this->normalizePath($path);
59 59
 	}
60 60
 
61 61
 	/**
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
 		}
69 69
 		if ($path === $this->path) {
70 70
 			return '/';
71
-		} else if (strpos($path, $this->path . '/') !== 0) {
71
+		} else if (strpos($path, $this->path.'/') !== 0) {
72 72
 			return null;
73 73
 		} else {
74 74
 			$path = substr($path, strlen($this->path));
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 	 * @return bool
84 84
 	 */
85 85
 	public function isSubNode($node) {
86
-		return strpos($node->getPath(), $this->path . '/') === 0;
86
+		return strpos($node->getPath(), $this->path.'/') === 0;
87 87
 	}
88 88
 
89 89
 	/**
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
 	public function getDirectoryListing() {
96 96
 		$folderContent = $this->view->getDirectoryContent($this->path);
97 97
 
98
-		return array_map(function (FileInfo $info) {
98
+		return array_map(function(FileInfo $info) {
99 99
 			if ($info->getMimetype() === 'httpd/unix-directory') {
100 100
 				return new Folder($this->root, $this->view, $info->getPath(), $info);
101 101
 			} else {
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
 	 */
197 197
 	public function search($query) {
198 198
 		if (is_string($query)) {
199
-			return $this->searchCommon('search', array('%' . $query . '%'));
199
+			return $this->searchCommon('search', array('%'.$query.'%'));
200 200
 		} else {
201 201
 			return $this->searchCommon('searchQuery', array($query));
202 202
 		}
@@ -236,7 +236,7 @@  discard block
 block discarded – undo
236 236
 		$internalPath = $mount->getInternalPath($this->path);
237 237
 		$internalPath = rtrim($internalPath, '/');
238 238
 		if ($internalPath !== '') {
239
-			$internalPath = $internalPath . '/';
239
+			$internalPath = $internalPath.'/';
240 240
 		}
241 241
 		$internalRootLength = strlen($internalPath);
242 242
 
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
 				$result['internalPath'] = $result['path'];
249 249
 				$result['path'] = substr($result['path'], $internalRootLength);
250 250
 				$result['storage'] = $storage;
251
-				$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
251
+				$files[] = new \OC\Files\FileInfo($this->path.'/'.$result['path'], $storage, $result['internalPath'], $result, $mount);
252 252
 			}
253 253
 		}
254 254
 
@@ -262,14 +262,14 @@  discard block
 block discarded – undo
262 262
 				$results = call_user_func_array(array($cache, $method), $args);
263 263
 				foreach ($results as $result) {
264 264
 					$result['internalPath'] = $result['path'];
265
-					$result['path'] = $relativeMountPoint . $result['path'];
265
+					$result['path'] = $relativeMountPoint.$result['path'];
266 266
 					$result['storage'] = $storage;
267
-					$files[] = new \OC\Files\FileInfo($this->path . '/' . $result['path'], $storage, $result['internalPath'], $result, $mount);
267
+					$files[] = new \OC\Files\FileInfo($this->path.'/'.$result['path'], $storage, $result['internalPath'], $result, $mount);
268 268
 				}
269 269
 			}
270 270
 		}
271 271
 
272
-		return array_map(function (FileInfo $file) {
272
+		return array_map(function(FileInfo $file) {
273 273
 			return $this->createNode($file->getPath(), $file);
274 274
 		}, $files);
275 275
 	}
@@ -285,16 +285,16 @@  discard block
 block discarded – undo
285 285
 		} else {
286 286
 			$user = null;
287 287
 		}
288
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
288
+		$mountsContainingFile = $mountCache->getMountsForFileId((int) $id, $user);
289 289
 		$mounts = $this->root->getMountsIn($this->path);
290 290
 		$mounts[] = $this->root->getMount($this->path);
291 291
 		/** @var IMountPoint[] $folderMounts */
292
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
292
+		$folderMounts = array_combine(array_map(function(IMountPoint $mountPoint) {
293 293
 			return $mountPoint->getMountPoint();
294 294
 		}, $mounts), $mounts);
295 295
 
296 296
 		/** @var ICachedMountInfo[] $mountsContainingFile */
297
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
297
+		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function(ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
298 298
 			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
299 299
 		}));
300 300
 
@@ -305,25 +305,25 @@  discard block
 block discarded – undo
305 305
 		// we only need to get the cache info once, since all mounts we found point to the same storage
306 306
 
307 307
 		$mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()];
308
-		$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
308
+		$cacheEntry = $mount->getStorage()->getCache()->get((int) $id);
309 309
 		if (!$cacheEntry) {
310 310
 			return [];
311 311
 		}
312 312
 		// cache jails will hide the "true" internal path
313
-		$internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
313
+		$internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath().'/'.$cacheEntry->getPath(), '/');
314 314
 
315
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
315
+		$nodes = array_map(function(ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
316 316
 			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
317 317
 			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
318 318
 			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
319
-			$absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount;
319
+			$absolutePath = $cachedMountInfo->getMountPoint().$pathRelativeToMount;
320 320
 			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
321 321
 				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
322 322
 				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
323 323
 			));
324 324
 		}, $mountsContainingFile);
325 325
 
326
-		return array_filter($nodes, function (Node $node) {
326
+		return array_filter($nodes, function(Node $node) {
327 327
 			return $this->getRelativePath($node->getPath());
328 328
 		});
329 329
 	}
@@ -367,10 +367,10 @@  discard block
 block discarded – undo
367 367
 		$mounts = $this->root->getMountsIn($this->path);
368 368
 		$mounts[] = $this->getMountPoint();
369 369
 
370
-		$mounts = array_filter($mounts, function (IMountPoint $mount) {
370
+		$mounts = array_filter($mounts, function(IMountPoint $mount) {
371 371
 			return $mount->getStorage();
372 372
 		});
373
-		$storageIds = array_map(function (IMountPoint $mount) {
373
+		$storageIds = array_map(function(IMountPoint $mount) {
374 374
 			return $mount->getStorage()->getCache()->getNumericStorageId();
375 375
 		}, $mounts);
376 376
 		/** @var IMountPoint[] $mountMap */
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
 
396 396
 		$result = $query->execute()->fetchAll();
397 397
 
398
-		$files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
398
+		$files = array_filter(array_map(function(array $entry) use ($mountMap, $mimetypeLoader) {
399 399
 			$mount = $mountMap[$entry['storage']];
400 400
 			$entry['internalPath'] = $entry['path'];
401 401
 			$entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
 			return $this->root->createNode($fileInfo->getPath(), $fileInfo);
409 409
 		}, $result));
410 410
 
411
-		return array_values(array_filter($files, function (Node $node) {
411
+		return array_values(array_filter($files, function(Node $node) {
412 412
 			$relative = $this->getRelativePath($node->getPath());
413 413
 			return $relative !== null && $relative !== '/';
414 414
 		}));
@@ -422,13 +422,13 @@  discard block
 block discarded – undo
422 422
 			$rootLength = strlen($jailRoot) + 1;
423 423
 			if ($path === $jailRoot) {
424 424
 				return $mount->getMountPoint();
425
-			} else if (substr($path, 0, $rootLength) === $jailRoot . '/') {
426
-				return $mount->getMountPoint() . substr($path, $rootLength);
425
+			} else if (substr($path, 0, $rootLength) === $jailRoot.'/') {
426
+				return $mount->getMountPoint().substr($path, $rootLength);
427 427
 			} else {
428 428
 				return null;
429 429
 			}
430 430
 		} else {
431
-			return $mount->getMountPoint() . $path;
431
+			return $mount->getMountPoint().$path;
432 432
 		}
433 433
 	}
434 434
 }
Please login to merge, or discard this patch.