Passed
Push — master ( 06ae9c...7c30d1 )
by Roeland
13:11 queued 11s
created
lib/private/Files/Mount/MountPoint.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -38,247 +38,247 @@
 block discarded – undo
38 38
 use OCP\ILogger;
39 39
 
40 40
 class MountPoint implements IMountPoint {
41
-	/**
42
-	 * @var \OC\Files\Storage\Storage|null $storage
43
-	 */
44
-	protected $storage = null;
45
-	protected $class;
46
-	protected $storageId;
47
-	protected $rootId = null;
41
+    /**
42
+     * @var \OC\Files\Storage\Storage|null $storage
43
+     */
44
+    protected $storage = null;
45
+    protected $class;
46
+    protected $storageId;
47
+    protected $rootId = null;
48 48
 
49
-	/**
50
-	 * Configuration options for the storage backend
51
-	 *
52
-	 * @var array
53
-	 */
54
-	protected $arguments = [];
55
-	protected $mountPoint;
49
+    /**
50
+     * Configuration options for the storage backend
51
+     *
52
+     * @var array
53
+     */
54
+    protected $arguments = [];
55
+    protected $mountPoint;
56 56
 
57
-	/**
58
-	 * Mount specific options
59
-	 *
60
-	 * @var array
61
-	 */
62
-	protected $mountOptions = [];
57
+    /**
58
+     * Mount specific options
59
+     *
60
+     * @var array
61
+     */
62
+    protected $mountOptions = [];
63 63
 
64
-	/**
65
-	 * @var \OC\Files\Storage\StorageFactory $loader
66
-	 */
67
-	private $loader;
64
+    /**
65
+     * @var \OC\Files\Storage\StorageFactory $loader
66
+     */
67
+    private $loader;
68 68
 
69
-	/**
70
-	 * Specified whether the storage is invalid after failing to
71
-	 * instantiate it.
72
-	 *
73
-	 * @var bool
74
-	 */
75
-	private $invalidStorage = false;
69
+    /**
70
+     * Specified whether the storage is invalid after failing to
71
+     * instantiate it.
72
+     *
73
+     * @var bool
74
+     */
75
+    private $invalidStorage = false;
76 76
 
77
-	/** @var int|null */
78
-	protected $mountId;
77
+    /** @var int|null */
78
+    protected $mountId;
79 79
 
80
-	/**
81
-	 * @param string|\OC\Files\Storage\Storage $storage
82
-	 * @param string $mountpoint
83
-	 * @param array $arguments (optional) configuration for the storage backend
84
-	 * @param \OCP\Files\Storage\IStorageFactory $loader
85
-	 * @param array $mountOptions mount specific options
86
-	 * @param int|null $mountId
87
-	 * @throws \Exception
88
-	 */
89
-	public function __construct($storage, $mountpoint, $arguments = null, $loader = null, $mountOptions = null, $mountId = null) {
90
-		if (is_null($arguments)) {
91
-			$arguments = [];
92
-		}
93
-		if (is_null($loader)) {
94
-			$this->loader = new StorageFactory();
95
-		} else {
96
-			$this->loader = $loader;
97
-		}
80
+    /**
81
+     * @param string|\OC\Files\Storage\Storage $storage
82
+     * @param string $mountpoint
83
+     * @param array $arguments (optional) configuration for the storage backend
84
+     * @param \OCP\Files\Storage\IStorageFactory $loader
85
+     * @param array $mountOptions mount specific options
86
+     * @param int|null $mountId
87
+     * @throws \Exception
88
+     */
89
+    public function __construct($storage, $mountpoint, $arguments = null, $loader = null, $mountOptions = null, $mountId = null) {
90
+        if (is_null($arguments)) {
91
+            $arguments = [];
92
+        }
93
+        if (is_null($loader)) {
94
+            $this->loader = new StorageFactory();
95
+        } else {
96
+            $this->loader = $loader;
97
+        }
98 98
 
99
-		if (!is_null($mountOptions)) {
100
-			$this->mountOptions = $mountOptions;
101
-		}
99
+        if (!is_null($mountOptions)) {
100
+            $this->mountOptions = $mountOptions;
101
+        }
102 102
 
103
-		$mountpoint = $this->formatPath($mountpoint);
104
-		$this->mountPoint = $mountpoint;
105
-		$this->mountId = $mountId;
106
-		if ($storage instanceof Storage) {
107
-			$this->class = get_class($storage);
108
-			$this->storage = $this->loader->wrap($this, $storage);
109
-		} else {
110
-			// Update old classes to new namespace
111
-			if (strpos($storage, 'OC_Filestorage_') !== false) {
112
-				$storage = '\OC\Files\Storage\\' . substr($storage, 15);
113
-			}
114
-			$this->class = $storage;
115
-			$this->arguments = $arguments;
116
-		}
117
-	}
103
+        $mountpoint = $this->formatPath($mountpoint);
104
+        $this->mountPoint = $mountpoint;
105
+        $this->mountId = $mountId;
106
+        if ($storage instanceof Storage) {
107
+            $this->class = get_class($storage);
108
+            $this->storage = $this->loader->wrap($this, $storage);
109
+        } else {
110
+            // Update old classes to new namespace
111
+            if (strpos($storage, 'OC_Filestorage_') !== false) {
112
+                $storage = '\OC\Files\Storage\\' . substr($storage, 15);
113
+            }
114
+            $this->class = $storage;
115
+            $this->arguments = $arguments;
116
+        }
117
+    }
118 118
 
119
-	/**
120
-	 * get complete path to the mount point, relative to data/
121
-	 *
122
-	 * @return string
123
-	 */
124
-	public function getMountPoint() {
125
-		return $this->mountPoint;
126
-	}
119
+    /**
120
+     * get complete path to the mount point, relative to data/
121
+     *
122
+     * @return string
123
+     */
124
+    public function getMountPoint() {
125
+        return $this->mountPoint;
126
+    }
127 127
 
128
-	/**
129
-	 * Sets the mount point path, relative to data/
130
-	 *
131
-	 * @param string $mountPoint new mount point
132
-	 */
133
-	public function setMountPoint($mountPoint) {
134
-		$this->mountPoint = $this->formatPath($mountPoint);
135
-	}
128
+    /**
129
+     * Sets the mount point path, relative to data/
130
+     *
131
+     * @param string $mountPoint new mount point
132
+     */
133
+    public function setMountPoint($mountPoint) {
134
+        $this->mountPoint = $this->formatPath($mountPoint);
135
+    }
136 136
 
137
-	/**
138
-	 * create the storage that is mounted
139
-	 */
140
-	private function createStorage() {
141
-		if ($this->invalidStorage) {
142
-			return;
143
-		}
137
+    /**
138
+     * create the storage that is mounted
139
+     */
140
+    private function createStorage() {
141
+        if ($this->invalidStorage) {
142
+            return;
143
+        }
144 144
 
145
-		if (class_exists($this->class)) {
146
-			try {
147
-				$class = $this->class;
148
-				// prevent recursion by setting the storage before applying wrappers
149
-				$this->storage = new $class($this->arguments);
150
-				$this->storage = $this->loader->wrap($this, $this->storage);
151
-			} catch (\Exception $exception) {
152
-				$this->storage = null;
153
-				$this->invalidStorage = true;
154
-				if ($this->mountPoint === '/') {
155
-					// the root storage could not be initialized, show the user!
156
-					throw new \Exception('The root storage could not be initialized. Please contact your local administrator.', $exception->getCode(), $exception);
157
-				} else {
158
-					\OC::$server->getLogger()->logException($exception, ['level' => ILogger::ERROR]);
159
-				}
160
-				return;
161
-			}
162
-		} else {
163
-			\OCP\Util::writeLog('core', 'storage backend ' . $this->class . ' not found', ILogger::ERROR);
164
-			$this->invalidStorage = true;
165
-			return;
166
-		}
167
-	}
145
+        if (class_exists($this->class)) {
146
+            try {
147
+                $class = $this->class;
148
+                // prevent recursion by setting the storage before applying wrappers
149
+                $this->storage = new $class($this->arguments);
150
+                $this->storage = $this->loader->wrap($this, $this->storage);
151
+            } catch (\Exception $exception) {
152
+                $this->storage = null;
153
+                $this->invalidStorage = true;
154
+                if ($this->mountPoint === '/') {
155
+                    // the root storage could not be initialized, show the user!
156
+                    throw new \Exception('The root storage could not be initialized. Please contact your local administrator.', $exception->getCode(), $exception);
157
+                } else {
158
+                    \OC::$server->getLogger()->logException($exception, ['level' => ILogger::ERROR]);
159
+                }
160
+                return;
161
+            }
162
+        } else {
163
+            \OCP\Util::writeLog('core', 'storage backend ' . $this->class . ' not found', ILogger::ERROR);
164
+            $this->invalidStorage = true;
165
+            return;
166
+        }
167
+    }
168 168
 
169
-	/**
170
-	 * @return \OC\Files\Storage\Storage|null
171
-	 */
172
-	public function getStorage() {
173
-		if (is_null($this->storage)) {
174
-			$this->createStorage();
175
-		}
176
-		return $this->storage;
177
-	}
169
+    /**
170
+     * @return \OC\Files\Storage\Storage|null
171
+     */
172
+    public function getStorage() {
173
+        if (is_null($this->storage)) {
174
+            $this->createStorage();
175
+        }
176
+        return $this->storage;
177
+    }
178 178
 
179
-	/**
180
-	 * @return string
181
-	 */
182
-	public function getStorageId() {
183
-		if (!$this->storageId) {
184
-			if (is_null($this->storage)) {
185
-				$storage = $this->createStorage(); //FIXME: start using exceptions
186
-				if (is_null($storage)) {
187
-					return null;
188
-				}
179
+    /**
180
+     * @return string
181
+     */
182
+    public function getStorageId() {
183
+        if (!$this->storageId) {
184
+            if (is_null($this->storage)) {
185
+                $storage = $this->createStorage(); //FIXME: start using exceptions
186
+                if (is_null($storage)) {
187
+                    return null;
188
+                }
189 189
 
190
-				$this->storage = $storage;
191
-			}
192
-			$this->storageId = $this->storage->getId();
193
-			if (strlen($this->storageId) > 64) {
194
-				$this->storageId = md5($this->storageId);
195
-			}
196
-		}
197
-		return $this->storageId;
198
-	}
190
+                $this->storage = $storage;
191
+            }
192
+            $this->storageId = $this->storage->getId();
193
+            if (strlen($this->storageId) > 64) {
194
+                $this->storageId = md5($this->storageId);
195
+            }
196
+        }
197
+        return $this->storageId;
198
+    }
199 199
 
200
-	/**
201
-	 * @return int
202
-	 */
203
-	public function getNumericStorageId() {
204
-		return $this->getStorage()->getStorageCache()->getNumericId();
205
-	}
200
+    /**
201
+     * @return int
202
+     */
203
+    public function getNumericStorageId() {
204
+        return $this->getStorage()->getStorageCache()->getNumericId();
205
+    }
206 206
 
207
-	/**
208
-	 * @param string $path
209
-	 * @return string
210
-	 */
211
-	public function getInternalPath($path) {
212
-		$path = Filesystem::normalizePath($path, true, false, true);
213
-		if ($this->mountPoint === $path or $this->mountPoint . '/' === $path) {
214
-			$internalPath = '';
215
-		} else {
216
-			$internalPath = substr($path, strlen($this->mountPoint));
217
-		}
218
-		// substr returns false instead of an empty string, we always want a string
219
-		return (string)$internalPath;
220
-	}
207
+    /**
208
+     * @param string $path
209
+     * @return string
210
+     */
211
+    public function getInternalPath($path) {
212
+        $path = Filesystem::normalizePath($path, true, false, true);
213
+        if ($this->mountPoint === $path or $this->mountPoint . '/' === $path) {
214
+            $internalPath = '';
215
+        } else {
216
+            $internalPath = substr($path, strlen($this->mountPoint));
217
+        }
218
+        // substr returns false instead of an empty string, we always want a string
219
+        return (string)$internalPath;
220
+    }
221 221
 
222
-	/**
223
-	 * @param string $path
224
-	 * @return string
225
-	 */
226
-	private function formatPath($path) {
227
-		$path = Filesystem::normalizePath($path);
228
-		if (strlen($path) > 1) {
229
-			$path .= '/';
230
-		}
231
-		return $path;
232
-	}
222
+    /**
223
+     * @param string $path
224
+     * @return string
225
+     */
226
+    private function formatPath($path) {
227
+        $path = Filesystem::normalizePath($path);
228
+        if (strlen($path) > 1) {
229
+            $path .= '/';
230
+        }
231
+        return $path;
232
+    }
233 233
 
234
-	/**
235
-	 * @param callable $wrapper
236
-	 */
237
-	public function wrapStorage($wrapper) {
238
-		$storage = $this->getStorage();
239
-		// storage can be null if it couldn't be initialized
240
-		if ($storage != null) {
241
-			$this->storage = $wrapper($this->mountPoint, $storage, $this);
242
-		}
243
-	}
234
+    /**
235
+     * @param callable $wrapper
236
+     */
237
+    public function wrapStorage($wrapper) {
238
+        $storage = $this->getStorage();
239
+        // storage can be null if it couldn't be initialized
240
+        if ($storage != null) {
241
+            $this->storage = $wrapper($this->mountPoint, $storage, $this);
242
+        }
243
+    }
244 244
 
245
-	/**
246
-	 * Get a mount option
247
-	 *
248
-	 * @param string $name Name of the mount option to get
249
-	 * @param mixed $default Default value for the mount option
250
-	 * @return mixed
251
-	 */
252
-	public function getOption($name, $default) {
253
-		return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
254
-	}
245
+    /**
246
+     * Get a mount option
247
+     *
248
+     * @param string $name Name of the mount option to get
249
+     * @param mixed $default Default value for the mount option
250
+     * @return mixed
251
+     */
252
+    public function getOption($name, $default) {
253
+        return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
254
+    }
255 255
 
256
-	/**
257
-	 * Get all options for the mount
258
-	 *
259
-	 * @return array
260
-	 */
261
-	public function getOptions() {
262
-		return $this->mountOptions;
263
-	}
256
+    /**
257
+     * Get all options for the mount
258
+     *
259
+     * @return array
260
+     */
261
+    public function getOptions() {
262
+        return $this->mountOptions;
263
+    }
264 264
 
265
-	/**
266
-	 * Get the file id of the root of the storage
267
-	 *
268
-	 * @return int
269
-	 */
270
-	public function getStorageRootId() {
271
-		if (is_null($this->rootId) || $this->rootId === -1) {
272
-			$this->rootId = (int)$this->getStorage()->getCache()->getId('');
273
-		}
274
-		return $this->rootId;
275
-	}
265
+    /**
266
+     * Get the file id of the root of the storage
267
+     *
268
+     * @return int
269
+     */
270
+    public function getStorageRootId() {
271
+        if (is_null($this->rootId) || $this->rootId === -1) {
272
+            $this->rootId = (int)$this->getStorage()->getCache()->getId('');
273
+        }
274
+        return $this->rootId;
275
+    }
276 276
 
277
-	public function getMountId() {
278
-		return $this->mountId;
279
-	}
277
+    public function getMountId() {
278
+        return $this->mountId;
279
+    }
280 280
 
281
-	public function getMountType() {
282
-		return '';
283
-	}
281
+    public function getMountType() {
282
+        return '';
283
+    }
284 284
 }
Please login to merge, or discard this patch.
lib/private/Files/Node/Folder.php 2 patches
Indentation   +584 added lines, -584 removed lines patch added patch discarded remove patch
@@ -52,595 +52,595 @@
 block discarded – undo
52 52
 use OCP\IUserManager;
53 53
 
54 54
 class Folder extends Node implements \OCP\Files\Folder {
55
-	/**
56
-	 * Creates a Folder that represents a non-existing path
57
-	 *
58
-	 * @param string $path path
59
-	 * @return string non-existing node class
60
-	 */
61
-	protected function createNonExistingNode($path) {
62
-		return new NonExistingFolder($this->root, $this->view, $path);
63
-	}
64
-
65
-	/**
66
-	 * @param string $path path relative to the folder
67
-	 * @return string
68
-	 * @throws \OCP\Files\NotPermittedException
69
-	 */
70
-	public function getFullPath($path) {
71
-		if (!$this->isValidPath($path)) {
72
-			throw new NotPermittedException('Invalid path');
73
-		}
74
-		return $this->path . $this->normalizePath($path);
75
-	}
76
-
77
-	/**
78
-	 * @param string $path
79
-	 * @return string|null
80
-	 */
81
-	public function getRelativePath($path) {
82
-		if ($this->path === '' or $this->path === '/') {
83
-			return $this->normalizePath($path);
84
-		}
85
-		if ($path === $this->path) {
86
-			return '/';
87
-		} elseif (strpos($path, $this->path . '/') !== 0) {
88
-			return null;
89
-		} else {
90
-			$path = substr($path, strlen($this->path));
91
-			return $this->normalizePath($path);
92
-		}
93
-	}
94
-
95
-	/**
96
-	 * check if a node is a (grand-)child of the folder
97
-	 *
98
-	 * @param \OC\Files\Node\Node $node
99
-	 * @return bool
100
-	 */
101
-	public function isSubNode($node) {
102
-		return strpos($node->getPath(), $this->path . '/') === 0;
103
-	}
104
-
105
-	/**
106
-	 * get the content of this directory
107
-	 *
108
-	 * @return Node[]
109
-	 * @throws \OCP\Files\NotFoundException
110
-	 */
111
-	public function getDirectoryListing() {
112
-		$folderContent = $this->view->getDirectoryContent($this->path);
113
-
114
-		return array_map(function (FileInfo $info) {
115
-			if ($info->getMimetype() === 'httpd/unix-directory') {
116
-				return new Folder($this->root, $this->view, $info->getPath(), $info);
117
-			} else {
118
-				return new File($this->root, $this->view, $info->getPath(), $info);
119
-			}
120
-		}, $folderContent);
121
-	}
122
-
123
-	/**
124
-	 * @param string $path
125
-	 * @param FileInfo $info
126
-	 * @return File|Folder
127
-	 */
128
-	protected function createNode($path, FileInfo $info = null) {
129
-		if (is_null($info)) {
130
-			$isDir = $this->view->is_dir($path);
131
-		} else {
132
-			$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
133
-		}
134
-		if ($isDir) {
135
-			return new Folder($this->root, $this->view, $path, $info);
136
-		} else {
137
-			return new File($this->root, $this->view, $path, $info);
138
-		}
139
-	}
140
-
141
-	/**
142
-	 * Get the node at $path
143
-	 *
144
-	 * @param string $path
145
-	 * @return \OC\Files\Node\Node
146
-	 * @throws \OCP\Files\NotFoundException
147
-	 */
148
-	public function get($path) {
149
-		return $this->root->get($this->getFullPath($path));
150
-	}
151
-
152
-	/**
153
-	 * @param string $path
154
-	 * @return bool
155
-	 */
156
-	public function nodeExists($path) {
157
-		try {
158
-			$this->get($path);
159
-			return true;
160
-		} catch (NotFoundException $e) {
161
-			return false;
162
-		}
163
-	}
164
-
165
-	/**
166
-	 * @param string $path
167
-	 * @return \OC\Files\Node\Folder
168
-	 * @throws \OCP\Files\NotPermittedException
169
-	 */
170
-	public function newFolder($path) {
171
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
172
-			$fullPath = $this->getFullPath($path);
173
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
174
-			$this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
175
-			if (!$this->view->mkdir($fullPath)) {
176
-				throw new NotPermittedException('Could not create folder');
177
-			}
178
-			$node = new Folder($this->root, $this->view, $fullPath);
179
-			$this->sendHooks(['postWrite', 'postCreate'], [$node]);
180
-			return $node;
181
-		} else {
182
-			throw new NotPermittedException('No create permission for folder');
183
-		}
184
-	}
185
-
186
-	/**
187
-	 * @param string $path
188
-	 * @param string | resource | null $content
189
-	 * @return \OC\Files\Node\File
190
-	 * @throws \OCP\Files\NotPermittedException
191
-	 */
192
-	public function newFile($path, $content = null) {
193
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
194
-			$fullPath = $this->getFullPath($path);
195
-			$nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
196
-			$this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
197
-			if ($content !== null) {
198
-				$result = $this->view->file_put_contents($fullPath, $content);
199
-			} else {
200
-				$result = $this->view->touch($fullPath);
201
-			}
202
-			if ($result === false) {
203
-				throw new NotPermittedException('Could not create path');
204
-			}
205
-			$node = new File($this->root, $this->view, $fullPath);
206
-			$this->sendHooks(['postWrite', 'postCreate'], [$node]);
207
-			return $node;
208
-		}
209
-		throw new NotPermittedException('No create permission for path');
210
-	}
211
-
212
-	private function queryFromOperator(ISearchOperator $operator, string $uid = null): ISearchQuery {
213
-		if ($uid === null) {
214
-			$user = null;
215
-		} else {
216
-			/** @var IUserManager $userManager */
217
-			$userManager = \OC::$server->query(IUserManager::class);
218
-			$user = $userManager->get($uid);
219
-		}
220
-		return new SearchQuery($operator, 0, 0, [], $user);
221
-	}
222
-
223
-	/**
224
-	 * search for files with the name matching $query
225
-	 *
226
-	 * @param string|ISearchQuery $query
227
-	 * @return \OC\Files\Node\Node[]
228
-	 */
229
-	public function search($query) {
230
-		if (is_string($query)) {
231
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
232
-		}
233
-
234
-		// Limit+offset for queries with ordering
235
-		//
236
-		// Because we currently can't do ordering between the results from different storages in sql
237
-		// The only way to do ordering is requesting the $limit number of entries from all storages
238
-		// sorting them and returning the first $limit entries.
239
-		//
240
-		// For offset we have the same problem, we don't know how many entries from each storage should be skipped
241
-		// by a given $offset, so instead we query $offset + $limit from each storage and return entries $offset..($offset+$limit)
242
-		// after merging and sorting them.
243
-		//
244
-		// This is suboptimal but because limit and offset tend to be fairly small in real world use cases it should
245
-		// still be significantly better than disabling paging altogether
246
-
247
-		$limitToHome = $query->limitToHome();
248
-		if ($limitToHome && count(explode('/', $this->path)) !== 3) {
249
-			throw new \InvalidArgumentException('searching by owner is only allows on the users home folder');
250
-		}
251
-
252
-		$rootLength = strlen($this->path);
253
-		$mount = $this->root->getMount($this->path);
254
-		$storage = $mount->getStorage();
255
-		$internalPath = $mount->getInternalPath($this->path);
256
-		$internalPath = rtrim($internalPath, '/');
257
-		if ($internalPath !== '') {
258
-			$internalPath = $internalPath . '/';
259
-		}
260
-
261
-		$subQueryLimit = $query->getLimit() > 0 ? $query->getLimit() + $query->getOffset() : 0;
262
-		$rootQuery = new SearchQuery(
263
-			new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
264
-				new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $internalPath . '%'),
265
-				$query->getSearchOperation(),
266
-			]
267
-			),
268
-			$subQueryLimit,
269
-			0,
270
-			$query->getOrder(),
271
-			$query->getUser()
272
-		);
273
-
274
-		$files = [];
275
-
276
-		$cache = $storage->getCache('');
277
-
278
-		$results = $cache->searchQuery($rootQuery);
279
-		foreach ($results as $result) {
280
-			$files[] = $this->cacheEntryToFileInfo($mount, '', $internalPath, $result);
281
-		}
282
-
283
-		if (!$limitToHome) {
284
-			$mounts = $this->root->getMountsIn($this->path);
285
-			foreach ($mounts as $mount) {
286
-				$subQuery = new SearchQuery(
287
-					$query->getSearchOperation(),
288
-					$subQueryLimit,
289
-					0,
290
-					$query->getOrder(),
291
-					$query->getUser()
292
-				);
293
-
294
-				$storage = $mount->getStorage();
295
-				if ($storage) {
296
-					$cache = $storage->getCache('');
297
-
298
-					$relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
299
-					$results = $cache->searchQuery($subQuery);
300
-					foreach ($results as $result) {
301
-						$files[] = $this->cacheEntryToFileInfo($mount, $relativeMountPoint, '', $result);
302
-					}
303
-				}
304
-			}
305
-		}
306
-
307
-		$order = $query->getOrder();
308
-		if ($order) {
309
-			usort($files, function (FileInfo $a,FileInfo  $b) use ($order) {
310
-				foreach ($order as $orderField) {
311
-					$cmp = $orderField->sortFileInfo($a, $b);
312
-					if ($cmp !== 0) {
313
-						return $cmp;
314
-					}
315
-				}
316
-				return 0;
317
-			});
318
-		}
319
-		$files = array_values(array_slice($files, $query->getOffset(), $query->getLimit() > 0 ? $query->getLimit() : null));
320
-
321
-		return array_map(function (FileInfo $file) {
322
-			return $this->createNode($file->getPath(), $file);
323
-		}, $files);
324
-	}
325
-
326
-	private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, string $trimRoot, ICacheEntry $cacheEntry): FileInfo {
327
-		$trimLength = strlen($trimRoot);
328
-		$cacheEntry['internalPath'] = $cacheEntry['path'];
329
-		$cacheEntry['path'] = $appendRoot . substr($cacheEntry['path'], $trimLength);
330
-		return new \OC\Files\FileInfo($this->path . '/' . $cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
331
-	}
332
-
333
-	/**
334
-	 * search for files by mimetype
335
-	 *
336
-	 * @param string $mimetype
337
-	 * @return Node[]
338
-	 */
339
-	public function searchByMime($mimetype) {
340
-		if (strpos($mimetype, '/') === false) {
341
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
342
-		} else {
343
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
344
-		}
345
-		return $this->search($query);
346
-	}
347
-
348
-	/**
349
-	 * search for files by tag
350
-	 *
351
-	 * @param string|int $tag name or tag id
352
-	 * @param string $userId owner of the tags
353
-	 * @return Node[]
354
-	 */
355
-	public function searchByTag($tag, $userId) {
356
-		$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'tagname', $tag), $userId);
357
-		return $this->search($query);
358
-	}
359
-
360
-	/**
361
-	 * @param int $id
362
-	 * @return \OC\Files\Node\Node[]
363
-	 */
364
-	public function getById($id) {
365
-		$mountCache = $this->root->getUserMountCache();
366
-		if (strpos($this->getPath(), '/', 1) > 0) {
367
-			[, $user] = explode('/', $this->getPath());
368
-		} else {
369
-			$user = null;
370
-		}
371
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
372
-		$mounts = $this->root->getMountsIn($this->path);
373
-		$mounts[] = $this->root->getMount($this->path);
374
-		/** @var IMountPoint[] $folderMounts */
375
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
376
-			return $mountPoint->getMountPoint();
377
-		}, $mounts), $mounts);
378
-
379
-		/** @var ICachedMountInfo[] $mountsContainingFile */
380
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
381
-			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
382
-		}));
383
-
384
-		if (count($mountsContainingFile) === 0) {
385
-			if ($user === $this->getAppDataDirectoryName()) {
386
-				return $this->getByIdInRootMount((int)$id);
387
-			}
388
-			return [];
389
-		}
390
-
391
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
392
-			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
393
-			$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
394
-			if (!$cacheEntry) {
395
-				return null;
396
-			}
397
-
398
-			// cache jails will hide the "true" internal path
399
-			$internalPath = ltrim($cachedMountInfo->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
400
-			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
401
-			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
402
-			$absolutePath = rtrim($cachedMountInfo->getMountPoint() . $pathRelativeToMount, '/');
403
-			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
404
-				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
405
-				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
406
-			));
407
-		}, $mountsContainingFile);
408
-
409
-		$nodes = array_filter($nodes);
410
-
411
-		return array_filter($nodes, function (Node $node) {
412
-			return $this->getRelativePath($node->getPath());
413
-		});
414
-	}
415
-
416
-	protected function getAppDataDirectoryName(): string {
417
-		$instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
418
-		return 'appdata_' . $instanceId;
419
-	}
420
-
421
-	/**
422
-	 * In case the path we are currently in is inside the appdata_* folder,
423
-	 * the original getById method does not work, because it can only look inside
424
-	 * the user's mount points. But the user has no mount point for the root storage.
425
-	 *
426
-	 * So in that case we directly check the mount of the root if it contains
427
-	 * the id. If it does we check if the path is inside the path we are working
428
-	 * in.
429
-	 *
430
-	 * @param int $id
431
-	 * @return array
432
-	 */
433
-	protected function getByIdInRootMount(int $id): array {
434
-		$mount = $this->root->getMount('');
435
-		$cacheEntry = $mount->getStorage()->getCache($this->path)->get($id);
436
-		if (!$cacheEntry) {
437
-			return [];
438
-		}
439
-
440
-		$absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
441
-		$currentPath = rtrim($this->path, '/') . '/';
442
-
443
-		if (strpos($absolutePath, $currentPath) !== 0) {
444
-			return [];
445
-		}
446
-
447
-		return [$this->root->createNode(
448
-			$absolutePath, new \OC\Files\FileInfo(
449
-			$absolutePath,
450
-			$mount->getStorage(),
451
-			$cacheEntry->getPath(),
452
-			$cacheEntry,
453
-			$mount
454
-		))];
455
-	}
456
-
457
-	public function getFreeSpace() {
458
-		return $this->view->free_space($this->path);
459
-	}
460
-
461
-	public function delete() {
462
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
463
-			$this->sendHooks(['preDelete']);
464
-			$fileInfo = $this->getFileInfo();
465
-			$this->view->rmdir($this->path);
466
-			$nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
467
-			$this->sendHooks(['postDelete'], [$nonExisting]);
468
-			$this->exists = false;
469
-		} else {
470
-			throw new NotPermittedException('No delete permission for path');
471
-		}
472
-	}
473
-
474
-	/**
475
-	 * Add a suffix to the name in case the file exists
476
-	 *
477
-	 * @param string $name
478
-	 * @return string
479
-	 * @throws NotPermittedException
480
-	 */
481
-	public function getNonExistingName($name) {
482
-		$uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
483
-		return trim($this->getRelativePath($uniqueName), '/');
484
-	}
485
-
486
-	/**
487
-	 * @param int $limit
488
-	 * @param int $offset
489
-	 * @return \OCP\Files\Node[]
490
-	 */
491
-	public function getRecent($limit, $offset = 0) {
492
-		$mimetypeLoader = \OC::$server->getMimeTypeLoader();
493
-		$mounts = $this->root->getMountsIn($this->path);
494
-		$mounts[] = $this->getMountPoint();
495
-
496
-		$mounts = array_filter($mounts, function (IMountPoint $mount) {
497
-			return $mount->getStorage() !== null;
498
-		});
499
-		$storageIds = array_map(function (IMountPoint $mount) {
500
-			return $mount->getStorage()->getCache()->getNumericStorageId();
501
-		}, $mounts);
502
-		/** @var IMountPoint[] $mountMap */
503
-		$mountMap = array_combine($storageIds, $mounts);
504
-		$folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
505
-
506
-		/*
55
+    /**
56
+     * Creates a Folder that represents a non-existing path
57
+     *
58
+     * @param string $path path
59
+     * @return string non-existing node class
60
+     */
61
+    protected function createNonExistingNode($path) {
62
+        return new NonExistingFolder($this->root, $this->view, $path);
63
+    }
64
+
65
+    /**
66
+     * @param string $path path relative to the folder
67
+     * @return string
68
+     * @throws \OCP\Files\NotPermittedException
69
+     */
70
+    public function getFullPath($path) {
71
+        if (!$this->isValidPath($path)) {
72
+            throw new NotPermittedException('Invalid path');
73
+        }
74
+        return $this->path . $this->normalizePath($path);
75
+    }
76
+
77
+    /**
78
+     * @param string $path
79
+     * @return string|null
80
+     */
81
+    public function getRelativePath($path) {
82
+        if ($this->path === '' or $this->path === '/') {
83
+            return $this->normalizePath($path);
84
+        }
85
+        if ($path === $this->path) {
86
+            return '/';
87
+        } elseif (strpos($path, $this->path . '/') !== 0) {
88
+            return null;
89
+        } else {
90
+            $path = substr($path, strlen($this->path));
91
+            return $this->normalizePath($path);
92
+        }
93
+    }
94
+
95
+    /**
96
+     * check if a node is a (grand-)child of the folder
97
+     *
98
+     * @param \OC\Files\Node\Node $node
99
+     * @return bool
100
+     */
101
+    public function isSubNode($node) {
102
+        return strpos($node->getPath(), $this->path . '/') === 0;
103
+    }
104
+
105
+    /**
106
+     * get the content of this directory
107
+     *
108
+     * @return Node[]
109
+     * @throws \OCP\Files\NotFoundException
110
+     */
111
+    public function getDirectoryListing() {
112
+        $folderContent = $this->view->getDirectoryContent($this->path);
113
+
114
+        return array_map(function (FileInfo $info) {
115
+            if ($info->getMimetype() === 'httpd/unix-directory') {
116
+                return new Folder($this->root, $this->view, $info->getPath(), $info);
117
+            } else {
118
+                return new File($this->root, $this->view, $info->getPath(), $info);
119
+            }
120
+        }, $folderContent);
121
+    }
122
+
123
+    /**
124
+     * @param string $path
125
+     * @param FileInfo $info
126
+     * @return File|Folder
127
+     */
128
+    protected function createNode($path, FileInfo $info = null) {
129
+        if (is_null($info)) {
130
+            $isDir = $this->view->is_dir($path);
131
+        } else {
132
+            $isDir = $info->getType() === FileInfo::TYPE_FOLDER;
133
+        }
134
+        if ($isDir) {
135
+            return new Folder($this->root, $this->view, $path, $info);
136
+        } else {
137
+            return new File($this->root, $this->view, $path, $info);
138
+        }
139
+    }
140
+
141
+    /**
142
+     * Get the node at $path
143
+     *
144
+     * @param string $path
145
+     * @return \OC\Files\Node\Node
146
+     * @throws \OCP\Files\NotFoundException
147
+     */
148
+    public function get($path) {
149
+        return $this->root->get($this->getFullPath($path));
150
+    }
151
+
152
+    /**
153
+     * @param string $path
154
+     * @return bool
155
+     */
156
+    public function nodeExists($path) {
157
+        try {
158
+            $this->get($path);
159
+            return true;
160
+        } catch (NotFoundException $e) {
161
+            return false;
162
+        }
163
+    }
164
+
165
+    /**
166
+     * @param string $path
167
+     * @return \OC\Files\Node\Folder
168
+     * @throws \OCP\Files\NotPermittedException
169
+     */
170
+    public function newFolder($path) {
171
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
172
+            $fullPath = $this->getFullPath($path);
173
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath);
174
+            $this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
175
+            if (!$this->view->mkdir($fullPath)) {
176
+                throw new NotPermittedException('Could not create folder');
177
+            }
178
+            $node = new Folder($this->root, $this->view, $fullPath);
179
+            $this->sendHooks(['postWrite', 'postCreate'], [$node]);
180
+            return $node;
181
+        } else {
182
+            throw new NotPermittedException('No create permission for folder');
183
+        }
184
+    }
185
+
186
+    /**
187
+     * @param string $path
188
+     * @param string | resource | null $content
189
+     * @return \OC\Files\Node\File
190
+     * @throws \OCP\Files\NotPermittedException
191
+     */
192
+    public function newFile($path, $content = null) {
193
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
194
+            $fullPath = $this->getFullPath($path);
195
+            $nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
196
+            $this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
197
+            if ($content !== null) {
198
+                $result = $this->view->file_put_contents($fullPath, $content);
199
+            } else {
200
+                $result = $this->view->touch($fullPath);
201
+            }
202
+            if ($result === false) {
203
+                throw new NotPermittedException('Could not create path');
204
+            }
205
+            $node = new File($this->root, $this->view, $fullPath);
206
+            $this->sendHooks(['postWrite', 'postCreate'], [$node]);
207
+            return $node;
208
+        }
209
+        throw new NotPermittedException('No create permission for path');
210
+    }
211
+
212
+    private function queryFromOperator(ISearchOperator $operator, string $uid = null): ISearchQuery {
213
+        if ($uid === null) {
214
+            $user = null;
215
+        } else {
216
+            /** @var IUserManager $userManager */
217
+            $userManager = \OC::$server->query(IUserManager::class);
218
+            $user = $userManager->get($uid);
219
+        }
220
+        return new SearchQuery($operator, 0, 0, [], $user);
221
+    }
222
+
223
+    /**
224
+     * search for files with the name matching $query
225
+     *
226
+     * @param string|ISearchQuery $query
227
+     * @return \OC\Files\Node\Node[]
228
+     */
229
+    public function search($query) {
230
+        if (is_string($query)) {
231
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
232
+        }
233
+
234
+        // Limit+offset for queries with ordering
235
+        //
236
+        // Because we currently can't do ordering between the results from different storages in sql
237
+        // The only way to do ordering is requesting the $limit number of entries from all storages
238
+        // sorting them and returning the first $limit entries.
239
+        //
240
+        // For offset we have the same problem, we don't know how many entries from each storage should be skipped
241
+        // by a given $offset, so instead we query $offset + $limit from each storage and return entries $offset..($offset+$limit)
242
+        // after merging and sorting them.
243
+        //
244
+        // This is suboptimal but because limit and offset tend to be fairly small in real world use cases it should
245
+        // still be significantly better than disabling paging altogether
246
+
247
+        $limitToHome = $query->limitToHome();
248
+        if ($limitToHome && count(explode('/', $this->path)) !== 3) {
249
+            throw new \InvalidArgumentException('searching by owner is only allows on the users home folder');
250
+        }
251
+
252
+        $rootLength = strlen($this->path);
253
+        $mount = $this->root->getMount($this->path);
254
+        $storage = $mount->getStorage();
255
+        $internalPath = $mount->getInternalPath($this->path);
256
+        $internalPath = rtrim($internalPath, '/');
257
+        if ($internalPath !== '') {
258
+            $internalPath = $internalPath . '/';
259
+        }
260
+
261
+        $subQueryLimit = $query->getLimit() > 0 ? $query->getLimit() + $query->getOffset() : 0;
262
+        $rootQuery = new SearchQuery(
263
+            new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
264
+                new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $internalPath . '%'),
265
+                $query->getSearchOperation(),
266
+            ]
267
+            ),
268
+            $subQueryLimit,
269
+            0,
270
+            $query->getOrder(),
271
+            $query->getUser()
272
+        );
273
+
274
+        $files = [];
275
+
276
+        $cache = $storage->getCache('');
277
+
278
+        $results = $cache->searchQuery($rootQuery);
279
+        foreach ($results as $result) {
280
+            $files[] = $this->cacheEntryToFileInfo($mount, '', $internalPath, $result);
281
+        }
282
+
283
+        if (!$limitToHome) {
284
+            $mounts = $this->root->getMountsIn($this->path);
285
+            foreach ($mounts as $mount) {
286
+                $subQuery = new SearchQuery(
287
+                    $query->getSearchOperation(),
288
+                    $subQueryLimit,
289
+                    0,
290
+                    $query->getOrder(),
291
+                    $query->getUser()
292
+                );
293
+
294
+                $storage = $mount->getStorage();
295
+                if ($storage) {
296
+                    $cache = $storage->getCache('');
297
+
298
+                    $relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
299
+                    $results = $cache->searchQuery($subQuery);
300
+                    foreach ($results as $result) {
301
+                        $files[] = $this->cacheEntryToFileInfo($mount, $relativeMountPoint, '', $result);
302
+                    }
303
+                }
304
+            }
305
+        }
306
+
307
+        $order = $query->getOrder();
308
+        if ($order) {
309
+            usort($files, function (FileInfo $a,FileInfo  $b) use ($order) {
310
+                foreach ($order as $orderField) {
311
+                    $cmp = $orderField->sortFileInfo($a, $b);
312
+                    if ($cmp !== 0) {
313
+                        return $cmp;
314
+                    }
315
+                }
316
+                return 0;
317
+            });
318
+        }
319
+        $files = array_values(array_slice($files, $query->getOffset(), $query->getLimit() > 0 ? $query->getLimit() : null));
320
+
321
+        return array_map(function (FileInfo $file) {
322
+            return $this->createNode($file->getPath(), $file);
323
+        }, $files);
324
+    }
325
+
326
+    private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, string $trimRoot, ICacheEntry $cacheEntry): FileInfo {
327
+        $trimLength = strlen($trimRoot);
328
+        $cacheEntry['internalPath'] = $cacheEntry['path'];
329
+        $cacheEntry['path'] = $appendRoot . substr($cacheEntry['path'], $trimLength);
330
+        return new \OC\Files\FileInfo($this->path . '/' . $cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
331
+    }
332
+
333
+    /**
334
+     * search for files by mimetype
335
+     *
336
+     * @param string $mimetype
337
+     * @return Node[]
338
+     */
339
+    public function searchByMime($mimetype) {
340
+        if (strpos($mimetype, '/') === false) {
341
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
342
+        } else {
343
+            $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
344
+        }
345
+        return $this->search($query);
346
+    }
347
+
348
+    /**
349
+     * search for files by tag
350
+     *
351
+     * @param string|int $tag name or tag id
352
+     * @param string $userId owner of the tags
353
+     * @return Node[]
354
+     */
355
+    public function searchByTag($tag, $userId) {
356
+        $query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'tagname', $tag), $userId);
357
+        return $this->search($query);
358
+    }
359
+
360
+    /**
361
+     * @param int $id
362
+     * @return \OC\Files\Node\Node[]
363
+     */
364
+    public function getById($id) {
365
+        $mountCache = $this->root->getUserMountCache();
366
+        if (strpos($this->getPath(), '/', 1) > 0) {
367
+            [, $user] = explode('/', $this->getPath());
368
+        } else {
369
+            $user = null;
370
+        }
371
+        $mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
372
+        $mounts = $this->root->getMountsIn($this->path);
373
+        $mounts[] = $this->root->getMount($this->path);
374
+        /** @var IMountPoint[] $folderMounts */
375
+        $folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
376
+            return $mountPoint->getMountPoint();
377
+        }, $mounts), $mounts);
378
+
379
+        /** @var ICachedMountInfo[] $mountsContainingFile */
380
+        $mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
381
+            return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
382
+        }));
383
+
384
+        if (count($mountsContainingFile) === 0) {
385
+            if ($user === $this->getAppDataDirectoryName()) {
386
+                return $this->getByIdInRootMount((int)$id);
387
+            }
388
+            return [];
389
+        }
390
+
391
+        $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
392
+            $mount = $folderMounts[$cachedMountInfo->getMountPoint()];
393
+            $cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
394
+            if (!$cacheEntry) {
395
+                return null;
396
+            }
397
+
398
+            // cache jails will hide the "true" internal path
399
+            $internalPath = ltrim($cachedMountInfo->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
400
+            $pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
401
+            $pathRelativeToMount = ltrim($pathRelativeToMount, '/');
402
+            $absolutePath = rtrim($cachedMountInfo->getMountPoint() . $pathRelativeToMount, '/');
403
+            return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
404
+                $absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
405
+                \OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
406
+            ));
407
+        }, $mountsContainingFile);
408
+
409
+        $nodes = array_filter($nodes);
410
+
411
+        return array_filter($nodes, function (Node $node) {
412
+            return $this->getRelativePath($node->getPath());
413
+        });
414
+    }
415
+
416
+    protected function getAppDataDirectoryName(): string {
417
+        $instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
418
+        return 'appdata_' . $instanceId;
419
+    }
420
+
421
+    /**
422
+     * In case the path we are currently in is inside the appdata_* folder,
423
+     * the original getById method does not work, because it can only look inside
424
+     * the user's mount points. But the user has no mount point for the root storage.
425
+     *
426
+     * So in that case we directly check the mount of the root if it contains
427
+     * the id. If it does we check if the path is inside the path we are working
428
+     * in.
429
+     *
430
+     * @param int $id
431
+     * @return array
432
+     */
433
+    protected function getByIdInRootMount(int $id): array {
434
+        $mount = $this->root->getMount('');
435
+        $cacheEntry = $mount->getStorage()->getCache($this->path)->get($id);
436
+        if (!$cacheEntry) {
437
+            return [];
438
+        }
439
+
440
+        $absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
441
+        $currentPath = rtrim($this->path, '/') . '/';
442
+
443
+        if (strpos($absolutePath, $currentPath) !== 0) {
444
+            return [];
445
+        }
446
+
447
+        return [$this->root->createNode(
448
+            $absolutePath, new \OC\Files\FileInfo(
449
+            $absolutePath,
450
+            $mount->getStorage(),
451
+            $cacheEntry->getPath(),
452
+            $cacheEntry,
453
+            $mount
454
+        ))];
455
+    }
456
+
457
+    public function getFreeSpace() {
458
+        return $this->view->free_space($this->path);
459
+    }
460
+
461
+    public function delete() {
462
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) {
463
+            $this->sendHooks(['preDelete']);
464
+            $fileInfo = $this->getFileInfo();
465
+            $this->view->rmdir($this->path);
466
+            $nonExisting = new NonExistingFolder($this->root, $this->view, $this->path, $fileInfo);
467
+            $this->sendHooks(['postDelete'], [$nonExisting]);
468
+            $this->exists = false;
469
+        } else {
470
+            throw new NotPermittedException('No delete permission for path');
471
+        }
472
+    }
473
+
474
+    /**
475
+     * Add a suffix to the name in case the file exists
476
+     *
477
+     * @param string $name
478
+     * @return string
479
+     * @throws NotPermittedException
480
+     */
481
+    public function getNonExistingName($name) {
482
+        $uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
483
+        return trim($this->getRelativePath($uniqueName), '/');
484
+    }
485
+
486
+    /**
487
+     * @param int $limit
488
+     * @param int $offset
489
+     * @return \OCP\Files\Node[]
490
+     */
491
+    public function getRecent($limit, $offset = 0) {
492
+        $mimetypeLoader = \OC::$server->getMimeTypeLoader();
493
+        $mounts = $this->root->getMountsIn($this->path);
494
+        $mounts[] = $this->getMountPoint();
495
+
496
+        $mounts = array_filter($mounts, function (IMountPoint $mount) {
497
+            return $mount->getStorage() !== null;
498
+        });
499
+        $storageIds = array_map(function (IMountPoint $mount) {
500
+            return $mount->getStorage()->getCache()->getNumericStorageId();
501
+        }, $mounts);
502
+        /** @var IMountPoint[] $mountMap */
503
+        $mountMap = array_combine($storageIds, $mounts);
504
+        $folderMimetype = $mimetypeLoader->getId(FileInfo::MIMETYPE_FOLDER);
505
+
506
+        /*
507 507
 		 * Construct an array of the storage id with their prefix path
508 508
 		 * This helps us to filter in the final query
509 509
 		 */
510
-		$filters = array_map(function (IMountPoint $mount) {
511
-			$storage = $mount->getStorage();
512
-
513
-			$storageId = $storage->getCache()->getNumericStorageId();
514
-			$prefix = '';
515
-
516
-			if ($storage->instanceOfStorage(Jail::class)) {
517
-				$prefix = $storage->getUnJailedPath('');
518
-			}
519
-
520
-			return [
521
-				'storageId' => $storageId,
522
-				'pathPrefix' => $prefix,
523
-			];
524
-		}, $mounts);
525
-
526
-		// Search in batches of 500 entries
527
-		$searchLimit = 500;
528
-		$results = [];
529
-		$searchResultCount = 0;
530
-		$count = 0;
531
-		do {
532
-			$searchResult = $this->recentSearch($searchLimit, $offset, $folderMimetype, $filters);
533
-
534
-			// Exit condition if there are no more results
535
-			if (count($searchResult) === 0) {
536
-				break;
537
-			}
538
-
539
-			$searchResultCount += count($searchResult);
540
-
541
-			$parseResult = $this->recentParse($searchResult, $mountMap, $mimetypeLoader);
542
-
543
-			foreach ($parseResult as $result) {
544
-				$results[] = $result;
545
-			}
546
-
547
-			$offset += $searchLimit;
548
-			$count++;
549
-		} while (count($results) < $limit && ($searchResultCount < (3 * $limit) || $count < 5));
550
-
551
-		return array_slice($results, 0, $limit);
552
-	}
553
-
554
-	private function recentSearch($limit, $offset, $folderMimetype, $filters) {
555
-		$dbconn = \OC::$server->getDatabaseConnection();
556
-		$builder = $dbconn->getQueryBuilder();
557
-		$query = $builder
558
-			->select('f.*')
559
-			->from('filecache', 'f');
560
-
561
-		/*
510
+        $filters = array_map(function (IMountPoint $mount) {
511
+            $storage = $mount->getStorage();
512
+
513
+            $storageId = $storage->getCache()->getNumericStorageId();
514
+            $prefix = '';
515
+
516
+            if ($storage->instanceOfStorage(Jail::class)) {
517
+                $prefix = $storage->getUnJailedPath('');
518
+            }
519
+
520
+            return [
521
+                'storageId' => $storageId,
522
+                'pathPrefix' => $prefix,
523
+            ];
524
+        }, $mounts);
525
+
526
+        // Search in batches of 500 entries
527
+        $searchLimit = 500;
528
+        $results = [];
529
+        $searchResultCount = 0;
530
+        $count = 0;
531
+        do {
532
+            $searchResult = $this->recentSearch($searchLimit, $offset, $folderMimetype, $filters);
533
+
534
+            // Exit condition if there are no more results
535
+            if (count($searchResult) === 0) {
536
+                break;
537
+            }
538
+
539
+            $searchResultCount += count($searchResult);
540
+
541
+            $parseResult = $this->recentParse($searchResult, $mountMap, $mimetypeLoader);
542
+
543
+            foreach ($parseResult as $result) {
544
+                $results[] = $result;
545
+            }
546
+
547
+            $offset += $searchLimit;
548
+            $count++;
549
+        } while (count($results) < $limit && ($searchResultCount < (3 * $limit) || $count < 5));
550
+
551
+        return array_slice($results, 0, $limit);
552
+    }
553
+
554
+    private function recentSearch($limit, $offset, $folderMimetype, $filters) {
555
+        $dbconn = \OC::$server->getDatabaseConnection();
556
+        $builder = $dbconn->getQueryBuilder();
557
+        $query = $builder
558
+            ->select('f.*')
559
+            ->from('filecache', 'f');
560
+
561
+        /*
562 562
 		 * Here is where we construct the filtering.
563 563
 		 * Note that this is expensive filtering as it is a lot of like queries.
564 564
 		 * However the alternative is we do this filtering and parsing later in php with the risk of looping endlessly
565 565
 		 */
566
-		$storageFilters = $builder->expr()->orX();
567
-		foreach ($filters as $filter) {
568
-			$storageFilter = $builder->expr()->andX(
569
-				$builder->expr()->eq('f.storage', $builder->createNamedParameter($filter['storageId']))
570
-			);
571
-
572
-			if ($filter['pathPrefix'] !== '') {
573
-				$storageFilter->add(
574
-					$builder->expr()->like('f.path', $builder->createNamedParameter($dbconn->escapeLikeParameter($filter['pathPrefix']) . '/%'))
575
-				);
576
-			}
577
-
578
-			$storageFilters->add($storageFilter);
579
-		}
580
-
581
-		$query->andWhere($storageFilters);
582
-
583
-		$query->andWhere($builder->expr()->orX(
584
-		// handle non empty folders separate
585
-			$builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
586
-			$builder->expr()->eq('f.size', new Literal(0))
587
-		))
588
-			->andWhere($builder->expr()->notLike('f.path', $builder->createNamedParameter('files_versions/%')))
589
-			->andWhere($builder->expr()->notLike('f.path', $builder->createNamedParameter('files_trashbin/%')))
590
-			->orderBy('f.mtime', 'DESC')
591
-			->setMaxResults($limit)
592
-			->setFirstResult($offset);
593
-
594
-		$result = $query->execute();
595
-		$rows = $result->fetchAll();
596
-		$result->closeCursor();
597
-
598
-		return $rows;
599
-	}
600
-
601
-	private function recentParse($result, $mountMap, $mimetypeLoader) {
602
-		$files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
603
-			$mount = $mountMap[$entry['storage']];
604
-			$entry['internalPath'] = $entry['path'];
605
-			$entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
606
-			$entry['mimepart'] = $mimetypeLoader->getMimetypeById($entry['mimepart']);
607
-			$path = $this->getAbsolutePath($mount, $entry['path']);
608
-			if (is_null($path)) {
609
-				return null;
610
-			}
611
-			$fileInfo = new \OC\Files\FileInfo($path, $mount->getStorage(), $entry['internalPath'], $entry, $mount);
612
-			return $this->root->createNode($fileInfo->getPath(), $fileInfo);
613
-		}, $result));
614
-
615
-		return array_values(array_filter($files, function (Node $node) {
616
-			$cacheEntry = $node->getMountPoint()->getStorage()->getCache()->get($node->getId());
617
-			if (!$cacheEntry) {
618
-				return false;
619
-			}
620
-			$relative = $this->getRelativePath($node->getPath());
621
-			return $relative !== null && $relative !== '/'
622
-				&& ($cacheEntry->getPermissions() & \OCP\Constants::PERMISSION_READ) === \OCP\Constants::PERMISSION_READ;
623
-		}));
624
-	}
625
-
626
-	private function getAbsolutePath(IMountPoint $mount, $path) {
627
-		$storage = $mount->getStorage();
628
-		if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Jail')) {
629
-			if ($storage->instanceOfStorage(SharedStorage::class)) {
630
-				$storage->getSourceStorage();
631
-			}
632
-			/** @var \OC\Files\Storage\Wrapper\Jail $storage */
633
-			$jailRoot = $storage->getUnjailedPath('');
634
-			$rootLength = strlen($jailRoot) + 1;
635
-			if ($path === $jailRoot) {
636
-				return $mount->getMountPoint();
637
-			} elseif (substr($path, 0, $rootLength) === $jailRoot . '/') {
638
-				return $mount->getMountPoint() . substr($path, $rootLength);
639
-			} else {
640
-				return null;
641
-			}
642
-		} else {
643
-			return $mount->getMountPoint() . $path;
644
-		}
645
-	}
566
+        $storageFilters = $builder->expr()->orX();
567
+        foreach ($filters as $filter) {
568
+            $storageFilter = $builder->expr()->andX(
569
+                $builder->expr()->eq('f.storage', $builder->createNamedParameter($filter['storageId']))
570
+            );
571
+
572
+            if ($filter['pathPrefix'] !== '') {
573
+                $storageFilter->add(
574
+                    $builder->expr()->like('f.path', $builder->createNamedParameter($dbconn->escapeLikeParameter($filter['pathPrefix']) . '/%'))
575
+                );
576
+            }
577
+
578
+            $storageFilters->add($storageFilter);
579
+        }
580
+
581
+        $query->andWhere($storageFilters);
582
+
583
+        $query->andWhere($builder->expr()->orX(
584
+        // handle non empty folders separate
585
+            $builder->expr()->neq('f.mimetype', $builder->createNamedParameter($folderMimetype, IQueryBuilder::PARAM_INT)),
586
+            $builder->expr()->eq('f.size', new Literal(0))
587
+        ))
588
+            ->andWhere($builder->expr()->notLike('f.path', $builder->createNamedParameter('files_versions/%')))
589
+            ->andWhere($builder->expr()->notLike('f.path', $builder->createNamedParameter('files_trashbin/%')))
590
+            ->orderBy('f.mtime', 'DESC')
591
+            ->setMaxResults($limit)
592
+            ->setFirstResult($offset);
593
+
594
+        $result = $query->execute();
595
+        $rows = $result->fetchAll();
596
+        $result->closeCursor();
597
+
598
+        return $rows;
599
+    }
600
+
601
+    private function recentParse($result, $mountMap, $mimetypeLoader) {
602
+        $files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
603
+            $mount = $mountMap[$entry['storage']];
604
+            $entry['internalPath'] = $entry['path'];
605
+            $entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
606
+            $entry['mimepart'] = $mimetypeLoader->getMimetypeById($entry['mimepart']);
607
+            $path = $this->getAbsolutePath($mount, $entry['path']);
608
+            if (is_null($path)) {
609
+                return null;
610
+            }
611
+            $fileInfo = new \OC\Files\FileInfo($path, $mount->getStorage(), $entry['internalPath'], $entry, $mount);
612
+            return $this->root->createNode($fileInfo->getPath(), $fileInfo);
613
+        }, $result));
614
+
615
+        return array_values(array_filter($files, function (Node $node) {
616
+            $cacheEntry = $node->getMountPoint()->getStorage()->getCache()->get($node->getId());
617
+            if (!$cacheEntry) {
618
+                return false;
619
+            }
620
+            $relative = $this->getRelativePath($node->getPath());
621
+            return $relative !== null && $relative !== '/'
622
+                && ($cacheEntry->getPermissions() & \OCP\Constants::PERMISSION_READ) === \OCP\Constants::PERMISSION_READ;
623
+        }));
624
+    }
625
+
626
+    private function getAbsolutePath(IMountPoint $mount, $path) {
627
+        $storage = $mount->getStorage();
628
+        if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Jail')) {
629
+            if ($storage->instanceOfStorage(SharedStorage::class)) {
630
+                $storage->getSourceStorage();
631
+            }
632
+            /** @var \OC\Files\Storage\Wrapper\Jail $storage */
633
+            $jailRoot = $storage->getUnjailedPath('');
634
+            $rootLength = strlen($jailRoot) + 1;
635
+            if ($path === $jailRoot) {
636
+                return $mount->getMountPoint();
637
+            } elseif (substr($path, 0, $rootLength) === $jailRoot . '/') {
638
+                return $mount->getMountPoint() . substr($path, $rootLength);
639
+            } else {
640
+                return null;
641
+            }
642
+        } else {
643
+            return $mount->getMountPoint() . $path;
644
+        }
645
+    }
646 646
 }
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 		if (!$this->isValidPath($path)) {
72 72
 			throw new NotPermittedException('Invalid path');
73 73
 		}
74
-		return $this->path . $this->normalizePath($path);
74
+		return $this->path.$this->normalizePath($path);
75 75
 	}
76 76
 
77 77
 	/**
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
 		}
85 85
 		if ($path === $this->path) {
86 86
 			return '/';
87
-		} elseif (strpos($path, $this->path . '/') !== 0) {
87
+		} elseif (strpos($path, $this->path.'/') !== 0) {
88 88
 			return null;
89 89
 		} else {
90 90
 			$path = substr($path, strlen($this->path));
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
 	 * @return bool
100 100
 	 */
101 101
 	public function isSubNode($node) {
102
-		return strpos($node->getPath(), $this->path . '/') === 0;
102
+		return strpos($node->getPath(), $this->path.'/') === 0;
103 103
 	}
104 104
 
105 105
 	/**
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
 	public function getDirectoryListing() {
112 112
 		$folderContent = $this->view->getDirectoryContent($this->path);
113 113
 
114
-		return array_map(function (FileInfo $info) {
114
+		return array_map(function(FileInfo $info) {
115 115
 			if ($info->getMimetype() === 'httpd/unix-directory') {
116 116
 				return new Folder($this->root, $this->view, $info->getPath(), $info);
117 117
 			} else {
@@ -228,7 +228,7 @@  discard block
 block discarded – undo
228 228
 	 */
229 229
 	public function search($query) {
230 230
 		if (is_string($query)) {
231
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%' . $query . '%'));
231
+			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%'.$query.'%'));
232 232
 		}
233 233
 
234 234
 		// Limit+offset for queries with ordering
@@ -255,13 +255,13 @@  discard block
 block discarded – undo
255 255
 		$internalPath = $mount->getInternalPath($this->path);
256 256
 		$internalPath = rtrim($internalPath, '/');
257 257
 		if ($internalPath !== '') {
258
-			$internalPath = $internalPath . '/';
258
+			$internalPath = $internalPath.'/';
259 259
 		}
260 260
 
261 261
 		$subQueryLimit = $query->getLimit() > 0 ? $query->getLimit() + $query->getOffset() : 0;
262 262
 		$rootQuery = new SearchQuery(
263 263
 			new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
264
-				new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $internalPath . '%'),
264
+				new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $internalPath.'%'),
265 265
 				$query->getSearchOperation(),
266 266
 			]
267 267
 			),
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
 
307 307
 		$order = $query->getOrder();
308 308
 		if ($order) {
309
-			usort($files, function (FileInfo $a,FileInfo  $b) use ($order) {
309
+			usort($files, function(FileInfo $a, FileInfo  $b) use ($order) {
310 310
 				foreach ($order as $orderField) {
311 311
 					$cmp = $orderField->sortFileInfo($a, $b);
312 312
 					if ($cmp !== 0) {
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
 		}
319 319
 		$files = array_values(array_slice($files, $query->getOffset(), $query->getLimit() > 0 ? $query->getLimit() : null));
320 320
 
321
-		return array_map(function (FileInfo $file) {
321
+		return array_map(function(FileInfo $file) {
322 322
 			return $this->createNode($file->getPath(), $file);
323 323
 		}, $files);
324 324
 	}
@@ -326,8 +326,8 @@  discard block
 block discarded – undo
326 326
 	private function cacheEntryToFileInfo(IMountPoint $mount, string $appendRoot, string $trimRoot, ICacheEntry $cacheEntry): FileInfo {
327 327
 		$trimLength = strlen($trimRoot);
328 328
 		$cacheEntry['internalPath'] = $cacheEntry['path'];
329
-		$cacheEntry['path'] = $appendRoot . substr($cacheEntry['path'], $trimLength);
330
-		return new \OC\Files\FileInfo($this->path . '/' . $cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
329
+		$cacheEntry['path'] = $appendRoot.substr($cacheEntry['path'], $trimLength);
330
+		return new \OC\Files\FileInfo($this->path.'/'.$cacheEntry['path'], $mount->getStorage(), $cacheEntry['internalPath'], $cacheEntry, $mount);
331 331
 	}
332 332
 
333 333
 	/**
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
 	 */
339 339
 	public function searchByMime($mimetype) {
340 340
 		if (strpos($mimetype, '/') === false) {
341
-			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype . '/%'));
341
+			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', $mimetype.'/%'));
342 342
 		} else {
343 343
 			$query = $this->queryFromOperator(new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', $mimetype));
344 344
 		}
@@ -368,38 +368,38 @@  discard block
 block discarded – undo
368 368
 		} else {
369 369
 			$user = null;
370 370
 		}
371
-		$mountsContainingFile = $mountCache->getMountsForFileId((int)$id, $user);
371
+		$mountsContainingFile = $mountCache->getMountsForFileId((int) $id, $user);
372 372
 		$mounts = $this->root->getMountsIn($this->path);
373 373
 		$mounts[] = $this->root->getMount($this->path);
374 374
 		/** @var IMountPoint[] $folderMounts */
375
-		$folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) {
375
+		$folderMounts = array_combine(array_map(function(IMountPoint $mountPoint) {
376 376
 			return $mountPoint->getMountPoint();
377 377
 		}, $mounts), $mounts);
378 378
 
379 379
 		/** @var ICachedMountInfo[] $mountsContainingFile */
380
-		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
380
+		$mountsContainingFile = array_values(array_filter($mountsContainingFile, function(ICachedMountInfo $cachedMountInfo) use ($folderMounts) {
381 381
 			return isset($folderMounts[$cachedMountInfo->getMountPoint()]);
382 382
 		}));
383 383
 
384 384
 		if (count($mountsContainingFile) === 0) {
385 385
 			if ($user === $this->getAppDataDirectoryName()) {
386
-				return $this->getByIdInRootMount((int)$id);
386
+				return $this->getByIdInRootMount((int) $id);
387 387
 			}
388 388
 			return [];
389 389
 		}
390 390
 
391
-		$nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
391
+		$nodes = array_map(function(ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
392 392
 			$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
393
-			$cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
393
+			$cacheEntry = $mount->getStorage()->getCache()->get((int) $id);
394 394
 			if (!$cacheEntry) {
395 395
 				return null;
396 396
 			}
397 397
 
398 398
 			// cache jails will hide the "true" internal path
399
-			$internalPath = ltrim($cachedMountInfo->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
399
+			$internalPath = ltrim($cachedMountInfo->getRootInternalPath().'/'.$cacheEntry->getPath(), '/');
400 400
 			$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
401 401
 			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
402
-			$absolutePath = rtrim($cachedMountInfo->getMountPoint() . $pathRelativeToMount, '/');
402
+			$absolutePath = rtrim($cachedMountInfo->getMountPoint().$pathRelativeToMount, '/');
403 403
 			return $this->root->createNode($absolutePath, new \OC\Files\FileInfo(
404 404
 				$absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount,
405 405
 				\OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount))
@@ -408,14 +408,14 @@  discard block
 block discarded – undo
408 408
 
409 409
 		$nodes = array_filter($nodes);
410 410
 
411
-		return array_filter($nodes, function (Node $node) {
411
+		return array_filter($nodes, function(Node $node) {
412 412
 			return $this->getRelativePath($node->getPath());
413 413
 		});
414 414
 	}
415 415
 
416 416
 	protected function getAppDataDirectoryName(): string {
417 417
 		$instanceId = \OC::$server->getConfig()->getSystemValueString('instanceid');
418
-		return 'appdata_' . $instanceId;
418
+		return 'appdata_'.$instanceId;
419 419
 	}
420 420
 
421 421
 	/**
@@ -437,8 +437,8 @@  discard block
 block discarded – undo
437 437
 			return [];
438 438
 		}
439 439
 
440
-		$absolutePath = '/' . ltrim($cacheEntry->getPath(), '/');
441
-		$currentPath = rtrim($this->path, '/') . '/';
440
+		$absolutePath = '/'.ltrim($cacheEntry->getPath(), '/');
441
+		$currentPath = rtrim($this->path, '/').'/';
442 442
 
443 443
 		if (strpos($absolutePath, $currentPath) !== 0) {
444 444
 			return [];
@@ -493,10 +493,10 @@  discard block
 block discarded – undo
493 493
 		$mounts = $this->root->getMountsIn($this->path);
494 494
 		$mounts[] = $this->getMountPoint();
495 495
 
496
-		$mounts = array_filter($mounts, function (IMountPoint $mount) {
496
+		$mounts = array_filter($mounts, function(IMountPoint $mount) {
497 497
 			return $mount->getStorage() !== null;
498 498
 		});
499
-		$storageIds = array_map(function (IMountPoint $mount) {
499
+		$storageIds = array_map(function(IMountPoint $mount) {
500 500
 			return $mount->getStorage()->getCache()->getNumericStorageId();
501 501
 		}, $mounts);
502 502
 		/** @var IMountPoint[] $mountMap */
@@ -507,7 +507,7 @@  discard block
 block discarded – undo
507 507
 		 * Construct an array of the storage id with their prefix path
508 508
 		 * This helps us to filter in the final query
509 509
 		 */
510
-		$filters = array_map(function (IMountPoint $mount) {
510
+		$filters = array_map(function(IMountPoint $mount) {
511 511
 			$storage = $mount->getStorage();
512 512
 
513 513
 			$storageId = $storage->getCache()->getNumericStorageId();
@@ -571,7 +571,7 @@  discard block
 block discarded – undo
571 571
 
572 572
 			if ($filter['pathPrefix'] !== '') {
573 573
 				$storageFilter->add(
574
-					$builder->expr()->like('f.path', $builder->createNamedParameter($dbconn->escapeLikeParameter($filter['pathPrefix']) . '/%'))
574
+					$builder->expr()->like('f.path', $builder->createNamedParameter($dbconn->escapeLikeParameter($filter['pathPrefix']).'/%'))
575 575
 				);
576 576
 			}
577 577
 
@@ -599,7 +599,7 @@  discard block
 block discarded – undo
599 599
 	}
600 600
 
601 601
 	private function recentParse($result, $mountMap, $mimetypeLoader) {
602
-		$files = array_filter(array_map(function (array $entry) use ($mountMap, $mimetypeLoader) {
602
+		$files = array_filter(array_map(function(array $entry) use ($mountMap, $mimetypeLoader) {
603 603
 			$mount = $mountMap[$entry['storage']];
604 604
 			$entry['internalPath'] = $entry['path'];
605 605
 			$entry['mimetype'] = $mimetypeLoader->getMimetypeById($entry['mimetype']);
@@ -612,7 +612,7 @@  discard block
 block discarded – undo
612 612
 			return $this->root->createNode($fileInfo->getPath(), $fileInfo);
613 613
 		}, $result));
614 614
 
615
-		return array_values(array_filter($files, function (Node $node) {
615
+		return array_values(array_filter($files, function(Node $node) {
616 616
 			$cacheEntry = $node->getMountPoint()->getStorage()->getCache()->get($node->getId());
617 617
 			if (!$cacheEntry) {
618 618
 				return false;
@@ -634,13 +634,13 @@  discard block
 block discarded – undo
634 634
 			$rootLength = strlen($jailRoot) + 1;
635 635
 			if ($path === $jailRoot) {
636 636
 				return $mount->getMountPoint();
637
-			} elseif (substr($path, 0, $rootLength) === $jailRoot . '/') {
638
-				return $mount->getMountPoint() . substr($path, $rootLength);
637
+			} elseif (substr($path, 0, $rootLength) === $jailRoot.'/') {
638
+				return $mount->getMountPoint().substr($path, $rootLength);
639 639
 			} else {
640 640
 				return null;
641 641
 			}
642 642
 		} else {
643
-			return $mount->getMountPoint() . $path;
643
+			return $mount->getMountPoint().$path;
644 644
 		}
645 645
 	}
646 646
 }
Please login to merge, or discard this patch.
lib/private/Files/Filesystem.php 1 patch
Indentation   +848 added lines, -848 removed lines patch added patch discarded remove patch
@@ -72,852 +72,852 @@
 block discarded – undo
72 72
 
73 73
 class Filesystem {
74 74
 
75
-	/**
76
-	 * @var Mount\Manager $mounts
77
-	 */
78
-	private static $mounts;
79
-
80
-	public static $loaded = false;
81
-	/**
82
-	 * @var \OC\Files\View $defaultInstance
83
-	 */
84
-	private static $defaultInstance;
85
-
86
-	private static $usersSetup = [];
87
-
88
-	private static $normalizedPathCache = null;
89
-
90
-	private static $listeningForProviders = false;
91
-
92
-	/**
93
-	 * classname which used for hooks handling
94
-	 * used as signalclass in OC_Hooks::emit()
95
-	 */
96
-	public const CLASSNAME = 'OC_Filesystem';
97
-
98
-	/**
99
-	 * signalname emitted before file renaming
100
-	 *
101
-	 * @param string $oldpath
102
-	 * @param string $newpath
103
-	 */
104
-	public const signal_rename = 'rename';
105
-
106
-	/**
107
-	 * signal emitted after file renaming
108
-	 *
109
-	 * @param string $oldpath
110
-	 * @param string $newpath
111
-	 */
112
-	public const signal_post_rename = 'post_rename';
113
-
114
-	/**
115
-	 * signal emitted before file/dir creation
116
-	 *
117
-	 * @param string $path
118
-	 * @param bool $run changing this flag to false in hook handler will cancel event
119
-	 */
120
-	public const signal_create = 'create';
121
-
122
-	/**
123
-	 * signal emitted after file/dir creation
124
-	 *
125
-	 * @param string $path
126
-	 * @param bool $run changing this flag to false in hook handler will cancel event
127
-	 */
128
-	public const signal_post_create = 'post_create';
129
-
130
-	/**
131
-	 * signal emits before file/dir copy
132
-	 *
133
-	 * @param string $oldpath
134
-	 * @param string $newpath
135
-	 * @param bool $run changing this flag to false in hook handler will cancel event
136
-	 */
137
-	public const signal_copy = 'copy';
138
-
139
-	/**
140
-	 * signal emits after file/dir copy
141
-	 *
142
-	 * @param string $oldpath
143
-	 * @param string $newpath
144
-	 */
145
-	public const signal_post_copy = 'post_copy';
146
-
147
-	/**
148
-	 * signal emits before file/dir save
149
-	 *
150
-	 * @param string $path
151
-	 * @param bool $run changing this flag to false in hook handler will cancel event
152
-	 */
153
-	public const signal_write = 'write';
154
-
155
-	/**
156
-	 * signal emits after file/dir save
157
-	 *
158
-	 * @param string $path
159
-	 */
160
-	public const signal_post_write = 'post_write';
161
-
162
-	/**
163
-	 * signal emitted before file/dir update
164
-	 *
165
-	 * @param string $path
166
-	 * @param bool $run changing this flag to false in hook handler will cancel event
167
-	 */
168
-	public const signal_update = 'update';
169
-
170
-	/**
171
-	 * signal emitted after file/dir update
172
-	 *
173
-	 * @param string $path
174
-	 * @param bool $run changing this flag to false in hook handler will cancel event
175
-	 */
176
-	public const signal_post_update = 'post_update';
177
-
178
-	/**
179
-	 * signal emits when reading file/dir
180
-	 *
181
-	 * @param string $path
182
-	 */
183
-	public const signal_read = 'read';
184
-
185
-	/**
186
-	 * signal emits when removing file/dir
187
-	 *
188
-	 * @param string $path
189
-	 */
190
-	public const signal_delete = 'delete';
191
-
192
-	/**
193
-	 * parameters definitions for signals
194
-	 */
195
-	public const signal_param_path = 'path';
196
-	public const signal_param_oldpath = 'oldpath';
197
-	public const signal_param_newpath = 'newpath';
198
-
199
-	/**
200
-	 * run - changing this flag to false in hook handler will cancel event
201
-	 */
202
-	public const signal_param_run = 'run';
203
-
204
-	public const signal_create_mount = 'create_mount';
205
-	public const signal_delete_mount = 'delete_mount';
206
-	public const signal_param_mount_type = 'mounttype';
207
-	public const signal_param_users = 'users';
208
-
209
-	/**
210
-	 * @var \OC\Files\Storage\StorageFactory $loader
211
-	 */
212
-	private static $loader;
213
-
214
-	/** @var bool */
215
-	private static $logWarningWhenAddingStorageWrapper = true;
216
-
217
-	/**
218
-	 * @param bool $shouldLog
219
-	 * @return bool previous value
220
-	 * @internal
221
-	 */
222
-	public static function logWarningWhenAddingStorageWrapper($shouldLog) {
223
-		$previousValue = self::$logWarningWhenAddingStorageWrapper;
224
-		self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
225
-		return $previousValue;
226
-	}
227
-
228
-	/**
229
-	 * @param string $wrapperName
230
-	 * @param callable $wrapper
231
-	 * @param int $priority
232
-	 */
233
-	public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
234
-		if (self::$logWarningWhenAddingStorageWrapper) {
235
-			\OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
236
-				'wrapper' => $wrapperName,
237
-				'app' => 'filesystem',
238
-			]);
239
-		}
240
-
241
-		$mounts = self::getMountManager()->getAll();
242
-		if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
243
-			// do not re-wrap if storage with this name already existed
244
-			return;
245
-		}
246
-	}
247
-
248
-	/**
249
-	 * Returns the storage factory
250
-	 *
251
-	 * @return IStorageFactory
252
-	 */
253
-	public static function getLoader() {
254
-		if (!self::$loader) {
255
-			self::$loader = \OC::$server->query(IStorageFactory::class);
256
-		}
257
-		return self::$loader;
258
-	}
259
-
260
-	/**
261
-	 * Returns the mount manager
262
-	 *
263
-	 * @return \OC\Files\Mount\Manager
264
-	 */
265
-	public static function getMountManager($user = '') {
266
-		if (!self::$mounts) {
267
-			\OC_Util::setupFS($user);
268
-		}
269
-		return self::$mounts;
270
-	}
271
-
272
-	/**
273
-	 * get the mountpoint of the storage object for a path
274
-	 * ( note: because a storage is not always mounted inside the fakeroot, the
275
-	 * returned mountpoint is relative to the absolute root of the filesystem
276
-	 * and doesn't take the chroot into account )
277
-	 *
278
-	 * @param string $path
279
-	 * @return string
280
-	 */
281
-	public static function getMountPoint($path) {
282
-		if (!self::$mounts) {
283
-			\OC_Util::setupFS();
284
-		}
285
-		$mount = self::$mounts->find($path);
286
-		if ($mount) {
287
-			return $mount->getMountPoint();
288
-		} else {
289
-			return '';
290
-		}
291
-	}
292
-
293
-	/**
294
-	 * get a list of all mount points in a directory
295
-	 *
296
-	 * @param string $path
297
-	 * @return string[]
298
-	 */
299
-	public static function getMountPoints($path) {
300
-		if (!self::$mounts) {
301
-			\OC_Util::setupFS();
302
-		}
303
-		$result = [];
304
-		$mounts = self::$mounts->findIn($path);
305
-		foreach ($mounts as $mount) {
306
-			$result[] = $mount->getMountPoint();
307
-		}
308
-		return $result;
309
-	}
310
-
311
-	/**
312
-	 * get the storage mounted at $mountPoint
313
-	 *
314
-	 * @param string $mountPoint
315
-	 * @return \OC\Files\Storage\Storage|null
316
-	 */
317
-	public static function getStorage($mountPoint) {
318
-		if (!self::$mounts) {
319
-			\OC_Util::setupFS();
320
-		}
321
-		$mount = self::$mounts->find($mountPoint);
322
-		return $mount->getStorage();
323
-	}
324
-
325
-	/**
326
-	 * @param string $id
327
-	 * @return Mount\MountPoint[]
328
-	 */
329
-	public static function getMountByStorageId($id) {
330
-		if (!self::$mounts) {
331
-			\OC_Util::setupFS();
332
-		}
333
-		return self::$mounts->findByStorageId($id);
334
-	}
335
-
336
-	/**
337
-	 * @param int $id
338
-	 * @return Mount\MountPoint[]
339
-	 */
340
-	public static function getMountByNumericId($id) {
341
-		if (!self::$mounts) {
342
-			\OC_Util::setupFS();
343
-		}
344
-		return self::$mounts->findByNumericId($id);
345
-	}
346
-
347
-	/**
348
-	 * resolve a path to a storage and internal path
349
-	 *
350
-	 * @param string $path
351
-	 * @return array an array consisting of the storage and the internal path
352
-	 */
353
-	public static function resolvePath($path) {
354
-		if (!self::$mounts) {
355
-			\OC_Util::setupFS();
356
-		}
357
-		$mount = self::$mounts->find($path);
358
-		if ($mount) {
359
-			return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
360
-		} else {
361
-			return [null, null];
362
-		}
363
-	}
364
-
365
-	public static function init($user, $root) {
366
-		if (self::$defaultInstance) {
367
-			return false;
368
-		}
369
-		self::getLoader();
370
-		self::$defaultInstance = new View($root);
371
-
372
-		if (!self::$mounts) {
373
-			self::$mounts = \OC::$server->getMountManager();
374
-		}
375
-
376
-		//load custom mount config
377
-		self::initMountPoints($user);
378
-
379
-		self::$loaded = true;
380
-
381
-		return true;
382
-	}
383
-
384
-	public static function initMountManager() {
385
-		if (!self::$mounts) {
386
-			self::$mounts = \OC::$server->getMountManager();
387
-		}
388
-	}
389
-
390
-	/**
391
-	 * Initialize system and personal mount points for a user
392
-	 *
393
-	 * @param string $user
394
-	 * @throws \OC\User\NoUserException if the user is not available
395
-	 */
396
-	public static function initMountPoints($user = '') {
397
-		if ($user == '') {
398
-			$user = \OC_User::getUser();
399
-		}
400
-		if ($user === null || $user === false || $user === '') {
401
-			throw new \OC\User\NoUserException('Attempted to initialize mount points for null user and no user in session');
402
-		}
403
-
404
-		if (isset(self::$usersSetup[$user])) {
405
-			return;
406
-		}
407
-
408
-		self::$usersSetup[$user] = true;
409
-
410
-		$userManager = \OC::$server->getUserManager();
411
-		$userObject = $userManager->get($user);
412
-
413
-		if (is_null($userObject)) {
414
-			\OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
415
-			// reset flag, this will make it possible to rethrow the exception if called again
416
-			unset(self::$usersSetup[$user]);
417
-			throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
418
-		}
419
-
420
-		$realUid = $userObject->getUID();
421
-		// workaround in case of different casings
422
-		if ($user !== $realUid) {
423
-			$stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
424
-			\OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
425
-			$user = $realUid;
426
-
427
-			// again with the correct casing
428
-			if (isset(self::$usersSetup[$user])) {
429
-				return;
430
-			}
431
-
432
-			self::$usersSetup[$user] = true;
433
-		}
434
-
435
-		if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
436
-			/** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
437
-			$mountConfigManager = \OC::$server->getMountProviderCollection();
438
-
439
-			// home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
440
-			$homeMount = $mountConfigManager->getHomeMountForUser($userObject);
441
-			self::getMountManager()->addMount($homeMount);
442
-
443
-			if ($homeMount->getStorageRootId() === -1) {
444
-				$homeMount->getStorage()->mkdir('');
445
-				$homeMount->getStorage()->getScanner()->scan('');
446
-			}
447
-
448
-			\OC\Files\Filesystem::getStorage($user);
449
-
450
-			// Chance to mount for other storages
451
-			if ($userObject) {
452
-				$mounts = $mountConfigManager->addMountForUser($userObject, self::getMountManager());
453
-				$mounts[] = $homeMount;
454
-				$mountConfigManager->registerMounts($userObject, $mounts);
455
-			}
456
-
457
-			self::listenForNewMountProviders($mountConfigManager, $userManager);
458
-		} else {
459
-			self::getMountManager()->addMount(new MountPoint(
460
-				new NullStorage([]),
461
-				'/' . $user
462
-			));
463
-			self::getMountManager()->addMount(new MountPoint(
464
-				new NullStorage([]),
465
-				'/' . $user . '/files'
466
-			));
467
-		}
468
-		\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
469
-	}
470
-
471
-	/**
472
-	 * Get mounts from mount providers that are registered after setup
473
-	 *
474
-	 * @param MountProviderCollection $mountConfigManager
475
-	 * @param IUserManager $userManager
476
-	 */
477
-	private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
478
-		if (!self::$listeningForProviders) {
479
-			self::$listeningForProviders = true;
480
-			$mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
481
-				foreach (Filesystem::$usersSetup as $user => $setup) {
482
-					$userObject = $userManager->get($user);
483
-					if ($userObject) {
484
-						$mounts = $provider->getMountsForUser($userObject, Filesystem::getLoader());
485
-						array_walk($mounts, [self::$mounts, 'addMount']);
486
-					}
487
-				}
488
-			});
489
-		}
490
-	}
491
-
492
-	/**
493
-	 * get the default filesystem view
494
-	 *
495
-	 * @return View
496
-	 */
497
-	public static function getView() {
498
-		return self::$defaultInstance;
499
-	}
500
-
501
-	/**
502
-	 * tear down the filesystem, removing all storage providers
503
-	 */
504
-	public static function tearDown() {
505
-		self::clearMounts();
506
-		self::$defaultInstance = null;
507
-	}
508
-
509
-	/**
510
-	 * get the relative path of the root data directory for the current user
511
-	 *
512
-	 * @return string
513
-	 *
514
-	 * Returns path like /admin/files
515
-	 */
516
-	public static function getRoot() {
517
-		if (!self::$defaultInstance) {
518
-			return null;
519
-		}
520
-		return self::$defaultInstance->getRoot();
521
-	}
522
-
523
-	/**
524
-	 * clear all mounts and storage backends
525
-	 */
526
-	public static function clearMounts() {
527
-		if (self::$mounts) {
528
-			self::$usersSetup = [];
529
-			self::$mounts->clear();
530
-		}
531
-	}
532
-
533
-	/**
534
-	 * mount an \OC\Files\Storage\Storage in our virtual filesystem
535
-	 *
536
-	 * @param \OC\Files\Storage\Storage|string $class
537
-	 * @param array $arguments
538
-	 * @param string $mountpoint
539
-	 */
540
-	public static function mount($class, $arguments, $mountpoint) {
541
-		if (!self::$mounts) {
542
-			\OC_Util::setupFS();
543
-		}
544
-		$mount = new Mount\MountPoint($class, $mountpoint, $arguments, self::getLoader());
545
-		self::$mounts->addMount($mount);
546
-	}
547
-
548
-	/**
549
-	 * return the path to a local version of the file
550
-	 * we need this because we can't know if a file is stored local or not from
551
-	 * outside the filestorage and for some purposes a local file is needed
552
-	 *
553
-	 * @param string $path
554
-	 * @return string
555
-	 */
556
-	public static function getLocalFile($path) {
557
-		return self::$defaultInstance->getLocalFile($path);
558
-	}
559
-
560
-	/**
561
-	 * @param string $path
562
-	 * @return string
563
-	 */
564
-	public static function getLocalFolder($path) {
565
-		return self::$defaultInstance->getLocalFolder($path);
566
-	}
567
-
568
-	/**
569
-	 * return path to file which reflects one visible in browser
570
-	 *
571
-	 * @param string $path
572
-	 * @return string
573
-	 */
574
-	public static function getLocalPath($path) {
575
-		$datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
576
-		$newpath = $path;
577
-		if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
578
-			$newpath = substr($path, strlen($datadir));
579
-		}
580
-		return $newpath;
581
-	}
582
-
583
-	/**
584
-	 * check if the requested path is valid
585
-	 *
586
-	 * @param string $path
587
-	 * @return bool
588
-	 */
589
-	public static function isValidPath($path) {
590
-		$path = self::normalizePath($path);
591
-		if (!$path || $path[0] !== '/') {
592
-			$path = '/' . $path;
593
-		}
594
-		if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
595
-			return false;
596
-		}
597
-		return true;
598
-	}
599
-
600
-	/**
601
-	 * checks if a file is blacklisted for storage in the filesystem
602
-	 * Listens to write and rename hooks
603
-	 *
604
-	 * @param array $data from hook
605
-	 */
606
-	public static function isBlacklisted($data) {
607
-		if (isset($data['path'])) {
608
-			$path = $data['path'];
609
-		} elseif (isset($data['newpath'])) {
610
-			$path = $data['newpath'];
611
-		}
612
-		if (isset($path)) {
613
-			if (self::isFileBlacklisted($path)) {
614
-				$data['run'] = false;
615
-			}
616
-		}
617
-	}
618
-
619
-	/**
620
-	 * @param string $filename
621
-	 * @return bool
622
-	 */
623
-	public static function isFileBlacklisted($filename) {
624
-		$filename = self::normalizePath($filename);
625
-
626
-		$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
627
-		$filename = strtolower(basename($filename));
628
-		return in_array($filename, $blacklist);
629
-	}
630
-
631
-	/**
632
-	 * check if the directory should be ignored when scanning
633
-	 * NOTE: the special directories . and .. would cause never ending recursion
634
-	 *
635
-	 * @param string $dir
636
-	 * @return boolean
637
-	 */
638
-	public static function isIgnoredDir($dir) {
639
-		if ($dir === '.' || $dir === '..') {
640
-			return true;
641
-		}
642
-		return false;
643
-	}
644
-
645
-	/**
646
-	 * following functions are equivalent to their php builtin equivalents for arguments/return values.
647
-	 */
648
-	public static function mkdir($path) {
649
-		return self::$defaultInstance->mkdir($path);
650
-	}
651
-
652
-	public static function rmdir($path) {
653
-		return self::$defaultInstance->rmdir($path);
654
-	}
655
-
656
-	public static function is_dir($path) {
657
-		return self::$defaultInstance->is_dir($path);
658
-	}
659
-
660
-	public static function is_file($path) {
661
-		return self::$defaultInstance->is_file($path);
662
-	}
663
-
664
-	public static function stat($path) {
665
-		return self::$defaultInstance->stat($path);
666
-	}
667
-
668
-	public static function filetype($path) {
669
-		return self::$defaultInstance->filetype($path);
670
-	}
671
-
672
-	public static function filesize($path) {
673
-		return self::$defaultInstance->filesize($path);
674
-	}
675
-
676
-	public static function readfile($path) {
677
-		return self::$defaultInstance->readfile($path);
678
-	}
679
-
680
-	public static function isCreatable($path) {
681
-		return self::$defaultInstance->isCreatable($path);
682
-	}
683
-
684
-	public static function isReadable($path) {
685
-		return self::$defaultInstance->isReadable($path);
686
-	}
687
-
688
-	public static function isUpdatable($path) {
689
-		return self::$defaultInstance->isUpdatable($path);
690
-	}
691
-
692
-	public static function isDeletable($path) {
693
-		return self::$defaultInstance->isDeletable($path);
694
-	}
695
-
696
-	public static function isSharable($path) {
697
-		return self::$defaultInstance->isSharable($path);
698
-	}
699
-
700
-	public static function file_exists($path) {
701
-		return self::$defaultInstance->file_exists($path);
702
-	}
703
-
704
-	public static function filemtime($path) {
705
-		return self::$defaultInstance->filemtime($path);
706
-	}
707
-
708
-	public static function touch($path, $mtime = null) {
709
-		return self::$defaultInstance->touch($path, $mtime);
710
-	}
711
-
712
-	/**
713
-	 * @return string
714
-	 */
715
-	public static function file_get_contents($path) {
716
-		return self::$defaultInstance->file_get_contents($path);
717
-	}
718
-
719
-	public static function file_put_contents($path, $data) {
720
-		return self::$defaultInstance->file_put_contents($path, $data);
721
-	}
722
-
723
-	public static function unlink($path) {
724
-		return self::$defaultInstance->unlink($path);
725
-	}
726
-
727
-	public static function rename($path1, $path2) {
728
-		return self::$defaultInstance->rename($path1, $path2);
729
-	}
730
-
731
-	public static function copy($path1, $path2) {
732
-		return self::$defaultInstance->copy($path1, $path2);
733
-	}
734
-
735
-	public static function fopen($path, $mode) {
736
-		return self::$defaultInstance->fopen($path, $mode);
737
-	}
738
-
739
-	/**
740
-	 * @return string
741
-	 */
742
-	public static function toTmpFile($path) {
743
-		return self::$defaultInstance->toTmpFile($path);
744
-	}
745
-
746
-	public static function fromTmpFile($tmpFile, $path) {
747
-		return self::$defaultInstance->fromTmpFile($tmpFile, $path);
748
-	}
749
-
750
-	public static function getMimeType($path) {
751
-		return self::$defaultInstance->getMimeType($path);
752
-	}
753
-
754
-	public static function hash($type, $path, $raw = false) {
755
-		return self::$defaultInstance->hash($type, $path, $raw);
756
-	}
757
-
758
-	public static function free_space($path = '/') {
759
-		return self::$defaultInstance->free_space($path);
760
-	}
761
-
762
-	public static function search($query) {
763
-		return self::$defaultInstance->search($query);
764
-	}
765
-
766
-	/**
767
-	 * @param string $query
768
-	 */
769
-	public static function searchByMime($query) {
770
-		return self::$defaultInstance->searchByMime($query);
771
-	}
772
-
773
-	/**
774
-	 * @param string|int $tag name or tag id
775
-	 * @param string $userId owner of the tags
776
-	 * @return FileInfo[] array or file info
777
-	 */
778
-	public static function searchByTag($tag, $userId) {
779
-		return self::$defaultInstance->searchByTag($tag, $userId);
780
-	}
781
-
782
-	/**
783
-	 * check if a file or folder has been updated since $time
784
-	 *
785
-	 * @param string $path
786
-	 * @param int $time
787
-	 * @return bool
788
-	 */
789
-	public static function hasUpdated($path, $time) {
790
-		return self::$defaultInstance->hasUpdated($path, $time);
791
-	}
792
-
793
-	/**
794
-	 * Fix common problems with a file path
795
-	 *
796
-	 * @param string $path
797
-	 * @param bool $stripTrailingSlash whether to strip the trailing slash
798
-	 * @param bool $isAbsolutePath whether the given path is absolute
799
-	 * @param bool $keepUnicode true to disable unicode normalization
800
-	 * @return string
801
-	 */
802
-	public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
803
-		if (is_null(self::$normalizedPathCache)) {
804
-			self::$normalizedPathCache = new CappedMemoryCache(2048);
805
-		}
806
-
807
-		/**
808
-		 * FIXME: This is a workaround for existing classes and files which call
809
-		 *        this function with another type than a valid string. This
810
-		 *        conversion should get removed as soon as all existing
811
-		 *        function calls have been fixed.
812
-		 */
813
-		$path = (string)$path;
814
-
815
-		$cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
816
-
817
-		if ($cacheKey && isset(self::$normalizedPathCache[$cacheKey])) {
818
-			return self::$normalizedPathCache[$cacheKey];
819
-		}
820
-
821
-		if ($path === '') {
822
-			return '/';
823
-		}
824
-
825
-		//normalize unicode if possible
826
-		if (!$keepUnicode) {
827
-			$path = \OC_Util::normalizeUnicode($path);
828
-		}
829
-
830
-		//add leading slash, if it is already there we strip it anyway
831
-		$path = '/' . $path;
832
-
833
-		$patterns = [
834
-			'/\\\\/s',          // no windows style slashes
835
-			'/\/\.(\/\.)?\//s', // remove '/./'
836
-			'/\/{2,}/s',        // remove sequence of slashes
837
-			'/\/\.$/s',         // remove trailing /.
838
-		];
839
-
840
-		do {
841
-			$count = 0;
842
-			$path = preg_replace($patterns, '/', $path, -1, $count);
843
-		} while ($count > 0);
844
-
845
-		//remove trailing slash
846
-		if ($stripTrailingSlash && strlen($path) > 1) {
847
-			$path = rtrim($path, '/');
848
-		}
849
-
850
-		self::$normalizedPathCache[$cacheKey] = $path;
851
-
852
-		return $path;
853
-	}
854
-
855
-	/**
856
-	 * get the filesystem info
857
-	 *
858
-	 * @param string $path
859
-	 * @param boolean $includeMountPoints whether to add mountpoint sizes,
860
-	 * defaults to true
861
-	 * @return \OC\Files\FileInfo|bool False if file does not exist
862
-	 */
863
-	public static function getFileInfo($path, $includeMountPoints = true) {
864
-		return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
865
-	}
866
-
867
-	/**
868
-	 * change file metadata
869
-	 *
870
-	 * @param string $path
871
-	 * @param array $data
872
-	 * @return int
873
-	 *
874
-	 * returns the fileid of the updated file
875
-	 */
876
-	public static function putFileInfo($path, $data) {
877
-		return self::$defaultInstance->putFileInfo($path, $data);
878
-	}
879
-
880
-	/**
881
-	 * get the content of a directory
882
-	 *
883
-	 * @param string $directory path under datadirectory
884
-	 * @param string $mimetype_filter limit returned content to this mimetype or mimepart
885
-	 * @return \OC\Files\FileInfo[]
886
-	 */
887
-	public static function getDirectoryContent($directory, $mimetype_filter = '') {
888
-		return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter);
889
-	}
890
-
891
-	/**
892
-	 * Get the path of a file by id
893
-	 *
894
-	 * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
895
-	 *
896
-	 * @param int $id
897
-	 * @throws NotFoundException
898
-	 * @return string
899
-	 */
900
-	public static function getPath($id) {
901
-		return self::$defaultInstance->getPath($id);
902
-	}
903
-
904
-	/**
905
-	 * Get the owner for a file or folder
906
-	 *
907
-	 * @param string $path
908
-	 * @return string
909
-	 */
910
-	public static function getOwner($path) {
911
-		return self::$defaultInstance->getOwner($path);
912
-	}
913
-
914
-	/**
915
-	 * get the ETag for a file or folder
916
-	 *
917
-	 * @param string $path
918
-	 * @return string
919
-	 */
920
-	public static function getETag($path) {
921
-		return self::$defaultInstance->getETag($path);
922
-	}
75
+    /**
76
+     * @var Mount\Manager $mounts
77
+     */
78
+    private static $mounts;
79
+
80
+    public static $loaded = false;
81
+    /**
82
+     * @var \OC\Files\View $defaultInstance
83
+     */
84
+    private static $defaultInstance;
85
+
86
+    private static $usersSetup = [];
87
+
88
+    private static $normalizedPathCache = null;
89
+
90
+    private static $listeningForProviders = false;
91
+
92
+    /**
93
+     * classname which used for hooks handling
94
+     * used as signalclass in OC_Hooks::emit()
95
+     */
96
+    public const CLASSNAME = 'OC_Filesystem';
97
+
98
+    /**
99
+     * signalname emitted before file renaming
100
+     *
101
+     * @param string $oldpath
102
+     * @param string $newpath
103
+     */
104
+    public const signal_rename = 'rename';
105
+
106
+    /**
107
+     * signal emitted after file renaming
108
+     *
109
+     * @param string $oldpath
110
+     * @param string $newpath
111
+     */
112
+    public const signal_post_rename = 'post_rename';
113
+
114
+    /**
115
+     * signal emitted before file/dir creation
116
+     *
117
+     * @param string $path
118
+     * @param bool $run changing this flag to false in hook handler will cancel event
119
+     */
120
+    public const signal_create = 'create';
121
+
122
+    /**
123
+     * signal emitted after file/dir creation
124
+     *
125
+     * @param string $path
126
+     * @param bool $run changing this flag to false in hook handler will cancel event
127
+     */
128
+    public const signal_post_create = 'post_create';
129
+
130
+    /**
131
+     * signal emits before file/dir copy
132
+     *
133
+     * @param string $oldpath
134
+     * @param string $newpath
135
+     * @param bool $run changing this flag to false in hook handler will cancel event
136
+     */
137
+    public const signal_copy = 'copy';
138
+
139
+    /**
140
+     * signal emits after file/dir copy
141
+     *
142
+     * @param string $oldpath
143
+     * @param string $newpath
144
+     */
145
+    public const signal_post_copy = 'post_copy';
146
+
147
+    /**
148
+     * signal emits before file/dir save
149
+     *
150
+     * @param string $path
151
+     * @param bool $run changing this flag to false in hook handler will cancel event
152
+     */
153
+    public const signal_write = 'write';
154
+
155
+    /**
156
+     * signal emits after file/dir save
157
+     *
158
+     * @param string $path
159
+     */
160
+    public const signal_post_write = 'post_write';
161
+
162
+    /**
163
+     * signal emitted before file/dir update
164
+     *
165
+     * @param string $path
166
+     * @param bool $run changing this flag to false in hook handler will cancel event
167
+     */
168
+    public const signal_update = 'update';
169
+
170
+    /**
171
+     * signal emitted after file/dir update
172
+     *
173
+     * @param string $path
174
+     * @param bool $run changing this flag to false in hook handler will cancel event
175
+     */
176
+    public const signal_post_update = 'post_update';
177
+
178
+    /**
179
+     * signal emits when reading file/dir
180
+     *
181
+     * @param string $path
182
+     */
183
+    public const signal_read = 'read';
184
+
185
+    /**
186
+     * signal emits when removing file/dir
187
+     *
188
+     * @param string $path
189
+     */
190
+    public const signal_delete = 'delete';
191
+
192
+    /**
193
+     * parameters definitions for signals
194
+     */
195
+    public const signal_param_path = 'path';
196
+    public const signal_param_oldpath = 'oldpath';
197
+    public const signal_param_newpath = 'newpath';
198
+
199
+    /**
200
+     * run - changing this flag to false in hook handler will cancel event
201
+     */
202
+    public const signal_param_run = 'run';
203
+
204
+    public const signal_create_mount = 'create_mount';
205
+    public const signal_delete_mount = 'delete_mount';
206
+    public const signal_param_mount_type = 'mounttype';
207
+    public const signal_param_users = 'users';
208
+
209
+    /**
210
+     * @var \OC\Files\Storage\StorageFactory $loader
211
+     */
212
+    private static $loader;
213
+
214
+    /** @var bool */
215
+    private static $logWarningWhenAddingStorageWrapper = true;
216
+
217
+    /**
218
+     * @param bool $shouldLog
219
+     * @return bool previous value
220
+     * @internal
221
+     */
222
+    public static function logWarningWhenAddingStorageWrapper($shouldLog) {
223
+        $previousValue = self::$logWarningWhenAddingStorageWrapper;
224
+        self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
225
+        return $previousValue;
226
+    }
227
+
228
+    /**
229
+     * @param string $wrapperName
230
+     * @param callable $wrapper
231
+     * @param int $priority
232
+     */
233
+    public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
234
+        if (self::$logWarningWhenAddingStorageWrapper) {
235
+            \OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [
236
+                'wrapper' => $wrapperName,
237
+                'app' => 'filesystem',
238
+            ]);
239
+        }
240
+
241
+        $mounts = self::getMountManager()->getAll();
242
+        if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
243
+            // do not re-wrap if storage with this name already existed
244
+            return;
245
+        }
246
+    }
247
+
248
+    /**
249
+     * Returns the storage factory
250
+     *
251
+     * @return IStorageFactory
252
+     */
253
+    public static function getLoader() {
254
+        if (!self::$loader) {
255
+            self::$loader = \OC::$server->query(IStorageFactory::class);
256
+        }
257
+        return self::$loader;
258
+    }
259
+
260
+    /**
261
+     * Returns the mount manager
262
+     *
263
+     * @return \OC\Files\Mount\Manager
264
+     */
265
+    public static function getMountManager($user = '') {
266
+        if (!self::$mounts) {
267
+            \OC_Util::setupFS($user);
268
+        }
269
+        return self::$mounts;
270
+    }
271
+
272
+    /**
273
+     * get the mountpoint of the storage object for a path
274
+     * ( note: because a storage is not always mounted inside the fakeroot, the
275
+     * returned mountpoint is relative to the absolute root of the filesystem
276
+     * and doesn't take the chroot into account )
277
+     *
278
+     * @param string $path
279
+     * @return string
280
+     */
281
+    public static function getMountPoint($path) {
282
+        if (!self::$mounts) {
283
+            \OC_Util::setupFS();
284
+        }
285
+        $mount = self::$mounts->find($path);
286
+        if ($mount) {
287
+            return $mount->getMountPoint();
288
+        } else {
289
+            return '';
290
+        }
291
+    }
292
+
293
+    /**
294
+     * get a list of all mount points in a directory
295
+     *
296
+     * @param string $path
297
+     * @return string[]
298
+     */
299
+    public static function getMountPoints($path) {
300
+        if (!self::$mounts) {
301
+            \OC_Util::setupFS();
302
+        }
303
+        $result = [];
304
+        $mounts = self::$mounts->findIn($path);
305
+        foreach ($mounts as $mount) {
306
+            $result[] = $mount->getMountPoint();
307
+        }
308
+        return $result;
309
+    }
310
+
311
+    /**
312
+     * get the storage mounted at $mountPoint
313
+     *
314
+     * @param string $mountPoint
315
+     * @return \OC\Files\Storage\Storage|null
316
+     */
317
+    public static function getStorage($mountPoint) {
318
+        if (!self::$mounts) {
319
+            \OC_Util::setupFS();
320
+        }
321
+        $mount = self::$mounts->find($mountPoint);
322
+        return $mount->getStorage();
323
+    }
324
+
325
+    /**
326
+     * @param string $id
327
+     * @return Mount\MountPoint[]
328
+     */
329
+    public static function getMountByStorageId($id) {
330
+        if (!self::$mounts) {
331
+            \OC_Util::setupFS();
332
+        }
333
+        return self::$mounts->findByStorageId($id);
334
+    }
335
+
336
+    /**
337
+     * @param int $id
338
+     * @return Mount\MountPoint[]
339
+     */
340
+    public static function getMountByNumericId($id) {
341
+        if (!self::$mounts) {
342
+            \OC_Util::setupFS();
343
+        }
344
+        return self::$mounts->findByNumericId($id);
345
+    }
346
+
347
+    /**
348
+     * resolve a path to a storage and internal path
349
+     *
350
+     * @param string $path
351
+     * @return array an array consisting of the storage and the internal path
352
+     */
353
+    public static function resolvePath($path) {
354
+        if (!self::$mounts) {
355
+            \OC_Util::setupFS();
356
+        }
357
+        $mount = self::$mounts->find($path);
358
+        if ($mount) {
359
+            return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
360
+        } else {
361
+            return [null, null];
362
+        }
363
+    }
364
+
365
+    public static function init($user, $root) {
366
+        if (self::$defaultInstance) {
367
+            return false;
368
+        }
369
+        self::getLoader();
370
+        self::$defaultInstance = new View($root);
371
+
372
+        if (!self::$mounts) {
373
+            self::$mounts = \OC::$server->getMountManager();
374
+        }
375
+
376
+        //load custom mount config
377
+        self::initMountPoints($user);
378
+
379
+        self::$loaded = true;
380
+
381
+        return true;
382
+    }
383
+
384
+    public static function initMountManager() {
385
+        if (!self::$mounts) {
386
+            self::$mounts = \OC::$server->getMountManager();
387
+        }
388
+    }
389
+
390
+    /**
391
+     * Initialize system and personal mount points for a user
392
+     *
393
+     * @param string $user
394
+     * @throws \OC\User\NoUserException if the user is not available
395
+     */
396
+    public static function initMountPoints($user = '') {
397
+        if ($user == '') {
398
+            $user = \OC_User::getUser();
399
+        }
400
+        if ($user === null || $user === false || $user === '') {
401
+            throw new \OC\User\NoUserException('Attempted to initialize mount points for null user and no user in session');
402
+        }
403
+
404
+        if (isset(self::$usersSetup[$user])) {
405
+            return;
406
+        }
407
+
408
+        self::$usersSetup[$user] = true;
409
+
410
+        $userManager = \OC::$server->getUserManager();
411
+        $userObject = $userManager->get($user);
412
+
413
+        if (is_null($userObject)) {
414
+            \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
415
+            // reset flag, this will make it possible to rethrow the exception if called again
416
+            unset(self::$usersSetup[$user]);
417
+            throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
418
+        }
419
+
420
+        $realUid = $userObject->getUID();
421
+        // workaround in case of different casings
422
+        if ($user !== $realUid) {
423
+            $stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
424
+            \OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
425
+            $user = $realUid;
426
+
427
+            // again with the correct casing
428
+            if (isset(self::$usersSetup[$user])) {
429
+                return;
430
+            }
431
+
432
+            self::$usersSetup[$user] = true;
433
+        }
434
+
435
+        if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
436
+            /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
437
+            $mountConfigManager = \OC::$server->getMountProviderCollection();
438
+
439
+            // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
440
+            $homeMount = $mountConfigManager->getHomeMountForUser($userObject);
441
+            self::getMountManager()->addMount($homeMount);
442
+
443
+            if ($homeMount->getStorageRootId() === -1) {
444
+                $homeMount->getStorage()->mkdir('');
445
+                $homeMount->getStorage()->getScanner()->scan('');
446
+            }
447
+
448
+            \OC\Files\Filesystem::getStorage($user);
449
+
450
+            // Chance to mount for other storages
451
+            if ($userObject) {
452
+                $mounts = $mountConfigManager->addMountForUser($userObject, self::getMountManager());
453
+                $mounts[] = $homeMount;
454
+                $mountConfigManager->registerMounts($userObject, $mounts);
455
+            }
456
+
457
+            self::listenForNewMountProviders($mountConfigManager, $userManager);
458
+        } else {
459
+            self::getMountManager()->addMount(new MountPoint(
460
+                new NullStorage([]),
461
+                '/' . $user
462
+            ));
463
+            self::getMountManager()->addMount(new MountPoint(
464
+                new NullStorage([]),
465
+                '/' . $user . '/files'
466
+            ));
467
+        }
468
+        \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
469
+    }
470
+
471
+    /**
472
+     * Get mounts from mount providers that are registered after setup
473
+     *
474
+     * @param MountProviderCollection $mountConfigManager
475
+     * @param IUserManager $userManager
476
+     */
477
+    private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
478
+        if (!self::$listeningForProviders) {
479
+            self::$listeningForProviders = true;
480
+            $mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
481
+                foreach (Filesystem::$usersSetup as $user => $setup) {
482
+                    $userObject = $userManager->get($user);
483
+                    if ($userObject) {
484
+                        $mounts = $provider->getMountsForUser($userObject, Filesystem::getLoader());
485
+                        array_walk($mounts, [self::$mounts, 'addMount']);
486
+                    }
487
+                }
488
+            });
489
+        }
490
+    }
491
+
492
+    /**
493
+     * get the default filesystem view
494
+     *
495
+     * @return View
496
+     */
497
+    public static function getView() {
498
+        return self::$defaultInstance;
499
+    }
500
+
501
+    /**
502
+     * tear down the filesystem, removing all storage providers
503
+     */
504
+    public static function tearDown() {
505
+        self::clearMounts();
506
+        self::$defaultInstance = null;
507
+    }
508
+
509
+    /**
510
+     * get the relative path of the root data directory for the current user
511
+     *
512
+     * @return string
513
+     *
514
+     * Returns path like /admin/files
515
+     */
516
+    public static function getRoot() {
517
+        if (!self::$defaultInstance) {
518
+            return null;
519
+        }
520
+        return self::$defaultInstance->getRoot();
521
+    }
522
+
523
+    /**
524
+     * clear all mounts and storage backends
525
+     */
526
+    public static function clearMounts() {
527
+        if (self::$mounts) {
528
+            self::$usersSetup = [];
529
+            self::$mounts->clear();
530
+        }
531
+    }
532
+
533
+    /**
534
+     * mount an \OC\Files\Storage\Storage in our virtual filesystem
535
+     *
536
+     * @param \OC\Files\Storage\Storage|string $class
537
+     * @param array $arguments
538
+     * @param string $mountpoint
539
+     */
540
+    public static function mount($class, $arguments, $mountpoint) {
541
+        if (!self::$mounts) {
542
+            \OC_Util::setupFS();
543
+        }
544
+        $mount = new Mount\MountPoint($class, $mountpoint, $arguments, self::getLoader());
545
+        self::$mounts->addMount($mount);
546
+    }
547
+
548
+    /**
549
+     * return the path to a local version of the file
550
+     * we need this because we can't know if a file is stored local or not from
551
+     * outside the filestorage and for some purposes a local file is needed
552
+     *
553
+     * @param string $path
554
+     * @return string
555
+     */
556
+    public static function getLocalFile($path) {
557
+        return self::$defaultInstance->getLocalFile($path);
558
+    }
559
+
560
+    /**
561
+     * @param string $path
562
+     * @return string
563
+     */
564
+    public static function getLocalFolder($path) {
565
+        return self::$defaultInstance->getLocalFolder($path);
566
+    }
567
+
568
+    /**
569
+     * return path to file which reflects one visible in browser
570
+     *
571
+     * @param string $path
572
+     * @return string
573
+     */
574
+    public static function getLocalPath($path) {
575
+        $datadir = \OC_User::getHome(\OC_User::getUser()) . '/files';
576
+        $newpath = $path;
577
+        if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
578
+            $newpath = substr($path, strlen($datadir));
579
+        }
580
+        return $newpath;
581
+    }
582
+
583
+    /**
584
+     * check if the requested path is valid
585
+     *
586
+     * @param string $path
587
+     * @return bool
588
+     */
589
+    public static function isValidPath($path) {
590
+        $path = self::normalizePath($path);
591
+        if (!$path || $path[0] !== '/') {
592
+            $path = '/' . $path;
593
+        }
594
+        if (strpos($path, '/../') !== false || strrchr($path, '/') === '/..') {
595
+            return false;
596
+        }
597
+        return true;
598
+    }
599
+
600
+    /**
601
+     * checks if a file is blacklisted for storage in the filesystem
602
+     * Listens to write and rename hooks
603
+     *
604
+     * @param array $data from hook
605
+     */
606
+    public static function isBlacklisted($data) {
607
+        if (isset($data['path'])) {
608
+            $path = $data['path'];
609
+        } elseif (isset($data['newpath'])) {
610
+            $path = $data['newpath'];
611
+        }
612
+        if (isset($path)) {
613
+            if (self::isFileBlacklisted($path)) {
614
+                $data['run'] = false;
615
+            }
616
+        }
617
+    }
618
+
619
+    /**
620
+     * @param string $filename
621
+     * @return bool
622
+     */
623
+    public static function isFileBlacklisted($filename) {
624
+        $filename = self::normalizePath($filename);
625
+
626
+        $blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
627
+        $filename = strtolower(basename($filename));
628
+        return in_array($filename, $blacklist);
629
+    }
630
+
631
+    /**
632
+     * check if the directory should be ignored when scanning
633
+     * NOTE: the special directories . and .. would cause never ending recursion
634
+     *
635
+     * @param string $dir
636
+     * @return boolean
637
+     */
638
+    public static function isIgnoredDir($dir) {
639
+        if ($dir === '.' || $dir === '..') {
640
+            return true;
641
+        }
642
+        return false;
643
+    }
644
+
645
+    /**
646
+     * following functions are equivalent to their php builtin equivalents for arguments/return values.
647
+     */
648
+    public static function mkdir($path) {
649
+        return self::$defaultInstance->mkdir($path);
650
+    }
651
+
652
+    public static function rmdir($path) {
653
+        return self::$defaultInstance->rmdir($path);
654
+    }
655
+
656
+    public static function is_dir($path) {
657
+        return self::$defaultInstance->is_dir($path);
658
+    }
659
+
660
+    public static function is_file($path) {
661
+        return self::$defaultInstance->is_file($path);
662
+    }
663
+
664
+    public static function stat($path) {
665
+        return self::$defaultInstance->stat($path);
666
+    }
667
+
668
+    public static function filetype($path) {
669
+        return self::$defaultInstance->filetype($path);
670
+    }
671
+
672
+    public static function filesize($path) {
673
+        return self::$defaultInstance->filesize($path);
674
+    }
675
+
676
+    public static function readfile($path) {
677
+        return self::$defaultInstance->readfile($path);
678
+    }
679
+
680
+    public static function isCreatable($path) {
681
+        return self::$defaultInstance->isCreatable($path);
682
+    }
683
+
684
+    public static function isReadable($path) {
685
+        return self::$defaultInstance->isReadable($path);
686
+    }
687
+
688
+    public static function isUpdatable($path) {
689
+        return self::$defaultInstance->isUpdatable($path);
690
+    }
691
+
692
+    public static function isDeletable($path) {
693
+        return self::$defaultInstance->isDeletable($path);
694
+    }
695
+
696
+    public static function isSharable($path) {
697
+        return self::$defaultInstance->isSharable($path);
698
+    }
699
+
700
+    public static function file_exists($path) {
701
+        return self::$defaultInstance->file_exists($path);
702
+    }
703
+
704
+    public static function filemtime($path) {
705
+        return self::$defaultInstance->filemtime($path);
706
+    }
707
+
708
+    public static function touch($path, $mtime = null) {
709
+        return self::$defaultInstance->touch($path, $mtime);
710
+    }
711
+
712
+    /**
713
+     * @return string
714
+     */
715
+    public static function file_get_contents($path) {
716
+        return self::$defaultInstance->file_get_contents($path);
717
+    }
718
+
719
+    public static function file_put_contents($path, $data) {
720
+        return self::$defaultInstance->file_put_contents($path, $data);
721
+    }
722
+
723
+    public static function unlink($path) {
724
+        return self::$defaultInstance->unlink($path);
725
+    }
726
+
727
+    public static function rename($path1, $path2) {
728
+        return self::$defaultInstance->rename($path1, $path2);
729
+    }
730
+
731
+    public static function copy($path1, $path2) {
732
+        return self::$defaultInstance->copy($path1, $path2);
733
+    }
734
+
735
+    public static function fopen($path, $mode) {
736
+        return self::$defaultInstance->fopen($path, $mode);
737
+    }
738
+
739
+    /**
740
+     * @return string
741
+     */
742
+    public static function toTmpFile($path) {
743
+        return self::$defaultInstance->toTmpFile($path);
744
+    }
745
+
746
+    public static function fromTmpFile($tmpFile, $path) {
747
+        return self::$defaultInstance->fromTmpFile($tmpFile, $path);
748
+    }
749
+
750
+    public static function getMimeType($path) {
751
+        return self::$defaultInstance->getMimeType($path);
752
+    }
753
+
754
+    public static function hash($type, $path, $raw = false) {
755
+        return self::$defaultInstance->hash($type, $path, $raw);
756
+    }
757
+
758
+    public static function free_space($path = '/') {
759
+        return self::$defaultInstance->free_space($path);
760
+    }
761
+
762
+    public static function search($query) {
763
+        return self::$defaultInstance->search($query);
764
+    }
765
+
766
+    /**
767
+     * @param string $query
768
+     */
769
+    public static function searchByMime($query) {
770
+        return self::$defaultInstance->searchByMime($query);
771
+    }
772
+
773
+    /**
774
+     * @param string|int $tag name or tag id
775
+     * @param string $userId owner of the tags
776
+     * @return FileInfo[] array or file info
777
+     */
778
+    public static function searchByTag($tag, $userId) {
779
+        return self::$defaultInstance->searchByTag($tag, $userId);
780
+    }
781
+
782
+    /**
783
+     * check if a file or folder has been updated since $time
784
+     *
785
+     * @param string $path
786
+     * @param int $time
787
+     * @return bool
788
+     */
789
+    public static function hasUpdated($path, $time) {
790
+        return self::$defaultInstance->hasUpdated($path, $time);
791
+    }
792
+
793
+    /**
794
+     * Fix common problems with a file path
795
+     *
796
+     * @param string $path
797
+     * @param bool $stripTrailingSlash whether to strip the trailing slash
798
+     * @param bool $isAbsolutePath whether the given path is absolute
799
+     * @param bool $keepUnicode true to disable unicode normalization
800
+     * @return string
801
+     */
802
+    public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
803
+        if (is_null(self::$normalizedPathCache)) {
804
+            self::$normalizedPathCache = new CappedMemoryCache(2048);
805
+        }
806
+
807
+        /**
808
+         * FIXME: This is a workaround for existing classes and files which call
809
+         *        this function with another type than a valid string. This
810
+         *        conversion should get removed as soon as all existing
811
+         *        function calls have been fixed.
812
+         */
813
+        $path = (string)$path;
814
+
815
+        $cacheKey = json_encode([$path, $stripTrailingSlash, $isAbsolutePath, $keepUnicode]);
816
+
817
+        if ($cacheKey && isset(self::$normalizedPathCache[$cacheKey])) {
818
+            return self::$normalizedPathCache[$cacheKey];
819
+        }
820
+
821
+        if ($path === '') {
822
+            return '/';
823
+        }
824
+
825
+        //normalize unicode if possible
826
+        if (!$keepUnicode) {
827
+            $path = \OC_Util::normalizeUnicode($path);
828
+        }
829
+
830
+        //add leading slash, if it is already there we strip it anyway
831
+        $path = '/' . $path;
832
+
833
+        $patterns = [
834
+            '/\\\\/s',          // no windows style slashes
835
+            '/\/\.(\/\.)?\//s', // remove '/./'
836
+            '/\/{2,}/s',        // remove sequence of slashes
837
+            '/\/\.$/s',         // remove trailing /.
838
+        ];
839
+
840
+        do {
841
+            $count = 0;
842
+            $path = preg_replace($patterns, '/', $path, -1, $count);
843
+        } while ($count > 0);
844
+
845
+        //remove trailing slash
846
+        if ($stripTrailingSlash && strlen($path) > 1) {
847
+            $path = rtrim($path, '/');
848
+        }
849
+
850
+        self::$normalizedPathCache[$cacheKey] = $path;
851
+
852
+        return $path;
853
+    }
854
+
855
+    /**
856
+     * get the filesystem info
857
+     *
858
+     * @param string $path
859
+     * @param boolean $includeMountPoints whether to add mountpoint sizes,
860
+     * defaults to true
861
+     * @return \OC\Files\FileInfo|bool False if file does not exist
862
+     */
863
+    public static function getFileInfo($path, $includeMountPoints = true) {
864
+        return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
865
+    }
866
+
867
+    /**
868
+     * change file metadata
869
+     *
870
+     * @param string $path
871
+     * @param array $data
872
+     * @return int
873
+     *
874
+     * returns the fileid of the updated file
875
+     */
876
+    public static function putFileInfo($path, $data) {
877
+        return self::$defaultInstance->putFileInfo($path, $data);
878
+    }
879
+
880
+    /**
881
+     * get the content of a directory
882
+     *
883
+     * @param string $directory path under datadirectory
884
+     * @param string $mimetype_filter limit returned content to this mimetype or mimepart
885
+     * @return \OC\Files\FileInfo[]
886
+     */
887
+    public static function getDirectoryContent($directory, $mimetype_filter = '') {
888
+        return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter);
889
+    }
890
+
891
+    /**
892
+     * Get the path of a file by id
893
+     *
894
+     * Note that the resulting path is not guaranteed to be unique for the id, multiple paths can point to the same file
895
+     *
896
+     * @param int $id
897
+     * @throws NotFoundException
898
+     * @return string
899
+     */
900
+    public static function getPath($id) {
901
+        return self::$defaultInstance->getPath($id);
902
+    }
903
+
904
+    /**
905
+     * Get the owner for a file or folder
906
+     *
907
+     * @param string $path
908
+     * @return string
909
+     */
910
+    public static function getOwner($path) {
911
+        return self::$defaultInstance->getOwner($path);
912
+    }
913
+
914
+    /**
915
+     * get the ETag for a file or folder
916
+     *
917
+     * @param string $path
918
+     * @return string
919
+     */
920
+    public static function getETag($path) {
921
+        return self::$defaultInstance->getETag($path);
922
+    }
923 923
 }
Please login to merge, or discard this patch.
lib/private/Search/Result/File.php 1 patch
Indentation   +101 added lines, -101 removed lines patch added patch discarded remove patch
@@ -38,116 +38,116 @@
 block discarded – undo
38 38
  */
39 39
 class File extends \OCP\Search\Result {
40 40
 
41
-	/**
42
-	 * Type name; translated in templates
43
-	 * @var string
44
-	 * @deprecated 20.0.0
45
-	 */
46
-	public $type = 'file';
41
+    /**
42
+     * Type name; translated in templates
43
+     * @var string
44
+     * @deprecated 20.0.0
45
+     */
46
+    public $type = 'file';
47 47
 
48
-	/**
49
-	 * Path to file
50
-	 * @var string
51
-	 * @deprecated 20.0.0
52
-	 */
53
-	public $path;
48
+    /**
49
+     * Path to file
50
+     * @var string
51
+     * @deprecated 20.0.0
52
+     */
53
+    public $path;
54 54
 
55
-	/**
56
-	 * Size, in bytes
57
-	 * @var int
58
-	 * @deprecated 20.0.0
59
-	 */
60
-	public $size;
55
+    /**
56
+     * Size, in bytes
57
+     * @var int
58
+     * @deprecated 20.0.0
59
+     */
60
+    public $size;
61 61
 
62
-	/**
63
-	 * Date modified, in human readable form
64
-	 * @var string
65
-	 * @deprecated 20.0.0
66
-	 */
67
-	public $modified;
62
+    /**
63
+     * Date modified, in human readable form
64
+     * @var string
65
+     * @deprecated 20.0.0
66
+     */
67
+    public $modified;
68 68
 
69
-	/**
70
-	 * File mime type
71
-	 * @var string
72
-	 * @deprecated 20.0.0
73
-	 */
74
-	public $mime_type;
69
+    /**
70
+     * File mime type
71
+     * @var string
72
+     * @deprecated 20.0.0
73
+     */
74
+    public $mime_type;
75 75
 
76
-	/**
77
-	 * File permissions:
78
-	 *
79
-	 * @var string
80
-	 * @deprecated 20.0.0
81
-	 */
82
-	public $permissions;
76
+    /**
77
+     * File permissions:
78
+     *
79
+     * @var string
80
+     * @deprecated 20.0.0
81
+     */
82
+    public $permissions;
83 83
 
84
-	/**
85
-	 * Has a preview
86
-	 *
87
-	 * @var string
88
-	 * @deprecated 20.0.0
89
-	 */
90
-	public $has_preview;
84
+    /**
85
+     * Has a preview
86
+     *
87
+     * @var string
88
+     * @deprecated 20.0.0
89
+     */
90
+    public $has_preview;
91 91
 
92
-	/**
93
-	 * Create a new file search result
94
-	 * @param FileInfo $data file data given by provider
95
-	 * @deprecated 20.0.0
96
-	 */
97
-	public function __construct(FileInfo $data) {
98
-		$path = $this->getRelativePath($data->getPath());
92
+    /**
93
+     * Create a new file search result
94
+     * @param FileInfo $data file data given by provider
95
+     * @deprecated 20.0.0
96
+     */
97
+    public function __construct(FileInfo $data) {
98
+        $path = $this->getRelativePath($data->getPath());
99 99
 
100
-		$this->id = $data->getId();
101
-		$this->name = $data->getName();
102
-		$this->link = \OC::$server->getURLGenerator()->linkToRoute(
103
-			'files.view.index',
104
-			[
105
-				'dir' => dirname($path),
106
-				'scrollto' => $data->getName(),
107
-			]
108
-		);
109
-		$this->permissions = $data->getPermissions();
110
-		$this->path = $path;
111
-		$this->size = $data->getSize();
112
-		$this->modified = $data->getMtime();
113
-		$this->mime_type = $data->getMimetype();
114
-		$this->has_preview = $this->hasPreview($data);
115
-	}
100
+        $this->id = $data->getId();
101
+        $this->name = $data->getName();
102
+        $this->link = \OC::$server->getURLGenerator()->linkToRoute(
103
+            'files.view.index',
104
+            [
105
+                'dir' => dirname($path),
106
+                'scrollto' => $data->getName(),
107
+            ]
108
+        );
109
+        $this->permissions = $data->getPermissions();
110
+        $this->path = $path;
111
+        $this->size = $data->getSize();
112
+        $this->modified = $data->getMtime();
113
+        $this->mime_type = $data->getMimetype();
114
+        $this->has_preview = $this->hasPreview($data);
115
+    }
116 116
 
117
-	/**
118
-	 * @var Folder $userFolderCache
119
-	 * @deprecated 20.0.0
120
-	 */
121
-	protected static $userFolderCache = null;
117
+    /**
118
+     * @var Folder $userFolderCache
119
+     * @deprecated 20.0.0
120
+     */
121
+    protected static $userFolderCache = null;
122 122
 
123
-	/**
124
-	 * converts a path relative to the users files folder
125
-	 * eg /user/files/foo.txt -> /foo.txt
126
-	 * @param string $path
127
-	 * @return string relative path
128
-	 * @deprecated 20.0.0
129
-	 */
130
-	protected function getRelativePath($path) {
131
-		if (!isset(self::$userFolderCache)) {
132
-			$userSession = \OC::$server->get(IUserSession::class);
133
-			$userID = $userSession->getUser()->getUID();
134
-			self::$userFolderCache = \OC::$server->getUserFolder($userID);
135
-		}
136
-		$relativePath = self::$userFolderCache->getRelativePath($path);
137
-		if ($relativePath === null) {
138
-			throw new \Exception("Search result not in user folder");
139
-		}
140
-		return $relativePath;
141
-	}
123
+    /**
124
+     * converts a path relative to the users files folder
125
+     * eg /user/files/foo.txt -> /foo.txt
126
+     * @param string $path
127
+     * @return string relative path
128
+     * @deprecated 20.0.0
129
+     */
130
+    protected function getRelativePath($path) {
131
+        if (!isset(self::$userFolderCache)) {
132
+            $userSession = \OC::$server->get(IUserSession::class);
133
+            $userID = $userSession->getUser()->getUID();
134
+            self::$userFolderCache = \OC::$server->getUserFolder($userID);
135
+        }
136
+        $relativePath = self::$userFolderCache->getRelativePath($path);
137
+        if ($relativePath === null) {
138
+            throw new \Exception("Search result not in user folder");
139
+        }
140
+        return $relativePath;
141
+    }
142 142
 
143
-	/**
144
-	 * Is the preview available
145
-	 * @param FileInfo $data
146
-	 * @return bool
147
-	 * @deprecated 20.0.0
148
-	 */
149
-	protected function hasPreview($data) {
150
-		$previewManager = \OC::$server->get(IPreview::class);
151
-		return $previewManager->isAvailable($data);
152
-	}
143
+    /**
144
+     * Is the preview available
145
+     * @param FileInfo $data
146
+     * @return bool
147
+     * @deprecated 20.0.0
148
+     */
149
+    protected function hasPreview($data) {
150
+        $previewManager = \OC::$server->get(IPreview::class);
151
+        return $previewManager->isAvailable($data);
152
+    }
153 153
 }
Please login to merge, or discard this patch.
lib/public/Files/Mount/IMountPoint.php 1 patch
Indentation   +88 added lines, -88 removed lines patch added patch discarded remove patch
@@ -29,103 +29,103 @@
 block discarded – undo
29 29
  */
30 30
 interface IMountPoint {
31 31
 
32
-	/**
33
-	 * get complete path to the mount point
34
-	 *
35
-	 * @return string
36
-	 * @since 8.0.0
37
-	 */
38
-	public function getMountPoint();
32
+    /**
33
+     * get complete path to the mount point
34
+     *
35
+     * @return string
36
+     * @since 8.0.0
37
+     */
38
+    public function getMountPoint();
39 39
 
40
-	/**
41
-	 * Set the mountpoint
42
-	 *
43
-	 * @param string $mountPoint new mount point
44
-	 * @since 8.0.0
45
-	 */
46
-	public function setMountPoint($mountPoint);
40
+    /**
41
+     * Set the mountpoint
42
+     *
43
+     * @param string $mountPoint new mount point
44
+     * @since 8.0.0
45
+     */
46
+    public function setMountPoint($mountPoint);
47 47
 
48
-	/**
49
-	 * Get the storage that is mounted
50
-	 *
51
-	 * @return \OC\Files\Storage\Storage|null
52
-	 * @since 8.0.0
53
-	 */
54
-	public function getStorage();
48
+    /**
49
+     * Get the storage that is mounted
50
+     *
51
+     * @return \OC\Files\Storage\Storage|null
52
+     * @since 8.0.0
53
+     */
54
+    public function getStorage();
55 55
 
56
-	/**
57
-	 * Get the id of the storages
58
-	 *
59
-	 * @return string
60
-	 * @since 8.0.0
61
-	 */
62
-	public function getStorageId();
56
+    /**
57
+     * Get the id of the storages
58
+     *
59
+     * @return string
60
+     * @since 8.0.0
61
+     */
62
+    public function getStorageId();
63 63
 
64
-	/**
65
-	 * Get the id of the storages
66
-	 *
67
-	 * @return int
68
-	 * @since 9.1.0
69
-	 */
70
-	public function getNumericStorageId();
64
+    /**
65
+     * Get the id of the storages
66
+     *
67
+     * @return int
68
+     * @since 9.1.0
69
+     */
70
+    public function getNumericStorageId();
71 71
 
72
-	/**
73
-	 * Get the path relative to the mountpoint
74
-	 *
75
-	 * @param string $path absolute path to a file or folder
76
-	 * @return string
77
-	 * @since 8.0.0
78
-	 */
79
-	public function getInternalPath($path);
72
+    /**
73
+     * Get the path relative to the mountpoint
74
+     *
75
+     * @param string $path absolute path to a file or folder
76
+     * @return string
77
+     * @since 8.0.0
78
+     */
79
+    public function getInternalPath($path);
80 80
 
81
-	/**
82
-	 * Apply a storage wrapper to the mounted storage
83
-	 *
84
-	 * @param callable $wrapper
85
-	 * @since 8.0.0
86
-	 */
87
-	public function wrapStorage($wrapper);
81
+    /**
82
+     * Apply a storage wrapper to the mounted storage
83
+     *
84
+     * @param callable $wrapper
85
+     * @since 8.0.0
86
+     */
87
+    public function wrapStorage($wrapper);
88 88
 
89
-	/**
90
-	 * Get a mount option
91
-	 *
92
-	 * @param string $name Name of the mount option to get
93
-	 * @param mixed $default Default value for the mount option
94
-	 * @return mixed
95
-	 * @since 8.0.0
96
-	 */
97
-	public function getOption($name, $default);
89
+    /**
90
+     * Get a mount option
91
+     *
92
+     * @param string $name Name of the mount option to get
93
+     * @param mixed $default Default value for the mount option
94
+     * @return mixed
95
+     * @since 8.0.0
96
+     */
97
+    public function getOption($name, $default);
98 98
 
99
-	/**
100
-	 * Get all options for the mount
101
-	 *
102
-	 * @return array
103
-	 * @since 8.1.0
104
-	 */
105
-	public function getOptions();
99
+    /**
100
+     * Get all options for the mount
101
+     *
102
+     * @return array
103
+     * @since 8.1.0
104
+     */
105
+    public function getOptions();
106 106
 
107
-	/**
108
-	 * Get the file id of the root of the storage
109
-	 *
110
-	 * @return int
111
-	 * @since 9.1.0
112
-	 */
113
-	public function getStorageRootId();
107
+    /**
108
+     * Get the file id of the root of the storage
109
+     *
110
+     * @return int
111
+     * @since 9.1.0
112
+     */
113
+    public function getStorageRootId();
114 114
 
115
-	/**
116
-	 * Get the id of the configured mount
117
-	 *
118
-	 * @return int|null mount id or null if not applicable
119
-	 * @since 9.1.0
120
-	 */
121
-	public function getMountId();
115
+    /**
116
+     * Get the id of the configured mount
117
+     *
118
+     * @return int|null mount id or null if not applicable
119
+     * @since 9.1.0
120
+     */
121
+    public function getMountId();
122 122
 
123
-	/**
124
-	 * Get the type of mount point, used to distinguish things like shares and external storages
125
-	 * in the web interface
126
-	 *
127
-	 * @return string
128
-	 * @since 12.0.0
129
-	 */
130
-	public function getMountType();
123
+    /**
124
+     * Get the type of mount point, used to distinguish things like shares and external storages
125
+     * in the web interface
126
+     *
127
+     * @return string
128
+     * @since 12.0.0
129
+     */
130
+    public function getMountType();
131 131
 }
Please login to merge, or discard this patch.
lib/public/Files/Folder.php 1 patch
Indentation   +152 added lines, -152 removed lines patch added patch discarded remove patch
@@ -40,156 +40,156 @@
 block discarded – undo
40 40
  * @since 6.0.0
41 41
  */
42 42
 interface Folder extends Node {
43
-	/**
44
-	 * Get the full path of an item in the folder within owncloud's filesystem
45
-	 *
46
-	 * @param string $path relative path of an item in the folder
47
-	 * @return string
48
-	 * @throws \OCP\Files\NotPermittedException
49
-	 * @since 6.0.0
50
-	 */
51
-	public function getFullPath($path);
52
-
53
-	/**
54
-	 * Get the path of an item in the folder relative to the folder
55
-	 *
56
-	 * @param string $path absolute path of an item in the folder
57
-	 * @throws \OCP\Files\NotFoundException
58
-	 * @return string|null
59
-	 * @since 6.0.0
60
-	 */
61
-	public function getRelativePath($path);
62
-
63
-	/**
64
-	 * check if a node is a (grand-)child of the folder
65
-	 *
66
-	 * @param \OCP\Files\Node $node
67
-	 * @return bool
68
-	 * @since 6.0.0
69
-	 */
70
-	public function isSubNode($node);
71
-
72
-	/**
73
-	 * get the content of this directory
74
-	 *
75
-	 * @throws \OCP\Files\NotFoundException
76
-	 * @return \OCP\Files\Node[]
77
-	 * @since 6.0.0
78
-	 */
79
-	public function getDirectoryListing();
80
-
81
-	/**
82
-	 * Get the node at $path
83
-	 *
84
-	 * @param string $path relative path of the file or folder
85
-	 * @return \OCP\Files\Node
86
-	 * @throws \OCP\Files\NotFoundException
87
-	 * @since 6.0.0
88
-	 */
89
-	public function get($path);
90
-
91
-	/**
92
-	 * Check if a file or folder exists in the folder
93
-	 *
94
-	 * @param string $path relative path of the file or folder
95
-	 * @return bool
96
-	 * @since 6.0.0
97
-	 */
98
-	public function nodeExists($path);
99
-
100
-	/**
101
-	 * Create a new folder
102
-	 *
103
-	 * @param string $path relative path of the new folder
104
-	 * @return \OCP\Files\Folder
105
-	 * @throws \OCP\Files\NotPermittedException
106
-	 * @since 6.0.0
107
-	 */
108
-	public function newFolder($path);
109
-
110
-	/**
111
-	 * Create a new file
112
-	 *
113
-	 * @param string $path relative path of the new file
114
-	 * @param string|resource|null $content content for the new file, since 19.0.0
115
-	 * @return \OCP\Files\File
116
-	 * @throws \OCP\Files\NotPermittedException
117
-	 * @since 6.0.0
118
-	 */
119
-	public function newFile($path, $content = null);
120
-
121
-	/**
122
-	 * search for files with the name matching $query
123
-	 *
124
-	 * @param string|ISearchQuery $query
125
-	 * @return \OCP\Files\Node[]
126
-	 * @since 6.0.0
127
-	 */
128
-	public function search($query);
129
-
130
-	/**
131
-	 * search for files by mimetype
132
-	 * $mimetype can either be a full mimetype (image/png) or a wildcard mimetype (image)
133
-	 *
134
-	 * @param string $mimetype
135
-	 * @return \OCP\Files\Node[]
136
-	 * @since 6.0.0
137
-	 */
138
-	public function searchByMime($mimetype);
139
-
140
-	/**
141
-	 * search for files by tag
142
-	 *
143
-	 * @param string|int $tag tag name or tag id
144
-	 * @param string $userId owner of the tags
145
-	 * @return \OCP\Files\Node[]
146
-	 * @since 8.0.0
147
-	 */
148
-	public function searchByTag($tag, $userId);
149
-
150
-	/**
151
-	 * get a file or folder inside the folder by it's internal id
152
-	 *
153
-	 * This method could return multiple entries. For example once the file/folder
154
-	 * is shared or mounted (files_external) to the user multiple times.
155
-	 *
156
-	 * @param int $id
157
-	 * @return \OCP\Files\Node[]
158
-	 * @since 6.0.0
159
-	 */
160
-	public function getById($id);
161
-
162
-	/**
163
-	 * Get the amount of free space inside the folder
164
-	 *
165
-	 * @return int
166
-	 * @since 6.0.0
167
-	 */
168
-	public function getFreeSpace();
169
-
170
-	/**
171
-	 * Check if new files or folders can be created within the folder
172
-	 *
173
-	 * @return bool
174
-	 * @since 6.0.0
175
-	 */
176
-	public function isCreatable();
177
-
178
-	/**
179
-	 * Add a suffix to the name in case the file exists
180
-	 *
181
-	 * @param string $name
182
-	 * @return string
183
-	 * @throws NotPermittedException
184
-	 * @since 8.1.0
185
-	 */
186
-	public function getNonExistingName($name);
187
-
188
-	/**
189
-	 * @param int $limit
190
-	 * @param int $offset
191
-	 * @return \OCP\Files\Node[]
192
-	 * @since 9.1.0
193
-	 */
194
-	public function getRecent($limit, $offset = 0);
43
+    /**
44
+     * Get the full path of an item in the folder within owncloud's filesystem
45
+     *
46
+     * @param string $path relative path of an item in the folder
47
+     * @return string
48
+     * @throws \OCP\Files\NotPermittedException
49
+     * @since 6.0.0
50
+     */
51
+    public function getFullPath($path);
52
+
53
+    /**
54
+     * Get the path of an item in the folder relative to the folder
55
+     *
56
+     * @param string $path absolute path of an item in the folder
57
+     * @throws \OCP\Files\NotFoundException
58
+     * @return string|null
59
+     * @since 6.0.0
60
+     */
61
+    public function getRelativePath($path);
62
+
63
+    /**
64
+     * check if a node is a (grand-)child of the folder
65
+     *
66
+     * @param \OCP\Files\Node $node
67
+     * @return bool
68
+     * @since 6.0.0
69
+     */
70
+    public function isSubNode($node);
71
+
72
+    /**
73
+     * get the content of this directory
74
+     *
75
+     * @throws \OCP\Files\NotFoundException
76
+     * @return \OCP\Files\Node[]
77
+     * @since 6.0.0
78
+     */
79
+    public function getDirectoryListing();
80
+
81
+    /**
82
+     * Get the node at $path
83
+     *
84
+     * @param string $path relative path of the file or folder
85
+     * @return \OCP\Files\Node
86
+     * @throws \OCP\Files\NotFoundException
87
+     * @since 6.0.0
88
+     */
89
+    public function get($path);
90
+
91
+    /**
92
+     * Check if a file or folder exists in the folder
93
+     *
94
+     * @param string $path relative path of the file or folder
95
+     * @return bool
96
+     * @since 6.0.0
97
+     */
98
+    public function nodeExists($path);
99
+
100
+    /**
101
+     * Create a new folder
102
+     *
103
+     * @param string $path relative path of the new folder
104
+     * @return \OCP\Files\Folder
105
+     * @throws \OCP\Files\NotPermittedException
106
+     * @since 6.0.0
107
+     */
108
+    public function newFolder($path);
109
+
110
+    /**
111
+     * Create a new file
112
+     *
113
+     * @param string $path relative path of the new file
114
+     * @param string|resource|null $content content for the new file, since 19.0.0
115
+     * @return \OCP\Files\File
116
+     * @throws \OCP\Files\NotPermittedException
117
+     * @since 6.0.0
118
+     */
119
+    public function newFile($path, $content = null);
120
+
121
+    /**
122
+     * search for files with the name matching $query
123
+     *
124
+     * @param string|ISearchQuery $query
125
+     * @return \OCP\Files\Node[]
126
+     * @since 6.0.0
127
+     */
128
+    public function search($query);
129
+
130
+    /**
131
+     * search for files by mimetype
132
+     * $mimetype can either be a full mimetype (image/png) or a wildcard mimetype (image)
133
+     *
134
+     * @param string $mimetype
135
+     * @return \OCP\Files\Node[]
136
+     * @since 6.0.0
137
+     */
138
+    public function searchByMime($mimetype);
139
+
140
+    /**
141
+     * search for files by tag
142
+     *
143
+     * @param string|int $tag tag name or tag id
144
+     * @param string $userId owner of the tags
145
+     * @return \OCP\Files\Node[]
146
+     * @since 8.0.0
147
+     */
148
+    public function searchByTag($tag, $userId);
149
+
150
+    /**
151
+     * get a file or folder inside the folder by it's internal id
152
+     *
153
+     * This method could return multiple entries. For example once the file/folder
154
+     * is shared or mounted (files_external) to the user multiple times.
155
+     *
156
+     * @param int $id
157
+     * @return \OCP\Files\Node[]
158
+     * @since 6.0.0
159
+     */
160
+    public function getById($id);
161
+
162
+    /**
163
+     * Get the amount of free space inside the folder
164
+     *
165
+     * @return int
166
+     * @since 6.0.0
167
+     */
168
+    public function getFreeSpace();
169
+
170
+    /**
171
+     * Check if new files or folders can be created within the folder
172
+     *
173
+     * @return bool
174
+     * @since 6.0.0
175
+     */
176
+    public function isCreatable();
177
+
178
+    /**
179
+     * Add a suffix to the name in case the file exists
180
+     *
181
+     * @param string $name
182
+     * @return string
183
+     * @throws NotPermittedException
184
+     * @since 8.1.0
185
+     */
186
+    public function getNonExistingName($name);
187
+
188
+    /**
189
+     * @param int $limit
190
+     * @param int $offset
191
+     * @return \OCP\Files\Node[]
192
+     * @since 9.1.0
193
+     */
194
+    public function getRecent($limit, $offset = 0);
195 195
 }
Please login to merge, or discard this patch.
apps/encryption/lib/Crypto/Encryption.php 1 patch
Indentation   +549 added lines, -549 removed lines patch added patch discarded remove patch
@@ -46,553 +46,553 @@
 block discarded – undo
46 46
 use Symfony\Component\Console\Output\OutputInterface;
47 47
 
48 48
 class Encryption implements IEncryptionModule {
49
-	public const ID = 'OC_DEFAULT_MODULE';
50
-	public const DISPLAY_NAME = 'Default encryption module';
51
-
52
-	/**
53
-	 * @var Crypt
54
-	 */
55
-	private $crypt;
56
-
57
-	/** @var string */
58
-	private $cipher;
59
-
60
-	/** @var string */
61
-	private $path;
62
-
63
-	/** @var string */
64
-	private $user;
65
-
66
-	/** @var  array */
67
-	private $owner;
68
-
69
-	/** @var string */
70
-	private $fileKey;
71
-
72
-	/** @var string */
73
-	private $writeCache;
74
-
75
-	/** @var KeyManager */
76
-	private $keyManager;
77
-
78
-	/** @var array */
79
-	private $accessList;
80
-
81
-	/** @var boolean */
82
-	private $isWriteOperation;
83
-
84
-	/** @var Util */
85
-	private $util;
86
-
87
-	/** @var  Session */
88
-	private $session;
89
-
90
-	/** @var  ILogger */
91
-	private $logger;
92
-
93
-	/** @var IL10N */
94
-	private $l;
95
-
96
-	/** @var EncryptAll */
97
-	private $encryptAll;
98
-
99
-	/** @var  bool */
100
-	private $useMasterPassword;
101
-
102
-	/** @var DecryptAll  */
103
-	private $decryptAll;
104
-
105
-	/** @var int unencrypted block size if block contains signature */
106
-	private $unencryptedBlockSizeSigned = 6072;
107
-
108
-	/** @var int unencrypted block size */
109
-	private $unencryptedBlockSize = 6126;
110
-
111
-	/** @var int Current version of the file */
112
-	private $version = 0;
113
-
114
-	/** @var array remember encryption signature version */
115
-	private static $rememberVersion = [];
116
-
117
-
118
-	/**
119
-	 *
120
-	 * @param Crypt $crypt
121
-	 * @param KeyManager $keyManager
122
-	 * @param Util $util
123
-	 * @param Session $session
124
-	 * @param EncryptAll $encryptAll
125
-	 * @param DecryptAll $decryptAll
126
-	 * @param ILogger $logger
127
-	 * @param IL10N $il10n
128
-	 */
129
-	public function __construct(Crypt $crypt,
130
-								KeyManager $keyManager,
131
-								Util $util,
132
-								Session $session,
133
-								EncryptAll $encryptAll,
134
-								DecryptAll $decryptAll,
135
-								ILogger $logger,
136
-								IL10N $il10n) {
137
-		$this->crypt = $crypt;
138
-		$this->keyManager = $keyManager;
139
-		$this->util = $util;
140
-		$this->session = $session;
141
-		$this->encryptAll = $encryptAll;
142
-		$this->decryptAll = $decryptAll;
143
-		$this->logger = $logger;
144
-		$this->l = $il10n;
145
-		$this->owner = [];
146
-		$this->useMasterPassword = $util->isMasterKeyEnabled();
147
-	}
148
-
149
-	/**
150
-	 * @return string defining the technical unique id
151
-	 */
152
-	public function getId() {
153
-		return self::ID;
154
-	}
155
-
156
-	/**
157
-	 * In comparison to getKey() this function returns a human readable (maybe translated) name
158
-	 *
159
-	 * @return string
160
-	 */
161
-	public function getDisplayName() {
162
-		return self::DISPLAY_NAME;
163
-	}
164
-
165
-	/**
166
-	 * start receiving chunks from a file. This is the place where you can
167
-	 * perform some initial step before starting encrypting/decrypting the
168
-	 * chunks
169
-	 *
170
-	 * @param string $path to the file
171
-	 * @param string $user who read/write the file
172
-	 * @param string $mode php stream open mode
173
-	 * @param array $header contains the header data read from the file
174
-	 * @param array $accessList who has access to the file contains the key 'users' and 'public'
175
-	 *
176
-	 * @return array $header contain data as key-value pairs which should be
177
-	 *                       written to the header, in case of a write operation
178
-	 *                       or if no additional data is needed return a empty array
179
-	 */
180
-	public function begin($path, $user, $mode, array $header, array $accessList) {
181
-		$this->path = $this->getPathToRealFile($path);
182
-		$this->accessList = $accessList;
183
-		$this->user = $user;
184
-		$this->isWriteOperation = false;
185
-		$this->writeCache = '';
186
-
187
-		if ($this->session->isReady() === false) {
188
-			// if the master key is enabled we can initialize encryption
189
-			// with a empty password and user name
190
-			if ($this->util->isMasterKeyEnabled()) {
191
-				$this->keyManager->init('', '');
192
-			}
193
-		}
194
-
195
-		if ($this->session->decryptAllModeActivated()) {
196
-			$encryptedFileKey = $this->keyManager->getEncryptedFileKey($this->path);
197
-			$shareKey = $this->keyManager->getShareKey($this->path, $this->session->getDecryptAllUid());
198
-			$this->fileKey = $this->crypt->multiKeyDecrypt($encryptedFileKey,
199
-				$shareKey,
200
-				$this->session->getDecryptAllKey());
201
-		} else {
202
-			$this->fileKey = $this->keyManager->getFileKey($this->path, $this->user);
203
-		}
204
-
205
-		// always use the version from the original file, also part files
206
-		// need to have a correct version number if they get moved over to the
207
-		// final location
208
-		$this->version = (int)$this->keyManager->getVersion($this->stripPartFileExtension($path), new View());
209
-
210
-		if (
211
-			$mode === 'w'
212
-			|| $mode === 'w+'
213
-			|| $mode === 'wb'
214
-			|| $mode === 'wb+'
215
-		) {
216
-			$this->isWriteOperation = true;
217
-			if (empty($this->fileKey)) {
218
-				$this->fileKey = $this->crypt->generateFileKey();
219
-			}
220
-		} else {
221
-			// if we read a part file we need to increase the version by 1
222
-			// because the version number was also increased by writing
223
-			// the part file
224
-			if (Scanner::isPartialFile($path)) {
225
-				$this->version = $this->version + 1;
226
-			}
227
-		}
228
-
229
-		if ($this->isWriteOperation) {
230
-			$this->cipher = $this->crypt->getCipher();
231
-		} elseif (isset($header['cipher'])) {
232
-			$this->cipher = $header['cipher'];
233
-		} else {
234
-			// if we read a file without a header we fall-back to the legacy cipher
235
-			// which was used in <=oC6
236
-			$this->cipher = $this->crypt->getLegacyCipher();
237
-		}
238
-
239
-		return ['cipher' => $this->cipher, 'signed' => 'true'];
240
-	}
241
-
242
-	/**
243
-	 * last chunk received. This is the place where you can perform some final
244
-	 * operation and return some remaining data if something is left in your
245
-	 * buffer.
246
-	 *
247
-	 * @param string $path to the file
248
-	 * @param int $position
249
-	 * @return string remained data which should be written to the file in case
250
-	 *                of a write operation
251
-	 * @throws PublicKeyMissingException
252
-	 * @throws \Exception
253
-	 * @throws \OCA\Encryption\Exceptions\MultiKeyEncryptException
254
-	 */
255
-	public function end($path, $position = 0) {
256
-		$result = '';
257
-		if ($this->isWriteOperation) {
258
-			// in case of a part file we remember the new signature versions
259
-			// the version will be set later on update.
260
-			// This way we make sure that other apps listening to the pre-hooks
261
-			// still get the old version which should be the correct value for them
262
-			if (Scanner::isPartialFile($path)) {
263
-				self::$rememberVersion[$this->stripPartFileExtension($path)] = $this->version + 1;
264
-			}
265
-			if (!empty($this->writeCache)) {
266
-				$result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $this->version + 1, $position);
267
-				$this->writeCache = '';
268
-			}
269
-			$publicKeys = [];
270
-			if ($this->useMasterPassword === true) {
271
-				$publicKeys[$this->keyManager->getMasterKeyId()] = $this->keyManager->getPublicMasterKey();
272
-			} else {
273
-				foreach ($this->accessList['users'] as $uid) {
274
-					try {
275
-						$publicKeys[$uid] = $this->keyManager->getPublicKey($uid);
276
-					} catch (PublicKeyMissingException $e) {
277
-						$this->logger->warning(
278
-							'no public key found for user "{uid}", user will not be able to read the file',
279
-							['app' => 'encryption', 'uid' => $uid]
280
-						);
281
-						// if the public key of the owner is missing we should fail
282
-						if ($uid === $this->user) {
283
-							throw $e;
284
-						}
285
-					}
286
-				}
287
-			}
288
-
289
-			$publicKeys = $this->keyManager->addSystemKeys($this->accessList, $publicKeys, $this->getOwner($path));
290
-			$encryptedKeyfiles = $this->crypt->multiKeyEncrypt($this->fileKey, $publicKeys);
291
-			$this->keyManager->setAllFileKeys($this->path, $encryptedKeyfiles);
292
-		}
293
-		return $result;
294
-	}
295
-
296
-
297
-
298
-	/**
299
-	 * encrypt data
300
-	 *
301
-	 * @param string $data you want to encrypt
302
-	 * @param int $position
303
-	 * @return string encrypted data
304
-	 */
305
-	public function encrypt($data, $position = 0) {
306
-		// If extra data is left over from the last round, make sure it
307
-		// is integrated into the next block
308
-		if ($this->writeCache) {
309
-
310
-			// Concat writeCache to start of $data
311
-			$data = $this->writeCache . $data;
312
-
313
-			// Clear the write cache, ready for reuse - it has been
314
-			// flushed and its old contents processed
315
-			$this->writeCache = '';
316
-		}
317
-
318
-		$encrypted = '';
319
-		// While there still remains some data to be processed & written
320
-		while (strlen($data) > 0) {
321
-
322
-			// Remaining length for this iteration, not of the
323
-			// entire file (may be greater than 8192 bytes)
324
-			$remainingLength = strlen($data);
325
-
326
-			// If data remaining to be written is less than the
327
-			// size of 1 6126 byte block
328
-			if ($remainingLength < $this->unencryptedBlockSizeSigned) {
329
-
330
-				// Set writeCache to contents of $data
331
-				// The writeCache will be carried over to the
332
-				// next write round, and added to the start of
333
-				// $data to ensure that written blocks are
334
-				// always the correct length. If there is still
335
-				// data in writeCache after the writing round
336
-				// has finished, then the data will be written
337
-				// to disk by $this->flush().
338
-				$this->writeCache = $data;
339
-
340
-				// Clear $data ready for next round
341
-				$data = '';
342
-			} else {
343
-
344
-				// Read the chunk from the start of $data
345
-				$chunk = substr($data, 0, $this->unencryptedBlockSizeSigned);
346
-
347
-				$encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey, $this->version + 1, $position);
348
-
349
-				// Remove the chunk we just processed from
350
-				// $data, leaving only unprocessed data in $data
351
-				// var, for handling on the next round
352
-				$data = substr($data, $this->unencryptedBlockSizeSigned);
353
-			}
354
-		}
355
-
356
-		return $encrypted;
357
-	}
358
-
359
-	/**
360
-	 * decrypt data
361
-	 *
362
-	 * @param string $data you want to decrypt
363
-	 * @param int|string $position
364
-	 * @return string decrypted data
365
-	 * @throws DecryptionFailedException
366
-	 */
367
-	public function decrypt($data, $position = 0) {
368
-		if (empty($this->fileKey)) {
369
-			$msg = 'Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.';
370
-			$hint = $this->l->t('Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.');
371
-			$this->logger->error($msg);
372
-
373
-			throw new DecryptionFailedException($msg, $hint);
374
-		}
375
-
376
-		return $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher, $this->version, $position);
377
-	}
378
-
379
-	/**
380
-	 * update encrypted file, e.g. give additional users access to the file
381
-	 *
382
-	 * @param string $path path to the file which should be updated
383
-	 * @param string $uid of the user who performs the operation
384
-	 * @param array $accessList who has access to the file contains the key 'users' and 'public'
385
-	 * @return boolean
386
-	 */
387
-	public function update($path, $uid, array $accessList) {
388
-		if (empty($accessList)) {
389
-			if (isset(self::$rememberVersion[$path])) {
390
-				$this->keyManager->setVersion($path, self::$rememberVersion[$path], new View());
391
-				unset(self::$rememberVersion[$path]);
392
-			}
393
-			return;
394
-		}
395
-
396
-		$fileKey = $this->keyManager->getFileKey($path, $uid);
397
-
398
-		if (!empty($fileKey)) {
399
-			$publicKeys = [];
400
-			if ($this->useMasterPassword === true) {
401
-				$publicKeys[$this->keyManager->getMasterKeyId()] = $this->keyManager->getPublicMasterKey();
402
-			} else {
403
-				foreach ($accessList['users'] as $user) {
404
-					try {
405
-						$publicKeys[$user] = $this->keyManager->getPublicKey($user);
406
-					} catch (PublicKeyMissingException $e) {
407
-						$this->logger->warning('Could not encrypt file for ' . $user . ': ' . $e->getMessage());
408
-					}
409
-				}
410
-			}
411
-
412
-			$publicKeys = $this->keyManager->addSystemKeys($accessList, $publicKeys, $this->getOwner($path));
413
-
414
-			$encryptedFileKey = $this->crypt->multiKeyEncrypt($fileKey, $publicKeys);
415
-
416
-			$this->keyManager->deleteAllFileKeys($path);
417
-
418
-			$this->keyManager->setAllFileKeys($path, $encryptedFileKey);
419
-		} else {
420
-			$this->logger->debug('no file key found, we assume that the file "{file}" is not encrypted',
421
-				['file' => $path, 'app' => 'encryption']);
422
-
423
-			return false;
424
-		}
425
-
426
-		return true;
427
-	}
428
-
429
-	/**
430
-	 * should the file be encrypted or not
431
-	 *
432
-	 * @param string $path
433
-	 * @return boolean
434
-	 */
435
-	public function shouldEncrypt($path) {
436
-		if ($this->util->shouldEncryptHomeStorage() === false) {
437
-			$storage = $this->util->getStorage($path);
438
-			if ($storage && $storage->instanceOfStorage('\OCP\Files\IHomeStorage')) {
439
-				return false;
440
-			}
441
-		}
442
-		$parts = explode('/', $path);
443
-		if (count($parts) < 4) {
444
-			return false;
445
-		}
446
-
447
-		if ($parts[2] === 'files') {
448
-			return true;
449
-		}
450
-		if ($parts[2] === 'files_versions') {
451
-			return true;
452
-		}
453
-		if ($parts[2] === 'files_trashbin') {
454
-			return true;
455
-		}
456
-
457
-		return false;
458
-	}
459
-
460
-	/**
461
-	 * get size of the unencrypted payload per block.
462
-	 * Nextcloud read/write files with a block size of 8192 byte
463
-	 *
464
-	 * @param bool $signed
465
-	 * @return int
466
-	 */
467
-	public function getUnencryptedBlockSize($signed = false) {
468
-		if ($signed === false) {
469
-			return $this->unencryptedBlockSize;
470
-		}
471
-
472
-		return $this->unencryptedBlockSizeSigned;
473
-	}
474
-
475
-	/**
476
-	 * check if the encryption module is able to read the file,
477
-	 * e.g. if all encryption keys exists
478
-	 *
479
-	 * @param string $path
480
-	 * @param string $uid user for whom we want to check if he can read the file
481
-	 * @return bool
482
-	 * @throws DecryptionFailedException
483
-	 */
484
-	public function isReadable($path, $uid) {
485
-		$fileKey = $this->keyManager->getFileKey($path, $uid);
486
-		if (empty($fileKey)) {
487
-			$owner = $this->util->getOwner($path);
488
-			if ($owner !== $uid) {
489
-				// if it is a shared file we throw a exception with a useful
490
-				// error message because in this case it means that the file was
491
-				// shared with the user at a point where the user didn't had a
492
-				// valid private/public key
493
-				$msg = 'Encryption module "' . $this->getDisplayName() .
494
-					'" is not able to read ' . $path;
495
-				$hint = $this->l->t('Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you.');
496
-				$this->logger->warning($msg);
497
-				throw new DecryptionFailedException($msg, $hint);
498
-			}
499
-			return false;
500
-		}
501
-
502
-		return true;
503
-	}
504
-
505
-	/**
506
-	 * Initial encryption of all files
507
-	 *
508
-	 * @param InputInterface $input
509
-	 * @param OutputInterface $output write some status information to the terminal during encryption
510
-	 */
511
-	public function encryptAll(InputInterface $input, OutputInterface $output) {
512
-		$this->encryptAll->encryptAll($input, $output);
513
-	}
514
-
515
-	/**
516
-	 * prepare module to perform decrypt all operation
517
-	 *
518
-	 * @param InputInterface $input
519
-	 * @param OutputInterface $output
520
-	 * @param string $user
521
-	 * @return bool
522
-	 */
523
-	public function prepareDecryptAll(InputInterface $input, OutputInterface $output, $user = '') {
524
-		return $this->decryptAll->prepare($input, $output, $user);
525
-	}
526
-
527
-
528
-	/**
529
-	 * @param string $path
530
-	 * @return string
531
-	 */
532
-	protected function getPathToRealFile($path) {
533
-		$realPath = $path;
534
-		$parts = explode('/', $path);
535
-		if ($parts[2] === 'files_versions') {
536
-			$realPath = '/' . $parts[1] . '/files/' . implode('/', array_slice($parts, 3));
537
-			$length = strrpos($realPath, '.');
538
-			$realPath = substr($realPath, 0, $length);
539
-		}
540
-
541
-		return $realPath;
542
-	}
543
-
544
-	/**
545
-	 * remove .part file extension and the ocTransferId from the file to get the
546
-	 * original file name
547
-	 *
548
-	 * @param string $path
549
-	 * @return string
550
-	 */
551
-	protected function stripPartFileExtension($path) {
552
-		if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
553
-			$pos = strrpos($path, '.', -6);
554
-			$path = substr($path, 0, $pos);
555
-		}
556
-
557
-		return $path;
558
-	}
559
-
560
-	/**
561
-	 * get owner of a file
562
-	 *
563
-	 * @param string $path
564
-	 * @return string
565
-	 */
566
-	protected function getOwner($path) {
567
-		if (!isset($this->owner[$path])) {
568
-			$this->owner[$path] = $this->util->getOwner($path);
569
-		}
570
-		return $this->owner[$path];
571
-	}
572
-
573
-	/**
574
-	 * Check if the module is ready to be used by that specific user.
575
-	 * In case a module is not ready - because e.g. key pairs have not been generated
576
-	 * upon login this method can return false before any operation starts and might
577
-	 * cause issues during operations.
578
-	 *
579
-	 * @param string $user
580
-	 * @return boolean
581
-	 * @since 9.1.0
582
-	 */
583
-	public function isReadyForUser($user) {
584
-		if ($this->util->isMasterKeyEnabled()) {
585
-			return true;
586
-		}
587
-		return $this->keyManager->userHasKeys($user);
588
-	}
589
-
590
-	/**
591
-	 * We only need a detailed access list if the master key is not enabled
592
-	 *
593
-	 * @return bool
594
-	 */
595
-	public function needDetailedAccessList() {
596
-		return !$this->util->isMasterKeyEnabled();
597
-	}
49
+    public const ID = 'OC_DEFAULT_MODULE';
50
+    public const DISPLAY_NAME = 'Default encryption module';
51
+
52
+    /**
53
+     * @var Crypt
54
+     */
55
+    private $crypt;
56
+
57
+    /** @var string */
58
+    private $cipher;
59
+
60
+    /** @var string */
61
+    private $path;
62
+
63
+    /** @var string */
64
+    private $user;
65
+
66
+    /** @var  array */
67
+    private $owner;
68
+
69
+    /** @var string */
70
+    private $fileKey;
71
+
72
+    /** @var string */
73
+    private $writeCache;
74
+
75
+    /** @var KeyManager */
76
+    private $keyManager;
77
+
78
+    /** @var array */
79
+    private $accessList;
80
+
81
+    /** @var boolean */
82
+    private $isWriteOperation;
83
+
84
+    /** @var Util */
85
+    private $util;
86
+
87
+    /** @var  Session */
88
+    private $session;
89
+
90
+    /** @var  ILogger */
91
+    private $logger;
92
+
93
+    /** @var IL10N */
94
+    private $l;
95
+
96
+    /** @var EncryptAll */
97
+    private $encryptAll;
98
+
99
+    /** @var  bool */
100
+    private $useMasterPassword;
101
+
102
+    /** @var DecryptAll  */
103
+    private $decryptAll;
104
+
105
+    /** @var int unencrypted block size if block contains signature */
106
+    private $unencryptedBlockSizeSigned = 6072;
107
+
108
+    /** @var int unencrypted block size */
109
+    private $unencryptedBlockSize = 6126;
110
+
111
+    /** @var int Current version of the file */
112
+    private $version = 0;
113
+
114
+    /** @var array remember encryption signature version */
115
+    private static $rememberVersion = [];
116
+
117
+
118
+    /**
119
+     *
120
+     * @param Crypt $crypt
121
+     * @param KeyManager $keyManager
122
+     * @param Util $util
123
+     * @param Session $session
124
+     * @param EncryptAll $encryptAll
125
+     * @param DecryptAll $decryptAll
126
+     * @param ILogger $logger
127
+     * @param IL10N $il10n
128
+     */
129
+    public function __construct(Crypt $crypt,
130
+                                KeyManager $keyManager,
131
+                                Util $util,
132
+                                Session $session,
133
+                                EncryptAll $encryptAll,
134
+                                DecryptAll $decryptAll,
135
+                                ILogger $logger,
136
+                                IL10N $il10n) {
137
+        $this->crypt = $crypt;
138
+        $this->keyManager = $keyManager;
139
+        $this->util = $util;
140
+        $this->session = $session;
141
+        $this->encryptAll = $encryptAll;
142
+        $this->decryptAll = $decryptAll;
143
+        $this->logger = $logger;
144
+        $this->l = $il10n;
145
+        $this->owner = [];
146
+        $this->useMasterPassword = $util->isMasterKeyEnabled();
147
+    }
148
+
149
+    /**
150
+     * @return string defining the technical unique id
151
+     */
152
+    public function getId() {
153
+        return self::ID;
154
+    }
155
+
156
+    /**
157
+     * In comparison to getKey() this function returns a human readable (maybe translated) name
158
+     *
159
+     * @return string
160
+     */
161
+    public function getDisplayName() {
162
+        return self::DISPLAY_NAME;
163
+    }
164
+
165
+    /**
166
+     * start receiving chunks from a file. This is the place where you can
167
+     * perform some initial step before starting encrypting/decrypting the
168
+     * chunks
169
+     *
170
+     * @param string $path to the file
171
+     * @param string $user who read/write the file
172
+     * @param string $mode php stream open mode
173
+     * @param array $header contains the header data read from the file
174
+     * @param array $accessList who has access to the file contains the key 'users' and 'public'
175
+     *
176
+     * @return array $header contain data as key-value pairs which should be
177
+     *                       written to the header, in case of a write operation
178
+     *                       or if no additional data is needed return a empty array
179
+     */
180
+    public function begin($path, $user, $mode, array $header, array $accessList) {
181
+        $this->path = $this->getPathToRealFile($path);
182
+        $this->accessList = $accessList;
183
+        $this->user = $user;
184
+        $this->isWriteOperation = false;
185
+        $this->writeCache = '';
186
+
187
+        if ($this->session->isReady() === false) {
188
+            // if the master key is enabled we can initialize encryption
189
+            // with a empty password and user name
190
+            if ($this->util->isMasterKeyEnabled()) {
191
+                $this->keyManager->init('', '');
192
+            }
193
+        }
194
+
195
+        if ($this->session->decryptAllModeActivated()) {
196
+            $encryptedFileKey = $this->keyManager->getEncryptedFileKey($this->path);
197
+            $shareKey = $this->keyManager->getShareKey($this->path, $this->session->getDecryptAllUid());
198
+            $this->fileKey = $this->crypt->multiKeyDecrypt($encryptedFileKey,
199
+                $shareKey,
200
+                $this->session->getDecryptAllKey());
201
+        } else {
202
+            $this->fileKey = $this->keyManager->getFileKey($this->path, $this->user);
203
+        }
204
+
205
+        // always use the version from the original file, also part files
206
+        // need to have a correct version number if they get moved over to the
207
+        // final location
208
+        $this->version = (int)$this->keyManager->getVersion($this->stripPartFileExtension($path), new View());
209
+
210
+        if (
211
+            $mode === 'w'
212
+            || $mode === 'w+'
213
+            || $mode === 'wb'
214
+            || $mode === 'wb+'
215
+        ) {
216
+            $this->isWriteOperation = true;
217
+            if (empty($this->fileKey)) {
218
+                $this->fileKey = $this->crypt->generateFileKey();
219
+            }
220
+        } else {
221
+            // if we read a part file we need to increase the version by 1
222
+            // because the version number was also increased by writing
223
+            // the part file
224
+            if (Scanner::isPartialFile($path)) {
225
+                $this->version = $this->version + 1;
226
+            }
227
+        }
228
+
229
+        if ($this->isWriteOperation) {
230
+            $this->cipher = $this->crypt->getCipher();
231
+        } elseif (isset($header['cipher'])) {
232
+            $this->cipher = $header['cipher'];
233
+        } else {
234
+            // if we read a file without a header we fall-back to the legacy cipher
235
+            // which was used in <=oC6
236
+            $this->cipher = $this->crypt->getLegacyCipher();
237
+        }
238
+
239
+        return ['cipher' => $this->cipher, 'signed' => 'true'];
240
+    }
241
+
242
+    /**
243
+     * last chunk received. This is the place where you can perform some final
244
+     * operation and return some remaining data if something is left in your
245
+     * buffer.
246
+     *
247
+     * @param string $path to the file
248
+     * @param int $position
249
+     * @return string remained data which should be written to the file in case
250
+     *                of a write operation
251
+     * @throws PublicKeyMissingException
252
+     * @throws \Exception
253
+     * @throws \OCA\Encryption\Exceptions\MultiKeyEncryptException
254
+     */
255
+    public function end($path, $position = 0) {
256
+        $result = '';
257
+        if ($this->isWriteOperation) {
258
+            // in case of a part file we remember the new signature versions
259
+            // the version will be set later on update.
260
+            // This way we make sure that other apps listening to the pre-hooks
261
+            // still get the old version which should be the correct value for them
262
+            if (Scanner::isPartialFile($path)) {
263
+                self::$rememberVersion[$this->stripPartFileExtension($path)] = $this->version + 1;
264
+            }
265
+            if (!empty($this->writeCache)) {
266
+                $result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $this->version + 1, $position);
267
+                $this->writeCache = '';
268
+            }
269
+            $publicKeys = [];
270
+            if ($this->useMasterPassword === true) {
271
+                $publicKeys[$this->keyManager->getMasterKeyId()] = $this->keyManager->getPublicMasterKey();
272
+            } else {
273
+                foreach ($this->accessList['users'] as $uid) {
274
+                    try {
275
+                        $publicKeys[$uid] = $this->keyManager->getPublicKey($uid);
276
+                    } catch (PublicKeyMissingException $e) {
277
+                        $this->logger->warning(
278
+                            'no public key found for user "{uid}", user will not be able to read the file',
279
+                            ['app' => 'encryption', 'uid' => $uid]
280
+                        );
281
+                        // if the public key of the owner is missing we should fail
282
+                        if ($uid === $this->user) {
283
+                            throw $e;
284
+                        }
285
+                    }
286
+                }
287
+            }
288
+
289
+            $publicKeys = $this->keyManager->addSystemKeys($this->accessList, $publicKeys, $this->getOwner($path));
290
+            $encryptedKeyfiles = $this->crypt->multiKeyEncrypt($this->fileKey, $publicKeys);
291
+            $this->keyManager->setAllFileKeys($this->path, $encryptedKeyfiles);
292
+        }
293
+        return $result;
294
+    }
295
+
296
+
297
+
298
+    /**
299
+     * encrypt data
300
+     *
301
+     * @param string $data you want to encrypt
302
+     * @param int $position
303
+     * @return string encrypted data
304
+     */
305
+    public function encrypt($data, $position = 0) {
306
+        // If extra data is left over from the last round, make sure it
307
+        // is integrated into the next block
308
+        if ($this->writeCache) {
309
+
310
+            // Concat writeCache to start of $data
311
+            $data = $this->writeCache . $data;
312
+
313
+            // Clear the write cache, ready for reuse - it has been
314
+            // flushed and its old contents processed
315
+            $this->writeCache = '';
316
+        }
317
+
318
+        $encrypted = '';
319
+        // While there still remains some data to be processed & written
320
+        while (strlen($data) > 0) {
321
+
322
+            // Remaining length for this iteration, not of the
323
+            // entire file (may be greater than 8192 bytes)
324
+            $remainingLength = strlen($data);
325
+
326
+            // If data remaining to be written is less than the
327
+            // size of 1 6126 byte block
328
+            if ($remainingLength < $this->unencryptedBlockSizeSigned) {
329
+
330
+                // Set writeCache to contents of $data
331
+                // The writeCache will be carried over to the
332
+                // next write round, and added to the start of
333
+                // $data to ensure that written blocks are
334
+                // always the correct length. If there is still
335
+                // data in writeCache after the writing round
336
+                // has finished, then the data will be written
337
+                // to disk by $this->flush().
338
+                $this->writeCache = $data;
339
+
340
+                // Clear $data ready for next round
341
+                $data = '';
342
+            } else {
343
+
344
+                // Read the chunk from the start of $data
345
+                $chunk = substr($data, 0, $this->unencryptedBlockSizeSigned);
346
+
347
+                $encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey, $this->version + 1, $position);
348
+
349
+                // Remove the chunk we just processed from
350
+                // $data, leaving only unprocessed data in $data
351
+                // var, for handling on the next round
352
+                $data = substr($data, $this->unencryptedBlockSizeSigned);
353
+            }
354
+        }
355
+
356
+        return $encrypted;
357
+    }
358
+
359
+    /**
360
+     * decrypt data
361
+     *
362
+     * @param string $data you want to decrypt
363
+     * @param int|string $position
364
+     * @return string decrypted data
365
+     * @throws DecryptionFailedException
366
+     */
367
+    public function decrypt($data, $position = 0) {
368
+        if (empty($this->fileKey)) {
369
+            $msg = 'Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.';
370
+            $hint = $this->l->t('Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.');
371
+            $this->logger->error($msg);
372
+
373
+            throw new DecryptionFailedException($msg, $hint);
374
+        }
375
+
376
+        return $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher, $this->version, $position);
377
+    }
378
+
379
+    /**
380
+     * update encrypted file, e.g. give additional users access to the file
381
+     *
382
+     * @param string $path path to the file which should be updated
383
+     * @param string $uid of the user who performs the operation
384
+     * @param array $accessList who has access to the file contains the key 'users' and 'public'
385
+     * @return boolean
386
+     */
387
+    public function update($path, $uid, array $accessList) {
388
+        if (empty($accessList)) {
389
+            if (isset(self::$rememberVersion[$path])) {
390
+                $this->keyManager->setVersion($path, self::$rememberVersion[$path], new View());
391
+                unset(self::$rememberVersion[$path]);
392
+            }
393
+            return;
394
+        }
395
+
396
+        $fileKey = $this->keyManager->getFileKey($path, $uid);
397
+
398
+        if (!empty($fileKey)) {
399
+            $publicKeys = [];
400
+            if ($this->useMasterPassword === true) {
401
+                $publicKeys[$this->keyManager->getMasterKeyId()] = $this->keyManager->getPublicMasterKey();
402
+            } else {
403
+                foreach ($accessList['users'] as $user) {
404
+                    try {
405
+                        $publicKeys[$user] = $this->keyManager->getPublicKey($user);
406
+                    } catch (PublicKeyMissingException $e) {
407
+                        $this->logger->warning('Could not encrypt file for ' . $user . ': ' . $e->getMessage());
408
+                    }
409
+                }
410
+            }
411
+
412
+            $publicKeys = $this->keyManager->addSystemKeys($accessList, $publicKeys, $this->getOwner($path));
413
+
414
+            $encryptedFileKey = $this->crypt->multiKeyEncrypt($fileKey, $publicKeys);
415
+
416
+            $this->keyManager->deleteAllFileKeys($path);
417
+
418
+            $this->keyManager->setAllFileKeys($path, $encryptedFileKey);
419
+        } else {
420
+            $this->logger->debug('no file key found, we assume that the file "{file}" is not encrypted',
421
+                ['file' => $path, 'app' => 'encryption']);
422
+
423
+            return false;
424
+        }
425
+
426
+        return true;
427
+    }
428
+
429
+    /**
430
+     * should the file be encrypted or not
431
+     *
432
+     * @param string $path
433
+     * @return boolean
434
+     */
435
+    public function shouldEncrypt($path) {
436
+        if ($this->util->shouldEncryptHomeStorage() === false) {
437
+            $storage = $this->util->getStorage($path);
438
+            if ($storage && $storage->instanceOfStorage('\OCP\Files\IHomeStorage')) {
439
+                return false;
440
+            }
441
+        }
442
+        $parts = explode('/', $path);
443
+        if (count($parts) < 4) {
444
+            return false;
445
+        }
446
+
447
+        if ($parts[2] === 'files') {
448
+            return true;
449
+        }
450
+        if ($parts[2] === 'files_versions') {
451
+            return true;
452
+        }
453
+        if ($parts[2] === 'files_trashbin') {
454
+            return true;
455
+        }
456
+
457
+        return false;
458
+    }
459
+
460
+    /**
461
+     * get size of the unencrypted payload per block.
462
+     * Nextcloud read/write files with a block size of 8192 byte
463
+     *
464
+     * @param bool $signed
465
+     * @return int
466
+     */
467
+    public function getUnencryptedBlockSize($signed = false) {
468
+        if ($signed === false) {
469
+            return $this->unencryptedBlockSize;
470
+        }
471
+
472
+        return $this->unencryptedBlockSizeSigned;
473
+    }
474
+
475
+    /**
476
+     * check if the encryption module is able to read the file,
477
+     * e.g. if all encryption keys exists
478
+     *
479
+     * @param string $path
480
+     * @param string $uid user for whom we want to check if he can read the file
481
+     * @return bool
482
+     * @throws DecryptionFailedException
483
+     */
484
+    public function isReadable($path, $uid) {
485
+        $fileKey = $this->keyManager->getFileKey($path, $uid);
486
+        if (empty($fileKey)) {
487
+            $owner = $this->util->getOwner($path);
488
+            if ($owner !== $uid) {
489
+                // if it is a shared file we throw a exception with a useful
490
+                // error message because in this case it means that the file was
491
+                // shared with the user at a point where the user didn't had a
492
+                // valid private/public key
493
+                $msg = 'Encryption module "' . $this->getDisplayName() .
494
+                    '" is not able to read ' . $path;
495
+                $hint = $this->l->t('Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you.');
496
+                $this->logger->warning($msg);
497
+                throw new DecryptionFailedException($msg, $hint);
498
+            }
499
+            return false;
500
+        }
501
+
502
+        return true;
503
+    }
504
+
505
+    /**
506
+     * Initial encryption of all files
507
+     *
508
+     * @param InputInterface $input
509
+     * @param OutputInterface $output write some status information to the terminal during encryption
510
+     */
511
+    public function encryptAll(InputInterface $input, OutputInterface $output) {
512
+        $this->encryptAll->encryptAll($input, $output);
513
+    }
514
+
515
+    /**
516
+     * prepare module to perform decrypt all operation
517
+     *
518
+     * @param InputInterface $input
519
+     * @param OutputInterface $output
520
+     * @param string $user
521
+     * @return bool
522
+     */
523
+    public function prepareDecryptAll(InputInterface $input, OutputInterface $output, $user = '') {
524
+        return $this->decryptAll->prepare($input, $output, $user);
525
+    }
526
+
527
+
528
+    /**
529
+     * @param string $path
530
+     * @return string
531
+     */
532
+    protected function getPathToRealFile($path) {
533
+        $realPath = $path;
534
+        $parts = explode('/', $path);
535
+        if ($parts[2] === 'files_versions') {
536
+            $realPath = '/' . $parts[1] . '/files/' . implode('/', array_slice($parts, 3));
537
+            $length = strrpos($realPath, '.');
538
+            $realPath = substr($realPath, 0, $length);
539
+        }
540
+
541
+        return $realPath;
542
+    }
543
+
544
+    /**
545
+     * remove .part file extension and the ocTransferId from the file to get the
546
+     * original file name
547
+     *
548
+     * @param string $path
549
+     * @return string
550
+     */
551
+    protected function stripPartFileExtension($path) {
552
+        if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
553
+            $pos = strrpos($path, '.', -6);
554
+            $path = substr($path, 0, $pos);
555
+        }
556
+
557
+        return $path;
558
+    }
559
+
560
+    /**
561
+     * get owner of a file
562
+     *
563
+     * @param string $path
564
+     * @return string
565
+     */
566
+    protected function getOwner($path) {
567
+        if (!isset($this->owner[$path])) {
568
+            $this->owner[$path] = $this->util->getOwner($path);
569
+        }
570
+        return $this->owner[$path];
571
+    }
572
+
573
+    /**
574
+     * Check if the module is ready to be used by that specific user.
575
+     * In case a module is not ready - because e.g. key pairs have not been generated
576
+     * upon login this method can return false before any operation starts and might
577
+     * cause issues during operations.
578
+     *
579
+     * @param string $user
580
+     * @return boolean
581
+     * @since 9.1.0
582
+     */
583
+    public function isReadyForUser($user) {
584
+        if ($this->util->isMasterKeyEnabled()) {
585
+            return true;
586
+        }
587
+        return $this->keyManager->userHasKeys($user);
588
+    }
589
+
590
+    /**
591
+     * We only need a detailed access list if the master key is not enabled
592
+     *
593
+     * @return bool
594
+     */
595
+    public function needDetailedAccessList() {
596
+        return !$this->util->isMasterKeyEnabled();
597
+    }
598 598
 }
Please login to merge, or discard this patch.
apps/encryption/lib/Util.php 1 patch
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -36,164 +36,164 @@
 block discarded – undo
36 36
 use OCP\PreConditionNotMetException;
37 37
 
38 38
 class Util {
39
-	/**
40
-	 * @var View
41
-	 */
42
-	private $files;
43
-	/**
44
-	 * @var Crypt
45
-	 */
46
-	private $crypt;
47
-	/**
48
-	 * @var ILogger
49
-	 */
50
-	private $logger;
51
-	/**
52
-	 * @var bool|IUser
53
-	 */
54
-	private $user;
55
-	/**
56
-	 * @var IConfig
57
-	 */
58
-	private $config;
59
-	/**
60
-	 * @var IUserManager
61
-	 */
62
-	private $userManager;
63
-
64
-	/**
65
-	 * Util constructor.
66
-	 *
67
-	 * @param View $files
68
-	 * @param Crypt $crypt
69
-	 * @param ILogger $logger
70
-	 * @param IUserSession $userSession
71
-	 * @param IConfig $config
72
-	 * @param IUserManager $userManager
73
-	 */
74
-	public function __construct(View $files,
75
-								Crypt $crypt,
76
-								ILogger $logger,
77
-								IUserSession $userSession,
78
-								IConfig $config,
79
-								IUserManager $userManager
80
-	) {
81
-		$this->files = $files;
82
-		$this->crypt = $crypt;
83
-		$this->logger = $logger;
84
-		$this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false;
85
-		$this->config = $config;
86
-		$this->userManager = $userManager;
87
-	}
88
-
89
-	/**
90
-	 * check if recovery key is enabled for user
91
-	 *
92
-	 * @param string $uid
93
-	 * @return bool
94
-	 */
95
-	public function isRecoveryEnabledForUser($uid) {
96
-		$recoveryMode = $this->config->getUserValue($uid,
97
-			'encryption',
98
-			'recoveryEnabled',
99
-			'0');
100
-
101
-		return ($recoveryMode === '1');
102
-	}
103
-
104
-	/**
105
-	 * check if the home storage should be encrypted
106
-	 *
107
-	 * @return bool
108
-	 */
109
-	public function shouldEncryptHomeStorage() {
110
-		$encryptHomeStorage = $this->config->getAppValue(
111
-			'encryption',
112
-			'encryptHomeStorage',
113
-			'1'
114
-		);
115
-
116
-		return ($encryptHomeStorage === '1');
117
-	}
118
-
119
-	/**
120
-	 * set the home storage encryption on/off
121
-	 *
122
-	 * @param bool $encryptHomeStorage
123
-	 */
124
-	public function setEncryptHomeStorage($encryptHomeStorage) {
125
-		$value = $encryptHomeStorage ? '1' : '0';
126
-		$this->config->setAppValue(
127
-			'encryption',
128
-			'encryptHomeStorage',
129
-			$value
130
-		);
131
-	}
132
-
133
-	/**
134
-	 * check if master key is enabled
135
-	 *
136
-	 * @return bool
137
-	 */
138
-	public function isMasterKeyEnabled() {
139
-		$userMasterKey = $this->config->getAppValue('encryption', 'useMasterKey', '1');
140
-		return ($userMasterKey === '1');
141
-	}
142
-
143
-	/**
144
-	 * @param $enabled
145
-	 * @return bool
146
-	 */
147
-	public function setRecoveryForUser($enabled) {
148
-		$value = $enabled ? '1' : '0';
149
-
150
-		try {
151
-			$this->config->setUserValue($this->user->getUID(),
152
-				'encryption',
153
-				'recoveryEnabled',
154
-				$value);
155
-			return true;
156
-		} catch (PreConditionNotMetException $e) {
157
-			return false;
158
-		}
159
-	}
160
-
161
-	/**
162
-	 * @param string $uid
163
-	 * @return bool
164
-	 */
165
-	public function userHasFiles($uid) {
166
-		return $this->files->file_exists($uid . '/files');
167
-	}
168
-
169
-	/**
170
-	 * get owner from give path, path relative to data/ expected
171
-	 *
172
-	 * @param string $path relative to data/
173
-	 * @return string
174
-	 * @throws \BadMethodCallException
175
-	 */
176
-	public function getOwner($path) {
177
-		$owner = '';
178
-		$parts = explode('/', $path, 3);
179
-		if (count($parts) > 1) {
180
-			$owner = $parts[1];
181
-			if ($this->userManager->userExists($owner) === false) {
182
-				throw new \BadMethodCallException('Unknown user: ' .
183
-				'method expects path to a user folder relative to the data folder');
184
-			}
185
-		}
186
-
187
-		return $owner;
188
-	}
189
-
190
-	/**
191
-	 * get storage of path
192
-	 *
193
-	 * @param string $path
194
-	 * @return \OC\Files\Storage\Storage|null
195
-	 */
196
-	public function getStorage($path) {
197
-		return $this->files->getMount($path)->getStorage();
198
-	}
39
+    /**
40
+     * @var View
41
+     */
42
+    private $files;
43
+    /**
44
+     * @var Crypt
45
+     */
46
+    private $crypt;
47
+    /**
48
+     * @var ILogger
49
+     */
50
+    private $logger;
51
+    /**
52
+     * @var bool|IUser
53
+     */
54
+    private $user;
55
+    /**
56
+     * @var IConfig
57
+     */
58
+    private $config;
59
+    /**
60
+     * @var IUserManager
61
+     */
62
+    private $userManager;
63
+
64
+    /**
65
+     * Util constructor.
66
+     *
67
+     * @param View $files
68
+     * @param Crypt $crypt
69
+     * @param ILogger $logger
70
+     * @param IUserSession $userSession
71
+     * @param IConfig $config
72
+     * @param IUserManager $userManager
73
+     */
74
+    public function __construct(View $files,
75
+                                Crypt $crypt,
76
+                                ILogger $logger,
77
+                                IUserSession $userSession,
78
+                                IConfig $config,
79
+                                IUserManager $userManager
80
+    ) {
81
+        $this->files = $files;
82
+        $this->crypt = $crypt;
83
+        $this->logger = $logger;
84
+        $this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false;
85
+        $this->config = $config;
86
+        $this->userManager = $userManager;
87
+    }
88
+
89
+    /**
90
+     * check if recovery key is enabled for user
91
+     *
92
+     * @param string $uid
93
+     * @return bool
94
+     */
95
+    public function isRecoveryEnabledForUser($uid) {
96
+        $recoveryMode = $this->config->getUserValue($uid,
97
+            'encryption',
98
+            'recoveryEnabled',
99
+            '0');
100
+
101
+        return ($recoveryMode === '1');
102
+    }
103
+
104
+    /**
105
+     * check if the home storage should be encrypted
106
+     *
107
+     * @return bool
108
+     */
109
+    public function shouldEncryptHomeStorage() {
110
+        $encryptHomeStorage = $this->config->getAppValue(
111
+            'encryption',
112
+            'encryptHomeStorage',
113
+            '1'
114
+        );
115
+
116
+        return ($encryptHomeStorage === '1');
117
+    }
118
+
119
+    /**
120
+     * set the home storage encryption on/off
121
+     *
122
+     * @param bool $encryptHomeStorage
123
+     */
124
+    public function setEncryptHomeStorage($encryptHomeStorage) {
125
+        $value = $encryptHomeStorage ? '1' : '0';
126
+        $this->config->setAppValue(
127
+            'encryption',
128
+            'encryptHomeStorage',
129
+            $value
130
+        );
131
+    }
132
+
133
+    /**
134
+     * check if master key is enabled
135
+     *
136
+     * @return bool
137
+     */
138
+    public function isMasterKeyEnabled() {
139
+        $userMasterKey = $this->config->getAppValue('encryption', 'useMasterKey', '1');
140
+        return ($userMasterKey === '1');
141
+    }
142
+
143
+    /**
144
+     * @param $enabled
145
+     * @return bool
146
+     */
147
+    public function setRecoveryForUser($enabled) {
148
+        $value = $enabled ? '1' : '0';
149
+
150
+        try {
151
+            $this->config->setUserValue($this->user->getUID(),
152
+                'encryption',
153
+                'recoveryEnabled',
154
+                $value);
155
+            return true;
156
+        } catch (PreConditionNotMetException $e) {
157
+            return false;
158
+        }
159
+    }
160
+
161
+    /**
162
+     * @param string $uid
163
+     * @return bool
164
+     */
165
+    public function userHasFiles($uid) {
166
+        return $this->files->file_exists($uid . '/files');
167
+    }
168
+
169
+    /**
170
+     * get owner from give path, path relative to data/ expected
171
+     *
172
+     * @param string $path relative to data/
173
+     * @return string
174
+     * @throws \BadMethodCallException
175
+     */
176
+    public function getOwner($path) {
177
+        $owner = '';
178
+        $parts = explode('/', $path, 3);
179
+        if (count($parts) > 1) {
180
+            $owner = $parts[1];
181
+            if ($this->userManager->userExists($owner) === false) {
182
+                throw new \BadMethodCallException('Unknown user: ' .
183
+                'method expects path to a user folder relative to the data folder');
184
+            }
185
+        }
186
+
187
+        return $owner;
188
+    }
189
+
190
+    /**
191
+     * get storage of path
192
+     *
193
+     * @param string $path
194
+     * @return \OC\Files\Storage\Storage|null
195
+     */
196
+    public function getStorage($path) {
197
+        return $this->files->getMount($path)->getStorage();
198
+    }
199 199
 }
Please login to merge, or discard this patch.