Passed
Push — master ( 37146c...328fbd )
by Roeland
18:50 queued 08:45
created
apps/files/lib/Service/OwnershipTransferService.php 1 patch
Indentation   +265 added lines, -265 removed lines patch added patch discarded remove patch
@@ -52,270 +52,270 @@
 block discarded – undo
52 52
 
53 53
 class OwnershipTransferService {
54 54
 
55
-	/** @var IEncryptionManager */
56
-	private $encryptionManager;
57
-
58
-	/** @var IShareManager */
59
-	private $shareManager;
60
-
61
-	/** @var IMountManager */
62
-	private $mountManager;
63
-
64
-	public function __construct(IEncryptionManager $manager,
65
-								IShareManager $shareManager,
66
-								IMountManager $mountManager) {
67
-		$this->encryptionManager = $manager;
68
-		$this->shareManager = $shareManager;
69
-		$this->mountManager = $mountManager;
70
-	}
71
-
72
-	/**
73
-	 * @param IUser $sourceUser
74
-	 * @param IUser $destinationUser
75
-	 * @param string $path
76
-	 *
77
-	 * @param OutputInterface|null $output
78
-	 * @param bool $move
79
-	 * @throws TransferOwnershipException
80
-	 * @throws \OC\User\NoUserException
81
-	 */
82
-	public function transfer(IUser $sourceUser,
83
-							 IUser $destinationUser,
84
-							 string $path,
85
-							 ?OutputInterface $output = null,
86
-							 bool $move = false,
87
-							 bool $firstLogin = false): void {
88
-		$output = $output ?? new NullOutput();
89
-		$sourceUid = $sourceUser->getUID();
90
-		$destinationUid = $destinationUser->getUID();
91
-		$sourcePath = rtrim($sourceUid . '/files/' . $path, '/');
92
-
93
-		// target user has to be ready
94
-		if ($destinationUser->getLastLogin() === 0 || !$this->encryptionManager->isReadyForUser($destinationUid)) {
95
-			throw new TransferOwnershipException("The target user is not ready to accept files. The user has at least to have logged in once.", 2);
96
-		}
97
-
98
-		// setup filesystem
99
-		Filesystem::initMountPoints($sourceUid);
100
-		Filesystem::initMountPoints($destinationUid);
101
-
102
-		$view = new View();
103
-
104
-		if ($move) {
105
-			$finalTarget = "$destinationUid/files/";
106
-		} else {
107
-			$date = date('Y-m-d H-i-s');
108
-
109
-			// Remove some characters which are prone to cause errors
110
-			$cleanUserName = str_replace(['\\', '/', ':', '.', '?', '#', '\'', '"'], '-', $sourceUser->getDisplayName());
111
-			// Replace multiple dashes with one dash
112
-			$cleanUserName = preg_replace('/-{2,}/s', '-', $cleanUserName);
113
-			$cleanUserName = $cleanUserName ?: $sourceUid;
114
-
115
-			$finalTarget = "$destinationUid/files/transferred from $cleanUserName on $date";
116
-			try {
117
-				$view->verifyPath(dirname($finalTarget), basename($finalTarget));
118
-			} catch (InvalidPathException $e) {
119
-				$finalTarget = "$destinationUid/files/transferred from $sourceUid on $date";
120
-			}
121
-		}
122
-
123
-		if (!($view->is_dir($sourcePath) || $view->is_file($sourcePath))) {
124
-			throw new TransferOwnershipException("Unknown path provided: $path", 1);
125
-		}
126
-
127
-		if ($move && (
128
-				!$view->is_dir($finalTarget) || (
129
-					!$firstLogin &&
130
-					count($view->getDirectoryContent($finalTarget)) > 0
131
-				)
132
-			)
133
-		) {
134
-			throw new TransferOwnershipException("Destination path does not exists or is not empty", 1);
135
-		}
136
-
137
-
138
-		// analyse source folder
139
-		$this->analyse(
140
-			$sourceUid,
141
-			$destinationUid,
142
-			$sourcePath,
143
-			$view,
144
-			$output
145
-		);
146
-
147
-		// collect all the shares
148
-		$shares = $this->collectUsersShares(
149
-			$sourceUid,
150
-			$output
151
-		);
152
-
153
-		// transfer the files
154
-		$this->transferFiles(
155
-			$sourceUid,
156
-			$sourcePath,
157
-			$finalTarget,
158
-			$view,
159
-			$output
160
-		);
161
-
162
-		// restore the shares
163
-		$this->restoreShares(
164
-			$sourceUid,
165
-			$destinationUid,
166
-			$shares,
167
-			$output
168
-		);
169
-	}
170
-
171
-	private function walkFiles(View $view, $path, Closure $callBack) {
172
-		foreach ($view->getDirectoryContent($path) as $fileInfo) {
173
-			if (!$callBack($fileInfo)) {
174
-				return;
175
-			}
176
-			if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
177
-				$this->walkFiles($view, $fileInfo->getPath(), $callBack);
178
-			}
179
-		}
180
-	}
181
-
182
-	/**
183
-	 * @param OutputInterface $output
184
-	 *
185
-	 * @throws \Exception
186
-	 */
187
-	protected function analyse(string $sourceUid,
188
-							   string $destinationUid,
189
-							   string $sourcePath,
190
-							   View $view,
191
-							   OutputInterface $output): void {
192
-		$output->writeln('Validating quota');
193
-		$size = $view->getFileInfo($sourcePath, false)->getSize(false);
194
-		$freeSpace = $view->free_space($destinationUid . '/files/');
195
-		if ($size > $freeSpace) {
196
-			$output->writeln('<error>Target user does not have enough free space available.</error>');
197
-			throw new \Exception('Execution terminated.');
198
-		}
199
-
200
-		$output->writeln("Analysing files of $sourceUid ...");
201
-		$progress = new ProgressBar($output);
202
-		$progress->start();
203
-
204
-		$encryptedFiles = [];
205
-		$this->walkFiles($view, $sourcePath,
206
-			function (FileInfo $fileInfo) use ($progress) {
207
-				if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
208
-					// only analyze into folders from main storage,
209
-					if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
210
-						return false;
211
-					}
212
-					return true;
213
-				}
214
-				$progress->advance();
215
-				if ($fileInfo->isEncrypted()) {
216
-					$encryptedFiles[] = $fileInfo;
217
-				}
218
-				return true;
219
-			});
220
-		$progress->finish();
221
-		$output->writeln('');
222
-
223
-		// no file is allowed to be encrypted
224
-		if (!empty($encryptedFiles)) {
225
-			$output->writeln("<error>Some files are encrypted - please decrypt them first.</error>");
226
-			foreach ($encryptedFiles as $encryptedFile) {
227
-				/** @var FileInfo $encryptedFile */
228
-				$output->writeln("  " . $encryptedFile->getPath());
229
-			}
230
-			throw new \Exception('Execution terminated.');
231
-		}
232
-	}
233
-
234
-	private function collectUsersShares(string $sourceUid,
235
-										OutputInterface $output): array {
236
-		$output->writeln("Collecting all share information for files and folders of $sourceUid ...");
237
-
238
-		$shares = [];
239
-		$progress = new ProgressBar($output);
240
-		foreach ([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_ROOM] as $shareType) {
241
-			$offset = 0;
242
-			while (true) {
243
-				$sharePage = $this->shareManager->getSharesBy($sourceUid, $shareType, null, true, 50, $offset);
244
-				$progress->advance(count($sharePage));
245
-				if (empty($sharePage)) {
246
-					break;
247
-				}
248
-				$shares = array_merge($shares, $sharePage);
249
-				$offset += 50;
250
-			}
251
-		}
252
-
253
-		$progress->finish();
254
-		$output->writeln('');
255
-		return $shares;
256
-	}
257
-
258
-	/**
259
-	 * @throws TransferOwnershipException
260
-	 */
261
-	protected function transferFiles(string $sourceUid,
262
-									 string $sourcePath,
263
-									 string $finalTarget,
264
-									 View $view,
265
-									 OutputInterface $output): void {
266
-		$output->writeln("Transferring files to $finalTarget ...");
267
-
268
-		// This change will help user to transfer the folder specified using --path option.
269
-		// Else only the content inside folder is transferred which is not correct.
270
-		if ($sourcePath !== "$sourceUid/files") {
271
-			$view->mkdir($finalTarget);
272
-			$finalTarget = $finalTarget . '/' . basename($sourcePath);
273
-		}
274
-		if ($view->rename($sourcePath, $finalTarget) === false) {
275
-			throw new TransferOwnershipException("Could not transfer files.", 1);
276
-		}
277
-		if (!is_dir("$sourceUid/files")) {
278
-			// because the files folder is moved away we need to recreate it
279
-			$view->mkdir("$sourceUid/files");
280
-		}
281
-	}
282
-
283
-	private function restoreShares(string $sourceUid,
284
-								   string $destinationUid,
285
-								   array $shares,
286
-								   OutputInterface $output) {
287
-		$output->writeln("Restoring shares ...");
288
-		$progress = new ProgressBar($output, count($shares));
289
-
290
-		foreach ($shares as $share) {
291
-			try {
292
-				if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
293
-					$share->getSharedWith() === $destinationUid) {
294
-					// Unmount the shares before deleting, so we don't try to get the storage later on.
295
-					$shareMountPoint = $this->mountManager->find('/' . $destinationUid . '/files' . $share->getTarget());
296
-					if ($shareMountPoint) {
297
-						$this->mountManager->removeMount($shareMountPoint->getMountPoint());
298
-					}
299
-					$this->shareManager->deleteShare($share);
300
-				} else {
301
-					if ($share->getShareOwner() === $sourceUid) {
302
-						$share->setShareOwner($destinationUid);
303
-					}
304
-					if ($share->getSharedBy() === $sourceUid) {
305
-						$share->setSharedBy($destinationUid);
306
-					}
307
-
308
-					$this->shareManager->updateShare($share);
309
-				}
310
-			} catch (\OCP\Files\NotFoundException $e) {
311
-				$output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
312
-			} catch (\Throwable $e) {
313
-				$output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getTraceAsString() . '</error>');
314
-			}
315
-			$progress->advance();
316
-		}
317
-		$progress->finish();
318
-		$output->writeln('');
319
-	}
55
+    /** @var IEncryptionManager */
56
+    private $encryptionManager;
57
+
58
+    /** @var IShareManager */
59
+    private $shareManager;
60
+
61
+    /** @var IMountManager */
62
+    private $mountManager;
63
+
64
+    public function __construct(IEncryptionManager $manager,
65
+                                IShareManager $shareManager,
66
+                                IMountManager $mountManager) {
67
+        $this->encryptionManager = $manager;
68
+        $this->shareManager = $shareManager;
69
+        $this->mountManager = $mountManager;
70
+    }
71
+
72
+    /**
73
+     * @param IUser $sourceUser
74
+     * @param IUser $destinationUser
75
+     * @param string $path
76
+     *
77
+     * @param OutputInterface|null $output
78
+     * @param bool $move
79
+     * @throws TransferOwnershipException
80
+     * @throws \OC\User\NoUserException
81
+     */
82
+    public function transfer(IUser $sourceUser,
83
+                                IUser $destinationUser,
84
+                                string $path,
85
+                             ?OutputInterface $output = null,
86
+                                bool $move = false,
87
+                                bool $firstLogin = false): void {
88
+        $output = $output ?? new NullOutput();
89
+        $sourceUid = $sourceUser->getUID();
90
+        $destinationUid = $destinationUser->getUID();
91
+        $sourcePath = rtrim($sourceUid . '/files/' . $path, '/');
92
+
93
+        // target user has to be ready
94
+        if ($destinationUser->getLastLogin() === 0 || !$this->encryptionManager->isReadyForUser($destinationUid)) {
95
+            throw new TransferOwnershipException("The target user is not ready to accept files. The user has at least to have logged in once.", 2);
96
+        }
97
+
98
+        // setup filesystem
99
+        Filesystem::initMountPoints($sourceUid);
100
+        Filesystem::initMountPoints($destinationUid);
101
+
102
+        $view = new View();
103
+
104
+        if ($move) {
105
+            $finalTarget = "$destinationUid/files/";
106
+        } else {
107
+            $date = date('Y-m-d H-i-s');
108
+
109
+            // Remove some characters which are prone to cause errors
110
+            $cleanUserName = str_replace(['\\', '/', ':', '.', '?', '#', '\'', '"'], '-', $sourceUser->getDisplayName());
111
+            // Replace multiple dashes with one dash
112
+            $cleanUserName = preg_replace('/-{2,}/s', '-', $cleanUserName);
113
+            $cleanUserName = $cleanUserName ?: $sourceUid;
114
+
115
+            $finalTarget = "$destinationUid/files/transferred from $cleanUserName on $date";
116
+            try {
117
+                $view->verifyPath(dirname($finalTarget), basename($finalTarget));
118
+            } catch (InvalidPathException $e) {
119
+                $finalTarget = "$destinationUid/files/transferred from $sourceUid on $date";
120
+            }
121
+        }
122
+
123
+        if (!($view->is_dir($sourcePath) || $view->is_file($sourcePath))) {
124
+            throw new TransferOwnershipException("Unknown path provided: $path", 1);
125
+        }
126
+
127
+        if ($move && (
128
+                !$view->is_dir($finalTarget) || (
129
+                    !$firstLogin &&
130
+                    count($view->getDirectoryContent($finalTarget)) > 0
131
+                )
132
+            )
133
+        ) {
134
+            throw new TransferOwnershipException("Destination path does not exists or is not empty", 1);
135
+        }
136
+
137
+
138
+        // analyse source folder
139
+        $this->analyse(
140
+            $sourceUid,
141
+            $destinationUid,
142
+            $sourcePath,
143
+            $view,
144
+            $output
145
+        );
146
+
147
+        // collect all the shares
148
+        $shares = $this->collectUsersShares(
149
+            $sourceUid,
150
+            $output
151
+        );
152
+
153
+        // transfer the files
154
+        $this->transferFiles(
155
+            $sourceUid,
156
+            $sourcePath,
157
+            $finalTarget,
158
+            $view,
159
+            $output
160
+        );
161
+
162
+        // restore the shares
163
+        $this->restoreShares(
164
+            $sourceUid,
165
+            $destinationUid,
166
+            $shares,
167
+            $output
168
+        );
169
+    }
170
+
171
+    private function walkFiles(View $view, $path, Closure $callBack) {
172
+        foreach ($view->getDirectoryContent($path) as $fileInfo) {
173
+            if (!$callBack($fileInfo)) {
174
+                return;
175
+            }
176
+            if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
177
+                $this->walkFiles($view, $fileInfo->getPath(), $callBack);
178
+            }
179
+        }
180
+    }
181
+
182
+    /**
183
+     * @param OutputInterface $output
184
+     *
185
+     * @throws \Exception
186
+     */
187
+    protected function analyse(string $sourceUid,
188
+                                string $destinationUid,
189
+                                string $sourcePath,
190
+                                View $view,
191
+                                OutputInterface $output): void {
192
+        $output->writeln('Validating quota');
193
+        $size = $view->getFileInfo($sourcePath, false)->getSize(false);
194
+        $freeSpace = $view->free_space($destinationUid . '/files/');
195
+        if ($size > $freeSpace) {
196
+            $output->writeln('<error>Target user does not have enough free space available.</error>');
197
+            throw new \Exception('Execution terminated.');
198
+        }
199
+
200
+        $output->writeln("Analysing files of $sourceUid ...");
201
+        $progress = new ProgressBar($output);
202
+        $progress->start();
203
+
204
+        $encryptedFiles = [];
205
+        $this->walkFiles($view, $sourcePath,
206
+            function (FileInfo $fileInfo) use ($progress) {
207
+                if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
208
+                    // only analyze into folders from main storage,
209
+                    if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
210
+                        return false;
211
+                    }
212
+                    return true;
213
+                }
214
+                $progress->advance();
215
+                if ($fileInfo->isEncrypted()) {
216
+                    $encryptedFiles[] = $fileInfo;
217
+                }
218
+                return true;
219
+            });
220
+        $progress->finish();
221
+        $output->writeln('');
222
+
223
+        // no file is allowed to be encrypted
224
+        if (!empty($encryptedFiles)) {
225
+            $output->writeln("<error>Some files are encrypted - please decrypt them first.</error>");
226
+            foreach ($encryptedFiles as $encryptedFile) {
227
+                /** @var FileInfo $encryptedFile */
228
+                $output->writeln("  " . $encryptedFile->getPath());
229
+            }
230
+            throw new \Exception('Execution terminated.');
231
+        }
232
+    }
233
+
234
+    private function collectUsersShares(string $sourceUid,
235
+                                        OutputInterface $output): array {
236
+        $output->writeln("Collecting all share information for files and folders of $sourceUid ...");
237
+
238
+        $shares = [];
239
+        $progress = new ProgressBar($output);
240
+        foreach ([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_ROOM] as $shareType) {
241
+            $offset = 0;
242
+            while (true) {
243
+                $sharePage = $this->shareManager->getSharesBy($sourceUid, $shareType, null, true, 50, $offset);
244
+                $progress->advance(count($sharePage));
245
+                if (empty($sharePage)) {
246
+                    break;
247
+                }
248
+                $shares = array_merge($shares, $sharePage);
249
+                $offset += 50;
250
+            }
251
+        }
252
+
253
+        $progress->finish();
254
+        $output->writeln('');
255
+        return $shares;
256
+    }
257
+
258
+    /**
259
+     * @throws TransferOwnershipException
260
+     */
261
+    protected function transferFiles(string $sourceUid,
262
+                                        string $sourcePath,
263
+                                        string $finalTarget,
264
+                                        View $view,
265
+                                        OutputInterface $output): void {
266
+        $output->writeln("Transferring files to $finalTarget ...");
267
+
268
+        // This change will help user to transfer the folder specified using --path option.
269
+        // Else only the content inside folder is transferred which is not correct.
270
+        if ($sourcePath !== "$sourceUid/files") {
271
+            $view->mkdir($finalTarget);
272
+            $finalTarget = $finalTarget . '/' . basename($sourcePath);
273
+        }
274
+        if ($view->rename($sourcePath, $finalTarget) === false) {
275
+            throw new TransferOwnershipException("Could not transfer files.", 1);
276
+        }
277
+        if (!is_dir("$sourceUid/files")) {
278
+            // because the files folder is moved away we need to recreate it
279
+            $view->mkdir("$sourceUid/files");
280
+        }
281
+    }
282
+
283
+    private function restoreShares(string $sourceUid,
284
+                                    string $destinationUid,
285
+                                    array $shares,
286
+                                    OutputInterface $output) {
287
+        $output->writeln("Restoring shares ...");
288
+        $progress = new ProgressBar($output, count($shares));
289
+
290
+        foreach ($shares as $share) {
291
+            try {
292
+                if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
293
+                    $share->getSharedWith() === $destinationUid) {
294
+                    // Unmount the shares before deleting, so we don't try to get the storage later on.
295
+                    $shareMountPoint = $this->mountManager->find('/' . $destinationUid . '/files' . $share->getTarget());
296
+                    if ($shareMountPoint) {
297
+                        $this->mountManager->removeMount($shareMountPoint->getMountPoint());
298
+                    }
299
+                    $this->shareManager->deleteShare($share);
300
+                } else {
301
+                    if ($share->getShareOwner() === $sourceUid) {
302
+                        $share->setShareOwner($destinationUid);
303
+                    }
304
+                    if ($share->getSharedBy() === $sourceUid) {
305
+                        $share->setSharedBy($destinationUid);
306
+                    }
307
+
308
+                    $this->shareManager->updateShare($share);
309
+                }
310
+            } catch (\OCP\Files\NotFoundException $e) {
311
+                $output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
312
+            } catch (\Throwable $e) {
313
+                $output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getTraceAsString() . '</error>');
314
+            }
315
+            $progress->advance();
316
+        }
317
+        $progress->finish();
318
+        $output->writeln('');
319
+    }
320 320
 
321 321
 }
Please login to merge, or discard this patch.
apps/files/lib/Notification/Notifier.php 1 patch
Indentation   +265 added lines, -265 removed lines patch added patch discarded remove patch
@@ -43,269 +43,269 @@
 block discarded – undo
43 43
 
44 44
 class Notifier implements INotifier, IDismissableNotifier {
45 45
 
46
-	/** @var IFactory */
47
-	protected $l10nFactory;
48
-
49
-	/** @var IURLGenerator */
50
-	protected $urlGenerator;
51
-	/** @var TransferOwnershipMapper */
52
-	private $mapper;
53
-	/** @var IManager */
54
-	private $notificationManager;
55
-	/** @var IUserManager */
56
-	private $userManager;
57
-	/** @var ITimeFactory */
58
-	private $timeFactory;
59
-
60
-	public function __construct(IFactory $l10nFactory,
61
-								IURLGenerator $urlGenerator,
62
-								TransferOwnershipMapper $mapper,
63
-								IManager $notificationManager,
64
-								IUserManager $userManager,
65
-								ITimeFactory $timeFactory) {
66
-		$this->l10nFactory = $l10nFactory;
67
-		$this->urlGenerator = $urlGenerator;
68
-		$this->mapper = $mapper;
69
-		$this->notificationManager = $notificationManager;
70
-		$this->userManager = $userManager;
71
-		$this->timeFactory = $timeFactory;
72
-	}
73
-
74
-	public function getID(): string {
75
-		return 'files';
76
-	}
77
-
78
-	public function getName(): string {
79
-		return $this->l10nFactory->get('files')->t('Files');
80
-	}
81
-
82
-	/**
83
-	 * @param INotification $notification
84
-	 * @param string $languageCode The code of the language that should be used to prepare the notification
85
-	 * @return INotification
86
-	 * @throws \InvalidArgumentException When the notification was not prepared by a notifier
87
-	 */
88
-	public function prepare(INotification $notification, string $languageCode): INotification {
89
-		if ($notification->getApp() !== 'files') {
90
-			throw new \InvalidArgumentException('Unhandled app');
91
-		}
92
-
93
-		if ($notification->getSubject() === 'transferownershipRequest') {
94
-			return $this->handleTransferownershipRequest($notification, $languageCode);
95
-		}
96
-		if ($notification->getSubject() === 'transferOwnershipFailedSource') {
97
-			return $this->handleTransferOwnershipFailedSource($notification, $languageCode);
98
-		}
99
-		if ($notification->getSubject() === 'transferOwnershipFailedTarget') {
100
-			return $this->handleTransferOwnershipFailedTarget($notification, $languageCode);
101
-		}
102
-		if ($notification->getSubject() === 'transferOwnershipDoneSource') {
103
-			return $this->handleTransferOwnershipDoneSource($notification, $languageCode);
104
-		}
105
-		if ($notification->getSubject() === 'transferOwnershipDoneTarget') {
106
-			return $this->handleTransferOwnershipDoneTarget($notification, $languageCode);
107
-		}
108
-
109
-		throw new \InvalidArgumentException('Unhandled subject');
110
-	}
111
-
112
-	public function handleTransferownershipRequest(INotification $notification, string $languageCode): INotification {
113
-		$l = $this->l10nFactory->get('files', $languageCode);
114
-		$id = $notification->getObjectId();
115
-		$param = $notification->getSubjectParameters();
116
-
117
-		$approveAction = $notification->createAction()
118
-			->setParsedLabel($l->t('Accept'))
119
-			->setPrimary(true)
120
-			->setLink(
121
-				$this->urlGenerator->getAbsoluteURL(
122
-					$this->urlGenerator->linkTo(
123
-						'',
124
-						'ocs/v2.php/apps/files/api/v1/transferownership/' . $id
125
-					)
126
-				),
127
-				IAction::TYPE_POST
128
-			);
129
-
130
-		$disapproveAction = $notification->createAction()
131
-			->setParsedLabel($l->t('Reject'))
132
-			->setPrimary(false)
133
-			->setLink(
134
-				$this->urlGenerator->getAbsoluteURL(
135
-					$this->urlGenerator->linkTo(
136
-						'',
137
-						'ocs/v2.php/apps/files/api/v1/transferownership/' . $id
138
-					)
139
-				),
140
-				IAction::TYPE_DELETE
141
-			);
142
-
143
-		$sourceUser = $this->getUser($param['sourceUser']);
144
-		$notification->addParsedAction($approveAction)
145
-			->addParsedAction($disapproveAction)
146
-			->setRichSubject(
147
-				$l->t('Incoming ownership transfer from {user}'),
148
-				[
149
-					'user' => [
150
-						'type' => 'user',
151
-						'id' => $sourceUser->getUID(),
152
-						'name' => $sourceUser->getDisplayName(),
153
-					],
154
-				])
155
-			->setParsedSubject(str_replace('{user}', $sourceUser->getDisplayName(), $l->t('Incoming ownership transfer from {user}')))
156
-			->setRichMessage(
157
-				$l->t("Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour."),
158
-				[
159
-					'path' => [
160
-						'type' => 'highlight',
161
-						'id' => $param['targetUser'] . '::' . $param['nodeName'],
162
-						'name' => $param['nodeName'],
163
-					]
164
-				])
165
-			->setParsedMessage(str_replace('{path}', $param['nodeName'], $l->t("Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour.")));
166
-
167
-		return $notification;
168
-	}
169
-
170
-	public function handleTransferOwnershipFailedSource(INotification $notification,  string $languageCode): INotification {
171
-		$l = $this->l10nFactory->get('files', $languageCode);
172
-		$param = $notification->getSubjectParameters();
173
-
174
-		$targetUser = $this->getUser($param['targetUser']);
175
-		$notification->setRichSubject($l->t('Ownership transfer failed'))
176
-			->setParsedSubject($l->t('Ownership transfer failed'))
177
-
178
-			->setRichMessage(
179
-				$l->t('Your ownership transfer of {path} to {user} failed.'),
180
-				[
181
-					'path' => [
182
-						'type' => 'highlight',
183
-						'id' => $param['targetUser'] . '::' . $param['nodeName'],
184
-						'name' => $param['nodeName'],
185
-					],
186
-					'user' => [
187
-						'type' => 'user',
188
-						'id' => $targetUser->getUID(),
189
-						'name' => $targetUser->getDisplayName(),
190
-					],
191
-				])
192
-			->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $targetUser->getDisplayName()], $l->t('Your ownership transfer of {path} to {user} failed.')));
193
-		return $notification;
194
-	}
195
-
196
-	public function handleTransferOwnershipFailedTarget(INotification $notification,  string $languageCode): INotification {
197
-		$l = $this->l10nFactory->get('files', $languageCode);
198
-		$param = $notification->getSubjectParameters();
199
-
200
-		$sourceUser = $this->getUser($param['sourceUser']);
201
-		$notification->setRichSubject($l->t('Ownership transfer failed'))
202
-			->setParsedSubject($l->t('Ownership transfer failed'))
203
-
204
-			->setRichMessage(
205
-				$l->t('The ownership transfer of {path} from {user} failed.'),
206
-				[
207
-					'path' => [
208
-						'type' => 'highlight',
209
-						'id' => $param['sourceUser'] . '::' . $param['nodeName'],
210
-						'name' => $param['nodeName'],
211
-					],
212
-					'user' => [
213
-						'type' => 'user',
214
-						'id' => $sourceUser->getUID(),
215
-						'name' => $sourceUser->getDisplayName(),
216
-					],
217
-				])
218
-			->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $sourceUser->getDisplayName()], $l->t('The ownership transfer of {path} from {user} failed.')));
219
-
220
-		return $notification;
221
-	}
222
-
223
-	public function handleTransferOwnershipDoneSource(INotification $notification,  string $languageCode): INotification {
224
-		$l = $this->l10nFactory->get('files', $languageCode);
225
-		$param = $notification->getSubjectParameters();
226
-
227
-		$targetUser = $this->getUser($param['targetUser']);
228
-		$notification->setRichSubject($l->t('Ownership transfer done'))
229
-			->setParsedSubject($l->t('Ownership transfer done'))
230
-
231
-			->setRichMessage(
232
-				$l->t('Your ownership transfer of {path} to {user} has completed.'),
233
-				[
234
-					'path' => [
235
-						'type' => 'highlight',
236
-						'id' => $param['targetUser'] . '::' . $param['nodeName'],
237
-						'name' => $param['nodeName'],
238
-					],
239
-					'user' => [
240
-						'type' => 'user',
241
-						'id' => $targetUser->getUID(),
242
-						'name' => $targetUser->getDisplayName(),
243
-					],
244
-				])
245
-			->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $targetUser->getDisplayName()], $l->t('Your ownership transfer of {path} to {user} has completed.')));
246
-
247
-		return $notification;
248
-	}
249
-
250
-	public function handleTransferOwnershipDoneTarget(INotification $notification,  string $languageCode): INotification {
251
-		$l = $this->l10nFactory->get('files', $languageCode);
252
-		$param = $notification->getSubjectParameters();
253
-
254
-		$sourceUser = $this->getUser($param['sourceUser']);
255
-		$notification->setRichSubject($l->t('Ownership transfer done'))
256
-			->setParsedSubject($l->t('Ownership transfer done'))
257
-
258
-			->setRichMessage(
259
-				$l->t('The ownership transfer of {path} from {user} has completed.'),
260
-				[
261
-					'path' => [
262
-						'type' => 'highlight',
263
-						'id' => $param['sourceUser'] . '::' . $param['nodeName'],
264
-						'name' => $param['nodeName'],
265
-					],
266
-					'user' => [
267
-						'type' => 'user',
268
-						'id' => $sourceUser->getUID(),
269
-						'name' => $sourceUser->getDisplayName(),
270
-					],
271
-				])
272
-			->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $sourceUser->getDisplayName()], $l->t('The ownership transfer of {path} from {user} has completed.')));
273
-
274
-		return $notification;
275
-	}
276
-
277
-	public function dismissNotification(INotification $notification): void {
278
-		if ($notification->getApp() !== 'files') {
279
-			throw new \InvalidArgumentException('Unhandled app');
280
-		}
281
-
282
-		// TODO: This should all be moved to a service that also the transferownershipContoller uses.
283
-		try {
284
-			$transferOwnership = $this->mapper->getById((int)$notification->getObjectId());
285
-		} catch (DoesNotExistException $e) {
286
-			return;
287
-		}
288
-
289
-		$notification = $this->notificationManager->createNotification();
290
-		$notification->setUser($transferOwnership->getSourceUser())
291
-			->setApp('files')
292
-			->setDateTime($this->timeFactory->getDateTime())
293
-			->setSubject('transferownershipRequestDenied', [
294
-				'sourceUser' => $transferOwnership->getSourceUser(),
295
-				'targetUser' => $transferOwnership->getTargetUser(),
296
-				'nodeName' => $transferOwnership->getNodeName()
297
-			])
298
-			->setObject('transfer', (string)$transferOwnership->getId());
299
-		$this->notificationManager->notify($notification);
300
-
301
-		$this->mapper->delete($transferOwnership);
302
-	}
303
-
304
-	protected function getUser(string $userId): IUser {
305
-		$user = $this->userManager->get($userId);
306
-		if ($user instanceof IUser) {
307
-			return $user;
308
-		}
309
-		throw new \InvalidArgumentException('User not found');
310
-	}
46
+    /** @var IFactory */
47
+    protected $l10nFactory;
48
+
49
+    /** @var IURLGenerator */
50
+    protected $urlGenerator;
51
+    /** @var TransferOwnershipMapper */
52
+    private $mapper;
53
+    /** @var IManager */
54
+    private $notificationManager;
55
+    /** @var IUserManager */
56
+    private $userManager;
57
+    /** @var ITimeFactory */
58
+    private $timeFactory;
59
+
60
+    public function __construct(IFactory $l10nFactory,
61
+                                IURLGenerator $urlGenerator,
62
+                                TransferOwnershipMapper $mapper,
63
+                                IManager $notificationManager,
64
+                                IUserManager $userManager,
65
+                                ITimeFactory $timeFactory) {
66
+        $this->l10nFactory = $l10nFactory;
67
+        $this->urlGenerator = $urlGenerator;
68
+        $this->mapper = $mapper;
69
+        $this->notificationManager = $notificationManager;
70
+        $this->userManager = $userManager;
71
+        $this->timeFactory = $timeFactory;
72
+    }
73
+
74
+    public function getID(): string {
75
+        return 'files';
76
+    }
77
+
78
+    public function getName(): string {
79
+        return $this->l10nFactory->get('files')->t('Files');
80
+    }
81
+
82
+    /**
83
+     * @param INotification $notification
84
+     * @param string $languageCode The code of the language that should be used to prepare the notification
85
+     * @return INotification
86
+     * @throws \InvalidArgumentException When the notification was not prepared by a notifier
87
+     */
88
+    public function prepare(INotification $notification, string $languageCode): INotification {
89
+        if ($notification->getApp() !== 'files') {
90
+            throw new \InvalidArgumentException('Unhandled app');
91
+        }
92
+
93
+        if ($notification->getSubject() === 'transferownershipRequest') {
94
+            return $this->handleTransferownershipRequest($notification, $languageCode);
95
+        }
96
+        if ($notification->getSubject() === 'transferOwnershipFailedSource') {
97
+            return $this->handleTransferOwnershipFailedSource($notification, $languageCode);
98
+        }
99
+        if ($notification->getSubject() === 'transferOwnershipFailedTarget') {
100
+            return $this->handleTransferOwnershipFailedTarget($notification, $languageCode);
101
+        }
102
+        if ($notification->getSubject() === 'transferOwnershipDoneSource') {
103
+            return $this->handleTransferOwnershipDoneSource($notification, $languageCode);
104
+        }
105
+        if ($notification->getSubject() === 'transferOwnershipDoneTarget') {
106
+            return $this->handleTransferOwnershipDoneTarget($notification, $languageCode);
107
+        }
108
+
109
+        throw new \InvalidArgumentException('Unhandled subject');
110
+    }
111
+
112
+    public function handleTransferownershipRequest(INotification $notification, string $languageCode): INotification {
113
+        $l = $this->l10nFactory->get('files', $languageCode);
114
+        $id = $notification->getObjectId();
115
+        $param = $notification->getSubjectParameters();
116
+
117
+        $approveAction = $notification->createAction()
118
+            ->setParsedLabel($l->t('Accept'))
119
+            ->setPrimary(true)
120
+            ->setLink(
121
+                $this->urlGenerator->getAbsoluteURL(
122
+                    $this->urlGenerator->linkTo(
123
+                        '',
124
+                        'ocs/v2.php/apps/files/api/v1/transferownership/' . $id
125
+                    )
126
+                ),
127
+                IAction::TYPE_POST
128
+            );
129
+
130
+        $disapproveAction = $notification->createAction()
131
+            ->setParsedLabel($l->t('Reject'))
132
+            ->setPrimary(false)
133
+            ->setLink(
134
+                $this->urlGenerator->getAbsoluteURL(
135
+                    $this->urlGenerator->linkTo(
136
+                        '',
137
+                        'ocs/v2.php/apps/files/api/v1/transferownership/' . $id
138
+                    )
139
+                ),
140
+                IAction::TYPE_DELETE
141
+            );
142
+
143
+        $sourceUser = $this->getUser($param['sourceUser']);
144
+        $notification->addParsedAction($approveAction)
145
+            ->addParsedAction($disapproveAction)
146
+            ->setRichSubject(
147
+                $l->t('Incoming ownership transfer from {user}'),
148
+                [
149
+                    'user' => [
150
+                        'type' => 'user',
151
+                        'id' => $sourceUser->getUID(),
152
+                        'name' => $sourceUser->getDisplayName(),
153
+                    ],
154
+                ])
155
+            ->setParsedSubject(str_replace('{user}', $sourceUser->getDisplayName(), $l->t('Incoming ownership transfer from {user}')))
156
+            ->setRichMessage(
157
+                $l->t("Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour."),
158
+                [
159
+                    'path' => [
160
+                        'type' => 'highlight',
161
+                        'id' => $param['targetUser'] . '::' . $param['nodeName'],
162
+                        'name' => $param['nodeName'],
163
+                    ]
164
+                ])
165
+            ->setParsedMessage(str_replace('{path}', $param['nodeName'], $l->t("Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour.")));
166
+
167
+        return $notification;
168
+    }
169
+
170
+    public function handleTransferOwnershipFailedSource(INotification $notification,  string $languageCode): INotification {
171
+        $l = $this->l10nFactory->get('files', $languageCode);
172
+        $param = $notification->getSubjectParameters();
173
+
174
+        $targetUser = $this->getUser($param['targetUser']);
175
+        $notification->setRichSubject($l->t('Ownership transfer failed'))
176
+            ->setParsedSubject($l->t('Ownership transfer failed'))
177
+
178
+            ->setRichMessage(
179
+                $l->t('Your ownership transfer of {path} to {user} failed.'),
180
+                [
181
+                    'path' => [
182
+                        'type' => 'highlight',
183
+                        'id' => $param['targetUser'] . '::' . $param['nodeName'],
184
+                        'name' => $param['nodeName'],
185
+                    ],
186
+                    'user' => [
187
+                        'type' => 'user',
188
+                        'id' => $targetUser->getUID(),
189
+                        'name' => $targetUser->getDisplayName(),
190
+                    ],
191
+                ])
192
+            ->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $targetUser->getDisplayName()], $l->t('Your ownership transfer of {path} to {user} failed.')));
193
+        return $notification;
194
+    }
195
+
196
+    public function handleTransferOwnershipFailedTarget(INotification $notification,  string $languageCode): INotification {
197
+        $l = $this->l10nFactory->get('files', $languageCode);
198
+        $param = $notification->getSubjectParameters();
199
+
200
+        $sourceUser = $this->getUser($param['sourceUser']);
201
+        $notification->setRichSubject($l->t('Ownership transfer failed'))
202
+            ->setParsedSubject($l->t('Ownership transfer failed'))
203
+
204
+            ->setRichMessage(
205
+                $l->t('The ownership transfer of {path} from {user} failed.'),
206
+                [
207
+                    'path' => [
208
+                        'type' => 'highlight',
209
+                        'id' => $param['sourceUser'] . '::' . $param['nodeName'],
210
+                        'name' => $param['nodeName'],
211
+                    ],
212
+                    'user' => [
213
+                        'type' => 'user',
214
+                        'id' => $sourceUser->getUID(),
215
+                        'name' => $sourceUser->getDisplayName(),
216
+                    ],
217
+                ])
218
+            ->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $sourceUser->getDisplayName()], $l->t('The ownership transfer of {path} from {user} failed.')));
219
+
220
+        return $notification;
221
+    }
222
+
223
+    public function handleTransferOwnershipDoneSource(INotification $notification,  string $languageCode): INotification {
224
+        $l = $this->l10nFactory->get('files', $languageCode);
225
+        $param = $notification->getSubjectParameters();
226
+
227
+        $targetUser = $this->getUser($param['targetUser']);
228
+        $notification->setRichSubject($l->t('Ownership transfer done'))
229
+            ->setParsedSubject($l->t('Ownership transfer done'))
230
+
231
+            ->setRichMessage(
232
+                $l->t('Your ownership transfer of {path} to {user} has completed.'),
233
+                [
234
+                    'path' => [
235
+                        'type' => 'highlight',
236
+                        'id' => $param['targetUser'] . '::' . $param['nodeName'],
237
+                        'name' => $param['nodeName'],
238
+                    ],
239
+                    'user' => [
240
+                        'type' => 'user',
241
+                        'id' => $targetUser->getUID(),
242
+                        'name' => $targetUser->getDisplayName(),
243
+                    ],
244
+                ])
245
+            ->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $targetUser->getDisplayName()], $l->t('Your ownership transfer of {path} to {user} has completed.')));
246
+
247
+        return $notification;
248
+    }
249
+
250
+    public function handleTransferOwnershipDoneTarget(INotification $notification,  string $languageCode): INotification {
251
+        $l = $this->l10nFactory->get('files', $languageCode);
252
+        $param = $notification->getSubjectParameters();
253
+
254
+        $sourceUser = $this->getUser($param['sourceUser']);
255
+        $notification->setRichSubject($l->t('Ownership transfer done'))
256
+            ->setParsedSubject($l->t('Ownership transfer done'))
257
+
258
+            ->setRichMessage(
259
+                $l->t('The ownership transfer of {path} from {user} has completed.'),
260
+                [
261
+                    'path' => [
262
+                        'type' => 'highlight',
263
+                        'id' => $param['sourceUser'] . '::' . $param['nodeName'],
264
+                        'name' => $param['nodeName'],
265
+                    ],
266
+                    'user' => [
267
+                        'type' => 'user',
268
+                        'id' => $sourceUser->getUID(),
269
+                        'name' => $sourceUser->getDisplayName(),
270
+                    ],
271
+                ])
272
+            ->setParsedMessage(str_replace(['{path}', '{user}'], [$param['nodeName'], $sourceUser->getDisplayName()], $l->t('The ownership transfer of {path} from {user} has completed.')));
273
+
274
+        return $notification;
275
+    }
276
+
277
+    public function dismissNotification(INotification $notification): void {
278
+        if ($notification->getApp() !== 'files') {
279
+            throw new \InvalidArgumentException('Unhandled app');
280
+        }
281
+
282
+        // TODO: This should all be moved to a service that also the transferownershipContoller uses.
283
+        try {
284
+            $transferOwnership = $this->mapper->getById((int)$notification->getObjectId());
285
+        } catch (DoesNotExistException $e) {
286
+            return;
287
+        }
288
+
289
+        $notification = $this->notificationManager->createNotification();
290
+        $notification->setUser($transferOwnership->getSourceUser())
291
+            ->setApp('files')
292
+            ->setDateTime($this->timeFactory->getDateTime())
293
+            ->setSubject('transferownershipRequestDenied', [
294
+                'sourceUser' => $transferOwnership->getSourceUser(),
295
+                'targetUser' => $transferOwnership->getTargetUser(),
296
+                'nodeName' => $transferOwnership->getNodeName()
297
+            ])
298
+            ->setObject('transfer', (string)$transferOwnership->getId());
299
+        $this->notificationManager->notify($notification);
300
+
301
+        $this->mapper->delete($transferOwnership);
302
+    }
303
+
304
+    protected function getUser(string $userId): IUser {
305
+        $user = $this->userManager->get($userId);
306
+        if ($user instanceof IUser) {
307
+            return $user;
308
+        }
309
+        throw new \InvalidArgumentException('User not found');
310
+    }
311 311
 }
Please login to merge, or discard this patch.
lib/private/Files/Filesystem.php 2 patches
Indentation   +844 added lines, -844 removed lines patch added patch discarded remove patch
@@ -71,848 +71,848 @@
 block discarded – undo
71 71
 
72 72
 class Filesystem {
73 73
 
74
-	/**
75
-	 * @var Mount\Manager $mounts
76
-	 */
77
-	private static $mounts;
78
-
79
-	public static $loaded = false;
80
-	/**
81
-	 * @var \OC\Files\View $defaultInstance
82
-	 */
83
-	static private $defaultInstance;
84
-
85
-	static private $usersSetup = [];
86
-
87
-	static private $normalizedPathCache = null;
88
-
89
-	static private $listeningForProviders = false;
90
-
91
-	/**
92
-	 * classname which used for hooks handling
93
-	 * used as signalclass in OC_Hooks::emit()
94
-	 */
95
-	const CLASSNAME = 'OC_Filesystem';
96
-
97
-	/**
98
-	 * signalname emitted before file renaming
99
-	 *
100
-	 * @param string $oldpath
101
-	 * @param string $newpath
102
-	 */
103
-	const signal_rename = 'rename';
104
-
105
-	/**
106
-	 * signal emitted after file renaming
107
-	 *
108
-	 * @param string $oldpath
109
-	 * @param string $newpath
110
-	 */
111
-	const signal_post_rename = 'post_rename';
112
-
113
-	/**
114
-	 * signal emitted before file/dir creation
115
-	 *
116
-	 * @param string $path
117
-	 * @param bool $run changing this flag to false in hook handler will cancel event
118
-	 */
119
-	const signal_create = 'create';
120
-
121
-	/**
122
-	 * signal emitted after file/dir creation
123
-	 *
124
-	 * @param string $path
125
-	 * @param bool $run changing this flag to false in hook handler will cancel event
126
-	 */
127
-	const signal_post_create = 'post_create';
128
-
129
-	/**
130
-	 * signal emits before file/dir copy
131
-	 *
132
-	 * @param string $oldpath
133
-	 * @param string $newpath
134
-	 * @param bool $run changing this flag to false in hook handler will cancel event
135
-	 */
136
-	const signal_copy = 'copy';
137
-
138
-	/**
139
-	 * signal emits after file/dir copy
140
-	 *
141
-	 * @param string $oldpath
142
-	 * @param string $newpath
143
-	 */
144
-	const signal_post_copy = 'post_copy';
145
-
146
-	/**
147
-	 * signal emits before file/dir save
148
-	 *
149
-	 * @param string $path
150
-	 * @param bool $run changing this flag to false in hook handler will cancel event
151
-	 */
152
-	const signal_write = 'write';
153
-
154
-	/**
155
-	 * signal emits after file/dir save
156
-	 *
157
-	 * @param string $path
158
-	 */
159
-	const signal_post_write = 'post_write';
160
-
161
-	/**
162
-	 * signal emitted before file/dir update
163
-	 *
164
-	 * @param string $path
165
-	 * @param bool $run changing this flag to false in hook handler will cancel event
166
-	 */
167
-	const signal_update = 'update';
168
-
169
-	/**
170
-	 * signal emitted after file/dir update
171
-	 *
172
-	 * @param string $path
173
-	 * @param bool $run changing this flag to false in hook handler will cancel event
174
-	 */
175
-	const signal_post_update = 'post_update';
176
-
177
-	/**
178
-	 * signal emits when reading file/dir
179
-	 *
180
-	 * @param string $path
181
-	 */
182
-	const signal_read = 'read';
183
-
184
-	/**
185
-	 * signal emits when removing file/dir
186
-	 *
187
-	 * @param string $path
188
-	 */
189
-	const signal_delete = 'delete';
190
-
191
-	/**
192
-	 * parameters definitions for signals
193
-	 */
194
-	const signal_param_path = 'path';
195
-	const signal_param_oldpath = 'oldpath';
196
-	const signal_param_newpath = 'newpath';
197
-
198
-	/**
199
-	 * run - changing this flag to false in hook handler will cancel event
200
-	 */
201
-	const signal_param_run = 'run';
202
-
203
-	const signal_create_mount = 'create_mount';
204
-	const signal_delete_mount = 'delete_mount';
205
-	const signal_param_mount_type = 'mounttype';
206
-	const signal_param_users = 'users';
207
-
208
-	/**
209
-	 * @var \OC\Files\Storage\StorageFactory $loader
210
-	 */
211
-	private static $loader;
212
-
213
-	/** @var bool */
214
-	private static $logWarningWhenAddingStorageWrapper = true;
215
-
216
-	/**
217
-	 * @param bool $shouldLog
218
-	 * @return bool previous value
219
-	 * @internal
220
-	 */
221
-	public static function logWarningWhenAddingStorageWrapper($shouldLog) {
222
-		$previousValue = self::$logWarningWhenAddingStorageWrapper;
223
-		self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
224
-		return $previousValue;
225
-	}
226
-
227
-	/**
228
-	 * @param string $wrapperName
229
-	 * @param callable $wrapper
230
-	 * @param int $priority
231
-	 */
232
-	public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
233
-		if (self::$logWarningWhenAddingStorageWrapper) {
234
-			\OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
235
-				'wrapper' => $wrapperName,
236
-				'app' => 'filesystem',
237
-			]);
238
-		}
239
-
240
-		$mounts = self::getMountManager()->getAll();
241
-		if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
242
-			// do not re-wrap if storage with this name already existed
243
-			return;
244
-		}
245
-	}
246
-
247
-	/**
248
-	 * Returns the storage factory
249
-	 *
250
-	 * @return IStorageFactory
251
-	 */
252
-	public static function getLoader() {
253
-		if (!self::$loader) {
254
-			self::$loader = \OC::$server->query(IStorageFactory::class);
255
-		}
256
-		return self::$loader;
257
-	}
258
-
259
-	/**
260
-	 * Returns the mount manager
261
-	 *
262
-	 * @return \OC\Files\Mount\Manager
263
-	 */
264
-	public static function getMountManager($user = '') {
265
-		if (!self::$mounts) {
266
-			\OC_Util::setupFS($user);
267
-		}
268
-		return self::$mounts;
269
-	}
270
-
271
-	/**
272
-	 * get the mountpoint of the storage object for a path
273
-	 * ( note: because a storage is not always mounted inside the fakeroot, the
274
-	 * returned mountpoint is relative to the absolute root of the filesystem
275
-	 * and doesn't take the chroot into account )
276
-	 *
277
-	 * @param string $path
278
-	 * @return string
279
-	 */
280
-	static public function getMountPoint($path) {
281
-		if (!self::$mounts) {
282
-			\OC_Util::setupFS();
283
-		}
284
-		$mount = self::$mounts->find($path);
285
-		if ($mount) {
286
-			return $mount->getMountPoint();
287
-		} else {
288
-			return '';
289
-		}
290
-	}
291
-
292
-	/**
293
-	 * get a list of all mount points in a directory
294
-	 *
295
-	 * @param string $path
296
-	 * @return string[]
297
-	 */
298
-	static public function getMountPoints($path) {
299
-		if (!self::$mounts) {
300
-			\OC_Util::setupFS();
301
-		}
302
-		$result = [];
303
-		$mounts = self::$mounts->findIn($path);
304
-		foreach ($mounts as $mount) {
305
-			$result[] = $mount->getMountPoint();
306
-		}
307
-		return $result;
308
-	}
309
-
310
-	/**
311
-	 * get the storage mounted at $mountPoint
312
-	 *
313
-	 * @param string $mountPoint
314
-	 * @return \OC\Files\Storage\Storage
315
-	 */
316
-	public static function getStorage($mountPoint) {
317
-		if (!self::$mounts) {
318
-			\OC_Util::setupFS();
319
-		}
320
-		$mount = self::$mounts->find($mountPoint);
321
-		return $mount->getStorage();
322
-	}
323
-
324
-	/**
325
-	 * @param string $id
326
-	 * @return Mount\MountPoint[]
327
-	 */
328
-	public static function getMountByStorageId($id) {
329
-		if (!self::$mounts) {
330
-			\OC_Util::setupFS();
331
-		}
332
-		return self::$mounts->findByStorageId($id);
333
-	}
334
-
335
-	/**
336
-	 * @param int $id
337
-	 * @return Mount\MountPoint[]
338
-	 */
339
-	public static function getMountByNumericId($id) {
340
-		if (!self::$mounts) {
341
-			\OC_Util::setupFS();
342
-		}
343
-		return self::$mounts->findByNumericId($id);
344
-	}
345
-
346
-	/**
347
-	 * resolve a path to a storage and internal path
348
-	 *
349
-	 * @param string $path
350
-	 * @return array an array consisting of the storage and the internal path
351
-	 */
352
-	static public function resolvePath($path) {
353
-		if (!self::$mounts) {
354
-			\OC_Util::setupFS();
355
-		}
356
-		$mount = self::$mounts->find($path);
357
-		if ($mount) {
358
-			return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
359
-		} else {
360
-			return [null, null];
361
-		}
362
-	}
363
-
364
-	static public function init($user, $root) {
365
-		if (self::$defaultInstance) {
366
-			return false;
367
-		}
368
-		self::getLoader();
369
-		self::$defaultInstance = new View($root);
370
-
371
-		if (!self::$mounts) {
372
-			self::$mounts = \OC::$server->getMountManager();
373
-		}
374
-
375
-		//load custom mount config
376
-		self::initMountPoints($user);
377
-
378
-		self::$loaded = true;
379
-
380
-		return true;
381
-	}
382
-
383
-	static public function initMountManager() {
384
-		if (!self::$mounts) {
385
-			self::$mounts = \OC::$server->getMountManager();
386
-		}
387
-	}
388
-
389
-	/**
390
-	 * Initialize system and personal mount points for a user
391
-	 *
392
-	 * @param string $user
393
-	 * @throws \OC\User\NoUserException if the user is not available
394
-	 */
395
-	public static function initMountPoints($user = '') {
396
-		if ($user == '') {
397
-			$user = \OC_User::getUser();
398
-		}
399
-		if ($user === null || $user === false || $user === '') {
400
-			throw new \OC\User\NoUserException('Attempted to initialize mount points for null user and no user in session');
401
-		}
402
-
403
-		if (isset(self::$usersSetup[$user])) {
404
-			return;
405
-		}
406
-
407
-		self::$usersSetup[$user] = true;
408
-
409
-		$userManager = \OC::$server->getUserManager();
410
-		$userObject = $userManager->get($user);
411
-
412
-		if (is_null($userObject)) {
413
-			\OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
414
-			// reset flag, this will make it possible to rethrow the exception if called again
415
-			unset(self::$usersSetup[$user]);
416
-			throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
417
-		}
418
-
419
-		$realUid = $userObject->getUID();
420
-		// workaround in case of different casings
421
-		if ($user !== $realUid) {
422
-			$stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
423
-			\OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
424
-			$user = $realUid;
425
-
426
-			// again with the correct casing
427
-			if (isset(self::$usersSetup[$user])) {
428
-				return;
429
-			}
430
-
431
-			self::$usersSetup[$user] = true;
432
-		}
433
-
434
-		if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
435
-			/** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
436
-			$mountConfigManager = \OC::$server->getMountProviderCollection();
437
-
438
-			// home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
439
-			$homeMount = $mountConfigManager->getHomeMountForUser($userObject);
440
-
441
-			self::getMountManager()->addMount($homeMount);
442
-
443
-			\OC\Files\Filesystem::getStorage($user);
444
-
445
-			// Chance to mount for other storages
446
-			if ($userObject) {
447
-				$mounts = $mountConfigManager->addMountForUser($userObject, self::getMountManager());
448
-				$mounts[] = $homeMount;
449
-				$mountConfigManager->registerMounts($userObject, $mounts);
450
-			}
451
-
452
-			self::listenForNewMountProviders($mountConfigManager, $userManager);
453
-		} else {
454
-			self::getMountManager()->addMount(new MountPoint(
455
-				new NullStorage([]),
456
-				'/' . $user
457
-			));
458
-			self::getMountManager()->addMount(new MountPoint(
459
-				new NullStorage([]),
460
-				'/' . $user . '/files'
461
-			));
462
-		}
463
-		\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
464
-	}
465
-
466
-	/**
467
-	 * Get mounts from mount providers that are registered after setup
468
-	 *
469
-	 * @param MountProviderCollection $mountConfigManager
470
-	 * @param IUserManager $userManager
471
-	 */
472
-	private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
473
-		if (!self::$listeningForProviders) {
474
-			self::$listeningForProviders = true;
475
-			$mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
476
-				foreach (Filesystem::$usersSetup as $user => $setup) {
477
-					$userObject = $userManager->get($user);
478
-					if ($userObject) {
479
-						$mounts = $provider->getMountsForUser($userObject, Filesystem::getLoader());
480
-						array_walk($mounts, [self::$mounts, 'addMount']);
481
-					}
482
-				}
483
-			});
484
-		}
485
-	}
486
-
487
-	/**
488
-	 * get the default filesystem view
489
-	 *
490
-	 * @return View
491
-	 */
492
-	static public function getView() {
493
-		return self::$defaultInstance;
494
-	}
495
-
496
-	/**
497
-	 * tear down the filesystem, removing all storage providers
498
-	 */
499
-	static public function tearDown() {
500
-		self::clearMounts();
501
-		self::$defaultInstance = null;
502
-	}
503
-
504
-	/**
505
-	 * get the relative path of the root data directory for the current user
506
-	 *
507
-	 * @return string
508
-	 *
509
-	 * Returns path like /admin/files
510
-	 */
511
-	static public function getRoot() {
512
-		if (!self::$defaultInstance) {
513
-			return null;
514
-		}
515
-		return self::$defaultInstance->getRoot();
516
-	}
517
-
518
-	/**
519
-	 * clear all mounts and storage backends
520
-	 */
521
-	public static function clearMounts() {
522
-		if (self::$mounts) {
523
-			self::$usersSetup = [];
524
-			self::$mounts->clear();
525
-		}
526
-	}
527
-
528
-	/**
529
-	 * mount an \OC\Files\Storage\Storage in our virtual filesystem
530
-	 *
531
-	 * @param \OC\Files\Storage\Storage|string $class
532
-	 * @param array $arguments
533
-	 * @param string $mountpoint
534
-	 */
535
-	static public function mount($class, $arguments, $mountpoint) {
536
-		if (!self::$mounts) {
537
-			\OC_Util::setupFS();
538
-		}
539
-		$mount = new Mount\MountPoint($class, $mountpoint, $arguments, self::getLoader());
540
-		self::$mounts->addMount($mount);
541
-	}
542
-
543
-	/**
544
-	 * return the path to a local version of the file
545
-	 * we need this because we can't know if a file is stored local or not from
546
-	 * outside the filestorage and for some purposes a local file is needed
547
-	 *
548
-	 * @param string $path
549
-	 * @return string
550
-	 */
551
-	static public function getLocalFile($path) {
552
-		return self::$defaultInstance->getLocalFile($path);
553
-	}
554
-
555
-	/**
556
-	 * @param string $path
557
-	 * @return string
558
-	 */
559
-	static public function getLocalFolder($path) {
560
-		return self::$defaultInstance->getLocalFolder($path);
561
-	}
562
-
563
-	/**
564
-	 * return path to file which reflects one visible in browser
565
-	 *
566
-	 * @param string $path
567
-	 * @return string
568
-	 */
569
-	static public function getLocalPath($path) {
570
-		$datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
571
-		$newpath = $path;
572
-		if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
573
-			$newpath = substr($path, strlen($datadir));
574
-		}
575
-		return $newpath;
576
-	}
577
-
578
-	/**
579
-	 * check if the requested path is valid
580
-	 *
581
-	 * @param string $path
582
-	 * @return bool
583
-	 */
584
-	static public function isValidPath($path) {
585
-		$path = self::normalizePath($path);
586
-		if (!$path || $path[0] !== '/') {
587
-			$path = '/' . $path;
588
-		}
589
-		if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
590
-			return false;
591
-		}
592
-		return true;
593
-	}
594
-
595
-	/**
596
-	 * checks if a file is blacklisted for storage in the filesystem
597
-	 * Listens to write and rename hooks
598
-	 *
599
-	 * @param array $data from hook
600
-	 */
601
-	static public function isBlacklisted($data) {
602
-		if (isset($data['path'])) {
603
-			$path = $data['path'];
604
-		} else if (isset($data['newpath'])) {
605
-			$path = $data['newpath'];
606
-		}
607
-		if (isset($path)) {
608
-			if (self::isFileBlacklisted($path)) {
609
-				$data['run'] = false;
610
-			}
611
-		}
612
-	}
613
-
614
-	/**
615
-	 * @param string $filename
616
-	 * @return bool
617
-	 */
618
-	static public function isFileBlacklisted($filename) {
619
-		$filename = self::normalizePath($filename);
620
-
621
-		$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
622
-		$filename = strtolower(basename($filename));
623
-		return in_array($filename, $blacklist);
624
-	}
625
-
626
-	/**
627
-	 * check if the directory should be ignored when scanning
628
-	 * NOTE: the special directories . and .. would cause never ending recursion
629
-	 *
630
-	 * @param string $dir
631
-	 * @return boolean
632
-	 */
633
-	static public function isIgnoredDir($dir) {
634
-		if ($dir === '.' || $dir === '..') {
635
-			return true;
636
-		}
637
-		return false;
638
-	}
639
-
640
-	/**
641
-	 * following functions are equivalent to their php builtin equivalents for arguments/return values.
642
-	 */
643
-	static public function mkdir($path) {
644
-		return self::$defaultInstance->mkdir($path);
645
-	}
646
-
647
-	static public function rmdir($path) {
648
-		return self::$defaultInstance->rmdir($path);
649
-	}
650
-
651
-	static public function is_dir($path) {
652
-		return self::$defaultInstance->is_dir($path);
653
-	}
654
-
655
-	static public function is_file($path) {
656
-		return self::$defaultInstance->is_file($path);
657
-	}
658
-
659
-	static public function stat($path) {
660
-		return self::$defaultInstance->stat($path);
661
-	}
662
-
663
-	static public function filetype($path) {
664
-		return self::$defaultInstance->filetype($path);
665
-	}
666
-
667
-	static public function filesize($path) {
668
-		return self::$defaultInstance->filesize($path);
669
-	}
670
-
671
-	static public function readfile($path) {
672
-		return self::$defaultInstance->readfile($path);
673
-	}
674
-
675
-	static public function isCreatable($path) {
676
-		return self::$defaultInstance->isCreatable($path);
677
-	}
678
-
679
-	static public function isReadable($path) {
680
-		return self::$defaultInstance->isReadable($path);
681
-	}
682
-
683
-	static public function isUpdatable($path) {
684
-		return self::$defaultInstance->isUpdatable($path);
685
-	}
686
-
687
-	static public function isDeletable($path) {
688
-		return self::$defaultInstance->isDeletable($path);
689
-	}
690
-
691
-	static public function isSharable($path) {
692
-		return self::$defaultInstance->isSharable($path);
693
-	}
694
-
695
-	static public function file_exists($path) {
696
-		return self::$defaultInstance->file_exists($path);
697
-	}
698
-
699
-	static public function filemtime($path) {
700
-		return self::$defaultInstance->filemtime($path);
701
-	}
702
-
703
-	static public function touch($path, $mtime = null) {
704
-		return self::$defaultInstance->touch($path, $mtime);
705
-	}
706
-
707
-	/**
708
-	 * @return string
709
-	 */
710
-	static public function file_get_contents($path) {
711
-		return self::$defaultInstance->file_get_contents($path);
712
-	}
713
-
714
-	static public function file_put_contents($path, $data) {
715
-		return self::$defaultInstance->file_put_contents($path, $data);
716
-	}
717
-
718
-	static public function unlink($path) {
719
-		return self::$defaultInstance->unlink($path);
720
-	}
721
-
722
-	static public function rename($path1, $path2) {
723
-		return self::$defaultInstance->rename($path1, $path2);
724
-	}
725
-
726
-	static public function copy($path1, $path2) {
727
-		return self::$defaultInstance->copy($path1, $path2);
728
-	}
729
-
730
-	static public function fopen($path, $mode) {
731
-		return self::$defaultInstance->fopen($path, $mode);
732
-	}
733
-
734
-	/**
735
-	 * @return string
736
-	 */
737
-	static public function toTmpFile($path) {
738
-		return self::$defaultInstance->toTmpFile($path);
739
-	}
740
-
741
-	static public function fromTmpFile($tmpFile, $path) {
742
-		return self::$defaultInstance->fromTmpFile($tmpFile, $path);
743
-	}
744
-
745
-	static public function getMimeType($path) {
746
-		return self::$defaultInstance->getMimeType($path);
747
-	}
748
-
749
-	static public function hash($type, $path, $raw = false) {
750
-		return self::$defaultInstance->hash($type, $path, $raw);
751
-	}
752
-
753
-	static public function free_space($path = '/') {
754
-		return self::$defaultInstance->free_space($path);
755
-	}
756
-
757
-	static public function search($query) {
758
-		return self::$defaultInstance->search($query);
759
-	}
760
-
761
-	/**
762
-	 * @param string $query
763
-	 */
764
-	static public function searchByMime($query) {
765
-		return self::$defaultInstance->searchByMime($query);
766
-	}
767
-
768
-	/**
769
-	 * @param string|int $tag name or tag id
770
-	 * @param string $userId owner of the tags
771
-	 * @return FileInfo[] array or file info
772
-	 */
773
-	static public function searchByTag($tag, $userId) {
774
-		return self::$defaultInstance->searchByTag($tag, $userId);
775
-	}
776
-
777
-	/**
778
-	 * check if a file or folder has been updated since $time
779
-	 *
780
-	 * @param string $path
781
-	 * @param int $time
782
-	 * @return bool
783
-	 */
784
-	static public function hasUpdated($path, $time) {
785
-		return self::$defaultInstance->hasUpdated($path, $time);
786
-	}
787
-
788
-	/**
789
-	 * Fix common problems with a file path
790
-	 *
791
-	 * @param string $path
792
-	 * @param bool $stripTrailingSlash whether to strip the trailing slash
793
-	 * @param bool $isAbsolutePath whether the given path is absolute
794
-	 * @param bool $keepUnicode true to disable unicode normalization
795
-	 * @return string
796
-	 */
797
-	public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
798
-		if (is_null(self::$normalizedPathCache)) {
799
-			self::$normalizedPathCache = new CappedMemoryCache(2048);
800
-		}
801
-
802
-		/**
803
-		 * FIXME: This is a workaround for existing classes and files which call
804
-		 *        this function with another type than a valid string. This
805
-		 *        conversion should get removed as soon as all existing
806
-		 *        function calls have been fixed.
807
-		 */
808
-		$path = (string)$path;
809
-
810
-		$cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
811
-
812
-		if (isset(self::$normalizedPathCache[$cacheKey])) {
813
-			return self::$normalizedPathCache[$cacheKey];
814
-		}
815
-
816
-		if ($path === '') {
817
-			return '/';
818
-		}
819
-
820
-		//normalize unicode if possible
821
-		if (!$keepUnicode) {
822
-			$path = \OC_Util::normalizeUnicode($path);
823
-		}
824
-
825
-		//add leading slash, if it is already there we strip it anyway
826
-		$path = '/' . $path;
827
-
828
-		$patterns = [
829
-			'/\\\\/s',          // no windows style slashes
830
-			'/\/\.(\/\.)?\//s', // remove '/./'
831
-			'/\/{2,}/s',        // remove sequence of slashes
832
-			'/\/\.$/s',         // remove trailing /.
833
-		];
834
-
835
-		do {
836
-			$count = 0;
837
-			$path = preg_replace($patterns, '/', $path, -1, $count);
838
-		} while ($count > 0);
839
-
840
-		//remove trailing slash
841
-		if ($stripTrailingSlash && strlen($path) > 1) {
842
-			$path = rtrim($path, '/');
843
-		}
844
-
845
-		self::$normalizedPathCache[$cacheKey] = $path;
846
-
847
-		return $path;
848
-	}
849
-
850
-	/**
851
-	 * get the filesystem info
852
-	 *
853
-	 * @param string $path
854
-	 * @param boolean $includeMountPoints whether to add mountpoint sizes,
855
-	 * defaults to true
856
-	 * @return \OC\Files\FileInfo|bool False if file does not exist
857
-	 */
858
-	public static function getFileInfo($path, $includeMountPoints = true) {
859
-		return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
860
-	}
861
-
862
-	/**
863
-	 * change file metadata
864
-	 *
865
-	 * @param string $path
866
-	 * @param array $data
867
-	 * @return int
868
-	 *
869
-	 * returns the fileid of the updated file
870
-	 */
871
-	public static function putFileInfo($path, $data) {
872
-		return self::$defaultInstance->putFileInfo($path, $data);
873
-	}
874
-
875
-	/**
876
-	 * get the content of a directory
877
-	 *
878
-	 * @param string $directory path under datadirectory
879
-	 * @param string $mimetype_filter limit returned content to this mimetype or mimepart
880
-	 * @return \OC\Files\FileInfo[]
881
-	 */
882
-	public static function getDirectoryContent($directory, $mimetype_filter = '') {
883
-		return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter);
884
-	}
885
-
886
-	/**
887
-	 * Get the path of a file by id
888
-	 *
889
-	 * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
890
-	 *
891
-	 * @param int $id
892
-	 * @throws NotFoundException
893
-	 * @return string
894
-	 */
895
-	public static function getPath($id) {
896
-		return self::$defaultInstance->getPath($id);
897
-	}
898
-
899
-	/**
900
-	 * Get the owner for a file or folder
901
-	 *
902
-	 * @param string $path
903
-	 * @return string
904
-	 */
905
-	public static function getOwner($path) {
906
-		return self::$defaultInstance->getOwner($path);
907
-	}
908
-
909
-	/**
910
-	 * get the ETag for a file or folder
911
-	 *
912
-	 * @param string $path
913
-	 * @return string
914
-	 */
915
-	static public function getETag($path) {
916
-		return self::$defaultInstance->getETag($path);
917
-	}
74
+    /**
75
+     * @var Mount\Manager $mounts
76
+     */
77
+    private static $mounts;
78
+
79
+    public static $loaded = false;
80
+    /**
81
+     * @var \OC\Files\View $defaultInstance
82
+     */
83
+    static private $defaultInstance;
84
+
85
+    static private $usersSetup = [];
86
+
87
+    static private $normalizedPathCache = null;
88
+
89
+    static private $listeningForProviders = false;
90
+
91
+    /**
92
+     * classname which used for hooks handling
93
+     * used as signalclass in OC_Hooks::emit()
94
+     */
95
+    const CLASSNAME = 'OC_Filesystem';
96
+
97
+    /**
98
+     * signalname emitted before file renaming
99
+     *
100
+     * @param string $oldpath
101
+     * @param string $newpath
102
+     */
103
+    const signal_rename = 'rename';
104
+
105
+    /**
106
+     * signal emitted after file renaming
107
+     *
108
+     * @param string $oldpath
109
+     * @param string $newpath
110
+     */
111
+    const signal_post_rename = 'post_rename';
112
+
113
+    /**
114
+     * signal emitted before file/dir creation
115
+     *
116
+     * @param string $path
117
+     * @param bool $run changing this flag to false in hook handler will cancel event
118
+     */
119
+    const signal_create = 'create';
120
+
121
+    /**
122
+     * signal emitted after file/dir creation
123
+     *
124
+     * @param string $path
125
+     * @param bool $run changing this flag to false in hook handler will cancel event
126
+     */
127
+    const signal_post_create = 'post_create';
128
+
129
+    /**
130
+     * signal emits before file/dir copy
131
+     *
132
+     * @param string $oldpath
133
+     * @param string $newpath
134
+     * @param bool $run changing this flag to false in hook handler will cancel event
135
+     */
136
+    const signal_copy = 'copy';
137
+
138
+    /**
139
+     * signal emits after file/dir copy
140
+     *
141
+     * @param string $oldpath
142
+     * @param string $newpath
143
+     */
144
+    const signal_post_copy = 'post_copy';
145
+
146
+    /**
147
+     * signal emits before file/dir save
148
+     *
149
+     * @param string $path
150
+     * @param bool $run changing this flag to false in hook handler will cancel event
151
+     */
152
+    const signal_write = 'write';
153
+
154
+    /**
155
+     * signal emits after file/dir save
156
+     *
157
+     * @param string $path
158
+     */
159
+    const signal_post_write = 'post_write';
160
+
161
+    /**
162
+     * signal emitted before file/dir update
163
+     *
164
+     * @param string $path
165
+     * @param bool $run changing this flag to false in hook handler will cancel event
166
+     */
167
+    const signal_update = 'update';
168
+
169
+    /**
170
+     * signal emitted after file/dir update
171
+     *
172
+     * @param string $path
173
+     * @param bool $run changing this flag to false in hook handler will cancel event
174
+     */
175
+    const signal_post_update = 'post_update';
176
+
177
+    /**
178
+     * signal emits when reading file/dir
179
+     *
180
+     * @param string $path
181
+     */
182
+    const signal_read = 'read';
183
+
184
+    /**
185
+     * signal emits when removing file/dir
186
+     *
187
+     * @param string $path
188
+     */
189
+    const signal_delete = 'delete';
190
+
191
+    /**
192
+     * parameters definitions for signals
193
+     */
194
+    const signal_param_path = 'path';
195
+    const signal_param_oldpath = 'oldpath';
196
+    const signal_param_newpath = 'newpath';
197
+
198
+    /**
199
+     * run - changing this flag to false in hook handler will cancel event
200
+     */
201
+    const signal_param_run = 'run';
202
+
203
+    const signal_create_mount = 'create_mount';
204
+    const signal_delete_mount = 'delete_mount';
205
+    const signal_param_mount_type = 'mounttype';
206
+    const signal_param_users = 'users';
207
+
208
+    /**
209
+     * @var \OC\Files\Storage\StorageFactory $loader
210
+     */
211
+    private static $loader;
212
+
213
+    /** @var bool */
214
+    private static $logWarningWhenAddingStorageWrapper = true;
215
+
216
+    /**
217
+     * @param bool $shouldLog
218
+     * @return bool previous value
219
+     * @internal
220
+     */
221
+    public static function logWarningWhenAddingStorageWrapper($shouldLog) {
222
+        $previousValue = self::$logWarningWhenAddingStorageWrapper;
223
+        self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
224
+        return $previousValue;
225
+    }
226
+
227
+    /**
228
+     * @param string $wrapperName
229
+     * @param callable $wrapper
230
+     * @param int $priority
231
+     */
232
+    public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
233
+        if (self::$logWarningWhenAddingStorageWrapper) {
234
+            \OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
235
+                'wrapper' => $wrapperName,
236
+                'app' => 'filesystem',
237
+            ]);
238
+        }
239
+
240
+        $mounts = self::getMountManager()->getAll();
241
+        if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
242
+            // do not re-wrap if storage with this name already existed
243
+            return;
244
+        }
245
+    }
246
+
247
+    /**
248
+     * Returns the storage factory
249
+     *
250
+     * @return IStorageFactory
251
+     */
252
+    public static function getLoader() {
253
+        if (!self::$loader) {
254
+            self::$loader = \OC::$server->query(IStorageFactory::class);
255
+        }
256
+        return self::$loader;
257
+    }
258
+
259
+    /**
260
+     * Returns the mount manager
261
+     *
262
+     * @return \OC\Files\Mount\Manager
263
+     */
264
+    public static function getMountManager($user = '') {
265
+        if (!self::$mounts) {
266
+            \OC_Util::setupFS($user);
267
+        }
268
+        return self::$mounts;
269
+    }
270
+
271
+    /**
272
+     * get the mountpoint of the storage object for a path
273
+     * ( note: because a storage is not always mounted inside the fakeroot, the
274
+     * returned mountpoint is relative to the absolute root of the filesystem
275
+     * and doesn't take the chroot into account )
276
+     *
277
+     * @param string $path
278
+     * @return string
279
+     */
280
+    static public function getMountPoint($path) {
281
+        if (!self::$mounts) {
282
+            \OC_Util::setupFS();
283
+        }
284
+        $mount = self::$mounts->find($path);
285
+        if ($mount) {
286
+            return $mount->getMountPoint();
287
+        } else {
288
+            return '';
289
+        }
290
+    }
291
+
292
+    /**
293
+     * get a list of all mount points in a directory
294
+     *
295
+     * @param string $path
296
+     * @return string[]
297
+     */
298
+    static public function getMountPoints($path) {
299
+        if (!self::$mounts) {
300
+            \OC_Util::setupFS();
301
+        }
302
+        $result = [];
303
+        $mounts = self::$mounts->findIn($path);
304
+        foreach ($mounts as $mount) {
305
+            $result[] = $mount->getMountPoint();
306
+        }
307
+        return $result;
308
+    }
309
+
310
+    /**
311
+     * get the storage mounted at $mountPoint
312
+     *
313
+     * @param string $mountPoint
314
+     * @return \OC\Files\Storage\Storage
315
+     */
316
+    public static function getStorage($mountPoint) {
317
+        if (!self::$mounts) {
318
+            \OC_Util::setupFS();
319
+        }
320
+        $mount = self::$mounts->find($mountPoint);
321
+        return $mount->getStorage();
322
+    }
323
+
324
+    /**
325
+     * @param string $id
326
+     * @return Mount\MountPoint[]
327
+     */
328
+    public static function getMountByStorageId($id) {
329
+        if (!self::$mounts) {
330
+            \OC_Util::setupFS();
331
+        }
332
+        return self::$mounts->findByStorageId($id);
333
+    }
334
+
335
+    /**
336
+     * @param int $id
337
+     * @return Mount\MountPoint[]
338
+     */
339
+    public static function getMountByNumericId($id) {
340
+        if (!self::$mounts) {
341
+            \OC_Util::setupFS();
342
+        }
343
+        return self::$mounts->findByNumericId($id);
344
+    }
345
+
346
+    /**
347
+     * resolve a path to a storage and internal path
348
+     *
349
+     * @param string $path
350
+     * @return array an array consisting of the storage and the internal path
351
+     */
352
+    static public function resolvePath($path) {
353
+        if (!self::$mounts) {
354
+            \OC_Util::setupFS();
355
+        }
356
+        $mount = self::$mounts->find($path);
357
+        if ($mount) {
358
+            return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
359
+        } else {
360
+            return [null, null];
361
+        }
362
+    }
363
+
364
+    static public function init($user, $root) {
365
+        if (self::$defaultInstance) {
366
+            return false;
367
+        }
368
+        self::getLoader();
369
+        self::$defaultInstance = new View($root);
370
+
371
+        if (!self::$mounts) {
372
+            self::$mounts = \OC::$server->getMountManager();
373
+        }
374
+
375
+        //load custom mount config
376
+        self::initMountPoints($user);
377
+
378
+        self::$loaded = true;
379
+
380
+        return true;
381
+    }
382
+
383
+    static public function initMountManager() {
384
+        if (!self::$mounts) {
385
+            self::$mounts = \OC::$server->getMountManager();
386
+        }
387
+    }
388
+
389
+    /**
390
+     * Initialize system and personal mount points for a user
391
+     *
392
+     * @param string $user
393
+     * @throws \OC\User\NoUserException if the user is not available
394
+     */
395
+    public static function initMountPoints($user = '') {
396
+        if ($user == '') {
397
+            $user = \OC_User::getUser();
398
+        }
399
+        if ($user === null || $user === false || $user === '') {
400
+            throw new \OC\User\NoUserException('Attempted to initialize mount points for null user and no user in session');
401
+        }
402
+
403
+        if (isset(self::$usersSetup[$user])) {
404
+            return;
405
+        }
406
+
407
+        self::$usersSetup[$user] = true;
408
+
409
+        $userManager = \OC::$server->getUserManager();
410
+        $userObject = $userManager->get($user);
411
+
412
+        if (is_null($userObject)) {
413
+            \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
414
+            // reset flag, this will make it possible to rethrow the exception if called again
415
+            unset(self::$usersSetup[$user]);
416
+            throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
417
+        }
418
+
419
+        $realUid = $userObject->getUID();
420
+        // workaround in case of different casings
421
+        if ($user !== $realUid) {
422
+            $stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
423
+            \OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
424
+            $user = $realUid;
425
+
426
+            // again with the correct casing
427
+            if (isset(self::$usersSetup[$user])) {
428
+                return;
429
+            }
430
+
431
+            self::$usersSetup[$user] = true;
432
+        }
433
+
434
+        if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
435
+            /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
436
+            $mountConfigManager = \OC::$server->getMountProviderCollection();
437
+
438
+            // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
439
+            $homeMount = $mountConfigManager->getHomeMountForUser($userObject);
440
+
441
+            self::getMountManager()->addMount($homeMount);
442
+
443
+            \OC\Files\Filesystem::getStorage($user);
444
+
445
+            // Chance to mount for other storages
446
+            if ($userObject) {
447
+                $mounts = $mountConfigManager->addMountForUser($userObject, self::getMountManager());
448
+                $mounts[] = $homeMount;
449
+                $mountConfigManager->registerMounts($userObject, $mounts);
450
+            }
451
+
452
+            self::listenForNewMountProviders($mountConfigManager, $userManager);
453
+        } else {
454
+            self::getMountManager()->addMount(new MountPoint(
455
+                new NullStorage([]),
456
+                '/' . $user
457
+            ));
458
+            self::getMountManager()->addMount(new MountPoint(
459
+                new NullStorage([]),
460
+                '/' . $user . '/files'
461
+            ));
462
+        }
463
+        \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
464
+    }
465
+
466
+    /**
467
+     * Get mounts from mount providers that are registered after setup
468
+     *
469
+     * @param MountProviderCollection $mountConfigManager
470
+     * @param IUserManager $userManager
471
+     */
472
+    private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
473
+        if (!self::$listeningForProviders) {
474
+            self::$listeningForProviders = true;
475
+            $mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
476
+                foreach (Filesystem::$usersSetup as $user => $setup) {
477
+                    $userObject = $userManager->get($user);
478
+                    if ($userObject) {
479
+                        $mounts = $provider->getMountsForUser($userObject, Filesystem::getLoader());
480
+                        array_walk($mounts, [self::$mounts, 'addMount']);
481
+                    }
482
+                }
483
+            });
484
+        }
485
+    }
486
+
487
+    /**
488
+     * get the default filesystem view
489
+     *
490
+     * @return View
491
+     */
492
+    static public function getView() {
493
+        return self::$defaultInstance;
494
+    }
495
+
496
+    /**
497
+     * tear down the filesystem, removing all storage providers
498
+     */
499
+    static public function tearDown() {
500
+        self::clearMounts();
501
+        self::$defaultInstance = null;
502
+    }
503
+
504
+    /**
505
+     * get the relative path of the root data directory for the current user
506
+     *
507
+     * @return string
508
+     *
509
+     * Returns path like /admin/files
510
+     */
511
+    static public function getRoot() {
512
+        if (!self::$defaultInstance) {
513
+            return null;
514
+        }
515
+        return self::$defaultInstance->getRoot();
516
+    }
517
+
518
+    /**
519
+     * clear all mounts and storage backends
520
+     */
521
+    public static function clearMounts() {
522
+        if (self::$mounts) {
523
+            self::$usersSetup = [];
524
+            self::$mounts->clear();
525
+        }
526
+    }
527
+
528
+    /**
529
+     * mount an \OC\Files\Storage\Storage in our virtual filesystem
530
+     *
531
+     * @param \OC\Files\Storage\Storage|string $class
532
+     * @param array $arguments
533
+     * @param string $mountpoint
534
+     */
535
+    static public function mount($class, $arguments, $mountpoint) {
536
+        if (!self::$mounts) {
537
+            \OC_Util::setupFS();
538
+        }
539
+        $mount = new Mount\MountPoint($class, $mountpoint, $arguments, self::getLoader());
540
+        self::$mounts->addMount($mount);
541
+    }
542
+
543
+    /**
544
+     * return the path to a local version of the file
545
+     * we need this because we can't know if a file is stored local or not from
546
+     * outside the filestorage and for some purposes a local file is needed
547
+     *
548
+     * @param string $path
549
+     * @return string
550
+     */
551
+    static public function getLocalFile($path) {
552
+        return self::$defaultInstance->getLocalFile($path);
553
+    }
554
+
555
+    /**
556
+     * @param string $path
557
+     * @return string
558
+     */
559
+    static public function getLocalFolder($path) {
560
+        return self::$defaultInstance->getLocalFolder($path);
561
+    }
562
+
563
+    /**
564
+     * return path to file which reflects one visible in browser
565
+     *
566
+     * @param string $path
567
+     * @return string
568
+     */
569
+    static public function getLocalPath($path) {
570
+        $datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
571
+        $newpath = $path;
572
+        if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
573
+            $newpath = substr($path, strlen($datadir));
574
+        }
575
+        return $newpath;
576
+    }
577
+
578
+    /**
579
+     * check if the requested path is valid
580
+     *
581
+     * @param string $path
582
+     * @return bool
583
+     */
584
+    static public function isValidPath($path) {
585
+        $path = self::normalizePath($path);
586
+        if (!$path || $path[0] !== '/') {
587
+            $path = '/' . $path;
588
+        }
589
+        if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
590
+            return false;
591
+        }
592
+        return true;
593
+    }
594
+
595
+    /**
596
+     * checks if a file is blacklisted for storage in the filesystem
597
+     * Listens to write and rename hooks
598
+     *
599
+     * @param array $data from hook
600
+     */
601
+    static public function isBlacklisted($data) {
602
+        if (isset($data['path'])) {
603
+            $path = $data['path'];
604
+        } else if (isset($data['newpath'])) {
605
+            $path = $data['newpath'];
606
+        }
607
+        if (isset($path)) {
608
+            if (self::isFileBlacklisted($path)) {
609
+                $data['run'] = false;
610
+            }
611
+        }
612
+    }
613
+
614
+    /**
615
+     * @param string $filename
616
+     * @return bool
617
+     */
618
+    static public function isFileBlacklisted($filename) {
619
+        $filename = self::normalizePath($filename);
620
+
621
+        $blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
622
+        $filename = strtolower(basename($filename));
623
+        return in_array($filename, $blacklist);
624
+    }
625
+
626
+    /**
627
+     * check if the directory should be ignored when scanning
628
+     * NOTE: the special directories . and .. would cause never ending recursion
629
+     *
630
+     * @param string $dir
631
+     * @return boolean
632
+     */
633
+    static public function isIgnoredDir($dir) {
634
+        if ($dir === '.' || $dir === '..') {
635
+            return true;
636
+        }
637
+        return false;
638
+    }
639
+
640
+    /**
641
+     * following functions are equivalent to their php builtin equivalents for arguments/return values.
642
+     */
643
+    static public function mkdir($path) {
644
+        return self::$defaultInstance->mkdir($path);
645
+    }
646
+
647
+    static public function rmdir($path) {
648
+        return self::$defaultInstance->rmdir($path);
649
+    }
650
+
651
+    static public function is_dir($path) {
652
+        return self::$defaultInstance->is_dir($path);
653
+    }
654
+
655
+    static public function is_file($path) {
656
+        return self::$defaultInstance->is_file($path);
657
+    }
658
+
659
+    static public function stat($path) {
660
+        return self::$defaultInstance->stat($path);
661
+    }
662
+
663
+    static public function filetype($path) {
664
+        return self::$defaultInstance->filetype($path);
665
+    }
666
+
667
+    static public function filesize($path) {
668
+        return self::$defaultInstance->filesize($path);
669
+    }
670
+
671
+    static public function readfile($path) {
672
+        return self::$defaultInstance->readfile($path);
673
+    }
674
+
675
+    static public function isCreatable($path) {
676
+        return self::$defaultInstance->isCreatable($path);
677
+    }
678
+
679
+    static public function isReadable($path) {
680
+        return self::$defaultInstance->isReadable($path);
681
+    }
682
+
683
+    static public function isUpdatable($path) {
684
+        return self::$defaultInstance->isUpdatable($path);
685
+    }
686
+
687
+    static public function isDeletable($path) {
688
+        return self::$defaultInstance->isDeletable($path);
689
+    }
690
+
691
+    static public function isSharable($path) {
692
+        return self::$defaultInstance->isSharable($path);
693
+    }
694
+
695
+    static public function file_exists($path) {
696
+        return self::$defaultInstance->file_exists($path);
697
+    }
698
+
699
+    static public function filemtime($path) {
700
+        return self::$defaultInstance->filemtime($path);
701
+    }
702
+
703
+    static public function touch($path, $mtime = null) {
704
+        return self::$defaultInstance->touch($path, $mtime);
705
+    }
706
+
707
+    /**
708
+     * @return string
709
+     */
710
+    static public function file_get_contents($path) {
711
+        return self::$defaultInstance->file_get_contents($path);
712
+    }
713
+
714
+    static public function file_put_contents($path, $data) {
715
+        return self::$defaultInstance->file_put_contents($path, $data);
716
+    }
717
+
718
+    static public function unlink($path) {
719
+        return self::$defaultInstance->unlink($path);
720
+    }
721
+
722
+    static public function rename($path1, $path2) {
723
+        return self::$defaultInstance->rename($path1, $path2);
724
+    }
725
+
726
+    static public function copy($path1, $path2) {
727
+        return self::$defaultInstance->copy($path1, $path2);
728
+    }
729
+
730
+    static public function fopen($path, $mode) {
731
+        return self::$defaultInstance->fopen($path, $mode);
732
+    }
733
+
734
+    /**
735
+     * @return string
736
+     */
737
+    static public function toTmpFile($path) {
738
+        return self::$defaultInstance->toTmpFile($path);
739
+    }
740
+
741
+    static public function fromTmpFile($tmpFile, $path) {
742
+        return self::$defaultInstance->fromTmpFile($tmpFile, $path);
743
+    }
744
+
745
+    static public function getMimeType($path) {
746
+        return self::$defaultInstance->getMimeType($path);
747
+    }
748
+
749
+    static public function hash($type, $path, $raw = false) {
750
+        return self::$defaultInstance->hash($type, $path, $raw);
751
+    }
752
+
753
+    static public function free_space($path = '/') {
754
+        return self::$defaultInstance->free_space($path);
755
+    }
756
+
757
+    static public function search($query) {
758
+        return self::$defaultInstance->search($query);
759
+    }
760
+
761
+    /**
762
+     * @param string $query
763
+     */
764
+    static public function searchByMime($query) {
765
+        return self::$defaultInstance->searchByMime($query);
766
+    }
767
+
768
+    /**
769
+     * @param string|int $tag name or tag id
770
+     * @param string $userId owner of the tags
771
+     * @return FileInfo[] array or file info
772
+     */
773
+    static public function searchByTag($tag, $userId) {
774
+        return self::$defaultInstance->searchByTag($tag, $userId);
775
+    }
776
+
777
+    /**
778
+     * check if a file or folder has been updated since $time
779
+     *
780
+     * @param string $path
781
+     * @param int $time
782
+     * @return bool
783
+     */
784
+    static public function hasUpdated($path, $time) {
785
+        return self::$defaultInstance->hasUpdated($path, $time);
786
+    }
787
+
788
+    /**
789
+     * Fix common problems with a file path
790
+     *
791
+     * @param string $path
792
+     * @param bool $stripTrailingSlash whether to strip the trailing slash
793
+     * @param bool $isAbsolutePath whether the given path is absolute
794
+     * @param bool $keepUnicode true to disable unicode normalization
795
+     * @return string
796
+     */
797
+    public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
798
+        if (is_null(self::$normalizedPathCache)) {
799
+            self::$normalizedPathCache = new CappedMemoryCache(2048);
800
+        }
801
+
802
+        /**
803
+         * FIXME: This is a workaround for existing classes and files which call
804
+         *        this function with another type than a valid string. This
805
+         *        conversion should get removed as soon as all existing
806
+         *        function calls have been fixed.
807
+         */
808
+        $path = (string)$path;
809
+
810
+        $cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
811
+
812
+        if (isset(self::$normalizedPathCache[$cacheKey])) {
813
+            return self::$normalizedPathCache[$cacheKey];
814
+        }
815
+
816
+        if ($path === '') {
817
+            return '/';
818
+        }
819
+
820
+        //normalize unicode if possible
821
+        if (!$keepUnicode) {
822
+            $path = \OC_Util::normalizeUnicode($path);
823
+        }
824
+
825
+        //add leading slash, if it is already there we strip it anyway
826
+        $path = '/' . $path;
827
+
828
+        $patterns = [
829
+            '/\\\\/s',          // no windows style slashes
830
+            '/\/\.(\/\.)?\//s', // remove '/./'
831
+            '/\/{2,}/s',        // remove sequence of slashes
832
+            '/\/\.$/s',         // remove trailing /.
833
+        ];
834
+
835
+        do {
836
+            $count = 0;
837
+            $path = preg_replace($patterns, '/', $path, -1, $count);
838
+        } while ($count > 0);
839
+
840
+        //remove trailing slash
841
+        if ($stripTrailingSlash && strlen($path) > 1) {
842
+            $path = rtrim($path, '/');
843
+        }
844
+
845
+        self::$normalizedPathCache[$cacheKey] = $path;
846
+
847
+        return $path;
848
+    }
849
+
850
+    /**
851
+     * get the filesystem info
852
+     *
853
+     * @param string $path
854
+     * @param boolean $includeMountPoints whether to add mountpoint sizes,
855
+     * defaults to true
856
+     * @return \OC\Files\FileInfo|bool False if file does not exist
857
+     */
858
+    public static function getFileInfo($path, $includeMountPoints = true) {
859
+        return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
860
+    }
861
+
862
+    /**
863
+     * change file metadata
864
+     *
865
+     * @param string $path
866
+     * @param array $data
867
+     * @return int
868
+     *
869
+     * returns the fileid of the updated file
870
+     */
871
+    public static function putFileInfo($path, $data) {
872
+        return self::$defaultInstance->putFileInfo($path, $data);
873
+    }
874
+
875
+    /**
876
+     * get the content of a directory
877
+     *
878
+     * @param string $directory path under datadirectory
879
+     * @param string $mimetype_filter limit returned content to this mimetype or mimepart
880
+     * @return \OC\Files\FileInfo[]
881
+     */
882
+    public static function getDirectoryContent($directory, $mimetype_filter = '') {
883
+        return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter);
884
+    }
885
+
886
+    /**
887
+     * Get the path of a file by id
888
+     *
889
+     * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
890
+     *
891
+     * @param int $id
892
+     * @throws NotFoundException
893
+     * @return string
894
+     */
895
+    public static function getPath($id) {
896
+        return self::$defaultInstance->getPath($id);
897
+    }
898
+
899
+    /**
900
+     * Get the owner for a file or folder
901
+     *
902
+     * @param string $path
903
+     * @return string
904
+     */
905
+    public static function getOwner($path) {
906
+        return self::$defaultInstance->getOwner($path);
907
+    }
908
+
909
+    /**
910
+     * get the ETag for a file or folder
911
+     *
912
+     * @param string $path
913
+     * @return string
914
+     */
915
+    static public function getETag($path) {
916
+        return self::$defaultInstance->getETag($path);
917
+    }
918 918
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -410,17 +410,17 @@  discard block
 block discarded – undo
410 410
 		$userObject = $userManager->get($user);
411 411
 
412 412
 		if (is_null($userObject)) {
413
-			\OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
413
+			\OCP\Util::writeLog('files', ' Backends provided no user object for '.$user, ILogger::ERROR);
414 414
 			// reset flag, this will make it possible to rethrow the exception if called again
415 415
 			unset(self::$usersSetup[$user]);
416
-			throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
416
+			throw new \OC\User\NoUserException('Backends provided no user object for '.$user);
417 417
 		}
418 418
 
419 419
 		$realUid = $userObject->getUID();
420 420
 		// workaround in case of different casings
421 421
 		if ($user !== $realUid) {
422 422
 			$stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
423
-			\OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
423
+			\OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "'.$realUid.'" got "'.$user.'". Stack: '.$stack, ILogger::WARN);
424 424
 			$user = $realUid;
425 425
 
426 426
 			// again with the correct casing
@@ -453,11 +453,11 @@  discard block
 block discarded – undo
453 453
 		} else {
454 454
 			self::getMountManager()->addMount(new MountPoint(
455 455
 				new NullStorage([]),
456
-				'/' . $user
456
+				'/'.$user
457 457
 			));
458 458
 			self::getMountManager()->addMount(new MountPoint(
459 459
 				new NullStorage([]),
460
-				'/' . $user . '/files'
460
+				'/'.$user.'/files'
461 461
 			));
462 462
 		}
463 463
 		\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
@@ -472,7 +472,7 @@  discard block
 block discarded – undo
472 472
 	private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
473 473
 		if (!self::$listeningForProviders) {
474 474
 			self::$listeningForProviders = true;
475
-			$mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
475
+			$mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function(IMountProvider $provider) use ($userManager) {
476 476
 				foreach (Filesystem::$usersSetup as $user => $setup) {
477 477
 					$userObject = $userManager->get($user);
478 478
 					if ($userObject) {
@@ -567,7 +567,7 @@  discard block
 block discarded – undo
567 567
 	 * @return string
568 568
 	 */
569 569
 	static public function getLocalPath($path) {
570
-		$datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
570
+		$datadir = \OC_User::getHome(\OC_User::getUser()).'/files';
571 571
 		$newpath = $path;
572 572
 		if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
573 573
 			$newpath = substr($path, strlen($datadir));
@@ -584,7 +584,7 @@  discard block
 block discarded – undo
584 584
 	static public function isValidPath($path) {
585 585
 		$path = self::normalizePath($path);
586 586
 		if (!$path || $path[0] !== '/') {
587
-			$path = '/' . $path;
587
+			$path = '/'.$path;
588 588
 		}
589 589
 		if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
590 590
 			return false;
@@ -805,7 +805,7 @@  discard block
 block discarded – undo
805 805
 		 *        conversion should get removed as soon as all existing
806 806
 		 *        function calls have been fixed.
807 807
 		 */
808
-		$path = (string)$path;
808
+		$path = (string) $path;
809 809
 
810 810
 		$cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
811 811
 
@@ -823,13 +823,13 @@  discard block
 block discarded – undo
823 823
 		}
824 824
 
825 825
 		//add leading slash, if it is already there we strip it anyway
826
-		$path = '/' . $path;
826
+		$path = '/'.$path;
827 827
 
828 828
 		$patterns = [
829
-			'/\\\\/s',          // no windows style slashes
829
+			'/\\\\/s', // no windows style slashes
830 830
 			'/\/\.(\/\.)?\//s', // remove '/./'
831
-			'/\/{2,}/s',        // remove sequence of slashes
832
-			'/\/\.$/s',         // remove trailing /.
831
+			'/\/{2,}/s', // remove sequence of slashes
832
+			'/\/\.$/s', // remove trailing /.
833 833
 		];
834 834
 
835 835
 		do {
Please login to merge, or discard this patch.