Passed
Push — master ( ae665e...1a0403 )
by Roeland
13:46 queued 53s
created
lib/private/Files/ObjectStore/SwiftFactory.php 2 patches
Indentation   +208 added lines, -208 removed lines patch added patch discarded remove patch
@@ -52,235 +52,235 @@
 block discarded – undo
52 52
 use Psr\Http\Message\RequestInterface;
53 53
 
54 54
 class SwiftFactory {
55
-	private $cache;
56
-	private $params;
57
-	/** @var Container|null */
58
-	private $container = null;
59
-	private $logger;
55
+    private $cache;
56
+    private $params;
57
+    /** @var Container|null */
58
+    private $container = null;
59
+    private $logger;
60 60
 
61
-	public const DEFAULT_OPTIONS = [
62
-		'autocreate' => false,
63
-		'urlType' => 'publicURL',
64
-		'catalogName' => 'swift',
65
-		'catalogType' => 'object-store'
66
-	];
61
+    public const DEFAULT_OPTIONS = [
62
+        'autocreate' => false,
63
+        'urlType' => 'publicURL',
64
+        'catalogName' => 'swift',
65
+        'catalogType' => 'object-store'
66
+    ];
67 67
 
68
-	public function __construct(ICache $cache, array $params, ILogger $logger) {
69
-		$this->cache = $cache;
70
-		$this->params = $params;
71
-		$this->logger = $logger;
72
-	}
68
+    public function __construct(ICache $cache, array $params, ILogger $logger) {
69
+        $this->cache = $cache;
70
+        $this->params = $params;
71
+        $this->logger = $logger;
72
+    }
73 73
 
74
-	/**
75
-	 * Gets currently cached token id
76
-	 *
77
-	 * @return string
78
-	 * @throws StorageAuthException
79
-	 */
80
-	public function getCachedTokenId() {
81
-		if (!isset($this->params['cachedToken'])) {
82
-			throw new StorageAuthException('Unauthenticated ObjectStore connection');
83
-		}
74
+    /**
75
+     * Gets currently cached token id
76
+     *
77
+     * @return string
78
+     * @throws StorageAuthException
79
+     */
80
+    public function getCachedTokenId() {
81
+        if (!isset($this->params['cachedToken'])) {
82
+            throw new StorageAuthException('Unauthenticated ObjectStore connection');
83
+        }
84 84
 
85
-		// Is it V2 token?
86
-		if (isset($this->params['cachedToken']['token'])) {
87
-			return $this->params['cachedToken']['token']['id'];
88
-		}
85
+        // Is it V2 token?
86
+        if (isset($this->params['cachedToken']['token'])) {
87
+            return $this->params['cachedToken']['token']['id'];
88
+        }
89 89
 
90
-		return $this->params['cachedToken']['id'];
91
-	}
90
+        return $this->params['cachedToken']['id'];
91
+    }
92 92
 
93
-	private function getCachedToken(string $cacheKey) {
94
-		$cachedTokenString = $this->cache->get($cacheKey . '/token');
95
-		if ($cachedTokenString) {
96
-			return json_decode($cachedTokenString, true);
97
-		} else {
98
-			return null;
99
-		}
100
-	}
93
+    private function getCachedToken(string $cacheKey) {
94
+        $cachedTokenString = $this->cache->get($cacheKey . '/token');
95
+        if ($cachedTokenString) {
96
+            return json_decode($cachedTokenString, true);
97
+        } else {
98
+            return null;
99
+        }
100
+    }
101 101
 
102
-	private function cacheToken(Token $token, string $serviceUrl, string $cacheKey) {
103
-		if ($token instanceof \OpenStack\Identity\v3\Models\Token) {
104
-			// for v3 the catalog is cached as part of the token, so no need to cache $serviceUrl separately
105
-			$value = $token->export();
106
-		} else {
107
-			/** @var \OpenStack\Identity\v2\Models\Token $token */
108
-			$value = [
109
-				'serviceUrl' => $serviceUrl,
110
-				'token' => [
111
-					'issued_at' => $token->issuedAt->format('c'),
112
-					'expires' => $token->expires->format('c'),
113
-					'id' => $token->id,
114
-					'tenant' => $token->tenant
115
-				]
116
-			];
117
-		}
102
+    private function cacheToken(Token $token, string $serviceUrl, string $cacheKey) {
103
+        if ($token instanceof \OpenStack\Identity\v3\Models\Token) {
104
+            // for v3 the catalog is cached as part of the token, so no need to cache $serviceUrl separately
105
+            $value = $token->export();
106
+        } else {
107
+            /** @var \OpenStack\Identity\v2\Models\Token $token */
108
+            $value = [
109
+                'serviceUrl' => $serviceUrl,
110
+                'token' => [
111
+                    'issued_at' => $token->issuedAt->format('c'),
112
+                    'expires' => $token->expires->format('c'),
113
+                    'id' => $token->id,
114
+                    'tenant' => $token->tenant
115
+                ]
116
+            ];
117
+        }
118 118
 
119
-		$this->params['cachedToken'] = $value;
120
-		$this->cache->set($cacheKey . '/token', json_encode($value));
121
-	}
119
+        $this->params['cachedToken'] = $value;
120
+        $this->cache->set($cacheKey . '/token', json_encode($value));
121
+    }
122 122
 
123
-	/**
124
-	 * @return OpenStack
125
-	 * @throws StorageAuthException
126
-	 */
127
-	private function getClient() {
128
-		if (isset($this->params['bucket'])) {
129
-			$this->params['container'] = $this->params['bucket'];
130
-		}
131
-		if (!isset($this->params['container'])) {
132
-			$this->params['container'] = 'nextcloud';
133
-		}
134
-		if (isset($this->params['user']) && is_array($this->params['user'])) {
135
-			$userName = $this->params['user']['name'];
136
-		} else {
137
-			if (!isset($this->params['username']) && isset($this->params['user'])) {
138
-				$this->params['username'] = $this->params['user'];
139
-			}
140
-			$userName = $this->params['username'];
141
-		}
142
-		if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) {
143
-			$this->params['tenantName'] = $this->params['tenant'];
144
-		}
145
-		if (isset($this->params['domain'])) {
146
-			$this->params['scope']['project']['name'] = $this->params['tenant'];
147
-			$this->params['scope']['project']['domain']['name'] = $this->params['domain'];
148
-		}
149
-		$this->params = array_merge(self::DEFAULT_OPTIONS, $this->params);
123
+    /**
124
+     * @return OpenStack
125
+     * @throws StorageAuthException
126
+     */
127
+    private function getClient() {
128
+        if (isset($this->params['bucket'])) {
129
+            $this->params['container'] = $this->params['bucket'];
130
+        }
131
+        if (!isset($this->params['container'])) {
132
+            $this->params['container'] = 'nextcloud';
133
+        }
134
+        if (isset($this->params['user']) && is_array($this->params['user'])) {
135
+            $userName = $this->params['user']['name'];
136
+        } else {
137
+            if (!isset($this->params['username']) && isset($this->params['user'])) {
138
+                $this->params['username'] = $this->params['user'];
139
+            }
140
+            $userName = $this->params['username'];
141
+        }
142
+        if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) {
143
+            $this->params['tenantName'] = $this->params['tenant'];
144
+        }
145
+        if (isset($this->params['domain'])) {
146
+            $this->params['scope']['project']['name'] = $this->params['tenant'];
147
+            $this->params['scope']['project']['domain']['name'] = $this->params['domain'];
148
+        }
149
+        $this->params = array_merge(self::DEFAULT_OPTIONS, $this->params);
150 150
 
151
-		$cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['container'];
152
-		$token = $this->getCachedToken($cacheKey);
153
-		$this->params['cachedToken'] = $token;
151
+        $cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['container'];
152
+        $token = $this->getCachedToken($cacheKey);
153
+        $this->params['cachedToken'] = $token;
154 154
 
155
-		$httpClient = new Client([
156
-			'base_uri' => TransportUtils::normalizeUrl($this->params['url']),
157
-			'handler' => HandlerStack::create()
158
-		]);
155
+        $httpClient = new Client([
156
+            'base_uri' => TransportUtils::normalizeUrl($this->params['url']),
157
+            'handler' => HandlerStack::create()
158
+        ]);
159 159
 
160
-		if (isset($this->params['user']) && is_array($this->params['user']) && isset($this->params['user']['name'])) {
161
-			if (!isset($this->params['scope'])) {
162
-				throw new StorageAuthException('Scope has to be defined for V3 requests');
163
-			}
160
+        if (isset($this->params['user']) && is_array($this->params['user']) && isset($this->params['user']['name'])) {
161
+            if (!isset($this->params['scope'])) {
162
+                throw new StorageAuthException('Scope has to be defined for V3 requests');
163
+            }
164 164
 
165
-			return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey);
166
-		} else {
167
-			return $this->auth(SwiftV2CachingAuthService::factory($httpClient), $cacheKey);
168
-		}
169
-	}
165
+            return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey);
166
+        } else {
167
+            return $this->auth(SwiftV2CachingAuthService::factory($httpClient), $cacheKey);
168
+        }
169
+    }
170 170
 
171
-	/**
172
-	 * @param IdentityV2Service|IdentityV3Service $authService
173
-	 * @param string $cacheKey
174
-	 * @return OpenStack
175
-	 * @throws StorageAuthException
176
-	 */
177
-	private function auth($authService, string $cacheKey) {
178
-		$this->params['identityService'] = $authService;
179
-		$this->params['authUrl'] = $this->params['url'];
171
+    /**
172
+     * @param IdentityV2Service|IdentityV3Service $authService
173
+     * @param string $cacheKey
174
+     * @return OpenStack
175
+     * @throws StorageAuthException
176
+     */
177
+    private function auth($authService, string $cacheKey) {
178
+        $this->params['identityService'] = $authService;
179
+        $this->params['authUrl'] = $this->params['url'];
180 180
 
181
-		$cachedToken = $this->params['cachedToken'];
182
-		$hasValidCachedToken = false;
183
-		if (\is_array($cachedToken)) {
184
-			if ($authService instanceof IdentityV3Service) {
185
-				$token = $authService->generateTokenFromCache($cachedToken);
186
-				if (\is_null($token->catalog)) {
187
-					$this->logger->warning('Invalid cached token for swift, no catalog set: ' . json_encode($cachedToken));
188
-				} elseif ($token->hasExpired()) {
189
-					$this->logger->debug('Cached token for swift expired');
190
-				} else {
191
-					$hasValidCachedToken = true;
192
-				}
193
-			} else {
194
-				try {
195
-					/** @var \OpenStack\Identity\v2\Models\Token $token */
196
-					$token = $authService->model(\OpenStack\Identity\v2\Models\Token::class, $cachedToken['token']);
197
-					$now = new \DateTimeImmutable("now");
198
-					if ($token->expires > $now) {
199
-						$hasValidCachedToken = true;
200
-						$this->params['v2cachedToken'] = $token;
201
-						$this->params['v2serviceUrl'] = $cachedToken['serviceUrl'];
202
-					} else {
203
-						$this->logger->debug('Cached token for swift expired');
204
-					}
205
-				} catch (\Exception $e) {
206
-					$this->logger->logException($e);
207
-				}
208
-			}
209
-		}
181
+        $cachedToken = $this->params['cachedToken'];
182
+        $hasValidCachedToken = false;
183
+        if (\is_array($cachedToken)) {
184
+            if ($authService instanceof IdentityV3Service) {
185
+                $token = $authService->generateTokenFromCache($cachedToken);
186
+                if (\is_null($token->catalog)) {
187
+                    $this->logger->warning('Invalid cached token for swift, no catalog set: ' . json_encode($cachedToken));
188
+                } elseif ($token->hasExpired()) {
189
+                    $this->logger->debug('Cached token for swift expired');
190
+                } else {
191
+                    $hasValidCachedToken = true;
192
+                }
193
+            } else {
194
+                try {
195
+                    /** @var \OpenStack\Identity\v2\Models\Token $token */
196
+                    $token = $authService->model(\OpenStack\Identity\v2\Models\Token::class, $cachedToken['token']);
197
+                    $now = new \DateTimeImmutable("now");
198
+                    if ($token->expires > $now) {
199
+                        $hasValidCachedToken = true;
200
+                        $this->params['v2cachedToken'] = $token;
201
+                        $this->params['v2serviceUrl'] = $cachedToken['serviceUrl'];
202
+                    } else {
203
+                        $this->logger->debug('Cached token for swift expired');
204
+                    }
205
+                } catch (\Exception $e) {
206
+                    $this->logger->logException($e);
207
+                }
208
+            }
209
+        }
210 210
 
211
-		if (!$hasValidCachedToken) {
212
-			unset($this->params['cachedToken']);
213
-			try {
214
-				list($token, $serviceUrl) = $authService->authenticate($this->params);
215
-				$this->cacheToken($token, $serviceUrl, $cacheKey);
216
-			} catch (ConnectException $e) {
217
-				throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e);
218
-			} catch (ClientException $e) {
219
-				$statusCode = $e->getResponse()->getStatusCode();
220
-				if ($statusCode === 404) {
221
-					throw new StorageAuthException('Keystone not found, verify the keystone url', $e);
222
-				} elseif ($statusCode === 412) {
223
-					throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
224
-				} elseif ($statusCode === 401) {
225
-					throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
226
-				} else {
227
-					throw new StorageAuthException('Unknown error', $e);
228
-				}
229
-			} catch (RequestException $e) {
230
-				throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e);
231
-			}
232
-		}
211
+        if (!$hasValidCachedToken) {
212
+            unset($this->params['cachedToken']);
213
+            try {
214
+                list($token, $serviceUrl) = $authService->authenticate($this->params);
215
+                $this->cacheToken($token, $serviceUrl, $cacheKey);
216
+            } catch (ConnectException $e) {
217
+                throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e);
218
+            } catch (ClientException $e) {
219
+                $statusCode = $e->getResponse()->getStatusCode();
220
+                if ($statusCode === 404) {
221
+                    throw new StorageAuthException('Keystone not found, verify the keystone url', $e);
222
+                } elseif ($statusCode === 412) {
223
+                    throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
224
+                } elseif ($statusCode === 401) {
225
+                    throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
226
+                } else {
227
+                    throw new StorageAuthException('Unknown error', $e);
228
+                }
229
+            } catch (RequestException $e) {
230
+                throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e);
231
+            }
232
+        }
233 233
 
234 234
 
235
-		$client = new OpenStack($this->params);
235
+        $client = new OpenStack($this->params);
236 236
 
237
-		return $client;
238
-	}
237
+        return $client;
238
+    }
239 239
 
240
-	/**
241
-	 * @return \OpenStack\ObjectStore\v1\Models\Container
242
-	 * @throws StorageAuthException
243
-	 * @throws StorageNotAvailableException
244
-	 */
245
-	public function getContainer() {
246
-		if (is_null($this->container)) {
247
-			$this->container = $this->createContainer();
248
-		}
240
+    /**
241
+     * @return \OpenStack\ObjectStore\v1\Models\Container
242
+     * @throws StorageAuthException
243
+     * @throws StorageNotAvailableException
244
+     */
245
+    public function getContainer() {
246
+        if (is_null($this->container)) {
247
+            $this->container = $this->createContainer();
248
+        }
249 249
 
250
-		return $this->container;
251
-	}
250
+        return $this->container;
251
+    }
252 252
 
253
-	/**
254
-	 * @return \OpenStack\ObjectStore\v1\Models\Container
255
-	 * @throws StorageAuthException
256
-	 * @throws StorageNotAvailableException
257
-	 */
258
-	private function createContainer() {
259
-		$client = $this->getClient();
260
-		$objectStoreService = $client->objectStoreV1();
253
+    /**
254
+     * @return \OpenStack\ObjectStore\v1\Models\Container
255
+     * @throws StorageAuthException
256
+     * @throws StorageNotAvailableException
257
+     */
258
+    private function createContainer() {
259
+        $client = $this->getClient();
260
+        $objectStoreService = $client->objectStoreV1();
261 261
 
262
-		$autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true;
263
-		try {
264
-			$container = $objectStoreService->getContainer($this->params['container']);
265
-			if ($autoCreate) {
266
-				$container->getMetadata();
267
-			}
268
-			return $container;
269
-		} catch (BadResponseError $ex) {
270
-			// if the container does not exist and autocreate is true try to create the container on the fly
271
-			if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) {
272
-				return $objectStoreService->createContainer([
273
-					'name' => $this->params['container']
274
-				]);
275
-			} else {
276
-				throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $ex);
277
-			}
278
-		} catch (ConnectException $e) {
279
-			/** @var RequestInterface $request */
280
-			$request = $e->getRequest();
281
-			$host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort();
282
-			\OC::$server->getLogger()->error("Can't connect to object storage server at $host");
283
-			throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e);
284
-		}
285
-	}
262
+        $autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true;
263
+        try {
264
+            $container = $objectStoreService->getContainer($this->params['container']);
265
+            if ($autoCreate) {
266
+                $container->getMetadata();
267
+            }
268
+            return $container;
269
+        } catch (BadResponseError $ex) {
270
+            // if the container does not exist and autocreate is true try to create the container on the fly
271
+            if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) {
272
+                return $objectStoreService->createContainer([
273
+                    'name' => $this->params['container']
274
+                ]);
275
+            } else {
276
+                throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $ex);
277
+            }
278
+        } catch (ConnectException $e) {
279
+            /** @var RequestInterface $request */
280
+            $request = $e->getRequest();
281
+            $host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort();
282
+            \OC::$server->getLogger()->error("Can't connect to object storage server at $host");
283
+            throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e);
284
+        }
285
+    }
286 286
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -91,7 +91,7 @@  discard block
 block discarded – undo
91 91
 	}
92 92
 
93 93
 	private function getCachedToken(string $cacheKey) {
94
-		$cachedTokenString = $this->cache->get($cacheKey . '/token');
94
+		$cachedTokenString = $this->cache->get($cacheKey.'/token');
95 95
 		if ($cachedTokenString) {
96 96
 			return json_decode($cachedTokenString, true);
97 97
 		} else {
@@ -117,7 +117,7 @@  discard block
 block discarded – undo
117 117
 		}
118 118
 
119 119
 		$this->params['cachedToken'] = $value;
120
-		$this->cache->set($cacheKey . '/token', json_encode($value));
120
+		$this->cache->set($cacheKey.'/token', json_encode($value));
121 121
 	}
122 122
 
123 123
 	/**
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
 		}
149 149
 		$this->params = array_merge(self::DEFAULT_OPTIONS, $this->params);
150 150
 
151
-		$cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['container'];
151
+		$cacheKey = $userName.'@'.$this->params['url'].'/'.$this->params['container'];
152 152
 		$token = $this->getCachedToken($cacheKey);
153 153
 		$this->params['cachedToken'] = $token;
154 154
 
@@ -184,7 +184,7 @@  discard block
 block discarded – undo
184 184
 			if ($authService instanceof IdentityV3Service) {
185 185
 				$token = $authService->generateTokenFromCache($cachedToken);
186 186
 				if (\is_null($token->catalog)) {
187
-					$this->logger->warning('Invalid cached token for swift, no catalog set: ' . json_encode($cachedToken));
187
+					$this->logger->warning('Invalid cached token for swift, no catalog set: '.json_encode($cachedToken));
188 188
 				} elseif ($token->hasExpired()) {
189 189
 					$this->logger->debug('Cached token for swift expired');
190 190
 				} else {
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
 		} catch (ConnectException $e) {
279 279
 			/** @var RequestInterface $request */
280 280
 			$request = $e->getRequest();
281
-			$host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort();
281
+			$host = $request->getUri()->getHost().':'.$request->getUri()->getPort();
282 282
 			\OC::$server->getLogger()->error("Can't connect to object storage server at $host");
283 283
 			throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e);
284 284
 		}
Please login to merge, or discard this patch.
lib/private/Files/Storage/Wrapper/Jail.php 1 patch
Indentation   +504 added lines, -504 removed lines patch added patch discarded remove patch
@@ -39,508 +39,508 @@
 block discarded – undo
39 39
  * This restricts access to a subfolder of the wrapped storage with the subfolder becoming the root folder new storage
40 40
  */
41 41
 class Jail extends Wrapper {
42
-	/**
43
-	 * @var string
44
-	 */
45
-	protected $rootPath;
46
-
47
-	/**
48
-	 * @param array $arguments ['storage' => $storage, 'mask' => $root]
49
-	 *
50
-	 * $storage: The storage that will be wrapper
51
-	 * $root: The folder in the wrapped storage that will become the root folder of the wrapped storage
52
-	 */
53
-	public function __construct($arguments) {
54
-		parent::__construct($arguments);
55
-		$this->rootPath = $arguments['root'];
56
-	}
57
-
58
-	public function getUnjailedPath($path) {
59
-		if ($path === '') {
60
-			return $this->rootPath;
61
-		} else {
62
-			return Filesystem::normalizePath($this->rootPath . '/' . $path);
63
-		}
64
-	}
65
-
66
-	/**
67
-	 * This is separate from Wrapper::getWrapperStorage so we can get the jailed storage consistently even if the jail is inside another wrapper
68
-	 */
69
-	public function getUnjailedStorage() {
70
-		return $this->storage;
71
-	}
72
-
73
-
74
-	public function getJailedPath($path) {
75
-		$root = rtrim($this->rootPath, '/') . '/';
76
-
77
-		if ($path !== $this->rootPath && strpos($path, $root) !== 0) {
78
-			return null;
79
-		} else {
80
-			$path = substr($path, strlen($this->rootPath));
81
-			return trim($path, '/');
82
-		}
83
-	}
84
-
85
-	public function getId() {
86
-		return parent::getId();
87
-	}
88
-
89
-	/**
90
-	 * see http://php.net/manual/en/function.mkdir.php
91
-	 *
92
-	 * @param string $path
93
-	 * @return bool
94
-	 */
95
-	public function mkdir($path) {
96
-		return $this->getWrapperStorage()->mkdir($this->getUnjailedPath($path));
97
-	}
98
-
99
-	/**
100
-	 * see http://php.net/manual/en/function.rmdir.php
101
-	 *
102
-	 * @param string $path
103
-	 * @return bool
104
-	 */
105
-	public function rmdir($path) {
106
-		return $this->getWrapperStorage()->rmdir($this->getUnjailedPath($path));
107
-	}
108
-
109
-	/**
110
-	 * see http://php.net/manual/en/function.opendir.php
111
-	 *
112
-	 * @param string $path
113
-	 * @return resource
114
-	 */
115
-	public function opendir($path) {
116
-		return $this->getWrapperStorage()->opendir($this->getUnjailedPath($path));
117
-	}
118
-
119
-	/**
120
-	 * see http://php.net/manual/en/function.is_dir.php
121
-	 *
122
-	 * @param string $path
123
-	 * @return bool
124
-	 */
125
-	public function is_dir($path) {
126
-		return $this->getWrapperStorage()->is_dir($this->getUnjailedPath($path));
127
-	}
128
-
129
-	/**
130
-	 * see http://php.net/manual/en/function.is_file.php
131
-	 *
132
-	 * @param string $path
133
-	 * @return bool
134
-	 */
135
-	public function is_file($path) {
136
-		return $this->getWrapperStorage()->is_file($this->getUnjailedPath($path));
137
-	}
138
-
139
-	/**
140
-	 * see http://php.net/manual/en/function.stat.php
141
-	 * only the following keys are required in the result: size and mtime
142
-	 *
143
-	 * @param string $path
144
-	 * @return array
145
-	 */
146
-	public function stat($path) {
147
-		return $this->getWrapperStorage()->stat($this->getUnjailedPath($path));
148
-	}
149
-
150
-	/**
151
-	 * see http://php.net/manual/en/function.filetype.php
152
-	 *
153
-	 * @param string $path
154
-	 * @return bool
155
-	 */
156
-	public function filetype($path) {
157
-		return $this->getWrapperStorage()->filetype($this->getUnjailedPath($path));
158
-	}
159
-
160
-	/**
161
-	 * see http://php.net/manual/en/function.filesize.php
162
-	 * The result for filesize when called on a folder is required to be 0
163
-	 *
164
-	 * @param string $path
165
-	 * @return int
166
-	 */
167
-	public function filesize($path) {
168
-		return $this->getWrapperStorage()->filesize($this->getUnjailedPath($path));
169
-	}
170
-
171
-	/**
172
-	 * check if a file can be created in $path
173
-	 *
174
-	 * @param string $path
175
-	 * @return bool
176
-	 */
177
-	public function isCreatable($path) {
178
-		return $this->getWrapperStorage()->isCreatable($this->getUnjailedPath($path));
179
-	}
180
-
181
-	/**
182
-	 * check if a file can be read
183
-	 *
184
-	 * @param string $path
185
-	 * @return bool
186
-	 */
187
-	public function isReadable($path) {
188
-		return $this->getWrapperStorage()->isReadable($this->getUnjailedPath($path));
189
-	}
190
-
191
-	/**
192
-	 * check if a file can be written to
193
-	 *
194
-	 * @param string $path
195
-	 * @return bool
196
-	 */
197
-	public function isUpdatable($path) {
198
-		return $this->getWrapperStorage()->isUpdatable($this->getUnjailedPath($path));
199
-	}
200
-
201
-	/**
202
-	 * check if a file can be deleted
203
-	 *
204
-	 * @param string $path
205
-	 * @return bool
206
-	 */
207
-	public function isDeletable($path) {
208
-		return $this->getWrapperStorage()->isDeletable($this->getUnjailedPath($path));
209
-	}
210
-
211
-	/**
212
-	 * check if a file can be shared
213
-	 *
214
-	 * @param string $path
215
-	 * @return bool
216
-	 */
217
-	public function isSharable($path) {
218
-		return $this->getWrapperStorage()->isSharable($this->getUnjailedPath($path));
219
-	}
220
-
221
-	/**
222
-	 * get the full permissions of a path.
223
-	 * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php
224
-	 *
225
-	 * @param string $path
226
-	 * @return int
227
-	 */
228
-	public function getPermissions($path) {
229
-		return $this->getWrapperStorage()->getPermissions($this->getUnjailedPath($path));
230
-	}
231
-
232
-	/**
233
-	 * see http://php.net/manual/en/function.file_exists.php
234
-	 *
235
-	 * @param string $path
236
-	 * @return bool
237
-	 */
238
-	public function file_exists($path) {
239
-		return $this->getWrapperStorage()->file_exists($this->getUnjailedPath($path));
240
-	}
241
-
242
-	/**
243
-	 * see http://php.net/manual/en/function.filemtime.php
244
-	 *
245
-	 * @param string $path
246
-	 * @return int
247
-	 */
248
-	public function filemtime($path) {
249
-		return $this->getWrapperStorage()->filemtime($this->getUnjailedPath($path));
250
-	}
251
-
252
-	/**
253
-	 * see http://php.net/manual/en/function.file_get_contents.php
254
-	 *
255
-	 * @param string $path
256
-	 * @return string
257
-	 */
258
-	public function file_get_contents($path) {
259
-		return $this->getWrapperStorage()->file_get_contents($this->getUnjailedPath($path));
260
-	}
261
-
262
-	/**
263
-	 * see http://php.net/manual/en/function.file_put_contents.php
264
-	 *
265
-	 * @param string $path
266
-	 * @param string $data
267
-	 * @return bool
268
-	 */
269
-	public function file_put_contents($path, $data) {
270
-		return $this->getWrapperStorage()->file_put_contents($this->getUnjailedPath($path), $data);
271
-	}
272
-
273
-	/**
274
-	 * see http://php.net/manual/en/function.unlink.php
275
-	 *
276
-	 * @param string $path
277
-	 * @return bool
278
-	 */
279
-	public function unlink($path) {
280
-		return $this->getWrapperStorage()->unlink($this->getUnjailedPath($path));
281
-	}
282
-
283
-	/**
284
-	 * see http://php.net/manual/en/function.rename.php
285
-	 *
286
-	 * @param string $path1
287
-	 * @param string $path2
288
-	 * @return bool
289
-	 */
290
-	public function rename($path1, $path2) {
291
-		return $this->getWrapperStorage()->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
292
-	}
293
-
294
-	/**
295
-	 * see http://php.net/manual/en/function.copy.php
296
-	 *
297
-	 * @param string $path1
298
-	 * @param string $path2
299
-	 * @return bool
300
-	 */
301
-	public function copy($path1, $path2) {
302
-		return $this->getWrapperStorage()->copy($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
303
-	}
304
-
305
-	/**
306
-	 * see http://php.net/manual/en/function.fopen.php
307
-	 *
308
-	 * @param string $path
309
-	 * @param string $mode
310
-	 * @return resource
311
-	 */
312
-	public function fopen($path, $mode) {
313
-		return $this->getWrapperStorage()->fopen($this->getUnjailedPath($path), $mode);
314
-	}
315
-
316
-	/**
317
-	 * get the mimetype for a file or folder
318
-	 * The mimetype for a folder is required to be "httpd/unix-directory"
319
-	 *
320
-	 * @param string $path
321
-	 * @return string
322
-	 */
323
-	public function getMimeType($path) {
324
-		return $this->getWrapperStorage()->getMimeType($this->getUnjailedPath($path));
325
-	}
326
-
327
-	/**
328
-	 * see http://php.net/manual/en/function.hash.php
329
-	 *
330
-	 * @param string $type
331
-	 * @param string $path
332
-	 * @param bool $raw
333
-	 * @return string
334
-	 */
335
-	public function hash($type, $path, $raw = false) {
336
-		return $this->getWrapperStorage()->hash($type, $this->getUnjailedPath($path), $raw);
337
-	}
338
-
339
-	/**
340
-	 * see http://php.net/manual/en/function.free_space.php
341
-	 *
342
-	 * @param string $path
343
-	 * @return int
344
-	 */
345
-	public function free_space($path) {
346
-		return $this->getWrapperStorage()->free_space($this->getUnjailedPath($path));
347
-	}
348
-
349
-	/**
350
-	 * search for occurrences of $query in file names
351
-	 *
352
-	 * @param string $query
353
-	 * @return array
354
-	 */
355
-	public function search($query) {
356
-		return $this->getWrapperStorage()->search($query);
357
-	}
358
-
359
-	/**
360
-	 * see http://php.net/manual/en/function.touch.php
361
-	 * If the backend does not support the operation, false should be returned
362
-	 *
363
-	 * @param string $path
364
-	 * @param int $mtime
365
-	 * @return bool
366
-	 */
367
-	public function touch($path, $mtime = null) {
368
-		return $this->getWrapperStorage()->touch($this->getUnjailedPath($path), $mtime);
369
-	}
370
-
371
-	/**
372
-	 * get the path to a local version of the file.
373
-	 * The local version of the file can be temporary and doesn't have to be persistent across requests
374
-	 *
375
-	 * @param string $path
376
-	 * @return string
377
-	 */
378
-	public function getLocalFile($path) {
379
-		return $this->getWrapperStorage()->getLocalFile($this->getUnjailedPath($path));
380
-	}
381
-
382
-	/**
383
-	 * check if a file or folder has been updated since $time
384
-	 *
385
-	 * @param string $path
386
-	 * @param int $time
387
-	 * @return bool
388
-	 *
389
-	 * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
390
-	 * returning true for other changes in the folder is optional
391
-	 */
392
-	public function hasUpdated($path, $time) {
393
-		return $this->getWrapperStorage()->hasUpdated($this->getUnjailedPath($path), $time);
394
-	}
395
-
396
-	/**
397
-	 * get a cache instance for the storage
398
-	 *
399
-	 * @param string $path
400
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
401
-	 * @return \OC\Files\Cache\Cache
402
-	 */
403
-	public function getCache($path = '', $storage = null) {
404
-		if (!$storage) {
405
-			$storage = $this->getWrapperStorage();
406
-		}
407
-		$sourceCache = $this->getWrapperStorage()->getCache($this->getUnjailedPath($path), $storage);
408
-		return new CacheJail($sourceCache, $this->rootPath);
409
-	}
410
-
411
-	/**
412
-	 * get the user id of the owner of a file or folder
413
-	 *
414
-	 * @param string $path
415
-	 * @return string
416
-	 */
417
-	public function getOwner($path) {
418
-		return $this->getWrapperStorage()->getOwner($this->getUnjailedPath($path));
419
-	}
420
-
421
-	/**
422
-	 * get a watcher instance for the cache
423
-	 *
424
-	 * @param string $path
425
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
426
-	 * @return \OC\Files\Cache\Watcher
427
-	 */
428
-	public function getWatcher($path = '', $storage = null) {
429
-		if (!$storage) {
430
-			$storage = $this;
431
-		}
432
-		return $this->getWrapperStorage()->getWatcher($this->getUnjailedPath($path), $storage);
433
-	}
434
-
435
-	/**
436
-	 * get the ETag for a file or folder
437
-	 *
438
-	 * @param string $path
439
-	 * @return string
440
-	 */
441
-	public function getETag($path) {
442
-		return $this->getWrapperStorage()->getETag($this->getUnjailedPath($path));
443
-	}
444
-
445
-	/**
446
-	 * @param string $path
447
-	 * @return array
448
-	 */
449
-	public function getMetaData($path) {
450
-		return $this->getWrapperStorage()->getMetaData($this->getUnjailedPath($path));
451
-	}
452
-
453
-	/**
454
-	 * @param string $path
455
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
456
-	 * @param \OCP\Lock\ILockingProvider $provider
457
-	 * @throws \OCP\Lock\LockedException
458
-	 */
459
-	public function acquireLock($path, $type, ILockingProvider $provider) {
460
-		$this->getWrapperStorage()->acquireLock($this->getUnjailedPath($path), $type, $provider);
461
-	}
462
-
463
-	/**
464
-	 * @param string $path
465
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
466
-	 * @param \OCP\Lock\ILockingProvider $provider
467
-	 */
468
-	public function releaseLock($path, $type, ILockingProvider $provider) {
469
-		$this->getWrapperStorage()->releaseLock($this->getUnjailedPath($path), $type, $provider);
470
-	}
471
-
472
-	/**
473
-	 * @param string $path
474
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
475
-	 * @param \OCP\Lock\ILockingProvider $provider
476
-	 */
477
-	public function changeLock($path, $type, ILockingProvider $provider) {
478
-		$this->getWrapperStorage()->changeLock($this->getUnjailedPath($path), $type, $provider);
479
-	}
480
-
481
-	/**
482
-	 * Resolve the path for the source of the share
483
-	 *
484
-	 * @param string $path
485
-	 * @return array
486
-	 */
487
-	public function resolvePath($path) {
488
-		return [$this->getWrapperStorage(), $this->getUnjailedPath($path)];
489
-	}
490
-
491
-	/**
492
-	 * @param IStorage $sourceStorage
493
-	 * @param string $sourceInternalPath
494
-	 * @param string $targetInternalPath
495
-	 * @return bool
496
-	 */
497
-	public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
498
-		if ($sourceStorage === $this) {
499
-			return $this->copy($sourceInternalPath, $targetInternalPath);
500
-		}
501
-		return $this->getWrapperStorage()->copyFromStorage($sourceStorage, $sourceInternalPath, $this->getUnjailedPath($targetInternalPath));
502
-	}
503
-
504
-	/**
505
-	 * @param IStorage $sourceStorage
506
-	 * @param string $sourceInternalPath
507
-	 * @param string $targetInternalPath
508
-	 * @return bool
509
-	 */
510
-	public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
511
-		if ($sourceStorage === $this) {
512
-			return $this->rename($sourceInternalPath, $targetInternalPath);
513
-		}
514
-		return $this->getWrapperStorage()->moveFromStorage($sourceStorage, $sourceInternalPath, $this->getUnjailedPath($targetInternalPath));
515
-	}
516
-
517
-	public function getPropagator($storage = null) {
518
-		if (isset($this->propagator)) {
519
-			return $this->propagator;
520
-		}
521
-
522
-		if (!$storage) {
523
-			$storage = $this;
524
-		}
525
-		$this->propagator = new JailPropagator($storage, \OC::$server->getDatabaseConnection());
526
-		return $this->propagator;
527
-	}
528
-
529
-	public function writeStream(string $path, $stream, int $size = null): int {
530
-		$storage = $this->getWrapperStorage();
531
-		if ($storage->instanceOfStorage(IWriteStreamStorage::class)) {
532
-			/** @var IWriteStreamStorage $storage */
533
-			return $storage->writeStream($this->getUnjailedPath($path), $stream, $size);
534
-		} else {
535
-			$target = $this->fopen($path, 'w');
536
-			list($count, $result) = \OC_Helper::streamCopy($stream, $target);
537
-			fclose($stream);
538
-			fclose($target);
539
-			return $count;
540
-		}
541
-	}
542
-
543
-	public function getDirectoryContent($directory): \Traversable {
544
-		return $this->getWrapperStorage()->getDirectoryContent($this->getUnjailedPath($directory));
545
-	}
42
+    /**
43
+     * @var string
44
+     */
45
+    protected $rootPath;
46
+
47
+    /**
48
+     * @param array $arguments ['storage' => $storage, 'mask' => $root]
49
+     *
50
+     * $storage: The storage that will be wrapper
51
+     * $root: The folder in the wrapped storage that will become the root folder of the wrapped storage
52
+     */
53
+    public function __construct($arguments) {
54
+        parent::__construct($arguments);
55
+        $this->rootPath = $arguments['root'];
56
+    }
57
+
58
+    public function getUnjailedPath($path) {
59
+        if ($path === '') {
60
+            return $this->rootPath;
61
+        } else {
62
+            return Filesystem::normalizePath($this->rootPath . '/' . $path);
63
+        }
64
+    }
65
+
66
+    /**
67
+     * This is separate from Wrapper::getWrapperStorage so we can get the jailed storage consistently even if the jail is inside another wrapper
68
+     */
69
+    public function getUnjailedStorage() {
70
+        return $this->storage;
71
+    }
72
+
73
+
74
+    public function getJailedPath($path) {
75
+        $root = rtrim($this->rootPath, '/') . '/';
76
+
77
+        if ($path !== $this->rootPath && strpos($path, $root) !== 0) {
78
+            return null;
79
+        } else {
80
+            $path = substr($path, strlen($this->rootPath));
81
+            return trim($path, '/');
82
+        }
83
+    }
84
+
85
+    public function getId() {
86
+        return parent::getId();
87
+    }
88
+
89
+    /**
90
+     * see http://php.net/manual/en/function.mkdir.php
91
+     *
92
+     * @param string $path
93
+     * @return bool
94
+     */
95
+    public function mkdir($path) {
96
+        return $this->getWrapperStorage()->mkdir($this->getUnjailedPath($path));
97
+    }
98
+
99
+    /**
100
+     * see http://php.net/manual/en/function.rmdir.php
101
+     *
102
+     * @param string $path
103
+     * @return bool
104
+     */
105
+    public function rmdir($path) {
106
+        return $this->getWrapperStorage()->rmdir($this->getUnjailedPath($path));
107
+    }
108
+
109
+    /**
110
+     * see http://php.net/manual/en/function.opendir.php
111
+     *
112
+     * @param string $path
113
+     * @return resource
114
+     */
115
+    public function opendir($path) {
116
+        return $this->getWrapperStorage()->opendir($this->getUnjailedPath($path));
117
+    }
118
+
119
+    /**
120
+     * see http://php.net/manual/en/function.is_dir.php
121
+     *
122
+     * @param string $path
123
+     * @return bool
124
+     */
125
+    public function is_dir($path) {
126
+        return $this->getWrapperStorage()->is_dir($this->getUnjailedPath($path));
127
+    }
128
+
129
+    /**
130
+     * see http://php.net/manual/en/function.is_file.php
131
+     *
132
+     * @param string $path
133
+     * @return bool
134
+     */
135
+    public function is_file($path) {
136
+        return $this->getWrapperStorage()->is_file($this->getUnjailedPath($path));
137
+    }
138
+
139
+    /**
140
+     * see http://php.net/manual/en/function.stat.php
141
+     * only the following keys are required in the result: size and mtime
142
+     *
143
+     * @param string $path
144
+     * @return array
145
+     */
146
+    public function stat($path) {
147
+        return $this->getWrapperStorage()->stat($this->getUnjailedPath($path));
148
+    }
149
+
150
+    /**
151
+     * see http://php.net/manual/en/function.filetype.php
152
+     *
153
+     * @param string $path
154
+     * @return bool
155
+     */
156
+    public function filetype($path) {
157
+        return $this->getWrapperStorage()->filetype($this->getUnjailedPath($path));
158
+    }
159
+
160
+    /**
161
+     * see http://php.net/manual/en/function.filesize.php
162
+     * The result for filesize when called on a folder is required to be 0
163
+     *
164
+     * @param string $path
165
+     * @return int
166
+     */
167
+    public function filesize($path) {
168
+        return $this->getWrapperStorage()->filesize($this->getUnjailedPath($path));
169
+    }
170
+
171
+    /**
172
+     * check if a file can be created in $path
173
+     *
174
+     * @param string $path
175
+     * @return bool
176
+     */
177
+    public function isCreatable($path) {
178
+        return $this->getWrapperStorage()->isCreatable($this->getUnjailedPath($path));
179
+    }
180
+
181
+    /**
182
+     * check if a file can be read
183
+     *
184
+     * @param string $path
185
+     * @return bool
186
+     */
187
+    public function isReadable($path) {
188
+        return $this->getWrapperStorage()->isReadable($this->getUnjailedPath($path));
189
+    }
190
+
191
+    /**
192
+     * check if a file can be written to
193
+     *
194
+     * @param string $path
195
+     * @return bool
196
+     */
197
+    public function isUpdatable($path) {
198
+        return $this->getWrapperStorage()->isUpdatable($this->getUnjailedPath($path));
199
+    }
200
+
201
+    /**
202
+     * check if a file can be deleted
203
+     *
204
+     * @param string $path
205
+     * @return bool
206
+     */
207
+    public function isDeletable($path) {
208
+        return $this->getWrapperStorage()->isDeletable($this->getUnjailedPath($path));
209
+    }
210
+
211
+    /**
212
+     * check if a file can be shared
213
+     *
214
+     * @param string $path
215
+     * @return bool
216
+     */
217
+    public function isSharable($path) {
218
+        return $this->getWrapperStorage()->isSharable($this->getUnjailedPath($path));
219
+    }
220
+
221
+    /**
222
+     * get the full permissions of a path.
223
+     * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php
224
+     *
225
+     * @param string $path
226
+     * @return int
227
+     */
228
+    public function getPermissions($path) {
229
+        return $this->getWrapperStorage()->getPermissions($this->getUnjailedPath($path));
230
+    }
231
+
232
+    /**
233
+     * see http://php.net/manual/en/function.file_exists.php
234
+     *
235
+     * @param string $path
236
+     * @return bool
237
+     */
238
+    public function file_exists($path) {
239
+        return $this->getWrapperStorage()->file_exists($this->getUnjailedPath($path));
240
+    }
241
+
242
+    /**
243
+     * see http://php.net/manual/en/function.filemtime.php
244
+     *
245
+     * @param string $path
246
+     * @return int
247
+     */
248
+    public function filemtime($path) {
249
+        return $this->getWrapperStorage()->filemtime($this->getUnjailedPath($path));
250
+    }
251
+
252
+    /**
253
+     * see http://php.net/manual/en/function.file_get_contents.php
254
+     *
255
+     * @param string $path
256
+     * @return string
257
+     */
258
+    public function file_get_contents($path) {
259
+        return $this->getWrapperStorage()->file_get_contents($this->getUnjailedPath($path));
260
+    }
261
+
262
+    /**
263
+     * see http://php.net/manual/en/function.file_put_contents.php
264
+     *
265
+     * @param string $path
266
+     * @param string $data
267
+     * @return bool
268
+     */
269
+    public function file_put_contents($path, $data) {
270
+        return $this->getWrapperStorage()->file_put_contents($this->getUnjailedPath($path), $data);
271
+    }
272
+
273
+    /**
274
+     * see http://php.net/manual/en/function.unlink.php
275
+     *
276
+     * @param string $path
277
+     * @return bool
278
+     */
279
+    public function unlink($path) {
280
+        return $this->getWrapperStorage()->unlink($this->getUnjailedPath($path));
281
+    }
282
+
283
+    /**
284
+     * see http://php.net/manual/en/function.rename.php
285
+     *
286
+     * @param string $path1
287
+     * @param string $path2
288
+     * @return bool
289
+     */
290
+    public function rename($path1, $path2) {
291
+        return $this->getWrapperStorage()->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
292
+    }
293
+
294
+    /**
295
+     * see http://php.net/manual/en/function.copy.php
296
+     *
297
+     * @param string $path1
298
+     * @param string $path2
299
+     * @return bool
300
+     */
301
+    public function copy($path1, $path2) {
302
+        return $this->getWrapperStorage()->copy($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
303
+    }
304
+
305
+    /**
306
+     * see http://php.net/manual/en/function.fopen.php
307
+     *
308
+     * @param string $path
309
+     * @param string $mode
310
+     * @return resource
311
+     */
312
+    public function fopen($path, $mode) {
313
+        return $this->getWrapperStorage()->fopen($this->getUnjailedPath($path), $mode);
314
+    }
315
+
316
+    /**
317
+     * get the mimetype for a file or folder
318
+     * The mimetype for a folder is required to be "httpd/unix-directory"
319
+     *
320
+     * @param string $path
321
+     * @return string
322
+     */
323
+    public function getMimeType($path) {
324
+        return $this->getWrapperStorage()->getMimeType($this->getUnjailedPath($path));
325
+    }
326
+
327
+    /**
328
+     * see http://php.net/manual/en/function.hash.php
329
+     *
330
+     * @param string $type
331
+     * @param string $path
332
+     * @param bool $raw
333
+     * @return string
334
+     */
335
+    public function hash($type, $path, $raw = false) {
336
+        return $this->getWrapperStorage()->hash($type, $this->getUnjailedPath($path), $raw);
337
+    }
338
+
339
+    /**
340
+     * see http://php.net/manual/en/function.free_space.php
341
+     *
342
+     * @param string $path
343
+     * @return int
344
+     */
345
+    public function free_space($path) {
346
+        return $this->getWrapperStorage()->free_space($this->getUnjailedPath($path));
347
+    }
348
+
349
+    /**
350
+     * search for occurrences of $query in file names
351
+     *
352
+     * @param string $query
353
+     * @return array
354
+     */
355
+    public function search($query) {
356
+        return $this->getWrapperStorage()->search($query);
357
+    }
358
+
359
+    /**
360
+     * see http://php.net/manual/en/function.touch.php
361
+     * If the backend does not support the operation, false should be returned
362
+     *
363
+     * @param string $path
364
+     * @param int $mtime
365
+     * @return bool
366
+     */
367
+    public function touch($path, $mtime = null) {
368
+        return $this->getWrapperStorage()->touch($this->getUnjailedPath($path), $mtime);
369
+    }
370
+
371
+    /**
372
+     * get the path to a local version of the file.
373
+     * The local version of the file can be temporary and doesn't have to be persistent across requests
374
+     *
375
+     * @param string $path
376
+     * @return string
377
+     */
378
+    public function getLocalFile($path) {
379
+        return $this->getWrapperStorage()->getLocalFile($this->getUnjailedPath($path));
380
+    }
381
+
382
+    /**
383
+     * check if a file or folder has been updated since $time
384
+     *
385
+     * @param string $path
386
+     * @param int $time
387
+     * @return bool
388
+     *
389
+     * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
390
+     * returning true for other changes in the folder is optional
391
+     */
392
+    public function hasUpdated($path, $time) {
393
+        return $this->getWrapperStorage()->hasUpdated($this->getUnjailedPath($path), $time);
394
+    }
395
+
396
+    /**
397
+     * get a cache instance for the storage
398
+     *
399
+     * @param string $path
400
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
401
+     * @return \OC\Files\Cache\Cache
402
+     */
403
+    public function getCache($path = '', $storage = null) {
404
+        if (!$storage) {
405
+            $storage = $this->getWrapperStorage();
406
+        }
407
+        $sourceCache = $this->getWrapperStorage()->getCache($this->getUnjailedPath($path), $storage);
408
+        return new CacheJail($sourceCache, $this->rootPath);
409
+    }
410
+
411
+    /**
412
+     * get the user id of the owner of a file or folder
413
+     *
414
+     * @param string $path
415
+     * @return string
416
+     */
417
+    public function getOwner($path) {
418
+        return $this->getWrapperStorage()->getOwner($this->getUnjailedPath($path));
419
+    }
420
+
421
+    /**
422
+     * get a watcher instance for the cache
423
+     *
424
+     * @param string $path
425
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
426
+     * @return \OC\Files\Cache\Watcher
427
+     */
428
+    public function getWatcher($path = '', $storage = null) {
429
+        if (!$storage) {
430
+            $storage = $this;
431
+        }
432
+        return $this->getWrapperStorage()->getWatcher($this->getUnjailedPath($path), $storage);
433
+    }
434
+
435
+    /**
436
+     * get the ETag for a file or folder
437
+     *
438
+     * @param string $path
439
+     * @return string
440
+     */
441
+    public function getETag($path) {
442
+        return $this->getWrapperStorage()->getETag($this->getUnjailedPath($path));
443
+    }
444
+
445
+    /**
446
+     * @param string $path
447
+     * @return array
448
+     */
449
+    public function getMetaData($path) {
450
+        return $this->getWrapperStorage()->getMetaData($this->getUnjailedPath($path));
451
+    }
452
+
453
+    /**
454
+     * @param string $path
455
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
456
+     * @param \OCP\Lock\ILockingProvider $provider
457
+     * @throws \OCP\Lock\LockedException
458
+     */
459
+    public function acquireLock($path, $type, ILockingProvider $provider) {
460
+        $this->getWrapperStorage()->acquireLock($this->getUnjailedPath($path), $type, $provider);
461
+    }
462
+
463
+    /**
464
+     * @param string $path
465
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
466
+     * @param \OCP\Lock\ILockingProvider $provider
467
+     */
468
+    public function releaseLock($path, $type, ILockingProvider $provider) {
469
+        $this->getWrapperStorage()->releaseLock($this->getUnjailedPath($path), $type, $provider);
470
+    }
471
+
472
+    /**
473
+     * @param string $path
474
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
475
+     * @param \OCP\Lock\ILockingProvider $provider
476
+     */
477
+    public function changeLock($path, $type, ILockingProvider $provider) {
478
+        $this->getWrapperStorage()->changeLock($this->getUnjailedPath($path), $type, $provider);
479
+    }
480
+
481
+    /**
482
+     * Resolve the path for the source of the share
483
+     *
484
+     * @param string $path
485
+     * @return array
486
+     */
487
+    public function resolvePath($path) {
488
+        return [$this->getWrapperStorage(), $this->getUnjailedPath($path)];
489
+    }
490
+
491
+    /**
492
+     * @param IStorage $sourceStorage
493
+     * @param string $sourceInternalPath
494
+     * @param string $targetInternalPath
495
+     * @return bool
496
+     */
497
+    public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
498
+        if ($sourceStorage === $this) {
499
+            return $this->copy($sourceInternalPath, $targetInternalPath);
500
+        }
501
+        return $this->getWrapperStorage()->copyFromStorage($sourceStorage, $sourceInternalPath, $this->getUnjailedPath($targetInternalPath));
502
+    }
503
+
504
+    /**
505
+     * @param IStorage $sourceStorage
506
+     * @param string $sourceInternalPath
507
+     * @param string $targetInternalPath
508
+     * @return bool
509
+     */
510
+    public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
511
+        if ($sourceStorage === $this) {
512
+            return $this->rename($sourceInternalPath, $targetInternalPath);
513
+        }
514
+        return $this->getWrapperStorage()->moveFromStorage($sourceStorage, $sourceInternalPath, $this->getUnjailedPath($targetInternalPath));
515
+    }
516
+
517
+    public function getPropagator($storage = null) {
518
+        if (isset($this->propagator)) {
519
+            return $this->propagator;
520
+        }
521
+
522
+        if (!$storage) {
523
+            $storage = $this;
524
+        }
525
+        $this->propagator = new JailPropagator($storage, \OC::$server->getDatabaseConnection());
526
+        return $this->propagator;
527
+    }
528
+
529
+    public function writeStream(string $path, $stream, int $size = null): int {
530
+        $storage = $this->getWrapperStorage();
531
+        if ($storage->instanceOfStorage(IWriteStreamStorage::class)) {
532
+            /** @var IWriteStreamStorage $storage */
533
+            return $storage->writeStream($this->getUnjailedPath($path), $stream, $size);
534
+        } else {
535
+            $target = $this->fopen($path, 'w');
536
+            list($count, $result) = \OC_Helper::streamCopy($stream, $target);
537
+            fclose($stream);
538
+            fclose($target);
539
+            return $count;
540
+        }
541
+    }
542
+
543
+    public function getDirectoryContent($directory): \Traversable {
544
+        return $this->getWrapperStorage()->getDirectoryContent($this->getUnjailedPath($directory));
545
+    }
546 546
 }
Please login to merge, or discard this patch.