Blame view

sources/apps/files_sharing/lib/cache.php 11.9 KB
03e52840d   Kload   Init
1
2
3
4
  <?php
  /**
   * ownCloud
   *
6d9380f96   Cédric Dupont   Update sources OC...
5
6
7
   * @author Bjoern Schiessle, Michael Gapczynski
   * @copyright 2012 Michael Gapczynski <mtgap@owncloud.com>
   *            2014 Bjoern Schiessle <schiessle@owncloud.com>
03e52840d   Kload   Init
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
   * License as published by the Free Software Foundation; either
   * version 3 of the License, or any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
   *
   * You should have received a copy of the GNU Affero General Public
   * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  namespace OC\Files\Cache;
837968727   Kload   [enh] Upgrade to ...
24

03e52840d   Kload   Init
25
26
27
28
29
30
31
32
33
34
35
  use OCP\Share_Backend_Collection;
  
  /**
   * Metadata cache for shared files
   *
   * don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead
   */
  class Shared_Cache extends Cache {
  
  	private $storage;
  	private $files = array();
6d9380f96   Cédric Dupont   Update sources OC...
36
37
38
  	/**
  	 * @param \OC\Files\Storage\Shared $storage
  	 */
03e52840d   Kload   Init
39
40
41
42
43
  	public function __construct($storage) {
  		$this->storage = $storage;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
44
  	 * Get the source cache of a shared file or folder
f7d878ff1   kload   [enh] Update to 7...
45
  	 *
03e52840d   Kload   Init
46
47
48
49
  	 * @param string $target Shared target file path
  	 * @return \OC\Files\Cache\Cache
  	 */
  	private function getSourceCache($target) {
6d9380f96   Cédric Dupont   Update sources OC...
50
51
52
53
  		if ($target === false || $target === $this->storage->getMountPoint()) {
  			$target = '';
  		}
  		$source = \OC_Share_Backend_File::getSource($target, $this->storage->getMountPoint(), $this->storage->getItemType());
03e52840d   Kload   Init
54
55
  		if (isset($source['path']) && isset($source['fileOwner'])) {
  			\OC\Files\Filesystem::initMountPoints($source['fileOwner']);
6d9380f96   Cédric Dupont   Update sources OC...
56
57
58
  			$mounts = \OC\Files\Filesystem::getMountByNumericId($source['storage']);
  			if (is_array($mounts) and !empty($mounts)) {
  				$fullPath = $mounts[0]->getMountPoint() . $source['path'];
03e52840d   Kload   Init
59
60
61
62
63
64
65
66
67
68
69
70
  				list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath);
  				if ($storage) {
  					$this->files[$target] = $internalPath;
  					$cache = $storage->getCache();
  					$this->storageId = $storage->getId();
  					$this->numericId = $cache->getNumericStorageId();
  					return $cache;
  				}
  			}
  		}
  		return false;
  	}
31b7f2792   Kload   Upgrade to ownclo...
71
72
73
74
75
76
77
  	public function getNumericStorageId() {
  		if (isset($this->numericId)) {
  			return $this->numericId;
  		} else {
  			return false;
  		}
  	}
03e52840d   Kload   Init
78
79
80
  	/**
  	 * get the stored metadata of a file or folder
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
81
  	 * @param string|int $file
03e52840d   Kload   Init
82
83
84
  	 * @return array
  	 */
  	public function get($file) {
6d9380f96   Cédric Dupont   Update sources OC...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  		if (is_string($file)) {
  			$cache = $this->getSourceCache($file);
  			if ($cache) {
  				$data = $cache->get($this->files[$file]);
  				$data['displayname_owner'] = \OC_User::getDisplayName($this->storage->getSharedFrom());
  				$data['path'] = $file;
  				if ($file === '') {
  					$data['is_share_mount_point'] = true;
  				}
  				$data['uid_owner'] = $this->storage->getOwner($file);
  				if (isset($data['permissions'])) {
  					$data['permissions'] &= $this->storage->getPermissions($file);
  				} else {
  					$data['permissions'] = $this->storage->getPermissions($file);
  				}
  				return $data;
03e52840d   Kload   Init
101
102
  			}
  		} else {
6d9380f96   Cédric Dupont   Update sources OC...
103
104
105
106
107
108
  			$sourceId = $file;
  			// if we are at the root of the mount point we want to return the
  			// cache information for the source item
  			if (!is_int($sourceId) || $sourceId === 0) {
  				$sourceId = $this->storage->getSourceId();
  			}
03e52840d   Kload   Init
109
110
  			$query = \OC_DB::prepare(
  				'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`,'
6d9380f96   Cédric Dupont   Update sources OC...
111
  				. ' `size`, `mtime`, `encrypted`, `unencrypted_size`, `storage_mtime`, `etag`, `permissions`'
837968727   Kload   [enh] Upgrade to ...
112
  				. ' FROM `*PREFIX*filecache` WHERE `fileid` = ?');
6d9380f96   Cédric Dupont   Update sources OC...
113
  			$result = $query->execute(array($sourceId));
03e52840d   Kload   Init
114
115
  			$data = $result->fetchRow();
  			$data['fileid'] = (int)$data['fileid'];
03e52840d   Kload   Init
116
  			$data['mtime'] = (int)$data['mtime'];
31b7f2792   Kload   Upgrade to ownclo...
117
  			$data['storage_mtime'] = (int)$data['storage_mtime'];
03e52840d   Kload   Init
118
119
120
  			$data['encrypted'] = (bool)$data['encrypted'];
  			$data['mimetype'] = $this->getMimetype($data['mimetype']);
  			$data['mimepart'] = $this->getMimetype($data['mimepart']);
31b7f2792   Kload   Upgrade to ownclo...
121
122
123
  			if ($data['storage_mtime'] === 0) {
  				$data['storage_mtime'] = $data['mtime'];
  			}
a293d369c   Kload   Update sources to...
124
125
126
127
128
129
  			if ($data['encrypted'] or ($data['unencrypted_size'] > 0 and $data['mimetype'] === 'httpd/unix-directory')) {
  				$data['encrypted_size'] = (int)$data['size'];
  				$data['size'] = (int)$data['unencrypted_size'];
  			} else {
  				$data['size'] = (int)$data['size'];
  			}
6d9380f96   Cédric Dupont   Update sources OC...
130
131
132
133
134
135
136
  			$data['permissions'] = (int)$data['permissions'];
  			if (!is_int($file) || $file === 0) {
  				$data['path'] = '';
  				$data['name'] = basename($this->storage->getMountPoint());
  				$data['is_share_mount_point'] = true;
  			}
  			$data['permissions'] &= $this->storage->getPermissions('');
03e52840d   Kload   Init
137
138
139
140
141
142
143
144
145
146
147
148
  			return $data;
  		}
  		return false;
  	}
  
  	/**
  	 * get the metadata of all files stored in $folder
  	 *
  	 * @param string $folder
  	 * @return array
  	 */
  	public function getFolderContents($folder) {
a293d369c   Kload   Update sources to...
149

6d9380f96   Cédric Dupont   Update sources OC...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  		if ($folder === false) {
  			$folder = '';
  		}
  
  		$dir = ($folder !== '') ? $folder . '/' : '';
  
  		$cache = $this->getSourceCache($folder);
  		if ($cache) {
  			$parent = $this->storage->getFile($folder);
  			$sourceFolderContent = $cache->getFolderContents($this->files[$folder]);
  			foreach ($sourceFolderContent as $key => $c) {
  				$sourceFolderContent[$key]['path'] = $dir . $c['name'];
  				$sourceFolderContent[$key]['uid_owner'] = $parent['uid_owner'];
  				$sourceFolderContent[$key]['displayname_owner'] = \OC_User::getDisplayName($parent['uid_owner']);
  				$sourceFolderContent[$key]['permissions'] = $sourceFolderContent[$key]['permissions'] & $this->storage->getPermissions($dir . $c['name']);
03e52840d   Kload   Init
165
  			}
6d9380f96   Cédric Dupont   Update sources OC...
166
167
  
  			return $sourceFolderContent;
03e52840d   Kload   Init
168
  		}
6d9380f96   Cédric Dupont   Update sources OC...
169

03e52840d   Kload   Init
170
171
172
173
174
175
176
177
178
179
180
181
  		return false;
  	}
  
  	/**
  	 * store meta data for a file or folder
  	 *
  	 * @param string $file
  	 * @param array $data
  	 *
  	 * @return int file id
  	 */
  	public function put($file, array $data) {
6d9380f96   Cédric Dupont   Update sources OC...
182
183
  		$file = ($file === false) ? '' : $file;
  		if ($cache = $this->getSourceCache($file)) {
03e52840d   Kload   Init
184
185
186
187
188
189
190
191
192
193
194
195
  			return $cache->put($this->files[$file], $data);
  		}
  		return false;
  	}
  
  	/**
  	 * get the file id for a file
  	 *
  	 * @param string $file
  	 * @return int
  	 */
  	public function getId($file) {
6d9380f96   Cédric Dupont   Update sources OC...
196
197
198
199
200
  		if ($file === false) {
  			return $this->storage->getSourceId();
  		}
  		$cache = $this->getSourceCache($file);
  		if ($cache) {
03e52840d   Kload   Init
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  			return $cache->getId($this->files[$file]);
  		}
  		return -1;
  	}
  
  	/**
  	 * check if a file is available in the cache
  	 *
  	 * @param string $file
  	 * @return bool
  	 */
  	public function inCache($file) {
  		if ($file == '') {
  			return true;
  		}
  		return parent::inCache($file);
  	}
  
  	/**
  	 * remove a file or folder from the cache
  	 *
  	 * @param string $file
  	 */
  	public function remove($file) {
6d9380f96   Cédric Dupont   Update sources OC...
225
  		$file = ($file === false) ? '' : $file;
03e52840d   Kload   Init
226
227
228
229
230
231
232
233
234
235
236
237
238
  		if ($cache = $this->getSourceCache($file)) {
  			$cache->remove($this->files[$file]);
  		}
  	}
  
  	/**
  	 * Move a file or folder in the cache
  	 *
  	 * @param string $source
  	 * @param string $target
  	 */
  	public function move($source, $target) {
  		if ($cache = $this->getSourceCache($source)) {
6d9380f96   Cédric Dupont   Update sources OC...
239
  			$file = \OC_Share_Backend_File::getSource($target, $this->storage->getMountPoint(), $this->storage->getItemType());
03e52840d   Kload   Init
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  			if ($file && isset($file['path'])) {
  				$cache->move($this->files[$source], $file['path']);
  			}
  		}
  	}
  
  	/**
  	 * remove all entries for files that are stored on the storage from the cache
  	 */
  	public function clear() {
  		// Not a valid action for Shared Cache
  	}
  
  	/**
  	 * @param string $file
  	 *
  	 * @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE
  	 */
  	public function getStatus($file) {
  		if ($file == '') {
  			return self::COMPLETE;
  		}
  		if ($cache = $this->getSourceCache($file)) {
  			return $cache->getStatus($this->files[$file]);
  		}
  		return self::NOT_FOUND;
  	}
  
  	/**
  	 * search for files matching $pattern
  	 *
  	 * @param string $pattern
  	 * @return array of file data
  	 */
  	public function search($pattern) {
f7d878ff1   kload   [enh] Update to 7...
275
  		$pattern = trim($pattern,'%');
03e52840d   Kload   Init
276

f7d878ff1   kload   [enh] Update to 7...
277
  		$normalizedPattern = $this->normalize($pattern);
03e52840d   Kload   Init
278

f7d878ff1   kload   [enh] Update to 7...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  		$result = array();
  		$exploreDirs = array('');
  		while (count($exploreDirs) > 0) {
  			$dir = array_pop($exploreDirs);
  			$files = $this->getFolderContents($dir);
  			// no results?
  			if (!$files) {
  				// maybe it's a single shared file
  				$file = $this->get('');
  				if ($normalizedPattern === '' || stristr($file['name'], $normalizedPattern) !== false) {
  					$result[] = $file;
  				}
  				continue;
  			}
  			foreach ($files as $file) {
  				if ($normalizedPattern === '' || stristr($file['name'], $normalizedPattern) !== false) {
  					$result[] = $file;
  				}
  				if ($file['mimetype'] === 'httpd/unix-directory') {
  					$exploreDirs[] = ltrim($dir . '/' . $file['name'], '/');
  				}
  			}
  		}
  		return $result;
03e52840d   Kload   Init
303
304
305
306
307
308
309
310
311
312
  
  	}
  
  	/**
  	 * search for files by mimetype
  	 *
  	 * @param string $mimetype
  	 * @return array
  	 */
  	public function searchByMime($mimetype) {
a293d369c   Kload   Update sources to...
313
314
315
316
  		$mimepart = null;
  		if (strpos($mimetype, '/') === false) {
  			$mimepart = $mimetype;
  			$mimetype = null;
03e52840d   Kload   Init
317
  		}
a293d369c   Kload   Update sources to...
318
319
320
321
322
323
324
  		$result = array();
  		$exploreDirs = array('');
  		while (count($exploreDirs) > 0) {
  			$dir = array_pop($exploreDirs);
  			$files = $this->getFolderContents($dir);
  			// no results?
  			if (!$files) {
6d9380f96   Cédric Dupont   Update sources OC...
325
326
327
328
329
  				// maybe it's a single shared file
  				$file = $this->get('');
  				if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) {
  					$result[] = $file;
  				}
a293d369c   Kload   Update sources to...
330
331
332
333
334
  				continue;
  			}
  			foreach ($files as $file) {
  				if ($file['mimetype'] === 'httpd/unix-directory') {
  					$exploreDirs[] = ltrim($dir . '/' . $file['name'], '/');
837968727   Kload   [enh] Upgrade to ...
335
  				} else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) {
a293d369c   Kload   Update sources to...
336
337
338
339
340
  					$result[] = $file;
  				}
  			}
  		}
  		return $result;
03e52840d   Kload   Init
341
  	}
a293d369c   Kload   Update sources to...
342

03e52840d   Kload   Init
343
  	/**
03e52840d   Kload   Init
344
345
346
  	 * get the size of a folder and set it in the cache
  	 *
  	 * @param string $path
6d9380f96   Cédric Dupont   Update sources OC...
347
  	 * @param array $entry (optional) meta data of the folder
03e52840d   Kload   Init
348
349
  	 * @return int
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
350
351
  	public function calculateFolderSize($path, $entry = null) {
  		$path = ($path === false) ? '' : $path;
03e52840d   Kload   Init
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
  		if ($cache = $this->getSourceCache($path)) {
  			return $cache->calculateFolderSize($this->files[$path]);
  		}
  		return 0;
  	}
  
  	/**
  	 * get all file ids on the files on the storage
  	 *
  	 * @return int[]
  	 */
  	public function getAll() {
  		$ids = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_ALL);
  		$folderBackend = \OCP\Share::getBackend('folder');
  		if ($folderBackend instanceof Share_Backend_Collection) {
  			foreach ($ids as $file) {
  				/** @var $folderBackend Share_Backend_Collection */
  				$children = $folderBackend->getChildren($file);
  				foreach ($children as $child) {
  					$ids[] = (int)$child['source'];
  				}
  
  			}
  		}
  
  		return $ids;
  	}
31b7f2792   Kload   Upgrade to ownclo...
379
380
381
382
383
384
385
  	/**
  	 * find a folder in the cache which has not been fully scanned
  	 *
  	 * If multiply incomplete folders are in the cache, the one with the highest id will be returned,
  	 * use the one with the highest id gives the best result with the background scanner, since that is most
  	 * likely the folder where we stopped scanning previously
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
386
  	 * @return boolean the path of the folder or false when no folder matched
31b7f2792   Kload   Upgrade to ownclo...
387
388
389
390
  	 */
  	public function getIncomplete() {
  		return false;
  	}
837968727   Kload   [enh] Upgrade to ...
391
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
392
  	 * get the path of a file on this storage relative to the mount point by it's id
837968727   Kload   [enh] Upgrade to ...
393
394
395
  	 *
  	 * @param int $id
  	 * @param string $pathEnd (optional) used internally for recursive calls
6d9380f96   Cédric Dupont   Update sources OC...
396
  	 * @return string|null
837968727   Kload   [enh] Upgrade to ...
397
398
399
  	 */
  	public function getPathById($id, $pathEnd = '') {
  		// direct shares are easy
f7d878ff1   kload   [enh] Update to 7...
400
  		if ($id === $this->storage->getSourceId()) {
6d9380f96   Cédric Dupont   Update sources OC...
401
  			return ltrim($pathEnd, '/');
837968727   Kload   [enh] Upgrade to ...
402
403
404
405
406
407
408
409
410
411
  		} else {
  			// if the item is a direct share we try and get the path of the parent and append the name of the item to it
  			list($parent, $name) = $this->getParentInfo($id);
  			if ($parent > 0) {
  				return $this->getPathById($parent, '/' . $name . $pathEnd);
  			} else {
  				return null;
  			}
  		}
  	}
6d9380f96   Cédric Dupont   Update sources OC...
412
413
  	/**
  	 * @param integer $id
f7d878ff1   kload   [enh] Update to 7...
414
  	 * @return array
6d9380f96   Cédric Dupont   Update sources OC...
415
  	 */
837968727   Kload   [enh] Upgrade to ...
416
417
418
419
420
  	private function getParentInfo($id) {
  		$sql = 'SELECT `parent`, `name` FROM `*PREFIX*filecache` WHERE `fileid` = ?';
  		$query = \OC_DB::prepare($sql);
  		$result = $query->execute(array($id));
  		if ($row = $result->fetchRow()) {
f7d878ff1   kload   [enh] Update to 7...
421
  			return array((int)$row['parent'], $row['name']);
837968727   Kload   [enh] Upgrade to ...
422
423
424
425
  		} else {
  			return array(-1, '');
  		}
  	}
03e52840d   Kload   Init
426
  }