Passed
Push — master ( 4c60ff...437d93 )
by Julius
15:25 queued 12s
created

CacheJail::searchQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 14
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 18
rs 9.7998

1 Method

Rating   Name   Duplication   Size   Complexity  
A CacheJail::getQueryFilterForStorage() 0 8 1
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Christoph Wurst <[email protected]>
6
 * @author Daniel Jagszent <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Robin Appelman <[email protected]>
9
 * @author Robin McCorkell <[email protected]>
10
 * @author Roeland Jago Douma <[email protected]>
11
 * @author Thomas Müller <[email protected]>
12
 *
13
 * @license AGPL-3.0
14
 *
15
 * This code is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License, version 3,
17
 * as published by the Free Software Foundation.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License, version 3,
25
 * along with this program. If not, see <http://www.gnu.org/licenses/>
26
 *
27
 */
28
namespace OC\Files\Cache\Wrapper;
29
30
use OC\Files\Cache\Cache;
31
use OC\Files\Search\SearchBinaryOperator;
32
use OC\Files\Search\SearchComparison;
33
use OCP\Files\Cache\ICacheEntry;
34
use OCP\Files\Search\ISearchBinaryOperator;
35
use OCP\Files\Search\ISearchComparison;
36
use OCP\Files\Search\ISearchOperator;
37
38
/**
39
 * Jail to a subdirectory of the wrapped cache
40
 */
41
class CacheJail extends CacheWrapper {
42
	/**
43
	 * @var string
44
	 */
45
	protected $root;
46
	protected $unjailedRoot;
47
48
	/**
49
	 * @param \OCP\Files\Cache\ICache $cache
50
	 * @param string $root
51
	 */
52
	public function __construct($cache, $root) {
53
		parent::__construct($cache);
54
		$this->root = $root;
55
		$this->connection = \OC::$server->getDatabaseConnection();
56
		$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
57
58
		if ($cache instanceof CacheJail) {
59
			$this->unjailedRoot = $cache->getSourcePath($root);
60
		} else {
61
			$this->unjailedRoot = $root;
62
		}
63
	}
64
65
	protected function getRoot() {
66
		return $this->root;
67
	}
68
69
	/**
70
	 * Get the root path with any nested jails resolved
71
	 *
72
	 * @return string
73
	 */
74
	protected function getGetUnjailedRoot() {
75
		return $this->unjailedRoot;
76
	}
77
78
	protected function getSourcePath($path) {
79
		if ($path === '') {
80
			return $this->getRoot();
81
		} else {
82
			return $this->getRoot() . '/' . ltrim($path, '/');
83
		}
84
	}
85
86
	/**
87
	 * @param string $path
88
	 * @param null|string $root
89
	 * @return null|string the jailed path or null if the path is outside the jail
90
	 */
91
	protected function getJailedPath(string $path, string $root = null) {
92
		if ($root === null) {
93
			$root = $this->getRoot();
94
		}
95
		if ($root === '') {
96
			return $path;
97
		}
98
		$rootLength = strlen($root) + 1;
99
		if ($path === $root) {
100
			return '';
101
		} elseif (substr($path, 0, $rootLength) === $root . '/') {
102
			return substr($path, $rootLength);
103
		} else {
104
			return null;
105
		}
106
	}
107
108
	protected function formatCacheEntry($entry) {
109
		if (isset($entry['path'])) {
110
			$entry['path'] = $this->getJailedPath($entry['path']);
111
		}
112
		return $entry;
113
	}
114
115
	/**
116
	 * get the stored metadata of a file or folder
117
	 *
118
	 * @param string /int $file
0 ignored issues
show
Documentation Bug introduced by
The doc comment /int at position 0 could not be parsed: Unknown type name '/int' at position 0 in /int.
Loading history...
119
	 * @return ICacheEntry|false
120
	 */
121
	public function get($file) {
122
		if (is_string($file) or $file == '') {
123
			$file = $this->getSourcePath($file);
124
		}
125
		return parent::get($file);
126
	}
127
128
	/**
129
	 * insert meta data for a new file or folder
130
	 *
131
	 * @param string $file
132
	 * @param array $data
133
	 *
134
	 * @return int file id
135
	 * @throws \RuntimeException
136
	 */
137
	public function insert($file, array $data) {
138
		return $this->getCache()->insert($this->getSourcePath($file), $data);
139
	}
140
141
	/**
142
	 * update the metadata in the cache
143
	 *
144
	 * @param int $id
145
	 * @param array $data
146
	 */
147
	public function update($id, array $data) {
148
		$this->getCache()->update($id, $data);
149
	}
150
151
	/**
152
	 * get the file id for a file
153
	 *
154
	 * @param string $file
155
	 * @return int
156
	 */
157
	public function getId($file) {
158
		return $this->getCache()->getId($this->getSourcePath($file));
159
	}
160
161
	/**
162
	 * get the id of the parent folder of a file
163
	 *
164
	 * @param string $file
165
	 * @return int
166
	 */
167
	public function getParentId($file) {
168
		return $this->getCache()->getParentId($this->getSourcePath($file));
169
	}
170
171
	/**
172
	 * check if a file is available in the cache
173
	 *
174
	 * @param string $file
175
	 * @return bool
176
	 */
177
	public function inCache($file) {
178
		return $this->getCache()->inCache($this->getSourcePath($file));
179
	}
180
181
	/**
182
	 * remove a file or folder from the cache
183
	 *
184
	 * @param string $file
185
	 */
186
	public function remove($file) {
187
		$this->getCache()->remove($this->getSourcePath($file));
188
	}
189
190
	/**
191
	 * Move a file or folder in the cache
192
	 *
193
	 * @param string $source
194
	 * @param string $target
195
	 */
196
	public function move($source, $target) {
197
		$this->getCache()->move($this->getSourcePath($source), $this->getSourcePath($target));
198
	}
199
200
	/**
201
	 * Get the storage id and path needed for a move
202
	 *
203
	 * @param string $path
204
	 * @return array [$storageId, $internalPath]
205
	 */
206
	protected function getMoveInfo($path) {
207
		return [$this->getNumericStorageId(), $this->getSourcePath($path)];
208
	}
209
210
	/**
211
	 * remove all entries for files that are stored on the storage from the cache
212
	 */
213
	public function clear() {
214
		$this->getCache()->remove($this->getRoot());
215
	}
216
217
	/**
218
	 * @param string $file
219
	 *
220
	 * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
221
	 */
222
	public function getStatus($file) {
223
		return $this->getCache()->getStatus($this->getSourcePath($file));
224
	}
225
226
	/**
227
	 * update the folder size and the size of all parent folders
228
	 *
229
	 * @param string|boolean $path
230
	 * @param array $data (optional) meta data of the folder
231
	 */
232
	public function correctFolderSize($path, $data = null, $isBackgroundScan = false) {
233
		if ($this->getCache() instanceof Cache) {
234
			$this->getCache()->correctFolderSize($this->getSourcePath($path), $data, $isBackgroundScan);
235
		}
236
	}
237
238
	/**
239
	 * get the size of a folder and set it in the cache
240
	 *
241
	 * @param string $path
242
	 * @param array $entry (optional) meta data of the folder
243
	 * @return int
244
	 */
245
	public function calculateFolderSize($path, $entry = null) {
246
		if ($this->getCache() instanceof Cache) {
247
			return $this->getCache()->calculateFolderSize($this->getSourcePath($path), $entry);
248
		} else {
249
			return 0;
250
		}
251
	}
252
253
	/**
254
	 * get all file ids on the files on the storage
255
	 *
256
	 * @return int[]
257
	 */
258
	public function getAll() {
259
		// not supported
260
		return [];
261
	}
262
263
	/**
264
	 * find a folder in the cache which has not been fully scanned
265
	 *
266
	 * If multiply incomplete folders are in the cache, the one with the highest id will be returned,
267
	 * use the one with the highest id gives the best result with the background scanner, since that is most
268
	 * likely the folder where we stopped scanning previously
269
	 *
270
	 * @return string|bool the path of the folder or false when no folder matched
271
	 */
272
	public function getIncomplete() {
273
		// not supported
274
		return false;
275
	}
276
277
	/**
278
	 * get the path of a file on this storage by it's id
279
	 *
280
	 * @param int $id
281
	 * @return string|null
282
	 */
283
	public function getPathById($id) {
284
		$path = $this->getCache()->getPathById($id);
285
		if ($path === null) {
286
			return null;
287
		}
288
289
		return $this->getJailedPath($path);
290
	}
291
292
	/**
293
	 * Move a file or folder in the cache
294
	 *
295
	 * Note that this should make sure the entries are removed from the source cache
296
	 *
297
	 * @param \OCP\Files\Cache\ICache $sourceCache
298
	 * @param string $sourcePath
299
	 * @param string $targetPath
300
	 */
301
	public function moveFromCache(\OCP\Files\Cache\ICache $sourceCache, $sourcePath, $targetPath) {
302
		if ($sourceCache === $this) {
0 ignored issues
show
introduced by
The condition $sourceCache === $this is always false.
Loading history...
303
			return $this->move($sourcePath, $targetPath);
304
		}
305
		return $this->getCache()->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath));
306
	}
307
308
	public function getQueryFilterForStorage(): ISearchOperator {
309
		return new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND,
310
			[
311
				$this->getCache()->getQueryFilterForStorage(),
312
				new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR,
313
					[
314
						new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
315
						new SearchComparison(ISearchComparison::COMPARE_LIKE, 'path', $this->getGetUnjailedRoot() . '/%'),
316
					],
317
				)
318
			]
319
		);
320
	}
321
322
	public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
323
		$rawEntry = $this->getCache()->getCacheEntryFromSearchResult($rawEntry);
324
		if ($rawEntry) {
325
			$jailedPath = $this->getJailedPath($rawEntry->getPath());
326
			if ($jailedPath !== null) {
327
				return $this->formatCacheEntry(clone $rawEntry);
328
			}
329
		}
330
331
		return null;
332
	}
333
}
334