Completed
Pull Request — master (#8359)
by Robin
62:09 queued 44:59
created
lib/private/Files/ObjectStore/SwiftFactory.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-declare(strict_types=1);
2
+declare(strict_types = 1);
3 3
 /**
4 4
  * @copyright Copyright (c) 2018 Robin Appelman <[email protected]>
5 5
  *
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
 	}
52 52
 
53 53
 	private function getCachedToken(string $cacheKey) {
54
-		$cachedTokenString = $this->cache->get($cacheKey . '/token');
54
+		$cachedTokenString = $this->cache->get($cacheKey.'/token');
55 55
 		if ($cachedTokenString) {
56 56
 			return json_decode($cachedTokenString);
57 57
 		} else {
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
 	}
61 61
 
62 62
 	private function cacheToken(Token $token, string $cacheKey) {
63
-		$this->cache->set($cacheKey . '/token', json_encode($token));
63
+		$this->cache->set($cacheKey.'/token', json_encode($token));
64 64
 	}
65 65
 
66 66
 	/**
@@ -90,7 +90,7 @@  discard block
 block discarded – undo
90 90
 			$this->params['tenantName'] = $this->params['tenant'];
91 91
 		}
92 92
 
93
-		$cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['bucket'];
93
+		$cacheKey = $userName.'@'.$this->params['url'].'/'.$this->params['bucket'];
94 94
 		$token = $this->getCachedToken($cacheKey);
95 95
 		$hasToken = is_array($token) && (new \DateTimeImmutable($token['expires_at'])) > (new \DateTimeImmutable('now'));
96 96
 		if ($hasToken) {
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
 		} catch (ConnectException $e) {
187 187
 			/** @var RequestInterface $request */
188 188
 			$request = $e->getRequest();
189
-			$host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort();
189
+			$host = $request->getUri()->getHost().':'.$request->getUri()->getPort();
190 190
 			\OC::$server->getLogger()->error("Can't connect to object storage server at $host");
191 191
 			throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e);
192 192
 		}
Please login to merge, or discard this patch.
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -40,155 +40,155 @@
 block discarded – undo
40 40
 use OpenStack\ObjectStore\v1\Models\Container;
41 41
 
42 42
 class SwiftFactory {
43
-	private $cache;
44
-	private $params;
45
-	/** @var Container|null */
46
-	private $container = null;
47
-
48
-	public function __construct(ICache $cache, array $params) {
49
-		$this->cache = $cache;
50
-		$this->params = $params;
51
-	}
52
-
53
-	private function getCachedToken(string $cacheKey) {
54
-		$cachedTokenString = $this->cache->get($cacheKey . '/token');
55
-		if ($cachedTokenString) {
56
-			return json_decode($cachedTokenString);
57
-		} else {
58
-			return null;
59
-		}
60
-	}
61
-
62
-	private function cacheToken(Token $token, string $cacheKey) {
63
-		$this->cache->set($cacheKey . '/token', json_encode($token));
64
-	}
65
-
66
-	/**
67
-	 * @return OpenStack
68
-	 * @throws StorageAuthException
69
-	 */
70
-	private function getClient() {
71
-		if (isset($this->params['bucket'])) {
72
-			$this->params['container'] = $this->params['bucket'];
73
-		}
74
-		if (!isset($this->params['container'])) {
75
-			$this->params['container'] = 'owncloud';
76
-		}
77
-		if (!isset($this->params['autocreate'])) {
78
-			// should only be true for tests
79
-			$this->params['autocreate'] = false;
80
-		}
81
-		if (isset($this->params['user']) && is_array($this->params['user'])) {
82
-			$userName = $this->params['user']['name'];
83
-		} else {
84
-			if (!isset($this->params['username']) && isset($this->params['user'])) {
85
-				$this->params['username'] = $this->params['user'];
86
-			}
87
-			$userName = $this->params['username'];
88
-		}
89
-		if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) {
90
-			$this->params['tenantName'] = $this->params['tenant'];
91
-		}
92
-
93
-		$cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['bucket'];
94
-		$token = $this->getCachedToken($cacheKey);
95
-		$hasToken = is_array($token) && (new \DateTimeImmutable($token['expires_at'])) > (new \DateTimeImmutable('now'));
96
-		if ($hasToken) {
97
-			$this->params['cachedToken'] = $token;
98
-		}
99
-
100
-		$httpClient = new Client([
101
-			'base_uri' => TransportUtils::normalizeUrl($this->params['url']),
102
-			'handler' => HandlerStack::create()
103
-		]);
104
-
105
-		if (isset($this->params['user']) && isset($this->params['user']['name'])) {
106
-			return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey);
107
-		} else {
108
-			return $this->auth(IdentityV2Service::factory($httpClient), $cacheKey);
109
-		}
110
-	}
111
-
112
-	/**
113
-	 * @param IdentityV2Service|IdentityV3Service $authService
114
-	 * @param string $cacheKey
115
-	 * @return OpenStack
116
-	 * @throws StorageAuthException
117
-	 */
118
-	private function auth($authService, string $cacheKey) {
119
-		$this->params['identityService'] = $authService;
120
-		$this->params['authUrl'] = $this->params['url'];
121
-		$client = new OpenStack($this->params);
122
-
123
-		if (!isset($this->params['cachedToken'])) {
124
-			try {
125
-				$token = $authService->generateToken($this->params);
126
-				$this->cacheToken($token, $cacheKey);
127
-			} catch (ConnectException $e) {
128
-				throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e);
129
-			} catch (ClientException $e) {
130
-				$statusCode = $e->getResponse()->getStatusCode();
131
-				if ($statusCode === 404) {
132
-					throw new StorageAuthException('Keystone not found, verify the keystone url', $e);
133
-				} else if ($statusCode === 412) {
134
-					throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
135
-				} else if ($statusCode === 401) {
136
-					throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
137
-				} else {
138
-					throw new StorageAuthException('Unknown error', $e);
139
-				}
140
-			} catch (RequestException $e) {
141
-				throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e);
142
-			}
143
-		}
144
-
145
-		return $client;
146
-	}
147
-
148
-	/**
149
-	 * @return \OpenStack\ObjectStore\v1\Models\Container
150
-	 * @throws StorageAuthException
151
-	 * @throws StorageNotAvailableException
152
-	 */
153
-	public function getContainer() {
154
-		if (is_null($this->container)) {
155
-			$this->container = $this->createContainer();
156
-		}
157
-
158
-		return $this->container;
159
-	}
160
-
161
-	/**
162
-	 * @return \OpenStack\ObjectStore\v1\Models\Container
163
-	 * @throws StorageAuthException
164
-	 * @throws StorageNotAvailableException
165
-	 */
166
-	private function createContainer() {
167
-		$client = $this->getClient();
168
-		$objectStoreService = $client->objectStoreV1();
169
-
170
-		$autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true;
171
-		try {
172
-			$container = $objectStoreService->getContainer($this->params['container']);
173
-			if ($autoCreate) {
174
-				$container->getMetadata();
175
-			}
176
-			return $container;
177
-		} catch (BadResponseError $ex) {
178
-			// if the container does not exist and autocreate is true try to create the container on the fly
179
-			if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) {
180
-				return $objectStoreService->createContainer([
181
-					'name' => $this->params['container']
182
-				]);
183
-			} else {
184
-				throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $e);
185
-			}
186
-		} catch (ConnectException $e) {
187
-			/** @var RequestInterface $request */
188
-			$request = $e->getRequest();
189
-			$host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort();
190
-			\OC::$server->getLogger()->error("Can't connect to object storage server at $host");
191
-			throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e);
192
-		}
193
-	}
43
+    private $cache;
44
+    private $params;
45
+    /** @var Container|null */
46
+    private $container = null;
47
+
48
+    public function __construct(ICache $cache, array $params) {
49
+        $this->cache = $cache;
50
+        $this->params = $params;
51
+    }
52
+
53
+    private function getCachedToken(string $cacheKey) {
54
+        $cachedTokenString = $this->cache->get($cacheKey . '/token');
55
+        if ($cachedTokenString) {
56
+            return json_decode($cachedTokenString);
57
+        } else {
58
+            return null;
59
+        }
60
+    }
61
+
62
+    private function cacheToken(Token $token, string $cacheKey) {
63
+        $this->cache->set($cacheKey . '/token', json_encode($token));
64
+    }
65
+
66
+    /**
67
+     * @return OpenStack
68
+     * @throws StorageAuthException
69
+     */
70
+    private function getClient() {
71
+        if (isset($this->params['bucket'])) {
72
+            $this->params['container'] = $this->params['bucket'];
73
+        }
74
+        if (!isset($this->params['container'])) {
75
+            $this->params['container'] = 'owncloud';
76
+        }
77
+        if (!isset($this->params['autocreate'])) {
78
+            // should only be true for tests
79
+            $this->params['autocreate'] = false;
80
+        }
81
+        if (isset($this->params['user']) && is_array($this->params['user'])) {
82
+            $userName = $this->params['user']['name'];
83
+        } else {
84
+            if (!isset($this->params['username']) && isset($this->params['user'])) {
85
+                $this->params['username'] = $this->params['user'];
86
+            }
87
+            $userName = $this->params['username'];
88
+        }
89
+        if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) {
90
+            $this->params['tenantName'] = $this->params['tenant'];
91
+        }
92
+
93
+        $cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['bucket'];
94
+        $token = $this->getCachedToken($cacheKey);
95
+        $hasToken = is_array($token) && (new \DateTimeImmutable($token['expires_at'])) > (new \DateTimeImmutable('now'));
96
+        if ($hasToken) {
97
+            $this->params['cachedToken'] = $token;
98
+        }
99
+
100
+        $httpClient = new Client([
101
+            'base_uri' => TransportUtils::normalizeUrl($this->params['url']),
102
+            'handler' => HandlerStack::create()
103
+        ]);
104
+
105
+        if (isset($this->params['user']) && isset($this->params['user']['name'])) {
106
+            return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey);
107
+        } else {
108
+            return $this->auth(IdentityV2Service::factory($httpClient), $cacheKey);
109
+        }
110
+    }
111
+
112
+    /**
113
+     * @param IdentityV2Service|IdentityV3Service $authService
114
+     * @param string $cacheKey
115
+     * @return OpenStack
116
+     * @throws StorageAuthException
117
+     */
118
+    private function auth($authService, string $cacheKey) {
119
+        $this->params['identityService'] = $authService;
120
+        $this->params['authUrl'] = $this->params['url'];
121
+        $client = new OpenStack($this->params);
122
+
123
+        if (!isset($this->params['cachedToken'])) {
124
+            try {
125
+                $token = $authService->generateToken($this->params);
126
+                $this->cacheToken($token, $cacheKey);
127
+            } catch (ConnectException $e) {
128
+                throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e);
129
+            } catch (ClientException $e) {
130
+                $statusCode = $e->getResponse()->getStatusCode();
131
+                if ($statusCode === 404) {
132
+                    throw new StorageAuthException('Keystone not found, verify the keystone url', $e);
133
+                } else if ($statusCode === 412) {
134
+                    throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
135
+                } else if ($statusCode === 401) {
136
+                    throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
137
+                } else {
138
+                    throw new StorageAuthException('Unknown error', $e);
139
+                }
140
+            } catch (RequestException $e) {
141
+                throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e);
142
+            }
143
+        }
144
+
145
+        return $client;
146
+    }
147
+
148
+    /**
149
+     * @return \OpenStack\ObjectStore\v1\Models\Container
150
+     * @throws StorageAuthException
151
+     * @throws StorageNotAvailableException
152
+     */
153
+    public function getContainer() {
154
+        if (is_null($this->container)) {
155
+            $this->container = $this->createContainer();
156
+        }
157
+
158
+        return $this->container;
159
+    }
160
+
161
+    /**
162
+     * @return \OpenStack\ObjectStore\v1\Models\Container
163
+     * @throws StorageAuthException
164
+     * @throws StorageNotAvailableException
165
+     */
166
+    private function createContainer() {
167
+        $client = $this->getClient();
168
+        $objectStoreService = $client->objectStoreV1();
169
+
170
+        $autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true;
171
+        try {
172
+            $container = $objectStoreService->getContainer($this->params['container']);
173
+            if ($autoCreate) {
174
+                $container->getMetadata();
175
+            }
176
+            return $container;
177
+        } catch (BadResponseError $ex) {
178
+            // if the container does not exist and autocreate is true try to create the container on the fly
179
+            if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) {
180
+                return $objectStoreService->createContainer([
181
+                    'name' => $this->params['container']
182
+                ]);
183
+            } else {
184
+                throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $e);
185
+            }
186
+        } catch (ConnectException $e) {
187
+            /** @var RequestInterface $request */
188
+            $request = $e->getRequest();
189
+            $host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort();
190
+            \OC::$server->getLogger()->error("Can't connect to object storage server at $host");
191
+            throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e);
192
+        }
193
+    }
194 194
 }
Please login to merge, or discard this patch.
apps/files_external/lib/AppInfo/Application.php 1 patch
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -66,88 +66,88 @@
 block discarded – undo
66 66
  */
67 67
 class Application extends App implements IBackendProvider, IAuthMechanismProvider {
68 68
 
69
-	public function __construct(array $urlParams = array()) {
70
-		parent::__construct('files_external', $urlParams);
71
-
72
-		$container = $this->getContainer();
73
-
74
-		$container->registerService(IUserMountCache::class, function (IAppContainer $c) {
75
-			return $c->getServer()->query('UserMountCache');
76
-		});
77
-
78
-		$backendService = $container->query(BackendService::class);
79
-		$backendService->registerBackendProvider($this);
80
-		$backendService->registerAuthMechanismProvider($this);
81
-
82
-		// force-load auth mechanisms since some will register hooks
83
-		// TODO: obsolete these and use the TokenProvider to get the user's password from the session
84
-		$this->getAuthMechanisms();
85
-
86
-		// app developers: do NOT depend on this! it will disappear with oC 9.0!
87
-		\OC::$server->getEventDispatcher()->dispatch(
88
-			'OCA\\Files_External::loadAdditionalBackends'
89
-		);
90
-	}
91
-
92
-	/**
93
-	 * @{inheritdoc}
94
-	 */
95
-	public function getBackends() {
96
-		$container = $this->getContainer();
97
-
98
-		$backends = [
99
-			$container->query(Local::class),
100
-			$container->query(FTP::class),
101
-			$container->query(DAV::class),
102
-			$container->query(OwnCloud::class),
103
-			$container->query(SFTP::class),
104
-			$container->query(AmazonS3::class),
105
-			$container->query(Swift::class),
106
-			$container->query(SFTP_Key::class),
107
-			$container->query(SMB::class),
108
-			$container->query(SMB_OC::class),
109
-		];
110
-
111
-		return $backends;
112
-	}
113
-
114
-	/**
115
-	 * @{inheritdoc}
116
-	 */
117
-	public function getAuthMechanisms() {
118
-		$container = $this->getContainer();
119
-
120
-		return [
121
-			// AuthMechanism::SCHEME_NULL mechanism
122
-			$container->query(NullMechanism::class),
123
-
124
-			// AuthMechanism::SCHEME_BUILTIN mechanism
125
-			$container->query(Builtin::class),
126
-
127
-			// AuthMechanism::SCHEME_PASSWORD mechanisms
128
-			$container->query(Password::class),
129
-			$container->query(SessionCredentials::class),
130
-			$container->query(LoginCredentials::class),
131
-			$container->query(UserProvided::class),
132
-			$container->query(GlobalAuth::class),
133
-
134
-			// AuthMechanism::SCHEME_OAUTH1 mechanisms
135
-			$container->query(OAuth1::class),
136
-
137
-			// AuthMechanism::SCHEME_OAUTH2 mechanisms
138
-			$container->query(OAuth2::class),
139
-
140
-			// AuthMechanism::SCHEME_PUBLICKEY mechanisms
141
-			$container->query(RSA::class),
142
-
143
-			// AuthMechanism::SCHEME_OPENSTACK mechanisms
144
-			$container->query(OpenStackV2::class),
145
-			$container->query(OpenStackV3::class),
146
-			$container->query(Rackspace::class),
147
-
148
-			// Specialized mechanisms
149
-			$container->query(AccessKey::class),
150
-		];
151
-	}
69
+    public function __construct(array $urlParams = array()) {
70
+        parent::__construct('files_external', $urlParams);
71
+
72
+        $container = $this->getContainer();
73
+
74
+        $container->registerService(IUserMountCache::class, function (IAppContainer $c) {
75
+            return $c->getServer()->query('UserMountCache');
76
+        });
77
+
78
+        $backendService = $container->query(BackendService::class);
79
+        $backendService->registerBackendProvider($this);
80
+        $backendService->registerAuthMechanismProvider($this);
81
+
82
+        // force-load auth mechanisms since some will register hooks
83
+        // TODO: obsolete these and use the TokenProvider to get the user's password from the session
84
+        $this->getAuthMechanisms();
85
+
86
+        // app developers: do NOT depend on this! it will disappear with oC 9.0!
87
+        \OC::$server->getEventDispatcher()->dispatch(
88
+            'OCA\\Files_External::loadAdditionalBackends'
89
+        );
90
+    }
91
+
92
+    /**
93
+     * @{inheritdoc}
94
+     */
95
+    public function getBackends() {
96
+        $container = $this->getContainer();
97
+
98
+        $backends = [
99
+            $container->query(Local::class),
100
+            $container->query(FTP::class),
101
+            $container->query(DAV::class),
102
+            $container->query(OwnCloud::class),
103
+            $container->query(SFTP::class),
104
+            $container->query(AmazonS3::class),
105
+            $container->query(Swift::class),
106
+            $container->query(SFTP_Key::class),
107
+            $container->query(SMB::class),
108
+            $container->query(SMB_OC::class),
109
+        ];
110
+
111
+        return $backends;
112
+    }
113
+
114
+    /**
115
+     * @{inheritdoc}
116
+     */
117
+    public function getAuthMechanisms() {
118
+        $container = $this->getContainer();
119
+
120
+        return [
121
+            // AuthMechanism::SCHEME_NULL mechanism
122
+            $container->query(NullMechanism::class),
123
+
124
+            // AuthMechanism::SCHEME_BUILTIN mechanism
125
+            $container->query(Builtin::class),
126
+
127
+            // AuthMechanism::SCHEME_PASSWORD mechanisms
128
+            $container->query(Password::class),
129
+            $container->query(SessionCredentials::class),
130
+            $container->query(LoginCredentials::class),
131
+            $container->query(UserProvided::class),
132
+            $container->query(GlobalAuth::class),
133
+
134
+            // AuthMechanism::SCHEME_OAUTH1 mechanisms
135
+            $container->query(OAuth1::class),
136
+
137
+            // AuthMechanism::SCHEME_OAUTH2 mechanisms
138
+            $container->query(OAuth2::class),
139
+
140
+            // AuthMechanism::SCHEME_PUBLICKEY mechanisms
141
+            $container->query(RSA::class),
142
+
143
+            // AuthMechanism::SCHEME_OPENSTACK mechanisms
144
+            $container->query(OpenStackV2::class),
145
+            $container->query(OpenStackV3::class),
146
+            $container->query(Rackspace::class),
147
+
148
+            // Specialized mechanisms
149
+            $container->query(AccessKey::class),
150
+        ];
151
+    }
152 152
 
153 153
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Auth/OpenStack/OpenStackV2.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -31,19 +31,19 @@
 block discarded – undo
31 31
  */
32 32
 class OpenStackV2 extends AuthMechanism {
33 33
 
34
-	public function __construct(IL10N $l) {
35
-		$this
36
-			->setIdentifier('openstack::openstack')
37
-			->setScheme(self::SCHEME_OPENSTACK)
38
-			->setText($l->t('OpenStack v2'))
39
-			->addParameters([
40
-				new DefinitionParameter('user', $l->t('Username')),
41
-				(new DefinitionParameter('password', $l->t('Password')))
42
-					->setType(DefinitionParameter::VALUE_PASSWORD),
43
-				new DefinitionParameter('tenant', $l->t('Tenant name')),
44
-				new DefinitionParameter('url', $l->t('Identity endpoint URL')),
45
-			])
46
-		;
47
-	}
34
+    public function __construct(IL10N $l) {
35
+        $this
36
+            ->setIdentifier('openstack::openstack')
37
+            ->setScheme(self::SCHEME_OPENSTACK)
38
+            ->setText($l->t('OpenStack v2'))
39
+            ->addParameters([
40
+                new DefinitionParameter('user', $l->t('Username')),
41
+                (new DefinitionParameter('password', $l->t('Password')))
42
+                    ->setType(DefinitionParameter::VALUE_PASSWORD),
43
+                new DefinitionParameter('tenant', $l->t('Tenant name')),
44
+                new DefinitionParameter('url', $l->t('Identity endpoint URL')),
45
+            ])
46
+        ;
47
+    }
48 48
 
49 49
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Auth/OpenStack/OpenStackV3.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@
 block discarded – undo
1 1
 <?php
2
-declare(strict_types=1);
2
+declare(strict_types = 1);
3 3
 /**
4 4
  * @copyright Copyright (c) 2018 Robin Appelman <[email protected]>
5 5
  *
Please login to merge, or discard this patch.
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -31,19 +31,19 @@
 block discarded – undo
31 31
  */
32 32
 class OpenStackV3 extends AuthMechanism {
33 33
 
34
-	public function __construct(IL10N $l) {
35
-		$this
36
-			->setIdentifier('openstack::openstackv3')
37
-			->setScheme(self::SCHEME_OPENSTACK)
38
-			->setText($l->t('OpenStack v3'))
39
-			->addParameters([
40
-				new DefinitionParameter('user', $l->t('Username')),
41
-				new DefinitionParameter('domain', $l->t('Domain')),
42
-				(new DefinitionParameter('password', $l->t('Password')))
43
-					->setType(DefinitionParameter::VALUE_PASSWORD),
44
-				new DefinitionParameter('url', $l->t('Identity endpoint URL'))
45
-			])
46
-		;
47
-	}
34
+    public function __construct(IL10N $l) {
35
+        $this
36
+            ->setIdentifier('openstack::openstackv3')
37
+            ->setScheme(self::SCHEME_OPENSTACK)
38
+            ->setText($l->t('OpenStack v3'))
39
+            ->addParameters([
40
+                new DefinitionParameter('user', $l->t('Username')),
41
+                new DefinitionParameter('domain', $l->t('Domain')),
42
+                (new DefinitionParameter('password', $l->t('Password')))
43
+                    ->setType(DefinitionParameter::VALUE_PASSWORD),
44
+                new DefinitionParameter('url', $l->t('Identity endpoint URL'))
45
+            ])
46
+        ;
47
+    }
48 48
 
49 49
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Backend/Swift.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -33,31 +33,31 @@
 block discarded – undo
33 33
 
34 34
 class Swift extends Backend {
35 35
 
36
-	use LegacyDependencyCheckPolyfill;
36
+    use LegacyDependencyCheckPolyfill;
37 37
 
38
-	public function __construct(IL10N $l, OpenStackV2 $openstackAuth, Rackspace $rackspaceAuth) {
39
-		$this
40
-			->setIdentifier('swift')
41
-			->addIdentifierAlias('\OC\Files\Storage\Swift') // legacy compat
42
-			->setStorageClass('\OCA\Files_External\Lib\Storage\Swift')
43
-			->setText($l->t('OpenStack Object Storage'))
44
-			->addParameters([
45
-				(new DefinitionParameter('service_name', $l->t('Service name')))
46
-					->setFlag(DefinitionParameter::FLAG_OPTIONAL),
47
-				(new DefinitionParameter('region', $l->t('Region')))
48
-					->setFlag(DefinitionParameter::FLAG_OPTIONAL),
49
-				new DefinitionParameter('bucket', $l->t('Bucket')),
50
-				(new DefinitionParameter('timeout', $l->t('Request timeout (seconds)')))
51
-					->setFlag(DefinitionParameter::FLAG_OPTIONAL),
52
-			])
53
-			->addAuthScheme(AuthMechanism::SCHEME_OPENSTACK)
54
-			->setLegacyAuthMechanismCallback(function(array $params) use ($openstackAuth, $rackspaceAuth) {
55
-				if (isset($params['options']['key']) && $params['options']['key']) {
56
-					return $rackspaceAuth;
57
-				}
58
-				return $openstackAuth;
59
-			})
60
-		;
61
-	}
38
+    public function __construct(IL10N $l, OpenStackV2 $openstackAuth, Rackspace $rackspaceAuth) {
39
+        $this
40
+            ->setIdentifier('swift')
41
+            ->addIdentifierAlias('\OC\Files\Storage\Swift') // legacy compat
42
+            ->setStorageClass('\OCA\Files_External\Lib\Storage\Swift')
43
+            ->setText($l->t('OpenStack Object Storage'))
44
+            ->addParameters([
45
+                (new DefinitionParameter('service_name', $l->t('Service name')))
46
+                    ->setFlag(DefinitionParameter::FLAG_OPTIONAL),
47
+                (new DefinitionParameter('region', $l->t('Region')))
48
+                    ->setFlag(DefinitionParameter::FLAG_OPTIONAL),
49
+                new DefinitionParameter('bucket', $l->t('Bucket')),
50
+                (new DefinitionParameter('timeout', $l->t('Request timeout (seconds)')))
51
+                    ->setFlag(DefinitionParameter::FLAG_OPTIONAL),
52
+            ])
53
+            ->addAuthScheme(AuthMechanism::SCHEME_OPENSTACK)
54
+            ->setLegacyAuthMechanismCallback(function(array $params) use ($openstackAuth, $rackspaceAuth) {
55
+                if (isset($params['options']['key']) && $params['options']['key']) {
56
+                    return $rackspaceAuth;
57
+                }
58
+                return $openstackAuth;
59
+            })
60
+        ;
61
+    }
62 62
 
63 63
 }
Please login to merge, or discard this patch.
config/config.sample.php 1 patch
Indentation   +118 added lines, -118 removed lines patch added patch discarded remove patch
@@ -41,17 +41,17 @@  discard block
 block discarded – undo
41 41
  */
42 42
 'instanceid' => '',
43 43
 
44
- /**
45
-  * The salt used to hash all passwords, auto-generated by the Nextcloud
46
-  * installer. (There are also per-user salts.) If you lose this salt you lose
47
-  * all your passwords. This example is for documentation only, and you should
48
-  * never use it.
49
-  *
50
-  * @deprecated This salt is deprecated and only used for legacy-compatibility,
51
-  * developers should *NOT* use this value for anything nowadays.
52
-  *
53
-  * 'passwordsalt' => 'd3c944a9af095aa08f',
54
- */
44
+    /**
45
+     * The salt used to hash all passwords, auto-generated by the Nextcloud
46
+     * installer. (There are also per-user salts.) If you lose this salt you lose
47
+     * all your passwords. This example is for documentation only, and you should
48
+     * never use it.
49
+     *
50
+     * @deprecated This salt is deprecated and only used for legacy-compatibility,
51
+     * developers should *NOT* use this value for anything nowadays.
52
+     *
53
+     * 'passwordsalt' => 'd3c944a9af095aa08f',
54
+     */
55 55
 'passwordsalt' => '',
56 56
 
57 57
 /**
@@ -67,10 +67,10 @@  discard block
 block discarded – undo
67 67
  *   ubos-raspberry-pi.local and ubos-raspberry-pi-2.local
68 68
  */
69 69
 'trusted_domains' =>
70
-  array (
70
+    array (
71 71
     'demo.example.org',
72 72
     'otherdomain.example.org',
73
-  ),
73
+    ),
74 74
 
75 75
 
76 76
 /**
@@ -260,10 +260,10 @@  discard block
 block discarded – undo
260 260
  * IMAP (OC_User_IMAP), SMB (OC_User_SMB), and FTP (OC_User_FTP).
261 261
  */
262 262
 'user_backends' => array(
263
-	array(
264
-		'class' => 'OC_User_IMAP',
265
-		'arguments' => array('{imap.gmail.com:993/imap/ssl}INBOX')
266
-	)
263
+    array(
264
+        'class' => 'OC_User_IMAP',
265
+        'arguments' => array('{imap.gmail.com:993/imap/ssl}INBOX')
266
+    )
267 267
 ),
268 268
 
269 269
 /**
@@ -730,9 +730,9 @@  discard block
 block discarded – undo
730 730
  * Defaults to an empty array.
731 731
  */
732 732
 'log.condition' => [
733
-	'shared_secret' => '57b58edb6637fe3059b3595cf9c41b9',
734
-	'users' => ['sample-user'],
735
-	'apps' => ['files'],
733
+    'shared_secret' => '57b58edb6637fe3059b3595cf9c41b9',
734
+    'users' => ['sample-user'],
735
+    'apps' => ['files'],
736 736
 ],
737 737
 
738 738
 /**
@@ -785,11 +785,11 @@  discard block
 block discarded – undo
785 785
  * * iOS client    : ``https://itunes.apple.com/us/app/nextcloud/id1125420102?mt=8``
786 786
  */
787 787
 'customclient_desktop' =>
788
-	'https://nextcloud.com/install/#install-clients',
788
+    'https://nextcloud.com/install/#install-clients',
789 789
 'customclient_android' =>
790
-	'https://play.google.com/store/apps/details?id=com.nextcloud.client',
790
+    'https://play.google.com/store/apps/details?id=com.nextcloud.client',
791 791
 'customclient_ios' =>
792
-	'https://itunes.apple.com/us/app/nextcloud/id1125420102?mt=8',
792
+    'https://itunes.apple.com/us/app/nextcloud/id1125420102?mt=8',
793 793
 
794 794
 /**
795 795
  * Apps
@@ -813,11 +813,11 @@  discard block
 block discarded – undo
813 813
  * indicates if a Web server can write files to that folder.
814 814
  */
815 815
 'apps_paths' => array(
816
-	array(
817
-		'path'=> '/var/www/nextcloud/apps',
818
-		'url' => '/apps',
819
-		'writable' => true,
820
-	),
816
+    array(
817
+        'path'=> '/var/www/nextcloud/apps',
818
+        'url' => '/apps',
819
+        'writable' => true,
820
+    ),
821 821
 ),
822 822
 
823 823
 /**
@@ -882,8 +882,8 @@  discard block
 block discarded – undo
882 882
  * Defaults to ``''`` (empty string)
883 883
  */
884 884
 'preview_office_cl_parameters' =>
885
-	' --headless --nologo --nofirststartwizard --invisible --norestore '.
886
-	'--convert-to pdf --outdir ',
885
+    ' --headless --nologo --nofirststartwizard --invisible --norestore '.
886
+    '--convert-to pdf --outdir ',
887 887
 
888 888
 /**
889 889
  * Only register providers that have been explicitly enabled
@@ -926,14 +926,14 @@  discard block
 block discarded – undo
926 926
  *  - OC\Preview\XBitmap
927 927
  */
928 928
 'enabledPreviewProviders' => array(
929
-	'OC\Preview\PNG',
930
-	'OC\Preview\JPEG',
931
-	'OC\Preview\GIF',
932
-	'OC\Preview\BMP',
933
-	'OC\Preview\XBitmap',
934
-	'OC\Preview\MP3',
935
-	'OC\Preview\TXT',
936
-	'OC\Preview\MarkDown'
929
+    'OC\Preview\PNG',
930
+    'OC\Preview\JPEG',
931
+    'OC\Preview\GIF',
932
+    'OC\Preview\BMP',
933
+    'OC\Preview\XBitmap',
934
+    'OC\Preview\MP3',
935
+    'OC\Preview\TXT',
936
+    'OC\Preview\MarkDown'
937 937
 ),
938 938
 
939 939
 /**
@@ -1016,11 +1016,11 @@  discard block
 block discarded – undo
1016 1016
 
1017 1017
 /**
1018 1018
  * Extra SSL options to be used for configuration.
1019
-  *
1019
+ *
1020 1020
  * Defaults to an empty array.
1021 1021
  */
1022 1022
 'openssl' => array(
1023
-	'config' => '/absolute/location/of/openssl.cnf',
1023
+    'config' => '/absolute/location/of/openssl.cnf',
1024 1024
 ),
1025 1025
 
1026 1026
 /**
@@ -1069,11 +1069,11 @@  discard block
 block discarded – undo
1069 1069
  * for more information.
1070 1070
  */
1071 1071
 'redis' => [
1072
-	'host' => 'localhost', // can also be a unix domain socket: '/tmp/redis.sock'
1073
-	'port' => 6379,
1074
-	'timeout' => 0.0,
1075
-	'password' => '', // Optional, if not defined no password will be used.
1076
-	'dbindex' => 0, // Optional, if undefined SELECT will not run and will use Redis Server's default DB Index.
1072
+    'host' => 'localhost', // can also be a unix domain socket: '/tmp/redis.sock'
1073
+    'port' => 6379,
1074
+    'timeout' => 0.0,
1075
+    'password' => '', // Optional, if not defined no password will be used.
1076
+    'dbindex' => 0, // Optional, if undefined SELECT will not run and will use Redis Server's default DB Index.
1077 1077
 ],
1078 1078
 
1079 1079
 /**
@@ -1099,13 +1099,13 @@  discard block
 block discarded – undo
1099 1099
  * See https://redis.io/topics/cluster-spec for details about the Redis cluster
1100 1100
  */
1101 1101
 'redis.cluster' => [
1102
-	'seeds' => [ // provide some/all of the cluster servers to bootstrap discovery, port required
1103
-		'localhost:7000',
1104
-		'localhost:7001'
1105
-	],
1106
-	'timeout' => 0.0,
1107
-	'read_timeout' => 0.0,
1108
-	'failover_mode' => \RedisCluster::FAILOVER_ERROR
1102
+    'seeds' => [ // provide some/all of the cluster servers to bootstrap discovery, port required
1103
+        'localhost:7000',
1104
+        'localhost:7001'
1105
+    ],
1106
+    'timeout' => 0.0,
1107
+    'read_timeout' => 0.0,
1108
+    'failover_mode' => \RedisCluster::FAILOVER_ERROR
1109 1109
 ],
1110 1110
 
1111 1111
 
@@ -1113,35 +1113,35 @@  discard block
 block discarded – undo
1113 1113
  * Server details for one or more memcached servers to use for memory caching.
1114 1114
  */
1115 1115
 'memcached_servers' => array(
1116
-	// hostname, port and optional weight. Also see:
1117
-	// http://www.php.net/manual/en/memcached.addservers.php
1118
-	// http://www.php.net/manual/en/memcached.addserver.php
1119
-	array('localhost', 11211),
1120
-	//array('other.host.local', 11211),
1116
+    // hostname, port and optional weight. Also see:
1117
+    // http://www.php.net/manual/en/memcached.addservers.php
1118
+    // http://www.php.net/manual/en/memcached.addserver.php
1119
+    array('localhost', 11211),
1120
+    //array('other.host.local', 11211),
1121 1121
 ),
1122 1122
 
1123 1123
 /**
1124 1124
  * Connection options for memcached, see http://apprize.info/php/scaling/15.html
1125 1125
  */
1126 1126
 'memcached_options' => array(
1127
-	// Set timeouts to 50ms
1128
-	\Memcached::OPT_CONNECT_TIMEOUT => 50,
1129
-	\Memcached::OPT_RETRY_TIMEOUT =>   50,
1130
-	\Memcached::OPT_SEND_TIMEOUT =>    50,
1131
-	\Memcached::OPT_RECV_TIMEOUT =>    50,
1132
-	\Memcached::OPT_POLL_TIMEOUT =>    50,
1127
+    // Set timeouts to 50ms
1128
+    \Memcached::OPT_CONNECT_TIMEOUT => 50,
1129
+    \Memcached::OPT_RETRY_TIMEOUT =>   50,
1130
+    \Memcached::OPT_SEND_TIMEOUT =>    50,
1131
+    \Memcached::OPT_RECV_TIMEOUT =>    50,
1132
+    \Memcached::OPT_POLL_TIMEOUT =>    50,
1133 1133
 
1134
-	// Enable compression
1135
-	\Memcached::OPT_COMPRESSION =>          true,
1134
+    // Enable compression
1135
+    \Memcached::OPT_COMPRESSION =>          true,
1136 1136
 
1137
-	// Turn on consistent hashing
1138
-	\Memcached::OPT_LIBKETAMA_COMPATIBLE => true,
1137
+    // Turn on consistent hashing
1138
+    \Memcached::OPT_LIBKETAMA_COMPATIBLE => true,
1139 1139
 
1140
-	// Enable Binary Protocol
1141
-	\Memcached::OPT_BINARY_PROTOCOL =>      true,
1140
+    // Enable Binary Protocol
1141
+    \Memcached::OPT_BINARY_PROTOCOL =>      true,
1142 1142
 
1143
-	// Binary serializer vill be enabled if the igbinary PECL module is available
1144
-	//\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_IGBINARY,
1143
+    // Binary serializer vill be enabled if the igbinary PECL module is available
1144
+    //\Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_IGBINARY,
1145 1145
 ),
1146 1146
 
1147 1147
 
@@ -1187,53 +1187,53 @@  discard block
 block discarded – undo
1187 1187
  * One way to test is applying for a trystack account at http://trystack.org/
1188 1188
  */
1189 1189
 'objectstore' => [
1190
-	'class' => 'OC\\Files\\ObjectStore\\Swift',
1191
-	'arguments' => [
1192
-		// trystack will use your facebook id as the user name
1193
-		'username' => 'facebook100000123456789',
1194
-		// in the trystack dashboard go to user -> settings -> API Password to
1195
-		// generate a password
1196
-		'password' => 'Secr3tPaSSWoRdt7',
1197
-		// must already exist in the objectstore, name can be different
1198
-		'container' => 'nextcloud',
1199
-		// prefix to prepend to the fileid, default is 'oid:urn:'
1200
-		'objectPrefix' => 'oid:urn:',
1201
-		// create the container if it does not exist. default is false
1202
-		'autocreate' => true,
1203
-		// required, dev-/trystack defaults to 'RegionOne'
1204
-		'region' => 'RegionOne',
1205
-		// The Identity / Keystone endpoint
1206
-		'url' => 'http://8.21.28.222:5000/v2.0',
1207
-		// required on dev-/trystack
1208
-		'tenantName' => 'facebook100000123456789',
1209
-		// dev-/trystack uses swift by default, the lib defaults to 'cloudFiles'
1210
-		// if omitted
1211
-		'serviceName' => 'swift',
1212
-		// The Interface / url Type, optional
1213
-		'urlType' => 'internal'
1214
-	],
1190
+    'class' => 'OC\\Files\\ObjectStore\\Swift',
1191
+    'arguments' => [
1192
+        // trystack will use your facebook id as the user name
1193
+        'username' => 'facebook100000123456789',
1194
+        // in the trystack dashboard go to user -> settings -> API Password to
1195
+        // generate a password
1196
+        'password' => 'Secr3tPaSSWoRdt7',
1197
+        // must already exist in the objectstore, name can be different
1198
+        'container' => 'nextcloud',
1199
+        // prefix to prepend to the fileid, default is 'oid:urn:'
1200
+        'objectPrefix' => 'oid:urn:',
1201
+        // create the container if it does not exist. default is false
1202
+        'autocreate' => true,
1203
+        // required, dev-/trystack defaults to 'RegionOne'
1204
+        'region' => 'RegionOne',
1205
+        // The Identity / Keystone endpoint
1206
+        'url' => 'http://8.21.28.222:5000/v2.0',
1207
+        // required on dev-/trystack
1208
+        'tenantName' => 'facebook100000123456789',
1209
+        // dev-/trystack uses swift by default, the lib defaults to 'cloudFiles'
1210
+        // if omitted
1211
+        'serviceName' => 'swift',
1212
+        // The Interface / url Type, optional
1213
+        'urlType' => 'internal'
1214
+    ],
1215 1215
 ],
1216 1216
 
1217 1217
 /**
1218 1218
  * To use swift V3
1219 1219
  */
1220 1220
 'objectstore' => [
1221
-	'class' => 'OC\\Files\\ObjectStore\\Swift',
1222
-	'arguments' => [
1223
-		'autocreate' => true,
1224
-		'user' => [
1225
-			'name' => 'swift',
1226
-			'password' => 'swift',
1227
-			'domain' => [
1228
-				'name' => 'default',
1229
-			]
1230
-		],
1231
-		'tenantName' => 'service',
1232
-		'serviceName' => 'swift',
1233
-		'region' => 'regionOne',
1234
-		'url' => "http://yourswifthost:5000/v3",
1235
-		'bucket' => 'nextcloud'
1236
-	],
1221
+    'class' => 'OC\\Files\\ObjectStore\\Swift',
1222
+    'arguments' => [
1223
+        'autocreate' => true,
1224
+        'user' => [
1225
+            'name' => 'swift',
1226
+            'password' => 'swift',
1227
+            'domain' => [
1228
+                'name' => 'default',
1229
+            ]
1230
+        ],
1231
+        'tenantName' => 'service',
1232
+        'serviceName' => 'swift',
1233
+        'region' => 'regionOne',
1234
+        'url' => "http://yourswifthost:5000/v3",
1235
+        'bucket' => 'nextcloud'
1236
+    ],
1237 1237
 ],
1238 1238
 
1239 1239
 
@@ -1273,8 +1273,8 @@  discard block
 block discarded – undo
1273 1273
  * encryption in MySQL or specify a custom wait timeout on a cheap hoster.
1274 1274
  */
1275 1275
 'dbdriveroptions' => array(
1276
-	PDO::MYSQL_ATTR_SSL_CA => '/file/path/to/ca_cert.pem',
1277
-	PDO::MYSQL_ATTR_INIT_COMMAND => 'SET wait_timeout = 28800'
1276
+    PDO::MYSQL_ATTR_SSL_CA => '/file/path/to/ca_cert.pem',
1277
+    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET wait_timeout = 28800'
1278 1278
 ),
1279 1279
 
1280 1280
 /**
@@ -1331,10 +1331,10 @@  discard block
 block discarded – undo
1331 1331
  *  - pgsql (PostgreSQL)
1332 1332
  */
1333 1333
 'supportedDatabases' => array(
1334
-	'sqlite',
1335
-	'mysql',
1336
-	'pgsql',
1337
-	'oci',
1334
+    'sqlite',
1335
+    'mysql',
1336
+    'pgsql',
1337
+    'oci',
1338 1338
 ),
1339 1339
 
1340 1340
 /**
Please login to merge, or discard this patch.
apps/files_external/lib/Lib/Storage/Swift.php 2 patches
Indentation   +565 added lines, -565 removed lines patch added patch discarded remove patch
@@ -49,573 +49,573 @@
 block discarded – undo
49 49
 use OpenStack\ObjectStore\v1\Models\StorageObject;
50 50
 
51 51
 class Swift extends \OC\Files\Storage\Common {
52
-	/** @var SwiftFactory */
53
-	private $connectionFactory;
54
-	/**
55
-	 * @var \OpenStack\ObjectStore\v1\Models\Container
56
-	 */
57
-	private $container;
58
-	/**
59
-	 * @var string
60
-	 */
61
-	private $bucket;
62
-	/**
63
-	 * Connection parameters
64
-	 *
65
-	 * @var array
66
-	 */
67
-	private $params;
68
-
69
-	/** @var string */
70
-	private $id;
71
-
72
-	/** @var \OC\Files\ObjectStore\Swift */
73
-	private $objectStore;
74
-
75
-	/**
76
-	 * Key value cache mapping path to data object. Maps path to
77
-	 * \OpenCloud\OpenStack\ObjectStorage\Resource\DataObject for existing
78
-	 * paths and path to false for not existing paths.
79
-	 *
80
-	 * @var \OCP\ICache
81
-	 */
82
-	private $objectCache;
83
-
84
-	/**
85
-	 * @param string $path
86
-	 * @return mixed|string
87
-	 */
88
-	private function normalizePath(string $path) {
89
-		$path = trim($path, '/');
90
-
91
-		if (!$path) {
92
-			$path = '.';
93
-		}
94
-
95
-		$path = str_replace('#', '%23', $path);
96
-
97
-		return $path;
98
-	}
99
-
100
-	const SUBCONTAINER_FILE = '.subcontainers';
101
-
102
-	/**
103
-	 * translate directory path to container name
104
-	 *
105
-	 * @param string $path
106
-	 * @return string
107
-	 */
108
-
109
-	/**
110
-	 * Fetches an object from the API.
111
-	 * If the object is cached already or a
112
-	 * failed "doesn't exist" response was cached,
113
-	 * that one will be returned.
114
-	 *
115
-	 * @param string $path
116
-	 * @return StorageObject|bool object
117
-	 * or false if the object did not exist
118
-	 * @throws \OCP\Files\StorageAuthException
119
-	 * @throws \OCP\Files\StorageNotAvailableException
120
-	 */
121
-	private function fetchObject(string $path) {
122
-		if ($this->objectCache->hasKey($path)) {
123
-			// might be "false" if object did not exist from last check
124
-			return $this->objectCache->get($path);
125
-		}
126
-		try {
127
-			$object = $this->getContainer()->getObject($path);
128
-			$object->retrieve();
129
-			$this->objectCache->set($path, $object);
130
-			return $object;
131
-		} catch (BadResponseError $e) {
132
-			// Expected response is "404 Not Found", so only log if it isn't
133
-			if ($e->getResponse()->getStatusCode() !== 404) {
134
-				\OC::$server->getLogger()->logException($e, [
135
-					'level' => \OCP\Util::ERROR,
136
-					'app' => 'files_external',
137
-				]);
138
-			}
139
-			$this->objectCache->set($path, false);
140
-			return false;
141
-		}
142
-	}
143
-
144
-	/**
145
-	 * Returns whether the given path exists.
146
-	 *
147
-	 * @param string $path
148
-	 *
149
-	 * @return bool true if the object exist, false otherwise
150
-	 * @throws \OCP\Files\StorageAuthException
151
-	 * @throws \OCP\Files\StorageNotAvailableException
152
-	 */
153
-	private function doesObjectExist($path) {
154
-		return $this->fetchObject($path) !== false;
155
-	}
156
-
157
-	public function __construct($params) {
158
-		if ((empty($params['key']) and empty($params['password']))
159
-			or (empty($params['user']) && empty($params['userid'])) or empty($params['bucket'])
160
-			or empty($params['region'])
161
-		) {
162
-			throw new StorageBadConfigException("API Key or password, Username, Bucket and Region have to be configured.");
163
-		}
164
-
165
-		$user = $params['user'];
166
-		$this->id = 'swift::' . $user . md5($params['bucket']);
167
-
168
-		$bucketUrl = new Uri($params['bucket']);
169
-		if ($bucketUrl->getHost()) {
170
-			$params['bucket'] = basename($bucketUrl->getPath());
171
-			$params['endpoint_url'] = (string)$bucketUrl->withPath(dirname($bucketUrl->getPath()));
172
-		}
173
-
174
-		if (empty($params['url'])) {
175
-			$params['url'] = 'https://identity.api.rackspacecloud.com/v2.0/';
176
-		}
177
-
178
-		if (empty($params['service_name'])) {
179
-			$params['service_name'] = 'cloudFiles';
180
-		}
181
-
182
-		$params['autocreate'] = true;
183
-
184
-		if (isset($params['domain'])) {
185
-			$params['user'] = [
186
-				'name' => $params['user'],
187
-				'password' => $params['password'],
188
-				'domain' => [
189
-					'name' => $params['domain'],
190
-				]
191
-			];
192
-		}
193
-
194
-		$this->params = $params;
195
-		// FIXME: private class...
196
-		$this->objectCache = new \OC\Cache\CappedMemoryCache();
197
-		$this->connectionFactory = new SwiftFactory(\OC::$server->getMemCacheFactory()->createDistributed('swift/'), $this->params);
198
-		$this->objectStore = new \OC\Files\ObjectStore\Swift($this->params, $this->connectionFactory);
199
-		$this->bucket = $params['bucket'];
200
-	}
201
-
202
-	public function mkdir($path) {
203
-		$path = $this->normalizePath($path);
204
-
205
-		if ($this->is_dir($path)) {
206
-			return false;
207
-		}
208
-
209
-		if ($path !== '.') {
210
-			$path .= '/';
211
-		}
212
-
213
-		try {
214
-			$this->getContainer()->createObject([
215
-				'name' => $path,
216
-				'content' => '',
217
-				'headers' => ['content-type' => 'httpd/unix-directory']
218
-			]);
219
-			// invalidate so that the next access gets the real object
220
-			// with all properties
221
-			$this->objectCache->remove($path);
222
-		} catch (BadResponseError $e) {
223
-			\OC::$server->getLogger()->logException($e, [
224
-				'level' => \OCP\Util::ERROR,
225
-				'app' => 'files_external',
226
-			]);
227
-			return false;
228
-		}
229
-
230
-		return true;
231
-	}
232
-
233
-	public function file_exists($path) {
234
-		$path = $this->normalizePath($path);
235
-
236
-		if ($path !== '.' && $this->is_dir($path)) {
237
-			$path .= '/';
238
-		}
239
-
240
-		return $this->doesObjectExist($path);
241
-	}
242
-
243
-	public function rmdir($path) {
244
-		$path = $this->normalizePath($path);
245
-
246
-		if (!$this->is_dir($path) || !$this->isDeletable($path)) {
247
-			return false;
248
-		}
249
-
250
-		$dh = $this->opendir($path);
251
-		while ($file = readdir($dh)) {
252
-			if (\OC\Files\Filesystem::isIgnoredDir($file)) {
253
-				continue;
254
-			}
255
-
256
-			if ($this->is_dir($path . '/' . $file)) {
257
-				$this->rmdir($path . '/' . $file);
258
-			} else {
259
-				$this->unlink($path . '/' . $file);
260
-			}
261
-		}
262
-
263
-		try {
264
-			$this->objectStore->deleteObject($path . '/');
265
-			$this->objectCache->remove($path . '/');
266
-		} catch (BadResponseError $e) {
267
-			\OC::$server->getLogger()->logException($e, [
268
-				'level' => \OCP\Util::ERROR,
269
-				'app' => 'files_external',
270
-			]);
271
-			return false;
272
-		}
273
-
274
-		return true;
275
-	}
276
-
277
-	public function opendir($path) {
278
-		$path = $this->normalizePath($path);
279
-
280
-		if ($path === '.') {
281
-			$path = '';
282
-		} else {
283
-			$path .= '/';
284
-		}
52
+    /** @var SwiftFactory */
53
+    private $connectionFactory;
54
+    /**
55
+     * @var \OpenStack\ObjectStore\v1\Models\Container
56
+     */
57
+    private $container;
58
+    /**
59
+     * @var string
60
+     */
61
+    private $bucket;
62
+    /**
63
+     * Connection parameters
64
+     *
65
+     * @var array
66
+     */
67
+    private $params;
68
+
69
+    /** @var string */
70
+    private $id;
71
+
72
+    /** @var \OC\Files\ObjectStore\Swift */
73
+    private $objectStore;
74
+
75
+    /**
76
+     * Key value cache mapping path to data object. Maps path to
77
+     * \OpenCloud\OpenStack\ObjectStorage\Resource\DataObject for existing
78
+     * paths and path to false for not existing paths.
79
+     *
80
+     * @var \OCP\ICache
81
+     */
82
+    private $objectCache;
83
+
84
+    /**
85
+     * @param string $path
86
+     * @return mixed|string
87
+     */
88
+    private function normalizePath(string $path) {
89
+        $path = trim($path, '/');
90
+
91
+        if (!$path) {
92
+            $path = '.';
93
+        }
94
+
95
+        $path = str_replace('#', '%23', $path);
96
+
97
+        return $path;
98
+    }
99
+
100
+    const SUBCONTAINER_FILE = '.subcontainers';
101
+
102
+    /**
103
+     * translate directory path to container name
104
+     *
105
+     * @param string $path
106
+     * @return string
107
+     */
108
+
109
+    /**
110
+     * Fetches an object from the API.
111
+     * If the object is cached already or a
112
+     * failed "doesn't exist" response was cached,
113
+     * that one will be returned.
114
+     *
115
+     * @param string $path
116
+     * @return StorageObject|bool object
117
+     * or false if the object did not exist
118
+     * @throws \OCP\Files\StorageAuthException
119
+     * @throws \OCP\Files\StorageNotAvailableException
120
+     */
121
+    private function fetchObject(string $path) {
122
+        if ($this->objectCache->hasKey($path)) {
123
+            // might be "false" if object did not exist from last check
124
+            return $this->objectCache->get($path);
125
+        }
126
+        try {
127
+            $object = $this->getContainer()->getObject($path);
128
+            $object->retrieve();
129
+            $this->objectCache->set($path, $object);
130
+            return $object;
131
+        } catch (BadResponseError $e) {
132
+            // Expected response is "404 Not Found", so only log if it isn't
133
+            if ($e->getResponse()->getStatusCode() !== 404) {
134
+                \OC::$server->getLogger()->logException($e, [
135
+                    'level' => \OCP\Util::ERROR,
136
+                    'app' => 'files_external',
137
+                ]);
138
+            }
139
+            $this->objectCache->set($path, false);
140
+            return false;
141
+        }
142
+    }
143
+
144
+    /**
145
+     * Returns whether the given path exists.
146
+     *
147
+     * @param string $path
148
+     *
149
+     * @return bool true if the object exist, false otherwise
150
+     * @throws \OCP\Files\StorageAuthException
151
+     * @throws \OCP\Files\StorageNotAvailableException
152
+     */
153
+    private function doesObjectExist($path) {
154
+        return $this->fetchObject($path) !== false;
155
+    }
156
+
157
+    public function __construct($params) {
158
+        if ((empty($params['key']) and empty($params['password']))
159
+            or (empty($params['user']) && empty($params['userid'])) or empty($params['bucket'])
160
+            or empty($params['region'])
161
+        ) {
162
+            throw new StorageBadConfigException("API Key or password, Username, Bucket and Region have to be configured.");
163
+        }
164
+
165
+        $user = $params['user'];
166
+        $this->id = 'swift::' . $user . md5($params['bucket']);
167
+
168
+        $bucketUrl = new Uri($params['bucket']);
169
+        if ($bucketUrl->getHost()) {
170
+            $params['bucket'] = basename($bucketUrl->getPath());
171
+            $params['endpoint_url'] = (string)$bucketUrl->withPath(dirname($bucketUrl->getPath()));
172
+        }
173
+
174
+        if (empty($params['url'])) {
175
+            $params['url'] = 'https://identity.api.rackspacecloud.com/v2.0/';
176
+        }
177
+
178
+        if (empty($params['service_name'])) {
179
+            $params['service_name'] = 'cloudFiles';
180
+        }
181
+
182
+        $params['autocreate'] = true;
183
+
184
+        if (isset($params['domain'])) {
185
+            $params['user'] = [
186
+                'name' => $params['user'],
187
+                'password' => $params['password'],
188
+                'domain' => [
189
+                    'name' => $params['domain'],
190
+                ]
191
+            ];
192
+        }
193
+
194
+        $this->params = $params;
195
+        // FIXME: private class...
196
+        $this->objectCache = new \OC\Cache\CappedMemoryCache();
197
+        $this->connectionFactory = new SwiftFactory(\OC::$server->getMemCacheFactory()->createDistributed('swift/'), $this->params);
198
+        $this->objectStore = new \OC\Files\ObjectStore\Swift($this->params, $this->connectionFactory);
199
+        $this->bucket = $params['bucket'];
200
+    }
201
+
202
+    public function mkdir($path) {
203
+        $path = $this->normalizePath($path);
204
+
205
+        if ($this->is_dir($path)) {
206
+            return false;
207
+        }
208
+
209
+        if ($path !== '.') {
210
+            $path .= '/';
211
+        }
212
+
213
+        try {
214
+            $this->getContainer()->createObject([
215
+                'name' => $path,
216
+                'content' => '',
217
+                'headers' => ['content-type' => 'httpd/unix-directory']
218
+            ]);
219
+            // invalidate so that the next access gets the real object
220
+            // with all properties
221
+            $this->objectCache->remove($path);
222
+        } catch (BadResponseError $e) {
223
+            \OC::$server->getLogger()->logException($e, [
224
+                'level' => \OCP\Util::ERROR,
225
+                'app' => 'files_external',
226
+            ]);
227
+            return false;
228
+        }
229
+
230
+        return true;
231
+    }
232
+
233
+    public function file_exists($path) {
234
+        $path = $this->normalizePath($path);
235
+
236
+        if ($path !== '.' && $this->is_dir($path)) {
237
+            $path .= '/';
238
+        }
239
+
240
+        return $this->doesObjectExist($path);
241
+    }
242
+
243
+    public function rmdir($path) {
244
+        $path = $this->normalizePath($path);
245
+
246
+        if (!$this->is_dir($path) || !$this->isDeletable($path)) {
247
+            return false;
248
+        }
249
+
250
+        $dh = $this->opendir($path);
251
+        while ($file = readdir($dh)) {
252
+            if (\OC\Files\Filesystem::isIgnoredDir($file)) {
253
+                continue;
254
+            }
255
+
256
+            if ($this->is_dir($path . '/' . $file)) {
257
+                $this->rmdir($path . '/' . $file);
258
+            } else {
259
+                $this->unlink($path . '/' . $file);
260
+            }
261
+        }
262
+
263
+        try {
264
+            $this->objectStore->deleteObject($path . '/');
265
+            $this->objectCache->remove($path . '/');
266
+        } catch (BadResponseError $e) {
267
+            \OC::$server->getLogger()->logException($e, [
268
+                'level' => \OCP\Util::ERROR,
269
+                'app' => 'files_external',
270
+            ]);
271
+            return false;
272
+        }
273
+
274
+        return true;
275
+    }
276
+
277
+    public function opendir($path) {
278
+        $path = $this->normalizePath($path);
279
+
280
+        if ($path === '.') {
281
+            $path = '';
282
+        } else {
283
+            $path .= '/';
284
+        }
285 285
 
286 286
 //		$path = str_replace('%23', '#', $path); // the prefix is sent as a query param, so revert the encoding of #
287 287
 
288
-		try {
289
-			$files = [];
290
-			$objects = $this->getContainer()->listObjects([
291
-				'prefix' => $path,
292
-				'delimiter' => '/'
293
-			]);
294
-
295
-			/** @var StorageObject $object */
296
-			foreach ($objects as $object) {
297
-				$file = basename($object->name);
298
-				if ($file !== basename($path) && $file !== '.') {
299
-					$files[] = $file;
300
-				}
301
-			}
302
-
303
-			return IteratorDirectory::wrap($files);
304
-		} catch (\Exception $e) {
305
-			\OC::$server->getLogger()->logException($e, [
306
-				'level' => \OCP\Util::ERROR,
307
-				'app' => 'files_external',
308
-			]);
309
-			return false;
310
-		}
311
-
312
-	}
313
-
314
-	public function stat($path) {
315
-		$path = $this->normalizePath($path);
316
-
317
-		if ($path === '.') {
318
-			$path = '';
319
-		} else if ($this->is_dir($path)) {
320
-			$path .= '/';
321
-		}
322
-
323
-		try {
324
-			$object = $this->fetchObject($path);
325
-			if (!$object) {
326
-				return false;
327
-			}
328
-		} catch (BadResponseError $e) {
329
-			\OC::$server->getLogger()->logException($e, [
330
-				'level' => \OCP\Util::ERROR,
331
-				'app' => 'files_external',
332
-			]);
333
-			return false;
334
-		}
335
-
336
-		$dateTime = $object->lastModified ? \DateTime::createFromFormat(\DateTime::RFC1123, $object->lastModified) : false;
337
-		$mtime = $dateTime ? $dateTime->getTimestamp() : null;
338
-		$objectMetadata = $object->getMetadata();
339
-		if (isset($objectMetadata['timestamp'])) {
340
-			$mtime = $objectMetadata['timestamp'];
341
-		}
342
-
343
-		if (!empty($mtime)) {
344
-			$mtime = floor($mtime);
345
-		}
346
-
347
-		$stat = array();
348
-		$stat['size'] = (int)$object->contentLength;
349
-		$stat['mtime'] = $mtime;
350
-		$stat['atime'] = time();
351
-		return $stat;
352
-	}
353
-
354
-	public function filetype($path) {
355
-		$path = $this->normalizePath($path);
356
-
357
-		if ($path !== '.' && $this->doesObjectExist($path)) {
358
-			return 'file';
359
-		}
360
-
361
-		if ($path !== '.') {
362
-			$path .= '/';
363
-		}
364
-
365
-		if ($this->doesObjectExist($path)) {
366
-			return 'dir';
367
-		}
368
-	}
369
-
370
-	public function unlink($path) {
371
-		$path = $this->normalizePath($path);
372
-
373
-		if ($this->is_dir($path)) {
374
-			return $this->rmdir($path);
375
-		}
376
-
377
-		try {
378
-			$this->objectStore->deleteObject($path);
379
-			$this->objectCache->remove($path);
380
-			$this->objectCache->remove($path . '/');
381
-		} catch (BadResponseError $e) {
382
-			if ($e->getResponse()->getStatusCode() !== 404) {
383
-				\OC::$server->getLogger()->logException($e, [
384
-					'level' => \OCP\Util::ERROR,
385
-					'app' => 'files_external',
386
-				]);
387
-				throw $e;
388
-			}
389
-		}
390
-
391
-		return true;
392
-	}
393
-
394
-	public function fopen($path, $mode) {
395
-		$path = $this->normalizePath($path);
396
-
397
-		switch ($mode) {
398
-			case 'a':
399
-			case 'ab':
400
-			case 'a+':
401
-				return false;
402
-			case 'r':
403
-			case 'rb':
404
-				try {
405
-					return $this->objectStore->readObject($path);
406
-				} catch (BadResponseError $e) {
407
-					\OC::$server->getLogger()->logException($e, [
408
-						'level' => \OCP\Util::ERROR,
409
-						'app' => 'files_external',
410
-					]);
411
-					return false;
412
-				}
413
-			case 'w':
414
-			case 'wb':
415
-			case 'r+':
416
-			case 'w+':
417
-			case 'wb+':
418
-			case 'x':
419
-			case 'x+':
420
-			case 'c':
421
-			case 'c+':
422
-				if (strrpos($path, '.') !== false) {
423
-					$ext = substr($path, strrpos($path, '.'));
424
-				} else {
425
-					$ext = '';
426
-				}
427
-				$tmpFile = \OCP\Files::tmpFile($ext);
428
-				// Fetch existing file if required
429
-				if ($mode[0] !== 'w' && $this->file_exists($path)) {
430
-					if ($mode[0] === 'x') {
431
-						// File cannot already exist
432
-						return false;
433
-					}
434
-					$source = $this->fopen($path, 'r');
435
-					file_put_contents($tmpFile, $source);
436
-				}
437
-				$handle = fopen($tmpFile, $mode);
438
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
439
-					$this->writeBack($tmpFile, $path);
440
-				});
441
-		}
442
-	}
443
-
444
-	public function touch($path, $mtime = null) {
445
-		$path = $this->normalizePath($path);
446
-		if (is_null($mtime)) {
447
-			$mtime = time();
448
-		}
449
-		$metadata = ['timestamp' => $mtime];
450
-		if ($this->file_exists($path)) {
451
-			if ($this->is_dir($path) && $path !== '.') {
452
-				$path .= '/';
453
-			}
454
-
455
-			$object = $this->fetchObject($path);
456
-			if ($object->mergeMetadata($metadata)) {
457
-				// invalidate target object to force repopulation on fetch
458
-				$this->objectCache->remove($path);
459
-			}
460
-			return true;
461
-		} else {
462
-			$mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
463
-			$this->getContainer()->createObject([
464
-				'name' => $path,
465
-				'content' => '',
466
-				'headers' => ['content-type' => 'httpd/unix-directory']
467
-			]);
468
-			// invalidate target object to force repopulation on fetch
469
-			$this->objectCache->remove($path);
470
-			return true;
471
-		}
472
-	}
473
-
474
-	public function copy($path1, $path2) {
475
-		$path1 = $this->normalizePath($path1);
476
-		$path2 = $this->normalizePath($path2);
477
-
478
-		$fileType = $this->filetype($path1);
479
-		if ($fileType) {
480
-			// make way
481
-			$this->unlink($path2);
482
-		}
483
-
484
-		if ($fileType === 'file') {
485
-			try {
486
-				$source = $this->fetchObject($path1);
487
-				$source->copy([
488
-					'destination' => $this->bucket . '/' . $path2
489
-				]);
490
-				// invalidate target object to force repopulation on fetch
491
-				$this->objectCache->remove($path2);
492
-				$this->objectCache->remove($path2 . '/');
493
-			} catch (BadResponseError $e) {
494
-				\OC::$server->getLogger()->logException($e, [
495
-					'level' => \OCP\Util::ERROR,
496
-					'app' => 'files_external',
497
-				]);
498
-				return false;
499
-			}
500
-
501
-		} else if ($fileType === 'dir') {
502
-			try {
503
-				$source = $this->fetchObject($path1 . '/');
504
-				$source->copy([
505
-					'destination' => $this->bucket . '/' . $path2 . '/'
506
-				]);
507
-				// invalidate target object to force repopulation on fetch
508
-				$this->objectCache->remove($path2);
509
-				$this->objectCache->remove($path2 . '/');
510
-			} catch (BadResponseError $e) {
511
-				\OC::$server->getLogger()->logException($e, [
512
-					'level' => \OCP\Util::ERROR,
513
-					'app' => 'files_external',
514
-				]);
515
-				return false;
516
-			}
517
-
518
-			$dh = $this->opendir($path1);
519
-			while ($file = readdir($dh)) {
520
-				if (\OC\Files\Filesystem::isIgnoredDir($file)) {
521
-					continue;
522
-				}
523
-
524
-				$source = $path1 . '/' . $file;
525
-				$target = $path2 . '/' . $file;
526
-				$this->copy($source, $target);
527
-			}
528
-
529
-		} else {
530
-			//file does not exist
531
-			return false;
532
-		}
533
-
534
-		return true;
535
-	}
536
-
537
-	public function rename($path1, $path2) {
538
-		$path1 = $this->normalizePath($path1);
539
-		$path2 = $this->normalizePath($path2);
540
-
541
-		$fileType = $this->filetype($path1);
542
-
543
-		if ($fileType === 'dir' || $fileType === 'file') {
544
-			// copy
545
-			if ($this->copy($path1, $path2) === false) {
546
-				return false;
547
-			}
548
-
549
-			// cleanup
550
-			if ($this->unlink($path1) === false) {
551
-				throw new \Exception('failed to remove original');
552
-				$this->unlink($path2);
553
-				return false;
554
-			}
555
-
556
-			return true;
557
-		}
558
-
559
-		return false;
560
-	}
561
-
562
-	public function getId() {
563
-		return $this->id;
564
-	}
565
-
566
-	/**
567
-	 * Returns the initialized object store container.
568
-	 *
569
-	 * @return \OpenStack\ObjectStore\v1\Models\Container
570
-	 * @throws \OCP\Files\StorageAuthException
571
-	 * @throws \OCP\Files\StorageNotAvailableException
572
-	 */
573
-	public function getContainer() {
574
-		if (is_null($this->container)) {
575
-			$this->container = $this->connectionFactory->getContainer();
576
-
577
-			if (!$this->file_exists('.')) {
578
-				$this->mkdir('.');
579
-			}
580
-		}
581
-		return $this->container;
582
-	}
583
-
584
-	public function writeBack($tmpFile, $path) {
585
-		$fileData = fopen($tmpFile, 'r');
586
-		$this->objectStore->writeObject($path, $fileData);
587
-		// invalidate target object to force repopulation on fetch
588
-		$this->objectCache->remove($path);
589
-		unlink($tmpFile);
590
-	}
591
-
592
-	public function hasUpdated($path, $time) {
593
-		if ($this->is_file($path)) {
594
-			return parent::hasUpdated($path, $time);
595
-		}
596
-		$path = $this->normalizePath($path);
597
-		$dh = $this->opendir($path);
598
-		$content = array();
599
-		while (($file = readdir($dh)) !== false) {
600
-			$content[] = $file;
601
-		}
602
-		if ($path === '.') {
603
-			$path = '';
604
-		}
605
-		$cachedContent = $this->getCache()->getFolderContents($path);
606
-		$cachedNames = array_map(function ($content) {
607
-			return $content['name'];
608
-		}, $cachedContent);
609
-		sort($cachedNames);
610
-		sort($content);
611
-		return $cachedNames !== $content;
612
-	}
613
-
614
-	/**
615
-	 * check if curl is installed
616
-	 */
617
-	public static function checkDependencies() {
618
-		return true;
619
-	}
288
+        try {
289
+            $files = [];
290
+            $objects = $this->getContainer()->listObjects([
291
+                'prefix' => $path,
292
+                'delimiter' => '/'
293
+            ]);
294
+
295
+            /** @var StorageObject $object */
296
+            foreach ($objects as $object) {
297
+                $file = basename($object->name);
298
+                if ($file !== basename($path) && $file !== '.') {
299
+                    $files[] = $file;
300
+                }
301
+            }
302
+
303
+            return IteratorDirectory::wrap($files);
304
+        } catch (\Exception $e) {
305
+            \OC::$server->getLogger()->logException($e, [
306
+                'level' => \OCP\Util::ERROR,
307
+                'app' => 'files_external',
308
+            ]);
309
+            return false;
310
+        }
311
+
312
+    }
313
+
314
+    public function stat($path) {
315
+        $path = $this->normalizePath($path);
316
+
317
+        if ($path === '.') {
318
+            $path = '';
319
+        } else if ($this->is_dir($path)) {
320
+            $path .= '/';
321
+        }
322
+
323
+        try {
324
+            $object = $this->fetchObject($path);
325
+            if (!$object) {
326
+                return false;
327
+            }
328
+        } catch (BadResponseError $e) {
329
+            \OC::$server->getLogger()->logException($e, [
330
+                'level' => \OCP\Util::ERROR,
331
+                'app' => 'files_external',
332
+            ]);
333
+            return false;
334
+        }
335
+
336
+        $dateTime = $object->lastModified ? \DateTime::createFromFormat(\DateTime::RFC1123, $object->lastModified) : false;
337
+        $mtime = $dateTime ? $dateTime->getTimestamp() : null;
338
+        $objectMetadata = $object->getMetadata();
339
+        if (isset($objectMetadata['timestamp'])) {
340
+            $mtime = $objectMetadata['timestamp'];
341
+        }
342
+
343
+        if (!empty($mtime)) {
344
+            $mtime = floor($mtime);
345
+        }
346
+
347
+        $stat = array();
348
+        $stat['size'] = (int)$object->contentLength;
349
+        $stat['mtime'] = $mtime;
350
+        $stat['atime'] = time();
351
+        return $stat;
352
+    }
353
+
354
+    public function filetype($path) {
355
+        $path = $this->normalizePath($path);
356
+
357
+        if ($path !== '.' && $this->doesObjectExist($path)) {
358
+            return 'file';
359
+        }
360
+
361
+        if ($path !== '.') {
362
+            $path .= '/';
363
+        }
364
+
365
+        if ($this->doesObjectExist($path)) {
366
+            return 'dir';
367
+        }
368
+    }
369
+
370
+    public function unlink($path) {
371
+        $path = $this->normalizePath($path);
372
+
373
+        if ($this->is_dir($path)) {
374
+            return $this->rmdir($path);
375
+        }
376
+
377
+        try {
378
+            $this->objectStore->deleteObject($path);
379
+            $this->objectCache->remove($path);
380
+            $this->objectCache->remove($path . '/');
381
+        } catch (BadResponseError $e) {
382
+            if ($e->getResponse()->getStatusCode() !== 404) {
383
+                \OC::$server->getLogger()->logException($e, [
384
+                    'level' => \OCP\Util::ERROR,
385
+                    'app' => 'files_external',
386
+                ]);
387
+                throw $e;
388
+            }
389
+        }
390
+
391
+        return true;
392
+    }
393
+
394
+    public function fopen($path, $mode) {
395
+        $path = $this->normalizePath($path);
396
+
397
+        switch ($mode) {
398
+            case 'a':
399
+            case 'ab':
400
+            case 'a+':
401
+                return false;
402
+            case 'r':
403
+            case 'rb':
404
+                try {
405
+                    return $this->objectStore->readObject($path);
406
+                } catch (BadResponseError $e) {
407
+                    \OC::$server->getLogger()->logException($e, [
408
+                        'level' => \OCP\Util::ERROR,
409
+                        'app' => 'files_external',
410
+                    ]);
411
+                    return false;
412
+                }
413
+            case 'w':
414
+            case 'wb':
415
+            case 'r+':
416
+            case 'w+':
417
+            case 'wb+':
418
+            case 'x':
419
+            case 'x+':
420
+            case 'c':
421
+            case 'c+':
422
+                if (strrpos($path, '.') !== false) {
423
+                    $ext = substr($path, strrpos($path, '.'));
424
+                } else {
425
+                    $ext = '';
426
+                }
427
+                $tmpFile = \OCP\Files::tmpFile($ext);
428
+                // Fetch existing file if required
429
+                if ($mode[0] !== 'w' && $this->file_exists($path)) {
430
+                    if ($mode[0] === 'x') {
431
+                        // File cannot already exist
432
+                        return false;
433
+                    }
434
+                    $source = $this->fopen($path, 'r');
435
+                    file_put_contents($tmpFile, $source);
436
+                }
437
+                $handle = fopen($tmpFile, $mode);
438
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
439
+                    $this->writeBack($tmpFile, $path);
440
+                });
441
+        }
442
+    }
443
+
444
+    public function touch($path, $mtime = null) {
445
+        $path = $this->normalizePath($path);
446
+        if (is_null($mtime)) {
447
+            $mtime = time();
448
+        }
449
+        $metadata = ['timestamp' => $mtime];
450
+        if ($this->file_exists($path)) {
451
+            if ($this->is_dir($path) && $path !== '.') {
452
+                $path .= '/';
453
+            }
454
+
455
+            $object = $this->fetchObject($path);
456
+            if ($object->mergeMetadata($metadata)) {
457
+                // invalidate target object to force repopulation on fetch
458
+                $this->objectCache->remove($path);
459
+            }
460
+            return true;
461
+        } else {
462
+            $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
463
+            $this->getContainer()->createObject([
464
+                'name' => $path,
465
+                'content' => '',
466
+                'headers' => ['content-type' => 'httpd/unix-directory']
467
+            ]);
468
+            // invalidate target object to force repopulation on fetch
469
+            $this->objectCache->remove($path);
470
+            return true;
471
+        }
472
+    }
473
+
474
+    public function copy($path1, $path2) {
475
+        $path1 = $this->normalizePath($path1);
476
+        $path2 = $this->normalizePath($path2);
477
+
478
+        $fileType = $this->filetype($path1);
479
+        if ($fileType) {
480
+            // make way
481
+            $this->unlink($path2);
482
+        }
483
+
484
+        if ($fileType === 'file') {
485
+            try {
486
+                $source = $this->fetchObject($path1);
487
+                $source->copy([
488
+                    'destination' => $this->bucket . '/' . $path2
489
+                ]);
490
+                // invalidate target object to force repopulation on fetch
491
+                $this->objectCache->remove($path2);
492
+                $this->objectCache->remove($path2 . '/');
493
+            } catch (BadResponseError $e) {
494
+                \OC::$server->getLogger()->logException($e, [
495
+                    'level' => \OCP\Util::ERROR,
496
+                    'app' => 'files_external',
497
+                ]);
498
+                return false;
499
+            }
500
+
501
+        } else if ($fileType === 'dir') {
502
+            try {
503
+                $source = $this->fetchObject($path1 . '/');
504
+                $source->copy([
505
+                    'destination' => $this->bucket . '/' . $path2 . '/'
506
+                ]);
507
+                // invalidate target object to force repopulation on fetch
508
+                $this->objectCache->remove($path2);
509
+                $this->objectCache->remove($path2 . '/');
510
+            } catch (BadResponseError $e) {
511
+                \OC::$server->getLogger()->logException($e, [
512
+                    'level' => \OCP\Util::ERROR,
513
+                    'app' => 'files_external',
514
+                ]);
515
+                return false;
516
+            }
517
+
518
+            $dh = $this->opendir($path1);
519
+            while ($file = readdir($dh)) {
520
+                if (\OC\Files\Filesystem::isIgnoredDir($file)) {
521
+                    continue;
522
+                }
523
+
524
+                $source = $path1 . '/' . $file;
525
+                $target = $path2 . '/' . $file;
526
+                $this->copy($source, $target);
527
+            }
528
+
529
+        } else {
530
+            //file does not exist
531
+            return false;
532
+        }
533
+
534
+        return true;
535
+    }
536
+
537
+    public function rename($path1, $path2) {
538
+        $path1 = $this->normalizePath($path1);
539
+        $path2 = $this->normalizePath($path2);
540
+
541
+        $fileType = $this->filetype($path1);
542
+
543
+        if ($fileType === 'dir' || $fileType === 'file') {
544
+            // copy
545
+            if ($this->copy($path1, $path2) === false) {
546
+                return false;
547
+            }
548
+
549
+            // cleanup
550
+            if ($this->unlink($path1) === false) {
551
+                throw new \Exception('failed to remove original');
552
+                $this->unlink($path2);
553
+                return false;
554
+            }
555
+
556
+            return true;
557
+        }
558
+
559
+        return false;
560
+    }
561
+
562
+    public function getId() {
563
+        return $this->id;
564
+    }
565
+
566
+    /**
567
+     * Returns the initialized object store container.
568
+     *
569
+     * @return \OpenStack\ObjectStore\v1\Models\Container
570
+     * @throws \OCP\Files\StorageAuthException
571
+     * @throws \OCP\Files\StorageNotAvailableException
572
+     */
573
+    public function getContainer() {
574
+        if (is_null($this->container)) {
575
+            $this->container = $this->connectionFactory->getContainer();
576
+
577
+            if (!$this->file_exists('.')) {
578
+                $this->mkdir('.');
579
+            }
580
+        }
581
+        return $this->container;
582
+    }
583
+
584
+    public function writeBack($tmpFile, $path) {
585
+        $fileData = fopen($tmpFile, 'r');
586
+        $this->objectStore->writeObject($path, $fileData);
587
+        // invalidate target object to force repopulation on fetch
588
+        $this->objectCache->remove($path);
589
+        unlink($tmpFile);
590
+    }
591
+
592
+    public function hasUpdated($path, $time) {
593
+        if ($this->is_file($path)) {
594
+            return parent::hasUpdated($path, $time);
595
+        }
596
+        $path = $this->normalizePath($path);
597
+        $dh = $this->opendir($path);
598
+        $content = array();
599
+        while (($file = readdir($dh)) !== false) {
600
+            $content[] = $file;
601
+        }
602
+        if ($path === '.') {
603
+            $path = '';
604
+        }
605
+        $cachedContent = $this->getCache()->getFolderContents($path);
606
+        $cachedNames = array_map(function ($content) {
607
+            return $content['name'];
608
+        }, $cachedContent);
609
+        sort($cachedNames);
610
+        sort($content);
611
+        return $cachedNames !== $content;
612
+    }
613
+
614
+    /**
615
+     * check if curl is installed
616
+     */
617
+    public static function checkDependencies() {
618
+        return true;
619
+    }
620 620
 
621 621
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-declare(strict_types=1);
2
+declare(strict_types = 1);
3 3
 /**
4 4
  * @copyright Copyright (c) 2016, ownCloud, Inc.
5 5
  *
@@ -163,12 +163,12 @@  discard block
 block discarded – undo
163 163
 		}
164 164
 
165 165
 		$user = $params['user'];
166
-		$this->id = 'swift::' . $user . md5($params['bucket']);
166
+		$this->id = 'swift::'.$user.md5($params['bucket']);
167 167
 
168 168
 		$bucketUrl = new Uri($params['bucket']);
169 169
 		if ($bucketUrl->getHost()) {
170 170
 			$params['bucket'] = basename($bucketUrl->getPath());
171
-			$params['endpoint_url'] = (string)$bucketUrl->withPath(dirname($bucketUrl->getPath()));
171
+			$params['endpoint_url'] = (string) $bucketUrl->withPath(dirname($bucketUrl->getPath()));
172 172
 		}
173 173
 
174 174
 		if (empty($params['url'])) {
@@ -253,16 +253,16 @@  discard block
 block discarded – undo
253 253
 				continue;
254 254
 			}
255 255
 
256
-			if ($this->is_dir($path . '/' . $file)) {
257
-				$this->rmdir($path . '/' . $file);
256
+			if ($this->is_dir($path.'/'.$file)) {
257
+				$this->rmdir($path.'/'.$file);
258 258
 			} else {
259
-				$this->unlink($path . '/' . $file);
259
+				$this->unlink($path.'/'.$file);
260 260
 			}
261 261
 		}
262 262
 
263 263
 		try {
264
-			$this->objectStore->deleteObject($path . '/');
265
-			$this->objectCache->remove($path . '/');
264
+			$this->objectStore->deleteObject($path.'/');
265
+			$this->objectCache->remove($path.'/');
266 266
 		} catch (BadResponseError $e) {
267 267
 			\OC::$server->getLogger()->logException($e, [
268 268
 				'level' => \OCP\Util::ERROR,
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
 		}
346 346
 
347 347
 		$stat = array();
348
-		$stat['size'] = (int)$object->contentLength;
348
+		$stat['size'] = (int) $object->contentLength;
349 349
 		$stat['mtime'] = $mtime;
350 350
 		$stat['atime'] = time();
351 351
 		return $stat;
@@ -377,7 +377,7 @@  discard block
 block discarded – undo
377 377
 		try {
378 378
 			$this->objectStore->deleteObject($path);
379 379
 			$this->objectCache->remove($path);
380
-			$this->objectCache->remove($path . '/');
380
+			$this->objectCache->remove($path.'/');
381 381
 		} catch (BadResponseError $e) {
382 382
 			if ($e->getResponse()->getStatusCode() !== 404) {
383 383
 				\OC::$server->getLogger()->logException($e, [
@@ -435,7 +435,7 @@  discard block
 block discarded – undo
435 435
 					file_put_contents($tmpFile, $source);
436 436
 				}
437 437
 				$handle = fopen($tmpFile, $mode);
438
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
438
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
439 439
 					$this->writeBack($tmpFile, $path);
440 440
 				});
441 441
 		}
@@ -485,11 +485,11 @@  discard block
 block discarded – undo
485 485
 			try {
486 486
 				$source = $this->fetchObject($path1);
487 487
 				$source->copy([
488
-					'destination' => $this->bucket . '/' . $path2
488
+					'destination' => $this->bucket.'/'.$path2
489 489
 				]);
490 490
 				// invalidate target object to force repopulation on fetch
491 491
 				$this->objectCache->remove($path2);
492
-				$this->objectCache->remove($path2 . '/');
492
+				$this->objectCache->remove($path2.'/');
493 493
 			} catch (BadResponseError $e) {
494 494
 				\OC::$server->getLogger()->logException($e, [
495 495
 					'level' => \OCP\Util::ERROR,
@@ -500,13 +500,13 @@  discard block
 block discarded – undo
500 500
 
501 501
 		} else if ($fileType === 'dir') {
502 502
 			try {
503
-				$source = $this->fetchObject($path1 . '/');
503
+				$source = $this->fetchObject($path1.'/');
504 504
 				$source->copy([
505
-					'destination' => $this->bucket . '/' . $path2 . '/'
505
+					'destination' => $this->bucket.'/'.$path2.'/'
506 506
 				]);
507 507
 				// invalidate target object to force repopulation on fetch
508 508
 				$this->objectCache->remove($path2);
509
-				$this->objectCache->remove($path2 . '/');
509
+				$this->objectCache->remove($path2.'/');
510 510
 			} catch (BadResponseError $e) {
511 511
 				\OC::$server->getLogger()->logException($e, [
512 512
 					'level' => \OCP\Util::ERROR,
@@ -521,8 +521,8 @@  discard block
 block discarded – undo
521 521
 					continue;
522 522
 				}
523 523
 
524
-				$source = $path1 . '/' . $file;
525
-				$target = $path2 . '/' . $file;
524
+				$source = $path1.'/'.$file;
525
+				$target = $path2.'/'.$file;
526 526
 				$this->copy($source, $target);
527 527
 			}
528 528
 
@@ -603,7 +603,7 @@  discard block
 block discarded – undo
603 603
 			$path = '';
604 604
 		}
605 605
 		$cachedContent = $this->getCache()->getFolderContents($path);
606
-		$cachedNames = array_map(function ($content) {
606
+		$cachedNames = array_map(function($content) {
607 607
 			return $content['name'];
608 608
 		}, $cachedContent);
609 609
 		sort($cachedNames);
Please login to merge, or discard this patch.