Passed
Push — master ( a91559...331f3b )
by Morris
10:02
created
lib/private/Encryption/EncryptionWrapper.php 1 patch
Indentation   +71 added lines, -71 removed lines patch added patch discarded remove patch
@@ -42,83 +42,83 @@
 block discarded – undo
42 42
  */
43 43
 class EncryptionWrapper {
44 44
 
45
-	/** @var ArrayCache  */
46
-	private $arrayCache;
45
+    /** @var ArrayCache  */
46
+    private $arrayCache;
47 47
 
48
-	/** @var  Manager */
49
-	private $manager;
48
+    /** @var  Manager */
49
+    private $manager;
50 50
 
51
-	/** @var  ILogger */
52
-	private $logger;
51
+    /** @var  ILogger */
52
+    private $logger;
53 53
 
54
-	/**
55
-	 * EncryptionWrapper constructor.
56
-	 *
57
-	 * @param ArrayCache $arrayCache
58
-	 * @param Manager $manager
59
-	 * @param ILogger $logger
60
-	 */
61
-	public function __construct(ArrayCache $arrayCache,
62
-								Manager $manager,
63
-								ILogger $logger
64
-	) {
65
-		$this->arrayCache = $arrayCache;
66
-		$this->manager = $manager;
67
-		$this->logger = $logger;
68
-	}
54
+    /**
55
+     * EncryptionWrapper constructor.
56
+     *
57
+     * @param ArrayCache $arrayCache
58
+     * @param Manager $manager
59
+     * @param ILogger $logger
60
+     */
61
+    public function __construct(ArrayCache $arrayCache,
62
+                                Manager $manager,
63
+                                ILogger $logger
64
+    ) {
65
+        $this->arrayCache = $arrayCache;
66
+        $this->manager = $manager;
67
+        $this->logger = $logger;
68
+    }
69 69
 
70
-	/**
71
-	 * Wraps the given storage when it is not a shared storage
72
-	 *
73
-	 * @param string $mountPoint
74
-	 * @param Storage $storage
75
-	 * @param IMountPoint $mount
76
-	 * @return Encryption|Storage
77
-	 */
78
-	public function wrapStorage($mountPoint, Storage $storage, IMountPoint $mount) {
79
-		$parameters = [
80
-			'storage' => $storage,
81
-			'mountPoint' => $mountPoint,
82
-			'mount' => $mount
83
-		];
70
+    /**
71
+     * Wraps the given storage when it is not a shared storage
72
+     *
73
+     * @param string $mountPoint
74
+     * @param Storage $storage
75
+     * @param IMountPoint $mount
76
+     * @return Encryption|Storage
77
+     */
78
+    public function wrapStorage($mountPoint, Storage $storage, IMountPoint $mount) {
79
+        $parameters = [
80
+            'storage' => $storage,
81
+            'mountPoint' => $mountPoint,
82
+            'mount' => $mount
83
+        ];
84 84
 
85
-		if (!$storage->instanceOfStorage(Storage\IDisableEncryptionStorage::class)) {
85
+        if (!$storage->instanceOfStorage(Storage\IDisableEncryptionStorage::class)) {
86 86
 
87
-			$user = \OC::$server->getUserSession()->getUser();
88
-			$mountManager = Filesystem::getMountManager();
89
-			$uid = $user ? $user->getUID() : null;
90
-			$fileHelper = \OC::$server->getEncryptionFilesHelper();
91
-			$keyStorage = \OC::$server->getEncryptionKeyStorage();
87
+            $user = \OC::$server->getUserSession()->getUser();
88
+            $mountManager = Filesystem::getMountManager();
89
+            $uid = $user ? $user->getUID() : null;
90
+            $fileHelper = \OC::$server->getEncryptionFilesHelper();
91
+            $keyStorage = \OC::$server->getEncryptionKeyStorage();
92 92
 
93
-			$util = new Util(
94
-				new View(),
95
-				\OC::$server->getUserManager(),
96
-				\OC::$server->getGroupManager(),
97
-				\OC::$server->getConfig()
98
-			);
99
-			$update = new Update(
100
-				new View(),
101
-				$util,
102
-				Filesystem::getMountManager(),
103
-				$this->manager,
104
-				$fileHelper,
105
-				$uid
106
-			);
107
-			return new Encryption(
108
-				$parameters,
109
-				$this->manager,
110
-				$util,
111
-				$this->logger,
112
-				$fileHelper,
113
-				$uid,
114
-				$keyStorage,
115
-				$update,
116
-				$mountManager,
117
-				$this->arrayCache
118
-			);
119
-		} else {
120
-			return $storage;
121
-		}
122
-	}
93
+            $util = new Util(
94
+                new View(),
95
+                \OC::$server->getUserManager(),
96
+                \OC::$server->getGroupManager(),
97
+                \OC::$server->getConfig()
98
+            );
99
+            $update = new Update(
100
+                new View(),
101
+                $util,
102
+                Filesystem::getMountManager(),
103
+                $this->manager,
104
+                $fileHelper,
105
+                $uid
106
+            );
107
+            return new Encryption(
108
+                $parameters,
109
+                $this->manager,
110
+                $util,
111
+                $this->logger,
112
+                $fileHelper,
113
+                $uid,
114
+                $keyStorage,
115
+                $update,
116
+                $mountManager,
117
+                $this->arrayCache
118
+            );
119
+        } else {
120
+            return $storage;
121
+        }
122
+    }
123 123
 
124 124
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/External/Storage.php 1 patch
Indentation   +376 added lines, -376 removed lines patch added patch discarded remove patch
@@ -44,380 +44,380 @@
 block discarded – undo
44 44
 use OCP\Files\StorageNotAvailableException;
45 45
 
46 46
 class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage {
47
-	/** @var ICloudId */
48
-	private $cloudId;
49
-	/** @var string */
50
-	private $mountPoint;
51
-	/** @var string */
52
-	private $token;
53
-	/** @var \OCP\ICacheFactory */
54
-	private $memcacheFactory;
55
-	/** @var \OCP\Http\Client\IClientService */
56
-	private $httpClient;
57
-	/** @var bool */
58
-	private $updateChecked = false;
59
-
60
-	/**
61
-	 * @var \OCA\Files_Sharing\External\Manager
62
-	 */
63
-	private $manager;
64
-
65
-	public function __construct($options) {
66
-		$this->memcacheFactory = \OC::$server->getMemCacheFactory();
67
-		$this->httpClient = $options['HttpClientService'];
68
-
69
-		$this->manager = $options['manager'];
70
-		$this->cloudId = $options['cloudId'];
71
-		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
72
-
73
-		list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
74
-		if (strpos($remote, '/')) {
75
-			list($host, $root) = explode('/', $remote, 2);
76
-		} else {
77
-			$host = $remote;
78
-			$root = '';
79
-		}
80
-		$secure = $protocol === 'https';
81
-		$federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
82
-		$webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
83
-		$root = rtrim($root, '/') . $webDavEndpoint;
84
-		$this->mountPoint = $options['mountpoint'];
85
-		$this->token = $options['token'];
86
-
87
-		parent::__construct(array(
88
-			'secure' => $secure,
89
-			'host' => $host,
90
-			'root' => $root,
91
-			'user' => $options['token'],
92
-			'password' => (string)$options['password']
93
-		));
94
-	}
95
-
96
-	public function getWatcher($path = '', $storage = null) {
97
-		if (!$storage) {
98
-			$storage = $this;
99
-		}
100
-		if (!isset($this->watcher)) {
101
-			$this->watcher = new Watcher($storage);
102
-			$this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
103
-		}
104
-		return $this->watcher;
105
-	}
106
-
107
-	public function getRemoteUser() {
108
-		return $this->cloudId->getUser();
109
-	}
110
-
111
-	public function getRemote() {
112
-		return $this->cloudId->getRemote();
113
-	}
114
-
115
-	public function getMountPoint() {
116
-		return $this->mountPoint;
117
-	}
118
-
119
-	public function getToken() {
120
-		return $this->token;
121
-	}
122
-
123
-	public function getPassword() {
124
-		return $this->password;
125
-	}
126
-
127
-	/**
128
-	 * @brief get id of the mount point
129
-	 * @return string
130
-	 */
131
-	public function getId() {
132
-		return 'shared::' . md5($this->token . '@' . $this->getRemote());
133
-	}
134
-
135
-	public function getCache($path = '', $storage = null) {
136
-		if (is_null($this->cache)) {
137
-			$this->cache = new Cache($this, $this->cloudId);
138
-		}
139
-		return $this->cache;
140
-	}
141
-
142
-	/**
143
-	 * @param string $path
144
-	 * @param \OC\Files\Storage\Storage $storage
145
-	 * @return \OCA\Files_Sharing\External\Scanner
146
-	 */
147
-	public function getScanner($path = '', $storage = null) {
148
-		if (!$storage) {
149
-			$storage = $this;
150
-		}
151
-		if (!isset($this->scanner)) {
152
-			$this->scanner = new Scanner($storage);
153
-		}
154
-		return $this->scanner;
155
-	}
156
-
157
-	/**
158
-	 * check if a file or folder has been updated since $time
159
-	 *
160
-	 * @param string $path
161
-	 * @param int $time
162
-	 * @throws \OCP\Files\StorageNotAvailableException
163
-	 * @throws \OCP\Files\StorageInvalidException
164
-	 * @return bool
165
-	 */
166
-	public function hasUpdated($path, $time) {
167
-		// since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
168
-		// because of that we only do one check for the entire storage per request
169
-		if ($this->updateChecked) {
170
-			return false;
171
-		}
172
-		$this->updateChecked = true;
173
-		try {
174
-			return parent::hasUpdated('', $time);
175
-		} catch (StorageInvalidException $e) {
176
-			// check if it needs to be removed
177
-			$this->checkStorageAvailability();
178
-			throw $e;
179
-		} catch (StorageNotAvailableException $e) {
180
-			// check if it needs to be removed or just temp unavailable
181
-			$this->checkStorageAvailability();
182
-			throw $e;
183
-		}
184
-	}
185
-
186
-	public function test() {
187
-		try {
188
-			return parent::test();
189
-		} catch (StorageInvalidException $e) {
190
-			// check if it needs to be removed
191
-			$this->checkStorageAvailability();
192
-			throw $e;
193
-		} catch (StorageNotAvailableException $e) {
194
-			// check if it needs to be removed or just temp unavailable
195
-			$this->checkStorageAvailability();
196
-			throw $e;
197
-		}
198
-	}
199
-
200
-	/**
201
-	 * Check whether this storage is permanently or temporarily
202
-	 * unavailable
203
-	 *
204
-	 * @throws \OCP\Files\StorageNotAvailableException
205
-	 * @throws \OCP\Files\StorageInvalidException
206
-	 */
207
-	public function checkStorageAvailability() {
208
-		// see if we can find out why the share is unavailable
209
-		try {
210
-			$this->getShareInfo();
211
-		} catch (NotFoundException $e) {
212
-			// a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
213
-			if ($this->testRemote()) {
214
-				// valid Nextcloud instance means that the public share no longer exists
215
-				// since this is permanent (re-sharing the file will create a new token)
216
-				// we remove the invalid storage
217
-				$this->manager->removeShare($this->mountPoint);
218
-				$this->manager->getMountManager()->removeMount($this->mountPoint);
219
-				throw new StorageInvalidException();
220
-			} else {
221
-				// Nextcloud instance is gone, likely to be a temporary server configuration error
222
-				throw new StorageNotAvailableException();
223
-			}
224
-		} catch (ForbiddenException $e) {
225
-			// auth error, remove share for now (provide a dialog in the future)
226
-			$this->manager->removeShare($this->mountPoint);
227
-			$this->manager->getMountManager()->removeMount($this->mountPoint);
228
-			throw new StorageInvalidException();
229
-		} catch (\GuzzleHttp\Exception\ConnectException $e) {
230
-			throw new StorageNotAvailableException();
231
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
232
-			throw new StorageNotAvailableException();
233
-		} catch (\Exception $e) {
234
-			throw $e;
235
-		}
236
-	}
237
-
238
-	public function file_exists($path) {
239
-		if ($path === '') {
240
-			return true;
241
-		} else {
242
-			return parent::file_exists($path);
243
-		}
244
-	}
245
-
246
-	/**
247
-	 * check if the configured remote is a valid federated share provider
248
-	 *
249
-	 * @return bool
250
-	 */
251
-	protected function testRemote() {
252
-		try {
253
-			return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
254
-				|| $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
255
-				|| $this->testRemoteUrl($this->getRemote() . '/status.php');
256
-		} catch (\Exception $e) {
257
-			return false;
258
-		}
259
-	}
260
-
261
-	/**
262
-	 * @param string $url
263
-	 * @return bool
264
-	 */
265
-	private function testRemoteUrl($url) {
266
-		$cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
267
-		if($cache->hasKey($url)) {
268
-			return (bool)$cache->get($url);
269
-		}
270
-
271
-		$client = $this->httpClient->newClient();
272
-		try {
273
-			$result = $client->get($url, [
274
-				'timeout' => 10,
275
-				'connect_timeout' => 10,
276
-			])->getBody();
277
-			$data = json_decode($result);
278
-			$returnValue = (is_object($data) && !empty($data->version));
279
-		} catch (ConnectException $e) {
280
-			$returnValue = false;
281
-		} catch (ClientException $e) {
282
-			$returnValue = false;
283
-		}
284
-
285
-		$cache->set($url, $returnValue, 60*60*24);
286
-		return $returnValue;
287
-	}
288
-
289
-	/**
290
-	 * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
291
-	 * standardized. Let's use this to detect whether to use it.
292
-	 *
293
-	 * @return bool
294
-	 */
295
-	public function remoteIsOwnCloud() {
296
-		if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
297
-			return false;
298
-		}
299
-		return true;
300
-	}
301
-
302
-	/**
303
-	 * @return mixed
304
-	 * @throws ForbiddenException
305
-	 * @throws NotFoundException
306
-	 * @throws \Exception
307
-	 */
308
-	public function getShareInfo() {
309
-		$remote = $this->getRemote();
310
-		$token = $this->getToken();
311
-		$password = $this->getPassword();
312
-
313
-		// If remote is not an ownCloud do not try to get any share info
314
-		if(!$this->remoteIsOwnCloud()) {
315
-			return ['status' => 'unsupported'];
316
-		}
317
-
318
-		$url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
319
-
320
-		// TODO: DI
321
-		$client = \OC::$server->getHTTPClientService()->newClient();
322
-		try {
323
-			$response = $client->post($url, [
324
-				'body' => ['password' => $password],
325
-				'timeout' => 10,
326
-				'connect_timeout' => 10,
327
-			]);
328
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
329
-			if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
330
-				throw new ForbiddenException();
331
-			}
332
-			if ($e->getCode() === Http::STATUS_NOT_FOUND) {
333
-				throw new NotFoundException();
334
-			}
335
-			// throw this to be on the safe side: the share will still be visible
336
-			// in the UI in case the failure is intermittent, and the user will
337
-			// be able to decide whether to remove it if it's really gone
338
-			throw new StorageNotAvailableException();
339
-		}
340
-
341
-		return json_decode($response->getBody(), true);
342
-	}
343
-
344
-	public function getOwner($path) {
345
-		return $this->cloudId->getDisplayId();
346
-	}
347
-
348
-	public function isSharable($path) {
349
-		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
350
-			return false;
351
-		}
352
-		return ($this->getPermissions($path) & Constants::PERMISSION_SHARE);
353
-	}
354
-
355
-	public function getPermissions($path) {
356
-		$response = $this->propfind($path);
357
-		// old federated sharing permissions
358
-		if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
359
-			$permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
360
-		} else if (isset($response['{http://open-cloud-mesh.org/ns}share-permissions'])) {
361
-			// permissions provided by the OCM API
362
-			$permissions = $this->ocmPermissions2ncPermissions($response['{http://open-collaboration-services.org/ns}share-permissions']);
363
-		} else {
364
-			// use default permission if remote server doesn't provide the share permissions
365
-			$permissions = $this->getDefaultPermissions($path);
366
-		}
367
-
368
-		return $permissions;
369
-	}
370
-
371
-	public function needsPartFile() {
372
-		return false;
373
-	}
374
-
375
-	/**
376
-	 * translate OCM Permissions to Nextcloud permissions
377
-	 *
378
-	 * @param string $ocmPermissions json encoded OCM permissions
379
-	 * @param string $path path to file
380
-	 * @return int
381
-	 */
382
-	protected function ocmPermissions2ncPermissions($ocmPermissions, $path) {
383
-		try {
384
-			$ocmPermissions = json_decode($ocmPermissions);
385
-			$ncPermissions = 0;
386
-			foreach($ocmPermissions as $permission) {
387
-				switch (strtolower($permission)) {
388
-					case 'read':
389
-						$ncPermissions += Constants::PERMISSION_READ;
390
-						break;
391
-					case 'write':
392
-						$ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
393
-						break;
394
-					case 'share':
395
-						$ncPermissions += Constants::PERMISSION_SHARE;
396
-						break;
397
-					default:
398
-						throw new \Exception();
399
-				}
400
-			}
401
-		} catch (\Exception $e) {
402
-			$ncPermissions = $this->getDefaultPermissions($path);
403
-		}
404
-
405
-		return $ncPermissions;
406
-	}
407
-
408
-	/**
409
-	 * calculate default permissions in case no permissions are provided
410
-	 *
411
-	 * @param $path
412
-	 * @return int
413
-	 */
414
-	protected function getDefaultPermissions($path) {
415
-		if ($this->is_dir($path)) {
416
-			$permissions = Constants::PERMISSION_ALL;
417
-		} else {
418
-			$permissions = Constants::PERMISSION_ALL & ~Constants::PERMISSION_CREATE;
419
-		}
420
-
421
-		return $permissions;
422
-	}
47
+    /** @var ICloudId */
48
+    private $cloudId;
49
+    /** @var string */
50
+    private $mountPoint;
51
+    /** @var string */
52
+    private $token;
53
+    /** @var \OCP\ICacheFactory */
54
+    private $memcacheFactory;
55
+    /** @var \OCP\Http\Client\IClientService */
56
+    private $httpClient;
57
+    /** @var bool */
58
+    private $updateChecked = false;
59
+
60
+    /**
61
+     * @var \OCA\Files_Sharing\External\Manager
62
+     */
63
+    private $manager;
64
+
65
+    public function __construct($options) {
66
+        $this->memcacheFactory = \OC::$server->getMemCacheFactory();
67
+        $this->httpClient = $options['HttpClientService'];
68
+
69
+        $this->manager = $options['manager'];
70
+        $this->cloudId = $options['cloudId'];
71
+        $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
72
+
73
+        list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
74
+        if (strpos($remote, '/')) {
75
+            list($host, $root) = explode('/', $remote, 2);
76
+        } else {
77
+            $host = $remote;
78
+            $root = '';
79
+        }
80
+        $secure = $protocol === 'https';
81
+        $federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
82
+        $webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
83
+        $root = rtrim($root, '/') . $webDavEndpoint;
84
+        $this->mountPoint = $options['mountpoint'];
85
+        $this->token = $options['token'];
86
+
87
+        parent::__construct(array(
88
+            'secure' => $secure,
89
+            'host' => $host,
90
+            'root' => $root,
91
+            'user' => $options['token'],
92
+            'password' => (string)$options['password']
93
+        ));
94
+    }
95
+
96
+    public function getWatcher($path = '', $storage = null) {
97
+        if (!$storage) {
98
+            $storage = $this;
99
+        }
100
+        if (!isset($this->watcher)) {
101
+            $this->watcher = new Watcher($storage);
102
+            $this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
103
+        }
104
+        return $this->watcher;
105
+    }
106
+
107
+    public function getRemoteUser() {
108
+        return $this->cloudId->getUser();
109
+    }
110
+
111
+    public function getRemote() {
112
+        return $this->cloudId->getRemote();
113
+    }
114
+
115
+    public function getMountPoint() {
116
+        return $this->mountPoint;
117
+    }
118
+
119
+    public function getToken() {
120
+        return $this->token;
121
+    }
122
+
123
+    public function getPassword() {
124
+        return $this->password;
125
+    }
126
+
127
+    /**
128
+     * @brief get id of the mount point
129
+     * @return string
130
+     */
131
+    public function getId() {
132
+        return 'shared::' . md5($this->token . '@' . $this->getRemote());
133
+    }
134
+
135
+    public function getCache($path = '', $storage = null) {
136
+        if (is_null($this->cache)) {
137
+            $this->cache = new Cache($this, $this->cloudId);
138
+        }
139
+        return $this->cache;
140
+    }
141
+
142
+    /**
143
+     * @param string $path
144
+     * @param \OC\Files\Storage\Storage $storage
145
+     * @return \OCA\Files_Sharing\External\Scanner
146
+     */
147
+    public function getScanner($path = '', $storage = null) {
148
+        if (!$storage) {
149
+            $storage = $this;
150
+        }
151
+        if (!isset($this->scanner)) {
152
+            $this->scanner = new Scanner($storage);
153
+        }
154
+        return $this->scanner;
155
+    }
156
+
157
+    /**
158
+     * check if a file or folder has been updated since $time
159
+     *
160
+     * @param string $path
161
+     * @param int $time
162
+     * @throws \OCP\Files\StorageNotAvailableException
163
+     * @throws \OCP\Files\StorageInvalidException
164
+     * @return bool
165
+     */
166
+    public function hasUpdated($path, $time) {
167
+        // since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
168
+        // because of that we only do one check for the entire storage per request
169
+        if ($this->updateChecked) {
170
+            return false;
171
+        }
172
+        $this->updateChecked = true;
173
+        try {
174
+            return parent::hasUpdated('', $time);
175
+        } catch (StorageInvalidException $e) {
176
+            // check if it needs to be removed
177
+            $this->checkStorageAvailability();
178
+            throw $e;
179
+        } catch (StorageNotAvailableException $e) {
180
+            // check if it needs to be removed or just temp unavailable
181
+            $this->checkStorageAvailability();
182
+            throw $e;
183
+        }
184
+    }
185
+
186
+    public function test() {
187
+        try {
188
+            return parent::test();
189
+        } catch (StorageInvalidException $e) {
190
+            // check if it needs to be removed
191
+            $this->checkStorageAvailability();
192
+            throw $e;
193
+        } catch (StorageNotAvailableException $e) {
194
+            // check if it needs to be removed or just temp unavailable
195
+            $this->checkStorageAvailability();
196
+            throw $e;
197
+        }
198
+    }
199
+
200
+    /**
201
+     * Check whether this storage is permanently or temporarily
202
+     * unavailable
203
+     *
204
+     * @throws \OCP\Files\StorageNotAvailableException
205
+     * @throws \OCP\Files\StorageInvalidException
206
+     */
207
+    public function checkStorageAvailability() {
208
+        // see if we can find out why the share is unavailable
209
+        try {
210
+            $this->getShareInfo();
211
+        } catch (NotFoundException $e) {
212
+            // a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
213
+            if ($this->testRemote()) {
214
+                // valid Nextcloud instance means that the public share no longer exists
215
+                // since this is permanent (re-sharing the file will create a new token)
216
+                // we remove the invalid storage
217
+                $this->manager->removeShare($this->mountPoint);
218
+                $this->manager->getMountManager()->removeMount($this->mountPoint);
219
+                throw new StorageInvalidException();
220
+            } else {
221
+                // Nextcloud instance is gone, likely to be a temporary server configuration error
222
+                throw new StorageNotAvailableException();
223
+            }
224
+        } catch (ForbiddenException $e) {
225
+            // auth error, remove share for now (provide a dialog in the future)
226
+            $this->manager->removeShare($this->mountPoint);
227
+            $this->manager->getMountManager()->removeMount($this->mountPoint);
228
+            throw new StorageInvalidException();
229
+        } catch (\GuzzleHttp\Exception\ConnectException $e) {
230
+            throw new StorageNotAvailableException();
231
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
232
+            throw new StorageNotAvailableException();
233
+        } catch (\Exception $e) {
234
+            throw $e;
235
+        }
236
+    }
237
+
238
+    public function file_exists($path) {
239
+        if ($path === '') {
240
+            return true;
241
+        } else {
242
+            return parent::file_exists($path);
243
+        }
244
+    }
245
+
246
+    /**
247
+     * check if the configured remote is a valid federated share provider
248
+     *
249
+     * @return bool
250
+     */
251
+    protected function testRemote() {
252
+        try {
253
+            return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
254
+                || $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
255
+                || $this->testRemoteUrl($this->getRemote() . '/status.php');
256
+        } catch (\Exception $e) {
257
+            return false;
258
+        }
259
+    }
260
+
261
+    /**
262
+     * @param string $url
263
+     * @return bool
264
+     */
265
+    private function testRemoteUrl($url) {
266
+        $cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
267
+        if($cache->hasKey($url)) {
268
+            return (bool)$cache->get($url);
269
+        }
270
+
271
+        $client = $this->httpClient->newClient();
272
+        try {
273
+            $result = $client->get($url, [
274
+                'timeout' => 10,
275
+                'connect_timeout' => 10,
276
+            ])->getBody();
277
+            $data = json_decode($result);
278
+            $returnValue = (is_object($data) && !empty($data->version));
279
+        } catch (ConnectException $e) {
280
+            $returnValue = false;
281
+        } catch (ClientException $e) {
282
+            $returnValue = false;
283
+        }
284
+
285
+        $cache->set($url, $returnValue, 60*60*24);
286
+        return $returnValue;
287
+    }
288
+
289
+    /**
290
+     * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
291
+     * standardized. Let's use this to detect whether to use it.
292
+     *
293
+     * @return bool
294
+     */
295
+    public function remoteIsOwnCloud() {
296
+        if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
297
+            return false;
298
+        }
299
+        return true;
300
+    }
301
+
302
+    /**
303
+     * @return mixed
304
+     * @throws ForbiddenException
305
+     * @throws NotFoundException
306
+     * @throws \Exception
307
+     */
308
+    public function getShareInfo() {
309
+        $remote = $this->getRemote();
310
+        $token = $this->getToken();
311
+        $password = $this->getPassword();
312
+
313
+        // If remote is not an ownCloud do not try to get any share info
314
+        if(!$this->remoteIsOwnCloud()) {
315
+            return ['status' => 'unsupported'];
316
+        }
317
+
318
+        $url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
319
+
320
+        // TODO: DI
321
+        $client = \OC::$server->getHTTPClientService()->newClient();
322
+        try {
323
+            $response = $client->post($url, [
324
+                'body' => ['password' => $password],
325
+                'timeout' => 10,
326
+                'connect_timeout' => 10,
327
+            ]);
328
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
329
+            if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
330
+                throw new ForbiddenException();
331
+            }
332
+            if ($e->getCode() === Http::STATUS_NOT_FOUND) {
333
+                throw new NotFoundException();
334
+            }
335
+            // throw this to be on the safe side: the share will still be visible
336
+            // in the UI in case the failure is intermittent, and the user will
337
+            // be able to decide whether to remove it if it's really gone
338
+            throw new StorageNotAvailableException();
339
+        }
340
+
341
+        return json_decode($response->getBody(), true);
342
+    }
343
+
344
+    public function getOwner($path) {
345
+        return $this->cloudId->getDisplayId();
346
+    }
347
+
348
+    public function isSharable($path) {
349
+        if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
350
+            return false;
351
+        }
352
+        return ($this->getPermissions($path) & Constants::PERMISSION_SHARE);
353
+    }
354
+
355
+    public function getPermissions($path) {
356
+        $response = $this->propfind($path);
357
+        // old federated sharing permissions
358
+        if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
359
+            $permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
360
+        } else if (isset($response['{http://open-cloud-mesh.org/ns}share-permissions'])) {
361
+            // permissions provided by the OCM API
362
+            $permissions = $this->ocmPermissions2ncPermissions($response['{http://open-collaboration-services.org/ns}share-permissions']);
363
+        } else {
364
+            // use default permission if remote server doesn't provide the share permissions
365
+            $permissions = $this->getDefaultPermissions($path);
366
+        }
367
+
368
+        return $permissions;
369
+    }
370
+
371
+    public function needsPartFile() {
372
+        return false;
373
+    }
374
+
375
+    /**
376
+     * translate OCM Permissions to Nextcloud permissions
377
+     *
378
+     * @param string $ocmPermissions json encoded OCM permissions
379
+     * @param string $path path to file
380
+     * @return int
381
+     */
382
+    protected function ocmPermissions2ncPermissions($ocmPermissions, $path) {
383
+        try {
384
+            $ocmPermissions = json_decode($ocmPermissions);
385
+            $ncPermissions = 0;
386
+            foreach($ocmPermissions as $permission) {
387
+                switch (strtolower($permission)) {
388
+                    case 'read':
389
+                        $ncPermissions += Constants::PERMISSION_READ;
390
+                        break;
391
+                    case 'write':
392
+                        $ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
393
+                        break;
394
+                    case 'share':
395
+                        $ncPermissions += Constants::PERMISSION_SHARE;
396
+                        break;
397
+                    default:
398
+                        throw new \Exception();
399
+                }
400
+            }
401
+        } catch (\Exception $e) {
402
+            $ncPermissions = $this->getDefaultPermissions($path);
403
+        }
404
+
405
+        return $ncPermissions;
406
+    }
407
+
408
+    /**
409
+     * calculate default permissions in case no permissions are provided
410
+     *
411
+     * @param $path
412
+     * @return int
413
+     */
414
+    protected function getDefaultPermissions($path) {
415
+        if ($this->is_dir($path)) {
416
+            $permissions = Constants::PERMISSION_ALL;
417
+        } else {
418
+            $permissions = Constants::PERMISSION_ALL & ~Constants::PERMISSION_CREATE;
419
+        }
420
+
421
+        return $permissions;
422
+    }
423 423
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/SharedStorage.php 1 patch
Indentation   +455 added lines, -455 removed lines patch added patch discarded remove patch
@@ -49,459 +49,459 @@
 block discarded – undo
49 49
  */
50 50
 class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage, IDisableEncryptionStorage {
51 51
 
52
-	/** @var \OCP\Share\IShare */
53
-	private $superShare;
54
-
55
-	/** @var \OCP\Share\IShare[] */
56
-	private $groupedShares;
57
-
58
-	/**
59
-	 * @var \OC\Files\View
60
-	 */
61
-	private $ownerView;
62
-
63
-	private $initialized = false;
64
-
65
-	/**
66
-	 * @var ICacheEntry
67
-	 */
68
-	private $sourceRootInfo;
69
-
70
-	/** @var string */
71
-	private $user;
72
-
73
-	/**
74
-	 * @var \OCP\ILogger
75
-	 */
76
-	private $logger;
77
-
78
-	/** @var  IStorage */
79
-	private $nonMaskedStorage;
80
-
81
-	private $options;
82
-
83
-	/** @var boolean */
84
-	private $sharingDisabledForUser;
85
-
86
-	public function __construct($arguments) {
87
-		$this->ownerView = $arguments['ownerView'];
88
-		$this->logger = \OC::$server->getLogger();
89
-
90
-		$this->superShare = $arguments['superShare'];
91
-		$this->groupedShares = $arguments['groupedShares'];
92
-
93
-		$this->user = $arguments['user'];
94
-		if (isset($arguments['sharingDisabledForUser'])) {
95
-			$this->sharingDisabledForUser = $arguments['sharingDisabledForUser'];
96
-		} else {
97
-			$this->sharingDisabledForUser = false;
98
-		}
99
-
100
-		parent::__construct([
101
-			'storage' => null,
102
-			'root' => null,
103
-		]);
104
-	}
105
-
106
-	/**
107
-	 * @return ICacheEntry
108
-	 */
109
-	private function getSourceRootInfo() {
110
-		if (is_null($this->sourceRootInfo)) {
111
-			if (is_null($this->superShare->getNodeCacheEntry())) {
112
-				$this->init();
113
-				$this->sourceRootInfo = $this->nonMaskedStorage->getCache()->get($this->rootPath);
114
-			} else {
115
-				$this->sourceRootInfo = $this->superShare->getNodeCacheEntry();
116
-			}
117
-		}
118
-		return $this->sourceRootInfo;
119
-	}
120
-
121
-	private function init() {
122
-		if ($this->initialized) {
123
-			return;
124
-		}
125
-		$this->initialized = true;
126
-		try {
127
-			Filesystem::initMountPoints($this->superShare->getShareOwner());
128
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
129
-			list($this->nonMaskedStorage, $this->rootPath) = $this->ownerView->resolvePath($sourcePath);
130
-			$this->storage = new PermissionsMask([
131
-				'storage' => $this->nonMaskedStorage,
132
-				'mask' => $this->superShare->getPermissions()
133
-			]);
134
-		} catch (NotFoundException $e) {
135
-			// original file not accessible or deleted, set FailedStorage
136
-			$this->storage = new FailedStorage(['exception' => $e]);
137
-			$this->cache = new FailedCache();
138
-			$this->rootPath = '';
139
-		} catch (NoUserException $e) {
140
-			// sharer user deleted, set FailedStorage
141
-			$this->storage = new FailedStorage(['exception' => $e]);
142
-			$this->cache = new FailedCache();
143
-			$this->rootPath = '';
144
-		} catch (\Exception $e) {
145
-			$this->storage = new FailedStorage(['exception' => $e]);
146
-			$this->cache = new FailedCache();
147
-			$this->rootPath = '';
148
-			$this->logger->logException($e);
149
-		}
150
-
151
-		if (!$this->nonMaskedStorage) {
152
-			$this->nonMaskedStorage = $this->storage;
153
-		}
154
-	}
155
-
156
-	/**
157
-	 * @inheritdoc
158
-	 */
159
-	public function instanceOfStorage($class) {
160
-		if ($class === '\OC\Files\Storage\Common') {
161
-			return true;
162
-		}
163
-		if (in_array($class, ['\OC\Files\Storage\Home', '\OC\Files\ObjectStore\HomeObjectStoreStorage'])) {
164
-			return false;
165
-		}
166
-		return parent::instanceOfStorage($class);
167
-	}
168
-
169
-	/**
170
-	 * @return string
171
-	 */
172
-	public function getShareId() {
173
-		return $this->superShare->getId();
174
-	}
175
-
176
-	private function isValid() {
177
-		return $this->getSourceRootInfo() && ($this->getSourceRootInfo()->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
178
-	}
179
-
180
-	/**
181
-	 * get id of the mount point
182
-	 *
183
-	 * @return string
184
-	 */
185
-	public function getId() {
186
-		return 'shared::' . $this->getMountPoint();
187
-	}
188
-
189
-	/**
190
-	 * Get the permissions granted for a shared file
191
-	 *
192
-	 * @param string $target Shared target file path
193
-	 * @return int CRUDS permissions granted
194
-	 */
195
-	public function getPermissions($target = '') {
196
-		if (!$this->isValid()) {
197
-			return 0;
198
-		}
199
-		$permissions = parent::getPermissions($target) & $this->superShare->getPermissions();
200
-
201
-		// part files and the mount point always have delete permissions
202
-		if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
203
-			$permissions |= \OCP\Constants::PERMISSION_DELETE;
204
-		}
205
-
206
-		if ($this->sharingDisabledForUser) {
207
-			$permissions &= ~\OCP\Constants::PERMISSION_SHARE;
208
-		}
209
-
210
-		return $permissions;
211
-	}
212
-
213
-	public function isCreatable($path) {
214
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_CREATE);
215
-	}
216
-
217
-	public function isReadable($path) {
218
-		if (!$this->isValid()) {
219
-			return false;
220
-		}
221
-		if (!$this->file_exists($path)) {
222
-			return false;
223
-		}
224
-		/** @var IStorage $storage */
225
-		/** @var string $internalPath */
226
-		list($storage, $internalPath) = $this->resolvePath($path);
227
-		return $storage->isReadable($internalPath);
228
-	}
229
-
230
-	public function isUpdatable($path) {
231
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_UPDATE);
232
-	}
233
-
234
-	public function isDeletable($path) {
235
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_DELETE);
236
-	}
237
-
238
-	public function isSharable($path) {
239
-		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
240
-			return false;
241
-		}
242
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
243
-	}
244
-
245
-	public function fopen($path, $mode) {
246
-		if ($source = $this->getUnjailedPath($path)) {
247
-			switch ($mode) {
248
-				case 'r+':
249
-				case 'rb+':
250
-				case 'w+':
251
-				case 'wb+':
252
-				case 'x+':
253
-				case 'xb+':
254
-				case 'a+':
255
-				case 'ab+':
256
-				case 'w':
257
-				case 'wb':
258
-				case 'x':
259
-				case 'xb':
260
-				case 'a':
261
-				case 'ab':
262
-					$creatable = $this->isCreatable(dirname($path));
263
-					$updatable = $this->isUpdatable($path);
264
-					// if neither permissions given, no need to continue
265
-					if (!$creatable && !$updatable) {
266
-						if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
267
-							$updatable = $this->isUpdatable(dirname($path));
268
-						}
269
-
270
-						if (!$updatable) {
271
-							return false;
272
-						}
273
-					}
274
-
275
-					$exists = $this->file_exists($path);
276
-					// if a file exists, updatable permissions are required
277
-					if ($exists && !$updatable) {
278
-						return false;
279
-					}
280
-
281
-					// part file is allowed if !$creatable but the final file is $updatable
282
-					if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
283
-						if (!$exists && !$creatable) {
284
-							return false;
285
-						}
286
-					}
287
-			}
288
-			$info = array(
289
-				'target' => $this->getMountPoint() . $path,
290
-				'source' => $source,
291
-				'mode' => $mode,
292
-			);
293
-			\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
294
-			return $this->nonMaskedStorage->fopen($this->getUnjailedPath($path), $mode);
295
-		}
296
-		return false;
297
-	}
298
-
299
-	/**
300
-	 * see http://php.net/manual/en/function.rename.php
301
-	 *
302
-	 * @param string $path1
303
-	 * @param string $path2
304
-	 * @return bool
305
-	 */
306
-	public function rename($path1, $path2) {
307
-		$this->init();
308
-		$isPartFile = pathinfo($path1, PATHINFO_EXTENSION) === 'part';
309
-		$targetExists = $this->file_exists($path2);
310
-		$sameFodler = dirname($path1) === dirname($path2);
311
-
312
-		if ($targetExists || ($sameFodler && !$isPartFile)) {
313
-			if (!$this->isUpdatable('')) {
314
-				return false;
315
-			}
316
-		} else {
317
-			if (!$this->isCreatable('')) {
318
-				return false;
319
-			}
320
-		}
321
-
322
-		return $this->nonMaskedStorage->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
323
-	}
324
-
325
-	/**
326
-	 * return mount point of share, relative to data/user/files
327
-	 *
328
-	 * @return string
329
-	 */
330
-	public function getMountPoint() {
331
-		return $this->superShare->getTarget();
332
-	}
333
-
334
-	/**
335
-	 * @param string $path
336
-	 */
337
-	public function setMountPoint($path) {
338
-		$this->superShare->setTarget($path);
339
-
340
-		foreach ($this->groupedShares as $share) {
341
-			$share->setTarget($path);
342
-		}
343
-	}
344
-
345
-	/**
346
-	 * get the user who shared the file
347
-	 *
348
-	 * @return string
349
-	 */
350
-	public function getSharedFrom() {
351
-		return $this->superShare->getShareOwner();
352
-	}
353
-
354
-	/**
355
-	 * @return \OCP\Share\IShare
356
-	 */
357
-	public function getShare() {
358
-		return $this->superShare;
359
-	}
360
-
361
-	/**
362
-	 * return share type, can be "file" or "folder"
363
-	 *
364
-	 * @return string
365
-	 */
366
-	public function getItemType() {
367
-		return $this->superShare->getNodeType();
368
-	}
369
-
370
-	/**
371
-	 * @param string $path
372
-	 * @param null $storage
373
-	 * @return Cache
374
-	 */
375
-	public function getCache($path = '', $storage = null) {
376
-		if ($this->cache) {
377
-			return $this->cache;
378
-		}
379
-		if (!$storage) {
380
-			$storage = $this;
381
-		}
382
-		$sourceRoot  = $this->getSourceRootInfo();
383
-		if ($this->storage instanceof FailedStorage) {
384
-			return new FailedCache();
385
-		}
386
-
387
-		$this->cache = new \OCA\Files_Sharing\Cache($storage, $sourceRoot, $this->superShare);
388
-		return $this->cache;
389
-	}
390
-
391
-	public function getScanner($path = '', $storage = null) {
392
-		if (!$storage) {
393
-			$storage = $this;
394
-		}
395
-		return new \OCA\Files_Sharing\Scanner($storage);
396
-	}
397
-
398
-	public function getOwner($path) {
399
-		return $this->superShare->getShareOwner();
400
-	}
401
-
402
-	/**
403
-	 * unshare complete storage, also the grouped shares
404
-	 *
405
-	 * @return bool
406
-	 */
407
-	public function unshareStorage() {
408
-		foreach ($this->groupedShares as $share) {
409
-			\OC::$server->getShareManager()->deleteFromSelf($share, $this->user);
410
-		}
411
-		return true;
412
-	}
413
-
414
-	/**
415
-	 * @param string $path
416
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
417
-	 * @param \OCP\Lock\ILockingProvider $provider
418
-	 * @throws \OCP\Lock\LockedException
419
-	 */
420
-	public function acquireLock($path, $type, ILockingProvider $provider) {
421
-		/** @var \OCP\Files\Storage $targetStorage */
422
-		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
423
-		$targetStorage->acquireLock($targetInternalPath, $type, $provider);
424
-		// lock the parent folders of the owner when locking the share as recipient
425
-		if ($path === '') {
426
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
427
-			$this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
428
-		}
429
-	}
430
-
431
-	/**
432
-	 * @param string $path
433
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
434
-	 * @param \OCP\Lock\ILockingProvider $provider
435
-	 */
436
-	public function releaseLock($path, $type, ILockingProvider $provider) {
437
-		/** @var \OCP\Files\Storage $targetStorage */
438
-		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
439
-		$targetStorage->releaseLock($targetInternalPath, $type, $provider);
440
-		// unlock the parent folders of the owner when unlocking the share as recipient
441
-		if ($path === '') {
442
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
443
-			$this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
444
-		}
445
-	}
446
-
447
-	/**
448
-	 * @param string $path
449
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
450
-	 * @param \OCP\Lock\ILockingProvider $provider
451
-	 */
452
-	public function changeLock($path, $type, ILockingProvider $provider) {
453
-		/** @var \OCP\Files\Storage $targetStorage */
454
-		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
455
-		$targetStorage->changeLock($targetInternalPath, $type, $provider);
456
-	}
457
-
458
-	/**
459
-	 * @return array [ available, last_checked ]
460
-	 */
461
-	public function getAvailability() {
462
-		// shares do not participate in availability logic
463
-		return [
464
-			'available' => true,
465
-			'last_checked' => 0
466
-		];
467
-	}
468
-
469
-	/**
470
-	 * @param bool $available
471
-	 */
472
-	public function setAvailability($available) {
473
-		// shares do not participate in availability logic
474
-	}
475
-
476
-	public function getSourceStorage() {
477
-		$this->init();
478
-		return $this->nonMaskedStorage;
479
-	}
480
-
481
-	public function getWrapperStorage() {
482
-		$this->init();
483
-		return $this->storage;
484
-	}
485
-
486
-	public function file_get_contents($path) {
487
-		$info = [
488
-			'target' => $this->getMountPoint() . '/' . $path,
489
-			'source' => $this->getUnjailedPath($path),
490
-		];
491
-		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
492
-		return parent::file_get_contents($path);
493
-	}
494
-
495
-	public function file_put_contents($path, $data) {
496
-		$info = [
497
-			'target' => $this->getMountPoint() . '/' . $path,
498
-			'source' => $this->getUnjailedPath($path),
499
-		];
500
-		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
501
-		return parent::file_put_contents($path, $data);
502
-	}
503
-
504
-	public function setMountOptions(array $options) {
505
-		$this->mountOptions = $options;
506
-	}
52
+    /** @var \OCP\Share\IShare */
53
+    private $superShare;
54
+
55
+    /** @var \OCP\Share\IShare[] */
56
+    private $groupedShares;
57
+
58
+    /**
59
+     * @var \OC\Files\View
60
+     */
61
+    private $ownerView;
62
+
63
+    private $initialized = false;
64
+
65
+    /**
66
+     * @var ICacheEntry
67
+     */
68
+    private $sourceRootInfo;
69
+
70
+    /** @var string */
71
+    private $user;
72
+
73
+    /**
74
+     * @var \OCP\ILogger
75
+     */
76
+    private $logger;
77
+
78
+    /** @var  IStorage */
79
+    private $nonMaskedStorage;
80
+
81
+    private $options;
82
+
83
+    /** @var boolean */
84
+    private $sharingDisabledForUser;
85
+
86
+    public function __construct($arguments) {
87
+        $this->ownerView = $arguments['ownerView'];
88
+        $this->logger = \OC::$server->getLogger();
89
+
90
+        $this->superShare = $arguments['superShare'];
91
+        $this->groupedShares = $arguments['groupedShares'];
92
+
93
+        $this->user = $arguments['user'];
94
+        if (isset($arguments['sharingDisabledForUser'])) {
95
+            $this->sharingDisabledForUser = $arguments['sharingDisabledForUser'];
96
+        } else {
97
+            $this->sharingDisabledForUser = false;
98
+        }
99
+
100
+        parent::__construct([
101
+            'storage' => null,
102
+            'root' => null,
103
+        ]);
104
+    }
105
+
106
+    /**
107
+     * @return ICacheEntry
108
+     */
109
+    private function getSourceRootInfo() {
110
+        if (is_null($this->sourceRootInfo)) {
111
+            if (is_null($this->superShare->getNodeCacheEntry())) {
112
+                $this->init();
113
+                $this->sourceRootInfo = $this->nonMaskedStorage->getCache()->get($this->rootPath);
114
+            } else {
115
+                $this->sourceRootInfo = $this->superShare->getNodeCacheEntry();
116
+            }
117
+        }
118
+        return $this->sourceRootInfo;
119
+    }
120
+
121
+    private function init() {
122
+        if ($this->initialized) {
123
+            return;
124
+        }
125
+        $this->initialized = true;
126
+        try {
127
+            Filesystem::initMountPoints($this->superShare->getShareOwner());
128
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
129
+            list($this->nonMaskedStorage, $this->rootPath) = $this->ownerView->resolvePath($sourcePath);
130
+            $this->storage = new PermissionsMask([
131
+                'storage' => $this->nonMaskedStorage,
132
+                'mask' => $this->superShare->getPermissions()
133
+            ]);
134
+        } catch (NotFoundException $e) {
135
+            // original file not accessible or deleted, set FailedStorage
136
+            $this->storage = new FailedStorage(['exception' => $e]);
137
+            $this->cache = new FailedCache();
138
+            $this->rootPath = '';
139
+        } catch (NoUserException $e) {
140
+            // sharer user deleted, set FailedStorage
141
+            $this->storage = new FailedStorage(['exception' => $e]);
142
+            $this->cache = new FailedCache();
143
+            $this->rootPath = '';
144
+        } catch (\Exception $e) {
145
+            $this->storage = new FailedStorage(['exception' => $e]);
146
+            $this->cache = new FailedCache();
147
+            $this->rootPath = '';
148
+            $this->logger->logException($e);
149
+        }
150
+
151
+        if (!$this->nonMaskedStorage) {
152
+            $this->nonMaskedStorage = $this->storage;
153
+        }
154
+    }
155
+
156
+    /**
157
+     * @inheritdoc
158
+     */
159
+    public function instanceOfStorage($class) {
160
+        if ($class === '\OC\Files\Storage\Common') {
161
+            return true;
162
+        }
163
+        if (in_array($class, ['\OC\Files\Storage\Home', '\OC\Files\ObjectStore\HomeObjectStoreStorage'])) {
164
+            return false;
165
+        }
166
+        return parent::instanceOfStorage($class);
167
+    }
168
+
169
+    /**
170
+     * @return string
171
+     */
172
+    public function getShareId() {
173
+        return $this->superShare->getId();
174
+    }
175
+
176
+    private function isValid() {
177
+        return $this->getSourceRootInfo() && ($this->getSourceRootInfo()->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
178
+    }
179
+
180
+    /**
181
+     * get id of the mount point
182
+     *
183
+     * @return string
184
+     */
185
+    public function getId() {
186
+        return 'shared::' . $this->getMountPoint();
187
+    }
188
+
189
+    /**
190
+     * Get the permissions granted for a shared file
191
+     *
192
+     * @param string $target Shared target file path
193
+     * @return int CRUDS permissions granted
194
+     */
195
+    public function getPermissions($target = '') {
196
+        if (!$this->isValid()) {
197
+            return 0;
198
+        }
199
+        $permissions = parent::getPermissions($target) & $this->superShare->getPermissions();
200
+
201
+        // part files and the mount point always have delete permissions
202
+        if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
203
+            $permissions |= \OCP\Constants::PERMISSION_DELETE;
204
+        }
205
+
206
+        if ($this->sharingDisabledForUser) {
207
+            $permissions &= ~\OCP\Constants::PERMISSION_SHARE;
208
+        }
209
+
210
+        return $permissions;
211
+    }
212
+
213
+    public function isCreatable($path) {
214
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_CREATE);
215
+    }
216
+
217
+    public function isReadable($path) {
218
+        if (!$this->isValid()) {
219
+            return false;
220
+        }
221
+        if (!$this->file_exists($path)) {
222
+            return false;
223
+        }
224
+        /** @var IStorage $storage */
225
+        /** @var string $internalPath */
226
+        list($storage, $internalPath) = $this->resolvePath($path);
227
+        return $storage->isReadable($internalPath);
228
+    }
229
+
230
+    public function isUpdatable($path) {
231
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_UPDATE);
232
+    }
233
+
234
+    public function isDeletable($path) {
235
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_DELETE);
236
+    }
237
+
238
+    public function isSharable($path) {
239
+        if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
240
+            return false;
241
+        }
242
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
243
+    }
244
+
245
+    public function fopen($path, $mode) {
246
+        if ($source = $this->getUnjailedPath($path)) {
247
+            switch ($mode) {
248
+                case 'r+':
249
+                case 'rb+':
250
+                case 'w+':
251
+                case 'wb+':
252
+                case 'x+':
253
+                case 'xb+':
254
+                case 'a+':
255
+                case 'ab+':
256
+                case 'w':
257
+                case 'wb':
258
+                case 'x':
259
+                case 'xb':
260
+                case 'a':
261
+                case 'ab':
262
+                    $creatable = $this->isCreatable(dirname($path));
263
+                    $updatable = $this->isUpdatable($path);
264
+                    // if neither permissions given, no need to continue
265
+                    if (!$creatable && !$updatable) {
266
+                        if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
267
+                            $updatable = $this->isUpdatable(dirname($path));
268
+                        }
269
+
270
+                        if (!$updatable) {
271
+                            return false;
272
+                        }
273
+                    }
274
+
275
+                    $exists = $this->file_exists($path);
276
+                    // if a file exists, updatable permissions are required
277
+                    if ($exists && !$updatable) {
278
+                        return false;
279
+                    }
280
+
281
+                    // part file is allowed if !$creatable but the final file is $updatable
282
+                    if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
283
+                        if (!$exists && !$creatable) {
284
+                            return false;
285
+                        }
286
+                    }
287
+            }
288
+            $info = array(
289
+                'target' => $this->getMountPoint() . $path,
290
+                'source' => $source,
291
+                'mode' => $mode,
292
+            );
293
+            \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
294
+            return $this->nonMaskedStorage->fopen($this->getUnjailedPath($path), $mode);
295
+        }
296
+        return false;
297
+    }
298
+
299
+    /**
300
+     * see http://php.net/manual/en/function.rename.php
301
+     *
302
+     * @param string $path1
303
+     * @param string $path2
304
+     * @return bool
305
+     */
306
+    public function rename($path1, $path2) {
307
+        $this->init();
308
+        $isPartFile = pathinfo($path1, PATHINFO_EXTENSION) === 'part';
309
+        $targetExists = $this->file_exists($path2);
310
+        $sameFodler = dirname($path1) === dirname($path2);
311
+
312
+        if ($targetExists || ($sameFodler && !$isPartFile)) {
313
+            if (!$this->isUpdatable('')) {
314
+                return false;
315
+            }
316
+        } else {
317
+            if (!$this->isCreatable('')) {
318
+                return false;
319
+            }
320
+        }
321
+
322
+        return $this->nonMaskedStorage->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
323
+    }
324
+
325
+    /**
326
+     * return mount point of share, relative to data/user/files
327
+     *
328
+     * @return string
329
+     */
330
+    public function getMountPoint() {
331
+        return $this->superShare->getTarget();
332
+    }
333
+
334
+    /**
335
+     * @param string $path
336
+     */
337
+    public function setMountPoint($path) {
338
+        $this->superShare->setTarget($path);
339
+
340
+        foreach ($this->groupedShares as $share) {
341
+            $share->setTarget($path);
342
+        }
343
+    }
344
+
345
+    /**
346
+     * get the user who shared the file
347
+     *
348
+     * @return string
349
+     */
350
+    public function getSharedFrom() {
351
+        return $this->superShare->getShareOwner();
352
+    }
353
+
354
+    /**
355
+     * @return \OCP\Share\IShare
356
+     */
357
+    public function getShare() {
358
+        return $this->superShare;
359
+    }
360
+
361
+    /**
362
+     * return share type, can be "file" or "folder"
363
+     *
364
+     * @return string
365
+     */
366
+    public function getItemType() {
367
+        return $this->superShare->getNodeType();
368
+    }
369
+
370
+    /**
371
+     * @param string $path
372
+     * @param null $storage
373
+     * @return Cache
374
+     */
375
+    public function getCache($path = '', $storage = null) {
376
+        if ($this->cache) {
377
+            return $this->cache;
378
+        }
379
+        if (!$storage) {
380
+            $storage = $this;
381
+        }
382
+        $sourceRoot  = $this->getSourceRootInfo();
383
+        if ($this->storage instanceof FailedStorage) {
384
+            return new FailedCache();
385
+        }
386
+
387
+        $this->cache = new \OCA\Files_Sharing\Cache($storage, $sourceRoot, $this->superShare);
388
+        return $this->cache;
389
+    }
390
+
391
+    public function getScanner($path = '', $storage = null) {
392
+        if (!$storage) {
393
+            $storage = $this;
394
+        }
395
+        return new \OCA\Files_Sharing\Scanner($storage);
396
+    }
397
+
398
+    public function getOwner($path) {
399
+        return $this->superShare->getShareOwner();
400
+    }
401
+
402
+    /**
403
+     * unshare complete storage, also the grouped shares
404
+     *
405
+     * @return bool
406
+     */
407
+    public function unshareStorage() {
408
+        foreach ($this->groupedShares as $share) {
409
+            \OC::$server->getShareManager()->deleteFromSelf($share, $this->user);
410
+        }
411
+        return true;
412
+    }
413
+
414
+    /**
415
+     * @param string $path
416
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
417
+     * @param \OCP\Lock\ILockingProvider $provider
418
+     * @throws \OCP\Lock\LockedException
419
+     */
420
+    public function acquireLock($path, $type, ILockingProvider $provider) {
421
+        /** @var \OCP\Files\Storage $targetStorage */
422
+        list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
423
+        $targetStorage->acquireLock($targetInternalPath, $type, $provider);
424
+        // lock the parent folders of the owner when locking the share as recipient
425
+        if ($path === '') {
426
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
427
+            $this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
428
+        }
429
+    }
430
+
431
+    /**
432
+     * @param string $path
433
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
434
+     * @param \OCP\Lock\ILockingProvider $provider
435
+     */
436
+    public function releaseLock($path, $type, ILockingProvider $provider) {
437
+        /** @var \OCP\Files\Storage $targetStorage */
438
+        list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
439
+        $targetStorage->releaseLock($targetInternalPath, $type, $provider);
440
+        // unlock the parent folders of the owner when unlocking the share as recipient
441
+        if ($path === '') {
442
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
443
+            $this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
444
+        }
445
+    }
446
+
447
+    /**
448
+     * @param string $path
449
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
450
+     * @param \OCP\Lock\ILockingProvider $provider
451
+     */
452
+    public function changeLock($path, $type, ILockingProvider $provider) {
453
+        /** @var \OCP\Files\Storage $targetStorage */
454
+        list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
455
+        $targetStorage->changeLock($targetInternalPath, $type, $provider);
456
+    }
457
+
458
+    /**
459
+     * @return array [ available, last_checked ]
460
+     */
461
+    public function getAvailability() {
462
+        // shares do not participate in availability logic
463
+        return [
464
+            'available' => true,
465
+            'last_checked' => 0
466
+        ];
467
+    }
468
+
469
+    /**
470
+     * @param bool $available
471
+     */
472
+    public function setAvailability($available) {
473
+        // shares do not participate in availability logic
474
+    }
475
+
476
+    public function getSourceStorage() {
477
+        $this->init();
478
+        return $this->nonMaskedStorage;
479
+    }
480
+
481
+    public function getWrapperStorage() {
482
+        $this->init();
483
+        return $this->storage;
484
+    }
485
+
486
+    public function file_get_contents($path) {
487
+        $info = [
488
+            'target' => $this->getMountPoint() . '/' . $path,
489
+            'source' => $this->getUnjailedPath($path),
490
+        ];
491
+        \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
492
+        return parent::file_get_contents($path);
493
+    }
494
+
495
+    public function file_put_contents($path, $data) {
496
+        $info = [
497
+            'target' => $this->getMountPoint() . '/' . $path,
498
+            'source' => $this->getUnjailedPath($path),
499
+        ];
500
+        \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
501
+        return parent::file_put_contents($path, $data);
502
+    }
503
+
504
+    public function setMountOptions(array $options) {
505
+        $this->mountOptions = $options;
506
+    }
507 507
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Storage/OwnCloud.php 2 patches
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -36,46 +36,46 @@
 block discarded – undo
36 36
  *
37 37
  */
38 38
 class OwnCloud extends \OC\Files\Storage\DAV implements IDisableEncryptionStorage {
39
-	const OC_URL_SUFFIX = 'remote.php/webdav';
39
+    const OC_URL_SUFFIX = 'remote.php/webdav';
40 40
 
41
-	public function __construct($params) {
42
-		// extract context path from host if specified
43
-		// (owncloud install path on host)
44
-		$host = $params['host'];
45
-		// strip protocol
46
-		if (substr($host, 0, 8) === "https://") {
47
-			$host = substr($host, 8);
48
-			$params['secure'] = true;
49
-		} else if (substr($host, 0, 7) === "http://") {
50
-			$host = substr($host, 7);
51
-			$params['secure'] = false;
52
-		}
53
-		$contextPath = '';
54
-		$hostSlashPos = strpos($host, '/');
55
-		if ($hostSlashPos !== false){
56
-			$contextPath = substr($host, $hostSlashPos);
57
-			$host = substr($host, 0, $hostSlashPos);
58
-		}
41
+    public function __construct($params) {
42
+        // extract context path from host if specified
43
+        // (owncloud install path on host)
44
+        $host = $params['host'];
45
+        // strip protocol
46
+        if (substr($host, 0, 8) === "https://") {
47
+            $host = substr($host, 8);
48
+            $params['secure'] = true;
49
+        } else if (substr($host, 0, 7) === "http://") {
50
+            $host = substr($host, 7);
51
+            $params['secure'] = false;
52
+        }
53
+        $contextPath = '';
54
+        $hostSlashPos = strpos($host, '/');
55
+        if ($hostSlashPos !== false){
56
+            $contextPath = substr($host, $hostSlashPos);
57
+            $host = substr($host, 0, $hostSlashPos);
58
+        }
59 59
 
60
-		if (substr($contextPath, -1) !== '/'){
61
-			$contextPath .= '/';
62
-		}
60
+        if (substr($contextPath, -1) !== '/'){
61
+            $contextPath .= '/';
62
+        }
63 63
 
64
-		if (isset($params['root'])){
65
-			$root = '/' . ltrim($params['root'], '/');
66
-		}
67
-		else{
68
-			$root = '/';
69
-		}
64
+        if (isset($params['root'])){
65
+            $root = '/' . ltrim($params['root'], '/');
66
+        }
67
+        else{
68
+            $root = '/';
69
+        }
70 70
 
71
-		$params['host'] = $host;
72
-		$params['root'] = $contextPath . self::OC_URL_SUFFIX . $root;
73
-		$params['authType'] = Client::AUTH_BASIC;
71
+        $params['host'] = $host;
72
+        $params['root'] = $contextPath . self::OC_URL_SUFFIX . $root;
73
+        $params['authType'] = Client::AUTH_BASIC;
74 74
 
75
-		parent::__construct($params);
76
-	}
75
+        parent::__construct($params);
76
+    }
77 77
 
78
-	public function needsPartFile() {
79
-		return false;
80
-	}
78
+    public function needsPartFile() {
79
+        return false;
80
+    }
81 81
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -52,24 +52,24 @@
 block discarded – undo
52 52
 		}
53 53
 		$contextPath = '';
54 54
 		$hostSlashPos = strpos($host, '/');
55
-		if ($hostSlashPos !== false){
55
+		if ($hostSlashPos !== false) {
56 56
 			$contextPath = substr($host, $hostSlashPos);
57 57
 			$host = substr($host, 0, $hostSlashPos);
58 58
 		}
59 59
 
60
-		if (substr($contextPath, -1) !== '/'){
60
+		if (substr($contextPath, -1) !== '/') {
61 61
 			$contextPath .= '/';
62 62
 		}
63 63
 
64
-		if (isset($params['root'])){
65
-			$root = '/' . ltrim($params['root'], '/');
64
+		if (isset($params['root'])) {
65
+			$root = '/'.ltrim($params['root'], '/');
66 66
 		}
67
-		else{
67
+		else {
68 68
 			$root = '/';
69 69
 		}
70 70
 
71 71
 		$params['host'] = $host;
72
-		$params['root'] = $contextPath . self::OC_URL_SUFFIX . $root;
72
+		$params['root'] = $contextPath.self::OC_URL_SUFFIX.$root;
73 73
 		$params['authType'] = Client::AUTH_BASIC;
74 74
 
75 75
 		parent::__construct($params);
Please login to merge, or discard this patch.